diff --git a/.gn b/.gn
index 255c1e9..2d446be 100644
--- a/.gn
+++ b/.gn
@@ -161,7 +161,7 @@
   "//third_party/snappy/*",
 
   #"//third_party/WebKit/*",  # Errors: https://crbug.com/800764
-  #"//third_party/webrtc/*",
+  #"//third_party/webrtc/*",  # Errors: https://crbug.com/824831
   "//third_party/webrtc_overrides/*",
   "//tools/*",
 
diff --git a/AUTHORS b/AUTHORS
index 28b8614..499e83bb 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -770,6 +770,7 @@
 Siddharth Bagai <b.siddharth@samsung.com>
 Siddharth Shankar <funkysidd@gmail.com>
 Simon Arlott <simon.arlott@gmail.com>
+Simon La Macchia <smacchia@amazon.com>
 Siva Kumar Gunturi <siva.gunturi@samsung.com>
 Sohan Jyoti Ghosh <sohan.jyoti@huawei.com>
 Sohan Jyoti Ghosh <sohan.jyoti@samsung.com>
@@ -956,6 +957,7 @@
 NIKE, Inc. <*@nike.com>
 NVIDIA Corporation <*@nvidia.com>
 Opera Software ASA <*@opera.com>
+Optical Tone Ltd <*@opticaltone.com>
 Seznam.cz, a.s. <*@firma.seznam.cz>
 Spotify AB <*@spotify.com>
 Tableau Software <*@tableau.com>
diff --git a/BUILD.gn b/BUILD.gn
index f83d903..012bd5d 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1074,7 +1074,10 @@
           [ "//third_party/breakpad:minidump_stackwalk($host_toolchain)" ]
     }
     if (is_win || is_android) {
-      data_deps += [ "//chrome/test:angle_perftests" ]
+      data_deps += [
+        "//components:components_perftests",
+        "//chrome/test:angle_perftests",
+      ]
     }
   }
 }
diff --git a/DEPS b/DEPS
index 9f2abf96..6d2a33f 100644
--- a/DEPS
+++ b/DEPS
@@ -79,11 +79,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': 'dab15f7a02ddaa2a6977a14d5d04955bd39350ab',
+  'skia_revision': '9b67c565cc7bb616fc8fd45b3191154117d02144',
   # 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': '2d4815d98a92ce938d575f69a29e4b425a215ebc',
+  'v8_revision': '0351f2cb83915f3f445fc731225fdbd4248b5bc1',
   # 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.
@@ -91,7 +91,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': 'c26214de3f86f9baddcb2f4b97a3dcc5c16498f1',
+  'angle_revision': '822a84b1959f9c1bb615ad4dff2569c58fb3b225',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
@@ -103,7 +103,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': '0f494c86440debd22449acd9743382ba14c7a805',
+  'pdfium_revision': '3ae75c2f2e5759fcf8218e59fa380c26b98aa6b6',
   # 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.
@@ -139,7 +139,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': '734f737c6b57655a718a178426fb09532ff6f0e9',
+  'catapult_revision': 'bffbf166f004d3d44f13cc4672674ca580e09a49',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -180,6 +180,17 @@
   'src/buildtools':
     Var('chromium_git') + '/chromium/buildtools.git' + '@' +  Var('buildtools_revision'),
 
+  'src/chrome/android/profiles': {
+      'packages': [
+          {
+              'package': 'chromium/afdo/profiles/android',
+              'version': 'version:3309',
+          },
+      ],
+      'condition': 'checkout_android',
+      'dep_type': 'cipd',
+  },
+
   'src/chrome/installer/mac/third_party/xz/xz': {
       'url': Var('chromium_git') + '/chromium/deps/xz.git' + '@' + 'eecaf55632ca72e90eb2641376bce7cdbc7284f7',
       'condition': 'checkout_mac',
@@ -270,6 +281,17 @@
   'src/third_party/SPIRV-Tools/src':
     Var('chromium_git') + '/external/github.com/KhronosGroup/SPIRV-Tools.git' + '@' + '9166854ac93ef81b026e943ccd230fed6c8b8d3c',
 
+  'src/third_party/accessibility_test_framework': {
+      'packages': [
+          {
+              'package': 'chromium/third_party/accessibility-test-framework',
+              'version': 'version:2.1-cr0',
+          },
+      ],
+      'condition': 'checkout_android',
+      'dep_type': 'cipd',
+  },
+
   'src/third_party/android_protobuf/src': {
       'url': Var('android_git') + '/platform/external/protobuf.git' + '@' + '7fca48d8ce97f7ba3ab8eea5c472f1ad3711762f',
       'condition': 'checkout_android',
@@ -280,6 +302,28 @@
       'condition': 'checkout_android',
   },
 
+  'src/third_party/android_support_test_runner': {
+      'packages': [
+          {
+              'package': 'chromium/third_party/android_support_test_runner',
+              'version': 'version:0.5-cr0',
+          },
+      ],
+      'condition': 'checkout_android',
+      'dep_type': 'cipd',
+  },
+
+  'src/third_party/android_system_sdk': {
+      'packages': [
+          {
+              'package': 'chromium/third_party/android_system_sdk',
+              'version': 'version:27-cr0',
+          },
+      ],
+      'condition': 'checkout_android',
+      'dep_type': 'cipd',
+  },
+
   'src/third_party/android_tools': {
       'url': Var('chromium_git') + '/android_tools.git' + '@' + 'c22a664c39af72dd8f89200220713dcad811300a',
       'condition': 'checkout_android',
@@ -293,11 +337,33 @@
       'condition': 'checkout_android',
   },
 
+  'src/third_party/apk-patch-size-estimator': {
+      'packages': [
+          {
+              'package': 'chromium/third_party/apk-patch-size-estimator',
+              'version': 'version:0.2-cr0',
+          },
+      ],
+      'condition': 'checkout_android',
+      'dep_type': 'cipd',
+  },
+
   'src/third_party/auto/src': {
       'url': Var('chromium_git') + '/external/github.com/google/auto.git' + '@' + '8a81a858ae7b78a1aef71ac3905fade0bbd64e82',
       'condition': 'checkout_android',
   },
 
+  'src/third_party/bazel': {
+      'packages': [
+          {
+              'package': 'chromium/third_party/bazel',
+              'version': 'version:0.10.0',
+          },
+      ],
+      'condition': 'checkout_android',
+      'dep_type': 'cipd',
+  },
+
   'src/third_party/bidichecker':
     Var('chromium_git') + '/external/bidichecker/lib.git' + '@' + '97f2aa645b74c28c57eca56992235c79850fa9e0',
 
@@ -309,9 +375,31 @@
   'src/third_party/boringssl/src':
     Var('boringssl_git') + '/boringssl.git' + '@' +  Var('boringssl_revision'),
 
+  'src/third_party/bouncycastle': {
+      'packages': [
+          {
+              'package': 'chromium/third_party/bouncycastle',
+              'version': 'version:1.46-cr0',
+          },
+      ],
+      'condition': 'checkout_android',
+      'dep_type': 'cipd',
+  },
+
   'src/third_party/breakpad/breakpad':
     Var('chromium_git') + '/breakpad/breakpad.git' + '@' + 'ac4a549e29fbc8fe58212380e41fa24f36e6c3ec',
 
+  'src/third_party/byte_buddy': {
+      'packages': [
+          {
+              'package': 'chromium/third_party/byte_buddy',
+              'version': 'version:1.4.17-cr0',
+          },
+      ],
+      'condition': 'checkout_android',
+      'dep_type': 'cipd',
+  },
+
   'src/third_party/catapult':
     Var('chromium_git') + '/catapult.git' + '@' + Var('catapult_revision'),
 
@@ -320,7 +408,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '051b1952ca4b29bde5f5b1f07ce0e1fff20d9fce',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '44123785ca9a78989d225628ee44d5bc1825439c',
       'condition': 'checkout_linux',
   },
 
@@ -335,7 +423,7 @@
 
   # For Linux and Chromium OS.
   'src/third_party/cros_system_api': {
-      'url': Var('chromium_git') + '/chromiumos/platform/system_api.git' + '@' + '72bfdd343136630b33cff1b1975fd929c4eb9e44',
+      'url': Var('chromium_git') + '/chromiumos/platform/system_api.git' + '@' + 'a0f6142f5733313cdb84337afc93bbd55f8ba344',
       'condition': 'checkout_linux',
   },
 
@@ -345,7 +433,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '869a2857a4f3acc08fdec6182ecec5b73593be3b',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'dbbf350a34ab7991e635f91a70bd2d211eb921be',
 
   'src/third_party/devtools-node-modules':
     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
@@ -363,6 +451,17 @@
       'condition': 'checkout_android',
   },
 
+  'src/third_party/espresso': {
+      'packages': [
+          {
+              'package': 'chromium/third_party/espresso',
+              'version': 'version:2.2.1-cr0',
+          },
+      ],
+      'condition': 'checkout_android',
+      'dep_type': 'cipd',
+  },
+
   'src/third_party/feed/src': {
       'url': Var('chromium_git') + '/feed' + '@' + Var('feed_revision'),
       'condition': 'checkout_android',
@@ -417,17 +516,83 @@
       'condition': 'checkout_win',
   },
 
+  'src/third_party/gson': {
+      'packages': [
+          {
+              'package': 'chromium/third_party/gson',
+              'version': 'version:2.8.0-cr0',
+          },
+      ],
+      'condition': 'checkout_android',
+      'dep_type': 'cipd',
+  },
+
+  'src/third_party/guava': {
+      'packages': [
+          {
+              'package': 'chromium/third_party/guava',
+              'version': 'version:23.0-cr0',
+          },
+      ],
+      'condition': 'checkout_android',
+      'dep_type': 'cipd',
+  },
+
   'src/third_party/gvr-android-sdk/src': {
       'url': Var('chromium_git') + '/external/github.com/googlevr/gvr-android-sdk.git' + '@' + '233e7fe922a543e0bc55382d64cacd047307d0e7',
       'condition': 'checkout_android',
   },
 
+  'src/third_party/hamcrest': {
+      'packages': [
+          {
+              'package': 'chromium/third_party/hamcrest',
+              'version': 'version:1.3-cr0',
+          },
+      ],
+      'condition': 'checkout_android',
+      'dep_type': 'cipd',
+  },
+
   'src/third_party/hunspell_dictionaries':
     Var('chromium_git') + '/chromium/deps/hunspell_dictionaries.git' + '@' + 'a9bac57ce6c9d390a52ebaad3259f5fdb871210e',
 
   'src/third_party/icu':
     Var('chromium_git') + '/chromium/deps/icu.git' + '@' + 'd888fd2a1be890f4d35e43f68d6d79f42519a357',
 
+  'src/third_party/icu4j': {
+      'packages': [
+          {
+              'package': 'chromium/third_party/icu4j',
+              'version': 'version:53.1-cr0',
+          },
+      ],
+      'condition': 'checkout_android',
+      'dep_type': 'cipd',
+  },
+
+  'src/third_party/intellij': {
+      'packages': [
+          {
+              'package': 'chromium/third_party/intellij',
+              'version': 'version:12.0-cr0',
+          },
+      ],
+      'condition': 'checkout_android',
+      'dep_type': 'cipd',
+  },
+
+  'src/third_party/javax_inject': {
+      'packages': [
+          {
+              'package': 'chromium/third_party/javax_inject',
+              'version': 'version:1-cr0',
+          },
+      ],
+      'condition': 'checkout_android',
+      'dep_type': 'cipd',
+  },
+
   'src/third_party/jsoncpp/source':
     Var('chromium_git') + '/external/github.com/open-source-parsers/jsoncpp.git' + '@' + 'f572e8e42e22cfcf5ab0aea26574f408943edfa4', # from svn 248
 
@@ -496,7 +661,7 @@
   },
 
   'src/third_party/libvpx/source/libvpx':
-    Var('chromium_git') + '/webm/libvpx.git' + '@' +  '7b5a57449ba07f35cc400516d311ce88c49dce9a',
+    Var('chromium_git') + '/webm/libvpx.git' + '@' +  '1f82e061229352b6e86564da7e3132b97ed924be',
 
   'src/third_party/libwebm/source':
     Var('chromium_git') + '/webm/libwebm.git' + '@' + 'b03c65468b06d097f27235d93d76bfc45f490ede',
@@ -562,12 +727,34 @@
       'condition': 'checkout_android',
   },
 
+  'src/third_party/objenesis': {
+      'packages': [
+          {
+              'package': 'chromium/third_party/objenesis',
+              'version': 'version:2.4-cr0',
+          },
+      ],
+      'condition': 'checkout_android',
+      'dep_type': 'cipd',
+  },
+
   'src/third_party/openh264/src':
     Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + '2e96d62426547ac4fb5cbcd122e5f6eb68d66ee6',
 
   'src/third_party/openmax_dl':
     Var('webrtc_git') + '/deps/third_party/openmax.git' + '@' +  Var('openmax_dl_revision'),
 
+  'src/third_party/ow2_asm': {
+      'packages': [
+          {
+              'package': 'chromium/third_party/ow2_asm',
+              'version': 'version:5.0.1-cr0',
+          },
+      ],
+      'condition': 'checkout_android',
+      'dep_type': 'cipd',
+  },
+
   'src/third_party/pdfium':
     Var('pdfium_git') + '/pdfium.git' + '@' +  Var('pdfium_revision'),
 
@@ -605,6 +792,17 @@
       'condition': 'checkout_android',
   },
 
+  'src/third_party/robolectric': {
+      'packages': [
+          {
+              'package': 'chromium/third_party/robolectric',
+              'version': 'version:3.5.1',
+          },
+      ],
+      'condition': 'checkout_android',
+      'dep_type': 'cipd',
+  },
+
   'src/third_party/robolectric/robolectric': {
       'url': Var('chromium_git') + '/external/robolectric.git' + '@' + '7e067f1112e1502caa742f7be72d37b5678d3403',
       'condition': 'checkout_android',
@@ -625,6 +823,17 @@
   'src/third_party/snappy/src':
     Var('chromium_git') + '/external/github.com/google/snappy.git' + '@' + 'ca37ab7fb9b718e056009babb4fea591626e5882',
 
+  'src/third_party/sqlite4java': {
+      'packages': [
+          {
+              'package': 'chromium/third_party/sqlite4java',
+              'version': 'version:0.282-cr0',
+          },
+      ],
+      'condition': 'checkout_android',
+      'dep_type': 'cipd',
+  },
+
   'src/third_party/swiftshader':
     Var('swiftshader_git') + '/SwiftShader.git' + '@' +  Var('swiftshader_revision'),
 
@@ -634,7 +843,7 @@
   },
 
   'src/third_party/usrsctp/usrsctplib':
-    Var('chromium_git') + '/external/github.com/sctplab/usrsctp' + '@' + '0e076261b832121cf120ddc04aaff87ac3a34d30',
+    Var('chromium_git') + '/external/github.com/sctplab/usrsctp' + '@' + '159d060dceec41a64a57356cbba8c455105f3f72',
 
   'src/third_party/visualmetrics/src':
     Var('chromium_git') + '/external/github.com/WPO-Foundation/visualmetrics.git' + '@' +  '1edde9d2fe203229c895b648fdec355917200ad6',
@@ -664,13 +873,24 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '3c1cb0203b6cfc10389e85a350b2ea6ca29d01ce',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'b3179c75ed409fffbaa64ecbee90db243b11efe9', # commit position 21742
+    Var('webrtc_git') + '/src.git' + '@' + 'dc4737bbdacc7ff662af0f0c33ac9bb8a5ddb28b', # commit position 21742
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
       'condition': 'checkout_linux',
   },
 
+  'src/third_party/xstream': {
+      'packages': [
+          {
+              'package': 'chromium/third_party/xstream',
+              'version': 'version:1.4.8-cr0',
+          },
+      ],
+      'condition': 'checkout_android',
+      'dep_type': 'cipd',
+  },
+
   'src/third_party/yasm/source/patched-yasm':
     Var('chromium_git') + '/chromium/deps/yasm/patched-yasm.git' + '@' + 'b98114e18d8b9b84586b10d24353ab8616d4c5fc',
 
@@ -687,7 +907,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@6ad0221d75390ba3f199eb50604def96364e1b60',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@48c82919be0ec44223941341bf2f8c199649df89',
     'condition': 'checkout_src_internal',
   },
 
@@ -1272,12 +1492,15 @@
   },
 
   {
-    'name': 'Android CIPD Ensure',
+    # We used to use src as a CIPD root. We moved it to a different directory
+    # in crrev.com/c/930178 but left the clobber here to ensure that that CL
+    # could be reverted safely. This can be safely removed once crbug.com/794764
+    # is resolved.
+    'name': 'Android Clobber Deprecated CIPD Root',
     'pattern': '.',
     'condition': 'checkout_android',
-    'action': ['src/build/cipd/cipd_wrapper.py',
-               '--chromium-root', 'src',
-               '--ensure-file', 'src/build/cipd/android/android.ensure',
+    'action': ['src/build/cipd/clobber_cipd_root.py',
+               '--root', 'src',
     ],
   },
   {
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 9aa6800..e539b70 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -731,18 +731,40 @@
   the reverse: changes in histograms.xml not matched in the code itself."""
   touched_histograms = []
   histograms_xml_modifications = []
-  pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
+  call_pattern_c = r'\bUMA_HISTOGRAM.*\('
+  call_pattern_java = r'\bRecordHistogram\.record[a-zA-Z]+Histogram\('
+  name_pattern = r'"(.*?)"'
+  single_line_c_re = input_api.re.compile(call_pattern_c + name_pattern)
+  single_line_java_re = input_api.re.compile(call_pattern_java + name_pattern)
+  split_line_c_prefix_re = input_api.re.compile(call_pattern_c)
+  split_line_java_prefix_re = input_api.re.compile(call_pattern_java)
+  split_line_suffix_re = input_api.re.compile(r'^\s*' + name_pattern)
+  last_line_matched_prefix = False
   for f in input_api.AffectedFiles():
     # If histograms.xml itself is modified, keep the modified lines for later.
     if f.LocalPath().endswith(('histograms.xml')):
       histograms_xml_modifications = f.ChangedContents()
       continue
-    if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
+    if f.LocalPath().endswith(('cc', 'mm', 'cpp')):
+      single_line_re = single_line_c_re
+      split_line_prefix_re = split_line_c_prefix_re
+    elif f.LocalPath().endswith(('java')):
+      single_line_re = single_line_java_re
+      split_line_prefix_re = split_line_java_prefix_re
+    else:
       continue
     for line_num, line in f.ChangedContents():
-      found = pattern.search(line)
+      if last_line_matched_prefix:
+        suffix_found = split_line_suffix_re.search(line)
+        if suffix_found :
+          touched_histograms.append([suffix_found.group(1), f, line_num])
+          last_line_matched_prefix = False
+          continue
+      found = single_line_re.search(line)
       if found:
         touched_histograms.append([found.group(1), f, line_num])
+        continue
+      last_line_matched_prefix = split_line_prefix_re.search(line)
 
   # Search for the touched histogram names in the local modifications to
   # histograms.xml, and, if not found, on the base histograms.xml file.
@@ -1769,7 +1791,12 @@
       mostly_json_lines = '\n'.join(f.NewContents())
       # Comments aren't allowed in strict JSON, so filter them out.
       json_lines = json_comment_eater.Nom(mostly_json_lines)
-      json_content = input_api.json.loads(json_lines)
+      try:
+        json_content = input_api.json.loads(json_lines)
+      except:
+        # There's another PRESUBMIT check that already verifies that JSON files
+        # are not invalid, so no need to emit another warning here.
+        continue
       if 'interface_provider_specs' in json_content:
         AddPatternToCheck(f, input_api.os_path.basename(f.LocalPath()))
     for pattern in file_patterns:
diff --git a/PRESUBMIT_test.py b/PRESUBMIT_test.py
index 5aa17a1..7b8a555 100755
--- a/PRESUBMIT_test.py
+++ b/PRESUBMIT_test.py
@@ -41,10 +41,13 @@
 class UmaHistogramChangeMatchedOrNotTest(unittest.TestCase):
   def testTypicalCorrectlyMatchedChange(self):
     diff_cc = ['UMA_HISTOGRAM_BOOL("Bla.Foo.Dummy", true)']
+    diff_java = [
+      'RecordHistogram.recordBooleanHistogram("Bla.Foo.Dummy", true)']
     diff_xml = ['<histogram name="Bla.Foo.Dummy"> </histogram>']
     mock_input_api = MockInputApi()
     mock_input_api.files = [
       MockFile('some/path/foo.cc', diff_cc),
+      MockFile('some/path/foo.java', diff_java),
       MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
     ]
     warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
@@ -53,15 +56,24 @@
 
   def testTypicalNotMatchedChange(self):
     diff_cc = ['UMA_HISTOGRAM_BOOL("Bla.Foo.Dummy", true)']
+    diff_java = [
+      'RecordHistogram.recordBooleanHistogram("Bla.Foo.Dummy", true)']
     mock_input_api = MockInputApi()
-    mock_input_api.files = [MockFile('some/path/foo.cc', diff_cc)]
+    mock_input_api.files = [
+      MockFile('some/path/foo.cc', diff_cc),
+      MockFile('some/path/foo.java', diff_java),
+    ]
     warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
                                                    MockOutputApi())
     self.assertEqual(1, len(warnings))
     self.assertEqual('warning', warnings[0].type)
+    self.assertTrue('foo.cc' in warnings[0].items[0])
+    self.assertTrue('foo.java' in warnings[0].items[1])
 
   def testTypicalNotMatchedChangeViaSuffixes(self):
     diff_cc = ['UMA_HISTOGRAM_BOOL("Bla.Foo.Dummy", true)']
+    diff_java = [
+      'RecordHistogram.recordBooleanHistogram("Bla.Foo.Dummy", true)']
     diff_xml = ['<histogram_suffixes name="SuperHistogram">',
                 '  <suffix name="Dummy"/>',
                 '  <affected-histogram name="Snafu.Dummy"/>',
@@ -69,15 +81,20 @@
     mock_input_api = MockInputApi()
     mock_input_api.files = [
       MockFile('some/path/foo.cc', diff_cc),
+      MockFile('some/path/foo.java', diff_java),
       MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
     ]
     warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
                                                    MockOutputApi())
     self.assertEqual(1, len(warnings))
     self.assertEqual('warning', warnings[0].type)
+    self.assertTrue('foo.cc' in warnings[0].items[0])
+    self.assertTrue('foo.java' in warnings[0].items[1])
 
   def testTypicalCorrectlyMatchedChangeViaSuffixes(self):
     diff_cc = ['UMA_HISTOGRAM_BOOL("Bla.Foo.Dummy", true)']
+    diff_java = [
+      'RecordHistogram.recordBooleanHistogram("Bla.Foo.Dummy", true)']
     diff_xml = ['<histogram_suffixes name="SuperHistogram">',
                 '  <suffix name="Dummy"/>',
                 '  <affected-histogram name="Bla.Foo"/>',
@@ -85,6 +102,7 @@
     mock_input_api = MockInputApi()
     mock_input_api.files = [
       MockFile('some/path/foo.cc', diff_cc),
+      MockFile('some/path/foo.java', diff_java),
       MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
     ]
     warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
@@ -93,6 +111,7 @@
 
   def testTypicalCorrectlyMatchedChangeViaSuffixesWithSeparator(self):
     diff_cc = ['UMA_HISTOGRAM_BOOL("Snafu_Dummy", true)']
+    diff_java = ['RecordHistogram.recordBooleanHistogram("Snafu_Dummy", true)']
     diff_xml = ['<histogram_suffixes name="SuperHistogram" separator="_">',
                 '  <suffix name="Dummy"/>',
                 '  <affected-histogram name="Snafu"/>',
@@ -100,12 +119,64 @@
     mock_input_api = MockInputApi()
     mock_input_api.files = [
       MockFile('some/path/foo.cc', diff_cc),
+      MockFile('some/path/foo.java', diff_java),
       MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
     ]
     warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
                                                    MockOutputApi())
     self.assertEqual(0, len(warnings))
 
+  def testNameMatch(self):
+    # Check that the detected histogram name is "Dummy" and not, e.g.,
+    # "Dummy\", true);  // The \"correct"
+    diff_cc = ['UMA_HISTOGRAM_BOOL("Dummy", true);  // The "correct" histogram']
+    diff_java = [
+      'RecordHistogram.recordBooleanHistogram("Dummy", true);'
+      + '  // The "correct" histogram']
+    diff_xml = ['<histogram name="Dummy"> </histogram>']
+    mock_input_api = MockInputApi()
+    mock_input_api.files = [
+      MockFile('some/path/foo.cc', diff_cc),
+      MockFile('some/path/foo.java', diff_java),
+      MockFile('tools/metrics/histograms/histograms.xml', diff_xml),
+    ]
+    warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
+                                                   MockOutputApi())
+    self.assertEqual(0, len(warnings))
+
+  def testSimilarMacroNames(self):
+    diff_cc = ['PUMA_HISTOGRAM_COOL("Mountain Lion", 42)']
+    diff_java = [
+      'FakeRecordHistogram.recordFakeHistogram("Mountain Lion", 42)']
+    mock_input_api = MockInputApi()
+    mock_input_api.files = [
+      MockFile('some/path/foo.cc', diff_cc),
+      MockFile('some/path/foo.java', diff_java),
+    ]
+    warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
+                                                   MockOutputApi())
+    self.assertEqual(0, len(warnings))
+
+  def testMultiLine(self):
+    diff_cc = ['UMA_HISTOGRAM_BOOLEAN(', '    "Multi.Line", true)']
+    diff_cc2 = ['UMA_HISTOGRAM_BOOLEAN(', '    "Multi.Line"', '    , true)']
+    diff_java = [
+      'RecordHistogram.recordBooleanHistogram(',
+      '    "Multi.Line", true);',
+    ]
+    mock_input_api = MockInputApi()
+    mock_input_api.files = [
+      MockFile('some/path/foo.cc', diff_cc),
+      MockFile('some/path/foo2.cc', diff_cc2),
+      MockFile('some/path/foo.java', diff_java),
+    ]
+    warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api,
+                                                   MockOutputApi())
+    self.assertEqual(1, len(warnings))
+    self.assertEqual('warning', warnings[0].type)
+    self.assertTrue('foo.cc' in warnings[0].items[0])
+    self.assertTrue('foo2.cc' in warnings[0].items[1])
+
 class BadExtensionsTest(unittest.TestCase):
   def testBadRejFile(self):
     mock_input_api = MockInputApi()
diff --git a/WATCHLISTS b/WATCHLISTS
index e5e0398..6a802881 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -216,7 +216,8 @@
     },
     'blink_audio': {
       'filepath': 'third_party/WebKit/Source/platform/audio' \
-                  '|third_party/WebKit/Source/modules/webaudio',
+                  '|third_party/WebKit/Source/modules/webaudio' \
+                  '|third_party/WebKit/LayoutTests/external/wpt/webaudio',
     },
     'blink_battery_status': {
       'filepath': 'third_party/WebKit/Source/modules/battery/' \
@@ -1533,9 +1534,6 @@
     'usb': {
       'filepath': '/usb/',
     },
-    'v4l2': {
-      'filepath': 'media/gpu/v4l2',
-    },
     'vaapi': {
       'filepath': 'media/gpu/vaapi',
     },
@@ -2313,13 +2311,13 @@
     'ui_strings': ['srahim+watch@chromium.org'],
     'usb': ['cco3+watch@chromium.org',
             'mattreynolds+watch@chromium.org'],
-    'v4l2': ['acourbot+watch@chromium.org'],
     'vaapi': ['vaapi-reviews@chromium.org'],
     'valgrind': ['bruening+watch@chromium.org',
                  'glider+watch@chromium.org'],
     'version_assembly': ['caitkp+watch@chromium.org',
                          'gab+watch@chromium.org'],
-    'video': ['posciak+watch@chromium.org'],
+    'video': ['posciak+watch@chromium.org',
+              'acourbot+watch@chromium.org'],
     'video_capture': ['chfremer+watch@chromium.org'],
     'views': ['tfarina@chromium.org'],
     'virtual_keyboard': ['blakeo+virtualkb@chromium.org',
diff --git a/android_webview/DEPS b/android_webview/DEPS
index 06231b6..ca38a95 100644
--- a/android_webview/DEPS
+++ b/android_webview/DEPS
@@ -22,7 +22,7 @@
   "+gpu",
   "+jni",
   # Only this one header in media which doesn't depend on anything else.
-  "+media/media_features.h",
+  "+media/media_buildflags.h",
   "+net",
   "+services/network/public/cpp",
   "+services/viz/public/interfaces",
diff --git a/android_webview/browser/aw_browser_context.cc b/android_webview/browser/aw_browser_context.cc
index d08a8fa..4dbc1b0 100644
--- a/android_webview/browser/aw_browser_context.cc
+++ b/android_webview/browser/aw_browser_context.cc
@@ -168,8 +168,8 @@
       new web_restrictions::WebRestrictionsClient());
   pref_change_registrar_.Add(
       prefs::kWebRestrictionsAuthority,
-      base::Bind(&AwBrowserContext::OnWebRestrictionsAuthorityChanged,
-                 base::Unretained(this)));
+      base::BindRepeating(&AwBrowserContext::OnWebRestrictionsAuthorityChanged,
+                          base::Unretained(this)));
   web_restriction_provider_->SetAuthority(
       user_pref_service_->GetString(prefs::kWebRestrictionsAuthority));
 
@@ -237,7 +237,8 @@
           browser_policy_connector_->GetPolicyService(),
           browser_policy_connector_->GetHandlerList(),
           policy::POLICY_LEVEL_MANDATORY));
-  pref_service_factory.set_read_error_callback(base::Bind(&HandleReadError));
+  pref_service_factory.set_read_error_callback(
+      base::BindRepeating(&HandleReadError));
   user_pref_service_ = pref_service_factory.Create(pref_registry);
   pref_change_registrar_.Init(user_pref_service_.get());
 
diff --git a/android_webview/browser/aw_browser_permission_request_delegate.h b/android_webview/browser/aw_browser_permission_request_delegate.h
index a0144a1..4452a6f1 100644
--- a/android_webview/browser/aw_browser_permission_request_delegate.h
+++ b/android_webview/browser/aw_browser_permission_request_delegate.h
@@ -20,20 +20,20 @@
 
   virtual void RequestProtectedMediaIdentifierPermission(
       const GURL& origin,
-      const base::Callback<void(bool)>& callback) = 0;
+      base::OnceCallback<void(bool)> callback) = 0;
 
   virtual void CancelProtectedMediaIdentifierPermissionRequests(
       const GURL& origin) = 0;
 
   virtual void RequestGeolocationPermission(
       const GURL& origin,
-      const base::Callback<void(bool)>& callback) = 0;
+      base::OnceCallback<void(bool)> callback) = 0;
 
   virtual void CancelGeolocationPermissionRequests(const GURL& origin) = 0;
 
   virtual void RequestMIDISysexPermission(
       const GURL& origin,
-      const base::Callback<void(bool)>& callback) = 0;
+      base::OnceCallback<void(bool)> callback) = 0;
 
   virtual void CancelMIDISysexPermissionRequests(const GURL& origin) = 0;
 
diff --git a/android_webview/browser/aw_browser_policy_connector.cc b/android_webview/browser/aw_browser_policy_connector.cc
index 523da4a..ebbdd611 100644
--- a/android_webview/browser/aw_browser_policy_connector.cc
+++ b/android_webview/browser/aw_browser_policy_connector.cc
@@ -34,8 +34,8 @@
     const policy::Schema& chrome_schema) {
   std::unique_ptr<policy::ConfigurationPolicyHandlerList> handlers(
       new policy::ConfigurationPolicyHandlerList(
-          base::Bind(&PopulatePolicyHandlerParameters),
-          base::Bind(&GetChromePolicyDetails)));
+          base::BindRepeating(&PopulatePolicyHandlerParameters),
+          base::BindRepeating(&GetChromePolicyDetails)));
 
   // URL Filtering
   handlers->AddHandler(std::make_unique<policy::SimplePolicyHandler>(
@@ -62,7 +62,7 @@
 }  // namespace
 
 AwBrowserPolicyConnector::AwBrowserPolicyConnector()
-    : BrowserPolicyConnectorBase(base::Bind(&BuildHandlerList)) {}
+    : BrowserPolicyConnectorBase(base::BindRepeating(&BuildHandlerList)) {}
 
 AwBrowserPolicyConnector::~AwBrowserPolicyConnector() = default;
 
diff --git a/android_webview/browser/aw_browser_terminator.cc b/android_webview/browser/aw_browser_terminator.cc
index eb284e68..c1b8d98 100644
--- a/android_webview/browser/aw_browser_terminator.cc
+++ b/android_webview/browser/aw_browser_terminator.cc
@@ -158,9 +158,9 @@
     crashed = true;
   }
 
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      base::Bind(&OnRenderProcessGoneDetail, process_host_id, pid, crashed));
+  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+                          base::BindOnce(&OnRenderProcessGoneDetail,
+                                         process_host_id, pid, crashed));
 }
 
 void AwBrowserTerminator::OnChildExit(
@@ -191,9 +191,9 @@
       FROM_HERE,
       {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
        base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
-      base::Bind(&AwBrowserTerminator::OnChildExitAsync, process_host_id, pid,
-                 process_type, termination_status, app_state, crash_dump_dir_,
-                 base::Passed(std::move(pipe))));
+      base::BindOnce(&AwBrowserTerminator::OnChildExitAsync, process_host_id,
+                     pid, process_type, termination_status, app_state,
+                     crash_dump_dir_, std::move(pipe)));
 }
 
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc
index b09a72c..e1efaa4 100644
--- a/android_webview/browser/aw_content_browser_client.cc
+++ b/android_webview/browser/aw_content_browser_client.cc
@@ -198,13 +198,14 @@
 }
 
 AwContentBrowserClient::AwContentBrowserClient() : net_log_(new net::NetLog()) {
-  frame_interfaces_.AddInterface(
-      base::Bind(&autofill::ContentAutofillDriverFactory::BindAutofillDriver));
+  frame_interfaces_.AddInterface(base::BindRepeating(
+      &autofill::ContentAutofillDriverFactory::BindAutofillDriver));
   // Although WebView does not support password manager feature, renderer code
   // could still request this interface, so we register a dummy binder which
   // just drops the incoming request, to avoid the 'Failed to locate a binder
   // for interface' error log..
-  frame_interfaces_.AddInterface(base::Bind(&DummyBindPasswordManagerDriver));
+  frame_interfaces_.AddInterface(
+      base::BindRepeating(&DummyBindPasswordManagerDriver));
   sniff_file_urls_ = AwSettings::GetAllowSniffingFileUrls();
 }
 
@@ -569,10 +570,10 @@
     content::ResourceContext* resource_context =
         render_process_host->GetBrowserContext()->GetResourceContext();
     registry->AddInterface(
-        base::Bind(
+        base::BindRepeating(
             &safe_browsing::MojoSafeBrowsingImpl::MaybeCreate,
             render_process_host->GetID(), resource_context,
-            base::Bind(
+            base::BindRepeating(
                 &AwContentBrowserClient::GetSafeBrowsingUrlCheckerDelegate,
                 base::Unretained(this))),
         BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
diff --git a/android_webview/browser/aw_contents.cc b/android_webview/browser/aw_contents.cc
index 8367b51..92e2e85a 100644
--- a/android_webview/browser/aw_contents.cc
+++ b/android_webview/browser/aw_contents.cc
@@ -478,7 +478,7 @@
   ScopedJavaGlobalRef<jobject> j_message;
   j_message.Reset(env, message);
   render_view_host_ext_->DocumentHasImages(
-      base::Bind(&DocumentHasImagesCallback, j_message));
+      base::BindOnce(&DocumentHasImagesCallback, j_message));
 }
 
 namespace {
@@ -573,19 +573,20 @@
   if (java_ref.get(env).obj()) {
     content::BrowserThread::PostTask(
         content::BrowserThread::UI, FROM_HERE,
-        base::Bind(&ShowGeolocationPromptHelperTask, java_ref, origin));
+        base::BindOnce(&ShowGeolocationPromptHelperTask, java_ref, origin));
   }
 }
 
 }  // anonymous namespace
 
-void AwContents::ShowGeolocationPrompt(const GURL& requesting_frame,
-                                       base::Callback<void(bool)> callback) {
+void AwContents::ShowGeolocationPrompt(
+    const GURL& requesting_frame,
+    base::OnceCallback<void(bool)> callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   GURL origin = requesting_frame.GetOrigin();
   bool show_prompt = pending_geolocation_prompts_.empty();
-  pending_geolocation_prompts_.push_back(OriginCallback(origin, callback));
+  pending_geolocation_prompts_.emplace_back(origin, std::move(callback));
   if (show_prompt) {
     ShowGeolocationPromptHelper(java_ref_, origin);
   }
@@ -604,7 +605,7 @@
   GURL callback_origin(base::android::ConvertJavaStringToUTF16(env, origin));
   if (callback_origin.GetOrigin() ==
       pending_geolocation_prompts_.front().first) {
-    pending_geolocation_prompts_.front().second.Run(value);
+    std::move(pending_geolocation_prompts_.front().second).Run(value);
     pending_geolocation_prompts_.pop_front();
     if (!pending_geolocation_prompts_.empty()) {
       ShowGeolocationPromptHelper(java_ref_,
@@ -680,10 +681,10 @@
 
 void AwContents::RequestProtectedMediaIdentifierPermission(
     const GURL& origin,
-    const base::Callback<void(bool)>& callback) {
+    base::OnceCallback<void(bool)> callback) {
   permission_request_handler_->SendRequest(
       std::unique_ptr<AwPermissionRequestDelegate>(new SimplePermissionRequest(
-          origin, AwPermissionRequest::ProtectedMediaId, callback)));
+          origin, AwPermissionRequest::ProtectedMediaId, std::move(callback))));
 }
 
 void AwContents::CancelProtectedMediaIdentifierPermissionRequests(
@@ -694,19 +695,19 @@
 
 void AwContents::RequestGeolocationPermission(
     const GURL& origin,
-    const base::Callback<void(bool)>& callback) {
+    base::OnceCallback<void(bool)> callback) {
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
   if (obj.is_null())
     return;
 
   if (Java_AwContents_useLegacyGeolocationPermissionAPI(env, obj)) {
-    ShowGeolocationPrompt(origin, callback);
+    ShowGeolocationPrompt(origin, std::move(callback));
     return;
   }
   permission_request_handler_->SendRequest(
       std::unique_ptr<AwPermissionRequestDelegate>(new SimplePermissionRequest(
-          origin, AwPermissionRequest::Geolocation, callback)));
+          origin, AwPermissionRequest::Geolocation, std::move(callback))));
 }
 
 void AwContents::CancelGeolocationPermissionRequests(const GURL& origin) {
@@ -725,10 +726,10 @@
 
 void AwContents::RequestMIDISysexPermission(
     const GURL& origin,
-    const base::Callback<void(bool)>& callback) {
+    base::OnceCallback<void(bool)> callback) {
   permission_request_handler_->SendRequest(
       std::unique_ptr<AwPermissionRequestDelegate>(new SimplePermissionRequest(
-          origin, AwPermissionRequest::MIDISysex, callback)));
+          origin, AwPermissionRequest::MIDISysex, std::move(callback))));
 }
 
 void AwContents::CancelMIDISysexPermissionRequests(const GURL& origin) {
diff --git a/android_webview/browser/aw_contents.h b/android_webview/browser/aw_contents.h
index ffb1ba7..792cebd 100644
--- a/android_webview/browser/aw_contents.h
+++ b/android_webview/browser/aw_contents.h
@@ -237,16 +237,16 @@
   // AwBrowserPermissionRequestDelegate implementation.
   void RequestProtectedMediaIdentifierPermission(
       const GURL& origin,
-      const base::Callback<void(bool)>& callback) override;
+      base::OnceCallback<void(bool)> callback) override;
   void CancelProtectedMediaIdentifierPermissionRequests(
       const GURL& origin) override;
   void RequestGeolocationPermission(
       const GURL& origin,
-      const base::Callback<void(bool)>& callback) override;
+      base::OnceCallback<void(bool)> callback) override;
   void CancelGeolocationPermissionRequests(const GURL& origin) override;
   void RequestMIDISysexPermission(
       const GURL& origin,
-      const base::Callback<void(bool)>& callback) override;
+      base::OnceCallback<void(bool)> callback) override;
   void CancelMIDISysexPermissionRequests(const GURL& origin) override;
 
   // Find-in-page API and related methods.
@@ -366,7 +366,8 @@
   void InitAutofillIfNecessary(bool autocomplete_enabled);
 
   // Geolocation API support
-  void ShowGeolocationPrompt(const GURL& origin, base::Callback<void(bool)>);
+  void ShowGeolocationPrompt(const GURL& origin,
+                             base::OnceCallback<void(bool)>);
   void HideGeolocationPrompt(const GURL& origin);
 
   void SetDipScaleInternal(float dip_scale);
@@ -390,7 +391,7 @@
   // GURL is supplied by the content layer as requesting frame.
   // Callback is supplied by the content layer, and is invoked with the result
   // from the permission prompt.
-  typedef std::pair<const GURL, base::Callback<void(bool)>> OriginCallback;
+  typedef std::pair<const GURL, base::OnceCallback<void(bool)>> OriginCallback;
   // The first element in the list is always the currently pending request.
   std::list<OriginCallback> pending_geolocation_prompts_;
 
diff --git a/android_webview/browser/aw_contents_client_bridge.cc b/android_webview/browser/aw_contents_client_bridge.cc
index 8abb9c3..beadeb7 100644
--- a/android_webview/browser/aw_contents_client_bridge.cc
+++ b/android_webview/browser/aw_contents_client_bridge.cc
@@ -125,12 +125,11 @@
   }
 }
 
-void AwContentsClientBridge::AllowCertificateError(
-    int cert_error,
-    net::X509Certificate* cert,
-    const GURL& request_url,
-    const base::Callback<void(content::CertificateRequestResultType)>& callback,
-    bool* cancel_request) {
+void AwContentsClientBridge::AllowCertificateError(int cert_error,
+                                                   net::X509Certificate* cert,
+                                                   const GURL& request_url,
+                                                   CertErrorCallback callback,
+                                                   bool* cancel_request) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   JNIEnv* env = AttachCurrentThread();
 
@@ -148,7 +147,7 @@
   // We need to add the callback before making the call to java side,
   // as it may do a synchronous callback prior to returning.
   int request_id = pending_cert_error_callbacks_.Add(
-      std::make_unique<CertErrorCallback>(callback));
+      std::make_unique<CertErrorCallback>(std::move(callback)));
   *cancel_request = !Java_AwContentsClientBridge_allowCertificateError(
       env, obj, cert_error, jcert, jurl, request_id);
   // if the request is cancelled, then cancel the stored callback
@@ -167,8 +166,9 @@
     LOG(WARNING) << "Ignoring unexpected ssl error proceed callback";
     return;
   }
-  callback->Run(proceed ? content::CERTIFICATE_REQUEST_RESULT_TYPE_CONTINUE
-                        : content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL);
+  std::move(*callback).Run(
+      proceed ? content::CERTIFICATE_REQUEST_RESULT_TYPE_CONTINUE
+              : content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL);
   pending_cert_error_callbacks_.Remove(id);
 }
 
@@ -453,9 +453,9 @@
 void AwContentsClientBridge::OnSafeBrowsingHit(
     const AwWebResourceRequest& request,
     const safe_browsing::SBThreatType& threat_type,
-    const SafeBrowsingActionCallback& callback) {
+    SafeBrowsingActionCallback callback) {
   int request_id = safe_browsing_callbacks_.Add(
-      std::make_unique<SafeBrowsingActionCallback>(callback));
+      std::make_unique<SafeBrowsingActionCallback>(std::move(callback)));
 
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   JNIEnv* env = AttachCurrentThread();
@@ -551,7 +551,7 @@
     LOG(WARNING) << "Unexpected TakeSafeBrowsingAction. " << request_id;
     return;
   }
-  callback->Run(
+  std::move(*callback).Run(
       static_cast<AwUrlCheckerDelegateImpl::SafeBrowsingAction>(action),
       reporting);
   safe_browsing_callbacks_.Remove(request_id);
diff --git a/android_webview/browser/aw_contents_client_bridge.h b/android_webview/browser/aw_contents_client_bridge.h
index 0188c249..29652fc24 100644
--- a/android_webview/browser/aw_contents_client_bridge.h
+++ b/android_webview/browser/aw_contents_client_bridge.h
@@ -43,6 +43,12 @@
 // any references.
 class AwContentsClientBridge {
  public:
+  using CertErrorCallback =
+      base::OnceCallback<void(content::CertificateRequestResultType)>;
+  using SafeBrowsingActionCallback =
+      base::OnceCallback<void(AwUrlCheckerDelegateImpl::SafeBrowsingAction,
+                              bool)>;
+
   // Adds the handler to the UserData registry.
   static void Associate(content::WebContents* web_contents,
                         AwContentsClientBridge* handler);
@@ -58,13 +64,11 @@
   ~AwContentsClientBridge();
 
   // AwContentsClientBridge implementation
-  void AllowCertificateError(
-      int cert_error,
-      net::X509Certificate* cert,
-      const GURL& request_url,
-      const base::Callback<void(content::CertificateRequestResultType)>&
-          callback,
-      bool* cancel_request);
+  void AllowCertificateError(int cert_error,
+                             net::X509Certificate* cert,
+                             const GURL& request_url,
+                             CertErrorCallback callback,
+                             bool* cancel_request);
   void SelectClientCertificate(
       net::SSLCertRequestInfo* cert_request_info,
       std::unique_ptr<content::ClientCertificateDelegate> delegate);
@@ -100,11 +104,9 @@
                        int error_code,
                        bool safebrowsing_hit);
 
-  void OnSafeBrowsingHit(
-      const AwWebResourceRequest& request,
-      const safe_browsing::SBThreatType& threat_type,
-      const base::Callback<void(AwUrlCheckerDelegateImpl::SafeBrowsingAction,
-                                bool)>& callback);
+  void OnSafeBrowsingHit(const AwWebResourceRequest& request,
+                         const safe_browsing::SBThreatType& threat_type,
+                         SafeBrowsingActionCallback callback);
 
   // Called when a response from the server is received with status code >= 400.
   void OnReceivedHttpError(
@@ -137,11 +139,6 @@
  private:
   JavaObjectWeakGlobalRef java_ref_;
 
-  typedef const base::Callback<void(content::CertificateRequestResultType)>
-      CertErrorCallback;
-  typedef const base::Callback<
-      void(AwUrlCheckerDelegateImpl::SafeBrowsingAction, bool)>
-      SafeBrowsingActionCallback;
   base::IDMap<std::unique_ptr<CertErrorCallback>> pending_cert_error_callbacks_;
   base::IDMap<std::unique_ptr<SafeBrowsingActionCallback>>
       safe_browsing_callbacks_;
diff --git a/android_webview/browser/aw_contents_io_thread_client.cc b/android_webview/browser/aw_contents_io_thread_client.cc
index 9300b27..f621a01 100644
--- a/android_webview/browser/aw_contents_io_thread_client.cc
+++ b/android_webview/browser/aw_contents_io_thread_client.cc
@@ -372,10 +372,10 @@
 
 void AwContentsIoThreadClient::ShouldInterceptRequestAsync(
     const net::URLRequest* request,
-    const ShouldInterceptRequestResultCallback callback) {
+    ShouldInterceptRequestResultCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  base::Callback<std::unique_ptr<AwWebResourceResponse>()> get_response =
-      base::Bind(&ReturnNull);
+  base::OnceCallback<std::unique_ptr<AwWebResourceResponse>()> get_response =
+      base::BindOnce(&ReturnNull);
   JNIEnv* env = AttachCurrentThread();
   if (bg_thread_client_object_.is_null() && !java_object_.is_null()) {
     bg_thread_client_object_.Reset(
@@ -383,12 +383,13 @@
                                                                 java_object_));
   }
   if (!bg_thread_client_object_.is_null()) {
-    get_response = base::Bind(
+    get_response = base::BindOnce(
         &RunShouldInterceptRequest, AwWebResourceRequest(*request),
         JavaObjectWeakGlobalRef(env, bg_thread_client_object_.obj()));
   }
   base::PostTaskAndReplyWithResult(sequenced_task_runner_.get(), FROM_HERE,
-                                   get_response, callback);
+                                   std::move(get_response),
+                                   std::move(callback));
 }
 
 bool AwContentsIoThreadClient::ShouldBlockContentUrls() const {
diff --git a/android_webview/browser/aw_contents_io_thread_client.h b/android_webview/browser/aw_contents_io_thread_client.h
index c65a9918..7d2b358 100644
--- a/android_webview/browser/aw_contents_io_thread_client.h
+++ b/android_webview/browser/aw_contents_io_thread_client.h
@@ -108,11 +108,11 @@
                               int child_render_frame_id);
 
   // This method is called on the IO thread only.
-  typedef base::Callback<void(std::unique_ptr<AwWebResourceResponse>)>
-      ShouldInterceptRequestResultCallback;
+  using ShouldInterceptRequestResultCallback =
+      base::OnceCallback<void(std::unique_ptr<AwWebResourceResponse>)>;
   void ShouldInterceptRequestAsync(
       const net::URLRequest* request,
-      const ShouldInterceptRequestResultCallback callback);
+      ShouldInterceptRequestResultCallback callback);
 
   // Retrieve the AllowContentAccess setting value of this AwContents.
   // This method is called on the IO thread only.
diff --git a/android_webview/browser/aw_contents_statics.cc b/android_webview/browser/aw_contents_statics.cc
index 4c100b9..b1f7b4f7 100644
--- a/android_webview/browser/aw_contents_statics.cc
+++ b/android_webview/browser/aw_contents_statics.cc
@@ -76,9 +76,9 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   BrowserThread::PostTaskAndReply(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&NotifyClientCertificatesChanged),
-      base::Bind(&ClientCertificatesCleared,
-                 ScopedJavaGlobalRef<jobject>(env, callback)));
+      base::BindOnce(&NotifyClientCertificatesChanged),
+      base::BindOnce(&ClientCertificatesCleared,
+                     ScopedJavaGlobalRef<jobject>(env, callback)));
 }
 
 // static
@@ -124,8 +124,8 @@
       AwBrowserContext::GetDefault()->GetSafeBrowsingWhitelistManager();
   whitelist_manager->SetWhitelistOnUIThread(
       std::move(rules),
-      base::Bind(&SafeBrowsingWhitelistAssigned,
-                 ScopedJavaGlobalRef<jobject>(env, callback)));
+      base::BindOnce(&SafeBrowsingWhitelistAssigned,
+                     ScopedJavaGlobalRef<jobject>(env, callback)));
 }
 
 // static
diff --git a/android_webview/browser/aw_devtools_server.cc b/android_webview/browser/aw_devtools_server.cc
index dff0da1..86107a3 100644
--- a/android_webview/browser/aw_devtools_server.cc
+++ b/android_webview/browser/aw_devtools_server.cc
@@ -46,7 +46,7 @@
   std::unique_ptr<net::ServerSocket> CreateForHttpServer() override {
     std::unique_ptr<net::UnixDomainServerSocket> socket(
         new net::UnixDomainServerSocket(
-            base::Bind(&content::CanUserConnectToDevTools),
+            base::BindRepeating(&content::CanUserConnectToDevTools),
             true /* use_abstract_namespace */));
     if (socket->BindAndListen(socket_name_, kBackLog) != net::OK)
       return std::unique_ptr<net::ServerSocket>();
@@ -60,7 +60,7 @@
                                ++last_tethering_socket_);
     std::unique_ptr<net::UnixDomainServerSocket> socket(
         new net::UnixDomainServerSocket(
-            base::Bind(&content::CanUserConnectToDevTools),
+            base::BindRepeating(&content::CanUserConnectToDevTools),
             true /* use_abstract_namespace */));
     if (socket->BindAndListen(*name, kBackLog) != net::OK)
       return std::unique_ptr<net::ServerSocket>();
diff --git a/android_webview/browser/aw_form_database_service.cc b/android_webview/browser/aw_form_database_service.cc
index b0efc43f..bbe8edb 100644
--- a/android_webview/browser/aw_form_database_service.cc
+++ b/android_webview/browser/aw_form_database_service.cc
@@ -80,8 +80,9 @@
   using awds = autofill::AutofillWebDataService;
   base::PostTask(
       FROM_HERE,
-      base::Bind(base::IgnoreResult(&awds::GetCountOfValuesContainedBetween),
-                 autofill_data_, base::Time(), base::Time::Max(), this));
+      base::BindOnce(
+          base::IgnoreResult(&awds::GetCountOfValuesContainedBetween),
+          autofill_data_, base::Time(), base::Time::Max(), this));
   {
     base::ThreadRestrictions::ScopedAllowWait wait;
     has_form_data_completion_.Wait();
diff --git a/android_webview/browser/aw_login_delegate.cc b/android_webview/browser/aw_login_delegate.cc
index 3874bc0..2ecdd263 100644
--- a/android_webview/browser/aw_login_delegate.cc
+++ b/android_webview/browser/aw_login_delegate.cc
@@ -29,8 +29,8 @@
     : auth_info_(auth_info), auth_required_callback_(auth_required_callback) {
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
-      base::Bind(&AwLoginDelegate::HandleHttpAuthRequestOnUIThread, this,
-                 first_auth_attempt, web_contents_getter));
+      base::BindOnce(&AwLoginDelegate::HandleHttpAuthRequestOnUIThread, this,
+                     first_auth_attempt, web_contents_getter));
 }
 
 AwLoginDelegate::~AwLoginDelegate() {
@@ -43,14 +43,15 @@
                               const base::string16& password) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
-      base::Bind(&AwLoginDelegate::ProceedOnIOThread,
-                 this, user, password));
+                          base::BindOnce(&AwLoginDelegate::ProceedOnIOThread,
+                                         this, user, password));
 }
 
 void AwLoginDelegate::Cancel() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
-      base::Bind(&AwLoginDelegate::CancelOnIOThread, this));
+  BrowserThread::PostTask(
+      BrowserThread::IO, FROM_HERE,
+      base::BindOnce(&AwLoginDelegate::CancelOnIOThread, this));
 }
 
 void AwLoginDelegate::HandleHttpAuthRequestOnUIThread(
@@ -93,8 +94,9 @@
 
 void AwLoginDelegate::DeleteAuthHandlerSoon() {
   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
-    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-        base::Bind(&AwLoginDelegate::DeleteAuthHandlerSoon, this));
+    BrowserThread::PostTask(
+        BrowserThread::UI, FROM_HERE,
+        base::BindOnce(&AwLoginDelegate::DeleteAuthHandlerSoon, this));
     return;
   }
   aw_http_auth_handler_.reset();
diff --git a/android_webview/browser/aw_metrics_service_client.cc b/android_webview/browser/aw_metrics_service_client.cc
index 3e720c01..3afecd0 100644
--- a/android_webview/browser/aw_metrics_service_client.cc
+++ b/android_webview/browser/aw_metrics_service_client.cc
@@ -142,9 +142,9 @@
   } else {
     base::PostTaskWithTraitsAndReply(
         FROM_HERE, {base::MayBlock()},
-        base::Bind(&AwMetricsServiceClient::LoadOrCreateClientId),
-        base::Bind(&AwMetricsServiceClient::InitializeWithClientId,
-                   base::Unretained(this)));
+        base::BindOnce(&AwMetricsServiceClient::LoadOrCreateClientId),
+        base::BindOnce(&AwMetricsServiceClient::InitializeWithClientId,
+                       base::Unretained(this)));
   }
 }
 
@@ -157,8 +157,9 @@
   in_sample_ = IsInSample(g_client_id.Get());
 
   metrics_state_manager_ = metrics::MetricsStateManager::Create(
-      pref_service_, this, base::string16(), base::Bind(&StoreClientInfo),
-      base::Bind(&LoadClientInfo));
+      pref_service_, this, base::string16(),
+      base::BindRepeating(&StoreClientInfo),
+      base::BindRepeating(&LoadClientInfo));
 
   metrics_service_.reset(new ::metrics::MetricsService(
       metrics_state_manager_.get(), this, pref_service_));
diff --git a/android_webview/browser/aw_permission_manager.cc b/android_webview/browser/aw_permission_manager.cc
index 71b4d1f6..0a19d99 100644
--- a/android_webview/browser/aw_permission_manager.cc
+++ b/android_webview/browser/aw_permission_manager.cc
@@ -21,7 +21,7 @@
 using content::PermissionType;
 
 using RequestPermissionsCallback =
-    base::Callback<void(const std::vector<PermissionStatus>&)>;
+    base::OnceCallback<void(const std::vector<PermissionStatus>&)>;
 
 namespace android_webview {
 
@@ -154,13 +154,13 @@
                  GURL embedding_origin,
                  int render_process_id,
                  int render_frame_id,
-                 const RequestPermissionsCallback callback)
+                 RequestPermissionsCallback callback)
       : permissions(permissions),
         requesting_origin(requesting_origin),
         embedding_origin(embedding_origin),
         render_process_id(render_process_id),
         render_frame_id(render_frame_id),
-        callback(callback),
+        callback(std::move(callback)),
         results(permissions.size(), PermissionStatus::DENIED),
         cancelled_(false) {
     for (size_t i = 0; i < permissions.size(); ++i)
@@ -302,20 +302,20 @@
       case PermissionType::GEOLOCATION:
         delegate->RequestGeolocationPermission(
             pending_request_raw->requesting_origin,
-            base::Bind(&OnRequestResponse, weak_ptr_factory_.GetWeakPtr(),
-                       request_id, permissions[i]));
+            base::BindOnce(&OnRequestResponse, weak_ptr_factory_.GetWeakPtr(),
+                           request_id, permissions[i]));
         break;
       case PermissionType::PROTECTED_MEDIA_IDENTIFIER:
         delegate->RequestProtectedMediaIdentifierPermission(
             pending_request_raw->requesting_origin,
-            base::Bind(&OnRequestResponse, weak_ptr_factory_.GetWeakPtr(),
-                       request_id, permissions[i]));
+            base::BindOnce(&OnRequestResponse, weak_ptr_factory_.GetWeakPtr(),
+                           request_id, permissions[i]));
         break;
       case PermissionType::MIDI_SYSEX:
         delegate->RequestMIDISysexPermission(
             pending_request_raw->requesting_origin,
-            base::Bind(&OnRequestResponse, weak_ptr_factory_.GetWeakPtr(),
-                       request_id, permissions[i]));
+            base::BindOnce(&OnRequestResponse, weak_ptr_factory_.GetWeakPtr(),
+                           request_id, permissions[i]));
         break;
       case PermissionType::AUDIO_CAPTURE:
       case PermissionType::VIDEO_CAPTURE:
@@ -384,8 +384,8 @@
                                     pending_request->embedding_origin, status);
 
   std::vector<int> complete_request_ids;
-  std::vector<std::pair<const RequestPermissionsCallback,
-                        std::vector<PermissionStatus>>>
+  std::vector<
+      std::pair<RequestPermissionsCallback, std::vector<PermissionStatus>>>
       complete_request_pairs;
   for (PendingRequestsMap::Iterator<PendingRequest> it(
            &manager->pending_requests_);
@@ -399,15 +399,16 @@
     if (it.GetCurrentValue()->IsCompleted()) {
       complete_request_ids.push_back(it.GetCurrentKey());
       if (!it.GetCurrentValue()->IsCancelled()) {
-        complete_request_pairs.push_back(std::make_pair(
-            it.GetCurrentValue()->callback, it.GetCurrentValue()->results));
+        complete_request_pairs.emplace_back(
+            std::move(it.GetCurrentValue()->callback),
+            std::move(it.GetCurrentValue()->results));
       }
     }
   }
   for (auto id : complete_request_ids)
     manager->pending_requests_.Remove(id);
-  for (auto pair : complete_request_pairs)
-    pair.first.Run(pair.second);
+  for (auto& pair : complete_request_pairs)
+    std::move(pair.first).Run(pair.second);
 }
 
 void AwPermissionManager::ResetPermission(PermissionType permission,
diff --git a/android_webview/browser/aw_permission_manager_unittest.cc b/android_webview/browser/aw_permission_manager_unittest.cc
index 41bc18a8..ab8914b74 100644
--- a/android_webview/browser/aw_permission_manager_unittest.cc
+++ b/android_webview/browser/aw_permission_manager_unittest.cc
@@ -39,9 +39,9 @@
     for (auto it = request_.begin(); it != request_.end(); ++it) {
       if ((*it)->type != type || (*it)->origin != origin)
         continue;
-      const base::Callback<void(bool)> callback = (*it)->callback;
+      base::OnceCallback<void(bool)> callback = std::move((*it)->callback);
       request_.erase(it);
-      callback.Run(grant);
+      std::move(callback).Run(grant);
       return;
     }
     response_.push_back(std::make_unique<Response>(origin, type, grant));
@@ -50,15 +50,15 @@
   // AwBrowserPermissionRequestDelegate:
   void RequestProtectedMediaIdentifierPermission(
       const GURL& origin,
-      const base::Callback<void(bool)>& callback) override {}
+      base::OnceCallback<void(bool)> callback) override {}
 
   void CancelProtectedMediaIdentifierPermissionRequests(
       const GURL& origin) override {}
 
   void RequestGeolocationPermission(
       const GURL& origin,
-      const base::Callback<void(bool)>& callback) override {
-    RequestPermission(origin, PermissionType::GEOLOCATION, callback);
+      base::OnceCallback<void(bool)> callback) override {
+    RequestPermission(origin, PermissionType::GEOLOCATION, std::move(callback));
   }
 
   void CancelGeolocationPermissionRequests(const GURL& origin) override {
@@ -67,8 +67,8 @@
 
   void RequestMIDISysexPermission(
       const GURL& origin,
-      const base::Callback<void(bool)>& callback) override {
-    RequestPermission(origin, PermissionType::MIDI_SYSEX, callback);
+      base::OnceCallback<void(bool)> callback) override {
+    RequestPermission(origin, PermissionType::MIDI_SYSEX, std::move(callback));
   }
 
   void CancelMIDISysexPermissionRequests(const GURL& origin) override {
@@ -78,16 +78,17 @@
  private:
   void RequestPermission(const GURL& origin,
                          PermissionType type,
-                         const base::Callback<void(bool)>& callback) {
+                         base::OnceCallback<void(bool)> callback) {
     for (auto it = response_.begin(); it != response_.end(); ++it) {
       if ((*it)->type != type || (*it)->origin != origin)
         continue;
       bool grant = (*it)->grant;
       response_.erase(it);
-      callback.Run(grant);
+      std::move(callback).Run(grant);
       return;
     }
-    request_.push_back(std::make_unique<Request>(origin, type, callback));
+    request_.push_back(
+        std::make_unique<Request>(origin, type, std::move(callback)));
   }
 
   void CancelPermission(const GURL& origin, PermissionType type) {
@@ -104,12 +105,12 @@
   struct Request {
     GURL origin;
     PermissionType type;
-    base::Callback<void(bool)> callback;
+    base::OnceCallback<void(bool)> callback;
 
     Request(const GURL& origin,
             PermissionType type,
-            const base::Callback<void(bool)>& callback)
-        : origin(origin), type(type), callback(callback) {}
+            base::OnceCallback<void(bool)> callback)
+        : origin(origin), type(type), callback(std::move(callback)) {}
   };
 
   struct Response {
diff --git a/android_webview/browser/aw_print_manager.cc b/android_webview/browser/aw_print_manager.cc
index 924193f3..736771c 100644
--- a/android_webview/browser/aw_print_manager.cc
+++ b/android_webview/browser/aw_print_manager.cc
@@ -35,22 +35,20 @@
     content::WebContents* contents,
     const printing::PrintSettings& settings,
     const base::FileDescriptor& file_descriptor,
-    const PrintManager::PdfWritingDoneCallback& callback) {
-  AwPrintManager* print_manager =
-      new AwPrintManager(contents, settings, file_descriptor, callback);
+    PrintManager::PdfWritingDoneCallback callback) {
+  AwPrintManager* print_manager = new AwPrintManager(
+      contents, settings, file_descriptor, std::move(callback));
   contents->SetUserData(UserDataKey(), base::WrapUnique(print_manager));
   return print_manager;
 }
 
-AwPrintManager::AwPrintManager(
-    content::WebContents* contents,
-    const printing::PrintSettings& settings,
-    const base::FileDescriptor& file_descriptor,
-    const PdfWritingDoneCallback& callback)
-    : PrintManager(contents),
-      settings_(settings) {
+AwPrintManager::AwPrintManager(content::WebContents* contents,
+                               const printing::PrintSettings& settings,
+                               const base::FileDescriptor& file_descriptor,
+                               PdfWritingDoneCallback callback)
+    : PrintManager(contents), settings_(settings) {
   set_file_descriptor(file_descriptor);
-  pdf_writing_done_callback_ = callback;
+  pdf_writing_done_callback_ = std::move(callback);
   cookie_ = 1;
 }
 
diff --git a/android_webview/browser/aw_print_manager.h b/android_webview/browser/aw_print_manager.h
index 12e4f19..b7bfb6f 100644
--- a/android_webview/browser/aw_print_manager.h
+++ b/android_webview/browser/aw_print_manager.h
@@ -22,7 +22,7 @@
       content::WebContents* contents,
       const printing::PrintSettings& settings,
       const base::FileDescriptor& file_descriptor,
-      const PdfWritingDoneCallback& callback);
+      PdfWritingDoneCallback callback);
 
   ~AwPrintManager() override;
 
@@ -34,7 +34,7 @@
   AwPrintManager(content::WebContents* contents,
                  const printing::PrintSettings& settings,
                  const base::FileDescriptor& file_descriptor,
-                 const PdfWritingDoneCallback& callback);
+                 PdfWritingDoneCallback callback);
 
   // printing::PrintManager:
   bool OnMessageReceived(const IPC::Message& message,
diff --git a/android_webview/browser/aw_quota_manager_bridge.cc b/android_webview/browser/aw_quota_manager_bridge.cc
index 06aa4a5a..6a24f2f 100644
--- a/android_webview/browser/aw_quota_manager_bridge.cc
+++ b/android_webview/browser/aw_quota_manager_bridge.cc
@@ -37,7 +37,7 @@
 // are destroyed at the end of DoneOnUIThread.
 class GetOriginsTask : public base::RefCountedThreadSafe<GetOriginsTask> {
  public:
-  GetOriginsTask(const AwQuotaManagerBridge::GetOriginsCallback& callback,
+  GetOriginsTask(AwQuotaManagerBridge::GetOriginsCallback callback,
                  QuotaManager* quota_manager);
 
   void Run();
@@ -71,9 +71,9 @@
 };
 
 GetOriginsTask::GetOriginsTask(
-    const AwQuotaManagerBridge::GetOriginsCallback& callback,
+    AwQuotaManagerBridge::GetOriginsCallback callback,
     QuotaManager* quota_manager)
-    : ui_callback_(callback), quota_manager_(quota_manager) {
+    : ui_callback_(std::move(callback)), quota_manager_(quota_manager) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 }
 
@@ -83,10 +83,10 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&QuotaManager::GetOriginsModifiedSince, quota_manager_,
-                 blink::mojom::StorageType::kTemporary,
-                 base::Time() /* Since beginning of time. */,
-                 base::Bind(&GetOriginsTask::OnOriginsObtained, this)));
+      base::BindOnce(&QuotaManager::GetOriginsModifiedSince, quota_manager_,
+                     blink::mojom::StorageType::kTemporary,
+                     base::Time() /* Since beginning of time. */,
+                     base::BindOnce(&GetOriginsTask::OnOriginsObtained, this)));
 }
 
 void GetOriginsTask::OnOriginsObtained(const std::set<GURL>& origins,
@@ -99,7 +99,8 @@
        origin != origins.end(); ++origin) {
     quota_manager_->GetUsageAndQuota(
         *origin, type,
-        base::Bind(&GetOriginsTask::OnUsageAndQuotaObtained, this, *origin));
+        base::BindOnce(&GetOriginsTask::OnUsageAndQuotaObtained, this,
+                       *origin));
   }
 
   CheckDone();
@@ -124,8 +125,9 @@
 void GetOriginsTask::CheckDone() {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (num_callbacks_received_ == num_callbacks_to_wait_) {
-    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-                            base::Bind(&GetOriginsTask::DoneOnUIThread, this));
+    BrowserThread::PostTask(
+        BrowserThread::UI, FROM_HERE,
+        base::BindOnce(&GetOriginsTask::DoneOnUIThread, this));
   } else if (num_callbacks_received_ > num_callbacks_to_wait_) {
     NOTREACHED();
   }
@@ -134,14 +136,14 @@
 // This method is to avoid copying the 3 vector arguments into a bound callback.
 void GetOriginsTask::DoneOnUIThread() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  ui_callback_.Run(origin_, usage_, quota_);
+  std::move(ui_callback_).Run(origin_, usage_, quota_);
 }
 
-void RunOnUIThread(const base::Closure& task) {
+void RunOnUIThread(base::OnceClosure task) {
   if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
-    task.Run();
+    std::move(task).Run();
   } else {
-    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, task);
+    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, std::move(task));
   }
 }
 
@@ -197,7 +199,7 @@
 void AwQuotaManagerBridge::DeleteAllData(JNIEnv* env,
                                          const JavaParamRef<jobject>& object) {
   RunOnUIThread(
-      base::Bind(&AwQuotaManagerBridge::DeleteAllDataOnUiThread, this));
+      base::BindOnce(&AwQuotaManagerBridge::DeleteAllDataOnUiThread, this));
 }
 
 void AwQuotaManagerBridge::DeleteAllDataOnUiThread() {
@@ -219,8 +221,8 @@
                                         const JavaParamRef<jstring>& origin) {
   base::string16 origin_string(
       base::android::ConvertJavaStringToUTF16(env, origin));
-  RunOnUIThread(base::Bind(&AwQuotaManagerBridge::DeleteOriginOnUiThread, this,
-                           origin_string));
+  RunOnUIThread(base::BindOnce(&AwQuotaManagerBridge::DeleteOriginOnUiThread,
+                               this, origin_string));
 }
 
 void AwQuotaManagerBridge::DeleteOriginOnUiThread(
@@ -239,18 +241,18 @@
 void AwQuotaManagerBridge::GetOrigins(JNIEnv* env,
                                       const JavaParamRef<jobject>& object,
                                       jint callback_id) {
-  RunOnUIThread(base::Bind(&AwQuotaManagerBridge::GetOriginsOnUiThread, this,
-                           callback_id));
+  RunOnUIThread(base::BindOnce(&AwQuotaManagerBridge::GetOriginsOnUiThread,
+                               this, callback_id));
 }
 
 void AwQuotaManagerBridge::GetOriginsOnUiThread(jint callback_id) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-  const GetOriginsCallback ui_callback =
-      base::Bind(&AwQuotaManagerBridge::GetOriginsCallbackImpl,
-                 weak_factory_.GetWeakPtr(), callback_id);
+  GetOriginsCallback ui_callback =
+      base::BindOnce(&AwQuotaManagerBridge::GetOriginsCallbackImpl,
+                     weak_factory_.GetWeakPtr(), callback_id);
 
-  (new GetOriginsTask(ui_callback, GetQuotaManager()))->Run();
+  (new GetOriginsTask(std::move(ui_callback), GetQuotaManager()))->Run();
 }
 
 void AwQuotaManagerBridge::GetOriginsCallbackImpl(
@@ -273,7 +275,7 @@
 namespace {
 
 void OnUsageAndQuotaObtained(
-    const AwQuotaManagerBridge::QuotaUsageCallback& ui_callback,
+    AwQuotaManagerBridge::QuotaUsageCallback ui_callback,
     blink::mojom::QuotaStatusCode status_code,
     int64_t usage,
     int64_t quota) {
@@ -283,7 +285,7 @@
     quota = 0;
   }
   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-                          base::Bind(ui_callback, usage, quota));
+                          base::BindOnce(std::move(ui_callback), usage, quota));
 }
 
 }  // namespace
@@ -297,8 +299,8 @@
   base::string16 origin_string(
       base::android::ConvertJavaStringToUTF16(env, origin));
   RunOnUIThread(
-      base::Bind(&AwQuotaManagerBridge::GetUsageAndQuotaForOriginOnUiThread,
-                 this, origin_string, callback_id, is_quota));
+      base::BindOnce(&AwQuotaManagerBridge::GetUsageAndQuotaForOriginOnUiThread,
+                     this, origin_string, callback_id, is_quota));
 }
 
 void AwQuotaManagerBridge::GetUsageAndQuotaForOriginOnUiThread(
@@ -306,15 +308,16 @@
     jint callback_id,
     bool is_quota) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  const QuotaUsageCallback ui_callback =
-      base::Bind(&AwQuotaManagerBridge::QuotaUsageCallbackImpl,
-                 weak_factory_.GetWeakPtr(), callback_id, is_quota);
+  QuotaUsageCallback ui_callback =
+      base::BindOnce(&AwQuotaManagerBridge::QuotaUsageCallbackImpl,
+                     weak_factory_.GetWeakPtr(), callback_id, is_quota);
 
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&QuotaManager::GetUsageAndQuota, GetQuotaManager(),
-                 GURL(origin), blink::mojom::StorageType::kTemporary,
-                 base::Bind(&OnUsageAndQuotaObtained, ui_callback)));
+      base::BindOnce(
+          &QuotaManager::GetUsageAndQuota, GetQuotaManager(), GURL(origin),
+          blink::mojom::StorageType::kTemporary,
+          base::BindOnce(&OnUsageAndQuotaObtained, std::move(ui_callback))));
 }
 
 void AwQuotaManagerBridge::QuotaUsageCallbackImpl(int jcallback_id,
diff --git a/android_webview/browser/aw_quota_manager_bridge.h b/android_webview/browser/aw_quota_manager_bridge.h
index 2df4e46..b65f4171 100644
--- a/android_webview/browser/aw_quota_manager_bridge.h
+++ b/android_webview/browser/aw_quota_manager_bridge.h
@@ -52,12 +52,12 @@
       jint callback_id,
       bool is_quota);
 
-  typedef base::Callback<void(const std::vector<std::string>& /* origin */,
+  using GetOriginsCallback =
+      base::OnceCallback<void(const std::vector<std::string>& /* origin */,
                               const std::vector<int64_t>& /* usaoge */,
-                              const std::vector<int64_t>& /* quota */)>
-      GetOriginsCallback;
-  typedef base::Callback<void(int64_t /* usage */, int64_t /* quota */)>
-      QuotaUsageCallback;
+                              const std::vector<int64_t>& /* quota */)>;
+  using QuotaUsageCallback =
+      base::OnceCallback<void(int64_t /* usage */, int64_t /* quota */)>;
 
  private:
   friend class base::RefCountedThreadSafe<AwQuotaManagerBridge>;
diff --git a/android_webview/browser/aw_render_thread_context_provider.cc b/android_webview/browser/aw_render_thread_context_provider.cc
index a860024..fbad080 100644
--- a/android_webview/browser/aw_render_thread_context_provider.cc
+++ b/android_webview/browser/aw_render_thread_context_provider.cc
@@ -68,7 +68,7 @@
                        gpu::kNullSurfaceHandle, nullptr /* share_context */,
                        attributes, limits, nullptr, nullptr, nullptr, nullptr);
 
-  context_->GetImplementation()->SetLostContextCallback(base::Bind(
+  context_->GetImplementation()->SetLostContextCallback(base::BindOnce(
       &AwRenderThreadContextProvider::OnLostContext, base::Unretained(this)));
 
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
diff --git a/android_webview/browser/aw_safe_browsing_whitelist_manager.cc b/android_webview/browser/aw_safe_browsing_whitelist_manager.cc
index 15990238..24bfa09 100644
--- a/android_webview/browser/aw_safe_browsing_whitelist_manager.cc
+++ b/android_webview/browser/aw_safe_browsing_whitelist_manager.cc
@@ -197,7 +197,7 @@
 // A task that builds the whitelist on a background thread.
 void AwSafeBrowsingWhitelistManager::BuildWhitelist(
     const std::vector<std::string>& rules,
-    const base::Callback<void(bool)>& callback) {
+    base::OnceCallback<void(bool)> callback) {
   DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
 
   std::unique_ptr<TrieNode> whitelist(std::make_unique<TrieNode>());
@@ -205,28 +205,29 @@
   DCHECK(!whitelist->is_terminal);
   DCHECK(!whitelist->match_prefix);
 
-  ui_task_runner_->PostTask(FROM_HERE, base::Bind(callback, success));
+  ui_task_runner_->PostTask(FROM_HERE,
+                            base::BindOnce(std::move(callback), success));
 
   if (success) {
     // use base::Unretained as AwSafeBrowsingWhitelistManager is a singleton and
     // not cleaned.
     io_task_runner_->PostTask(
         FROM_HERE,
-        base::Bind(&AwSafeBrowsingWhitelistManager::SetWhitelist,
-                   base::Unretained(this), base::Passed(std::move(whitelist))));
+        base::BindOnce(&AwSafeBrowsingWhitelistManager::SetWhitelist,
+                       base::Unretained(this), std::move(whitelist)));
   }
 }
 
 void AwSafeBrowsingWhitelistManager::SetWhitelistOnUIThread(
     std::vector<std::string>&& rules,
-    const base::Callback<void(bool)>& callback) {
+    base::OnceCallback<void(bool)> callback) {
   DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
   // use base::Unretained as AwSafeBrowsingWhitelistManager is a singleton and
   // not cleaned.
   background_task_runner_->PostTask(
-      FROM_HERE, base::Bind(&AwSafeBrowsingWhitelistManager::BuildWhitelist,
-                            base::Unretained(this),
-                            base::Passed(std::move(rules)), callback));
+      FROM_HERE, base::BindOnce(&AwSafeBrowsingWhitelistManager::BuildWhitelist,
+                                base::Unretained(this), std::move(rules),
+                                std::move(callback)));
 }
 
 bool AwSafeBrowsingWhitelistManager::IsURLWhitelisted(const GURL& url) const {
diff --git a/android_webview/browser/aw_safe_browsing_whitelist_manager.h b/android_webview/browser/aw_safe_browsing_whitelist_manager.h
index e4dfcea..3d98ebb 100644
--- a/android_webview/browser/aw_safe_browsing_whitelist_manager.h
+++ b/android_webview/browser/aw_safe_browsing_whitelist_manager.h
@@ -66,12 +66,12 @@
 
   // Replace the current host whitelist with a new one.
   void SetWhitelistOnUIThread(std::vector<std::string>&& rules,
-                              const base::Callback<void(bool)>& callback);
+                              base::OnceCallback<void(bool)> callback);
 
  private:
   // Builds whitelist on background thread.
   void BuildWhitelist(const std::vector<std::string>& rules,
-                      const base::Callback<void(bool)>& callback);
+                      base::OnceCallback<void(bool)> callback);
   // Replaces the current whitelist. Must be called on the IO thread.
   void SetWhitelist(std::unique_ptr<TrieNode> whitelist);
 
diff --git a/android_webview/browser/aw_safe_browsing_whitelist_manager_unittest.cc b/android_webview/browser/aw_safe_browsing_whitelist_manager_unittest.cc
index e862e46..c7b1f5e5 100644
--- a/android_webview/browser/aw_safe_browsing_whitelist_manager_unittest.cc
+++ b/android_webview/browser/aw_safe_browsing_whitelist_manager_unittest.cc
@@ -40,8 +40,8 @@
 void AwSafeBrowsingWhitelistManagerTest::SetWhitelist(
     std::vector<std::string>&& whitelist,
     bool expected) {
-  wm_->SetWhitelistOnUIThread(std::move(whitelist),
-                              base::Bind(&VerifyWhitelistCallback, expected));
+  wm_->SetWhitelistOnUIThread(
+      std::move(whitelist), base::BindOnce(&VerifyWhitelistCallback, expected));
 }
 
 TEST_F(AwSafeBrowsingWhitelistManagerTest, WsSchemeCanBeWhitelisted) {
diff --git a/android_webview/browser/aw_url_checker_delegate_impl.cc b/android_webview/browser/aw_url_checker_delegate_impl.cc
index 04b8625..f61d9b11 100644
--- a/android_webview/browser/aw_url_checker_delegate_impl.cc
+++ b/android_webview/browser/aw_url_checker_delegate_impl.cc
@@ -47,8 +47,8 @@
 
   content::BrowserThread::PostTask(
       content::BrowserThread::UI, FROM_HERE,
-      base::Bind(&AwUrlCheckerDelegateImpl::StartApplicationResponse,
-                 ui_manager_, resource, std::move(request)));
+      base::BindOnce(&AwUrlCheckerDelegateImpl::StartApplicationResponse,
+                     ui_manager_, resource, std::move(request)));
 }
 
 bool AwUrlCheckerDelegateImpl::IsUrlWhitelisted(const GURL& url) {
@@ -101,10 +101,12 @@
       AwContentsClientBridge::FromWebContents(web_contents);
 
   if (client) {
-    base::Callback<void(SafeBrowsingAction, bool)> callback = base::Bind(
-        &AwUrlCheckerDelegateImpl::DoApplicationResponse, ui_manager, resource);
+    base::OnceCallback<void(SafeBrowsingAction, bool)> callback =
+        base::BindOnce(&AwUrlCheckerDelegateImpl::DoApplicationResponse,
+                       ui_manager, resource);
 
-    client->OnSafeBrowsingHit(request, resource.threat_type, callback);
+    client->OnSafeBrowsingHit(request, resource.threat_type,
+                              std::move(callback));
   }
 }
 
@@ -123,7 +125,7 @@
     case SafeBrowsingAction::SHOW_INTERSTITIAL:
       content::BrowserThread::PostTask(
           content::BrowserThread::UI, FROM_HERE,
-          base::Bind(
+          base::BindOnce(
               &AwUrlCheckerDelegateImpl::StartDisplayingDefaultBlockingPage,
               ui_manager, resource));
       return;
@@ -169,7 +171,7 @@
 
   // Reporting back that it is not okay to proceed with loading the URL.
   content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
-                                   base::Bind(resource.callback, false));
+                                   base::BindOnce(resource.callback, false));
 }
 
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_variations_service_client.cc b/android_webview/browser/aw_variations_service_client.cc
index 88112c9..fc71aa4 100644
--- a/android_webview/browser/aw_variations_service_client.cc
+++ b/android_webview/browser/aw_variations_service_client.cc
@@ -31,7 +31,7 @@
 
 base::Callback<base::Version(void)>
 AwVariationsServiceClient::GetVersionForSimulationCallback() {
-  return base::Bind(&GetVersionForSimulation);
+  return base::BindRepeating(&GetVersionForSimulation);
 }
 
 net::URLRequestContextGetter*
diff --git a/android_webview/browser/browser_view_renderer_unittest.cc b/android_webview/browser/browser_view_renderer_unittest.cc
index d4af915..6d7b50d 100644
--- a/android_webview/browser/browser_view_renderer_unittest.cc
+++ b/android_webview/browser/browser_view_renderer_unittest.cc
@@ -186,9 +186,9 @@
   bool WillDrawOnRT(AwDrawGLInfo* draw_info) override {
     if (draw_gl_count_on_rt_ == 1) {
       draw_gl_count_on_rt_++;
-      ui_task_runner_->PostTask(
-          FROM_HERE,
-          base::Bind(&RenderingTest::PostInvalidate, base::Unretained(this)));
+      ui_task_runner_->PostTask(FROM_HERE,
+                                base::BindOnce(&RenderingTest::PostInvalidate,
+                                               base::Unretained(this)));
       return false;
     }
 
@@ -359,9 +359,9 @@
   void DidOnDraw(bool success) override {
     EXPECT_EQ(next_frame_ != nullptr, success);
     if (!AdvanceFrame()) {
-      ui_task_runner_->PostTask(FROM_HERE,
-                                base::Bind(&ResourceRenderingTest::CheckResults,
-                                           base::Unretained(this)));
+      ui_task_runner_->PostTask(
+          FROM_HERE, base::BindOnce(&ResourceRenderingTest::CheckResults,
+                                    base::Unretained(this)));
     }
   }
 
diff --git a/android_webview/browser/cookie_manager.cc b/android_webview/browser/cookie_manager.cc
index f03fc0bb..f92fbad3 100644
--- a/android_webview/browser/cookie_manager.cc
+++ b/android_webview/browser/cookie_manager.cc
@@ -64,8 +64,8 @@
 
 namespace {
 
-typedef base::Callback<void(bool)> BoolCallback;
-typedef base::Callback<void(int)> IntCallback;
+using BoolCallback = base::RepeatingCallback<void(bool)>;
+using IntCallback = base::RepeatingCallback<void(int)>;
 
 // Holds a Java BooleanCookieCallback, knows how to invoke it and turn it
 // into a base callback.
@@ -84,8 +84,8 @@
 
   static BoolCallback ConvertToCallback(
       std::unique_ptr<BoolCookieCallbackHolder> me) {
-    return base::Bind(&BoolCookieCallbackHolder::Invoke,
-                      base::Owned(me.release()));
+    return base::BindRepeating(&BoolCookieCallbackHolder::Invoke,
+                               base::Owned(me.release()));
   }
 
  private:
@@ -95,24 +95,25 @@
 
 // Construct a closure which signals a waitable event if and when the closure
 // is called the waitable event must still exist.
-static base::Closure SignalEventClosure(WaitableEvent* completion) {
-  return base::Bind(&WaitableEvent::Signal, base::Unretained(completion));
+static base::RepeatingClosure SignalEventClosure(WaitableEvent* completion) {
+  return base::BindRepeating(&WaitableEvent::Signal,
+                             base::Unretained(completion));
 }
 
-static void DiscardBool(const base::Closure& f, bool b) {
+static void DiscardBool(base::RepeatingClosure f, bool b) {
   f.Run();
 }
 
-static BoolCallback BoolCallbackAdapter(const base::Closure& f) {
-  return base::Bind(&DiscardBool, f);
+static BoolCallback BoolCallbackAdapter(base::RepeatingClosure f) {
+  return base::BindRepeating(&DiscardBool, std::move(f));
 }
 
-static void DiscardInt(const base::Closure& f, int i) {
+static void DiscardInt(base::RepeatingClosure f, int i) {
   f.Run();
 }
 
-static IntCallback IntCallbackAdapter(const base::Closure& f) {
-  return base::Bind(&DiscardInt, f);
+static IntCallback IntCallbackAdapter(base::RepeatingClosure f) {
+  return base::BindRepeating(&DiscardInt, std::move(f));
 }
 
 // Are cookies allowed for file:// URLs by default?
@@ -338,15 +339,16 @@
     std::unique_ptr<BoolCookieCallbackHolder> callback_holder) {
   BoolCallback callback =
       BoolCookieCallbackHolder::ConvertToCallback(std::move(callback_holder));
-  ExecCookieTask(base::Bind(&CookieManager::SetCookieHelper,
-                            base::Unretained(this), host, cookie_value,
-                            callback));
+  ExecCookieTask(base::BindOnce(&CookieManager::SetCookieHelper,
+                                base::Unretained(this), host, cookie_value,
+                                callback));
 }
 
 void CookieManager::SetCookieSync(const GURL& host,
                                   const std::string& cookie_value) {
-  ExecCookieTaskSync(base::Bind(&CookieManager::SetCookieHelper,
-                                base::Unretained(this), host, cookie_value));
+  ExecCookieTaskSync(base::BindOnce(&CookieManager::SetCookieHelper,
+                                    base::Unretained(this), host,
+                                    cookie_value));
 }
 
 void CookieManager::SetCookieHelper(const GURL& host,
@@ -407,19 +409,19 @@
     std::unique_ptr<BoolCookieCallbackHolder> callback_holder) {
   BoolCallback callback =
       BoolCookieCallbackHolder::ConvertToCallback(std::move(callback_holder));
-  ExecCookieTask(base::Bind(&CookieManager::RemoveSessionCookiesHelper,
-                            base::Unretained(this), callback));
+  ExecCookieTask(base::BindOnce(&CookieManager::RemoveSessionCookiesHelper,
+                                base::Unretained(this), callback));
 }
 
 void CookieManager::RemoveSessionCookiesSync() {
-  ExecCookieTaskSync(base::Bind(&CookieManager::RemoveSessionCookiesHelper,
-                                base::Unretained(this)));
+  ExecCookieTaskSync(base::BindOnce(&CookieManager::RemoveSessionCookiesHelper,
+                                    base::Unretained(this)));
 }
 
 void CookieManager::RemoveSessionCookiesHelper(BoolCallback callback) {
   GetCookieStore()->DeleteSessionCookiesAsync(
-      base::Bind(&CookieManager::RemoveCookiesCompleted, base::Unretained(this),
-                 callback));
+      base::BindOnce(&CookieManager::RemoveCookiesCompleted,
+                     base::Unretained(this), callback));
 }
 
 void CookieManager::RemoveCookiesCompleted(BoolCallback callback,
@@ -442,8 +444,8 @@
 
 void CookieManager::RemoveAllCookiesHelper(const BoolCallback callback) {
   GetCookieStore()->DeleteAllAsync(
-      base::Bind(&CookieManager::RemoveCookiesCompleted, base::Unretained(this),
-                 callback));
+      base::BindOnce(&CookieManager::RemoveCookiesCompleted,
+                     base::Unretained(this), callback));
 }
 
 void CookieManager::RemoveExpiredCookies() {
diff --git a/android_webview/browser/net/android_stream_reader_url_request_job.cc b/android_webview/browser/net/android_stream_reader_url_request_job.cc
index 0fb895f..f3904c0 100644
--- a/android_webview/browser/net/android_stream_reader_url_request_job.cc
+++ b/android_webview/browser/net/android_stream_reader_url_request_job.cc
@@ -110,10 +110,9 @@
 
 namespace {
 
-typedef base::Callback<void(
+using OnInputStreamOpenedCallback = base::OnceCallback<void(
     std::unique_ptr<AndroidStreamReaderURLRequestJob::Delegate>,
-    std::unique_ptr<InputStream>)>
-    OnInputStreamOpenedCallback;
+    std::unique_ptr<InputStream>)>;
 
 // static
 void OpenInputStreamOnWorkerThread(
@@ -127,8 +126,8 @@
   std::unique_ptr<InputStream> input_stream =
       delegate->OpenInputStream(env, url);
   job_thread_task_runner->PostTask(
-      FROM_HERE, base::Bind(callback, base::Passed(std::move(delegate)),
-                            base::Passed(std::move(input_stream))));
+      FROM_HERE, base::BindOnce(std::move(callback), std::move(delegate),
+                                std::move(input_stream)));
 }
 
 } // namespace
@@ -139,13 +138,13 @@
     DCHECK(delegate_obtainer_);
     delegate_obtainer_->ObtainDelegate(
         request(),
-        base::Bind(&AndroidStreamReaderURLRequestJob::DelegateObtained,
-                   weak_factory_.GetWeakPtr()));
+        base::BindOnce(&AndroidStreamReaderURLRequestJob::DelegateObtained,
+                       weak_factory_.GetWeakPtr()));
   } else {
     // Run DoStart asynchronously to avoid re-entering the delegate.
     base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::Bind(&AndroidStreamReaderURLRequestJob::DoStart,
-                              weak_factory_.GetWeakPtr()));
+        FROM_HERE, base::BindOnce(&AndroidStreamReaderURLRequestJob::DoStart,
+                                  weak_factory_.GetWeakPtr()));
   }
 }
 
@@ -188,10 +187,10 @@
 
   base::PostTaskWithTraitsAndReplyWithResult(
       FROM_HERE, {base::MayBlock()},
-      base::Bind(&InputStreamReaderWrapper::Seek, input_stream_reader_wrapper_,
-                 byte_range_),
-      base::Bind(&AndroidStreamReaderURLRequestJob::OnReaderSeekCompleted,
-                 weak_factory_.GetWeakPtr()));
+      base::BindOnce(&InputStreamReaderWrapper::Seek,
+                     input_stream_reader_wrapper_, byte_range_),
+      base::BindOnce(&AndroidStreamReaderURLRequestJob::OnReaderSeekCompleted,
+                     weak_factory_.GetWeakPtr()));
 }
 
 void AndroidStreamReaderURLRequestJob::OnReaderSeekCompleted(int result) {
@@ -223,11 +222,11 @@
 
   base::PostTaskWithTraitsAndReplyWithResult(
       FROM_HERE, {base::MayBlock()},
-      base::Bind(&InputStreamReaderWrapper::ReadRawData,
-                 input_stream_reader_wrapper_, base::RetainedRef(dest),
-                 dest_size),
-      base::Bind(&AndroidStreamReaderURLRequestJob::OnReaderReadCompleted,
-                 weak_factory_.GetWeakPtr()));
+      base::BindOnce(&InputStreamReaderWrapper::ReadRawData,
+                     input_stream_reader_wrapper_, base::RetainedRef(dest),
+                     dest_size),
+      base::BindOnce(&AndroidStreamReaderURLRequestJob::OnReaderReadCompleted,
+                     weak_factory_.GetWeakPtr()));
 
   return net::ERR_IO_PENDING;
 }
@@ -285,15 +284,15 @@
   // complex synchronization in the delegate.
   base::PostTaskWithTraits(
       FROM_HERE, {base::MayBlock()},
-      base::Bind(
+      base::BindOnce(
           &OpenInputStreamOnWorkerThread, base::ThreadTaskRunnerHandle::Get(),
           // This is intentional - the job could be deleted while the callback
           // is executing on the background thread.
           // The delegate will be "returned" to the job once the InputStream
           // open attempt is completed.
-          base::Passed(&delegate_), request()->url(),
-          base::Bind(&AndroidStreamReaderURLRequestJob::OnInputStreamOpened,
-                     weak_factory_.GetWeakPtr())));
+          std::move(delegate_), request()->url(),
+          base::BindOnce(&AndroidStreamReaderURLRequestJob::OnInputStreamOpened,
+                         weak_factory_.GetWeakPtr())));
 }
 
 void AndroidStreamReaderURLRequestJob::HeadersComplete(
diff --git a/android_webview/browser/net/android_stream_reader_url_request_job.h b/android_webview/browser/net/android_stream_reader_url_request_job.h
index aabaf315..a7e0a84 100644
--- a/android_webview/browser/net/android_stream_reader_url_request_job.h
+++ b/android_webview/browser/net/android_stream_reader_url_request_job.h
@@ -75,9 +75,9 @@
    public:
     virtual ~DelegateObtainer() {}
 
-    typedef base::Callback<void(std::unique_ptr<Delegate>)> Callback;
+    using Callback = base::OnceCallback<void(std::unique_ptr<Delegate>)>;
     virtual void ObtainDelegate(net::URLRequest* request,
-                                const Callback& callback) = 0;
+                                Callback callback) = 0;
   };
 
   AndroidStreamReaderURLRequestJob(net::URLRequest* request,
diff --git a/android_webview/browser/net/aw_cookie_store_wrapper.cc b/android_webview/browser/net/aw_cookie_store_wrapper.cc
index 37a78cc..cc3f4f8e 100644
--- a/android_webview/browser/net/aw_cookie_store_wrapper.cc
+++ b/android_webview/browser/net/aw_cookie_store_wrapper.cc
@@ -193,7 +193,7 @@
 void AwCookieStoreWrapper::SetForceKeepSessionState() {
   DCHECK(client_task_runner_->RunsTasksInCurrentSequence());
   PostTaskToCookieStoreTaskRunner(
-      base::Bind(&SetForceKeepSessionStateOnCookieThread));
+      base::BindOnce(&SetForceKeepSessionStateOnCookieThread));
 }
 
 net::CookieChangeDispatcher& AwCookieStoreWrapper::GetChangeDispatcher() {
diff --git a/android_webview/browser/net/aw_network_delegate.cc b/android_webview/browser/net/aw_network_delegate.cc
index 1955b27..658b142 100644
--- a/android_webview/browser/net/aw_network_delegate.cc
+++ b/android_webview/browser/net/aw_network_delegate.cc
@@ -79,9 +79,9 @@
         original_response_headers);
     BrowserThread::PostTask(
         BrowserThread::UI, FROM_HERE,
-        base::Bind(&OnReceivedHttpErrorOnUiThread,
-                   request_info->GetWebContentsGetterForRequest(),
-                   AwWebResourceRequest(*request), response_headers));
+        base::BindOnce(&OnReceivedHttpErrorOnUiThread,
+                       request_info->GetWebContentsGetterForRequest(),
+                       AwWebResourceRequest(*request), response_headers));
   }
   return net::OK;
 }
diff --git a/android_webview/browser/net/aw_request_interceptor.cc b/android_webview/browser/net/aw_request_interceptor.cc
index bfccbbe..d94a51d 100644
--- a/android_webview/browser/net/aw_request_interceptor.cc
+++ b/android_webview/browser/net/aw_request_interceptor.cc
@@ -86,26 +86,26 @@
       : io_thread_client_(std::move(io_thread_client)), weak_factory_(this) {}
   ~ShouldInterceptRequestAdaptor() override {}
 
-  void ObtainDelegate(net::URLRequest* request,
-                      const Callback& callback) override {
-    callback_ = callback;
+  void ObtainDelegate(net::URLRequest* request, Callback callback) override {
+    callback_ = std::move(callback);
     io_thread_client_->ShouldInterceptRequestAsync(
         // The request is only used while preparing the call, not retained.
         request,
-        base::Bind(&ShouldInterceptRequestAdaptor::WebResourceResponseObtained,
-                   // The lifetime of the DelegateObtainer is managed by
-                   // AndroidStreamReaderURLRequestJob, it might get deleted.
-                   weak_factory_.GetWeakPtr()));
+        base::BindOnce(
+            &ShouldInterceptRequestAdaptor::WebResourceResponseObtained,
+            // The lifetime of the DelegateObtainer is managed by
+            // AndroidStreamReaderURLRequestJob, it might get deleted.
+            weak_factory_.GetWeakPtr()));
   }
 
  private:
   void WebResourceResponseObtained(
       std::unique_ptr<AwWebResourceResponse> response) {
     if (response) {
-      callback_.Run(
+      std::move(callback_).Run(
           std::make_unique<StreamReaderJobDelegateImpl>(std::move(response)));
     } else {
-      callback_.Run(nullptr);
+      std::move(callback_).Run(nullptr);
     }
   }
 
diff --git a/android_webview/browser/net/aw_url_request_context_getter.cc b/android_webview/browser/net/aw_url_request_context_getter.cc
index 875f154..a10169eac 100644
--- a/android_webview/browser/net/aw_url_request_context_getter.cc
+++ b/android_webview/browser/net/aw_url_request_context_getter.cc
@@ -50,7 +50,7 @@
 #include "net/log/file_net_log_observer.h"
 #include "net/log/net_log_capture_mode.h"
 #include "net/log/net_log_util.h"
-#include "net/net_features.h"
+#include "net/net_buildflags.h"
 #include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/socket/next_proto.h"
 #include "net/ssl/channel_id_service.h"
@@ -214,13 +214,13 @@
 
   auth_server_whitelist_.Init(
       prefs::kAuthServerWhitelist, user_pref_service,
-      base::Bind(&AwURLRequestContextGetter::UpdateServerWhitelist,
-                 base::Unretained(this)));
+      base::BindRepeating(&AwURLRequestContextGetter::UpdateServerWhitelist,
+                          base::Unretained(this)));
   auth_server_whitelist_.MoveToThread(io_thread_proxy);
 
   auth_android_negotiate_account_type_.Init(
       prefs::kAuthAndroidNegotiateAccountType, user_pref_service,
-      base::Bind(
+      base::BindRepeating(
           &AwURLRequestContextGetter::UpdateAndroidAuthNegotiateAccountType,
           base::Unretained(this)));
   auth_android_negotiate_account_type_.MoveToThread(io_thread_proxy);
diff --git a/android_webview/browser/net/token_binding_manager.cc b/android_webview/browser/net/token_binding_manager.cc
index 01b1e3c..de0bcef 100644
--- a/android_webview/browser/net/token_binding_manager.cc
+++ b/android_webview/browser/net/token_binding_manager.cc
@@ -5,6 +5,7 @@
 #include "android_webview/browser/net/token_binding_manager.h"
 
 #include "android_webview/browser/aw_browser_context.h"
+#include "base/callback_helpers.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/storage_partition.h"
 #include "net/ssl/channel_id_service.h"
@@ -26,12 +27,12 @@
                         int status) {
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
-      base::Bind(callback, status, base::Owned(key->release())));
+      base::BindOnce(std::move(callback), status, base::Owned(key->release())));
 }
 
 void DeletionCompleteCallback(
     TokenBindingManager::DeletionCompleteCallback callback) {
-  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
+  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, std::move(callback));
 }
 
 void GetKeyImpl(const std::string& host,
@@ -44,8 +45,11 @@
       new std::unique_ptr<crypto::ECPrivateKey>();
   // The request will own the callback if the call to service returns
   // PENDING. The request releases the ownership before calling the callback.
-  net::CompletionCallback completion_callback = base::Bind(
-      &CompletionCallback, callback, base::Owned(request), base::Owned(key));
+  // TODO(crbug.com/714018): Update base::Bind here to BindOnce after we update
+  // net::CompletionCallback to support OnceCallback.
+  net::CompletionCallback completion_callback =
+      base::Bind(&CompletionCallback, base::Passed(&callback),
+                 base::Owned(request), base::Owned(key));
   int status =
       service->GetOrCreateChannelID(host, key, completion_callback, request);
   if (status == net::ERR_IO_PENDING) {
@@ -53,7 +57,7 @@
     return;
   }
   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
-                          base::Bind(completion_callback, status));
+                          base::BindOnce(completion_callback, status));
 }
 
 void DeleteKeyImpl(const std::string& host,
@@ -63,12 +67,14 @@
   ChannelIDService* service =
       context_getter->GetURLRequestContext()->channel_id_service();
   ChannelIDStore* store = service->GetChannelIDStore();
-  base::Closure completion_callback =
-      base::Bind(&DeletionCompleteCallback, callback);
+  base::OnceClosure completion_callback =
+      base::BindOnce(&DeletionCompleteCallback, std::move(callback));
   if (all) {
-    store->DeleteAll(completion_callback);
+    store->DeleteAll(
+        base::AdaptCallbackForRepeating(std::move(completion_callback)));
   } else {
-    store->DeleteChannelID(host, completion_callback);
+    store->DeleteChannelID(
+        host, base::AdaptCallbackForRepeating(std::move(completion_callback)));
   }
 }
 
@@ -89,7 +95,7 @@
           AwBrowserContext::GetDefault())->GetURLRequestContext();
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&GetKeyImpl, host, callback, context_getter));
+      base::BindOnce(&GetKeyImpl, host, std::move(callback), context_getter));
 }
 
 void TokenBindingManager::DeleteKey(const std::string& host,
@@ -99,7 +105,8 @@
           AwBrowserContext::GetDefault())->GetURLRequestContext();
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&DeleteKeyImpl, host, callback, context_getter, false));
+      base::BindOnce(&DeleteKeyImpl, host, std::move(callback), context_getter,
+                     false));
 }
 
 void TokenBindingManager::DeleteAllKeys(DeletionCompleteCallback callback) {
@@ -108,7 +115,8 @@
           AwBrowserContext::GetDefault())->GetURLRequestContext();
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::Bind(&DeleteKeyImpl, "", callback, context_getter, true));
+      base::BindOnce(&DeleteKeyImpl, "", std::move(callback), context_getter,
+                     true));
 }
 
 }  // namespace android_webview
diff --git a/android_webview/browser/net/token_binding_manager.h b/android_webview/browser/net/token_binding_manager.h
index 5a2fd20a..3bc0158 100644
--- a/android_webview/browser/net/token_binding_manager.h
+++ b/android_webview/browser/net/token_binding_manager.h
@@ -37,8 +37,9 @@
   // parameter is one of a network error code (see the underlying protocol
   // implementation for more), and the second parameter is the key. The
   // key is owned by the callback and be destroyed at the end of the call.
-  using KeyReadyCallback = base::Callback<void(int, crypto::ECPrivateKey* key)>;
-  using DeletionCompleteCallback = base::Callback<void(void)>;
+  using KeyReadyCallback =
+      base::OnceCallback<void(int, crypto::ECPrivateKey* key)>;
+  using DeletionCompleteCallback = base::OnceCallback<void(void)>;
 
   // Retrieve (or create if not exist) the key for the given host. The callback
   // is called asynchonously to indicate the status for the key creation and
diff --git a/android_webview/browser/permission/media_access_permission_request_unittest.cc b/android_webview/browser/permission/media_access_permission_request_unittest.cc
index 402ee34..a8cf2d24 100644
--- a/android_webview/browser/permission/media_access_permission_request_unittest.cc
+++ b/android_webview/browser/permission/media_access_permission_request_unittest.cc
@@ -54,8 +54,8 @@
     std::unique_ptr<TestMediaAccessPermissionRequest> permission_request;
     permission_request.reset(new TestMediaAccessPermissionRequest(
         request,
-        base::Bind(&MediaAccessPermissionRequestTest::Callback,
-                   base::Unretained(this)),
+        base::BindRepeating(&MediaAccessPermissionRequestTest::Callback,
+                            base::Unretained(this)),
         audio_devices, video_devices));
     return permission_request;
   }
diff --git a/android_webview/browser/permission/permission_request_handler_unittest.cc b/android_webview/browser/permission/permission_request_handler_unittest.cc
index 9f87232..c97acb14 100644
--- a/android_webview/browser/permission/permission_request_handler_unittest.cc
+++ b/android_webview/browser/permission/permission_request_handler_unittest.cc
@@ -19,8 +19,10 @@
  public:
   TestAwPermissionRequestDelegate(const GURL& origin,
                                   int64_t resources,
-                                  base::Callback<void(bool)> callback)
-      : origin_(origin), resources_(resources), callback_(callback) {}
+                                  base::RepeatingCallback<void(bool)> callback)
+      : origin_(origin),
+        resources_(resources),
+        callback_(std::move(callback)) {}
 
   // Get the origin which initiated the permission request.
   const GURL& GetOrigin() override { return origin_; }
@@ -34,7 +36,7 @@
  private:
   GURL origin_;
   int64_t resources_;
-  base::Callback<void(bool)> callback_;
+  base::RepeatingCallback<void(bool)> callback_;
 };
 
 class TestPermissionRequestHandlerClient
@@ -121,8 +123,8 @@
         AwPermissionRequest::VideoCapture | AwPermissionRequest::AudioCapture;
     delegate_.reset(new TestAwPermissionRequestDelegate(
         origin_, resources_,
-        base::Bind(&PermissionRequestHandlerTest::NotifyRequestResult,
-                   base::Unretained(this))));
+        base::BindRepeating(&PermissionRequestHandlerTest::NotifyRequestResult,
+                            base::Unretained(this))));
   }
 
   const GURL& origin() { return origin_; }
@@ -195,8 +197,8 @@
   std::unique_ptr<AwPermissionRequestDelegate> delegate1;
   delegate1.reset(new TestAwPermissionRequestDelegate(
       origin1, resources1,
-      base::Bind(&PermissionRequestHandlerTest::NotifyRequestResult,
-                 base::Unretained(this))));
+      base::BindRepeating(&PermissionRequestHandlerTest::NotifyRequestResult,
+                          base::Unretained(this))));
 
   // Send 1st request
   handler()->SendRequest(delegate());
@@ -223,8 +225,8 @@
   // Send 3rd request which has same origin and resources as first one.
   delegate1.reset(new TestAwPermissionRequestDelegate(
       origin(), resources(),
-      base::Bind(&PermissionRequestHandlerTest::NotifyRequestResult,
-                 base::Unretained(this))));
+      base::BindRepeating(&PermissionRequestHandlerTest::NotifyRequestResult,
+                          base::Unretained(this))));
   handler()->SendRequest(std::move(delegate1));
   // Verify Handler store the request correctly.
   ASSERT_EQ(3u, handler()->requests().size());
@@ -263,8 +265,8 @@
   std::unique_ptr<AwPermissionRequestDelegate> delegate;
   delegate.reset(new TestAwPermissionRequestDelegate(
       origin(), AwPermissionRequest::AudioCapture,
-      base::Bind(&PermissionRequestHandlerTest::NotifyRequestResult,
-                 base::Unretained(this))));
+      base::BindRepeating(&PermissionRequestHandlerTest::NotifyRequestResult,
+                          base::Unretained(this))));
   client()->Reset();
   handler()->SendRequest(std::move(delegate));
   EXPECT_TRUE(allowed());
@@ -280,8 +282,8 @@
   int64_t requested_resources = AwPermissionRequest::AudioCapture;
   delegate.reset(new TestAwPermissionRequestDelegate(
       origin, requested_resources,
-      base::Bind(&PermissionRequestHandlerTest::NotifyRequestResult,
-                 base::Unretained(this))));
+      base::BindRepeating(&PermissionRequestHandlerTest::NotifyRequestResult,
+                          base::Unretained(this))));
   handler()->SendRequest(std::move(delegate));
   EXPECT_EQ(origin, handler()->requests()[0]->GetOrigin());
   EXPECT_EQ(requested_resources, handler()->requests()[0]->GetResources());
@@ -298,8 +300,8 @@
       AwPermissionRequest::AudioCapture | AwPermissionRequest::Geolocation;
   delegate.reset(new TestAwPermissionRequestDelegate(
       origin(), requested_resources,
-      base::Bind(&PermissionRequestHandlerTest::NotifyRequestResult,
-                 base::Unretained(this))));
+      base::BindRepeating(&PermissionRequestHandlerTest::NotifyRequestResult,
+                          base::Unretained(this))));
 
   handler()->SendRequest(std::move(delegate));
   EXPECT_EQ(origin(), handler()->requests()[0]->GetOrigin());
@@ -317,8 +319,8 @@
   std::unique_ptr<AwPermissionRequestDelegate> delegate;
   delegate.reset(new TestAwPermissionRequestDelegate(
       origin_hostname, AwPermissionRequest::Geolocation,
-      base::Bind(&PermissionRequestHandlerTest::NotifyRequestResult,
-                 base::Unretained(this))));
+      base::BindRepeating(&PermissionRequestHandlerTest::NotifyRequestResult,
+                          base::Unretained(this))));
   handler()->SendRequest(std::move(delegate));
   EXPECT_TRUE(allowed());
   EXPECT_EQ(NULL, client()->request());
diff --git a/android_webview/browser/permission/simple_permission_request.cc b/android_webview/browser/permission/simple_permission_request.cc
index 1f76830..09ca8b2 100644
--- a/android_webview/browser/permission/simple_permission_request.cc
+++ b/android_webview/browser/permission/simple_permission_request.cc
@@ -12,13 +12,13 @@
 SimplePermissionRequest::SimplePermissionRequest(
     const GURL& origin,
     int64_t resources,
-    const base::Callback<void(bool)>& callback)
-    : origin_(origin), resources_(resources), callback_(callback) {}
+    base::OnceCallback<void(bool)> callback)
+    : origin_(origin), resources_(resources), callback_(std::move(callback)) {}
 
 SimplePermissionRequest::~SimplePermissionRequest() {}
 
 void SimplePermissionRequest::NotifyRequestResult(bool allowed) {
-  callback_.Run(allowed);
+  std::move(callback_).Run(allowed);
 }
 
 const GURL& SimplePermissionRequest::GetOrigin() {
diff --git a/android_webview/browser/permission/simple_permission_request.h b/android_webview/browser/permission/simple_permission_request.h
index b720b20..0981d98 100644
--- a/android_webview/browser/permission/simple_permission_request.h
+++ b/android_webview/browser/permission/simple_permission_request.h
@@ -19,7 +19,7 @@
  public:
   SimplePermissionRequest(const GURL& origin,
                           int64_t resources,
-                          const base::Callback<void(bool)>& callback);
+                          base::OnceCallback<void(bool)> callback);
   ~SimplePermissionRequest() override;
 
   // AwPermissionRequestDelegate implementation.
@@ -30,7 +30,7 @@
  private:
   const GURL origin_;
   int64_t resources_;
-  const base::Callback<void(bool)> callback_;
+  base::OnceCallback<void(bool)> callback_;
 
   DISALLOW_COPY_AND_ASSIGN(SimplePermissionRequest);
 };
diff --git a/android_webview/browser/render_thread_manager.cc b/android_webview/browser/render_thread_manager.cc
index 1d139ea..5ccb82c2 100644
--- a/android_webview/browser/render_thread_manager.cc
+++ b/android_webview/browser/render_thread_manager.cc
@@ -122,7 +122,7 @@
   } else {
     if (!g_request_invoke_gl_tracker.Get().ShouldRequestOnNonUiThread(this))
       return;
-    base::Closure callback;
+    base::OnceClosure callback;
     {
       base::AutoLock lock(lock_);
       callback = request_draw_gl_closure_;
@@ -131,7 +131,7 @@
     // after the next frame so that the idle work is taken care off by
     // the next frame instead.
     ui_loop_->PostDelayedTask(
-        FROM_HERE, callback,
+        FROM_HERE, std::move(callback),
         for_idle ? base::TimeDelta::FromMilliseconds(17) : base::TimeDelta());
   }
 }
@@ -143,7 +143,7 @@
 void RenderThreadManager::ResetRequestInvokeGLCallback() {
   DCHECK(ui_loop_->BelongsToCurrentThread());
   base::AutoLock lock(lock_);
-  request_draw_gl_cancelable_closure_.Reset(base::Bind(
+  request_draw_gl_cancelable_closure_.Reset(base::BindRepeating(
       &RenderThreadManager::ClientRequestInvokeGLOnUI, base::Unretained(this)));
   request_draw_gl_closure_ = request_draw_gl_cancelable_closure_.callback();
 }
@@ -222,8 +222,8 @@
   // No need to hold the lock_ during the post task.
   ui_loop_->PostTask(
       FROM_HERE,
-      base::Bind(&RenderThreadManager::UpdateParentDrawConstraintsOnUI,
-                 ui_thread_weak_ptr_));
+      base::BindOnce(&RenderThreadManager::UpdateParentDrawConstraintsOnUI,
+                     ui_thread_weak_ptr_));
 }
 
 ParentCompositorDrawConstraints
diff --git a/android_webview/browser/render_thread_manager.h b/android_webview/browser/render_thread_manager.h
index 5fc9f0e..5e39764 100644
--- a/android_webview/browser/render_thread_manager.h
+++ b/android_webview/browser/render_thread_manager.h
@@ -117,7 +117,7 @@
   bool inside_hardware_release_;
   ParentCompositorDrawConstraints parent_draw_constraints_;
   ReturnedResourcesMap returned_resources_map_;
-  base::Closure request_draw_gl_closure_;
+  base::RepeatingClosure request_draw_gl_closure_;
 
   base::WeakPtrFactory<RenderThreadManager> weak_factory_on_ui_thread_;
 
diff --git a/android_webview/browser/renderer_host/aw_render_view_host_ext.cc b/android_webview/browser/renderer_host/aw_render_view_host_ext.cc
index 47577948..a5d925d 100644
--- a/android_webview/browser/renderer_host/aw_render_view_host_ext.cc
+++ b/android_webview/browser/renderer_host/aw_render_view_host_ext.cc
@@ -37,7 +37,7 @@
 void AwRenderViewHostExt::DocumentHasImages(DocumentHasImagesResult result) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (!web_contents()->GetRenderViewHost()) {
-    result.Run(false);
+    std::move(result).Run(false);
     return;
   }
   static uint32_t next_id = 1;
@@ -46,11 +46,11 @@
   // because it only makes sense on the main frame.
   if (web_contents()->GetMainFrame()->Send(new AwViewMsg_DocumentHasImages(
           web_contents()->GetMainFrame()->GetRoutingID(), this_id))) {
-    image_requests_callback_map_[this_id] = result;
+    image_requests_callback_map_[this_id] = std::move(result);
   } else {
     // Still have to respond to the API call WebView#docuemntHasImages.
     // Otherwise the listener of the response may be starved.
-    result.Run(false);
+    std::move(result).Run(false);
   }
 }
 
@@ -136,8 +136,8 @@
 }
 
 void AwRenderViewHostExt::ClearImageRequests() {
-  for (const auto& pair : image_requests_callback_map_) {
-    pair.second.Run(false);
+  for (auto& pair : image_requests_callback_map_) {
+    std::move(pair.second).Run(false);
   }
 
   image_requests_callback_map_.clear();
@@ -145,9 +145,9 @@
 
 void AwRenderViewHostExt::RenderFrameCreated(
     content::RenderFrameHost* frame_host) {
-  registry_.AddInterface(
-      base::Bind(&web_restrictions::WebRestrictionsMojoImplementation::Create,
-                 AwBrowserContext::GetDefault()->GetWebRestrictionProvider()));
+  registry_.AddInterface(base::BindRepeating(
+      &web_restrictions::WebRestrictionsMojoImplementation::Create,
+      AwBrowserContext::GetDefault()->GetWebRestrictionProvider()));
   if (!frame_host->GetParent()) {
     frame_host->Send(new AwViewMsg_SetBackgroundColor(
         frame_host->GetRoutingID(), background_color_));
@@ -212,7 +212,7 @@
   if (pending_req == image_requests_callback_map_.end()) {
     DLOG(WARNING) << "unexpected DocumentHasImages Response: " << msg_id;
   } else {
-    pending_req->second.Run(has_images);
+    std::move(pending_req->second).Run(has_images);
     image_requests_callback_map_.erase(pending_req);
   }
 }
diff --git a/android_webview/browser/renderer_host/aw_render_view_host_ext.h b/android_webview/browser/renderer_host/aw_render_view_host_ext.h
index 911cd66..a78962d 100644
--- a/android_webview/browser/renderer_host/aw_render_view_host_ext.h
+++ b/android_webview/browser/renderer_host/aw_render_view_host_ext.h
@@ -42,7 +42,7 @@
   ~AwRenderViewHostExt() override;
 
   // |result| will be invoked with the outcome of the request.
-  typedef base::Callback<void(bool)> DocumentHasImagesResult;
+  using DocumentHasImagesResult = base::OnceCallback<void(bool)>;
   void DocumentHasImages(DocumentHasImagesResult result);
 
   // Clear all WebCore memory cache (not only for this view).
diff --git a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc
index 74c56c9..0f27fb0 100644
--- a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc
+++ b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc
@@ -357,10 +357,10 @@
     }
     BrowserThread::PostTask(
         BrowserThread::UI, FROM_HERE,
-        base::Bind(&OnReceivedErrorOnUiThread,
-                   request_info->GetWebContentsGetterForRequest(),
-                   AwWebResourceRequest(*request), request->status().error(),
-                   safebrowsing_hit));
+        base::BindOnce(&OnReceivedErrorOnUiThread,
+                       request_info->GetWebContentsGetterForRequest(),
+                       AwWebResourceRequest(*request),
+                       request->status().error(), safebrowsing_hit));
   }
 }
 
@@ -399,9 +399,10 @@
 
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
-      base::Bind(&DownloadStartingOnUIThread,
-                 request_info->GetWebContentsGetterForRequest(), url,
-                 user_agent, content_disposition, mime_type, content_length));
+      base::BindOnce(&DownloadStartingOnUIThread,
+                     request_info->GetWebContentsGetterForRequest(), url,
+                     user_agent, content_disposition, mime_type,
+                     content_length));
 }
 
 void AwResourceDispatcherHostDelegate::OnResponseStarted(
@@ -422,9 +423,10 @@
     if (ParserHeaderInResponse(request, ALLOW_ANY_REALM, &header_data)) {
       BrowserThread::PostTask(
           BrowserThread::UI, FROM_HERE,
-          base::Bind(&NewLoginRequestOnUIThread,
-                     request_info->GetWebContentsGetterForRequest(),
-                     header_data.realm, header_data.account, header_data.args));
+          base::BindOnce(&NewLoginRequestOnUIThread,
+                         request_info->GetWebContentsGetterForRequest(),
+                         header_data.realm, header_data.account,
+                         header_data.args));
     }
   }
 }
@@ -444,8 +446,9 @@
 void AwResourceDispatcherHostDelegate::OnIoThreadClientReady(
     int new_render_process_id,
     int new_render_frame_id) {
-  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
-      base::Bind(
+  BrowserThread::PostTask(
+      BrowserThread::IO, FROM_HERE,
+      base::BindOnce(
           &AwResourceDispatcherHostDelegate::OnIoThreadClientReadyInternal,
           base::Unretained(
               g_webview_resource_dispatcher_host_delegate.Pointer()),
@@ -457,8 +460,9 @@
     int render_process_id,
     int render_frame_id,
     IoThreadClientThrottle* pending_throttle) {
-  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
-      base::Bind(
+  BrowserThread::PostTask(
+      BrowserThread::IO, FROM_HERE,
+      base::BindOnce(
           &AwResourceDispatcherHostDelegate::AddPendingThrottleOnIoThread,
           base::Unretained(
               g_webview_resource_dispatcher_host_delegate.Pointer()),
diff --git a/android_webview/browser/test/fake_window.cc b/android_webview/browser/test/fake_window.cc
index 411ee217..943bbb230 100644
--- a/android_webview/browser/test/fake_window.cc
+++ b/android_webview/browser/test/fake_window.cc
@@ -65,8 +65,8 @@
         base::WaitableEvent::ResetPolicy::MANUAL,
         base::WaitableEvent::InitialState::NOT_SIGNALED);
     render_thread_loop_->PostTask(
-        FROM_HERE, base::Bind(&FakeWindow::DestroyOnRT, base::Unretained(this),
-                              &completion));
+        FROM_HERE, base::BindOnce(&FakeWindow::DestroyOnRT,
+                                  base::Unretained(this), &completion));
     completion.Wait();
   }
 
@@ -86,8 +86,8 @@
       base::WaitableEvent::InitialState::NOT_SIGNALED);
   render_thread_loop_->PostTask(
       FROM_HERE,
-      base::Bind(&FakeWindow::InvokeFunctorOnRT, base::Unretained(this),
-                 functor, wait_for_completion ? &completion : nullptr));
+      base::BindOnce(&FakeWindow::InvokeFunctorOnRT, base::Unretained(this),
+                     functor, wait_for_completion ? &completion : nullptr));
   if (wait_for_completion)
     completion.Wait();
 }
@@ -103,9 +103,9 @@
 
 void FakeWindow::RequestDrawGL(FakeFunctor* functor) {
   CheckCurrentlyOnUIThread();
-  render_thread_loop_->PostTask(FROM_HERE,
-                                base::Bind(&FakeWindow::ProcessDrawOnRT,
-                                           base::Unretained(this), functor));
+  render_thread_loop_->PostTask(
+      FROM_HERE, base::BindOnce(&FakeWindow::ProcessDrawOnRT,
+                                base::Unretained(this), functor));
 }
 
 void FakeWindow::PostInvalidate() {
@@ -114,8 +114,8 @@
     return;
   on_draw_hardware_pending_ = true;
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE,
-      base::Bind(&FakeWindow::OnDrawHardware, weak_ptr_factory_.GetWeakPtr()));
+      FROM_HERE, base::BindOnce(&FakeWindow::OnDrawHardware,
+                                weak_ptr_factory_.GetWeakPtr()));
 }
 
 void FakeWindow::OnDrawHardware() {
@@ -135,8 +135,9 @@
         base::WaitableEvent::ResetPolicy::MANUAL,
         base::WaitableEvent::InitialState::NOT_SIGNALED);
     render_thread_loop_->PostTask(
-        FROM_HERE, base::Bind(&FakeWindow::DrawFunctorOnRT,
-                              base::Unretained(this), functor, &completion));
+        FROM_HERE,
+        base::BindOnce(&FakeWindow::DrawFunctorOnRT, base::Unretained(this),
+                       functor, &completion));
     completion.Wait();
   }
 }
@@ -179,8 +180,8 @@
       base::WaitableEvent::ResetPolicy::MANUAL,
       base::WaitableEvent::InitialState::NOT_SIGNALED);
   render_thread_loop_->PostTask(
-      FROM_HERE, base::Bind(&FakeWindow::InitializeOnRT, base::Unretained(this),
-                            &completion));
+      FROM_HERE, base::BindOnce(&FakeWindow::InitializeOnRT,
+                                base::Unretained(this), &completion));
   completion.Wait();
 }
 
@@ -220,8 +221,9 @@
     std::unique_ptr<RenderThreadManager> render_thread_manager) {
   window_ = window;
   render_thread_manager_ = std::move(render_thread_manager);
-  callback_ = base::Bind(&RenderThreadManager::DrawGL,
-                         base::Unretained(render_thread_manager_.get()));
+  callback_ =
+      base::BindRepeating(&RenderThreadManager::DrawGL,
+                          base::Unretained(render_thread_manager_.get()));
 }
 
 void FakeFunctor::Sync(const gfx::Rect& location,
diff --git a/android_webview/browser/test/fake_window.h b/android_webview/browser/test/fake_window.h
index 8f53975..0f1eea8 100644
--- a/android_webview/browser/test/fake_window.h
+++ b/android_webview/browser/test/fake_window.h
@@ -98,7 +98,7 @@
 
 class FakeFunctor : public RenderThreadManagerClient {
  public:
-  using DrawGLCallback = base::Callback<void(AwDrawGLInfo*)>;
+  using DrawGLCallback = base::RepeatingCallback<void(AwDrawGLInfo*)>;
 
   FakeFunctor();
   ~FakeFunctor() override;
diff --git a/android_webview/browser/test/rendering_test.cc b/android_webview/browser/test/rendering_test.cc
index 9561a29..23eeb78a 100644
--- a/android_webview/browser/test/rendering_test.cc
+++ b/android_webview/browser/test/rendering_test.cc
@@ -96,8 +96,8 @@
 void RenderingTest::RunTest() {
   SetUpTestHarness();
 
-  ui_task_runner_->PostTask(
-      FROM_HERE, base::Bind(&RenderingTest::StartTest, base::Unretained(this)));
+  ui_task_runner_->PostTask(FROM_HERE, base::BindOnce(&RenderingTest::StartTest,
+                                                      base::Unretained(this)));
   run_loop_.Run();
 }
 
diff --git a/android_webview/browser/token_binding_manager_bridge.cc b/android_webview/browser/token_binding_manager_bridge.cc
index 6fa49eb..73d93f6 100644
--- a/android_webview/browser/token_binding_manager_bridge.cc
+++ b/android_webview/browser/token_binding_manager_bridge.cc
@@ -80,9 +80,9 @@
   j_callback.Reset(env, callback);
 
   TokenBindingManager::KeyReadyCallback key_callback =
-      base::Bind(&OnKeyReady, j_callback);
+      base::BindOnce(&OnKeyReady, j_callback);
   TokenBindingManager::GetInstance()->GetKey(ConvertJavaStringToUTF8(env, host),
-                                             key_callback);
+                                             std::move(key_callback));
 }
 
 static void JNI_AwTokenBindingManager_DeleteTokenBindingKey(
@@ -96,9 +96,9 @@
   ScopedJavaGlobalRef<jobject> j_callback;
   j_callback.Reset(env, callback);
   TokenBindingManager::DeletionCompleteCallback complete_callback =
-      base::Bind(&OnDeletionComplete, j_callback);
+      base::BindOnce(&OnDeletionComplete, j_callback);
   TokenBindingManager::GetInstance()->DeleteKey(
-      ConvertJavaStringToUTF8(env, host), complete_callback);
+      ConvertJavaStringToUTF8(env, host), std::move(complete_callback));
 }
 
 static void JNI_AwTokenBindingManager_DeleteAllTokenBindingKeys(
@@ -111,8 +111,9 @@
   ScopedJavaGlobalRef<jobject> j_callback;
   j_callback.Reset(env, callback);
   TokenBindingManager::DeletionCompleteCallback complete_callback =
-      base::Bind(&OnDeletionComplete, j_callback);
-  TokenBindingManager::GetInstance()->DeleteAllKeys(complete_callback);
+      base::BindOnce(&OnDeletionComplete, j_callback);
+  TokenBindingManager::GetInstance()->DeleteAllKeys(
+      std::move(complete_callback));
 }
 
 }  // namespace android_webview
diff --git a/android_webview/browser/tracing/aw_trace_event_args_whitelist.cc b/android_webview/browser/tracing/aw_trace_event_args_whitelist.cc
index 4436ce6..64dfe5d2 100644
--- a/android_webview/browser/tracing/aw_trace_event_args_whitelist.cc
+++ b/android_webview/browser/tracing/aw_trace_event_args_whitelist.cc
@@ -60,8 +60,8 @@
                              whitelist_entry.category_name) &&
           base::MatchPattern(event_name, whitelist_entry.event_name)) {
         if (whitelist_entry.arg_name_filter) {
-          *arg_name_filter = base::Bind(&IsTraceArgumentNameWhitelisted,
-                                        whitelist_entry.arg_name_filter);
+          *arg_name_filter = base::BindRepeating(
+              &IsTraceArgumentNameWhitelisted, whitelist_entry.arg_name_filter);
         }
         return true;
       }
diff --git a/android_webview/browser/tracing/aw_tracing_controller.cc b/android_webview/browser/tracing/aw_tracing_controller.cc
index 74aa5ff..d045abb 100644
--- a/android_webview/browser/tracing/aw_tracing_controller.cc
+++ b/android_webview/browser/tracing/aw_tracing_controller.cc
@@ -30,34 +30,35 @@
 class AwTraceDataEndpoint
     : public content::TracingController::TraceDataEndpoint {
  public:
-  typedef base::Callback<void(std::unique_ptr<std::string>)>
-      ReceivedChunkCallback;
-  typedef base::Callback<void(std::unique_ptr<const base::DictionaryValue>)>
-      CompletedCallback;
+  using ReceivedChunkCallback =
+      base::RepeatingCallback<void(std::unique_ptr<std::string>)>;
+  using CompletedCallback =
+      base::OnceCallback<void(std::unique_ptr<const base::DictionaryValue>)>;
 
   static scoped_refptr<content::TracingController::TraceDataEndpoint> Create(
       ReceivedChunkCallback received_chunk_callback,
       CompletedCallback completed_callback) {
-    return new AwTraceDataEndpoint(received_chunk_callback, completed_callback);
+    return new AwTraceDataEndpoint(std::move(received_chunk_callback),
+                                   std::move(completed_callback));
   }
 
   void ReceiveTraceFinalContents(
       std::unique_ptr<const base::DictionaryValue> metadata) override {
     content::BrowserThread::PostTask(
         content::BrowserThread::UI, FROM_HERE,
-        base::Bind(completed_callback_, base::Passed(std::move(metadata))));
+        base::BindOnce(std::move(completed_callback_), std::move(metadata)));
   }
 
   void ReceiveTraceChunk(std::unique_ptr<std::string> chunk) override {
     content::BrowserThread::PostTask(
         content::BrowserThread::UI, FROM_HERE,
-        base::Bind(received_chunk_callback_, base::Passed(std::move(chunk))));
+        base::BindOnce(received_chunk_callback_, std::move(chunk)));
   }
 
   explicit AwTraceDataEndpoint(ReceivedChunkCallback received_chunk_callback,
                                CompletedCallback completed_callback)
-      : received_chunk_callback_(received_chunk_callback),
-        completed_callback_(completed_callback) {}
+      : received_chunk_callback_(std::move(received_chunk_callback)),
+        completed_callback_(std::move(completed_callback)) {}
 
  private:
   ~AwTraceDataEndpoint() override {}
@@ -101,10 +102,10 @@
                                        const JavaParamRef<jobject>& obj) {
   return content::TracingController::GetInstance()->StopTracing(
       AwTraceDataEndpoint::Create(
-          base::Bind(&AwTracingController::OnTraceDataReceived,
-                     weak_factory_.GetWeakPtr()),
-          base::Bind(&AwTracingController::OnTraceDataComplete,
-                     weak_factory_.GetWeakPtr())));
+          base::BindRepeating(&AwTracingController::OnTraceDataReceived,
+                              weak_factory_.GetWeakPtr()),
+          base::BindOnce(&AwTracingController::OnTraceDataComplete,
+                         weak_factory_.GetWeakPtr())));
 }
 
 void AwTracingController::OnTraceDataComplete(
diff --git a/android_webview/java/src/org/chromium/android_webview/AwAutofillProvider.java b/android_webview/java/src/org/chromium/android_webview/AwAutofillProvider.java
index 13a8b32..d2d30ba 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwAutofillProvider.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwAutofillProvider.java
@@ -17,6 +17,7 @@
 import android.view.ViewStructure;
 import android.view.autofill.AutofillValue;
 
+import org.chromium.base.BuildInfo;
 import org.chromium.base.ThreadUtils;
 import org.chromium.components.autofill.AutofillProvider;
 import org.chromium.components.autofill.FormData;
@@ -262,7 +263,9 @@
         // Check focusField inside short value?
         // Autofill Manager might have session that wasn't started by WebView,
         // we just always cancel existing session here.
-        mAutofillManager.cancel();
+        if (!BuildInfo.isAtLeastP()) {
+            mAutofillManager.cancel();
+        }
         Rect absBound = transformToWindowBounds(new RectF(x, y, x + width, y + height));
         mRequest = new AutofillRequest(formData, new FocusField((short) focus, absBound));
         int virtualId = mRequest.getVirtualId((short) focus);
@@ -428,11 +431,4 @@
         return new Rect(
                 (int) bounds.left, (int) bounds.top, (int) bounds.right, (int) bounds.bottom);
     }
-
-    @VisibleForTesting
-    public void fireSelectControlDidChangeForTesting(
-            int selectControlIndex, String selectControlId, String[] options, int selectedOption) {
-        nativeFireSelectControlDidChangeForTesting(mNativeAutofillProvider, selectControlIndex,
-                selectControlId, options, selectedOption);
-    }
 }
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java
index 57dbbb5..040d7c2 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContents.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -3591,15 +3591,6 @@
     }
 
     //--------------------------------------------------------------------------------------------
-    //  Methods which is only for testing
-    //--------------------------------------------------------------------------------------------
-
-    @VisibleForTesting
-    public AwAutofillProvider getAwAutofillProviderForTesting() {
-        return (AwAutofillProvider) mAutofillProvider;
-    }
-
-    //--------------------------------------------------------------------------------------------
     //  Native methods
     //--------------------------------------------------------------------------------------------
 
diff --git a/android_webview/java/src/org/chromium/android_webview/PopupTouchHandleDrawable.java b/android_webview/java/src/org/chromium/android_webview/PopupTouchHandleDrawable.java
index 30d83fc3..03bd781 100644
--- a/android_webview/java/src/org/chromium/android_webview/PopupTouchHandleDrawable.java
+++ b/android_webview/java/src/org/chromium/android_webview/PopupTouchHandleDrawable.java
@@ -120,8 +120,9 @@
         mDrawableObserverList.addObserver(this);
 
         mContentViewCore = contentViewCore;
+        mWebContents = mContentViewCore.getWebContents();
 
-        WindowAndroid windowAndroid = mContentViewCore.getWindowAndroid();
+        WindowAndroid windowAndroid = mWebContents.getTopLevelNativeWindow();
         mDeviceScale = windowAndroid.getDisplay().getDipScale();
 
         mContainer = new PopupWindow(
@@ -176,7 +177,6 @@
                 destroy();
             }
         };
-        mWebContents = mContentViewCore.getWebContents();
         GestureListenerManager.fromWebContents(mWebContents).addListener(mGestureStateListener);
         mNativeDrawable = nativeInit(HandleViewResources.getHandleHorizontalPaddingRatio());
     }
@@ -518,7 +518,7 @@
         mAttachedToWindow = true;
         onVisibilityInputChanged();
 
-        WindowAndroid windowAndroid = mContentViewCore.getWindowAndroid();
+        WindowAndroid windowAndroid = mWebContents.getTopLevelNativeWindow();
         if (windowAndroid != null) {
             windowAndroid.getDisplay().addObserver(this);
             mDeviceScale = windowAndroid.getDisplay().getDipScale();
@@ -530,7 +530,7 @@
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
 
-        WindowAndroid windowAndroid = mContentViewCore.getWindowAndroid();
+        WindowAndroid windowAndroid = mWebContents.getTopLevelNativeWindow();
         if (windowAndroid != null) windowAndroid.getDisplay().removeObserver(this);
 
         mAttachedToWindow = false;
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java
index 016fabf..eaf65381 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java
@@ -41,6 +41,7 @@
 import org.chromium.android_webview.AwContentsClient.AwWebResourceRequest;
 import org.chromium.android_webview.AwWebResourceResponse;
 import org.chromium.android_webview.test.AwActivityTestRule.TestDependencyFactory;
+import org.chromium.base.BuildInfo;
 import org.chromium.base.Log;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.CallbackHelper;
@@ -768,7 +769,12 @@
             assertEquals(1, values.size());
             assertEquals("a", values.get(0).second.getTextValue());
             executeJavaScriptAndWaitForResult("document.getElementById('text1').value='c';");
-            assertEquals(5, getCallbackCount());
+            if (BuildInfo.isAtLeastP()) {
+                // There is no AUTOFILL_CANCEL from Android P.
+                assertEquals(4, getCallbackCount());
+            } else {
+                assertEquals(5, getCallbackCount());
+            }
             dispatchDownAndUpKeyEvents(KeyEvent.KEYCODE_B);
             // Check if NotifyVirtualValueChanged() called one more time and value is 'cb', this
             // means javascript change didn't trigger the NotifyVirtualValueChanged().
@@ -1101,8 +1107,10 @@
                     new Integer[] {AUTOFILL_CANCEL, AUTOFILL_VIEW_ENTERED, AUTOFILL_VIEW_EXITED,
                             AUTOFILL_VIEW_ENTERED, AUTOFILL_VALUE_CHANGED});
             clearChangedValues();
-            mAwContents.getAwAutofillProviderForTesting().fireSelectControlDidChangeForTesting(
-                    1, "color", new String[] {"red", "blue"}, 1);
+            executeJavaScriptAndWaitForResult("document.getElementById('color').focus();");
+            dispatchDownAndUpKeyEvents(KeyEvent.KEYCODE_DPAD_CENTER);
+            // Use key B to select 'blue'.
+            dispatchDownAndUpKeyEvents(KeyEvent.KEYCODE_B);
             cnt += waitForCallbackAndVerifyTypes(cnt,
                     new Integer[] {
                             AUTOFILL_VIEW_EXITED, AUTOFILL_VIEW_ENTERED, AUTOFILL_VALUE_CHANGED});
@@ -1135,8 +1143,9 @@
             final String url = webServer.setResponse(FILE, data, null);
             loadUrlSync(url);
             // Change select control first shall start autofill session.
-            mAwContents.getAwAutofillProviderForTesting().fireSelectControlDidChangeForTesting(
-                    1, "color", new String[] {"red", "blue"}, 1);
+            dispatchDownAndUpKeyEvents(KeyEvent.KEYCODE_DPAD_CENTER);
+            // Use key B to select 'blue'.
+            dispatchDownAndUpKeyEvents(KeyEvent.KEYCODE_B);
             cnt += waitForCallbackAndVerifyTypes(cnt,
                     new Integer[] {AUTOFILL_CANCEL, AUTOFILL_VIEW_ENTERED, AUTOFILL_VIEW_EXITED,
                             AUTOFILL_VIEW_ENTERED, AUTOFILL_VALUE_CHANGED});
@@ -1207,23 +1216,35 @@
      */
     private int waitForCallbackAndVerifyTypes(int currentCallCount, Integer[] expectedEventArray)
             throws InterruptedException, TimeoutException {
+        Integer[] adjustedEventArray;
+        // Didn't call cancel after Android P.
+        if (BuildInfo.isAtLeastP()) {
+            ArrayList<Integer> adjusted = new ArrayList<Integer>();
+            for (Integer event : expectedEventArray) {
+                if (event != AUTOFILL_CANCEL) adjusted.add(event);
+            }
+            adjustedEventArray = new Integer[adjusted.size()];
+            adjusted.toArray(adjustedEventArray);
+        } else {
+            adjustedEventArray = expectedEventArray;
+        }
         try {
             // Check against the call count to avoid missing out a callback in between waits, while
             // exposing it so that the test can control where the call count starts.
-            mCallbackHelper.waitForCallback(currentCallCount, expectedEventArray.length);
+            mCallbackHelper.waitForCallback(currentCallCount, adjustedEventArray.length);
             Object[] objectArray = mEventQueue.toArray();
             mEventQueue.clear();
             Integer[] resultArray = Arrays.copyOf(objectArray, objectArray.length, Integer[].class);
-            Assert.assertArrayEquals("Expect: " + Arrays.toString(expectedEventArray)
+            Assert.assertArrayEquals("Expect: " + Arrays.toString(adjustedEventArray)
                             + " Result: " + Arrays.toString(resultArray),
-                    expectedEventArray, resultArray);
-            return expectedEventArray.length;
+                    adjustedEventArray, resultArray);
+            return adjustedEventArray.length;
         } catch (TimeoutException e) {
             Object[] objectArray = mEventQueue.toArray();
             Integer[] resultArray = Arrays.copyOf(objectArray, objectArray.length, Integer[].class);
-            Assert.assertArrayEquals("Expect:" + Arrays.toString(expectedEventArray)
+            Assert.assertArrayEquals("Expect:" + Arrays.toString(adjustedEventArray)
                             + " Result:" + Arrays.toString(resultArray),
-                    expectedEventArray, resultArray);
+                    adjustedEventArray, resultArray);
             throw e;
         }
     }
diff --git a/android_webview/lib/aw_main_delegate.cc b/android_webview/lib/aw_main_delegate.cc
index aade6bc96..c8c4a95e 100644
--- a/android_webview/lib/aw_main_delegate.cc
+++ b/android_webview/lib/aw_main_delegate.cc
@@ -47,7 +47,7 @@
 #include "gpu/command_buffer/service/gpu_switches.h"
 #include "gpu/ipc/gl_in_process_context.h"
 #include "media/base/media_switches.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/events/gesture_detection/gesture_configuration.h"
 
@@ -187,7 +187,7 @@
   // Used only if the argument filter is enabled in tracing config,
   // as is the case by default in aw_tracing_controller.cc
   base::trace_event::TraceLog::GetInstance()->SetArgumentFilterPredicate(
-      base::Bind(&IsTraceEventArgsWhitelisted));
+      base::BindRepeating(&IsTraceEventArgsWhitelisted));
 
   return false;
 }
@@ -294,7 +294,7 @@
 
 content::ContentGpuClient* AwMainDelegate::CreateContentGpuClient() {
   content_gpu_client_.reset(
-      new AwContentGpuClient(base::Bind(&GetSyncPointManager)));
+      new AwContentGpuClient(base::BindRepeating(&GetSyncPointManager)));
   return content_gpu_client_.get();
 }
 
diff --git a/android_webview/support_library/boundary_interfaces/BUILD.gn b/android_webview/support_library/boundary_interfaces/BUILD.gn
index 9b36892..07c3cb67 100644
--- a/android_webview/support_library/boundary_interfaces/BUILD.gn
+++ b/android_webview/support_library/boundary_interfaces/BUILD.gn
@@ -14,6 +14,7 @@
     "src/org/chromium/support_lib_boundary/SupportLibraryInfoBoundaryInterface.java",
     "src/org/chromium/support_lib_boundary/VisualStateCallbackBoundaryInterface.java",
     "src/org/chromium/support_lib_boundary/WebSettingsBoundaryInterface.java",
+    "src/org/chromium/support_lib_boundary/WebViewClientBoundaryInterface.java",
     "src/org/chromium/support_lib_boundary/WebViewProviderBoundaryInterface.java",
     "src/org/chromium/support_lib_boundary/WebViewProviderFactoryBoundaryInterface.java",
     "src/org/chromium/support_lib_boundary/WebkitToCompatConverterBoundaryInterface.java",
diff --git a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/WebViewClientBoundaryInterface.java b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/WebViewClientBoundaryInterface.java
new file mode 100644
index 0000000..2fccfe4
--- /dev/null
+++ b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/WebViewClientBoundaryInterface.java
@@ -0,0 +1,25 @@
+// Copyright 2018 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.
+
+package org.chromium.support_lib_boundary;
+
+import android.webkit.WebResourceRequest;
+import android.webkit.WebResourceResponse;
+import android.webkit.WebView;
+
+import java.lang.reflect.InvocationHandler;
+
+/**
+ * Boundary interface for WebViewClientCompat.
+ */
+public interface WebViewClientBoundaryInterface {
+    void onPageCommitVisible(WebView view, String url);
+    void onReceivedError(WebView view, WebResourceRequest request,
+            /* WebResourceError */ InvocationHandler error);
+    void onReceivedHttpError(
+            WebView view, WebResourceRequest request, WebResourceResponse errorResponse);
+    void onSafeBrowsingHit(WebView view, WebResourceRequest request, int threatType,
+            /* SafeBrowsingResponse */ InvocationHandler callback);
+    boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request);
+}
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index a84acc5c..bead388 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -275,6 +275,8 @@
     "login/ui/animated_rounded_image_view.cc",
     "login/ui/animated_rounded_image_view.h",
     "login/ui/animation_frame.h",
+    "login/ui/arrow_button_view.cc",
+    "login/ui/arrow_button_view.h",
     "login/ui/hover_notifier.cc",
     "login/ui/hover_notifier.h",
     "login/ui/image_parser.cc",
@@ -293,6 +295,8 @@
     "login/ui/login_auth_user_view.h",
     "login/ui/login_base_bubble_view.cc",
     "login/ui/login_base_bubble_view.h",
+    "login/ui/login_big_user_view.cc",
+    "login/ui/login_big_user_view.h",
     "login/ui/login_bubble.cc",
     "login/ui/login_bubble.h",
     "login/ui/login_button.cc",
@@ -305,6 +309,8 @@
     "login/ui/login_password_view.h",
     "login/ui/login_pin_view.cc",
     "login/ui/login_pin_view.h",
+    "login/ui/login_public_account_user_view.cc",
+    "login/ui/login_public_account_user_view.h",
     "login/ui/login_user_view.cc",
     "login/ui/login_user_view.h",
     "login/ui/non_accessible_view.cc",
@@ -847,8 +853,16 @@
     "wallpaper/wallpaper_controller.cc",
     "wallpaper/wallpaper_controller.h",
     "wallpaper/wallpaper_controller_observer.h",
-    "wallpaper/wallpaper_decoder.cc",
-    "wallpaper/wallpaper_decoder.h",
+    "wallpaper/wallpaper_info.h",
+    "wallpaper/wallpaper_utils/wallpaper_color_calculator.cc",
+    "wallpaper/wallpaper_utils/wallpaper_color_calculator.h",
+    "wallpaper/wallpaper_utils/wallpaper_color_calculator_observer.h",
+    "wallpaper/wallpaper_utils/wallpaper_color_extraction_result.h",
+    "wallpaper/wallpaper_utils/wallpaper_decoder.cc",
+    "wallpaper/wallpaper_utils/wallpaper_decoder.h",
+    "wallpaper/wallpaper_utils/wallpaper_resizer.cc",
+    "wallpaper/wallpaper_utils/wallpaper_resizer.h",
+    "wallpaper/wallpaper_utils/wallpaper_resizer_observer.h",
     "wallpaper/wallpaper_view.cc",
     "wallpaper/wallpaper_view.h",
     "wallpaper/wallpaper_widget_controller.cc",
@@ -1160,7 +1174,6 @@
     "//components/vector_icons",
     "//components/viz/host",
     "//components/viz/service",
-    "//components/wallpaper",
     "//device/bluetooth",
     "//extensions/common:common_constants",
     "//gpu/command_buffer/client",
@@ -1616,6 +1629,8 @@
     "virtual_keyboard_controller_unittest.cc",
     "voice_interaction/voice_interaction_controller_unittest.cc",
     "wallpaper/wallpaper_controller_unittest.cc",
+    "wallpaper/wallpaper_utils/wallpaper_color_calculator_unittest.cc",
+    "wallpaper/wallpaper_utils/wallpaper_resizer_unittest.cc",
     "window_manager_common_unittests.cc",
     "window_user_data_unittest.cc",
     "wm/always_on_top_controller_unittest.cc",
diff --git a/ash/accelerators/debug_commands.cc b/ash/accelerators/debug_commands.cc
index c52b194a..49032e82 100644
--- a/ash/accelerators/debug_commands.cc
+++ b/ash/accelerators/debug_commands.cc
@@ -109,9 +109,8 @@
   static int index = 0;
   WallpaperController* wallpaper_controller =
       Shell::Get()->wallpaper_controller();
-  wallpaper::WallpaperInfo info("", wallpaper::WALLPAPER_LAYOUT_STRETCH,
-                                wallpaper::DEFAULT,
-                                base::Time::Now().LocalMidnight());
+  WallpaperInfo info("", WALLPAPER_LAYOUT_STRETCH, DEFAULT,
+                     base::Time::Now().LocalMidnight());
   switch (++index % 4) {
     case 0:
       wallpaper_controller->ShowDefaultWallpaperForTesting();
@@ -122,13 +121,13 @@
           false /*preview_mode=*/);
       break;
     case 2:
-      info.layout = wallpaper::WALLPAPER_LAYOUT_CENTER;
+      info.layout = WALLPAPER_LAYOUT_CENTER;
       wallpaper_controller->ShowWallpaperImage(
           CreateWallpaperImage(SK_ColorBLUE, SK_ColorGREEN), info,
           false /*preview_mode=*/);
       break;
     case 3:
-      info.layout = wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED;
+      info.layout = WALLPAPER_LAYOUT_CENTER_CROPPED;
       wallpaper_controller->ShowWallpaperImage(
           CreateWallpaperImage(SK_ColorGREEN, SK_ColorRED), info,
           false /*preview_mode=*/);
diff --git a/ash/accessibility/accessibility_controller.cc b/ash/accessibility/accessibility_controller.cc
index ab7efae..464702f 100644
--- a/ash/accessibility/accessibility_controller.cc
+++ b/ash/accessibility/accessibility_controller.cc
@@ -23,7 +23,6 @@
 #include "ash/sticky_keys/sticky_keys_controller.h"
 #include "ash/system/power/backlights_forced_off_setter.h"
 #include "ash/system/power/scoped_backlights_forced_off.h"
-#include "ash/touch/touch_devices_controller.h"
 #include "chromeos/audio/cras_audio_handler.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_change_registrar.h"
@@ -675,14 +674,6 @@
   Shell::Get()->sticky_keys_controller()->Enable(enabled);
 }
 
-void AccessibilityController::SetTapDraggingEnabled(bool enabled) {
-  Shell::Get()->touch_devices_controller()->SetTapDraggingEnabled(enabled);
-}
-
-bool AccessibilityController::IsTapDraggingEnabled() const {
-  return Shell::Get()->touch_devices_controller()->GetTapDraggingEnabled();
-}
-
 void AccessibilityController::UpdateVirtualKeyboardFromPref() {
   PrefService* prefs = GetActivePrefService();
   const bool enabled =
diff --git a/ash/accessibility/accessibility_controller.h b/ash/accessibility/accessibility_controller.h
index 65c39dd..38cef0a 100644
--- a/ash/accessibility/accessibility_controller.h
+++ b/ash/accessibility/accessibility_controller.h
@@ -82,9 +82,6 @@
   void SetStickyKeysEnabled(bool enabled);
   bool IsStickyKeysEnabled() const;
 
-  void SetTapDraggingEnabled(bool enabled);
-  bool IsTapDraggingEnabled() const;
-
   void SetVirtualKeyboardEnabled(bool enabled);
   bool IsVirtualKeyboardEnabled() const;
 
@@ -129,8 +126,8 @@
   // countdown.
   void PlaySpokenFeedbackToggleCountdown(int tick_count);
 
-  // Public because a11y features like screen magnifier and tap dragging are
-  // managed outside of this controller.
+  // Public because a11y features like screen magnifier are managed outside of
+  // this controller.
   void NotifyAccessibilityStatusChanged(
       AccessibilityNotificationVisibility notify);
 
diff --git a/ash/accessibility/accessibility_controller_unittest.cc b/ash/accessibility/accessibility_controller_unittest.cc
index 4aa8bd0..fe5ac81 100644
--- a/ash/accessibility/accessibility_controller_unittest.cc
+++ b/ash/accessibility/accessibility_controller_unittest.cc
@@ -298,26 +298,6 @@
   controller->RemoveObserver(&observer);
 }
 
-TEST_F(AccessibilityControllerTest, SetTapDraggingEnabled) {
-  AccessibilityController* controller =
-      Shell::Get()->accessibility_controller();
-  EXPECT_FALSE(controller->IsTapDraggingEnabled());
-
-  TestAccessibilityObserver observer;
-  controller->AddObserver(&observer);
-  EXPECT_EQ(0, observer.notification_none_changed_);
-
-  controller->SetTapDraggingEnabled(true);
-  EXPECT_TRUE(controller->IsTapDraggingEnabled());
-  EXPECT_EQ(1, observer.notification_none_changed_);
-
-  controller->SetTapDraggingEnabled(false);
-  EXPECT_FALSE(controller->IsTapDraggingEnabled());
-  EXPECT_EQ(2, observer.notification_none_changed_);
-
-  controller->RemoveObserver(&observer);
-}
-
 TEST_F(AccessibilityControllerTest, SetVirtualKeyboardEnabled) {
   AccessibilityController* controller =
       Shell::Get()->accessibility_controller();
diff --git a/ash/app_list/model/app_list_item_list.cc b/ash/app_list/model/app_list_item_list.cc
index 76ba3ad..71cf9f45 100644
--- a/ash/app_list/model/app_list_item_list.cc
+++ b/ash/app_list/model/app_list_item_list.cc
@@ -218,10 +218,8 @@
 }
 
 void AppListItemList::DeleteAllItems() {
-  if (app_list_items_.empty())
-    return;
-  for (size_t index = app_list_items_.size() - 1; index >= 0; --index)
-    DeleteItemAt(index);
+  while (!app_list_items_.empty())
+    DeleteItemAt(app_list_items_.size() - 1);
 }
 
 void AppListItemList::EnsureValidItemPosition(AppListItem* item) {
diff --git a/ash/app_list/model/search/search_result.h b/ash/app_list/model/search/search_result.h
index e8aa2fbb..c89a0cc 100644
--- a/ash/app_list/model/search/search_result.h
+++ b/ash/app_list/model/search/search_result.h
@@ -98,11 +98,6 @@
   const Actions& actions() const { return actions_; }
   void SetActions(const Actions& sets);
 
-  // Whether the result can be automatically selected by a voice query.
-  // (Non-voice results can still appear in the results list to be manually
-  // selected.)
-  bool voice_result() const { return voice_result_; }
-
   bool is_installing() const { return is_installing_; }
   void SetIsInstalling(bool is_installing);
 
@@ -145,7 +140,6 @@
   void set_comparable_id(const std::string& comparable_id) {
     comparable_id_ = comparable_id;
   }
-  void set_voice_result(bool voice_result) { voice_result_ = voice_result; }
 
  private:
   friend class SearchController;
@@ -189,7 +183,6 @@
   int distance_from_origin_ = -1;
 
   Actions actions_;
-  bool voice_result_ = false;
 
   bool is_installing_ = false;
   int percent_downloaded_ = 0;
diff --git a/ash/ash_layout_constants.cc b/ash/ash_layout_constants.cc
index 0b696159..c5fcdab2 100644
--- a/ash/ash_layout_constants.cc
+++ b/ash/ash_layout_constants.cc
@@ -8,27 +8,20 @@
 #include "ui/base/material_design/material_design_controller.h"
 
 gfx::Size GetAshLayoutSize(AshLayoutSize size) {
-  const int kBrowserMaximizedCaptionButtonHeight[] = {29, 33, 41};
-  const int kBrowserMaximizedCaptionButtonWidth[] = {32, 32, 32};
-  const int kBrowserRestoredCaptionButtonHeight[] = {36, 40, 48};
-  const int kBrowserRestoredCaptionButtonWidth[] = {32, 32, 32};
-  const int kNonBrowserCaptionButtonHeight[] = {33, 33, 33};
-  const int kNonBrowserCaptionButtonWidth[] = {32, 32, 32};
-
+  constexpr int kButtonWidth = 32;
   const int mode = ui::MaterialDesignController::GetMode();
   switch (size) {
-    case AshLayoutSize::BROWSER_MAXIMIZED_CAPTION_BUTTON: {
-      return gfx::Size(kBrowserMaximizedCaptionButtonWidth[mode],
+    case AshLayoutSize::kBrowserCaptionMaximized: {
+      constexpr int kBrowserMaximizedCaptionButtonHeight[] = {29, 33, 41, 29};
+      return gfx::Size(kButtonWidth,
                        kBrowserMaximizedCaptionButtonHeight[mode]);
     }
-    case AshLayoutSize::BROWSER_RESTORED_CAPTION_BUTTON: {
-      return gfx::Size(kBrowserRestoredCaptionButtonWidth[mode],
-                       kBrowserRestoredCaptionButtonHeight[mode]);
+    case AshLayoutSize::kBrowserCaptionRestored: {
+      constexpr int kBrowserRestoredCaptionButtonHeight[] = {36, 40, 48, 36};
+      return gfx::Size(kButtonWidth, kBrowserRestoredCaptionButtonHeight[mode]);
     }
-    case AshLayoutSize::NON_BROWSER_CAPTION_BUTTON: {
-      return gfx::Size(kNonBrowserCaptionButtonWidth[mode],
-                       kNonBrowserCaptionButtonHeight[mode]);
-    }
+    case AshLayoutSize::kNonBrowserCaption:
+      return gfx::Size(kButtonWidth, 33);
   }
 
   NOTREACHED();
diff --git a/ash/ash_layout_constants.h b/ash/ash_layout_constants.h
index 5e0c088b..5951396 100644
--- a/ash/ash_layout_constants.h
+++ b/ash/ash_layout_constants.h
@@ -10,13 +10,13 @@
 
 enum class AshLayoutSize {
   // Size of a caption button in a maximized browser window.
-  BROWSER_MAXIMIZED_CAPTION_BUTTON,
+  kBrowserCaptionMaximized,
 
   // Size of a caption button in a restored browser window.
-  BROWSER_RESTORED_CAPTION_BUTTON,
+  kBrowserCaptionRestored,
 
   // Size of a caption button in a non-browser window.
-  NON_BROWSER_CAPTION_BUTTON,
+  kNonBrowserCaption,
 };
 
 ASH_EXPORT gfx::Size GetAshLayoutSize(AshLayoutSize size);
diff --git a/ash/components/autoclick/autoclick_application.cc b/ash/components/autoclick/autoclick_application.cc
index 219039f..b4219f2 100644
--- a/ash/components/autoclick/autoclick_application.cc
+++ b/ash/components/autoclick/autoclick_application.cc
@@ -14,7 +14,7 @@
 #include "services/service_manager/public/cpp/service_context.h"
 #include "services/ui/public/cpp/property_type_converters.h"
 #include "services/ui/public/interfaces/constants.mojom.h"
-#include "services/ui/public/interfaces/remote_event_dispatcher.mojom.h"
+#include "services/ui/public/interfaces/event_injector.mojom.h"
 #include "services/ui/public/interfaces/window_manager_constants.mojom.h"
 #include "ui/aura/mus/property_converter.h"
 #include "ui/base/ui_base_types.h"
@@ -181,9 +181,9 @@
       gfx::ScaleToFlooredPoint(point_in_root, display.device_scale_factor());
 
   // Connect to the window service event generation interface.
-  ui::mojom::RemoteEventDispatcherPtr remote_event_dispatcher;
+  ui::mojom::EventInjectorPtr event_injector;
   context()->connector()->BindInterface(ui::mojom::kServiceName,
-                                        &remote_event_dispatcher);
+                                        &event_injector);
 
   // Inject a synthetic click.
   ui::MouseEvent press_event(ui::ET_MOUSE_PRESSED, point_in_pixels,
@@ -194,14 +194,14 @@
                                point_in_pixels, ui::EventTimeForNow(),
                                mouse_event_flags | ui::EF_LEFT_MOUSE_BUTTON,
                                ui::EF_LEFT_MOUSE_BUTTON);
-  remote_event_dispatcher->DispatchEvent(
+  event_injector->InjectEvent(
       display.id(), std::make_unique<ui::PointerEvent>(press_event),
       base::BindOnce([](bool result) { DCHECK(result); }));
   // Don't check the next dispatch result because it's possible the first event
   // will initiate shutdown.
-  remote_event_dispatcher->DispatchEvent(
-      display.id(), std::make_unique<ui::PointerEvent>(release_event),
-      base::DoNothing());
+  event_injector->InjectEvent(display.id(),
+                              std::make_unique<ui::PointerEvent>(release_event),
+                              base::DoNothing());
 }
 
 void AutoclickApplication::OnAutoclickCanceled() {
diff --git a/ash/components/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc b/ash/components/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc
index 826de80..0e17da0 100644
--- a/ash/components/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc
+++ b/ash/components/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc
@@ -20,6 +20,7 @@
 #include "ui/events/keycodes/keyboard_code_conversion.h"
 #include "ui/events/ozone/layout/keyboard_layout_engine.h"
 #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
+#include "ui/gfx/vector_icon_types.h"
 
 namespace keyboard_shortcut_viewer {
 
@@ -129,6 +130,8 @@
   ui::KeyboardCode keycode_ignored;
   if (ui::KeyboardLayoutEngineManager::GetKeyboardLayoutEngine()->Lookup(
           dom_code, 0 /* flags */, &dom_key, &keycode_ignored)) {
+    if (dom_key.IsValid() && dom_key.IsDeadKey())
+      return base::string16();
     return base::UTF8ToUTF16(ui::KeycodeConverter::DomKeyToKeyString(dom_key));
   }
 
@@ -136,6 +139,8 @@
   const bool has_mapping = ui::DomCodeToUsLayoutDomKey(
       dom_code, 0 /* flags */, &dom_key, &keycode_ignored);
   DCHECK(has_mapping);
+  if (dom_key.IsValid() && dom_key.IsDeadKey())
+    return base::string16();
   return base::UTF8ToUTF16(ui::KeycodeConverter::DomKeyToKeyString(dom_key));
 }
 
diff --git a/ash/components/shortcut_viewer/keyboard_shortcut_viewer_metadata.h b/ash/components/shortcut_viewer/keyboard_shortcut_viewer_metadata.h
index e4c387e..492bae0 100644
--- a/ash/components/shortcut_viewer/keyboard_shortcut_viewer_metadata.h
+++ b/ash/components/shortcut_viewer/keyboard_shortcut_viewer_metadata.h
@@ -12,7 +12,10 @@
 #include "base/optional.h"
 #include "base/strings/string16.h"
 #include "ui/events/keycodes/keyboard_codes.h"
-#include "ui/gfx/vector_icon_types.h"
+
+namespace gfx {
+struct VectorIcon;
+}  // namespace gfx
 
 namespace keyboard_shortcut_viewer {
 
@@ -28,7 +31,8 @@
 // Returns the string of a DomeKey for a given VKEY. VKEY needs to be mapped to
 // a physical key |dom_code| and then the |dom_code| needs to be mapped to a
 // meaning or character of |dom_key| based on the corresponding keyboard layout.
-// TODO(https://crbug.com/803502): Get strings for non US keyboard layout.
+// Returns empty string if the |dom_key| IsDeadKey or has no mapped meaning or
+// character.
 base::string16 GetStringForKeyboardCode(ui::KeyboardCode key_code);
 
 // Returns the VectorIcon if |key_code| need to be represented as an icon.
diff --git a/ash/components/shortcut_viewer/vector_icons/BUILD.gn b/ash/components/shortcut_viewer/vector_icons/BUILD.gn
index 06735ca0..36b5a99 100644
--- a/ash/components/shortcut_viewer/vector_icons/BUILD.gn
+++ b/ash/components/shortcut_viewer/vector_icons/BUILD.gn
@@ -8,43 +8,24 @@
   icon_directory = "."
 
   icons = [
-    "ksv_search_back.1x.icon",
     "ksv_search_back.icon",
-    "ksv_search_bar.1x.icon",
     "ksv_search_bar.icon",
-    "ksv_search_close.1x.icon",
     "ksv_search_close.icon",
-    "ksv_search_no_result.1x.icon",
     "ksv_search_no_result.icon",
-    "ksv_separator_plus.1x.icon",
     "ksv_separator_plus.icon",
-    "ksv_arrow_down.1x.icon",
     "ksv_arrow_down.icon",
-    "ksv_arrow_left.1x.icon",
     "ksv_arrow_left.icon",
-    "ksv_arrow_right.1x.icon",
     "ksv_arrow_right.icon",
-    "ksv_arrow_up.1x.icon",
     "ksv_arrow_up.icon",
-    "ksv_brightness_down.1x.icon",
     "ksv_brightness_down.icon",
-    "ksv_brightness_up.1x.icon",
     "ksv_brightness_up.icon",
-    "ksv_browser_back.1x.icon",
     "ksv_browser_back.icon",
-    "ksv_browser_forward.1x.icon",
     "ksv_browser_forward.icon",
-    "ksv_fullscreen.1x.icon",
     "ksv_fullscreen.icon",
-    "ksv_mute.1x.icon",
     "ksv_mute.icon",
-    "ksv_overview.1x.icon",
     "ksv_overview.icon",
-    "ksv_reload.1x.icon",
     "ksv_reload.icon",
-    "ksv_volume_down.1x.icon",
     "ksv_volume_down.icon",
-    "ksv_volume_up.1x.icon",
     "ksv_volume_up.icon",
   ]
 }
diff --git a/ash/components/shortcut_viewer/vector_icons/OWNERS b/ash/components/shortcut_viewer/vector_icons/OWNERS
new file mode 100644
index 0000000..d7ec991
--- /dev/null
+++ b/ash/components/shortcut_viewer/vector_icons/OWNERS
@@ -0,0 +1 @@
+file://components/vector_icons/OWNERS
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_arrow_down.1x.icon b/ash/components/shortcut_viewer/vector_icons/ksv_arrow_down.1x.icon
deleted file mode 100644
index 968f1d2..0000000
--- a/ash/components/shortcut_viewer/vector_icons/ksv_arrow_down.1x.icon
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2018 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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 8, 11.5f,
-LINE_TO, 2.5f, 6.04f,
-LINE_TO, 3.55f, 5,
-R_LINE_TO, 4.45f, 4.41f,
-LINE_TO, 12.45f, 5,
-LINE_TO, 13.5f, 6.04f,
-CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_arrow_down.icon b/ash/components/shortcut_viewer/vector_icons/ksv_arrow_down.icon
index 1fddea3..1469d19 100644
--- a/ash/components/shortcut_viewer/vector_icons/ksv_arrow_down.icon
+++ b/ash/components/shortcut_viewer/vector_icons/ksv_arrow_down.icon
@@ -10,3 +10,12 @@
 LINE_TO, 24.9f, 10,
 LINE_TO, 27, 12.09f,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 8, 11.5f,
+LINE_TO, 2.5f, 6.04f,
+LINE_TO, 3.55f, 5,
+R_LINE_TO, 4.45f, 4.41f,
+LINE_TO, 12.45f, 5,
+LINE_TO, 13.5f, 6.04f,
+CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_arrow_left.1x.icon b/ash/components/shortcut_viewer/vector_icons/ksv_arrow_left.1x.icon
deleted file mode 100644
index d2cadf7b..0000000
--- a/ash/components/shortcut_viewer/vector_icons/ksv_arrow_left.1x.icon
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2018 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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 4.75f, 8.25f,
-R_LINE_TO, 5.46f, 5.5f,
-R_LINE_TO, 1.04f, -1.05f,
-R_LINE_TO, -4.41f, -4.45f,
-R_LINE_TO, 4.41f, -4.45f,
-R_LINE_TO, -1.04f, -1.05f,
-CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_arrow_left.icon b/ash/components/shortcut_viewer/vector_icons/ksv_arrow_left.icon
index 1f88f2f..8d544eb 100644
--- a/ash/components/shortcut_viewer/vector_icons/ksv_arrow_left.icon
+++ b/ash/components/shortcut_viewer/vector_icons/ksv_arrow_left.icon
@@ -10,3 +10,12 @@
 LINE_TO, 22.5f, 7.6f,
 LINE_TO, 20.41f, 5.5f,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 4.75f, 8.25f,
+R_LINE_TO, 5.46f, 5.5f,
+R_LINE_TO, 1.04f, -1.05f,
+R_LINE_TO, -4.41f, -4.45f,
+R_LINE_TO, 4.41f, -4.45f,
+R_LINE_TO, -1.04f, -1.05f,
+CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_arrow_right.1x.icon b/ash/components/shortcut_viewer/vector_icons/ksv_arrow_right.1x.icon
deleted file mode 100644
index ca0cacf..0000000
--- a/ash/components/shortcut_viewer/vector_icons/ksv_arrow_right.1x.icon
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2018 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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 11.25f, 8.25f,
-LINE_TO, 5.79f, 13.75f,
-LINE_TO, 4.75f, 12.7f,
-R_LINE_TO, 4.41f, -4.45f,
-LINE_TO, 4.75f, 3.8f,
-LINE_TO, 5.79f, 2.75f,
-CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_arrow_right.icon b/ash/components/shortcut_viewer/vector_icons/ksv_arrow_right.icon
index e86867b..7de1198 100644
--- a/ash/components/shortcut_viewer/vector_icons/ksv_arrow_right.icon
+++ b/ash/components/shortcut_viewer/vector_icons/ksv_arrow_right.icon
@@ -10,3 +10,12 @@
 LINE_TO, 9.5f, 7.6f,
 LINE_TO, 11.59f, 5.5f,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 11.25f, 8.25f,
+LINE_TO, 5.79f, 13.75f,
+LINE_TO, 4.75f, 12.7f,
+R_LINE_TO, 4.41f, -4.45f,
+LINE_TO, 4.75f, 3.8f,
+LINE_TO, 5.79f, 2.75f,
+CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_arrow_up.1x.icon b/ash/components/shortcut_viewer/vector_icons/ksv_arrow_up.1x.icon
deleted file mode 100644
index 0016c7f..0000000
--- a/ash/components/shortcut_viewer/vector_icons/ksv_arrow_up.1x.icon
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2018 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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 8, 5,
-LINE_TO, 2.5f, 10.46f,
-LINE_TO, 3.55f, 11.5f,
-R_LINE_TO, 4.45f, -4.41f,
-R_LINE_TO, 4.45f, 4.41f,
-R_LINE_TO, 1.05f, -1.04f,
-CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_arrow_up.icon b/ash/components/shortcut_viewer/vector_icons/ksv_arrow_up.icon
index 1d6cffc..f39da9bb 100644
--- a/ash/components/shortcut_viewer/vector_icons/ksv_arrow_up.icon
+++ b/ash/components/shortcut_viewer/vector_icons/ksv_arrow_up.icon
@@ -10,3 +10,12 @@
 LINE_TO, 24.9f, 23,
 LINE_TO, 27, 20.91f,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 8, 5,
+LINE_TO, 2.5f, 10.46f,
+LINE_TO, 3.55f, 11.5f,
+R_LINE_TO, 4.45f, -4.41f,
+R_LINE_TO, 4.45f, 4.41f,
+R_LINE_TO, 1.05f, -1.04f,
+CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_brightness_down.1x.icon b/ash/components/shortcut_viewer/vector_icons/ksv_brightness_down.1x.icon
deleted file mode 100644
index fb9ebec..0000000
--- a/ash/components/shortcut_viewer/vector_icons/ksv_brightness_down.1x.icon
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2018 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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 7.91f, 9.85f,
-CUBIC_TO, 6.84f, 9.85f, 5.98f, 8.98f, 5.98f, 7.91f,
-CUBIC_TO, 5.98f, 6.84f, 6.84f, 5.98f, 7.91f, 5.98f,
-CUBIC_TO, 8.98f, 5.98f, 9.84f, 6.84f, 9.84f, 7.91f,
-CUBIC_TO, 9.84f, 8.98f, 8.98f, 9.85f, 7.91f, 9.85f,
-CLOSE,
-MOVE_TO, 10.68f, 6.76f,
-LINE_TO, 10.68f, 5.15f,
-LINE_TO, 9.06f, 5.15f,
-LINE_TO, 7.91f, 4,
-LINE_TO, 6.77f, 5.15f,
-LINE_TO, 5.15f, 5.15f,
-LINE_TO, 5.15f, 6.76f,
-LINE_TO, 4, 7.91f,
-LINE_TO, 5.15f, 9.06f,
-LINE_TO, 5.15f, 10.68f,
-LINE_TO, 6.77f, 10.68f,
-LINE_TO, 7.91f, 11.82f,
-LINE_TO, 9.06f, 10.68f,
-LINE_TO, 10.68f, 10.68f,
-LINE_TO, 10.68f, 9.06f,
-LINE_TO, 11.82f, 7.91f,
-LINE_TO, 10.68f, 6.76f,
-CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_brightness_down.icon b/ash/components/shortcut_viewer/vector_icons/ksv_brightness_down.icon
index 8d42331..68714a4 100644
--- a/ash/components/shortcut_viewer/vector_icons/ksv_brightness_down.icon
+++ b/ash/components/shortcut_viewer/vector_icons/ksv_brightness_down.icon
@@ -27,3 +27,29 @@
 LINE_TO, 23.64f, 15.82f,
 LINE_TO, 21.35f, 13.53f,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 7.91f, 9.85f,
+CUBIC_TO, 6.84f, 9.85f, 5.98f, 8.98f, 5.98f, 7.91f,
+CUBIC_TO, 5.98f, 6.84f, 6.84f, 5.98f, 7.91f, 5.98f,
+CUBIC_TO, 8.98f, 5.98f, 9.84f, 6.84f, 9.84f, 7.91f,
+CUBIC_TO, 9.84f, 8.98f, 8.98f, 9.85f, 7.91f, 9.85f,
+CLOSE,
+MOVE_TO, 10.68f, 6.76f,
+LINE_TO, 10.68f, 5.15f,
+LINE_TO, 9.06f, 5.15f,
+LINE_TO, 7.91f, 4,
+LINE_TO, 6.77f, 5.15f,
+LINE_TO, 5.15f, 5.15f,
+LINE_TO, 5.15f, 6.76f,
+LINE_TO, 4, 7.91f,
+LINE_TO, 5.15f, 9.06f,
+LINE_TO, 5.15f, 10.68f,
+LINE_TO, 6.77f, 10.68f,
+LINE_TO, 7.91f, 11.82f,
+LINE_TO, 9.06f, 10.68f,
+LINE_TO, 10.68f, 10.68f,
+LINE_TO, 10.68f, 9.06f,
+LINE_TO, 11.82f, 7.91f,
+LINE_TO, 10.68f, 6.76f,
+CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_brightness_up.1x.icon b/ash/components/shortcut_viewer/vector_icons/ksv_brightness_up.1x.icon
deleted file mode 100644
index 6e4c72e..0000000
--- a/ash/components/shortcut_viewer/vector_icons/ksv_brightness_up.1x.icon
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2018 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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 7.86f, 10.88f,
-R_ARC_TO, 3.03f, 3.03f, 0, 0, 1, -3.02f, -3.02f,
-R_ARC_TO, 3.03f, 3.03f, 0, 0, 1, 3.02f, -3.02f,
-R_ARC_TO, 3.03f, 3.03f, 0, 0, 1, 3.02f, 3.02f,
-R_ARC_TO, 3.03f, 3.03f, 0, 0, 1, -3.02f, 3.03f,
-CLOSE,
-R_MOVE_TO, 3.79f, -4.59f,
-V_LINE_TO, 4.07f,
-R_H_LINE_TO, -2.22f,
-LINE_TO, 7.86f, 2.5f,
-LINE_TO, 6.29f, 4.07f,
-H_LINE_TO, 4.07f,
-R_V_LINE_TO, 2.22f,
-LINE_TO, 2.5f, 7.86f,
-R_LINE_TO, 1.57f, 1.57f,
-R_V_LINE_TO, 2.22f,
-R_H_LINE_TO, 2.22f,
-R_LINE_TO, 1.57f, 1.57f,
-R_LINE_TO, 1.57f, -1.57f,
-R_H_LINE_TO, 2.22f,
-R_V_LINE_TO, -2.22f,
-R_LINE_TO, 1.57f, -1.57f,
-R_LINE_TO, -1.57f, -1.57f,
-CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_brightness_up.icon b/ash/components/shortcut_viewer/vector_icons/ksv_brightness_up.icon
index 6e3dcf7f..126f5b4 100644
--- a/ash/components/shortcut_viewer/vector_icons/ksv_brightness_up.icon
+++ b/ash/components/shortcut_viewer/vector_icons/ksv_brightness_up.icon
@@ -27,3 +27,29 @@
 R_LINE_TO, 3.14f, -3.14f,
 R_LINE_TO, -3.14f, -3.14f,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 7.86f, 10.88f,
+R_ARC_TO, 3.03f, 3.03f, 0, 0, 1, -3.02f, -3.02f,
+R_ARC_TO, 3.03f, 3.03f, 0, 0, 1, 3.02f, -3.02f,
+R_ARC_TO, 3.03f, 3.03f, 0, 0, 1, 3.02f, 3.02f,
+R_ARC_TO, 3.03f, 3.03f, 0, 0, 1, -3.02f, 3.03f,
+CLOSE,
+R_MOVE_TO, 3.79f, -4.59f,
+V_LINE_TO, 4.07f,
+R_H_LINE_TO, -2.22f,
+LINE_TO, 7.86f, 2.5f,
+LINE_TO, 6.29f, 4.07f,
+H_LINE_TO, 4.07f,
+R_V_LINE_TO, 2.22f,
+LINE_TO, 2.5f, 7.86f,
+R_LINE_TO, 1.57f, 1.57f,
+R_V_LINE_TO, 2.22f,
+R_H_LINE_TO, 2.22f,
+R_LINE_TO, 1.57f, 1.57f,
+R_LINE_TO, 1.57f, -1.57f,
+R_H_LINE_TO, 2.22f,
+R_V_LINE_TO, -2.22f,
+R_LINE_TO, 1.57f, -1.57f,
+R_LINE_TO, -1.57f, -1.57f,
+CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_browser_back.1x.icon b/ash/components/shortcut_viewer/vector_icons/ksv_browser_back.1x.icon
deleted file mode 100644
index b902618..0000000
--- a/ash/components/shortcut_viewer/vector_icons/ksv_browser_back.1x.icon
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2018 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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 7.76f, 3.5f,
-LINE_TO, 3, 8.22f,
-LINE_TO, 7.75f, 13,
-R_LINE_TO, 1.15f, -1.13f,
-R_LINE_TO, -2.8f, -2.82f,
-H_LINE_TO, 13,
-V_LINE_TO, 7.45f,
-H_LINE_TO, 6.07f,
-R_LINE_TO, 2.84f, -2.81f,
-CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_browser_back.icon b/ash/components/shortcut_viewer/vector_icons/ksv_browser_back.icon
index 7d3990b..82812c0 100644
--- a/ash/components/shortcut_viewer/vector_icons/ksv_browser_back.icon
+++ b/ash/components/shortcut_viewer/vector_icons/ksv_browser_back.icon
@@ -13,3 +13,15 @@
 H_LINE_TO, 12.13f,
 R_LINE_TO, 5.67f, -5.62f,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 7.76f, 3.5f,
+LINE_TO, 3, 8.22f,
+LINE_TO, 7.75f, 13,
+R_LINE_TO, 1.15f, -1.13f,
+R_LINE_TO, -2.8f, -2.82f,
+H_LINE_TO, 13,
+V_LINE_TO, 7.45f,
+H_LINE_TO, 6.07f,
+R_LINE_TO, 2.84f, -2.81f,
+CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_browser_forward.1x.icon b/ash/components/shortcut_viewer/vector_icons/ksv_browser_forward.1x.icon
deleted file mode 100644
index d2ea6609..0000000
--- a/ash/components/shortcut_viewer/vector_icons/ksv_browser_forward.1x.icon
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2018 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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 8.24f, 3.5f,
-LINE_TO, 13, 8.22f,
-LINE_TO, 8.25f, 13,
-R_LINE_TO, -1.15f, -1.13f,
-R_LINE_TO, 2.8f, -2.82f,
-H_LINE_TO, 3,
-V_LINE_TO, 7.45f,
-R_H_LINE_TO, 6.93f,
-LINE_TO, 7.1f, 4.64f,
-CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_browser_forward.icon b/ash/components/shortcut_viewer/vector_icons/ksv_browser_forward.icon
index 92e1c712..18f4850 100644
--- a/ash/components/shortcut_viewer/vector_icons/ksv_browser_forward.icon
+++ b/ash/components/shortcut_viewer/vector_icons/ksv_browser_forward.icon
@@ -13,3 +13,15 @@
 R_H_LINE_TO, 13.87f,
 LINE_TO, 14.2f, 9.27f,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 8.24f, 3.5f,
+LINE_TO, 13, 8.22f,
+LINE_TO, 8.25f, 13,
+R_LINE_TO, -1.15f, -1.13f,
+R_LINE_TO, 2.8f, -2.82f,
+H_LINE_TO, 3,
+V_LINE_TO, 7.45f,
+R_H_LINE_TO, 6.93f,
+LINE_TO, 7.1f, 4.64f,
+CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_fullscreen.1x.icon b/ash/components/shortcut_viewer/vector_icons/ksv_fullscreen.1x.icon
deleted file mode 100644
index 5e2ac30..0000000
--- a/ash/components/shortcut_viewer/vector_icons/ksv_fullscreen.1x.icon
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2018 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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 8.89f, 4,
-R_V_LINE_TO, 1.3f,
-R_H_LINE_TO, 2.79f,
-R_V_LINE_TO, 1.84f,
-R_H_LINE_TO, 1.32f,
-V_LINE_TO, 4,
-H_LINE_TO, 8.89f,
-CLOSE,
-MOVE_TO, 2.5f, 4,
-R_V_LINE_TO, 3.14f,
-R_H_LINE_TO, 1.32f,
-V_LINE_TO, 5.3f,
-R_H_LINE_TO, 2.8f,
-V_LINE_TO, 4,
-H_LINE_TO, 2.5f,
-CLOSE,
-R_MOVE_TO, 0, 5.35f,
-V_LINE_TO, 12.5f,
-R_H_LINE_TO, 4.11f,
-R_V_LINE_TO, -1.31f,
-H_LINE_TO, 3.82f,
-V_LINE_TO, 9.35f,
-H_LINE_TO, 2.5f,
-CLOSE,
-R_MOVE_TO, 9.18f, 0,
-R_V_LINE_TO, 1.84f,
-R_H_LINE_TO, -2.79f,
-V_LINE_TO, 12.5f,
-H_LINE_TO, 13,
-V_LINE_TO, 9.35f,
-R_H_LINE_TO, -1.32f,
-CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_fullscreen.icon b/ash/components/shortcut_viewer/vector_icons/ksv_fullscreen.icon
index f2c9b0db..721cb86 100644
--- a/ash/components/shortcut_viewer/vector_icons/ksv_fullscreen.icon
+++ b/ash/components/shortcut_viewer/vector_icons/ksv_fullscreen.icon
@@ -35,3 +35,37 @@
 R_V_LINE_TO, -6.3f,
 R_H_LINE_TO, -2.64f,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 8.89f, 4,
+R_V_LINE_TO, 1.3f,
+R_H_LINE_TO, 2.79f,
+R_V_LINE_TO, 1.84f,
+R_H_LINE_TO, 1.32f,
+V_LINE_TO, 4,
+H_LINE_TO, 8.89f,
+CLOSE,
+MOVE_TO, 2.5f, 4,
+R_V_LINE_TO, 3.14f,
+R_H_LINE_TO, 1.32f,
+V_LINE_TO, 5.3f,
+R_H_LINE_TO, 2.8f,
+V_LINE_TO, 4,
+H_LINE_TO, 2.5f,
+CLOSE,
+R_MOVE_TO, 0, 5.35f,
+V_LINE_TO, 12.5f,
+R_H_LINE_TO, 4.11f,
+R_V_LINE_TO, -1.31f,
+H_LINE_TO, 3.82f,
+V_LINE_TO, 9.35f,
+H_LINE_TO, 2.5f,
+CLOSE,
+R_MOVE_TO, 9.18f, 0,
+R_V_LINE_TO, 1.84f,
+R_H_LINE_TO, -2.79f,
+V_LINE_TO, 12.5f,
+H_LINE_TO, 13,
+V_LINE_TO, 9.35f,
+R_H_LINE_TO, -1.32f,
+CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_mute.1x.icon b/ash/components/shortcut_viewer/vector_icons/ksv_mute.1x.icon
deleted file mode 100644
index 0305760..0000000
--- a/ash/components/shortcut_viewer/vector_icons/ksv_mute.1x.icon
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2018 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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 8, 3.56f,
-LINE_TO, 6.84f, 4.72f,
-LINE_TO, 8, 5.88f,
-LINE_TO, 8, 3.56f,
-CLOSE,
-MOVE_TO, 3.71f, 3,
-LINE_TO, 3, 3.71f,
-LINE_TO, 5.63f, 6.33f,
-LINE_TO, 3, 6.33f,
-LINE_TO, 3, 9.67f,
-LINE_TO, 5.22f, 9.67f,
-LINE_TO, 8, 12.44f,
-LINE_TO, 8, 8.71f,
-LINE_TO, 10.36f, 11.07f,
-CUBIC_TO, 9.99f, 11.36f, 9.57f, 11.58f, 9.11f, 11.72f,
-LINE_TO, 9.11f, 12.87f,
-CUBIC_TO, 9.88f, 12.69f, 10.57f, 12.34f, 11.16f, 11.86f,
-LINE_TO, 12.29f, 13,
-LINE_TO, 13, 12.29f,
-LINE_TO, 8, 7.29f,
-LINE_TO, 3.71f, 3,
-CLOSE,
-MOVE_TO, 11.89f, 8,
-CUBIC_TO, 11.89f, 8.52f, 11.78f, 9.01f, 11.59f, 9.47f,
-LINE_TO, 12.43f, 10.31f,
-CUBIC_TO, 12.79f, 9.62f, 13, 8.83f, 13, 8,
-CUBIC_TO, 13, 5.62f, 11.34f, 3.63f, 9.11f, 3.13f,
-LINE_TO, 9.11f, 4.27f,
-CUBIC_TO, 10.72f, 4.75f, 11.89f, 6.24f, 11.89f, 8,
-CLOSE,
-MOVE_TO, 10.5f, 8,
-CUBIC_TO, 10.5f, 7.02f, 9.93f, 6.17f, 9.11f, 5.76f,
-LINE_TO, 9.11f, 6.99f,
-LINE_TO, 10.47f, 8.35f,
-CUBIC_TO, 10.49f, 8.24f, 10.5f, 8.12f, 10.5f, 8,
-CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_mute.icon b/ash/components/shortcut_viewer/vector_icons/ksv_mute.icon
index 2d4d688..53e5f0de 100644
--- a/ash/components/shortcut_viewer/vector_icons/ksv_mute.icon
+++ b/ash/components/shortcut_viewer/vector_icons/ksv_mute.icon
@@ -39,3 +39,41 @@
 LINE_TO, 20.94f, 16.7f,
 CUBIC_TO, 20.98f, 16.48f, 21, 16.25f, 21, 16,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 8, 3.56f,
+LINE_TO, 6.84f, 4.72f,
+LINE_TO, 8, 5.88f,
+LINE_TO, 8, 3.56f,
+CLOSE,
+MOVE_TO, 3.71f, 3,
+LINE_TO, 3, 3.71f,
+LINE_TO, 5.63f, 6.33f,
+LINE_TO, 3, 6.33f,
+LINE_TO, 3, 9.67f,
+LINE_TO, 5.22f, 9.67f,
+LINE_TO, 8, 12.44f,
+LINE_TO, 8, 8.71f,
+LINE_TO, 10.36f, 11.07f,
+CUBIC_TO, 9.99f, 11.36f, 9.57f, 11.58f, 9.11f, 11.72f,
+LINE_TO, 9.11f, 12.87f,
+CUBIC_TO, 9.88f, 12.69f, 10.57f, 12.34f, 11.16f, 11.86f,
+LINE_TO, 12.29f, 13,
+LINE_TO, 13, 12.29f,
+LINE_TO, 8, 7.29f,
+LINE_TO, 3.71f, 3,
+CLOSE,
+MOVE_TO, 11.89f, 8,
+CUBIC_TO, 11.89f, 8.52f, 11.78f, 9.01f, 11.59f, 9.47f,
+LINE_TO, 12.43f, 10.31f,
+CUBIC_TO, 12.79f, 9.62f, 13, 8.83f, 13, 8,
+CUBIC_TO, 13, 5.62f, 11.34f, 3.63f, 9.11f, 3.13f,
+LINE_TO, 9.11f, 4.27f,
+CUBIC_TO, 10.72f, 4.75f, 11.89f, 6.24f, 11.89f, 8,
+CLOSE,
+MOVE_TO, 10.5f, 8,
+CUBIC_TO, 10.5f, 7.02f, 9.93f, 6.17f, 9.11f, 5.76f,
+LINE_TO, 9.11f, 6.99f,
+LINE_TO, 10.47f, 8.35f,
+CUBIC_TO, 10.49f, 8.24f, 10.5f, 8.12f, 10.5f, 8,
+CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_overview.1x.icon b/ash/components/shortcut_viewer/vector_icons/ksv_overview.1x.icon
deleted file mode 100644
index c2f4f72..0000000
--- a/ash/components/shortcut_viewer/vector_icons/ksv_overview.1x.icon
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2018 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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 1, 11.49f,
-R_H_LINE_TO, 9,
-V_LINE_TO, 4.5f,
-H_LINE_TO, 1,
-R_V_LINE_TO, 6.99f,
-CLOSE,
-R_MOVE_TO, 1, -0.99f,
-R_H_LINE_TO, 7,
-R_V_LINE_TO, -5,
-H_LINE_TO, 2,
-R_V_LINE_TO, 5,
-CLOSE,
-MOVE_TO, 11.5f, 11.49f,
-R_H_LINE_TO, 1,
-V_LINE_TO, 4.5f,
-R_H_LINE_TO, -1,
-CLOSE,
-MOVE_TO, 13.5f, 11.5f,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, -7,
-R_H_LINE_TO, -1,
-CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_overview.icon b/ash/components/shortcut_viewer/vector_icons/ksv_overview.icon
index a810a00..d860a48 100644
--- a/ash/components/shortcut_viewer/vector_icons/ksv_overview.icon
+++ b/ash/components/shortcut_viewer/vector_icons/ksv_overview.icon
@@ -25,3 +25,27 @@
 V_LINE_TO, 9,
 R_H_LINE_TO, -2,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 1, 11.49f,
+R_H_LINE_TO, 9,
+V_LINE_TO, 4.5f,
+H_LINE_TO, 1,
+R_V_LINE_TO, 6.99f,
+CLOSE,
+R_MOVE_TO, 1, -0.99f,
+R_H_LINE_TO, 7,
+R_V_LINE_TO, -5,
+H_LINE_TO, 2,
+R_V_LINE_TO, 5,
+CLOSE,
+MOVE_TO, 11.5f, 11.49f,
+R_H_LINE_TO, 1,
+V_LINE_TO, 4.5f,
+R_H_LINE_TO, -1,
+CLOSE,
+MOVE_TO, 13.5f, 11.5f,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, -7,
+R_H_LINE_TO, -1,
+CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_reload.1x.icon b/ash/components/shortcut_viewer/vector_icons/ksv_reload.1x.icon
deleted file mode 100644
index 392be2a8..0000000
--- a/ash/components/shortcut_viewer/vector_icons/ksv_reload.1x.icon
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2018 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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 13.19f, 7.27f,
-LINE_TO, 13.19f, 3,
-LINE_TO, 11.53f, 4.66f,
-CUBIC_TO, 10.63f, 3.65f, 9.35f, 3.03f, 7.97f, 3,
-CUBIC_TO, 6.69f, 2.98f, 5.43f, 3.46f, 4.5f, 4.37f,
-CUBIC_TO, 3.56f, 5.27f, 3.03f, 6.49f, 3, 7.79f,
-CUBIC_TO, 2.95f, 10.48f, 5.1f, 12.71f, 7.79f, 12.76f,
-CUBIC_TO, 7.82f, 12.77f, 7.85f, 12.77f, 7.88f, 12.77f,
-CUBIC_TO, 9.58f, 12.77f, 11.17f, 11.87f, 12.06f, 10.4f,
-LINE_TO, 10.86f, 9.68f,
-CUBIC_TO, 10.22f, 10.74f, 9.05f, 11.36f, 7.82f, 11.37f,
-CUBIC_TO, 5.9f, 11.33f, 4.37f, 9.74f, 4.4f, 7.82f,
-CUBIC_TO, 4.42f, 6.89f, 4.8f, 6.02f, 5.47f, 5.38f,
-CUBIC_TO, 6.14f, 4.73f, 6.98f, 4.39f, 7.95f, 4.4f,
-CUBIC_TO, 8.96f, 4.42f, 9.9f, 4.89f, 10.54f, 5.65f,
-LINE_TO, 8.92f, 7.27f,
-LINE_TO, 13.19f, 7.27f,
-CLOSE
-
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_reload.icon b/ash/components/shortcut_viewer/vector_icons/ksv_reload.icon
index 1d62433a..7e84d2c5 100644
--- a/ash/components/shortcut_viewer/vector_icons/ksv_reload.icon
+++ b/ash/components/shortcut_viewer/vector_icons/ksv_reload.icon
@@ -21,3 +21,24 @@
 LINE_TO, 17.84f, 14.53f,
 LINE_TO, 26.37f, 14.53f,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 13.19f, 7.27f,
+LINE_TO, 13.19f, 3,
+LINE_TO, 11.53f, 4.66f,
+CUBIC_TO, 10.63f, 3.65f, 9.35f, 3.03f, 7.97f, 3,
+CUBIC_TO, 6.69f, 2.98f, 5.43f, 3.46f, 4.5f, 4.37f,
+CUBIC_TO, 3.56f, 5.27f, 3.03f, 6.49f, 3, 7.79f,
+CUBIC_TO, 2.95f, 10.48f, 5.1f, 12.71f, 7.79f, 12.76f,
+CUBIC_TO, 7.82f, 12.77f, 7.85f, 12.77f, 7.88f, 12.77f,
+CUBIC_TO, 9.58f, 12.77f, 11.17f, 11.87f, 12.06f, 10.4f,
+LINE_TO, 10.86f, 9.68f,
+CUBIC_TO, 10.22f, 10.74f, 9.05f, 11.36f, 7.82f, 11.37f,
+CUBIC_TO, 5.9f, 11.33f, 4.37f, 9.74f, 4.4f, 7.82f,
+CUBIC_TO, 4.42f, 6.89f, 4.8f, 6.02f, 5.47f, 5.38f,
+CUBIC_TO, 6.14f, 4.73f, 6.98f, 4.39f, 7.95f, 4.4f,
+CUBIC_TO, 8.96f, 4.42f, 9.9f, 4.89f, 10.54f, 5.65f,
+LINE_TO, 8.92f, 7.27f,
+LINE_TO, 13.19f, 7.27f,
+CLOSE
+
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_search_back.1x.icon b/ash/components/shortcut_viewer/vector_icons/ksv_search_back.1x.icon
deleted file mode 100644
index b2c2931a..0000000
--- a/ash/components/shortcut_viewer/vector_icons/ksv_search_back.1x.icon
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2018 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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 16, 9.02f,
-H_LINE_TO, 6.45f,
-R_LINE_TO, 4.54f, -4.54f,
-R_LINE_TO, -1.15f, -1.15f,
-LINE_TO, 3.33f, 10,
-R_LINE_TO, 6.5f, 6.33f,
-R_LINE_TO, 1.15f, -1.15f,
-LINE_TO, 6.45f, 10.5f,
-H_LINE_TO, 16,
-CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_search_back.icon b/ash/components/shortcut_viewer/vector_icons/ksv_search_back.icon
index 33f08fa5..863b9780 100644
--- a/ash/components/shortcut_viewer/vector_icons/ksv_search_back.icon
+++ b/ash/components/shortcut_viewer/vector_icons/ksv_search_back.icon
@@ -13,3 +13,15 @@
 LINE_TO, 12.89f, 21,
 H_LINE_TO, 33,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 16, 9.02f,
+H_LINE_TO, 6.45f,
+R_LINE_TO, 4.54f, -4.54f,
+R_LINE_TO, -1.15f, -1.15f,
+LINE_TO, 3.33f, 10,
+R_LINE_TO, 6.5f, 6.33f,
+R_LINE_TO, 1.15f, -1.15f,
+LINE_TO, 6.45f, 10.5f,
+H_LINE_TO, 16,
+CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_search_bar.1x.icon b/ash/components/shortcut_viewer/vector_icons/ksv_search_bar.1x.icon
deleted file mode 100644
index 3b4cd225..0000000
--- a/ash/components/shortcut_viewer/vector_icons/ksv_search_bar.1x.icon
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2018 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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 12.92f, 11.67f,
-R_H_LINE_TO, -0.66f,
-R_LINE_TO, -0.23f, -0.22f,
-R_ARC_TO, 5.39f, 5.39f, 0, 0, 0, 1.31f, -3.52f,
-R_ARC_TO, 5.42f, 5.42f, 0, 1, 0, -5.42f, 5.42f,
-R_ARC_TO, 5.39f, 5.39f, 0, 0, 0, 3.53f, -1.31f,
-R_LINE_TO, 0.23f, 0.23f,
-R_V_LINE_TO, 0.66f,
-R_LINE_TO, 4.17f, 4.16f,
-R_LINE_TO, 1.24f, -1.24f,
-R_LINE_TO, -4.16f, -4.17f,
-CLOSE,
-R_MOVE_TO, -5, 0,
-R_ARC_TO, 3.75f, 3.75f, 0, 0, 1, -3.75f, -3.75f,
-R_ARC_TO, 3.75f, 3.75f, 0, 0, 1, 3.75f, -3.75f,
-R_ARC_TO, 3.75f, 3.75f, 0, 0, 1, 3.75f, 3.75f,
-R_ARC_TO, 3.75f, 3.75f, 0, 0, 1, -3.75f, 3.75f,
-CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_search_bar.icon b/ash/components/shortcut_viewer/vector_icons/ksv_search_bar.icon
index 5988315..1773f58 100644
--- a/ash/components/shortcut_viewer/vector_icons/ksv_search_bar.icon
+++ b/ash/components/shortcut_viewer/vector_icons/ksv_search_bar.icon
@@ -23,3 +23,23 @@
 R_CUBIC_TO, 4.15f, 0, 7.5f, 3.35f, 7.5f, 7.5f,
 R_CUBIC_TO, 0, 4.15f, -3.35f, 7.5f, -7.5f, 7.5f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 12.92f, 11.67f,
+R_H_LINE_TO, -0.66f,
+R_LINE_TO, -0.23f, -0.22f,
+R_ARC_TO, 5.39f, 5.39f, 0, 0, 0, 1.31f, -3.52f,
+R_ARC_TO, 5.42f, 5.42f, 0, 1, 0, -5.42f, 5.42f,
+R_ARC_TO, 5.39f, 5.39f, 0, 0, 0, 3.53f, -1.31f,
+R_LINE_TO, 0.23f, 0.23f,
+R_V_LINE_TO, 0.66f,
+R_LINE_TO, 4.17f, 4.16f,
+R_LINE_TO, 1.24f, -1.24f,
+R_LINE_TO, -4.16f, -4.17f,
+CLOSE,
+R_MOVE_TO, -5, 0,
+R_ARC_TO, 3.75f, 3.75f, 0, 0, 1, -3.75f, -3.75f,
+R_ARC_TO, 3.75f, 3.75f, 0, 0, 1, 3.75f, -3.75f,
+R_ARC_TO, 3.75f, 3.75f, 0, 0, 1, 3.75f, 3.75f,
+R_ARC_TO, 3.75f, 3.75f, 0, 0, 1, -3.75f, 3.75f,
+CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_search_close.1x.icon b/ash/components/shortcut_viewer/vector_icons/ksv_search_close.1x.icon
deleted file mode 100644
index db1d582..0000000
--- a/ash/components/shortcut_viewer/vector_icons/ksv_search_close.1x.icon
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2018 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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 10, 1.67f,
-R_CUBIC_TO, 4.6f, 0, 8.33f, 3.73f, 8.33f, 8.33f,
-CUBIC_TO_SHORTHAND, 14.6f, 18.33f, 10, 18.33f,
-ARC_TO, 8.34f, 8.34f, 0, 0, 1, 1.67f, 10,
-CUBIC_TO, 1.67f, 5.4f, 5.4f, 1.67f, 10, 1.67f,
-CLOSE,
-R_MOVE_TO, 3.9f, 5.24f,
-R_LINE_TO, -0.79f, -0.79f,
-R_LINE_TO, -3.1f, 3.1f,
-LINE_TO, 6.91f, 6.13f,
-R_LINE_TO, -0.79f, 0.79f,
-R_LINE_TO, 3.1f, 3.1f,
-R_LINE_TO, -3.1f, 3.1f,
-R_LINE_TO, 0.79f, 0.79f,
-R_LINE_TO, 3.1f, -3.1f,
-R_LINE_TO, 3.1f, 3.1f,
-R_LINE_TO, 0.79f, -0.79f,
-R_LINE_TO, -3.1f, -3.1f,
-R_LINE_TO, 3.1f, -3.1f,
-CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_search_close.icon b/ash/components/shortcut_viewer/vector_icons/ksv_search_close.icon
index 340b406..891f4da 100644
--- a/ash/components/shortcut_viewer/vector_icons/ksv_search_close.icon
+++ b/ash/components/shortcut_viewer/vector_icons/ksv_search_close.icon
@@ -23,3 +23,25 @@
 R_LINE_TO, -6.21f, -6.2f,
 R_LINE_TO, 6.21f, -6.21f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 10, 1.67f,
+R_CUBIC_TO, 4.6f, 0, 8.33f, 3.73f, 8.33f, 8.33f,
+CUBIC_TO_SHORTHAND, 14.6f, 18.33f, 10, 18.33f,
+ARC_TO, 8.34f, 8.34f, 0, 0, 1, 1.67f, 10,
+CUBIC_TO, 1.67f, 5.4f, 5.4f, 1.67f, 10, 1.67f,
+CLOSE,
+R_MOVE_TO, 3.9f, 5.24f,
+R_LINE_TO, -0.79f, -0.79f,
+R_LINE_TO, -3.1f, 3.1f,
+LINE_TO, 6.91f, 6.13f,
+R_LINE_TO, -0.79f, 0.79f,
+R_LINE_TO, 3.1f, 3.1f,
+R_LINE_TO, -3.1f, 3.1f,
+R_LINE_TO, 0.79f, 0.79f,
+R_LINE_TO, 3.1f, -3.1f,
+R_LINE_TO, 3.1f, 3.1f,
+R_LINE_TO, 0.79f, -0.79f,
+R_LINE_TO, -3.1f, -3.1f,
+R_LINE_TO, 3.1f, -3.1f,
+CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_search_no_result.1x.icon b/ash/components/shortcut_viewer/vector_icons/ksv_search_no_result.1x.icon
deleted file mode 100644
index 2d5b56b6..0000000
--- a/ash/components/shortcut_viewer/vector_icons/ksv_search_no_result.1x.icon
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2018 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.
-
-CANVAS_DIMENSIONS, 150,
-MOVE_TO, 110.58f, 49,
-H_LINE_TO, 38.47f,
-R_CUBIC_TO, -4.96f, 0, -8.97f, 4.05f, -8.97f, 9,
-R_LINE_TO, -0.04f, 45,
-R_CUBIC_TO, 0, 4.95f, 4.06f, 9, 9.01f, 9,
-R_H_LINE_TO, 72.11f,
-R_CUBIC_TO, 4.96f, 0, 9.02f, -4.05f, 9.02f, -9,
-V_LINE_TO, 58,
-R_CUBIC_TO, 0, -4.95f, -4.06f, -9, -9.01f, -9,
-CLOSE,
-NEW_PATH,
-STROKE, 2.254f,
-MOVE_TO, 122.97f, 38.12f,
-R_LINE_TO, 1.94f, -7.08f,
-CLOSE,
-NEW_PATH,
-STROKE, 2.254f,
-MOVE_TO, 130.18f, 45.26f,
-R_LINE_TO, 6.45f, -3,
-CLOSE,
-NEW_PATH,
-STROKE, 2.254f,
-MOVE_TO, 131.68f, 56.81f,
-R_LINE_TO, 6.88f, 2.88f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0xFF, 0xFF, 0xFF,
-MOVE_TO, 81, 89,
-R_ARC_TO, 6, 6, 0, 1, 0, -12, 0,
-R_CUBIC_TO, 0, 0.06f, 12, 0.05f, 12, 0,
-CLOSE,
-CIRCLE, 52, 75, 4.5,
-CIRCLE, 98, 75, 4.5,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0x9A, 0xA0, 0xA6,
-MOVE_TO, 121.85f, 106.5f,
-R_H_LINE_TO, -1.79f,
-R_LINE_TO, -0.62f, -0.62f,
-R_ARC_TO, 14.47f, 14.47f, 0, 0, 0, 3.54f, -9.51f,
-R_CUBIC_TO, 0, -8.08f, -6.56f, -14.62f, -14.65f, -14.62f,
-R_CUBIC_TO, -8.09f, 0, -14.65f, 6.55f, -14.65f, 14.63f,
-CUBIC_TO_SHORTHAND, 100.23f, 111, 108.32f, 111,
-R_CUBIC_TO, 3.64f, 0, 6.96f, -1.33f, 9.52f, -3.52f,
-R_LINE_TO, 0.62f, 0.62f,
-R_V_LINE_TO, 1.78f,
-R_LINE_TO, 11.27f, 11.23f,
-R_LINE_TO, 3.36f, -3.35f,
-R_LINE_TO, -11.24f, -11.25f,
-CLOSE,
-R_MOVE_TO, -13.52f, 0,
-R_CUBIC_TO, -5.6f, 0, -10.14f, -4.53f, -10.14f, -10.12f,
-R_CUBIC_TO, 0, -5.59f, 4.54f, -10.12f, 10.14f, -10.12f,
-R_CUBIC_TO, 5.6f, 0, 10.14f, 4.53f, 10.14f, 10.13f,
-R_CUBIC_TO, 0, 5.6f, -4.54f, 10.13f, -10.14f, 10.13f,
-CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_search_no_result.icon b/ash/components/shortcut_viewer/vector_icons/ksv_search_no_result.icon
index d0578a3..8de074c 100644
--- a/ash/components/shortcut_viewer/vector_icons/ksv_search_no_result.icon
+++ b/ash/components/shortcut_viewer/vector_icons/ksv_search_no_result.icon
@@ -59,3 +59,60 @@
 R_CUBIC_TO, 11.2f, 0, 20.28f, 9.07f, 20.28f, 20.25f,
 R_CUBIC_TO, 0, 11.18f, -9.08f, 20.25f, -20.28f, 20.25f,
 CLOSE
+
+CANVAS_DIMENSIONS, 150,
+MOVE_TO, 110.58f, 49,
+H_LINE_TO, 38.47f,
+R_CUBIC_TO, -4.96f, 0, -8.97f, 4.05f, -8.97f, 9,
+R_LINE_TO, -0.04f, 45,
+R_CUBIC_TO, 0, 4.95f, 4.06f, 9, 9.01f, 9,
+R_H_LINE_TO, 72.11f,
+R_CUBIC_TO, 4.96f, 0, 9.02f, -4.05f, 9.02f, -9,
+V_LINE_TO, 58,
+R_CUBIC_TO, 0, -4.95f, -4.06f, -9, -9.01f, -9,
+CLOSE,
+NEW_PATH,
+STROKE, 2.254f,
+MOVE_TO, 122.97f, 38.12f,
+R_LINE_TO, 1.94f, -7.08f,
+CLOSE,
+NEW_PATH,
+STROKE, 2.254f,
+MOVE_TO, 130.18f, 45.26f,
+R_LINE_TO, 6.45f, -3,
+CLOSE,
+NEW_PATH,
+STROKE, 2.254f,
+MOVE_TO, 131.68f, 56.81f,
+R_LINE_TO, 6.88f, 2.88f,
+CLOSE,
+NEW_PATH,
+PATH_COLOR_ARGB, 0xFF, 0xFF, 0xFF, 0xFF,
+MOVE_TO, 81, 89,
+R_ARC_TO, 6, 6, 0, 1, 0, -12, 0,
+R_CUBIC_TO, 0, 0.06f, 12, 0.05f, 12, 0,
+CLOSE,
+CIRCLE, 52, 75, 4.5,
+CIRCLE, 98, 75, 4.5,
+NEW_PATH,
+PATH_COLOR_ARGB, 0xFF, 0x9A, 0xA0, 0xA6,
+MOVE_TO, 121.85f, 106.5f,
+R_H_LINE_TO, -1.79f,
+R_LINE_TO, -0.62f, -0.62f,
+R_ARC_TO, 14.47f, 14.47f, 0, 0, 0, 3.54f, -9.51f,
+R_CUBIC_TO, 0, -8.08f, -6.56f, -14.62f, -14.65f, -14.62f,
+R_CUBIC_TO, -8.09f, 0, -14.65f, 6.55f, -14.65f, 14.63f,
+CUBIC_TO_SHORTHAND, 100.23f, 111, 108.32f, 111,
+R_CUBIC_TO, 3.64f, 0, 6.96f, -1.33f, 9.52f, -3.52f,
+R_LINE_TO, 0.62f, 0.62f,
+R_V_LINE_TO, 1.78f,
+R_LINE_TO, 11.27f, 11.23f,
+R_LINE_TO, 3.36f, -3.35f,
+R_LINE_TO, -11.24f, -11.25f,
+CLOSE,
+R_MOVE_TO, -13.52f, 0,
+R_CUBIC_TO, -5.6f, 0, -10.14f, -4.53f, -10.14f, -10.12f,
+R_CUBIC_TO, 0, -5.59f, 4.54f, -10.12f, 10.14f, -10.12f,
+R_CUBIC_TO, 5.6f, 0, 10.14f, 4.53f, 10.14f, 10.13f,
+R_CUBIC_TO, 0, 5.6f, -4.54f, 10.13f, -10.14f, 10.13f,
+CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_separator_plus.1x.icon b/ash/components/shortcut_viewer/vector_icons/ksv_separator_plus.1x.icon
deleted file mode 100644
index 1882cfb..0000000
--- a/ash/components/shortcut_viewer/vector_icons/ksv_separator_plus.1x.icon
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2018 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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 12, 9,
-H_LINE_TO, 9,
-R_V_LINE_TO, 3,
-H_LINE_TO, 7,
-V_LINE_TO, 9,
-H_LINE_TO, 4,
-V_LINE_TO, 7,
-R_H_LINE_TO, 3,
-V_LINE_TO, 4,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, 3,
-R_H_LINE_TO, 3,
-CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_separator_plus.icon b/ash/components/shortcut_viewer/vector_icons/ksv_separator_plus.icon
index f71544c..b6644bc6 100644
--- a/ash/components/shortcut_viewer/vector_icons/ksv_separator_plus.icon
+++ b/ash/components/shortcut_viewer/vector_icons/ksv_separator_plus.icon
@@ -16,3 +16,18 @@
 R_V_LINE_TO, 6,
 R_H_LINE_TO, 6,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 12, 9,
+H_LINE_TO, 9,
+R_V_LINE_TO, 3,
+H_LINE_TO, 7,
+V_LINE_TO, 9,
+H_LINE_TO, 4,
+V_LINE_TO, 7,
+R_H_LINE_TO, 3,
+V_LINE_TO, 4,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 3,
+R_H_LINE_TO, 3,
+CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_volume_down.1x.icon b/ash/components/shortcut_viewer/vector_icons/ksv_volume_down.1x.icon
deleted file mode 100644
index 1e55f0ce..0000000
--- a/ash/components/shortcut_viewer/vector_icons/ksv_volume_down.1x.icon
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2018 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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 4, 6.31f,
-LINE_TO, 4, 9.69f,
-LINE_TO, 6.25f, 9.69f,
-LINE_TO, 9.06f, 12.5f,
-LINE_TO, 9.06f, 3.5f,
-LINE_TO, 6.25f, 6.31f,
-LINE_TO, 4, 6.31f,
-CLOSE,
-MOVE_TO, 11.59f, 8,
-CUBIC_TO, 11.59f, 7, 11.02f, 6.15f, 10.19f, 5.73f,
-LINE_TO, 10.19f, 10.26f,
-CUBIC_TO, 11.02f, 9.85f, 11.59f, 9, 11.59f, 8,
-CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_volume_down.icon b/ash/components/shortcut_viewer/vector_icons/ksv_volume_down.icon
index d24273cb..32044125 100644
--- a/ash/components/shortcut_viewer/vector_icons/ksv_volume_down.icon
+++ b/ash/components/shortcut_viewer/vector_icons/ksv_volume_down.icon
@@ -16,3 +16,18 @@
 LINE_TO, 20.37f, 20.52f,
 CUBIC_TO, 22.04f, 19.7f, 23.19f, 17.99f, 23.19f, 16,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 4, 6.31f,
+LINE_TO, 4, 9.69f,
+LINE_TO, 6.25f, 9.69f,
+LINE_TO, 9.06f, 12.5f,
+LINE_TO, 9.06f, 3.5f,
+LINE_TO, 6.25f, 6.31f,
+LINE_TO, 4, 6.31f,
+CLOSE,
+MOVE_TO, 11.59f, 8,
+CUBIC_TO, 11.59f, 7, 11.02f, 6.15f, 10.19f, 5.73f,
+LINE_TO, 10.19f, 10.26f,
+CUBIC_TO, 11.02f, 9.85f, 11.59f, 9, 11.59f, 8,
+CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_volume_up.1x.icon b/ash/components/shortcut_viewer/vector_icons/ksv_volume_up.1x.icon
deleted file mode 100644
index f59c157..0000000
--- a/ash/components/shortcut_viewer/vector_icons/ksv_volume_up.1x.icon
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2018 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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 9.18f, 3,
-LINE_TO, 9.18f, 4.16f,
-CUBIC_TO, 10.8f, 4.64f, 11.99f, 6.15f, 11.99f, 7.93f,
-CUBIC_TO, 11.99f, 9.71f, 10.8f, 11.21f, 9.18f, 11.7f,
-LINE_TO, 9.18f, 12.85f,
-CUBIC_TO, 11.43f, 12.34f, 13.11f, 10.33f, 13.11f, 7.93f,
-CUBIC_TO, 13.11f, 5.52f, 11.43f, 3.51f, 9.18f, 3,
-CLOSE,
-MOVE_TO, 10.58f, 7.93f,
-CUBIC_TO, 10.58f, 6.93f, 10.01f, 6.08f, 9.18f, 5.66f,
-LINE_TO, 9.18f, 10.19f,
-CUBIC_TO, 10.01f, 9.78f, 10.58f, 8.92f, 10.58f, 7.93f,
-CLOSE,
-MOVE_TO, 3, 6.24f,
-LINE_TO, 3, 9.61f,
-LINE_TO, 5.25f, 9.61f,
-LINE_TO, 8.06f, 12.42f,
-LINE_TO, 8.06f, 3.43f,
-LINE_TO, 5.25f, 6.24f,
-LINE_TO, 3, 6.24f,
-CLOSE
diff --git a/ash/components/shortcut_viewer/vector_icons/ksv_volume_up.icon b/ash/components/shortcut_viewer/vector_icons/ksv_volume_up.icon
index 4a77d47..81effdc 100644
--- a/ash/components/shortcut_viewer/vector_icons/ksv_volume_up.icon
+++ b/ash/components/shortcut_viewer/vector_icons/ksv_volume_up.icon
@@ -24,3 +24,26 @@
 LINE_TO, 10.49f, 12.48f,
 LINE_TO, 6, 12.48f,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 9.18f, 3,
+LINE_TO, 9.18f, 4.16f,
+CUBIC_TO, 10.8f, 4.64f, 11.99f, 6.15f, 11.99f, 7.93f,
+CUBIC_TO, 11.99f, 9.71f, 10.8f, 11.21f, 9.18f, 11.7f,
+LINE_TO, 9.18f, 12.85f,
+CUBIC_TO, 11.43f, 12.34f, 13.11f, 10.33f, 13.11f, 7.93f,
+CUBIC_TO, 13.11f, 5.52f, 11.43f, 3.51f, 9.18f, 3,
+CLOSE,
+MOVE_TO, 10.58f, 7.93f,
+CUBIC_TO, 10.58f, 6.93f, 10.01f, 6.08f, 9.18f, 5.66f,
+LINE_TO, 9.18f, 10.19f,
+CUBIC_TO, 10.01f, 9.78f, 10.58f, 8.92f, 10.58f, 7.93f,
+CLOSE,
+MOVE_TO, 3, 6.24f,
+LINE_TO, 3, 9.61f,
+LINE_TO, 5.25f, 9.61f,
+LINE_TO, 8.06f, 12.42f,
+LINE_TO, 8.06f, 3.43f,
+LINE_TO, 5.25f, 6.24f,
+LINE_TO, 3, 6.24f,
+CLOSE
diff --git a/ash/components/shortcut_viewer/views/keyboard_shortcut_item_view.cc b/ash/components/shortcut_viewer/views/keyboard_shortcut_item_view.cc
index b0a85236..98c937b 100644
--- a/ash/components/shortcut_viewer/views/keyboard_shortcut_item_view.cc
+++ b/ash/components/shortcut_viewer/views/keyboard_shortcut_item_view.cc
@@ -11,6 +11,7 @@
 #include "ash/components/shortcut_viewer/keyboard_shortcut_viewer_metadata.h"
 #include "ash/components/shortcut_viewer/vector_icons/vector_icons.h"
 #include "ash/components/shortcut_viewer/views/bubble_view.h"
+#include "ash/components/strings/grit/ash_components_strings.h"
 #include "base/i18n/rtl.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/accessibility/ax_node_data.h"
@@ -20,7 +21,6 @@
 #include "ui/views/border.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/styled_label.h"
-
 namespace keyboard_shortcut_viewer {
 
 namespace {
@@ -73,12 +73,25 @@
   const size_t shortcut_key_codes_size = item.shortcut_key_codes.size();
   offsets.reserve(shortcut_key_codes_size);
   replacement_strings.reserve(shortcut_key_codes_size);
-  for (ui::KeyboardCode key_code : item.shortcut_key_codes)
-    replacement_strings.emplace_back(GetStringForKeyboardCode(key_code));
+  bool has_invalid_dom_key = false;
+  for (ui::KeyboardCode key_code : item.shortcut_key_codes) {
+    const base::string16& dom_key_string = GetStringForKeyboardCode(key_code);
+    // If the |key_code| has no mapped |dom_key_string|, we use alternative
+    // string to indicate that the shortcut is not supported by current keyboard
+    // layout.
+    if (dom_key_string.empty()) {
+      replacement_strings.clear();
+      has_invalid_dom_key = true;
+      break;
+    }
+    replacement_strings.emplace_back(dom_key_string);
+  }
 
   base::string16 shortcut_string;
   if (replacement_strings.empty()) {
-    shortcut_string = l10n_util::GetStringUTF16(item.shortcut_message_id);
+    shortcut_string = l10n_util::GetStringUTF16(has_invalid_dom_key
+                                                    ? IDS_KSV_KEY_NO_MAPPING
+                                                    : item.shortcut_message_id);
   } else {
     shortcut_string = l10n_util::GetStringFUTF16(item.shortcut_message_id,
                                                  replacement_strings, &offsets);
diff --git a/ash/components/shortcut_viewer/views/keyboard_shortcut_view.cc b/ash/components/shortcut_viewer/views/keyboard_shortcut_view.cc
index 21246573..a0a0bae 100644
--- a/ash/components/shortcut_viewer/views/keyboard_shortcut_view.cc
+++ b/ash/components/shortcut_viewer/views/keyboard_shortcut_view.cc
@@ -19,6 +19,7 @@
 #include "base/i18n/string_search.h"
 #include "base/metrics/user_metrics.h"
 #include "base/metrics/user_metrics_action.h"
+#include "base/strings/string_number_conversions.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/window.h"
 #include "ui/base/default_style.h"
@@ -139,11 +140,79 @@
                         new gfx::ImageSkia(*icon));
 
     g_ksv_view->GetWidget()->Show();
-    g_ksv_view->RequestFocusForActiveTab();
+    g_ksv_view->search_box_view_->search_box()->RequestFocus();
   }
   return g_ksv_view->GetWidget();
 }
 
+void KeyboardShortcutView::Layout() {
+  gfx::Rect content_bounds(GetContentsBounds());
+  if (content_bounds.IsEmpty())
+    return;
+
+  constexpr int kSearchBoxTopPadding = 8;
+  constexpr int kSearchBoxBottomPadding = 16;
+  constexpr int kSearchBoxHorizontalPadding = 30;
+  const int left = content_bounds.x();
+  const int top = content_bounds.y();
+  gfx::Rect search_box_bounds(search_box_view_->GetPreferredSize());
+  search_box_bounds.set_width(
+      std::min(search_box_bounds.width(),
+               content_bounds.width() - 2 * kSearchBoxHorizontalPadding));
+  search_box_bounds.set_x(
+      left + (content_bounds.width() - search_box_bounds.width()) / 2);
+  search_box_bounds.set_y(top + kSearchBoxTopPadding);
+  search_box_view_->SetBoundsRect(search_box_bounds);
+
+  views::View* content_view = categories_tabbed_pane_->visible()
+                                  ? categories_tabbed_pane_
+                                  : search_results_container_;
+  const int search_box_used_height = search_box_bounds.height() +
+                                     kSearchBoxTopPadding +
+                                     kSearchBoxBottomPadding;
+  content_view->SetBounds(left, top + search_box_used_height,
+                          content_bounds.width(),
+                          content_bounds.height() - search_box_used_height);
+}
+
+void KeyboardShortcutView::QueryChanged(search_box::SearchBoxViewBase* sender) {
+  const bool query_empty = sender->IsSearchBoxTrimmedQueryEmpty();
+  if (is_search_box_empty_ != query_empty) {
+    is_search_box_empty_ = query_empty;
+    UpdateViewsLayout(/*is_search_box_active=*/true);
+  }
+
+  debounce_timer_.Stop();
+  // If search box is empty, do not show |search_results_container_|.
+  if (query_empty)
+    return;
+
+  // TODO(wutao): This timeout value is chosen based on subjective search
+  // latency tests on Minnie. Objective method or UMA is desired.
+  constexpr base::TimeDelta kTimeOut(base::TimeDelta::FromMilliseconds(250));
+  debounce_timer_.Start(
+      FROM_HERE, kTimeOut,
+      base::Bind(&KeyboardShortcutView::ShowSearchResults,
+                 base::Unretained(this), sender->search_box()->text()));
+}
+
+void KeyboardShortcutView::BackButtonPressed() {
+  search_box_view_->ClearSearch();
+  search_box_view_->SetSearchBoxActive(false);
+}
+
+void KeyboardShortcutView::ActiveChanged(
+    search_box::SearchBoxViewBase* sender) {
+  const bool is_search_box_active = sender->is_search_box_active();
+  is_search_box_empty_ = sender->IsSearchBoxTrimmedQueryEmpty();
+  sender->ShowBackOrGoogleIcon(is_search_box_active);
+  if (is_search_box_active) {
+    base::RecordAction(
+        base::UserMetricsAction("KeyboardShortcutViewer.Search"));
+  }
+  UpdateViewsLayout(is_search_box_active);
+}
+
 KeyboardShortcutView::KeyboardShortcutView() {
   DCHECK_EQ(g_ksv_view, nullptr);
   g_ksv_view = this;
@@ -235,99 +304,6 @@
   }
 }
 
-void KeyboardShortcutView::RequestFocusForActiveTab() {
-  // Get the |tab_strip_| of the |categories_tabbed_pane_| in order to set focus
-  // on the selected tab.
-  categories_tabbed_pane_->child_at(0)
-      ->child_at(active_tab_index_)
-      ->RequestFocus();
-}
-
-bool KeyboardShortcutView::CanMaximize() const {
-  return false;
-}
-
-bool KeyboardShortcutView::CanMinimize() const {
-  return true;
-}
-
-bool KeyboardShortcutView::CanResize() const {
-  return false;
-}
-
-views::ClientView* KeyboardShortcutView::CreateClientView(
-    views::Widget* widget) {
-  return new views::ClientView(widget, this);
-}
-
-void KeyboardShortcutView::Layout() {
-  gfx::Rect content_bounds(GetContentsBounds());
-  if (content_bounds.IsEmpty())
-    return;
-
-  constexpr int kSearchBoxTopPadding = 8;
-  constexpr int kSearchBoxBottomPadding = 16;
-  constexpr int kSearchBoxHorizontalPadding = 30;
-  const int left = content_bounds.x();
-  const int top = content_bounds.y();
-  gfx::Rect search_box_bounds(search_box_view_->GetPreferredSize());
-  search_box_bounds.set_width(
-      std::min(search_box_bounds.width(),
-               content_bounds.width() - 2 * kSearchBoxHorizontalPadding));
-  search_box_bounds.set_x(
-      left + (content_bounds.width() - search_box_bounds.width()) / 2);
-  search_box_bounds.set_y(top + kSearchBoxTopPadding);
-  search_box_view_->SetBoundsRect(search_box_bounds);
-
-  views::View* content_view = categories_tabbed_pane_->visible()
-                                  ? categories_tabbed_pane_
-                                  : search_results_container_;
-  const int search_box_used_height = search_box_bounds.height() +
-                                     kSearchBoxTopPadding +
-                                     kSearchBoxBottomPadding;
-  content_view->SetBounds(left, top + search_box_used_height,
-                          content_bounds.width(),
-                          content_bounds.height() - search_box_used_height);
-}
-
-void KeyboardShortcutView::BackButtonPressed() {
-  search_box_view_->ClearSearch();
-  search_box_view_->SetSearchBoxActive(false);
-}
-
-void KeyboardShortcutView::QueryChanged(search_box::SearchBoxViewBase* sender) {
-  const bool query_empty = sender->IsSearchBoxTrimmedQueryEmpty();
-  if (is_search_box_empty_ != query_empty) {
-    is_search_box_empty_ = query_empty;
-    UpdateViewsLayout(/*is_search_box_active=*/true);
-  }
-
-  debounce_timer_.Stop();
-  // If search box is empty, do not show |search_results_container_|.
-  if (query_empty)
-    return;
-
-  // TODO(wutao): This timeout value is chosen based on subjective search
-  // latency tests on Minnie. Objective method or UMA is desired.
-  constexpr base::TimeDelta kTimeOut(base::TimeDelta::FromMilliseconds(250));
-  debounce_timer_.Start(
-      FROM_HERE, kTimeOut,
-      base::Bind(&KeyboardShortcutView::ShowSearchResults,
-                 base::Unretained(this), sender->search_box()->text()));
-}
-
-void KeyboardShortcutView::ActiveChanged(
-    search_box::SearchBoxViewBase* sender) {
-  const bool is_search_box_active = sender->is_search_box_active();
-  is_search_box_empty_ = sender->IsSearchBoxTrimmedQueryEmpty();
-  sender->ShowBackOrGoogleIcon(is_search_box_active);
-  if (is_search_box_active) {
-    base::RecordAction(
-        base::UserMetricsAction("KeyboardShortcutViewer.Search"));
-  }
-  UpdateViewsLayout(is_search_box_active);
-}
-
 void KeyboardShortcutView::UpdateViewsLayout(bool is_search_box_active) {
   // 1. Search box is not active: show |categories_tabbed_pane_| and focus on
   //    active tab.
@@ -348,8 +324,6 @@
       // Select the category that was active before entering search mode.
       categories_tabbed_pane_->SelectTabAt(active_tab_index_);
     }
-    if (!is_search_box_active)
-      RequestFocusForActiveTab();
   }
   categories_tabbed_pane_->SetVisible(!should_show_search_results);
   search_results_container_->SetVisible(should_show_search_results);
@@ -366,6 +340,7 @@
       search_query);
   ShortcutCategory current_category = ShortcutCategory::kUnknown;
   bool has_category_item = false;
+  int number_search_results = 0;
   for (const auto& item_view : shortcut_views_) {
     base::string16 description_text =
         item_view->description_label_view()->text();
@@ -405,10 +380,15 @@
       }
 
       found_items_list_view->AddChildView(item_view.get());
+      ++number_search_results;
     }
   }
 
+  std::vector<base::string16> replacement_strings;
   if (found_items_list_view->has_children()) {
+    replacement_strings.emplace_back(
+        base::NumberToString16(number_search_results));
+
     // To offset the padding between the bottom of the |search_box_view_| and
     // the top of the |search_results_container_|.
     constexpr int kTopPadding = -16;
@@ -419,12 +399,34 @@
     scroller->SetContents(found_items_list_view.release());
     search_container_content_view = scroller;
   }
-
+  replacement_strings.emplace_back(search_query);
+  search_box_view_->SetAccessibleValue(l10n_util::GetStringFUTF16(
+      number_search_results == 0
+          ? IDS_KSV_SEARCH_BOX_ACCESSIBILITY_VALUE_WITHOUT_RESULTS
+          : IDS_KSV_SEARCH_BOX_ACCESSIBILITY_VALUE_WITH_RESULTS,
+      replacement_strings, nullptr));
   search_results_container_->AddChildView(search_container_content_view);
   Layout();
   SchedulePaint();
 }
 
+bool KeyboardShortcutView::CanMaximize() const {
+  return false;
+}
+
+bool KeyboardShortcutView::CanMinimize() const {
+  return true;
+}
+
+bool KeyboardShortcutView::CanResize() const {
+  return false;
+}
+
+views::ClientView* KeyboardShortcutView::CreateClientView(
+    views::Widget* widget) {
+  return new views::ClientView(widget, this);
+}
+
 KeyboardShortcutView* KeyboardShortcutView::GetInstanceForTesting() {
   return g_ksv_view;
 }
@@ -438,4 +440,8 @@
   return shortcut_views_;
 }
 
+KSVSearchBoxView* KeyboardShortcutView::GetSearchBoxViewForTesting() {
+  return search_box_view_.get();
+}
+
 }  // namespace keyboard_shortcut_viewer
diff --git a/ash/components/shortcut_viewer/views/keyboard_shortcut_view.h b/ash/components/shortcut_viewer/views/keyboard_shortcut_view.h
index 47f212f9..f19fb7d 100644
--- a/ash/components/shortcut_viewer/views/keyboard_shortcut_view.h
+++ b/ash/components/shortcut_viewer/views/keyboard_shortcut_view.h
@@ -53,10 +53,6 @@
   // |shortcut_views_|, called on construction and when exiting search mode.
   void InitCategoriesTabbedPane();
 
-  // Put focus on the active tab. Used when the first time to show the widget or
-  // after exiting search mode.
-  void RequestFocusForActiveTab();
-
   // Update views' layout based on search box status.
   void UpdateViewsLayout(bool is_search_box_active);
 
@@ -73,6 +69,7 @@
   int GetTabCountForTesting() const;
   const std::vector<std::unique_ptr<KeyboardShortcutItemView>>&
   GetShortcutViewsForTesting() const;
+  KSVSearchBoxView* GetSearchBoxViewForTesting();
 
   // Owned by views hierarchy.
   // The container for category tabs and lists of KeyboardShortcutItemViews.
diff --git a/ash/components/shortcut_viewer/views/keyboard_shortcut_view_unittest.cc b/ash/components/shortcut_viewer/views/keyboard_shortcut_view_unittest.cc
index b43ab0a..a781c9a 100644
--- a/ash/components/shortcut_viewer/views/keyboard_shortcut_view_unittest.cc
+++ b/ash/components/shortcut_viewer/views/keyboard_shortcut_view_unittest.cc
@@ -8,8 +8,10 @@
 
 #include "ash/components/shortcut_viewer/keyboard_shortcut_viewer_metadata.h"
 #include "ash/components/shortcut_viewer/views/keyboard_shortcut_item_view.h"
+#include "ash/components/shortcut_viewer/views/ksv_search_box_view.h"
 #include "ash/test/ash_test_base.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/views/controls/textfield/textfield.h"
 #include "ui/views/widget/widget.h"
 
 namespace keyboard_shortcut_viewer {
@@ -31,6 +33,25 @@
     return GetView()->GetShortcutViewsForTesting();
   }
 
+  KSVSearchBoxView* GetSearchBoxView() {
+    DCHECK(GetView());
+    return GetView()->GetSearchBoxViewForTesting();
+  }
+
+  void KeyPress(ui::KeyboardCode key_code, bool should_insert) {
+    ui::KeyEvent event(ui::ET_KEY_PRESSED, key_code, ui::EF_NONE);
+    GetSearchBoxView()->OnKeyEvent(&event);
+    if (!should_insert)
+      return;
+
+    // Emulates the input method.
+    if (::isalnum(static_cast<int>(key_code))) {
+      base::char16 character = ::tolower(static_cast<int>(key_code));
+      GetSearchBoxView()->search_box()->InsertText(
+          base::string16(1, character));
+    }
+  }
+
  private:
   KeyboardShortcutView* GetView() const {
     return KeyboardShortcutView::GetInstanceForTesting();
@@ -95,4 +116,41 @@
   widget->CloseNow();
 }
 
+// Test that the focus is on search box when window inits and exits search mode.
+TEST_F(KeyboardShortcutViewTest, FocusOnSearchBox) {
+  // Showing the widget.
+  views::Widget* widget = KeyboardShortcutView::Show(CurrentContext());
+
+  // Case 1: when window creates. The focus should be on search box.
+  EXPECT_TRUE(GetSearchBoxView()->search_box()->HasFocus());
+
+  // Press a key should enter search mode.
+  KeyPress(ui::VKEY_A, /*should_insert=*/true);
+  EXPECT_TRUE(GetSearchBoxView()->back_button()->visible());
+  EXPECT_FALSE(GetSearchBoxView()->search_box()->text().empty());
+
+  // Case 2: Exit search mode by clicking |back_button|. The focus should be on
+  // search box.
+  GetSearchBoxView()->ButtonPressed(
+      GetSearchBoxView()->back_button(),
+      ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
+                     base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON,
+                     ui::EF_LEFT_MOUSE_BUTTON));
+  EXPECT_TRUE(GetSearchBoxView()->search_box()->text().empty());
+  EXPECT_TRUE(GetSearchBoxView()->search_box()->HasFocus());
+
+  // Enter search mode again.
+  KeyPress(ui::VKEY_A, /*should_insert=*/true);
+  EXPECT_FALSE(GetSearchBoxView()->search_box()->text().empty());
+
+  // Case 3: Exit search mode by pressing |VKEY_ESCAPE|. The focus should be on
+  // search box.
+  KeyPress(ui::VKEY_ESCAPE, /*should_insert=*/false);
+  EXPECT_TRUE(GetSearchBoxView()->search_box()->text().empty());
+  EXPECT_TRUE(GetSearchBoxView()->search_box()->HasFocus());
+
+  // Cleaning up.
+  widget->CloseNow();
+}
+
 }  // namespace keyboard_shortcut_viewer
diff --git a/ash/components/shortcut_viewer/views/ksv_search_box_view.cc b/ash/components/shortcut_viewer/views/ksv_search_box_view.cc
index 520c460..1ea091c8 100644
--- a/ash/components/shortcut_viewer/views/ksv_search_box_view.cc
+++ b/ash/components/shortcut_viewer/views/ksv_search_box_view.cc
@@ -6,6 +6,7 @@
 
 #include "ash/components/shortcut_viewer/vector_icons/vector_icons.h"
 #include "ash/components/strings/grit/ash_components_strings.h"
+#include "ui/accessibility/ax_node_data.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/chromeos/search_box/search_box_view_delegate.h"
 #include "ui/gfx/canvas.h"
@@ -52,6 +53,11 @@
   return gfx::Size(740, 32);
 }
 
+void KSVSearchBoxView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
+  node_data->role = ax::mojom::Role::kSearchBox;
+  node_data->SetValue(accessible_value_);
+}
+
 void KSVSearchBoxView::OnKeyEvent(ui::KeyEvent* event) {
   const ui::KeyboardCode key = event->key_code();
   const bool is_escape_key = (key == ui::VKEY_ESCAPE);
@@ -74,6 +80,11 @@
   SearchBoxViewBase::ButtonPressed(sender, event);
 }
 
+void KSVSearchBoxView::SetAccessibleValue(const base::string16& value) {
+  accessible_value_ = value;
+  NotifyAccessibilityEvent(ax::mojom::Event::kValueChanged, true);
+}
+
 void KSVSearchBoxView::UpdateBackgroundColor(SkColor color) {
   SetSearchBoxBackgroundColor(color);
 }
diff --git a/ash/components/shortcut_viewer/views/ksv_search_box_view.h b/ash/components/shortcut_viewer/views/ksv_search_box_view.h
index e32349b..913ac917 100644
--- a/ash/components/shortcut_viewer/views/ksv_search_box_view.h
+++ b/ash/components/shortcut_viewer/views/ksv_search_box_view.h
@@ -6,6 +6,7 @@
 #define ASH_COMPONENTS_SHORTCUT_VIEWER_VIEWS_KSV_SEARCH_BOX_VIEW_H_
 
 #include "base/macros.h"
+#include "base/strings/string16.h"
 #include "ui/chromeos/search_box/search_box_view_base.h"
 
 namespace search_box {
@@ -22,11 +23,14 @@
 
   // views::View:
   gfx::Size CalculatePreferredSize() const override;
+  void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
   void OnKeyEvent(ui::KeyEvent* event) override;
 
   // Overridden from views::ButtonListener:
   void ButtonPressed(views::Button* sender, const ui::Event& event) override;
 
+  void SetAccessibleValue(const base::string16& value);
+
  private:
   // search_box::SearchBoxViewBase:
   void ModelChanged() override {}
@@ -38,6 +42,9 @@
   void SetupCloseButton() override;
   void SetupBackButton() override;
 
+  // Accessibility data value. Used to pronounce the number of search results.
+  base::string16 accessible_value_;
+
   DISALLOW_COPY_AND_ASSIGN(KSVSearchBoxView);
 };
 
diff --git a/ash/components/shortcut_viewer_strings.grdp b/ash/components/shortcut_viewer_strings.grdp
index 37bcf08e..15cd51d 100644
--- a/ash/components/shortcut_viewer_strings.grdp
+++ b/ash/components/shortcut_viewer_strings.grdp
@@ -15,6 +15,12 @@
   <message name="IDS_KSV_CLEAR_SEARCHBOX_ACCESSIBILITY_NAME" desc="Accessibility name for the button that clears all text from the search box.">
     Clear searchbox text
   </message>
+  <message name="IDS_KSV_SEARCH_BOX_ACCESSIBILITY_VALUE_WITH_RESULTS" desc="Accessibility value for the search box with searched results.">
+    Displaying <ph name="n">$1<ex>1</ex></ph> search results for <ph name="query">$2<ex>a</ex></ph>
+  </message>
+  <message name="IDS_KSV_SEARCH_BOX_ACCESSIBILITY_VALUE_WITHOUT_RESULTS" desc="Accessibility value for the search box without searched results.">
+    No search result for <ph name="query">$1<ex>a</ex></ph>
+  </message>
 
   <!-- Search illustration -->
   <message name="IDS_KSV_SEARCH_NO_RESULT" desc="No search results.">
@@ -71,6 +77,9 @@
   <message name="IDS_KSV_KEY_FULLSCREEN" desc="Name of the key on a Chromebook keyboard that triggers the fullscreen.">
     Fullscreen key
   </message>
+  <message name="IDS_KSV_KEY_NO_MAPPING" desc="Alternative string to display if no meaning found for the key.">
+    Not supported with current keyboard layout
+  </message>
 
   <!-- Generic shortcut strings -->
   <message name="IDS_KSV_SHORTCUT_ONE_KEY" desc="Human readable version of the keyboard shortcut. This is for all single key shortcuts.">
diff --git a/ash/content/keyboard_overlay/keyboard_overlay_delegate.cc b/ash/content/keyboard_overlay/keyboard_overlay_delegate.cc
index 6ff9e1f..ab1c28c 100644
--- a/ash/content/keyboard_overlay/keyboard_overlay_delegate.cc
+++ b/ash/content/keyboard_overlay/keyboard_overlay_delegate.cc
@@ -48,7 +48,8 @@
 
 void PaintMessageHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
-      "didPaint", base::Bind(&PaintMessageHandler::DidPaint, AsWeakPtr()));
+      "didPaint",
+      base::BindRepeating(&PaintMessageHandler::DidPaint, AsWeakPtr()));
 }
 
 void PaintMessageHandler::DidPaint(const base::ListValue* args) {
diff --git a/ash/drag_drop/drag_drop_tracker.cc b/ash/drag_drop/drag_drop_tracker.cc
index 1f814b3..63ba697e17 100644
--- a/ash/drag_drop/drag_drop_tracker.cc
+++ b/ash/drag_drop/drag_drop_tracker.cc
@@ -85,10 +85,12 @@
   aura::Window::ConvertPointToTarget(capture_window_->GetRootWindow(),
                                      wm::GetRootWindowAt(location_in_screen),
                                      &target_root_location);
-  return new ui::MouseEvent(
-      event.type(), target_location, target_root_location,
-      ui::EventTimeForNow(), event.flags(),
-      static_cast<const ui::MouseEvent&>(event).changed_button_flags());
+  int changed_button_flags = 0;
+  if (event.IsMouseEvent())
+    changed_button_flags = event.AsMouseEvent()->changed_button_flags();
+  return new ui::MouseEvent(event.type(), target_location, target_root_location,
+                            ui::EventTimeForNow(), event.flags(),
+                            changed_button_flags);
 }
 
 }  // namespace ash
diff --git a/ash/frame/caption_buttons/frame_back_button.cc b/ash/frame/caption_buttons/frame_back_button.cc
index f738c2b..f035551 100644
--- a/ash/frame/caption_buttons/frame_back_button.cc
+++ b/ash/frame/caption_buttons/frame_back_button.cc
@@ -20,7 +20,7 @@
 FrameBackButton::FrameBackButton()
     : FrameCaptionButton(this, CAPTION_BUTTON_ICON_BACK) {
   SetImage(CAPTION_BUTTON_ICON_BACK, ANIMATE_NO, kWindowControlBackIcon);
-  SetPreferredSize(GetAshLayoutSize(AshLayoutSize::NON_BROWSER_CAPTION_BUTTON));
+  SetPreferredSize(GetAshLayoutSize(AshLayoutSize::kNonBrowserCaption));
   SetAccessibleName(
       l10n_util::GetStringUTF16(IDS_ASH_WINDOW_CONTROL_ACCNAME_BACK));
 }
diff --git a/ash/frame/caption_buttons/frame_caption_button.h b/ash/frame/caption_buttons/frame_caption_button.h
index 5c9a606..365b844 100644
--- a/ash/frame/caption_buttons/frame_caption_button.h
+++ b/ash/frame/caption_buttons/frame_caption_button.h
@@ -65,6 +65,10 @@
 
   CaptionButtonIcon icon() const { return icon_; }
 
+  const gfx::VectorIcon* icon_definition_for_test() const {
+    return icon_definition_;
+  }
+
  protected:
   // views::Button override:
   void PaintButtonContents(gfx::Canvas* canvas) override;
diff --git a/ash/frame/caption_buttons/frame_caption_button_container_view_unittest.cc b/ash/frame/caption_buttons/frame_caption_button_container_view_unittest.cc
index 4d99a9bf..d3ddaef93 100644
--- a/ash/frame/caption_buttons/frame_caption_button_container_view_unittest.cc
+++ b/ash/frame/caption_buttons/frame_caption_button_container_view_unittest.cc
@@ -67,7 +67,7 @@
   // size to the buttons in |container|.
   void InitContainer(FrameCaptionButtonContainerView* container) {
     container->SetButtonSize(
-        GetAshLayoutSize(AshLayoutSize::NON_BROWSER_CAPTION_BUTTON));
+        GetAshLayoutSize(AshLayoutSize::kNonBrowserCaption));
     for (int icon = 0; icon < CAPTION_BUTTON_ICON_COUNT; ++icon) {
       container->SetButtonImage(static_cast<CaptionButtonIcon>(icon),
                                 ash::kWindowControlCloseIcon);
diff --git a/ash/frame/caption_buttons/frame_size_button_unittest.cc b/ash/frame/caption_buttons/frame_size_button_unittest.cc
index be6eb6c..19f092b 100644
--- a/ash/frame/caption_buttons/frame_size_button_unittest.cc
+++ b/ash/frame/caption_buttons/frame_size_button_unittest.cc
@@ -59,7 +59,7 @@
       // Set arbitrary images for the button icons and assign the default
       // caption button size.
       caption_button_container_->SetButtonSize(
-          GetAshLayoutSize(AshLayoutSize::NON_BROWSER_CAPTION_BUTTON));
+          GetAshLayoutSize(AshLayoutSize::kNonBrowserCaption));
       for (int icon = 0; icon < CAPTION_BUTTON_ICON_COUNT; ++icon) {
         caption_button_container_->SetButtonImage(
             static_cast<CaptionButtonIcon>(icon), kWindowControlCloseIcon);
diff --git a/ash/frame/custom_frame_view_ash_unittest.cc b/ash/frame/custom_frame_view_ash_unittest.cc
index 4a0a4c8..20a7fc7 100644
--- a/ash/frame/custom_frame_view_ash_unittest.cc
+++ b/ash/frame/custom_frame_view_ash_unittest.cc
@@ -146,9 +146,8 @@
 
   // The header should have enough room for the window controls. The
   // header/content separator line overlays the window controls.
-  EXPECT_EQ(
-      GetAshLayoutSize(AshLayoutSize::NON_BROWSER_CAPTION_BUTTON).height(),
-      delegate->custom_frame_view()->GetHeaderView()->height());
+  EXPECT_EQ(GetAshLayoutSize(AshLayoutSize::kNonBrowserCaption).height(),
+            delegate->custom_frame_view()->GetHeaderView()->height());
 }
 
 // Verify that CustomFrameViewAsh returns the correct minimum and maximum frame
@@ -269,9 +268,8 @@
   std::unique_ptr<views::Widget> widget(CreateWidget(delegate));
 
   Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(true);
-  EXPECT_EQ(
-      GetAshLayoutSize(AshLayoutSize::NON_BROWSER_CAPTION_BUTTON).height(),
-      delegate->GetCustomFrameViewTopBorderHeight());
+  EXPECT_EQ(GetAshLayoutSize(AshLayoutSize::kNonBrowserCaption).height(),
+            delegate->GetCustomFrameViewTopBorderHeight());
 }
 
 // Verify that if originally in fullscreen mode, and enter tablet mode, the
@@ -313,9 +311,8 @@
   EXPECT_EQ(0, delegate->GetCustomFrameViewTopBorderHeight());
 
   Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(false);
-  EXPECT_EQ(
-      GetAshLayoutSize(AshLayoutSize::NON_BROWSER_CAPTION_BUTTON).height(),
-      delegate->GetCustomFrameViewTopBorderHeight());
+  EXPECT_EQ(GetAshLayoutSize(AshLayoutSize::kNonBrowserCaption).height(),
+            delegate->GetCustomFrameViewTopBorderHeight());
 }
 
 // Verify windows that are minimized and then entered into tablet mode will have
diff --git a/ash/frame/default_frame_header.cc b/ash/frame/default_frame_header.cc
index 94ae882..b902fb3b 100644
--- a/ash/frame/default_frame_header.cc
+++ b/ash/frame/default_frame_header.cc
@@ -10,6 +10,8 @@
 #include "ash/frame/frame_header_util.h"
 #include "ash/public/cpp/vector_icons/vector_icons.h"
 #include "ash/resources/grit/ash_resources.h"
+#include "ash/shell.h"
+#include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "base/debug/leak_annotations.h"
 #include "base/logging.h"  // DCHECK
 #include "third_party/skia/include/core/SkPath.h"
@@ -92,7 +94,7 @@
   DCHECK(header_view);
   DCHECK(caption_button_container);
   caption_button_container_->SetButtonSize(
-      GetAshLayoutSize(AshLayoutSize::NON_BROWSER_CAPTION_BUTTON));
+      GetAshLayoutSize(AshLayoutSize::kNonBrowserCaption));
   UpdateAllButtonImages();
 }
 
@@ -150,11 +152,14 @@
 void DefaultFrameHeader::LayoutHeader() {
   // TODO(sky): this needs to reset images as well.
   if (window_style_ == mojom::WindowStyle::BROWSER) {
+    const bool is_in_tablet_mode = Shell::Get()
+                                       ->tablet_mode_controller()
+                                       ->IsTabletModeWindowManagerEnabled();
     const bool use_maximized_size =
-        frame_->IsMaximized() || frame_->IsFullscreen();
+        frame_->IsMaximized() || frame_->IsFullscreen() || is_in_tablet_mode;
     const gfx::Size button_size(GetAshLayoutSize(
-        use_maximized_size ? AshLayoutSize::BROWSER_MAXIMIZED_CAPTION_BUTTON
-                           : AshLayoutSize::BROWSER_RESTORED_CAPTION_BUTTON));
+        use_maximized_size ? AshLayoutSize::kBrowserCaptionMaximized
+                           : AshLayoutSize::kBrowserCaptionRestored));
     caption_button_container_->SetButtonSize(button_size);
   }
 
@@ -329,6 +334,10 @@
 }
 
 void DefaultFrameHeader::UpdateSizeButtonImages() {
+  // When |frame_| minimized, avoid tablet mode toggling to update caption
+  // buttons as it would cause mismatch beteen window state and size button.
+  if (frame_->IsMinimized())
+    return;
   const gfx::VectorIcon& icon = frame_->IsMaximized() || frame_->IsFullscreen()
                                     ? kWindowControlRestoreIcon
                                     : kWindowControlMaximizeIcon;
diff --git a/ash/frame/header_view.cc b/ash/frame/header_view.cc
index c46c339..279411ab 100644
--- a/ash/frame/header_view.cc
+++ b/ash/frame/header_view.cc
@@ -194,8 +194,12 @@
 void HeaderView::OnImmersiveRevealStarted() {
   fullscreen_visible_fraction_ = 0;
   SetPaintToLayer();
-  // The immersive layer should always be top.
-  layer()->parent()->StackAtTop(layer());
+  // AppWindow may call this before being added to the widget.
+  // https://crbug.com/825260.
+  if (layer()->parent()) {
+    // The immersive layer should always be top.
+    layer()->parent()->StackAtTop(layer());
+  }
   parent()->Layout();
 }
 
diff --git a/ash/login/login_screen_controller.cc b/ash/login/login_screen_controller.cc
index 8bdb35fd..203bcc6 100644
--- a/ash/login/login_screen_controller.cc
+++ b/ash/login/login_screen_controller.cc
@@ -327,6 +327,15 @@
   login_screen_client_->RemoveUser(account_id);
 }
 
+void LoginScreenController::LaunchPublicSession(
+    const AccountId& account_id,
+    const std::string& locale,
+    const std::string& input_method) {
+  if (!login_screen_client_)
+    return;
+  login_screen_client_->LaunchPublicSession(account_id, locale, input_method);
+}
+
 void LoginScreenController::AddLockScreenAppsFocusObserver(
     LockScreenAppsFocusObserver* observer) {
   lock_screen_apps_focus_observers_.AddObserver(observer);
diff --git a/ash/login/login_screen_controller.h b/ash/login/login_screen_controller.h
index c1a24b2..987bd69 100644
--- a/ash/login/login_screen_controller.h
+++ b/ash/login/login_screen_controller.h
@@ -94,6 +94,9 @@
   void ShowGaiaSignin();
   void OnRemoveUserWarningShown();
   void RemoveUser(const AccountId& account_id);
+  void LaunchPublicSession(const AccountId& account_id,
+                           const std::string& locale,
+                           const std::string& input_method);
 
   // Methods to manage lock screen apps focus observers.
   // The observers will be notified when lock screen apps focus changes are
diff --git a/ash/login/mock_login_screen_client.h b/ash/login/mock_login_screen_client.h
index 5a9ce6d..bc500c3 100644
--- a/ash/login/mock_login_screen_client.h
+++ b/ash/login/mock_login_screen_client.h
@@ -61,6 +61,10 @@
   MOCK_METHOD0(ShowGaiaSignin, void());
   MOCK_METHOD0(OnRemoveUserWarningShown, void());
   MOCK_METHOD1(RemoveUser, void(const AccountId& account_id));
+  MOCK_METHOD3(LaunchPublicSession,
+               void(const AccountId& account_id,
+                    const std::string& locale,
+                    const std::string& input_method));
 
  private:
   bool authenticate_user_callback_result_ = true;
diff --git a/ash/login/ui/arrow_button_view.cc b/ash/login/ui/arrow_button_view.cc
new file mode 100644
index 0000000..16caa92
--- /dev/null
+++ b/ash/login/ui/arrow_button_view.cc
@@ -0,0 +1,54 @@
+// Copyright 2018 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 "ash/login/ui/arrow_button_view.h"
+
+#include "ash/resources/vector_icons/vector_icons.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/paint_vector_icon.h"
+
+namespace ash {
+namespace {
+
+// Arrow icon size.
+constexpr int kArrowIconSizeDp = 20;
+
+}  // namespace
+
+ArrowButtonView::ArrowButtonView(views::ButtonListener* listener, int size)
+    : LoginButton(listener), size_(size) {
+  SetPreferredSize(gfx::Size(size, size));
+  SetFocusBehavior(FocusBehavior::ALWAYS);
+
+  // Layer rendering is needed for animation.
+  SetPaintToLayer();
+  layer()->SetFillsBoundsOpaquely(false);
+
+  SetImage(Button::STATE_NORMAL,
+           gfx::CreateVectorIcon(kLockScreenArrowIcon, kArrowIconSizeDp,
+                                 SK_ColorWHITE));
+}
+
+ArrowButtonView::~ArrowButtonView() = default;
+
+void ArrowButtonView::PaintButtonContents(gfx::Canvas* canvas) {
+  const gfx::Rect rect(GetContentsBounds());
+
+  // Draw background.
+  cc::PaintFlags flags;
+  flags.setAntiAlias(true);
+  flags.setColor(background_color_);
+  flags.setStyle(cc::PaintFlags::kFill_Style);
+  canvas->DrawCircle(gfx::PointF(rect.CenterPoint()), size_ / 2, flags);
+
+  // Draw arrow icon.
+  views::ImageButton::PaintButtonContents(canvas);
+}
+
+void ArrowButtonView::SetBackgroundColor(SkColor color) {
+  background_color_ = color;
+  SchedulePaint();
+}
+
+}  // namespace ash
diff --git a/ash/login/ui/arrow_button_view.h b/ash/login/ui/arrow_button_view.h
new file mode 100644
index 0000000..441b044
--- /dev/null
+++ b/ash/login/ui/arrow_button_view.h
@@ -0,0 +1,36 @@
+// Copyright 2018 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 ASH_LOGIN_UI_ARROW_BUTTON_VIEW_H_
+#define ASH_LOGIN_UI_ARROW_BUTTON_VIEW_H_
+
+#include "ash/login/ui/login_button.h"
+#include "ui/views/controls/image_view.h"
+
+namespace ash {
+
+// A round button with arrow icon in the middle.
+// This will be used by LoginPublicAccountUserView and expanded public account
+// view.
+class ArrowButtonView : public LoginButton {
+ public:
+  ArrowButtonView(views::ButtonListener* listener, int size);
+  ~ArrowButtonView() override;
+
+  // views::Button:
+  void PaintButtonContents(gfx::Canvas* canvas) override;
+
+  // Set background color of the button.
+  void SetBackgroundColor(SkColor color);
+
+ private:
+  int size_;
+  SkColor background_color_;
+
+  DISALLOW_COPY_AND_ASSIGN(ArrowButtonView);
+};
+
+}  // namespace ash
+
+#endif  // ASH_LOGIN_UI_ARROW_BUTTON_VIEW_H_
diff --git a/ash/login/ui/lock_contents_view.cc b/ash/login/ui/lock_contents_view.cc
index b3a9ad4..4817bf0 100644
--- a/ash/login/ui/lock_contents_view.cc
+++ b/ash/login/ui/lock_contents_view.cc
@@ -16,8 +16,10 @@
 #include "ash/login/ui/layout_util.h"
 #include "ash/login/ui/lock_screen.h"
 #include "ash/login/ui/login_auth_user_view.h"
+#include "ash/login/ui/login_big_user_view.h"
 #include "ash/login/ui/login_bubble.h"
 #include "ash/login/ui/login_detachable_base_model.h"
+#include "ash/login/ui/login_public_account_user_view.h"
 #include "ash/login/ui/login_user_view.h"
 #include "ash/login/ui/non_accessible_view.h"
 #include "ash/login/ui/note_action_launch_button.h"
@@ -32,6 +34,7 @@
 #include "ash/system/tray/system_tray_notifier.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
+#include "components/user_manager/user_type.h"
 #include "mojo/common/values_struct_traits.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -175,18 +178,22 @@
   return keyboard_window == this_window ? keyboard_controller : nullptr;
 }
 
+bool IsPublicAccountUser(const mojom::LoginUserInfoPtr& user) {
+  return user->basic_user_info->type == user_manager::USER_TYPE_PUBLIC_ACCOUNT;
+}
+
 }  // namespace
 
 LockContentsView::TestApi::TestApi(LockContentsView* view) : view_(view) {}
 
 LockContentsView::TestApi::~TestApi() = default;
 
-LoginAuthUserView* LockContentsView::TestApi::primary_auth() const {
-  return view_->primary_auth_;
+LoginBigUserView* LockContentsView::TestApi::primary_big_view() const {
+  return view_->primary_big_view_;
 }
 
-LoginAuthUserView* LockContentsView::TestApi::opt_secondary_auth() const {
-  return view_->opt_secondary_auth_;
+LoginBigUserView* LockContentsView::TestApi::opt_secondary_big_view() const {
+  return view_->opt_secondary_big_view_;
 }
 
 ScrollableUsersListView* LockContentsView::TestApi::users_list() const {
@@ -310,17 +317,17 @@
   DoLayout();
 
   // Focus the primary user when showing the UI. This will focus the password.
-  if (primary_auth_)
-    primary_auth_->RequestFocus();
+  if (primary_big_view_)
+    primary_big_view_->RequestFocus();
 }
 
 void LockContentsView::OnFocus() {
   // If LockContentsView somehow gains focus (ie, a test, but it should not
   // under typical circumstances), immediately forward the focus to the
-  // primary_auth_ since LockContentsView has no real focusable content by
+  // primary_big_view_ since LockContentsView has no real focusable content by
   // itself.
-  if (primary_auth_)
-    primary_auth_->RequestFocus();
+  if (primary_big_view_)
+    primary_big_view_->RequestFocus();
 }
 
 void LockContentsView::AboutToRequestFocusFromTabTraversal(bool reverse) {
@@ -353,7 +360,7 @@
   // The debug view will potentially call this method many times. Make sure to
   // invalidate any child references.
   main_view_->RemoveAllChildViews(true /*delete_children*/);
-  opt_secondary_auth_ = nullptr;
+  opt_secondary_big_view_ = nullptr;
   users_list_ = nullptr;
   rotation_actions_.clear();
   users_.clear();
@@ -377,9 +384,9 @@
       views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER);
   main_view_->SetLayoutManager(std::move(box_layout));
 
-  // Add auth user.
-  primary_auth_ = AllocateLoginAuthUserView(users[0], true /*is_primary*/);
-  main_view_->AddChildView(primary_auth_);
+  // Add big user.
+  primary_big_view_ = AllocateLoginBigUserView(users[0], true /*is_primary*/);
+  main_view_->AddChildView(primary_big_view_);
 
   // Build layout for additional users.
   if (users.size() == 2)
@@ -389,10 +396,10 @@
   else if (users.size() >= 7)
     CreateHighDensityLayout(users);
 
-  LayoutAuth(primary_auth_, opt_secondary_auth_, false /*animate*/);
+  LayoutAuth(primary_big_view_, opt_secondary_big_view_, false /*animate*/);
 
-  // Auth user may be the same if we already built lock screen.
-  OnAuthUserChanged();
+  // Big user may be the same if we already built lock screen.
+  OnBigUserChanged();
 
   // Force layout.
   PreferredSizeChanged();
@@ -409,10 +416,10 @@
 
   state->show_pin = enabled;
 
-  LoginAuthUserView* auth_user =
-      TryToFindAuthUser(user, true /*require_auth_active*/);
-  if (auth_user)
-    LayoutAuth(auth_user, nullptr /*opt_to_hide*/, true /*animate*/);
+  LoginBigUserView* big_user =
+      TryToFindBigUser(user, true /*require_auth_active*/);
+  if (big_user && big_user->auth_user())
+    LayoutAuth(big_user, nullptr /*opt_to_hide*/, true /*animate*/);
 }
 
 void LockContentsView::OnClickToUnlockEnabledForUserChanged(
@@ -425,10 +432,10 @@
   }
   state->enable_tap_auth = enabled;
 
-  LoginAuthUserView* auth_user =
-      TryToFindAuthUser(user, true /*require_auth_active*/);
-  if (auth_user)
-    LayoutAuth(auth_user, nullptr /*opt_to_hide*/, true /*animate*/);
+  LoginBigUserView* big_user =
+      TryToFindBigUser(user, true /*require_auth_active*/);
+  if (big_user && big_user->auth_user())
+    LayoutAuth(big_user, nullptr /*opt_to_hide*/, true /*animate*/);
 }
 
 void LockContentsView::OnShowEasyUnlockIcon(
@@ -442,14 +449,15 @@
   UpdateEasyUnlockIconForUser(user);
 
   // Show tooltip only if the user is actively showing auth.
-  auto* auth_user = TryToFindAuthUser(user, true /*require_auth_active*/);
-  if (auth_user) {
-    tooltip_bubble_->Close();
-    if (icon->autoshow_tooltip) {
-      tooltip_bubble_->ShowTooltip(
-          icon->tooltip,
-          CurrentAuthUserView()->password_view() /*anchor_view*/);
-    }
+  LoginBigUserView* big_user =
+      TryToFindBigUser(user, true /*require_auth_active*/);
+  if (!big_user || !big_user->auth_user())
+    return;
+
+  tooltip_bubble_->Close();
+  if (icon->autoshow_tooltip) {
+    tooltip_bubble_->ShowTooltip(
+        icon->tooltip, big_user->auth_user()->password_view() /*anchor_view*/);
   }
 }
 
@@ -462,8 +470,9 @@
 
   // If lock screen apps just got deactivated - request focus for primary auth,
   // which should focus the password field.
-  if (old_lock_screen_apps_active && !lock_screen_apps_active_ && primary_auth_)
-    primary_auth_->RequestFocus();
+  if (old_lock_screen_apps_active && !lock_screen_apps_active_ &&
+      primary_big_view_)
+    primary_big_view_->RequestFocus();
 }
 
 void LockContentsView::OnDevChannelInfoChanged(
@@ -501,7 +510,13 @@
 void LockContentsView::OnPublicSessionDisplayNameChanged(
     const AccountId& account_id,
     const std::string& display_name) {
-  NOTIMPLEMENTED();
+  LoginUserView* user_view = TryToFindUserView(account_id);
+  if (!user_view || !IsPublicAccountUser(user_view->current_user()))
+    return;
+
+  mojom::LoginUserInfoPtr user_info = user_view->current_user()->Clone();
+  user_info->basic_user_info->display_name = display_name;
+  user_view->UpdateForUser(user_info, false /*animate*/);
 }
 
 void LockContentsView::OnPublicSessionLocalesChanged(
@@ -509,17 +524,28 @@
     const base::ListValue& locales,
     const std::string& default_locale,
     bool show_advanced_view) {
-  NOTIMPLEMENTED();
+  LoginUserView* user_view = TryToFindUserView(account_id);
+  if (!user_view || !IsPublicAccountUser(user_view->current_user()))
+    return;
+
+  mojom::LoginUserInfoPtr user_info = user_view->current_user()->Clone();
+  user_info->public_account_info->available_locales =
+      std::make_unique<base::ListValue>(locales.Clone().GetList());
+  user_info->public_account_info->default_locale = default_locale;
+  user_info->public_account_info->show_advanced_view = show_advanced_view;
+  user_view->UpdateForUser(user_info, false /*animate*/);
 }
 
 void LockContentsView::OnDetachableBasePairingStatusChanged(
     DetachableBasePairingStatus pairing_status) {
   const mojom::UserInfoPtr& user_info =
-      CurrentAuthUserView()->current_user()->basic_user_info;
-  // If the base is not paired, or the paired base matches the last used by the
-  // current user, the detachable base error bubble should be hidden. Otherwise,
-  // the bubble should be shown.
-  if (pairing_status == DetachableBasePairingStatus::kNone ||
+      CurrentBigUserView()->GetCurrentUser()->basic_user_info;
+  // If the current big user is public account user, or the base is not paired,
+  // or the paired base matches the last used by the current user, the
+  // detachable base error bubble should be hidden. Otherwise, the bubble should
+  // be shown.
+  if (!CurrentBigUserView()->auth_user() ||
+      pairing_status == DetachableBasePairingStatus::kNone ||
       (pairing_status == DetachableBasePairingStatus::kAuthenticated &&
        detachable_base_model_->PairedBaseMatchesLastUsedByUser(*user_info))) {
     detachable_base_error_bubble_->Close();
@@ -540,7 +566,7 @@
   label->SetEnabledColor(SK_ColorWHITE);
 
   detachable_base_error_bubble_->ShowErrorBubble(
-      label, CurrentAuthUserView()->password_view() /*anchor_view*/,
+      label, CurrentBigUserView()->auth_user()->password_view() /*anchor_view*/,
       LoginBubble::kFlagPersistent);
 
   // Remove the focus from the password field, to make user less likely to enter
@@ -605,7 +631,7 @@
     const keyboard::KeyboardControllerState state) {
   if (state == keyboard::KeyboardControllerState::SHOWN ||
       state == keyboard::KeyboardControllerState::HIDDEN) {
-    LayoutAuth(primary_auth_, opt_secondary_auth_, false /*animate*/);
+    LayoutAuth(primary_big_view_, opt_secondary_big_view_, false /*animate*/);
   }
 }
 
@@ -634,10 +660,9 @@
       kLowDensityDistanceBetweenUsersInPortraitDp));
 
   // Build auth user.
-  opt_secondary_auth_ =
-      AllocateLoginAuthUserView(users[1], false /*is_primary*/);
-  opt_secondary_auth_->SetAuthMethods(LoginAuthUserView::AUTH_NONE);
-  main_view_->AddChildView(opt_secondary_auth_);
+  opt_secondary_big_view_ =
+      AllocateLoginBigUserView(users[1], false /*is_primary*/);
+  main_view_->AddChildView(opt_secondary_big_view_);
 }
 
 void LockContentsView::CreateMediumDensityLayout(
@@ -735,15 +760,13 @@
 
 void LockContentsView::SwapActiveAuthBetweenPrimaryAndSecondary(
     bool is_primary) {
-  if (is_primary &&
-      primary_auth_->auth_methods() == LoginAuthUserView::AUTH_NONE) {
-    LayoutAuth(primary_auth_, opt_secondary_auth_, true /*animate*/);
-    OnAuthUserChanged();
-  } else if (!is_primary && opt_secondary_auth_ &&
-             opt_secondary_auth_->auth_methods() ==
-                 LoginAuthUserView::AUTH_NONE) {
-    LayoutAuth(opt_secondary_auth_, primary_auth_, true /*animate*/);
-    OnAuthUserChanged();
+  if (is_primary && !primary_big_view_->auth_enabled()) {
+    LayoutAuth(primary_big_view_, opt_secondary_big_view_, true /*animate*/);
+    OnBigUserChanged();
+  } else if (!is_primary && opt_secondary_big_view_ &&
+             !opt_secondary_big_view_->auth_enabled()) {
+    LayoutAuth(opt_secondary_big_view_, primary_big_view_, true /*animate*/);
+    OnBigUserChanged();
   }
 }
 
@@ -756,10 +779,11 @@
     // detachable base (if one is attached). This will prevent further
     // detachable base change notifications from appearing for this base (until
     // the user uses another detachable base).
-    if (detachable_base_model_->GetPairingStatus() ==
-        DetachableBasePairingStatus::kAuthenticated) {
+    if (CurrentBigUserView()->auth_user() &&
+        detachable_base_model_->GetPairingStatus() ==
+            DetachableBasePairingStatus::kAuthenticated) {
       detachable_base_model_->SetPairedBaseAsLastUsedByUser(
-          *CurrentAuthUserView()->current_user()->basic_user_info);
+          *CurrentBigUserView()->GetCurrentUser()->basic_user_info);
     }
   } else {
     ShowAuthErrorMessage();
@@ -777,53 +801,30 @@
   return nullptr;
 }
 
-void LockContentsView::LayoutAuth(LoginAuthUserView* to_update,
-                                  LoginAuthUserView* opt_to_hide,
+void LockContentsView::LayoutAuth(LoginBigUserView* to_update,
+                                  LoginBigUserView* opt_to_hide,
                                   bool animate) {
-  // Capture animation metadata before we changing state.
-  if (animate) {
-    to_update->CaptureStateForAnimationPreLayout();
-    if (opt_to_hide)
-      opt_to_hide->CaptureStateForAnimationPreLayout();
-  }
-
-  // Update auth methods for |to_update|. Disable auth on |opt_to_hide|.
-  uint32_t to_update_auth = LoginAuthUserView::AUTH_PASSWORD;
-  UserState* state =
-      FindStateForUser(to_update->current_user()->basic_user_info->account_id);
-  keyboard::KeyboardController* keyboard_controller = GetKeyboardController();
-  bool keyboard_visible =
-      keyboard_controller ? keyboard_controller->keyboard_visible() : false;
-  if (state->show_pin && !keyboard_visible)
-    to_update_auth |= LoginAuthUserView::AUTH_PIN;
-  if (state->enable_tap_auth)
-    to_update_auth |= LoginAuthUserView::AUTH_TAP;
-  to_update->SetAuthMethods(to_update_auth);
-  if (opt_to_hide)
-    opt_to_hide->SetAuthMethods(LoginAuthUserView::AUTH_NONE);
-
-  Layout();
-
-  // Apply animations.
-  if (animate) {
-    to_update->ApplyAnimationPostLayout();
-    if (opt_to_hide)
-      opt_to_hide->ApplyAnimationPostLayout();
-  }
+  DCHECK(to_update);
+  UpdateAuthForAuthUser(to_update->auth_user(),
+                        opt_to_hide ? opt_to_hide->auth_user() : nullptr,
+                        animate);
+  UpdateAuthForPublicAccount(
+      to_update->public_account(),
+      opt_to_hide ? opt_to_hide->public_account() : nullptr, animate);
 }
 
-void LockContentsView::SwapToAuthUser(int user_index) {
+void LockContentsView::SwapToBigUser(int user_index) {
   DCHECK(users_list_);
   LoginUserView* view = users_list_->user_view_at(user_index);
   DCHECK(view);
-  mojom::LoginUserInfoPtr previous_auth_user =
-      primary_auth_->current_user()->Clone();
-  mojom::LoginUserInfoPtr new_auth_user = view->current_user()->Clone();
+  mojom::LoginUserInfoPtr previous_big_user =
+      primary_big_view_->GetCurrentUser()->Clone();
+  mojom::LoginUserInfoPtr new_big_user = view->current_user()->Clone();
 
-  view->UpdateForUser(previous_auth_user, true /*animate*/);
-  primary_auth_->UpdateForUser(new_auth_user);
-  LayoutAuth(primary_auth_, nullptr, true /*animate*/);
-  OnAuthUserChanged();
+  view->UpdateForUser(previous_big_user, true /*animate*/);
+  primary_big_view_->UpdateForUser(new_big_user);
+  LayoutAuth(primary_big_view_, nullptr, true /*animate*/);
+  OnBigUserChanged();
 }
 
 void LockContentsView::OnRemoveUserWarningShown(bool is_primary) {
@@ -831,10 +832,10 @@
 }
 
 void LockContentsView::RemoveUser(bool is_primary) {
-  LoginAuthUserView* to_remove =
-      is_primary ? primary_auth_ : opt_secondary_auth_;
-  DCHECK(to_remove->current_user()->can_remove);
-  AccountId user = to_remove->current_user()->basic_user_info->account_id;
+  LoginBigUserView* to_remove =
+      is_primary ? primary_big_view_ : opt_secondary_big_view_;
+  DCHECK(to_remove->GetCurrentUser()->can_remove);
+  AccountId user = to_remove->GetCurrentUser()->basic_user_info->account_id;
 
   // Ask chrome to remove the user.
   Shell::Get()->login_screen_controller()->RemoveUser(user);
@@ -842,9 +843,9 @@
   // Display the new user list less |user|.
   std::vector<mojom::LoginUserInfoPtr> new_users;
   if (!is_primary)
-    new_users.push_back(primary_auth_->current_user()->Clone());
-  if (is_primary && opt_secondary_auth_)
-    new_users.push_back(opt_secondary_auth_->current_user()->Clone());
+    new_users.push_back(primary_big_view_->GetCurrentUser()->Clone());
+  if (is_primary && opt_secondary_big_view_)
+    new_users.push_back(opt_secondary_big_view_->GetCurrentUser()->Clone());
   if (users_list_) {
     for (int i = 0; i < users_list_->user_count(); ++i) {
       new_users.push_back(
@@ -854,12 +855,12 @@
   data_dispatcher_->NotifyUsers(new_users);
 }
 
-void LockContentsView::OnAuthUserChanged() {
-  const AccountId new_auth_user =
-      CurrentAuthUserView()->current_user()->basic_user_info->account_id;
+void LockContentsView::OnBigUserChanged() {
+  const AccountId new_big_user =
+      CurrentBigUserView()->GetCurrentUser()->basic_user_info->account_id;
 
-  Shell::Get()->login_screen_controller()->OnFocusPod(new_auth_user);
-  UpdateEasyUnlockIconForUser(new_auth_user);
+  Shell::Get()->login_screen_controller()->OnFocusPod(new_big_user);
+  UpdateEasyUnlockIconForUser(new_big_user);
 
   if (unlock_attempt_ > 0) {
     // Times a password was incorrectly entered until user gives up (change
@@ -878,11 +879,11 @@
 }
 
 void LockContentsView::UpdateEasyUnlockIconForUser(const AccountId& user) {
-  // Try to find an auth view for |user|. If there is none, there is no state to
+  // Try to find an big view for |user|. If there is none, there is no state to
   // update.
-  LoginAuthUserView* auth_view =
-      TryToFindAuthUser(user, false /*require_auth_active*/);
-  if (!auth_view)
+  LoginBigUserView* big_view =
+      TryToFindBigUser(user, false /*require_auth_active*/);
+  if (!big_view || !big_view->auth_user())
     return;
 
   UserState* state = FindStateForUser(user);
@@ -890,8 +891,8 @@
 
   // Hide easy unlock icon if there is no data is available.
   if (!state->easy_unlock_state) {
-    auth_view->SetEasyUnlockIcon(mojom::EasyUnlockIconId::NONE,
-                                 base::string16());
+    big_view->auth_user()->SetEasyUnlockIcon(mojom::EasyUnlockIconId::NONE,
+                                             base::string16());
     return;
   }
 
@@ -901,21 +902,24 @@
   if (accessibility_label.empty())
     accessibility_label = state->easy_unlock_state->tooltip;
 
-  auth_view->SetEasyUnlockIcon(state->easy_unlock_state->icon,
-                               accessibility_label);
+  big_view->auth_user()->SetEasyUnlockIcon(state->easy_unlock_state->icon,
+                                           accessibility_label);
 }
 
-LoginAuthUserView* LockContentsView::CurrentAuthUserView() {
-  if (opt_secondary_auth_ &&
-      opt_secondary_auth_->auth_methods() != LoginAuthUserView::AUTH_NONE) {
-    DCHECK(primary_auth_->auth_methods() == LoginAuthUserView::AUTH_NONE);
-    return opt_secondary_auth_;
+LoginBigUserView* LockContentsView::CurrentBigUserView() {
+  if (opt_secondary_big_view_ && opt_secondary_big_view_->auth_enabled()) {
+    DCHECK(!primary_big_view_->auth_enabled());
+    return opt_secondary_big_view_;
   }
 
-  return primary_auth_;
+  return primary_big_view_;
 }
 
 void LockContentsView::ShowAuthErrorMessage() {
+  LoginBigUserView* big_view = CurrentBigUserView();
+  if (!big_view->auth_user())
+    return;
+
   base::string16 error_text = l10n_util::GetStringUTF16(
       unlock_attempt_ ? IDS_ASH_LOGIN_ERROR_AUTHENTICATING_2ND_TIME
                       : IDS_ASH_LOGIN_ERROR_AUTHENTICATING);
@@ -948,13 +952,17 @@
   label->set_auto_color_readability_enabled(false);
 
   auth_error_bubble_->ShowErrorBubble(
-      label, CurrentAuthUserView()->password_view() /*anchor_view*/,
+      label, big_view->auth_user()->password_view() /*anchor_view*/,
       LoginBubble::kFlagsNone);
 }
 
 void LockContentsView::OnEasyUnlockIconHovered() {
-  UserState* state = FindStateForUser(
-      CurrentAuthUserView()->current_user()->basic_user_info->account_id);
+  LoginBigUserView* big_view = CurrentBigUserView();
+  if (!big_view->auth_user())
+    return;
+
+  UserState* state =
+      FindStateForUser(big_view->GetCurrentUser()->basic_user_info->account_id);
   DCHECK(state);
   mojom::EasyUnlockIconOptionsPtr& easy_unlock_state = state->easy_unlock_state;
   DCHECK(easy_unlock_state);
@@ -962,20 +970,20 @@
   if (!easy_unlock_state->tooltip.empty()) {
     tooltip_bubble_->ShowTooltip(
         easy_unlock_state->tooltip,
-        CurrentAuthUserView()->password_view() /*anchor_view*/);
+        big_view->auth_user()->password_view() /*anchor_view*/);
   }
 }
 
 void LockContentsView::OnEasyUnlockIconTapped() {
   UserState* state = FindStateForUser(
-      CurrentAuthUserView()->current_user()->basic_user_info->account_id);
+      CurrentBigUserView()->GetCurrentUser()->basic_user_info->account_id);
   DCHECK(state);
   mojom::EasyUnlockIconOptionsPtr& easy_unlock_state = state->easy_unlock_state;
   DCHECK(easy_unlock_state);
 
   if (easy_unlock_state->hardlock_on_click) {
     AccountId user =
-        CurrentAuthUserView()->current_user()->basic_user_info->account_id;
+        CurrentBigUserView()->GetCurrentUser()->basic_user_info->account_id;
     Shell::Get()->login_screen_controller()->HardlockPod(user);
     // TODO(jdufault): This should get called as a result of HardlockPod.
     OnClickToUnlockEnabledForUserChanged(user, false /*enabled*/);
@@ -986,60 +994,128 @@
   return GetWidget() ? GetKeyboardControllerForWidget(GetWidget()) : nullptr;
 }
 
-LoginAuthUserView* LockContentsView::AllocateLoginAuthUserView(
-    const mojom::LoginUserInfoPtr& user,
-    bool is_primary) {
-  LoginAuthUserView::Callbacks callbacks;
-  callbacks.on_auth = base::BindRepeating(&LockContentsView::OnAuthenticate,
-                                          base::Unretained(this)),
-  callbacks.on_tap = base::BindRepeating(
-      &LockContentsView::SwapActiveAuthBetweenPrimaryAndSecondary,
-      base::Unretained(this), is_primary),
-  callbacks.on_remove_warning_shown =
-      base::BindRepeating(&LockContentsView::OnRemoveUserWarningShown,
-                          base::Unretained(this), is_primary);
-  callbacks.on_remove = base::BindRepeating(&LockContentsView::RemoveUser,
-                                            base::Unretained(this), is_primary);
-  callbacks.on_easy_unlock_icon_hovered = base::BindRepeating(
-      &LockContentsView::OnEasyUnlockIconHovered, base::Unretained(this));
-  callbacks.on_easy_unlock_icon_tapped = base::BindRepeating(
-      &LockContentsView::OnEasyUnlockIconTapped, base::Unretained(this));
-  return new LoginAuthUserView(user, callbacks);
+void LockContentsView::OnPublicAccountTapped() {
+  NOTIMPLEMENTED();
 }
 
-LoginAuthUserView* LockContentsView::TryToFindAuthUser(
-    const AccountId& user,
-    bool require_auth_active) {
-  LoginAuthUserView* view = nullptr;
+LoginBigUserView* LockContentsView::AllocateLoginBigUserView(
+    const mojom::LoginUserInfoPtr& user,
+    bool is_primary) {
+  LoginAuthUserView::Callbacks auth_user_callbacks;
+  auth_user_callbacks.on_auth = base::BindRepeating(
+      &LockContentsView::OnAuthenticate, base::Unretained(this)),
+  auth_user_callbacks.on_tap = base::BindRepeating(
+      &LockContentsView::SwapActiveAuthBetweenPrimaryAndSecondary,
+      base::Unretained(this), is_primary),
+  auth_user_callbacks.on_remove_warning_shown =
+      base::BindRepeating(&LockContentsView::OnRemoveUserWarningShown,
+                          base::Unretained(this), is_primary);
+  auth_user_callbacks.on_remove = base::BindRepeating(
+      &LockContentsView::RemoveUser, base::Unretained(this), is_primary);
+  auth_user_callbacks.on_easy_unlock_icon_hovered = base::BindRepeating(
+      &LockContentsView::OnEasyUnlockIconHovered, base::Unretained(this));
+  auth_user_callbacks.on_easy_unlock_icon_tapped = base::BindRepeating(
+      &LockContentsView::OnEasyUnlockIconTapped, base::Unretained(this));
+
+  LoginPublicAccountUserView::Callbacks public_account_callbacks;
+  public_account_callbacks.on_tap = auth_user_callbacks.on_tap;
+  public_account_callbacks.on_public_account_tapped = base::BindRepeating(
+      &LockContentsView::OnPublicAccountTapped, base::Unretained(this));
+  return new LoginBigUserView(user, auth_user_callbacks,
+                              public_account_callbacks);
+}
+
+LoginBigUserView* LockContentsView::TryToFindBigUser(const AccountId& user,
+                                                     bool require_auth_active) {
+  LoginBigUserView* view = nullptr;
 
   // Find auth instance.
-  if (primary_auth_->current_user()->basic_user_info->account_id == user) {
-    view = primary_auth_;
-  } else if (opt_secondary_auth_ &&
-             opt_secondary_auth_->current_user()->basic_user_info->account_id ==
-                 user) {
-    view = opt_secondary_auth_;
+  if (primary_big_view_->GetCurrentUser()->basic_user_info->account_id ==
+      user) {
+    view = primary_big_view_;
+  } else if (opt_secondary_big_view_ &&
+             opt_secondary_big_view_->GetCurrentUser()
+                     ->basic_user_info->account_id == user) {
+    view = opt_secondary_big_view_;
   }
 
   // Make sure auth instance is active if required.
-  if (require_auth_active && view &&
-      view->auth_methods() == LoginAuthUserView::AUTH_NONE) {
+  if (require_auth_active && view && !view->auth_enabled())
     view = nullptr;
-  }
 
   return view;
 }
 
+LoginUserView* LockContentsView::TryToFindUserView(const AccountId& user) {
+  // Try to find |user| in big user view first.
+  LoginBigUserView* big_view =
+      TryToFindBigUser(user, false /*require_auth_active*/);
+  if (big_view)
+    return big_view->GetUserView();
+
+  // Try to find |user| in users_list_.
+  return users_list_->GetUserView(user);
+}
+
 ScrollableUsersListView* LockContentsView::BuildScrollableUsersListView(
     const std::vector<mojom::LoginUserInfoPtr>& users,
     LoginDisplayStyle display_style) {
   auto* view = new ScrollableUsersListView(
       users,
-      base::BindRepeating(&LockContentsView::SwapToAuthUser,
+      base::BindRepeating(&LockContentsView::SwapToBigUser,
                           base::Unretained(this)),
       display_style);
   view->ClipHeightTo(view->contents()->size().height(), size().height());
   return view;
 }
 
+void LockContentsView::UpdateAuthForPublicAccount(
+    LoginPublicAccountUserView* opt_to_update,
+    LoginPublicAccountUserView* opt_to_hide,
+    bool animate) {
+  if (opt_to_update)
+    opt_to_update->SetAuthEnabled(true /*enabled*/, animate);
+  if (opt_to_hide)
+    opt_to_hide->SetAuthEnabled(false /*enabled*/, animate);
+}
+
+void LockContentsView::UpdateAuthForAuthUser(LoginAuthUserView* opt_to_update,
+                                             LoginAuthUserView* opt_to_hide,
+                                             bool animate) {
+  // Capture animation metadata before we changing state.
+  if (animate) {
+    if (opt_to_update)
+      opt_to_update->CaptureStateForAnimationPreLayout();
+    if (opt_to_hide)
+      opt_to_hide->CaptureStateForAnimationPreLayout();
+  }
+
+  // Update auth methods for |opt_to_update|. Disable auth on |opt_to_hide|.
+  if (opt_to_update) {
+    uint32_t to_update_auth = LoginAuthUserView::AUTH_PASSWORD;
+    UserState* state = FindStateForUser(
+        opt_to_update->current_user()->basic_user_info->account_id);
+    keyboard::KeyboardController* keyboard_controller = GetKeyboardController();
+    const bool keyboard_visible =
+        keyboard_controller ? keyboard_controller->keyboard_visible() : false;
+    if (state->show_pin && !keyboard_visible)
+      to_update_auth |= LoginAuthUserView::AUTH_PIN;
+    if (state->enable_tap_auth)
+      to_update_auth |= LoginAuthUserView::AUTH_TAP;
+    opt_to_update->SetAuthMethods(to_update_auth);
+  }
+  if (opt_to_hide)
+    opt_to_hide->SetAuthMethods(LoginAuthUserView::AUTH_NONE);
+
+  Layout();
+
+  // Apply animations.
+  if (animate) {
+    if (opt_to_update)
+      opt_to_update->ApplyAnimationPostLayout();
+    if (opt_to_hide)
+      opt_to_hide->ApplyAnimationPostLayout();
+  }
+}
+
 }  // namespace ash
diff --git a/ash/login/ui/lock_contents_view.h b/ash/login/ui/lock_contents_view.h
index a0d2eee..7bbc43bf 100644
--- a/ash/login/ui/lock_contents_view.h
+++ b/ash/login/ui/lock_contents_view.h
@@ -38,8 +38,11 @@
 namespace ash {
 
 class LoginAuthUserView;
+class LoginBigUserView;
 class LoginBubble;
 class LoginDetachableBaseModel;
+class LoginPublicAccountUserView;
+class LoginUserView;
 class NoteActionLaunchButton;
 class ScrollableUsersListView;
 
@@ -67,8 +70,8 @@
     explicit TestApi(LockContentsView* view);
     ~TestApi();
 
-    LoginAuthUserView* primary_auth() const;
-    LoginAuthUserView* opt_secondary_auth() const;
+    LoginBigUserView* primary_big_view() const;
+    LoginBigUserView* opt_secondary_big_view() const;
     ScrollableUsersListView* users_list() const;
     views::View* note_action() const;
     LoginBubble* tooltip_bubble() const;
@@ -191,8 +194,8 @@
   void AddRotationAction(const OnRotate& on_rotate);
 
   // Change the active |auth_user_|. If |is_primary| is true, the active auth
-  // switches to |opt_secondary_auth_|. If |is_primary| is false, the active
-  // auth switches to |primary_auth_|.
+  // switches to |opt_secondary_big_view_|. If |is_primary| is false, the active
+  // auth switches to |primary_big_view_|.
   void SwapActiveAuthBetweenPrimaryAndSecondary(bool is_primary);
 
   // Called when an authentication check is complete.
@@ -203,29 +206,33 @@
   UserState* FindStateForUser(const AccountId& user);
 
   // Updates the auth methods for |to_update| and |to_hide|, if passed.
-  // |to_hide| will be set to LoginAuthUserView::AUTH_NONE. At minimum,
-  // |to_update| will show a password prompt.
-  void LayoutAuth(LoginAuthUserView* to_update,
-                  LoginAuthUserView* opt_to_hide,
+  // For auth users:
+  //   |to_hide| will be set to LoginAuthUserView::AUTH_NONE. At minimum,
+  //   |to_update| will show a password prompt.
+  // For pubic account users:
+  //   |to_hide| will set to disable auth.
+  //   |to_update| will show an arrow button.
+  void LayoutAuth(LoginBigUserView* to_update,
+                  LoginBigUserView* opt_to_hide,
                   bool animate);
 
-  // Make the user at |user_index| the auth user. We pass in the index because
-  // the actual user may change.
-  void SwapToAuthUser(int user_index);
+  // Make the user at |user_index| the big user with auth enabled.
+  // We pass in the index because the actual user may change.
+  void SwapToBigUser(int user_index);
 
   // Warning to remove a user is shown.
   void OnRemoveUserWarningShown(bool is_primary);
   // Remove one of the auth users.
   void RemoveUser(bool is_primary);
 
-  // Called after the auth user change has taken place.
-  void OnAuthUserChanged();
+  // Called after the big user change has taken place.
+  void OnBigUserChanged();
 
   // Shows the correct (cached) easy unlock icon for the given auth user.
   void UpdateEasyUnlockIconForUser(const AccountId& user);
 
-  // Get the LoginAuthUserView of the current auth user.
-  LoginAuthUserView* CurrentAuthUserView();
+  // Get the current active big user view.
+  LoginBigUserView* CurrentBigUserView();
 
   // Opens an error bubble to indicate authentication failure.
   void ShowAuthErrorMessage();
@@ -240,29 +247,47 @@
   // displayed in this window.
   keyboard::KeyboardController* GetKeyboardController() const;
 
-  // Helper method to allocate a LoginAuthUserView instance.
-  LoginAuthUserView* AllocateLoginAuthUserView(
+  // Called when the public account is tapped.
+  void OnPublicAccountTapped();
+
+  // Helper method to allocate a LoginBigUserView instance.
+  LoginBigUserView* AllocateLoginBigUserView(
       const mojom::LoginUserInfoPtr& user,
       bool is_primary);
 
-  // Returns the authentication view for |user| if |user| is one of the active
-  // authentication views. If |require_auth_active| is true then the view must
-  // also be actively displaying auth.
-  LoginAuthUserView* TryToFindAuthUser(const AccountId& user,
-                                       bool require_auth_active);
+  // Returns the big view for |user| if |user| is one of the active
+  // big views. If |require_auth_active| is true then the view must
+  // have auth enabled.
+  LoginBigUserView* TryToFindBigUser(const AccountId& user,
+                                     bool require_auth_active);
+
+  // Returns the user view for |user|.
+  LoginUserView* TryToFindUserView(const AccountId& user);
 
   // Returns scrollable view with initialized size and rows for all |users|.
   ScrollableUsersListView* BuildScrollableUsersListView(
       const std::vector<mojom::LoginUserInfoPtr>& users,
       LoginDisplayStyle display_style);
 
+  // Update the auth enable/disabled for public account user.
+  // Both |opt_to_update| and |opt_to_hide| could be null.
+  void UpdateAuthForPublicAccount(LoginPublicAccountUserView* opt_to_update,
+                                  LoginPublicAccountUserView* opt_to_hide,
+                                  bool animate);
+
+  // Update the auth method for regular user.
+  // Both |opt_to_update| and |opt_to_hide| could be null.
+  void UpdateAuthForAuthUser(LoginAuthUserView* opt_to_update,
+                             LoginAuthUserView* opt_to_hide,
+                             bool animate);
+
   std::vector<UserState> users_;
 
   LoginDataDispatcher* const data_dispatcher_;  // Unowned.
   std::unique_ptr<LoginDetachableBaseModel> detachable_base_model_;
 
-  LoginAuthUserView* primary_auth_ = nullptr;
-  LoginAuthUserView* opt_secondary_auth_ = nullptr;
+  LoginBigUserView* primary_big_view_ = nullptr;
+  LoginBigUserView* opt_secondary_big_view_ = nullptr;
   ScrollableUsersListView* users_list_ = nullptr;
 
   // View that contains the note action button and the dev channel info labels,
diff --git a/ash/login/ui/lock_contents_view_unittest.cc b/ash/login/ui/lock_contents_view_unittest.cc
index 9240825..15a5ef7 100644
--- a/ash/login/ui/lock_contents_view_unittest.cc
+++ b/ash/login/ui/lock_contents_view_unittest.cc
@@ -9,14 +9,17 @@
 
 #include "ash/detachable_base/detachable_base_pairing_status.h"
 #include "ash/login/mock_login_screen_client.h"
+#include "ash/login/ui/arrow_button_view.h"
 #include "ash/login/ui/fake_login_detachable_base_model.h"
 #include "ash/login/ui/lock_contents_view.h"
 #include "ash/login/ui/lock_screen.h"
 #include "ash/login/ui/login_auth_user_view.h"
+#include "ash/login/ui/login_big_user_view.h"
 #include "ash/login/ui/login_bubble.h"
 #include "ash/login/ui/login_display_style.h"
 #include "ash/login/ui/login_keyboard_test_base.h"
 #include "ash/login/ui/login_pin_view.h"
+#include "ash/login/ui/login_public_account_user_view.h"
 #include "ash/login/ui/login_test_base.h"
 #include "ash/login/ui/login_user_view.h"
 #include "ash/login/ui/scrollable_users_list_view.h"
@@ -48,12 +51,12 @@
   // Verify user list and secondary auth are not shown for one user.
   LockContentsView::TestApi lock_contents(contents);
   EXPECT_EQ(nullptr, lock_contents.users_list());
-  EXPECT_FALSE(lock_contents.opt_secondary_auth());
+  EXPECT_FALSE(lock_contents.opt_secondary_big_view());
 
   // Verify user list is not shown for two users, but secondary auth is.
   SetUserCount(2);
   EXPECT_EQ(nullptr, lock_contents.users_list());
-  EXPECT_TRUE(lock_contents.opt_secondary_auth());
+  EXPECT_TRUE(lock_contents.opt_secondary_big_view());
 
   // Verify user names and pod style is set correctly for 3-25 users. This also
   // sanity checks that LockContentsView can respond to a multiple user change
@@ -92,7 +95,7 @@
   std::unique_ptr<views::Widget> widget = CreateWidgetWithContent(contents);
 
   LockContentsView::TestApi test_api(contents);
-  LoginAuthUserView* auth_view = test_api.primary_auth();
+  LoginBigUserView* auth_view = test_api.primary_big_view();
   gfx::Rect widget_bounds = widget->GetWindowBoundsInScreen();
   int expected_margin =
       (widget_bounds.width() - auth_view->GetPreferredSize().width()) / 2;
@@ -114,7 +117,7 @@
   std::unique_ptr<views::Widget> widget = CreateWidgetWithContent(contents);
 
   LockContentsView::TestApi test_api(contents);
-  LoginAuthUserView* auth_view = test_api.primary_auth();
+  LoginBigUserView* auth_view = test_api.primary_big_view();
   gfx::Rect widget_bounds = widget->GetWindowBoundsInScreen();
   int expected_margin =
       (widget_bounds.width() - auth_view->GetPreferredSize().width()) / 2;
@@ -140,13 +143,13 @@
 
   // Returns the distance between the auth user view and the user view.
   auto calculate_distance = [&]() {
-    if (lock_contents.opt_secondary_auth()) {
-      return lock_contents.opt_secondary_auth()->GetBoundsInScreen().x() -
-             lock_contents.primary_auth()->GetBoundsInScreen().x();
+    if (lock_contents.opt_secondary_big_view()) {
+      return lock_contents.opt_secondary_big_view()->GetBoundsInScreen().x() -
+             lock_contents.primary_big_view()->GetBoundsInScreen().x();
     }
     ScrollableUsersListView::TestApi users_list(lock_contents.users_list());
     return users_list.user_views()[0]->GetBoundsInScreen().x() -
-           lock_contents.primary_auth()->GetBoundsInScreen().x();
+           lock_contents.primary_big_view()->GetBoundsInScreen().x();
   };
 
   const display::Display& display =
@@ -339,39 +342,38 @@
   std::unique_ptr<views::Widget> widget = CreateWidgetWithContent(contents);
 
   // Capture user info to validate it did not change during the swap.
-  AccountId primary_user =
-      test_api.primary_auth()->current_user()->basic_user_info->account_id;
-  AccountId secondary_user = test_api.opt_secondary_auth()
-                                 ->current_user()
+  AccountId primary_user = test_api.primary_big_view()
+                               ->GetCurrentUser()
+                               ->basic_user_info->account_id;
+  AccountId secondary_user = test_api.opt_secondary_big_view()
+                                 ->GetCurrentUser()
                                  ->basic_user_info->account_id;
   EXPECT_NE(primary_user, secondary_user);
 
-  auto has_auth = [](LoginAuthUserView* view) -> bool {
-    return view->auth_methods() != LoginAuthUserView::AUTH_NONE;
-  };
-
   // Primary user starts with auth. Secondary user does not have any auth.
-  EXPECT_TRUE(has_auth(test_api.primary_auth()));
-  EXPECT_FALSE(has_auth(test_api.opt_secondary_auth()));
+  EXPECT_TRUE(test_api.primary_big_view()->auth_enabled());
+  EXPECT_FALSE(test_api.opt_secondary_big_view()->auth_enabled());
+  ASSERT_NE(nullptr, test_api.opt_secondary_big_view()->auth_user());
 
   // Send event to swap users.
   ui::test::EventGenerator& generator = GetEventGenerator();
-  LoginAuthUserView::TestApi secondary_test_api(test_api.opt_secondary_auth());
+  LoginAuthUserView::TestApi secondary_test_api(
+      test_api.opt_secondary_big_view()->auth_user());
   generator.MoveMouseTo(
       secondary_test_api.user_view()->GetBoundsInScreen().CenterPoint());
   generator.ClickLeftButton();
 
   // User info is not swapped.
-  EXPECT_EQ(
-      primary_user,
-      test_api.primary_auth()->current_user()->basic_user_info->account_id);
-  EXPECT_EQ(secondary_user, test_api.opt_secondary_auth()
-                                ->current_user()
+  EXPECT_EQ(primary_user, test_api.primary_big_view()
+                              ->GetCurrentUser()
+                              ->basic_user_info->account_id);
+  EXPECT_EQ(secondary_user, test_api.opt_secondary_big_view()
+                                ->GetCurrentUser()
                                 ->basic_user_info->account_id);
 
   // Active auth user (ie, which user is showing password) is swapped.
-  EXPECT_FALSE(has_auth(test_api.primary_auth()));
-  EXPECT_TRUE(has_auth(test_api.opt_secondary_auth()));
+  EXPECT_FALSE(test_api.primary_big_view()->auth_enabled());
+  EXPECT_TRUE(test_api.opt_secondary_big_view()->auth_enabled());
 }
 
 // Ensures that when swapping from a user list, the entire user info is swapped.
@@ -386,11 +388,12 @@
   EXPECT_EQ(users().size() - 1, users_list.user_views().size());
   std::unique_ptr<views::Widget> widget = CreateWidgetWithContent(contents);
 
-  LoginAuthUserView* auth_view = lock_contents.primary_auth();
+  LoginBigUserView* auth_view = lock_contents.primary_big_view();
 
   for (const LoginUserView* const list_user_view : users_list.user_views()) {
     // Capture user info to validate it did not change during the swap.
-    AccountId auth_id = auth_view->current_user()->basic_user_info->account_id;
+    AccountId auth_id =
+        auth_view->GetCurrentUser()->basic_user_info->account_id;
     AccountId list_user_id =
         list_user_view->current_user()->basic_user_info->account_id;
     EXPECT_NE(auth_id, list_user_id);
@@ -402,7 +405,7 @@
 
     // User info is swapped.
     EXPECT_EQ(list_user_id,
-              auth_view->current_user()->basic_user_info->account_id);
+              auth_view->GetCurrentUser()->basic_user_info->account_id);
     EXPECT_EQ(auth_id,
               list_user_view->current_user()->basic_user_info->account_id);
 
@@ -584,38 +587,42 @@
   SetWidget(CreateWidgetWithContent(contents));
 
   LockContentsView::TestApi test_api(contents);
-  LoginAuthUserView* primary = test_api.primary_auth();
-  LoginAuthUserView* secondary = test_api.opt_secondary_auth();
+  LoginBigUserView* primary = test_api.primary_big_view();
+  LoginBigUserView* secondary = test_api.opt_secondary_big_view();
 
   // Returns true if the easy unlock icon is displayed for |view|.
-  auto showing_easy_unlock_icon = [&](LoginAuthUserView* view) {
-    views::View* icon = LoginPasswordView::TestApi(
-                            LoginAuthUserView::TestApi(view).password_view())
-                            .easy_unlock_icon();
+  auto showing_easy_unlock_icon = [&](LoginBigUserView* view) {
+    if (!view->auth_user())
+      return false;
+
+    views::View* icon =
+        LoginPasswordView::TestApi(
+            LoginAuthUserView::TestApi(view->auth_user()).password_view())
+            .easy_unlock_icon();
     return icon->visible();
   };
 
   // Enables easy unlock icon for |view|.
-  auto enable_icon = [&](LoginAuthUserView* view) {
+  auto enable_icon = [&](LoginBigUserView* view) {
     auto icon = mojom::EasyUnlockIconOptions::New();
     icon->icon = mojom::EasyUnlockIconId::LOCKED;
     data_dispatcher()->ShowEasyUnlockIcon(
-        view->current_user()->basic_user_info->account_id, icon);
+        view->GetCurrentUser()->basic_user_info->account_id, icon);
   };
 
   // Disables easy unlock icon for |view|.
-  auto disable_icon = [&](LoginAuthUserView* view) {
+  auto disable_icon = [&](LoginBigUserView* view) {
     auto icon = mojom::EasyUnlockIconOptions::New();
     icon->icon = mojom::EasyUnlockIconId::NONE;
     data_dispatcher()->ShowEasyUnlockIcon(
-        view->current_user()->basic_user_info->account_id, icon);
+        view->GetCurrentUser()->basic_user_info->account_id, icon);
   };
 
   // Makes |view| the active auth view so it will can show auth methods.
-  auto make_active_auth_view = [&](LoginAuthUserView* view) {
+  auto make_active_auth_view = [&](LoginBigUserView* view) {
     // Send event to swap users.
     ui::test::EventGenerator& generator = GetEventGenerator();
-    LoginUserView* user_view = LoginAuthUserView::TestApi(view).user_view();
+    LoginUserView* user_view = view->GetUserView();
     generator.MoveMouseTo(user_view->GetBoundsInScreen().CenterPoint());
     generator.ClickLeftButton();
   };
@@ -734,7 +741,8 @@
   // Switching to the user that doesn't have previously used detachable base
   // (and should thus not be warned about the detachable base missmatch) should
   // hide the login bubble.
-  LoginAuthUserView::TestApi secondary_test_api(test_api.opt_secondary_auth());
+  LoginAuthUserView::TestApi secondary_test_api(
+      test_api.opt_secondary_big_view()->auth_user());
   generator.MoveMouseTo(
       secondary_test_api.user_view()->GetBoundsInScreen().CenterPoint());
   generator.ClickLeftButton();
@@ -742,7 +750,8 @@
   EXPECT_FALSE(test_api.detachable_base_error_bubble()->IsVisible());
 
   // The error should be shown again when switching back to the primary user.
-  LoginAuthUserView::TestApi primary_test_api(test_api.primary_auth());
+  LoginAuthUserView::TestApi primary_test_api(
+      test_api.primary_big_view()->auth_user());
   generator.MoveMouseTo(
       primary_test_api.user_view()->GetBoundsInScreen().CenterPoint());
   generator.ClickLeftButton();
@@ -807,7 +816,8 @@
   EXPECT_TRUE(test_api.detachable_base_error_bubble()->IsVisible());
 
   // Switching to another user should not hide the error bubble.
-  LoginAuthUserView::TestApi secondary_test_api(test_api.opt_secondary_auth());
+  LoginAuthUserView::TestApi secondary_test_api(
+      test_api.opt_secondary_big_view()->auth_user());
   generator.MoveMouseTo(
       secondary_test_api.user_view()->GetBoundsInScreen().CenterPoint());
   generator.ClickLeftButton();
@@ -960,7 +970,7 @@
   EXPECT_CALL(*client, AuthenticateUser_(kUserAccountId, _, _, false, _));
 
   // Submit password.
-  LoginAuthUserView::TestApi(test_api.primary_auth())
+  LoginAuthUserView::TestApi(test_api.primary_big_view()->auth_user())
       .password_view()
       ->RequestFocus();
   generator.PressKey(ui::KeyboardCode::VKEY_A, 0);
@@ -988,13 +998,15 @@
   const std::string email = "user@domain.com";
   LoadUser(email);
   contents->OnPinEnabledForUserChanged(AccountId::FromUserEmail(email), true);
-  LoginAuthUserView* auth_view =
-      LockContentsView::TestApi(contents).primary_auth();
-  ASSERT_NE(nullptr, auth_view);
+  LoginBigUserView* big_view =
+      LockContentsView::TestApi(contents).primary_big_view();
+  ASSERT_NE(nullptr, big_view);
+  ASSERT_NE(nullptr, big_view->auth_user());
 
   // Pin keyboard should only be visible when there is no virtual keyboard
   // shown.
-  LoginPinView* pin_view = LoginAuthUserView::TestApi(auth_view).pin_view();
+  LoginPinView* pin_view =
+      LoginAuthUserView::TestApi(big_view->auth_user()).pin_view();
   EXPECT_TRUE(pin_view->visible());
 
   ASSERT_NO_FATAL_FAILURE(ShowKeyboard());
@@ -1004,4 +1016,190 @@
   EXPECT_TRUE(pin_view->visible());
 }
 
+// Verify that swapping works in two user layout between one regular auth user
+// and one public account user.
+TEST_F(LockContentsViewUnitTest, SwapAuthAndPublicAccountUserInTwoUserLayout) {
+  // Build lock screen with two users: one public account user and one regular
+  // user.
+  auto* contents = new LockContentsView(
+      mojom::TrayActionState::kNotAvailable, data_dispatcher(),
+      std::make_unique<FakeLoginDetachableBaseModel>(data_dispatcher()));
+  LockContentsView::TestApi test_api(contents);
+  std::unique_ptr<views::Widget> widget = CreateWidgetWithContent(contents);
+  AddPublicAccountUsers(1);
+  AddUsers(1);
+
+  // Capture user info to validate it did not change during the swap.
+  AccountId primary_user = test_api.primary_big_view()
+                               ->GetCurrentUser()
+                               ->basic_user_info->account_id;
+  AccountId secondary_user = test_api.opt_secondary_big_view()
+                                 ->GetCurrentUser()
+                                 ->basic_user_info->account_id;
+  EXPECT_NE(primary_user, secondary_user);
+
+  // Primary user starts with auth. Secondary user does not have any auth.
+  EXPECT_TRUE(test_api.primary_big_view()->auth_enabled());
+  EXPECT_FALSE(test_api.opt_secondary_big_view()->auth_enabled());
+
+  // Verify the LoginBigUserView has built the child view correctly.
+  ASSERT_TRUE(test_api.primary_big_view()->public_account());
+  ASSERT_FALSE(test_api.primary_big_view()->auth_user());
+  ASSERT_FALSE(test_api.opt_secondary_big_view()->public_account());
+  ASSERT_TRUE(test_api.opt_secondary_big_view()->auth_user());
+
+  // Send event to swap users.
+  ui::test::EventGenerator& generator = GetEventGenerator();
+  LoginAuthUserView::TestApi secondary_test_api(
+      test_api.opt_secondary_big_view()->auth_user());
+  generator.MoveMouseTo(
+      secondary_test_api.user_view()->GetBoundsInScreen().CenterPoint());
+  generator.ClickLeftButton();
+
+  // User info is not swapped.
+  EXPECT_EQ(primary_user, test_api.primary_big_view()
+                              ->GetCurrentUser()
+                              ->basic_user_info->account_id);
+  EXPECT_EQ(secondary_user, test_api.opt_secondary_big_view()
+                                ->GetCurrentUser()
+                                ->basic_user_info->account_id);
+
+  // Child view of LoginBigUserView stays the same.
+  ASSERT_TRUE(test_api.primary_big_view()->public_account());
+  ASSERT_FALSE(test_api.primary_big_view()->auth_user());
+  ASSERT_FALSE(test_api.opt_secondary_big_view()->public_account());
+  ASSERT_TRUE(test_api.opt_secondary_big_view()->auth_user());
+
+  // Active auth (ie, which user is showing password) is swapped.
+  EXPECT_FALSE(test_api.primary_big_view()->auth_enabled());
+  EXPECT_TRUE(test_api.opt_secondary_big_view()->auth_enabled());
+}
+
+// Ensures that when swapping from a user list, the entire user info is swapped
+// and the primary big user will rebuild its child view when necessary.
+TEST_F(LockContentsViewUnitTest, SwapUserListToPrimaryBigUser) {
+  // Build lock screen with 4 users: two public account users and two regular
+  // users.
+  auto* contents = new LockContentsView(
+      mojom::TrayActionState::kNotAvailable, data_dispatcher(),
+      std::make_unique<FakeLoginDetachableBaseModel>(data_dispatcher()));
+  LockContentsView::TestApi lock_contents(contents);
+  AddPublicAccountUsers(2);
+  AddUsers(2);
+  ScrollableUsersListView::TestApi users_list(lock_contents.users_list());
+  EXPECT_EQ(users().size() - 1, users_list.user_views().size());
+  std::unique_ptr<views::Widget> widget = CreateWidgetWithContent(contents);
+
+  LoginBigUserView* primary_big_view = lock_contents.primary_big_view();
+
+  // Verify that primary_big_view is public account user.
+  ASSERT_TRUE(primary_big_view->public_account());
+  ASSERT_FALSE(primary_big_view->auth_user());
+
+  const LoginUserView* user_view0 = users_list.user_views().at(0);
+  const LoginUserView* user_view1 = users_list.user_views().at(1);
+  const LoginUserView* user_view2 = users_list.user_views().at(2);
+
+  // Clicks on |view| to make it swap with the primary big user.
+  auto click_view = [&](const LoginUserView* view) {
+    ui::test::EventGenerator& generator = GetEventGenerator();
+    generator.MoveMouseTo(view->GetBoundsInScreen().CenterPoint());
+    generator.ClickLeftButton();
+  };
+
+  auto is_public_account = [](const LoginUserView* view) -> bool {
+    return view->current_user()->basic_user_info->type ==
+           user_manager::USER_TYPE_PUBLIC_ACCOUNT;
+  };
+
+  // Case 1: Swap user_view0 (public account user) with primary big user (public
+  // account user).
+  EXPECT_TRUE(is_public_account(user_view0));
+  AccountId primary_id =
+      primary_big_view->GetCurrentUser()->basic_user_info->account_id;
+  AccountId list_user_id =
+      user_view0->current_user()->basic_user_info->account_id;
+  EXPECT_NE(primary_id, list_user_id);
+
+  // Send event to swap users.
+  click_view(user_view0);
+
+  // User info is swapped.
+  EXPECT_EQ(list_user_id,
+            primary_big_view->GetCurrentUser()->basic_user_info->account_id);
+  EXPECT_EQ(primary_id,
+            user_view0->current_user()->basic_user_info->account_id);
+
+  // Child view of primary big user stays the same.
+  ASSERT_TRUE(primary_big_view->public_account());
+  ASSERT_FALSE(primary_big_view->auth_user());
+  // user_view0 is still public account user.
+  EXPECT_TRUE(is_public_account(user_view0));
+
+  // Case 2: Swap user_view1 (auth user) with primary big user (public account
+  // user).
+  EXPECT_FALSE(is_public_account(user_view1));
+  primary_id = primary_big_view->GetCurrentUser()->basic_user_info->account_id;
+  list_user_id = user_view1->current_user()->basic_user_info->account_id;
+  EXPECT_NE(primary_id, list_user_id);
+
+  // Send event to swap users.
+  click_view(user_view1);
+
+  // User info is swapped.
+  EXPECT_EQ(list_user_id,
+            primary_big_view->GetCurrentUser()->basic_user_info->account_id);
+  EXPECT_EQ(primary_id,
+            user_view1->current_user()->basic_user_info->account_id);
+
+  // Primary big user becomes auth user and its child view is rebuilt.
+  ASSERT_FALSE(primary_big_view->public_account());
+  ASSERT_TRUE(primary_big_view->auth_user());
+  // user_view1 becomes public account user.
+  EXPECT_TRUE(is_public_account(user_view1));
+
+  // Case 3: Swap user_view2 (auth user) with primary big user (auth user).
+  EXPECT_FALSE(is_public_account(user_view2));
+  primary_id = primary_big_view->GetCurrentUser()->basic_user_info->account_id;
+  list_user_id = user_view2->current_user()->basic_user_info->account_id;
+  EXPECT_NE(primary_id, list_user_id);
+
+  // Send event to swap users.
+  click_view(user_view2);
+
+  // User info is swapped.
+  EXPECT_EQ(list_user_id,
+            primary_big_view->GetCurrentUser()->basic_user_info->account_id);
+  EXPECT_EQ(primary_id,
+            user_view2->current_user()->basic_user_info->account_id);
+
+  // Child view of primary big user stays the same.
+  ASSERT_FALSE(primary_big_view->public_account());
+  ASSERT_TRUE(primary_big_view->auth_user());
+  // user_view2 is still auth user.
+  EXPECT_FALSE(is_public_account(user_view2));
+
+  // Case 4: Swap user_view0 (public account user) with with primary big user
+  // (auth user).
+  EXPECT_TRUE(is_public_account(user_view0));
+  primary_id = primary_big_view->GetCurrentUser()->basic_user_info->account_id;
+  list_user_id = user_view0->current_user()->basic_user_info->account_id;
+  EXPECT_NE(primary_id, list_user_id);
+
+  // Send event to swap users.
+  click_view(user_view0);
+
+  // User info is swapped.
+  EXPECT_EQ(list_user_id,
+            primary_big_view->GetCurrentUser()->basic_user_info->account_id);
+  EXPECT_EQ(primary_id,
+            user_view0->current_user()->basic_user_info->account_id);
+
+  // Primary big user becomes public account user and its child view is rebuilt.
+  ASSERT_TRUE(primary_big_view->public_account());
+  ASSERT_FALSE(primary_big_view->auth_user());
+  // user_view0 becomes auth user.
+  EXPECT_FALSE(is_public_account(user_view0));
+}
+
 }  // namespace ash
diff --git a/ash/login/ui/lock_screen_sanity_unittest.cc b/ash/login/ui/lock_screen_sanity_unittest.cc
index 2ecbecb..9642b6e 100644
--- a/ash/login/ui/lock_screen_sanity_unittest.cc
+++ b/ash/login/ui/lock_screen_sanity_unittest.cc
@@ -9,6 +9,7 @@
 #include "ash/login/ui/fake_login_detachable_base_model.h"
 #include "ash/login/ui/lock_contents_view.h"
 #include "ash/login/ui/login_auth_user_view.h"
+#include "ash/login/ui/login_big_user_view.h"
 #include "ash/login/ui/login_bubble.h"
 #include "ash/login/ui/login_test_base.h"
 #include "ash/login/ui/login_test_utils.h"
@@ -434,10 +435,10 @@
   submit();
 
   // Secondary auth should be gone because it is now the primary auth.
-  EXPECT_FALSE(MakeLockContentsViewTestApi(contents).opt_secondary_auth());
+  EXPECT_FALSE(MakeLockContentsViewTestApi(contents).opt_secondary_big_view());
   EXPECT_TRUE(MakeLockContentsViewTestApi(contents)
-                  .primary_auth()
-                  ->current_user()
+                  .primary_big_view()
+                  ->GetCurrentUser()
                   ->basic_user_info->account_id ==
               users()[1]->basic_user_info->account_id);
 }
diff --git a/ash/login/ui/lock_window_unittest.cc b/ash/login/ui/lock_window_unittest.cc
index 343dd9c..7b40c62d 100644
--- a/ash/login/ui/lock_window_unittest.cc
+++ b/ash/login/ui/lock_window_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "ash/login/ui/lock_contents_view.h"
 #include "ash/login/ui/lock_screen.h"
+#include "ash/login/ui/login_big_user_view.h"
 #include "ash/login/ui/login_keyboard_test_base.h"
 #include "ash/login/ui/login_test_utils.h"
 
@@ -21,8 +22,8 @@
 
   LoadUsers(1);
 
-  LoginAuthUserView* auth_view =
-      MakeLockContentsViewTestApi(lock_contents).primary_auth();
+  LoginBigUserView* auth_view =
+      MakeLockContentsViewTestApi(lock_contents).primary_big_view();
   ASSERT_NE(nullptr, auth_view);
 
   ASSERT_NO_FATAL_FAILURE(ShowKeyboard());
diff --git a/ash/login/ui/login_auth_user_view.cc b/ash/login/ui/login_auth_user_view.cc
index ddf306b..0089cea 100644
--- a/ash/login/ui/login_auth_user_view.cc
+++ b/ash/login/ui/login_auth_user_view.cc
@@ -101,9 +101,11 @@
   return view_->pin_view_;
 }
 
-LoginAuthUserView::Callbacks::Callbacks() {}
+LoginAuthUserView::Callbacks::Callbacks() = default;
 
-LoginAuthUserView::Callbacks::~Callbacks() {}
+LoginAuthUserView::Callbacks::Callbacks(const Callbacks& other) = default;
+
+LoginAuthUserView::Callbacks::~Callbacks() = default;
 
 LoginAuthUserView::LoginAuthUserView(const mojom::LoginUserInfoPtr& user,
                                      const Callbacks& callbacks)
@@ -148,7 +150,6 @@
       callbacks.on_easy_unlock_icon_hovered,
       callbacks.on_easy_unlock_icon_tapped);
 
-  // Child views animate outside view bounds.
   SetPaintToLayer(ui::LayerType::LAYER_NOT_DRAWN);
 
   // Build layout.
diff --git a/ash/login/ui/login_auth_user_view.h b/ash/login/ui/login_auth_user_view.h
index 806aba53..c09b17d3 100644
--- a/ash/login/ui/login_auth_user_view.h
+++ b/ash/login/ui/login_auth_user_view.h
@@ -50,6 +50,7 @@
 
   struct Callbacks {
     Callbacks();
+    Callbacks(const Callbacks& other);
     ~Callbacks();
 
     // Executed whenever an authentication result is available, such as when the
@@ -102,6 +103,7 @@
   const mojom::LoginUserInfoPtr& current_user() const;
 
   LoginPasswordView* password_view() { return password_view_; }
+  LoginUserView* user_view() { return user_view_; }
 
   // views::View:
   gfx::Size CalculatePreferredSize() const override;
diff --git a/ash/login/ui/login_big_user_view.cc b/ash/login/ui/login_big_user_view.cc
new file mode 100644
index 0000000..5c2dfebe
--- /dev/null
+++ b/ash/login/ui/login_big_user_view.cc
@@ -0,0 +1,102 @@
+// 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 "ash/login/ui/login_big_user_view.h"
+#include "ui/views/layout/fill_layout.h"
+
+namespace ash {
+
+namespace {
+
+bool IsPublicAccountUser(const mojom::LoginUserInfoPtr& user) {
+  return user->basic_user_info->type == user_manager::USER_TYPE_PUBLIC_ACCOUNT;
+}
+
+}  // namespace
+
+LoginBigUserView::LoginBigUserView(
+    const mojom::LoginUserInfoPtr& user,
+    const LoginAuthUserView::Callbacks& auth_user_callbacks,
+    const LoginPublicAccountUserView::Callbacks& public_account_callbacks)
+    : NonAccessibleView(),
+      auth_user_callbacks_(auth_user_callbacks),
+      public_account_callbacks_(public_account_callbacks) {
+  SetLayoutManager(std::make_unique<views::FillLayout>());
+  CreateChildView(user);
+}
+
+LoginBigUserView::~LoginBigUserView() = default;
+
+void LoginBigUserView::CreateAuthUser(const mojom::LoginUserInfoPtr& user) {
+  DCHECK(!IsPublicAccountUser(user));
+  DCHECK(!auth_user_);
+
+  auth_user_ = new LoginAuthUserView(user, auth_user_callbacks_);
+  delete public_account_;
+  public_account_ = nullptr;
+  AddChildView(auth_user_);
+}
+
+void LoginBigUserView::CreatePublicAccount(
+    const mojom::LoginUserInfoPtr& user) {
+  DCHECK(IsPublicAccountUser(user));
+  DCHECK(!public_account_);
+
+  public_account_ =
+      new LoginPublicAccountUserView(user, public_account_callbacks_);
+  delete auth_user_;
+  auth_user_ = nullptr;
+  AddChildView(public_account_);
+}
+
+void LoginBigUserView::CreateChildView(const mojom::LoginUserInfoPtr& user) {
+  if (IsPublicAccountUser(user))
+    CreatePublicAccount(user);
+  else
+    CreateAuthUser(user);
+}
+
+void LoginBigUserView::UpdateForUser(const mojom::LoginUserInfoPtr& user) {
+  // Rebuild child view for the following swap case:
+  // 1. Public Account -> Auth User
+  // 2. Auth User      -> Public Account
+  if (IsPublicAccountUser(user) != IsPublicAccountUser(GetCurrentUser()))
+    CreateChildView(user);
+
+  DCHECK(!!public_account_ ^ !!auth_user_);
+  if (public_account_)
+    public_account_->UpdateForUser(user);
+  if (auth_user_)
+    auth_user_->UpdateForUser(user);
+}
+
+const mojom::LoginUserInfoPtr& LoginBigUserView::GetCurrentUser() const {
+  DCHECK(!!public_account_ ^ !!auth_user_);
+  if (public_account_)
+    return public_account_->current_user();
+  return auth_user_->current_user();
+}
+
+LoginUserView* LoginBigUserView::GetUserView() {
+  DCHECK(!!public_account_ ^ !!auth_user_);
+  if (public_account_)
+    return public_account_->user_view();
+  return auth_user_->user_view();
+}
+
+bool LoginBigUserView::auth_enabled() const {
+  DCHECK(!!public_account_ ^ !!auth_user_);
+  if (public_account_)
+    return public_account_->auth_enabled();
+  return auth_user_->auth_methods() != LoginAuthUserView::AUTH_NONE;
+}
+
+void LoginBigUserView::RequestFocus() {
+  DCHECK(!!public_account_ ^ !!auth_user_);
+  if (public_account_)
+    return public_account_->RequestFocus();
+  return auth_user_->RequestFocus();
+}
+
+}  // namespace ash
diff --git a/ash/login/ui/login_big_user_view.h b/ash/login/ui/login_big_user_view.h
new file mode 100644
index 0000000..9b2d7ec
--- /dev/null
+++ b/ash/login/ui/login_big_user_view.h
@@ -0,0 +1,68 @@
+// Copyright 2018 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 ASH_LOGIN_UI_LOGIN_BIG_USER_VIEW_H_
+#define ASH_LOGIN_UI_LOGIN_BIG_USER_VIEW_H_
+
+#include "ash/ash_export.h"
+#include "ash/login/ui/login_auth_user_view.h"
+#include "ash/login/ui/login_public_account_user_view.h"
+#include "ash/login/ui/login_user_view.h"
+#include "ash/login/ui/non_accessible_view.h"
+#include "ash/public/interfaces/user_info.mojom.h"
+
+namespace ash {
+
+// This class displays the big user view in the login screen.
+// This is a container view which has one of the following views as its only
+// child:
+//  - LoginAuthUserView: for regular user.
+//  - LoginPublicAccountUserView: for public account user.
+class ASH_EXPORT LoginBigUserView : public NonAccessibleView {
+ public:
+  LoginBigUserView(
+      const mojom::LoginUserInfoPtr& user,
+      const LoginAuthUserView::Callbacks& auth_user_callbacks,
+      const LoginPublicAccountUserView::Callbacks& public_account_callbacks);
+  ~LoginBigUserView() override;
+
+  // Create LoginAuthUserView and add it as child view.
+  // |public_account_| will be deleted if exists to ensure the single child.
+  void CreateAuthUser(const mojom::LoginUserInfoPtr& user);
+
+  // Create LoginPublicAccountUserView and add it as child view.
+  // |auth_user_| will be deleted if exists to ensure the single child.
+  void CreatePublicAccount(const mojom::LoginUserInfoPtr& user);
+
+  // Base on the user type, call CreateAuthUser or CreatePublicAccount;
+  void CreateChildView(const mojom::LoginUserInfoPtr& user);
+
+  // Update the displayed name, icon, etc to that of |user|.
+  void UpdateForUser(const mojom::LoginUserInfoPtr& user);
+
+  const mojom::LoginUserInfoPtr& GetCurrentUser() const;
+  LoginUserView* GetUserView();
+  bool auth_enabled() const;
+
+  // views::View:
+  void RequestFocus() override;
+
+  LoginPublicAccountUserView* public_account() { return public_account_; }
+  LoginAuthUserView* auth_user() { return auth_user_; }
+
+ private:
+  // One of these is nullptr, one is not, ie.
+  // DCHECK(!!public_account_^!!auth_user_);
+  LoginPublicAccountUserView* public_account_ = nullptr;
+  LoginAuthUserView* auth_user_ = nullptr;
+
+  LoginAuthUserView::Callbacks auth_user_callbacks_;
+  LoginPublicAccountUserView::Callbacks public_account_callbacks_;
+
+  DISALLOW_COPY_AND_ASSIGN(LoginBigUserView);
+};
+
+}  // namespace ash
+
+#endif  // ASH_LOGIN_UI_LOGIN_BIG_USER_VIEW_H_
diff --git a/ash/login/ui/login_public_account_user_view.cc b/ash/login/ui/login_public_account_user_view.cc
new file mode 100644
index 0000000..e33e46ab
--- /dev/null
+++ b/ash/login/ui/login_public_account_user_view.cc
@@ -0,0 +1,172 @@
+// Copyright 2018 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 "ash/login/ui/login_public_account_user_view.h"
+
+#include <memory>
+
+#include "ash/login/ui/arrow_button_view.h"
+#include "ash/login/ui/hover_notifier.h"
+#include "ash/login/ui/layout_util.h"
+#include "ash/login/ui/login_display_style.h"
+#include "ui/compositor/scoped_layer_animation_settings.h"
+#include "ui/views/layout/box_layout.h"
+
+namespace ash {
+namespace {
+
+constexpr char kLoginPublicAccountUserViewClassName[] =
+    "LoginPublicAccountUserView";
+
+// Color of the user domain text.
+constexpr SkColor kArrowButtonBackground =
+    SkColorSetARGBMacro(0x2B, 0xFF, 0xFF, 0xFF);
+
+// Distance from the top of the user view to the user icon.
+constexpr int kDistanceFromTopOfBigUserViewToUserIconDp = 54;
+
+// Distance from the top of the user view to the user icon.
+constexpr int kDistanceFromUserViewToArrowButton = 44;
+
+// Distance from the end of arrow button to the bottom of the big user view.
+constexpr int kDistanceFromArrowButtonToBigUserViewBottom = 20;
+
+constexpr int kArrowButtonSizeDp = 40;
+
+// Non-empty width, useful for debugging/visualization.
+constexpr int kNonEmptyWidth = 1;
+
+constexpr int kArrowButtonFadeAnimationDurationMs = 180;
+
+}  // namespace
+
+LoginPublicAccountUserView::Callbacks::Callbacks() = default;
+
+LoginPublicAccountUserView::Callbacks::Callbacks(const Callbacks& other) =
+    default;
+
+LoginPublicAccountUserView::Callbacks::~Callbacks() = default;
+
+LoginPublicAccountUserView::LoginPublicAccountUserView(
+    const mojom::LoginUserInfoPtr& user,
+    const Callbacks& callbacks)
+    : NonAccessibleView(kLoginPublicAccountUserViewClassName),
+      on_tap_(callbacks.on_tap),
+      on_public_account_tap_(callbacks.on_public_account_tapped) {
+  DCHECK_EQ(user->basic_user_info->type,
+            user_manager::USER_TYPE_PUBLIC_ACCOUNT);
+  DCHECK(callbacks.on_tap);
+  DCHECK(callbacks.on_public_account_tapped);
+
+  user_view_ = new LoginUserView(
+      LoginDisplayStyle::kLarge, false /*show_dropdown*/, true /*show_domain*/,
+      base::BindRepeating(&LoginPublicAccountUserView::OnUserViewTap,
+                          base::Unretained(this)),
+      base::RepeatingClosure(), base::RepeatingClosure());
+  arrow_button_ = new ArrowButtonView(this, kArrowButtonSizeDp);
+  arrow_button_->SetBackgroundColor(kArrowButtonBackground);
+  arrow_button_->SetFocusPainter(nullptr);
+
+  SetPaintToLayer(ui::LayerType::LAYER_NOT_DRAWN);
+
+  // build layout for public account.
+  SetLayoutManager(
+      std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical));
+  views::View* wrapped_user_view =
+      login_layout_util::WrapViewForPreferredSize(user_view_);
+
+  auto add_padding = [&](int amount) {
+    auto* padding = new views::View();
+    padding->SetPreferredSize(gfx::Size(kNonEmptyWidth, amount));
+    AddChildView(padding);
+  };
+
+  add_padding(kDistanceFromTopOfBigUserViewToUserIconDp);
+  AddChildView(wrapped_user_view);
+  add_padding(kDistanceFromUserViewToArrowButton);
+  AddChildView(arrow_button_);
+  add_padding(kDistanceFromArrowButtonToBigUserViewBottom);
+
+  // Update authentication UI.
+  SetAuthEnabled(auth_enabled_, false /*animate*/);
+  user_view_->UpdateForUser(user, false /*animate*/);
+
+  hover_notifier_ = std::make_unique<HoverNotifier>(
+      this, base::BindRepeating(&LoginPublicAccountUserView::OnHover,
+                                base::Unretained(this)));
+}
+
+LoginPublicAccountUserView::~LoginPublicAccountUserView() = default;
+
+void LoginPublicAccountUserView::SetAuthEnabled(bool enabled, bool animate) {
+  auth_enabled_ = enabled;
+  ignore_hover_ = enabled;
+  UpdateArrowButtonOpacity(enabled ? 1 : 0, animate);
+  arrow_button_->SetFocusBehavior(enabled ? FocusBehavior::ALWAYS
+                                          : FocusBehavior::NEVER);
+
+  // Only the active auth user view has auth enabled. If that is the
+  // case, then render the user view as if it was always focused, since clicking
+  // on it will not do anything (such as swapping users).
+  user_view_->SetForceOpaque(enabled);
+  user_view_->SetTapEnabled(!enabled);
+  if (enabled)
+    arrow_button_->RequestFocus();
+}
+
+void LoginPublicAccountUserView::UpdateForUser(
+    const mojom::LoginUserInfoPtr& user) {
+  user_view_->UpdateForUser(user, true /*animate*/);
+}
+
+const mojom::LoginUserInfoPtr& LoginPublicAccountUserView::current_user()
+    const {
+  return user_view_->current_user();
+}
+
+gfx::Size LoginPublicAccountUserView::CalculatePreferredSize() const {
+  gfx::Size size = views::View::CalculatePreferredSize();
+  // Make sure we are at least as big as the user view. If we do not do this the
+  // view will be below minimum size when no auth methods are displayed.
+  size.SetToMax(user_view_->GetPreferredSize());
+  return size;
+}
+
+void LoginPublicAccountUserView::ButtonPressed(views::Button* sender,
+                                               const ui::Event& event) {
+  if (sender == arrow_button_) {
+    DCHECK(arrow_button_);
+    on_public_account_tap_.Run();
+  }
+}
+
+void LoginPublicAccountUserView::OnUserViewTap() {
+  on_tap_.Run();
+}
+
+void LoginPublicAccountUserView::OnHover(bool has_hover) {
+  if (!ignore_hover_)
+    UpdateArrowButtonOpacity(has_hover ? 1 : 0, true /*animate*/);
+}
+
+void LoginPublicAccountUserView::UpdateArrowButtonOpacity(float target_opacity,
+                                                          bool animate) {
+  if (!animate) {
+    arrow_button_->layer()->SetOpacity(target_opacity);
+    return;
+  }
+
+  // Set up animation.
+  {
+    ui::ScopedLayerAnimationSettings settings(
+        arrow_button_->layer()->GetAnimator());
+    settings.SetTransitionDuration(
+        base::TimeDelta::FromMilliseconds(kArrowButtonFadeAnimationDurationMs));
+    settings.SetTweenType(gfx::Tween::EASE_IN_OUT);
+
+    arrow_button_->layer()->SetOpacity(target_opacity);
+  }
+}
+
+}  // namespace ash
diff --git a/ash/login/ui/login_public_account_user_view.h b/ash/login/ui/login_public_account_user_view.h
new file mode 100644
index 0000000..b2f56b9
--- /dev/null
+++ b/ash/login/ui/login_public_account_user_view.h
@@ -0,0 +1,82 @@
+// Copyright 2018 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 ASH_LOGIN_UI_LOGIN_PUBLIC_ACCOUNT_USER_VIEW_H_
+#define ASH_LOGIN_UI_LOGIN_PUBLIC_ACCOUNT_USER_VIEW_H_
+
+#include "ash/ash_export.h"
+#include "ash/login/ui/login_user_view.h"
+#include "ash/login/ui/non_accessible_view.h"
+#include "ash/public/interfaces/login_user_info.mojom.h"
+#include "ui/views/controls/button/button.h"
+#include "ui/views/view.h"
+
+namespace ash {
+
+class ArrowButtonView;
+class HoverNotifier;
+
+// This is the big user view for the public account user. It wraps a UserView
+// and a arrow button below.
+// TODO(crbug.com/809635): Add test for this class.
+class ASH_EXPORT LoginPublicAccountUserView : public NonAccessibleView,
+                                              public views::ButtonListener {
+ public:
+  using OnPublicAccountTapped = base::RepeatingClosure;
+
+  struct Callbacks {
+    Callbacks();
+    Callbacks(const Callbacks& other);
+    ~Callbacks();
+
+    // Called when the user taps the user view.
+    LoginUserView::OnTap on_tap;
+    // Called when the user taps on the public account user view.
+    OnPublicAccountTapped on_public_account_tapped;
+  };
+
+  LoginPublicAccountUserView(const mojom::LoginUserInfoPtr& user,
+                             const Callbacks& callbacks);
+  ~LoginPublicAccountUserView() override;
+
+  void SetAuthEnabled(bool enabled, bool animate);
+  void UpdateForUser(const mojom::LoginUserInfoPtr& user);
+  const mojom::LoginUserInfoPtr& current_user() const;
+
+  // views::View:
+  gfx::Size CalculatePreferredSize() const override;
+
+  // views::ButtonListener:
+  void ButtonPressed(views::Button* sender, const ui::Event& event) override;
+
+  bool auth_enabled() const { return auth_enabled_; }
+  LoginUserView* user_view() { return user_view_; }
+
+ private:
+  // Called when the user view has been tapped and it will run |on_tap_|.
+  void OnUserViewTap();
+
+  // Show an arrow button for public session when hovered.
+  void OnHover(bool has_hover);
+
+  // Update the opacity of the arrow button.
+  void UpdateArrowButtonOpacity(float target_opacity, bool animate);
+
+  const LoginUserView::OnTap on_tap_;
+  const OnPublicAccountTapped on_public_account_tap_;
+
+  // Used to show an arrow button for public session when hovered.
+  std::unique_ptr<HoverNotifier> hover_notifier_;
+
+  ArrowButtonView* arrow_button_ = nullptr;
+  bool ignore_hover_ = false;
+  bool auth_enabled_ = false;
+  LoginUserView* user_view_ = nullptr;
+
+  DISALLOW_COPY_AND_ASSIGN(LoginPublicAccountUserView);
+};
+
+}  // namespace ash
+
+#endif  // ASH_LOGIN_UI_LOGIN_PUBLIC_ACCOUNT_USER_VIEW_H_
diff --git a/ash/login/ui/login_test_base.cc b/ash/login/ui/login_test_base.cc
index 440ddc0..c99f41d 100644
--- a/ash/login/ui/login_test_base.cc
+++ b/ash/login/ui/login_test_base.cc
@@ -71,13 +71,33 @@
 }
 
 void LoginTestBase::SetUserCount(size_t count) {
-  // Add missing users, then remove extra users.
-  while (users_.size() < count) {
+  if (count > users_.size()) {
+    AddUsers(count - users_.size());
+    return;
+  }
+
+  users_.erase(users_.begin() + count, users_.end());
+  // Notify any listeners that the user count has changed.
+  data_dispatcher_.NotifyUsers(users_);
+}
+
+void LoginTestBase::AddUsers(size_t num_users) {
+  for (size_t i = 0; i < num_users; i++) {
     std::string email =
         base::StrCat({"user", std::to_string(users_.size()), "@domain.com"});
     users_.push_back(CreateUser(email));
   }
-  users_.erase(users_.begin() + count, users_.end());
+
+  // Notify any listeners that the user count has changed.
+  data_dispatcher_.NotifyUsers(users_);
+}
+
+void LoginTestBase::AddPublicAccountUsers(size_t num_public_accounts) {
+  for (size_t i = 0; i < num_public_accounts; i++) {
+    std::string email =
+        base::StrCat({"user", std::to_string(users_.size()), "@domain.com"});
+    users_.push_back(CreatePublicAccountUser(email));
+  }
 
   // Notify any listeners that the user count has changed.
   data_dispatcher_.NotifyUsers(users_);
diff --git a/ash/login/ui/login_test_base.h b/ash/login/ui/login_test_base.h
index 7605055..298d32a 100644
--- a/ash/login/ui/login_test_base.h
+++ b/ash/login/ui/login_test_base.h
@@ -40,7 +40,18 @@
   // Changes the active number of users. Fires an event on |data_dispatcher()|.
   void SetUserCount(size_t count);
 
+  // Append number of |num_users| regular auth users.
+  // Changes the active number of users. Fires an event on
+  // |data_dispatcher()|.
+  void AddUsers(size_t num_users);
+
+  // Append number of |num_public_accounts| public account users.
+  // Changes the active number of users. Fires an event on
+  // |data_dispatcher()|.
+  void AddPublicAccountUsers(size_t num_public_accounts);
+
   std::vector<mojom::LoginUserInfoPtr>& users() { return users_; }
+
   const std::vector<mojom::LoginUserInfoPtr>& users() const { return users_; }
 
   LoginDataDispatcher* data_dispatcher() { return &data_dispatcher_; }
diff --git a/ash/login/ui/login_test_utils.cc b/ash/login/ui/login_test_utils.cc
index 46a55228..da7d301 100644
--- a/ash/login/ui/login_test_utils.cc
+++ b/ash/login/ui/login_test_utils.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "ash/login/ui/login_test_utils.h"
+#include "ash/login/ui/login_big_user_view.h"
 #include "base/strings/string_split.h"
 
 namespace ash {
@@ -16,10 +17,11 @@
   switch (target) {
     case AuthTarget::kPrimary:
       return LoginAuthUserView::TestApi(
-          MakeLockContentsViewTestApi(view).primary_auth());
+          MakeLockContentsViewTestApi(view).primary_big_view()->auth_user());
     case AuthTarget::kSecondary:
-      return LoginAuthUserView::TestApi(
-          MakeLockContentsViewTestApi(view).opt_secondary_auth());
+      return LoginAuthUserView::TestApi(MakeLockContentsViewTestApi(view)
+                                            .opt_secondary_big_view()
+                                            ->auth_user());
   }
 
   NOTREACHED();
@@ -41,4 +43,18 @@
   return user;
 }
 
+mojom::LoginUserInfoPtr CreatePublicAccountUser(const std::string& email) {
+  auto user = mojom::LoginUserInfo::New();
+  user->basic_user_info = mojom::UserInfo::New();
+  std::vector<std::string> email_parts = base::SplitString(
+      email, "@", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+  user->basic_user_info->account_id = AccountId::FromUserEmail(email);
+  user->basic_user_info->display_name = email_parts[0];
+  user->basic_user_info->display_email = email;
+  user->basic_user_info->type = user_manager::USER_TYPE_PUBLIC_ACCOUNT;
+  user->public_account_info = ash::mojom::PublicAccountInfo::New();
+  user->public_account_info->enterprise_domain = email_parts[1];
+  return user;
+}
+
 }  // namespace ash
diff --git a/ash/login/ui/login_test_utils.h b/ash/login/ui/login_test_utils.h
index 91fc4da..4121c09 100644
--- a/ash/login/ui/login_test_utils.h
+++ b/ash/login/ui/login_test_utils.h
@@ -21,9 +21,14 @@
 LoginPasswordView::TestApi MakeLoginPasswordTestApi(LockContentsView* view,
                                                     AuthTarget auth);
 
-// Utility method to create a new |mojom::UserInfoPtr| instance.
+// Utility method to create a new |mojom::LoginUserInfoPtr| instance
+// for regular user.
 mojom::LoginUserInfoPtr CreateUser(const std::string& email);
 
+// Utility method to create a new |mojom::LoginUserInfoPtr| instance for
+// public account user.
+mojom::LoginUserInfoPtr CreatePublicAccountUser(const std::string& email);
+
 }  // namespace ash
 
 #endif  // ASH_LOGIN_UI_LOGIN_TEST_UTILS_H_
diff --git a/ash/login/ui/login_user_view.cc b/ash/login/ui/login_user_view.cc
index 400dc67..ef37741 100644
--- a/ash/login/ui/login_user_view.cc
+++ b/ash/login/ui/login_user_view.cc
@@ -521,6 +521,7 @@
   }
 
   if (user_domain_) {
+    DCHECK(current_user_->public_account_info);
     const base::Optional<std::string>& enterprise_domain =
         current_user_->public_account_info->enterprise_domain;
     if (enterprise_domain) {
diff --git a/ash/login/ui/scrollable_users_list_view.cc b/ash/login/ui/scrollable_users_list_view.cc
index 08e87b8b..ec62e306 100644
--- a/ash/login/ui/scrollable_users_list_view.cc
+++ b/ash/login/ui/scrollable_users_list_view.cc
@@ -158,6 +158,15 @@
 
 ScrollableUsersListView::~ScrollableUsersListView() = default;
 
+LoginUserView* ScrollableUsersListView::GetUserView(
+    const AccountId& account_id) {
+  for (auto* view : user_views_) {
+    if (view->current_user()->basic_user_info->account_id == account_id)
+      return view;
+  }
+  return nullptr;
+}
+
 void ScrollableUsersListView::Layout() {
   DCHECK(layout_);
   bool should_show_landscape =
diff --git a/ash/login/ui/scrollable_users_list_view.h b/ash/login/ui/scrollable_users_list_view.h
index 99e433e..fb74e93 100644
--- a/ash/login/ui/scrollable_users_list_view.h
+++ b/ash/login/ui/scrollable_users_list_view.h
@@ -60,6 +60,9 @@
     return user_views_[index];
   }
 
+  // Returns user view with |account_id| if it exists or nullptr otherwise.
+  LoginUserView* GetUserView(const AccountId& account_id);
+
   // views::View:
   void Layout() override;
   void OnPaintBackground(gfx::Canvas* canvas) override;
diff --git a/ash/metrics/login_metrics_recorder_unittest.cc b/ash/metrics/login_metrics_recorder_unittest.cc
index 5a8224b..def04f9 100644
--- a/ash/metrics/login_metrics_recorder_unittest.cc
+++ b/ash/metrics/login_metrics_recorder_unittest.cc
@@ -13,6 +13,7 @@
 #include "ash/login/ui/lock_contents_view.h"
 #include "ash/login/ui/lock_screen.h"
 #include "ash/login/ui/login_auth_user_view.h"
+#include "ash/login/ui/login_big_user_view.h"
 #include "ash/login/ui/login_test_base.h"
 #include "ash/login/ui/login_test_utils.h"
 #include "ash/public/cpp/config.h"
@@ -117,9 +118,13 @@
   SetUserCount(1);
   std::unique_ptr<views::Widget> widget = CreateWidgetWithContent(contents);
   LoginAuthUserView::AuthMethods auth_method = LoginAuthUserView::AUTH_PASSWORD;
-  AccountId primary_user =
-      test_api.primary_auth()->current_user()->basic_user_info->account_id;
-  EXPECT_EQ(test_api.primary_auth()->auth_methods(), auth_method);
+  AccountId primary_user = test_api.primary_big_view()
+                               ->GetCurrentUser()
+                               ->basic_user_info->account_id;
+
+  EXPECT_NE(nullptr, test_api.primary_big_view()->auth_user());
+  EXPECT_EQ(test_api.primary_big_view()->auth_user()->auth_methods(),
+            auth_method);
   EXPECT_CALL(*client, AuthenticateUser_(primary_user, testing::_, testing::_,
                                          false, testing::_));
   EXPECT_CALL(*client, OnFocusPod(primary_user));
@@ -142,9 +147,9 @@
       static_cast<int>(LoginMetricsRecorder::AuthMethod::kPassword), 1);
 
   // Authentication attempt with pin "1111"
-  test_api.primary_auth()->SetAuthMethods(auth_method |
-                                          LoginAuthUserView::AUTH_PIN);
-  EXPECT_EQ(test_api.primary_auth()->auth_methods(),
+  test_api.primary_big_view()->auth_user()->SetAuthMethods(
+      auth_method | LoginAuthUserView::AUTH_PIN);
+  EXPECT_EQ(test_api.primary_big_view()->auth_user()->auth_methods(),
             (auth_method | LoginAuthUserView::AUTH_PIN));
   EXPECT_CALL(*client, AuthenticateUser_(primary_user, testing::_, testing::_,
                                          true, testing::_));
@@ -164,9 +169,9 @@
       static_cast<int>(LoginMetricsRecorder::AuthMethod::kPin), 1);
 
   // Authentication attempt with easy unlock tap.
-  test_api.primary_auth()->SetAuthMethods(auth_method |
-                                          LoginAuthUserView::AUTH_TAP);
-  EXPECT_EQ(test_api.primary_auth()->auth_methods(),
+  test_api.primary_big_view()->auth_user()->SetAuthMethods(
+      auth_method | LoginAuthUserView::AUTH_TAP);
+  EXPECT_EQ(test_api.primary_big_view()->auth_user()->auth_methods(),
             (auth_method | LoginAuthUserView::AUTH_TAP));
   EXPECT_CALL(*client, AttemptUnlock(primary_user));
   generator.MoveMouseTo(MakeLoginAuthTestApi(contents, AuthTarget::kPrimary)
diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn
index 3cb3527..d1f43a4 100644
--- a/ash/public/cpp/BUILD.gn
+++ b/ash/public/cpp/BUILD.gn
@@ -65,6 +65,7 @@
     "shell_window_ids.h",
     "stylus_utils.cc",
     "stylus_utils.h",
+    "wallpaper_types.h",
     "window_pin_type.cc",
     "window_pin_type.h",
     "window_properties.cc",
diff --git a/ash/public/cpp/ash_switches.cc b/ash/public/cpp/ash_switches.cc
index ad454868d..22d224c 100644
--- a/ash/public/cpp/ash_switches.cc
+++ b/ash/public/cpp/ash_switches.cc
@@ -74,6 +74,17 @@
 // Enables the stylus tools next to the status area.
 const char kAshForceEnableStylusTools[] = "force-enable-stylus-tools";
 
+// Power button position includes the power button's physical display side and
+// the percentage for power button center position to the display's
+// width/height in landscape_primary screen orientation. The value is a JSON
+// object containing a "position" property with the value "left", "right",
+// "top", or "bottom". For "left" and "right", a "y" property specifies the
+// button's center position as a fraction of the display's height (in [0.0,
+// 1.0]) relative to the top of the display. For "top" and "bottom", an "x"
+// property gives the position as a fraction of the display's width relative to
+// the left side of the display.
+const char kAshPowerButtonPosition[] = "ash-power-button-position";
+
 // Enables required things for the selected UI mode, regardless of whether the
 // Chromebook is currently in the selected UI mode.
 const char kAshUiMode[] = "force-tablet-mode";
diff --git a/ash/public/cpp/ash_switches.h b/ash/public/cpp/ash_switches.h
index 69acf6d..5807fe2 100644
--- a/ash/public/cpp/ash_switches.h
+++ b/ash/public/cpp/ash_switches.h
@@ -33,6 +33,7 @@
 ASH_PUBLIC_EXPORT extern const char kAshEnableWaylandServer[];
 ASH_PUBLIC_EXPORT extern const char kAshEnableMirroredScreen[];
 ASH_PUBLIC_EXPORT extern const char kAshForceEnableStylusTools[];
+ASH_PUBLIC_EXPORT extern const char kAshPowerButtonPosition[];
 ASH_PUBLIC_EXPORT extern const char kAshUiMode[];
 ASH_PUBLIC_EXPORT extern const char kAshUiModeAuto[];
 ASH_PUBLIC_EXPORT extern const char kAshUiModeClamshell[];
diff --git a/ash/public/cpp/vector_icons/BUILD.gn b/ash/public/cpp/vector_icons/BUILD.gn
index 75a0743..d5b87d6 100644
--- a/ash/public/cpp/vector_icons/BUILD.gn
+++ b/ash/public/cpp/vector_icons/BUILD.gn
@@ -10,7 +10,6 @@
 
   icons = [
     "notification_captive_portal.icon",
-    "notification_cellular_alert.1x.icon",
     "notification_cellular_alert.icon",
     "notification_google.icon",
     "notification_image.icon",
@@ -27,25 +26,15 @@
     "notification_wifi_off.icon",
     "notification_download.icon",
     "notification_end_of_support.icon",
-    "window_control_left_snapped.1x.icon",
     "window_control_left_snapped.icon",
-    "window_control_right_snapped.1x.icon",
     "window_control_right_snapped.icon",
-    "window_control_close.1x.icon",
     "window_control_close.icon",
-    "window_control_maximize.1x.icon",
     "window_control_maximize.icon",
-    "window_control_minimize.1x.icon",
     "window_control_minimize.icon",
-    "window_control_restore.1x.icon",
     "window_control_restore.icon",
-    "window_control_back.1x.icon",
     "window_control_back.icon",
-    "window_control_menu.1x.icon",
     "window_control_menu.icon",
-    "window_control_zoom.1x.icon",
     "window_control_zoom.icon",
-    "window_control_dezoom.1x.icon",
     "window_control_dezoom.icon",
   ]
 }
diff --git a/ash/public/cpp/vector_icons/notification_cellular_alert.1x.icon b/ash/public/cpp/vector_icons/notification_cellular_alert.1x.icon
deleted file mode 100644
index b1c722fb..0000000
--- a/ash/public/cpp/vector_icons/notification_cellular_alert.1x.icon
+++ /dev/null
@@ -1,35 +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.
-
-CANVAS_DIMENSIONS, 18,
-PATH_COLOR_ALPHA, 0x4C,
-MOVE_TO, 2, 16,
-H_LINE_TO, 13,
-V_LINE_TO, 7,
-H_LINE_TO, 11,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ALPHA, 0x4C,
-MOVE_TO, 11, 7,
-H_LINE_TO, 16,
-V_LINE_TO, 2,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ALPHA, 0xFF,
-MOVE_TO, 2, 16,
-H_LINE_TO, 9,
-V_LINE_TO, 9,
-CLOSE,
-NEW_PATH,
-MOVE_TO, 14, 16,
-H_LINE_TO, 16,
-V_LINE_TO, 14,
-H_LINE_TO, 14,
-CLOSE,
-NEW_PATH,
-MOVE_TO, 14, 13,
-H_LINE_TO, 16,
-V_LINE_TO, 8,
-H_LINE_TO, 14,
-CLOSE
diff --git a/ash/public/cpp/vector_icons/notification_cellular_alert.icon b/ash/public/cpp/vector_icons/notification_cellular_alert.icon
index 92ed360..0291476 100644
--- a/ash/public/cpp/vector_icons/notification_cellular_alert.icon
+++ b/ash/public/cpp/vector_icons/notification_cellular_alert.icon
@@ -33,3 +33,35 @@
 V_LINE_TO, 16,
 H_LINE_TO, 28,
 CLOSE
+
+CANVAS_DIMENSIONS, 18,
+PATH_COLOR_ALPHA, 0x4C,
+MOVE_TO, 2, 16,
+H_LINE_TO, 13,
+V_LINE_TO, 7,
+H_LINE_TO, 11,
+CLOSE,
+NEW_PATH,
+PATH_COLOR_ALPHA, 0x4C,
+MOVE_TO, 11, 7,
+H_LINE_TO, 16,
+V_LINE_TO, 2,
+CLOSE,
+NEW_PATH,
+PATH_COLOR_ALPHA, 0xFF,
+MOVE_TO, 2, 16,
+H_LINE_TO, 9,
+V_LINE_TO, 9,
+CLOSE,
+NEW_PATH,
+MOVE_TO, 14, 16,
+H_LINE_TO, 16,
+V_LINE_TO, 14,
+H_LINE_TO, 14,
+CLOSE,
+NEW_PATH,
+MOVE_TO, 14, 13,
+H_LINE_TO, 16,
+V_LINE_TO, 8,
+H_LINE_TO, 14,
+CLOSE
diff --git a/ash/public/cpp/vector_icons/window_control_back.1x.icon b/ash/public/cpp/vector_icons/window_control_back.1x.icon
deleted file mode 100644
index d7865b2..0000000
--- a/ash/public/cpp/vector_icons/window_control_back.1x.icon
+++ /dev/null
@@ -1,18 +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.
-
-CANVAS_DIMENSIONS, 12,
-FLIPS_IN_RTL,
-MOVE_TO, 4.92f, 5,
-H_LINE_TO, 11,
-R_V_LINE_TO, 2,
-H_LINE_TO, 4.92f,
-LINE_TO, 8, 9.75f,
-LINE_TO, 6.6f, 11,
-LINE_TO, 1, 6,
-R_LINE_TO, 0.7f, -0.62f,
-LINE_TO, 6.6f, 1,
-LINE_TO, 8, 2.25f,
-LINE_TO, 4.92f, 5,
-CLOSE
diff --git a/ash/public/cpp/vector_icons/window_control_back.icon b/ash/public/cpp/vector_icons/window_control_back.icon
index 1820b1a8..aa40587 100644
--- a/ash/public/cpp/vector_icons/window_control_back.icon
+++ b/ash/public/cpp/vector_icons/window_control_back.icon
@@ -17,3 +17,18 @@
 LINE_TO, 15, 2.05f,
 LINE_TO, 6.83f, 10,
 CLOSE
+
+CANVAS_DIMENSIONS, 12,
+FLIPS_IN_RTL,
+MOVE_TO, 4.92f, 5,
+H_LINE_TO, 11,
+R_V_LINE_TO, 2,
+H_LINE_TO, 4.92f,
+LINE_TO, 8, 9.75f,
+LINE_TO, 6.6f, 11,
+LINE_TO, 1, 6,
+R_LINE_TO, 0.7f, -0.62f,
+LINE_TO, 6.6f, 1,
+LINE_TO, 8, 2.25f,
+LINE_TO, 4.92f, 5,
+CLOSE
diff --git a/ash/public/cpp/vector_icons/window_control_close.1x.icon b/ash/public/cpp/vector_icons/window_control_close.1x.icon
deleted file mode 100644
index 813445e..0000000
--- a/ash/public/cpp/vector_icons/window_control_close.1x.icon
+++ /dev/null
@@ -1,19 +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.
-
-CANVAS_DIMENSIONS, 12,
-MOVE_TO, 6, 4.59f,
-LINE_TO, 2.46f, 1.05f,
-LINE_TO, 1.05f, 2.46f,
-LINE_TO, 4.59f, 6,
-LINE_TO, 1.05f, 9.54f,
-R_LINE_TO, 1.41f, 1.41f,
-LINE_TO, 6, 7.41f,
-R_LINE_TO, 3.54f, 3.54f,
-R_LINE_TO, 1.41f, -1.41f,
-LINE_TO, 7.41f, 6,
-R_LINE_TO, 3.54f, -3.54f,
-LINE_TO, 9.54f, 1.05f,
-LINE_TO, 6, 4.59f,
-CLOSE
diff --git a/ash/public/cpp/vector_icons/window_control_close.icon b/ash/public/cpp/vector_icons/window_control_close.icon
index d9d780e..704ebd942 100644
--- a/ash/public/cpp/vector_icons/window_control_close.icon
+++ b/ash/public/cpp/vector_icons/window_control_close.icon
@@ -17,3 +17,19 @@
 LINE_TO, 14.22f, 12,
 LINE_TO, 23, 3.22f,
 CLOSE
+
+CANVAS_DIMENSIONS, 12,
+MOVE_TO, 6, 4.59f,
+LINE_TO, 2.46f, 1.05f,
+LINE_TO, 1.05f, 2.46f,
+LINE_TO, 4.59f, 6,
+LINE_TO, 1.05f, 9.54f,
+R_LINE_TO, 1.41f, 1.41f,
+LINE_TO, 6, 7.41f,
+R_LINE_TO, 3.54f, 3.54f,
+R_LINE_TO, 1.41f, -1.41f,
+LINE_TO, 7.41f, 6,
+R_LINE_TO, 3.54f, -3.54f,
+LINE_TO, 9.54f, 1.05f,
+LINE_TO, 6, 4.59f,
+CLOSE
diff --git a/ash/public/cpp/vector_icons/window_control_dezoom.1x.icon b/ash/public/cpp/vector_icons/window_control_dezoom.1x.icon
deleted file mode 100644
index e4e3b22..0000000
--- a/ash/public/cpp/vector_icons/window_control_dezoom.1x.icon
+++ /dev/null
@@ -1,17 +0,0 @@
-CANVAS_DIMENSIONS, 12,
-MOVE_TO, 7, 0,
-LINE_TO, 9, 0,
-LINE_TO, 9, 3,
-LINE_TO, 12, 3,
-LINE_TO, 12, 5,
-LINE_TO, 7, 5,
-LINE_TO, 7, 0,
-CLOSE,
-MOVE_TO, 0, 7,
-LINE_TO, 5, 7,
-LINE_TO, 5, 12,
-LINE_TO, 3, 12,
-LINE_TO, 3, 9,
-LINE_TO, 0, 9,
-LINE_TO, 0, 7,
-CLOSE
diff --git a/ash/public/cpp/vector_icons/window_control_dezoom.icon b/ash/public/cpp/vector_icons/window_control_dezoom.icon
index dee200e..9fb77a2 100644
--- a/ash/public/cpp/vector_icons/window_control_dezoom.icon
+++ b/ash/public/cpp/vector_icons/window_control_dezoom.icon
@@ -15,3 +15,21 @@
 H_LINE_TO, 0,
 R_V_LINE_TO, -4,
 CLOSE
+
+CANVAS_DIMENSIONS, 12,
+MOVE_TO, 7, 0,
+LINE_TO, 9, 0,
+LINE_TO, 9, 3,
+LINE_TO, 12, 3,
+LINE_TO, 12, 5,
+LINE_TO, 7, 5,
+LINE_TO, 7, 0,
+CLOSE,
+MOVE_TO, 0, 7,
+LINE_TO, 5, 7,
+LINE_TO, 5, 12,
+LINE_TO, 3, 12,
+LINE_TO, 3, 9,
+LINE_TO, 0, 9,
+LINE_TO, 0, 7,
+CLOSE
diff --git a/ash/public/cpp/vector_icons/window_control_left_snapped.1x.icon b/ash/public/cpp/vector_icons/window_control_left_snapped.1x.icon
deleted file mode 100644
index b5bfa0e..0000000
--- a/ash/public/cpp/vector_icons/window_control_left_snapped.1x.icon
+++ /dev/null
@@ -1,14 +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.
-
-CANVAS_DIMENSIONS, 12,
-MOVE_TO, 1, 6,
-R_LINE_TO, 5.6f, 5,
-LINE_TO, 8, 9.75f,
-LINE_TO, 3.8f, 6,
-LINE_TO, 8, 2.25f,
-LINE_TO, 6.6f, 1,
-LINE_TO, 1.7f, 5.38f,
-LINE_TO, 1, 6,
-CLOSE
diff --git a/ash/public/cpp/vector_icons/window_control_left_snapped.icon b/ash/public/cpp/vector_icons/window_control_left_snapped.icon
index 694f178e1..2d255d14f 100644
--- a/ash/public/cpp/vector_icons/window_control_left_snapped.icon
+++ b/ash/public/cpp/vector_icons/window_control_left_snapped.icon
@@ -13,3 +13,14 @@
 LINE_TO, 12.86f, 0,
 LINE_TO, 15, 2.05f,
 CLOSE
+
+CANVAS_DIMENSIONS, 12,
+MOVE_TO, 1, 6,
+R_LINE_TO, 5.6f, 5,
+LINE_TO, 8, 9.75f,
+LINE_TO, 3.8f, 6,
+LINE_TO, 8, 2.25f,
+LINE_TO, 6.6f, 1,
+LINE_TO, 1.7f, 5.38f,
+LINE_TO, 1, 6,
+CLOSE
diff --git a/ash/public/cpp/vector_icons/window_control_maximize.1x.icon b/ash/public/cpp/vector_icons/window_control_maximize.1x.icon
deleted file mode 100644
index d5b91ae..0000000
--- a/ash/public/cpp/vector_icons/window_control_maximize.1x.icon
+++ /dev/null
@@ -1,17 +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.
-
-CANVAS_DIMENSIONS, 12,
-MOVE_TO, 11, 1,
-R_V_LINE_TO, 10,
-H_LINE_TO, 1,
-V_LINE_TO, 1,
-R_H_LINE_TO, 10,
-CLOSE,
-MOVE_TO, 9, 9,
-H_LINE_TO, 3,
-V_LINE_TO, 3,
-R_H_LINE_TO, 6,
-R_V_LINE_TO, 6,
-CLOSE
diff --git a/ash/public/cpp/vector_icons/window_control_maximize.icon b/ash/public/cpp/vector_icons/window_control_maximize.icon
index 9eef1c7..2cabda2 100644
--- a/ash/public/cpp/vector_icons/window_control_maximize.icon
+++ b/ash/public/cpp/vector_icons/window_control_maximize.icon
@@ -15,3 +15,17 @@
 R_H_LINE_TO, 16,
 R_V_LINE_TO, 16,
 CLOSE
+
+CANVAS_DIMENSIONS, 12,
+MOVE_TO, 11, 1,
+R_V_LINE_TO, 10,
+H_LINE_TO, 1,
+V_LINE_TO, 1,
+R_H_LINE_TO, 10,
+CLOSE,
+MOVE_TO, 9, 9,
+H_LINE_TO, 3,
+V_LINE_TO, 3,
+R_H_LINE_TO, 6,
+R_V_LINE_TO, 6,
+CLOSE
diff --git a/ash/public/cpp/vector_icons/window_control_menu.1x.icon b/ash/public/cpp/vector_icons/window_control_menu.1x.icon
deleted file mode 100644
index af26d89..0000000
--- a/ash/public/cpp/vector_icons/window_control_menu.1x.icon
+++ /dev/null
@@ -1,19 +0,0 @@
-CANVAS_DIMENSIONS, 12,
-MOVE_TO, 6, 3,
-R_CUBIC_TO, 0.83f, 0, 1.5f, -0.67f, 1.5f, -1.5f,
-CUBIC_TO_SHORTHAND, 6.83f, 0, 6, 0,
-CUBIC_TO_SHORTHAND, 4.5f, 0.68f, 4.5f, 1.5f,
-CUBIC_TO_SHORTHAND, 5.18f, 3, 6, 3,
-CLOSE,
-R_MOVE_TO, 0, 1.5f,
-R_CUBIC_TO, -0.82f, 0, -1.5f, 0.68f, -1.5f, 1.5f,
-CUBIC_TO_SHORTHAND, 5.18f, 7.5f, 6, 7.5f,
-CUBIC_TO_SHORTHAND, 7.5f, 6.83f, 7.5f, 6,
-CUBIC_TO_SHORTHAND, 6.83f, 4.5f, 6, 4.5f,
-CLOSE,
-MOVE_TO, 6, 9,
-R_CUBIC_TO, -0.82f, 0, -1.5f, 0.68f, -1.5f, 1.5f,
-CUBIC_TO_SHORTHAND, 5.18f, 12, 6, 12,
-R_CUBIC_TO, 0.82f, 0, 1.5f, -0.67f, 1.5f, -1.5f,
-CUBIC_TO_SHORTHAND, 6.83f, 9, 6, 9,
-CLOSE
diff --git a/ash/public/cpp/vector_icons/window_control_menu.icon b/ash/public/cpp/vector_icons/window_control_menu.icon
index e04ba84..f491591 100644
--- a/ash/public/cpp/vector_icons/window_control_menu.icon
+++ b/ash/public/cpp/vector_icons/window_control_menu.icon
@@ -17,3 +17,23 @@
 R_CUBIC_TO, 1.65f, 0, 3, -1.35f, 3, -3,
 R_CUBIC_TO, 0, -1.65f, -1.35f, -3, -3, -3,
 CLOSE
+
+CANVAS_DIMENSIONS, 12,
+MOVE_TO, 6, 3,
+R_CUBIC_TO, 0.83f, 0, 1.5f, -0.67f, 1.5f, -1.5f,
+CUBIC_TO_SHORTHAND, 6.83f, 0, 6, 0,
+CUBIC_TO_SHORTHAND, 4.5f, 0.68f, 4.5f, 1.5f,
+CUBIC_TO_SHORTHAND, 5.18f, 3, 6, 3,
+CLOSE,
+R_MOVE_TO, 0, 1.5f,
+R_CUBIC_TO, -0.82f, 0, -1.5f, 0.68f, -1.5f, 1.5f,
+CUBIC_TO_SHORTHAND, 5.18f, 7.5f, 6, 7.5f,
+CUBIC_TO_SHORTHAND, 7.5f, 6.83f, 7.5f, 6,
+CUBIC_TO_SHORTHAND, 6.83f, 4.5f, 6, 4.5f,
+CLOSE,
+MOVE_TO, 6, 9,
+R_CUBIC_TO, -0.82f, 0, -1.5f, 0.68f, -1.5f, 1.5f,
+CUBIC_TO_SHORTHAND, 5.18f, 12, 6, 12,
+R_CUBIC_TO, 0.82f, 0, 1.5f, -0.67f, 1.5f, -1.5f,
+CUBIC_TO_SHORTHAND, 6.83f, 9, 6, 9,
+CLOSE
diff --git a/ash/public/cpp/vector_icons/window_control_minimize.1x.icon b/ash/public/cpp/vector_icons/window_control_minimize.1x.icon
deleted file mode 100644
index 3064a7c8..0000000
--- a/ash/public/cpp/vector_icons/window_control_minimize.1x.icon
+++ /dev/null
@@ -1,10 +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.
-
-CANVAS_DIMENSIONS, 12,
-MOVE_TO, 1, 9,
-R_H_LINE_TO, 10,
-R_V_LINE_TO, 2,
-H_LINE_TO, 1,
-CLOSE
diff --git a/ash/public/cpp/vector_icons/window_control_minimize.icon b/ash/public/cpp/vector_icons/window_control_minimize.icon
index 680228f..c15e84b2 100644
--- a/ash/public/cpp/vector_icons/window_control_minimize.icon
+++ b/ash/public/cpp/vector_icons/window_control_minimize.icon
@@ -8,3 +8,10 @@
 R_V_LINE_TO, 3,
 H_LINE_TO, 1,
 CLOSE
+
+CANVAS_DIMENSIONS, 12,
+MOVE_TO, 1, 9,
+R_H_LINE_TO, 10,
+R_V_LINE_TO, 2,
+H_LINE_TO, 1,
+CLOSE
diff --git a/ash/public/cpp/vector_icons/window_control_restore.1x.icon b/ash/public/cpp/vector_icons/window_control_restore.1x.icon
deleted file mode 100644
index 3836338..0000000
--- a/ash/public/cpp/vector_icons/window_control_restore.1x.icon
+++ /dev/null
@@ -1,25 +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.
-
-CANVAS_DIMENSIONS, 12,
-MOVE_TO, 11, 8,
-H_LINE_TO, 4,
-V_LINE_TO, 1,
-R_H_LINE_TO, 7,
-R_V_LINE_TO, 7,
-CLOSE,
-MOVE_TO, 6, 6,
-V_LINE_TO, 3,
-R_H_LINE_TO, 3,
-R_V_LINE_TO, 3,
-H_LINE_TO, 6,
-CLOSE,
-MOVE_TO, 3, 3,
-H_LINE_TO, 1,
-R_V_LINE_TO, 8,
-R_H_LINE_TO, 8,
-V_LINE_TO, 9,
-H_LINE_TO, 3,
-V_LINE_TO, 3,
-CLOSE
diff --git a/ash/public/cpp/vector_icons/window_control_restore.icon b/ash/public/cpp/vector_icons/window_control_restore.icon
index 037ad4e..f01da8f6 100644
--- a/ash/public/cpp/vector_icons/window_control_restore.icon
+++ b/ash/public/cpp/vector_icons/window_control_restore.icon
@@ -23,3 +23,25 @@
 H_LINE_TO, 4,
 V_LINE_TO, 8,
 CLOSE
+
+CANVAS_DIMENSIONS, 12,
+MOVE_TO, 11, 8,
+H_LINE_TO, 4,
+V_LINE_TO, 1,
+R_H_LINE_TO, 7,
+R_V_LINE_TO, 7,
+CLOSE,
+MOVE_TO, 6, 6,
+V_LINE_TO, 3,
+R_H_LINE_TO, 3,
+R_V_LINE_TO, 3,
+H_LINE_TO, 6,
+CLOSE,
+MOVE_TO, 3, 3,
+H_LINE_TO, 1,
+R_V_LINE_TO, 8,
+R_H_LINE_TO, 8,
+V_LINE_TO, 9,
+H_LINE_TO, 3,
+V_LINE_TO, 3,
+CLOSE
diff --git a/ash/public/cpp/vector_icons/window_control_right_snapped.1x.icon b/ash/public/cpp/vector_icons/window_control_right_snapped.1x.icon
deleted file mode 100644
index 2c6add2..0000000
--- a/ash/public/cpp/vector_icons/window_control_right_snapped.1x.icon
+++ /dev/null
@@ -1,14 +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.
-
-CANVAS_DIMENSIONS, 12,
-MOVE_TO, 11, 6,
-R_LINE_TO, -5.6f, 5,
-LINE_TO, 4, 9.75f,
-LINE_TO, 8.2f, 6,
-LINE_TO, 4, 2.25f,
-LINE_TO, 5.4f, 1,
-R_LINE_TO, 4.9f, 4.38f,
-LINE_TO, 11, 6,
-CLOSE
diff --git a/ash/public/cpp/vector_icons/window_control_right_snapped.icon b/ash/public/cpp/vector_icons/window_control_right_snapped.icon
index fc6cff21..10aa5ed 100644
--- a/ash/public/cpp/vector_icons/window_control_right_snapped.icon
+++ b/ash/public/cpp/vector_icons/window_control_right_snapped.icon
@@ -13,3 +13,14 @@
 LINE_TO, 11.14f, 0,
 LINE_TO, 9, 2.05f,
 CLOSE
+
+CANVAS_DIMENSIONS, 12,
+MOVE_TO, 11, 6,
+R_LINE_TO, -5.6f, 5,
+LINE_TO, 4, 9.75f,
+LINE_TO, 8.2f, 6,
+LINE_TO, 4, 2.25f,
+LINE_TO, 5.4f, 1,
+R_LINE_TO, 4.9f, 4.38f,
+LINE_TO, 11, 6,
+CLOSE
diff --git a/ash/public/cpp/vector_icons/window_control_zoom.1x.icon b/ash/public/cpp/vector_icons/window_control_zoom.1x.icon
deleted file mode 100644
index 3a44a48..0000000
--- a/ash/public/cpp/vector_icons/window_control_zoom.1x.icon
+++ /dev/null
@@ -1,17 +0,0 @@
-CANVAS_DIMENSIONS, 12,
-MOVE_TO, 7, 0,
-R_H_LINE_TO, 5,
-R_V_LINE_TO, 5,
-R_H_LINE_TO, -2,
-V_LINE_TO, 2,
-H_LINE_TO, 7,
-V_LINE_TO, 0,
-CLOSE,
-MOVE_TO, 0, 7,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, 3,
-R_H_LINE_TO, 3,
-R_V_LINE_TO, 2,
-H_LINE_TO, 0,
-V_LINE_TO, 7,
-CLOSE
diff --git a/ash/public/cpp/vector_icons/window_control_zoom.icon b/ash/public/cpp/vector_icons/window_control_zoom.icon
index 64269abf..c0d3b07 100644
--- a/ash/public/cpp/vector_icons/window_control_zoom.icon
+++ b/ash/public/cpp/vector_icons/window_control_zoom.icon
@@ -15,3 +15,21 @@
 H_LINE_TO, 0,
 V_LINE_TO, 14,
 CLOSE
+
+CANVAS_DIMENSIONS, 12,
+MOVE_TO, 7, 0,
+R_H_LINE_TO, 5,
+R_V_LINE_TO, 5,
+R_H_LINE_TO, -2,
+V_LINE_TO, 2,
+H_LINE_TO, 7,
+V_LINE_TO, 0,
+CLOSE,
+MOVE_TO, 0, 7,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 3,
+R_H_LINE_TO, 3,
+R_V_LINE_TO, 2,
+H_LINE_TO, 0,
+V_LINE_TO, 7,
+CLOSE
diff --git a/ash/public/cpp/wallpaper_struct_traits.h b/ash/public/cpp/wallpaper_struct_traits.h
index d9d2d6f..590eed9 100644
--- a/ash/public/cpp/wallpaper_struct_traits.h
+++ b/ash/public/cpp/wallpaper_struct_traits.h
@@ -5,24 +5,24 @@
 #ifndef ASH_PUBLIC_CPP_WALLPAPER_STRUCT_TRAITS_H_
 #define ASH_PUBLIC_CPP_WALLPAPER_STRUCT_TRAITS_H_
 
+#include "ash/public/cpp/wallpaper_types.h"
 #include "ash/public/interfaces/wallpaper.mojom.h"
-#include "components/wallpaper/wallpaper_info.h"
 
 namespace mojo {
 
 template <>
-struct EnumTraits<ash::mojom::WallpaperLayout, wallpaper::WallpaperLayout> {
-  static ash::mojom::WallpaperLayout ToMojom(wallpaper::WallpaperLayout input) {
+struct EnumTraits<ash::mojom::WallpaperLayout, ash::WallpaperLayout> {
+  static ash::mojom::WallpaperLayout ToMojom(ash::WallpaperLayout input) {
     switch (input) {
-      case wallpaper::WALLPAPER_LAYOUT_CENTER:
+      case ash::WALLPAPER_LAYOUT_CENTER:
         return ash::mojom::WallpaperLayout::CENTER;
-      case wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED:
+      case ash::WALLPAPER_LAYOUT_CENTER_CROPPED:
         return ash::mojom::WallpaperLayout::CENTER_CROPPED;
-      case wallpaper::WALLPAPER_LAYOUT_STRETCH:
+      case ash::WALLPAPER_LAYOUT_STRETCH:
         return ash::mojom::WallpaperLayout::STRETCH;
-      case wallpaper::WALLPAPER_LAYOUT_TILE:
+      case ash::WALLPAPER_LAYOUT_TILE:
         return ash::mojom::WallpaperLayout::TILE;
-      case wallpaper::NUM_WALLPAPER_LAYOUT:
+      case ash::NUM_WALLPAPER_LAYOUT:
         break;
     }
     NOTREACHED();
@@ -30,19 +30,19 @@
   }
 
   static bool FromMojom(ash::mojom::WallpaperLayout input,
-                        wallpaper::WallpaperLayout* out) {
+                        ash::WallpaperLayout* out) {
     switch (input) {
       case ash::mojom::WallpaperLayout::CENTER:
-        *out = wallpaper::WALLPAPER_LAYOUT_CENTER;
+        *out = ash::WALLPAPER_LAYOUT_CENTER;
         return true;
       case ash::mojom::WallpaperLayout::CENTER_CROPPED:
-        *out = wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED;
+        *out = ash::WALLPAPER_LAYOUT_CENTER_CROPPED;
         return true;
       case ash::mojom::WallpaperLayout::STRETCH:
-        *out = wallpaper::WALLPAPER_LAYOUT_STRETCH;
+        *out = ash::WALLPAPER_LAYOUT_STRETCH;
         return true;
       case ash::mojom::WallpaperLayout::TILE:
-        *out = wallpaper::WALLPAPER_LAYOUT_TILE;
+        *out = ash::WALLPAPER_LAYOUT_TILE;
         return true;
     }
     NOTREACHED();
diff --git a/ash/public/cpp/wallpaper_types.h b/ash/public/cpp/wallpaper_types.h
new file mode 100644
index 0000000..b177200d
--- /dev/null
+++ b/ash/public/cpp/wallpaper_types.h
@@ -0,0 +1,65 @@
+// Copyright 2018 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 ASH_PUBLIC_CPP_WALLPAPER_TYPES_H_
+#define ASH_PUBLIC_CPP_WALLPAPER_TYPES_H_
+
+#include "ash/public/cpp/ash_public_export.h"
+
+namespace ash {
+
+// This enum is used to define the buckets for an enumerated UMA histogram.
+// Hence,
+//   (a) existing enumerated constants should never be deleted or reordered,
+//   (b) new constants should only be appended at the end of the enumeration.
+enum WallpaperLayout {
+  // Center the wallpaper on the desktop without scaling it. The wallpaper
+  // may be cropped.
+  WALLPAPER_LAYOUT_CENTER,
+  // Scale the wallpaper (while preserving its aspect ratio) to cover the
+  // desktop; the wallpaper may be cropped.
+  WALLPAPER_LAYOUT_CENTER_CROPPED,
+  // Scale the wallpaper (without preserving its aspect ratio) to match the
+  // desktop's size.
+  WALLPAPER_LAYOUT_STRETCH,
+  // Tile the wallpaper over the background without scaling it.
+  WALLPAPER_LAYOUT_TILE,
+  // This must remain last.
+  NUM_WALLPAPER_LAYOUT,
+};
+
+// This enum is used to define the buckets for an enumerated UMA histogram.
+// Hence,
+//   (a) existing enumerated constants should never be deleted or reordered,
+//   (b) new constants should only be appended at the end of the enumeration.
+enum WallpaperType {
+  DAILY = 0,         // Surprise wallpaper. Changes once a day if enabled.
+  CUSTOMIZED = 1,    // Selected by user.
+  DEFAULT = 2,       // Default.
+  /* UNKNOWN = 3 */  // Removed.
+  ONLINE = 4,        // WallpaperInfo.location denotes an URL.
+  POLICY = 5,        // Controlled by policy, can't be changed by the user.
+  THIRDPARTY = 6,    // Current wallpaper is set by a third party app.
+  DEVICE = 7,        // Current wallpaper is the device policy controlled
+                     // wallpaper. It shows on the login screen if the device
+                     // is an enterprise managed device.
+  WALLPAPER_TYPE_COUNT = 8
+};
+
+// The color profile type, ordered as the color profiles applied in
+// ash::WallpaperController.
+enum class ColorProfileType {
+  DARK_VIBRANT = 0,
+  NORMAL_VIBRANT,
+  LIGHT_VIBRANT,
+  DARK_MUTED,
+  NORMAL_MUTED,
+  LIGHT_MUTED,
+
+  NUM_OF_COLOR_PROFILES,
+};
+
+}  // namespace ash
+
+#endif  // ASH_PUBLIC_CPP_WALLPAPER_TYPES_H_
diff --git a/ash/public/interfaces/login_screen.mojom b/ash/public/interfaces/login_screen.mojom
index c614cc58..1a78f26 100644
--- a/ash/public/interfaces/login_screen.mojom
+++ b/ash/public/interfaces/login_screen.mojom
@@ -172,4 +172,14 @@
 
   // Try to remove |account_id|.
   RemoveUser(signin.mojom.AccountId account_id);
+
+  // Launch a public session for user with |account_id|.
+  // |locale|:       Locale for this user.
+  //                 The value is language code like "en-US", "zh-CN"
+  // |input_method|: Input method for this user.
+  //                 This is the id of InputMethodDescriptor like
+  //                 "t:latn-post", "pinyin".
+  LaunchPublicSession(signin.mojom.AccountId account_id,
+                      string locale,
+                      string input_method);
 };
diff --git a/ash/public/interfaces/system_tray.mojom b/ash/public/interfaces/system_tray.mojom
index 44bb103..8414c65a 100644
--- a/ash/public/interfaces/system_tray.mojom
+++ b/ash/public/interfaces/system_tray.mojom
@@ -131,6 +131,9 @@
   // be any string.
   ShowNetworkSettings(string network_id);
 
+  // Shows the MultiDevice setup flow dialog.
+  ShowMultiDeviceSetup();
+
   // Attempts to restart the system for update.
   RequestRestartForUpdate();
 };
diff --git a/ash/public/interfaces/wallpaper.mojom b/ash/public/interfaces/wallpaper.mojom
index 3605f4b..a0c8f2b 100644
--- a/ash/public/interfaces/wallpaper.mojom
+++ b/ash/public/interfaces/wallpaper.mojom
@@ -11,7 +11,7 @@
 import "ui/gfx/image/mojo/image.mojom";
 import "url/mojom/url.mojom";
 
-// These values match wallpaper::WallpaperLayout.
+// These values match ash::WallpaperLayout.
 enum WallpaperLayout {
   CENTER,
   CENTER_CROPPED,
diff --git a/ash/public/interfaces/wallpaper.typemap b/ash/public/interfaces/wallpaper.typemap
index aae8e35..16b5792f 100644
--- a/ash/public/interfaces/wallpaper.typemap
+++ b/ash/public/interfaces/wallpaper.typemap
@@ -3,6 +3,6 @@
 # found in the LICENSE file.
 
 mojom = "//ash/public/interfaces/wallpaper.mojom"
-public_headers = [ "//components/wallpaper/wallpaper_info.h" ]
+public_headers = [ "//ash/public/cpp/wallpaper_types.h" ]
 traits_headers = [ "//ash/public/cpp/wallpaper_struct_traits.h" ]
-type_mappings = [ "ash.mojom.WallpaperLayout=wallpaper::WallpaperLayout" ]
+type_mappings = [ "ash.mojom.WallpaperLayout=ash::WallpaperLayout" ]
diff --git a/ash/resources/vector_icons/BUILD.gn b/ash/resources/vector_icons/BUILD.gn
index 2dd4370f..c0ab3b31 100644
--- a/ash/resources/vector_icons/BUILD.gn
+++ b/ash/resources/vector_icons/BUILD.gn
@@ -9,67 +9,36 @@
   icon_directory = "."
 
   icons = [
-    "captive_portal.1x.icon",
     "captive_portal.icon",
-    "check_circle.1x.icon",
     "check_circle.icon",
-    "ime_menu_emoticon.1x.icon",
     "ime_menu_emoticon.icon",
-    "ime_menu_microphone.1x.icon",
     "ime_menu_microphone.icon",
-    "ime_menu_on_screen_keyboard.1x.icon",
     "ime_menu_on_screen_keyboard.icon",
-    "ime_menu_write.1x.icon",
     "ime_menu_write.icon",
-    "lock_screen_alert.1x.icon",
     "lock_screen_alert.icon",
-    "lock_screen_arrow.1x.icon",
     "lock_screen_arrow.icon",
-    "lock_screen_backspace.1x.icon",
     "lock_screen_backspace.icon",
-    "lock_screen_caps_lock.1x.icon",
     "lock_screen_caps_lock.icon",
-    "lock_screen_dropdown.1x.icon",
     "lock_screen_dropdown.icon",
-    "login_screen_enterprise.1x.icon",
     "login_screen_enterprise.icon",
-    "network_badge_add_other.1x.icon",
     "network_badge_add_other.icon",
-    "network_badge_captive_portal.1x.icon",
     "network_badge_captive_portal.icon",
-    "network_badge_off.1x.icon",
     "network_badge_off.icon",
-    "network_badge_roaming.1x.icon",
     "network_badge_roaming.icon",
-    "network_badge_secure.1x.icon",
     "network_badge_secure.icon",
-    "network_badge_technology_1x.1x.icon",
     "network_badge_technology_1x.icon",
-    "network_badge_technology_3g.1x.icon",
     "network_badge_technology_3g.icon",
-    "network_badge_technology_4g.1x.icon",
     "network_badge_technology_4g.icon",
-    "network_badge_technology_edge.1x.icon",
     "network_badge_technology_edge.icon",
-    "network_badge_technology_evdo.1x.icon",
     "network_badge_technology_evdo.icon",
-    "network_badge_technology_gprs.1x.icon",
     "network_badge_technology_gprs.icon",
-    "network_badge_technology_hspa.1x.icon",
     "network_badge_technology_hspa.icon",
-    "network_badge_technology_hspa_plus.1x.icon",
     "network_badge_technology_hspa_plus.icon",
-    "network_badge_technology_lte.1x.icon",
     "network_badge_technology_lte.icon",
-    "network_badge_technology_lte_advanced.1x.icon",
     "network_badge_technology_lte_advanced.icon",
-    "network_badge_vpn.1x.icon",
     "network_badge_vpn.icon",
-    "network_ethernet.1x.icon",
     "network_ethernet.icon",
-    "network_mobile_not_connected_x.1x.icon",
     "network_mobile_not_connected_x.icon",
-    "network_vpn.1x.icon",
     "network_vpn.icon",
     "notification_accessibility.icon",
     "notification_accessibility_braille.icon",
@@ -100,216 +69,113 @@
     "notification_timer.icon",
     "overview_text_filter_search.icon",
     "overview_window_close.icon",
-    "palette_action_capture_region.1x.icon",
     "palette_action_capture_region.icon",
-    "palette_action_capture_screen.1x.icon",
     "palette_action_capture_screen.icon",
-    "palette_action_create_note.1x.icon",
     "palette_action_create_note.icon",
-    "palette_mode_laser_pointer.1x.icon",
     "palette_mode_laser_pointer.icon",
-    "palette_mode_magnify.1x.icon",
     "palette_mode_magnify.icon",
-    "palette_mode_metalayer.1x.icon",
     "palette_mode_metalayer.icon",
-    "palette_tray_icon_capture_region.1x.icon",
     "palette_tray_icon_capture_region.icon",
-    "palette_tray_icon_default.1x.icon",
     "palette_tray_icon_default.icon",
-    "palette_tray_icon_laser_pointer.1x.icon",
     "palette_tray_icon_laser_pointer.icon",
-    "palette_tray_icon_magnify.1x.icon",
     "palette_tray_icon_magnify.icon",
-    "palette_tray_icon_metalayer.1x.icon",
     "palette_tray_icon_metalayer.icon",
-    "shelf_add_person_button.1x.icon",
     "shelf_add_person_button.icon",
-    "shelf_back.1x.icon",
     "shelf_back.icon",
-    "shelf_browse_as_guest_button.1x.icon",
     "shelf_browse_as_guest_button.icon",
-    "shelf_cancel_button.1x.icon",
     "shelf_cancel_button.icon",
-    "shelf_keyboard.1x.icon",
     "shelf_keyboard.icon",
-    "shelf_logout.1x.icon",
     "shelf_logout.icon",
-    "shelf_notifications.1x.icon",
     "shelf_notifications.icon",
-    "shelf_overflow.1x.icon",
     "shelf_overflow.icon",
-    "shelf_overview.1x.icon",
     "shelf_overview.icon",
-    "shelf_shutdown_button.1x.icon",
     "shelf_shutdown_button.icon",
-    "shelf_sign_out_button.1x.icon",
     "shelf_sign_out_button.icon",
-    "shelf_unlock_button.1x.icon",
     "shelf_unlock_button.icon",
-    "system_menu_accessibility.1x.icon",
     "system_menu_accessibility.icon",
-    "system_menu_accessibility_auto_click.1x.icon",
     "system_menu_accessibility_auto_click.icon",
-    "system_menu_accessibility_chromevox.1x.icon",
     "system_menu_accessibility_chromevox.icon",
-    "system_menu_accessibility_contrast.1x.icon",
     "system_menu_accessibility_contrast.icon",
-    "system_menu_accessibility_docked_magnifier.1x.icon",
     "system_menu_accessibility_docked_magnifier.icon",
-    "system_menu_accessibility_fullscreen_magnifier.1x.icon",
     "system_menu_accessibility_fullscreen_magnifier.icon",
-    "system_menu_accessibility_select_to_speak.1x.icon",
     "system_menu_accessibility_select_to_speak.icon",
     "system_menu_audio_input.icon",
-    "system_menu_audio_input.1x.icon",
     "system_menu_audio_output.icon",
-    "system_menu_audio_output.1x.icon",
-    "system_menu_add_connection.1x.icon",
     "system_menu_add_connection.icon",
-    "system_menu_arrow_back.1x.icon",
     "system_menu_arrow_back.icon",
-    "system_menu_arrow_right.1x.icon",
     "system_menu_arrow_right.icon",
-    "system_menu_bluetooth.1x.icon",
     "system_menu_bluetooth.icon",
-    "system_menu_bluetooth_connected.1x.icon",
     "system_menu_bluetooth_connected.icon",
-    "system_menu_bluetooth_disabled.1x.icon",
     "system_menu_bluetooth_disabled.icon",
-    "system_menu_brightness.1x.icon",
     "system_menu_brightness.icon",
-    "system_menu_business.1x.icon",
     "system_menu_business.icon",
-    "system_menu_caps_lock.1x.icon",
     "system_menu_caps_lock.icon",
-    "system_menu_cast.1x.icon",
     "system_menu_cast.icon",
-    "system_menu_cast_audio.1x.icon",
     "system_menu_cast_audio.icon",
-    "system_menu_cast_audio_group.1x.icon",
     "system_menu_cast_audio_group.icon",
-    "system_menu_cast_enabled.1x.icon",
     "system_menu_cast_enabled.icon",
-    "system_menu_cast_generic.1x.icon",
     "system_menu_cast_generic.icon",
-    "system_menu_cast_message.1x.icon",
     "system_menu_cast_message.icon",
-    "system_menu_child_user.1x.icon",
     "system_menu_child_user.icon",
-    "system_menu_computer.1x.icon",
     "system_menu_computer.icon",
-    "system_menu_gamepad.1x.icon",
     "system_menu_gamepad.icon",
-    "system_menu_guest.1x.icon",
     "system_menu_guest.icon",
-    "system_menu_hdmi.1x.icon",
     "system_menu_hdmi.icon",
-    "system_menu_headset.1x.icon",
     "system_menu_headset.icon",
-    "system_menu_help.1x.icon",
     "system_menu_help.icon",
-    "system_menu_info.1x.icon",
     "system_menu_info.icon",
-    "system_menu_keyboard.1x.icon",
     "system_menu_keyboard.icon",
-    "system_menu_keyboard_brightness.1x.icon",
     "system_menu_keyboard_brightness.icon",
-    "system_menu_lock.1x.icon",
     "system_menu_lock.icon",
-    "system_menu_mouse.1x.icon",
     "system_menu_mouse.icon",
-    "system_menu_phone.1x.icon",
     "system_menu_phone.icon",
-    "system_menu_power.1x.icon",
     "system_menu_power.icon",
-    "system_menu_rotation_lock_auto.1x.icon",
     "system_menu_rotation_lock_auto.icon",
-    "system_menu_rotation_lock_landscape.1x.icon",
     "system_menu_rotation_lock_landscape.icon",
-    "system_menu_rotation_lock_portrait.1x.icon",
     "system_menu_rotation_lock_portrait.icon",
-    "system_menu_screen_share.1x.icon",
     "system_menu_screen_share.icon",
-    "system_menu_settings.1x.icon",
     "system_menu_settings.icon",
-    "system_menu_supervised_user.1x.icon",
     "system_menu_supervised_user.icon",
-    "system_menu_tablet.1x.icon",
     "system_menu_tablet.icon",
-    "system_menu_timer.1x.icon",
-    "system_menu_tracing.1x.icon",
     "system_menu_tracing.icon",
     "system_menu_timer.icon",
-    "system_menu_update.1x.icon",
     "system_menu_update.icon",
-    "system_menu_new_user.1x.icon",
     "system_menu_new_user.icon",
-    "system_menu_night_light_off.1x.icon",
     "system_menu_night_light_off.icon",
-    "system_menu_night_light_on.1x.icon",
     "system_menu_night_light_on.icon",
-    "system_menu_usb.1x.icon",
     "system_menu_usb.icon",
-    "system_menu_videocam.1x.icon",
     "system_menu_videocam.icon",
-    "system_menu_volume_high.1x.icon",
     "system_menu_volume_high.icon",
-    "system_menu_volume_low.1x.icon",
     "system_menu_volume_low.icon",
-    "system_menu_volume_medium.1x.icon",
     "system_menu_volume_medium.icon",
-    "system_menu_volume_mute.1x.icon",
     "system_menu_volume_mute.icon",
-    "system_power_button_menu_power_off.1x.icon",
     "system_power_button_menu_power_off.icon",
-    "system_power_button_menu_sign_out.1x.icon",
     "system_power_button_menu_sign_out.icon",
-    "system_tray_accessibility.1x.icon",
     "system_tray_accessibility.icon",
-    "system_tray_battery_alert.1x.icon",
     "system_tray_battery_alert.icon",
-    "system_tray_battery_bolt.1x.icon",
     "system_tray_battery_bolt.icon",
-    "system_tray_battery_unreliable.1x.icon",
     "system_tray_battery_unreliable.icon",
-    "system_tray_battery_x.1x.icon",
     "system_tray_battery_x.icon",
-    "system_tray_caps_lock.1x.icon",
     "system_tray_caps_lock.icon",
-    "system_tray_cast.1x.icon",
     "system_tray_cast.icon",
-    "system_tray_night_light.1x.icon",
     "system_tray_night_light.icon",
-    "system_tray_recording.1x.icon",
     "system_tray_recording.icon",
-    "system_tray_rotation_lock_auto.1x.icon",
     "system_tray_rotation_lock_auto.icon",
-    "system_tray_rotation_lock_locked.1x.icon",
     "system_tray_rotation_lock_locked.icon",
-    "system_tray_screen_share.1x.icon",
     "system_tray_screen_share.icon",
-    "system_tray_tracing.1x.icon",
     "system_tray_tracing.icon",
-    "system_tray_update.1x.icon",
     "system_tray_update.icon",
-    "system_tray_volume_mute.1x.icon",
     "system_tray_volume_mute.icon",
-    "touch_calibration_complete_check.1x.icon",
     "touch_calibration_complete_check.icon",
     "touch_calibration_hand.icon",
-    "tray_action_new_lock_screen_note.1x.icon",
     "tray_action_new_lock_screen_note.icon",
   ]
 
   if (is_chrome_branded) {
     icons += [
-      "system_menu_cast_device.1x.icon",
       "system_menu_cast_device.icon",
-      "system_menu_cast_education.1x.icon",
       "system_menu_cast_education.icon",
-      "system_menu_cast_hangout.1x.icon",
       "system_menu_cast_hangout.icon",
-      "system_menu_cast_meeting.1x.icon",
       "system_menu_cast_meeting.icon",
     ]
   }
diff --git a/ash/resources/vector_icons/captive_portal.1x.icon b/ash/resources/vector_icons/captive_portal.1x.icon
deleted file mode 100644
index 32f691f..0000000
--- a/ash/resources/vector_icons/captive_portal.1x.icon
+++ /dev/null
@@ -1,60 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 10, 13,
-R_V_LINE_TO, -1.5f,
-H_LINE_TO, 8,
-R_CUBIC_TO, 0.06f, -0.42f, 0, -0.95f, 0, -1.5f,
-R_CUBIC_TO, 0, -0.54f, -0.02f, -0.58f, 0, -1,
-R_H_LINE_TO, 4,
-R_CUBIC_TO, -0.13f, 0.42f, -0.05f, 0.46f, 0, 1,
-R_CUBIC_TO, -0.05f, 0.01f, 1.5f, 0, 1.5f, 0,
-R_CUBIC_TO, 0.11f, -0.61f, 0, -0.57f, 0, -1,
-H_LINE_TO, 16,
-R_CUBIC_TO, 0.27f, 0.42f, -0.14f, 0.58f, 0, 1,
-R_CUBIC_TO, -0.11f, -0.03f, 2, 0, 2, 0,
-R_CUBIC_TO, 0, -4.34f, -3.58f, -8, -8, -8,
-R_CUBIC_TO, -4.42f, 0, -8, 3.59f, -8, 8,
-R_CUBIC_TO, 0, 4.36f, 3.5f, 8, 8, 8,
-R_V_LINE_TO, -2,
-R_CUBIC_TO, -0.35f, -0.81f, -0.72f, -1.77f, -1, -3,
-R_H_LINE_TO, 1,
-CLOSE,
-R_MOVE_TO, 2, -5.5f,
-H_LINE_TO, 9,
-R_CUBIC_TO, 0.32f, -1.26f, 0.84f, -2.47f, 1.5f, -3.5f,
-R_CUBIC_TO, 0.65f, 1.03f, 1.16f, 2.24f, 1.5f, 3.5f,
-CLOSE,
-MOVE_TO, 7.86f, 13,
-R_CUBIC_TO, 0.22f, 1.01f, 0.59f, 2.1f, 1.14f, 3,
-R_CUBIC_TO, -1.68f, -0.51f, -3.09f, -1.54f, -4, -3,
-R_H_LINE_TO, 2.86f,
-CLOSE,
-MOVE_TO, 4, 11.5f,
-R_CUBIC_TO, 0.08f, -0.48f, 0, -0.48f, 0, -1,
-CUBIC_TO, 4, 9.98f, 4.08f, 9.48f, 4, 9,
-R_H_LINE_TO, 3,
-R_CUBIC_TO, -0.07f, 0.5f, -0.11f, 0.99f, 0, 1.5f,
-R_CUBIC_TO, -0.11f, 0.51f, -0.07f, 0.51f, 0, 1,
-H_LINE_TO, 4,
-CLOSE,
-R_MOVE_TO, 1, -4,
-CUBIC_TO, 5.89f, 6.1f, 7.3f, 4.53f, 9, 4,
-R_CUBIC_TO, -0.55f, 0.94f, -0.84f, 2.45f, -1, 3.5f,
-H_LINE_TO, 5,
-CLOSE,
-R_MOVE_TO, 8.5f, 0,
-R_CUBIC_TO, -0.16f, -1.05f, -0.94f, -2.56f, -1.5f, -3.5f,
-R_CUBIC_TO, 1.7f, 0.53f, 3.11f, 2.11f, 4, 3.5f,
-R_H_LINE_TO, -2.5f,
-CLOSE,
-MOVE_TO, 16, 18,
-R_LINE_TO, -2.5f, -2.5f,
-R_LINE_TO, -1.5f, 2,
-V_LINE_TO, 12,
-R_H_LINE_TO, 5.5f,
-R_LINE_TO, -2, 1.5f,
-LINE_TO, 18, 16,
-CLOSE
diff --git a/ash/resources/vector_icons/captive_portal.icon b/ash/resources/vector_icons/captive_portal.icon
index 255f47d..ffff1b6 100644
--- a/ash/resources/vector_icons/captive_portal.icon
+++ b/ash/resources/vector_icons/captive_portal.icon
@@ -58,3 +58,60 @@
 R_LINE_TO, -3.29f, 3.31f,
 LINE_TO, 34, 30.72f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 10, 13,
+R_V_LINE_TO, -1.5f,
+H_LINE_TO, 8,
+R_CUBIC_TO, 0.06f, -0.42f, 0, -0.95f, 0, -1.5f,
+R_CUBIC_TO, 0, -0.54f, -0.02f, -0.58f, 0, -1,
+R_H_LINE_TO, 4,
+R_CUBIC_TO, -0.13f, 0.42f, -0.05f, 0.46f, 0, 1,
+R_CUBIC_TO, -0.05f, 0.01f, 1.5f, 0, 1.5f, 0,
+R_CUBIC_TO, 0.11f, -0.61f, 0, -0.57f, 0, -1,
+H_LINE_TO, 16,
+R_CUBIC_TO, 0.27f, 0.42f, -0.14f, 0.58f, 0, 1,
+R_CUBIC_TO, -0.11f, -0.03f, 2, 0, 2, 0,
+R_CUBIC_TO, 0, -4.34f, -3.58f, -8, -8, -8,
+R_CUBIC_TO, -4.42f, 0, -8, 3.59f, -8, 8,
+R_CUBIC_TO, 0, 4.36f, 3.5f, 8, 8, 8,
+R_V_LINE_TO, -2,
+R_CUBIC_TO, -0.35f, -0.81f, -0.72f, -1.77f, -1, -3,
+R_H_LINE_TO, 1,
+CLOSE,
+R_MOVE_TO, 2, -5.5f,
+H_LINE_TO, 9,
+R_CUBIC_TO, 0.32f, -1.26f, 0.84f, -2.47f, 1.5f, -3.5f,
+R_CUBIC_TO, 0.65f, 1.03f, 1.16f, 2.24f, 1.5f, 3.5f,
+CLOSE,
+MOVE_TO, 7.86f, 13,
+R_CUBIC_TO, 0.22f, 1.01f, 0.59f, 2.1f, 1.14f, 3,
+R_CUBIC_TO, -1.68f, -0.51f, -3.09f, -1.54f, -4, -3,
+R_H_LINE_TO, 2.86f,
+CLOSE,
+MOVE_TO, 4, 11.5f,
+R_CUBIC_TO, 0.08f, -0.48f, 0, -0.48f, 0, -1,
+CUBIC_TO, 4, 9.98f, 4.08f, 9.48f, 4, 9,
+R_H_LINE_TO, 3,
+R_CUBIC_TO, -0.07f, 0.5f, -0.11f, 0.99f, 0, 1.5f,
+R_CUBIC_TO, -0.11f, 0.51f, -0.07f, 0.51f, 0, 1,
+H_LINE_TO, 4,
+CLOSE,
+R_MOVE_TO, 1, -4,
+CUBIC_TO, 5.89f, 6.1f, 7.3f, 4.53f, 9, 4,
+R_CUBIC_TO, -0.55f, 0.94f, -0.84f, 2.45f, -1, 3.5f,
+H_LINE_TO, 5,
+CLOSE,
+R_MOVE_TO, 8.5f, 0,
+R_CUBIC_TO, -0.16f, -1.05f, -0.94f, -2.56f, -1.5f, -3.5f,
+R_CUBIC_TO, 1.7f, 0.53f, 3.11f, 2.11f, 4, 3.5f,
+R_H_LINE_TO, -2.5f,
+CLOSE,
+MOVE_TO, 16, 18,
+R_LINE_TO, -2.5f, -2.5f,
+R_LINE_TO, -1.5f, 2,
+V_LINE_TO, 12,
+R_H_LINE_TO, 5.5f,
+R_LINE_TO, -2, 1.5f,
+LINE_TO, 18, 16,
+CLOSE
diff --git a/ash/resources/vector_icons/check_circle.1x.icon b/ash/resources/vector_icons/check_circle.1x.icon
deleted file mode 100644
index 2ed8bab..0000000
--- a/ash/resources/vector_icons/check_circle.1x.icon
+++ /dev/null
@@ -1,19 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 10, 2,
-R_CUBIC_TO, -4.42f, 0, -8, 3.58f, -8, 8,
-R_CUBIC_TO, 0, 4.42f, 3.58f, 8, 8, 8,
-R_CUBIC_TO, 4.42f, 0, 8, -3.58f, 8, -8,
-R_CUBIC_TO, 0, -4.42f, -3.58f, -8, -8, -8,
-CLOSE,
-MOVE_TO, 8.4f, 14,
-R_LINE_TO, -4, -4,
-R_LINE_TO, 1.13f, -1.13f,
-LINE_TO, 8.4f, 11.74f,
-R_LINE_TO, 6.07f, -6.07f,
-LINE_TO, 15.6f, 6.8f,
-LINE_TO, 8.4f, 14,
-CLOSE
diff --git a/ash/resources/vector_icons/check_circle.icon b/ash/resources/vector_icons/check_circle.icon
index f2ef12f..822edee 100644
--- a/ash/resources/vector_icons/check_circle.icon
+++ b/ash/resources/vector_icons/check_circle.icon
@@ -19,3 +19,19 @@
 LINE_TO, 31.2f, 13.6f,
 LINE_TO, 16.8f, 28,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 10, 2,
+R_CUBIC_TO, -4.42f, 0, -8, 3.58f, -8, 8,
+R_CUBIC_TO, 0, 4.42f, 3.58f, 8, 8, 8,
+R_CUBIC_TO, 4.42f, 0, 8, -3.58f, 8, -8,
+R_CUBIC_TO, 0, -4.42f, -3.58f, -8, -8, -8,
+CLOSE,
+MOVE_TO, 8.4f, 14,
+R_LINE_TO, -4, -4,
+R_LINE_TO, 1.13f, -1.13f,
+LINE_TO, 8.4f, 11.74f,
+R_LINE_TO, 6.07f, -6.07f,
+LINE_TO, 15.6f, 6.8f,
+LINE_TO, 8.4f, 14,
+CLOSE
diff --git a/ash/resources/vector_icons/ime_menu_emoticon.1x.icon b/ash/resources/vector_icons/ime_menu_emoticon.1x.icon
deleted file mode 100644
index c31d4f0..0000000
--- a/ash/resources/vector_icons/ime_menu_emoticon.1x.icon
+++ /dev/null
@@ -1,39 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 9.99f, 2,
-CUBIC_TO, 5.58f, 2, 2, 5.58f, 2, 10,
-CUBIC_TO, 2, 14.42f, 5.58f, 18, 9.99f, 18,
-CUBIC_TO, 14.42f, 18, 18, 14.42f, 18, 10,
-CUBIC_TO, 18, 5.58f, 14.42f, 2, 9.99f, 2,
-LINE_TO, 9.99f, 2,
-CLOSE,
-MOVE_TO, 10, 16.5f,
-CUBIC_TO, 6.41f, 16.5f, 3.5f, 13.59f, 3.5f, 10,
-CUBIC_TO, 3.5f, 6.41f, 6.41f, 3.5f, 10, 3.5f,
-CUBIC_TO, 13.59f, 3.5f, 16.5f, 6.41f, 16.5f, 10,
-CUBIC_TO, 16.5f, 13.59f, 13.59f, 16.5f, 10, 16.5f,
-LINE_TO, 10, 16.5f,
-CLOSE,
-MOVE_TO, 12.8f, 9.2f,
-CUBIC_TO, 13.46f, 9.2f, 14, 8.66f, 14, 8,
-CUBIC_TO, 14, 7.34f, 13.46f, 6.8f, 12.8f, 6.8f,
-CUBIC_TO, 12.14f, 6.8f, 11.6f, 7.34f, 11.6f, 8,
-CUBIC_TO, 11.6f, 8.66f, 12.14f, 9.2f, 12.8f, 9.2f,
-LINE_TO, 12.8f, 9.2f,
-CLOSE,
-MOVE_TO, 7.2f, 9.2f,
-CUBIC_TO, 7.86f, 9.2f, 8.4f, 8.66f, 8.4f, 8,
-CUBIC_TO, 8.4f, 7.34f, 7.86f, 6.8f, 7.2f, 6.8f,
-CUBIC_TO, 6.54f, 6.8f, 6, 7.34f, 6, 8,
-CUBIC_TO, 6, 8.66f, 6.54f, 9.2f, 7.2f, 9.2f,
-LINE_TO, 7.2f, 9.2f,
-CLOSE,
-MOVE_TO, 10, 14,
-CUBIC_TO, 11.86f, 14, 13.45f, 12.75f, 14.09f, 11,
-LINE_TO, 5.91f, 11,
-CUBIC_TO, 6.55f, 12.75f, 8.14f, 14, 10, 14,
-LINE_TO, 10, 14,
-CLOSE
diff --git a/ash/resources/vector_icons/ime_menu_emoticon.icon b/ash/resources/vector_icons/ime_menu_emoticon.icon
index fa34c76a..b408792 100644
--- a/ash/resources/vector_icons/ime_menu_emoticon.icon
+++ b/ash/resources/vector_icons/ime_menu_emoticon.icon
@@ -37,3 +37,39 @@
 CUBIC_TO, 13.1f, 26.5f, 16.27f, 29, 20, 29,
 LINE_TO, 20, 29,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 9.99f, 2,
+CUBIC_TO, 5.58f, 2, 2, 5.58f, 2, 10,
+CUBIC_TO, 2, 14.42f, 5.58f, 18, 9.99f, 18,
+CUBIC_TO, 14.42f, 18, 18, 14.42f, 18, 10,
+CUBIC_TO, 18, 5.58f, 14.42f, 2, 9.99f, 2,
+LINE_TO, 9.99f, 2,
+CLOSE,
+MOVE_TO, 10, 16.5f,
+CUBIC_TO, 6.41f, 16.5f, 3.5f, 13.59f, 3.5f, 10,
+CUBIC_TO, 3.5f, 6.41f, 6.41f, 3.5f, 10, 3.5f,
+CUBIC_TO, 13.59f, 3.5f, 16.5f, 6.41f, 16.5f, 10,
+CUBIC_TO, 16.5f, 13.59f, 13.59f, 16.5f, 10, 16.5f,
+LINE_TO, 10, 16.5f,
+CLOSE,
+MOVE_TO, 12.8f, 9.2f,
+CUBIC_TO, 13.46f, 9.2f, 14, 8.66f, 14, 8,
+CUBIC_TO, 14, 7.34f, 13.46f, 6.8f, 12.8f, 6.8f,
+CUBIC_TO, 12.14f, 6.8f, 11.6f, 7.34f, 11.6f, 8,
+CUBIC_TO, 11.6f, 8.66f, 12.14f, 9.2f, 12.8f, 9.2f,
+LINE_TO, 12.8f, 9.2f,
+CLOSE,
+MOVE_TO, 7.2f, 9.2f,
+CUBIC_TO, 7.86f, 9.2f, 8.4f, 8.66f, 8.4f, 8,
+CUBIC_TO, 8.4f, 7.34f, 7.86f, 6.8f, 7.2f, 6.8f,
+CUBIC_TO, 6.54f, 6.8f, 6, 7.34f, 6, 8,
+CUBIC_TO, 6, 8.66f, 6.54f, 9.2f, 7.2f, 9.2f,
+LINE_TO, 7.2f, 9.2f,
+CLOSE,
+MOVE_TO, 10, 14,
+CUBIC_TO, 11.86f, 14, 13.45f, 12.75f, 14.09f, 11,
+LINE_TO, 5.91f, 11,
+CUBIC_TO, 6.55f, 12.75f, 8.14f, 14, 10, 14,
+LINE_TO, 10, 14,
+CLOSE
diff --git a/ash/resources/vector_icons/ime_menu_microphone.1x.icon b/ash/resources/vector_icons/ime_menu_microphone.1x.icon
deleted file mode 100644
index 05253cc..0000000
--- a/ash/resources/vector_icons/ime_menu_microphone.1x.icon
+++ /dev/null
@@ -1,26 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 10, 12.11f,
-CUBIC_TO, 11.42f, 12.11f, 12.56f, 10.98f, 12.56f, 9.58f,
-LINE_TO, 12.57f, 4.53f,
-CUBIC_TO, 12.57f, 3.13f, 11.42f, 2, 10, 2,
-CUBIC_TO, 8.58f, 2, 7.43f, 3.13f, 7.43f, 4.53f,
-LINE_TO, 7.43f, 9.58f,
-CUBIC_TO, 7.43f, 10.98f, 8.58f, 12.11f, 10, 12.11f,
-LINE_TO, 10, 12.11f,
-CLOSE,
-MOVE_TO, 14.54f, 9.58f,
-CUBIC_TO, 14.54f, 12.11f, 12.37f, 13.87f, 10, 13.87f,
-CUBIC_TO, 7.63f, 13.87f, 5.46f, 12.11f, 5.46f, 9.58f,
-LINE_TO, 4, 9.58f,
-CUBIC_TO, 4, 12.46f, 6.33f, 14.83f, 9.14f, 15.24f,
-LINE_TO, 9.14f, 18,
-LINE_TO, 10.86f, 18,
-LINE_TO, 10.86f, 15.24f,
-CUBIC_TO, 13.67f, 14.83f, 16, 12.46f, 16, 9.58f,
-LINE_TO, 14.54f, 9.58f,
-LINE_TO, 14.54f, 9.58f,
-CLOSE
diff --git a/ash/resources/vector_icons/ime_menu_microphone.icon b/ash/resources/vector_icons/ime_menu_microphone.icon
index c248111d..0efad85 100644
--- a/ash/resources/vector_icons/ime_menu_microphone.icon
+++ b/ash/resources/vector_icons/ime_menu_microphone.icon
@@ -24,3 +24,26 @@
 LINE_TO, 28.83f, 20.16f,
 LINE_TO, 28.83f, 20.16f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 10, 12.11f,
+CUBIC_TO, 11.42f, 12.11f, 12.56f, 10.98f, 12.56f, 9.58f,
+LINE_TO, 12.57f, 4.53f,
+CUBIC_TO, 12.57f, 3.13f, 11.42f, 2, 10, 2,
+CUBIC_TO, 8.58f, 2, 7.43f, 3.13f, 7.43f, 4.53f,
+LINE_TO, 7.43f, 9.58f,
+CUBIC_TO, 7.43f, 10.98f, 8.58f, 12.11f, 10, 12.11f,
+LINE_TO, 10, 12.11f,
+CLOSE,
+MOVE_TO, 14.54f, 9.58f,
+CUBIC_TO, 14.54f, 12.11f, 12.37f, 13.87f, 10, 13.87f,
+CUBIC_TO, 7.63f, 13.87f, 5.46f, 12.11f, 5.46f, 9.58f,
+LINE_TO, 4, 9.58f,
+CUBIC_TO, 4, 12.46f, 6.33f, 14.83f, 9.14f, 15.24f,
+LINE_TO, 9.14f, 18,
+LINE_TO, 10.86f, 18,
+LINE_TO, 10.86f, 15.24f,
+CUBIC_TO, 13.67f, 14.83f, 16, 12.46f, 16, 9.58f,
+LINE_TO, 14.54f, 9.58f,
+LINE_TO, 14.54f, 9.58f,
+CLOSE
diff --git a/ash/resources/vector_icons/ime_menu_on_screen_keyboard.1x.icon b/ash/resources/vector_icons/ime_menu_on_screen_keyboard.1x.icon
deleted file mode 100644
index d21e3ac2a..0000000
--- a/ash/resources/vector_icons/ime_menu_on_screen_keyboard.1x.icon
+++ /dev/null
@@ -1,57 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 4, 10,
-R_V_LINE_TO, 5,
-R_H_LINE_TO, 11,
-R_V_LINE_TO, -5,
-H_LINE_TO, 4,
-CLOSE,
-MOVE_TO, 2.64f, 3,
-CUBIC_TO, 1.74f, 3, 1, 3.75f, 1, 4.67f,
-R_V_LINE_TO, 11.68f,
-CUBIC_TO, 1, 17.27f, 1.74f, 18, 2.64f, 18,
-R_H_LINE_TO, 13.73f,
-R_CUBIC_TO, 0.9f, 0, 1.64f, -0.73f, 1.64f, -1.65f,
-V_LINE_TO, 4.67f,
-CUBIC_TO, 18, 3.75f, 17.26f, 3, 16.36f, 3,
-H_LINE_TO, 2.64f,
-CLOSE,
-MOVE_TO, 3, 16,
-V_LINE_TO, 5,
-R_H_LINE_TO, 13,
-R_V_LINE_TO, 11,
-H_LINE_TO, 3,
-CLOSE,
-R_MOVE_TO, 4, -3,
-R_H_LINE_TO, 5,
-R_V_LINE_TO, 1,
-H_LINE_TO, 7,
-R_V_LINE_TO, -1,
-CLOSE,
-R_MOVE_TO, -1, -2,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-H_LINE_TO, 6,
-R_V_LINE_TO, -1,
-CLOSE,
-R_MOVE_TO, 2, 0,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-H_LINE_TO, 8,
-R_V_LINE_TO, -1,
-CLOSE,
-R_MOVE_TO, 2, 0,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-R_H_LINE_TO, -1,
-R_V_LINE_TO, -1,
-CLOSE,
-R_MOVE_TO, 2, 0,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-R_H_LINE_TO, -1,
-R_V_LINE_TO, -1,
-CLOSE
diff --git a/ash/resources/vector_icons/ime_menu_on_screen_keyboard.icon b/ash/resources/vector_icons/ime_menu_on_screen_keyboard.icon
index 0830899..f5b5ef4 100644
--- a/ash/resources/vector_icons/ime_menu_on_screen_keyboard.icon
+++ b/ash/resources/vector_icons/ime_menu_on_screen_keyboard.icon
@@ -67,3 +67,57 @@
 R_H_LINE_TO, -2,
 R_V_LINE_TO, -2,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 4, 10,
+R_V_LINE_TO, 5,
+R_H_LINE_TO, 11,
+R_V_LINE_TO, -5,
+H_LINE_TO, 4,
+CLOSE,
+MOVE_TO, 2.64f, 3,
+CUBIC_TO, 1.74f, 3, 1, 3.75f, 1, 4.67f,
+R_V_LINE_TO, 11.68f,
+CUBIC_TO, 1, 17.27f, 1.74f, 18, 2.64f, 18,
+R_H_LINE_TO, 13.73f,
+R_CUBIC_TO, 0.9f, 0, 1.64f, -0.73f, 1.64f, -1.65f,
+V_LINE_TO, 4.67f,
+CUBIC_TO, 18, 3.75f, 17.26f, 3, 16.36f, 3,
+H_LINE_TO, 2.64f,
+CLOSE,
+MOVE_TO, 3, 16,
+V_LINE_TO, 5,
+R_H_LINE_TO, 13,
+R_V_LINE_TO, 11,
+H_LINE_TO, 3,
+CLOSE,
+R_MOVE_TO, 4, -3,
+R_H_LINE_TO, 5,
+R_V_LINE_TO, 1,
+H_LINE_TO, 7,
+R_V_LINE_TO, -1,
+CLOSE,
+R_MOVE_TO, -1, -2,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+H_LINE_TO, 6,
+R_V_LINE_TO, -1,
+CLOSE,
+R_MOVE_TO, 2, 0,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+H_LINE_TO, 8,
+R_V_LINE_TO, -1,
+CLOSE,
+R_MOVE_TO, 2, 0,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+R_H_LINE_TO, -1,
+R_V_LINE_TO, -1,
+CLOSE,
+R_MOVE_TO, 2, 0,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+R_H_LINE_TO, -1,
+R_V_LINE_TO, -1,
+CLOSE
diff --git a/ash/resources/vector_icons/ime_menu_write.1x.icon b/ash/resources/vector_icons/ime_menu_write.1x.icon
deleted file mode 100644
index f261758..0000000
--- a/ash/resources/vector_icons/ime_menu_write.1x.icon
+++ /dev/null
@@ -1,26 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 10.66f, 15,
-LINE_TO, 17, 15,
-LINE_TO, 17, 17,
-LINE_TO, 9, 17,
-LINE_TO, 10.66f, 15,
-CLOSE,
-MOVE_TO, 3, 14.21f,
-LINE_TO, 3, 17,
-LINE_TO, 5.79f, 17,
-LINE_TO, 14, 8.79f,
-LINE_TO, 11.21f, 6,
-LINE_TO, 3, 14.21f,
-CLOSE,
-MOVE_TO, 16.75f, 6.44f,
-CUBIC_TO, 17.08f, 6.11f, 17.08f, 5.57f, 16.75f, 5.24f,
-LINE_TO, 14.76f, 3.25f,
-CUBIC_TO, 14.43f, 2.92f, 13.89f, 2.92f, 13.56f, 3.25f,
-LINE_TO, 12, 4.81f,
-LINE_TO, 15.19f, 8,
-LINE_TO, 16.75f, 6.44f,
-CLOSE
diff --git a/ash/resources/vector_icons/ime_menu_write.icon b/ash/resources/vector_icons/ime_menu_write.icon
index 2d2ca449..b6e10dc 100644
--- a/ash/resources/vector_icons/ime_menu_write.icon
+++ b/ash/resources/vector_icons/ime_menu_write.icon
@@ -24,3 +24,26 @@
 LINE_TO, 31.47f, 14.78f,
 LINE_TO, 34.52f, 11.73f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 10.66f, 15,
+LINE_TO, 17, 15,
+LINE_TO, 17, 17,
+LINE_TO, 9, 17,
+LINE_TO, 10.66f, 15,
+CLOSE,
+MOVE_TO, 3, 14.21f,
+LINE_TO, 3, 17,
+LINE_TO, 5.79f, 17,
+LINE_TO, 14, 8.79f,
+LINE_TO, 11.21f, 6,
+LINE_TO, 3, 14.21f,
+CLOSE,
+MOVE_TO, 16.75f, 6.44f,
+CUBIC_TO, 17.08f, 6.11f, 17.08f, 5.57f, 16.75f, 5.24f,
+LINE_TO, 14.76f, 3.25f,
+CUBIC_TO, 14.43f, 2.92f, 13.89f, 2.92f, 13.56f, 3.25f,
+LINE_TO, 12, 4.81f,
+LINE_TO, 15.19f, 8,
+LINE_TO, 16.75f, 6.44f,
+CLOSE
diff --git a/ash/resources/vector_icons/lock_screen_alert.1x.icon b/ash/resources/vector_icons/lock_screen_alert.1x.icon
deleted file mode 100644
index a22a1ae..0000000
--- a/ash/resources/vector_icons/lock_screen_alert.1x.icon
+++ /dev/null
@@ -1,22 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 0.83f, 17.5f,
-LINE_TO, 19.17f, 17.5f,
-LINE_TO, 10, 1.67f,
-LINE_TO, 0.83f, 17.5f,
-CLOSE,
-MOVE_TO, 10.83f, 15,
-LINE_TO, 9.17f, 15,
-LINE_TO, 9.17f, 13.33f,
-LINE_TO, 10.83f, 13.33f,
-LINE_TO, 10.83f, 15,
-CLOSE,
-MOVE_TO, 10.83f, 11.67f,
-LINE_TO, 9.17f, 11.67f,
-LINE_TO, 9.17f, 8.33f,
-LINE_TO, 10.83f, 8.33f,
-LINE_TO, 10.83f, 11.67f,
-CLOSE
diff --git a/ash/resources/vector_icons/lock_screen_alert.icon b/ash/resources/vector_icons/lock_screen_alert.icon
index cc8f849..db94d704 100644
--- a/ash/resources/vector_icons/lock_screen_alert.icon
+++ b/ash/resources/vector_icons/lock_screen_alert.icon
@@ -20,3 +20,22 @@
 LINE_TO, 22, 16,
 LINE_TO, 22, 23,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 0.83f, 17.5f,
+LINE_TO, 19.17f, 17.5f,
+LINE_TO, 10, 1.67f,
+LINE_TO, 0.83f, 17.5f,
+CLOSE,
+MOVE_TO, 10.83f, 15,
+LINE_TO, 9.17f, 15,
+LINE_TO, 9.17f, 13.33f,
+LINE_TO, 10.83f, 13.33f,
+LINE_TO, 10.83f, 15,
+CLOSE,
+MOVE_TO, 10.83f, 11.67f,
+LINE_TO, 9.17f, 11.67f,
+LINE_TO, 9.17f, 8.33f,
+LINE_TO, 10.83f, 8.33f,
+LINE_TO, 10.83f, 11.67f,
+CLOSE
diff --git a/ash/resources/vector_icons/lock_screen_arrow.1x.icon b/ash/resources/vector_icons/lock_screen_arrow.1x.icon
deleted file mode 100644
index 079394de..0000000
--- a/ash/resources/vector_icons/lock_screen_arrow.1x.icon
+++ /dev/null
@@ -1,15 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 10.42f, 5,
-R_LINE_TO, -0.96f, 0.96f,
-R_LINE_TO, 3.77f, 3.78f,
-H_LINE_TO, 5,
-R_V_LINE_TO, 1.35f,
-R_H_LINE_TO, 8.24f,
-R_LINE_TO, -3.77f, 3.78f,
-LINE_TO, 10.42f, 15.83,
-R_LINE_TO, 5.42f, -5.42f,
-CLOSE
diff --git a/ash/resources/vector_icons/lock_screen_arrow.icon b/ash/resources/vector_icons/lock_screen_arrow.icon
index 61c1ed8..b0802838 100644
--- a/ash/resources/vector_icons/lock_screen_arrow.icon
+++ b/ash/resources/vector_icons/lock_screen_arrow.icon
@@ -12,3 +12,15 @@
 LINE_TO, 24, 37,
 R_LINE_TO, 13, -13,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 10.42f, 5,
+R_LINE_TO, -0.96f, 0.96f,
+R_LINE_TO, 3.77f, 3.78f,
+H_LINE_TO, 5,
+R_V_LINE_TO, 1.35f,
+R_H_LINE_TO, 8.24f,
+R_LINE_TO, -3.77f, 3.78f,
+LINE_TO, 10.42f, 15.83,
+R_LINE_TO, 5.42f, -5.42f,
+CLOSE
diff --git a/ash/resources/vector_icons/lock_screen_backspace.1x.icon b/ash/resources/vector_icons/lock_screen_backspace.1x.icon
deleted file mode 100644
index 1a675fe..0000000
--- a/ash/resources/vector_icons/lock_screen_backspace.1x.icon
+++ /dev/null
@@ -1,30 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 16.67f, 4,
-LINE_TO, 6.67f, 4,
-CUBIC_TO, 6.21f, 4, 5.85f, 4.23f, 5.61f, 4.59f,
-LINE_TO, 2, 10,
-LINE_TO, 5.61f, 15.41f,
-CUBIC_TO, 5.85f, 15.76f, 6.21f, 16, 6.67f, 16,
-LINE_TO, 16.67f, 16,
-CUBIC_TO, 17.4f, 16, 18, 15.4f, 18, 14.67f,
-LINE_TO, 18, 5.33f,
-CUBIC_TO, 18, 4.6f, 17.4f, 4, 16.67f, 4,
-CLOSE,
-MOVE_TO, 14.67f, 12.39f,
-LINE_TO, 13.73f, 13.33f,
-LINE_TO, 11.33f, 10.94f,
-LINE_TO, 8.94f, 13.33f,
-LINE_TO, 8, 12.39f,
-LINE_TO, 10.39f, 10,
-LINE_TO, 8, 7.61f,
-LINE_TO, 8.94f, 6.67f,
-LINE_TO, 11.33f, 9.06f,
-LINE_TO, 13.73f, 6.67f,
-LINE_TO, 14.67f, 7.61f,
-LINE_TO, 12.27f, 10,
-LINE_TO, 14.67f, 12.39f,
-CLOSE
diff --git a/ash/resources/vector_icons/lock_screen_backspace.icon b/ash/resources/vector_icons/lock_screen_backspace.icon
index c047d5a..1220860 100644
--- a/ash/resources/vector_icons/lock_screen_backspace.icon
+++ b/ash/resources/vector_icons/lock_screen_backspace.icon
@@ -28,3 +28,30 @@
 LINE_TO, 24.55f, 20,
 LINE_TO, 29.33f, 24.79f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 16.67f, 4,
+LINE_TO, 6.67f, 4,
+CUBIC_TO, 6.21f, 4, 5.85f, 4.23f, 5.61f, 4.59f,
+LINE_TO, 2, 10,
+LINE_TO, 5.61f, 15.41f,
+CUBIC_TO, 5.85f, 15.76f, 6.21f, 16, 6.67f, 16,
+LINE_TO, 16.67f, 16,
+CUBIC_TO, 17.4f, 16, 18, 15.4f, 18, 14.67f,
+LINE_TO, 18, 5.33f,
+CUBIC_TO, 18, 4.6f, 17.4f, 4, 16.67f, 4,
+CLOSE,
+MOVE_TO, 14.67f, 12.39f,
+LINE_TO, 13.73f, 13.33f,
+LINE_TO, 11.33f, 10.94f,
+LINE_TO, 8.94f, 13.33f,
+LINE_TO, 8, 12.39f,
+LINE_TO, 10.39f, 10,
+LINE_TO, 8, 7.61f,
+LINE_TO, 8.94f, 6.67f,
+LINE_TO, 11.33f, 9.06f,
+LINE_TO, 13.73f, 6.67f,
+LINE_TO, 14.67f, 7.61f,
+LINE_TO, 12.27f, 10,
+LINE_TO, 14.67f, 12.39f,
+CLOSE
diff --git a/ash/resources/vector_icons/lock_screen_caps_lock.1x.icon b/ash/resources/vector_icons/lock_screen_caps_lock.1x.icon
deleted file mode 100644
index 18a1e754..0000000
--- a/ash/resources/vector_icons/lock_screen_caps_lock.1x.icon
+++ /dev/null
@@ -1,29 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 2.5f, 4.49f,
-CUBIC_TO, 2.5f, 3.39f, 3.39f, 2.5f, 4.49f, 2.5f,
-LINE_TO, 15.51f, 2.5f,
-CUBIC_TO, 16.61f, 2.5f, 17.5f, 3.39f, 17.5f, 4.49f,
-LINE_TO, 17.5f, 15.51f,
-CUBIC_TO, 17.5f, 16.61f, 16.61f, 17.5f, 15.51f, 17.5f,
-LINE_TO, 4.49f, 17.5f,
-CUBIC_TO, 3.39f, 17.5f, 2.5f, 16.61f, 2.5f, 15.51f,
-LINE_TO, 2.5f, 4.49f,
-CLOSE,
-MOVE_TO, 10, 7.47f,
-LINE_TO, 13.83f, 11.5f,
-LINE_TO, 15, 10.26f,
-LINE_TO, 10, 5,
-LINE_TO, 5, 10.26f,
-LINE_TO, 6.18f, 11.5f,
-LINE_TO, 10, 7.47f,
-CLOSE,
-MOVE_TO, 5, 15,
-LINE_TO, 15, 15,
-LINE_TO, 15, 13.5f,
-LINE_TO, 5, 13.5f,
-LINE_TO, 5, 15,
-CLOSE
diff --git a/ash/resources/vector_icons/lock_screen_caps_lock.icon b/ash/resources/vector_icons/lock_screen_caps_lock.icon
index d04a5099..01342b0f 100644
--- a/ash/resources/vector_icons/lock_screen_caps_lock.icon
+++ b/ash/resources/vector_icons/lock_screen_caps_lock.icon
@@ -29,3 +29,29 @@
 LINE_TO, 10, 27,
 LINE_TO, 10, 30,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 2.5f, 4.49f,
+CUBIC_TO, 2.5f, 3.39f, 3.39f, 2.5f, 4.49f, 2.5f,
+LINE_TO, 15.51f, 2.5f,
+CUBIC_TO, 16.61f, 2.5f, 17.5f, 3.39f, 17.5f, 4.49f,
+LINE_TO, 17.5f, 15.51f,
+CUBIC_TO, 17.5f, 16.61f, 16.61f, 17.5f, 15.51f, 17.5f,
+LINE_TO, 4.49f, 17.5f,
+CUBIC_TO, 3.39f, 17.5f, 2.5f, 16.61f, 2.5f, 15.51f,
+LINE_TO, 2.5f, 4.49f,
+CLOSE,
+MOVE_TO, 10, 7.47f,
+LINE_TO, 13.83f, 11.5f,
+LINE_TO, 15, 10.26f,
+LINE_TO, 10, 5,
+LINE_TO, 5, 10.26f,
+LINE_TO, 6.18f, 11.5f,
+LINE_TO, 10, 7.47f,
+CLOSE,
+MOVE_TO, 5, 15,
+LINE_TO, 15, 15,
+LINE_TO, 15, 13.5f,
+LINE_TO, 5, 13.5f,
+LINE_TO, 5, 15,
+CLOSE
diff --git a/ash/resources/vector_icons/lock_screen_dropdown.1x.icon b/ash/resources/vector_icons/lock_screen_dropdown.1x.icon
deleted file mode 100644
index c926e74..0000000
--- a/ash/resources/vector_icons/lock_screen_dropdown.1x.icon
+++ /dev/null
@@ -1,13 +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.
-
-CANVAS_DIMENSIONS, 24,
-PATH_COLOR_ARGB, 0x57, 0xFF, 0xFF, 0xFF,
-MOVE_TO, 16.59f, 8.59f,
-LINE_TO, 12, 13.17f,
-LINE_TO, 7.41f, 8.59f,
-LINE_TO, 6, 10,
-R_LINE_TO, 6, 6,
-R_LINE_TO, 6, -6,
-CLOSE
diff --git a/ash/resources/vector_icons/lock_screen_dropdown.icon b/ash/resources/vector_icons/lock_screen_dropdown.icon
index 45090b59..3e84395 100644
--- a/ash/resources/vector_icons/lock_screen_dropdown.icon
+++ b/ash/resources/vector_icons/lock_screen_dropdown.icon
@@ -10,3 +10,13 @@
 R_LINE_TO, 12, 12,
 R_LINE_TO, 12, -12,
 CLOSE
+
+CANVAS_DIMENSIONS, 24,
+PATH_COLOR_ARGB, 0x57, 0xFF, 0xFF, 0xFF,
+MOVE_TO, 16.59f, 8.59f,
+LINE_TO, 12, 13.17f,
+LINE_TO, 7.41f, 8.59f,
+LINE_TO, 6, 10,
+R_LINE_TO, 6, 6,
+R_LINE_TO, 6, -6,
+CLOSE
diff --git a/ash/resources/vector_icons/login_screen_enterprise.1x.icon b/ash/resources/vector_icons/login_screen_enterprise.1x.icon
deleted file mode 100644
index af9258701..0000000
--- a/ash/resources/vector_icons/login_screen_enterprise.1x.icon
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2018 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.
-
-CANVAS_DIMENSIONS, 12,
-MOVE_TO, 8, 9,
-R_H_LINE_TO, 1,
-V_LINE_TO, 8,
-H_LINE_TO, 8,
-R_V_LINE_TO, 1,
-CLOSE,
-R_MOVE_TO, 0, -2,
-R_H_LINE_TO, 1,
-V_LINE_TO, 6,
-H_LINE_TO, 8,
-R_V_LINE_TO, 1,
-CLOSE,
-MOVE_TO, 4, 4,
-R_H_LINE_TO, 1,
-V_LINE_TO, 3,
-H_LINE_TO, 4,
-R_V_LINE_TO, 1,
-CLOSE,
-R_MOVE_TO, 0, 2,
-R_H_LINE_TO, 1,
-V_LINE_TO, 5,
-H_LINE_TO, 4,
-R_V_LINE_TO, 1,
-CLOSE,
-R_MOVE_TO, 0, 2,
-R_H_LINE_TO, 1,
-V_LINE_TO, 7,
-H_LINE_TO, 4,
-R_V_LINE_TO, 1,
-CLOSE,
-R_MOVE_TO, 0, 2,
-R_H_LINE_TO, 1,
-V_LINE_TO, 9,
-H_LINE_TO, 4,
-R_V_LINE_TO, 1,
-CLOSE,
-MOVE_TO, 2, 4,
-R_H_LINE_TO, 1,
-V_LINE_TO, 3,
-H_LINE_TO, 2,
-R_V_LINE_TO, 1,
-CLOSE,
-R_MOVE_TO, 0, 2,
-R_H_LINE_TO, 1,
-V_LINE_TO, 5,
-H_LINE_TO, 2,
-R_V_LINE_TO, 1,
-CLOSE,
-R_MOVE_TO, 0, 2,
-R_H_LINE_TO, 1,
-V_LINE_TO, 7,
-H_LINE_TO, 2,
-R_V_LINE_TO, 1,
-CLOSE,
-R_MOVE_TO, 0, 2,
-R_H_LINE_TO, 1,
-V_LINE_TO, 9,
-H_LINE_TO, 2,
-R_V_LINE_TO, 1,
-CLOSE,
-R_MOVE_TO, 4, -6,
-V_LINE_TO, 2,
-H_LINE_TO, 1,
-R_V_LINE_TO, 9,
-R_H_LINE_TO, 10,
-V_LINE_TO, 4,
-H_LINE_TO, 6,
-CLOSE,
-R_MOVE_TO, 4, 6,
-H_LINE_TO, 6,
-V_LINE_TO, 9,
-R_H_LINE_TO, 1,
-V_LINE_TO, 8,
-H_LINE_TO, 6,
-V_LINE_TO, 7,
-R_H_LINE_TO, 1,
-V_LINE_TO, 6,
-H_LINE_TO, 6,
-V_LINE_TO, 5,
-R_H_LINE_TO, 4,
-R_V_LINE_TO, 5,
-CLOSE
diff --git a/ash/resources/vector_icons/login_screen_enterprise.icon b/ash/resources/vector_icons/login_screen_enterprise.icon
index 44715279..46d09ce 100644
--- a/ash/resources/vector_icons/login_screen_enterprise.icon
+++ b/ash/resources/vector_icons/login_screen_enterprise.icon
@@ -85,3 +85,87 @@
 V_LINE_TO, 7,
 H_LINE_TO, 12,
 CLOSE
+
+CANVAS_DIMENSIONS, 12,
+MOVE_TO, 8, 9,
+R_H_LINE_TO, 1,
+V_LINE_TO, 8,
+H_LINE_TO, 8,
+R_V_LINE_TO, 1,
+CLOSE,
+R_MOVE_TO, 0, -2,
+R_H_LINE_TO, 1,
+V_LINE_TO, 6,
+H_LINE_TO, 8,
+R_V_LINE_TO, 1,
+CLOSE,
+MOVE_TO, 4, 4,
+R_H_LINE_TO, 1,
+V_LINE_TO, 3,
+H_LINE_TO, 4,
+R_V_LINE_TO, 1,
+CLOSE,
+R_MOVE_TO, 0, 2,
+R_H_LINE_TO, 1,
+V_LINE_TO, 5,
+H_LINE_TO, 4,
+R_V_LINE_TO, 1,
+CLOSE,
+R_MOVE_TO, 0, 2,
+R_H_LINE_TO, 1,
+V_LINE_TO, 7,
+H_LINE_TO, 4,
+R_V_LINE_TO, 1,
+CLOSE,
+R_MOVE_TO, 0, 2,
+R_H_LINE_TO, 1,
+V_LINE_TO, 9,
+H_LINE_TO, 4,
+R_V_LINE_TO, 1,
+CLOSE,
+MOVE_TO, 2, 4,
+R_H_LINE_TO, 1,
+V_LINE_TO, 3,
+H_LINE_TO, 2,
+R_V_LINE_TO, 1,
+CLOSE,
+R_MOVE_TO, 0, 2,
+R_H_LINE_TO, 1,
+V_LINE_TO, 5,
+H_LINE_TO, 2,
+R_V_LINE_TO, 1,
+CLOSE,
+R_MOVE_TO, 0, 2,
+R_H_LINE_TO, 1,
+V_LINE_TO, 7,
+H_LINE_TO, 2,
+R_V_LINE_TO, 1,
+CLOSE,
+R_MOVE_TO, 0, 2,
+R_H_LINE_TO, 1,
+V_LINE_TO, 9,
+H_LINE_TO, 2,
+R_V_LINE_TO, 1,
+CLOSE,
+R_MOVE_TO, 4, -6,
+V_LINE_TO, 2,
+H_LINE_TO, 1,
+R_V_LINE_TO, 9,
+R_H_LINE_TO, 10,
+V_LINE_TO, 4,
+H_LINE_TO, 6,
+CLOSE,
+R_MOVE_TO, 4, 6,
+H_LINE_TO, 6,
+V_LINE_TO, 9,
+R_H_LINE_TO, 1,
+V_LINE_TO, 8,
+H_LINE_TO, 6,
+V_LINE_TO, 7,
+R_H_LINE_TO, 1,
+V_LINE_TO, 6,
+H_LINE_TO, 6,
+V_LINE_TO, 5,
+R_H_LINE_TO, 4,
+R_V_LINE_TO, 5,
+CLOSE
diff --git a/ash/resources/vector_icons/network_badge_add_other.1x.icon b/ash/resources/vector_icons/network_badge_add_other.1x.icon
deleted file mode 100644
index 5d081e32..0000000
--- a/ash/resources/vector_icons/network_badge_add_other.1x.icon
+++ /dev/null
@@ -1,26 +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.
-
-CANVAS_DIMENSIONS, 14,
-PATH_COLOR_ARGB, 0xFF, 0xFF, 0xFF, 0xFF,
-CIRCLE, 8, 6, 6,
-NEW_PATH,
-MOVE_TO, 7, 2,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, 8,
-R_H_LINE_TO, -2,
-V_LINE_TO, 2,
-CLOSE,
-MOVE_TO, 4, 5,
-R_H_LINE_TO, 8,
-R_V_LINE_TO, 2,
-H_LINE_TO, 4,
-R_V_LINE_TO, -2,
-CLOSE,
-MOVE_TO, 7, 5,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, 2,
-R_H_LINE_TO, -2,
-R_V_LINE_TO, -2,
-CLOSE
diff --git a/ash/resources/vector_icons/network_badge_add_other.icon b/ash/resources/vector_icons/network_badge_add_other.icon
index 17e3002..c7e09ce8 100644
--- a/ash/resources/vector_icons/network_badge_add_other.icon
+++ b/ash/resources/vector_icons/network_badge_add_other.icon
@@ -24,3 +24,26 @@
 R_H_LINE_TO, -4,
 R_V_LINE_TO, -4,
 CLOSE
+
+CANVAS_DIMENSIONS, 14,
+PATH_COLOR_ARGB, 0xFF, 0xFF, 0xFF, 0xFF,
+CIRCLE, 8, 6, 6,
+NEW_PATH,
+MOVE_TO, 7, 2,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 8,
+R_H_LINE_TO, -2,
+V_LINE_TO, 2,
+CLOSE,
+MOVE_TO, 4, 5,
+R_H_LINE_TO, 8,
+R_V_LINE_TO, 2,
+H_LINE_TO, 4,
+R_V_LINE_TO, -2,
+CLOSE,
+MOVE_TO, 7, 5,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 2,
+R_H_LINE_TO, -2,
+R_V_LINE_TO, -2,
+CLOSE
diff --git a/ash/resources/vector_icons/network_badge_captive_portal.1x.icon b/ash/resources/vector_icons/network_badge_captive_portal.1x.icon
deleted file mode 100644
index 8f616d7..0000000
--- a/ash/resources/vector_icons/network_badge_captive_portal.1x.icon
+++ /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.
-
-CANVAS_DIMENSIONS, 8,
-MOVE_TO, 1, 1,
-R_H_LINE_TO, 7,
-R_V_LINE_TO, 7,
-H_LINE_TO, 1,
-V_LINE_TO, 1,
-CLOSE,
-R_MOVE_TO, 3, 1,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 3,
-H_LINE_TO, 4,
-V_LINE_TO, 2,
-CLOSE,
-R_MOVE_TO, 0, 4,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-H_LINE_TO, 4,
-V_LINE_TO, 6,
-CLOSE
diff --git a/ash/resources/vector_icons/network_badge_captive_portal.icon b/ash/resources/vector_icons/network_badge_captive_portal.icon
index c592eb1..2ebf1bf1 100644
--- a/ash/resources/vector_icons/network_badge_captive_portal.icon
+++ b/ash/resources/vector_icons/network_badge_captive_portal.icon
@@ -21,3 +21,23 @@
 H_LINE_TO, 7,
 R_V_LINE_TO, -2,
 CLOSE
+
+CANVAS_DIMENSIONS, 8,
+MOVE_TO, 1, 1,
+R_H_LINE_TO, 7,
+R_V_LINE_TO, 7,
+H_LINE_TO, 1,
+V_LINE_TO, 1,
+CLOSE,
+R_MOVE_TO, 3, 1,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 3,
+H_LINE_TO, 4,
+V_LINE_TO, 2,
+CLOSE,
+R_MOVE_TO, 0, 4,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+H_LINE_TO, 4,
+V_LINE_TO, 6,
+CLOSE
diff --git a/ash/resources/vector_icons/network_badge_off.1x.icon b/ash/resources/vector_icons/network_badge_off.1x.icon
deleted file mode 100644
index 6fab9ad2..0000000
--- a/ash/resources/vector_icons/network_badge_off.1x.icon
+++ /dev/null
@@ -1,14 +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.
-
-CANVAS_DIMENSIONS, 20,
-PATH_MODE_CLEAR,
-STROKE, 2,
-MOVE_TO, 4, 1.5f,
-R_LINE_TO, 14, 14,
-NEW_PATH,
-CAP_SQUARE,
-STROKE, 2,
-MOVE_TO, 2, 1.5f,
-R_LINE_TO, 14, 14
diff --git a/ash/resources/vector_icons/network_badge_off.icon b/ash/resources/vector_icons/network_badge_off.icon
index 3726648..fa5ddf6e 100644
--- a/ash/resources/vector_icons/network_badge_off.icon
+++ b/ash/resources/vector_icons/network_badge_off.icon
@@ -12,3 +12,14 @@
 STROKE, 3,
 MOVE_TO, 4, 4,
 R_LINE_TO, 28, 28
+
+CANVAS_DIMENSIONS, 20,
+PATH_MODE_CLEAR,
+STROKE, 2,
+MOVE_TO, 4, 1.5f,
+R_LINE_TO, 14, 14,
+NEW_PATH,
+CAP_SQUARE,
+STROKE, 2,
+MOVE_TO, 2, 1.5f,
+R_LINE_TO, 14, 14
diff --git a/ash/resources/vector_icons/network_badge_roaming.1x.icon b/ash/resources/vector_icons/network_badge_roaming.1x.icon
deleted file mode 100644
index a028fb08..0000000
--- a/ash/resources/vector_icons/network_badge_roaming.1x.icon
+++ /dev/null
@@ -1,9 +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.
-
-CANVAS_DIMENSIONS, 8,
-MOVE_TO, 3.5f, 2,
-LINE_TO, 1, 6,
-R_H_LINE_TO, 5,
-CLOSE
diff --git a/ash/resources/vector_icons/network_badge_roaming.icon b/ash/resources/vector_icons/network_badge_roaming.icon
index 1395081..d897a7d 100644
--- a/ash/resources/vector_icons/network_badge_roaming.icon
+++ b/ash/resources/vector_icons/network_badge_roaming.icon
@@ -7,3 +7,9 @@
 R_LINE_TO, -5, 8,
 R_H_LINE_TO, 10,
 CLOSE
+
+CANVAS_DIMENSIONS, 8,
+MOVE_TO, 3.5f, 2,
+LINE_TO, 1, 6,
+R_H_LINE_TO, 5,
+CLOSE
diff --git a/ash/resources/vector_icons/network_badge_secure.1x.icon b/ash/resources/vector_icons/network_badge_secure.1x.icon
deleted file mode 100644
index d341cd2..0000000
--- a/ash/resources/vector_icons/network_badge_secure.1x.icon
+++ /dev/null
@@ -1,39 +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.
-
-CANVAS_DIMENSIONS, 8,
-MOVE_TO, 1, 4,
-R_CUBIC_TO, 0, -0.55f, 0.45f, -1, 0.99f, -1,
-R_H_LINE_TO, 4.02f,
-R_CUBIC_TO, 0.55f, 0, 0.99f, 0.44f, 0.99f, 1,
-R_V_LINE_TO, 3,
-R_CUBIC_TO, 0, 0.55f, -0.45f, 1, -0.99f, 1,
-H_LINE_TO, 1.99f,
-CUBIC_TO, 1.45f, 8, 1, 7.56f, 1, 7,
-V_LINE_TO, 4,
-CLOSE,
-R_MOVE_TO, 2.5f, 1,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-R_H_LINE_TO, -1,
-V_LINE_TO, 5,
-CLOSE,
-MOVE_TO, 2, 1,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 2,
-H_LINE_TO, 2,
-V_LINE_TO, 1,
-CLOSE,
-R_MOVE_TO, 3, 0,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 2,
-H_LINE_TO, 5,
-V_LINE_TO, 1,
-CLOSE,
-R_MOVE_TO, 0.5f, -1,
-R_V_LINE_TO, 1,
-R_H_LINE_TO, -3,
-V_LINE_TO, 0,
-R_H_LINE_TO, 3,
-CLOSE
diff --git a/ash/resources/vector_icons/network_badge_secure.icon b/ash/resources/vector_icons/network_badge_secure.icon
index 16b32d6..1ea787d 100644
--- a/ash/resources/vector_icons/network_badge_secure.icon
+++ b/ash/resources/vector_icons/network_badge_secure.icon
@@ -33,3 +33,39 @@
 V_LINE_TO, 5,
 CUBIC_TO, 6, 3.89f, 6.89f, 3, 8, 3,
 CLOSE
+
+CANVAS_DIMENSIONS, 8,
+MOVE_TO, 1, 4,
+R_CUBIC_TO, 0, -0.55f, 0.45f, -1, 0.99f, -1,
+R_H_LINE_TO, 4.02f,
+R_CUBIC_TO, 0.55f, 0, 0.99f, 0.44f, 0.99f, 1,
+R_V_LINE_TO, 3,
+R_CUBIC_TO, 0, 0.55f, -0.45f, 1, -0.99f, 1,
+H_LINE_TO, 1.99f,
+CUBIC_TO, 1.45f, 8, 1, 7.56f, 1, 7,
+V_LINE_TO, 4,
+CLOSE,
+R_MOVE_TO, 2.5f, 1,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+R_H_LINE_TO, -1,
+V_LINE_TO, 5,
+CLOSE,
+MOVE_TO, 2, 1,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 2,
+H_LINE_TO, 2,
+V_LINE_TO, 1,
+CLOSE,
+R_MOVE_TO, 3, 0,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 2,
+H_LINE_TO, 5,
+V_LINE_TO, 1,
+CLOSE,
+R_MOVE_TO, 0.5f, -1,
+R_V_LINE_TO, 1,
+R_H_LINE_TO, -3,
+V_LINE_TO, 0,
+R_H_LINE_TO, 3,
+CLOSE
diff --git a/ash/resources/vector_icons/network_badge_technology_1x.1x.icon b/ash/resources/vector_icons/network_badge_technology_1x.1x.icon
deleted file mode 100644
index 68940a1..0000000
--- a/ash/resources/vector_icons/network_badge_technology_1x.1x.icon
+++ /dev/null
@@ -1,43 +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.
-
-CANVAS_DIMENSIONS, 6,
-MOVE_TO, 0, 1,
-R_H_LINE_TO, 1,
-V_LINE_TO, 0,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 5,
-H_LINE_TO, 1,
-V_LINE_TO, 2,
-H_LINE_TO, 0,
-MOVE_TO, 3, 2,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-H_LINE_TO, 3,
-V_LINE_TO, 2,
-CLOSE,
-R_MOVE_TO, 1, 1,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-H_LINE_TO, 4,
-V_LINE_TO, 3,
-CLOSE,
-MOVE_TO, 3, 4,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-H_LINE_TO, 3,
-V_LINE_TO, 4,
-CLOSE,
-R_MOVE_TO, 2, 0,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-H_LINE_TO, 5,
-V_LINE_TO, 4,
-CLOSE,
-R_MOVE_TO, 0, -2,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-H_LINE_TO, 5,
-V_LINE_TO, 2,
-CLOSE
diff --git a/ash/resources/vector_icons/network_badge_technology_1x.icon b/ash/resources/vector_icons/network_badge_technology_1x.icon
index cb39af6..1b64bb1 100644
--- a/ash/resources/vector_icons/network_badge_technology_1x.icon
+++ b/ash/resources/vector_icons/network_badge_technology_1x.icon
@@ -41,3 +41,43 @@
 R_H_LINE_TO, -2,
 V_LINE_TO, 4,
 CLOSE
+
+CANVAS_DIMENSIONS, 6,
+MOVE_TO, 0, 1,
+R_H_LINE_TO, 1,
+V_LINE_TO, 0,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 5,
+H_LINE_TO, 1,
+V_LINE_TO, 2,
+H_LINE_TO, 0,
+MOVE_TO, 3, 2,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+H_LINE_TO, 3,
+V_LINE_TO, 2,
+CLOSE,
+R_MOVE_TO, 1, 1,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+H_LINE_TO, 4,
+V_LINE_TO, 3,
+CLOSE,
+MOVE_TO, 3, 4,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+H_LINE_TO, 3,
+V_LINE_TO, 4,
+CLOSE,
+R_MOVE_TO, 2, 0,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+H_LINE_TO, 5,
+V_LINE_TO, 4,
+CLOSE,
+R_MOVE_TO, 0, -2,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+H_LINE_TO, 5,
+V_LINE_TO, 2,
+CLOSE
diff --git a/ash/resources/vector_icons/network_badge_technology_3g.1x.icon b/ash/resources/vector_icons/network_badge_technology_3g.1x.icon
deleted file mode 100644
index 3fc0c19..0000000
--- a/ash/resources/vector_icons/network_badge_technology_3g.1x.icon
+++ /dev/null
@@ -1,35 +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.
-
-CANVAS_DIMENSIONS, 9,
-MOVE_TO, 9, 0,
-H_LINE_TO, 5,
-R_V_LINE_TO, 5,
-R_H_LINE_TO, 4,
-V_LINE_TO, 2,
-H_LINE_TO, 7,
-R_V_LINE_TO, 1,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-H_LINE_TO, 6,
-V_LINE_TO, 1,
-R_H_LINE_TO, 3,
-MOVE_TO, 3, 3,
-R_V_LINE_TO, 2,
-R_H_LINE_TO, 1,
-V_LINE_TO, 0,
-H_LINE_TO, 0,
-R_V_LINE_TO, 1,
-R_H_LINE_TO, 3,
-R_V_LINE_TO, 1,
-H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-R_H_LINE_TO, 2,
-CLOSE,
-MOVE_TO, 0, 4,
-R_H_LINE_TO, 3,
-R_V_LINE_TO, 1,
-H_LINE_TO, 0,
-V_LINE_TO, 4,
-CLOSE
diff --git a/ash/resources/vector_icons/network_badge_technology_3g.icon b/ash/resources/vector_icons/network_badge_technology_3g.icon
index b599cbb5..2d71a3c 100644
--- a/ash/resources/vector_icons/network_badge_technology_3g.icon
+++ b/ash/resources/vector_icons/network_badge_technology_3g.icon
@@ -29,3 +29,35 @@
 R_V_LINE_TO, 2,
 R_H_LINE_TO, 4,
 CLOSE
+
+CANVAS_DIMENSIONS, 9,
+MOVE_TO, 9, 0,
+H_LINE_TO, 5,
+R_V_LINE_TO, 5,
+R_H_LINE_TO, 4,
+V_LINE_TO, 2,
+H_LINE_TO, 7,
+R_V_LINE_TO, 1,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+H_LINE_TO, 6,
+V_LINE_TO, 1,
+R_H_LINE_TO, 3,
+MOVE_TO, 3, 3,
+R_V_LINE_TO, 2,
+R_H_LINE_TO, 1,
+V_LINE_TO, 0,
+H_LINE_TO, 0,
+R_V_LINE_TO, 1,
+R_H_LINE_TO, 3,
+R_V_LINE_TO, 1,
+H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+R_H_LINE_TO, 2,
+CLOSE,
+MOVE_TO, 0, 4,
+R_H_LINE_TO, 3,
+R_V_LINE_TO, 1,
+H_LINE_TO, 0,
+V_LINE_TO, 4,
+CLOSE
diff --git a/ash/resources/vector_icons/network_badge_technology_4g.1x.icon b/ash/resources/vector_icons/network_badge_technology_4g.1x.icon
deleted file mode 100644
index e3671d6..0000000
--- a/ash/resources/vector_icons/network_badge_technology_4g.1x.icon
+++ /dev/null
@@ -1,46 +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.
-
-CANVAS_DIMENSIONS, 9,
-MOVE_TO, 3, 4,
-R_V_LINE_TO, 1,
-R_H_LINE_TO, 1,
-V_LINE_TO, 0,
-H_LINE_TO, 3,
-R_V_LINE_TO, 3,
-H_LINE_TO, 0,
-R_V_LINE_TO, 1,
-R_H_LINE_TO, 3,
-CLOSE,
-MOVE_TO, 0, 2,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-H_LINE_TO, 0,
-V_LINE_TO, 2,
-CLOSE,
-R_MOVE_TO, 1, -1,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-H_LINE_TO, 1,
-V_LINE_TO, 1,
-CLOSE,
-R_MOVE_TO, 1, -1,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-H_LINE_TO, 2,
-V_LINE_TO, 0,
-CLOSE,
-MOVE_TO, 9, 0,
-H_LINE_TO, 5,
-R_V_LINE_TO, 5,
-R_H_LINE_TO, 4,
-V_LINE_TO, 2,
-H_LINE_TO, 7,
-R_V_LINE_TO, 1,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-H_LINE_TO, 6,
-V_LINE_TO, 1,
-R_H_LINE_TO, 3,
-CLOSE
diff --git a/ash/resources/vector_icons/network_badge_technology_4g.icon b/ash/resources/vector_icons/network_badge_technology_4g.icon
index 0476d56..77c262b 100644
--- a/ash/resources/vector_icons/network_badge_technology_4g.icon
+++ b/ash/resources/vector_icons/network_badge_technology_4g.icon
@@ -44,3 +44,46 @@
 V_LINE_TO, 2,
 R_H_LINE_TO, 6,
 CLOSE
+
+CANVAS_DIMENSIONS, 9,
+MOVE_TO, 3, 4,
+R_V_LINE_TO, 1,
+R_H_LINE_TO, 1,
+V_LINE_TO, 0,
+H_LINE_TO, 3,
+R_V_LINE_TO, 3,
+H_LINE_TO, 0,
+R_V_LINE_TO, 1,
+R_H_LINE_TO, 3,
+CLOSE,
+MOVE_TO, 0, 2,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+H_LINE_TO, 0,
+V_LINE_TO, 2,
+CLOSE,
+R_MOVE_TO, 1, -1,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+H_LINE_TO, 1,
+V_LINE_TO, 1,
+CLOSE,
+R_MOVE_TO, 1, -1,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+H_LINE_TO, 2,
+V_LINE_TO, 0,
+CLOSE,
+MOVE_TO, 9, 0,
+H_LINE_TO, 5,
+R_V_LINE_TO, 5,
+R_H_LINE_TO, 4,
+V_LINE_TO, 2,
+H_LINE_TO, 7,
+R_V_LINE_TO, 1,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+H_LINE_TO, 6,
+V_LINE_TO, 1,
+R_H_LINE_TO, 3,
+CLOSE
diff --git a/ash/resources/vector_icons/network_badge_technology_edge.1x.icon b/ash/resources/vector_icons/network_badge_technology_edge.1x.icon
deleted file mode 100644
index eb063f0..0000000
--- a/ash/resources/vector_icons/network_badge_technology_edge.1x.icon
+++ /dev/null
@@ -1,18 +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.
-
-CANVAS_DIMENSIONS, 5,
-MOVE_TO, 0, 0,
-R_V_LINE_TO, 5,
-R_H_LINE_TO, 3,
-V_LINE_TO, 4,
-H_LINE_TO, 1,
-V_LINE_TO, 3,
-R_H_LINE_TO, 1,
-V_LINE_TO, 2,
-H_LINE_TO, 1,
-V_LINE_TO, 1,
-R_H_LINE_TO, 2,
-V_LINE_TO, 0,
-CLOSE
diff --git a/ash/resources/vector_icons/network_badge_technology_edge.icon b/ash/resources/vector_icons/network_badge_technology_edge.icon
index d49cbc6..5e7b578 100644
--- a/ash/resources/vector_icons/network_badge_technology_edge.icon
+++ b/ash/resources/vector_icons/network_badge_technology_edge.icon
@@ -16,3 +16,18 @@
 R_H_LINE_TO, 4,
 V_LINE_TO, 0,
 CLOSE
+
+CANVAS_DIMENSIONS, 5,
+MOVE_TO, 0, 0,
+R_V_LINE_TO, 5,
+R_H_LINE_TO, 3,
+V_LINE_TO, 4,
+H_LINE_TO, 1,
+V_LINE_TO, 3,
+R_H_LINE_TO, 1,
+V_LINE_TO, 2,
+H_LINE_TO, 1,
+V_LINE_TO, 1,
+R_H_LINE_TO, 2,
+V_LINE_TO, 0,
+CLOSE
diff --git a/ash/resources/vector_icons/network_badge_technology_evdo.1x.icon b/ash/resources/vector_icons/network_badge_technology_evdo.1x.icon
deleted file mode 100644
index 1fd544b..0000000
--- a/ash/resources/vector_icons/network_badge_technology_evdo.1x.icon
+++ /dev/null
@@ -1,47 +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.
-
-CANVAS_DIMENSIONS, 9,
-MOVE_TO, 0, 0,
-R_V_LINE_TO, 5,
-R_H_LINE_TO, 3,
-V_LINE_TO, 4,
-H_LINE_TO, 1,
-V_LINE_TO, 3,
-R_H_LINE_TO, 1,
-V_LINE_TO, 2,
-H_LINE_TO, 1,
-V_LINE_TO, 1,
-R_H_LINE_TO, 2,
-V_LINE_TO, 0,
-MOVE_TO, 4, 0,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 2,
-H_LINE_TO, 4,
-V_LINE_TO, 0,
-CLOSE,
-R_MOVE_TO, 1, 2,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 2,
-H_LINE_TO, 5,
-V_LINE_TO, 2,
-CLOSE,
-R_MOVE_TO, 2, 0,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 2,
-H_LINE_TO, 7,
-V_LINE_TO, 2,
-CLOSE,
-R_MOVE_TO, 1, -2,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 2,
-H_LINE_TO, 8,
-V_LINE_TO, 0,
-CLOSE,
-MOVE_TO, 6, 4,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-H_LINE_TO, 6,
-V_LINE_TO, 4,
-CLOSE
diff --git a/ash/resources/vector_icons/network_badge_technology_evdo.icon b/ash/resources/vector_icons/network_badge_technology_evdo.icon
index 899db78..e87d6f2 100644
--- a/ash/resources/vector_icons/network_badge_technology_evdo.icon
+++ b/ash/resources/vector_icons/network_badge_technology_evdo.icon
@@ -45,3 +45,47 @@
 R_H_LINE_TO, -2,
 V_LINE_TO, 8,
 CLOSE
+
+CANVAS_DIMENSIONS, 9,
+MOVE_TO, 0, 0,
+R_V_LINE_TO, 5,
+R_H_LINE_TO, 3,
+V_LINE_TO, 4,
+H_LINE_TO, 1,
+V_LINE_TO, 3,
+R_H_LINE_TO, 1,
+V_LINE_TO, 2,
+H_LINE_TO, 1,
+V_LINE_TO, 1,
+R_H_LINE_TO, 2,
+V_LINE_TO, 0,
+MOVE_TO, 4, 0,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 2,
+H_LINE_TO, 4,
+V_LINE_TO, 0,
+CLOSE,
+R_MOVE_TO, 1, 2,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 2,
+H_LINE_TO, 5,
+V_LINE_TO, 2,
+CLOSE,
+R_MOVE_TO, 2, 0,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 2,
+H_LINE_TO, 7,
+V_LINE_TO, 2,
+CLOSE,
+R_MOVE_TO, 1, -2,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 2,
+H_LINE_TO, 8,
+V_LINE_TO, 0,
+CLOSE,
+MOVE_TO, 6, 4,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+H_LINE_TO, 6,
+V_LINE_TO, 4,
+CLOSE
diff --git a/ash/resources/vector_icons/network_badge_technology_gprs.1x.icon b/ash/resources/vector_icons/network_badge_technology_gprs.1x.icon
deleted file mode 100644
index 6eb86f0..0000000
--- a/ash/resources/vector_icons/network_badge_technology_gprs.1x.icon
+++ /dev/null
@@ -1,18 +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.
-
-CANVAS_DIMENSIONS, 5,
-MOVE_TO, 4, 0,
-H_LINE_TO, 0,
-R_V_LINE_TO, 5,
-R_H_LINE_TO, 4,
-V_LINE_TO, 2,
-H_LINE_TO, 2,
-R_V_LINE_TO, 1,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-H_LINE_TO, 1,
-V_LINE_TO, 1,
-R_H_LINE_TO, 3,
-CLOSE
diff --git a/ash/resources/vector_icons/network_badge_technology_gprs.icon b/ash/resources/vector_icons/network_badge_technology_gprs.icon
index 5067630..29ba4ea8 100644
--- a/ash/resources/vector_icons/network_badge_technology_gprs.icon
+++ b/ash/resources/vector_icons/network_badge_technology_gprs.icon
@@ -16,3 +16,18 @@
 V_LINE_TO, 2,
 R_H_LINE_TO, 6,
 CLOSE
+
+CANVAS_DIMENSIONS, 5,
+MOVE_TO, 4, 0,
+H_LINE_TO, 0,
+R_V_LINE_TO, 5,
+R_H_LINE_TO, 4,
+V_LINE_TO, 2,
+H_LINE_TO, 2,
+R_V_LINE_TO, 1,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+H_LINE_TO, 1,
+V_LINE_TO, 1,
+R_H_LINE_TO, 3,
+CLOSE
diff --git a/ash/resources/vector_icons/network_badge_technology_hspa.1x.icon b/ash/resources/vector_icons/network_badge_technology_hspa.1x.icon
deleted file mode 100644
index fcc4378..0000000
--- a/ash/resources/vector_icons/network_badge_technology_hspa.1x.icon
+++ /dev/null
@@ -1,18 +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.
-
-CANVAS_DIMENSIONS, 5,
-MOVE_TO, 0, 0,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 2,
-R_H_LINE_TO, 2,
-V_LINE_TO, 0,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 5,
-H_LINE_TO, 3,
-V_LINE_TO, 3,
-H_LINE_TO, 1,
-R_V_LINE_TO, 2,
-H_LINE_TO, 0,
-CLOSE
diff --git a/ash/resources/vector_icons/network_badge_technology_hspa.icon b/ash/resources/vector_icons/network_badge_technology_hspa.icon
index e739db6..7bedb290 100644
--- a/ash/resources/vector_icons/network_badge_technology_hspa.icon
+++ b/ash/resources/vector_icons/network_badge_technology_hspa.icon
@@ -16,3 +16,18 @@
 R_V_LINE_TO, 4,
 H_LINE_TO, 0,
 CLOSE
+
+CANVAS_DIMENSIONS, 5,
+MOVE_TO, 0, 0,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 2,
+R_H_LINE_TO, 2,
+V_LINE_TO, 0,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 5,
+H_LINE_TO, 3,
+V_LINE_TO, 3,
+H_LINE_TO, 1,
+R_V_LINE_TO, 2,
+H_LINE_TO, 0,
+CLOSE
diff --git a/ash/resources/vector_icons/network_badge_technology_hspa_plus.1x.icon b/ash/resources/vector_icons/network_badge_technology_hspa_plus.1x.icon
deleted file mode 100644
index 531bd6c..0000000
--- a/ash/resources/vector_icons/network_badge_technology_hspa_plus.1x.icon
+++ /dev/null
@@ -1,31 +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.
-
-CANVAS_DIMENSIONS, 9,
-MOVE_TO, 0, 0,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 2,
-R_H_LINE_TO, 2,
-V_LINE_TO, 0,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 5,
-H_LINE_TO, 3,
-V_LINE_TO, 3,
-H_LINE_TO, 1,
-R_V_LINE_TO, 2,
-H_LINE_TO, 0,
-MOVE_TO, 7, 1,
-V_LINE_TO, 0,
-H_LINE_TO, 6,
-R_V_LINE_TO, 1,
-H_LINE_TO, 5,
-R_V_LINE_TO, 1,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-R_H_LINE_TO, 1,
-V_LINE_TO, 2,
-R_H_LINE_TO, 1,
-V_LINE_TO, 1,
-H_LINE_TO, 7,
-CLOSE
diff --git a/ash/resources/vector_icons/network_badge_technology_hspa_plus.icon b/ash/resources/vector_icons/network_badge_technology_hspa_plus.icon
index 3b02ec6..7e66d873 100644
--- a/ash/resources/vector_icons/network_badge_technology_hspa_plus.icon
+++ b/ash/resources/vector_icons/network_badge_technology_hspa_plus.icon
@@ -28,3 +28,31 @@
 R_V_LINE_TO, 4,
 H_LINE_TO, 0,
 CLOSE
+
+CANVAS_DIMENSIONS, 9,
+MOVE_TO, 0, 0,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 2,
+R_H_LINE_TO, 2,
+V_LINE_TO, 0,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 5,
+H_LINE_TO, 3,
+V_LINE_TO, 3,
+H_LINE_TO, 1,
+R_V_LINE_TO, 2,
+H_LINE_TO, 0,
+MOVE_TO, 7, 1,
+V_LINE_TO, 0,
+H_LINE_TO, 6,
+R_V_LINE_TO, 1,
+H_LINE_TO, 5,
+R_V_LINE_TO, 1,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+R_H_LINE_TO, 1,
+V_LINE_TO, 2,
+R_H_LINE_TO, 1,
+V_LINE_TO, 1,
+H_LINE_TO, 7,
+CLOSE
diff --git a/ash/resources/vector_icons/network_badge_technology_lte.1x.icon b/ash/resources/vector_icons/network_badge_technology_lte.1x.icon
deleted file mode 100644
index a29b7d2..0000000
--- a/ash/resources/vector_icons/network_badge_technology_lte.1x.icon
+++ /dev/null
@@ -1,32 +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.
-
-CANVAS_DIMENSIONS, 12,
-MOVE_TO, 0, 0,
-R_V_LINE_TO, 5,
-R_H_LINE_TO, 3,
-V_LINE_TO, 4,
-H_LINE_TO, 1,
-V_LINE_TO, 0,
-MOVE_TO, 3, 0,
-R_H_LINE_TO, 5,
-R_V_LINE_TO, 1,
-H_LINE_TO, 6,
-R_V_LINE_TO, 4,
-H_LINE_TO, 5,
-V_LINE_TO, 1,
-H_LINE_TO, 3,
-MOVE_TO, 9, 0,
-R_V_LINE_TO, 5,
-R_H_LINE_TO, 3,
-V_LINE_TO, 4,
-R_H_LINE_TO, -2,
-V_LINE_TO, 3,
-R_H_LINE_TO, 1,
-V_LINE_TO, 2,
-R_H_LINE_TO, -1,
-V_LINE_TO, 1,
-R_H_LINE_TO, 2,
-V_LINE_TO, 0,
-CLOSE
diff --git a/ash/resources/vector_icons/network_badge_technology_lte.icon b/ash/resources/vector_icons/network_badge_technology_lte.icon
index ef5d14f..eefefe74e 100644
--- a/ash/resources/vector_icons/network_badge_technology_lte.icon
+++ b/ash/resources/vector_icons/network_badge_technology_lte.icon
@@ -30,3 +30,32 @@
 R_H_LINE_TO, 4,
 V_LINE_TO, 0,
 CLOSE
+
+CANVAS_DIMENSIONS, 12,
+MOVE_TO, 0, 0,
+R_V_LINE_TO, 5,
+R_H_LINE_TO, 3,
+V_LINE_TO, 4,
+H_LINE_TO, 1,
+V_LINE_TO, 0,
+MOVE_TO, 3, 0,
+R_H_LINE_TO, 5,
+R_V_LINE_TO, 1,
+H_LINE_TO, 6,
+R_V_LINE_TO, 4,
+H_LINE_TO, 5,
+V_LINE_TO, 1,
+H_LINE_TO, 3,
+MOVE_TO, 9, 0,
+R_V_LINE_TO, 5,
+R_H_LINE_TO, 3,
+V_LINE_TO, 4,
+R_H_LINE_TO, -2,
+V_LINE_TO, 3,
+R_H_LINE_TO, 1,
+V_LINE_TO, 2,
+R_H_LINE_TO, -1,
+V_LINE_TO, 1,
+R_H_LINE_TO, 2,
+V_LINE_TO, 0,
+CLOSE
diff --git a/ash/resources/vector_icons/network_badge_technology_lte_advanced.1x.icon b/ash/resources/vector_icons/network_badge_technology_lte_advanced.1x.icon
deleted file mode 100644
index d4df8a6..0000000
--- a/ash/resources/vector_icons/network_badge_technology_lte_advanced.1x.icon
+++ /dev/null
@@ -1,45 +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.
-
-CANVAS_DIMENSIONS, 17,
-MOVE_TO, 0, 0,
-R_V_LINE_TO, 5,
-R_H_LINE_TO, 3,
-V_LINE_TO, 4,
-H_LINE_TO, 1,
-V_LINE_TO, 0,
-MOVE_TO, 3, 0,
-R_H_LINE_TO, 5,
-R_V_LINE_TO, 1,
-H_LINE_TO, 6,
-R_V_LINE_TO, 4,
-H_LINE_TO, 5,
-V_LINE_TO, 1,
-H_LINE_TO, 3,
-MOVE_TO, 9, 0,
-R_V_LINE_TO, 5,
-R_H_LINE_TO, 3,
-V_LINE_TO, 4,
-R_H_LINE_TO, -2,
-V_LINE_TO, 3,
-R_H_LINE_TO, 1,
-V_LINE_TO, 2,
-R_H_LINE_TO, -1,
-V_LINE_TO, 1,
-R_H_LINE_TO, 2,
-V_LINE_TO, 0,
-MOVE_TO, 15, 1,
-V_LINE_TO, 0,
-R_H_LINE_TO, -1,
-R_V_LINE_TO, 1,
-R_H_LINE_TO, -1,
-R_V_LINE_TO, 1,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-R_H_LINE_TO, 1,
-V_LINE_TO, 2,
-R_H_LINE_TO, 1,
-V_LINE_TO, 1,
-R_H_LINE_TO, -1,
-CLOSE
diff --git a/ash/resources/vector_icons/network_badge_technology_lte_advanced.icon b/ash/resources/vector_icons/network_badge_technology_lte_advanced.icon
index 88e954a..720d622 100644
--- a/ash/resources/vector_icons/network_badge_technology_lte_advanced.icon
+++ b/ash/resources/vector_icons/network_badge_technology_lte_advanced.icon
@@ -42,3 +42,45 @@
 R_H_LINE_TO, -3,
 V_LINE_TO, 0,
 CLOSE
+
+CANVAS_DIMENSIONS, 17,
+MOVE_TO, 0, 0,
+R_V_LINE_TO, 5,
+R_H_LINE_TO, 3,
+V_LINE_TO, 4,
+H_LINE_TO, 1,
+V_LINE_TO, 0,
+MOVE_TO, 3, 0,
+R_H_LINE_TO, 5,
+R_V_LINE_TO, 1,
+H_LINE_TO, 6,
+R_V_LINE_TO, 4,
+H_LINE_TO, 5,
+V_LINE_TO, 1,
+H_LINE_TO, 3,
+MOVE_TO, 9, 0,
+R_V_LINE_TO, 5,
+R_H_LINE_TO, 3,
+V_LINE_TO, 4,
+R_H_LINE_TO, -2,
+V_LINE_TO, 3,
+R_H_LINE_TO, 1,
+V_LINE_TO, 2,
+R_H_LINE_TO, -1,
+V_LINE_TO, 1,
+R_H_LINE_TO, 2,
+V_LINE_TO, 0,
+MOVE_TO, 15, 1,
+V_LINE_TO, 0,
+R_H_LINE_TO, -1,
+R_V_LINE_TO, 1,
+R_H_LINE_TO, -1,
+R_V_LINE_TO, 1,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+R_H_LINE_TO, 1,
+V_LINE_TO, 2,
+R_H_LINE_TO, 1,
+V_LINE_TO, 1,
+R_H_LINE_TO, -1,
+CLOSE
diff --git a/ash/resources/vector_icons/network_badge_vpn.1x.icon b/ash/resources/vector_icons/network_badge_vpn.1x.icon
deleted file mode 100644
index c324612..0000000
--- a/ash/resources/vector_icons/network_badge_vpn.1x.icon
+++ /dev/null
@@ -1,25 +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.
-
-CANVAS_DIMENSIONS, 8,
-MOVE_TO, 5, 4,
-H_LINE_TO, 4,
-R_V_LINE_TO, 1,
-H_LINE_TO, 1,
-V_LINE_TO, 2,
-R_H_LINE_TO, 3,
-R_V_LINE_TO, 1,
-R_H_LINE_TO, 3,
-R_V_LINE_TO, 1,
-H_LINE_TO, 6,
-R_V_LINE_TO, 1,
-H_LINE_TO, 5,
-V_LINE_TO, 4,
-CLOSE,
-MOVE_TO, 2, 3,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-H_LINE_TO, 2,
-V_LINE_TO, 3,
-CLOSE
diff --git a/ash/resources/vector_icons/network_badge_vpn.icon b/ash/resources/vector_icons/network_badge_vpn.icon
index 7d67067e..edc9fcec 100644
--- a/ash/resources/vector_icons/network_badge_vpn.icon
+++ b/ash/resources/vector_icons/network_badge_vpn.icon
@@ -23,3 +23,25 @@
 H_LINE_TO, 4,
 V_LINE_TO, 7,
 CLOSE
+
+CANVAS_DIMENSIONS, 8,
+MOVE_TO, 5, 4,
+H_LINE_TO, 4,
+R_V_LINE_TO, 1,
+H_LINE_TO, 1,
+V_LINE_TO, 2,
+R_H_LINE_TO, 3,
+R_V_LINE_TO, 1,
+R_H_LINE_TO, 3,
+R_V_LINE_TO, 1,
+H_LINE_TO, 6,
+R_V_LINE_TO, 1,
+H_LINE_TO, 5,
+V_LINE_TO, 4,
+CLOSE,
+MOVE_TO, 2, 3,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+H_LINE_TO, 2,
+V_LINE_TO, 3,
+CLOSE
diff --git a/ash/resources/vector_icons/network_ethernet.1x.icon b/ash/resources/vector_icons/network_ethernet.1x.icon
deleted file mode 100644
index 06e490e..0000000
--- a/ash/resources/vector_icons/network_ethernet.1x.icon
+++ /dev/null
@@ -1,39 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 6.02f, 6,
-LINE_TO, 2, 10.5f,
-LINE_TO, 6.02f, 15,
-LINE_TO, 7, 14.23f,
-LINE_TO, 3.66f, 10.5f,
-LINE_TO, 7, 6.77f,
-LINE_TO, 6.02f, 6,
-CLOSE,
-MOVE_TO, 7, 11,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, -1,
-H_LINE_TO, 7,
-R_V_LINE_TO, 1,
-CLOSE,
-R_MOVE_TO, 5, -1,
-R_H_LINE_TO, -1,
-R_V_LINE_TO, 1,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, -1,
-CLOSE,
-R_MOVE_TO, -3, 1,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, -1,
-H_LINE_TO, 9,
-R_V_LINE_TO, 1,
-CLOSE,
-R_MOVE_TO, 3, -4.23f,
-R_LINE_TO, 3.34f, 3.73f,
-LINE_TO, 12, 14.23f,
-R_LINE_TO, 0.99f, 0.77f,
-LINE_TO, 17, 10.5f,
-LINE_TO, 12.99f, 6,
-LINE_TO, 12, 6.77f,
-CLOSE
diff --git a/ash/resources/vector_icons/network_ethernet.icon b/ash/resources/vector_icons/network_ethernet.icon
index 2d03672..046b957 100644
--- a/ash/resources/vector_icons/network_ethernet.icon
+++ b/ash/resources/vector_icons/network_ethernet.icon
@@ -37,3 +37,39 @@
 R_LINE_TO, -7.23f, -8,
 LINE_TO, 25, 13.37f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 6.02f, 6,
+LINE_TO, 2, 10.5f,
+LINE_TO, 6.02f, 15,
+LINE_TO, 7, 14.23f,
+LINE_TO, 3.66f, 10.5f,
+LINE_TO, 7, 6.77f,
+LINE_TO, 6.02f, 6,
+CLOSE,
+MOVE_TO, 7, 11,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, -1,
+H_LINE_TO, 7,
+R_V_LINE_TO, 1,
+CLOSE,
+R_MOVE_TO, 5, -1,
+R_H_LINE_TO, -1,
+R_V_LINE_TO, 1,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, -1,
+CLOSE,
+R_MOVE_TO, -3, 1,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, -1,
+H_LINE_TO, 9,
+R_V_LINE_TO, 1,
+CLOSE,
+R_MOVE_TO, 3, -4.23f,
+R_LINE_TO, 3.34f, 3.73f,
+LINE_TO, 12, 14.23f,
+R_LINE_TO, 0.99f, 0.77f,
+LINE_TO, 17, 10.5f,
+LINE_TO, 12.99f, 6,
+LINE_TO, 12, 6.77f,
+CLOSE
diff --git a/ash/resources/vector_icons/network_mobile_not_connected_x.1x.icon b/ash/resources/vector_icons/network_mobile_not_connected_x.1x.icon
deleted file mode 100644
index ed4b5087..0000000
--- a/ash/resources/vector_icons/network_mobile_not_connected_x.1x.icon
+++ /dev/null
@@ -1,18 +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.
-
-CANVAS_DIMENSIONS, 24,
-MOVE_TO, 9.5f, 3.21f,
-LINE_TO, 8.8f, 2.5f,
-LINE_TO, 6, 5.3f,
-LINE_TO, 3.21f, 2.5f,
-R_LINE_TO, -0.7f, 0.71f,
-LINE_TO, 5.3f, 6,
-LINE_TO, 2.5f, 8.8f,
-R_LINE_TO, 0.71f, 0.71f,
-LINE_TO, 6, 6.71f,
-LINE_TO, 8.8f, 9.5f,
-R_LINE_TO, 0.71f, -0.7f,
-LINE_TO, 6.71f, 6,
-CLOSE
diff --git a/ash/resources/vector_icons/network_mobile_not_connected_x.icon b/ash/resources/vector_icons/network_mobile_not_connected_x.icon
index 01e70a8..22e76bdb 100644
--- a/ash/resources/vector_icons/network_mobile_not_connected_x.icon
+++ b/ash/resources/vector_icons/network_mobile_not_connected_x.icon
@@ -16,3 +16,18 @@
 R_LINE_TO, 1.45f, -1.45f,
 LINE_TO, 13.45f, 12,
 CLOSE
+
+CANVAS_DIMENSIONS, 24,
+MOVE_TO, 9.5f, 3.21f,
+LINE_TO, 8.8f, 2.5f,
+LINE_TO, 6, 5.3f,
+LINE_TO, 3.21f, 2.5f,
+R_LINE_TO, -0.7f, 0.71f,
+LINE_TO, 5.3f, 6,
+LINE_TO, 2.5f, 8.8f,
+R_LINE_TO, 0.71f, 0.71f,
+LINE_TO, 6, 6.71f,
+LINE_TO, 8.8f, 9.5f,
+R_LINE_TO, 0.71f, -0.7f,
+LINE_TO, 6.71f, 6,
+CLOSE
diff --git a/ash/resources/vector_icons/network_vpn.1x.icon b/ash/resources/vector_icons/network_vpn.1x.icon
deleted file mode 100644
index 4bb19e3..0000000
--- a/ash/resources/vector_icons/network_vpn.1x.icon
+++ /dev/null
@@ -1,24 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 6.36f, 5,
-CUBIC_TO, 3.96f, 5, 2, 7.02f, 2, 9.5f,
-CUBIC_TO, 2, 11.98f, 3.96f, 14, 6.36f, 14,
-R_CUBIC_TO, 1.9f, 0, 3.51f, -1.25f, 4.11f, -3,
-H_LINE_TO, 13.5f,
-R_V_LINE_TO, 3,
-R_H_LINE_TO, 3,
-R_V_LINE_TO, -3,
-H_LINE_TO, 18,
-V_LINE_TO, 8,
-R_H_LINE_TO, -7.53f,
-R_CUBIC_TO, -0.6f, -1.75f, -2.21f, -3, -4.11f, -3,
-CLOSE,
-R_MOVE_TO, 0, 6,
-R_CUBIC_TO, -0.8f, 0, -1.45f, -0.67f, -1.45f, -1.5f,
-CUBIC_TO_SHORTHAND, 5.56f, 8, 6.36f, 8,
-R_CUBIC_TO, 0.8f, 0, 1.45f, 0.68f, 1.45f, 1.5f,
-CUBIC_TO_SHORTHAND, 7.16f, 11, 6.36f, 11,
-CLOSE
diff --git a/ash/resources/vector_icons/network_vpn.icon b/ash/resources/vector_icons/network_vpn.icon
index bf71962..cc8d51e 100644
--- a/ash/resources/vector_icons/network_vpn.icon
+++ b/ash/resources/vector_icons/network_vpn.icon
@@ -22,3 +22,24 @@
 R_CUBIC_TO, 1.6f, 0, 2.91f, 1.35f, 2.91f, 3,
 R_CUBIC_TO, 0, 1.65f, -1.31f, 3, -2.91f, 3,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 6.36f, 5,
+CUBIC_TO, 3.96f, 5, 2, 7.02f, 2, 9.5f,
+CUBIC_TO, 2, 11.98f, 3.96f, 14, 6.36f, 14,
+R_CUBIC_TO, 1.9f, 0, 3.51f, -1.25f, 4.11f, -3,
+H_LINE_TO, 13.5f,
+R_V_LINE_TO, 3,
+R_H_LINE_TO, 3,
+R_V_LINE_TO, -3,
+H_LINE_TO, 18,
+V_LINE_TO, 8,
+R_H_LINE_TO, -7.53f,
+R_CUBIC_TO, -0.6f, -1.75f, -2.21f, -3, -4.11f, -3,
+CLOSE,
+R_MOVE_TO, 0, 6,
+R_CUBIC_TO, -0.8f, 0, -1.45f, -0.67f, -1.45f, -1.5f,
+CUBIC_TO_SHORTHAND, 5.56f, 8, 6.36f, 8,
+R_CUBIC_TO, 0.8f, 0, 1.45f, 0.68f, 1.45f, 1.5f,
+CUBIC_TO_SHORTHAND, 7.16f, 11, 6.36f, 11,
+CLOSE
diff --git a/ash/resources/vector_icons/palette_action_capture_region.1x.icon b/ash/resources/vector_icons/palette_action_capture_region.1x.icon
deleted file mode 100644
index 38166de..0000000
--- a/ash/resources/vector_icons/palette_action_capture_region.1x.icon
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 5.03f, 2.04f,
-H_LINE_TO, 3.04f,
-R_LINE_TO, -0.02f, 1.95f,
-H_LINE_TO, 1.02f,
-R_V_LINE_TO, 2,
-R_H_LINE_TO, 2.02f,
-R_LINE_TO, -0.01f, 1.99f,
-R_H_LINE_TO, 2,
-R_LINE_TO, -0.01f, -1.99f,
-R_H_LINE_TO, 1.97f,
-V_LINE_TO, 4.05f,
-R_LINE_TO, -1.96f, -0.07f,
-V_LINE_TO, 2.04f,
-CLOSE,
-MOVE_TO, 16, 8,
-R_H_LINE_TO, 2,
-V_LINE_TO, 6,
-R_H_LINE_TO, -2,
-R_V_LINE_TO, 2,
-CLOSE,
-R_MOVE_TO, 2, -3,
-R_H_LINE_TO, -2,
-V_LINE_TO, 3,
-R_CUBIC_TO, 1.1f, 0, 2, 0.96f, 2, 2,
-CLOSE,
-R_MOVE_TO, -6, 0,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, -2,
-R_H_LINE_TO, -2,
-R_V_LINE_TO, 2,
-CLOSE,
-MOVE_TO, 16, 11,
-R_H_LINE_TO, 2,
-V_LINE_TO, 9,
-R_H_LINE_TO, -2,
-R_V_LINE_TO, 2,
-CLOSE,
-MOVE_TO, 6, 18,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, -2,
-H_LINE_TO, 6,
-R_V_LINE_TO, 2,
-CLOSE,
-R_MOVE_TO, -3.97f, -4,
-H_LINE_TO, 4,
-R_V_LINE_TO, -1.97f,
-H_LINE_TO, 2.03f,
-V_LINE_TO, 14,
-CLOSE,
-MOVE_TO, 9, 5,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, -2,
-H_LINE_TO, 9,
-R_V_LINE_TO, 2,
-CLOSE,
-MOVE_TO, 9, 18,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, -2,
-H_LINE_TO, 9,
-R_V_LINE_TO, 2,
-CLOSE,
-R_MOVE_TO, -7, -7,
-R_H_LINE_TO, 2,
-V_LINE_TO, 9,
-H_LINE_TO, 2,
-R_V_LINE_TO, 2,
-CLOSE,
-R_MOVE_TO, 2, 7,
-R_CUBIC_TO, -1.1f, 0, -2, -1.04f, -2, -2,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, 2,
-CLOSE,
-R_MOVE_TO, 9, 0,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, -2,
-R_H_LINE_TO, -2,
-R_V_LINE_TO, 2,
-CLOSE,
-R_MOVE_TO, 4.97f, -3,
-R_V_LINE_TO, -1.97f,
-H_LINE_TO, 16,
-V_LINE_TO, 15,
-R_H_LINE_TO, 1.97f,
-CLOSE,
-MOVE_TO, 16, 18,
-R_CUBIC_TO, 1.1f, 0, 2, -0.9f, 2, -2,
-R_H_LINE_TO, -2,
-R_V_LINE_TO, 2,
-CLOSE
diff --git a/ash/resources/vector_icons/palette_action_capture_region.icon b/ash/resources/vector_icons/palette_action_capture_region.icon
index ec36ff1c..5ba19543 100644
--- a/ash/resources/vector_icons/palette_action_capture_region.icon
+++ b/ash/resources/vector_icons/palette_action_capture_region.icon
@@ -92,3 +92,94 @@
 R_H_LINE_TO, -3,
 R_V_LINE_TO, 3,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 5.03f, 2.04f,
+H_LINE_TO, 3.04f,
+R_LINE_TO, -0.02f, 1.95f,
+H_LINE_TO, 1.02f,
+R_V_LINE_TO, 2,
+R_H_LINE_TO, 2.02f,
+R_LINE_TO, -0.01f, 1.99f,
+R_H_LINE_TO, 2,
+R_LINE_TO, -0.01f, -1.99f,
+R_H_LINE_TO, 1.97f,
+V_LINE_TO, 4.05f,
+R_LINE_TO, -1.96f, -0.07f,
+V_LINE_TO, 2.04f,
+CLOSE,
+MOVE_TO, 16, 8,
+R_H_LINE_TO, 2,
+V_LINE_TO, 6,
+R_H_LINE_TO, -2,
+R_V_LINE_TO, 2,
+CLOSE,
+R_MOVE_TO, 2, -3,
+R_H_LINE_TO, -2,
+V_LINE_TO, 3,
+R_CUBIC_TO, 1.1f, 0, 2, 0.96f, 2, 2,
+CLOSE,
+R_MOVE_TO, -6, 0,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, -2,
+R_H_LINE_TO, -2,
+R_V_LINE_TO, 2,
+CLOSE,
+MOVE_TO, 16, 11,
+R_H_LINE_TO, 2,
+V_LINE_TO, 9,
+R_H_LINE_TO, -2,
+R_V_LINE_TO, 2,
+CLOSE,
+MOVE_TO, 6, 18,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, -2,
+H_LINE_TO, 6,
+R_V_LINE_TO, 2,
+CLOSE,
+R_MOVE_TO, -3.97f, -4,
+H_LINE_TO, 4,
+R_V_LINE_TO, -1.97f,
+H_LINE_TO, 2.03f,
+V_LINE_TO, 14,
+CLOSE,
+MOVE_TO, 9, 5,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, -2,
+H_LINE_TO, 9,
+R_V_LINE_TO, 2,
+CLOSE,
+MOVE_TO, 9, 18,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, -2,
+H_LINE_TO, 9,
+R_V_LINE_TO, 2,
+CLOSE,
+R_MOVE_TO, -7, -7,
+R_H_LINE_TO, 2,
+V_LINE_TO, 9,
+H_LINE_TO, 2,
+R_V_LINE_TO, 2,
+CLOSE,
+R_MOVE_TO, 2, 7,
+R_CUBIC_TO, -1.1f, 0, -2, -1.04f, -2, -2,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 2,
+CLOSE,
+R_MOVE_TO, 9, 0,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, -2,
+R_H_LINE_TO, -2,
+R_V_LINE_TO, 2,
+CLOSE,
+R_MOVE_TO, 4.97f, -3,
+R_V_LINE_TO, -1.97f,
+H_LINE_TO, 16,
+V_LINE_TO, 15,
+R_H_LINE_TO, 1.97f,
+CLOSE,
+MOVE_TO, 16, 18,
+R_CUBIC_TO, 1.1f, 0, 2, -0.9f, 2, -2,
+R_H_LINE_TO, -2,
+R_V_LINE_TO, 2,
+CLOSE
diff --git a/ash/resources/vector_icons/palette_action_capture_screen.1x.icon b/ash/resources/vector_icons/palette_action_capture_screen.1x.icon
deleted file mode 100644
index e31838c..0000000
--- a/ash/resources/vector_icons/palette_action_capture_screen.1x.icon
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 16, 8,
-R_H_LINE_TO, 2,
-V_LINE_TO, 6,
-R_H_LINE_TO, -2,
-V_LINE_TO, 8,
-CLOSE,
-R_MOVE_TO, 2, -4,
-R_H_LINE_TO, -2,
-V_LINE_TO, 2,
-R_CUBIC_TO, 1.1f, 0, 2, 0.96f, 2, 2,
-CLOSE,
-R_MOVE_TO, -6, 0,
-R_H_LINE_TO, 2,
-V_LINE_TO, 2,
-R_H_LINE_TO, -2,
-R_V_LINE_TO, 2,
-CLOSE,
-R_MOVE_TO, 4, 7,
-R_H_LINE_TO, 2,
-V_LINE_TO, 9,
-R_H_LINE_TO, -2,
-V_LINE_TO, 11,
-CLOSE,
-R_MOVE_TO, -10, 7,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, -2,
-H_LINE_TO, 6,
-V_LINE_TO, 18,
-CLOSE,
-MOVE_TO, 2, 14,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, -2,
-H_LINE_TO, 2,
-R_V_LINE_TO, 2,
-CLOSE,
-MOVE_TO, 9, 4,
-R_H_LINE_TO, 2,
-V_LINE_TO, 2,
-H_LINE_TO, 9,
-V_LINE_TO, 4,
-CLOSE,
-R_MOVE_TO, 0, 14,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, -2,
-H_LINE_TO, 9,
-V_LINE_TO, 18,
-CLOSE,
-MOVE_TO, 2, 11,
-R_H_LINE_TO, 2,
-V_LINE_TO, 9,
-H_LINE_TO, 2,
-V_LINE_TO, 11,
-CLOSE,
-R_MOVE_TO, 2, 7,
-CUBIC_TO, 2.9f, 18, 2, 16.96f, 2, 16,
-R_H_LINE_TO, 2,
-V_LINE_TO, 18,
-CLOSE,
-MOVE_TO, 4.56f, 3.01f,
-R_H_LINE_TO, 2.38f,
-LINE_TO, 7, 2,
-H_LINE_TO, 2,
-R_V_LINE_TO, 5,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, -2.5f,
-R_LINE_TO, 2.5f, 2.5f,
-R_LINE_TO, 1.5f, -1.5f,
-MOVE_TO, 15.6f, 17.01f,
-LINE_TO, 13, 17,
-R_V_LINE_TO, 1,
-R_H_LINE_TO, 5,
-R_V_LINE_TO, -5,
-R_H_LINE_TO, -0.97f,
-LINE_TO, 17, 15.5f,
-LINE_TO, 14.5f, 13,
-LINE_TO, 13, 14.5f,
-CLOSE
diff --git a/ash/resources/vector_icons/palette_action_capture_screen.icon b/ash/resources/vector_icons/palette_action_capture_screen.icon
index 58384359..f62ccbe 100644
--- a/ash/resources/vector_icons/palette_action_capture_screen.icon
+++ b/ash/resources/vector_icons/palette_action_capture_screen.icon
@@ -80,3 +80,82 @@
 R_LINE_TO, -4.5f, -4.1f,
 R_LINE_TO, -2.38f, 2.29f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 16, 8,
+R_H_LINE_TO, 2,
+V_LINE_TO, 6,
+R_H_LINE_TO, -2,
+V_LINE_TO, 8,
+CLOSE,
+R_MOVE_TO, 2, -4,
+R_H_LINE_TO, -2,
+V_LINE_TO, 2,
+R_CUBIC_TO, 1.1f, 0, 2, 0.96f, 2, 2,
+CLOSE,
+R_MOVE_TO, -6, 0,
+R_H_LINE_TO, 2,
+V_LINE_TO, 2,
+R_H_LINE_TO, -2,
+R_V_LINE_TO, 2,
+CLOSE,
+R_MOVE_TO, 4, 7,
+R_H_LINE_TO, 2,
+V_LINE_TO, 9,
+R_H_LINE_TO, -2,
+V_LINE_TO, 11,
+CLOSE,
+R_MOVE_TO, -10, 7,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, -2,
+H_LINE_TO, 6,
+V_LINE_TO, 18,
+CLOSE,
+MOVE_TO, 2, 14,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, -2,
+H_LINE_TO, 2,
+R_V_LINE_TO, 2,
+CLOSE,
+MOVE_TO, 9, 4,
+R_H_LINE_TO, 2,
+V_LINE_TO, 2,
+H_LINE_TO, 9,
+V_LINE_TO, 4,
+CLOSE,
+R_MOVE_TO, 0, 14,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, -2,
+H_LINE_TO, 9,
+V_LINE_TO, 18,
+CLOSE,
+MOVE_TO, 2, 11,
+R_H_LINE_TO, 2,
+V_LINE_TO, 9,
+H_LINE_TO, 2,
+V_LINE_TO, 11,
+CLOSE,
+R_MOVE_TO, 2, 7,
+CUBIC_TO, 2.9f, 18, 2, 16.96f, 2, 16,
+R_H_LINE_TO, 2,
+V_LINE_TO, 18,
+CLOSE,
+MOVE_TO, 4.56f, 3.01f,
+R_H_LINE_TO, 2.38f,
+LINE_TO, 7, 2,
+H_LINE_TO, 2,
+R_V_LINE_TO, 5,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, -2.5f,
+R_LINE_TO, 2.5f, 2.5f,
+R_LINE_TO, 1.5f, -1.5f,
+MOVE_TO, 15.6f, 17.01f,
+LINE_TO, 13, 17,
+R_V_LINE_TO, 1,
+R_H_LINE_TO, 5,
+R_V_LINE_TO, -5,
+R_H_LINE_TO, -0.97f,
+LINE_TO, 17, 15.5f,
+LINE_TO, 14.5f, 13,
+LINE_TO, 13, 14.5f,
+CLOSE
diff --git a/ash/resources/vector_icons/palette_action_create_note.1x.icon b/ash/resources/vector_icons/palette_action_create_note.1x.icon
deleted file mode 100644
index 5130810..0000000
--- a/ash/resources/vector_icons/palette_action_create_note.1x.icon
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 10, 8,
-V_LINE_TO, 3.02f,
-LINE_TO, 14.97f, 8,
-H_LINE_TO, 10,
-CLOSE,
-R_MOVE_TO, 1.5f, -6,
-R_H_LINE_TO, -6,
-R_CUBIC_TO, -0.82f, 0, -1.49f, 0.68f, -1.49f, 1.5f,
-LINE_TO, 4, 15.5f,
-R_CUBIC_TO, 0, 0.83f, 0.67f, 1.5f, 1.49f, 1.5f,
-H_LINE_TO, 14.5f,
-R_CUBIC_TO, 0.83f, 0, 1.5f, -0.67f, 1.5f, -1.5f,
-R_V_LINE_TO, -9,
-LINE_TO, 11.5f, 2,
-CLOSE,
-MOVE_TO, 13, 13.03f,
-R_H_LINE_TO, -1.98f,
-LINE_TO, 11, 15,
-H_LINE_TO, 9,
-R_V_LINE_TO, -1.97f,
-H_LINE_TO, 7,
-R_V_LINE_TO, -2.02f,
-LINE_TO, 9, 11,
-V_LINE_TO, 9,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, 2,
-R_LINE_TO, 2, 0.02f,
-R_V_LINE_TO, 2.02f,
-CLOSE
diff --git a/ash/resources/vector_icons/palette_action_create_note.icon b/ash/resources/vector_icons/palette_action_create_note.icon
index 7fff6de..d82fda8 100644
--- a/ash/resources/vector_icons/palette_action_create_note.icon
+++ b/ash/resources/vector_icons/palette_action_create_note.icon
@@ -32,3 +32,34 @@
 H_LINE_TO, 26,
 R_V_LINE_TO, 3,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 10, 8,
+V_LINE_TO, 3.02f,
+LINE_TO, 14.97f, 8,
+H_LINE_TO, 10,
+CLOSE,
+R_MOVE_TO, 1.5f, -6,
+R_H_LINE_TO, -6,
+R_CUBIC_TO, -0.82f, 0, -1.49f, 0.68f, -1.49f, 1.5f,
+LINE_TO, 4, 15.5f,
+R_CUBIC_TO, 0, 0.83f, 0.67f, 1.5f, 1.49f, 1.5f,
+H_LINE_TO, 14.5f,
+R_CUBIC_TO, 0.83f, 0, 1.5f, -0.67f, 1.5f, -1.5f,
+R_V_LINE_TO, -9,
+LINE_TO, 11.5f, 2,
+CLOSE,
+MOVE_TO, 13, 13.03f,
+R_H_LINE_TO, -1.98f,
+LINE_TO, 11, 15,
+H_LINE_TO, 9,
+R_V_LINE_TO, -1.97f,
+H_LINE_TO, 7,
+R_V_LINE_TO, -2.02f,
+LINE_TO, 9, 11,
+V_LINE_TO, 9,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 2,
+R_LINE_TO, 2, 0.02f,
+R_V_LINE_TO, 2.02f,
+CLOSE
diff --git a/ash/resources/vector_icons/palette_mode_laser_pointer.1x.icon b/ash/resources/vector_icons/palette_mode_laser_pointer.1x.icon
deleted file mode 100644
index da1e02f..0000000
--- a/ash/resources/vector_icons/palette_mode_laser_pointer.1x.icon
+++ /dev/null
@@ -1,42 +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.
-
-CANVAS_DIMENSIONS, 20,
-PATH_COLOR_ARGB, 0x4D, 0x00, 0x00, 0x00,
-MOVE_TO, 14.96f, 8.04f,
-R_H_LINE_TO, -4.56f,
-R_LINE_TO, 4.56f, -4.8f,
-R_CUBIC_TO, 0.3f, -0.23f, 0.5f, -0.59f, 0.5f, -0.99f,
-R_CUBIC_TO, 0, -0.68f, -0.55f, -1.24f, -1.22f, -1.24f,
-R_CUBIC_TO, -0.25f, 0, -0.48f, 0.08f, -0.68f, 0.21f,
-R_CUBIC_TO, 0, 0, -9.48f, 6.42f, -9.48f, 6.42f,
-R_LINE_TO, -0.36f, 0.24f,
-R_CUBIC_TO, -0.41f, 0.37f, -0.7f, 0.16f, -0.7f, 1.41f,
-R_CUBIC_TO, 0, 0.56f, 0.92f, 1.69f, 2, 1.69f,
-H_LINE_TO, 9.03f,
-R_LINE_TO, -1.18f, 0.69f,
-R_CUBIC_TO, -1.17f, 0.68f, -3.52f, 2.04f, -3.52f, 2.04f,
-R_CUBIC_TO, 0.42f, -0.25f, 0.9f, -0.41f, 1.42f, -0.41f,
-R_CUBIC_TO, 1.52f, 0, 2.75f, 1.25f, 2.75f, 2.79f,
-R_CUBIC_TO, 0, 0.76f, -0.3f, 1.45f, -0.79f, 1.96f,
-R_LINE_TO, 8.26f, -6.98f,
-R_CUBIC_TO, 0.16f, -0.1f, 0.3f, -0.22f, 0.43f, -0.36f,
-R_CUBIC_TO, 0.25f, -0.29f, 0.47f, -0.54f, 0.56f, -0.86f,
-R_CUBIC_TO, 0.03f, -0.1f, 0.04f, -0.2f, 0.04f, -0.32f,
-R_CUBIC_TO, 0, -1.31f, -0.96f, -1.48f, -2.04f, -1.48f,
-CLOSE,
-NEW_PATH,
-MOVE_TO, 9, 16,
-R_CUBIC_TO, 0, -1.66f, -1.34f, -3, -3, -3,
-R_CUBIC_TO, -0.57f, 0, -1.09f, 0.17f, -1.54f, 0.44f,
-R_LINE_TO, -0.18f, 0.11f,
-R_CUBIC_TO, -0.01f, 0.01f, -0.03f, 0.02f, -0.04f, 0.03f,
-CUBIC_TO, 3.49f, 14.13f, 3, 15.01f, 3, 16,
-R_CUBIC_TO, 0, 1.66f, 1.34f, 3, 3, 3,
-R_CUBIC_TO, 0.62f, 0, 1.19f, -0.19f, 1.67f, -0.51f,
-R_H_LINE_TO, 0,
-R_LINE_TO, 0.01f, -0.01f,
-R_CUBIC_TO, 0.16f, -0.11f, 0.32f, -0.24f, 0.45f, -0.38f,
-CUBIC_TO, 8.67f, 17.56f, 9, 16.82f, 9, 16,
-CLOSE
diff --git a/ash/resources/vector_icons/palette_mode_laser_pointer.icon b/ash/resources/vector_icons/palette_mode_laser_pointer.icon
index 7fbb1574..1cd6a519 100644
--- a/ash/resources/vector_icons/palette_mode_laser_pointer.icon
+++ b/ash/resources/vector_icons/palette_mode_laser_pointer.icon
@@ -39,3 +39,42 @@
 R_CUBIC_TO, 0.33f, -0.22f, 0.63f, -0.48f, 0.91f, -0.76f,
 CUBIC_TO, 17.34f, 35.69f, 18, 34.21f, 18, 32.57f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+PATH_COLOR_ARGB, 0x4D, 0x00, 0x00, 0x00,
+MOVE_TO, 14.96f, 8.04f,
+R_H_LINE_TO, -4.56f,
+R_LINE_TO, 4.56f, -4.8f,
+R_CUBIC_TO, 0.3f, -0.23f, 0.5f, -0.59f, 0.5f, -0.99f,
+R_CUBIC_TO, 0, -0.68f, -0.55f, -1.24f, -1.22f, -1.24f,
+R_CUBIC_TO, -0.25f, 0, -0.48f, 0.08f, -0.68f, 0.21f,
+R_CUBIC_TO, 0, 0, -9.48f, 6.42f, -9.48f, 6.42f,
+R_LINE_TO, -0.36f, 0.24f,
+R_CUBIC_TO, -0.41f, 0.37f, -0.7f, 0.16f, -0.7f, 1.41f,
+R_CUBIC_TO, 0, 0.56f, 0.92f, 1.69f, 2, 1.69f,
+H_LINE_TO, 9.03f,
+R_LINE_TO, -1.18f, 0.69f,
+R_CUBIC_TO, -1.17f, 0.68f, -3.52f, 2.04f, -3.52f, 2.04f,
+R_CUBIC_TO, 0.42f, -0.25f, 0.9f, -0.41f, 1.42f, -0.41f,
+R_CUBIC_TO, 1.52f, 0, 2.75f, 1.25f, 2.75f, 2.79f,
+R_CUBIC_TO, 0, 0.76f, -0.3f, 1.45f, -0.79f, 1.96f,
+R_LINE_TO, 8.26f, -6.98f,
+R_CUBIC_TO, 0.16f, -0.1f, 0.3f, -0.22f, 0.43f, -0.36f,
+R_CUBIC_TO, 0.25f, -0.29f, 0.47f, -0.54f, 0.56f, -0.86f,
+R_CUBIC_TO, 0.03f, -0.1f, 0.04f, -0.2f, 0.04f, -0.32f,
+R_CUBIC_TO, 0, -1.31f, -0.96f, -1.48f, -2.04f, -1.48f,
+CLOSE,
+NEW_PATH,
+MOVE_TO, 9, 16,
+R_CUBIC_TO, 0, -1.66f, -1.34f, -3, -3, -3,
+R_CUBIC_TO, -0.57f, 0, -1.09f, 0.17f, -1.54f, 0.44f,
+R_LINE_TO, -0.18f, 0.11f,
+R_CUBIC_TO, -0.01f, 0.01f, -0.03f, 0.02f, -0.04f, 0.03f,
+CUBIC_TO, 3.49f, 14.13f, 3, 15.01f, 3, 16,
+R_CUBIC_TO, 0, 1.66f, 1.34f, 3, 3, 3,
+R_CUBIC_TO, 0.62f, 0, 1.19f, -0.19f, 1.67f, -0.51f,
+R_H_LINE_TO, 0,
+R_LINE_TO, 0.01f, -0.01f,
+R_CUBIC_TO, 0.16f, -0.11f, 0.32f, -0.24f, 0.45f, -0.38f,
+CUBIC_TO, 8.67f, 17.56f, 9, 16.82f, 9, 16,
+CLOSE
diff --git a/ash/resources/vector_icons/palette_mode_magnify.1x.icon b/ash/resources/vector_icons/palette_mode_magnify.1x.icon
deleted file mode 100644
index d78a6bd..0000000
--- a/ash/resources/vector_icons/palette_mode_magnify.1x.icon
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 8, 10,
-H_LINE_TO, 5.5f,
-V_LINE_TO, 8,
-H_LINE_TO, 8,
-V_LINE_TO, 5.5f,
-R_H_LINE_TO, 2,
-V_LINE_TO, 8,
-R_H_LINE_TO, 2.5f,
-R_V_LINE_TO, 2,
-H_LINE_TO, 10,
-R_V_LINE_TO, 2.5f,
-H_LINE_TO, 8,
-V_LINE_TO, 10,
-CLOSE,
-R_MOVE_TO, 8.32f, 7.9f,
-R_LINE_TO, 1.65f, -1.8f,
-R_LINE_TO, -3.29f, -3.01f,
-R_CUBIC_TO, 0.83f, -1.15f, 1.32f, -2.56f, 1.32f, -4.09f,
-R_CUBIC_TO, 0, -3.86f, -3.14f, -7, -7, -7,
-CUBIC_TO, 5.14f, 2, 2, 5.14f, 2, 9,
-R_CUBIC_TO, 0, 3.86f, 3.14f, 7, 7, 7,
-R_CUBIC_TO, 1.45f, 0, 2.81f, -0.45f, 3.93f, -1.21f,
-R_LINE_TO, 3.39f, 3.11f,
-CLOSE,
-MOVE_TO, 9, 4,
-CUBIC_TO, 6.24f, 4, 4, 6.24f, 4, 9,
-R_CUBIC_TO, 0, 2.76f, 2.24f, 5, 5, 5,
-R_CUBIC_TO, 2.76f, 0, 5, -2.24f, 5, -5,
-R_CUBIC_TO, 0, -2.76f, -2.24f, -5, -5, -5,
-CLOSE
diff --git a/ash/resources/vector_icons/palette_mode_magnify.icon b/ash/resources/vector_icons/palette_mode_magnify.icon
index 9dc94580..cc7d6f9 100644
--- a/ash/resources/vector_icons/palette_mode_magnify.icon
+++ b/ash/resources/vector_icons/palette_mode_magnify.icon
@@ -33,3 +33,35 @@
 R_CUBIC_TO, 5.51f, 0, 10, -4.49f, 10, -10,
 R_CUBIC_TO, 0, -5.51f, -4.49f, -10, -10, -10,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 8, 10,
+H_LINE_TO, 5.5f,
+V_LINE_TO, 8,
+H_LINE_TO, 8,
+V_LINE_TO, 5.5f,
+R_H_LINE_TO, 2,
+V_LINE_TO, 8,
+R_H_LINE_TO, 2.5f,
+R_V_LINE_TO, 2,
+H_LINE_TO, 10,
+R_V_LINE_TO, 2.5f,
+H_LINE_TO, 8,
+V_LINE_TO, 10,
+CLOSE,
+R_MOVE_TO, 8.32f, 7.9f,
+R_LINE_TO, 1.65f, -1.8f,
+R_LINE_TO, -3.29f, -3.01f,
+R_CUBIC_TO, 0.83f, -1.15f, 1.32f, -2.56f, 1.32f, -4.09f,
+R_CUBIC_TO, 0, -3.86f, -3.14f, -7, -7, -7,
+CUBIC_TO, 5.14f, 2, 2, 5.14f, 2, 9,
+R_CUBIC_TO, 0, 3.86f, 3.14f, 7, 7, 7,
+R_CUBIC_TO, 1.45f, 0, 2.81f, -0.45f, 3.93f, -1.21f,
+R_LINE_TO, 3.39f, 3.11f,
+CLOSE,
+MOVE_TO, 9, 4,
+CUBIC_TO, 6.24f, 4, 4, 6.24f, 4, 9,
+R_CUBIC_TO, 0, 2.76f, 2.24f, 5, 5, 5,
+R_CUBIC_TO, 2.76f, 0, 5, -2.24f, 5, -5,
+R_CUBIC_TO, 0, -2.76f, -2.24f, -5, -5, -5,
+CLOSE
diff --git a/ash/resources/vector_icons/palette_mode_metalayer.1x.icon b/ash/resources/vector_icons/palette_mode_metalayer.1x.icon
deleted file mode 100644
index af625a90..0000000
--- a/ash/resources/vector_icons/palette_mode_metalayer.1x.icon
+++ /dev/null
@@ -1,26 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 16.79f, 7.9f,
-CUBIC_TO, 17.38f, 7.9f, 17.86f, 7.42f, 17.86f, 6.83f,
-CUBIC_TO, 17.86f, 6.24f, 17.38f, 5.77f, 16.79f, 5.77f,
-CUBIC_TO, 16.2f, 5.77f, 15.72f, 6.24f, 15.72f, 6.83f,
-CUBIC_TO, 15.72f, 7.42f, 16.2f, 7.9f, 16.79f, 7.9f,
-MOVE_TO, 13.59f, 11.46f,
-CUBIC_TO, 14.77f, 11.46f, 15.72f, 10.5f, 15.72f, 9.32f,
-CUBIC_TO, 15.72f, 8.14f, 14.77f, 7.19f, 13.59f, 7.19f,
-CUBIC_TO, 12.41f, 7.19f, 11.46f, 8.14f, 11.46f, 9.32f,
-CUBIC_TO, 11.46f, 10.5f, 12.41f, 11.46f, 13.59f, 11.46f,
-MOVE_TO, 13.59f, 17.14f,
-CUBIC_TO, 14.96f, 17.14f, 16.08f, 16.03f, 16.08f, 14.66f,
-CUBIC_TO, 16.08f, 13.28f, 14.96f, 12.17f, 13.59f, 12.17f,
-CUBIC_TO, 12.21f, 12.17f, 11.1f, 13.28f, 11.1f, 14.66f,
-CUBIC_TO, 11.1f, 16.03f, 12.21f, 17.14f, 13.59f, 17.14f,
-MOVE_TO, 10.74f, 7.19f,
-CUBIC_TO, 10.74f, 4.83f, 8.83f, 2.92f, 6.48f, 2.92f,
-CUBIC_TO, 4.12f, 2.92f, 2.21f, 4.83f, 2.21f, 7.19f,
-CUBIC_TO, 2.21f, 9.55f, 4.12f, 11.46f, 6.48f, 11.46f,
-CUBIC_TO, 8.83f, 11.46f, 10.74f, 9.55f, 10.74f, 7.19f,
-CLOSE
diff --git a/ash/resources/vector_icons/palette_mode_metalayer.icon b/ash/resources/vector_icons/palette_mode_metalayer.icon
index 30f7b153..6d31579 100644
--- a/ash/resources/vector_icons/palette_mode_metalayer.icon
+++ b/ash/resources/vector_icons/palette_mode_metalayer.icon
@@ -24,3 +24,26 @@
 CUBIC_TO, 4.42f, 19.09f, 8.24f, 22.91f, 12.96f, 22.91f,
 CUBIC_TO, 17.67f, 22.91f, 21.49f, 19.09f, 21.49f, 14.38f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 16.79f, 7.9f,
+CUBIC_TO, 17.38f, 7.9f, 17.86f, 7.42f, 17.86f, 6.83f,
+CUBIC_TO, 17.86f, 6.24f, 17.38f, 5.77f, 16.79f, 5.77f,
+CUBIC_TO, 16.2f, 5.77f, 15.72f, 6.24f, 15.72f, 6.83f,
+CUBIC_TO, 15.72f, 7.42f, 16.2f, 7.9f, 16.79f, 7.9f,
+MOVE_TO, 13.59f, 11.46f,
+CUBIC_TO, 14.77f, 11.46f, 15.72f, 10.5f, 15.72f, 9.32f,
+CUBIC_TO, 15.72f, 8.14f, 14.77f, 7.19f, 13.59f, 7.19f,
+CUBIC_TO, 12.41f, 7.19f, 11.46f, 8.14f, 11.46f, 9.32f,
+CUBIC_TO, 11.46f, 10.5f, 12.41f, 11.46f, 13.59f, 11.46f,
+MOVE_TO, 13.59f, 17.14f,
+CUBIC_TO, 14.96f, 17.14f, 16.08f, 16.03f, 16.08f, 14.66f,
+CUBIC_TO, 16.08f, 13.28f, 14.96f, 12.17f, 13.59f, 12.17f,
+CUBIC_TO, 12.21f, 12.17f, 11.1f, 13.28f, 11.1f, 14.66f,
+CUBIC_TO, 11.1f, 16.03f, 12.21f, 17.14f, 13.59f, 17.14f,
+MOVE_TO, 10.74f, 7.19f,
+CUBIC_TO, 10.74f, 4.83f, 8.83f, 2.92f, 6.48f, 2.92f,
+CUBIC_TO, 4.12f, 2.92f, 2.21f, 4.83f, 2.21f, 7.19f,
+CUBIC_TO, 2.21f, 9.55f, 4.12f, 11.46f, 6.48f, 11.46f,
+CUBIC_TO, 8.83f, 11.46f, 10.74f, 9.55f, 10.74f, 7.19f,
+CLOSE
diff --git a/ash/resources/vector_icons/palette_tray_icon_capture_region.1x.icon b/ash/resources/vector_icons/palette_tray_icon_capture_region.1x.icon
deleted file mode 100644
index fc023d8..0000000
--- a/ash/resources/vector_icons/palette_tray_icon_capture_region.1x.icon
+++ /dev/null
@@ -1,94 +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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 4.39f, 2.64f,
-V_LINE_TO, 0.5f,
-H_LINE_TO, 3.14f,
-R_V_LINE_TO, 2.14f,
-H_LINE_TO, 1,
-R_V_LINE_TO, 1.25f,
-R_H_LINE_TO, 2.12f,
-V_LINE_TO, 6,
-R_H_LINE_TO, 1.27f,
-V_LINE_TO, 3.89f,
-H_LINE_TO, 6.5f,
-R_V_LINE_TO, -1.27f,
-R_LINE_TO, -2.12f, 0.02f,
-CLOSE,
-MOVE_TO, 13, 5.5f,
-R_H_LINE_TO, 1.5f,
-V_LINE_TO, 4,
-H_LINE_TO, 13,
-R_V_LINE_TO, 1.5f,
-CLOSE,
-MOVE_TO, 13, 3,
-V_LINE_TO, 1.5f,
-R_CUBIC_TO, 0.83f, 0, 1.5f, 0.72f, 1.5f, 1.5f,
-H_LINE_TO, 13,
-CLOSE,
-R_MOVE_TO, -2.5f, 0,
-H_LINE_TO, 12,
-V_LINE_TO, 1.5f,
-R_H_LINE_TO, -1.5f,
-V_LINE_TO, 3,
-CLOSE,
-MOVE_TO, 13, 8,
-R_H_LINE_TO, 1.5f,
-V_LINE_TO, 6.5f,
-H_LINE_TO, 13,
-V_LINE_TO, 8,
-CLOSE,
-R_MOVE_TO, -8.5f, 6,
-H_LINE_TO, 6,
-R_V_LINE_TO, -1.5f,
-H_LINE_TO, 4.5f,
-V_LINE_TO, 14,
-CLOSE,
-MOVE_TO, 2, 11,
-R_H_LINE_TO, 1.5f,
-V_LINE_TO, 9.5f,
-H_LINE_TO, 2,
-V_LINE_TO, 11,
-CLOSE,
-R_MOVE_TO, 5.5f, -8,
-H_LINE_TO, 9,
-V_LINE_TO, 1.5f,
-H_LINE_TO, 7.5f,
-V_LINE_TO, 3,
-CLOSE,
-R_MOVE_TO, 0, 11,
-H_LINE_TO, 9,
-R_V_LINE_TO, -1.5f,
-H_LINE_TO, 7.5f,
-V_LINE_TO, 14,
-CLOSE,
-MOVE_TO, 2, 8,
-R_H_LINE_TO, 1.5f,
-V_LINE_TO, 6.5f,
-H_LINE_TO, 2,
-V_LINE_TO, 8,
-CLOSE,
-R_MOVE_TO, 1.5f, 6,
-R_CUBIC_TO, -0.82f, 0, -1.5f, -0.78f, -1.5f, -1.5f,
-R_H_LINE_TO, 1.5f,
-V_LINE_TO, 14,
-CLOSE,
-R_MOVE_TO, 7, 0,
-H_LINE_TO, 12,
-R_V_LINE_TO, -1.5f,
-R_H_LINE_TO, -1.5f,
-V_LINE_TO, 14,
-CLOSE,
-R_MOVE_TO, 2.5f, -3,
-R_H_LINE_TO, 1.5f,
-V_LINE_TO, 9.5f,
-H_LINE_TO, 13,
-V_LINE_TO, 11,
-CLOSE,
-R_MOVE_TO, 0, 3,
-R_CUBIC_TO, 0.83f, 0, 1.5f, -0.67f, 1.5f, -1.5f,
-H_LINE_TO, 13,
-V_LINE_TO, 14,
-CLOSE
diff --git a/ash/resources/vector_icons/palette_tray_icon_capture_region.icon b/ash/resources/vector_icons/palette_tray_icon_capture_region.icon
index e625132..2f45080 100644
--- a/ash/resources/vector_icons/palette_tray_icon_capture_region.icon
+++ b/ash/resources/vector_icons/palette_tray_icon_capture_region.icon
@@ -92,3 +92,94 @@
 R_H_LINE_TO, -3,
 R_V_LINE_TO, 3,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 4.39f, 2.64f,
+V_LINE_TO, 0.5f,
+H_LINE_TO, 3.14f,
+R_V_LINE_TO, 2.14f,
+H_LINE_TO, 1,
+R_V_LINE_TO, 1.25f,
+R_H_LINE_TO, 2.12f,
+V_LINE_TO, 6,
+R_H_LINE_TO, 1.27f,
+V_LINE_TO, 3.89f,
+H_LINE_TO, 6.5f,
+R_V_LINE_TO, -1.27f,
+R_LINE_TO, -2.12f, 0.02f,
+CLOSE,
+MOVE_TO, 13, 5.5f,
+R_H_LINE_TO, 1.5f,
+V_LINE_TO, 4,
+H_LINE_TO, 13,
+R_V_LINE_TO, 1.5f,
+CLOSE,
+MOVE_TO, 13, 3,
+V_LINE_TO, 1.5f,
+R_CUBIC_TO, 0.83f, 0, 1.5f, 0.72f, 1.5f, 1.5f,
+H_LINE_TO, 13,
+CLOSE,
+R_MOVE_TO, -2.5f, 0,
+H_LINE_TO, 12,
+V_LINE_TO, 1.5f,
+R_H_LINE_TO, -1.5f,
+V_LINE_TO, 3,
+CLOSE,
+MOVE_TO, 13, 8,
+R_H_LINE_TO, 1.5f,
+V_LINE_TO, 6.5f,
+H_LINE_TO, 13,
+V_LINE_TO, 8,
+CLOSE,
+R_MOVE_TO, -8.5f, 6,
+H_LINE_TO, 6,
+R_V_LINE_TO, -1.5f,
+H_LINE_TO, 4.5f,
+V_LINE_TO, 14,
+CLOSE,
+MOVE_TO, 2, 11,
+R_H_LINE_TO, 1.5f,
+V_LINE_TO, 9.5f,
+H_LINE_TO, 2,
+V_LINE_TO, 11,
+CLOSE,
+R_MOVE_TO, 5.5f, -8,
+H_LINE_TO, 9,
+V_LINE_TO, 1.5f,
+H_LINE_TO, 7.5f,
+V_LINE_TO, 3,
+CLOSE,
+R_MOVE_TO, 0, 11,
+H_LINE_TO, 9,
+R_V_LINE_TO, -1.5f,
+H_LINE_TO, 7.5f,
+V_LINE_TO, 14,
+CLOSE,
+MOVE_TO, 2, 8,
+R_H_LINE_TO, 1.5f,
+V_LINE_TO, 6.5f,
+H_LINE_TO, 2,
+V_LINE_TO, 8,
+CLOSE,
+R_MOVE_TO, 1.5f, 6,
+R_CUBIC_TO, -0.82f, 0, -1.5f, -0.78f, -1.5f, -1.5f,
+R_H_LINE_TO, 1.5f,
+V_LINE_TO, 14,
+CLOSE,
+R_MOVE_TO, 7, 0,
+H_LINE_TO, 12,
+R_V_LINE_TO, -1.5f,
+R_H_LINE_TO, -1.5f,
+V_LINE_TO, 14,
+CLOSE,
+R_MOVE_TO, 2.5f, -3,
+R_H_LINE_TO, 1.5f,
+V_LINE_TO, 9.5f,
+H_LINE_TO, 13,
+V_LINE_TO, 11,
+CLOSE,
+R_MOVE_TO, 0, 3,
+R_CUBIC_TO, 0.83f, 0, 1.5f, -0.67f, 1.5f, -1.5f,
+H_LINE_TO, 13,
+V_LINE_TO, 14,
+CLOSE
diff --git a/ash/resources/vector_icons/palette_tray_icon_default.1x.icon b/ash/resources/vector_icons/palette_tray_icon_default.1x.icon
deleted file mode 100644
index 4fc848e9..0000000
--- a/ash/resources/vector_icons/palette_tray_icon_default.1x.icon
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 12.24f, 2.2f,
-R_LINE_TO, 1.56f, 1.55f,
-R_CUBIC_TO, 0.26f, 0.26f, 0.27f, 0.69f, 0.01f, 0.95f,
-LINE_TO, 10.23f, 8.27f,
-LINE_TO, 7.72f, 5.77f,
-LINE_TO, 9.41f, 4.08f,
-R_LINE_TO, -0.49f, -0.49f,
-R_LINE_TO, -3.77f, 3.77f,
-R_LINE_TO, -0.93f, -0.93f,
-R_LINE_TO, 4.24f, -4.24f,
-R_CUBIC_TO, 0.26f, -0.26f, 0.69f, -0.25f, 0.95f, 0.01f,
-R_LINE_TO, 0.95f, 0.94f,
-R_LINE_TO, 0.95f, -0.94f,
-R_CUBIC_TO, 0.25f, -0.26f, 0.68f, -0.26f, 0.94f, 0,
-CLOSE,
-MOVE_TO, 2, 11.5f,
-V_LINE_TO, 14,
-R_H_LINE_TO, 2.49f,
-R_LINE_TO, 5.03f, -5.02f,
-R_LINE_TO, -2.5f, -2.5f,
-LINE_TO, 2, 11.5f,
-CLOSE
diff --git a/ash/resources/vector_icons/palette_tray_icon_default.icon b/ash/resources/vector_icons/palette_tray_icon_default.icon
index 6a13e8b..743add6 100644
--- a/ash/resources/vector_icons/palette_tray_icon_default.icon
+++ b/ash/resources/vector_icons/palette_tray_icon_default.icon
@@ -25,3 +25,27 @@
 R_LINE_TO, -5, -5,
 LINE_TO, 4, 23,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 12.24f, 2.2f,
+R_LINE_TO, 1.56f, 1.55f,
+R_CUBIC_TO, 0.26f, 0.26f, 0.27f, 0.69f, 0.01f, 0.95f,
+LINE_TO, 10.23f, 8.27f,
+LINE_TO, 7.72f, 5.77f,
+LINE_TO, 9.41f, 4.08f,
+R_LINE_TO, -0.49f, -0.49f,
+R_LINE_TO, -3.77f, 3.77f,
+R_LINE_TO, -0.93f, -0.93f,
+R_LINE_TO, 4.24f, -4.24f,
+R_CUBIC_TO, 0.26f, -0.26f, 0.69f, -0.25f, 0.95f, 0.01f,
+R_LINE_TO, 0.95f, 0.94f,
+R_LINE_TO, 0.95f, -0.94f,
+R_CUBIC_TO, 0.25f, -0.26f, 0.68f, -0.26f, 0.94f, 0,
+CLOSE,
+MOVE_TO, 2, 11.5f,
+V_LINE_TO, 14,
+R_H_LINE_TO, 2.49f,
+R_LINE_TO, 5.03f, -5.02f,
+R_LINE_TO, -2.5f, -2.5f,
+LINE_TO, 2, 11.5f,
+CLOSE
diff --git a/ash/resources/vector_icons/palette_tray_icon_laser_pointer.1x.icon b/ash/resources/vector_icons/palette_tray_icon_laser_pointer.1x.icon
deleted file mode 100644
index 640bf3a..0000000
--- a/ash/resources/vector_icons/palette_tray_icon_laser_pointer.1x.icon
+++ /dev/null
@@ -1,41 +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.
-
-CANVAS_DIMENSIONS, 16,
-NEW_PATH,
-PATH_COLOR_ARGB, 0x4D, 0xFF, 0xFF, 0xFF,
-MOVE_TO, 12.03f, 6,
-H_LINE_TO, 8.19f,
-R_LINE_TO, 3.84f, -3.71f,
-R_CUBIC_TO, 0.24f, -0.19f, 0.4f, -0.5f, 0.4f, -0.84f,
-CUBIC_TO, 12.43f, 0.87f, 11.99f, 0.4f, 11.44f, 0.4f,
-R_CUBIC_TO, -0.2f, 0, -0.39f, 0.07f, -0.55f, 0.18f,
-LINE_TO, 3.24f, 6.01f,
-R_CUBIC_TO, -0.09f, 0.05f, -0.18f, 0.11f, -0.26f, 0.18f,
-R_LINE_TO, -0.03f, 0.02f,
-R_CUBIC_TO, -0.33f, 0.31f, -0.55f, 0.76f, -0.55f, 1.26f,
-R_CUBIC_TO, 0, 0.92f, 0.7f, 1.67f, 1.57f, 1.72f,
-R_H_LINE_TO, 2.49f,
-R_LINE_TO, -3.02f, 1.93f,
-R_CUBIC_TO, 0.34f, -0.21f, 0.72f, -0.35f, 1.14f, -0.35f,
-R_CUBIC_TO, 1.23f, 0, 2.22f, 1.06f, 2.22f, 2.36f,
-R_CUBIC_TO, 0, 0.64f, -0.24f, 1.23f, -0.64f, 1.65f,
-R_LINE_TO, 6.68f, -5.9f,
-R_CUBIC_TO, 0.13f, -0.08f, 0.24f, -0.18f, 0.34f, -0.3f,
-R_CUBIC_TO, 0.26f, -0.32f, 0.41f, -0.7f, 0.41f, -1.12f,
-R_CUBIC_TO, 0, -0.92f, -0.71f, -1.47f, -1.57f, -1.48f,
-CLOSE,
-NEW_PATH,
-MOVE_TO, 7.2f, 13.03f,
-R_CUBIC_TO, 0, -1.33f, -1.07f, -2.4f, -2.4f, -2.4f,
-R_CUBIC_TO, -0.45f, 0, -0.87f, 0.13f, -1.24f, 0.35f,
-R_LINE_TO, -0.15f, 0.09f,
-R_CUBIC_TO, -0.01f, 0.01f, -0.02f, 0.02f, -0.03f, 0.03f,
-R_CUBIC_TO, -0.59f, 0.44f, -0.98f, 1.14f, -0.98f, 1.93f,
-R_CUBIC_TO, 0, 1.33f, 1.08f, 2.4f, 2.4f, 2.4f,
-R_CUBIC_TO, 0.5f, 0, 0.96f, -0.15f, 1.34f, -0.41f,
-R_LINE_TO, 0.01f, 0,
-R_CUBIC_TO, 0.13f, -0.09f, 0.25f, -0.19f, 0.36f, -0.3f,
-R_CUBIC_TO, 0.43f, -0.43f, 0.69f, -1.02f, 0.69f, -1.68f,
-CLOSE
diff --git a/ash/resources/vector_icons/palette_tray_icon_laser_pointer.icon b/ash/resources/vector_icons/palette_tray_icon_laser_pointer.icon
index 66f7e02..8dc901f 100644
--- a/ash/resources/vector_icons/palette_tray_icon_laser_pointer.icon
+++ b/ash/resources/vector_icons/palette_tray_icon_laser_pointer.icon
@@ -39,3 +39,41 @@
 R_CUBIC_TO, 0.26f, -0.18f, 0.51f, -0.38f, 0.73f, -0.61f,
 R_CUBIC_TO, 0.85f, -0.87f, 1.38f, -2.05f, 1.38f, -3.36f,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+NEW_PATH,
+PATH_COLOR_ARGB, 0x4D, 0xFF, 0xFF, 0xFF,
+MOVE_TO, 12.03f, 6,
+H_LINE_TO, 8.19f,
+R_LINE_TO, 3.84f, -3.71f,
+R_CUBIC_TO, 0.24f, -0.19f, 0.4f, -0.5f, 0.4f, -0.84f,
+CUBIC_TO, 12.43f, 0.87f, 11.99f, 0.4f, 11.44f, 0.4f,
+R_CUBIC_TO, -0.2f, 0, -0.39f, 0.07f, -0.55f, 0.18f,
+LINE_TO, 3.24f, 6.01f,
+R_CUBIC_TO, -0.09f, 0.05f, -0.18f, 0.11f, -0.26f, 0.18f,
+R_LINE_TO, -0.03f, 0.02f,
+R_CUBIC_TO, -0.33f, 0.31f, -0.55f, 0.76f, -0.55f, 1.26f,
+R_CUBIC_TO, 0, 0.92f, 0.7f, 1.67f, 1.57f, 1.72f,
+R_H_LINE_TO, 2.49f,
+R_LINE_TO, -3.02f, 1.93f,
+R_CUBIC_TO, 0.34f, -0.21f, 0.72f, -0.35f, 1.14f, -0.35f,
+R_CUBIC_TO, 1.23f, 0, 2.22f, 1.06f, 2.22f, 2.36f,
+R_CUBIC_TO, 0, 0.64f, -0.24f, 1.23f, -0.64f, 1.65f,
+R_LINE_TO, 6.68f, -5.9f,
+R_CUBIC_TO, 0.13f, -0.08f, 0.24f, -0.18f, 0.34f, -0.3f,
+R_CUBIC_TO, 0.26f, -0.32f, 0.41f, -0.7f, 0.41f, -1.12f,
+R_CUBIC_TO, 0, -0.92f, -0.71f, -1.47f, -1.57f, -1.48f,
+CLOSE,
+NEW_PATH,
+MOVE_TO, 7.2f, 13.03f,
+R_CUBIC_TO, 0, -1.33f, -1.07f, -2.4f, -2.4f, -2.4f,
+R_CUBIC_TO, -0.45f, 0, -0.87f, 0.13f, -1.24f, 0.35f,
+R_LINE_TO, -0.15f, 0.09f,
+R_CUBIC_TO, -0.01f, 0.01f, -0.02f, 0.02f, -0.03f, 0.03f,
+R_CUBIC_TO, -0.59f, 0.44f, -0.98f, 1.14f, -0.98f, 1.93f,
+R_CUBIC_TO, 0, 1.33f, 1.08f, 2.4f, 2.4f, 2.4f,
+R_CUBIC_TO, 0.5f, 0, 0.96f, -0.15f, 1.34f, -0.41f,
+R_LINE_TO, 0.01f, 0,
+R_CUBIC_TO, 0.13f, -0.09f, 0.25f, -0.19f, 0.36f, -0.3f,
+R_CUBIC_TO, 0.43f, -0.43f, 0.69f, -1.02f, 0.69f, -1.68f,
+CLOSE
diff --git a/ash/resources/vector_icons/palette_tray_icon_magnify.1x.icon b/ash/resources/vector_icons/palette_tray_icon_magnify.1x.icon
deleted file mode 100644
index fd09e3d..0000000
--- a/ash/resources/vector_icons/palette_tray_icon_magnify.1x.icon
+++ /dev/null
@@ -1,35 +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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 6.4f, 8,
-R_H_LINE_TO, -2,
-V_LINE_TO, 6.4f,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, -2,
-H_LINE_TO, 8,
-R_V_LINE_TO, 2,
-R_H_LINE_TO, 2,
-V_LINE_TO, 8,
-H_LINE_TO, 8,
-R_V_LINE_TO, 2,
-H_LINE_TO, 6.4f,
-V_LINE_TO, 8,
-CLOSE,
-R_MOVE_TO, 6.65f, 6.32f,
-R_LINE_TO, 1.32f, -1.44f,
-R_LINE_TO, -2.63f, -2.41f,
-R_CUBIC_TO, 0.67f, -0.92f, 1.06f, -2.05f, 1.06f, -3.27f,
-R_CUBIC_TO, 0, -3.09f, -2.51f, -5.6f, -5.6f, -5.6f,
-R_CUBIC_TO, -3.09f, 0, -5.6f, 2.51f, -5.6f, 5.6f,
-R_CUBIC_TO, 0, 3.09f, 2.51f, 5.6f, 5.6f, 5.6f,
-R_CUBIC_TO, 1.16f, 0, 2.25f, -0.36f, 3.14f, -0.97f,
-R_LINE_TO, 2.71f, 2.49f,
-CLOSE,
-MOVE_TO, 7.2f, 3.2f,
-R_CUBIC_TO, -2.21f, 0, -4, 1.79f, -4, 4,
-R_CUBIC_TO, 0, 2.21f, 1.79f, 4, 4, 4,
-R_CUBIC_TO, 2.2f, 0, 4, -1.79f, 4, -4,
-R_CUBIC_TO, 0, -2.21f, -1.8f, -4, -4, -4,
-CLOSE
diff --git a/ash/resources/vector_icons/palette_tray_icon_magnify.icon b/ash/resources/vector_icons/palette_tray_icon_magnify.icon
index 229edf3..dea365b7 100644
--- a/ash/resources/vector_icons/palette_tray_icon_magnify.icon
+++ b/ash/resources/vector_icons/palette_tray_icon_magnify.icon
@@ -33,3 +33,35 @@
 R_CUBIC_TO, 4.41f, 0, 8, -3.59f, 8, -8,
 R_CUBIC_TO, 0, -4.41f, -3.59f, -8, -8, -8,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 6.4f, 8,
+R_H_LINE_TO, -2,
+V_LINE_TO, 6.4f,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, -2,
+H_LINE_TO, 8,
+R_V_LINE_TO, 2,
+R_H_LINE_TO, 2,
+V_LINE_TO, 8,
+H_LINE_TO, 8,
+R_V_LINE_TO, 2,
+H_LINE_TO, 6.4f,
+V_LINE_TO, 8,
+CLOSE,
+R_MOVE_TO, 6.65f, 6.32f,
+R_LINE_TO, 1.32f, -1.44f,
+R_LINE_TO, -2.63f, -2.41f,
+R_CUBIC_TO, 0.67f, -0.92f, 1.06f, -2.05f, 1.06f, -3.27f,
+R_CUBIC_TO, 0, -3.09f, -2.51f, -5.6f, -5.6f, -5.6f,
+R_CUBIC_TO, -3.09f, 0, -5.6f, 2.51f, -5.6f, 5.6f,
+R_CUBIC_TO, 0, 3.09f, 2.51f, 5.6f, 5.6f, 5.6f,
+R_CUBIC_TO, 1.16f, 0, 2.25f, -0.36f, 3.14f, -0.97f,
+R_LINE_TO, 2.71f, 2.49f,
+CLOSE,
+MOVE_TO, 7.2f, 3.2f,
+R_CUBIC_TO, -2.21f, 0, -4, 1.79f, -4, 4,
+R_CUBIC_TO, 0, 2.21f, 1.79f, 4, 4, 4,
+R_CUBIC_TO, 2.2f, 0, 4, -1.79f, 4, -4,
+R_CUBIC_TO, 0, -2.21f, -1.8f, -4, -4, -4,
+CLOSE
diff --git a/ash/resources/vector_icons/palette_tray_icon_metalayer.1x.icon b/ash/resources/vector_icons/palette_tray_icon_metalayer.1x.icon
deleted file mode 100644
index cda823b..0000000
--- a/ash/resources/vector_icons/palette_tray_icon_metalayer.1x.icon
+++ /dev/null
@@ -1,26 +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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 13.43f, 6.32f,
-CUBIC_TO, 13.9f, 6.32f, 14.28f, 5.94f, 14.28f, 5.47f,
-CUBIC_TO, 14.28f, 5, 13.9f, 4.61f, 13.43f, 4.61f,
-CUBIC_TO, 12.96f, 4.61f, 12.58f, 5, 12.58f, 5.47f,
-CUBIC_TO, 12.58f, 5.94f, 12.96f, 6.32f, 13.43f, 6.32f,
-MOVE_TO, 10.87f, 9.16f,
-CUBIC_TO, 11.81f, 9.16f, 12.58f, 8.4f, 12.58f, 7.46f,
-CUBIC_TO, 12.58f, 6.52f, 11.81f, 5.75f, 10.87f, 5.75f,
-CUBIC_TO, 9.93f, 5.75f, 9.16f, 6.52f, 9.16f, 7.46f,
-CUBIC_TO, 9.16f, 8.4f, 9.93f, 9.16f, 10.87f, 9.16f,
-MOVE_TO, 10.87f, 13.72f,
-CUBIC_TO, 11.97f, 13.72f, 12.86f, 12.82f, 12.86f, 11.72f,
-CUBIC_TO, 12.86f, 10.62f, 11.97f, 9.73f, 10.87f, 9.73f,
-CUBIC_TO, 9.77f, 9.73f, 8.88f, 10.62f, 8.88f, 11.72f,
-CUBIC_TO, 8.88f, 12.82f, 9.77f, 13.72f, 10.87f, 13.72f,
-MOVE_TO, 8.6f, 5.75f,
-CUBIC_TO, 8.6f, 3.87f, 7.07f, 2.34f, 5.18f, 2.34f,
-CUBIC_TO, 3.3f, 2.34f, 1.77f, 3.87f, 1.77f, 5.75f,
-CUBIC_TO, 1.77f, 7.64f, 3.3f, 9.16f, 5.18f, 9.16f,
-CUBIC_TO, 7.07f, 9.16f, 8.6f, 7.64f, 8.6f, 5.75f,
-CLOSE
diff --git a/ash/resources/vector_icons/palette_tray_icon_metalayer.icon b/ash/resources/vector_icons/palette_tray_icon_metalayer.icon
index 485fe19..88c6a17 100644
--- a/ash/resources/vector_icons/palette_tray_icon_metalayer.icon
+++ b/ash/resources/vector_icons/palette_tray_icon_metalayer.icon
@@ -24,3 +24,26 @@
 CUBIC_TO, 3.54f, 15.27f, 6.59f, 18.33f, 10.36f, 18.33f,
 CUBIC_TO, 14.13f, 18.33f, 17.19f, 15.27f, 17.19f, 11.5f,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 13.43f, 6.32f,
+CUBIC_TO, 13.9f, 6.32f, 14.28f, 5.94f, 14.28f, 5.47f,
+CUBIC_TO, 14.28f, 5, 13.9f, 4.61f, 13.43f, 4.61f,
+CUBIC_TO, 12.96f, 4.61f, 12.58f, 5, 12.58f, 5.47f,
+CUBIC_TO, 12.58f, 5.94f, 12.96f, 6.32f, 13.43f, 6.32f,
+MOVE_TO, 10.87f, 9.16f,
+CUBIC_TO, 11.81f, 9.16f, 12.58f, 8.4f, 12.58f, 7.46f,
+CUBIC_TO, 12.58f, 6.52f, 11.81f, 5.75f, 10.87f, 5.75f,
+CUBIC_TO, 9.93f, 5.75f, 9.16f, 6.52f, 9.16f, 7.46f,
+CUBIC_TO, 9.16f, 8.4f, 9.93f, 9.16f, 10.87f, 9.16f,
+MOVE_TO, 10.87f, 13.72f,
+CUBIC_TO, 11.97f, 13.72f, 12.86f, 12.82f, 12.86f, 11.72f,
+CUBIC_TO, 12.86f, 10.62f, 11.97f, 9.73f, 10.87f, 9.73f,
+CUBIC_TO, 9.77f, 9.73f, 8.88f, 10.62f, 8.88f, 11.72f,
+CUBIC_TO, 8.88f, 12.82f, 9.77f, 13.72f, 10.87f, 13.72f,
+MOVE_TO, 8.6f, 5.75f,
+CUBIC_TO, 8.6f, 3.87f, 7.07f, 2.34f, 5.18f, 2.34f,
+CUBIC_TO, 3.3f, 2.34f, 1.77f, 3.87f, 1.77f, 5.75f,
+CUBIC_TO, 1.77f, 7.64f, 3.3f, 9.16f, 5.18f, 9.16f,
+CUBIC_TO, 7.07f, 9.16f, 8.6f, 7.64f, 8.6f, 5.75f,
+CLOSE
diff --git a/ash/resources/vector_icons/shelf_add_person_button.1x.icon b/ash/resources/vector_icons/shelf_add_person_button.1x.icon
deleted file mode 100644
index 8ddc616f..0000000
--- a/ash/resources/vector_icons/shelf_add_person_button.1x.icon
+++ /dev/null
@@ -1,28 +0,0 @@
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 7.6f, 9.8f,
-R_CUBIC_TO, -0.55f, 0, -1, 0.45f, -1, 1,
-R_CUBIC_TO, 0, 0.55f, 0.45f, 1, 1, 1,
-R_CUBIC_TO, 0.55f, 0, 1, -0.45f, 1, -1,
-R_CUBIC_TO, 0, -0.55f, -0.45f, -1, -1, -1,
-CLOSE,
-R_MOVE_TO, 4.8f, 0,
-R_CUBIC_TO, -0.55f, 0, -1, 0.45f, -1, 1,
-R_CUBIC_TO, 0, 0.55f, 0.45f, 1, 1, 1,
-R_CUBIC_TO, 0.55f, 0, 1, -0.45f, 1, -1,
-R_CUBIC_TO, 0, -0.55f, -0.45f, -1, -1, -1,
-CLOSE,
-MOVE_TO, 10, 2,
-R_CUBIC_TO, -4.42f, 0, -8, 3.58f, -8, 8,
-R_CUBIC_TO, 0, 4.42f, 3.58f, 8, 8, 8,
-R_CUBIC_TO, 4.42f, 0, 8, -3.58f, 8, -8,
-R_CUBIC_TO, 0, -4.42f, -3.58f, -8, -8, -8,
-CLOSE,
-R_MOVE_TO, 0, 14.4f,
-R_CUBIC_TO, -3.53f, 0, -6.4f, -2.87f, -6.4f, -6.4f,
-R_CUBIC_TO, 0, -0.23f, 0.02f, -0.46f, 0.04f, -0.69f,
-R_CUBIC_TO, 1.89f, -0.84f, 3.38f, -2.38f, 4.17f, -4.3f,
-CUBIC_TO, 9.26f, 7.06f, 11.64f, 8.4f, 14.34f, 8.4f,
-R_CUBIC_TO, 0.62f, 0, 1.22f, -0.07f, 1.8f, -0.21f,
-R_CUBIC_TO, 0.17f, 0.57f, 0.26f, 1.18f, 0.26f, 1.81f,
-R_CUBIC_TO, 0, 3.53f, -2.87f, 6.4f, -6.4f, 6.4f,
-CLOSE
diff --git a/ash/resources/vector_icons/shelf_add_person_button.icon b/ash/resources/vector_icons/shelf_add_person_button.icon
index 0095061..74ef6f5 100644
--- a/ash/resources/vector_icons/shelf_add_person_button.icon
+++ b/ash/resources/vector_icons/shelf_add_person_button.icon
@@ -26,3 +26,32 @@
 R_CUBIC_TO, 0.34f, 1.14f, 0.53f, 2.35f, 0.53f, 3.62f,
 R_CUBIC_TO, 0, 7.06f, -5.74f, 12.8f, -12.8f, 12.8f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 7.6f, 9.8f,
+R_CUBIC_TO, -0.55f, 0, -1, 0.45f, -1, 1,
+R_CUBIC_TO, 0, 0.55f, 0.45f, 1, 1, 1,
+R_CUBIC_TO, 0.55f, 0, 1, -0.45f, 1, -1,
+R_CUBIC_TO, 0, -0.55f, -0.45f, -1, -1, -1,
+CLOSE,
+R_MOVE_TO, 4.8f, 0,
+R_CUBIC_TO, -0.55f, 0, -1, 0.45f, -1, 1,
+R_CUBIC_TO, 0, 0.55f, 0.45f, 1, 1, 1,
+R_CUBIC_TO, 0.55f, 0, 1, -0.45f, 1, -1,
+R_CUBIC_TO, 0, -0.55f, -0.45f, -1, -1, -1,
+CLOSE,
+MOVE_TO, 10, 2,
+R_CUBIC_TO, -4.42f, 0, -8, 3.58f, -8, 8,
+R_CUBIC_TO, 0, 4.42f, 3.58f, 8, 8, 8,
+R_CUBIC_TO, 4.42f, 0, 8, -3.58f, 8, -8,
+R_CUBIC_TO, 0, -4.42f, -3.58f, -8, -8, -8,
+CLOSE,
+R_MOVE_TO, 0, 14.4f,
+R_CUBIC_TO, -3.53f, 0, -6.4f, -2.87f, -6.4f, -6.4f,
+R_CUBIC_TO, 0, -0.23f, 0.02f, -0.46f, 0.04f, -0.69f,
+R_CUBIC_TO, 1.89f, -0.84f, 3.38f, -2.38f, 4.17f, -4.3f,
+CUBIC_TO, 9.26f, 7.06f, 11.64f, 8.4f, 14.34f, 8.4f,
+R_CUBIC_TO, 0.62f, 0, 1.22f, -0.07f, 1.8f, -0.21f,
+R_CUBIC_TO, 0.17f, 0.57f, 0.26f, 1.18f, 0.26f, 1.81f,
+R_CUBIC_TO, 0, 3.53f, -2.87f, 6.4f, -6.4f, 6.4f,
+CLOSE
diff --git a/ash/resources/vector_icons/shelf_back.1x.icon b/ash/resources/vector_icons/shelf_back.1x.icon
deleted file mode 100644
index 01836db5..0000000
--- a/ash/resources/vector_icons/shelf_back.1x.icon
+++ /dev/null
@@ -1,17 +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.
-
-CANVAS_DIMENSIONS, 16,
-NEW_PATH,
-MOVE_TO, 5.2f, 7,
-H_LINE_TO, 15,
-R_V_LINE_TO, 2,
-H_LINE_TO, 5.2f,
-R_LINE_TO, 4.8f, 4.8f,
-LINE_TO, 8.9f, 15,
-LINE_TO, 2, 8,
-R_LINE_TO, 6.9f, -7,
-LINE_TO, 10, 2.2f,
-LINE_TO, 5.2f, 7,
-CLOSE
diff --git a/ash/resources/vector_icons/shelf_back.icon b/ash/resources/vector_icons/shelf_back.icon
index 2b21689..b66d848 100644
--- a/ash/resources/vector_icons/shelf_back.icon
+++ b/ash/resources/vector_icons/shelf_back.icon
@@ -14,3 +14,17 @@
 H_LINE_TO, 29,
 R_V_LINE_TO, 3,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+NEW_PATH,
+MOVE_TO, 5.2f, 7,
+H_LINE_TO, 15,
+R_V_LINE_TO, 2,
+H_LINE_TO, 5.2f,
+R_LINE_TO, 4.8f, 4.8f,
+LINE_TO, 8.9f, 15,
+LINE_TO, 2, 8,
+R_LINE_TO, 6.9f, -7,
+LINE_TO, 10, 2.2f,
+LINE_TO, 5.2f, 7,
+CLOSE
diff --git a/ash/resources/vector_icons/shelf_browse_as_guest_button.1x.icon b/ash/resources/vector_icons/shelf_browse_as_guest_button.1x.icon
deleted file mode 100644
index 65e2be2..0000000
--- a/ash/resources/vector_icons/shelf_browse_as_guest_button.1x.icon
+++ /dev/null
@@ -1,19 +0,0 @@
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 10, 2,
-R_CUBIC_TO, -4.42f, 0, -8, 3.58f, -8, 8,
-R_CUBIC_TO, 0, 4.42f, 3.58f, 8, 8, 8,
-R_CUBIC_TO, 4.42f, 0, 8, -3.58f, 8, -8,
-R_CUBIC_TO, 0, -4.42f, -3.58f, -8, -8, -8,
-CLOSE,
-R_MOVE_TO, 0, 2.4f,
-R_CUBIC_TO, 1.33f, 0, 2.4f, 1.07f, 2.4f, 2.4f,
-R_CUBIC_TO, 0, 1.33f, -1.07f, 2.4f, -2.4f, 2.4f,
-R_CUBIC_TO, -1.33f, 0, -2.4f, -1.07f, -2.4f, -2.4f,
-R_CUBIC_TO, 0, -1.33f, 1.07f, -2.4f, 2.4f, -2.4f,
-CLOSE,
-R_MOVE_TO, -5, 8.79f,
-R_CUBIC_TO, 0.03f, -1.74f, 3.33f, -2.69f, 5, -2.69f,
-R_CUBIC_TO, 1.66f, 0, 4.97f, 0.95f, 5, 2.69f,
-R_CUBIC_TO, -1.07f, 1.69f, -2.92f, 2.81f, -5, 2.81f,
-R_CUBIC_TO, -2.08f, 0, -3.92f, -1.12f, -5, -2.81f,
-CLOSE
diff --git a/ash/resources/vector_icons/shelf_browse_as_guest_button.icon b/ash/resources/vector_icons/shelf_browse_as_guest_button.icon
index 7e8882f..32121ef 100644
--- a/ash/resources/vector_icons/shelf_browse_as_guest_button.icon
+++ b/ash/resources/vector_icons/shelf_browse_as_guest_button.icon
@@ -17,3 +17,23 @@
 CUBIC_TO, 27.85f, 29.77f, 24.17f, 32, 20, 32,
 R_CUBIC_TO, -4.17f, 0, -7.85f, -2.23f, -10, -5.62f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 10, 2,
+R_CUBIC_TO, -4.42f, 0, -8, 3.58f, -8, 8,
+R_CUBIC_TO, 0, 4.42f, 3.58f, 8, 8, 8,
+R_CUBIC_TO, 4.42f, 0, 8, -3.58f, 8, -8,
+R_CUBIC_TO, 0, -4.42f, -3.58f, -8, -8, -8,
+CLOSE,
+R_MOVE_TO, 0, 2.4f,
+R_CUBIC_TO, 1.33f, 0, 2.4f, 1.07f, 2.4f, 2.4f,
+R_CUBIC_TO, 0, 1.33f, -1.07f, 2.4f, -2.4f, 2.4f,
+R_CUBIC_TO, -1.33f, 0, -2.4f, -1.07f, -2.4f, -2.4f,
+R_CUBIC_TO, 0, -1.33f, 1.07f, -2.4f, 2.4f, -2.4f,
+CLOSE,
+R_MOVE_TO, -5, 8.79f,
+R_CUBIC_TO, 0.03f, -1.74f, 3.33f, -2.69f, 5, -2.69f,
+R_CUBIC_TO, 1.66f, 0, 4.97f, 0.95f, 5, 2.69f,
+R_CUBIC_TO, -1.07f, 1.69f, -2.92f, 2.81f, -5, 2.81f,
+R_CUBIC_TO, -2.08f, 0, -3.92f, -1.12f, -5, -2.81f,
+CLOSE
diff --git a/ash/resources/vector_icons/shelf_cancel_button.1x.icon b/ash/resources/vector_icons/shelf_cancel_button.1x.icon
deleted file mode 100644
index afb813a..0000000
--- a/ash/resources/vector_icons/shelf_cancel_button.1x.icon
+++ /dev/null
@@ -1,12 +0,0 @@
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 9.72f, 5.89f,
-R_CUBIC_TO, -2.2f, 0, -4.19f, 0.88f, -5.73f, 2.31f,
-LINE_TO, 1, 5,
-R_V_LINE_TO, 8,
-R_H_LINE_TO, 7.47f,
-LINE_TO, 5.47f, 9.78f,
-R_CUBIC_TO, 1.15f, -1.03f, 2.62f, -1.67f, 4.25f, -1.67f,
-R_CUBIC_TO, 2.94f, 0, 5.44f, 2.05f, 6.31f, 4.89f,
-LINE_TO, 18, 12.31f,
-CUBIC_TO, 16.85f, 8.58f, 13.58f, 5.89f, 9.72f, 5.89f,
-CLOSE
diff --git a/ash/resources/vector_icons/shelf_cancel_button.icon b/ash/resources/vector_icons/shelf_cancel_button.icon
index 049be591..4f92b3d 100644
--- a/ash/resources/vector_icons/shelf_cancel_button.icon
+++ b/ash/resources/vector_icons/shelf_cancel_button.icon
@@ -10,3 +10,16 @@
 LINE_TO, 37, 24.7f,
 R_CUBIC_TO, -2.31f, -6.98f, -8.84f, -12.03f, -16.56f, -12.03f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 9.72f, 5.89f,
+R_CUBIC_TO, -2.2f, 0, -4.19f, 0.88f, -5.73f, 2.31f,
+LINE_TO, 1, 5,
+R_V_LINE_TO, 8,
+R_H_LINE_TO, 7.47f,
+LINE_TO, 5.47f, 9.78f,
+R_CUBIC_TO, 1.15f, -1.03f, 2.62f, -1.67f, 4.25f, -1.67f,
+R_CUBIC_TO, 2.94f, 0, 5.44f, 2.05f, 6.31f, 4.89f,
+LINE_TO, 18, 12.31f,
+CUBIC_TO, 16.85f, 8.58f, 13.58f, 5.89f, 9.72f, 5.89f,
+CLOSE
diff --git a/ash/resources/vector_icons/shelf_keyboard.1x.icon b/ash/resources/vector_icons/shelf_keyboard.1x.icon
deleted file mode 100644
index f1e2695..0000000
--- a/ash/resources/vector_icons/shelf_keyboard.1x.icon
+++ /dev/null
@@ -1,81 +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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 13.14f, 4,
-H_LINE_TO, 3.86f,
-CUBIC_TO, 2.59f, 4, 2.01f, 4.58f, 2, 5.8f,
-R_V_LINE_TO, 5.4f,
-R_CUBIC_TO, 0, 1.22f, 0.59f, 1.8f, 1.86f, 1.8f,
-R_H_LINE_TO, 9.29f,
-CUBIC_TO, 14.42f, 13, 15, 12.42f, 15, 11.2f,
-V_LINE_TO, 5.8f,
-R_CUBIC_TO, 0, -1.22f, -0.58f, -1.8f, -1.86f, -1.8f,
-CLOSE,
-MOVE_TO, 8, 6,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-H_LINE_TO, 8,
-V_LINE_TO, 6,
-CLOSE,
-R_MOVE_TO, 0, 2,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-H_LINE_TO, 8,
-V_LINE_TO, 8,
-CLOSE,
-MOVE_TO, 6, 6,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-H_LINE_TO, 6,
-V_LINE_TO, 6,
-CLOSE,
-R_MOVE_TO, 0, 2,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-H_LINE_TO, 6,
-V_LINE_TO, 8,
-CLOSE,
-MOVE_TO, 5, 9,
-H_LINE_TO, 4,
-V_LINE_TO, 8,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-CLOSE,
-R_MOVE_TO, 0, -2,
-H_LINE_TO, 4,
-V_LINE_TO, 6,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-CLOSE,
-R_MOVE_TO, 6, 2,
-R_H_LINE_TO, -1,
-V_LINE_TO, 8,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-CLOSE,
-R_MOVE_TO, 0, -2,
-R_H_LINE_TO, -1,
-V_LINE_TO, 6,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-CLOSE,
-R_MOVE_TO, 2, 2,
-R_H_LINE_TO, -1,
-V_LINE_TO, 8,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-CLOSE,
-R_MOVE_TO, 0, -2,
-R_H_LINE_TO, -1,
-V_LINE_TO, 6,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-CLOSE,
-R_MOVE_TO, -7, 5,
-R_V_LINE_TO, -1,
-R_H_LINE_TO, 5,
-R_V_LINE_TO, 1,
-H_LINE_TO, 6,
-CLOSE
diff --git a/ash/resources/vector_icons/shelf_keyboard.icon b/ash/resources/vector_icons/shelf_keyboard.icon
index a7baa914..9aa6efc 100644
--- a/ash/resources/vector_icons/shelf_keyboard.icon
+++ b/ash/resources/vector_icons/shelf_keyboard.icon
@@ -79,3 +79,81 @@
 R_H_LINE_TO, 3,
 R_V_LINE_TO, 3,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 13.14f, 4,
+H_LINE_TO, 3.86f,
+CUBIC_TO, 2.59f, 4, 2.01f, 4.58f, 2, 5.8f,
+R_V_LINE_TO, 5.4f,
+R_CUBIC_TO, 0, 1.22f, 0.59f, 1.8f, 1.86f, 1.8f,
+R_H_LINE_TO, 9.29f,
+CUBIC_TO, 14.42f, 13, 15, 12.42f, 15, 11.2f,
+V_LINE_TO, 5.8f,
+R_CUBIC_TO, 0, -1.22f, -0.58f, -1.8f, -1.86f, -1.8f,
+CLOSE,
+MOVE_TO, 8, 6,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+H_LINE_TO, 8,
+V_LINE_TO, 6,
+CLOSE,
+R_MOVE_TO, 0, 2,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+H_LINE_TO, 8,
+V_LINE_TO, 8,
+CLOSE,
+MOVE_TO, 6, 6,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+H_LINE_TO, 6,
+V_LINE_TO, 6,
+CLOSE,
+R_MOVE_TO, 0, 2,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+H_LINE_TO, 6,
+V_LINE_TO, 8,
+CLOSE,
+MOVE_TO, 5, 9,
+H_LINE_TO, 4,
+V_LINE_TO, 8,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+CLOSE,
+R_MOVE_TO, 0, -2,
+H_LINE_TO, 4,
+V_LINE_TO, 6,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+CLOSE,
+R_MOVE_TO, 6, 2,
+R_H_LINE_TO, -1,
+V_LINE_TO, 8,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+CLOSE,
+R_MOVE_TO, 0, -2,
+R_H_LINE_TO, -1,
+V_LINE_TO, 6,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+CLOSE,
+R_MOVE_TO, 2, 2,
+R_H_LINE_TO, -1,
+V_LINE_TO, 8,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+CLOSE,
+R_MOVE_TO, 0, -2,
+R_H_LINE_TO, -1,
+V_LINE_TO, 6,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+CLOSE,
+R_MOVE_TO, -7, 5,
+R_V_LINE_TO, -1,
+R_H_LINE_TO, 5,
+R_V_LINE_TO, 1,
+H_LINE_TO, 6,
+CLOSE
diff --git a/ash/resources/vector_icons/shelf_logout.1x.icon b/ash/resources/vector_icons/shelf_logout.1x.icon
deleted file mode 100644
index 87915739..0000000
--- a/ash/resources/vector_icons/shelf_logout.1x.icon
+++ /dev/null
@@ -1,34 +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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 8, 12,
-R_LINE_TO, 4, -4,
-R_LINE_TO, -4, -4,
-R_LINE_TO, -1.5f, 1.5f,
-LINE_TO, 8, 7,
-H_LINE_TO, 1,
-R_V_LINE_TO, 2,
-R_H_LINE_TO, 7,
-R_LINE_TO, -1.5f, 1.5f,
-LINE_TO, 8, 12,
-CLOSE,
-MOVE_TO, 3.57f, 1.03f,
-CUBIC_TO, 2, 1.03f, 1.03f, 2, 1.03f, 3.57f,
-V_LINE_TO, 6,
-H_LINE_TO, 3,
-V_LINE_TO, 3,
-R_H_LINE_TO, 10,
-R_V_LINE_TO, 10,
-H_LINE_TO, 3,
-R_V_LINE_TO, -2,
-H_LINE_TO, 1.03f,
-R_V_LINE_TO, 1.47f,
-CUBIC_TO, 1.03f, 14, 2, 15, 3.57f, 15,
-R_H_LINE_TO, 8.9f,
-R_CUBIC_TO, 1.54f, 0, 2.53f, -1, 2.53f, -2.53f,
-R_V_LINE_TO, -8.9f,
-CUBIC_TO, 15, 2, 13.96f, 1.03f, 12.46f, 1.03f,
-R_H_LINE_TO, -8.9f,
-CLOSE
diff --git a/ash/resources/vector_icons/shelf_logout.icon b/ash/resources/vector_icons/shelf_logout.icon
index aeca144b..4482ba2 100644
--- a/ash/resources/vector_icons/shelf_logout.icon
+++ b/ash/resources/vector_icons/shelf_logout.icon
@@ -32,3 +32,34 @@
 CUBIC_TO, 29, 4.5f, 27.5f, 3, 25.67f, 3,
 H_LINE_TO, 6,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 8, 12,
+R_LINE_TO, 4, -4,
+R_LINE_TO, -4, -4,
+R_LINE_TO, -1.5f, 1.5f,
+LINE_TO, 8, 7,
+H_LINE_TO, 1,
+R_V_LINE_TO, 2,
+R_H_LINE_TO, 7,
+R_LINE_TO, -1.5f, 1.5f,
+LINE_TO, 8, 12,
+CLOSE,
+MOVE_TO, 3.57f, 1.03f,
+CUBIC_TO, 2, 1.03f, 1.03f, 2, 1.03f, 3.57f,
+V_LINE_TO, 6,
+H_LINE_TO, 3,
+V_LINE_TO, 3,
+R_H_LINE_TO, 10,
+R_V_LINE_TO, 10,
+H_LINE_TO, 3,
+R_V_LINE_TO, -2,
+H_LINE_TO, 1.03f,
+R_V_LINE_TO, 1.47f,
+CUBIC_TO, 1.03f, 14, 2, 15, 3.57f, 15,
+R_H_LINE_TO, 8.9f,
+R_CUBIC_TO, 1.54f, 0, 2.53f, -1, 2.53f, -2.53f,
+R_V_LINE_TO, -8.9f,
+CUBIC_TO, 15, 2, 13.96f, 1.03f, 12.46f, 1.03f,
+R_H_LINE_TO, -8.9f,
+CLOSE
diff --git a/ash/resources/vector_icons/shelf_notifications.1x.icon b/ash/resources/vector_icons/shelf_notifications.1x.icon
deleted file mode 100644
index 9ecfd7df..0000000
--- a/ash/resources/vector_icons/shelf_notifications.1x.icon
+++ /dev/null
@@ -1,25 +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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 8.38f, 14,
-R_CUBIC_TO, 0.76f, 0, 1.38f, -0.45f, 1.38f, -1,
-H_LINE_TO, 7,
-R_CUBIC_TO, 0, 0.55f, 0.61f, 1, 1.38f, 1,
-CLOSE,
-MOVE_TO, 12, 10.1f,
-V_LINE_TO, 7,
-R_CUBIC_TO, 0, -1.5f, -0.5f, -2.76f, -2.5f, -3,
-R_V_LINE_TO, -0.79f,
-R_CUBIC_TO, 0, -0.48f, -0.5f, -0.71f, -1, -0.71f,
-R_CUBIC_TO, -0.5f, 0, -1, 0.24f, -1, 0.71f,
-V_LINE_TO, 4,
-CUBIC_TO, 5.5f, 4.24f, 5, 5.5f, 5, 7,
-R_V_LINE_TO, 3.1f,
-R_LINE_TO, -1.5f, 1.19f,
-V_LINE_TO, 12,
-R_H_LINE_TO, 10,
-R_V_LINE_TO, -0.71f,
-LINE_TO, 12, 10.1f,
-CLOSE
diff --git a/ash/resources/vector_icons/shelf_notifications.icon b/ash/resources/vector_icons/shelf_notifications.icon
index 780a14d0..100e77a0 100644
--- a/ash/resources/vector_icons/shelf_notifications.icon
+++ b/ash/resources/vector_icons/shelf_notifications.icon
@@ -23,3 +23,25 @@
 R_V_LINE_TO, -1.5f,
 LINE_TO, 24, 21,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 8.38f, 14,
+R_CUBIC_TO, 0.76f, 0, 1.38f, -0.45f, 1.38f, -1,
+H_LINE_TO, 7,
+R_CUBIC_TO, 0, 0.55f, 0.61f, 1, 1.38f, 1,
+CLOSE,
+MOVE_TO, 12, 10.1f,
+V_LINE_TO, 7,
+R_CUBIC_TO, 0, -1.5f, -0.5f, -2.76f, -2.5f, -3,
+R_V_LINE_TO, -0.79f,
+R_CUBIC_TO, 0, -0.48f, -0.5f, -0.71f, -1, -0.71f,
+R_CUBIC_TO, -0.5f, 0, -1, 0.24f, -1, 0.71f,
+V_LINE_TO, 4,
+CUBIC_TO, 5.5f, 4.24f, 5, 5.5f, 5, 7,
+R_V_LINE_TO, 3.1f,
+R_LINE_TO, -1.5f, 1.19f,
+V_LINE_TO, 12,
+R_H_LINE_TO, 10,
+R_V_LINE_TO, -0.71f,
+LINE_TO, 12, 10.1f,
+CLOSE
diff --git a/ash/resources/vector_icons/shelf_overflow.1x.icon b/ash/resources/vector_icons/shelf_overflow.1x.icon
deleted file mode 100644
index a13a532..0000000
--- a/ash/resources/vector_icons/shelf_overflow.1x.icon
+++ /dev/null
@@ -1,18 +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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 8.59f, 5.25f,
-R_ARC_TO, 0.82f, 0.82f, 0, 0, 0, -1.18f, 0,
-LINE_TO, 3.25f, 9.54f,
-R_ARC_TO, 0.87f, 0.87f, 0, 0, 0, -0.24f, 0.61f,
-R_CUBIC_TO, 0, 0.47f, 0.37f, 0.86f, 0.83f, 0.86f,
-R_ARC_TO, 0.82f, 0.82f, 0, 0, 0, 0.59f, -0.25f,
-LINE_TO, 8, 7.07f,
-R_LINE_TO, 3.58f, 3.68f,
-R_ARC_TO, 0.82f, 0.82f, 0, 0, 0, 0.59f, 0.25f,
-R_CUBIC_TO, 0.46f, 0, 0.83f, -0.38f, 0.83f, -0.86f,
-R_ARC_TO, 0.87f, 0.87f, 0, 0, 0, -0.24f, -0.61f,
-LINE_TO, 8.59f, 5.25f,
-CLOSE
diff --git a/ash/resources/vector_icons/shelf_overflow.icon b/ash/resources/vector_icons/shelf_overflow.icon
index 7886947..c97a48c5 100644
--- a/ash/resources/vector_icons/shelf_overflow.icon
+++ b/ash/resources/vector_icons/shelf_overflow.icon
@@ -17,3 +17,18 @@
 R_CUBIC_TO, 0, -0.47f, -0.19f, -0.9f, -0.49f, -1.21f,
 R_LINE_TO, -8.33f, -8.57f,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 8.59f, 5.25f,
+R_ARC_TO, 0.82f, 0.82f, 0, 0, 0, -1.18f, 0,
+LINE_TO, 3.25f, 9.54f,
+R_ARC_TO, 0.87f, 0.87f, 0, 0, 0, -0.24f, 0.61f,
+R_CUBIC_TO, 0, 0.47f, 0.37f, 0.86f, 0.83f, 0.86f,
+R_ARC_TO, 0.82f, 0.82f, 0, 0, 0, 0.59f, -0.25f,
+LINE_TO, 8, 7.07f,
+R_LINE_TO, 3.58f, 3.68f,
+R_ARC_TO, 0.82f, 0.82f, 0, 0, 0, 0.59f, 0.25f,
+R_CUBIC_TO, 0.46f, 0, 0.83f, -0.38f, 0.83f, -0.86f,
+R_ARC_TO, 0.87f, 0.87f, 0, 0, 0, -0.24f, -0.61f,
+LINE_TO, 8.59f, 5.25f,
+CLOSE
diff --git a/ash/resources/vector_icons/shelf_overview.1x.icon b/ash/resources/vector_icons/shelf_overview.1x.icon
deleted file mode 100644
index bc606772..0000000
--- a/ash/resources/vector_icons/shelf_overview.1x.icon
+++ /dev/null
@@ -1,29 +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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 2, 4,
-R_H_LINE_TO, 9,
-R_V_LINE_TO, 8,
-H_LINE_TO, 2,
-V_LINE_TO, 4,
-CLOSE,
-R_MOVE_TO, 1, 1,
-R_V_LINE_TO, 6,
-R_CUBIC_TO, 0, 0, 6.95f, 0.01f, 7, 0,
-R_CUBIC_TO, 0.05f, -0.01f, 0, -6, 0, -6,
-H_LINE_TO, 3,
-CLOSE,
-R_MOVE_TO, 11, -1,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 8,
-R_H_LINE_TO, -1,
-V_LINE_TO, 4,
-CLOSE,
-R_MOVE_TO, -2, 0,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 8,
-R_H_LINE_TO, -1,
-V_LINE_TO, 4,
-CLOSE
diff --git a/ash/resources/vector_icons/shelf_overview.icon b/ash/resources/vector_icons/shelf_overview.icon
index b3b6e65..a9f5897 100644
--- a/ash/resources/vector_icons/shelf_overview.icon
+++ b/ash/resources/vector_icons/shelf_overview.icon
@@ -27,3 +27,29 @@
 R_H_LINE_TO, -3,
 V_LINE_TO, 7,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 2, 4,
+R_H_LINE_TO, 9,
+R_V_LINE_TO, 8,
+H_LINE_TO, 2,
+V_LINE_TO, 4,
+CLOSE,
+R_MOVE_TO, 1, 1,
+R_V_LINE_TO, 6,
+R_CUBIC_TO, 0, 0, 6.95f, 0.01f, 7, 0,
+R_CUBIC_TO, 0.05f, -0.01f, 0, -6, 0, -6,
+H_LINE_TO, 3,
+CLOSE,
+R_MOVE_TO, 11, -1,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 8,
+R_H_LINE_TO, -1,
+V_LINE_TO, 4,
+CLOSE,
+R_MOVE_TO, -2, 0,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 8,
+R_H_LINE_TO, -1,
+V_LINE_TO, 4,
+CLOSE
diff --git a/ash/resources/vector_icons/shelf_shutdown_button.1x.icon b/ash/resources/vector_icons/shelf_shutdown_button.1x.icon
deleted file mode 100644
index b6f277af..0000000
--- a/ash/resources/vector_icons/shelf_shutdown_button.1x.icon
+++ /dev/null
@@ -1,19 +0,0 @@
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 10.83f, 2.5f,
-H_LINE_TO, 9.17f,
-R_V_LINE_TO, 8.33f,
-R_H_LINE_TO, 1.67f,
-V_LINE_TO, 2.5f,
-CLOSE,
-R_MOVE_TO, 4.03f, 1.81f,
-R_LINE_TO, -1.18f, 1.18f,
-CUBIC_TO, 14.99f, 6.55f, 15.83f, 8.18f, 15.83f, 10,
-R_CUBIC_TO, 0, 3.23f, -2.61f, 5.83f, -5.83f, 5.83f,
-R_CUBIC_TO, -3.22f, 0, -5.83f, -2.61f, -5.83f, -5.83f,
-R_CUBIC_TO, 0, -1.82f, 0.84f, -3.45f, 2.15f, -4.52f,
-LINE_TO, 5.14f, 4.31f,
-CUBIC_TO, 3.53f, 5.68f, 2.5f, 7.72f, 2.5f, 10,
-R_CUBIC_TO, 0, 4.14f, 3.36f, 7.5f, 7.5f, 7.5f,
-R_CUBIC_TO, 4.14f, 0, 7.5f, -3.36f, 7.5f, -7.5f,
-R_CUBIC_TO, 0, -2.28f, -1.02f, -4.32f, -2.64f, -5.69f,
-CLOSE
diff --git a/ash/resources/vector_icons/shelf_shutdown_button.icon b/ash/resources/vector_icons/shelf_shutdown_button.icon
index c7a3582..6e1862a1 100644
--- a/ash/resources/vector_icons/shelf_shutdown_button.icon
+++ b/ash/resources/vector_icons/shelf_shutdown_button.icon
@@ -17,3 +17,23 @@
 R_CUBIC_TO, 8.28f, 0, 15, -6.72f, 15, -15,
 R_CUBIC_TO, 0, -4.57f, -2.05f, -8.63f, -5.28f, -11.38f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 10.83f, 2.5f,
+H_LINE_TO, 9.17f,
+R_V_LINE_TO, 8.33f,
+R_H_LINE_TO, 1.67f,
+V_LINE_TO, 2.5f,
+CLOSE,
+R_MOVE_TO, 4.03f, 1.81f,
+R_LINE_TO, -1.18f, 1.18f,
+CUBIC_TO, 14.99f, 6.55f, 15.83f, 8.18f, 15.83f, 10,
+R_CUBIC_TO, 0, 3.23f, -2.61f, 5.83f, -5.83f, 5.83f,
+R_CUBIC_TO, -3.22f, 0, -5.83f, -2.61f, -5.83f, -5.83f,
+R_CUBIC_TO, 0, -1.82f, 0.84f, -3.45f, 2.15f, -4.52f,
+LINE_TO, 5.14f, 4.31f,
+CUBIC_TO, 3.53f, 5.68f, 2.5f, 7.72f, 2.5f, 10,
+R_CUBIC_TO, 0, 4.14f, 3.36f, 7.5f, 7.5f, 7.5f,
+R_CUBIC_TO, 4.14f, 0, 7.5f, -3.36f, 7.5f, -7.5f,
+R_CUBIC_TO, 0, -2.28f, -1.02f, -4.32f, -2.64f, -5.69f,
+CLOSE
diff --git a/ash/resources/vector_icons/shelf_sign_out_button.1x.icon b/ash/resources/vector_icons/shelf_sign_out_button.1x.icon
deleted file mode 100644
index 0d2816b..0000000
--- a/ash/resources/vector_icons/shelf_sign_out_button.1x.icon
+++ /dev/null
@@ -1,30 +0,0 @@
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 9.5f, 15,
-R_LINE_TO, 5, -5,
-R_LINE_TO, -5, -5,
-LINE_TO, 8, 6.5f,
-LINE_TO, 10.5f, 9,
-H_LINE_TO, 2,
-R_V_LINE_TO, 2,
-R_H_LINE_TO, 8.5f,
-LINE_TO, 8, 13.5f,
-LINE_TO, 9.5f, 15,
-CLOSE,
-MOVE_TO, 4, 2,
-R_CUBIC_TO, -0.99f, 0, -2, 1.02f, -2, 2,
-R_V_LINE_TO, 3.07f,
-R_H_LINE_TO, 2,
-V_LINE_TO, 4,
-R_H_LINE_TO, 12,
-R_V_LINE_TO, 12,
-H_LINE_TO, 4,
-R_V_LINE_TO, -3,
-H_LINE_TO, 2,
-R_V_LINE_TO, 3,
-R_CUBIC_TO, 0, 0.98f, 1.01f, 2, 2, 2,
-R_H_LINE_TO, 12,
-R_CUBIC_TO, 0.98f, 0, 2, -1.02f, 2, -2,
-V_LINE_TO, 4,
-R_CUBIC_TO, 0, -1, -1.02f, -2, -2, -2,
-H_LINE_TO, 4,
-CLOSE
diff --git a/ash/resources/vector_icons/shelf_sign_out_button.icon b/ash/resources/vector_icons/shelf_sign_out_button.icon
index cb67a00..bcbbe44 100644
--- a/ash/resources/vector_icons/shelf_sign_out_button.icon
+++ b/ash/resources/vector_icons/shelf_sign_out_button.icon
@@ -28,3 +28,34 @@
 CUBIC_TO, 35, 6.5f, 33.5f, 5, 31.67f, 5,
 H_LINE_TO, 8.33f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 9.5f, 15,
+R_LINE_TO, 5, -5,
+R_LINE_TO, -5, -5,
+LINE_TO, 8, 6.5f,
+LINE_TO, 10.5f, 9,
+H_LINE_TO, 2,
+R_V_LINE_TO, 2,
+R_H_LINE_TO, 8.5f,
+LINE_TO, 8, 13.5f,
+LINE_TO, 9.5f, 15,
+CLOSE,
+MOVE_TO, 4, 2,
+R_CUBIC_TO, -0.99f, 0, -2, 1.02f, -2, 2,
+R_V_LINE_TO, 3.07f,
+R_H_LINE_TO, 2,
+V_LINE_TO, 4,
+R_H_LINE_TO, 12,
+R_V_LINE_TO, 12,
+H_LINE_TO, 4,
+R_V_LINE_TO, -3,
+H_LINE_TO, 2,
+R_V_LINE_TO, 3,
+R_CUBIC_TO, 0, 0.98f, 1.01f, 2, 2, 2,
+R_H_LINE_TO, 12,
+R_CUBIC_TO, 0.98f, 0, 2, -1.02f, 2, -2,
+V_LINE_TO, 4,
+R_CUBIC_TO, 0, -1, -1.02f, -2, -2, -2,
+H_LINE_TO, 4,
+CLOSE
diff --git a/ash/resources/vector_icons/shelf_unlock_button.1x.icon b/ash/resources/vector_icons/shelf_unlock_button.1x.icon
deleted file mode 100644
index 6f02f39..0000000
--- a/ash/resources/vector_icons/shelf_unlock_button.1x.icon
+++ /dev/null
@@ -1,31 +0,0 @@
-CANVAS_DIMENSIONS, 24,
-MOVE_TO, 12, 17,
-R_CUBIC_TO, 1.1f, 0, 2, -0.9f, 2, -2,
-R_CUBIC_TO, 0, -1.1f, -0.9f, -2, -2, -2,
-R_CUBIC_TO, -1.1f, 0, -2, 0.9f, -2, 2,
-R_CUBIC_TO, 0, 1.1f, 0.9f, 2, 2, 2,
-CLOSE,
-R_MOVE_TO, 6, -9,
-R_H_LINE_TO, -1,
-V_LINE_TO, 6,
-R_CUBIC_TO, 0, -2.76f, -2.24f, -5, -5, -5,
-CUBIC_TO_SHORTHAND, 7, 3.24f, 7, 6,
-R_H_LINE_TO, 1.9f,
-R_CUBIC_TO, 0, -1.71f, 1.39f, -3.1f, 3.1f, -3.1f,
-R_CUBIC_TO, 1.71f, 0, 3.1f, 1.39f, 3.1f, 3.1f,
-R_V_LINE_TO, 2,
-H_LINE_TO, 6,
-R_CUBIC_TO, -1.1f, 0, -2, 0.9f, -2, 2,
-R_V_LINE_TO, 10,
-R_CUBIC_TO, 0, 1.1f, 0.9f, 2, 2, 2,
-R_H_LINE_TO, 12,
-R_CUBIC_TO, 1.1f, 0, 2, -0.9f, 2, -2,
-V_LINE_TO, 10,
-R_CUBIC_TO, 0, -1.1f, -0.9f, -2, -2, -2,
-CLOSE,
-R_MOVE_TO, 0, 12,
-H_LINE_TO, 6,
-V_LINE_TO, 10,
-R_H_LINE_TO, 12,
-R_V_LINE_TO, 10,
-CLOSE
diff --git a/ash/resources/vector_icons/shelf_unlock_button.icon b/ash/resources/vector_icons/shelf_unlock_button.icon
index 05d82af..a849daa8 100644
--- a/ash/resources/vector_icons/shelf_unlock_button.icon
+++ b/ash/resources/vector_icons/shelf_unlock_button.icon
@@ -29,3 +29,35 @@
 R_H_LINE_TO, 24,
 R_V_LINE_TO, 20,
 CLOSE
+
+CANVAS_DIMENSIONS, 24,
+MOVE_TO, 12, 17,
+R_CUBIC_TO, 1.1f, 0, 2, -0.9f, 2, -2,
+R_CUBIC_TO, 0, -1.1f, -0.9f, -2, -2, -2,
+R_CUBIC_TO, -1.1f, 0, -2, 0.9f, -2, 2,
+R_CUBIC_TO, 0, 1.1f, 0.9f, 2, 2, 2,
+CLOSE,
+R_MOVE_TO, 6, -9,
+R_H_LINE_TO, -1,
+V_LINE_TO, 6,
+R_CUBIC_TO, 0, -2.76f, -2.24f, -5, -5, -5,
+CUBIC_TO_SHORTHAND, 7, 3.24f, 7, 6,
+R_H_LINE_TO, 1.9f,
+R_CUBIC_TO, 0, -1.71f, 1.39f, -3.1f, 3.1f, -3.1f,
+R_CUBIC_TO, 1.71f, 0, 3.1f, 1.39f, 3.1f, 3.1f,
+R_V_LINE_TO, 2,
+H_LINE_TO, 6,
+R_CUBIC_TO, -1.1f, 0, -2, 0.9f, -2, 2,
+R_V_LINE_TO, 10,
+R_CUBIC_TO, 0, 1.1f, 0.9f, 2, 2, 2,
+R_H_LINE_TO, 12,
+R_CUBIC_TO, 1.1f, 0, 2, -0.9f, 2, -2,
+V_LINE_TO, 10,
+R_CUBIC_TO, 0, -1.1f, -0.9f, -2, -2, -2,
+CLOSE,
+R_MOVE_TO, 0, 12,
+H_LINE_TO, 6,
+V_LINE_TO, 10,
+R_H_LINE_TO, 12,
+R_V_LINE_TO, 10,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_accessibility.1x.icon b/ash/resources/vector_icons/system_menu_accessibility.1x.icon
deleted file mode 100644
index 1db087d..0000000
--- a/ash/resources/vector_icons/system_menu_accessibility.1x.icon
+++ /dev/null
@@ -1,24 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 10.04f, 6.27f,
-R_CUBIC_TO, -2.64f, 0, -4.46f, 0.24f, -7.61f, -1.15f,
-V_LINE_TO, 7,
-R_CUBIC_TO, 1.55f, 0.53f, 2.9f, 0.8f, 4.57f, 1,
-R_V_LINE_TO, 10,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, -5,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, 5,
-R_H_LINE_TO, 2,
-V_LINE_TO, 8,
-R_CUBIC_TO, 1.67f, -0.2f, 2.95f, -0.47f, 4.5f, -1,
-V_LINE_TO, 5.12f,
-R_CUBIC_TO, -2.88f, 1.34f, -4.82f, 1.15f, -7.46f, 1.15f,
-CLOSE,
-MOVE_TO, 10, 5,
-R_ARC_TO, 2, 2, 0, 1, 0, 0, -4,
-R_ARC_TO, 2, 2, 0, 0, 0, 0, 4,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_accessibility.icon b/ash/resources/vector_icons/system_menu_accessibility.icon
index c5033fb1..da0b113 100644
--- a/ash/resources/vector_icons/system_menu_accessibility.icon
+++ b/ash/resources/vector_icons/system_menu_accessibility.icon
@@ -22,3 +22,24 @@
 R_ARC_TO, 3.5f, 3.5f, 0, 1, 0, 0, -7,
 R_ARC_TO, 3.5f, 3.5f, 0, 0, 0, 0, 7,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 10.04f, 6.27f,
+R_CUBIC_TO, -2.64f, 0, -4.46f, 0.24f, -7.61f, -1.15f,
+V_LINE_TO, 7,
+R_CUBIC_TO, 1.55f, 0.53f, 2.9f, 0.8f, 4.57f, 1,
+R_V_LINE_TO, 10,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, -5,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 5,
+R_H_LINE_TO, 2,
+V_LINE_TO, 8,
+R_CUBIC_TO, 1.67f, -0.2f, 2.95f, -0.47f, 4.5f, -1,
+V_LINE_TO, 5.12f,
+R_CUBIC_TO, -2.88f, 1.34f, -4.82f, 1.15f, -7.46f, 1.15f,
+CLOSE,
+MOVE_TO, 10, 5,
+R_ARC_TO, 2, 2, 0, 1, 0, 0, -4,
+R_ARC_TO, 2, 2, 0, 0, 0, 0, 4,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_accessibility_auto_click.1x.icon b/ash/resources/vector_icons/system_menu_accessibility_auto_click.1x.icon
deleted file mode 100644
index 85c15d8e..0000000
--- a/ash/resources/vector_icons/system_menu_accessibility_auto_click.1x.icon
+++ /dev/null
@@ -1,47 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 13.47f, 9.55f,
-LINE_TO, 16, 11.81f,
-R_LINE_TO, -6, -0.52f,
-R_LINE_TO, 2.5f, 5.68f,
-LINE_TO, 10.75f, 18,
-R_LINE_TO, -2.5f, -5.93f,
-LINE_TO, 5, 17.23f,
-V_LINE_TO, 2,
-R_LINE_TO, 2.25f, 2.01f,
-CUBIC_TO, 7.09f, 4.47f, 7, 4.98f, 7, 5.5f,
-CUBIC_TO, 7, 7.99f, 9.02f, 10, 11.5f, 10,
-R_CUBIC_TO, 0.71f, 0, 1.37f, -0.16f, 1.97f, -0.45f,
-CLOSE,
-MOVE_TO, 10, 8,
-V_LINE_TO, 7,
-R_H_LINE_TO, 1,
-V_LINE_TO, 6,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-R_H_LINE_TO, 1,
-V_LINE_TO, 5,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 3,
-R_H_LINE_TO, -2,
-R_V_LINE_TO, 1,
-R_H_LINE_TO, -1,
-V_LINE_TO, 8,
-MOVE_TO, 13, 3,
-R_V_LINE_TO, 1,
-R_H_LINE_TO, -1,
-R_V_LINE_TO, 1,
-R_H_LINE_TO, -1,
-V_LINE_TO, 4,
-R_H_LINE_TO, -1,
-R_V_LINE_TO, 2,
-H_LINE_TO, 9,
-V_LINE_TO, 3,
-R_H_LINE_TO, 2,
-V_LINE_TO, 2,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_accessibility_auto_click.icon b/ash/resources/vector_icons/system_menu_accessibility_auto_click.icon
index b81c373..83bb63c 100644
--- a/ash/resources/vector_icons/system_menu_accessibility_auto_click.icon
+++ b/ash/resources/vector_icons/system_menu_accessibility_auto_click.icon
@@ -38,3 +38,47 @@
 R_CUBIC_TO, 2.86f, 0, 5.17f, -2.31f, 5.17f, -5.17f,
 R_CUBIC_TO, 0, -1.01f, -0.3f, -1.96f, -0.8f, -2.75f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 13.47f, 9.55f,
+LINE_TO, 16, 11.81f,
+R_LINE_TO, -6, -0.52f,
+R_LINE_TO, 2.5f, 5.68f,
+LINE_TO, 10.75f, 18,
+R_LINE_TO, -2.5f, -5.93f,
+LINE_TO, 5, 17.23f,
+V_LINE_TO, 2,
+R_LINE_TO, 2.25f, 2.01f,
+CUBIC_TO, 7.09f, 4.47f, 7, 4.98f, 7, 5.5f,
+CUBIC_TO, 7, 7.99f, 9.02f, 10, 11.5f, 10,
+R_CUBIC_TO, 0.71f, 0, 1.37f, -0.16f, 1.97f, -0.45f,
+CLOSE,
+MOVE_TO, 10, 8,
+V_LINE_TO, 7,
+R_H_LINE_TO, 1,
+V_LINE_TO, 6,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+R_H_LINE_TO, 1,
+V_LINE_TO, 5,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 3,
+R_H_LINE_TO, -2,
+R_V_LINE_TO, 1,
+R_H_LINE_TO, -1,
+V_LINE_TO, 8,
+MOVE_TO, 13, 3,
+R_V_LINE_TO, 1,
+R_H_LINE_TO, -1,
+R_V_LINE_TO, 1,
+R_H_LINE_TO, -1,
+V_LINE_TO, 4,
+R_H_LINE_TO, -1,
+R_V_LINE_TO, 2,
+H_LINE_TO, 9,
+V_LINE_TO, 3,
+R_H_LINE_TO, 2,
+V_LINE_TO, 2,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_accessibility_chromevox.1x.icon b/ash/resources/vector_icons/system_menu_accessibility_chromevox.1x.icon
deleted file mode 100644
index 0720f3b..0000000
--- a/ash/resources/vector_icons/system_menu_accessibility_chromevox.1x.icon
+++ /dev/null
@@ -1,41 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 10, 18,
-R_CUBIC_TO, -4.42f, 0, -8, -3.58f, -8, -8,
-R_CUBIC_TO, 0, -4.42f, 3.58f, -8, 8, -8,
-R_CUBIC_TO, 4.42f, 0, 8, 3.58f, 8, 8,
-R_CUBIC_TO, 0, 4.42f, -3.58f, 8, -8, 8,
-CLOSE,
-R_MOVE_TO, 1.9f, -10.76f,
-R_CUBIC_TO, 0.71f, 0.79f, 1.51f, 1.66f, 1.45f, 2.78f,
-R_CUBIC_TO, 0.07f, 1.13f, -0.67f, 2.05f, -1.43f, 2.81f,
-R_LINE_TO, 0.66f, 0.86f,
-R_CUBIC_TO, 1.26f, -0.83f, 2.04f, -2.31f, 1.94f, -3.81f,
-R_CUBIC_TO, -0.02f, -1.35f, -0.8f, -2.58f, -1.84f, -3.42f,
-R_CUBIC_TO, -0.26f, 0.26f, -0.51f, 0.53f, -0.76f, 0.79f,
-CLOSE,
-R_MOVE_TO, 4.53f, 4.56f,
-R_CUBIC_TO, 0.7f, -2.52f, -0.23f, -5.5f, -2.49f, -6.97f,
-R_CUBIC_TO, -0.24f, 0.31f, -0.47f, 0.61f, -0.7f, 0.92f,
-R_CUBIC_TO, 0.52f, 0.54f, 1.08f, 1.04f, 1.46f, 1.68f,
-R_CUBIC_TO, 0.92f, 1.54f, 0.97f, 3.54f, 0.1f, 5.1f,
-R_CUBIC_TO, -0.4f, 0.73f, -1.02f, 1.31f, -1.61f, 1.89f,
-R_CUBIC_TO, 0.22f, 0.32f, 0.45f, 0.63f, 0.68f, 0.94f,
-R_CUBIC_TO, 1.23f, -0.86f, 2.15f, -2.11f, 2.56f, -3.57f,
-CLOSE,
-MOVE_TO, 8.42f, 3.67f,
-R_CUBIC_TO, -2.92f, 0.7f, -5.09f, 3.28f, -5.09f, 6.36f,
-R_CUBIC_TO, 0, 2.66f, 1.62f, 4.94f, 3.93f, 5.97f,
-R_CUBIC_TO, 0.55f, -0.16f, 1.06f, -0.3f, 1.48f, -0.39f,
-R_CUBIC_TO, 0.21f, -1.04f, 0.33f, -2.1f, 0.38f, -3.16f,
-R_CUBIC_TO, -0.7f, -0.4f, -1.44f, -0.73f, -2.16f, -1.09f,
-R_CUBIC_TO, 0.84f, -0.16f, 1.68f, -0.29f, 2.5f, -0.52f,
-R_CUBIC_TO, 0.04f, -0.51f, 0.06f, -1.01f, 0.1f, -1.52f,
-R_CUBIC_TO, 0.51f, -0.33f, 1.02f, -0.66f, 1.54f, -0.98f,
-R_CUBIC_TO, -0.22f, -0.61f, -0.5f, -1.2f, -0.81f, -1.77f,
-R_CUBIC_TO, -0.53f, -0.95f, -0.95f, -1.96f, -1.54f, -2.88f,
-LINE_TO, 8.42f, 3.67f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_accessibility_chromevox.icon b/ash/resources/vector_icons/system_menu_accessibility_chromevox.icon
index 319b8bee..e7a110dd 100644
--- a/ash/resources/vector_icons/system_menu_accessibility_chromevox.icon
+++ b/ash/resources/vector_icons/system_menu_accessibility_chromevox.icon
@@ -39,3 +39,41 @@
 R_CUBIC_TO, -1.05f, -1.91f, -1.89f, -3.93f, -3.07f, -5.77f,
 R_CUBIC_TO, -0.22f, -0.01f, -0.45f, -0.02f, -0.69f, -0.03f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 10, 18,
+R_CUBIC_TO, -4.42f, 0, -8, -3.58f, -8, -8,
+R_CUBIC_TO, 0, -4.42f, 3.58f, -8, 8, -8,
+R_CUBIC_TO, 4.42f, 0, 8, 3.58f, 8, 8,
+R_CUBIC_TO, 0, 4.42f, -3.58f, 8, -8, 8,
+CLOSE,
+R_MOVE_TO, 1.9f, -10.76f,
+R_CUBIC_TO, 0.71f, 0.79f, 1.51f, 1.66f, 1.45f, 2.78f,
+R_CUBIC_TO, 0.07f, 1.13f, -0.67f, 2.05f, -1.43f, 2.81f,
+R_LINE_TO, 0.66f, 0.86f,
+R_CUBIC_TO, 1.26f, -0.83f, 2.04f, -2.31f, 1.94f, -3.81f,
+R_CUBIC_TO, -0.02f, -1.35f, -0.8f, -2.58f, -1.84f, -3.42f,
+R_CUBIC_TO, -0.26f, 0.26f, -0.51f, 0.53f, -0.76f, 0.79f,
+CLOSE,
+R_MOVE_TO, 4.53f, 4.56f,
+R_CUBIC_TO, 0.7f, -2.52f, -0.23f, -5.5f, -2.49f, -6.97f,
+R_CUBIC_TO, -0.24f, 0.31f, -0.47f, 0.61f, -0.7f, 0.92f,
+R_CUBIC_TO, 0.52f, 0.54f, 1.08f, 1.04f, 1.46f, 1.68f,
+R_CUBIC_TO, 0.92f, 1.54f, 0.97f, 3.54f, 0.1f, 5.1f,
+R_CUBIC_TO, -0.4f, 0.73f, -1.02f, 1.31f, -1.61f, 1.89f,
+R_CUBIC_TO, 0.22f, 0.32f, 0.45f, 0.63f, 0.68f, 0.94f,
+R_CUBIC_TO, 1.23f, -0.86f, 2.15f, -2.11f, 2.56f, -3.57f,
+CLOSE,
+MOVE_TO, 8.42f, 3.67f,
+R_CUBIC_TO, -2.92f, 0.7f, -5.09f, 3.28f, -5.09f, 6.36f,
+R_CUBIC_TO, 0, 2.66f, 1.62f, 4.94f, 3.93f, 5.97f,
+R_CUBIC_TO, 0.55f, -0.16f, 1.06f, -0.3f, 1.48f, -0.39f,
+R_CUBIC_TO, 0.21f, -1.04f, 0.33f, -2.1f, 0.38f, -3.16f,
+R_CUBIC_TO, -0.7f, -0.4f, -1.44f, -0.73f, -2.16f, -1.09f,
+R_CUBIC_TO, 0.84f, -0.16f, 1.68f, -0.29f, 2.5f, -0.52f,
+R_CUBIC_TO, 0.04f, -0.51f, 0.06f, -1.01f, 0.1f, -1.52f,
+R_CUBIC_TO, 0.51f, -0.33f, 1.02f, -0.66f, 1.54f, -0.98f,
+R_CUBIC_TO, -0.22f, -0.61f, -0.5f, -1.2f, -0.81f, -1.77f,
+R_CUBIC_TO, -0.53f, -0.95f, -0.95f, -1.96f, -1.54f, -2.88f,
+LINE_TO, 8.42f, 3.67f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_accessibility_contrast.1x.icon b/ash/resources/vector_icons/system_menu_accessibility_contrast.1x.icon
deleted file mode 100644
index 974f9352..0000000
--- a/ash/resources/vector_icons/system_menu_accessibility_contrast.1x.icon
+++ /dev/null
@@ -1,16 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 10, 18,
-R_CUBIC_TO, 4.42f, 0, 8, -3.58f, 8, -8,
-R_CUBIC_TO, 0, -4.42f, -3.58f, -8, -8, -8,
-R_CUBIC_TO, -4.42f, 0, -8, 3.58f, -8, 8,
-R_CUBIC_TO, 0, 4.42f, 3.58f, 8, 8, 8,
-CLOSE,
-R_MOVE_TO, 0, -14.12f,
-R_CUBIC_TO, 3.38f, 0, 6.12f, 2.74f, 6.12f, 6.12f,
-R_CUBIC_TO, 0, 3.38f, -2.74f, 6.12f, -6.12f, 6.12f,
-V_LINE_TO, 3.88f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_accessibility_contrast.icon b/ash/resources/vector_icons/system_menu_accessibility_contrast.icon
index c5f5813..90326a3 100644
--- a/ash/resources/vector_icons/system_menu_accessibility_contrast.icon
+++ b/ash/resources/vector_icons/system_menu_accessibility_contrast.icon
@@ -14,3 +14,16 @@
 CUBIC_TO_SHORTHAND, 26.76f, 32.24f, 20, 32.24f,
 V_LINE_TO, 7.77f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 10, 18,
+R_CUBIC_TO, 4.42f, 0, 8, -3.58f, 8, -8,
+R_CUBIC_TO, 0, -4.42f, -3.58f, -8, -8, -8,
+R_CUBIC_TO, -4.42f, 0, -8, 3.58f, -8, 8,
+R_CUBIC_TO, 0, 4.42f, 3.58f, 8, 8, 8,
+CLOSE,
+R_MOVE_TO, 0, -14.12f,
+R_CUBIC_TO, 3.38f, 0, 6.12f, 2.74f, 6.12f, 6.12f,
+R_CUBIC_TO, 0, 3.38f, -2.74f, 6.12f, -6.12f, 6.12f,
+V_LINE_TO, 3.88f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_accessibility_docked_magnifier.1x.icon b/ash/resources/vector_icons/system_menu_accessibility_docked_magnifier.1x.icon
deleted file mode 100644
index cb822666..0000000
--- a/ash/resources/vector_icons/system_menu_accessibility_docked_magnifier.1x.icon
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2018 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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 17.5f, 3,
-CUBIC_TO, 18.4f, 3, 19, 3.64f, 19, 4.5f,
-LINE_TO, 19, 15.5f,
-CUBIC_TO, 19, 16.36f, 18.4f, 17, 17.5f, 17,
-LINE_TO, 2.5f, 17,
-CUBIC_TO, 1.6f, 17, 1, 16.36f, 1, 15.5f,
-LINE_TO, 1, 4.56f,
-CUBIC_TO, 1, 3.7f, 1.6f, 3, 2.5f, 3,
-LINE_TO, 17.5f, 3,
-CLOSE,
-MOVE_TO, 17, 12,
-LINE_TO, 17, 5,
-LINE_TO, 3, 5,
-LINE_TO, 3, 12,
-LINE_TO, 17, 12,
-CLOSE,
-MOVE_TO, 14, 9,
-LINE_TO, 14, 11,
-LINE_TO, 13, 11,
-LINE_TO, 13, 9,
-LINE_TO, 11, 9,
-LINE_TO, 11, 8,
-LINE_TO, 13, 8,
-LINE_TO, 13, 6,
-LINE_TO, 14, 6,
-LINE_TO, 14, 8,
-LINE_TO, 16, 8,
-LINE_TO, 16, 9,
-LINE_TO, 14, 9,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_accessibility_docked_magnifier.icon b/ash/resources/vector_icons/system_menu_accessibility_docked_magnifier.icon
index b0f1f77..6c31024 100644
--- a/ash/resources/vector_icons/system_menu_accessibility_docked_magnifier.icon
+++ b/ash/resources/vector_icons/system_menu_accessibility_docked_magnifier.icon
@@ -33,3 +33,35 @@
 LINE_TO, 33, 16,
 LINE_TO, 30, 16,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 17.5f, 3,
+CUBIC_TO, 18.4f, 3, 19, 3.64f, 19, 4.5f,
+LINE_TO, 19, 15.5f,
+CUBIC_TO, 19, 16.36f, 18.4f, 17, 17.5f, 17,
+LINE_TO, 2.5f, 17,
+CUBIC_TO, 1.6f, 17, 1, 16.36f, 1, 15.5f,
+LINE_TO, 1, 4.56f,
+CUBIC_TO, 1, 3.7f, 1.6f, 3, 2.5f, 3,
+LINE_TO, 17.5f, 3,
+CLOSE,
+MOVE_TO, 17, 12,
+LINE_TO, 17, 5,
+LINE_TO, 3, 5,
+LINE_TO, 3, 12,
+LINE_TO, 17, 12,
+CLOSE,
+MOVE_TO, 14, 9,
+LINE_TO, 14, 11,
+LINE_TO, 13, 11,
+LINE_TO, 13, 9,
+LINE_TO, 11, 9,
+LINE_TO, 11, 8,
+LINE_TO, 13, 8,
+LINE_TO, 13, 6,
+LINE_TO, 14, 6,
+LINE_TO, 14, 8,
+LINE_TO, 16, 8,
+LINE_TO, 16, 9,
+LINE_TO, 14, 9,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_accessibility_fullscreen_magnifier.1x.icon b/ash/resources/vector_icons/system_menu_accessibility_fullscreen_magnifier.1x.icon
deleted file mode 100644
index e266dbdd..0000000
--- a/ash/resources/vector_icons/system_menu_accessibility_fullscreen_magnifier.1x.icon
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2018 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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 17.5f, 3,
-CUBIC_TO, 18.4f, 3, 19, 3.64f, 19, 4.5f,
-LINE_TO, 19, 15.5f,
-CUBIC_TO, 19, 16.36f, 18.4f, 17, 17.5f, 17,
-LINE_TO, 2.5f, 17,
-CUBIC_TO, 1.6f, 17, 1, 16.36f, 1, 15.5f,
-LINE_TO, 1, 4.56f,
-CUBIC_TO, 1, 3.7f, 1.6f, 3, 2.5f, 3,
-LINE_TO, 17.5f, 3,
-CLOSE,
-MOVE_TO, 17, 15,
-LINE_TO, 17, 5,
-LINE_TO, 3, 5,
-LINE_TO, 3, 15,
-LINE_TO, 17, 15,
-CLOSE,
-MOVE_TO, 14, 9,
-LINE_TO, 14, 11,
-LINE_TO, 13, 11,
-LINE_TO, 13, 9,
-LINE_TO, 11, 9,
-LINE_TO, 11, 8,
-LINE_TO, 13, 8,
-LINE_TO, 13, 6,
-LINE_TO, 14, 6,
-LINE_TO, 14, 8,
-LINE_TO, 16, 8,
-LINE_TO, 16, 9,
-LINE_TO, 14, 9,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_accessibility_fullscreen_magnifier.icon b/ash/resources/vector_icons/system_menu_accessibility_fullscreen_magnifier.icon
index 5bd7acb..d456d33 100644
--- a/ash/resources/vector_icons/system_menu_accessibility_fullscreen_magnifier.icon
+++ b/ash/resources/vector_icons/system_menu_accessibility_fullscreen_magnifier.icon
@@ -33,3 +33,35 @@
 LINE_TO, 33, 16,
 LINE_TO, 30, 16,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 17.5f, 3,
+CUBIC_TO, 18.4f, 3, 19, 3.64f, 19, 4.5f,
+LINE_TO, 19, 15.5f,
+CUBIC_TO, 19, 16.36f, 18.4f, 17, 17.5f, 17,
+LINE_TO, 2.5f, 17,
+CUBIC_TO, 1.6f, 17, 1, 16.36f, 1, 15.5f,
+LINE_TO, 1, 4.56f,
+CUBIC_TO, 1, 3.7f, 1.6f, 3, 2.5f, 3,
+LINE_TO, 17.5f, 3,
+CLOSE,
+MOVE_TO, 17, 15,
+LINE_TO, 17, 5,
+LINE_TO, 3, 5,
+LINE_TO, 3, 15,
+LINE_TO, 17, 15,
+CLOSE,
+MOVE_TO, 14, 9,
+LINE_TO, 14, 11,
+LINE_TO, 13, 11,
+LINE_TO, 13, 9,
+LINE_TO, 11, 9,
+LINE_TO, 11, 8,
+LINE_TO, 13, 8,
+LINE_TO, 13, 6,
+LINE_TO, 14, 6,
+LINE_TO, 14, 8,
+LINE_TO, 16, 8,
+LINE_TO, 16, 9,
+LINE_TO, 14, 9,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_accessibility_select_to_speak.1x.icon b/ash/resources/vector_icons/system_menu_accessibility_select_to_speak.1x.icon
deleted file mode 100644
index 12336cc..0000000
--- a/ash/resources/vector_icons/system_menu_accessibility_select_to_speak.1x.icon
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2018 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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 14, 14,
-LINE_TO, 13, 14,
-LINE_TO, 13, 15,
-LINE_TO, 15, 15,
-LINE_TO, 15, 14,
-LINE_TO, 15, 13,
-LINE_TO, 14, 13,
-LINE_TO, 14, 14,
-CLOSE,
-MOVE_TO, 6, 6,
-LINE_TO, 7, 6,
-LINE_TO, 7, 5,
-LINE_TO, 5, 5,
-LINE_TO, 5, 6,
-LINE_TO, 5, 7,
-LINE_TO, 6, 7,
-LINE_TO, 6, 6,
-CLOSE,
-MOVE_TO, 10, 18,
-CUBIC_TO, 5.58f, 18, 2, 14.42f, 2, 10,
-CUBIC_TO, 2, 5.58f, 5.58f, 2, 10, 2,
-CUBIC_TO, 14.42f, 2, 18, 5.58f, 18, 10,
-CUBIC_TO, 18, 14.42f, 14.42f, 18, 10, 18,
-CLOSE,
-MOVE_TO, 6, 8.63f,
-LINE_TO, 6, 11.37f,
-LINE_TO, 7.78f, 11.37f,
-LINE_TO, 10, 13.65f,
-LINE_TO, 10, 6.35f,
-LINE_TO, 7.78f, 8.63f,
-LINE_TO, 6, 8.63f,
-CLOSE,
-MOVE_TO, 12, 10,
-CUBIC_TO, 12, 9.19f, 11.55f, 8.5f, 10.89f, 8.16f,
-LINE_TO, 10.89f, 11.83f,
-CUBIC_TO, 11.55f, 11.5f, 12, 10.81f, 12, 10,
-CLOSE,
-MOVE_TO, 10.89f, 6,
-LINE_TO, 10.89f, 6.94f,
-CUBIC_TO, 12.17f, 7.33f, 13.11f, 8.55f, 13.11f, 10,
-CUBIC_TO, 13.11f, 11.45f, 12.17f, 12.67f, 10.89f, 13.06f,
-LINE_TO, 10.89f, 14,
-CUBIC_TO, 12.67f, 13.58f, 14, 11.95f, 14, 10,
-CUBIC_TO, 14, 8.05f, 12.67f, 6.42f, 10.89f, 6,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_accessibility_select_to_speak.icon b/ash/resources/vector_icons/system_menu_accessibility_select_to_speak.icon
index bdbc301c..e43b174 100644
--- a/ash/resources/vector_icons/system_menu_accessibility_select_to_speak.icon
+++ b/ash/resources/vector_icons/system_menu_accessibility_select_to_speak.icon
@@ -48,3 +48,50 @@
 CUBIC_TO, 25.34f, 27.17f, 28, 23.9f, 28, 20,
 CUBIC_TO, 28, 16.1f, 25.34f, 12.83f, 21.78f, 12,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 14, 14,
+LINE_TO, 13, 14,
+LINE_TO, 13, 15,
+LINE_TO, 15, 15,
+LINE_TO, 15, 14,
+LINE_TO, 15, 13,
+LINE_TO, 14, 13,
+LINE_TO, 14, 14,
+CLOSE,
+MOVE_TO, 6, 6,
+LINE_TO, 7, 6,
+LINE_TO, 7, 5,
+LINE_TO, 5, 5,
+LINE_TO, 5, 6,
+LINE_TO, 5, 7,
+LINE_TO, 6, 7,
+LINE_TO, 6, 6,
+CLOSE,
+MOVE_TO, 10, 18,
+CUBIC_TO, 5.58f, 18, 2, 14.42f, 2, 10,
+CUBIC_TO, 2, 5.58f, 5.58f, 2, 10, 2,
+CUBIC_TO, 14.42f, 2, 18, 5.58f, 18, 10,
+CUBIC_TO, 18, 14.42f, 14.42f, 18, 10, 18,
+CLOSE,
+MOVE_TO, 6, 8.63f,
+LINE_TO, 6, 11.37f,
+LINE_TO, 7.78f, 11.37f,
+LINE_TO, 10, 13.65f,
+LINE_TO, 10, 6.35f,
+LINE_TO, 7.78f, 8.63f,
+LINE_TO, 6, 8.63f,
+CLOSE,
+MOVE_TO, 12, 10,
+CUBIC_TO, 12, 9.19f, 11.55f, 8.5f, 10.89f, 8.16f,
+LINE_TO, 10.89f, 11.83f,
+CUBIC_TO, 11.55f, 11.5f, 12, 10.81f, 12, 10,
+CLOSE,
+MOVE_TO, 10.89f, 6,
+LINE_TO, 10.89f, 6.94f,
+CUBIC_TO, 12.17f, 7.33f, 13.11f, 8.55f, 13.11f, 10,
+CUBIC_TO, 13.11f, 11.45f, 12.17f, 12.67f, 10.89f, 13.06f,
+LINE_TO, 10.89f, 14,
+CUBIC_TO, 12.67f, 13.58f, 14, 11.95f, 14, 10,
+CUBIC_TO, 14, 8.05f, 12.67f, 6.42f, 10.89f, 6,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_add_connection.1x.icon b/ash/resources/vector_icons/system_menu_add_connection.1x.icon
deleted file mode 100644
index 534bcfbd..0000000
--- a/ash/resources/vector_icons/system_menu_add_connection.1x.icon
+++ /dev/null
@@ -1,25 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 10, 18,
-R_CUBIC_TO, 4.42f, 0, 8, -3.58f, 8, -8,
-R_CUBIC_TO, 0, -4.42f, -3.58f, -8, -8, -8,
-R_CUBIC_TO, -4.42f, 0, -8, 3.58f, -8, 8,
-R_CUBIC_TO, 0, 4.42f, 3.58f, 8, 8, 8,
-CLOSE,
-R_MOVE_TO, -1, -3,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, -4,
-R_H_LINE_TO, 4,
-R_V_LINE_TO, -2,
-R_H_LINE_TO, -4,
-R_V_LINE_TO, -4,
-R_H_LINE_TO, -2,
-R_V_LINE_TO, 4,
-R_H_LINE_TO, -4,
-R_V_LINE_TO, 2,
-R_H_LINE_TO, 4,
-R_V_LINE_TO, 4,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_add_connection.icon b/ash/resources/vector_icons/system_menu_add_connection.icon
index 33d74ed..81dec61 100644
--- a/ash/resources/vector_icons/system_menu_add_connection.icon
+++ b/ash/resources/vector_icons/system_menu_add_connection.icon
@@ -23,3 +23,25 @@
 R_H_LINE_TO, 7,
 R_V_LINE_TO, 7,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 10, 18,
+R_CUBIC_TO, 4.42f, 0, 8, -3.58f, 8, -8,
+R_CUBIC_TO, 0, -4.42f, -3.58f, -8, -8, -8,
+R_CUBIC_TO, -4.42f, 0, -8, 3.58f, -8, 8,
+R_CUBIC_TO, 0, 4.42f, 3.58f, 8, 8, 8,
+CLOSE,
+R_MOVE_TO, -1, -3,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, -4,
+R_H_LINE_TO, 4,
+R_V_LINE_TO, -2,
+R_H_LINE_TO, -4,
+R_V_LINE_TO, -4,
+R_H_LINE_TO, -2,
+R_V_LINE_TO, 4,
+R_H_LINE_TO, -4,
+R_V_LINE_TO, 2,
+R_H_LINE_TO, 4,
+R_V_LINE_TO, 4,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_arrow_back.1x.icon b/ash/resources/vector_icons/system_menu_arrow_back.1x.icon
deleted file mode 100644
index d45b7e6..0000000
--- a/ash/resources/vector_icons/system_menu_arrow_back.1x.icon
+++ /dev/null
@@ -1,15 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 7, 9,
-R_LINE_TO, 4, -4,
-R_LINE_TO, -1.5f, -1.5f,
-LINE_TO, 3, 10,
-R_LINE_TO, 6.5f, 6.5f,
-LINE_TO, 11, 15,
-R_LINE_TO, -4, -4,
-R_H_LINE_TO, 9,
-V_LINE_TO, 9,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_arrow_back.icon b/ash/resources/vector_icons/system_menu_arrow_back.icon
index 128b826..922d782 100644
--- a/ash/resources/vector_icons/system_menu_arrow_back.icon
+++ b/ash/resources/vector_icons/system_menu_arrow_back.icon
@@ -13,3 +13,15 @@
 H_LINE_TO, 33,
 R_V_LINE_TO, -3,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 7, 9,
+R_LINE_TO, 4, -4,
+R_LINE_TO, -1.5f, -1.5f,
+LINE_TO, 3, 10,
+R_LINE_TO, 6.5f, 6.5f,
+LINE_TO, 11, 15,
+R_LINE_TO, -4, -4,
+R_H_LINE_TO, 9,
+V_LINE_TO, 9,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_arrow_right.1x.icon b/ash/resources/vector_icons/system_menu_arrow_right.1x.icon
deleted file mode 100644
index 21b5b76..0000000
--- a/ash/resources/vector_icons/system_menu_arrow_right.1x.icon
+++ /dev/null
@@ -1,9 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 8, 14,
-R_LINE_TO, 4, -4,
-R_LINE_TO, -4, -4,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_arrow_right.icon b/ash/resources/vector_icons/system_menu_arrow_right.icon
index 5ea2cb4..f15761f9 100644
--- a/ash/resources/vector_icons/system_menu_arrow_right.icon
+++ b/ash/resources/vector_icons/system_menu_arrow_right.icon
@@ -7,3 +7,9 @@
 R_LINE_TO, 8, -8,
 R_LINE_TO, -8, -8,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 8, 14,
+R_LINE_TO, 4, -4,
+R_LINE_TO, -4, -4,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_audio_input.1x.icon b/ash/resources/vector_icons/system_menu_audio_input.1x.icon
deleted file mode 100644
index 384d224..0000000
--- a/ash/resources/vector_icons/system_menu_audio_input.1x.icon
+++ /dev/null
@@ -1,26 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 10, 7,
-R_LINE_TO, 3.5f, 4,
-H_LINE_TO, 11,
-R_V_LINE_TO, 7,
-H_LINE_TO, 9,
-R_V_LINE_TO, -7,
-H_LINE_TO, 6.5f,
-LINE_TO, 10, 7,
-CLOSE,
-R_MOVE_TO, -3.67f, 6.83f,
-ARC_TO, 5.65f, 5.65f, 0, 0, 1, 4.17f, 9.39f,
-R_CUBIC_TO, 0, -3.18f, 2.61f, -5.75f, 5.83f, -5.75f,
-R_CUBIC_TO, 3.22f, 0, 5.83f, 2.57f, 5.83f, 5.75f,
-R_ARC_TO, 5.7f, 5.7f, 0, 0, 1, -2.15f, 4.45f,
-LINE_TO, 14.86f, 15,
-R_CUBIC_TO, 1.62f, -1.35f, 2.64f, -3.36f, 2.64f, -5.61f,
-CUBIC_TO, 17.5f, 5.31f, 14.14f, 2, 10, 2,
-CUBIC_TO, 5.86f, 2, 2.5f, 5.31f, 2.5f, 9.39f,
-R_CUBIC_TO, 0, 2.25f, 1.02f, 4.25f, 2.64f, 5.61f,
-R_LINE_TO, 1.18f, -1.17f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_audio_input.icon b/ash/resources/vector_icons/system_menu_audio_input.icon
index 1cfda15c..8faf87f 100644
--- a/ash/resources/vector_icons/system_menu_audio_input.icon
+++ b/ash/resources/vector_icons/system_menu_audio_input.icon
@@ -24,3 +24,26 @@
 CUBIC_TO, 11.72f, 3, 5, 9.72f, 5, 18,
 R_CUBIC_TO, 0, 4.57f, 2.05f, 8.63f, 5.28f, 11.38f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 10, 7,
+R_LINE_TO, 3.5f, 4,
+H_LINE_TO, 11,
+R_V_LINE_TO, 7,
+H_LINE_TO, 9,
+R_V_LINE_TO, -7,
+H_LINE_TO, 6.5f,
+LINE_TO, 10, 7,
+CLOSE,
+R_MOVE_TO, -3.67f, 6.83f,
+ARC_TO, 5.65f, 5.65f, 0, 0, 1, 4.17f, 9.39f,
+R_CUBIC_TO, 0, -3.18f, 2.61f, -5.75f, 5.83f, -5.75f,
+R_CUBIC_TO, 3.22f, 0, 5.83f, 2.57f, 5.83f, 5.75f,
+R_ARC_TO, 5.7f, 5.7f, 0, 0, 1, -2.15f, 4.45f,
+LINE_TO, 14.86f, 15,
+R_CUBIC_TO, 1.62f, -1.35f, 2.64f, -3.36f, 2.64f, -5.61f,
+CUBIC_TO, 17.5f, 5.31f, 14.14f, 2, 10, 2,
+CUBIC_TO, 5.86f, 2, 2.5f, 5.31f, 2.5f, 9.39f,
+R_CUBIC_TO, 0, 2.25f, 1.02f, 4.25f, 2.64f, 5.61f,
+R_LINE_TO, 1.18f, -1.17f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_audio_output.1x.icon b/ash/resources/vector_icons/system_menu_audio_output.1x.icon
deleted file mode 100644
index 2d0b8066..0000000
--- a/ash/resources/vector_icons/system_menu_audio_output.1x.icon
+++ /dev/null
@@ -1,26 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 6.5f, 16,
-R_LINE_TO, 3.5f, 4,
-R_LINE_TO, 3.5f, -4,
-H_LINE_TO, 11,
-V_LINE_TO, 8,
-H_LINE_TO, 9,
-R_V_LINE_TO, 8,
-H_LINE_TO, 6.5f,
-CLOSE,
-R_MOVE_TO, -0.17f, -2.17f,
-ARC_TO, 5.65f, 5.65f, 0, 0, 1, 4.17f, 9.39f,
-R_CUBIC_TO, 0, -3.18f, 2.61f, -5.75f, 5.83f, -5.75f,
-R_CUBIC_TO, 3.22f, 0, 5.83f, 2.57f, 5.83f, 5.75f,
-R_ARC_TO, 5.7f, 5.7f, 0, 0, 1, -2.15f, 4.45f,
-LINE_TO, 14.86f, 15,
-R_CUBIC_TO, 1.62f, -1.35f, 2.64f, -3.36f, 2.64f, -5.61f,
-CUBIC_TO, 17.5f, 5.31f, 14.14f, 2, 10, 2,
-CUBIC_TO, 5.86f, 2, 2.5f, 5.31f, 2.5f, 9.39f,
-R_CUBIC_TO, 0, 2.25f, 1.02f, 4.25f, 2.64f, 5.61f,
-R_LINE_TO, 1.18f, -1.17f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_audio_output.icon b/ash/resources/vector_icons/system_menu_audio_output.icon
index 10e8663..b8d8f9a 100644
--- a/ash/resources/vector_icons/system_menu_audio_output.icon
+++ b/ash/resources/vector_icons/system_menu_audio_output.icon
@@ -24,3 +24,26 @@
 CUBIC_TO, 11.72f, 3, 5, 9.72f, 5, 18,
 R_CUBIC_TO, 0, 4.57f, 2.05f, 8.63f, 5.28f, 11.38f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 6.5f, 16,
+R_LINE_TO, 3.5f, 4,
+R_LINE_TO, 3.5f, -4,
+H_LINE_TO, 11,
+V_LINE_TO, 8,
+H_LINE_TO, 9,
+R_V_LINE_TO, 8,
+H_LINE_TO, 6.5f,
+CLOSE,
+R_MOVE_TO, -0.17f, -2.17f,
+ARC_TO, 5.65f, 5.65f, 0, 0, 1, 4.17f, 9.39f,
+R_CUBIC_TO, 0, -3.18f, 2.61f, -5.75f, 5.83f, -5.75f,
+R_CUBIC_TO, 3.22f, 0, 5.83f, 2.57f, 5.83f, 5.75f,
+R_ARC_TO, 5.7f, 5.7f, 0, 0, 1, -2.15f, 4.45f,
+LINE_TO, 14.86f, 15,
+R_CUBIC_TO, 1.62f, -1.35f, 2.64f, -3.36f, 2.64f, -5.61f,
+CUBIC_TO, 17.5f, 5.31f, 14.14f, 2, 10, 2,
+CUBIC_TO, 5.86f, 2, 2.5f, 5.31f, 2.5f, 9.39f,
+R_CUBIC_TO, 0, 2.25f, 1.02f, 4.25f, 2.64f, 5.61f,
+R_LINE_TO, 1.18f, -1.17f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_bluetooth.1x.icon b/ash/resources/vector_icons/system_menu_bluetooth.1x.icon
deleted file mode 100644
index 5b61141b..0000000
--- a/ash/resources/vector_icons/system_menu_bluetooth.1x.icon
+++ /dev/null
@@ -1,31 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 10.5f, 1.5f,
-R_H_LINE_TO, -1,
-V_LINE_TO, 8,
-LINE_TO, 5.69f, 4.17f,
-LINE_TO, 4.5f, 5.34f,
-LINE_TO, 9.5f, 10,
-R_LINE_TO, -5, 4.66f,
-R_LINE_TO, 1.19f, 1.09f,
-LINE_TO, 9.5f, 12,
-R_V_LINE_TO, 6.5f,
-R_H_LINE_TO, 1,
-R_LINE_TO, 4.5f, -5,
-R_LINE_TO, -3.5f, -3.5f,
-LINE_TO, 15, 6.5f,
-R_LINE_TO, -4.5f, -5,
-CLOSE,
-R_MOVE_TO, 0.77f, 3.36f,
-R_LINE_TO, 1.59f, 1.57f,
-R_LINE_TO, -1.59f, 1.57f,
-V_LINE_TO, 4.86f,
-CLOSE,
-R_MOVE_TO, 0, 10.28f,
-R_V_LINE_TO, -3.13f,
-R_LINE_TO, 1.59f, 1.57f,
-R_LINE_TO, -1.59f, 1.57f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_bluetooth.icon b/ash/resources/vector_icons/system_menu_bluetooth.icon
index fa4daafe..269cd39 100644
--- a/ash/resources/vector_icons/system_menu_bluetooth.icon
+++ b/ash/resources/vector_icons/system_menu_bluetooth.icon
@@ -29,3 +29,31 @@
 R_LINE_TO, 3.18f, 3.13f,
 R_LINE_TO, -3.18f, 3.13f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 10.5f, 1.5f,
+R_H_LINE_TO, -1,
+V_LINE_TO, 8,
+LINE_TO, 5.69f, 4.17f,
+LINE_TO, 4.5f, 5.34f,
+LINE_TO, 9.5f, 10,
+R_LINE_TO, -5, 4.66f,
+R_LINE_TO, 1.19f, 1.09f,
+LINE_TO, 9.5f, 12,
+R_V_LINE_TO, 6.5f,
+R_H_LINE_TO, 1,
+R_LINE_TO, 4.5f, -5,
+R_LINE_TO, -3.5f, -3.5f,
+LINE_TO, 15, 6.5f,
+R_LINE_TO, -4.5f, -5,
+CLOSE,
+R_MOVE_TO, 0.77f, 3.36f,
+R_LINE_TO, 1.59f, 1.57f,
+R_LINE_TO, -1.59f, 1.57f,
+V_LINE_TO, 4.86f,
+CLOSE,
+R_MOVE_TO, 0, 10.28f,
+R_V_LINE_TO, -3.13f,
+R_LINE_TO, 1.59f, 1.57f,
+R_LINE_TO, -1.59f, 1.57f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_bluetooth_connected.1x.icon b/ash/resources/vector_icons/system_menu_bluetooth_connected.1x.icon
deleted file mode 100644
index 8fa4f96..0000000
--- a/ash/resources/vector_icons/system_menu_bluetooth_connected.1x.icon
+++ /dev/null
@@ -1,43 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 10.5f, 1.5f,
-R_H_LINE_TO, -1,
-V_LINE_TO, 8,
-LINE_TO, 5.69f, 4.17f,
-LINE_TO, 4.5f, 5.34f,
-LINE_TO, 9.5f, 10,
-R_LINE_TO, -5, 4.66f,
-R_LINE_TO, 1.19f, 1.09f,
-LINE_TO, 9.5f, 12,
-R_V_LINE_TO, 6.5f,
-R_H_LINE_TO, 1,
-R_LINE_TO, 4.5f, -5,
-R_LINE_TO, -3.5f, -3.5f,
-LINE_TO, 15, 6.5f,
-R_LINE_TO, -4.5f, -5,
-CLOSE,
-MOVE_TO, 15, 10,
-R_LINE_TO, 2, -2,
-R_LINE_TO, 2, 2,
-R_LINE_TO, -2, 2,
-R_LINE_TO, -2, -2,
-CLOSE,
-MOVE_TO, 2, 10,
-R_LINE_TO, 2, -2,
-R_LINE_TO, 2, 2,
-R_LINE_TO, -2, 2,
-R_LINE_TO, -2, -2,
-CLOSE,
-R_MOVE_TO, 9.27f, -5.14f,
-R_LINE_TO, 1.59f, 1.57f,
-R_LINE_TO, -1.59f, 1.57f,
-V_LINE_TO, 4.86f,
-CLOSE,
-R_MOVE_TO, 0, 10.28f,
-R_V_LINE_TO, -3.13f,
-R_LINE_TO, 1.59f, 1.57f,
-R_LINE_TO, -1.59f, 1.57f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_bluetooth_connected.icon b/ash/resources/vector_icons/system_menu_bluetooth_connected.icon
index 94b7c40..caedab94 100644
--- a/ash/resources/vector_icons/system_menu_bluetooth_connected.icon
+++ b/ash/resources/vector_icons/system_menu_bluetooth_connected.icon
@@ -41,3 +41,43 @@
 R_LINE_TO, -3, 3,
 R_LINE_TO, -3, -3,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 10.5f, 1.5f,
+R_H_LINE_TO, -1,
+V_LINE_TO, 8,
+LINE_TO, 5.69f, 4.17f,
+LINE_TO, 4.5f, 5.34f,
+LINE_TO, 9.5f, 10,
+R_LINE_TO, -5, 4.66f,
+R_LINE_TO, 1.19f, 1.09f,
+LINE_TO, 9.5f, 12,
+R_V_LINE_TO, 6.5f,
+R_H_LINE_TO, 1,
+R_LINE_TO, 4.5f, -5,
+R_LINE_TO, -3.5f, -3.5f,
+LINE_TO, 15, 6.5f,
+R_LINE_TO, -4.5f, -5,
+CLOSE,
+MOVE_TO, 15, 10,
+R_LINE_TO, 2, -2,
+R_LINE_TO, 2, 2,
+R_LINE_TO, -2, 2,
+R_LINE_TO, -2, -2,
+CLOSE,
+MOVE_TO, 2, 10,
+R_LINE_TO, 2, -2,
+R_LINE_TO, 2, 2,
+R_LINE_TO, -2, 2,
+R_LINE_TO, -2, -2,
+CLOSE,
+R_MOVE_TO, 9.27f, -5.14f,
+R_LINE_TO, 1.59f, 1.57f,
+R_LINE_TO, -1.59f, 1.57f,
+V_LINE_TO, 4.86f,
+CLOSE,
+R_MOVE_TO, 0, 10.28f,
+R_V_LINE_TO, -3.13f,
+R_LINE_TO, 1.59f, 1.57f,
+R_LINE_TO, -1.59f, 1.57f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_bluetooth_disabled.1x.icon b/ash/resources/vector_icons/system_menu_bluetooth_disabled.1x.icon
deleted file mode 100644
index b166bd1b..0000000
--- a/ash/resources/vector_icons/system_menu_bluetooth_disabled.1x.icon
+++ /dev/null
@@ -1,34 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 12.84f, 6.43f,
-R_LINE_TO, -1.3f, 1.33f,
-R_LINE_TO, 1.15f, 1.18f,
-LINE_TO, 14.89f, 6.5f,
-R_LINE_TO, -4.39f, -5,
-R_H_LINE_TO, -0.97f,
-R_V_LINE_TO, 4.25f,
-R_LINE_TO, 1.79f, 1.78f,
-V_LINE_TO, 4.86f,
-R_LINE_TO, 1.53f, 1.57f,
-CLOSE,
-MOVE_TO, 4, 4.51f,
-LINE_TO, 9.53f, 10,
-R_LINE_TO, -4.71f, 4.66f,
-R_LINE_TO, 1.15f, 1.18f,
-LINE_TO, 9.53f, 12,
-R_V_LINE_TO, 6.5f,
-R_H_LINE_TO, 0.98f,
-R_LINE_TO, 3.49f, -3.74f,
-R_LINE_TO, 1.87f, 1.91f,
-LINE_TO, 17, 15.49f,
-LINE_TO, 5.15f, 3.33f,
-LINE_TO, 4, 4.51f,
-CLOSE,
-R_MOVE_TO, 7.31f, 7.5f,
-R_LINE_TO, 1.53f, 1.57f,
-R_LINE_TO, -1.53f, 1.57f,
-R_V_LINE_TO, -3.13f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_bluetooth_disabled.icon b/ash/resources/vector_icons/system_menu_bluetooth_disabled.icon
index d8f054a..3f19abd 100644
--- a/ash/resources/vector_icons/system_menu_bluetooth_disabled.icon
+++ b/ash/resources/vector_icons/system_menu_bluetooth_disabled.icon
@@ -32,3 +32,34 @@
 R_LINE_TO, -3.05f, 3.13f,
 R_V_LINE_TO, -6.27f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 12.84f, 6.43f,
+R_LINE_TO, -1.3f, 1.33f,
+R_LINE_TO, 1.15f, 1.18f,
+LINE_TO, 14.89f, 6.5f,
+R_LINE_TO, -4.39f, -5,
+R_H_LINE_TO, -0.97f,
+R_V_LINE_TO, 4.25f,
+R_LINE_TO, 1.79f, 1.78f,
+V_LINE_TO, 4.86f,
+R_LINE_TO, 1.53f, 1.57f,
+CLOSE,
+MOVE_TO, 4, 4.51f,
+LINE_TO, 9.53f, 10,
+R_LINE_TO, -4.71f, 4.66f,
+R_LINE_TO, 1.15f, 1.18f,
+LINE_TO, 9.53f, 12,
+R_V_LINE_TO, 6.5f,
+R_H_LINE_TO, 0.98f,
+R_LINE_TO, 3.49f, -3.74f,
+R_LINE_TO, 1.87f, 1.91f,
+LINE_TO, 17, 15.49f,
+LINE_TO, 5.15f, 3.33f,
+LINE_TO, 4, 4.51f,
+CLOSE,
+R_MOVE_TO, 7.31f, 7.5f,
+R_LINE_TO, 1.53f, 1.57f,
+R_LINE_TO, -1.53f, 1.57f,
+R_V_LINE_TO, -3.13f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_brightness.1x.icon b/ash/resources/vector_icons/system_menu_brightness.1x.icon
deleted file mode 100644
index 58eac7f..0000000
--- a/ash/resources/vector_icons/system_menu_brightness.1x.icon
+++ /dev/null
@@ -1,33 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 15, 5,
-R_H_LINE_TO, -2.5f,
-LINE_TO, 10, 2,
-LINE_TO, 7.5f, 5,
-H_LINE_TO, 5,
-R_V_LINE_TO, 2.5f,
-LINE_TO, 2, 10,
-R_LINE_TO, 3, 2.5f,
-V_LINE_TO, 15,
-R_H_LINE_TO, 2.5f,
-R_LINE_TO, 2.5f, 3,
-R_LINE_TO, 2.5f, -3,
-H_LINE_TO, 15,
-R_V_LINE_TO, -2.5f,
-R_LINE_TO, 3, -2.5f,
-R_LINE_TO, -3, -2.5f,
-V_LINE_TO, 5,
-CLOSE,
-R_MOVE_TO, -5, 9,
-R_CUBIC_TO, -2.21f, 0, -4, -1.79f, -4, -4,
-R_CUBIC_TO, 0, -2.21f, 1.79f, -4, 4, -4,
-R_CUBIC_TO, 2.21f, 0, 4, 1.79f, 4, 4,
-R_CUBIC_TO, 0, 2.21f, -1.79f, 4, -4, 4,
-CLOSE,
-R_MOVE_TO, 0, -1,
-R_ARC_TO, 3, 3, 0, 1, 0, 0, -6,
-R_ARC_TO, 3, 3, 0, 0, 0, 0, 6,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_brightness.icon b/ash/resources/vector_icons/system_menu_brightness.icon
index daa5d6e..610c48a2 100644
--- a/ash/resources/vector_icons/system_menu_brightness.icon
+++ b/ash/resources/vector_icons/system_menu_brightness.icon
@@ -31,3 +31,33 @@
 R_ARC_TO, 6, 6, 0, 1, 0, 0, -12,
 R_ARC_TO, 6, 6, 0, 0, 0, 0, 12,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 15, 5,
+R_H_LINE_TO, -2.5f,
+LINE_TO, 10, 2,
+LINE_TO, 7.5f, 5,
+H_LINE_TO, 5,
+R_V_LINE_TO, 2.5f,
+LINE_TO, 2, 10,
+R_LINE_TO, 3, 2.5f,
+V_LINE_TO, 15,
+R_H_LINE_TO, 2.5f,
+R_LINE_TO, 2.5f, 3,
+R_LINE_TO, 2.5f, -3,
+H_LINE_TO, 15,
+R_V_LINE_TO, -2.5f,
+R_LINE_TO, 3, -2.5f,
+R_LINE_TO, -3, -2.5f,
+V_LINE_TO, 5,
+CLOSE,
+R_MOVE_TO, -5, 9,
+R_CUBIC_TO, -2.21f, 0, -4, -1.79f, -4, -4,
+R_CUBIC_TO, 0, -2.21f, 1.79f, -4, 4, -4,
+R_CUBIC_TO, 2.21f, 0, 4, 1.79f, 4, 4,
+R_CUBIC_TO, 0, 2.21f, -1.79f, 4, -4, 4,
+CLOSE,
+R_MOVE_TO, 0, -1,
+R_ARC_TO, 3, 3, 0, 1, 0, 0, -6,
+R_ARC_TO, 3, 3, 0, 0, 0, 0, 6,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_business.1x.icon b/ash/resources/vector_icons/system_menu_business.1x.icon
deleted file mode 100644
index 8044ff29..0000000
--- a/ash/resources/vector_icons/system_menu_business.1x.icon
+++ /dev/null
@@ -1,61 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 2, 3,
-R_V_LINE_TO, 14,
-R_H_LINE_TO, 16,
-V_LINE_TO, 7,
-R_H_LINE_TO, -6,
-V_LINE_TO, 3,
-H_LINE_TO, 2,
-CLOSE,
-R_MOVE_TO, 6, 10,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, 2,
-H_LINE_TO, 8,
-R_V_LINE_TO, -2,
-CLOSE,
-R_MOVE_TO, -4, 0,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, 2,
-H_LINE_TO, 4,
-R_V_LINE_TO, -2,
-CLOSE,
-R_MOVE_TO, 4, -4,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, 2,
-H_LINE_TO, 8,
-V_LINE_TO, 9,
-CLOSE,
-MOVE_TO, 4, 9,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, 2,
-H_LINE_TO, 4,
-V_LINE_TO, 9,
-CLOSE,
-R_MOVE_TO, 8, 0,
-R_H_LINE_TO, 4,
-R_V_LINE_TO, 6,
-R_H_LINE_TO, -4,
-V_LINE_TO, 9,
-CLOSE,
-R_MOVE_TO, 0, 2,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, 2,
-R_H_LINE_TO, -2,
-R_V_LINE_TO, -2,
-CLOSE,
-MOVE_TO, 8, 5,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, 2,
-H_LINE_TO, 8,
-V_LINE_TO, 5,
-CLOSE,
-MOVE_TO, 4, 5,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, 2,
-H_LINE_TO, 4,
-V_LINE_TO, 5,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_business.icon b/ash/resources/vector_icons/system_menu_business.icon
index 433fba4..a130564 100644
--- a/ash/resources/vector_icons/system_menu_business.icon
+++ b/ash/resources/vector_icons/system_menu_business.icon
@@ -85,3 +85,61 @@
 R_H_LINE_TO, 3,
 R_V_LINE_TO, -3,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 2, 3,
+R_V_LINE_TO, 14,
+R_H_LINE_TO, 16,
+V_LINE_TO, 7,
+R_H_LINE_TO, -6,
+V_LINE_TO, 3,
+H_LINE_TO, 2,
+CLOSE,
+R_MOVE_TO, 6, 10,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 2,
+H_LINE_TO, 8,
+R_V_LINE_TO, -2,
+CLOSE,
+R_MOVE_TO, -4, 0,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 2,
+H_LINE_TO, 4,
+R_V_LINE_TO, -2,
+CLOSE,
+R_MOVE_TO, 4, -4,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 2,
+H_LINE_TO, 8,
+V_LINE_TO, 9,
+CLOSE,
+MOVE_TO, 4, 9,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 2,
+H_LINE_TO, 4,
+V_LINE_TO, 9,
+CLOSE,
+R_MOVE_TO, 8, 0,
+R_H_LINE_TO, 4,
+R_V_LINE_TO, 6,
+R_H_LINE_TO, -4,
+V_LINE_TO, 9,
+CLOSE,
+R_MOVE_TO, 0, 2,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 2,
+R_H_LINE_TO, -2,
+R_V_LINE_TO, -2,
+CLOSE,
+MOVE_TO, 8, 5,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 2,
+H_LINE_TO, 8,
+V_LINE_TO, 5,
+CLOSE,
+MOVE_TO, 4, 5,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 2,
+H_LINE_TO, 4,
+V_LINE_TO, 5,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_caps_lock.1x.icon b/ash/resources/vector_icons/system_menu_caps_lock.1x.icon
deleted file mode 100644
index e090c70..0000000
--- a/ash/resources/vector_icons/system_menu_caps_lock.1x.icon
+++ /dev/null
@@ -1,29 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 2, 3.99f,
-CUBIC_TO, 2, 2.89f, 2.9f, 2, 3.99f, 2,
-R_H_LINE_TO, 12.01f,
-CUBIC_TO, 17.11f, 2, 18, 2.9f, 18, 3.99f,
-R_V_LINE_TO, 12.01f,
-ARC_TO, 2, 2, 0, 0, 1, 16.01f, 18,
-H_LINE_TO, 3.99f,
-ARC_TO, 2, 2, 0, 0, 1, 2, 16.01f,
-V_LINE_TO, 3.99f,
-CLOSE,
-R_MOVE_TO, 8, 2.67f,
-LINE_TO, 13.83f, 11,
-LINE_TO, 15, 9.67f,
-LINE_TO, 10, 4,
-LINE_TO, 5, 9.67f,
-LINE_TO, 6.18f, 11,
-LINE_TO, 10, 6.66f,
-CLOSE,
-MOVE_TO, 5, 15,
-R_H_LINE_TO, 10,
-R_V_LINE_TO, -2,
-H_LINE_TO, 5,
-R_V_LINE_TO, 2,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_caps_lock.icon b/ash/resources/vector_icons/system_menu_caps_lock.icon
index 725eb542..ab1291fbb 100644
--- a/ash/resources/vector_icons/system_menu_caps_lock.icon
+++ b/ash/resources/vector_icons/system_menu_caps_lock.icon
@@ -27,3 +27,29 @@
 H_LINE_TO, 10,
 R_V_LINE_TO, 3,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 2, 3.99f,
+CUBIC_TO, 2, 2.89f, 2.9f, 2, 3.99f, 2,
+R_H_LINE_TO, 12.01f,
+CUBIC_TO, 17.11f, 2, 18, 2.9f, 18, 3.99f,
+R_V_LINE_TO, 12.01f,
+ARC_TO, 2, 2, 0, 0, 1, 16.01f, 18,
+H_LINE_TO, 3.99f,
+ARC_TO, 2, 2, 0, 0, 1, 2, 16.01f,
+V_LINE_TO, 3.99f,
+CLOSE,
+R_MOVE_TO, 8, 2.67f,
+LINE_TO, 13.83f, 11,
+LINE_TO, 15, 9.67f,
+LINE_TO, 10, 4,
+LINE_TO, 5, 9.67f,
+LINE_TO, 6.18f, 11,
+LINE_TO, 10, 6.66f,
+CLOSE,
+MOVE_TO, 5, 15,
+R_H_LINE_TO, 10,
+R_V_LINE_TO, -2,
+H_LINE_TO, 5,
+R_V_LINE_TO, 2,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_cast.1x.icon b/ash/resources/vector_icons/system_menu_cast.1x.icon
deleted file mode 100644
index 35401944..0000000
--- a/ash/resources/vector_icons/system_menu_cast.1x.icon
+++ /dev/null
@@ -1,37 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 2, 15.03f,
-V_LINE_TO, 17,
-R_H_LINE_TO, 2,
-R_CUBIC_TO, 0, -1.09f, -0.89f, -1.97f, -2, -1.97f,
-CLOSE,
-R_MOVE_TO, 0, -3.15f,
-R_V_LINE_TO, 1.46f,
-R_CUBIC_TO, 2.05f, 0, 3.71f, 1.64f, 3.71f, 3.66f,
-H_LINE_TO, 7.2f,
-R_CUBIC_TO, 0, -2.83f, -2.33f, -5.12f, -5.2f, -5.12f,
-CLOSE,
-MOVE_TO, 2, 9.12f,
-R_V_LINE_TO, 1.43f,
-R_CUBIC_TO, 3.62f, 0, 6.55f, 2.89f, 6.55f, 6.45f,
-H_LINE_TO, 10,
-R_CUBIC_TO, 0, -4.36f, -3.58f, -7.88f, -8, -7.88f,
-CLOSE,
-MOVE_TO, 3.46f, 4,
-CUBIC_TO, 2.66f, 4, 2, 4.65f, 2, 5.44f,
-V_LINE_TO, 8,
-R_H_LINE_TO, 2,
-V_LINE_TO, 6,
-R_H_LINE_TO, 12,
-R_V_LINE_TO, 9,
-R_H_LINE_TO, -5,
-R_V_LINE_TO, 2,
-R_H_LINE_TO, 5.55f,
-R_CUBIC_TO, 0.8f, 0, 1.46f, -0.65f, 1.46f, -1.44f,
-V_LINE_TO, 5.44f,
-CUBIC_TO, 18, 4.65f, 17.35f, 4, 16.55f, 4,
-H_LINE_TO, 3.46f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_cast.icon b/ash/resources/vector_icons/system_menu_cast.icon
index f9aa938..ed220b2 100644
--- a/ash/resources/vector_icons/system_menu_cast.icon
+++ b/ash/resources/vector_icons/system_menu_cast.icon
@@ -35,3 +35,37 @@
 CUBIC_TO, 36, 9.3f, 34.69f, 8, 33.09f, 8,
 H_LINE_TO, 6.91f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 2, 15.03f,
+V_LINE_TO, 17,
+R_H_LINE_TO, 2,
+R_CUBIC_TO, 0, -1.09f, -0.89f, -1.97f, -2, -1.97f,
+CLOSE,
+R_MOVE_TO, 0, -3.15f,
+R_V_LINE_TO, 1.46f,
+R_CUBIC_TO, 2.05f, 0, 3.71f, 1.64f, 3.71f, 3.66f,
+H_LINE_TO, 7.2f,
+R_CUBIC_TO, 0, -2.83f, -2.33f, -5.12f, -5.2f, -5.12f,
+CLOSE,
+MOVE_TO, 2, 9.12f,
+R_V_LINE_TO, 1.43f,
+R_CUBIC_TO, 3.62f, 0, 6.55f, 2.89f, 6.55f, 6.45f,
+H_LINE_TO, 10,
+R_CUBIC_TO, 0, -4.36f, -3.58f, -7.88f, -8, -7.88f,
+CLOSE,
+MOVE_TO, 3.46f, 4,
+CUBIC_TO, 2.66f, 4, 2, 4.65f, 2, 5.44f,
+V_LINE_TO, 8,
+R_H_LINE_TO, 2,
+V_LINE_TO, 6,
+R_H_LINE_TO, 12,
+R_V_LINE_TO, 9,
+R_H_LINE_TO, -5,
+R_V_LINE_TO, 2,
+R_H_LINE_TO, 5.55f,
+R_CUBIC_TO, 0.8f, 0, 1.46f, -0.65f, 1.46f, -1.44f,
+V_LINE_TO, 5.44f,
+CUBIC_TO, 18, 4.65f, 17.35f, 4, 16.55f, 4,
+H_LINE_TO, 3.46f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_cast_audio.1x.icon b/ash/resources/vector_icons/system_menu_cast_audio.1x.icon
deleted file mode 100644
index e02895b..0000000
--- a/ash/resources/vector_icons/system_menu_cast_audio.1x.icon
+++ /dev/null
@@ -1,33 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 14.29f, 2,
-H_LINE_TO, 5.71f,
-CUBIC_TO, 4.77f, 2, 4, 2.72f, 4, 3.6f,
-R_V_LINE_TO, 12.8f,
-R_CUBIC_TO, 0, 0.88f, 0.77f, 1.59f, 1.71f, 1.59f,
-R_LINE_TO, 8.57f, 0.01f,
-CUBIC_TO, 15.23f, 18, 16, 17.28f, 16, 16.4f,
-V_LINE_TO, 3.6f,
-R_CUBIC_TO, 0, -0.88f, -0.77f, -1.6f, -1.71f, -1.6f,
-CLOSE,
-MOVE_TO, 10, 3.5f,
-R_CUBIC_TO, 0.83f, 0, 1.5f, 0.68f, 1.5f, 1.5f,
-R_CUBIC_TO, 0, 0.82f, -0.67f, 1.5f, -1.5f, 1.5f,
-R_CUBIC_TO, -0.83f, 0, -1.5f, -0.67f, -1.5f, -1.5f,
-R_CUBIC_TO, 0, -0.83f, 0.67f, -1.5f, 1.5f, -1.5f,
-CLOSE,
-MOVE_TO, 10, 16,
-R_CUBIC_TO, -2.21f, 0, -4, -1.79f, -4, -4,
-R_CUBIC_TO, 0, -2.21f, 1.79f, -4, 4, -4,
-R_CUBIC_TO, 2.21f, 0, 4, 1.79f, 4, 4,
-R_CUBIC_TO, 0, 2.21f, -1.79f, 4, -4, 4,
-CLOSE,
-R_MOVE_TO, 0, -6,
-R_CUBIC_TO, -1.11f, 0, -2, 0.89f, -2, 2,
-R_CUBIC_TO, 0, 1.11f, 0.89f, 2, 2, 2,
-R_CUBIC_TO, 1.11f, 0, 2, -0.89f, 2, -2,
-R_CUBIC_TO, 0, -1.11f, -0.89f, -2, -2, -2,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_cast_audio.icon b/ash/resources/vector_icons/system_menu_cast_audio.icon
index b1f7e4e..056bcb8 100644
--- a/ash/resources/vector_icons/system_menu_cast_audio.icon
+++ b/ash/resources/vector_icons/system_menu_cast_audio.icon
@@ -31,3 +31,33 @@
 R_CUBIC_TO, 2.77f, 0, 5, -2.23f, 5, -5,
 R_CUBIC_TO, 0, -2.77f, -2.23f, -5, -5, -5,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 14.29f, 2,
+H_LINE_TO, 5.71f,
+CUBIC_TO, 4.77f, 2, 4, 2.72f, 4, 3.6f,
+R_V_LINE_TO, 12.8f,
+R_CUBIC_TO, 0, 0.88f, 0.77f, 1.59f, 1.71f, 1.59f,
+R_LINE_TO, 8.57f, 0.01f,
+CUBIC_TO, 15.23f, 18, 16, 17.28f, 16, 16.4f,
+V_LINE_TO, 3.6f,
+R_CUBIC_TO, 0, -0.88f, -0.77f, -1.6f, -1.71f, -1.6f,
+CLOSE,
+MOVE_TO, 10, 3.5f,
+R_CUBIC_TO, 0.83f, 0, 1.5f, 0.68f, 1.5f, 1.5f,
+R_CUBIC_TO, 0, 0.82f, -0.67f, 1.5f, -1.5f, 1.5f,
+R_CUBIC_TO, -0.83f, 0, -1.5f, -0.67f, -1.5f, -1.5f,
+R_CUBIC_TO, 0, -0.83f, 0.67f, -1.5f, 1.5f, -1.5f,
+CLOSE,
+MOVE_TO, 10, 16,
+R_CUBIC_TO, -2.21f, 0, -4, -1.79f, -4, -4,
+R_CUBIC_TO, 0, -2.21f, 1.79f, -4, 4, -4,
+R_CUBIC_TO, 2.21f, 0, 4, 1.79f, 4, 4,
+R_CUBIC_TO, 0, 2.21f, -1.79f, 4, -4, 4,
+CLOSE,
+R_MOVE_TO, 0, -6,
+R_CUBIC_TO, -1.11f, 0, -2, 0.89f, -2, 2,
+R_CUBIC_TO, 0, 1.11f, 0.89f, 2, 2, 2,
+R_CUBIC_TO, 1.11f, 0, 2, -0.89f, 2, -2,
+R_CUBIC_TO, 0, -1.11f, -0.89f, -2, -2, -2,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_cast_audio_group.1x.icon b/ash/resources/vector_icons/system_menu_cast_audio_group.1x.icon
deleted file mode 100644
index 7a67c1a..0000000
--- a/ash/resources/vector_icons/system_menu_cast_audio_group.1x.icon
+++ /dev/null
@@ -1,37 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 8.26f, 0,
-R_CUBIC_TO, -0.66f, 0, -1.2f, 0.68f, -1.2f, 1.5f,
-R_V_LINE_TO, 12,
-R_CUBIC_TO, 0, 0.83f, 0.54f, 1.49f, 1.2f, 1.49f,
-R_LINE_TO, 7.6f, 0.01f,
-R_CUBIC_TO, 0.66f, 0, 1.14f, -0.67f, 1.14f, -1.5f,
-R_V_LINE_TO, -12,
-R_CUBIC_TO, 0, -0.82f, -0.48f, -1.5f, -1.14f, -1.5f,
-R_H_LINE_TO, -7.6f,
-CLOSE,
-MOVE_TO, 12, 2.5f,
-R_CUBIC_TO, 0.83f, 0, 1.5f, 0.67f, 1.5f, 1.5f,
-R_CUBIC_TO, 0, 0.83f, -0.67f, 1.5f, -1.5f, 1.5f,
-R_CUBIC_TO, -0.83f, 0, -1.5f, -0.67f, -1.5f, -1.5f,
-R_CUBIC_TO, 0, -0.83f, 0.68f, -1.5f, 1.5f, -1.5f,
-CLOSE,
-MOVE_TO, 12, 13,
-R_CUBIC_TO, -1.66f, 0, -3, -1.34f, -3, -3,
-R_CUBIC_TO, 0, -1.66f, 1.34f, -3, 3, -3,
-R_CUBIC_TO, 1.66f, 0, 3, 1.34f, 3, 3,
-R_CUBIC_TO, 0, 1.66f, -1.34f, 3, -3, 3,
-CLOSE,
-CIRCLE, 12, 10, 2,
-MOVE_TO, 5, 4,
-H_LINE_TO, 3,
-R_V_LINE_TO, 13.33f,
-CUBIC_TO, 3, 18.25f, 3.74f, 19, 4.67f, 19,
-H_LINE_TO, 13,
-R_V_LINE_TO, -2,
-H_LINE_TO, 5,
-V_LINE_TO, 4,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_cast_audio_group.icon b/ash/resources/vector_icons/system_menu_cast_audio_group.icon
index 510789a..e9597f8 100644
--- a/ash/resources/vector_icons/system_menu_cast_audio_group.icon
+++ b/ash/resources/vector_icons/system_menu_cast_audio_group.icon
@@ -35,3 +35,37 @@
 H_LINE_TO, 10,
 V_LINE_TO, 8,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 8.26f, 0,
+R_CUBIC_TO, -0.66f, 0, -1.2f, 0.68f, -1.2f, 1.5f,
+R_V_LINE_TO, 12,
+R_CUBIC_TO, 0, 0.83f, 0.54f, 1.49f, 1.2f, 1.49f,
+R_LINE_TO, 7.6f, 0.01f,
+R_CUBIC_TO, 0.66f, 0, 1.14f, -0.67f, 1.14f, -1.5f,
+R_V_LINE_TO, -12,
+R_CUBIC_TO, 0, -0.82f, -0.48f, -1.5f, -1.14f, -1.5f,
+R_H_LINE_TO, -7.6f,
+CLOSE,
+MOVE_TO, 12, 2.5f,
+R_CUBIC_TO, 0.83f, 0, 1.5f, 0.67f, 1.5f, 1.5f,
+R_CUBIC_TO, 0, 0.83f, -0.67f, 1.5f, -1.5f, 1.5f,
+R_CUBIC_TO, -0.83f, 0, -1.5f, -0.67f, -1.5f, -1.5f,
+R_CUBIC_TO, 0, -0.83f, 0.68f, -1.5f, 1.5f, -1.5f,
+CLOSE,
+MOVE_TO, 12, 13,
+R_CUBIC_TO, -1.66f, 0, -3, -1.34f, -3, -3,
+R_CUBIC_TO, 0, -1.66f, 1.34f, -3, 3, -3,
+R_CUBIC_TO, 1.66f, 0, 3, 1.34f, 3, 3,
+R_CUBIC_TO, 0, 1.66f, -1.34f, 3, -3, 3,
+CLOSE,
+CIRCLE, 12, 10, 2,
+MOVE_TO, 5, 4,
+H_LINE_TO, 3,
+R_V_LINE_TO, 13.33f,
+CUBIC_TO, 3, 18.25f, 3.74f, 19, 4.67f, 19,
+H_LINE_TO, 13,
+R_V_LINE_TO, -2,
+H_LINE_TO, 5,
+V_LINE_TO, 4,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_cast_device.1x.icon b/ash/resources/vector_icons/system_menu_cast_device.1x.icon
deleted file mode 100644
index 82e40fe..0000000
--- a/ash/resources/vector_icons/system_menu_cast_device.1x.icon
+++ /dev/null
@@ -1,42 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 10, 2,
-R_CUBIC_TO, -4.42f, 0, -8, 3.58f, -8, 8,
-R_CUBIC_TO, 0, 4.42f, 3.58f, 8, 8, 8,
-R_CUBIC_TO, 4.42f, 0, 8, -3.58f, 8, -8,
-R_CUBIC_TO, 0, -4.42f, -3.58f, -8, -8, -8,
-CLOSE,
-R_MOVE_TO, 0, 1.6f,
-R_CUBIC_TO, 2.37f, 0, 4.43f, 1.29f, 5.54f, 3.2f,
-H_LINE_TO, 10,
-R_CUBIC_TO, -1.55f, 0, -2.84f, 1.1f, -3.14f, 2.57f,
-LINE_TO, 4.96f, 6.06f,
-CUBIC_TO, 6.13f, 4.57f, 7.95f, 3.6f, 10, 3.6f,
-CLOSE,
-R_MOVE_TO, 2.4f, 6.4f,
-R_CUBIC_TO, 0, 1.33f, -1.07f, 2.4f, -2.4f, 2.4f,
-R_CUBIC_TO, -1.33f, 0, -2.4f, -1.07f, -2.4f, -2.4f,
-R_CUBIC_TO, 0, -1.33f, 1.07f, -2.4f, 2.4f, -2.4f,
-R_CUBIC_TO, 1.33f, 0, 2.4f, 1.07f, 2.4f, 2.4f,
-CLOSE,
-R_MOVE_TO, -8.8f, 0,
-R_CUBIC_TO, 0, -1.17f, 0.32f, -2.26f, 0.86f, -3.19f,
-R_LINE_TO, 2.77f, 4.8f,
-R_LINE_TO, 0.01f, -0.01f,
-R_CUBIC_TO, 0.55f, 0.95f, 1.58f, 1.6f, 2.76f, 1.6f,
-R_CUBIC_TO, 0.36f, 0, 0.7f, -0.07f, 1.03f, -0.18f,
-R_LINE_TO, -1.91f, 3.32f,
-CUBIC_TO, 6, 15.9f, 3.6f, 13.23f, 3.6f, 10,
-CLOSE,
-R_MOVE_TO, 6.4f, 6.4f,
-R_LINE_TO, 2.77f, -4.8f,
-R_LINE_TO, -0.02f, -0.01f,
-R_CUBIC_TO, 0.28f, -0.47f, 0.45f, -1.01f, 0.45f, -1.59f,
-R_CUBIC_TO, 0, -0.96f, -0.43f, -1.82f, -1.1f, -2.4f,
-R_H_LINE_TO, 3.83f,
-R_CUBIC_TO, 0.3f, 0.74f, 0.47f, 1.55f, 0.47f, 2.4f,
-R_CUBIC_TO, 0, 3.54f, -2.86f, 6.4f, -6.4f, 6.4f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_cast_device.icon b/ash/resources/vector_icons/system_menu_cast_device.icon
index 9c633d8..8eb66f4 100644
--- a/ash/resources/vector_icons/system_menu_cast_device.icon
+++ b/ash/resources/vector_icons/system_menu_cast_device.icon
@@ -40,3 +40,42 @@
 R_CUBIC_TO, 0.61f, 1.49f, 0.94f, 3.1f, 0.94f, 4.8f,
 R_CUBIC_TO, 0, 7.07f, -5.73f, 12.8f, -12.8f, 12.8f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 10, 2,
+R_CUBIC_TO, -4.42f, 0, -8, 3.58f, -8, 8,
+R_CUBIC_TO, 0, 4.42f, 3.58f, 8, 8, 8,
+R_CUBIC_TO, 4.42f, 0, 8, -3.58f, 8, -8,
+R_CUBIC_TO, 0, -4.42f, -3.58f, -8, -8, -8,
+CLOSE,
+R_MOVE_TO, 0, 1.6f,
+R_CUBIC_TO, 2.37f, 0, 4.43f, 1.29f, 5.54f, 3.2f,
+H_LINE_TO, 10,
+R_CUBIC_TO, -1.55f, 0, -2.84f, 1.1f, -3.14f, 2.57f,
+LINE_TO, 4.96f, 6.06f,
+CUBIC_TO, 6.13f, 4.57f, 7.95f, 3.6f, 10, 3.6f,
+CLOSE,
+R_MOVE_TO, 2.4f, 6.4f,
+R_CUBIC_TO, 0, 1.33f, -1.07f, 2.4f, -2.4f, 2.4f,
+R_CUBIC_TO, -1.33f, 0, -2.4f, -1.07f, -2.4f, -2.4f,
+R_CUBIC_TO, 0, -1.33f, 1.07f, -2.4f, 2.4f, -2.4f,
+R_CUBIC_TO, 1.33f, 0, 2.4f, 1.07f, 2.4f, 2.4f,
+CLOSE,
+R_MOVE_TO, -8.8f, 0,
+R_CUBIC_TO, 0, -1.17f, 0.32f, -2.26f, 0.86f, -3.19f,
+R_LINE_TO, 2.77f, 4.8f,
+R_LINE_TO, 0.01f, -0.01f,
+R_CUBIC_TO, 0.55f, 0.95f, 1.58f, 1.6f, 2.76f, 1.6f,
+R_CUBIC_TO, 0.36f, 0, 0.7f, -0.07f, 1.03f, -0.18f,
+R_LINE_TO, -1.91f, 3.32f,
+CUBIC_TO, 6, 15.9f, 3.6f, 13.23f, 3.6f, 10,
+CLOSE,
+R_MOVE_TO, 6.4f, 6.4f,
+R_LINE_TO, 2.77f, -4.8f,
+R_LINE_TO, -0.02f, -0.01f,
+R_CUBIC_TO, 0.28f, -0.47f, 0.45f, -1.01f, 0.45f, -1.59f,
+R_CUBIC_TO, 0, -0.96f, -0.43f, -1.82f, -1.1f, -2.4f,
+R_H_LINE_TO, 3.83f,
+R_CUBIC_TO, 0.3f, 0.74f, 0.47f, 1.55f, 0.47f, 2.4f,
+R_CUBIC_TO, 0, 3.54f, -2.86f, 6.4f, -6.4f, 6.4f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_cast_education.1x.icon b/ash/resources/vector_icons/system_menu_cast_education.1x.icon
deleted file mode 100644
index 34da227a..0000000
--- a/ash/resources/vector_icons/system_menu_cast_education.1x.icon
+++ /dev/null
@@ -1,51 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 17.36f, 3,
-H_LINE_TO, 2.64f,
-CUBIC_TO, 1.74f, 3, 1, 3.7f, 1, 4.56f,
-V_LINE_TO, 6.89f,
-R_H_LINE_TO, 1.64f,
-V_LINE_TO, 4.56f,
-R_H_LINE_TO, 14.73f,
-R_V_LINE_TO, 10.89f,
-R_H_LINE_TO, -5.73f,
-V_LINE_TO, 17,
-R_H_LINE_TO, 5.73f,
-R_CUBIC_TO, 0.9f, 0, 1.64f, -0.7f, 1.64f, -1.56f,
-V_LINE_TO, 4.56f,
-CUBIC_TO, 19, 3.7f, 18.26f, 3, 17.36f, 3,
-CLOSE,
-MOVE_TO, 1, 14.67f,
-V_LINE_TO, 17,
-R_H_LINE_TO, 2.46f,
-R_CUBIC_TO, 0, -1.29f, -1.1f, -2.33f, -2.45f, -2.33f,
-CLOSE,
-R_MOVE_TO, 0, -3.11f,
-R_V_LINE_TO, 1.55f,
-R_CUBIC_TO, 2.26f, 0, 4.09f, 1.74f, 4.09f, 3.89f,
-R_H_LINE_TO, 1.64f,
-R_CUBIC_TO, 0, -3.01f, -2.56f, -5.44f, -5.73f, -5.44f,
-CLOSE,
-R_MOVE_TO, 0, -3.11f,
-V_LINE_TO, 10,
-R_CUBIC_TO, 4.07f, 0, 7.36f, 3.13f, 7.36f, 7,
-H_LINE_TO, 10,
-R_CUBIC_TO, 0, -4.73f, -4.03f, -8.56f, -9, -8.56f,
-CLOSE,
-R_MOVE_TO, 8.18f, 0.85f,
-R_V_LINE_TO, 1.56f,
-R_LINE_TO, 2.86f, 1.49f,
-R_LINE_TO, 2.86f, -1.48f,
-V_LINE_TO, 9.29f,
-R_LINE_TO, -2.86f, 1.49f,
-R_LINE_TO, -2.86f, -1.49f,
-CLOSE,
-R_MOVE_TO, 2.86f, -3.96f,
-R_LINE_TO, -4.5f, 2.34f,
-R_LINE_TO, 4.5f, 2.33f,
-R_LINE_TO, 4.5f, -2.33f,
-R_LINE_TO, -4.5f, -2.33f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_cast_education.icon b/ash/resources/vector_icons/system_menu_cast_education.icon
index e4fde4e..f48b3fb 100644
--- a/ash/resources/vector_icons/system_menu_cast_education.icon
+++ b/ash/resources/vector_icons/system_menu_cast_education.icon
@@ -49,3 +49,51 @@
 R_LINE_TO, 9, -4.67f,
 R_LINE_TO, -9, -4.67f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 17.36f, 3,
+H_LINE_TO, 2.64f,
+CUBIC_TO, 1.74f, 3, 1, 3.7f, 1, 4.56f,
+V_LINE_TO, 6.89f,
+R_H_LINE_TO, 1.64f,
+V_LINE_TO, 4.56f,
+R_H_LINE_TO, 14.73f,
+R_V_LINE_TO, 10.89f,
+R_H_LINE_TO, -5.73f,
+V_LINE_TO, 17,
+R_H_LINE_TO, 5.73f,
+R_CUBIC_TO, 0.9f, 0, 1.64f, -0.7f, 1.64f, -1.56f,
+V_LINE_TO, 4.56f,
+CUBIC_TO, 19, 3.7f, 18.26f, 3, 17.36f, 3,
+CLOSE,
+MOVE_TO, 1, 14.67f,
+V_LINE_TO, 17,
+R_H_LINE_TO, 2.46f,
+R_CUBIC_TO, 0, -1.29f, -1.1f, -2.33f, -2.45f, -2.33f,
+CLOSE,
+R_MOVE_TO, 0, -3.11f,
+R_V_LINE_TO, 1.55f,
+R_CUBIC_TO, 2.26f, 0, 4.09f, 1.74f, 4.09f, 3.89f,
+R_H_LINE_TO, 1.64f,
+R_CUBIC_TO, 0, -3.01f, -2.56f, -5.44f, -5.73f, -5.44f,
+CLOSE,
+R_MOVE_TO, 0, -3.11f,
+V_LINE_TO, 10,
+R_CUBIC_TO, 4.07f, 0, 7.36f, 3.13f, 7.36f, 7,
+H_LINE_TO, 10,
+R_CUBIC_TO, 0, -4.73f, -4.03f, -8.56f, -9, -8.56f,
+CLOSE,
+R_MOVE_TO, 8.18f, 0.85f,
+R_V_LINE_TO, 1.56f,
+R_LINE_TO, 2.86f, 1.49f,
+R_LINE_TO, 2.86f, -1.48f,
+V_LINE_TO, 9.29f,
+R_LINE_TO, -2.86f, 1.49f,
+R_LINE_TO, -2.86f, -1.49f,
+CLOSE,
+R_MOVE_TO, 2.86f, -3.96f,
+R_LINE_TO, -4.5f, 2.34f,
+R_LINE_TO, 4.5f, 2.33f,
+R_LINE_TO, 4.5f, -2.33f,
+R_LINE_TO, -4.5f, -2.33f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_cast_enabled.1x.icon b/ash/resources/vector_icons/system_menu_cast_enabled.1x.icon
deleted file mode 100644
index cdefe94..0000000
--- a/ash/resources/vector_icons/system_menu_cast_enabled.1x.icon
+++ /dev/null
@@ -1,44 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 2, 15.03f,
-V_LINE_TO, 17,
-R_H_LINE_TO, 2,
-R_CUBIC_TO, 0, -1.09f, -0.89f, -1.97f, -2, -1.97f,
-CLOSE,
-R_MOVE_TO, 0, -3.15f,
-R_V_LINE_TO, 1.46f,
-R_CUBIC_TO, 2.05f, 0, 3.71f, 1.64f, 3.71f, 3.66f,
-H_LINE_TO, 7.2f,
-R_CUBIC_TO, 0, -2.83f, -2.33f, -5.12f, -5.2f, -5.12f,
-CLOSE,
-MOVE_TO, 2, 9.12f,
-R_V_LINE_TO, 1.43f,
-R_CUBIC_TO, 3.62f, 0, 6.55f, 2.89f, 6.55f, 6.45f,
-H_LINE_TO, 10,
-R_CUBIC_TO, 0, -4.36f, -3.58f, -7.88f, -8, -7.88f,
-CLOSE,
-MOVE_TO, 3.46f, 4,
-CUBIC_TO, 2.66f, 4, 2, 4.65f, 2, 5.44f,
-V_LINE_TO, 8,
-R_H_LINE_TO, 2,
-V_LINE_TO, 6,
-R_H_LINE_TO, 12,
-R_V_LINE_TO, 9,
-R_H_LINE_TO, -5,
-R_V_LINE_TO, 2,
-R_H_LINE_TO, 5.55f,
-R_CUBIC_TO, 0.8f, 0, 1.46f, -0.65f, 1.46f, -1.44f,
-V_LINE_TO, 5.44f,
-CUBIC_TO, 18, 4.65f, 17.35f, 4, 16.55f, 4,
-H_LINE_TO, 3.46f,
-CLOSE,
-MOVE_TO, 5, 7,
-R_V_LINE_TO, 1.31f,
-R_CUBIC_TO, 3.13f, 0.44f, 5.42f, 4.16f, 6.04f, 5.69f,
-H_LINE_TO, 15,
-V_LINE_TO, 7,
-H_LINE_TO, 5,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_cast_enabled.icon b/ash/resources/vector_icons/system_menu_cast_enabled.icon
index 6efd4ab..75a9239 100644
--- a/ash/resources/vector_icons/system_menu_cast_enabled.icon
+++ b/ash/resources/vector_icons/system_menu_cast_enabled.icon
@@ -42,3 +42,44 @@
 V_LINE_TO, 14,
 H_LINE_TO, 10,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 2, 15.03f,
+V_LINE_TO, 17,
+R_H_LINE_TO, 2,
+R_CUBIC_TO, 0, -1.09f, -0.89f, -1.97f, -2, -1.97f,
+CLOSE,
+R_MOVE_TO, 0, -3.15f,
+R_V_LINE_TO, 1.46f,
+R_CUBIC_TO, 2.05f, 0, 3.71f, 1.64f, 3.71f, 3.66f,
+H_LINE_TO, 7.2f,
+R_CUBIC_TO, 0, -2.83f, -2.33f, -5.12f, -5.2f, -5.12f,
+CLOSE,
+MOVE_TO, 2, 9.12f,
+R_V_LINE_TO, 1.43f,
+R_CUBIC_TO, 3.62f, 0, 6.55f, 2.89f, 6.55f, 6.45f,
+H_LINE_TO, 10,
+R_CUBIC_TO, 0, -4.36f, -3.58f, -7.88f, -8, -7.88f,
+CLOSE,
+MOVE_TO, 3.46f, 4,
+CUBIC_TO, 2.66f, 4, 2, 4.65f, 2, 5.44f,
+V_LINE_TO, 8,
+R_H_LINE_TO, 2,
+V_LINE_TO, 6,
+R_H_LINE_TO, 12,
+R_V_LINE_TO, 9,
+R_H_LINE_TO, -5,
+R_V_LINE_TO, 2,
+R_H_LINE_TO, 5.55f,
+R_CUBIC_TO, 0.8f, 0, 1.46f, -0.65f, 1.46f, -1.44f,
+V_LINE_TO, 5.44f,
+CUBIC_TO, 18, 4.65f, 17.35f, 4, 16.55f, 4,
+H_LINE_TO, 3.46f,
+CLOSE,
+MOVE_TO, 5, 7,
+R_V_LINE_TO, 1.31f,
+R_CUBIC_TO, 3.13f, 0.44f, 5.42f, 4.16f, 6.04f, 5.69f,
+H_LINE_TO, 15,
+V_LINE_TO, 7,
+H_LINE_TO, 5,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_cast_generic.1x.icon b/ash/resources/vector_icons/system_menu_cast_generic.1x.icon
deleted file mode 100644
index 96b67ab0..0000000
--- a/ash/resources/vector_icons/system_menu_cast_generic.1x.icon
+++ /dev/null
@@ -1,25 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 17.5f, 3,
-R_H_LINE_TO, -15,
-CUBIC_TO, 1.6f, 3, 1, 3.7f, 1, 4.56f,
-V_LINE_TO, 13.5f,
-R_CUBIC_TO, 0, 0.86f, 0.6f, 1.5f, 1.5f, 1.5f,
-H_LINE_TO, 7,
-R_V_LINE_TO, 2,
-R_H_LINE_TO, 6,
-R_V_LINE_TO, -2,
-R_H_LINE_TO, 4.5f,
-R_CUBIC_TO, 0.9f, 0, 1.5f, -0.64f, 1.5f, -1.5f,
-R_V_LINE_TO, -9,
-R_CUBIC_TO, 0, -0.86f, -0.6f, -1.5f, -1.5f, -1.5f,
-CLOSE,
-R_MOVE_TO, 0, 10.5f,
-R_H_LINE_TO, -15,
-V_LINE_TO, 4.56f,
-R_H_LINE_TO, 15,
-V_LINE_TO, 13.5f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_cast_generic.icon b/ash/resources/vector_icons/system_menu_cast_generic.icon
index 5c8a6703..b9188ca3 100644
--- a/ash/resources/vector_icons/system_menu_cast_generic.icon
+++ b/ash/resources/vector_icons/system_menu_cast_generic.icon
@@ -23,3 +23,25 @@
 R_H_LINE_TO, 30,
 R_V_LINE_TO, 18,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 17.5f, 3,
+R_H_LINE_TO, -15,
+CUBIC_TO, 1.6f, 3, 1, 3.7f, 1, 4.56f,
+V_LINE_TO, 13.5f,
+R_CUBIC_TO, 0, 0.86f, 0.6f, 1.5f, 1.5f, 1.5f,
+H_LINE_TO, 7,
+R_V_LINE_TO, 2,
+R_H_LINE_TO, 6,
+R_V_LINE_TO, -2,
+R_H_LINE_TO, 4.5f,
+R_CUBIC_TO, 0.9f, 0, 1.5f, -0.64f, 1.5f, -1.5f,
+R_V_LINE_TO, -9,
+R_CUBIC_TO, 0, -0.86f, -0.6f, -1.5f, -1.5f, -1.5f,
+CLOSE,
+R_MOVE_TO, 0, 10.5f,
+R_H_LINE_TO, -15,
+V_LINE_TO, 4.56f,
+R_H_LINE_TO, 15,
+V_LINE_TO, 13.5f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_cast_hangout.1x.icon b/ash/resources/vector_icons/system_menu_cast_hangout.1x.icon
deleted file mode 100644
index df91815..0000000
--- a/ash/resources/vector_icons/system_menu_cast_hangout.1x.icon
+++ /dev/null
@@ -1,31 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 10, 2,
-CUBIC_TO, 6.14f, 2, 3, 4.97f, 3, 8.63f,
-R_CUBIC_TO, 0, 3.66f, 3.14f, 6.63f, 7, 6.63f,
-R_H_LINE_TO, 0.41f,
-V_LINE_TO, 18,
-CUBIC_TO, 14.41f, 16.17f, 17, 12.15f, 17, 8.63f,
-CUBIC_TO, 17, 4.97f, 13.86f, 2, 10, 2,
-CLOSE,
-R_MOVE_TO, -0.41f, 7.02f,
-R_LINE_TO, -0.82f, 1.56f,
-H_LINE_TO, 7.53f,
-R_LINE_TO, 0.82f, -1.56f,
-H_LINE_TO, 7.12f,
-R_V_LINE_TO, -2.34f,
-R_H_LINE_TO, 2.47f,
-R_V_LINE_TO, 2.34f,
-CLOSE,
-R_MOVE_TO, 3.29f, 0,
-R_LINE_TO, -0.82f, 1.56f,
-R_H_LINE_TO, -1.24f,
-R_LINE_TO, 0.82f, -1.56f,
-R_H_LINE_TO, -1.24f,
-R_V_LINE_TO, -2.34f,
-R_H_LINE_TO, 2.47f,
-R_V_LINE_TO, 2.34f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_cast_hangout.icon b/ash/resources/vector_icons/system_menu_cast_hangout.icon
index 3edba278..6b7509b 100644
--- a/ash/resources/vector_icons/system_menu_cast_hangout.icon
+++ b/ash/resources/vector_icons/system_menu_cast_hangout.icon
@@ -29,3 +29,31 @@
 R_H_LINE_TO, 5,
 R_V_LINE_TO, 5,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 10, 2,
+CUBIC_TO, 6.14f, 2, 3, 4.97f, 3, 8.63f,
+R_CUBIC_TO, 0, 3.66f, 3.14f, 6.63f, 7, 6.63f,
+R_H_LINE_TO, 0.41f,
+V_LINE_TO, 18,
+CUBIC_TO, 14.41f, 16.17f, 17, 12.15f, 17, 8.63f,
+CUBIC_TO, 17, 4.97f, 13.86f, 2, 10, 2,
+CLOSE,
+R_MOVE_TO, -0.41f, 7.02f,
+R_LINE_TO, -0.82f, 1.56f,
+H_LINE_TO, 7.53f,
+R_LINE_TO, 0.82f, -1.56f,
+H_LINE_TO, 7.12f,
+R_V_LINE_TO, -2.34f,
+R_H_LINE_TO, 2.47f,
+R_V_LINE_TO, 2.34f,
+CLOSE,
+R_MOVE_TO, 3.29f, 0,
+R_LINE_TO, -0.82f, 1.56f,
+R_H_LINE_TO, -1.24f,
+R_LINE_TO, 0.82f, -1.56f,
+R_H_LINE_TO, -1.24f,
+R_V_LINE_TO, -2.34f,
+R_H_LINE_TO, 2.47f,
+R_V_LINE_TO, 2.34f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_cast_meeting.1x.icon b/ash/resources/vector_icons/system_menu_cast_meeting.1x.icon
deleted file mode 100644
index 9ed8a77..0000000
--- a/ash/resources/vector_icons/system_menu_cast_meeting.1x.icon
+++ /dev/null
@@ -1,22 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 10, 2,
-CUBIC_TO, 6.13f, 2, 3, 5.04f, 3, 8.86f,
-R_CUBIC_TO, 0, 3.61f, 3.34f, 6.48f, 7, 6.48f,
-V_LINE_TO, 18,
-R_CUBIC_TO, 4.25f, -2.13f, 7, -5.61f, 7, -9.14f,
-CUBIC_TO, 17, 5.04f, 13.87f, 2, 10, 2,
-CLOSE,
-R_MOVE_TO, 4, 9,
-R_LINE_TO, -2.5f, -1.5f,
-V_LINE_TO, 11,
-H_LINE_TO, 7,
-V_LINE_TO, 7,
-R_H_LINE_TO, 4.5f,
-R_V_LINE_TO, 1.5f,
-LINE_TO, 14, 7,
-R_V_LINE_TO, 4,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_cast_meeting.icon b/ash/resources/vector_icons/system_menu_cast_meeting.icon
index 5b185bf..0c24f8211 100644
--- a/ash/resources/vector_icons/system_menu_cast_meeting.icon
+++ b/ash/resources/vector_icons/system_menu_cast_meeting.icon
@@ -20,3 +20,22 @@
 R_LINE_TO, 5, -3,
 R_V_LINE_TO, 8,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 10, 2,
+CUBIC_TO, 6.13f, 2, 3, 5.04f, 3, 8.86f,
+R_CUBIC_TO, 0, 3.61f, 3.34f, 6.48f, 7, 6.48f,
+V_LINE_TO, 18,
+R_CUBIC_TO, 4.25f, -2.13f, 7, -5.61f, 7, -9.14f,
+CUBIC_TO, 17, 5.04f, 13.87f, 2, 10, 2,
+CLOSE,
+R_MOVE_TO, 4, 9,
+R_LINE_TO, -2.5f, -1.5f,
+V_LINE_TO, 11,
+H_LINE_TO, 7,
+V_LINE_TO, 7,
+R_H_LINE_TO, 4.5f,
+R_V_LINE_TO, 1.5f,
+LINE_TO, 14, 7,
+R_V_LINE_TO, 4,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_cast_message.1x.icon b/ash/resources/vector_icons/system_menu_cast_message.1x.icon
deleted file mode 100644
index f13d2fd..0000000
--- a/ash/resources/vector_icons/system_menu_cast_message.1x.icon
+++ /dev/null
@@ -1,33 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 16.4f, 3,
-H_LINE_TO, 3.6f,
-R_CUBIC_TO, -0.88f, 0, -1.59f, 0.72f, -1.59f, 1.6f,
-V_LINE_TO, 18,
-LINE_TO, 5, 15,
-R_H_LINE_TO, 11.4f,
-R_CUBIC_TO, 0.88f, 0, 1.6f, -0.62f, 1.6f, -1.5f,
-V_LINE_TO, 4.6f,
-R_CUBIC_TO, 0, -0.88f, -0.72f, -1.6f, -1.6f, -1.6f,
-CLOSE,
-MOVE_TO, 15, 12.5f,
-H_LINE_TO, 5,
-V_LINE_TO, 11,
-R_H_LINE_TO, 10,
-R_V_LINE_TO, 1.5f,
-CLOSE,
-R_MOVE_TO, 0, -3,
-H_LINE_TO, 5,
-V_LINE_TO, 8,
-R_H_LINE_TO, 10,
-R_V_LINE_TO, 1.5f,
-CLOSE,
-R_MOVE_TO, 0, -3,
-H_LINE_TO, 5,
-V_LINE_TO, 5,
-R_H_LINE_TO, 10,
-R_V_LINE_TO, 1.5f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_cast_message.icon b/ash/resources/vector_icons/system_menu_cast_message.icon
index 71c2779f..5ce830d8 100644
--- a/ash/resources/vector_icons/system_menu_cast_message.icon
+++ b/ash/resources/vector_icons/system_menu_cast_message.icon
@@ -31,3 +31,33 @@
 R_H_LINE_TO, 20,
 R_V_LINE_TO, 3,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 16.4f, 3,
+H_LINE_TO, 3.6f,
+R_CUBIC_TO, -0.88f, 0, -1.59f, 0.72f, -1.59f, 1.6f,
+V_LINE_TO, 18,
+LINE_TO, 5, 15,
+R_H_LINE_TO, 11.4f,
+R_CUBIC_TO, 0.88f, 0, 1.6f, -0.62f, 1.6f, -1.5f,
+V_LINE_TO, 4.6f,
+R_CUBIC_TO, 0, -0.88f, -0.72f, -1.6f, -1.6f, -1.6f,
+CLOSE,
+MOVE_TO, 15, 12.5f,
+H_LINE_TO, 5,
+V_LINE_TO, 11,
+R_H_LINE_TO, 10,
+R_V_LINE_TO, 1.5f,
+CLOSE,
+R_MOVE_TO, 0, -3,
+H_LINE_TO, 5,
+V_LINE_TO, 8,
+R_H_LINE_TO, 10,
+R_V_LINE_TO, 1.5f,
+CLOSE,
+R_MOVE_TO, 0, -3,
+H_LINE_TO, 5,
+V_LINE_TO, 5,
+R_H_LINE_TO, 10,
+R_V_LINE_TO, 1.5f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_child_user.1x.icon b/ash/resources/vector_icons/system_menu_child_user.1x.icon
deleted file mode 100644
index 54b7a08..0000000
--- a/ash/resources/vector_icons/system_menu_child_user.1x.icon
+++ /dev/null
@@ -1,24 +0,0 @@
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 10.32f, 2,
-LINE_TO, 4.63f, 8,
-R_LINE_TO, 4.92f, 7.5f,
-R_LINE_TO, -0.4f, 0.6f,
-R_CUBIC_TO, -0.04f, 0.07f, -0.09f, 0.12f, -0.14f, 0.18f,
-R_CUBIC_TO, -0.24f, 0.25f, -0.56f, 0.39f, -0.9f, 0.39f,
-R_CUBIC_TO, -0.34f, 0, -0.65f, -0.13f, -0.9f, -0.39f,
-R_ARC_TO, 1.35f, 1.35f, 0, 0, 1, -0.37f, -0.94f,
-R_ARC_TO, 2.72f, 2.72f, 0, 0, 0, -0.74f, -1.88f,
-R_ARC_TO, 2.44f, 2.44f, 0, 0, 0, -1.78f, -0.78f,
-H_LINE_TO, 4,
-R_V_LINE_TO, 1.34f,
-R_H_LINE_TO, 0.33f,
-R_CUBIC_TO, 0.34f, 0, 0.65f, 0.14f, 0.9f, 0.39f,
-R_CUBIC_TO, 0.24f, 0.26f, 0.37f, 0.59f, 0.37f, 0.95f,
-R_CUBIC_TO, 0, 0.71f, 0.26f, 1.38f, 0.74f, 1.88f,
-R_CUBIC_TO, 0.48f, 0.5f, 1.11f, 0.78f, 1.78f, 0.78f,
-R_CUBIC_TO, 0.67f, 0, 1.31f, -0.28f, 1.78f, -0.78f,
-R_CUBIC_TO, 0.11f, -0.11f, 0.2f, -0.23f, 0.28f, -0.35f,
-R_LINE_TO, 1.27f, -1.94f,
-LINE_TO, 16, 8,
-LINE_TO, 10.32f, 2,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_child_user.icon b/ash/resources/vector_icons/system_menu_child_user.icon
index 5c566026..f10ab8e 100644
--- a/ash/resources/vector_icons/system_menu_child_user.icon
+++ b/ash/resources/vector_icons/system_menu_child_user.icon
@@ -22,3 +22,28 @@
 LINE_TO, 32, 16,
 LINE_TO, 20.64f, 4,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 10.32f, 2,
+LINE_TO, 4.63f, 8,
+R_LINE_TO, 4.92f, 7.5f,
+R_LINE_TO, -0.4f, 0.6f,
+R_CUBIC_TO, -0.04f, 0.07f, -0.09f, 0.12f, -0.14f, 0.18f,
+R_CUBIC_TO, -0.24f, 0.25f, -0.56f, 0.39f, -0.9f, 0.39f,
+R_CUBIC_TO, -0.34f, 0, -0.65f, -0.13f, -0.9f, -0.39f,
+R_ARC_TO, 1.35f, 1.35f, 0, 0, 1, -0.37f, -0.94f,
+R_ARC_TO, 2.72f, 2.72f, 0, 0, 0, -0.74f, -1.88f,
+R_ARC_TO, 2.44f, 2.44f, 0, 0, 0, -1.78f, -0.78f,
+H_LINE_TO, 4,
+R_V_LINE_TO, 1.34f,
+R_H_LINE_TO, 0.33f,
+R_CUBIC_TO, 0.34f, 0, 0.65f, 0.14f, 0.9f, 0.39f,
+R_CUBIC_TO, 0.24f, 0.26f, 0.37f, 0.59f, 0.37f, 0.95f,
+R_CUBIC_TO, 0, 0.71f, 0.26f, 1.38f, 0.74f, 1.88f,
+R_CUBIC_TO, 0.48f, 0.5f, 1.11f, 0.78f, 1.78f, 0.78f,
+R_CUBIC_TO, 0.67f, 0, 1.31f, -0.28f, 1.78f, -0.78f,
+R_CUBIC_TO, 0.11f, -0.11f, 0.2f, -0.23f, 0.28f, -0.35f,
+R_LINE_TO, 1.27f, -1.94f,
+LINE_TO, 16, 8,
+LINE_TO, 10.32f, 2,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_computer.1x.icon b/ash/resources/vector_icons/system_menu_computer.1x.icon
deleted file mode 100644
index 2cdfb48..0000000
--- a/ash/resources/vector_icons/system_menu_computer.1x.icon
+++ /dev/null
@@ -1,25 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 17, 12,
-V_LINE_TO, 6,
-R_CUBIC_TO, 0, -1, -1, -2, -2, -2,
-H_LINE_TO, 5,
-CUBIC_TO, 4, 4, 3, 5, 3, 6,
-R_V_LINE_TO, 6,
-R_CUBIC_TO, 0, 1, 1, 2, 2, 2,
-H_LINE_TO, 2,
-R_V_LINE_TO, 2,
-R_H_LINE_TO, 16,
-R_V_LINE_TO, -2,
-R_H_LINE_TO, -3,
-R_CUBIC_TO, 0, 0, 2, -1, 2, -2,
-CLOSE,
-MOVE_TO, 5, 6,
-R_H_LINE_TO, 10,
-R_V_LINE_TO, 6,
-H_LINE_TO, 5,
-V_LINE_TO, 6,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_computer.icon b/ash/resources/vector_icons/system_menu_computer.icon
index 607d8be..8328cf7 100644
--- a/ash/resources/vector_icons/system_menu_computer.icon
+++ b/ash/resources/vector_icons/system_menu_computer.icon
@@ -23,3 +23,25 @@
 H_LINE_TO, 8,
 V_LINE_TO, 11,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 17, 12,
+V_LINE_TO, 6,
+R_CUBIC_TO, 0, -1, -1, -2, -2, -2,
+H_LINE_TO, 5,
+CUBIC_TO, 4, 4, 3, 5, 3, 6,
+R_V_LINE_TO, 6,
+R_CUBIC_TO, 0, 1, 1, 2, 2, 2,
+H_LINE_TO, 2,
+R_V_LINE_TO, 2,
+R_H_LINE_TO, 16,
+R_V_LINE_TO, -2,
+R_H_LINE_TO, -3,
+R_CUBIC_TO, 0, 0, 2, -1, 2, -2,
+CLOSE,
+MOVE_TO, 5, 6,
+R_H_LINE_TO, 10,
+R_V_LINE_TO, 6,
+H_LINE_TO, 5,
+V_LINE_TO, 6,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_gamepad.1x.icon b/ash/resources/vector_icons/system_menu_gamepad.1x.icon
deleted file mode 100644
index d19e9f6d..0000000
--- a/ash/resources/vector_icons/system_menu_gamepad.1x.icon
+++ /dev/null
@@ -1,33 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 13, 6,
-V_LINE_TO, 2,
-H_LINE_TO, 7,
-R_V_LINE_TO, 4,
-R_LINE_TO, 3, 3,
-R_LINE_TO, 3, -3,
-CLOSE,
-MOVE_TO, 6, 7,
-H_LINE_TO, 2,
-R_V_LINE_TO, 6,
-R_H_LINE_TO, 4,
-R_LINE_TO, 3, -3,
-R_LINE_TO, -3, -3,
-CLOSE,
-R_MOVE_TO, 1, 7,
-R_V_LINE_TO, 4,
-R_H_LINE_TO, 6,
-R_V_LINE_TO, -4,
-R_LINE_TO, -3, -3,
-R_LINE_TO, -3, 3,
-CLOSE,
-R_MOVE_TO, 7, -7,
-R_LINE_TO, -3, 3,
-R_LINE_TO, 3, 3,
-R_H_LINE_TO, 4,
-V_LINE_TO, 7,
-R_H_LINE_TO, -4,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_gamepad.icon b/ash/resources/vector_icons/system_menu_gamepad.icon
index 4841b639..e08dea6 100644
--- a/ash/resources/vector_icons/system_menu_gamepad.icon
+++ b/ash/resources/vector_icons/system_menu_gamepad.icon
@@ -31,3 +31,33 @@
 V_LINE_TO, 15,
 R_H_LINE_TO, -9.06f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 13, 6,
+V_LINE_TO, 2,
+H_LINE_TO, 7,
+R_V_LINE_TO, 4,
+R_LINE_TO, 3, 3,
+R_LINE_TO, 3, -3,
+CLOSE,
+MOVE_TO, 6, 7,
+H_LINE_TO, 2,
+R_V_LINE_TO, 6,
+R_H_LINE_TO, 4,
+R_LINE_TO, 3, -3,
+R_LINE_TO, -3, -3,
+CLOSE,
+R_MOVE_TO, 1, 7,
+R_V_LINE_TO, 4,
+R_H_LINE_TO, 6,
+R_V_LINE_TO, -4,
+R_LINE_TO, -3, -3,
+R_LINE_TO, -3, 3,
+CLOSE,
+R_MOVE_TO, 7, -7,
+R_LINE_TO, -3, 3,
+R_LINE_TO, 3, 3,
+R_H_LINE_TO, 4,
+V_LINE_TO, 7,
+R_H_LINE_TO, -4,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_guest.1x.icon b/ash/resources/vector_icons/system_menu_guest.1x.icon
deleted file mode 100644
index a713ed7..0000000
--- a/ash/resources/vector_icons/system_menu_guest.1x.icon
+++ /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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 10, 2,
-R_CUBIC_TO, -4.42f, 0, -8, 3.58f, -8, 8,
-R_CUBIC_TO, 0, 4.42f, 3.58f, 8, 8, 8,
-R_CUBIC_TO, 4.42f, 0, 8, -3.58f, 8, -8,
-R_CUBIC_TO, 0, -4.42f, -3.58f, -8, -8, -8,
-CLOSE,
-R_MOVE_TO, 0, 2.4f,
-R_CUBIC_TO, 1.33f, 0, 2.4f, 1.07f, 2.4f, 2.4f,
-R_CUBIC_TO, 0, 1.33f, -1.07f, 2.4f, -2.4f, 2.4f,
-R_CUBIC_TO, -1.33f, 0, -2.4f, -1.07f, -2.4f, -2.4f,
-R_CUBIC_TO, 0, -1.33f, 1.07f, -2.4f, 2.4f, -2.4f,
-CLOSE,
-MOVE_TO, 10, 16,
-R_CUBIC_TO, -2.08f, 0, -3.92f, -1.07f, -5, -2.7f,
-R_CUBIC_TO, 0.03f, -1.67f, 3.33f, -2.58f, 5, -2.58f,
-R_CUBIC_TO, 1.66f, 0, 4.97f, 0.91f, 5, 2.58f,
-R_CUBIC_TO, -1.07f, 1.63f, -2.92f, 2.7f, -5, 2.7f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_guest.icon b/ash/resources/vector_icons/system_menu_guest.icon
index 21c18cf..8dfb7544 100644
--- a/ash/resources/vector_icons/system_menu_guest.icon
+++ b/ash/resources/vector_icons/system_menu_guest.icon
@@ -21,3 +21,23 @@
 CUBIC_TO, 27.85f, 29.77f, 24.17f, 32, 20, 32,
 R_CUBIC_TO, -4.17f, 0, -7.85f, -2.23f, -10, -5.62f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 10, 2,
+R_CUBIC_TO, -4.42f, 0, -8, 3.58f, -8, 8,
+R_CUBIC_TO, 0, 4.42f, 3.58f, 8, 8, 8,
+R_CUBIC_TO, 4.42f, 0, 8, -3.58f, 8, -8,
+R_CUBIC_TO, 0, -4.42f, -3.58f, -8, -8, -8,
+CLOSE,
+R_MOVE_TO, 0, 2.4f,
+R_CUBIC_TO, 1.33f, 0, 2.4f, 1.07f, 2.4f, 2.4f,
+R_CUBIC_TO, 0, 1.33f, -1.07f, 2.4f, -2.4f, 2.4f,
+R_CUBIC_TO, -1.33f, 0, -2.4f, -1.07f, -2.4f, -2.4f,
+R_CUBIC_TO, 0, -1.33f, 1.07f, -2.4f, 2.4f, -2.4f,
+CLOSE,
+MOVE_TO, 10, 16,
+R_CUBIC_TO, -2.08f, 0, -3.92f, -1.07f, -5, -2.7f,
+R_CUBIC_TO, 0.03f, -1.67f, 3.33f, -2.58f, 5, -2.58f,
+R_CUBIC_TO, 1.66f, 0, 4.97f, 0.91f, 5, 2.58f,
+R_CUBIC_TO, -1.07f, 1.63f, -2.92f, 2.7f, -5, 2.7f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_hdmi.1x.icon b/ash/resources/vector_icons/system_menu_hdmi.1x.icon
deleted file mode 100644
index 3e56ac0e..0000000
--- a/ash/resources/vector_icons/system_menu_hdmi.1x.icon
+++ /dev/null
@@ -1,35 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 15, 6,
-V_LINE_TO, 3.75f,
-CUBIC_TO, 15, 2.87f, 14.37f, 2, 13.43f, 2,
-H_LINE_TO, 6.57f,
-CUBIC_TO, 5.63f, 2, 5, 2.72f, 5, 3.6f,
-V_LINE_TO, 6,
-H_LINE_TO, 4,
-R_V_LINE_TO, 4.8f,
-R_LINE_TO, 3, 4.7f,
-V_LINE_TO, 18,
-R_H_LINE_TO, 6,
-R_V_LINE_TO, -2.5f,
-R_LINE_TO, 3, -4.7f,
-V_LINE_TO, 6,
-R_H_LINE_TO, -1,
-CLOSE,
-R_MOVE_TO, -2, -2,
-R_V_LINE_TO, 2,
-R_H_LINE_TO, -1,
-V_LINE_TO, 5,
-R_H_LINE_TO, -1,
-R_V_LINE_TO, 1,
-H_LINE_TO, 9,
-V_LINE_TO, 5,
-H_LINE_TO, 8,
-R_V_LINE_TO, 1,
-H_LINE_TO, 7,
-V_LINE_TO, 4,
-R_H_LINE_TO, 6,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_hdmi.icon b/ash/resources/vector_icons/system_menu_hdmi.icon
index 69c33cdff..bf10848 100644
--- a/ash/resources/vector_icons/system_menu_hdmi.icon
+++ b/ash/resources/vector_icons/system_menu_hdmi.icon
@@ -33,3 +33,35 @@
 H_LINE_TO, 13,
 V_LINE_TO, 7,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 15, 6,
+V_LINE_TO, 3.75f,
+CUBIC_TO, 15, 2.87f, 14.37f, 2, 13.43f, 2,
+H_LINE_TO, 6.57f,
+CUBIC_TO, 5.63f, 2, 5, 2.72f, 5, 3.6f,
+V_LINE_TO, 6,
+H_LINE_TO, 4,
+R_V_LINE_TO, 4.8f,
+R_LINE_TO, 3, 4.7f,
+V_LINE_TO, 18,
+R_H_LINE_TO, 6,
+R_V_LINE_TO, -2.5f,
+R_LINE_TO, 3, -4.7f,
+V_LINE_TO, 6,
+R_H_LINE_TO, -1,
+CLOSE,
+R_MOVE_TO, -2, -2,
+R_V_LINE_TO, 2,
+R_H_LINE_TO, -1,
+V_LINE_TO, 5,
+R_H_LINE_TO, -1,
+R_V_LINE_TO, 1,
+H_LINE_TO, 9,
+V_LINE_TO, 5,
+H_LINE_TO, 8,
+R_V_LINE_TO, 1,
+H_LINE_TO, 7,
+V_LINE_TO, 4,
+R_H_LINE_TO, 6,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_headset.1x.icon b/ash/resources/vector_icons/system_menu_headset.1x.icon
deleted file mode 100644
index fd67785c..0000000
--- a/ash/resources/vector_icons/system_menu_headset.1x.icon
+++ /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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 2, 9.58f,
-R_V_LINE_TO, 5.89f,
-CUBIC_TO, 2, 16.87f, 3, 18, 4.5f, 18,
-H_LINE_TO, 7,
-R_V_LINE_TO, -6,
-H_LINE_TO, 4,
-V_LINE_TO, 9.58f,
-CUBIC_TO, 4, 6.32f, 6.78f, 4, 10, 4,
-R_CUBIC_TO, 3.22f, 0, 6, 2.32f, 6, 5.58f,
-V_LINE_TO, 12,
-R_H_LINE_TO, -3,
-R_V_LINE_TO, 6,
-R_H_LINE_TO, 2.5f,
-R_CUBIC_TO, 1.38f, 0, 2.5f, -1.13f, 2.5f, -2.53f,
-V_LINE_TO, 9.58f,
-CUBIC_TO, 18, 5.39f, 14.14f, 2, 10, 2,
-CUBIC_TO, 5.86f, 2, 2, 5.39f, 2, 9.58f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_headset.icon b/ash/resources/vector_icons/system_menu_headset.icon
index 64eeccd..d112a00 100644
--- a/ash/resources/vector_icons/system_menu_headset.icon
+++ b/ash/resources/vector_icons/system_menu_headset.icon
@@ -21,3 +21,23 @@
 CUBIC_TO, 35, 10.79f, 28.28f, 4, 20, 4,
 CUBIC_TO, 11.72f, 4, 5, 10.79f, 5, 19.16f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 2, 9.58f,
+R_V_LINE_TO, 5.89f,
+CUBIC_TO, 2, 16.87f, 3, 18, 4.5f, 18,
+H_LINE_TO, 7,
+R_V_LINE_TO, -6,
+H_LINE_TO, 4,
+V_LINE_TO, 9.58f,
+CUBIC_TO, 4, 6.32f, 6.78f, 4, 10, 4,
+R_CUBIC_TO, 3.22f, 0, 6, 2.32f, 6, 5.58f,
+V_LINE_TO, 12,
+R_H_LINE_TO, -3,
+R_V_LINE_TO, 6,
+R_H_LINE_TO, 2.5f,
+R_CUBIC_TO, 1.38f, 0, 2.5f, -1.13f, 2.5f, -2.53f,
+V_LINE_TO, 9.58f,
+CUBIC_TO, 18, 5.39f, 14.14f, 2, 10, 2,
+CUBIC_TO, 5.86f, 2, 2, 5.39f, 2, 9.58f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_help.1x.icon b/ash/resources/vector_icons/system_menu_help.1x.icon
deleted file mode 100644
index c9a6a25..0000000
--- a/ash/resources/vector_icons/system_menu_help.1x.icon
+++ /dev/null
@@ -1,32 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 10, 2,
-R_CUBIC_TO, -4.42f, 0, -8, 3.58f, -8, 8,
-R_CUBIC_TO, 0, 4.42f, 3.58f, 8, 8, 8,
-R_CUBIC_TO, 4.42f, 0, 8, -3.58f, 8, -8,
-R_CUBIC_TO, 0, -4.42f, -3.58f, -8, -8, -8,
-CLOSE,
-R_MOVE_TO, 0.8f, 13.6f,
-H_LINE_TO, 9.2f,
-V_LINE_TO, 14,
-R_H_LINE_TO, 1.6f,
-R_V_LINE_TO, 1.6f,
-CLOSE,
-R_MOVE_TO, 1.66f, -6.2f,
-R_LINE_TO, -0.72f, 0.74f,
-R_CUBIC_TO, -0.58f, 0.58f, -0.94f, 1.06f, -0.94f, 2.26f,
-H_LINE_TO, 9.2f,
-V_LINE_TO, 12,
-R_CUBIC_TO, 0, -0.88f, 0.36f, -1.68f, 0.94f, -2.26f,
-R_LINE_TO, 0.99f, -1.01f,
-R_CUBIC_TO, 0.3f, -0.29f, 0.47f, -0.69f, 0.47f, -1.13f,
-R_CUBIC_TO, 0, -0.88f, -0.72f, -1.6f, -1.6f, -1.6f,
-R_CUBIC_TO, -0.88f, 0, -1.6f, 0.72f, -1.6f, 1.6f,
-H_LINE_TO, 6.8f,
-R_CUBIC_TO, 0, -1.77f, 1.43f, -3.2f, 3.2f, -3.2f,
-R_CUBIC_TO, 1.77f, 0, 3.2f, 1.43f, 3.2f, 3.2f,
-R_CUBIC_TO, 0, 0.7f, -0.29f, 1.34f, -0.74f, 1.8f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_help.icon b/ash/resources/vector_icons/system_menu_help.icon
index 83d28d6..52c5398a 100644
--- a/ash/resources/vector_icons/system_menu_help.icon
+++ b/ash/resources/vector_icons/system_menu_help.icon
@@ -30,3 +30,32 @@
 R_CUBIC_TO, 3.54f, 0, 6.4f, 2.86f, 6.4f, 6.4f,
 R_CUBIC_TO, 0, 1.41f, -0.58f, 2.69f, -1.49f, 3.6f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 10, 2,
+R_CUBIC_TO, -4.42f, 0, -8, 3.58f, -8, 8,
+R_CUBIC_TO, 0, 4.42f, 3.58f, 8, 8, 8,
+R_CUBIC_TO, 4.42f, 0, 8, -3.58f, 8, -8,
+R_CUBIC_TO, 0, -4.42f, -3.58f, -8, -8, -8,
+CLOSE,
+R_MOVE_TO, 0.8f, 13.6f,
+H_LINE_TO, 9.2f,
+V_LINE_TO, 14,
+R_H_LINE_TO, 1.6f,
+R_V_LINE_TO, 1.6f,
+CLOSE,
+R_MOVE_TO, 1.66f, -6.2f,
+R_LINE_TO, -0.72f, 0.74f,
+R_CUBIC_TO, -0.58f, 0.58f, -0.94f, 1.06f, -0.94f, 2.26f,
+H_LINE_TO, 9.2f,
+V_LINE_TO, 12,
+R_CUBIC_TO, 0, -0.88f, 0.36f, -1.68f, 0.94f, -2.26f,
+R_LINE_TO, 0.99f, -1.01f,
+R_CUBIC_TO, 0.3f, -0.29f, 0.47f, -0.69f, 0.47f, -1.13f,
+R_CUBIC_TO, 0, -0.88f, -0.72f, -1.6f, -1.6f, -1.6f,
+R_CUBIC_TO, -0.88f, 0, -1.6f, 0.72f, -1.6f, 1.6f,
+H_LINE_TO, 6.8f,
+R_CUBIC_TO, 0, -1.77f, 1.43f, -3.2f, 3.2f, -3.2f,
+R_CUBIC_TO, 1.77f, 0, 3.2f, 1.43f, 3.2f, 3.2f,
+R_CUBIC_TO, 0, 0.7f, -0.29f, 1.34f, -0.74f, 1.8f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_info.1x.icon b/ash/resources/vector_icons/system_menu_info.1x.icon
deleted file mode 100644
index 98303d3..0000000
--- a/ash/resources/vector_icons/system_menu_info.1x.icon
+++ /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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 10, 2,
-R_CUBIC_TO, -4.42f, 0, -8, 3.58f, -8, 8,
-R_CUBIC_TO, 0, 4.42f, 3.58f, 8, 8, 8,
-R_CUBIC_TO, 4.42f, 0, 8, -3.58f, 8, -8,
-R_CUBIC_TO, 0, -4.42f, -3.58f, -8, -8, -8,
-CLOSE,
-R_MOVE_TO, 1, 12,
-H_LINE_TO, 9,
-V_LINE_TO, 9,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, 5,
-CLOSE,
-R_MOVE_TO, 0, -6,
-H_LINE_TO, 9,
-V_LINE_TO, 6,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, 2,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_info.icon b/ash/resources/vector_icons/system_menu_info.icon
index fe44ba7..7ba7d33 100644
--- a/ash/resources/vector_icons/system_menu_info.icon
+++ b/ash/resources/vector_icons/system_menu_info.icon
@@ -21,3 +21,23 @@
 R_H_LINE_TO, 3,
 R_V_LINE_TO, 3,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 10, 2,
+R_CUBIC_TO, -4.42f, 0, -8, 3.58f, -8, 8,
+R_CUBIC_TO, 0, 4.42f, 3.58f, 8, 8, 8,
+R_CUBIC_TO, 4.42f, 0, 8, -3.58f, 8, -8,
+R_CUBIC_TO, 0, -4.42f, -3.58f, -8, -8, -8,
+CLOSE,
+R_MOVE_TO, 1, 12,
+H_LINE_TO, 9,
+V_LINE_TO, 9,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 5,
+CLOSE,
+R_MOVE_TO, 0, -6,
+H_LINE_TO, 9,
+V_LINE_TO, 6,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 2,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_keyboard.1x.icon b/ash/resources/vector_icons/system_menu_keyboard.1x.icon
deleted file mode 100644
index a489093..0000000
--- a/ash/resources/vector_icons/system_menu_keyboard.1x.icon
+++ /dev/null
@@ -1,81 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 16.5f, 5,
-R_H_LINE_TO, -12,
-R_CUBIC_TO, -0.82f, 0, -1.49f, 0.71f, -1.49f, 1.57f,
-LINE_TO, 3, 14.43f,
-CUBIC_TO, 3, 15.29f, 3.68f, 16, 4.5f, 16,
-R_H_LINE_TO, 12,
-R_CUBIC_TO, 0.83f, 0, 1.5f, -0.71f, 1.5f, -1.57f,
-V_LINE_TO, 6.57f,
-CUBIC_TO, 18, 5.71f, 17.33f, 5, 16.5f, 5,
-CLOSE,
-MOVE_TO, 10, 8,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-R_H_LINE_TO, -1,
-V_LINE_TO, 8,
-CLOSE,
-R_MOVE_TO, 0, 2,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-R_H_LINE_TO, -1,
-R_V_LINE_TO, -1,
-CLOSE,
-MOVE_TO, 8, 8,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-H_LINE_TO, 8,
-V_LINE_TO, 8,
-CLOSE,
-R_MOVE_TO, 0, 2,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-H_LINE_TO, 8,
-R_V_LINE_TO, -1,
-CLOSE,
-R_MOVE_TO, -1, 1,
-H_LINE_TO, 6,
-R_V_LINE_TO, -1,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-CLOSE,
-R_MOVE_TO, 0, -2,
-H_LINE_TO, 6,
-V_LINE_TO, 8,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-CLOSE,
-R_MOVE_TO, 7, 5,
-H_LINE_TO, 7,
-R_V_LINE_TO, -1,
-R_H_LINE_TO, 7,
-R_V_LINE_TO, 1,
-CLOSE,
-R_MOVE_TO, -1, -3,
-R_H_LINE_TO, -1,
-R_V_LINE_TO, -1,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-CLOSE,
-R_MOVE_TO, 0, -2,
-R_H_LINE_TO, -1,
-V_LINE_TO, 8,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-CLOSE,
-R_MOVE_TO, 2, 2,
-R_H_LINE_TO, -1,
-R_V_LINE_TO, -1,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-CLOSE,
-R_MOVE_TO, 0, -2,
-R_H_LINE_TO, -1,
-V_LINE_TO, 8,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_keyboard.icon b/ash/resources/vector_icons/system_menu_keyboard.icon
index 2be7249..8fa542a4 100644
--- a/ash/resources/vector_icons/system_menu_keyboard.icon
+++ b/ash/resources/vector_icons/system_menu_keyboard.icon
@@ -79,3 +79,81 @@
 R_H_LINE_TO, 3,
 R_V_LINE_TO, 3,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 16.5f, 5,
+R_H_LINE_TO, -12,
+R_CUBIC_TO, -0.82f, 0, -1.49f, 0.71f, -1.49f, 1.57f,
+LINE_TO, 3, 14.43f,
+CUBIC_TO, 3, 15.29f, 3.68f, 16, 4.5f, 16,
+R_H_LINE_TO, 12,
+R_CUBIC_TO, 0.83f, 0, 1.5f, -0.71f, 1.5f, -1.57f,
+V_LINE_TO, 6.57f,
+CUBIC_TO, 18, 5.71f, 17.33f, 5, 16.5f, 5,
+CLOSE,
+MOVE_TO, 10, 8,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+R_H_LINE_TO, -1,
+V_LINE_TO, 8,
+CLOSE,
+R_MOVE_TO, 0, 2,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+R_H_LINE_TO, -1,
+R_V_LINE_TO, -1,
+CLOSE,
+MOVE_TO, 8, 8,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+H_LINE_TO, 8,
+V_LINE_TO, 8,
+CLOSE,
+R_MOVE_TO, 0, 2,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+H_LINE_TO, 8,
+R_V_LINE_TO, -1,
+CLOSE,
+R_MOVE_TO, -1, 1,
+H_LINE_TO, 6,
+R_V_LINE_TO, -1,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+CLOSE,
+R_MOVE_TO, 0, -2,
+H_LINE_TO, 6,
+V_LINE_TO, 8,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+CLOSE,
+R_MOVE_TO, 7, 5,
+H_LINE_TO, 7,
+R_V_LINE_TO, -1,
+R_H_LINE_TO, 7,
+R_V_LINE_TO, 1,
+CLOSE,
+R_MOVE_TO, -1, -3,
+R_H_LINE_TO, -1,
+R_V_LINE_TO, -1,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+CLOSE,
+R_MOVE_TO, 0, -2,
+R_H_LINE_TO, -1,
+V_LINE_TO, 8,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+CLOSE,
+R_MOVE_TO, 2, 2,
+R_H_LINE_TO, -1,
+R_V_LINE_TO, -1,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+CLOSE,
+R_MOVE_TO, 0, -2,
+R_H_LINE_TO, -1,
+V_LINE_TO, 8,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_keyboard_brightness.1x.icon b/ash/resources/vector_icons/system_menu_keyboard_brightness.1x.icon
deleted file mode 100644
index 5c9028e..0000000
--- a/ash/resources/vector_icons/system_menu_keyboard_brightness.1x.icon
+++ /dev/null
@@ -1,59 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 0, 0,
-R_H_LINE_TO, 20,
-R_V_LINE_TO, 20,
-H_LINE_TO, 0,
-V_LINE_TO, 0,
-CLOSE,
-R_MOVE_TO, 0, 0,
-R_H_LINE_TO, 20,
-R_V_LINE_TO, 20,
-H_LINE_TO, 0,
-V_LINE_TO, 0,
-CLOSE,
-MOVE_TO, 6.95f, 13,
-R_H_LINE_TO, 6.09f,
-R_CUBIC_TO, 0.18f, 0, 0.35f, 0.11f, 0.43f, 0.28f,
-R_LINE_TO, 0.48f, 1,
-R_CUBIC_TO, 0.12f, 0.25f, 0.02f, 0.55f, -0.21f, 0.67f,
-R_CUBIC_TO, -0.07f, 0.04f, -0.14f, 0.05f, -0.21f, 0.05f,
-H_LINE_TO, 6.48f,
-CUBIC_TO, 6.21f, 15, 6, 14.78f, 6, 14.5f,
-R_CUBIC_TO, 0, -0.08f, 0.02f, -0.15f, 0.05f, -0.22f,
-R_LINE_TO, 0.48f, -1,
-R_CUBIC_TO, 0.08f, -0.17f, 0.25f, -0.28f, 0.43f, -0.28f,
-CLOSE,
-MOVE_TO, 6, 7.38f,
-LINE_TO, 4.71f, 8.56f,
-LINE_TO, 3.09f, 7.06f,
-R_LINE_TO, 1.28f, -1.18f,
-LINE_TO, 6, 7.38f,
-CLOSE,
-MOVE_TO, 3.46f, 11,
-R_V_LINE_TO, 2,
-H_LINE_TO, 1,
-R_V_LINE_TO, -2,
-R_H_LINE_TO, 2.46f,
-CLOSE,
-MOVE_TO, 11, 4,
-R_V_LINE_TO, 2.22f,
-H_LINE_TO, 9,
-V_LINE_TO, 4,
-R_H_LINE_TO, 2,
-CLOSE,
-R_MOVE_TO, 5.91f, 3.07f,
-R_LINE_TO, -1.63f, 1.5f,
-LINE_TO, 14, 7.38f,
-R_LINE_TO, 1.63f, -1.5f,
-R_LINE_TO, 1.28f, 1.18f,
-CLOSE,
-MOVE_TO, 16.54f, 11,
-H_LINE_TO, 19,
-R_V_LINE_TO, 2,
-R_H_LINE_TO, -2.45f,
-R_V_LINE_TO, -2,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_keyboard_brightness.icon b/ash/resources/vector_icons/system_menu_keyboard_brightness.icon
index 23ba163b..91c41d0 100644
--- a/ash/resources/vector_icons/system_menu_keyboard_brightness.icon
+++ b/ash/resources/vector_icons/system_menu_keyboard_brightness.icon
@@ -57,3 +57,59 @@
 R_H_LINE_TO, -4.64f,
 R_V_LINE_TO, -3.01f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 0, 0,
+R_H_LINE_TO, 20,
+R_V_LINE_TO, 20,
+H_LINE_TO, 0,
+V_LINE_TO, 0,
+CLOSE,
+R_MOVE_TO, 0, 0,
+R_H_LINE_TO, 20,
+R_V_LINE_TO, 20,
+H_LINE_TO, 0,
+V_LINE_TO, 0,
+CLOSE,
+MOVE_TO, 6.95f, 13,
+R_H_LINE_TO, 6.09f,
+R_CUBIC_TO, 0.18f, 0, 0.35f, 0.11f, 0.43f, 0.28f,
+R_LINE_TO, 0.48f, 1,
+R_CUBIC_TO, 0.12f, 0.25f, 0.02f, 0.55f, -0.21f, 0.67f,
+R_CUBIC_TO, -0.07f, 0.04f, -0.14f, 0.05f, -0.21f, 0.05f,
+H_LINE_TO, 6.48f,
+CUBIC_TO, 6.21f, 15, 6, 14.78f, 6, 14.5f,
+R_CUBIC_TO, 0, -0.08f, 0.02f, -0.15f, 0.05f, -0.22f,
+R_LINE_TO, 0.48f, -1,
+R_CUBIC_TO, 0.08f, -0.17f, 0.25f, -0.28f, 0.43f, -0.28f,
+CLOSE,
+MOVE_TO, 6, 7.38f,
+LINE_TO, 4.71f, 8.56f,
+LINE_TO, 3.09f, 7.06f,
+R_LINE_TO, 1.28f, -1.18f,
+LINE_TO, 6, 7.38f,
+CLOSE,
+MOVE_TO, 3.46f, 11,
+R_V_LINE_TO, 2,
+H_LINE_TO, 1,
+R_V_LINE_TO, -2,
+R_H_LINE_TO, 2.46f,
+CLOSE,
+MOVE_TO, 11, 4,
+R_V_LINE_TO, 2.22f,
+H_LINE_TO, 9,
+V_LINE_TO, 4,
+R_H_LINE_TO, 2,
+CLOSE,
+R_MOVE_TO, 5.91f, 3.07f,
+R_LINE_TO, -1.63f, 1.5f,
+LINE_TO, 14, 7.38f,
+R_LINE_TO, 1.63f, -1.5f,
+R_LINE_TO, 1.28f, 1.18f,
+CLOSE,
+MOVE_TO, 16.54f, 11,
+H_LINE_TO, 19,
+R_V_LINE_TO, 2,
+R_H_LINE_TO, -2.45f,
+R_V_LINE_TO, -2,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_lock.1x.icon b/ash/resources/vector_icons/system_menu_lock.1x.icon
deleted file mode 100644
index 9bb0992..0000000
--- a/ash/resources/vector_icons/system_menu_lock.1x.icon
+++ /dev/null
@@ -1,31 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 14, 8,
-V_LINE_TO, 6.5f,
-CUBIC_TO, 14, 4.2f, 12.23f, 3, 10, 3,
-CUBIC_TO_SHORTHAND, 6, 4.2f, 6, 6.5f,
-V_LINE_TO, 8,
-R_CUBIC_TO, -1, 0, -2, 1, -2, 2,
-R_V_LINE_TO, 6,
-R_CUBIC_TO, 0, 1, 1, 2, 2, 2,
-R_H_LINE_TO, 8,
-R_CUBIC_TO, 1, 0, 2, -1, 2, -2,
-R_V_LINE_TO, -6,
-R_CUBIC_TO, 0, -0.92f, -1, -2, -2, -2,
-CLOSE,
-R_MOVE_TO, -4, 6.5f,
-R_CUBIC_TO, -0.82f, 0, -1.5f, -0.67f, -1.5f, -1.5f,
-R_CUBIC_TO, 0, -0.83f, 0.68f, -1.5f, 1.5f, -1.5f,
-R_CUBIC_TO, 0.82f, 0, 1.5f, 0.68f, 1.5f, 1.5f,
-R_CUBIC_TO, 0, 0.82f, -0.67f, 1.5f, -1.5f, 1.5f,
-CLOSE,
-MOVE_TO, 7.5f, 8,
-V_LINE_TO, 6.5f,
-R_CUBIC_TO, 0, -1.51f, 1.4f, -2, 2.5f, -2,
-R_CUBIC_TO, 1.1f, 0, 2.5f, 0.49f, 2.5f, 2,
-V_LINE_TO, 8,
-R_H_LINE_TO, -5,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_lock.icon b/ash/resources/vector_icons/system_menu_lock.icon
index a6e6d8fb..94575da 100644
--- a/ash/resources/vector_icons/system_menu_lock.icon
+++ b/ash/resources/vector_icons/system_menu_lock.icon
@@ -31,3 +31,31 @@
 V_LINE_TO, 15,
 H_LINE_TO, 14,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 14, 8,
+V_LINE_TO, 6.5f,
+CUBIC_TO, 14, 4.2f, 12.23f, 3, 10, 3,
+CUBIC_TO_SHORTHAND, 6, 4.2f, 6, 6.5f,
+V_LINE_TO, 8,
+R_CUBIC_TO, -1, 0, -2, 1, -2, 2,
+R_V_LINE_TO, 6,
+R_CUBIC_TO, 0, 1, 1, 2, 2, 2,
+R_H_LINE_TO, 8,
+R_CUBIC_TO, 1, 0, 2, -1, 2, -2,
+R_V_LINE_TO, -6,
+R_CUBIC_TO, 0, -0.92f, -1, -2, -2, -2,
+CLOSE,
+R_MOVE_TO, -4, 6.5f,
+R_CUBIC_TO, -0.82f, 0, -1.5f, -0.67f, -1.5f, -1.5f,
+R_CUBIC_TO, 0, -0.83f, 0.68f, -1.5f, 1.5f, -1.5f,
+R_CUBIC_TO, 0.82f, 0, 1.5f, 0.68f, 1.5f, 1.5f,
+R_CUBIC_TO, 0, 0.82f, -0.67f, 1.5f, -1.5f, 1.5f,
+CLOSE,
+MOVE_TO, 7.5f, 8,
+V_LINE_TO, 6.5f,
+R_CUBIC_TO, 0, -1.51f, 1.4f, -2, 2.5f, -2,
+R_CUBIC_TO, 1.1f, 0, 2.5f, 0.49f, 2.5f, 2,
+V_LINE_TO, 8,
+R_H_LINE_TO, -5,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_mouse.1x.icon b/ash/resources/vector_icons/system_menu_mouse.1x.icon
deleted file mode 100644
index 675be538..0000000
--- a/ash/resources/vector_icons/system_menu_mouse.1x.icon
+++ /dev/null
@@ -1,22 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 9.96f, 3,
-R_V_LINE_TO, 5,
-H_LINE_TO, 15,
-R_CUBIC_TO, 0, -2.57f, -2.2f, -4.69f, -5.04f, -5,
-CLOSE,
-MOVE_TO, 4, 12,
-R_CUBIC_TO, 0, 3.32f, 2.46f, 6, 5.5f, 6,
-R_CUBIC_TO, 3.04f, 0, 5.5f, -2.68f, 5.5f, -6,
-V_LINE_TO, 9,
-H_LINE_TO, 4,
-R_V_LINE_TO, 3,
-CLOSE,
-R_MOVE_TO, 5.04f, -9,
-CUBIC_TO, 6.2f, 3.31f, 4, 5.43f, 4, 8,
-R_H_LINE_TO, 5.04f,
-V_LINE_TO, 3,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_mouse.icon b/ash/resources/vector_icons/system_menu_mouse.icon
index 7e427f9..e37d34c 100644
--- a/ash/resources/vector_icons/system_menu_mouse.icon
+++ b/ash/resources/vector_icons/system_menu_mouse.icon
@@ -20,3 +20,22 @@
 R_H_LINE_TO, 11,
 V_LINE_TO, 4,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 9.96f, 3,
+R_V_LINE_TO, 5,
+H_LINE_TO, 15,
+R_CUBIC_TO, 0, -2.57f, -2.2f, -4.69f, -5.04f, -5,
+CLOSE,
+MOVE_TO, 4, 12,
+R_CUBIC_TO, 0, 3.32f, 2.46f, 6, 5.5f, 6,
+R_CUBIC_TO, 3.04f, 0, 5.5f, -2.68f, 5.5f, -6,
+V_LINE_TO, 9,
+H_LINE_TO, 4,
+R_V_LINE_TO, 3,
+CLOSE,
+R_MOVE_TO, 5.04f, -9,
+CUBIC_TO, 6.2f, 3.31f, 4, 5.43f, 4, 8,
+R_H_LINE_TO, 5.04f,
+V_LINE_TO, 3,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_new_user.1x.icon b/ash/resources/vector_icons/system_menu_new_user.1x.icon
deleted file mode 100644
index 8c7a0e13..0000000
--- a/ash/resources/vector_icons/system_menu_new_user.1x.icon
+++ /dev/null
@@ -1,32 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 7.6f, 9.8f,
-R_CUBIC_TO, -0.55f, 0, -1, 0.45f, -1, 1,
-R_CUBIC_TO, 0, 0.55f, 0.45f, 1, 1, 1,
-R_CUBIC_TO, 0.55f, 0, 1, -0.45f, 1, -1,
-R_CUBIC_TO, 0, -0.55f, -0.45f, -1, -1, -1,
-CLOSE,
-R_MOVE_TO, 4.8f, 0,
-R_CUBIC_TO, -0.55f, 0, -1, 0.45f, -1, 1,
-R_CUBIC_TO, 0, 0.55f, 0.45f, 1, 1, 1,
-R_CUBIC_TO, 0.55f, 0, 1, -0.45f, 1, -1,
-R_CUBIC_TO, 0, -0.55f, -0.45f, -1, -1, -1,
-CLOSE,
-MOVE_TO, 10, 2,
-R_CUBIC_TO, -4.42f, 0, -8, 3.58f, -8, 8,
-R_CUBIC_TO, 0, 4.42f, 3.58f, 8, 8, 8,
-R_CUBIC_TO, 4.42f, 0, 8, -3.58f, 8, -8,
-R_CUBIC_TO, 0, -4.42f, -3.58f, -8, -8, -8,
-CLOSE,
-R_MOVE_TO, 0, 14.4f,
-R_CUBIC_TO, -3.53f, 0, -6.4f, -2.87f, -6.4f, -6.4f,
-R_CUBIC_TO, 0, -0.23f, 0.02f, -0.46f, 0.04f, -0.69f,
-R_CUBIC_TO, 1.89f, -0.84f, 3.38f, -2.38f, 4.17f, -4.3f,
-CUBIC_TO, 9.26f, 7.06f, 11.64f, 8.4f, 14.34f, 8.4f,
-R_CUBIC_TO, 0.62f, 0, 1.22f, -0.07f, 1.8f, -0.21f,
-R_CUBIC_TO, 0.17f, 0.57f, 0.26f, 1.18f, 0.26f, 1.81f,
-R_CUBIC_TO, 0, 3.53f, -2.87f, 6.4f, -6.4f, 6.4f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_new_user.icon b/ash/resources/vector_icons/system_menu_new_user.icon
index 68e24b77..2c3697e2 100644
--- a/ash/resources/vector_icons/system_menu_new_user.icon
+++ b/ash/resources/vector_icons/system_menu_new_user.icon
@@ -30,3 +30,32 @@
 R_CUBIC_TO, 0.34f, 1.14f, 0.53f, 2.35f, 0.53f, 3.62f,
 R_CUBIC_TO, 0, 7.06f, -5.74f, 12.8f, -12.8f, 12.8f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 7.6f, 9.8f,
+R_CUBIC_TO, -0.55f, 0, -1, 0.45f, -1, 1,
+R_CUBIC_TO, 0, 0.55f, 0.45f, 1, 1, 1,
+R_CUBIC_TO, 0.55f, 0, 1, -0.45f, 1, -1,
+R_CUBIC_TO, 0, -0.55f, -0.45f, -1, -1, -1,
+CLOSE,
+R_MOVE_TO, 4.8f, 0,
+R_CUBIC_TO, -0.55f, 0, -1, 0.45f, -1, 1,
+R_CUBIC_TO, 0, 0.55f, 0.45f, 1, 1, 1,
+R_CUBIC_TO, 0.55f, 0, 1, -0.45f, 1, -1,
+R_CUBIC_TO, 0, -0.55f, -0.45f, -1, -1, -1,
+CLOSE,
+MOVE_TO, 10, 2,
+R_CUBIC_TO, -4.42f, 0, -8, 3.58f, -8, 8,
+R_CUBIC_TO, 0, 4.42f, 3.58f, 8, 8, 8,
+R_CUBIC_TO, 4.42f, 0, 8, -3.58f, 8, -8,
+R_CUBIC_TO, 0, -4.42f, -3.58f, -8, -8, -8,
+CLOSE,
+R_MOVE_TO, 0, 14.4f,
+R_CUBIC_TO, -3.53f, 0, -6.4f, -2.87f, -6.4f, -6.4f,
+R_CUBIC_TO, 0, -0.23f, 0.02f, -0.46f, 0.04f, -0.69f,
+R_CUBIC_TO, 1.89f, -0.84f, 3.38f, -2.38f, 4.17f, -4.3f,
+CUBIC_TO, 9.26f, 7.06f, 11.64f, 8.4f, 14.34f, 8.4f,
+R_CUBIC_TO, 0.62f, 0, 1.22f, -0.07f, 1.8f, -0.21f,
+R_CUBIC_TO, 0.17f, 0.57f, 0.26f, 1.18f, 0.26f, 1.81f,
+R_CUBIC_TO, 0, 3.53f, -2.87f, 6.4f, -6.4f, 6.4f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_night_light_off.1x.icon b/ash/resources/vector_icons/system_menu_night_light_off.1x.icon
deleted file mode 100644
index 3c71773..0000000
--- a/ash/resources/vector_icons/system_menu_night_light_off.1x.icon
+++ /dev/null
@@ -1,33 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 17.15f, 13.59f,
-LINE_TO, 9.44f, 5.88f,
-R_CUBIC_TO, 0.7f, -0.72f, 1.57f, -1.27f, 2.56f, -1.59f,
-R_CUBIC_TO, -0.59f, -0.19f, -1.23f, -0.29f, -1.88f, -0.29f,
-R_CUBIC_TO, -0.76f, 0, -1.49f, 0.14f, -2.17f, 0.39f,
-LINE_TO, 6.41f, 2.85f,
-CUBIC_TO, 7.49f, 2.31f, 8.71f, 2, 10, 2,
-R_CUBIC_TO, 4.42f, 0, 8, 3.58f, 8, 8,
-R_CUBIC_TO, 0, 1.29f, -0.31f, 2.51f, -0.85f, 3.59f,
-CLOSE,
-R_MOVE_TO, -1.78f, 2.34f,
-CUBIC_TO, 13.95f, 17.22f, 12.06f, 18, 10, 18,
-R_CUBIC_TO, -4.42f, 0, -8, -3.58f, -8, -8,
-R_CUBIC_TO, 0, -2.06f, 0.78f, -3.95f, 2.07f, -5.37f,
-R_LINE_TO, 1.43f, 1.43f,
-CUBIC_TO, 4.57f, 7.12f, 4, 8.49f, 4, 10,
-R_CUBIC_TO, 0, 3.31f, 2.74f, 6, 6.12f, 6,
-R_CUBIC_TO, 0.66f, 0, 1.29f, -0.1f, 1.88f, -0.29f,
-R_CUBIC_TO, -2.46f, -0.78f, -4.24f, -3.04f, -4.24f, -5.71f,
-R_CUBIC_TO, 0, -0.51f, 0.07f, -1.01f, 0.19f, -1.49f,
-R_LINE_TO, 7.41f, 7.42f,
-CLOSE,
-MOVE_TO, 2.5f, 3.06f,
-LINE_TO, 3.56f, 2,
-R_LINE_TO, 14.31f, 14.31f,
-R_LINE_TO, -1.06f, 1.06f,
-LINE_TO, 2.5f, 3.06f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_night_light_off.icon b/ash/resources/vector_icons/system_menu_night_light_off.icon
index 660bb50..cb618cec 100644
--- a/ash/resources/vector_icons/system_menu_night_light_off.icon
+++ b/ash/resources/vector_icons/system_menu_night_light_off.icon
@@ -31,3 +31,33 @@
 R_LINE_TO, -2.12f, 2.12f,
 LINE_TO, 5, 6.12f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 17.15f, 13.59f,
+LINE_TO, 9.44f, 5.88f,
+R_CUBIC_TO, 0.7f, -0.72f, 1.57f, -1.27f, 2.56f, -1.59f,
+R_CUBIC_TO, -0.59f, -0.19f, -1.23f, -0.29f, -1.88f, -0.29f,
+R_CUBIC_TO, -0.76f, 0, -1.49f, 0.14f, -2.17f, 0.39f,
+LINE_TO, 6.41f, 2.85f,
+CUBIC_TO, 7.49f, 2.31f, 8.71f, 2, 10, 2,
+R_CUBIC_TO, 4.42f, 0, 8, 3.58f, 8, 8,
+R_CUBIC_TO, 0, 1.29f, -0.31f, 2.51f, -0.85f, 3.59f,
+CLOSE,
+R_MOVE_TO, -1.78f, 2.34f,
+CUBIC_TO, 13.95f, 17.22f, 12.06f, 18, 10, 18,
+R_CUBIC_TO, -4.42f, 0, -8, -3.58f, -8, -8,
+R_CUBIC_TO, 0, -2.06f, 0.78f, -3.95f, 2.07f, -5.37f,
+R_LINE_TO, 1.43f, 1.43f,
+CUBIC_TO, 4.57f, 7.12f, 4, 8.49f, 4, 10,
+R_CUBIC_TO, 0, 3.31f, 2.74f, 6, 6.12f, 6,
+R_CUBIC_TO, 0.66f, 0, 1.29f, -0.1f, 1.88f, -0.29f,
+R_CUBIC_TO, -2.46f, -0.78f, -4.24f, -3.04f, -4.24f, -5.71f,
+R_CUBIC_TO, 0, -0.51f, 0.07f, -1.01f, 0.19f, -1.49f,
+R_LINE_TO, 7.41f, 7.42f,
+CLOSE,
+MOVE_TO, 2.5f, 3.06f,
+LINE_TO, 3.56f, 2,
+R_LINE_TO, 14.31f, 14.31f,
+R_LINE_TO, -1.06f, 1.06f,
+LINE_TO, 2.5f, 3.06f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_night_light_on.1x.icon b/ash/resources/vector_icons/system_menu_night_light_on.1x.icon
deleted file mode 100644
index 34b4c54..0000000
--- a/ash/resources/vector_icons/system_menu_night_light_on.1x.icon
+++ /dev/null
@@ -1,19 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 10, 2,
-R_CUBIC_TO, 4.42f, 0, 8, 3.58f, 8, 8,
-R_CUBIC_TO, 0, 4.42f, -3.58f, 8, -8, 8,
-R_CUBIC_TO, -4.42f, 0, -8, -3.58f, -8, -8,
-R_CUBIC_TO, 0, -4.42f, 3.58f, -8, 8, -8,
-CLOSE,
-R_MOVE_TO, -0.65f, 2,
-CUBIC_TO, 6.4f, 4, 4, 6.69f, 4, 10,
-R_CUBIC_TO, 0, 3.31f, 2.4f, 6, 5.35f, 6,
-R_CUBIC_TO, 0.57f, 0, 1.13f, -0.1f, 1.65f, -0.29f,
-CUBIC_TO, 8.85f, 14.93f, 7.29f, 12.67f, 7.29f, 10,
-R_CUBIC_TO, 0, -2.67f, 1.56f, -4.93f, 3.71f, -5.71f,
-CUBIC_TO, 10.48f, 4.1f, 9.93f, 4, 9.35f, 4,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_night_light_on.icon b/ash/resources/vector_icons/system_menu_night_light_on.icon
index f1cd0aa..442834d 100644
--- a/ash/resources/vector_icons/system_menu_night_light_on.icon
+++ b/ash/resources/vector_icons/system_menu_night_light_on.icon
@@ -17,3 +17,19 @@
 R_CUBIC_TO, -5.22f, -1.69f, -9, -6.59f, -9, -12.37f,
 R_CUBIC_TO, 0, -5.78f, 3.78f, -10.69f, 9, -12.37f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 10, 2,
+R_CUBIC_TO, 4.42f, 0, 8, 3.58f, 8, 8,
+R_CUBIC_TO, 0, 4.42f, -3.58f, 8, -8, 8,
+R_CUBIC_TO, -4.42f, 0, -8, -3.58f, -8, -8,
+R_CUBIC_TO, 0, -4.42f, 3.58f, -8, 8, -8,
+CLOSE,
+R_MOVE_TO, -0.65f, 2,
+CUBIC_TO, 6.4f, 4, 4, 6.69f, 4, 10,
+R_CUBIC_TO, 0, 3.31f, 2.4f, 6, 5.35f, 6,
+R_CUBIC_TO, 0.57f, 0, 1.13f, -0.1f, 1.65f, -0.29f,
+CUBIC_TO, 8.85f, 14.93f, 7.29f, 12.67f, 7.29f, 10,
+R_CUBIC_TO, 0, -2.67f, 1.56f, -4.93f, 3.71f, -5.71f,
+CUBIC_TO, 10.48f, 4.1f, 9.93f, 4, 9.35f, 4,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_phone.1x.icon b/ash/resources/vector_icons/system_menu_phone.1x.icon
deleted file mode 100644
index c837268..0000000
--- a/ash/resources/vector_icons/system_menu_phone.1x.icon
+++ /dev/null
@@ -1,21 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 5, 3.99f,
-CUBIC_TO, 5, 2.89f, 5.89f, 2, 7, 2,
-R_H_LINE_TO, 6,
-R_CUBIC_TO, 1.11f, 0, 2, 0.9f, 2, 1.99f,
-R_V_LINE_TO, 12.01f,
-R_CUBIC_TO, 0, 1.1f, -0.89f, 1.99f, -2, 1.99f,
-H_LINE_TO, 7,
-R_CUBIC_TO, -1.1f, 0, -2, -0.89f, -2, -1.99f,
-V_LINE_TO, 3.99f,
-CLOSE,
-MOVE_TO, 7, 5,
-R_H_LINE_TO, 6,
-R_V_LINE_TO, 10,
-H_LINE_TO, 7,
-V_LINE_TO, 5,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_phone.icon b/ash/resources/vector_icons/system_menu_phone.icon
index 2c0ec69d..20729e9 100644
--- a/ash/resources/vector_icons/system_menu_phone.icon
+++ b/ash/resources/vector_icons/system_menu_phone.icon
@@ -19,3 +19,21 @@
 R_H_LINE_TO, 14,
 R_V_LINE_TO, 20,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 5, 3.99f,
+CUBIC_TO, 5, 2.89f, 5.89f, 2, 7, 2,
+R_H_LINE_TO, 6,
+R_CUBIC_TO, 1.11f, 0, 2, 0.9f, 2, 1.99f,
+R_V_LINE_TO, 12.01f,
+R_CUBIC_TO, 0, 1.1f, -0.89f, 1.99f, -2, 1.99f,
+H_LINE_TO, 7,
+R_CUBIC_TO, -1.1f, 0, -2, -0.89f, -2, -1.99f,
+V_LINE_TO, 3.99f,
+CLOSE,
+MOVE_TO, 7, 5,
+R_H_LINE_TO, 6,
+R_V_LINE_TO, 10,
+H_LINE_TO, 7,
+V_LINE_TO, 5,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_power.1x.icon b/ash/resources/vector_icons/system_menu_power.1x.icon
deleted file mode 100644
index 806d0f6..0000000
--- a/ash/resources/vector_icons/system_menu_power.1x.icon
+++ /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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 11, 2,
-H_LINE_TO, 9,
-R_V_LINE_TO, 9,
-R_H_LINE_TO, 2,
-V_LINE_TO, 2,
-CLOSE,
-R_MOVE_TO, 4.18f, 2,
-LINE_TO, 13.92f, 5.26f,
-R_CUBIC_TO, 1.4f, 1.12f, 2.3f, 2.85f, 2.3f, 4.78f,
-R_CUBIC_TO, 0, 3.42f, -2.78f, 6.19f, -6.22f, 6.19f,
-R_CUBIC_TO, -3.44f, 0, -6.22f, -2.77f, -6.22f, -6.19f,
-R_CUBIC_TO, 0, -1.94f, 0.9f, -3.66f, 2.29f, -4.79f,
-LINE_TO, 4.82f, 4,
-CUBIC_TO, 3.09f, 5.46f, 2, 7.62f, 2, 10.04f,
-CUBIC_TO, 2, 14.44f, 5.58f, 18, 10, 18,
-R_CUBIC_TO, 4.42f, 0, 8, -3.56f, 8, -7.96f,
-R_CUBIC_TO, 0, -2.42f, -1.09f, -4.58f, -2.82f, -6.04f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_power.icon b/ash/resources/vector_icons/system_menu_power.icon
index 5cdb93d..84ea8cd 100644
--- a/ash/resources/vector_icons/system_menu_power.icon
+++ b/ash/resources/vector_icons/system_menu_power.icon
@@ -21,3 +21,23 @@
 R_CUBIC_TO, 8.28f, 0, 15, -6.72f, 15, -15,
 R_CUBIC_TO, 0, -4.57f, -2.05f, -8.63f, -5.28f, -11.38f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 11, 2,
+H_LINE_TO, 9,
+R_V_LINE_TO, 9,
+R_H_LINE_TO, 2,
+V_LINE_TO, 2,
+CLOSE,
+R_MOVE_TO, 4.18f, 2,
+LINE_TO, 13.92f, 5.26f,
+R_CUBIC_TO, 1.4f, 1.12f, 2.3f, 2.85f, 2.3f, 4.78f,
+R_CUBIC_TO, 0, 3.42f, -2.78f, 6.19f, -6.22f, 6.19f,
+R_CUBIC_TO, -3.44f, 0, -6.22f, -2.77f, -6.22f, -6.19f,
+R_CUBIC_TO, 0, -1.94f, 0.9f, -3.66f, 2.29f, -4.79f,
+LINE_TO, 4.82f, 4,
+CUBIC_TO, 3.09f, 5.46f, 2, 7.62f, 2, 10.04f,
+CUBIC_TO, 2, 14.44f, 5.58f, 18, 10, 18,
+R_CUBIC_TO, 4.42f, 0, 8, -3.56f, 8, -7.96f,
+R_CUBIC_TO, 0, -2.42f, -1.09f, -4.58f, -2.82f, -6.04f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_rotation_lock_auto.1x.icon b/ash/resources/vector_icons/system_menu_rotation_lock_auto.1x.icon
deleted file mode 100644
index 6cfe68ab..0000000
--- a/ash/resources/vector_icons/system_menu_rotation_lock_auto.1x.icon
+++ /dev/null
@@ -1,41 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 6.03f, 16.72f,
-R_CUBIC_TO, -1.76f, -0.87f, -3.03f, -2.66f, -3.22f, -4.78f,
-H_LINE_TO, 2,
-R_CUBIC_TO, 0.28f, 3.47f, 3.06f, 6.2f, 6.45f, 6.2f,
-R_LINE_TO, 0.36f, -0.02f,
-R_LINE_TO, -2.06f, -2.15f,
-R_LINE_TO, -0.72f, 0.75f,
-CLOSE,
-MOVE_TO, 14.64f, 3.07f,
-R_CUBIC_TO, 1.77f, 0.87f, 3.03f, 2.66f, 3.22f, 4.78f,
-R_H_LINE_TO, 0.81f,
-R_CUBIC_TO, -0.28f, -3.47f, -3.05f, -6.2f, -6.45f, -6.2f,
-R_LINE_TO, -0.36f, 0.02f,
-R_LINE_TO, 2.06f, 2.15f,
-R_LINE_TO, 0.72f, -0.75f,
-CLOSE,
-MOVE_TO, 11.9f, 16.98f,
-LINE_TO, 3.54f, 8.25f,
-R_LINE_TO, 5.23f, -5.45f,
-R_LINE_TO, 6.6f, 6.89f,
-R_LINE_TO, 0.39f, 0.41f,
-R_LINE_TO, 1.37f, 1.43f,
-R_LINE_TO, -5.23f, 5.46f,
-CLOSE,
-R_MOVE_TO, 6.27f, -6.54f,
-LINE_TO, 16.8f, 9,
-R_LINE_TO, -0.39f, -0.41f,
-R_LINE_TO, -6.6f, -6.89f,
-R_CUBIC_TO, -0.57f, -0.6f, -1.51f, -0.6f, -2.09f, 0,
-LINE_TO, 2.49f, 7.16f,
-R_CUBIC_TO, -0.57f, 0.6f, -0.57f, 1.58f, 0, 2.18f,
-R_LINE_TO, 8.36f, 8.73f,
-R_CUBIC_TO, 0.57f, 0.6f, 1.51f, 0.59f, 2.09f, -0.01f,
-R_LINE_TO, 5.23f, -5.45f,
-R_CUBIC_TO, 0.58f, -0.6f, 0.58f, -1.58f, 0, -2.18f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_rotation_lock_auto.icon b/ash/resources/vector_icons/system_menu_rotation_lock_auto.icon
index a3ad737..9c91fc6e 100644
--- a/ash/resources/vector_icons/system_menu_rotation_lock_auto.icon
+++ b/ash/resources/vector_icons/system_menu_rotation_lock_auto.icon
@@ -39,3 +39,41 @@
 R_LINE_TO, 10.46f, -10.6f,
 R_CUBIC_TO, 1.15f, -1.17f, 1.15f, -3.08f, 0, -4.24f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 6.03f, 16.72f,
+R_CUBIC_TO, -1.76f, -0.87f, -3.03f, -2.66f, -3.22f, -4.78f,
+H_LINE_TO, 2,
+R_CUBIC_TO, 0.28f, 3.47f, 3.06f, 6.2f, 6.45f, 6.2f,
+R_LINE_TO, 0.36f, -0.02f,
+R_LINE_TO, -2.06f, -2.15f,
+R_LINE_TO, -0.72f, 0.75f,
+CLOSE,
+MOVE_TO, 14.64f, 3.07f,
+R_CUBIC_TO, 1.77f, 0.87f, 3.03f, 2.66f, 3.22f, 4.78f,
+R_H_LINE_TO, 0.81f,
+R_CUBIC_TO, -0.28f, -3.47f, -3.05f, -6.2f, -6.45f, -6.2f,
+R_LINE_TO, -0.36f, 0.02f,
+R_LINE_TO, 2.06f, 2.15f,
+R_LINE_TO, 0.72f, -0.75f,
+CLOSE,
+MOVE_TO, 11.9f, 16.98f,
+LINE_TO, 3.54f, 8.25f,
+R_LINE_TO, 5.23f, -5.45f,
+R_LINE_TO, 6.6f, 6.89f,
+R_LINE_TO, 0.39f, 0.41f,
+R_LINE_TO, 1.37f, 1.43f,
+R_LINE_TO, -5.23f, 5.46f,
+CLOSE,
+R_MOVE_TO, 6.27f, -6.54f,
+LINE_TO, 16.8f, 9,
+R_LINE_TO, -0.39f, -0.41f,
+R_LINE_TO, -6.6f, -6.89f,
+R_CUBIC_TO, -0.57f, -0.6f, -1.51f, -0.6f, -2.09f, 0,
+LINE_TO, 2.49f, 7.16f,
+R_CUBIC_TO, -0.57f, 0.6f, -0.57f, 1.58f, 0, 2.18f,
+R_LINE_TO, 8.36f, 8.73f,
+R_CUBIC_TO, 0.57f, 0.6f, 1.51f, 0.59f, 2.09f, -0.01f,
+R_LINE_TO, 5.23f, -5.45f,
+R_CUBIC_TO, 0.58f, -0.6f, 0.58f, -1.58f, 0, -2.18f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_rotation_lock_landscape.1x.icon b/ash/resources/vector_icons/system_menu_rotation_lock_landscape.1x.icon
deleted file mode 100644
index 1183c3c..0000000
--- a/ash/resources/vector_icons/system_menu_rotation_lock_landscape.1x.icon
+++ /dev/null
@@ -1,21 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 2, 6.01f,
-CUBIC_TO, 2, 4.9f, 2.9f, 4, 3.99f, 4,
-R_H_LINE_TO, 12.01f,
-CUBIC_TO, 17.11f, 4, 18, 4.9f, 18, 6.01f,
-R_V_LINE_TO, 7.98f,
-R_CUBIC_TO, 0, 1.11f, -0.89f, 2.01f, -1.99f, 2.01f,
-H_LINE_TO, 3.99f,
-CUBIC_TO, 2.89f, 16, 2, 15.1f, 2, 13.99f,
-V_LINE_TO, 6.01f,
-CLOSE,
-MOVE_TO, 5, 6,
-R_H_LINE_TO, 10,
-R_V_LINE_TO, 8,
-H_LINE_TO, 5,
-V_LINE_TO, 6,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_rotation_lock_landscape.icon b/ash/resources/vector_icons/system_menu_rotation_lock_landscape.icon
index 35363c3a..5fe97a8 100644
--- a/ash/resources/vector_icons/system_menu_rotation_lock_landscape.icon
+++ b/ash/resources/vector_icons/system_menu_rotation_lock_landscape.icon
@@ -19,3 +19,21 @@
 R_H_LINE_TO, 20,
 R_V_LINE_TO, 18,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 2, 6.01f,
+CUBIC_TO, 2, 4.9f, 2.9f, 4, 3.99f, 4,
+R_H_LINE_TO, 12.01f,
+CUBIC_TO, 17.11f, 4, 18, 4.9f, 18, 6.01f,
+R_V_LINE_TO, 7.98f,
+R_CUBIC_TO, 0, 1.11f, -0.89f, 2.01f, -1.99f, 2.01f,
+H_LINE_TO, 3.99f,
+CUBIC_TO, 2.89f, 16, 2, 15.1f, 2, 13.99f,
+V_LINE_TO, 6.01f,
+CLOSE,
+MOVE_TO, 5, 6,
+R_H_LINE_TO, 10,
+R_V_LINE_TO, 8,
+H_LINE_TO, 5,
+V_LINE_TO, 6,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_rotation_lock_portrait.1x.icon b/ash/resources/vector_icons/system_menu_rotation_lock_portrait.1x.icon
deleted file mode 100644
index 60b6fa2..0000000
--- a/ash/resources/vector_icons/system_menu_rotation_lock_portrait.1x.icon
+++ /dev/null
@@ -1,21 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 16, 3.6f,
-R_V_LINE_TO, 12.8f,
-R_CUBIC_TO, 0, 0.88f, -0.77f, 1.6f, -1.71f, 1.6f,
-H_LINE_TO, 5.71f,
-CUBIC_TO, 4.77f, 18, 4, 17.28f, 4, 16.4f,
-V_LINE_TO, 3.6f,
-R_CUBIC_TO, 0, -0.88f, 0.77f, -1.59f, 1.71f, -1.59f,
-LINE_TO, 14.29f, 2,
-CUBIC_TO, 15.23f, 2, 16, 2.72f, 16, 3.6f,
-CLOSE,
-MOVE_TO, 6, 4,
-R_V_LINE_TO, 12,
-R_H_LINE_TO, 8,
-V_LINE_TO, 4,
-H_LINE_TO, 6,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_rotation_lock_portrait.icon b/ash/resources/vector_icons/system_menu_rotation_lock_portrait.icon
index 12b4b2a..31b4f54 100644
--- a/ash/resources/vector_icons/system_menu_rotation_lock_portrait.icon
+++ b/ash/resources/vector_icons/system_menu_rotation_lock_portrait.icon
@@ -19,3 +19,21 @@
 V_LINE_TO, 8,
 H_LINE_TO, 12,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 16, 3.6f,
+R_V_LINE_TO, 12.8f,
+R_CUBIC_TO, 0, 0.88f, -0.77f, 1.6f, -1.71f, 1.6f,
+H_LINE_TO, 5.71f,
+CUBIC_TO, 4.77f, 18, 4, 17.28f, 4, 16.4f,
+V_LINE_TO, 3.6f,
+R_CUBIC_TO, 0, -0.88f, 0.77f, -1.59f, 1.71f, -1.59f,
+LINE_TO, 14.29f, 2,
+CUBIC_TO, 15.23f, 2, 16, 2.72f, 16, 3.6f,
+CLOSE,
+MOVE_TO, 6, 4,
+R_V_LINE_TO, 12,
+R_H_LINE_TO, 8,
+V_LINE_TO, 4,
+H_LINE_TO, 6,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_screen_share.1x.icon b/ash/resources/vector_icons/system_menu_screen_share.1x.icon
deleted file mode 100644
index 55e47c6..0000000
--- a/ash/resources/vector_icons/system_menu_screen_share.1x.icon
+++ /dev/null
@@ -1,29 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 2.5f, 3,
-CUBIC_TO, 1.32f, 3, 1, 3.5f, 1, 4.59f,
-V_LINE_TO, 15.5f,
-R_CUBIC_TO, 0, 1, 0.5f, 1.5f, 1.5f, 1.5f,
-R_H_LINE_TO, 15,
-R_CUBIC_TO, 0.93f, 0, 1.5f, -0.62f, 1.5f, -1.5f,
-V_LINE_TO, 4.59f,
-CUBIC_TO, 19, 3.72f, 18.5f, 3, 17.32f, 3,
-H_LINE_TO, 2.5f,
-CLOSE,
-MOVE_TO, 3, 15,
-V_LINE_TO, 5,
-R_H_LINE_TO, 14,
-R_V_LINE_TO, 10,
-H_LINE_TO, 3,
-CLOSE,
-R_MOVE_TO, 8, -4,
-R_CUBIC_TO, -2.42f, -0.38f, -3.89f, 0.36f, -5, 2,
-R_CUBIC_TO, 0.45f, -2.34f, 1.69f, -4.66f, 5, -5,
-V_LINE_TO, 6,
-R_LINE_TO, 3, 3.5f,
-R_LINE_TO, -3, 3.5f,
-R_V_LINE_TO, -2,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_screen_share.icon b/ash/resources/vector_icons/system_menu_screen_share.icon
index e6d8797c..75ffe04 100644
--- a/ash/resources/vector_icons/system_menu_screen_share.icon
+++ b/ash/resources/vector_icons/system_menu_screen_share.icon
@@ -27,3 +27,29 @@
 R_LINE_TO, -6, 6,
 R_V_LINE_TO, -4,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 2.5f, 3,
+CUBIC_TO, 1.32f, 3, 1, 3.5f, 1, 4.59f,
+V_LINE_TO, 15.5f,
+R_CUBIC_TO, 0, 1, 0.5f, 1.5f, 1.5f, 1.5f,
+R_H_LINE_TO, 15,
+R_CUBIC_TO, 0.93f, 0, 1.5f, -0.62f, 1.5f, -1.5f,
+V_LINE_TO, 4.59f,
+CUBIC_TO, 19, 3.72f, 18.5f, 3, 17.32f, 3,
+H_LINE_TO, 2.5f,
+CLOSE,
+MOVE_TO, 3, 15,
+V_LINE_TO, 5,
+R_H_LINE_TO, 14,
+R_V_LINE_TO, 10,
+H_LINE_TO, 3,
+CLOSE,
+R_MOVE_TO, 8, -4,
+R_CUBIC_TO, -2.42f, -0.38f, -3.89f, 0.36f, -5, 2,
+R_CUBIC_TO, 0.45f, -2.34f, 1.69f, -4.66f, 5, -5,
+V_LINE_TO, 6,
+R_LINE_TO, 3, 3.5f,
+R_LINE_TO, -3, 3.5f,
+R_V_LINE_TO, -2,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_settings.1x.icon b/ash/resources/vector_icons/system_menu_settings.1x.icon
deleted file mode 100644
index 6707c8a6..0000000
--- a/ash/resources/vector_icons/system_menu_settings.1x.icon
+++ /dev/null
@@ -1,51 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 15.98f, 10.73f,
-R_CUBIC_TO, 0.14f, -0.2f, 0.17f, -0.45f, 0, -0.97f,
-R_CUBIC_TO, 0.17f, -0.03f, 0.14f, -0.28f, 0, -0.48f,
-R_LINE_TO, 2, -1.45f,
-R_CUBIC_TO, 0, -0.04f, 0.05f, -0.26f, 0, -0.48f,
-R_LINE_TO, -1.5f, -2.91f,
-R_CUBIC_TO, -0.3f, 0.02f, -0.52f, -0.05f, -0.5f, 0,
-R_LINE_TO, -1.99f, 0.97f,
-R_CUBIC_TO, -0.67f, -0.47f, -1.13f, -0.74f, -1.5f, -0.97f,
-R_LINE_TO, -0.5f, -1.94f,
-R_CUBIC_TO, 0.03f, -0.34f, -0.15f, -0.48f, -0.5f, -0.48f,
-H_LINE_TO, 8.51f,
-R_CUBIC_TO, -0.35f, 0, -0.52f, 0.14f, -0.5f, 0.49f,
-R_LINE_TO, -0.5f, 1.94f,
-R_CUBIC_TO, -0.36f, 0.23f, -0.82f, 0.5f, -1, 0.97f,
-R_LINE_TO, -2.49f, -0.97f,
-R_CUBIC_TO, 0.01f, -0.06f, -0.2f, 0.02f, -0.5f, 0,
-R_LINE_TO, -1.5f, 2.91f,
-R_CUBIC_TO, -0.05f, 0.23f, 0, 0.44f, 0, 0.48f,
-R_LINE_TO, 2, 1.46f,
-R_CUBIC_TO, -0.14f, 0.2f, -0.17f, 0.46f, 0, 0.97f,
-R_CUBIC_TO, -0.17f, 0.02f, -0.14f, 0.28f, 0, 0.48f,
-R_LINE_TO, -1.99f, 1.46f,
-R_CUBIC_TO, 0, 0.04f, -0.04f, 0.26f, 0, 0.49f,
-R_LINE_TO, 1.5f, 2.91f,
-R_CUBIC_TO, 0.3f, -0.02f, 0.52f, 0.05f, 0.5f, 0,
-R_LINE_TO, 2.49f, -0.97f,
-R_CUBIC_TO, 0.18f, 0.47f, 0.64f, 0.74f, 1, 0.97f,
-R_LINE_TO, 0.5f, 1.94f,
-R_CUBIC_TO, -0.02f, 0.34f, 0.15f, 0.48f, 0.5f, 0.48f,
-R_H_LINE_TO, 2.99f,
-R_CUBIC_TO, 0.35f, 0, 0.52f, -0.14f, 0.5f, -0.48f,
-R_LINE_TO, 0.5f, -1.94f,
-R_CUBIC_TO, 0.36f, -0.23f, 0.82f, -0.5f, 1.5f, -0.97f,
-R_LINE_TO, 1.99f, 0.97f,
-R_CUBIC_TO, -0.01f, 0.06f, 0.2f, -0.02f, 0.5f, 0,
-R_LINE_TO, 1.5f, -2.91f,
-R_CUBIC_TO, 0.05f, -0.23f, 0, -0.44f, 0, -0.48f,
-R_LINE_TO, -1.99f, -1.45f,
-CLOSE,
-MOVE_TO, 10, 13,
-R_CUBIC_TO, -1.65f, 0, -3, -1.35f, -3, -3,
-R_CUBIC_TO, 0, -1.65f, 1.35f, -3, 3, -3,
-R_CUBIC_TO, 1.65f, 0, 3, 1.35f, 3, 3,
-R_CUBIC_TO, 0, 1.65f, -1.35f, 3, -3, 3,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_settings.icon b/ash/resources/vector_icons/system_menu_settings.icon
index 77dca19..dc7f39ce 100644
--- a/ash/resources/vector_icons/system_menu_settings.icon
+++ b/ash/resources/vector_icons/system_menu_settings.icon
@@ -49,3 +49,51 @@
 R_CUBIC_TO, 3.3f, 0, 5.98f, 2.61f, 5.98f, 5.82f,
 R_CUBIC_TO, 0, 3.21f, -2.68f, 5.82f, -5.98f, 5.82f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 15.98f, 10.73f,
+R_CUBIC_TO, 0.14f, -0.2f, 0.17f, -0.45f, 0, -0.97f,
+R_CUBIC_TO, 0.17f, -0.03f, 0.14f, -0.28f, 0, -0.48f,
+R_LINE_TO, 2, -1.45f,
+R_CUBIC_TO, 0, -0.04f, 0.05f, -0.26f, 0, -0.48f,
+R_LINE_TO, -1.5f, -2.91f,
+R_CUBIC_TO, -0.3f, 0.02f, -0.52f, -0.05f, -0.5f, 0,
+R_LINE_TO, -1.99f, 0.97f,
+R_CUBIC_TO, -0.67f, -0.47f, -1.13f, -0.74f, -1.5f, -0.97f,
+R_LINE_TO, -0.5f, -1.94f,
+R_CUBIC_TO, 0.03f, -0.34f, -0.15f, -0.48f, -0.5f, -0.48f,
+H_LINE_TO, 8.51f,
+R_CUBIC_TO, -0.35f, 0, -0.52f, 0.14f, -0.5f, 0.49f,
+R_LINE_TO, -0.5f, 1.94f,
+R_CUBIC_TO, -0.36f, 0.23f, -0.82f, 0.5f, -1, 0.97f,
+R_LINE_TO, -2.49f, -0.97f,
+R_CUBIC_TO, 0.01f, -0.06f, -0.2f, 0.02f, -0.5f, 0,
+R_LINE_TO, -1.5f, 2.91f,
+R_CUBIC_TO, -0.05f, 0.23f, 0, 0.44f, 0, 0.48f,
+R_LINE_TO, 2, 1.46f,
+R_CUBIC_TO, -0.14f, 0.2f, -0.17f, 0.46f, 0, 0.97f,
+R_CUBIC_TO, -0.17f, 0.02f, -0.14f, 0.28f, 0, 0.48f,
+R_LINE_TO, -1.99f, 1.46f,
+R_CUBIC_TO, 0, 0.04f, -0.04f, 0.26f, 0, 0.49f,
+R_LINE_TO, 1.5f, 2.91f,
+R_CUBIC_TO, 0.3f, -0.02f, 0.52f, 0.05f, 0.5f, 0,
+R_LINE_TO, 2.49f, -0.97f,
+R_CUBIC_TO, 0.18f, 0.47f, 0.64f, 0.74f, 1, 0.97f,
+R_LINE_TO, 0.5f, 1.94f,
+R_CUBIC_TO, -0.02f, 0.34f, 0.15f, 0.48f, 0.5f, 0.48f,
+R_H_LINE_TO, 2.99f,
+R_CUBIC_TO, 0.35f, 0, 0.52f, -0.14f, 0.5f, -0.48f,
+R_LINE_TO, 0.5f, -1.94f,
+R_CUBIC_TO, 0.36f, -0.23f, 0.82f, -0.5f, 1.5f, -0.97f,
+R_LINE_TO, 1.99f, 0.97f,
+R_CUBIC_TO, -0.01f, 0.06f, 0.2f, -0.02f, 0.5f, 0,
+R_LINE_TO, 1.5f, -2.91f,
+R_CUBIC_TO, 0.05f, -0.23f, 0, -0.44f, 0, -0.48f,
+R_LINE_TO, -1.99f, -1.45f,
+CLOSE,
+MOVE_TO, 10, 13,
+R_CUBIC_TO, -1.65f, 0, -3, -1.35f, -3, -3,
+R_CUBIC_TO, 0, -1.65f, 1.35f, -3, 3, -3,
+R_CUBIC_TO, 1.65f, 0, 3, 1.35f, 3, 3,
+R_CUBIC_TO, 0, 1.65f, -1.35f, 3, -3, 3,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_supervised_user.1x.icon b/ash/resources/vector_icons/system_menu_supervised_user.1x.icon
deleted file mode 100644
index 426d646..0000000
--- a/ash/resources/vector_icons/system_menu_supervised_user.1x.icon
+++ /dev/null
@@ -1,32 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 14.05f, 10,
-R_CUBIC_TO, 1.24f, 0, 2.24f, -0.96f, 2.24f, -2.14f,
-R_CUBIC_TO, 0, -1.18f, -1, -2.14f, -2.24f, -2.14f,
-R_CUBIC_TO, -1.24f, 0, -2.25f, 0.96f, -2.25f, 2.14f,
-CUBIC_TO, 11.8f, 9.04f, 12.81f, 10, 14.05f, 10,
-CLOSE,
-MOVE_TO, 7.3f, 9.14f,
-R_CUBIC_TO, 1.49f, 0, 2.69f, -1.15f, 2.69f, -2.57f,
-CUBIC_TO, 9.99f, 5.15f, 8.79f, 4, 7.3f, 4,
-CUBIC_TO, 5.81f, 4, 4.6f, 5.15f, 4.6f, 6.57f,
-R_CUBIC_TO, 0, 1.42f, 1.21f, 2.57f, 2.7f, 2.57f,
-CLOSE,
-MOVE_TO, 9, 14,
-R_V_LINE_TO, 2,
-R_H_LINE_TO, 10,
-R_V_LINE_TO, -1.93f,
-CUBIC_TO, 19, 12.5f, 15.52f, 11, 14, 11,
-R_CUBIC_TO, -1.52f, 0, -5, 1.5f, -5, 3,
-CLOSE,
-R_MOVE_TO, -8, -0.14f,
-V_LINE_TO, 16,
-R_H_LINE_TO, 7,
-R_V_LINE_TO, -2,
-R_CUBIC_TO, 0, -0.73f, 0, -2, 2, -2.9f,
-R_CUBIC_TO, -0.83f, -0.15f, -1.87f, 0, -2.5f, 0,
-R_CUBIC_TO, -2.24f, 0, -6.5f, 0.76f, -6.5f, 2.76f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_supervised_user.icon b/ash/resources/vector_icons/system_menu_supervised_user.icon
index 2c27f93b..b268396f 100644
--- a/ash/resources/vector_icons/system_menu_supervised_user.icon
+++ b/ash/resources/vector_icons/system_menu_supervised_user.icon
@@ -29,3 +29,32 @@
 R_CUBIC_TO, 0, -1.44f, 0.56f, -3.95f, 4.03f, -5.87f,
 R_CUBIC_TO, -1.48f, -0.3f, -2.91f, -0.47f, -4.03f, -0.47f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 14.05f, 10,
+R_CUBIC_TO, 1.24f, 0, 2.24f, -0.96f, 2.24f, -2.14f,
+R_CUBIC_TO, 0, -1.18f, -1, -2.14f, -2.24f, -2.14f,
+R_CUBIC_TO, -1.24f, 0, -2.25f, 0.96f, -2.25f, 2.14f,
+CUBIC_TO, 11.8f, 9.04f, 12.81f, 10, 14.05f, 10,
+CLOSE,
+MOVE_TO, 7.3f, 9.14f,
+R_CUBIC_TO, 1.49f, 0, 2.69f, -1.15f, 2.69f, -2.57f,
+CUBIC_TO, 9.99f, 5.15f, 8.79f, 4, 7.3f, 4,
+CUBIC_TO, 5.81f, 4, 4.6f, 5.15f, 4.6f, 6.57f,
+R_CUBIC_TO, 0, 1.42f, 1.21f, 2.57f, 2.7f, 2.57f,
+CLOSE,
+MOVE_TO, 9, 14,
+R_V_LINE_TO, 2,
+R_H_LINE_TO, 10,
+R_V_LINE_TO, -1.93f,
+CUBIC_TO, 19, 12.5f, 15.52f, 11, 14, 11,
+R_CUBIC_TO, -1.52f, 0, -5, 1.5f, -5, 3,
+CLOSE,
+R_MOVE_TO, -8, -0.14f,
+V_LINE_TO, 16,
+R_H_LINE_TO, 7,
+R_V_LINE_TO, -2,
+R_CUBIC_TO, 0, -0.73f, 0, -2, 2, -2.9f,
+R_CUBIC_TO, -0.83f, -0.15f, -1.87f, 0, -2.5f, 0,
+R_CUBIC_TO, -2.24f, 0, -6.5f, 0.76f, -6.5f, 2.76f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_tablet.1x.icon b/ash/resources/vector_icons/system_menu_tablet.1x.icon
deleted file mode 100644
index 4fdcf72..0000000
--- a/ash/resources/vector_icons/system_menu_tablet.1x.icon
+++ /dev/null
@@ -1,21 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 2, 6.01f,
-CUBIC_TO, 2, 4.9f, 2.9f, 4, 3.99f, 4,
-R_H_LINE_TO, 12.01f,
-CUBIC_TO, 17.11f, 4, 18, 4.9f, 18, 6.01f,
-R_V_LINE_TO, 7.98f,
-R_CUBIC_TO, 0, 1.11f, -0.89f, 2.01f, -1.99f, 2.01f,
-H_LINE_TO, 3.99f,
-CUBIC_TO, 2.89f, 16, 2, 15.1f, 2, 13.99f,
-V_LINE_TO, 6.01f,
-CLOSE,
-MOVE_TO, 5, 6,
-R_H_LINE_TO, 10,
-R_V_LINE_TO, 8,
-H_LINE_TO, 5,
-V_LINE_TO, 6,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_tablet.icon b/ash/resources/vector_icons/system_menu_tablet.icon
index 49cb10e..c4fe27c 100644
--- a/ash/resources/vector_icons/system_menu_tablet.icon
+++ b/ash/resources/vector_icons/system_menu_tablet.icon
@@ -19,3 +19,21 @@
 R_H_LINE_TO, 20,
 R_V_LINE_TO, 18,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 2, 6.01f,
+CUBIC_TO, 2, 4.9f, 2.9f, 4, 3.99f, 4,
+R_H_LINE_TO, 12.01f,
+CUBIC_TO, 17.11f, 4, 18, 4.9f, 18, 6.01f,
+R_V_LINE_TO, 7.98f,
+R_CUBIC_TO, 0, 1.11f, -0.89f, 2.01f, -1.99f, 2.01f,
+H_LINE_TO, 3.99f,
+CUBIC_TO, 2.89f, 16, 2, 15.1f, 2, 13.99f,
+V_LINE_TO, 6.01f,
+CLOSE,
+MOVE_TO, 5, 6,
+R_H_LINE_TO, 10,
+R_V_LINE_TO, 8,
+H_LINE_TO, 5,
+V_LINE_TO, 6,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_timer.1x.icon b/ash/resources/vector_icons/system_menu_timer.1x.icon
deleted file mode 100644
index 7f9d8c6..0000000
--- a/ash/resources/vector_icons/system_menu_timer.1x.icon
+++ /dev/null
@@ -1,31 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 15.47f, 6.64f,
-R_LINE_TO, 1.1f, -1.1f,
-R_CUBIC_TO, -0.33f, -0.4f, -0.7f, -0.77f, -1.1f, -1.1f,
-LINE_TO, 14.37f, 5.54f,
-ARC_TO, 6.97f, 6.97f, 0, 0, 0, 10, 4,
-R_ARC_TO, 7, 7, 0, 1, 0, 7, 7,
-R_ARC_TO, 6.97f, 6.97f, 0, 0, 0, -1.53f, -4.36f,
-CLOSE,
-MOVE_TO, 10, 16,
-R_CUBIC_TO, -2.76f, 0, -5, -2.24f, -5, -5,
-R_CUBIC_TO, 0, -2.76f, 2.24f, -5, 5, -5,
-R_CUBIC_TO, 2.76f, 0, 5, 2.24f, 5, 5,
-R_CUBIC_TO, 0, 2.76f, -2.24f, 5, -5, 5,
-CLOSE,
-R_MOVE_TO, 2, -15,
-H_LINE_TO, 8,
-R_V_LINE_TO, 2,
-R_H_LINE_TO, 4,
-V_LINE_TO, 1,
-CLOSE,
-MOVE_TO, 9, 12,
-R_H_LINE_TO, 2,
-V_LINE_TO, 8,
-H_LINE_TO, 9,
-R_V_LINE_TO, 4,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_timer.icon b/ash/resources/vector_icons/system_menu_timer.icon
index 22f61938..fdd13ac 100644
--- a/ash/resources/vector_icons/system_menu_timer.icon
+++ b/ash/resources/vector_icons/system_menu_timer.icon
@@ -31,3 +31,31 @@
 R_H_LINE_TO, -3,
 R_V_LINE_TO, 8,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 15.47f, 6.64f,
+R_LINE_TO, 1.1f, -1.1f,
+R_CUBIC_TO, -0.33f, -0.4f, -0.7f, -0.77f, -1.1f, -1.1f,
+LINE_TO, 14.37f, 5.54f,
+ARC_TO, 6.97f, 6.97f, 0, 0, 0, 10, 4,
+R_ARC_TO, 7, 7, 0, 1, 0, 7, 7,
+R_ARC_TO, 6.97f, 6.97f, 0, 0, 0, -1.53f, -4.36f,
+CLOSE,
+MOVE_TO, 10, 16,
+R_CUBIC_TO, -2.76f, 0, -5, -2.24f, -5, -5,
+R_CUBIC_TO, 0, -2.76f, 2.24f, -5, 5, -5,
+R_CUBIC_TO, 2.76f, 0, 5, 2.24f, 5, 5,
+R_CUBIC_TO, 0, 2.76f, -2.24f, 5, -5, 5,
+CLOSE,
+R_MOVE_TO, 2, -15,
+H_LINE_TO, 8,
+R_V_LINE_TO, 2,
+R_H_LINE_TO, 4,
+V_LINE_TO, 1,
+CLOSE,
+MOVE_TO, 9, 12,
+R_H_LINE_TO, 2,
+V_LINE_TO, 8,
+H_LINE_TO, 9,
+R_V_LINE_TO, 4,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_tracing.1x.icon b/ash/resources/vector_icons/system_menu_tracing.1x.icon
deleted file mode 100644
index 8e6bcf3..0000000
--- a/ash/resources/vector_icons/system_menu_tracing.1x.icon
+++ /dev/null
@@ -1,33 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 16.22f, 2,
-H_LINE_TO, 3.78f,
-CUBIC_TO, 2.8f, 2, 2, 2.8f, 2, 3.78f,
-R_V_LINE_TO, 12.44f,
-CUBIC_TO, 2, 17.2f, 2.8f, 18, 3.78f, 18,
-R_H_LINE_TO, 12.44f,
-CUBIC_TO, 17.2f, 18, 18, 17.2f, 18, 16.22f,
-V_LINE_TO, 3.78f,
-CUBIC_TO, 18, 2.8f, 17.2f, 2, 16.22f, 2,
-CLOSE,
-MOVE_TO, 8, 15,
-H_LINE_TO, 6,
-V_LINE_TO, 9,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, 6,
-CLOSE,
-R_MOVE_TO, 3, 0,
-H_LINE_TO, 9,
-V_LINE_TO, 6,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, 9,
-CLOSE,
-R_MOVE_TO, 3, 0,
-R_H_LINE_TO, -2,
-R_V_LINE_TO, -4,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, 4,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_tracing.icon b/ash/resources/vector_icons/system_menu_tracing.icon
index 14f7eb40..98d838e 100644
--- a/ash/resources/vector_icons/system_menu_tracing.icon
+++ b/ash/resources/vector_icons/system_menu_tracing.icon
@@ -31,3 +31,33 @@
 R_H_LINE_TO, 3,
 R_V_LINE_TO, 7,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 16.22f, 2,
+H_LINE_TO, 3.78f,
+CUBIC_TO, 2.8f, 2, 2, 2.8f, 2, 3.78f,
+R_V_LINE_TO, 12.44f,
+CUBIC_TO, 2, 17.2f, 2.8f, 18, 3.78f, 18,
+R_H_LINE_TO, 12.44f,
+CUBIC_TO, 17.2f, 18, 18, 17.2f, 18, 16.22f,
+V_LINE_TO, 3.78f,
+CUBIC_TO, 18, 2.8f, 17.2f, 2, 16.22f, 2,
+CLOSE,
+MOVE_TO, 8, 15,
+H_LINE_TO, 6,
+V_LINE_TO, 9,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 6,
+CLOSE,
+R_MOVE_TO, 3, 0,
+H_LINE_TO, 9,
+V_LINE_TO, 6,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 9,
+CLOSE,
+R_MOVE_TO, 3, 0,
+R_H_LINE_TO, -2,
+R_V_LINE_TO, -4,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 4,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_update.1x.icon b/ash/resources/vector_icons/system_menu_update.1x.icon
deleted file mode 100644
index b13dfe1b..0000000
--- a/ash/resources/vector_icons/system_menu_update.1x.icon
+++ /dev/null
@@ -1,20 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 10, 18,
-R_CUBIC_TO, 4.42f, 0, 8, -3.58f, 8, -8,
-R_CUBIC_TO, 0, -4.42f, -3.58f, -8, -8, -8,
-R_CUBIC_TO, -4.42f, 0, -8, 3.58f, -8, 8,
-R_CUBIC_TO, 0, 4.42f, 3.58f, 8, 8, 8,
-CLOSE,
-R_MOVE_TO, -2, -4,
-R_H_LINE_TO, 4,
-R_V_LINE_TO, -3,
-R_H_LINE_TO, 3,
-R_LINE_TO, -5, -6,
-R_LINE_TO, -5, 6,
-R_H_LINE_TO, 3,
-R_V_LINE_TO, 3,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_update.icon b/ash/resources/vector_icons/system_menu_update.icon
index 28a0cadc..d96e6d9 100644
--- a/ash/resources/vector_icons/system_menu_update.icon
+++ b/ash/resources/vector_icons/system_menu_update.icon
@@ -18,3 +18,20 @@
 R_H_LINE_TO, 6,
 R_V_LINE_TO, 6,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 10, 18,
+R_CUBIC_TO, 4.42f, 0, 8, -3.58f, 8, -8,
+R_CUBIC_TO, 0, -4.42f, -3.58f, -8, -8, -8,
+R_CUBIC_TO, -4.42f, 0, -8, 3.58f, -8, 8,
+R_CUBIC_TO, 0, 4.42f, 3.58f, 8, 8, 8,
+CLOSE,
+R_MOVE_TO, -2, -4,
+R_H_LINE_TO, 4,
+R_V_LINE_TO, -3,
+R_H_LINE_TO, 3,
+R_LINE_TO, -5, -6,
+R_LINE_TO, -5, 6,
+R_H_LINE_TO, 3,
+R_V_LINE_TO, 3,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_usb.1x.icon b/ash/resources/vector_icons/system_menu_usb.1x.icon
deleted file mode 100644
index e9f5b7e..0000000
--- a/ash/resources/vector_icons/system_menu_usb.1x.icon
+++ /dev/null
@@ -1,38 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 12.54f, 9.55f,
-R_H_LINE_TO, 0.74f,
-R_V_LINE_TO, 1.51f,
-H_LINE_TO, 11,
-V_LINE_TO, 5.02f,
-R_H_LINE_TO, 1.54f,
-LINE_TO, 10.25f, 2,
-LINE_TO, 8, 5.02f,
-R_H_LINE_TO, 1.5f,
-R_V_LINE_TO, 6.04f,
-H_LINE_TO, 7.37f,
-V_LINE_TO, 9.49f,
-R_CUBIC_TO, 0.52f, -0.28f, 0.89f, -0.81f, 0.89f, -1.46f,
-R_CUBIC_TO, 0, -0.91f, -0.73f, -1.66f, -1.63f, -1.66f,
-R_CUBIC_TO, -0.89f, 0, -1.63f, 0.75f, -1.63f, 1.66f,
-R_CUBIC_TO, 0, 0.64f, 0.37f, 1.18f, 0.89f, 1.46f,
-R_V_LINE_TO, 1.56f,
-R_CUBIC_TO, 0, 0.84f, 0.54f, 1.44f, 1.36f, 1.44f,
-H_LINE_TO, 9.5f,
-V_LINE_TO, 15,
-R_CUBIC_TO, -0.52f, 0.28f, -0.8f, 0.7f, -0.8f, 1.34f,
-R_CUBIC_TO, 0, 0.92f, 0.73f, 1.66f, 1.63f, 1.66f,
-R_CUBIC_TO, 0.9f, 0, 1.63f, -0.74f, 1.63f, -1.66f,
-R_CUBIC_TO, 0, -0.64f, -0.42f, -1.06f, -0.95f, -1.34f,
-R_V_LINE_TO, -2.5f,
-R_H_LINE_TO, 2.28f,
-R_CUBIC_TO, 0.82f, 0, 1.48f, -0.61f, 1.48f, -1.44f,
-R_V_LINE_TO, -1.51f,
-R_H_LINE_TO, 0.74f,
-R_V_LINE_TO, -3.02f,
-R_H_LINE_TO, -2.96f,
-R_V_LINE_TO, 3.02f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_usb.icon b/ash/resources/vector_icons/system_menu_usb.icon
index 0d2713d..75c0805 100644
--- a/ash/resources/vector_icons/system_menu_usb.icon
+++ b/ash/resources/vector_icons/system_menu_usb.icon
@@ -36,3 +36,38 @@
 R_H_LINE_TO, -5.91f,
 R_V_LINE_TO, 6.04f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 12.54f, 9.55f,
+R_H_LINE_TO, 0.74f,
+R_V_LINE_TO, 1.51f,
+H_LINE_TO, 11,
+V_LINE_TO, 5.02f,
+R_H_LINE_TO, 1.54f,
+LINE_TO, 10.25f, 2,
+LINE_TO, 8, 5.02f,
+R_H_LINE_TO, 1.5f,
+R_V_LINE_TO, 6.04f,
+H_LINE_TO, 7.37f,
+V_LINE_TO, 9.49f,
+R_CUBIC_TO, 0.52f, -0.28f, 0.89f, -0.81f, 0.89f, -1.46f,
+R_CUBIC_TO, 0, -0.91f, -0.73f, -1.66f, -1.63f, -1.66f,
+R_CUBIC_TO, -0.89f, 0, -1.63f, 0.75f, -1.63f, 1.66f,
+R_CUBIC_TO, 0, 0.64f, 0.37f, 1.18f, 0.89f, 1.46f,
+R_V_LINE_TO, 1.56f,
+R_CUBIC_TO, 0, 0.84f, 0.54f, 1.44f, 1.36f, 1.44f,
+H_LINE_TO, 9.5f,
+V_LINE_TO, 15,
+R_CUBIC_TO, -0.52f, 0.28f, -0.8f, 0.7f, -0.8f, 1.34f,
+R_CUBIC_TO, 0, 0.92f, 0.73f, 1.66f, 1.63f, 1.66f,
+R_CUBIC_TO, 0.9f, 0, 1.63f, -0.74f, 1.63f, -1.66f,
+R_CUBIC_TO, 0, -0.64f, -0.42f, -1.06f, -0.95f, -1.34f,
+R_V_LINE_TO, -2.5f,
+R_H_LINE_TO, 2.28f,
+R_CUBIC_TO, 0.82f, 0, 1.48f, -0.61f, 1.48f, -1.44f,
+R_V_LINE_TO, -1.51f,
+R_H_LINE_TO, 0.74f,
+R_V_LINE_TO, -3.02f,
+R_H_LINE_TO, -2.96f,
+R_V_LINE_TO, 3.02f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_videocam.1x.icon b/ash/resources/vector_icons/system_menu_videocam.1x.icon
deleted file mode 100644
index 6035f7d7..0000000
--- a/ash/resources/vector_icons/system_menu_videocam.1x.icon
+++ /dev/null
@@ -1,21 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 2, 6,
-CUBIC_TO, 2, 5.45f, 2.45f, 5, 3, 5,
-R_H_LINE_TO, 10,
-CUBIC_TO, 13.55f, 5, 14, 5.45f, 14, 6,
-R_V_LINE_TO, 8.01f,
-R_CUBIC_TO, 0, 0.55f, -0.45f, 1, -1, 1,
-H_LINE_TO, 3,
-CUBIC_TO, 2.45f, 15, 2, 14.55f, 2, 14.01f,
-R_V_LINE_TO, -8.01f,
-CLOSE,
-MOVE_TO, 14, 8.5f,
-R_LINE_TO, 4, -3,
-R_V_LINE_TO, 9,
-LINE_TO, 14, 12,
-V_LINE_TO, 8.5f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_videocam.icon b/ash/resources/vector_icons/system_menu_videocam.icon
index 4c484c9..4a538e04 100644
--- a/ash/resources/vector_icons/system_menu_videocam.icon
+++ b/ash/resources/vector_icons/system_menu_videocam.icon
@@ -19,3 +19,21 @@
 R_LINE_TO, -6, -5,
 R_V_LINE_TO, -7,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 2, 6,
+CUBIC_TO, 2, 5.45f, 2.45f, 5, 3, 5,
+R_H_LINE_TO, 10,
+CUBIC_TO, 13.55f, 5, 14, 5.45f, 14, 6,
+R_V_LINE_TO, 8.01f,
+R_CUBIC_TO, 0, 0.55f, -0.45f, 1, -1, 1,
+H_LINE_TO, 3,
+CUBIC_TO, 2.45f, 15, 2, 14.55f, 2, 14.01f,
+R_V_LINE_TO, -8.01f,
+CLOSE,
+MOVE_TO, 14, 8.5f,
+R_LINE_TO, 4, -3,
+R_V_LINE_TO, 9,
+LINE_TO, 14, 12,
+V_LINE_TO, 8.5f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_volume_high.1x.icon b/ash/resources/vector_icons/system_menu_volume_high.1x.icon
deleted file mode 100644
index 80835fc2..0000000
--- a/ash/resources/vector_icons/system_menu_volume_high.1x.icon
+++ /dev/null
@@ -1,26 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 2, 13,
-R_H_LINE_TO, 3.47f,
-LINE_TO, 10, 17,
-V_LINE_TO, 3,
-LINE_TO, 5.47f, 7,
-H_LINE_TO, 2,
-R_V_LINE_TO, 6,
-CLOSE,
-R_MOVE_TO, 9, -6.5f,
-R_V_LINE_TO, 7,
-R_CUBIC_TO, 1.78f, -0.63f, 2.5f, -2.5f, 2.5f, -3.5f,
-R_CUBIC_TO, 0, -1, -0.72f, -2.86f, -2.5f, -3.5f,
-CLOSE,
-R_MOVE_TO, 0, -2.24f,
-R_CUBIC_TO, 2.48f, 0.74f, 4.5f, 3.03f, 4.5f, 5.74f,
-R_CUBIC_TO, 0, 2.71f, -2.02f, 5, -4.5f, 5.74f,
-V_LINE_TO, 17.5f,
-R_CUBIC_TO, 3.44f, -0.78f, 6, -3.84f, 6, -7.5f,
-R_CUBIC_TO, 0, -3.66f, -2.56f, -6.72f, -6, -7.5f,
-R_V_LINE_TO, 1.76f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_volume_high.icon b/ash/resources/vector_icons/system_menu_volume_high.icon
index ba69d04..8f4bd56 100644
--- a/ash/resources/vector_icons/system_menu_volume_high.icon
+++ b/ash/resources/vector_icons/system_menu_volume_high.icon
@@ -24,3 +24,26 @@
 CUBIC_TO_SHORTHAND, 29.87f, 6.56f, 23, 5,
 R_V_LINE_TO, 3.52f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 2, 13,
+R_H_LINE_TO, 3.47f,
+LINE_TO, 10, 17,
+V_LINE_TO, 3,
+LINE_TO, 5.47f, 7,
+H_LINE_TO, 2,
+R_V_LINE_TO, 6,
+CLOSE,
+R_MOVE_TO, 9, -6.5f,
+R_V_LINE_TO, 7,
+R_CUBIC_TO, 1.78f, -0.63f, 2.5f, -2.5f, 2.5f, -3.5f,
+R_CUBIC_TO, 0, -1, -0.72f, -2.86f, -2.5f, -3.5f,
+CLOSE,
+R_MOVE_TO, 0, -2.24f,
+R_CUBIC_TO, 2.48f, 0.74f, 4.5f, 3.03f, 4.5f, 5.74f,
+R_CUBIC_TO, 0, 2.71f, -2.02f, 5, -4.5f, 5.74f,
+V_LINE_TO, 17.5f,
+R_CUBIC_TO, 3.44f, -0.78f, 6, -3.84f, 6, -7.5f,
+R_CUBIC_TO, 0, -3.66f, -2.56f, -6.72f, -6, -7.5f,
+R_V_LINE_TO, 1.76f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_volume_low.1x.icon b/ash/resources/vector_icons/system_menu_volume_low.1x.icon
deleted file mode 100644
index db8b384..0000000
--- a/ash/resources/vector_icons/system_menu_volume_low.1x.icon
+++ /dev/null
@@ -1,12 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 2, 13,
-R_H_LINE_TO, 3.47f,
-LINE_TO, 10, 17,
-V_LINE_TO, 3,
-LINE_TO, 5.47f, 7,
-H_LINE_TO, 2,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_volume_low.icon b/ash/resources/vector_icons/system_menu_volume_low.icon
index a8ea90d..21c8863 100644
--- a/ash/resources/vector_icons/system_menu_volume_low.icon
+++ b/ash/resources/vector_icons/system_menu_volume_low.icon
@@ -10,3 +10,12 @@
 V_LINE_TO, 6,
 R_LINE_TO, -8.5f, 9,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 2, 13,
+R_H_LINE_TO, 3.47f,
+LINE_TO, 10, 17,
+V_LINE_TO, 3,
+LINE_TO, 5.47f, 7,
+H_LINE_TO, 2,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_volume_medium.1x.icon b/ash/resources/vector_icons/system_menu_volume_medium.1x.icon
deleted file mode 100644
index c3ecec8..0000000
--- a/ash/resources/vector_icons/system_menu_volume_medium.1x.icon
+++ /dev/null
@@ -1,18 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 2, 13,
-R_H_LINE_TO, 3.47f,
-LINE_TO, 10, 17,
-V_LINE_TO, 3,
-LINE_TO, 5.47f, 7,
-H_LINE_TO, 2,
-R_V_LINE_TO, 6,
-CLOSE,
-R_MOVE_TO, 9, -6.5f,
-R_V_LINE_TO, 7,
-R_CUBIC_TO, 1.78f, -0.63f, 2.5f, -2.5f, 2.5f, -3.5f,
-R_CUBIC_TO, 0, -1, -0.72f, -2.86f, -2.5f, -3.5f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_volume_medium.icon b/ash/resources/vector_icons/system_menu_volume_medium.icon
index ee3bc081..bdc7c9d 100644
--- a/ash/resources/vector_icons/system_menu_volume_medium.icon
+++ b/ash/resources/vector_icons/system_menu_volume_medium.icon
@@ -16,3 +16,18 @@
 H_LINE_TO, 5,
 R_V_LINE_TO, 10,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 2, 13,
+R_H_LINE_TO, 3.47f,
+LINE_TO, 10, 17,
+V_LINE_TO, 3,
+LINE_TO, 5.47f, 7,
+H_LINE_TO, 2,
+R_V_LINE_TO, 6,
+CLOSE,
+R_MOVE_TO, 9, -6.5f,
+R_V_LINE_TO, 7,
+R_CUBIC_TO, 1.78f, -0.63f, 2.5f, -2.5f, 2.5f, -3.5f,
+R_CUBIC_TO, 0, -1, -0.72f, -2.86f, -2.5f, -3.5f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_menu_volume_mute.1x.icon b/ash/resources/vector_icons/system_menu_volume_mute.1x.icon
deleted file mode 100644
index 61ef7f6..0000000
--- a/ash/resources/vector_icons/system_menu_volume_mute.1x.icon
+++ /dev/null
@@ -1,41 +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.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 13.73f, 9.96f,
-R_CUBIC_TO, 0, -1.62f, -1.11f, -3.01f, -2.73f, -3.69f,
-V_LINE_TO, 8.29f,
-R_LINE_TO, 2.68f, 2.24f,
-R_CUBIC_TO, 0.03f, -0.18f, 0.05f, -0.37f, 0.05f, -0.58f,
-CLOSE,
-R_MOVE_TO, 1.95f, 2.4f,
-R_LINE_TO, 1.38f, 1.37f,
-R_CUBIC_TO, 0.6f, -1.12f, 0.94f, -2.4f, 0.94f, -3.77f,
-CUBIC_TO, 18, 6.08f, 14.67f, 2.83f, 11, 2,
-R_V_LINE_TO, 2,
-R_CUBIC_TO, 2.64f, 0.78f, 5.5f, 3.09f, 5.5f, 5.96f,
-R_CUBIC_TO, 0, 0.85f, -0.51f, 1.65f, -0.82f, 2.4f,
-CLOSE,
-MOVE_TO, 2, 3.13f,
-LINE_TO, 5.5f, 7,
-H_LINE_TO, 2,
-R_V_LINE_TO, 6,
-R_H_LINE_TO, 3.5f,
-R_LINE_TO, 4.5f, 4.11f,
-R_V_LINE_TO, -5.98f,
-R_LINE_TO, 3.78f, 3.78f,
-CUBIC_TO, 13.18f, 15.37f, 12.5f, 16, 11, 16,
-R_V_LINE_TO, 2,
-R_CUBIC_TO, 1.5f, 0, 3.12f, -1.06f, 4.06f, -1.82f,
-LINE_TO, 16.87f, 18,
-LINE_TO, 18, 16.87f,
-R_LINE_TO, -8, -8,
-LINE_TO, 3.13f, 2,
-LINE_TO, 2, 3.13f,
-CLOSE,
-R_MOVE_TO, 8, -0.24f,
-LINE_TO, 8.14f, 4.75f,
-LINE_TO, 10, 6.6f,
-V_LINE_TO, 2.89f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_menu_volume_mute.icon b/ash/resources/vector_icons/system_menu_volume_mute.icon
index d06982d..f118436 100644
--- a/ash/resources/vector_icons/system_menu_volume_mute.icon
+++ b/ash/resources/vector_icons/system_menu_volume_mute.icon
@@ -39,3 +39,41 @@
 LINE_TO, 20, 13.63f,
 V_LINE_TO, 6.67f,
 CLOSE
+
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 13.73f, 9.96f,
+R_CUBIC_TO, 0, -1.62f, -1.11f, -3.01f, -2.73f, -3.69f,
+V_LINE_TO, 8.29f,
+R_LINE_TO, 2.68f, 2.24f,
+R_CUBIC_TO, 0.03f, -0.18f, 0.05f, -0.37f, 0.05f, -0.58f,
+CLOSE,
+R_MOVE_TO, 1.95f, 2.4f,
+R_LINE_TO, 1.38f, 1.37f,
+R_CUBIC_TO, 0.6f, -1.12f, 0.94f, -2.4f, 0.94f, -3.77f,
+CUBIC_TO, 18, 6.08f, 14.67f, 2.83f, 11, 2,
+R_V_LINE_TO, 2,
+R_CUBIC_TO, 2.64f, 0.78f, 5.5f, 3.09f, 5.5f, 5.96f,
+R_CUBIC_TO, 0, 0.85f, -0.51f, 1.65f, -0.82f, 2.4f,
+CLOSE,
+MOVE_TO, 2, 3.13f,
+LINE_TO, 5.5f, 7,
+H_LINE_TO, 2,
+R_V_LINE_TO, 6,
+R_H_LINE_TO, 3.5f,
+R_LINE_TO, 4.5f, 4.11f,
+R_V_LINE_TO, -5.98f,
+R_LINE_TO, 3.78f, 3.78f,
+CUBIC_TO, 13.18f, 15.37f, 12.5f, 16, 11, 16,
+R_V_LINE_TO, 2,
+R_CUBIC_TO, 1.5f, 0, 3.12f, -1.06f, 4.06f, -1.82f,
+LINE_TO, 16.87f, 18,
+LINE_TO, 18, 16.87f,
+R_LINE_TO, -8, -8,
+LINE_TO, 3.13f, 2,
+LINE_TO, 2, 3.13f,
+CLOSE,
+R_MOVE_TO, 8, -0.24f,
+LINE_TO, 8.14f, 4.75f,
+LINE_TO, 10, 6.6f,
+V_LINE_TO, 2.89f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_power_button_menu_power_off.1x.icon b/ash/resources/vector_icons/system_power_button_menu_power_off.1x.icon
deleted file mode 100644
index c3e5729..0000000
--- a/ash/resources/vector_icons/system_power_button_menu_power_off.1x.icon
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2018 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.
-
-CANVAS_DIMENSIONS, 24,
-MOVE_TO, 13, 3,
-LINE_TO, 11, 3,
-LINE_TO, 11, 13,
-LINE_TO, 13, 13,
-LINE_TO, 13, 3,
-CLOSE,
-MOVE_TO, 17.83f, 5.17f,
-LINE_TO, 16.41f, 6.59f,
-CUBIC_TO, 17.99f, 7.86f, 19, 9.81f, 19, 12,
-CUBIC_TO, 19, 15.87f, 15.87f, 19, 12, 19,
-CUBIC_TO, 8.13f, 19, 5, 15.87f, 5, 12,
-CUBIC_TO, 5, 9.81f, 6.01f, 7.86f, 7.58f, 6.58f,
-LINE_TO, 6.17f, 5.17f,
-CUBIC_TO, 4.23f, 6.82f, 3, 9.26f, 3, 12,
-CUBIC_TO, 3, 16.97f, 7.03f, 21, 12, 21,
-CUBIC_TO, 16.97f, 21, 21, 16.97f, 21, 12,
-CUBIC_TO, 21, 9.26f, 19.77f, 6.82f, 17.83f, 5.17f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_power_button_menu_power_off.icon b/ash/resources/vector_icons/system_power_button_menu_power_off.icon
index 290036b..ee26dca 100644
--- a/ash/resources/vector_icons/system_power_button_menu_power_off.icon
+++ b/ash/resources/vector_icons/system_power_button_menu_power_off.icon
@@ -20,3 +20,23 @@
 CUBIC_TO, 33.94f, 42, 42, 33.94f, 42, 24,
 CUBIC_TO, 42, 18.52f, 39.54f, 13.64f, 35.66f, 10.34f,
 CLOSE
+
+CANVAS_DIMENSIONS, 24,
+MOVE_TO, 13, 3,
+LINE_TO, 11, 3,
+LINE_TO, 11, 13,
+LINE_TO, 13, 13,
+LINE_TO, 13, 3,
+CLOSE,
+MOVE_TO, 17.83f, 5.17f,
+LINE_TO, 16.41f, 6.59f,
+CUBIC_TO, 17.99f, 7.86f, 19, 9.81f, 19, 12,
+CUBIC_TO, 19, 15.87f, 15.87f, 19, 12, 19,
+CUBIC_TO, 8.13f, 19, 5, 15.87f, 5, 12,
+CUBIC_TO, 5, 9.81f, 6.01f, 7.86f, 7.58f, 6.58f,
+LINE_TO, 6.17f, 5.17f,
+CUBIC_TO, 4.23f, 6.82f, 3, 9.26f, 3, 12,
+CUBIC_TO, 3, 16.97f, 7.03f, 21, 12, 21,
+CUBIC_TO, 16.97f, 21, 21, 16.97f, 21, 12,
+CUBIC_TO, 21, 9.26f, 19.77f, 6.82f, 17.83f, 5.17f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_power_button_menu_sign_out.1x.icon b/ash/resources/vector_icons/system_power_button_menu_sign_out.1x.icon
deleted file mode 100644
index 1ce82f4d..0000000
--- a/ash/resources/vector_icons/system_power_button_menu_sign_out.1x.icon
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2018 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.
-
-CANVAS_DIMENSIONS, 24,
-MOVE_TO, 10.09f, 15.59f,
-LINE_TO, 11.5f, 17,
-LINE_TO, 16.5f, 12,
-LINE_TO, 11.5f, 7,
-LINE_TO, 10.09f, 8.41f,
-LINE_TO, 12.67f, 11,
-LINE_TO, 3, 11,
-LINE_TO, 3, 13,
-LINE_TO, 12.67f, 13,
-LINE_TO, 10.09f, 15.59f,
-CLOSE,
-MOVE_TO, 19, 3,
-LINE_TO, 5, 3,
-CUBIC_TO, 3.89f, 3, 3, 3.9f, 3, 5,
-LINE_TO, 3, 9,
-LINE_TO, 5, 9,
-LINE_TO, 5, 5,
-LINE_TO, 19, 5,
-LINE_TO, 19, 19,
-LINE_TO, 5, 19,
-LINE_TO, 5, 15,
-LINE_TO, 3, 15,
-LINE_TO, 3, 19,
-CUBIC_TO, 3, 20.1f, 3.89f, 21, 5, 21,
-LINE_TO, 19, 21,
-CUBIC_TO, 20.1f, 21, 21, 20.1f, 21, 19,
-LINE_TO, 21, 5,
-CUBIC_TO, 21, 3.9f, 20.1f, 3, 19, 3,
-CLOSE
diff --git a/ash/resources/vector_icons/system_power_button_menu_sign_out.icon b/ash/resources/vector_icons/system_power_button_menu_sign_out.icon
index 40486df..2ff87a3 100644
--- a/ash/resources/vector_icons/system_power_button_menu_sign_out.icon
+++ b/ash/resources/vector_icons/system_power_button_menu_sign_out.icon
@@ -31,3 +31,34 @@
 LINE_TO, 42, 10,
 CUBIC_TO, 42, 7.8f, 40.2f, 6, 38, 6,
 CLOSE
+
+CANVAS_DIMENSIONS, 24,
+MOVE_TO, 10.09f, 15.59f,
+LINE_TO, 11.5f, 17,
+LINE_TO, 16.5f, 12,
+LINE_TO, 11.5f, 7,
+LINE_TO, 10.09f, 8.41f,
+LINE_TO, 12.67f, 11,
+LINE_TO, 3, 11,
+LINE_TO, 3, 13,
+LINE_TO, 12.67f, 13,
+LINE_TO, 10.09f, 15.59f,
+CLOSE,
+MOVE_TO, 19, 3,
+LINE_TO, 5, 3,
+CUBIC_TO, 3.89f, 3, 3, 3.9f, 3, 5,
+LINE_TO, 3, 9,
+LINE_TO, 5, 9,
+LINE_TO, 5, 5,
+LINE_TO, 19, 5,
+LINE_TO, 19, 19,
+LINE_TO, 5, 19,
+LINE_TO, 5, 15,
+LINE_TO, 3, 15,
+LINE_TO, 3, 19,
+CUBIC_TO, 3, 20.1f, 3.89f, 21, 5, 21,
+LINE_TO, 19, 21,
+CUBIC_TO, 20.1f, 21, 21, 20.1f, 21, 19,
+LINE_TO, 21, 5,
+CUBIC_TO, 21, 3.9f, 20.1f, 3, 19, 3,
+CLOSE
diff --git a/ash/resources/vector_icons/system_tray_accessibility.1x.icon b/ash/resources/vector_icons/system_tray_accessibility.1x.icon
deleted file mode 100644
index be68c83..0000000
--- a/ash/resources/vector_icons/system_tray_accessibility.1x.icon
+++ /dev/null
@@ -1,26 +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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 8.5f, 6.87f,
-CUBIC_TO, 6.92f, 6.87f, 5.88f, 6.8f, 4, 6,
-R_V_LINE_TO, 1.24f,
-CUBIC_TO, 5, 7.62f, 6, 8, 7, 8,
-R_V_LINE_TO, 6,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, -3,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 3,
-R_H_LINE_TO, 1,
-V_LINE_TO, 8,
-R_CUBIC_TO, 1, 0, 2, -0.38f, 3, -0.76f,
-V_LINE_TO, 6,
-R_CUBIC_TO, -1.72f, 0.77f, -2.92f, 0.87f, -4.5f, 0.87f,
-CLOSE,
-R_MOVE_TO, 0.02f, -1.26f,
-R_CUBIC_TO, 0.73f, 0, 1.33f, -0.58f, 1.33f, -1.31f,
-CUBIC_TO, 9.85f, 3.59f, 9.25f, 3, 8.52f, 3,
-R_CUBIC_TO, -0.73f, 0, -1.33f, 0.59f, -1.33f, 1.31f,
-R_CUBIC_TO, 0, 0.72f, 0.6f, 1.31f, 1.33f, 1.31f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_tray_accessibility.icon b/ash/resources/vector_icons/system_tray_accessibility.icon
index f24ceb9..2ce7daa 100644
--- a/ash/resources/vector_icons/system_tray_accessibility.icon
+++ b/ash/resources/vector_icons/system_tray_accessibility.icon
@@ -22,3 +22,26 @@
 R_ARC_TO, 2.5f, 2.5f, 0, 1, 0, 0, -5,
 R_ARC_TO, 2.5f, 2.5f, 0, 0, 0, 0, 5,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 8.5f, 6.87f,
+CUBIC_TO, 6.92f, 6.87f, 5.88f, 6.8f, 4, 6,
+R_V_LINE_TO, 1.24f,
+CUBIC_TO, 5, 7.62f, 6, 8, 7, 8,
+R_V_LINE_TO, 6,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, -3,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 3,
+R_H_LINE_TO, 1,
+V_LINE_TO, 8,
+R_CUBIC_TO, 1, 0, 2, -0.38f, 3, -0.76f,
+V_LINE_TO, 6,
+R_CUBIC_TO, -1.72f, 0.77f, -2.92f, 0.87f, -4.5f, 0.87f,
+CLOSE,
+R_MOVE_TO, 0.02f, -1.26f,
+R_CUBIC_TO, 0.73f, 0, 1.33f, -0.58f, 1.33f, -1.31f,
+CUBIC_TO, 9.85f, 3.59f, 9.25f, 3, 8.52f, 3,
+R_CUBIC_TO, -0.73f, 0, -1.33f, 0.59f, -1.33f, 1.31f,
+R_CUBIC_TO, 0, 0.72f, 0.6f, 1.31f, 1.33f, 1.31f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_tray_battery_alert.1x.icon b/ash/resources/vector_icons/system_tray_battery_alert.1x.icon
deleted file mode 100644
index 91e7fb3f..0000000
--- a/ash/resources/vector_icons/system_tray_battery_alert.1x.icon
+++ /dev/null
@@ -1,17 +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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 7, 5,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, 4,
-H_LINE_TO, 7,
-V_LINE_TO, 5,
-CLOSE,
-R_MOVE_TO, 0, 5,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, 2,
-H_LINE_TO, 7,
-R_V_LINE_TO, -2,
-CLOSE
diff --git a/ash/resources/vector_icons/system_tray_battery_alert.icon b/ash/resources/vector_icons/system_tray_battery_alert.icon
index 8670cb6f..d343134 100644
--- a/ash/resources/vector_icons/system_tray_battery_alert.icon
+++ b/ash/resources/vector_icons/system_tray_battery_alert.icon
@@ -15,3 +15,17 @@
 R_H_LINE_TO, -2,
 R_V_LINE_TO, -2,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 7, 5,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 4,
+H_LINE_TO, 7,
+V_LINE_TO, 5,
+CLOSE,
+R_MOVE_TO, 0, 5,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 2,
+H_LINE_TO, 7,
+R_V_LINE_TO, -2,
+CLOSE
diff --git a/ash/resources/vector_icons/system_tray_battery_bolt.1x.icon b/ash/resources/vector_icons/system_tray_battery_bolt.1x.icon
deleted file mode 100644
index 87bdf57..0000000
--- a/ash/resources/vector_icons/system_tray_battery_bolt.1x.icon
+++ /dev/null
@@ -1,12 +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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 7.52f, 8.5f,
-H_LINE_TO, 6,
-LINE_TO, 8.53f, 4,
-R_V_LINE_TO, 3.5f,
-H_LINE_TO, 10,
-LINE_TO, 7.52f, 12,
-CLOSE
diff --git a/ash/resources/vector_icons/system_tray_battery_bolt.icon b/ash/resources/vector_icons/system_tray_battery_bolt.icon
index 6f64a3c..3eeced88b 100644
--- a/ash/resources/vector_icons/system_tray_battery_bolt.icon
+++ b/ash/resources/vector_icons/system_tray_battery_bolt.icon
@@ -10,3 +10,12 @@
 H_LINE_TO, 20,
 R_LINE_TO, -4.97f, 9,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 7.52f, 8.5f,
+H_LINE_TO, 6,
+LINE_TO, 8.53f, 4,
+R_V_LINE_TO, 3.5f,
+H_LINE_TO, 10,
+LINE_TO, 7.52f, 12,
+CLOSE
diff --git a/ash/resources/vector_icons/system_tray_battery_unreliable.1x.icon b/ash/resources/vector_icons/system_tray_battery_unreliable.1x.icon
deleted file mode 100644
index e489428..0000000
--- a/ash/resources/vector_icons/system_tray_battery_unreliable.1x.icon
+++ /dev/null
@@ -1,15 +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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 7.25f, 9.19f,
-R_CUBIC_TO, -0.99f, 0.01f, -1.25f, 0.6f, -1.25f, 0.6f,
-V_LINE_TO, 8.6f,
-CUBIC_TO, 6, 8.6f, 6.27f, 8, 7.26f, 8,
-R_CUBIC_TO, 0.99f, 0, 1.5f, 1.17f, 2.53f, 1.17f,
-R_CUBIC_TO, 1.03f, 0, 1.21f, -0.57f, 1.21f, -0.57f,
-R_V_LINE_TO, 1.19f,
-R_CUBIC_TO, 0, 0, -0.19f, 0.63f, -1.22f, 0.63f,
-R_CUBIC_TO, -1.03f, 0, -1.53f, -1.25f, -2.53f, -1.23f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_tray_battery_unreliable.icon b/ash/resources/vector_icons/system_tray_battery_unreliable.icon
index 4c8920d..d11e8eb 100644
--- a/ash/resources/vector_icons/system_tray_battery_unreliable.icon
+++ b/ash/resources/vector_icons/system_tray_battery_unreliable.icon
@@ -13,3 +13,15 @@
 R_CUBIC_TO, 0, 0, -0.38f, 1.05f, -2.44f, 1.05f,
 R_CUBIC_TO, -2.06f, 0, -3.07f, -2.08f, -5.06f, -2.05f,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 7.25f, 9.19f,
+R_CUBIC_TO, -0.99f, 0.01f, -1.25f, 0.6f, -1.25f, 0.6f,
+V_LINE_TO, 8.6f,
+CUBIC_TO, 6, 8.6f, 6.27f, 8, 7.26f, 8,
+R_CUBIC_TO, 0.99f, 0, 1.5f, 1.17f, 2.53f, 1.17f,
+R_CUBIC_TO, 1.03f, 0, 1.21f, -0.57f, 1.21f, -0.57f,
+R_V_LINE_TO, 1.19f,
+R_CUBIC_TO, 0, 0, -0.19f, 0.63f, -1.22f, 0.63f,
+R_CUBIC_TO, -1.03f, 0, -1.53f, -1.25f, -2.53f, -1.23f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_tray_battery_x.1x.icon b/ash/resources/vector_icons/system_tray_battery_x.1x.icon
deleted file mode 100644
index 81e484d..0000000
--- a/ash/resources/vector_icons/system_tray_battery_x.1x.icon
+++ /dev/null
@@ -1,19 +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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 8.67f, 9,
-LINE_TO, 10, 7.67f,
-LINE_TO, 9.33f, 7,
-LINE_TO, 8, 8.33f,
-LINE_TO, 6.67f, 7,
-LINE_TO, 6, 7.67f,
-LINE_TO, 7.33f, 9,
-LINE_TO, 6, 10.33f,
-R_LINE_TO, 0.67f, 0.67f,
-LINE_TO, 8, 9.67f,
-LINE_TO, 9.33f, 11,
-R_LINE_TO, 0.67f, -0.67f,
-LINE_TO, 8.67f, 9,
-CLOSE
diff --git a/ash/resources/vector_icons/system_tray_battery_x.icon b/ash/resources/vector_icons/system_tray_battery_x.icon
index 9d8fd327e..3571d142 100644
--- a/ash/resources/vector_icons/system_tray_battery_x.icon
+++ b/ash/resources/vector_icons/system_tray_battery_x.icon
@@ -17,3 +17,19 @@
 LINE_TO, 20, 20.67f,
 LINE_TO, 17.33f, 18,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 8.67f, 9,
+LINE_TO, 10, 7.67f,
+LINE_TO, 9.33f, 7,
+LINE_TO, 8, 8.33f,
+LINE_TO, 6.67f, 7,
+LINE_TO, 6, 7.67f,
+LINE_TO, 7.33f, 9,
+LINE_TO, 6, 10.33f,
+R_LINE_TO, 0.67f, 0.67f,
+LINE_TO, 8, 9.67f,
+LINE_TO, 9.33f, 11,
+R_LINE_TO, 0.67f, -0.67f,
+LINE_TO, 8.67f, 9,
+CLOSE
diff --git a/ash/resources/vector_icons/system_tray_caps_lock.1x.icon b/ash/resources/vector_icons/system_tray_caps_lock.1x.icon
deleted file mode 100644
index 95a9126..0000000
--- a/ash/resources/vector_icons/system_tray_caps_lock.1x.icon
+++ /dev/null
@@ -1,19 +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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 8, 6,
-R_LINE_TO, 3, 3,
-R_LINE_TO, 1, -1,
-R_LINE_TO, -4, -4,
-R_LINE_TO, -4, 4,
-R_LINE_TO, 1, 1,
-R_LINE_TO, 3, -3,
-CLOSE,
-R_MOVE_TO, -4, 7,
-R_H_LINE_TO, 8,
-R_V_LINE_TO, -2,
-H_LINE_TO, 4,
-R_V_LINE_TO, 2,
-CLOSE
diff --git a/ash/resources/vector_icons/system_tray_caps_lock.icon b/ash/resources/vector_icons/system_tray_caps_lock.icon
index 7a5c551..69c3e4b 100644
--- a/ash/resources/vector_icons/system_tray_caps_lock.icon
+++ b/ash/resources/vector_icons/system_tray_caps_lock.icon
@@ -17,3 +17,19 @@
 H_LINE_TO, 8,
 R_V_LINE_TO, 3,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 8, 6,
+R_LINE_TO, 3, 3,
+R_LINE_TO, 1, -1,
+R_LINE_TO, -4, -4,
+R_LINE_TO, -4, 4,
+R_LINE_TO, 1, 1,
+R_LINE_TO, 3, -3,
+CLOSE,
+R_MOVE_TO, -4, 7,
+R_H_LINE_TO, 8,
+R_V_LINE_TO, -2,
+H_LINE_TO, 4,
+R_V_LINE_TO, 2,
+CLOSE
diff --git a/ash/resources/vector_icons/system_tray_cast.1x.icon b/ash/resources/vector_icons/system_tray_cast.1x.icon
deleted file mode 100644
index 09d17d1..0000000
--- a/ash/resources/vector_icons/system_tray_cast.1x.icon
+++ /dev/null
@@ -1,44 +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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 2, 11.5f,
-V_LINE_TO, 13,
-R_H_LINE_TO, 1.5f,
-R_CUBIC_TO, 0, -0.83f, -0.67f, -1.5f, -1.5f, -1.5f,
-CLOSE,
-R_MOVE_TO, 0, -2,
-R_V_LINE_TO, 1,
-ARC_TO, 2.5f, 2.5f, 0, 0, 1, 4.5f, 13,
-R_H_LINE_TO, 1,
-R_CUBIC_TO, 0, -1.93f, -1.56f, -3.5f, -3.5f, -3.5f,
-CLOSE,
-MOVE_TO, 11, 6,
-H_LINE_TO, 4,
-R_V_LINE_TO, 0.82f,
-ARC_TO, 6.52f, 6.52f, 0, 0, 1, 8.19f, 11,
-H_LINE_TO, 11,
-V_LINE_TO, 6,
-CLOSE,
-MOVE_TO, 2, 7.5f,
-R_V_LINE_TO, 1,
-ARC_TO, 4.5f, 4.5f, 0, 0, 1, 6.5f, 13,
-R_H_LINE_TO, 1,
-ARC_TO, 5.5f, 5.5f, 0, 0, 0, 2, 7.5f,
-CLOSE,
-MOVE_TO, 12, 4,
-H_LINE_TO, 3,
-R_CUBIC_TO, -0.55f, 0, -1, 0.45f, -1, 1,
-R_V_LINE_TO, 1.5f,
-R_H_LINE_TO, 1,
-V_LINE_TO, 5,
-R_H_LINE_TO, 9,
-R_V_LINE_TO, 7,
-H_LINE_TO, 8.5f,
-R_V_LINE_TO, 1,
-H_LINE_TO, 12,
-R_CUBIC_TO, 0.55f, 0, 1, -0.45f, 1, -1,
-V_LINE_TO, 5,
-R_CUBIC_TO, 0, -0.55f, -0.45f, -1, -1, -1,
-CLOSE
diff --git a/ash/resources/vector_icons/system_tray_cast.icon b/ash/resources/vector_icons/system_tray_cast.icon
index 4ffc1401..d7e5f0c 100644
--- a/ash/resources/vector_icons/system_tray_cast.icon
+++ b/ash/resources/vector_icons/system_tray_cast.icon
@@ -52,3 +52,44 @@
 V_LINE_TO, 9,
 R_CUBIC_TO, 0, -1.1f, -0.9f, -2, -2, -2,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 2, 11.5f,
+V_LINE_TO, 13,
+R_H_LINE_TO, 1.5f,
+R_CUBIC_TO, 0, -0.83f, -0.67f, -1.5f, -1.5f, -1.5f,
+CLOSE,
+R_MOVE_TO, 0, -2,
+R_V_LINE_TO, 1,
+ARC_TO, 2.5f, 2.5f, 0, 0, 1, 4.5f, 13,
+R_H_LINE_TO, 1,
+R_CUBIC_TO, 0, -1.93f, -1.56f, -3.5f, -3.5f, -3.5f,
+CLOSE,
+MOVE_TO, 11, 6,
+H_LINE_TO, 4,
+R_V_LINE_TO, 0.82f,
+ARC_TO, 6.52f, 6.52f, 0, 0, 1, 8.19f, 11,
+H_LINE_TO, 11,
+V_LINE_TO, 6,
+CLOSE,
+MOVE_TO, 2, 7.5f,
+R_V_LINE_TO, 1,
+ARC_TO, 4.5f, 4.5f, 0, 0, 1, 6.5f, 13,
+R_H_LINE_TO, 1,
+ARC_TO, 5.5f, 5.5f, 0, 0, 0, 2, 7.5f,
+CLOSE,
+MOVE_TO, 12, 4,
+H_LINE_TO, 3,
+R_CUBIC_TO, -0.55f, 0, -1, 0.45f, -1, 1,
+R_V_LINE_TO, 1.5f,
+R_H_LINE_TO, 1,
+V_LINE_TO, 5,
+R_H_LINE_TO, 9,
+R_V_LINE_TO, 7,
+H_LINE_TO, 8.5f,
+R_V_LINE_TO, 1,
+H_LINE_TO, 12,
+R_CUBIC_TO, 0.55f, 0, 1, -0.45f, 1, -1,
+V_LINE_TO, 5,
+R_CUBIC_TO, 0, -0.55f, -0.45f, -1, -1, -1,
+CLOSE
diff --git a/ash/resources/vector_icons/system_tray_night_light.1x.icon b/ash/resources/vector_icons/system_tray_night_light.1x.icon
deleted file mode 100644
index e05838fa..0000000
--- a/ash/resources/vector_icons/system_tray_night_light.1x.icon
+++ /dev/null
@@ -1,20 +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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 7, 0,
-CUBIC_TO, 10.86f, 0, 14, 3.14f, 14, 7,
-CUBIC_TO, 14, 10.86f, 10.86f, 14, 7, 14,
-CUBIC_TO, 3.14f, 14, 0, 10.86f, 0, 7,
-CUBIC_TO, 0, 3.14f, 3.14f, 0, 7, 0,
-CLOSE,
-MOVE_TO, 9, 1.29f,
-CUBIC_TO, 8.41f, 1.1f, 7.77f, 1, 7.12f, 1,
-CUBIC_TO, 3.74f, 1, 1, 3.69f, 1, 7,
-CUBIC_TO, 1, 10.31f, 3.74f, 13, 7.12f, 13,
-CUBIC_TO, 7.77f, 13, 8.41f, 12.9f, 9, 12.71f,
-CUBIC_TO, 6.54f, 11.93f, 4.76f, 9.67f, 4.76f, 7,
-CUBIC_TO, 4.76f, 4.33f, 6.54f, 2.07f, 9, 1.29f,
-LINE_TO, 9, 1.29f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_tray_night_light.icon b/ash/resources/vector_icons/system_tray_night_light.icon
index 1ccd9c5..236d22a 100644
--- a/ash/resources/vector_icons/system_tray_night_light.icon
+++ b/ash/resources/vector_icons/system_tray_night_light.icon
@@ -17,3 +17,20 @@
 R_CUBIC_TO, -4.3f, -1.43f, -7.41f, -5.58f, -7.41f, -10.47f,
 R_CUBIC_TO, 0, -4.89f, 3.11f, -9.04f, 7.41f, -10.47f,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 7, 0,
+CUBIC_TO, 10.86f, 0, 14, 3.14f, 14, 7,
+CUBIC_TO, 14, 10.86f, 10.86f, 14, 7, 14,
+CUBIC_TO, 3.14f, 14, 0, 10.86f, 0, 7,
+CUBIC_TO, 0, 3.14f, 3.14f, 0, 7, 0,
+CLOSE,
+MOVE_TO, 9, 1.29f,
+CUBIC_TO, 8.41f, 1.1f, 7.77f, 1, 7.12f, 1,
+CUBIC_TO, 3.74f, 1, 1, 3.69f, 1, 7,
+CUBIC_TO, 1, 10.31f, 3.74f, 13, 7.12f, 13,
+CUBIC_TO, 7.77f, 13, 8.41f, 12.9f, 9, 12.71f,
+CUBIC_TO, 6.54f, 11.93f, 4.76f, 9.67f, 4.76f, 7,
+CUBIC_TO, 4.76f, 4.33f, 6.54f, 2.07f, 9, 1.29f,
+LINE_TO, 9, 1.29f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_tray_recording.1x.icon b/ash/resources/vector_icons/system_tray_recording.1x.icon
deleted file mode 100644
index 1d33b65..0000000
--- a/ash/resources/vector_icons/system_tray_recording.1x.icon
+++ /dev/null
@@ -1,8 +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.
-
-CANVAS_DIMENSIONS, 16,
-CIRCLE, 8, 8, 6,
-CIRCLE, 8, 8, 4.5f,
-CIRCLE, 8, 8, 3
diff --git a/ash/resources/vector_icons/system_tray_recording.icon b/ash/resources/vector_icons/system_tray_recording.icon
index bdc4091..7d2b99e 100644
--- a/ash/resources/vector_icons/system_tray_recording.icon
+++ b/ash/resources/vector_icons/system_tray_recording.icon
@@ -6,3 +6,8 @@
 CIRCLE, 16, 16, 12,
 CIRCLE, 16, 16, 9,
 CIRCLE, 16, 16, 7
+
+CANVAS_DIMENSIONS, 16,
+CIRCLE, 8, 8, 6,
+CIRCLE, 8, 8, 4.5f,
+CIRCLE, 8, 8, 3
diff --git a/ash/resources/vector_icons/system_tray_rotation_lock_auto.1x.icon b/ash/resources/vector_icons/system_tray_rotation_lock_auto.1x.icon
deleted file mode 100644
index a21753db..0000000
--- a/ash/resources/vector_icons/system_tray_rotation_lock_auto.1x.icon
+++ /dev/null
@@ -1,40 +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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 1.5f, 9.97f,
-R_CUBIC_TO, 0.23f, 2.72f, 2.52f, 4.85f, 5.31f, 4.85f,
-R_LINE_TO, 0.29f, -0.01f,
-R_LINE_TO, -1.69f, -1.68f,
-R_LINE_TO, -0.59f, 0.59f,
-R_CUBIC_TO, -1.45f, -0.68f, -2.49f, -2.08f, -2.65f, -3.74f,
-H_LINE_TO, 1.5f,
-MOVE_TO, 11.91f, 3.02f,
-R_CUBIC_TO, 1.45f, 0.68f, 2.49f, 2.08f, 2.65f, 3.74f,
-R_H_LINE_TO, 0.67f,
-CUBIC_TO, 15, 4.05f, 12.71f, 1.91f, 9.92f, 1.91f,
-R_LINE_TO, -0.29f, 0.01f,
-R_LINE_TO, 1.69f, 1.69f,
-R_LINE_TO, 0.59f, -0.59f,
-CLOSE,
-MOVE_TO, 9.65f, 13.92f,
-LINE_TO, 2.77f, 7.08f,
-LINE_TO, 7.07f, 2.81f,
-R_LINE_TO, 5.43f, 5.39f,
-R_LINE_TO, 0.32f, 0.32f,
-R_LINE_TO, 1.13f, 1.12f,
-LINE_TO, 9.65f, 13.92f,
-CLOSE,
-R_MOVE_TO, 5.16f, -5.13f,
-R_LINE_TO, -1.13f, -1.12f,
-R_LINE_TO, -0.32f, -0.32f,
-LINE_TO, 7.93f, 1.96f,
-R_CUBIC_TO, -0.47f, -0.47f, -1.25f, -0.47f, -1.72f, 0,
-LINE_TO, 1.9f, 6.23f,
-R_CUBIC_TO, -0.47f, 0.47f, -0.47f, 1.24f, 0, 1.71f,
-R_LINE_TO, 6.89f, 6.84f,
-R_CUBIC_TO, 0.47f, 0.47f, 1.25f, 0.47f, 1.72f, 0,
-R_LINE_TO, 4.31f, -4.27f,
-R_CUBIC_TO, 0.47f, -0.47f, 0.47f, -1.24f, 0, -1.71f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_tray_rotation_lock_auto.icon b/ash/resources/vector_icons/system_tray_rotation_lock_auto.icon
index 52d97659..2773249 100644
--- a/ash/resources/vector_icons/system_tray_rotation_lock_auto.icon
+++ b/ash/resources/vector_icons/system_tray_rotation_lock_auto.icon
@@ -38,3 +38,40 @@
 R_LINE_TO, 8.62f, -8.53f,
 R_CUBIC_TO, 0.95f, -0.94f, 0.95f, -2.48f, 0, -3.42f,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 1.5f, 9.97f,
+R_CUBIC_TO, 0.23f, 2.72f, 2.52f, 4.85f, 5.31f, 4.85f,
+R_LINE_TO, 0.29f, -0.01f,
+R_LINE_TO, -1.69f, -1.68f,
+R_LINE_TO, -0.59f, 0.59f,
+R_CUBIC_TO, -1.45f, -0.68f, -2.49f, -2.08f, -2.65f, -3.74f,
+H_LINE_TO, 1.5f,
+MOVE_TO, 11.91f, 3.02f,
+R_CUBIC_TO, 1.45f, 0.68f, 2.49f, 2.08f, 2.65f, 3.74f,
+R_H_LINE_TO, 0.67f,
+CUBIC_TO, 15, 4.05f, 12.71f, 1.91f, 9.92f, 1.91f,
+R_LINE_TO, -0.29f, 0.01f,
+R_LINE_TO, 1.69f, 1.69f,
+R_LINE_TO, 0.59f, -0.59f,
+CLOSE,
+MOVE_TO, 9.65f, 13.92f,
+LINE_TO, 2.77f, 7.08f,
+LINE_TO, 7.07f, 2.81f,
+R_LINE_TO, 5.43f, 5.39f,
+R_LINE_TO, 0.32f, 0.32f,
+R_LINE_TO, 1.13f, 1.12f,
+LINE_TO, 9.65f, 13.92f,
+CLOSE,
+R_MOVE_TO, 5.16f, -5.13f,
+R_LINE_TO, -1.13f, -1.12f,
+R_LINE_TO, -0.32f, -0.32f,
+LINE_TO, 7.93f, 1.96f,
+R_CUBIC_TO, -0.47f, -0.47f, -1.25f, -0.47f, -1.72f, 0,
+LINE_TO, 1.9f, 6.23f,
+R_CUBIC_TO, -0.47f, 0.47f, -0.47f, 1.24f, 0, 1.71f,
+R_LINE_TO, 6.89f, 6.84f,
+R_CUBIC_TO, 0.47f, 0.47f, 1.25f, 0.47f, 1.72f, 0,
+R_LINE_TO, 4.31f, -4.27f,
+R_CUBIC_TO, 0.47f, -0.47f, 0.47f, -1.24f, 0, -1.71f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_tray_rotation_lock_locked.1x.icon b/ash/resources/vector_icons/system_tray_rotation_lock_locked.1x.icon
deleted file mode 100644
index 45286a6..0000000
--- a/ash/resources/vector_icons/system_tray_rotation_lock_locked.1x.icon
+++ /dev/null
@@ -1,51 +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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 4.89f, 13.41f,
-R_CUBIC_TO, -1.41f, -0.66f, -2.42f, -2.01f, -2.58f, -3.61f,
-R_H_LINE_TO, -0.65f,
-R_CUBIC_TO, 0.22f, 2.62f, 2.44f, 4.69f, 5.16f, 4.69f,
-R_LINE_TO, 0.29f, -0.01f,
-R_LINE_TO, -1.65f, -1.63f,
-R_LINE_TO, -0.57f, 0.57f,
-CLOSE,
-MOVE_TO, 14.49f, 8.76f,
-R_LINE_TO, -1.41f, -1.39f,
-R_LINE_TO, -0.84f, 0.83f,
-R_LINE_TO, 1.41f, 1.39f,
-R_LINE_TO, -4.18f, 4.12f,
-R_LINE_TO, -6.69f, -6.6f,
-LINE_TO, 6.96f, 2.99f,
-R_LINE_TO, 1.41f, 1.39f,
-R_LINE_TO, 0.84f, -0.82f,
-LINE_TO, 7.8f, 2.16f,
-R_CUBIC_TO, -0.46f, -0.45f, -1.21f, -0.45f, -1.67f, 0,
-LINE_TO, 1.95f, 6.29f,
-R_CUBIC_TO, -0.46f, 0.45f, -0.46f, 1.2f, 0, 1.65f,
-R_LINE_TO, 6.69f, 6.6f,
-R_CUBIC_TO, 0.46f, 0.45f, 1.21f, 0.45f, 1.67f, -0.01f,
-R_LINE_TO, 4.18f, -4.12f,
-R_CUBIC_TO, 0.46f, -0.45f, 0.46f, -1.2f, 0, -1.65f,
-CLOSE,
-MOVE_TO, 11, 3.77f,
-R_CUBIC_TO, 0, -0.43f, 0.43f, -0.77f, 0.97f, -0.77f,
-R_CUBIC_TO, 0.54f, 0, 0.97f, 0.35f, 0.97f, 0.77f,
-V_LINE_TO, 4,
-H_LINE_TO, 11,
-R_V_LINE_TO, -0.23f,
-CLOSE,
-MOVE_TO, 10.57f, 7,
-R_H_LINE_TO, 2.86f,
-R_CUBIC_TO, 0.31f, 0, 0.57f, -0.25f, 0.57f, -0.56f,
-R_V_LINE_TO, -2.22f,
-R_CUBIC_TO, 0, -0.31f, -0.26f, -0.56f, -0.57f, -0.56f,
-V_LINE_TO, 3.39f,
-CUBIC_TO, 13.43f, 2.62f, 12.79f, 2, 12, 2,
-R_CUBIC_TO, -0.79f, 0, -1.43f, 0.62f, -1.43f, 1.39f,
-R_V_LINE_TO, 0.28f,
-R_CUBIC_TO, -0.31f, 0, -0.57f, 0.25f, -0.57f, 0.56f,
-R_V_LINE_TO, 2.22f,
-R_CUBIC_TO, 0, 0.31f, 0.26f, 0.56f, 0.57f, 0.56f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_tray_rotation_lock_locked.icon b/ash/resources/vector_icons/system_tray_rotation_lock_locked.icon
index be80263a..5f81ff9 100644
--- a/ash/resources/vector_icons/system_tray_rotation_lock_locked.icon
+++ b/ash/resources/vector_icons/system_tray_rotation_lock_locked.icon
@@ -49,3 +49,51 @@
 R_V_LINE_TO, 4.44f,
 CUBIC_TO, 19, 13.5f, 19.52f, 14, 20.14f, 14,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 4.89f, 13.41f,
+R_CUBIC_TO, -1.41f, -0.66f, -2.42f, -2.01f, -2.58f, -3.61f,
+R_H_LINE_TO, -0.65f,
+R_CUBIC_TO, 0.22f, 2.62f, 2.44f, 4.69f, 5.16f, 4.69f,
+R_LINE_TO, 0.29f, -0.01f,
+R_LINE_TO, -1.65f, -1.63f,
+R_LINE_TO, -0.57f, 0.57f,
+CLOSE,
+MOVE_TO, 14.49f, 8.76f,
+R_LINE_TO, -1.41f, -1.39f,
+R_LINE_TO, -0.84f, 0.83f,
+R_LINE_TO, 1.41f, 1.39f,
+R_LINE_TO, -4.18f, 4.12f,
+R_LINE_TO, -6.69f, -6.6f,
+LINE_TO, 6.96f, 2.99f,
+R_LINE_TO, 1.41f, 1.39f,
+R_LINE_TO, 0.84f, -0.82f,
+LINE_TO, 7.8f, 2.16f,
+R_CUBIC_TO, -0.46f, -0.45f, -1.21f, -0.45f, -1.67f, 0,
+LINE_TO, 1.95f, 6.29f,
+R_CUBIC_TO, -0.46f, 0.45f, -0.46f, 1.2f, 0, 1.65f,
+R_LINE_TO, 6.69f, 6.6f,
+R_CUBIC_TO, 0.46f, 0.45f, 1.21f, 0.45f, 1.67f, -0.01f,
+R_LINE_TO, 4.18f, -4.12f,
+R_CUBIC_TO, 0.46f, -0.45f, 0.46f, -1.2f, 0, -1.65f,
+CLOSE,
+MOVE_TO, 11, 3.77f,
+R_CUBIC_TO, 0, -0.43f, 0.43f, -0.77f, 0.97f, -0.77f,
+R_CUBIC_TO, 0.54f, 0, 0.97f, 0.35f, 0.97f, 0.77f,
+V_LINE_TO, 4,
+H_LINE_TO, 11,
+R_V_LINE_TO, -0.23f,
+CLOSE,
+MOVE_TO, 10.57f, 7,
+R_H_LINE_TO, 2.86f,
+R_CUBIC_TO, 0.31f, 0, 0.57f, -0.25f, 0.57f, -0.56f,
+R_V_LINE_TO, -2.22f,
+R_CUBIC_TO, 0, -0.31f, -0.26f, -0.56f, -0.57f, -0.56f,
+V_LINE_TO, 3.39f,
+CUBIC_TO, 13.43f, 2.62f, 12.79f, 2, 12, 2,
+R_CUBIC_TO, -0.79f, 0, -1.43f, 0.62f, -1.43f, 1.39f,
+R_V_LINE_TO, 0.28f,
+R_CUBIC_TO, -0.31f, 0, -0.57f, 0.25f, -0.57f, 0.56f,
+R_V_LINE_TO, 2.22f,
+R_CUBIC_TO, 0, 0.31f, 0.26f, 0.56f, 0.57f, 0.56f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_tray_screen_share.1x.icon b/ash/resources/vector_icons/system_tray_screen_share.1x.icon
deleted file mode 100644
index 661d84c..0000000
--- a/ash/resources/vector_icons/system_tray_screen_share.1x.icon
+++ /dev/null
@@ -1,29 +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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 2.31f, 3,
-CUBIC_TO, 1.59f, 3, 1, 3.57f, 1, 4.27f,
-R_V_LINE_TO, 7.62f,
-CUBIC_TO, 1, 12.58f, 1.59f, 13, 2.31f, 13,
-R_H_LINE_TO, 11.38f,
-R_CUBIC_TO, 0.72f, 0, 1.31f, -0.42f, 1.31f, -1.11f,
-V_LINE_TO, 4.27f,
-CUBIC_TO, 15, 3.57f, 14.41f, 3, 13.69f, 3,
-H_LINE_TO, 2.31f,
-CLOSE,
-MOVE_TO, 2, 12,
-V_LINE_TO, 4,
-R_H_LINE_TO, 12,
-R_V_LINE_TO, 8,
-H_LINE_TO, 2,
-CLOSE,
-R_MOVE_TO, 6.36f, -3.33f,
-CUBIC_TO, 6.62f, 8.64f, 5.8f, 9.07f, 5, 10,
-R_CUBIC_TO, 0.32f, -1.33f, 0.98f, -2.66f, 3.36f, -2.67f,
-V_LINE_TO, 6,
-LINE_TO, 11, 8,
-R_LINE_TO, -2.64f, 2,
-V_LINE_TO, 8.67f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_tray_screen_share.icon b/ash/resources/vector_icons/system_tray_screen_share.icon
index 32b8cfc..6c9fed1 100644
--- a/ash/resources/vector_icons/system_tray_screen_share.icon
+++ b/ash/resources/vector_icons/system_tray_screen_share.icon
@@ -27,3 +27,29 @@
 LINE_TO, 17, 20,
 R_V_LINE_TO, -3,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 2.31f, 3,
+CUBIC_TO, 1.59f, 3, 1, 3.57f, 1, 4.27f,
+R_V_LINE_TO, 7.62f,
+CUBIC_TO, 1, 12.58f, 1.59f, 13, 2.31f, 13,
+R_H_LINE_TO, 11.38f,
+R_CUBIC_TO, 0.72f, 0, 1.31f, -0.42f, 1.31f, -1.11f,
+V_LINE_TO, 4.27f,
+CUBIC_TO, 15, 3.57f, 14.41f, 3, 13.69f, 3,
+H_LINE_TO, 2.31f,
+CLOSE,
+MOVE_TO, 2, 12,
+V_LINE_TO, 4,
+R_H_LINE_TO, 12,
+R_V_LINE_TO, 8,
+H_LINE_TO, 2,
+CLOSE,
+R_MOVE_TO, 6.36f, -3.33f,
+CUBIC_TO, 6.62f, 8.64f, 5.8f, 9.07f, 5, 10,
+R_CUBIC_TO, 0.32f, -1.33f, 0.98f, -2.66f, 3.36f, -2.67f,
+V_LINE_TO, 6,
+LINE_TO, 11, 8,
+R_LINE_TO, -2.64f, 2,
+V_LINE_TO, 8.67f,
+CLOSE
diff --git a/ash/resources/vector_icons/system_tray_tracing.1x.icon b/ash/resources/vector_icons/system_tray_tracing.1x.icon
deleted file mode 100644
index a761968..0000000
--- a/ash/resources/vector_icons/system_tray_tracing.1x.icon
+++ /dev/null
@@ -1,33 +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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 12.67f, 2,
-H_LINE_TO, 3.33f,
-CUBIC_TO, 2.6f, 2, 2, 2.6f, 2, 3.33f,
-R_V_LINE_TO, 9.33f,
-CUBIC_TO, 2, 13.4f, 2.6f, 14, 3.33f, 14,
-R_H_LINE_TO, 9.33f,
-CUBIC_TO, 13.4f, 14, 14, 13.4f, 14, 12.67f,
-V_LINE_TO, 3.33f,
-CUBIC_TO, 14, 2.6f, 13.4f, 2, 12.67f, 2,
-CLOSE,
-MOVE_TO, 6, 12,
-H_LINE_TO, 4,
-V_LINE_TO, 7,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, 5,
-CLOSE,
-R_MOVE_TO, 3, 0,
-H_LINE_TO, 7,
-V_LINE_TO, 4,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, 8,
-CLOSE,
-R_MOVE_TO, 3, 0,
-R_H_LINE_TO, -2,
-V_LINE_TO, 8,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, 4,
-CLOSE
diff --git a/ash/resources/vector_icons/system_tray_tracing.icon b/ash/resources/vector_icons/system_tray_tracing.icon
index 6d4b8d8..70a70e3 100644
--- a/ash/resources/vector_icons/system_tray_tracing.icon
+++ b/ash/resources/vector_icons/system_tray_tracing.icon
@@ -31,3 +31,33 @@
 R_H_LINE_TO, 3,
 R_V_LINE_TO, 7,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 12.67f, 2,
+H_LINE_TO, 3.33f,
+CUBIC_TO, 2.6f, 2, 2, 2.6f, 2, 3.33f,
+R_V_LINE_TO, 9.33f,
+CUBIC_TO, 2, 13.4f, 2.6f, 14, 3.33f, 14,
+R_H_LINE_TO, 9.33f,
+CUBIC_TO, 13.4f, 14, 14, 13.4f, 14, 12.67f,
+V_LINE_TO, 3.33f,
+CUBIC_TO, 14, 2.6f, 13.4f, 2, 12.67f, 2,
+CLOSE,
+MOVE_TO, 6, 12,
+H_LINE_TO, 4,
+V_LINE_TO, 7,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 5,
+CLOSE,
+R_MOVE_TO, 3, 0,
+H_LINE_TO, 7,
+V_LINE_TO, 4,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 8,
+CLOSE,
+R_MOVE_TO, 3, 0,
+R_H_LINE_TO, -2,
+V_LINE_TO, 8,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 4,
+CLOSE
diff --git a/ash/resources/vector_icons/system_tray_update.1x.icon b/ash/resources/vector_icons/system_tray_update.1x.icon
deleted file mode 100644
index 92de678..0000000
--- a/ash/resources/vector_icons/system_tray_update.1x.icon
+++ /dev/null
@@ -1,20 +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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 8, 14,
-R_CUBIC_TO, 3.31f, 0, 6, -2.69f, 6, -6,
-R_CUBIC_TO, 0, -3.31f, -2.69f, -6, -6, -6,
-R_CUBIC_TO, -3.31f, 0, -6, 2.69f, -6, 6,
-R_CUBIC_TO, 0, 3.31f, 2.69f, 6, 6, 6,
-CLOSE,
-R_MOVE_TO, -1.85f, -2,
-R_H_LINE_TO, 3.69f,
-V_LINE_TO, 9,
-H_LINE_TO, 12.5f,
-LINE_TO, 8, 4,
-LINE_TO, 3.5f, 9,
-R_H_LINE_TO, 2.65f,
-R_V_LINE_TO, 3,
-CLOSE
diff --git a/ash/resources/vector_icons/system_tray_update.icon b/ash/resources/vector_icons/system_tray_update.icon
index bb2c67f..52d66dd 100644
--- a/ash/resources/vector_icons/system_tray_update.icon
+++ b/ash/resources/vector_icons/system_tray_update.icon
@@ -18,3 +18,20 @@
 R_H_LINE_TO, 5,
 R_V_LINE_TO, 6,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 8, 14,
+R_CUBIC_TO, 3.31f, 0, 6, -2.69f, 6, -6,
+R_CUBIC_TO, 0, -3.31f, -2.69f, -6, -6, -6,
+R_CUBIC_TO, -3.31f, 0, -6, 2.69f, -6, 6,
+R_CUBIC_TO, 0, 3.31f, 2.69f, 6, 6, 6,
+CLOSE,
+R_MOVE_TO, -1.85f, -2,
+R_H_LINE_TO, 3.69f,
+V_LINE_TO, 9,
+H_LINE_TO, 12.5f,
+LINE_TO, 8, 4,
+LINE_TO, 3.5f, 9,
+R_H_LINE_TO, 2.65f,
+R_V_LINE_TO, 3,
+CLOSE
diff --git a/ash/resources/vector_icons/system_tray_volume_mute.1x.icon b/ash/resources/vector_icons/system_tray_volume_mute.1x.icon
deleted file mode 100644
index c2810f15..0000000
--- a/ash/resources/vector_icons/system_tray_volume_mute.1x.icon
+++ /dev/null
@@ -1,41 +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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 11, 8,
-R_ARC_TO, 3, 3, 0, 0, 0, -1.67f, -2.69f,
-R_V_LINE_TO, 1.47f,
-R_LINE_TO, 1.63f, 1.63f,
-R_CUBIC_TO, 0.02f, -0.13f, 0.03f, -0.27f, 0.03f, -0.42f,
-CLOSE,
-R_MOVE_TO, 1.67f, 0,
-R_CUBIC_TO, 0, 0.63f, -0.13f, 1.21f, -0.36f, 1.76f,
-R_LINE_TO, 1.01f, 1.01f,
-CUBIC_TO, 13.75f, 9.94f, 14, 9, 14, 8,
-R_ARC_TO, 6, 6, 0, 0, 0, -4.67f, -5.85f,
-R_V_LINE_TO, 1.37f,
-ARC_TO, 4.67f, 4.67f, 0, 0, 1, 12.67f, 8,
-CLOSE,
-R_MOVE_TO, -9.82f, -6,
-LINE_TO, 2, 2.85f,
-LINE_TO, 5.15f, 6,
-H_LINE_TO, 2,
-R_V_LINE_TO, 4,
-R_H_LINE_TO, 2.67f,
-LINE_TO, 8, 13.33f,
-V_LINE_TO, 8.85f,
-R_LINE_TO, 2.83f, 2.83f,
-R_CUBIC_TO, -0.45f, 0.35f, -0.95f, 0.62f, -1.5f, 0.79f,
-R_V_LINE_TO, 1.37f,
-R_ARC_TO, 5.99f, 5.99f, 0, 0, 0, 2.46f, -1.21f,
-LINE_TO, 13.15f, 14,
-R_LINE_TO, 0.85f, -0.85f,
-R_LINE_TO, -6, -6,
-LINE_TO, 2.85f, 2,
-CLOSE,
-MOVE_TO, 8, 2.67f,
-LINE_TO, 6.61f, 4.06f,
-LINE_TO, 8, 5.45f,
-V_LINE_TO, 2.67f,
-CLOSE
diff --git a/ash/resources/vector_icons/system_tray_volume_mute.icon b/ash/resources/vector_icons/system_tray_volume_mute.icon
index a2479b9..e05c2df 100644
--- a/ash/resources/vector_icons/system_tray_volume_mute.icon
+++ b/ash/resources/vector_icons/system_tray_volume_mute.icon
@@ -39,3 +39,41 @@
 LINE_TO, 16, 10.91f,
 V_LINE_TO, 5.33f,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 11, 8,
+R_ARC_TO, 3, 3, 0, 0, 0, -1.67f, -2.69f,
+R_V_LINE_TO, 1.47f,
+R_LINE_TO, 1.63f, 1.63f,
+R_CUBIC_TO, 0.02f, -0.13f, 0.03f, -0.27f, 0.03f, -0.42f,
+CLOSE,
+R_MOVE_TO, 1.67f, 0,
+R_CUBIC_TO, 0, 0.63f, -0.13f, 1.21f, -0.36f, 1.76f,
+R_LINE_TO, 1.01f, 1.01f,
+CUBIC_TO, 13.75f, 9.94f, 14, 9, 14, 8,
+R_ARC_TO, 6, 6, 0, 0, 0, -4.67f, -5.85f,
+R_V_LINE_TO, 1.37f,
+ARC_TO, 4.67f, 4.67f, 0, 0, 1, 12.67f, 8,
+CLOSE,
+R_MOVE_TO, -9.82f, -6,
+LINE_TO, 2, 2.85f,
+LINE_TO, 5.15f, 6,
+H_LINE_TO, 2,
+R_V_LINE_TO, 4,
+R_H_LINE_TO, 2.67f,
+LINE_TO, 8, 13.33f,
+V_LINE_TO, 8.85f,
+R_LINE_TO, 2.83f, 2.83f,
+R_CUBIC_TO, -0.45f, 0.35f, -0.95f, 0.62f, -1.5f, 0.79f,
+R_V_LINE_TO, 1.37f,
+R_ARC_TO, 5.99f, 5.99f, 0, 0, 0, 2.46f, -1.21f,
+LINE_TO, 13.15f, 14,
+R_LINE_TO, 0.85f, -0.85f,
+R_LINE_TO, -6, -6,
+LINE_TO, 2.85f, 2,
+CLOSE,
+MOVE_TO, 8, 2.67f,
+LINE_TO, 6.61f, 4.06f,
+LINE_TO, 8, 5.45f,
+V_LINE_TO, 2.67f,
+CLOSE
diff --git a/ash/resources/vector_icons/touch_calibration_complete_check.1x.icon b/ash/resources/vector_icons/touch_calibration_complete_check.1x.icon
deleted file mode 100644
index 0b8d779..0000000
--- a/ash/resources/vector_icons/touch_calibration_complete_check.1x.icon
+++ /dev/null
@@ -1,21 +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.
-
-CANVAS_DIMENSIONS, 64,
-MOVE_TO, 32, 5.33f,
-CUBIC_TO, 17.28f, 5.33f, 5.33f, 17.28f, 5.33f, 32,
-CUBIC_TO, 5.33f, 46.72f, 17.28f, 58.67f, 32, 58.67f,
-CUBIC_TO, 46.72f, 58.67f, 58.67f, 46.72f, 58.67f, 32,
-CUBIC_TO, 58.67f, 17.28f, 46.72f, 5.33f, 32, 5.33f,
-LINE_TO, 32, 5.33f,
-CLOSE,
-MOVE_TO, 26.67f, 45.33f,
-LINE_TO, 13.33f, 32,
-LINE_TO, 17.09f, 28.24f,
-LINE_TO, 26.67f, 37.79f,
-LINE_TO, 46.91f, 17.55f,
-LINE_TO, 50.67f, 21.33f,
-LINE_TO, 26.67f, 45.33f,
-LINE_TO, 26.67f, 45.33f,
-CLOSE
diff --git a/ash/resources/vector_icons/touch_calibration_complete_check.icon b/ash/resources/vector_icons/touch_calibration_complete_check.icon
index 14b14f0..991112a 100644
--- a/ash/resources/vector_icons/touch_calibration_complete_check.icon
+++ b/ash/resources/vector_icons/touch_calibration_complete_check.icon
@@ -19,3 +19,21 @@
 LINE_TO, 53.33f, 90.67f,
 LINE_TO, 53.33f, 90.67f,
 CLOSE
+
+CANVAS_DIMENSIONS, 64,
+MOVE_TO, 32, 5.33f,
+CUBIC_TO, 17.28f, 5.33f, 5.33f, 17.28f, 5.33f, 32,
+CUBIC_TO, 5.33f, 46.72f, 17.28f, 58.67f, 32, 58.67f,
+CUBIC_TO, 46.72f, 58.67f, 58.67f, 46.72f, 58.67f, 32,
+CUBIC_TO, 58.67f, 17.28f, 46.72f, 5.33f, 32, 5.33f,
+LINE_TO, 32, 5.33f,
+CLOSE,
+MOVE_TO, 26.67f, 45.33f,
+LINE_TO, 13.33f, 32,
+LINE_TO, 17.09f, 28.24f,
+LINE_TO, 26.67f, 37.79f,
+LINE_TO, 46.91f, 17.55f,
+LINE_TO, 50.67f, 21.33f,
+LINE_TO, 26.67f, 45.33f,
+LINE_TO, 26.67f, 45.33f,
+CLOSE
diff --git a/ash/resources/vector_icons/tray_action_new_lock_screen_note.1x.icon b/ash/resources/vector_icons/tray_action_new_lock_screen_note.1x.icon
deleted file mode 100644
index e3fd929..0000000
--- a/ash/resources/vector_icons/tray_action_new_lock_screen_note.1x.icon
+++ /dev/null
@@ -1,20 +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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 8.99f, 1.01f,
-LINE_TO, 4.32f, 1.01f,
-CUBIC_TO, 3.59f, 1.01f, 3, 1.61f, 3, 2.34f,
-LINE_TO, 2.99f, 13.69f,
-CUBIC_TO, 2.99f, 14.42f, 3.58f, 15, 4.32f, 15,
-LINE_TO, 11.68f, 15,
-CUBIC_TO, 12.41f, 15, 13.01f, 14.42f, 13.01f, 13.69f,
-LINE_TO, 13.01f, 4.98f,
-LINE_TO, 8.99f, 1.01f,
-CLOSE,
-MOVE_TO, 9, 6,
-LINE_TO, 9, 2.53f,
-LINE_TO, 12.54f, 6,
-LINE_TO, 9, 6,
-CLOSE
diff --git a/ash/resources/vector_icons/tray_action_new_lock_screen_note.icon b/ash/resources/vector_icons/tray_action_new_lock_screen_note.icon
index df9d179..ae2ceb3 100644
--- a/ash/resources/vector_icons/tray_action_new_lock_screen_note.icon
+++ b/ash/resources/vector_icons/tray_action_new_lock_screen_note.icon
@@ -18,3 +18,20 @@
 LINE_TO, 24.67f, 12,
 LINE_TO, 17.33f, 12,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 8.99f, 1.01f,
+LINE_TO, 4.32f, 1.01f,
+CUBIC_TO, 3.59f, 1.01f, 3, 1.61f, 3, 2.34f,
+LINE_TO, 2.99f, 13.69f,
+CUBIC_TO, 2.99f, 14.42f, 3.58f, 15, 4.32f, 15,
+LINE_TO, 11.68f, 15,
+CUBIC_TO, 12.41f, 15, 13.01f, 14.42f, 13.01f, 13.69f,
+LINE_TO, 13.01f, 4.98f,
+LINE_TO, 8.99f, 1.01f,
+CLOSE,
+MOVE_TO, 9, 6,
+LINE_TO, 9, 2.53f,
+LINE_TO, 12.54f, 6,
+LINE_TO, 9, 6,
+CLOSE
diff --git a/ash/system/network/network_list.cc b/ash/system/network/network_list.cc
index 036eb9b..34472dc68 100644
--- a/ash/system/network/network_list.cc
+++ b/ash/system/network/network_list.cc
@@ -140,16 +140,6 @@
 
   void SetSubtitle(int subtitle_id) {
     network_row_title_view_->SetSubtitle(subtitle_id);
-
-    // The left padding of the toggle is different depending on whether the
-    // subtitle is displayed.
-    const int toggle_left_padding = subtitle_id == 0
-                                        ? kToggleLeftPaddingWithoutSubtitle
-                                        : kToggleLeftPaddingWithSubtitle;
-    const gfx::Insets previous_insets = toggle_->border()->GetInsets();
-    toggle_->SetBorder(views::CreateEmptyBorder(
-        gfx::Insets(previous_insets.top(), toggle_left_padding,
-                    previous_insets.bottom(), previous_insets.right())));
   }
 
   virtual void SetToggleState(bool toggle_enabled, bool is_on) {
@@ -188,9 +178,6 @@
   }
 
  private:
-  static const int kToggleLeftPaddingWithoutSubtitle = 18;
-  static const int kToggleLeftPaddingWithSubtitle = 8;
-
   void InitializeLayout() {
     TrayPopupUtils::ConfigureAsStickyHeader(this);
     SetLayoutManager(std::make_unique<views::FillLayout>());
@@ -233,7 +220,7 @@
 class MobileHeaderRowView : public NetworkListView::SectionHeaderRowView,
                             public chromeos::NetworkStateHandlerObserver {
  public:
-  MobileHeaderRowView(NetworkStateHandler* network_state_handler)
+  explicit MobileHeaderRowView(NetworkStateHandler* network_state_handler)
       : SectionHeaderRowView(IDS_ASH_STATUS_TRAY_NETWORK_MOBILE),
         network_state_handler_(network_state_handler),
         weak_ptr_factory_(this) {
diff --git a/ash/system/power/power_button_controller.cc b/ash/system/power/power_button_controller.cc
index 9fc4ca4..964ed7fa 100644
--- a/ash/system/power/power_button_controller.cc
+++ b/ash/system/power/power_button_controller.cc
@@ -5,6 +5,7 @@
 #include "ash/system/power/power_button_controller.h"
 
 #include <limits>
+#include <string>
 #include <utility>
 
 #include "ash/accelerators/accelerator_controller.h"
@@ -21,6 +22,7 @@
 #include "ash/wm/session_state_animator.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "base/command_line.h"
+#include "base/json/json_reader.h"
 #include "base/time/default_tick_clock.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power_manager/backlight.pb.h"
@@ -73,6 +75,14 @@
 constexpr base::TimeDelta
     PowerButtonController::kIgnorePowerButtonAfterResumeDelay;
 
+constexpr const char* PowerButtonController::kPositionField;
+constexpr const char* PowerButtonController::kXField;
+constexpr const char* PowerButtonController::kYField;
+constexpr const char* PowerButtonController::kLeftPosition;
+constexpr const char* PowerButtonController::kRightPosition;
+constexpr const char* PowerButtonController::kTopPosition;
+constexpr const char* PowerButtonController::kBottomPosition;
+
 PowerButtonController::PowerButtonController(
     BacklightsForcedOffSetter* backlights_forced_off_setter)
     : backlights_forced_off_setter_(backlights_forced_off_setter),
@@ -356,6 +366,7 @@
   if (!menu_widget_)
     menu_widget_ = CreateMenuWidget();
   menu_widget_->SetContentsView(new PowerButtonMenuScreenView(
+      power_button_position_, power_button_offset_percentage_,
       base::BindRepeating(&PowerButtonController::SetShowMenuAnimationDone,
                           base::Unretained(this))));
   menu_widget_->Show();
@@ -382,6 +393,8 @@
   observe_accelerometer_events_ = cl->HasSwitch(switches::kAshEnableTabletMode);
   force_clamshell_power_button_ =
       cl->HasSwitch(switches::kForceClamshellPowerButton);
+
+  ParsePowerButtonPositionSwitch();
 }
 
 void PowerButtonController::InitTabletPowerButtonMembers() {
@@ -409,4 +422,56 @@
   show_menu_animation_done_ = true;
 }
 
+void PowerButtonController::ParsePowerButtonPositionSwitch() {
+  const base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
+  if (!cl->HasSwitch(switches::kAshPowerButtonPosition))
+    return;
+
+  std::unique_ptr<base::DictionaryValue> position_info =
+      base::DictionaryValue::From(base::JSONReader::Read(
+          cl->GetSwitchValueASCII(switches::kAshPowerButtonPosition)));
+  if (!position_info) {
+    LOG(ERROR) << switches::kAshPowerButtonPosition << " flag has no value";
+    return;
+  }
+
+  std::string str_power_button_position;
+  if (!position_info->GetString(kPositionField, &str_power_button_position)) {
+    LOG(ERROR) << kPositionField << " field is always needed if "
+               << switches::kAshPowerButtonPosition << " is set";
+    return;
+  }
+
+  if (str_power_button_position == kLeftPosition) {
+    power_button_position_ = PowerButtonPosition::LEFT;
+  } else if (str_power_button_position == kRightPosition) {
+    power_button_position_ = PowerButtonPosition::RIGHT;
+  } else if (str_power_button_position == kTopPosition) {
+    power_button_position_ = PowerButtonPosition::TOP;
+  } else if (str_power_button_position == kBottomPosition) {
+    power_button_position_ = PowerButtonPosition::BOTTOM;
+  } else {
+    LOG(ERROR) << "Invalid " << kPositionField << " field in "
+               << switches::kAshPowerButtonPosition;
+    return;
+  }
+
+  if (power_button_position_ == PowerButtonPosition::LEFT ||
+      power_button_position_ == PowerButtonPosition::RIGHT) {
+    if (!position_info->GetDouble(kYField, &power_button_offset_percentage_)) {
+      LOG(ERROR) << kYField << " not set in "
+                 << switches::kAshPowerButtonPosition;
+      power_button_position_ = PowerButtonPosition::NONE;
+      return;
+    }
+  } else {
+    if (!position_info->GetDouble(kXField, &power_button_offset_percentage_)) {
+      LOG(ERROR) << kXField << " not set in "
+                 << switches::kAshPowerButtonPosition;
+      power_button_position_ = PowerButtonPosition::NONE;
+      return;
+    }
+  }
+}
+
 }  // namespace ash
diff --git a/ash/system/power/power_button_controller.h b/ash/system/power/power_button_controller.h
index 63c365bd..08b704dd 100644
--- a/ash/system/power/power_button_controller.h
+++ b/ash/system/power/power_button_controller.h
@@ -57,6 +57,9 @@
     LEGACY,
   };
 
+  // The physical display side of power button.
+  enum class PowerButtonPosition { NONE, LEFT, TOP, RIGHT, BOTTOM };
+
   // Amount of time since last screen state change that power button event needs
   // to be ignored.
   static constexpr base::TimeDelta kScreenStateChangeDelay =
@@ -73,6 +76,18 @@
   static constexpr base::TimeDelta kIgnorePowerButtonAfterResumeDelay =
       base::TimeDelta::FromSeconds(2);
 
+  // Value of switches::kAshPowerButtonPosition stored in JSON format. These
+  // are the field names of the flag.
+  static constexpr const char* kPositionField = "position";
+  static constexpr const char* kXField = "x";
+  static constexpr const char* kYField = "y";
+
+  // Value of |kPositionField|.
+  static constexpr const char* kLeftPosition = "left";
+  static constexpr const char* kRightPosition = "right";
+  static constexpr const char* kTopPosition = "top";
+  static constexpr const char* kBottomPosition = "bottom";
+
   explicit PowerButtonController(
       BacklightsForcedOffSetter* backlights_forced_off_setter);
   ~PowerButtonController() override;
@@ -157,6 +172,10 @@
   // Sets |show_menu_animation_done_| to true.
   void SetShowMenuAnimationDone();
 
+  // A helper function called by ProcessCommandLine to parse the value of
+  // switches::kAshPowerButtonPosition.
+  void ParsePowerButtonPositionSwitch();
+
   // Are the power or lock buttons currently held?
   bool power_button_down_ = false;
   bool lock_button_down_ = false;
@@ -228,6 +247,15 @@
   // The fullscreen widget of power button menu.
   std::unique_ptr<views::Widget> menu_widget_;
 
+  // The physical display side of power button in landscape primary.
+  PowerButtonPosition power_button_position_ = PowerButtonPosition::NONE;
+
+  // The center of the power button's offset from the top of the screen (for
+  // left/right) or left side of the screen (for top/bottom) in
+  // landscape_primary. Values are in [0.0, 1.0] and express a fraction of the
+  // display's height or width, respectively.
+  double power_button_offset_percentage_ = 0.f;
+
   ScopedObserver<BacklightsForcedOffSetter, BacklightsForcedOffSetter::Observer>
       backlights_forced_off_observer_;
 
diff --git a/ash/system/power/power_button_controller_unittest.cc b/ash/system/power/power_button_controller_unittest.cc
index db46e90..7b9d536c 100644
--- a/ash/system/power/power_button_controller_unittest.cc
+++ b/ash/system/power/power_button_controller_unittest.cc
@@ -6,6 +6,8 @@
 
 #include "ash/accessibility/accessibility_controller.h"
 #include "ash/accessibility/test_accessibility_controller_client.h"
+#include "ash/display/screen_orientation_controller.h"
+#include "ash/display/screen_orientation_controller_test_api.h"
 #include "ash/media_controller.h"
 #include "ash/public/cpp/ash_switches.h"
 #include "ash/public/cpp/config.h"
@@ -17,14 +19,17 @@
 #include "ash/test_media_client.h"
 #include "ash/touch/touch_devices_controller.h"
 #include "ash/wm/lock_state_controller_test_api.h"
+#include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "ash/wm/test_session_state_animator.h"
 #include "ash/wm/window_util.h"
 #include "base/command_line.h"
+#include "base/json/json_writer.h"
 #include "base/run_loop.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "chromeos/dbus/fake_power_manager_client.h"
 #include "chromeos/dbus/fake_session_manager_client.h"
 #include "chromeos/dbus/power_manager/suspend.pb.h"
+#include "ui/display/test/display_manager_test_api.h"
 #include "ui/events/event.h"
 #include "ui/events/test/event_generator.h"
 #include "ui/views/widget/widget.h"
@@ -38,6 +43,15 @@
 // A non-zero brightness used for test.
 constexpr double kNonZeroBrightness = 10.;
 
+// Width of the display.
+constexpr int kDisplayWidth = 800;
+
+// Height of the display.
+constexpr int kDisplayHeight = 600;
+
+// Power button position offset percentage.
+constexpr double kPowerButtonPercentage = 0.75f;
+
 // Shorthand for some long constants.
 constexpr power_manager::BacklightBrightnessChange_Cause kUserCause =
     power_manager::BacklightBrightnessChange_Cause_USER_REQUEST;
@@ -46,6 +60,8 @@
 
 }  // namespace
 
+using PowerButtonPosition = PowerButtonController::PowerButtonPosition;
+
 class PowerButtonControllerTest : public PowerButtonTestBase {
  public:
   PowerButtonControllerTest() = default;
@@ -912,4 +928,241 @@
   EXPECT_TRUE(cursor_manager->IsCursorVisible());
 }
 
+class PowerButtonControllerWithPositionTest
+    : public PowerButtonControllerTest,
+      public testing::WithParamInterface<PowerButtonPosition> {
+ public:
+  PowerButtonControllerWithPositionTest() : power_button_position_(GetParam()) {
+    base::DictionaryValue position_info;
+    switch (power_button_position_) {
+      case PowerButtonPosition::LEFT:
+        position_info.SetString(PowerButtonController::kPositionField,
+                                PowerButtonController::kLeftPosition);
+        break;
+      case PowerButtonPosition::RIGHT:
+        position_info.SetString(PowerButtonController::kPositionField,
+                                PowerButtonController::kRightPosition);
+        break;
+      case PowerButtonPosition::TOP:
+        position_info.SetString(PowerButtonController::kPositionField,
+                                PowerButtonController::kTopPosition);
+        break;
+      case PowerButtonPosition::BOTTOM:
+        position_info.SetString(PowerButtonController::kPositionField,
+                                PowerButtonController::kBottomPosition);
+        break;
+      default:
+        return;
+    }
+    if (IsLeftOrRightPosition()) {
+      position_info.SetDouble(PowerButtonController::kYField,
+                              kPowerButtonPercentage);
+    } else {
+      position_info.SetDouble(PowerButtonController::kXField,
+                              kPowerButtonPercentage);
+    }
+
+    std::string json_position_info;
+    base::JSONWriter::Write(position_info, &json_position_info);
+    base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+        switches::kAshPowerButtonPosition, json_position_info);
+  }
+
+  bool IsLeftOrRightPosition() const {
+    return power_button_position_ == PowerButtonPosition::LEFT ||
+           power_button_position_ == PowerButtonPosition::RIGHT;
+  }
+
+  // Returns true if it is in tablet mode.
+  bool IsTabletMode() const {
+    return Shell::Get()
+        ->tablet_mode_controller()
+        ->IsTabletModeWindowManagerEnabled();
+  }
+
+  // Returns true if the menu is at the center of the display.
+  bool IsMenuCentered() const {
+    return power_button_test_api_->GetMenuBoundsInScreen().CenterPoint() ==
+           display::Screen::GetScreen()
+               ->GetPrimaryDisplay()
+               .bounds()
+               .CenterPoint();
+  }
+
+  PowerButtonPosition power_button_position() const {
+    return power_button_position_;
+  }
+
+ private:
+  PowerButtonPosition power_button_position_;
+
+  DISALLOW_COPY_AND_ASSIGN(PowerButtonControllerWithPositionTest);
+};
+
+TEST_P(PowerButtonControllerWithPositionTest,
+       MenuNextToPowerButtonInTabletMode) {
+  std::string display =
+      std::to_string(kDisplayWidth) + "x" + std::to_string(kDisplayHeight);
+  UpdateDisplay(display);
+  display::test::ScopedSetInternalDisplayId set_internal(
+      display_manager(), GetPrimaryDisplay().id());
+
+  ScreenOrientationControllerTestApi test_api(
+      Shell::Get()->screen_orientation_controller());
+  // Set the screen orientation to LANDSCAPE_PRIMARY.
+  test_api.SetDisplayRotation(display::Display::ROTATE_0,
+                              display::Display::RotationSource::ACTIVE);
+  EXPECT_EQ(test_api.GetCurrentOrientation(),
+            OrientationLockType::kLandscapePrimary);
+
+  // Menu is set at the center of the display if it is not in tablet mode.
+  OpenPowerButtonMenu();
+  ASSERT_FALSE(IsTabletMode());
+  EXPECT_TRUE(IsMenuCentered());
+  TapToDismissPowerButtonMenu();
+
+  int animation_transform = PowerButtonMenuView::kMenuViewTransformDistanceDp;
+  EnableTabletMode(true);
+  EXPECT_TRUE(IsTabletMode());
+  OpenPowerButtonMenu();
+  EXPECT_FALSE(IsMenuCentered());
+  if (power_button_position() == PowerButtonPosition::LEFT) {
+    EXPECT_EQ(animation_transform,
+              power_button_test_api_->GetMenuBoundsInScreen().x());
+  } else if (power_button_position() == PowerButtonPosition::RIGHT) {
+    EXPECT_EQ(animation_transform,
+              kDisplayWidth -
+                  power_button_test_api_->GetMenuBoundsInScreen().right());
+  } else if (power_button_position() == PowerButtonPosition::TOP) {
+    EXPECT_EQ(animation_transform,
+              power_button_test_api_->GetMenuBoundsInScreen().y());
+  } else if (power_button_position() == PowerButtonPosition::BOTTOM) {
+    EXPECT_EQ(animation_transform,
+              kDisplayHeight -
+                  power_button_test_api_->GetMenuBoundsInScreen().bottom());
+  }
+
+  // Rotate the screen by 270 degree.
+  test_api.SetDisplayRotation(display::Display::ROTATE_270,
+                              display::Display::RotationSource::ACTIVE);
+  EXPECT_EQ(test_api.GetCurrentOrientation(),
+            OrientationLockType::kPortraitPrimary);
+  EXPECT_FALSE(IsMenuCentered());
+  if (power_button_position() == PowerButtonPosition::LEFT) {
+    EXPECT_EQ(animation_transform,
+              power_button_test_api_->GetMenuBoundsInScreen().y());
+  } else if (power_button_position() == PowerButtonPosition::RIGHT) {
+    EXPECT_EQ(animation_transform,
+              kDisplayWidth -
+                  power_button_test_api_->GetMenuBoundsInScreen().bottom());
+  } else if (power_button_position() == PowerButtonPosition::TOP) {
+    EXPECT_EQ(animation_transform,
+              kDisplayHeight -
+                  power_button_test_api_->GetMenuBoundsInScreen().right());
+  } else if (power_button_position() == PowerButtonPosition::BOTTOM) {
+    EXPECT_EQ(animation_transform,
+              power_button_test_api_->GetMenuBoundsInScreen().x());
+  }
+
+  // Rotate the screen by 180 degree.
+  test_api.SetDisplayRotation(display::Display::ROTATE_180,
+                              display::Display::RotationSource::ACTIVE);
+  EXPECT_EQ(test_api.GetCurrentOrientation(),
+            OrientationLockType::kLandscapeSecondary);
+  EXPECT_FALSE(IsMenuCentered());
+  if (power_button_position() == PowerButtonPosition::LEFT) {
+    EXPECT_EQ(animation_transform,
+              kDisplayWidth -
+                  power_button_test_api_->GetMenuBoundsInScreen().right());
+  } else if (power_button_position() == PowerButtonPosition::RIGHT) {
+    EXPECT_EQ(animation_transform,
+              power_button_test_api_->GetMenuBoundsInScreen().x());
+  } else if (power_button_position() == PowerButtonPosition::TOP) {
+    EXPECT_EQ(animation_transform,
+              kDisplayHeight -
+                  power_button_test_api_->GetMenuBoundsInScreen().bottom());
+  } else if (power_button_position() == PowerButtonPosition::BOTTOM) {
+    EXPECT_EQ(animation_transform,
+              power_button_test_api_->GetMenuBoundsInScreen().y());
+  }
+
+  // Rotate the screen by 90 degree.
+  test_api.SetDisplayRotation(display::Display::ROTATE_90,
+                              display::Display::RotationSource::ACTIVE);
+  EXPECT_EQ(test_api.GetCurrentOrientation(),
+            OrientationLockType::kPortraitSecondary);
+  EXPECT_FALSE(IsMenuCentered());
+  if (power_button_position() == PowerButtonPosition::LEFT) {
+    EXPECT_EQ(animation_transform,
+              kDisplayWidth -
+                  power_button_test_api_->GetMenuBoundsInScreen().bottom());
+  } else if (power_button_position() == PowerButtonPosition::RIGHT) {
+    EXPECT_EQ(animation_transform,
+              power_button_test_api_->GetMenuBoundsInScreen().y());
+  } else if (power_button_position() == PowerButtonPosition::TOP) {
+    EXPECT_EQ(animation_transform,
+              power_button_test_api_->GetMenuBoundsInScreen().x());
+  } else if (power_button_position() == PowerButtonPosition::BOTTOM) {
+    EXPECT_EQ(animation_transform,
+              kDisplayHeight -
+                  power_button_test_api_->GetMenuBoundsInScreen().right());
+  }
+}
+
+// Tests that the menu is always shown at the percentage of position when
+// display has different scale factors.
+TEST_P(PowerButtonControllerWithPositionTest, MenuShownAtPercentageOfPosition) {
+  const int scale_factor = 2;
+  std::string display = "1000x500*" + std::to_string(scale_factor);
+  UpdateDisplay(display);
+  int64_t primary_id = GetPrimaryDisplay().id();
+  display::test::ScopedSetInternalDisplayId set_internal(display_manager(),
+                                                         primary_id);
+  ASSERT_EQ(scale_factor, GetPrimaryDisplay().device_scale_factor());
+
+  EnableTabletMode(true);
+  OpenPowerButtonMenu();
+  EXPECT_FALSE(IsMenuCentered());
+  gfx::Point menu_center_point =
+      power_button_test_api_->GetMenuBoundsInScreen().CenterPoint();
+  gfx::Rect display_bounds = GetPrimaryDisplay().bounds();
+  int original_width = display_bounds.width();
+  int original_height = display_bounds.height();
+  if (IsLeftOrRightPosition()) {
+    EXPECT_EQ(menu_center_point.y(), static_cast<int>(display_bounds.height() *
+                                                      kPowerButtonPercentage));
+  } else {
+    EXPECT_EQ(menu_center_point.x(), static_cast<int>(display_bounds.width() *
+                                                      kPowerButtonPercentage));
+  }
+  TapToDismissPowerButtonMenu();
+
+  ASSERT_TRUE(display::test::DisplayManagerTestApi(display_manager())
+                  .SetDisplayUIScale(primary_id, scale_factor));
+  ASSERT_EQ(1.0f, GetPrimaryDisplay().device_scale_factor());
+  display_bounds = GetPrimaryDisplay().bounds();
+  int scale_up_width = display_bounds.width();
+  int scale_up_height = display_bounds.height();
+  EXPECT_EQ(scale_up_width, original_width * scale_factor);
+  EXPECT_EQ(scale_up_height, original_height * scale_factor);
+  OpenPowerButtonMenu();
+  menu_center_point =
+      power_button_test_api_->GetMenuBoundsInScreen().CenterPoint();
+  // Menu is still at the kPowerButtonPercentage position after scale up screen.
+  if (IsLeftOrRightPosition()) {
+    EXPECT_EQ(menu_center_point.y(), static_cast<int>(display_bounds.height() *
+                                                      kPowerButtonPercentage));
+  } else {
+    EXPECT_EQ(menu_center_point.x(), static_cast<int>(display_bounds.width() *
+                                                      kPowerButtonPercentage));
+  }
+}
+
+INSTANTIATE_TEST_CASE_P(AshPowerButtonPosition,
+                        PowerButtonControllerWithPositionTest,
+                        testing::Values(PowerButtonPosition::LEFT,
+                                        PowerButtonPosition::RIGHT,
+                                        PowerButtonPosition::TOP,
+                                        PowerButtonPosition::BOTTOM));
+
 }  // namespace ash
diff --git a/ash/system/power/power_button_menu_screen_view.cc b/ash/system/power/power_button_menu_screen_view.cc
index 72bc31a..1dc6165 100644
--- a/ash/system/power/power_button_menu_screen_view.cc
+++ b/ash/system/power/power_button_menu_screen_view.cc
@@ -4,9 +4,11 @@
 
 #include "ash/system/power/power_button_menu_screen_view.h"
 
+#include <utility>
+
 #include "ash/shell.h"
-#include "ash/system/power/power_button_controller.h"
 #include "ash/system/power/power_button_menu_view.h"
+#include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "ui/compositor/layer.h"
 #include "ui/compositor/layer_animation_observer.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
@@ -24,8 +26,20 @@
 // Opacity of the power button menu fullscreen background shield.
 constexpr float kPowerButtonMenuOpacity = 0.6f;
 
+// TODO(minch): Get the internal display size instead if needed.
+// Gets the landscape size of the primary display. For landscape orientation,
+// the width is always larger than height.
+gfx::Size GetPrimaryDisplayLandscapeSize() {
+  gfx::Rect bounds = display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
+  return gfx::Size(std::max(bounds.width(), bounds.height()),
+                   std::min(bounds.width(), bounds.height()));
+}
+
 }  // namespace
 
+using PowerButtonPosition = PowerButtonController::PowerButtonPosition;
+using TransformDirection = PowerButtonMenuView::TransformDirection;
+
 class PowerButtonMenuScreenView::PowerButtonMenuBackgroundView
     : public views::View,
       public ui::ImplicitAnimationObserver {
@@ -72,15 +86,21 @@
 };
 
 PowerButtonMenuScreenView::PowerButtonMenuScreenView(
-    base::RepeatingClosure show_animation_done) {
+    PowerButtonPosition power_button_position,
+    double power_button_offset_percentage,
+    base::RepeatingClosure show_animation_done)
+    : power_button_position_(power_button_position),
+      power_button_offset_percentage_(power_button_offset_percentage) {
   power_button_screen_background_shield_ =
       new PowerButtonMenuBackgroundView(show_animation_done);
   AddChildView(power_button_screen_background_shield_);
-
-  power_button_menu_view_ = new PowerButtonMenuView();
+  power_button_menu_view_ = new PowerButtonMenuView(power_button_position_);
   AddChildView(power_button_menu_view_);
 
   display::Screen::GetScreen()->AddObserver(this);
+
+  if (power_button_position_ != PowerButtonPosition::NONE)
+    InitializeMenuBoundsOrigins();
 }
 
 PowerButtonMenuScreenView::~PowerButtonMenuScreenView() {
@@ -93,13 +113,16 @@
 }
 
 void PowerButtonMenuScreenView::Layout() {
-  const gfx::Rect contents_bounds = GetContentsBounds();
-  power_button_screen_background_shield_->SetBoundsRect(contents_bounds);
+  power_button_screen_background_shield_->SetBoundsRect(GetContentsBounds());
 
-  // TODO(minch): Get the menu bounds according to the power button position.
-  gfx::Rect menu_bounds = contents_bounds;
-  menu_bounds.ClampToCenteredSize(power_button_menu_view_->GetPreferredSize());
-  menu_bounds.set_y(menu_bounds.y() - PowerButtonMenuView::kMenuViewTopPadding);
+  gfx::Rect menu_bounds = GetMenuBounds();
+  PowerButtonMenuView::TransformDisplacement transform_displacement =
+      power_button_menu_view_->GetTransformDisplacement();
+  if (transform_displacement.direction == TransformDirection::X)
+    menu_bounds.set_x(menu_bounds.x() - transform_displacement.distance);
+  else if (transform_displacement.direction == TransformDirection::Y)
+    menu_bounds.set_y(menu_bounds.y() - transform_displacement.distance);
+
   power_button_menu_view_->SetBoundsRect(menu_bounds);
 }
 
@@ -122,6 +145,135 @@
     uint32_t changed_metrics) {
   GetWidget()->SetBounds(
       display::Screen::GetScreen()->GetPrimaryDisplay().bounds());
+
+  LayoutWithoutTransform();
+}
+
+void PowerButtonMenuScreenView::LayoutWithoutTransform() {
+  power_button_screen_background_shield_->SetBoundsRect(GetContentsBounds());
+  power_button_menu_view_->layer()->SetTransform(gfx::Transform());
+  power_button_menu_view_->SetBoundsRect(GetMenuBounds());
+}
+
+void PowerButtonMenuScreenView::InitializeMenuBoundsOrigins() {
+  // Power button position offset in pixels from the top when the button is at
+  // the left/right of the screen after rotation.
+  int left_power_button_y = 0, right_power_button_y = 0;
+
+  // Power button position offset in pixels from the left when the button is at
+  // the top/bottom of the screen after rotation.
+  int top_power_button_x = 0, bottom_power_button_x = 0;
+
+  // The screen orientation when the power button is at the
+  // left/right/top/bottom of the screen after rotation.
+  OrientationLockType left_screen_orientation, right_screen_orientation,
+      top_screen_orientation, bottom_screen_orientation;
+  const gfx::Size landscape_size = GetPrimaryDisplayLandscapeSize();
+  int display_width = landscape_size.width();
+  int display_height = landscape_size.height();
+
+  if (power_button_position_ == PowerButtonPosition::TOP ||
+      power_button_position_ == PowerButtonPosition::BOTTOM) {
+    std::swap(display_width, display_height);
+  }
+
+  int power_button_offset = display_height * power_button_offset_percentage_;
+  switch (power_button_position_) {
+    case PowerButtonPosition::LEFT:
+    case PowerButtonPosition::BOTTOM:
+      left_power_button_y = bottom_power_button_x = power_button_offset;
+      right_power_button_y = top_power_button_x =
+          display_height - power_button_offset;
+      break;
+    case PowerButtonPosition::RIGHT:
+    case PowerButtonPosition::TOP:
+      left_power_button_y = bottom_power_button_x =
+          display_height - power_button_offset;
+      right_power_button_y = top_power_button_x = power_button_offset;
+      break;
+    default:
+      NOTREACHED();
+      return;
+  }
+
+  switch (power_button_position_) {
+    case PowerButtonPosition::LEFT:
+      left_screen_orientation = OrientationLockType::kLandscapePrimary;
+      right_screen_orientation = OrientationLockType::kLandscapeSecondary;
+      top_screen_orientation = OrientationLockType::kPortraitPrimary;
+      bottom_screen_orientation = OrientationLockType::kPortraitSecondary;
+      break;
+    case PowerButtonPosition::RIGHT:
+      left_screen_orientation = OrientationLockType::kLandscapeSecondary;
+      right_screen_orientation = OrientationLockType::kLandscapePrimary;
+      top_screen_orientation = OrientationLockType::kPortraitSecondary;
+      bottom_screen_orientation = OrientationLockType::kPortraitPrimary;
+      break;
+    case PowerButtonPosition::TOP:
+      left_screen_orientation = OrientationLockType::kPortraitSecondary;
+      right_screen_orientation = OrientationLockType::kPortraitPrimary;
+      top_screen_orientation = OrientationLockType::kLandscapePrimary;
+      bottom_screen_orientation = OrientationLockType::kLandscapeSecondary;
+      break;
+    case PowerButtonPosition::BOTTOM:
+      left_screen_orientation = OrientationLockType::kPortraitPrimary;
+      right_screen_orientation = OrientationLockType::kPortraitSecondary;
+      top_screen_orientation = OrientationLockType::kLandscapeSecondary;
+      bottom_screen_orientation = OrientationLockType::kLandscapePrimary;
+      break;
+    default:
+      NOTREACHED();
+      return;
+  }
+
+  const gfx::Size menu_size = power_button_menu_view_->GetPreferredSize();
+  // Power button position offset from the left when the button is at the left
+  // is always zero.
+  menu_bounds_origins_.insert(std::make_pair(
+      left_screen_orientation,
+      gfx::Point(PowerButtonMenuView::kMenuViewTransformDistanceDp,
+                 left_power_button_y - menu_size.height() / 2)));
+
+  menu_bounds_origins_.insert(std::make_pair(
+      right_screen_orientation,
+      gfx::Point(display_width -
+                     PowerButtonMenuView::kMenuViewTransformDistanceDp -
+                     menu_size.width(),
+                 right_power_button_y - menu_size.height() / 2)));
+
+  // Power button position offset from the top when the button is at the top
+  // is always zero.
+  menu_bounds_origins_.insert(std::make_pair(
+      top_screen_orientation,
+      gfx::Point(top_power_button_x - menu_size.width() / 2,
+                 PowerButtonMenuView::kMenuViewTransformDistanceDp)));
+
+  menu_bounds_origins_.insert(std::make_pair(
+      bottom_screen_orientation,
+      gfx::Point(bottom_power_button_x - menu_size.width() / 2,
+                 display_width -
+                     PowerButtonMenuView::kMenuViewTransformDistanceDp -
+                     menu_size.height())));
+}
+
+gfx::Rect PowerButtonMenuScreenView::GetMenuBounds() {
+  gfx::Rect menu_bounds;
+
+  if (power_button_position_ == PowerButtonPosition::NONE ||
+      !Shell::Get()
+           ->tablet_mode_controller()
+           ->IsTabletModeWindowManagerEnabled()) {
+    menu_bounds = GetContentsBounds();
+    menu_bounds.ClampToCenteredSize(
+        power_button_menu_view_->GetPreferredSize());
+  } else {
+    menu_bounds.set_origin(
+        menu_bounds_origins_[Shell::Get()
+                                 ->screen_orientation_controller()
+                                 ->GetCurrentOrientation()]);
+    menu_bounds.set_size(power_button_menu_view_->GetPreferredSize());
+  }
+  return menu_bounds;
 }
 
 }  // namespace ash
diff --git a/ash/system/power/power_button_menu_screen_view.h b/ash/system/power/power_button_menu_screen_view.h
index 0118b78..79e01ce 100644
--- a/ash/system/power/power_button_menu_screen_view.h
+++ b/ash/system/power/power_button_menu_screen_view.h
@@ -5,7 +5,11 @@
 #ifndef ASH_SYSTEM_POWER_POWER_BUTTON_MENU_SCREEN_VIEW_H_
 #define ASH_SYSTEM_POWER_POWER_BUTTON_MENU_SCREEN_VIEW_H_
 
+#include <unordered_map>
+
 #include "ash/ash_export.h"
+#include "ash/display/screen_orientation_controller.h"
+#include "ash/system/power/power_button_controller.h"
 #include "base/macros.h"
 #include "ui/display/display_observer.h"
 #include "ui/views/view.h"
@@ -21,7 +25,9 @@
  public:
   // |show_animation_done| is a callback for when the animation that shows the
   // power menu has finished.
-  explicit PowerButtonMenuScreenView(
+  PowerButtonMenuScreenView(
+      PowerButtonController::PowerButtonPosition power_button_position,
+      double power_button_offset,
       base::RepeatingClosure show_animation_done);
   ~PowerButtonMenuScreenView() override;
 
@@ -47,11 +53,32 @@
   void OnDisplayMetricsChanged(const display::Display& display,
                                uint32_t changed_metrics) override;
 
+  // Lays out the view without animation transform.
+  void LayoutWithoutTransform();
+
+  // Initializes |menu_bounds_origins_| according to power button position info.
+  void InitializeMenuBoundsOrigins();
+
+  // Gets the bounds of power button menu.
+  gfx::Rect GetMenuBounds();
+
   // Created by PowerButtonMenuScreenView. Owned by views hierarchy.
   PowerButtonMenuView* power_button_menu_view_ = nullptr;
   PowerButtonMenuBackgroundView* power_button_screen_background_shield_ =
       nullptr;
 
+  // The physical display side of power button in landscape primary.
+  PowerButtonController::PowerButtonPosition power_button_position_;
+
+  // The center of the power button's offset from the top of the screen (for
+  // left/right) or left side of the screen (for top/bottom) in
+  // landscape_primary. Values are in [0.0, 1.0] and express a fraction of the
+  // display's height or width, respectively.
+  double power_button_offset_percentage_ = 0.f;
+
+  // The origin of the menu bounds in different screen orientations.
+  std::unordered_map<OrientationLockType, gfx::Point> menu_bounds_origins_;
+
   DISALLOW_COPY_AND_ASSIGN(PowerButtonMenuScreenView);
 };
 
diff --git a/ash/system/power/power_button_menu_view.cc b/ash/system/power/power_button_menu_view.cc
index d7caccc..f489fc8 100644
--- a/ash/system/power/power_button_menu_view.cc
+++ b/ash/system/power/power_button_menu_view.cc
@@ -4,6 +4,7 @@
 
 #include "ash/system/power/power_button_menu_view.h"
 
+#include "ash/display/screen_orientation_controller.h"
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/session/session_controller.h"
 #include "ash/shell.h"
@@ -11,6 +12,7 @@
 #include "ash/system/power/power_button_menu_item_view.h"
 #include "ash/system/user/login_status.h"
 #include "ash/wm/lock_state_controller.h"
+#include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
 #include "ui/gfx/canvas.h"
@@ -28,7 +30,11 @@
 
 }  // namespace
 
-PowerButtonMenuView::PowerButtonMenuView() {
+using PowerButtonPosition = PowerButtonController::PowerButtonPosition;
+
+PowerButtonMenuView::PowerButtonMenuView(
+    PowerButtonPosition power_button_position)
+    : power_button_position_(power_button_position) {
   SetPaintToLayer();
   layer()->SetFillsBoundsOpaquely(false);
 
@@ -57,13 +63,64 @@
   // Animation of the menu view bounds change.
   if (show) {
     gfx::Transform transform;
-    transform.Translate(0, kMenuViewTopPadding);
+    TransformDisplacement transform_displacement = GetTransformDisplacement();
+    if (transform_displacement.direction == TransformDirection::X)
+      transform.Translate(transform_displacement.distance, 0);
+    else if (transform_displacement.direction == TransformDirection::Y)
+      transform.Translate(0, transform_displacement.distance);
+
     layer()->SetTransform(transform);
   } else {
     layer()->SetTransform(gfx::Transform());
   }
 }
 
+PowerButtonMenuView::TransformDisplacement
+PowerButtonMenuView::GetTransformDisplacement() const {
+  TransformDisplacement transform_displacement;
+  if (power_button_position_ == PowerButtonPosition::NONE ||
+      !Shell::Get()
+           ->tablet_mode_controller()
+           ->IsTabletModeWindowManagerEnabled()) {
+    transform_displacement.direction = TransformDirection::Y;
+    transform_displacement.distance = kMenuViewTransformDistanceDp;
+    return transform_displacement;
+  }
+
+  OrientationLockType screen_orientation =
+      Shell::Get()->screen_orientation_controller()->GetCurrentOrientation();
+  bool is_left_or_right = power_button_position_ == PowerButtonPosition::LEFT ||
+                          power_button_position_ == PowerButtonPosition::RIGHT;
+
+  if (IsLandscapeOrientation(screen_orientation)) {
+    transform_displacement.direction =
+        is_left_or_right ? TransformDirection::X : TransformDirection::Y;
+  } else {
+    transform_displacement.direction =
+        is_left_or_right ? TransformDirection::Y : TransformDirection::X;
+  }
+
+  bool positive_transform = false;
+  if (is_left_or_right) {
+    bool is_primary = IsPrimaryOrientation(screen_orientation);
+    positive_transform = power_button_position_ == PowerButtonPosition::LEFT
+                             ? is_primary
+                             : !is_primary;
+  } else {
+    bool is_landscape_primary_or_portrait_secondary =
+        screen_orientation == OrientationLockType::kLandscapePrimary ||
+        screen_orientation == OrientationLockType::kPortraitSecondary;
+
+    positive_transform = power_button_position_ == PowerButtonPosition::TOP
+                             ? is_landscape_primary_or_portrait_secondary
+                             : !is_landscape_primary_or_portrait_secondary;
+  }
+  transform_displacement.distance = positive_transform
+                                        ? kMenuViewTransformDistanceDp
+                                        : -kMenuViewTransformDistanceDp;
+  return transform_displacement;
+}
+
 void PowerButtonMenuView::CreateItems() {
   power_off_item_ = new PowerButtonMenuItemView(
       this, kSystemPowerButtonMenuPowerOffIcon,
diff --git a/ash/system/power/power_button_menu_view.h b/ash/system/power/power_button_menu_view.h
index e8ea010..29781cb 100644
--- a/ash/system/power/power_button_menu_view.h
+++ b/ash/system/power/power_button_menu_view.h
@@ -2,10 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef ASH_SYSTEM_POWER_BUTTON_MENU_VIEW_H_
-#define ASH_SYSTEM_POWER_BUTTON_MENU_VIEW_H_
+#ifndef ASH_SYSTEM_POWER_POWER_BUTTON_MENU_VIEW_H_
+#define ASH_SYSTEM_POWER_POWER_BUTTON_MENU_VIEW_H_
 
 #include "ash/ash_export.h"
+#include "ash/system/power/power_button_controller.h"
 #include "base/macros.h"
 #include "ui/compositor/layer_animation_observer.h"
 #include "ui/views/controls/button/button.h"
@@ -23,10 +24,21 @@
   // The duration of the animation to show or hide the power button menu view.
   static constexpr int kAnimationTimeoutMs = 500;
 
-  // Top padding of the menu view.
-  static constexpr int kMenuViewTopPadding = 16;
+  // Distance of the menu animation transform.
+  static constexpr int kMenuViewTransformDistanceDp = 16;
 
-  PowerButtonMenuView();
+  // Direction of the animation transform. X means to translate from
+  // x-coordinate. Y means to translate from y-coordinate.
+  enum class TransformDirection { NONE, X, Y };
+
+  // The translate direction and distance of the animation transform.
+  struct TransformDisplacement {
+    TransformDirection direction;
+    int distance;
+  };
+
+  explicit PowerButtonMenuView(
+      PowerButtonController::PowerButtonPosition power_button_position);
   ~PowerButtonMenuView() override;
 
   bool sign_out_item_for_testing() const { return sign_out_item_; }
@@ -34,6 +46,9 @@
   // Schedules an animation to show or hide the view.
   void ScheduleShowHideAnimation(bool show);
 
+  // Gets the transform displacement, which contains direction and distance.
+  TransformDisplacement GetTransformDisplacement() const;
+
  private:
   // Creates the items that in the menu.
   void CreateItems();
@@ -53,9 +68,12 @@
   PowerButtonMenuItemView* power_off_item_ = nullptr;
   PowerButtonMenuItemView* sign_out_item_ = nullptr;
 
+  // The physical display side of power button in landscape primary.
+  PowerButtonController::PowerButtonPosition power_button_position_;
+
   DISALLOW_COPY_AND_ASSIGN(PowerButtonMenuView);
 };
 
 }  // namespace ash
 
-#endif  // ASH_SYSTEM_POWER_BUTTON_MENU_VIEW_H_
+#endif  // ASH_SYSTEM_POWER_POWER_BUTTON_MENU_VIEW_H_
diff --git a/ash/system/screen_security/screen_capture_tray_item.cc b/ash/system/screen_security/screen_capture_tray_item.cc
index f83e67f..8694688 100644
--- a/ash/system/screen_security/screen_capture_tray_item.cc
+++ b/ash/system/screen_security/screen_capture_tray_item.cc
@@ -8,6 +8,7 @@
 
 #include "ash/metrics/user_metrics_action.h"
 #include "ash/metrics/user_metrics_recorder.h"
+#include "ash/public/cpp/ash_features.h"
 #include "ash/resources/grit/ash_resources.h"
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/shell.h"
@@ -63,6 +64,8 @@
           kNotificationScreenshareIcon,
           message_center::SystemNotificationWarningLevel::NORMAL);
   notification->SetSystemPriority();
+  if (features::IsSystemTrayUnifiedEnabled())
+    notification->set_pinned(true);
   message_center::MessageCenter::Get()->AddNotification(
       std::move(notification));
 }
diff --git a/ash/system/screen_security/screen_share_tray_item.cc b/ash/system/screen_security/screen_share_tray_item.cc
index 9679138..9c6c459 100644
--- a/ash/system/screen_security/screen_share_tray_item.cc
+++ b/ash/system/screen_security/screen_share_tray_item.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "ash/public/cpp/ash_features.h"
 #include "ash/resources/grit/ash_resources.h"
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/shell.h"
@@ -68,6 +69,8 @@
           kNotificationScreenshareIcon,
           message_center::SystemNotificationWarningLevel::NORMAL);
   notification->SetSystemPriority();
+  if (features::IsSystemTrayUnifiedEnabled())
+    notification->set_pinned(true);
   message_center::MessageCenter::Get()->AddNotification(
       std::move(notification));
 }
diff --git a/ash/system/tray/system_tray_controller.cc b/ash/system/tray/system_tray_controller.cc
index f1169f363..bd683b0 100644
--- a/ash/system/tray/system_tray_controller.cc
+++ b/ash/system/tray/system_tray_controller.cc
@@ -137,6 +137,11 @@
     system_tray_client_->ShowNetworkSettings(network_id);
 }
 
+void SystemTrayController::ShowMultiDeviceSetup() {
+  if (system_tray_client_)
+    system_tray_client_->ShowMultiDeviceSetup();
+}
+
 void SystemTrayController::RequestRestartForUpdate() {
   if (system_tray_client_)
     system_tray_client_->RequestRestartForUpdate();
diff --git a/ash/system/tray/system_tray_controller.h b/ash/system/tray/system_tray_controller.h
index 1e76c0dc..9dd3e59 100644
--- a/ash/system/tray/system_tray_controller.h
+++ b/ash/system/tray/system_tray_controller.h
@@ -51,6 +51,7 @@
   void ShowThirdPartyVpnCreate(const std::string& extension_id);
   void ShowArcVpnCreate(const std::string& app_id);
   void ShowNetworkSettings(const std::string& network_id);
+  void ShowMultiDeviceSetup();
   void RequestRestartForUpdate();
 
   // Binds the mojom::SystemTray interface to this object.
diff --git a/ash/system/tray/tray_background_view.cc b/ash/system/tray/tray_background_view.cc
index e669c0a..3cc1862 100644
--- a/ash/system/tray/tray_background_view.cc
+++ b/ash/system/tray/tray_background_view.cc
@@ -396,6 +396,12 @@
   tray_container_->UpdateAfterShelfAlignmentChange();
 }
 
+void TrayBackgroundView::UpdateAfterRootWindowBoundsChange(
+    const gfx::Rect& old_bounds,
+    const gfx::Rect& new_bounds) {
+  // Do nothing by default. Child class may do something.
+}
+
 void TrayBackgroundView::AnchorUpdated() {
   if (GetBubbleView())
     UpdateClippingWindowBounds();
diff --git a/ash/system/tray/tray_background_view.h b/ash/system/tray/tray_background_view.h
index e293b8d..6cbd928 100644
--- a/ash/system/tray/tray_background_view.h
+++ b/ash/system/tray/tray_background_view.h
@@ -75,6 +75,10 @@
   // Called whenever the shelf alignment changes.
   virtual void UpdateAfterShelfAlignmentChange();
 
+  // Called whenever the bounds of the root window changes.
+  virtual void UpdateAfterRootWindowBoundsChange(const gfx::Rect& old_bounds,
+                                                 const gfx::Rect& new_bounds);
+
   // Called when the anchor (tray or bubble) may have moved or changed.
   virtual void AnchorUpdated();
 
diff --git a/ash/system/tray/tray_bubble_wrapper.cc b/ash/system/tray/tray_bubble_wrapper.cc
index b605c8b..32616e2a 100644
--- a/ash/system/tray/tray_bubble_wrapper.cc
+++ b/ash/system/tray/tray_bubble_wrapper.cc
@@ -31,6 +31,8 @@
 
   tray->tray_event_filter()->AddWrapper(this);
 
+  bubble_widget_->GetNativeWindow()->GetRootWindow()->AddObserver(this);
+
   if (!is_persistent_)
     Shell::Get()->activation_client()->AddObserver(this);
 }
@@ -41,11 +43,19 @@
 
   tray_->tray_event_filter()->RemoveWrapper(this);
   if (bubble_widget_) {
+    bubble_widget_->GetNativeWindow()->GetRootWindow()->RemoveObserver(this);
     bubble_widget_->RemoveObserver(this);
     bubble_widget_->Close();
   }
 }
 
+void TrayBubbleWrapper::OnWidgetClosing(views::Widget* widget) {
+  CHECK_EQ(bubble_widget_, widget);
+  // Remove this from the observer list before the widget is closed and detached
+  // from the root window.
+  bubble_widget_->GetNativeWindow()->GetRootWindow()->RemoveObserver(this);
+}
+
 void TrayBubbleWrapper::OnWidgetDestroying(views::Widget* widget) {
   CHECK_EQ(bubble_widget_, widget);
   bubble_widget_->RemoveObserver(this);
@@ -66,6 +76,13 @@
   tray_->BubbleResized(bubble_view_);
 }
 
+void TrayBubbleWrapper::OnWindowBoundsChanged(aura::Window* window,
+                                              const gfx::Rect& old_bounds,
+                                              const gfx::Rect& new_bounds,
+                                              ui::PropertyChangeReason reason) {
+  tray_->UpdateAfterRootWindowBoundsChange(old_bounds, new_bounds);
+}
+
 void TrayBubbleWrapper::OnWindowActivated(ActivationReason reason,
                                           aura::Window* gained_active,
                                           aura::Window* lost_active) {
diff --git a/ash/system/tray/tray_bubble_wrapper.h b/ash/system/tray/tray_bubble_wrapper.h
index b13f804..4ec7f171 100644
--- a/ash/system/tray/tray_bubble_wrapper.h
+++ b/ash/system/tray/tray_bubble_wrapper.h
@@ -7,6 +7,7 @@
 
 #include "ash/ash_export.h"
 #include "base/macros.h"
+#include "ui/aura/window_observer.h"
 #include "ui/views/widget/widget_observer.h"
 #include "ui/wm/public/activation_change_observer.h"
 
@@ -20,6 +21,7 @@
 // Creates and manages the Widget and EventFilter components of a bubble.
 
 class ASH_EXPORT TrayBubbleWrapper : public views::WidgetObserver,
+                                     public aura::WindowObserver,
                                      public ::wm::ActivationChangeObserver {
  public:
   TrayBubbleWrapper(TrayBackgroundView* tray,
@@ -28,10 +30,17 @@
   ~TrayBubbleWrapper() override;
 
   // views::WidgetObserver overrides:
+  void OnWidgetClosing(views::Widget* widget) override;
   void OnWidgetDestroying(views::Widget* widget) override;
   void OnWidgetBoundsChanged(views::Widget* widget,
                              const gfx::Rect& new_bounds) override;
 
+  // aura::WindowObserver:
+  void OnWindowBoundsChanged(aura::Window* window,
+                             const gfx::Rect& old_bounds,
+                             const gfx::Rect& new_bounds,
+                             ui::PropertyChangeReason reason) override;
+
   // ::wm::ActivationChangeObserver overrides:
   void OnWindowActivated(ActivationReason reason,
                          aura::Window* gained_active,
diff --git a/ash/system/tray_accessibility.cc b/ash/system/tray_accessibility.cc
index ff75729..fd27fd8 100644
--- a/ash/system/tray_accessibility.cc
+++ b/ash/system/tray_accessibility.cc
@@ -57,9 +57,8 @@
   A11Y_HIGHLIGHT_MOUSE_CURSOR = 1 << 9,
   A11Y_HIGHLIGHT_KEYBOARD_FOCUS = 1 << 10,
   A11Y_STICKY_KEYS = 1 << 11,
-  A11Y_TAP_DRAGGING = 1 << 12,
-  A11Y_SELECT_TO_SPEAK = 1 << 13,
-  A11Y_DOCKED_MAGNIFIER = 1 << 14,
+  A11Y_SELECT_TO_SPEAK = 1 << 12,
+  A11Y_DOCKED_MAGNIFIER = 1 << 13,
 };
 
 uint32_t GetAccessibilityState() {
@@ -91,8 +90,6 @@
     state |= A11Y_HIGHLIGHT_KEYBOARD_FOCUS;
   if (controller->IsStickyKeysEnabled())
     state |= A11Y_STICKY_KEYS;
-  if (controller->IsTapDraggingEnabled())
-    state |= A11Y_TAP_DRAGGING;
   if (controller->IsSelectToSpeakEnabled())
     state |= A11Y_SELECT_TO_SPEAK;
   if (features::IsDockedMagnifierEnabled() &&
@@ -219,10 +216,6 @@
   sticky_keys_enabled_ = controller->IsStickyKeysEnabled();
   TrayPopupUtils::UpdateCheckMarkVisibility(sticky_keys_view_,
                                             sticky_keys_enabled_);
-
-  tap_dragging_enabled_ = controller->IsTapDraggingEnabled();
-  TrayPopupUtils::UpdateCheckMarkVisibility(tap_dragging_view_,
-                                            tap_dragging_enabled_);
 }
 
 void AccessibilityDetailedView::AppendAccessibilityList() {
@@ -324,11 +317,6 @@
   sticky_keys_view_ = AddScrollListCheckableItem(
       l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ACCESSIBILITY_STICKY_KEYS),
       sticky_keys_enabled_);
-
-  tap_dragging_enabled_ = controller->IsTapDraggingEnabled();
-  tap_dragging_view_ = AddScrollListCheckableItem(
-      l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ACCESSIBILITY_TAP_DRAGGING),
-      tap_dragging_enabled_);
 }
 
 void AccessibilityDetailedView::HandleViewClicked(views::View* view) {
@@ -419,12 +407,6 @@
                      ? UserMetricsAction("StatusArea_StickyKeysEnabled")
                      : UserMetricsAction("StatusArea_StickyKeysDisabled"));
     controller->SetStickyKeysEnabled(new_state);
-  } else if (tap_dragging_view_ && view == tap_dragging_view_) {
-    bool new_state = !controller->IsTapDraggingEnabled();
-    RecordAction(new_state
-                     ? UserMetricsAction("StatusArea_TapDraggingEnabled")
-                     : UserMetricsAction("StatusArea_TapDraggingDisabled"));
-    controller->SetTapDraggingEnabled(new_state);
   }
 }
 
diff --git a/ash/system/tray_accessibility.h b/ash/system/tray_accessibility.h
index 410c41da..89087d5 100644
--- a/ash/system/tray_accessibility.h
+++ b/ash/system/tray_accessibility.h
@@ -73,7 +73,6 @@
   HoverHighlightView* highlight_mouse_cursor_view_ = nullptr;
   HoverHighlightView* highlight_keyboard_focus_view_ = nullptr;
   HoverHighlightView* sticky_keys_view_ = nullptr;
-  HoverHighlightView* tap_dragging_view_ = nullptr;
   views::Button* help_view_ = nullptr;
   views::Button* settings_view_ = nullptr;
 
@@ -91,7 +90,6 @@
   bool highlight_mouse_cursor_enabled_ = false;
   bool highlight_keyboard_focus_enabled_ = false;
   bool sticky_keys_enabled_ = false;
-  bool tap_dragging_enabled_ = false;
 
   LoginStatus login_;
 
diff --git a/ash/system/tray_accessibility_unittest.cc b/ash/system/tray_accessibility_unittest.cc
index c1a41301..1a42ed24 100644
--- a/ash/system/tray_accessibility_unittest.cc
+++ b/ash/system/tray_accessibility_unittest.cc
@@ -108,10 +108,6 @@
     return tray_item_->detailed_menu_->sticky_keys_view_;
   }
 
-  bool IsTapDraggingMenuShownOnDetailMenu() const {
-    return tray_item_->detailed_menu_->tap_dragging_view_;
-  }
-
   // In material design we show the help button but theme it as disabled if
   // it is not possible to load the help page.
   bool IsHelpAvailableOnDetailMenu() {
@@ -246,7 +242,6 @@
   EXPECT_TRUE(IsHighlightMouseCursorMenuShownOnDetailMenu());
   EXPECT_TRUE(IsHighlightKeyboardFocusMenuShownOnDetailMenu());
   EXPECT_TRUE(IsStickyKeysMenuShownOnDetailMenu());
-  EXPECT_TRUE(IsTapDraggingMenuShownOnDetailMenu());
   CloseDetailMenu();
 
   // Simulate screen lock.
@@ -266,7 +261,6 @@
   EXPECT_TRUE(IsHighlightMouseCursorMenuShownOnDetailMenu());
   EXPECT_TRUE(IsHighlightKeyboardFocusMenuShownOnDetailMenu());
   EXPECT_TRUE(IsStickyKeysMenuShownOnDetailMenu());
-  EXPECT_TRUE(IsTapDraggingMenuShownOnDetailMenu());
   CloseDetailMenu();
   UnblockUserSession();
 
@@ -287,7 +281,6 @@
   EXPECT_TRUE(IsHighlightMouseCursorMenuShownOnDetailMenu());
   EXPECT_TRUE(IsHighlightKeyboardFocusMenuShownOnDetailMenu());
   EXPECT_TRUE(IsStickyKeysMenuShownOnDetailMenu());
-  EXPECT_TRUE(IsTapDraggingMenuShownOnDetailMenu());
   CloseDetailMenu();
   UnblockUserSession();
 }
diff --git a/ash/system/tray_caps_lock.cc b/ash/system/tray_caps_lock.cc
index 8fe3e9f6..27af730 100644
--- a/ash/system/tray_caps_lock.cc
+++ b/ash/system/tray_caps_lock.cc
@@ -9,6 +9,7 @@
 #include "ash/accessibility/accessibility_controller.h"
 #include "ash/ime/ime_controller.h"
 #include "ash/metrics/user_metrics_recorder.h"
+#include "ash/public/cpp/ash_features.h"
 #include "ash/public/cpp/config.h"
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/session/session_controller.h"
@@ -74,16 +75,20 @@
       IsSearchKeyMappedToCapsLock()
           ? IDS_ASH_STATUS_TRAY_CAPS_LOCK_CANCEL_BY_SEARCH
           : IDS_ASH_STATUS_TRAY_CAPS_LOCK_CANCEL_BY_ALT_SEARCH;
-  return Notification::CreateSystemNotification(
-      message_center::NOTIFICATION_TYPE_SIMPLE, kCapsLockNotificationId,
-      l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_CAPS_LOCK_ENABLED),
-      l10n_util::GetStringUTF16(string_id), gfx::Image(),
-      base::string16() /* display_source */, GURL(),
-      message_center::NotifierId(message_center::NotifierId::SYSTEM_COMPONENT,
-                                 kNotifierCapsLock),
-      message_center::RichNotificationData(), nullptr,
-      kNotificationCapslockIcon,
-      message_center::SystemNotificationWarningLevel::NORMAL);
+  std::unique_ptr<Notification> notification =
+      Notification::CreateSystemNotification(
+          message_center::NOTIFICATION_TYPE_SIMPLE, kCapsLockNotificationId,
+          l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_CAPS_LOCK_ENABLED),
+          l10n_util::GetStringUTF16(string_id), gfx::Image(),
+          base::string16() /* display_source */, GURL(),
+          message_center::NotifierId(
+              message_center::NotifierId::SYSTEM_COMPONENT, kNotifierCapsLock),
+          message_center::RichNotificationData(), nullptr,
+          kNotificationCapslockIcon,
+          message_center::SystemNotificationWarningLevel::NORMAL);
+  if (features::IsSystemTrayUnifiedEnabled())
+    notification->set_pinned(true);
+  return notification;
 }
 
 }  // namespace
diff --git a/ash/system/web_notification/web_notification_tray.cc b/ash/system/web_notification/web_notification_tray.cc
index 1d066c8a..c087bc4 100644
--- a/ash/system/web_notification/web_notification_tray.cc
+++ b/ash/system/web_notification/web_notification_tray.cc
@@ -414,7 +414,7 @@
   if (IsMessageCenterVisible())
     return false;
 
-  popup_collection_->DoUpdateIfPossible();
+  popup_collection_->DoUpdate();
   return true;
 }
 
@@ -452,6 +452,16 @@
   message_center_ui_controller_->ShowPopupBubble();
 }
 
+void WebNotificationTray::UpdateAfterRootWindowBoundsChange(
+    const gfx::Rect& old_bounds,
+    const gfx::Rect& new_bounds) {
+  TrayBackgroundView::UpdateAfterRootWindowBoundsChange(old_bounds, new_bounds);
+  // Hide the message center bubble, since the bounds may not have enough to
+  // show the current size of the message center. This handler is invoked when
+  // the screen is rotated or the screen size is changed.
+  message_center_ui_controller_->HideMessageCenterBubble();
+}
+
 void WebNotificationTray::AnchorUpdated() {
   if (message_center_bubble()) {
     UpdateClippingWindowBounds();
diff --git a/ash/system/web_notification/web_notification_tray.h b/ash/system/web_notification/web_notification_tray.h
index 5ce5b0a..0c1976f1 100644
--- a/ash/system/web_notification/web_notification_tray.h
+++ b/ash/system/web_notification/web_notification_tray.h
@@ -69,6 +69,8 @@
 
   // Overridden from TrayBackgroundView.
   void UpdateAfterShelfAlignmentChange() override;
+  void UpdateAfterRootWindowBoundsChange(const gfx::Rect& old_bounds,
+                                         const gfx::Rect& new_bounds) override;
   void AnchorUpdated() override;
   base::string16 GetAccessibleNameForTray() override;
   void HideBubbleWithView(const views::TrayBubbleView* bubble_view) override;
diff --git a/ash/touch/touch_devices_controller.cc b/ash/touch/touch_devices_controller.cc
index 33d63c79..539666c 100644
--- a/ash/touch/touch_devices_controller.cc
+++ b/ash/touch/touch_devices_controller.cc
@@ -6,8 +6,6 @@
 
 #include <utility>
 
-#include "ash/accessibility/accessibility_controller.h"
-#include "ash/public/cpp/accessibility_types.h"
 #include "ash/public/cpp/ash_pref_names.h"
 #include "ash/root_window_controller.h"
 #include "ash/session/session_controller.h"
@@ -69,18 +67,6 @@
   Shell::Get()->session_controller()->RemoveObserver(this);
 }
 
-void TouchDevicesController::SetTapDraggingEnabled(bool enabled) {
-  PrefService* prefs = GetActivePrefService();
-  if (!prefs)
-    return;
-  prefs->SetBoolean(prefs::kTapDraggingEnabled, enabled);
-  prefs->CommitPendingWrite();
-}
-
-bool TouchDevicesController::GetTapDraggingEnabled() const {
-  return tap_dragging_enabled_;
-}
-
 void TouchDevicesController::ToggleTouchpad() {
   PrefService* prefs = GetActivePrefService();
   if (!prefs)
@@ -167,12 +153,6 @@
 
   UMA_HISTOGRAM_BOOLEAN("Touchpad.TapDragging.Changed", enabled);
 
-  // Tap dragging is listed as a11y feature, so notifying a11y status changed.
-  // TODO(warx): tap dragging is considered to be removed from a11y feature.
-  // https://crbug.com/164273, https://crbug.com/724501.
-  Shell::Get()->accessibility_controller()->NotifyAccessibilityStatusChanged(
-      A11Y_NOTIFICATION_NONE);
-
   if (!GetInputDeviceControllerClient())
     return;  // Happens in tests.
 
diff --git a/ash/touch/touch_devices_controller.h b/ash/touch/touch_devices_controller.h
index 6aa82700..37bcb68 100644
--- a/ash/touch/touch_devices_controller.h
+++ b/ash/touch/touch_devices_controller.h
@@ -35,10 +35,6 @@
 
   static void RegisterProfilePrefs(PrefRegistrySimple* registry, bool for_test);
 
-  // Gets/Sets tap dragging enabled.
-  void SetTapDraggingEnabled(bool enabled);
-  bool GetTapDraggingEnabled() const;
-
   // Toggles the status of touchpad between enabled and disabled.
   void ToggleTouchpad();
 
@@ -52,6 +48,8 @@
   // based on the requests of multiple sources.
   void SetTouchscreenEnabled(bool enabled, TouchscreenEnabledSource source);
 
+  bool tap_dragging_enabled_for_test() { return tap_dragging_enabled_; }
+
  private:
   // Overridden from SessionObserver:
   void OnUserSessionAdded(const AccountId& account_id) override;
diff --git a/ash/touch/touch_devices_controller_unittest.cc b/ash/touch/touch_devices_controller_unittest.cc
index dc3014f..8bd3b591 100644
--- a/ash/touch/touch_devices_controller_unittest.cc
+++ b/ash/touch/touch_devices_controller_unittest.cc
@@ -39,6 +39,13 @@
       TouchscreenEnabledSource::GLOBAL);
 }
 
+void SetTapDraggingEnabled(bool enabled) {
+  PrefService* prefs =
+      Shell::Get()->session_controller()->GetLastActiveUserPrefService();
+  prefs->SetBoolean(prefs::kTapDraggingEnabled, enabled);
+  prefs->CommitPendingWrite();
+}
+
 class TouchDevicesControllerSigninTest : public NoSessionAshTestBase {
  public:
   TouchDevicesControllerSigninTest() = default;
@@ -82,18 +89,18 @@
 
 TEST_F(TouchDevicesControllerSigninTest, SetTapDraggingEnabled) {
   auto* controller = Shell::Get()->touch_devices_controller();
-  ASSERT_FALSE(controller->GetTapDraggingEnabled());
-  controller->SetTapDraggingEnabled(true);
-  EXPECT_TRUE(controller->GetTapDraggingEnabled());
+  ASSERT_FALSE(controller->tap_dragging_enabled_for_test());
+  SetTapDraggingEnabled(true);
+  EXPECT_TRUE(controller->tap_dragging_enabled_for_test());
 
   // Switch to user 2 and switch back.
   SwitchActiveUser(kUser2Email);
-  EXPECT_FALSE(controller->GetTapDraggingEnabled());
+  EXPECT_FALSE(controller->tap_dragging_enabled_for_test());
   SwitchActiveUser(kUser1Email);
-  EXPECT_TRUE(controller->GetTapDraggingEnabled());
+  EXPECT_TRUE(controller->tap_dragging_enabled_for_test());
 
-  controller->SetTapDraggingEnabled(false);
-  EXPECT_FALSE(controller->GetTapDraggingEnabled());
+  SetTapDraggingEnabled(false);
+  EXPECT_FALSE(controller->tap_dragging_enabled_for_test());
 }
 
 // Tests that touchpad enabled user pref works properly under debug accelerator.
@@ -148,7 +155,7 @@
 // time pref changes.
 TEST_F(TouchDevicesControllerPrefsTest, RecordUma) {
   auto* controller = Shell::Get()->touch_devices_controller();
-  ASSERT_FALSE(controller->GetTapDraggingEnabled());
+  ASSERT_FALSE(controller->tap_dragging_enabled_for_test());
 
   TestSessionControllerClient* session = GetSessionControllerClient();
   // Disable auto-provision of PrefService.
@@ -172,8 +179,8 @@
   histogram_tester.ExpectTotalCount("Touchpad.TapDragging.Started", 1);
   histogram_tester.ExpectTotalCount("Touchpad.TapDragging.Changed", 0);
 
-  EXPECT_FALSE(controller->GetTapDraggingEnabled());
-  controller->SetTapDraggingEnabled(true);
+  EXPECT_FALSE(controller->tap_dragging_enabled_for_test());
+  SetTapDraggingEnabled(true);
   histogram_tester.ExpectTotalCount("Touchpad.TapDragging.Started", 1);
   histogram_tester.ExpectTotalCount("Touchpad.TapDragging.Changed", 1);
 }
diff --git a/ash/wallpaper/DEPS b/ash/wallpaper/DEPS
index f6a0335..cbd7c55 100644
--- a/ash/wallpaper/DEPS
+++ b/ash/wallpaper/DEPS
@@ -1,4 +1,3 @@
 include_rules = [
-  "+components/wallpaper",
   "+services/data_decoder/public",
 ]
diff --git a/ash/wallpaper/wallpaper_controller.cc b/ash/wallpaper/wallpaper_controller.cc
index fb86de49..b5e9af9 100644
--- a/ash/wallpaper/wallpaper_controller.cc
+++ b/ash/wallpaper/wallpaper_controller.cc
@@ -20,7 +20,9 @@
 #include "ash/shell.h"
 #include "ash/shell_delegate.h"
 #include "ash/wallpaper/wallpaper_controller_observer.h"
-#include "ash/wallpaper/wallpaper_decoder.h"
+#include "ash/wallpaper/wallpaper_utils/wallpaper_color_calculator.h"
+#include "ash/wallpaper/wallpaper_utils/wallpaper_decoder.h"
+#include "ash/wallpaper/wallpaper_utils/wallpaper_resizer.h"
 #include "ash/wallpaper/wallpaper_view.h"
 #include "ash/wallpaper/wallpaper_widget_controller.h"
 #include "base/bind.h"
@@ -37,10 +39,6 @@
 #include "chromeos/chromeos_switches.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/scoped_user_pref_update.h"
-#include "components/wallpaper/wallpaper_color_calculator.h"
-#include "components/wallpaper/wallpaper_color_profile.h"
-#include "components/wallpaper/wallpaper_files_id.h"
-#include "components/wallpaper/wallpaper_resizer.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/manager/managed_display_info.h"
 #include "ui/display/screen.h"
@@ -53,8 +51,6 @@
 using color_utils::ColorProfile;
 using color_utils::LumaRange;
 using color_utils::SaturationRange;
-using wallpaper::ColorProfileType;
-using wallpaper::WallpaperInfo;
 
 namespace ash {
 
@@ -246,7 +242,7 @@
 // and starts resizing operation of the custom wallpaper if necessary.
 void SaveCustomWallpaper(const std::string& wallpaper_files_id,
                          const base::FilePath& original_path,
-                         wallpaper::WallpaperLayout layout,
+                         WallpaperLayout layout,
                          std::unique_ptr<gfx::ImageSkia> image) {
   base::DeleteFile(WallpaperController::GetCustomWallpaperDir(
                        WallpaperController::kOriginalWallpaperSubDir)
@@ -275,8 +271,8 @@
   // resized wallpaper is not generated (i.e. chrome shutdown before resized
   // wallpaper is saved).
   WallpaperController::ResizeAndSaveWallpaper(
-      *image, original_path, wallpaper::WALLPAPER_LAYOUT_STRETCH,
-      image->width(), image->height(), nullptr);
+      *image, original_path, WALLPAPER_LAYOUT_STRETCH, image->width(),
+      image->height(), nullptr);
   WallpaperController::ResizeAndSaveWallpaper(
       *image, small_wallpaper_path, layout,
       WallpaperController::kSmallWallpaperMaxWidth,
@@ -434,7 +430,7 @@
 // static
 bool WallpaperController::ResizeImage(
     const gfx::ImageSkia& image,
-    wallpaper::WallpaperLayout layout,
+    WallpaperLayout layout,
     int preferred_width,
     int preferred_height,
     scoped_refptr<base::RefCountedBytes>* output,
@@ -445,7 +441,7 @@
   int resized_height;
   *output = new base::RefCountedBytes();
 
-  if (layout == wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED) {
+  if (layout == WALLPAPER_LAYOUT_CENTER_CROPPED) {
     // Do not resize custom wallpaper if it is smaller than preferred size.
     if (!(width > preferred_width && height > preferred_height))
       return false;
@@ -461,7 +457,7 @@
       resized_height =
           gfx::ToRoundedInt(static_cast<double>(height) * horizontal_ratio);
     }
-  } else if (layout == wallpaper::WALLPAPER_LAYOUT_STRETCH) {
+  } else if (layout == WALLPAPER_LAYOUT_STRETCH) {
     resized_width = preferred_width;
     resized_height = preferred_height;
   } else {
@@ -485,14 +481,13 @@
 }
 
 // static
-bool WallpaperController::ResizeAndSaveWallpaper(
-    const gfx::ImageSkia& image,
-    const base::FilePath& path,
-    wallpaper::WallpaperLayout layout,
-    int preferred_width,
-    int preferred_height,
-    gfx::ImageSkia* output_skia) {
-  if (layout == wallpaper::WALLPAPER_LAYOUT_CENTER) {
+bool WallpaperController::ResizeAndSaveWallpaper(const gfx::ImageSkia& image,
+                                                 const base::FilePath& path,
+                                                 WallpaperLayout layout,
+                                                 int preferred_width,
+                                                 int preferred_height,
+                                                 gfx::ImageSkia* output_skia) {
+  if (layout == WALLPAPER_LAYOUT_CENTER) {
     // TODO(bshe): Generates cropped custom wallpaper for CENTER layout.
     if (base::PathExists(path))
       base::DeleteFile(path, false);
@@ -518,7 +513,7 @@
 void WallpaperController::SetWallpaperFromPath(
     const AccountId& account_id,
     const user_manager::UserType& user_type,
-    const wallpaper::WallpaperInfo& info,
+    const WallpaperInfo& info,
     const base::FilePath& wallpaper_path,
     bool show_wallpaper,
     const scoped_refptr<base::SingleThreadTaskRunner>& reply_task_runner,
@@ -624,16 +619,16 @@
   return 0;
 }
 
-wallpaper::WallpaperLayout WallpaperController::GetWallpaperLayout() const {
+WallpaperLayout WallpaperController::GetWallpaperLayout() const {
   if (current_wallpaper_)
     return current_wallpaper_->wallpaper_info().layout;
-  return wallpaper::NUM_WALLPAPER_LAYOUT;
+  return NUM_WALLPAPER_LAYOUT;
 }
 
-wallpaper::WallpaperType WallpaperController::GetWallpaperType() const {
+WallpaperType WallpaperController::GetWallpaperType() const {
   if (current_wallpaper_)
     return current_wallpaper_->wallpaper_info().type;
-  return wallpaper::WALLPAPER_TYPE_COUNT;
+  return WALLPAPER_TYPE_COUNT;
 }
 
 bool WallpaperController::ShouldShowInitialAnimation() {
@@ -677,9 +672,8 @@
 
   const bool use_small =
       (GetAppropriateResolution() == WALLPAPER_RESOLUTION_SMALL);
-  wallpaper::WallpaperLayout layout =
-      use_small ? wallpaper::WALLPAPER_LAYOUT_CENTER
-                : wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED;
+  WallpaperLayout layout =
+      use_small ? WALLPAPER_LAYOUT_CENTER : WALLPAPER_LAYOUT_CENTER_CROPPED;
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
   base::FilePath file_path;
   base::Optional<user_manager::UserType> active_user_type =
@@ -743,10 +737,9 @@
   // 1x1 wallpaper should be stretched to fill the entire screen.
   // (WALLPAPER_LAYOUT_TILE also serves this purpose.)
   if (image.width() == 1 && image.height() == 1)
-    info.layout = wallpaper::WALLPAPER_LAYOUT_STRETCH;
+    info.layout = WALLPAPER_LAYOUT_STRETCH;
 
-  VLOG(1) << "SetWallpaper: image_id="
-          << wallpaper::WallpaperResizer::GetImageId(image)
+  VLOG(1) << "SetWallpaper: image_id=" << WallpaperResizer::GetImageId(image)
           << " layout=" << info.layout;
 
   if (WallpaperIsAlreadyLoaded(image, true /*compare_layouts=*/, info.layout)) {
@@ -755,7 +748,7 @@
   }
 
   UMA_HISTOGRAM_ENUMERATION("Ash.Wallpaper.Type", info.type,
-                            wallpaper::WALLPAPER_TYPE_COUNT);
+                            WALLPAPER_TYPE_COUNT);
 
   // Cancel any in-flight color calculation because we have a new wallpaper.
   if (color_calculator_) {
@@ -764,7 +757,7 @@
   }
 
   is_first_wallpaper_ = !current_wallpaper_;
-  current_wallpaper_.reset(new wallpaper::WallpaperResizer(
+  current_wallpaper_.reset(new WallpaperResizer(
       image, GetMaxDisplaySizeInNative(), info, sequenced_task_runner_));
   current_wallpaper_->AddObserver(this);
   current_wallpaper_->StartResize();
@@ -785,7 +778,7 @@
   WallpaperInfo info;
   if (!GetUserWallpaperInfo(account_id, &info, is_ephemeral))
     return false;
-  return info.type == wallpaper::POLICY;
+  return info.type == POLICY;
 }
 
 bool WallpaperController::CanSetUserWallpaper(const AccountId& account_id,
@@ -902,7 +895,7 @@
 bool WallpaperController::WallpaperIsAlreadyLoaded(
     const gfx::ImageSkia& image,
     bool compare_layouts,
-    wallpaper::WallpaperLayout layout) const {
+    WallpaperLayout layout) const {
   if (!current_wallpaper_)
     return false;
 
@@ -910,7 +903,7 @@
   if (compare_layouts && layout != current_wallpaper_->wallpaper_info().layout)
     return false;
 
-  return wallpaper::WallpaperResizer::GetImageId(image) ==
+  return WallpaperResizer::GetImageId(image) ==
          current_wallpaper_->original_image_id();
 }
 
@@ -1020,8 +1013,8 @@
     return false;
 
   info->location = location;
-  info->layout = static_cast<wallpaper::WallpaperLayout>(layout);
-  info->type = static_cast<wallpaper::WallpaperType>(type);
+  info->layout = static_cast<WallpaperLayout>(layout);
+  info->type = static_cast<WallpaperType>(type);
   info->date = base::Time::FromInternalValue(date_val);
   return true;
 }
@@ -1029,9 +1022,8 @@
 bool WallpaperController::InitializeUserWallpaperInfo(
     const AccountId& account_id,
     bool is_ephemeral) {
-  const wallpaper::WallpaperInfo info = {
-      std::string(), wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED,
-      wallpaper::DEFAULT, base::Time::Now().LocalMidnight()};
+  const WallpaperInfo info = {std::string(), WALLPAPER_LAYOUT_CENTER_CROPPED,
+                              DEFAULT, base::Time::Now().LocalMidnight()};
   return SetUserWallpaperInfo(account_id, info, is_ephemeral);
 }
 
@@ -1088,7 +1080,7 @@
     mojom::WallpaperUserInfoPtr user_info,
     const std::string& wallpaper_files_id,
     const std::string& file_name,
-    wallpaper::WallpaperLayout layout,
+    WallpaperLayout layout,
     const gfx::ImageSkia& image,
     bool preview_mode) {
   DCHECK(Shell::Get()->session_controller()->IsActiveUserSessionStarted());
@@ -1100,17 +1092,16 @@
     DCHECK(is_active_user);
     confirm_preview_wallpaper_callback_ = base::BindOnce(
         &WallpaperController::SaveAndSetWallpaper, weak_factory_.GetWeakPtr(),
-        std::move(user_info), wallpaper_files_id, file_name,
-        wallpaper::CUSTOMIZED, layout, false /*show_wallpaper=*/, image);
-    ShowWallpaperImage(
-        image,
-        wallpaper::WallpaperInfo{std::string(), layout, wallpaper::CUSTOMIZED,
-                                 base::Time::Now().LocalMidnight()},
-        true /*preview_mode=*/);
+        std::move(user_info), wallpaper_files_id, file_name, CUSTOMIZED, layout,
+        false /*show_wallpaper=*/, image);
+    ShowWallpaperImage(image,
+                       WallpaperInfo{std::string(), layout, CUSTOMIZED,
+                                     base::Time::Now().LocalMidnight()},
+                       true /*preview_mode=*/);
   } else {
     SaveAndSetWallpaper(std::move(user_info), wallpaper_files_id, file_name,
-                        wallpaper::CUSTOMIZED, layout,
-                        is_active_user /*show_wallpaper=*/, image);
+                        CUSTOMIZED, layout, is_active_user /*show_wallpaper=*/,
+                        image);
   }
 }
 
@@ -1118,7 +1109,7 @@
     mojom::WallpaperUserInfoPtr user_info,
     const gfx::ImageSkia& image,
     const std::string& url,
-    wallpaper::WallpaperLayout layout,
+    WallpaperLayout layout,
     bool preview_mode) {
   DCHECK(Shell::Get()->session_controller()->IsActiveUserSessionStarted());
   if (!CanSetUserWallpaper(user_info->account_id, user_info->is_ephemeral))
@@ -1131,11 +1122,10 @@
         base::BindOnce(&WallpaperController::SetOnlineWallpaperImpl,
                        weak_factory_.GetWeakPtr(), image, url, layout,
                        std::move(user_info), false /*show_wallpaper=*/);
-    ShowWallpaperImage(
-        image,
-        wallpaper::WallpaperInfo{std::string(), layout, wallpaper::ONLINE,
-                                 base::Time::Now().LocalMidnight()},
-        true /*preview_mode=*/);
+    ShowWallpaperImage(image,
+                       WallpaperInfo{std::string(), layout, ONLINE,
+                                     base::Time::Now().LocalMidnight()},
+                       true /*preview_mode=*/);
   } else {
     SetOnlineWallpaperImpl(image, url, layout, std::move(user_info),
                            is_active_user /*show_wallpaper=*/);
@@ -1171,7 +1161,7 @@
   // If the current wallpaper has type DEFAULT, the new customized default
   // wallpaper should be shown immediately to update the screen. It shouldn't
   // replace wallpapers of other types.
-  bool show_wallpaper = (GetWallpaperType() == wallpaper::DEFAULT);
+  bool show_wallpaper = (GetWallpaperType() == DEFAULT);
 
   // Customized default wallpapers are subject to the same restrictions as other
   // default wallpapers, e.g. they should not be set during guest sessions.
@@ -1192,11 +1182,10 @@
   // Updates the screen only when the user has logged in.
   const bool show_wallpaper =
       Shell::Get()->session_controller()->IsActiveUserSessionStarted();
-  LoadedCallback callback =
-      base::Bind(&WallpaperController::SaveAndSetWallpaper,
-                 weak_factory_.GetWeakPtr(), base::Passed(&user_info),
-                 wallpaper_files_id, kPolicyWallpaperFile, wallpaper::POLICY,
-                 wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED, show_wallpaper);
+  LoadedCallback callback = base::Bind(
+      &WallpaperController::SaveAndSetWallpaper, weak_factory_.GetWeakPtr(),
+      base::Passed(&user_info), wallpaper_files_id, kPolicyWallpaperFile,
+      POLICY, WALLPAPER_LAYOUT_CENTER_CROPPED, show_wallpaper);
 
   if (bypass_decode_for_testing_)
     std::move(callback).Run(CreateSolidColorWallpaper());
@@ -1224,10 +1213,10 @@
     mojom::WallpaperUserInfoPtr user_info,
     const std::string& wallpaper_files_id,
     const std::string& file_name,
-    wallpaper::WallpaperLayout layout,
+    WallpaperLayout layout,
     const gfx::ImageSkia& image,
     SetThirdPartyWallpaperCallback callback) {
-  const uint32_t image_id = wallpaper::WallpaperResizer::GetImageId(image);
+  const uint32_t image_id = WallpaperResizer::GetImageId(image);
   bool allowed_to_set_wallpaper =
       CanSetUserWallpaper(user_info->account_id, user_info->is_ephemeral);
   bool allowed_to_show_wallpaper = IsActiveUser(user_info->account_id);
@@ -1236,8 +1225,7 @@
 
   if (allowed_to_set_wallpaper) {
     SaveAndSetWallpaper(std::move(user_info), wallpaper_files_id, file_name,
-                        wallpaper::CUSTOMIZED, layout,
-                        allowed_to_show_wallpaper, image);
+                        CUSTOMIZED, layout, allowed_to_show_wallpaper, image);
   }
 }
 
@@ -1254,7 +1242,7 @@
 
 void WallpaperController::UpdateCustomWallpaperLayout(
     mojom::WallpaperUserInfoPtr user_info,
-    wallpaper::WallpaperLayout layout) {
+    WallpaperLayout layout) {
   // This method has a very specific use case: the user should be active and
   // have a custom wallpaper.
   // The currently active user has index 0.
@@ -1267,7 +1255,7 @@
   WallpaperInfo info;
   if (!GetUserWallpaperInfo(user_info->account_id, &info,
                             user_info->is_ephemeral) ||
-      info.type != wallpaper::CUSTOMIZED) {
+      info.type != CUSTOMIZED) {
     return;
   }
   if (info.layout == layout)
@@ -1330,8 +1318,7 @@
     return;
   }
 
-  if (info.type != wallpaper::CUSTOMIZED && info.type != wallpaper::POLICY &&
-      info.type != wallpaper::DEVICE) {
+  if (info.type != CUSTOMIZED && info.type != POLICY && info.type != DEVICE) {
     // Load wallpaper according to WallpaperInfo.
     SetWallpaperFromInfo(account_id, current_user_->type, info,
                          true /*show_wallpaper=*/);
@@ -1339,15 +1326,15 @@
   }
 
   base::FilePath wallpaper_path;
-  if (info.type == wallpaper::DEVICE) {
+  if (info.type == DEVICE) {
     wallpaper_path = GetDevicePolicyWallpaperFilePath();
   } else {
     std::string sub_dir = GetCustomWallpaperSubdirForCurrentResolution();
     // Wallpaper is not resized when layout is
-    // wallpaper::WALLPAPER_LAYOUT_CENTER.
+    // WALLPAPER_LAYOUT_CENTER.
     // Original wallpaper should be used in this case.
     // TODO(bshe): Generates cropped custom wallpaper for CENTER layout.
-    if (info.layout == wallpaper::WALLPAPER_LAYOUT_CENTER)
+    if (info.layout == WALLPAPER_LAYOUT_CENTER)
       sub_dir = kOriginalWallpaperSubDir;
     wallpaper_path = GetCustomWallpaperDir(sub_dir);
     wallpaper_path = wallpaper_path.Append(info.location);
@@ -1450,7 +1437,7 @@
   const std::vector<SkColor> colors = color_calculator_->prominent_colors();
   color_calculator_.reset();
   // Use |WallpaperInfo::location| as the key for storing |prominent_colors_| in
-  // the |wallpaper::kWallpaperColors| pref.
+  // the |kWallpaperColors| pref.
   // TODO(crbug.com/787134): The |prominent_colors_| of wallpapers with empty
   // location should be cached as well.
   if (!current_wallpaper_->wallpaper_info().location.empty())
@@ -1591,7 +1578,7 @@
 void WallpaperController::SetOnlineWallpaperImpl(
     const gfx::ImageSkia& image,
     const std::string& url,
-    const wallpaper::WallpaperLayout& layout,
+    const WallpaperLayout& layout,
     mojom::WallpaperUserInfoPtr user_info,
     bool show_wallpaper) {
   if (image.isNull()) {
@@ -1599,7 +1586,7 @@
     return;
   }
 
-  WallpaperInfo wallpaper_info = {url, layout, wallpaper::ONLINE,
+  WallpaperInfo wallpaper_info = {url, layout, ONLINE,
                                   base::Time::Now().LocalMidnight()};
   if (!SetUserWallpaperInfo(user_info->account_id, wallpaper_info,
                             user_info->is_ephemeral)) {
@@ -1620,7 +1607,7 @@
     const user_manager::UserType& user_type,
     const WallpaperInfo& info,
     bool show_wallpaper) {
-  if (info.type != wallpaper::ONLINE && info.type != wallpaper::DEFAULT) {
+  if (info.type != ONLINE && info.type != DEFAULT) {
     // This method is meant to be used for ONLINE and DEFAULT types. In
     // unexpected cases, revert to default wallpaper to fail safely. See
     // crosbug.com/38429.
@@ -1640,12 +1627,12 @@
   }
 
   base::FilePath wallpaper_path;
-  if (info.type == wallpaper::ONLINE) {
+  if (info.type == ONLINE) {
     std::string file_name = GURL(info.location).ExtractFileName();
     WallpaperResolution resolution = GetAppropriateResolution();
     // Only solid color wallpapers have stretch layout and they have only
     // one resolution.
-    if (info.layout != wallpaper::WALLPAPER_LAYOUT_STRETCH &&
+    if (info.layout != WALLPAPER_LAYOUT_STRETCH &&
         resolution == WALLPAPER_RESOLUTION_SMALL) {
       file_name = base::FilePath(file_name)
                       .InsertBeforeExtension(kSmallWallpaperSuffix)
@@ -1686,7 +1673,7 @@
 
 void WallpaperController::OnDefaultWallpaperDecoded(
     const base::FilePath& path,
-    wallpaper::WallpaperLayout layout,
+    WallpaperLayout layout,
     bool show_wallpaper,
     const gfx::ImageSkia& image) {
   if (image.isNull()) {
@@ -1700,7 +1687,7 @@
 
   if (show_wallpaper) {
     WallpaperInfo info(cached_default_wallpaper_.file_path.value(), layout,
-                       wallpaper::DEFAULT, base::Time::Now().LocalMidnight());
+                       DEFAULT, base::Time::Now().LocalMidnight());
     ShowWallpaperImage(cached_default_wallpaper_.image, info,
                        false /*preview_mode=*/);
   }
@@ -1710,8 +1697,8 @@
     mojom::WallpaperUserInfoPtr user_info,
     const std::string& wallpaper_files_id,
     const std::string& file_name,
-    wallpaper::WallpaperType type,
-    wallpaper::WallpaperLayout layout,
+    WallpaperType type,
+    WallpaperLayout layout,
     bool show_wallpaper,
     const gfx::ImageSkia& image) {
   // If the image of the new wallpaper is empty, the current wallpaper is still
@@ -1740,7 +1727,7 @@
 
   const bool should_save_to_disk =
       !user_info->is_ephemeral ||
-      (type == wallpaper::POLICY &&
+      (type == POLICY &&
        user_info->type == user_manager::USER_TYPE_PUBLIC_ACCOUNT);
 
   if (should_save_to_disk) {
@@ -1770,7 +1757,7 @@
     const AccountId& account_id,
     const user_manager::UserType& user_type,
     const base::FilePath& wallpaper_path,
-    const wallpaper::WallpaperInfo& info,
+    const WallpaperInfo& info,
     bool show_wallpaper) {
   ReadAndDecodeWallpaper(
       base::Bind(&WallpaperController::OnWallpaperDecoded,
@@ -1783,7 +1770,7 @@
     const AccountId& account_id,
     const user_manager::UserType& user_type,
     const base::FilePath& path,
-    const wallpaper::WallpaperInfo& info,
+    const WallpaperInfo& info,
     bool show_wallpaper,
     const gfx::ImageSkia& image) {
   // Empty image indicates decode failure. Use default wallpaper in this case.
@@ -1851,7 +1838,7 @@
     return;
   }
 
-  color_calculator_ = std::make_unique<wallpaper::WallpaperColorCalculator>(
+  color_calculator_ = std::make_unique<WallpaperColorCalculator>(
       GetWallpaper(), color_profiles_, sequenced_task_runner_);
   color_calculator_->AddObserver(this);
   if (!color_calculator_->StartCalculation()) {
@@ -1889,8 +1876,7 @@
 
 bool WallpaperController::IsDevicePolicyWallpaper() const {
   if (current_wallpaper_) {
-    return current_wallpaper_->wallpaper_info().type ==
-           wallpaper::WallpaperType::DEVICE;
+    return current_wallpaper_->wallpaper_info().type == WallpaperType::DEVICE;
   }
   return false;
 }
@@ -1917,8 +1903,8 @@
                             true /*show_wallpaper=*/);
   } else {
     WallpaperInfo info(GetDevicePolicyWallpaperFilePath().value(),
-                       wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED,
-                       wallpaper::DEVICE, base::Time::Now().LocalMidnight());
+                       WALLPAPER_LAYOUT_CENTER_CROPPED, DEVICE,
+                       base::Time::Now().LocalMidnight());
     ShowWallpaperImage(image, info, false /*preview_mode=*/);
   }
 }
diff --git a/ash/wallpaper/wallpaper_controller.h b/ash/wallpaper/wallpaper_controller.h
index f622d7a..faf7bf1 100644
--- a/ash/wallpaper/wallpaper_controller.h
+++ b/ash/wallpaper/wallpaper_controller.h
@@ -9,17 +9,18 @@
 
 #include "ash/ash_export.h"
 #include "ash/display/window_tree_host_manager.h"
+#include "ash/public/cpp/wallpaper_types.h"
 #include "ash/public/interfaces/wallpaper.mojom.h"
 #include "ash/session/session_observer.h"
 #include "ash/shell_observer.h"
+#include "ash/wallpaper/wallpaper_info.h"
+#include "ash/wallpaper/wallpaper_utils/wallpaper_color_calculator_observer.h"
+#include "ash/wallpaper/wallpaper_utils/wallpaper_resizer_observer.h"
 #include "base/files/file_path.h"
 #include "base/memory/ref_counted.h"
 #include "base/observer_list.h"
 #include "base/timer/timer.h"
 #include "components/user_manager/user_type.h"
-#include "components/wallpaper/wallpaper_color_calculator_observer.h"
-#include "components/wallpaper/wallpaper_info.h"
-#include "components/wallpaper/wallpaper_resizer_observer.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "mojo/public/cpp/bindings/interface_ptr_set.h"
 #include "ui/compositor/compositor_lock.h"
@@ -36,14 +37,11 @@
 struct ColorProfile;
 }  // namespace color_utils
 
-namespace wallpaper {
-class WallpaperColorCalculator;
-class WallpaperResizer;
-}  // namespace wallpaper
-
 namespace ash {
 
+class WallpaperColorCalculator;
 class WallpaperControllerObserver;
+class WallpaperResizer;
 
 // The |CustomWallpaperElement| contains |first| the path of the image which
 // is currently being loaded and or in progress of being loaded and |second|
@@ -60,14 +58,13 @@
 //   - Move wallpaper to locked container(s) when session state is not ACTIVE to
 //     hide the user desktop and move it to unlocked container when session
 //     state is ACTIVE;
-class ASH_EXPORT WallpaperController
-    : public mojom::WallpaperController,
-      public WindowTreeHostManager::Observer,
-      public ShellObserver,
-      public wallpaper::WallpaperResizerObserver,
-      public wallpaper::WallpaperColorCalculatorObserver,
-      public SessionObserver,
-      public ui::CompositorLockClient {
+class ASH_EXPORT WallpaperController : public mojom::WallpaperController,
+                                       public WindowTreeHostManager::Observer,
+                                       public ShellObserver,
+                                       public WallpaperResizerObserver,
+                                       public WallpaperColorCalculatorObserver,
+                                       public SessionObserver,
+                                       public ui::CompositorLockClient {
  public:
   enum WallpaperMode { WALLPAPER_NONE, WALLPAPER_IMAGE };
 
@@ -145,7 +142,7 @@
   // |preferred_height| while respecting the |layout| choice. |output_skia| is
   // optional (may be null). Returns true on success.
   static bool ResizeImage(const gfx::ImageSkia& image,
-                          wallpaper::WallpaperLayout layout,
+                          WallpaperLayout layout,
                           int preferred_width,
                           int preferred_height,
                           scoped_refptr<base::RefCountedBytes>* output,
@@ -157,7 +154,7 @@
   // null). Returns true on success.
   static bool ResizeAndSaveWallpaper(const gfx::ImageSkia& image,
                                      const base::FilePath& path,
-                                     wallpaper::WallpaperLayout layout,
+                                     WallpaperLayout layout,
                                      int preferred_width,
                                      int preferred_height,
                                      gfx::ImageSkia* output_skia);
@@ -171,7 +168,7 @@
   static void SetWallpaperFromPath(
       const AccountId& account_id,
       const user_manager::UserType& user_type,
-      const wallpaper::WallpaperInfo& info,
+      const WallpaperInfo& info,
       const base::FilePath& wallpaper_path,
       bool show_wallpaper,
       const scoped_refptr<base::SingleThreadTaskRunner>& reply_task_runner,
@@ -217,11 +214,11 @@
 
   // Returns the layout of the current wallpaper, or an invalid value if there's
   // no wallpaper.
-  wallpaper::WallpaperLayout GetWallpaperLayout() const;
+  WallpaperLayout GetWallpaperLayout() const;
 
   // Returns the type of the current wallpaper, or an invalid value if there's
   // no wallpaper.
-  wallpaper::WallpaperType GetWallpaperType() const;
+  WallpaperType GetWallpaperType() const;
 
   base::TimeDelta animation_duration() const { return animation_duration_; }
 
@@ -240,7 +237,7 @@
   // image if |preview_mode| is false and the current wallpaper is still being
   // previewed. See comments for |confirm_preview_wallpaper_callback_|.
   void ShowWallpaperImage(const gfx::ImageSkia& image,
-                          wallpaper::WallpaperInfo info,
+                          WallpaperInfo info,
                           bool preview_mode);
 
   // Implementation of |SetDefaultWallpaper|. Sets wallpaper to default if
@@ -283,7 +280,7 @@
   // |current_wallpaper_|. If |compare_layouts| is false, layout is ignored.
   bool WallpaperIsAlreadyLoaded(const gfx::ImageSkia& image,
                                 bool compare_layouts,
-                                wallpaper::WallpaperLayout layout) const;
+                                WallpaperLayout layout) const;
 
   // Reads image from |file_path| on disk, and calls |OnWallpaperDataRead|
   // with the result of |ReadFileToString|.
@@ -310,13 +307,13 @@
   // |is_ephemeral| is false. Returns false if it fails (which happens if local
   // state is not available).
   bool SetUserWallpaperInfo(const AccountId& account_id,
-                            const wallpaper::WallpaperInfo& info,
+                            const WallpaperInfo& info,
                             bool is_ephemeral);
 
   // Gets wallpaper info of |account_id| from local state, or memory if
   // |is_ephemeral| is true. Returns false if wallpaper info is not found.
   bool GetUserWallpaperInfo(const AccountId& account_id,
-                            wallpaper::WallpaperInfo* info,
+                            WallpaperInfo* info,
                             bool is_ephemeral) const;
 
   // Initializes wallpaper info for the user to default and saves it to local
@@ -344,13 +341,13 @@
   void SetCustomWallpaper(mojom::WallpaperUserInfoPtr user_info,
                           const std::string& wallpaper_files_id,
                           const std::string& file_name,
-                          wallpaper::WallpaperLayout layout,
+                          WallpaperLayout layout,
                           const gfx::ImageSkia& image,
                           bool preview_mode) override;
   void SetOnlineWallpaper(mojom::WallpaperUserInfoPtr user_info,
                           const gfx::ImageSkia& image,
                           const std::string& url,
-                          wallpaper::WallpaperLayout layout,
+                          WallpaperLayout layout,
                           bool preview_mode) override;
   void SetDefaultWallpaper(mojom::WallpaperUserInfoPtr user_info,
                            const std::string& wallpaper_files_id,
@@ -365,13 +362,13 @@
   void SetThirdPartyWallpaper(mojom::WallpaperUserInfoPtr user_info,
                               const std::string& wallpaper_files_id,
                               const std::string& file_name,
-                              wallpaper::WallpaperLayout layout,
+                              WallpaperLayout layout,
                               const gfx::ImageSkia& image,
                               SetThirdPartyWallpaperCallback callback) override;
   void ConfirmPreviewWallpaper() override;
   void CancelPreviewWallpaper() override;
   void UpdateCustomWallpaperLayout(mojom::WallpaperUserInfoPtr user_info,
-                                   wallpaper::WallpaperLayout layout) override;
+                                   WallpaperLayout layout) override;
   void ShowUserWallpaper(mojom::WallpaperUserInfoPtr user_info) override;
   void ShowSigninWallpaper() override;
   void RemoveUserWallpaper(mojom::WallpaperUserInfoPtr user_info,
@@ -452,7 +449,7 @@
   // |show_wallpaper| is true.
   void SetOnlineWallpaperImpl(const gfx::ImageSkia& image,
                               const std::string& url,
-                              const wallpaper::WallpaperLayout& layout,
+                              const WallpaperLayout& layout,
                               mojom::WallpaperUserInfoPtr user_info,
                               bool show_wallpaper);
 
@@ -460,14 +457,14 @@
   // |show_wallpaper| is true.
   void SetWallpaperFromInfo(const AccountId& account_id,
                             const user_manager::UserType& user_type,
-                            const wallpaper::WallpaperInfo& info,
+                            const WallpaperInfo& info,
                             bool show_wallpaper);
 
   // Used as the callback of default wallpaper decoding. Sets default wallpaper
   // to be the decoded image, and shows the wallpaper now if |show_wallpaper|
   // is true.
   void OnDefaultWallpaperDecoded(const base::FilePath& path,
-                                 wallpaper::WallpaperLayout layout,
+                                 WallpaperLayout layout,
                                  bool show_wallpaper,
                                  const gfx::ImageSkia& image);
 
@@ -478,8 +475,8 @@
   void SaveAndSetWallpaper(mojom::WallpaperUserInfoPtr user_info,
                            const std::string& wallpaper_files_id,
                            const std::string& file_name,
-                           wallpaper::WallpaperType type,
-                           wallpaper::WallpaperLayout layout,
+                           WallpaperType type,
+                           WallpaperLayout layout,
                            bool show_wallpaper,
                            const gfx::ImageSkia& image);
 
@@ -487,7 +484,7 @@
   void StartDecodeFromPath(const AccountId& account_id,
                            const user_manager::UserType& user_type,
                            const base::FilePath& wallpaper_path,
-                           const wallpaper::WallpaperInfo& info,
+                           const WallpaperInfo& info,
                            bool show_wallpaper);
 
   // Used as the callback of wallpaper decoding. (Wallpapers of type DEFAULT
@@ -497,7 +494,7 @@
   void OnWallpaperDecoded(const AccountId& account_id,
                           const user_manager::UserType& user_type,
                           const base::FilePath& path,
-                          const wallpaper::WallpaperInfo& info,
+                          const WallpaperInfo& info,
                           bool show_wallpaper,
                           const gfx::ImageSkia& image);
 
@@ -570,10 +567,10 @@
 
   mojo::AssociatedInterfacePtrSet<mojom::WallpaperObserver> mojo_observers_;
 
-  std::unique_ptr<wallpaper::WallpaperResizer> current_wallpaper_;
+  std::unique_ptr<WallpaperResizer> current_wallpaper_;
 
   // Asynchronous task to extract colors from the wallpaper.
-  std::unique_ptr<wallpaper::WallpaperColorCalculator> color_calculator_;
+  std::unique_ptr<WallpaperColorCalculator> color_calculator_;
 
   // The prominent colors extracted from the current wallpaper.
   // kInvalidColor is used by default or if extracting colors fails.
@@ -584,7 +581,7 @@
 
   // The wallpaper info for ephemeral users, which is not stored to local state.
   // See |WallpaperUserInfo::is_ephemeral| for details.
-  std::map<AccountId, wallpaper::WallpaperInfo> ephemeral_users_wallpaper_info_;
+  std::map<AccountId, WallpaperInfo> ephemeral_users_wallpaper_info_;
 
   // Cached user info of the current user.
   mojom::WallpaperUserInfoPtr current_user_;
diff --git a/ash/wallpaper/wallpaper_controller_test_api.cc b/ash/wallpaper/wallpaper_controller_test_api.cc
index 212f74c..8f19234e 100644
--- a/ash/wallpaper/wallpaper_controller_test_api.cc
+++ b/ash/wallpaper/wallpaper_controller_test_api.cc
@@ -24,9 +24,8 @@
   gfx::Canvas canvas(gfx::Size(5, 5), 1.0f, true);
   canvas.DrawColor(color);
   gfx::ImageSkia image = gfx::ImageSkia::CreateFrom1xBitmap(canvas.GetBitmap());
-  wallpaper::WallpaperInfo info("", wallpaper::WALLPAPER_LAYOUT_CENTER,
-                                wallpaper::DEFAULT,
-                                base::Time::Now().LocalMidnight());
+  WallpaperInfo info("", WALLPAPER_LAYOUT_CENTER, DEFAULT,
+                     base::Time::Now().LocalMidnight());
   controller_->ShowWallpaperImage(image, info, false /*preview_mode=*/);
 
   return expected_color;
diff --git a/ash/wallpaper/wallpaper_controller_unittest.cc b/ash/wallpaper/wallpaper_controller_unittest.cc
index 2b1ce3a..044cdd3f 100644
--- a/ash/wallpaper/wallpaper_controller_unittest.cc
+++ b/ash/wallpaper/wallpaper_controller_unittest.cc
@@ -37,12 +37,6 @@
 #include "ui/gfx/canvas.h"
 #include "ui/views/widget/widget.h"
 
-using wallpaper::WallpaperLayout;
-using wallpaper::WALLPAPER_LAYOUT_CENTER;
-using wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED;
-using wallpaper::WALLPAPER_LAYOUT_STRETCH;
-using wallpaper::WALLPAPER_LAYOUT_TILE;
-
 using session_manager::SessionState;
 
 namespace ash {
@@ -346,9 +340,9 @@
 
   // Helper function to create a |WallpaperInfo| struct with dummy values
   // given the desired layout.
-  wallpaper::WallpaperInfo CreateWallpaperInfo(WallpaperLayout layout) {
-    return wallpaper::WallpaperInfo("", layout, wallpaper::DEFAULT,
-                                    base::Time::Now().LocalMidnight());
+  WallpaperInfo CreateWallpaperInfo(WallpaperLayout layout) {
+    return WallpaperInfo("", layout, DEFAULT,
+                         base::Time::Now().LocalMidnight());
   }
 
   // Helper function to create a new |mojom::WallpaperUserInfoPtr| instance with
@@ -392,9 +386,8 @@
     std::string relative_path =
         base::FilePath(wallpaper_files_id).Append(file_name).value();
     // Saves wallpaper info to local state for user.
-    wallpaper::WallpaperInfo info = {
-        relative_path, WALLPAPER_LAYOUT_CENTER_CROPPED, wallpaper::CUSTOMIZED,
-        base::Time::Now().LocalMidnight()};
+    WallpaperInfo info = {relative_path, WALLPAPER_LAYOUT_CENTER_CROPPED,
+                          CUSTOMIZED, base::Time::Now().LocalMidnight()};
     ASSERT_TRUE(controller_->SetUserWallpaperInfo(account_id, info,
                                                   false /*is_ephemeral=*/));
   }
@@ -404,9 +397,8 @@
   void SimulateSettingCustomWallpaper(const AccountId& account_id) {
     ASSERT_TRUE(controller_->SetUserWallpaperInfo(
         account_id,
-        wallpaper::WallpaperInfo("dummy_file_location", WALLPAPER_LAYOUT_CENTER,
-                                 wallpaper::CUSTOMIZED,
-                                 base::Time::Now().LocalMidnight()),
+        WallpaperInfo("dummy_file_location", WALLPAPER_LAYOUT_CENTER,
+                      CUSTOMIZED, base::Time::Now().LocalMidnight()),
         false /*is_ephemeral=*/));
   }
 
@@ -862,13 +854,13 @@
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
   EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
-  EXPECT_EQ(controller_->GetWallpaperType(), wallpaper::CUSTOMIZED);
-  wallpaper::WallpaperInfo wallpaper_info;
+  EXPECT_EQ(controller_->GetWallpaperType(), CUSTOMIZED);
+  WallpaperInfo wallpaper_info;
   EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
                                                 false /*is_ephemeral=*/));
-  wallpaper::WallpaperInfo expected_wallpaper_info(
+  WallpaperInfo expected_wallpaper_info(
       base::FilePath(wallpaper_files_id_1).Append(file_name_1).value(), layout,
-      wallpaper::CUSTOMIZED, base::Time::Now().LocalMidnight());
+      CUSTOMIZED, base::Time::Now().LocalMidnight());
   EXPECT_EQ(wallpaper_info, expected_wallpaper_info);
 
   // Now set another custom wallpaper for |user_1|. Verify that the on-screen
@@ -909,12 +901,12 @@
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
   EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
-  EXPECT_EQ(controller_->GetWallpaperType(), wallpaper::ONLINE);
-  wallpaper::WallpaperInfo wallpaper_info;
+  EXPECT_EQ(controller_->GetWallpaperType(), ONLINE);
+  WallpaperInfo wallpaper_info;
   EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
                                                 false /*is_ephemeral=*/));
-  wallpaper::WallpaperInfo expected_wallpaper_info(
-      url, layout, wallpaper::ONLINE, base::Time::Now().LocalMidnight());
+  WallpaperInfo expected_wallpaper_info(url, layout, ONLINE,
+                                        base::Time::Now().LocalMidnight());
   EXPECT_EQ(wallpaper_info, expected_wallpaper_info);
 
   // Now set another online wallpaper for |user_1|. Verify that the on-screen
@@ -946,7 +938,7 @@
   ClearLogin();
 
   // The user starts with no wallpaper info and is not controlled by policy.
-  wallpaper::WallpaperInfo wallpaper_info;
+  WallpaperInfo wallpaper_info;
   EXPECT_FALSE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
                                                  false /*is_ephemeral=*/));
   EXPECT_FALSE(
@@ -954,7 +946,7 @@
   // A default wallpaper is shown for the user.
   controller_->ShowUserWallpaper(InitializeUser(account_id_1));
   EXPECT_EQ(1, GetWallpaperCount());
-  EXPECT_EQ(controller_->GetWallpaperType(), wallpaper::DEFAULT);
+  EXPECT_EQ(controller_->GetWallpaperType(), DEFAULT);
 
   // Set a policy wallpaper. Verify that the user becomes policy controlled and
   // the wallpaper info is updated.
@@ -964,12 +956,11 @@
   RunAllTasksUntilIdle();
   EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
                                                 false /*is_ephemeral=*/));
-  wallpaper::WallpaperInfo policy_wallpaper_info(
-      base::FilePath(wallpaper_files_id_1)
-          .Append("policy-controlled.jpeg")
-          .value(),
-      wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED, wallpaper::POLICY,
-      base::Time::Now().LocalMidnight());
+  WallpaperInfo policy_wallpaper_info(base::FilePath(wallpaper_files_id_1)
+                                          .Append("policy-controlled.jpeg")
+                                          .value(),
+                                      WALLPAPER_LAYOUT_CENTER_CROPPED, POLICY,
+                                      base::Time::Now().LocalMidnight());
   EXPECT_EQ(wallpaper_info, policy_wallpaper_info);
   EXPECT_TRUE(
       controller_->IsPolicyControlled(account_id_1, false /*is_ephemeral=*/));
@@ -980,7 +971,7 @@
   SimulateUserLogin(user_1);
   controller_->ShowUserWallpaper(InitializeUser(account_id_1));
   EXPECT_EQ(1, GetWallpaperCount());
-  EXPECT_EQ(controller_->GetWallpaperType(), wallpaper::POLICY);
+  EXPECT_EQ(controller_->GetWallpaperType(), POLICY);
 
   // Log out the user and remove the policy wallpaper. Verify the wallpaper
   // info is reset to default and the user is no longer policy controlled.
@@ -990,21 +981,21 @@
   WaitUntilCustomWallpapersDeleted(account_id_1);
   EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
                                                 false /*is_ephemeral=*/));
-  wallpaper::WallpaperInfo default_wallpaper_info(
-      std::string(), wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED,
-      wallpaper::DEFAULT, base::Time::Now().LocalMidnight());
+  WallpaperInfo default_wallpaper_info(std::string(),
+                                       WALLPAPER_LAYOUT_CENTER_CROPPED, DEFAULT,
+                                       base::Time::Now().LocalMidnight());
   EXPECT_EQ(wallpaper_info, default_wallpaper_info);
   EXPECT_FALSE(
       controller_->IsPolicyControlled(account_id_1, false /*is_ephemeral=*/));
   // Verify the wallpaper is not updated since the user hasn't logged in.
   EXPECT_EQ(0, GetWallpaperCount());
-  EXPECT_EQ(controller_->GetWallpaperType(), wallpaper::POLICY);
+  EXPECT_EQ(controller_->GetWallpaperType(), POLICY);
 
   // Log in the user. Verify the default wallpaper is now being shown.
   SimulateUserLogin(user_1);
   controller_->ShowUserWallpaper(InitializeUser(account_id_1));
   EXPECT_EQ(1, GetWallpaperCount());
-  EXPECT_EQ(controller_->GetWallpaperType(), wallpaper::DEFAULT);
+  EXPECT_EQ(controller_->GetWallpaperType(), DEFAULT);
 }
 
 TEST_F(WallpaperControllerTest, SetThirdPartyWallpaper) {
@@ -1012,7 +1003,7 @@
   SimulateUserLogin(user_1);
 
   // Verify the user starts with no wallpaper info.
-  wallpaper::WallpaperInfo wallpaper_info;
+  WallpaperInfo wallpaper_info;
   EXPECT_FALSE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
                                                  false /*is_ephemeral=*/));
 
@@ -1037,9 +1028,9 @@
   // Verify the user wallpaper info is updated.
   EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
                                                 false /*is_ephemeral=*/));
-  wallpaper::WallpaperInfo expected_wallpaper_info(
+  WallpaperInfo expected_wallpaper_info(
       base::FilePath(wallpaper_files_id_1).Append(file_name_1).value(), layout,
-      wallpaper::CUSTOMIZED, base::Time::Now().LocalMidnight());
+      CUSTOMIZED, base::Time::Now().LocalMidnight());
   EXPECT_EQ(wallpaper_info, expected_wallpaper_info);
 
   // Switch active user to |user_2|, but set another third-party wallpaper for
@@ -1064,9 +1055,9 @@
   // wallpaper is still allowed for non-active users.
   EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
                                                 false /*is_ephemeral=*/));
-  wallpaper::WallpaperInfo expected_wallpaper_info_2(
+  WallpaperInfo expected_wallpaper_info_2(
       base::FilePath(wallpaper_files_id_2).Append(file_name_2).value(), layout,
-      wallpaper::CUSTOMIZED, base::Time::Now().LocalMidnight());
+      CUSTOMIZED, base::Time::Now().LocalMidnight());
   EXPECT_EQ(wallpaper_info, expected_wallpaper_info_2);
 
   // Set a policy wallpaper for |user_2|. Verify that |user_2| becomes policy
@@ -1103,12 +1094,11 @@
   EXPECT_TRUE(IsActiveUserWallpaperControlledByPolicy());
   EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_2, &wallpaper_info,
                                                 false /*is_ephemeral=*/));
-  wallpaper::WallpaperInfo policy_wallpaper_info(
-      base::FilePath(wallpaper_files_id_2)
-          .Append("policy-controlled.jpeg")
-          .value(),
-      wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED, wallpaper::POLICY,
-      base::Time::Now().LocalMidnight());
+  WallpaperInfo policy_wallpaper_info(base::FilePath(wallpaper_files_id_2)
+                                          .Append("policy-controlled.jpeg")
+                                          .value(),
+                                      WALLPAPER_LAYOUT_CENTER_CROPPED, POLICY,
+                                      base::Time::Now().LocalMidnight());
   EXPECT_EQ(wallpaper_info, policy_wallpaper_info);
 }
 
@@ -1118,12 +1108,12 @@
 
   // First, simulate setting a user custom wallpaper.
   SimulateSettingCustomWallpaper(account_id_1);
-  wallpaper::WallpaperInfo wallpaper_info;
+  WallpaperInfo wallpaper_info;
   EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
                                                 false /*is_ephemeral=*/));
-  wallpaper::WallpaperInfo default_wallpaper_info(
-      std::string(), wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED,
-      wallpaper::DEFAULT, base::Time::Now().LocalMidnight());
+  WallpaperInfo default_wallpaper_info(std::string(),
+                                       WALLPAPER_LAYOUT_CENTER_CROPPED, DEFAULT,
+                                       base::Time::Now().LocalMidnight());
   EXPECT_NE(wallpaper_info.type, default_wallpaper_info.type);
 
   // Verify |SetDefaultWallpaper| removes the previously set custom wallpaper
@@ -1136,7 +1126,7 @@
                                    true /*show_wallpaper=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
-  EXPECT_EQ(controller_->GetWallpaperType(), wallpaper::DEFAULT);
+  EXPECT_EQ(controller_->GetWallpaperType(), DEFAULT);
   EXPECT_TRUE(CompareDecodeFilePaths(
       {wallpaper_dir_->GetPath().Append(default_large_wallpaper_name)}));
 
@@ -1156,7 +1146,7 @@
                                    true /*show_wallpaper=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
-  EXPECT_EQ(controller_->GetWallpaperType(), wallpaper::DEFAULT);
+  EXPECT_EQ(controller_->GetWallpaperType(), DEFAULT);
   EXPECT_TRUE(CompareDecodeFilePaths(
       {wallpaper_dir_->GetPath().Append(default_small_wallpaper_name)}));
 
@@ -1176,7 +1166,7 @@
                                    true /*show_wallpaper=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
-  EXPECT_EQ(controller_->GetWallpaperType(), wallpaper::DEFAULT);
+  EXPECT_EQ(controller_->GetWallpaperType(), DEFAULT);
   EXPECT_TRUE(CompareDecodeFilePaths(
       {wallpaper_dir_->GetPath().Append(default_small_wallpaper_name)}));
 
@@ -1206,7 +1196,7 @@
                                    true /*show_wallpaper=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
-  EXPECT_EQ(controller_->GetWallpaperType(), wallpaper::DEFAULT);
+  EXPECT_EQ(controller_->GetWallpaperType(), DEFAULT);
   EXPECT_TRUE(CompareDecodeFilePaths(
       {wallpaper_dir_->GetPath().Append(child_large_wallpaper_name)}));
 
@@ -1221,7 +1211,7 @@
                                    true /*show_wallpaper=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
-  EXPECT_EQ(controller_->GetWallpaperType(), wallpaper::DEFAULT);
+  EXPECT_EQ(controller_->GetWallpaperType(), DEFAULT);
   EXPECT_TRUE(CompareDecodeFilePaths(
       {wallpaper_dir_->GetPath().Append(child_small_wallpaper_name)}));
 }
@@ -1232,12 +1222,12 @@
   // First, simulate setting a custom wallpaper for a regular user.
   SimulateUserLogin(user_1);
   SimulateSettingCustomWallpaper(account_id_1);
-  wallpaper::WallpaperInfo wallpaper_info;
+  WallpaperInfo wallpaper_info;
   EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
                                                 false /*is_ephemeral=*/));
-  wallpaper::WallpaperInfo default_wallpaper_info(
-      std::string(), wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED,
-      wallpaper::DEFAULT, base::Time::Now().LocalMidnight());
+  WallpaperInfo default_wallpaper_info(std::string(),
+                                       WALLPAPER_LAYOUT_CENTER_CROPPED, DEFAULT,
+                                       base::Time::Now().LocalMidnight());
   EXPECT_NE(wallpaper_info.type, default_wallpaper_info.type);
 
   SimulateGuestLogin();
@@ -1252,7 +1242,7 @@
                                    true /*show_wallpaper=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
-  EXPECT_EQ(controller_->GetWallpaperType(), wallpaper::DEFAULT);
+  EXPECT_EQ(controller_->GetWallpaperType(), DEFAULT);
   EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
                                                 false /*is_ephemeral=*/));
   EXPECT_EQ(wallpaper_info, default_wallpaper_info);
@@ -1266,7 +1256,7 @@
                                    true /*show_wallpaper=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
-  EXPECT_EQ(controller_->GetWallpaperType(), wallpaper::DEFAULT);
+  EXPECT_EQ(controller_->GetWallpaperType(), DEFAULT);
   EXPECT_TRUE(CompareDecodeFilePaths(
       {wallpaper_dir_->GetPath().Append(guest_small_wallpaper_name)}));
 }
@@ -1288,7 +1278,7 @@
       WALLPAPER_LAYOUT_CENTER, image, false /*preview_mode=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(0, GetWallpaperCount());
-  wallpaper::WallpaperInfo wallpaper_info;
+  WallpaperInfo wallpaper_info;
   EXPECT_FALSE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
                                                  false /*is_ephemeral=*/));
 
@@ -1333,15 +1323,14 @@
       WALLPAPER_LAYOUT_CENTER, image, false /*preview_mode=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(0, GetWallpaperCount());
-  wallpaper::WallpaperInfo wallpaper_info;
+  WallpaperInfo wallpaper_info;
   EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
                                                 false /*is_ephemeral=*/));
-  wallpaper::WallpaperInfo policy_wallpaper_info(
-      base::FilePath(wallpaper_files_id_1)
-          .Append("policy-controlled.jpeg")
-          .value(),
-      wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED, wallpaper::POLICY,
-      base::Time::Now().LocalMidnight());
+  WallpaperInfo policy_wallpaper_info(base::FilePath(wallpaper_files_id_1)
+                                          .Append("policy-controlled.jpeg")
+                                          .value(),
+                                      WALLPAPER_LAYOUT_CENTER_CROPPED, POLICY,
+                                      base::Time::Now().LocalMidnight());
   EXPECT_EQ(wallpaper_info, policy_wallpaper_info);
 
   // Verify that |SetOnlineWallpaper| doesn't set wallpaper when policy is
@@ -1492,7 +1481,7 @@
   // Display is initialized to 800x600. The small resolution default wallpaper
   // is expected.
   EXPECT_EQ(1, GetWallpaperCount());
-  EXPECT_EQ(controller_->GetWallpaperType(), wallpaper::DEFAULT);
+  EXPECT_EQ(controller_->GetWallpaperType(), DEFAULT);
   EXPECT_TRUE(CompareDecodeFilePaths(
       {wallpaper_dir_->GetPath().Append(default_small_wallpaper_name)}));
 
@@ -1503,7 +1492,7 @@
   UpdateDisplay("800x600/r");
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
-  EXPECT_EQ(controller_->GetWallpaperType(), wallpaper::DEFAULT);
+  EXPECT_EQ(controller_->GetWallpaperType(), DEFAULT);
   EXPECT_TRUE(CompareDecodeFilePaths(
       {wallpaper_dir_->GetPath().Append(default_small_wallpaper_name)}));
 }
@@ -1535,12 +1524,12 @@
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
   EXPECT_EQ(controller_->GetWallpaperLayout(), layout);
-  wallpaper::WallpaperInfo wallpaper_info;
+  WallpaperInfo wallpaper_info;
   EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
                                                 false /*is_ephemeral=*/));
-  wallpaper::WallpaperInfo expected_wallpaper_info(
+  WallpaperInfo expected_wallpaper_info(
       base::FilePath(wallpaper_files_id_1).Append(file_name_1).value(), layout,
-      wallpaper::CUSTOMIZED, base::Time::Now().LocalMidnight());
+      CUSTOMIZED, base::Time::Now().LocalMidnight());
   EXPECT_EQ(wallpaper_info, expected_wallpaper_info);
 
   // Now change to a different layout. Verify that the layout is updated for
@@ -1564,10 +1553,10 @@
                                   layout, false /*preview_mode=*/);
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
-  EXPECT_EQ(controller_->GetWallpaperType(), wallpaper::ONLINE);
+  EXPECT_EQ(controller_->GetWallpaperType(), ONLINE);
   EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info,
                                                 false /*is_ephemeral=*/));
-  expected_wallpaper_info.type = wallpaper::ONLINE;
+  expected_wallpaper_info.type = ONLINE;
   expected_wallpaper_info.location = url;
   EXPECT_EQ(wallpaper_info, expected_wallpaper_info);
 
@@ -1709,8 +1698,8 @@
 
 TEST_F(WallpaperControllerTest, WallpaperBlurDisabledByPolicy) {
   // Simulate DEVICE policy wallpaper.
-  const wallpaper::WallpaperInfo info("", WALLPAPER_LAYOUT_CENTER,
-                                      wallpaper::DEVICE, base::Time::Now());
+  const WallpaperInfo info("", WALLPAPER_LAYOUT_CENTER, DEVICE,
+                           base::Time::Now());
   const gfx::ImageSkia image = CreateImage(10, 10, kWallpaperColor);
   controller_->ShowWallpaperImage(image, info, false /*preview_mode=*/);
   ASSERT_FALSE(controller_->IsBlurEnabled());
@@ -1881,10 +1870,10 @@
   controller_->ShowUserWallpaper(InitializeUser(account_id_1));
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
-  wallpaper::WallpaperInfo user_wallpaper_info;
-  wallpaper::WallpaperInfo default_wallpaper_info(
-      std::string(), wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED,
-      wallpaper::DEFAULT, base::Time::Now().LocalMidnight());
+  WallpaperInfo user_wallpaper_info;
+  WallpaperInfo default_wallpaper_info(std::string(),
+                                       WALLPAPER_LAYOUT_CENTER_CROPPED, DEFAULT,
+                                       base::Time::Now().LocalMidnight());
   EXPECT_TRUE(controller_->GetUserWallpaperInfo(
       account_id_1, &user_wallpaper_info, false /*is_ephemeral=*/));
   EXPECT_EQ(user_wallpaper_info, default_wallpaper_info);
@@ -1914,9 +1903,9 @@
   EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
   // Verify that the user wallpaper info is now updated to the custom wallpaper
   // info.
-  wallpaper::WallpaperInfo custom_wallpaper_info(
+  WallpaperInfo custom_wallpaper_info(
       base::FilePath(wallpaper_files_id_1).Append(file_name_1).value(), layout,
-      wallpaper::CUSTOMIZED, base::Time::Now().LocalMidnight());
+      CUSTOMIZED, base::Time::Now().LocalMidnight());
   EXPECT_TRUE(controller_->GetUserWallpaperInfo(
       account_id_1, &user_wallpaper_info, false /*is_ephemeral=*/));
   EXPECT_EQ(user_wallpaper_info, custom_wallpaper_info);
@@ -1948,8 +1937,8 @@
   EXPECT_EQ(online_wallpaper_color, GetWallpaperColor());
   // Verify that the user wallpaper info is now updated to the online wallpaper
   // info.
-  wallpaper::WallpaperInfo online_wallpaper_info(
-      url, layout, wallpaper::ONLINE, base::Time::Now().LocalMidnight());
+  WallpaperInfo online_wallpaper_info(url, layout, ONLINE,
+                                      base::Time::Now().LocalMidnight());
   EXPECT_TRUE(controller_->GetUserWallpaperInfo(
       account_id_1, &user_wallpaper_info, false /*is_ephemeral=*/));
   EXPECT_EQ(user_wallpaper_info, online_wallpaper_info);
@@ -1962,10 +1951,10 @@
   controller_->ShowUserWallpaper(InitializeUser(account_id_1));
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
-  wallpaper::WallpaperInfo user_wallpaper_info;
-  wallpaper::WallpaperInfo default_wallpaper_info(
-      std::string(), wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED,
-      wallpaper::DEFAULT, base::Time::Now().LocalMidnight());
+  WallpaperInfo user_wallpaper_info;
+  WallpaperInfo default_wallpaper_info(std::string(),
+                                       WALLPAPER_LAYOUT_CENTER_CROPPED, DEFAULT,
+                                       base::Time::Now().LocalMidnight());
   EXPECT_TRUE(controller_->GetUserWallpaperInfo(
       account_id_1, &user_wallpaper_info, false /*is_ephemeral=*/));
   EXPECT_EQ(user_wallpaper_info, default_wallpaper_info);
@@ -1993,7 +1982,7 @@
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
   EXPECT_NE(kWallpaperColor, GetWallpaperColor());
-  EXPECT_EQ(controller_->GetWallpaperType(), wallpaper::DEFAULT);
+  EXPECT_EQ(controller_->GetWallpaperType(), DEFAULT);
   EXPECT_EQ(user_wallpaper_info, default_wallpaper_info);
 
   // Now set an online wallpaper for the user and enable preview. Verify that
@@ -2021,7 +2010,7 @@
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
   EXPECT_NE(online_wallpaper_color, GetWallpaperColor());
-  EXPECT_EQ(controller_->GetWallpaperType(), wallpaper::DEFAULT);
+  EXPECT_EQ(controller_->GetWallpaperType(), DEFAULT);
   EXPECT_EQ(user_wallpaper_info, default_wallpaper_info);
 }
 
@@ -2032,10 +2021,10 @@
   controller_->ShowUserWallpaper(InitializeUser(account_id_1));
   RunAllTasksUntilIdle();
   EXPECT_EQ(1, GetWallpaperCount());
-  wallpaper::WallpaperInfo user_wallpaper_info;
-  wallpaper::WallpaperInfo default_wallpaper_info(
-      std::string(), wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED,
-      wallpaper::DEFAULT, base::Time::Now().LocalMidnight());
+  WallpaperInfo user_wallpaper_info;
+  WallpaperInfo default_wallpaper_info(std::string(),
+                                       WALLPAPER_LAYOUT_CENTER_CROPPED, DEFAULT,
+                                       base::Time::Now().LocalMidnight());
   EXPECT_TRUE(controller_->GetUserWallpaperInfo(
       account_id_1, &user_wallpaper_info, false /*is_ephemeral=*/));
   EXPECT_EQ(user_wallpaper_info, default_wallpaper_info);
@@ -2071,9 +2060,9 @@
   EXPECT_EQ(0, GetWallpaperCount());
   EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
   // However, the user wallpaper info should already be updated to the new info.
-  wallpaper::WallpaperInfo synced_custom_wallpaper_info(
+  WallpaperInfo synced_custom_wallpaper_info(
       base::FilePath(wallpaper_files_id_2).Append(file_name_2).value(), layout,
-      wallpaper::CUSTOMIZED, base::Time::Now().LocalMidnight());
+      CUSTOMIZED, base::Time::Now().LocalMidnight());
   EXPECT_TRUE(controller_->GetUserWallpaperInfo(
       account_id_1, &user_wallpaper_info, false /*is_ephemeral=*/));
   EXPECT_EQ(user_wallpaper_info, synced_custom_wallpaper_info);
@@ -2121,8 +2110,8 @@
   EXPECT_EQ(0, GetWallpaperCount());
   EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
   // However, the user wallpaper info should already be updated to the new info.
-  wallpaper::WallpaperInfo synced_online_wallpaper_info(
-      synced_url, layout, wallpaper::ONLINE, base::Time::Now().LocalMidnight());
+  WallpaperInfo synced_online_wallpaper_info(synced_url, layout, ONLINE,
+                                             base::Time::Now().LocalMidnight());
   EXPECT_TRUE(controller_->GetUserWallpaperInfo(
       account_id_1, &user_wallpaper_info, false /*is_ephemeral=*/));
   EXPECT_EQ(user_wallpaper_info, synced_online_wallpaper_info);
diff --git a/ash/wallpaper/wallpaper_decoder.cc b/ash/wallpaper/wallpaper_decoder.cc
deleted file mode 100644
index aaeff7a6..0000000
--- a/ash/wallpaper/wallpaper_decoder.cc
+++ /dev/null
@@ -1,49 +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 "ash/wallpaper/wallpaper_decoder.h"
-
-#include "ash/shell.h"
-#include "ash/shell_delegate.h"
-#include "ipc/ipc_channel.h"
-#include "services/data_decoder/public/cpp/decode_image.h"
-
-namespace ash {
-namespace {
-
-const int64_t kMaxImageSizeInBytes =
-    static_cast<int64_t>(IPC::Channel::kMaximumMessageSize);
-
-void ConvertToImageSkia(OnWallpaperDecoded callback, const SkBitmap& image) {
-  if (image.isNull()) {
-    std::move(callback).Run(gfx::ImageSkia());
-    return;
-  }
-  SkBitmap final_image = image;
-  final_image.setImmutable();
-  gfx::ImageSkia image_skia = gfx::ImageSkia::CreateFrom1xBitmap(final_image);
-  image_skia.MakeThreadSafe();
-
-  std::move(callback).Run(image_skia);
-}
-
-}  // namespace
-
-void DecodeWallpaper(const std::string& image_data,
-                     OnWallpaperDecoded callback) {
-  // The connector for the mojo service manager is null in unit tests.
-  if (!Shell::Get()->shell_delegate()->GetShellConnector()) {
-    std::move(callback).Run(gfx::ImageSkia());
-    return;
-  }
-  std::vector<uint8_t> image_bytes(image_data.begin(), image_data.end());
-  data_decoder::DecodeImage(
-      Shell::Get()->shell_delegate()->GetShellConnector(),
-      std::move(image_bytes), data_decoder::mojom::ImageCodec::ROBUST_JPEG,
-      false /* shrink_to_fit */, kMaxImageSizeInBytes,
-      gfx::Size() /* desired_image_frame_size */,
-      base::BindOnce(&ConvertToImageSkia, std::move(callback)));
-}
-
-}  // namespace ash
\ No newline at end of file
diff --git a/ash/wallpaper/wallpaper_decoder.h b/ash/wallpaper/wallpaper_decoder.h
deleted file mode 100644
index 3964f10..0000000
--- a/ash/wallpaper/wallpaper_decoder.h
+++ /dev/null
@@ -1,28 +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 ASH_WALLPAPER_WALLPAPER_DECODER_H_
-#define ASH_WALLPAPER_WALLPAPER_DECODER_H_
-
-#include "ash/ash_export.h"
-#include "base/callback_forward.h"
-#include "base/memory/scoped_refptr.h"
-
-namespace gfx {
-class ImageSkia;
-}
-
-namespace ash {
-
-using OnWallpaperDecoded =
-    base::OnceCallback<void(const gfx::ImageSkia& image)>;
-
-// Do an async wallpaper decode; |on_decoded| is run on the calling thread when
-// the decode has finished.
-ASH_EXPORT void DecodeWallpaper(const std::string& image_data,
-                                OnWallpaperDecoded callback);
-
-}  // namespace ash
-
-#endif  // ASH_WALLPAPER_WALLPAPER_DECODER_H_
\ No newline at end of file
diff --git a/ash/wallpaper/wallpaper_info.h b/ash/wallpaper/wallpaper_info.h
new file mode 100644
index 0000000..671f32c3
--- /dev/null
+++ b/ash/wallpaper/wallpaper_info.h
@@ -0,0 +1,43 @@
+// Copyright 2018 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 ASH_WALLPAPER_WALLPAPER_INFO_H_
+#define ASH_WALLPAPER_WALLPAPER_INFO_H_
+
+#include "ash/public/cpp/wallpaper_types.h"
+#include "base/time/time.h"
+
+namespace ash {
+
+struct WallpaperInfo {
+  WallpaperInfo()
+      : layout(WALLPAPER_LAYOUT_CENTER), type(WALLPAPER_TYPE_COUNT) {}
+
+  WallpaperInfo(const std::string& in_location,
+                WallpaperLayout in_layout,
+                WallpaperType in_type,
+                const base::Time& in_date)
+      : location(in_location),
+        layout(in_layout),
+        type(in_type),
+        date(in_date) {}
+
+  ~WallpaperInfo() {}
+
+  bool operator==(const WallpaperInfo& other) const {
+    return (location == other.location) && (layout == other.layout) &&
+           (type == other.type);
+  }
+
+  // Either file name of migrated wallpaper including first directory level
+  // (corresponding to user wallpaper_files_id) or online wallpaper URL.
+  std::string location;
+  WallpaperLayout layout;
+  WallpaperType type;
+  base::Time date;
+};
+
+}  // namespace ash
+
+#endif  // ASH_WALLPAPER_WALLPAPER_INFO_H_
diff --git a/ash/wallpaper/wallpaper_utils/wallpaper_color_calculator.cc b/ash/wallpaper/wallpaper_utils/wallpaper_color_calculator.cc
new file mode 100644
index 0000000..2e0964cb
--- /dev/null
+++ b/ash/wallpaper/wallpaper_utils/wallpaper_color_calculator.cc
@@ -0,0 +1,166 @@
+// Copyright 2018 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 "ash/wallpaper/wallpaper_utils/wallpaper_color_calculator.h"
+
+#include <string>
+#include <utility>
+
+#include "ash/wallpaper/wallpaper_utils/wallpaper_color_calculator_observer.h"
+#include "ash/wallpaper/wallpaper_utils/wallpaper_color_extraction_result.h"
+#include "base/bind.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/task_runner.h"
+#include "base/task_runner_util.h"
+#include "ui/gfx/color_analysis.h"
+#include "ui/gfx/image/image_skia.h"
+
+using LumaRange = color_utils::LumaRange;
+using SaturationRange = color_utils::SaturationRange;
+
+namespace ash {
+
+namespace {
+
+// The largest image size, in pixels, to synchronously calculate the prominent
+// color. This is a simple heuristic optimization because extraction on images
+// smaller than this should run very quickly, and offloading the task to another
+// thread would actually take longer.
+const int kMaxPixelsForSynchronousCalculation = 100;
+
+// Wrapper for color_utils::CalculateProminentColorsOfBitmap() that records
+// wallpaper specific metrics.
+//
+// NOTE: |image| is intentionally a copy to ensure it exists for the duration of
+// the calculation.
+std::vector<SkColor> CalculateWallpaperColor(
+    const gfx::ImageSkia image,
+    const std::vector<color_utils::ColorProfile> color_profiles) {
+  base::TimeTicks start_time = base::TimeTicks::Now();
+  const std::vector<SkColor> prominent_colors =
+      color_utils::CalculateProminentColorsOfBitmap(*image.bitmap(),
+                                                    color_profiles);
+
+  UMA_HISTOGRAM_TIMES("Ash.Wallpaper.ColorExtraction.Durations",
+                      base::TimeTicks::Now() - start_time);
+  WallpaperColorExtractionResult result = NUM_COLOR_EXTRACTION_RESULTS;
+  for (size_t i = 0; i < color_profiles.size(); ++i) {
+    bool is_result_transparent = prominent_colors[i] == SK_ColorTRANSPARENT;
+    if (color_profiles[i].saturation == SaturationRange::VIBRANT) {
+      switch (color_profiles[i].luma) {
+        case LumaRange::DARK:
+          result = is_result_transparent ? RESULT_DARK_VIBRANT_TRANSPARENT
+                                         : RESULT_DARK_VIBRANT_OPAQUE;
+          break;
+        case LumaRange::NORMAL:
+          result = is_result_transparent ? RESULT_NORMAL_VIBRANT_TRANSPARENT
+                                         : RESULT_NORMAL_VIBRANT_OPAQUE;
+          break;
+        case LumaRange::LIGHT:
+          result = is_result_transparent ? RESULT_LIGHT_VIBRANT_TRANSPARENT
+                                         : RESULT_LIGHT_VIBRANT_OPAQUE;
+          break;
+      }
+    } else {
+      switch (color_profiles[i].luma) {
+        case LumaRange::DARK:
+          result = is_result_transparent ? RESULT_DARK_MUTED_TRANSPARENT
+                                         : RESULT_DARK_MUTED_OPAQUE;
+          break;
+        case LumaRange::NORMAL:
+          result = is_result_transparent ? RESULT_NORMAL_MUTED_TRANSPARENT
+                                         : RESULT_NORMAL_MUTED_OPAQUE;
+          break;
+        case LumaRange::LIGHT:
+          result = is_result_transparent ? RESULT_LIGHT_MUTED_TRANSPARENT
+                                         : RESULT_LIGHT_MUTED_OPAQUE;
+          break;
+      }
+    }
+  }
+  DCHECK_NE(NUM_COLOR_EXTRACTION_RESULTS, result);
+  UMA_HISTOGRAM_ENUMERATION("Ash.Wallpaper.ColorExtractionResult2", result,
+                            NUM_COLOR_EXTRACTION_RESULTS);
+
+  return prominent_colors;
+}
+
+bool ShouldCalculateSync(const gfx::ImageSkia& image) {
+  return image.width() * image.height() <= kMaxPixelsForSynchronousCalculation;
+}
+
+}  // namespace
+
+WallpaperColorCalculator::WallpaperColorCalculator(
+    const gfx::ImageSkia& image,
+    const std::vector<color_utils::ColorProfile>& color_profiles,
+    scoped_refptr<base::TaskRunner> task_runner)
+    : image_(image),
+      color_profiles_(color_profiles),
+      task_runner_(std::move(task_runner)),
+      weak_ptr_factory_(this) {
+  prominent_colors_ =
+      std::vector<SkColor>(color_profiles_.size(), SK_ColorTRANSPARENT);
+}
+
+WallpaperColorCalculator::~WallpaperColorCalculator() = default;
+
+void WallpaperColorCalculator::AddObserver(
+    WallpaperColorCalculatorObserver* observer) {
+  observers_.AddObserver(observer);
+}
+
+void WallpaperColorCalculator::RemoveObserver(
+    WallpaperColorCalculatorObserver* observer) {
+  observers_.RemoveObserver(observer);
+}
+
+bool WallpaperColorCalculator::StartCalculation() {
+  if (ShouldCalculateSync(image_)) {
+    const std::vector<SkColor> prominent_colors =
+        CalculateWallpaperColor(image_, color_profiles_);
+    NotifyCalculationComplete(prominent_colors);
+    return true;
+  }
+
+  image_.MakeThreadSafe();
+  if (base::PostTaskAndReplyWithResult(
+          task_runner_.get(), FROM_HERE,
+          base::Bind(&CalculateWallpaperColor, image_, color_profiles_),
+          base::Bind(&WallpaperColorCalculator::OnAsyncCalculationComplete,
+                     weak_ptr_factory_.GetWeakPtr(), base::TimeTicks::Now()))) {
+    return true;
+  }
+
+  LOG(WARNING) << "PostSequencedWorkerTask failed. "
+               << "Wallpaper prominent colors may not be calculated.";
+
+  prominent_colors_ =
+      std::vector<SkColor>(color_profiles_.size(), SK_ColorTRANSPARENT);
+  return false;
+}
+
+void WallpaperColorCalculator::SetTaskRunnerForTest(
+    scoped_refptr<base::TaskRunner> task_runner) {
+  task_runner_ = task_runner;
+}
+
+void WallpaperColorCalculator::OnAsyncCalculationComplete(
+    base::TimeTicks async_start_time,
+    const std::vector<SkColor>& prominent_colors) {
+  UMA_HISTOGRAM_TIMES("Ash.Wallpaper.ColorExtraction.UserDelay",
+                      base::TimeTicks::Now() - async_start_time);
+  NotifyCalculationComplete(prominent_colors);
+}
+
+void WallpaperColorCalculator::NotifyCalculationComplete(
+    const std::vector<SkColor>& prominent_colors) {
+  prominent_colors_ = prominent_colors;
+  for (auto& observer : observers_)
+    observer.OnColorCalculationComplete();
+
+  // This could be deleted!
+}
+
+}  // namespace ash
diff --git a/ash/wallpaper/wallpaper_utils/wallpaper_color_calculator.h b/ash/wallpaper/wallpaper_utils/wallpaper_color_calculator.h
new file mode 100644
index 0000000..b2ee2e4
--- /dev/null
+++ b/ash/wallpaper/wallpaper_utils/wallpaper_color_calculator.h
@@ -0,0 +1,90 @@
+// Copyright 2018 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 ASH_WALLPAPER_WALLPAPER_UTILS_WALLPAPER_COLOR_CALCULATOR_H_
+#define ASH_WALLPAPER_WALLPAPER_UTILS_WALLPAPER_COLOR_CALCULATOR_H_
+
+#include "ash/ash_export.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
+#include "base/time/time.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/image/image_skia.h"
+
+namespace base {
+class TaskRunner;
+}
+
+namespace color_utils {
+struct ColorProfile;
+}
+
+namespace ash {
+
+class WallpaperColorCalculatorObserver;
+
+// Calculates colors based on a wallpaper image.
+class ASH_EXPORT WallpaperColorCalculator {
+ public:
+  // |image|, |color_profiles| are the input parameters to the color calculation
+  // that is executed on the |task_runner|.
+  WallpaperColorCalculator(
+      const gfx::ImageSkia& image,
+      const std::vector<color_utils::ColorProfile>& color_profiles,
+      scoped_refptr<base::TaskRunner> task_runner);
+  ~WallpaperColorCalculator();
+
+  void AddObserver(WallpaperColorCalculatorObserver* observer);
+
+  void RemoveObserver(WallpaperColorCalculatorObserver* observer);
+
+  // Initiates the calculation and returns false if the calculation fails to be
+  // initiated. Observers may be notified synchronously or asynchronously.
+  // Callers should be aware that this will make |image_| read-only.
+  bool StartCalculation() WARN_UNUSED_RESULT;
+
+  std::vector<SkColor> prominent_colors() const { return prominent_colors_; }
+
+  void set_prominent_colors_for_test(
+      const std::vector<SkColor>& prominent_colors) {
+    prominent_colors_ = prominent_colors;
+  }
+
+  // Explicitly sets the |task_runner_| for testing.
+  void SetTaskRunnerForTest(scoped_refptr<base::TaskRunner> task_runner);
+
+ private:
+  // Handles asynchronous calculation results. |async_start_time| is used to
+  // record duration metrics.
+  void OnAsyncCalculationComplete(base::TimeTicks async_start_time,
+                                  const std::vector<SkColor>& prominent_colors);
+
+  // Notifies observers that a color calulation has completed. Called on the
+  // same thread that constructed |this|.
+  void NotifyCalculationComplete(const std::vector<SkColor>& prominent_colors);
+
+  // The result of the color calculation.
+  std::vector<SkColor> prominent_colors_;
+
+  // The image to calculate colors from.
+  gfx::ImageSkia image_;
+
+  // The color profiles used to calculate colors.
+  std::vector<color_utils::ColorProfile> color_profiles_;
+
+  // The task runner to run the calculation on.
+  scoped_refptr<base::TaskRunner> task_runner_;
+
+  base::ObserverList<WallpaperColorCalculatorObserver> observers_;
+
+  base::WeakPtrFactory<WallpaperColorCalculator> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(WallpaperColorCalculator);
+};
+
+}  // namespace ash
+
+#endif  // ASH_WALLPAPER_WALLPAPER_UTILS_WALLPAPER_COLOR_CALCULATOR_H_
diff --git a/ash/wallpaper/wallpaper_utils/wallpaper_color_calculator_observer.h b/ash/wallpaper/wallpaper_utils/wallpaper_color_calculator_observer.h
new file mode 100644
index 0000000..aa3e0bb
--- /dev/null
+++ b/ash/wallpaper/wallpaper_utils/wallpaper_color_calculator_observer.h
@@ -0,0 +1,22 @@
+// Copyright 2018 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 ASH_WALLPAPER_WALLPAPER_UTILS_WALLPAPER_COLOR_CALCULATOR_OBSERVER_H_
+#define ASH_WALLPAPER_WALLPAPER_UTILS_WALLPAPER_COLOR_CALCULATOR_OBSERVER_H_
+
+namespace ash {
+
+// Observer for the WallpaperColorCalculator.
+class WallpaperColorCalculatorObserver {
+ public:
+  // Notified when a color calculation completes.
+  virtual void OnColorCalculationComplete() = 0;
+
+ protected:
+  virtual ~WallpaperColorCalculatorObserver() {}
+};
+
+}  // namespace ash
+
+#endif  // ASH_WALLPAPER_WALLPAPER_UTILS_WALLPAPER_COLOR_CALCULATOR_OBSERVER_H_
diff --git a/ash/wallpaper/wallpaper_utils/wallpaper_color_calculator_unittest.cc b/ash/wallpaper/wallpaper_utils/wallpaper_color_calculator_unittest.cc
new file mode 100644
index 0000000..c96d55d
--- /dev/null
+++ b/ash/wallpaper/wallpaper_utils/wallpaper_color_calculator_unittest.cc
@@ -0,0 +1,251 @@
+// Copyright 2018 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 "ash/wallpaper/wallpaper_utils/wallpaper_color_calculator.h"
+
+#include <memory>
+
+#include "ash/public/cpp/wallpaper_types.h"
+#include "ash/wallpaper/wallpaper_utils/wallpaper_color_calculator_observer.h"
+#include "ash/wallpaper/wallpaper_utils/wallpaper_color_extraction_result.h"
+#include "base/macros.h"
+#include "base/single_thread_task_runner.h"
+#include "base/test/histogram_tester.h"
+#include "base/test/null_task_runner.h"
+#include "base/test/test_mock_time_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "skia/ext/platform_canvas.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/color_analysis.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/image/image_skia.h"
+
+using ::testing::ElementsAre;
+using ::testing::IsEmpty;
+
+namespace ash {
+namespace {
+
+const SkColor kDefaultColor = SK_ColorTRANSPARENT;
+
+const SkColor kGray = SkColorSetRGB(10, 10, 10);
+
+const SkColor kVibrantGreen = SkColorSetRGB(25, 200, 25);
+
+// Image size that causes the WallpaperColorCalculator to synchronously extract
+// the prominent color.
+constexpr gfx::Size kSyncImageSize = gfx::Size(5, 5);
+
+// Image size that causes the WallpaperColorCalculator to asynchronously extract
+// the prominent color.
+constexpr gfx::Size kAsyncImageSize = gfx::Size(50, 50);
+
+class TestWallpaperColorCalculatorObserver
+    : public WallpaperColorCalculatorObserver {
+ public:
+  TestWallpaperColorCalculatorObserver() {}
+
+  ~TestWallpaperColorCalculatorObserver() override {}
+
+  bool WasNotified() const { return notified_; }
+
+  // WallpaperColorCalculatorObserver:
+  void OnColorCalculationComplete() override { notified_ = true; }
+
+ private:
+  bool notified_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(TestWallpaperColorCalculatorObserver);
+};
+
+// Returns an image that will yield a color using the LumaRange::NORMAL and
+// SaturationRange::VIBRANT values.
+gfx::ImageSkia CreateColorProducingImage(const gfx::Size& size) {
+  gfx::Canvas canvas(size, 1.0f, true);
+  canvas.DrawColor(kGray);
+  canvas.FillRect(gfx::Rect(0, 1, size.height(), 1), kVibrantGreen);
+  return gfx::ImageSkia::CreateFrom1xBitmap(canvas.GetBitmap());
+}
+
+// Returns an image that will not yield a color using the LumaRange::NORMAL and
+// SaturationRange::VIBRANT values.
+gfx::ImageSkia CreateNonColorProducingImage(const gfx::Size& size) {
+  gfx::Canvas canvas(size, 1.0f, true);
+  canvas.DrawColor(kGray);
+  return gfx::ImageSkia::CreateFrom1xBitmap(canvas.GetBitmap());
+}
+
+class WallpaperColorCalculatorTest : public testing::Test {
+ public:
+  WallpaperColorCalculatorTest();
+  ~WallpaperColorCalculatorTest() override;
+
+ protected:
+  // Installs the given |task_runner| globally and on the |calculator_| instance
+  // if it exists.
+  void InstallTaskRunner(
+      scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+
+  // Creates a new |calculator_| for the given |image| and installs the current
+  // |task_runner_|.
+  void CreateCalculator(const gfx::ImageSkia& image);
+
+  std::unique_ptr<WallpaperColorCalculator> calculator_;
+
+  // Required for asynchronous calculations.
+  scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
+
+  TestWallpaperColorCalculatorObserver observer_;
+
+  base::HistogramTester histograms_;
+
+ private:
+  // Required for asynchronous calculations, e.g. by PostTaskAndReplyImpl.
+  std::unique_ptr<base::ThreadTaskRunnerHandle> task_runner_handle_;
+
+  DISALLOW_COPY_AND_ASSIGN(WallpaperColorCalculatorTest);
+};
+
+WallpaperColorCalculatorTest::WallpaperColorCalculatorTest()
+    : task_runner_(new base::TestMockTimeTaskRunner()) {
+  CreateCalculator(CreateColorProducingImage(kAsyncImageSize));
+  InstallTaskRunner(task_runner_);
+}
+
+WallpaperColorCalculatorTest::~WallpaperColorCalculatorTest() {}
+
+void WallpaperColorCalculatorTest::InstallTaskRunner(
+    scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+  task_runner_handle_.reset();
+  task_runner_handle_ =
+      std::make_unique<base::ThreadTaskRunnerHandle>(task_runner);
+  if (calculator_)
+    calculator_->SetTaskRunnerForTest(task_runner);
+}
+
+void WallpaperColorCalculatorTest::CreateCalculator(
+    const gfx::ImageSkia& image) {
+  std::vector<color_utils::ColorProfile> color_profiles;
+  color_profiles.emplace_back(color_utils::LumaRange::NORMAL,
+                              color_utils::SaturationRange::VIBRANT);
+  calculator_ = std::make_unique<WallpaperColorCalculator>(
+      image, color_profiles, task_runner_);
+  calculator_->AddObserver(&observer_);
+}
+
+// Used to group the asynchronous calculation tests.
+using WallPaperColorCalculatorAsyncTest = WallpaperColorCalculatorTest;
+
+TEST_F(WallPaperColorCalculatorAsyncTest, MetricsForSuccessfulExtraction) {
+  histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.Durations", 0);
+  histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.UserDelay", 0);
+  EXPECT_THAT(histograms_.GetAllSamples("Ash.Wallpaper.ColorExtractionResult2"),
+              IsEmpty());
+
+  EXPECT_TRUE(calculator_->StartCalculation());
+  task_runner_->RunUntilIdle();
+
+  histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.Durations", 1);
+  histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.UserDelay", 1);
+  EXPECT_THAT(histograms_.GetAllSamples("Ash.Wallpaper.ColorExtractionResult2"),
+              ElementsAre(base::Bucket(RESULT_NORMAL_VIBRANT_OPAQUE, 1)));
+}
+
+TEST_F(WallPaperColorCalculatorAsyncTest, MetricsWhenPostingTaskFails) {
+  scoped_refptr<base::NullTaskRunner> task_runner = new base::NullTaskRunner();
+  InstallTaskRunner(task_runner);
+
+  histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.Durations", 0);
+  histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.UserDelay", 0);
+  EXPECT_THAT(histograms_.GetAllSamples("Ash.Wallpaper.ColorExtractionResult2"),
+              IsEmpty());
+
+  EXPECT_FALSE(calculator_->StartCalculation());
+  task_runner_->RunUntilIdle();
+
+  histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.Durations", 0);
+  histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.UserDelay", 0);
+  EXPECT_THAT(histograms_.GetAllSamples("Ash.Wallpaper.ColorExtractionResult2"),
+              IsEmpty());
+
+  EXPECT_EQ(kDefaultColor, calculator_->prominent_colors()[0]);
+}
+
+TEST_F(WallPaperColorCalculatorAsyncTest,
+       ObserverNotifiedOnSuccessfulCalculation) {
+  EXPECT_FALSE(observer_.WasNotified());
+
+  EXPECT_TRUE(calculator_->StartCalculation());
+  EXPECT_FALSE(observer_.WasNotified());
+
+  task_runner_->RunUntilIdle();
+  EXPECT_TRUE(observer_.WasNotified());
+}
+
+TEST_F(WallPaperColorCalculatorAsyncTest, ColorUpdatedOnSuccessfulCalculation) {
+  std::vector<SkColor> colors = {kDefaultColor};
+  calculator_->set_prominent_colors_for_test(colors);
+
+  EXPECT_TRUE(calculator_->StartCalculation());
+  EXPECT_EQ(kDefaultColor, calculator_->prominent_colors()[0]);
+
+  task_runner_->RunUntilIdle();
+  EXPECT_NE(kDefaultColor, calculator_->prominent_colors()[0]);
+}
+
+TEST_F(WallPaperColorCalculatorAsyncTest,
+       NoCrashWhenCalculatorDestroyedBeforeTaskProcessing) {
+  EXPECT_TRUE(calculator_->StartCalculation());
+  calculator_.reset();
+
+  EXPECT_TRUE(task_runner_->HasPendingTask());
+
+  task_runner_->RunUntilIdle();
+  EXPECT_FALSE(observer_.WasNotified());
+  EXPECT_FALSE(task_runner_->HasPendingTask());
+}
+
+// Used to group the synchronous calculation tests.
+using WallpaperColorCalculatorSyncTest = WallpaperColorCalculatorTest;
+
+TEST_F(WallpaperColorCalculatorSyncTest, MetricsForSuccessfulExtraction) {
+  CreateCalculator(CreateColorProducingImage(kSyncImageSize));
+  calculator_->SetTaskRunnerForTest(nullptr);
+
+  histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.Durations", 0);
+  histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.UserDelay", 0);
+  EXPECT_THAT(histograms_.GetAllSamples("Ash.Wallpaper.ColorExtractionResult2"),
+              IsEmpty());
+
+  EXPECT_TRUE(calculator_->StartCalculation());
+
+  histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.Durations", 1);
+  histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.UserDelay", 0);
+  EXPECT_THAT(histograms_.GetAllSamples("Ash.Wallpaper.ColorExtractionResult2"),
+              ElementsAre(base::Bucket(RESULT_NORMAL_VIBRANT_OPAQUE, 1)));
+}
+
+TEST_F(WallpaperColorCalculatorSyncTest, MetricsForFailedExctraction) {
+  CreateCalculator(CreateNonColorProducingImage(kSyncImageSize));
+
+  histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.Durations", 0);
+  histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.UserDelay", 0);
+  EXPECT_THAT(histograms_.GetAllSamples("Ash.Wallpaper.ColorExtractionResult2"),
+              IsEmpty());
+
+  EXPECT_TRUE(calculator_->StartCalculation());
+
+  histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.Durations", 1);
+  histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.UserDelay", 0);
+  EXPECT_THAT(histograms_.GetAllSamples("Ash.Wallpaper.ColorExtractionResult2"),
+              ElementsAre(base::Bucket(RESULT_NORMAL_VIBRANT_TRANSPARENT, 1)));
+}
+
+}  // namespace
+}  // namespace ash
diff --git a/ash/wallpaper/wallpaper_utils/wallpaper_color_extraction_result.h b/ash/wallpaper/wallpaper_utils/wallpaper_color_extraction_result.h
new file mode 100644
index 0000000..3084ba6
--- /dev/null
+++ b/ash/wallpaper/wallpaper_utils/wallpaper_color_extraction_result.h
@@ -0,0 +1,45 @@
+// Copyright 2018 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 ASH_WALLPAPER_WALLPAPER_UTILS_WALLPAPER_COLOR_EXTRACTION_RESULT_H_
+#define ASH_WALLPAPER_WALLPAPER_UTILS_WALLPAPER_COLOR_EXTRACTION_RESULT_H_
+
+namespace ash {
+
+// This enum is used to back a histogram, and should therefore be treated as
+// append-only.
+// For result, transparent indicates extraction failure and opaque indicates
+// extraction success.
+enum WallpaperColorExtractionResult {
+  // Transparent result on (dark, vibrant) color profile.
+  RESULT_DARK_VIBRANT_TRANSPARENT = 0,
+  // Opaque result on (dark, vibrant) color profile.
+  RESULT_DARK_VIBRANT_OPAQUE,
+  // Transparent result on (normal, vibrant) color profile.
+  RESULT_NORMAL_VIBRANT_TRANSPARENT,
+  // Opaque result on (normal, vibrant) color profile.
+  RESULT_NORMAL_VIBRANT_OPAQUE,
+  // Transparent result on (light, vibrant) color profile.
+  RESULT_LIGHT_VIBRANT_TRANSPARENT,
+  // Opaque result on (light, vibrant) color profile.
+  RESULT_LIGHT_VIBRANT_OPAQUE,
+  // Transparent result on (dark, muted) color profile.
+  RESULT_DARK_MUTED_TRANSPARENT,
+  // Opaque result on (dark, muted) color profile.
+  RESULT_DARK_MUTED_OPAQUE,
+  // Transparent result on (normal, muted) color profile.
+  RESULT_NORMAL_MUTED_TRANSPARENT,
+  // Opaque result on (normal, muted) color profile.
+  RESULT_NORMAL_MUTED_OPAQUE,
+  // Transparent result on (light, muted) color profile.
+  RESULT_LIGHT_MUTED_TRANSPARENT,
+  // Opaque result on (light, muted) color profile.
+  RESULT_LIGHT_MUTED_OPAQUE,
+
+  NUM_COLOR_EXTRACTION_RESULTS,
+};
+
+}  // namespace ash
+
+#endif  // ASH_WALLPAPER_WALLPAPER_UTILS_WALLPAPER_COLOR_EXTRACTION_RESULT_H_
\ No newline at end of file
diff --git a/ash/wallpaper/wallpaper_utils/wallpaper_decoder.cc b/ash/wallpaper/wallpaper_utils/wallpaper_decoder.cc
new file mode 100644
index 0000000..24f5a91
--- /dev/null
+++ b/ash/wallpaper/wallpaper_utils/wallpaper_decoder.cc
@@ -0,0 +1,49 @@
+// Copyright 2018 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 "ash/wallpaper/wallpaper_utils/wallpaper_decoder.h"
+
+#include "ash/shell.h"
+#include "ash/shell_delegate.h"
+#include "ipc/ipc_channel.h"
+#include "services/data_decoder/public/cpp/decode_image.h"
+
+namespace ash {
+namespace {
+
+const int64_t kMaxImageSizeInBytes =
+    static_cast<int64_t>(IPC::Channel::kMaximumMessageSize);
+
+void ConvertToImageSkia(OnWallpaperDecoded callback, const SkBitmap& image) {
+  if (image.isNull()) {
+    std::move(callback).Run(gfx::ImageSkia());
+    return;
+  }
+  SkBitmap final_image = image;
+  final_image.setImmutable();
+  gfx::ImageSkia image_skia = gfx::ImageSkia::CreateFrom1xBitmap(final_image);
+  image_skia.MakeThreadSafe();
+
+  std::move(callback).Run(image_skia);
+}
+
+}  // namespace
+
+void DecodeWallpaper(const std::string& image_data,
+                     OnWallpaperDecoded callback) {
+  // The connector for the mojo service manager is null in unit tests.
+  if (!Shell::Get()->shell_delegate()->GetShellConnector()) {
+    std::move(callback).Run(gfx::ImageSkia());
+    return;
+  }
+  std::vector<uint8_t> image_bytes(image_data.begin(), image_data.end());
+  data_decoder::DecodeImage(
+      Shell::Get()->shell_delegate()->GetShellConnector(),
+      std::move(image_bytes), data_decoder::mojom::ImageCodec::ROBUST_JPEG,
+      false /* shrink_to_fit */, kMaxImageSizeInBytes,
+      gfx::Size() /* desired_image_frame_size */,
+      base::BindOnce(&ConvertToImageSkia, std::move(callback)));
+}
+
+}  // namespace ash
\ No newline at end of file
diff --git a/ash/wallpaper/wallpaper_utils/wallpaper_decoder.h b/ash/wallpaper/wallpaper_utils/wallpaper_decoder.h
new file mode 100644
index 0000000..ba5ac494
--- /dev/null
+++ b/ash/wallpaper/wallpaper_utils/wallpaper_decoder.h
@@ -0,0 +1,27 @@
+// Copyright 2018 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 ASH_WALLPAPER_WALLPAPER_UTILS_WALLPAPER_DECODER_H_
+#define ASH_WALLPAPER_WALLPAPER_UTILS_WALLPAPER_DECODER_H_
+
+#include "base/callback_forward.h"
+#include "base/memory/scoped_refptr.h"
+
+namespace gfx {
+class ImageSkia;
+}
+
+namespace ash {
+
+using OnWallpaperDecoded =
+    base::OnceCallback<void(const gfx::ImageSkia& image)>;
+
+// Do an async wallpaper decode; |on_decoded| is run on the calling thread when
+// the decode has finished.
+void DecodeWallpaper(const std::string& image_data,
+                     OnWallpaperDecoded callback);
+
+}  // namespace ash
+
+#endif  // ASH_WALLPAPER_WALLPAPER_UTILS_WALLPAPER_DECODER_H_
\ No newline at end of file
diff --git a/ash/wallpaper/wallpaper_utils/wallpaper_resizer.cc b/ash/wallpaper/wallpaper_utils/wallpaper_resizer.cc
new file mode 100644
index 0000000..85394d0d
--- /dev/null
+++ b/ash/wallpaper/wallpaper_utils/wallpaper_resizer.cc
@@ -0,0 +1,154 @@
+// Copyright 2018 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 "ash/wallpaper/wallpaper_utils/wallpaper_resizer.h"
+
+#include <utility>
+
+#include "ash/wallpaper/wallpaper_utils/wallpaper_resizer_observer.h"
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/task_runner.h"
+#include "third_party/skia/include/core/SkImage.h"
+#include "ui/gfx/geometry/safe_integer_conversions.h"
+#include "ui/gfx/image/image_skia_rep.h"
+#include "ui/gfx/skia_util.h"
+
+namespace ash {
+namespace {
+
+// Resizes |image| to |target_size| using |layout| and stores the
+// resulting bitmap at |resized_bitmap_out|.
+//
+// NOTE: |image| is intentionally a copy to ensure it exists for the duration of
+// the function.
+void Resize(const gfx::ImageSkia image,
+            const gfx::Size& target_size,
+            WallpaperLayout layout,
+            SkBitmap* resized_bitmap_out,
+            base::TaskRunner* task_runner) {
+  DCHECK(task_runner->RunsTasksInCurrentSequence());
+
+  SkBitmap orig_bitmap = *image.bitmap();
+  SkBitmap new_bitmap = orig_bitmap;
+
+  const int orig_width = orig_bitmap.width();
+  const int orig_height = orig_bitmap.height();
+  const int new_width = target_size.width();
+  const int new_height = target_size.height();
+
+  if (orig_width > new_width || orig_height > new_height) {
+    gfx::Rect wallpaper_rect(0, 0, orig_width, orig_height);
+    gfx::Size cropped_size = gfx::Size(std::min(new_width, orig_width),
+                                       std::min(new_height, orig_height));
+    switch (layout) {
+      case WALLPAPER_LAYOUT_CENTER:
+        wallpaper_rect.ClampToCenteredSize(cropped_size);
+        orig_bitmap.extractSubset(&new_bitmap,
+                                  gfx::RectToSkIRect(wallpaper_rect));
+        break;
+      case WALLPAPER_LAYOUT_TILE:
+        wallpaper_rect.set_size(cropped_size);
+        orig_bitmap.extractSubset(&new_bitmap,
+                                  gfx::RectToSkIRect(wallpaper_rect));
+        break;
+      case WALLPAPER_LAYOUT_STRETCH:
+        new_bitmap = skia::ImageOperations::Resize(
+            orig_bitmap, skia::ImageOperations::RESIZE_LANCZOS3, new_width,
+            new_height);
+        break;
+      case WALLPAPER_LAYOUT_CENTER_CROPPED:
+        if (orig_width > new_width && orig_height > new_height) {
+          // The dimension with the smallest ratio must be cropped, the other
+          // one is preserved. Both are set in gfx::Size cropped_size.
+          double horizontal_ratio =
+              static_cast<double>(new_width) / static_cast<double>(orig_width);
+          double vertical_ratio = static_cast<double>(new_height) /
+                                  static_cast<double>(orig_height);
+
+          if (vertical_ratio > horizontal_ratio) {
+            cropped_size = gfx::Size(
+                gfx::ToRoundedInt(new_width / vertical_ratio), orig_height);
+          } else {
+            cropped_size = gfx::Size(
+                orig_width, gfx::ToRoundedInt(new_height / horizontal_ratio));
+          }
+          wallpaper_rect.ClampToCenteredSize(cropped_size);
+          SkBitmap sub_image;
+          orig_bitmap.extractSubset(&sub_image,
+                                    gfx::RectToSkIRect(wallpaper_rect));
+          new_bitmap = skia::ImageOperations::Resize(
+              sub_image, skia::ImageOperations::RESIZE_LANCZOS3, new_width,
+              new_height);
+        }
+        break;
+      case NUM_WALLPAPER_LAYOUT:
+        NOTREACHED();
+        break;
+    }
+  }
+
+  *resized_bitmap_out = new_bitmap;
+  resized_bitmap_out->setImmutable();
+}
+
+}  // namespace
+
+// static
+uint32_t WallpaperResizer::GetImageId(const gfx::ImageSkia& image) {
+  const gfx::ImageSkiaRep& image_rep = image.GetRepresentation(1.0f);
+  return image_rep.is_null() ? 0 : image_rep.sk_bitmap().getGenerationID();
+}
+
+WallpaperResizer::WallpaperResizer(const gfx::ImageSkia& image,
+                                   const gfx::Size& target_size,
+                                   const WallpaperInfo& wallpaper_info,
+                                   scoped_refptr<base::TaskRunner> task_runner)
+    : image_(image),
+      original_image_id_(GetImageId(image_)),
+      target_size_(target_size),
+      wallpaper_info_(wallpaper_info),
+      task_runner_(std::move(task_runner)),
+      weak_ptr_factory_(this) {
+  image_.MakeThreadSafe();
+}
+
+WallpaperResizer::~WallpaperResizer() {}
+
+void WallpaperResizer::StartResize() {
+  start_calculation_time_ = base::TimeTicks::Now();
+
+  SkBitmap* resized_bitmap = new SkBitmap;
+  if (!task_runner_->PostTaskAndReply(
+          FROM_HERE,
+          base::Bind(&Resize, image_, target_size_, wallpaper_info_.layout,
+                     resized_bitmap, base::RetainedRef(task_runner_)),
+          base::Bind(&WallpaperResizer::OnResizeFinished,
+                     weak_ptr_factory_.GetWeakPtr(),
+                     base::Owned(resized_bitmap)))) {
+    LOG(WARNING) << "PostSequencedWorkerTask failed. "
+                 << "Wallpaper may not be resized.";
+  }
+}
+
+void WallpaperResizer::AddObserver(WallpaperResizerObserver* observer) {
+  observers_.AddObserver(observer);
+}
+
+void WallpaperResizer::RemoveObserver(WallpaperResizerObserver* observer) {
+  observers_.RemoveObserver(observer);
+}
+
+void WallpaperResizer::OnResizeFinished(SkBitmap* resized_bitmap) {
+  image_ = gfx::ImageSkia::CreateFrom1xBitmap(*resized_bitmap);
+  UMA_HISTOGRAM_TIMES("Ash.Wallpaper.TimeSpentResizing",
+                      base::TimeTicks::Now() - start_calculation_time_);
+
+  for (auto& observer : observers_)
+    observer.OnWallpaperResized();
+}
+
+}  // namespace ash
diff --git a/ash/wallpaper/wallpaper_utils/wallpaper_resizer.h b/ash/wallpaper/wallpaper_utils/wallpaper_resizer.h
new file mode 100644
index 0000000..a8328bf
--- /dev/null
+++ b/ash/wallpaper/wallpaper_utils/wallpaper_resizer.h
@@ -0,0 +1,91 @@
+// Copyright 2018 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 ASH_WALLPAPER_WALLPAPER_UTILS_WALLPAPER_RESIZER_H_
+#define ASH_WALLPAPER_WALLPAPER_UTILS_WALLPAPER_RESIZER_H_
+
+#include <stdint.h>
+
+#include "ash/ash_export.h"
+#include "ash/wallpaper/wallpaper_info.h"
+#include "ash/wallpaper/wallpaper_utils/wallpaper_resizer_observer.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
+#include "base/time/time.h"
+#include "skia/ext/image_operations.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/image/image_skia.h"
+
+namespace base {
+class TaskRunner;
+}
+
+namespace ash {
+
+class WallpaperResizerObserver;
+
+// Stores the current wallpaper data and resize it to |target_size| if needed.
+class ASH_EXPORT WallpaperResizer {
+ public:
+  // Returns a unique identifier corresponding to |image|, suitable for
+  // comparison against the value returned by original_image_id(). If the image
+  // is modified, its ID will change.
+  static uint32_t GetImageId(const gfx::ImageSkia& image);
+
+  WallpaperResizer(const gfx::ImageSkia& image,
+                   const gfx::Size& target_size,
+                   const WallpaperInfo& info,
+                   scoped_refptr<base::TaskRunner> task_runner);
+
+  ~WallpaperResizer();
+
+  const gfx::ImageSkia& image() const { return image_; }
+  uint32_t original_image_id() const { return original_image_id_; }
+  const WallpaperInfo& wallpaper_info() const { return wallpaper_info_; }
+
+  // Called on the UI thread to run Resize() on the task runner and post an
+  // OnResizeFinished() task back to the UI thread on completion.
+  void StartResize();
+
+  // Add/Remove observers.
+  void AddObserver(WallpaperResizerObserver* observer);
+  void RemoveObserver(WallpaperResizerObserver* observer);
+
+ private:
+  // Copies |resized_bitmap| to |image_| and notifies observers after Resize()
+  // has finished running.
+  void OnResizeFinished(SkBitmap* resized_bitmap);
+
+  base::ObserverList<WallpaperResizerObserver> observers_;
+
+  // Image that should currently be used for wallpaper. It initially
+  // contains the original image and is updated to contain the resized
+  // image by OnResizeFinished().
+  gfx::ImageSkia image_;
+
+  // Unique identifier corresponding to the original (i.e. pre-resize) |image_|.
+  uint32_t original_image_id_;
+
+  gfx::Size target_size_;
+
+  const WallpaperInfo wallpaper_info_;
+
+  // The time that StartResize() was last called. Used for recording timing
+  // metrics.
+  base::TimeTicks start_calculation_time_;
+
+  scoped_refptr<base::TaskRunner> task_runner_;
+
+  base::WeakPtrFactory<WallpaperResizer> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(WallpaperResizer);
+};
+
+}  // namespace ash
+
+#endif  // ASH_WALLPAPER_WALLPAPER_UTILS_WALLPAPER_RESIZER_H_
diff --git a/ash/wallpaper/wallpaper_utils/wallpaper_resizer_observer.h b/ash/wallpaper/wallpaper_utils/wallpaper_resizer_observer.h
new file mode 100644
index 0000000..81ea731
--- /dev/null
+++ b/ash/wallpaper/wallpaper_utils/wallpaper_resizer_observer.h
@@ -0,0 +1,21 @@
+// Copyright 2018 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 ASH_WALLPAPER_WALLPAPER_UTILS_WALLPAPER_RESIZER_OBSERVER_H_
+#define ASH_WALLPAPER_WALLPAPER_UTILS_WALLPAPER_RESIZER_OBSERVER_H_
+
+namespace ash {
+
+class WallpaperResizerObserver {
+ public:
+  // Invoked when the wallpaper is resized.
+  virtual void OnWallpaperResized() = 0;
+
+ protected:
+  virtual ~WallpaperResizerObserver() {}
+};
+
+}  // namespace ash
+
+#endif  // ASH_WALLPAPER_WALLPAPER_UTILS_WALLPAPER_RESIZER_OBSERVER_H_
diff --git a/ash/wallpaper/wallpaper_utils/wallpaper_resizer_unittest.cc b/ash/wallpaper/wallpaper_utils/wallpaper_resizer_unittest.cc
new file mode 100644
index 0000000..da6689b
--- /dev/null
+++ b/ash/wallpaper/wallpaper_utils/wallpaper_resizer_unittest.cc
@@ -0,0 +1,170 @@
+// Copyright 2018 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 "ash/wallpaper/wallpaper_utils/wallpaper_resizer.h"
+
+#include <stdint.h>
+
+#include <memory>
+
+#include "ash/public/cpp/wallpaper_types.h"
+#include "ash/wallpaper/wallpaper_utils/wallpaper_resizer_observer.h"
+#include "base/macros.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/threading/thread.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/image/image_skia_rep.h"
+
+namespace ash {
+namespace {
+
+const int kTestImageWidth = 5;
+const int kTestImageHeight = 2;
+const int kTargetWidth = 1;
+const int kTargetHeight = 1;
+const uint32_t kExpectedCenter = 0x02020202u;
+const uint32_t kExpectedCenterCropped = 0x03030303u;
+const uint32_t kExpectedStretch = 0x04040404u;
+const uint32_t kExpectedTile = 0;
+
+gfx::ImageSkia CreateTestImage(const gfx::Size& size) {
+  SkBitmap src;
+  int w = size.width();
+  int h = size.height();
+  src.allocN32Pixels(w, h);
+
+  // Fill bitmap with data.
+  for (int y = 0; y < h; ++y) {
+    for (int x = 0; x < w; ++x) {
+      const uint8_t component = static_cast<uint8_t>(y * w + x);
+      const SkColor pixel =
+          SkColorSetARGB(component, component, component, component);
+      *(src.getAddr32(x, y)) = pixel;
+    }
+  }
+
+  gfx::ImageSkia image = gfx::ImageSkia::CreateFrom1xBitmap(src);
+  return image;
+}
+
+bool IsColor(const gfx::ImageSkia& image, const uint32_t expect) {
+  EXPECT_EQ(image.width(), kTargetWidth);
+  EXPECT_EQ(image.height(), kTargetHeight);
+  return *image.bitmap()->getAddr32(0, 0) == expect;
+}
+
+}  // namespace
+
+namespace wallpaper {
+
+class WallpaperResizerTest : public testing::Test,
+                             public WallpaperResizerObserver {
+ public:
+  WallpaperResizerTest() : worker_thread_("WallpaperResizerTest") {}
+  ~WallpaperResizerTest() override {}
+
+  void SetUp() override { ASSERT_TRUE(worker_thread_.Start()); }
+
+  gfx::ImageSkia Resize(const gfx::ImageSkia& image,
+                        const gfx::Size& target_size,
+                        WallpaperLayout layout) {
+    std::unique_ptr<WallpaperResizer> resizer;
+    resizer.reset(new WallpaperResizer(
+        image, target_size,
+        WallpaperInfo("", layout, DEFAULT, base::Time::Now().LocalMidnight()),
+        task_runner()));
+    resizer->AddObserver(this);
+    resizer->StartResize();
+    WaitForResize();
+    resizer->RemoveObserver(this);
+    return resizer->image();
+  }
+
+  scoped_refptr<base::TaskRunner> task_runner() {
+    return worker_thread_.task_runner();
+  }
+
+  void WaitForResize() {
+    active_runloop_ = std::make_unique<base::RunLoop>();
+    active_runloop_->Run();
+  }
+
+  void OnWallpaperResized() override { active_runloop_->Quit(); }
+
+ private:
+  base::MessageLoop message_loop_;
+  std::unique_ptr<base::RunLoop> active_runloop_;
+  base::Thread worker_thread_;
+
+  DISALLOW_COPY_AND_ASSIGN(WallpaperResizerTest);
+};
+
+TEST_F(WallpaperResizerTest, BasicResize) {
+  // Keeps in sync with WallpaperLayout enum.
+  WallpaperLayout layouts[4] = {
+      WALLPAPER_LAYOUT_CENTER, WALLPAPER_LAYOUT_CENTER_CROPPED,
+      WALLPAPER_LAYOUT_STRETCH, WALLPAPER_LAYOUT_TILE,
+  };
+  const int length = arraysize(layouts);
+
+  for (int i = 0; i < length; i++) {
+    WallpaperLayout layout = layouts[i];
+    gfx::ImageSkia small_image(gfx::ImageSkiaRep(gfx::Size(10, 20), 1.0f));
+
+    gfx::ImageSkia resized_small =
+        Resize(small_image, gfx::Size(800, 600), layout);
+    EXPECT_EQ(10, resized_small.width());
+    EXPECT_EQ(20, resized_small.height());
+
+    gfx::ImageSkia large_image(gfx::ImageSkiaRep(gfx::Size(1000, 1000), 1.0f));
+    gfx::ImageSkia resized_large =
+        Resize(large_image, gfx::Size(800, 600), layout);
+    EXPECT_EQ(800, resized_large.width());
+    EXPECT_EQ(600, resized_large.height());
+  }
+}
+
+// Test for crbug.com/244629. "CENTER_CROPPED generates the same image as
+// STRETCH layout"
+TEST_F(WallpaperResizerTest, AllLayoutDifferent) {
+  gfx::ImageSkia image =
+      CreateTestImage(gfx::Size(kTestImageWidth, kTestImageHeight));
+
+  gfx::Size target_size = gfx::Size(kTargetWidth, kTargetHeight);
+  gfx::ImageSkia center = Resize(image, target_size, WALLPAPER_LAYOUT_CENTER);
+
+  gfx::ImageSkia center_cropped =
+      Resize(image, target_size, WALLPAPER_LAYOUT_CENTER_CROPPED);
+
+  gfx::ImageSkia stretch = Resize(image, target_size, WALLPAPER_LAYOUT_STRETCH);
+
+  gfx::ImageSkia tile = Resize(image, target_size, WALLPAPER_LAYOUT_TILE);
+
+  EXPECT_TRUE(IsColor(center, kExpectedCenter));
+  EXPECT_TRUE(IsColor(center_cropped, kExpectedCenterCropped));
+  EXPECT_TRUE(IsColor(stretch, kExpectedStretch));
+  EXPECT_TRUE(IsColor(tile, kExpectedTile));
+}
+
+TEST_F(WallpaperResizerTest, ImageId) {
+  gfx::ImageSkia image =
+      CreateTestImage(gfx::Size(kTestImageWidth, kTestImageHeight));
+
+  // Create a WallpaperResizer and check that it reports an original image ID
+  // both pre- and post-resize that matches the ID returned by GetImageId().
+  WallpaperResizer resizer(image, gfx::Size(10, 20),
+                           WallpaperInfo("", WALLPAPER_LAYOUT_STRETCH, DEFAULT,
+                                         base::Time::Now().LocalMidnight()),
+                           task_runner());
+  EXPECT_EQ(WallpaperResizer::GetImageId(image), resizer.original_image_id());
+  resizer.AddObserver(this);
+  resizer.StartResize();
+  WaitForResize();
+  resizer.RemoveObserver(this);
+  EXPECT_EQ(WallpaperResizer::GetImageId(image), resizer.original_image_id());
+}
+
+}  // namespace wallpaper
+}  // namespace ash
diff --git a/ash/wallpaper/wallpaper_view.cc b/ash/wallpaper/wallpaper_view.cc
index ae4e5a08..5366b00 100644
--- a/ash/wallpaper/wallpaper_view.cc
+++ b/ash/wallpaper/wallpaper_view.cc
@@ -146,10 +146,10 @@
   // Scale the image while maintaining the aspect ratio, cropping as necessary
   // to fill the wallpaper. Ideally the image should be larger than the largest
   // display supported, if not we will scale and center it if the layout is
-  // wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED.
+  // WALLPAPER_LAYOUT_CENTER_CROPPED.
   WallpaperController* controller = Shell::Get()->wallpaper_controller();
   gfx::ImageSkia wallpaper = controller->GetWallpaper();
-  wallpaper::WallpaperLayout layout = controller->GetWallpaperLayout();
+  WallpaperLayout layout = controller->GetWallpaperLayout();
 
   // Wallpapers with png format could be partially transparent. Fill the canvas
   // with black to make it opaque before painting the wallpaper.
@@ -165,7 +165,7 @@
   }
 
   switch (layout) {
-    case wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED: {
+    case WALLPAPER_LAYOUT_CENTER_CROPPED: {
       // The dimension with the smallest ratio must be cropped, the other one
       // is preserved. Both are set in gfx::Size cropped_size.
       double horizontal_ratio =
@@ -193,19 +193,19 @@
           width(), height(), true, flags);
       break;
     }
-    case wallpaper::WALLPAPER_LAYOUT_TILE: {
+    case WALLPAPER_LAYOUT_TILE: {
       canvas->TileImageInt(wallpaper, 0, 0, 0, 0, width(), height(), 1.0f,
                            &flags);
       break;
     }
-    case wallpaper::WALLPAPER_LAYOUT_STRETCH: {
+    case WALLPAPER_LAYOUT_STRETCH: {
       // This is generally not recommended as it may show artifacts.
       canvas->DrawImageInt(wallpaper, 0, 0, wallpaper.width(),
                            wallpaper.height(), 0, 0, width(), height(), true,
                            flags);
       break;
     }
-    case wallpaper::WALLPAPER_LAYOUT_CENTER: {
+    case WALLPAPER_LAYOUT_CENTER: {
       float image_scale = canvas->image_scale();
       gfx::Rect wallpaper_rect(0, 0, wallpaper.width() / image_scale,
                                wallpaper.height() / image_scale);
diff --git a/ash/wm/default_state.cc b/ash/wm/default_state.cc
index 95efd87..5f62f2a1 100644
--- a/ash/wm/default_state.cc
+++ b/ash/wm/default_state.cc
@@ -107,6 +107,16 @@
                                WindowState::State* state_in_previous_mode) {
   DCHECK_EQ(stored_window_state_, window_state);
 
+  // If previous state is unminimized but window state is minimized, sync window
+  // state to unminimized.
+  if (window_state->IsMinimized() &&
+      !IsMinimizedWindowStateType(state_in_previous_mode->GetType())) {
+    aura::Window* window = window_state->window();
+    window->SetProperty(
+        aura::client::kShowStateKey,
+        window->GetProperty(aura::client::kPreMinimizedShowStateKey));
+  }
+
   ReenterToCurrentState(window_state, state_in_previous_mode);
 
   // If the display has changed while in the another mode,
diff --git a/ash/wm/non_client_frame_controller.cc b/ash/wm/non_client_frame_controller.cc
index 911c17c8..861188a 100644
--- a/ash/wm/non_client_frame_controller.cc
+++ b/ash/wm/non_client_frame_controller.cc
@@ -334,14 +334,12 @@
 // static
 gfx::Insets NonClientFrameController::GetPreferredClientAreaInsets() {
   return gfx::Insets(
-      GetAshLayoutSize(AshLayoutSize::NON_BROWSER_CAPTION_BUTTON).height(), 0,
-      0, 0);
+      GetAshLayoutSize(AshLayoutSize::kNonBrowserCaption).height(), 0, 0, 0);
 }
 
 // static
 int NonClientFrameController::GetMaxTitleBarButtonWidth() {
-  return GetAshLayoutSize(AshLayoutSize::NON_BROWSER_CAPTION_BUTTON).width() *
-         3;
+  return GetAshLayoutSize(AshLayoutSize::kNonBrowserCaption).width() * 3;
 }
 
 void NonClientFrameController::SetClientArea(
diff --git a/ash/wm/non_client_frame_controller_unittest.cc b/ash/wm/non_client_frame_controller_unittest.cc
index b096e41..beabbee 100644
--- a/ash/wm/non_client_frame_controller_unittest.cc
+++ b/ash/wm/non_client_frame_controller_unittest.cc
@@ -117,7 +117,7 @@
   ASSERT_TRUE(widget);
 
   const int caption_height =
-      GetAshLayoutSize(AshLayoutSize::NON_BROWSER_CAPTION_BUTTON).height();
+      GetAshLayoutSize(AshLayoutSize::kNonBrowserCaption).height();
   const gfx::Size tile_size = cc::LayerTreeSettings().default_tile_size;
   const int tile_width = tile_size.width();
   const int tile_height = tile_size.height();
diff --git a/ash/wm/overview/overview_animation_type.h b/ash/wm/overview/overview_animation_type.h
index cd60da0..0b66f8f 100644
--- a/ash/wm/overview/overview_animation_type.h
+++ b/ash/wm/overview/overview_animation_type.h
@@ -30,9 +30,6 @@
   // Used to animate hiding of a window that is closed while overview mode is
   // active.
   OVERVIEW_ANIMATION_CLOSE_SELECTOR_ITEM,
-  // Used to animate scaling up of a window that is about to get dragged while
-  // overview mode is active.
-  OVERVIEW_ANIMATION_DRAGGING_SELECTOR_ITEM,
 };
 
 }  // namespace ash
diff --git a/ash/wm/overview/overview_window_drag_controller.cc b/ash/wm/overview/overview_window_drag_controller.cc
index 6956ee5..0e259259e 100644
--- a/ash/wm/overview/overview_window_drag_controller.cc
+++ b/ash/wm/overview/overview_window_drag_controller.cc
@@ -303,8 +303,9 @@
 
   // |item_| will be deleted after RemoveWindowSelectorItem().
   aura::Window* window = item_->GetWindow();
+  const gfx::Rect item_bounds = item_->target_bounds();
   window_selector_->RemoveWindowSelectorItem(item_);
-  split_view_controller_->SnapWindow(window, snap_position);
+  split_view_controller_->SnapWindow(window, snap_position, item_bounds);
   item_ = nullptr;
 }
 
diff --git a/ash/wm/overview/scoped_overview_animation_settings.cc b/ash/wm/overview/scoped_overview_animation_settings.cc
index 6d8d5f5..ce74e99d 100644
--- a/ash/wm/overview/scoped_overview_animation_settings.cc
+++ b/ash/wm/overview/scoped_overview_animation_settings.cc
@@ -53,8 +53,6 @@
       return base::TimeDelta::FromMilliseconds(kCloseScaleMilliseconds);
     case OVERVIEW_ANIMATION_CLOSE_SELECTOR_ITEM:
       return base::TimeDelta::FromMilliseconds(kCloseFadeOutMilliseconds);
-    case OVERVIEW_ANIMATION_DRAGGING_SELECTOR_ITEM:
-      return base::TimeDelta::FromMilliseconds(kTransitionMilliseconds);
   }
   NOTREACHED();
   return base::TimeDelta();
@@ -113,7 +111,6 @@
     OverviewAnimationType animation_type) {
   switch (animation_type) {
     case OVERVIEW_ANIMATION_NONE:
-    case OVERVIEW_ANIMATION_DRAGGING_SELECTOR_ITEM:
       return nullptr;
     case OVERVIEW_ANIMATION_ENTER_OVERVIEW_MODE_FADE_IN:
     case OVERVIEW_ANIMATION_ENTER_OVERVIEW_MODE_TABLET_FADE_IN:
@@ -164,7 +161,6 @@
       break;
     case OVERVIEW_ANIMATION_CLOSING_SELECTOR_ITEM:
     case OVERVIEW_ANIMATION_CLOSE_SELECTOR_ITEM:
-    case OVERVIEW_ANIMATION_DRAGGING_SELECTOR_ITEM:
       animation_settings_->SetPreemptionStrategy(
           ui::LayerAnimator::ENQUEUE_NEW_ANIMATION);
       animation_settings_->SetTweenType(gfx::Tween::EASE_OUT);
diff --git a/ash/wm/overview/window_selector_controller.cc b/ash/wm/overview/window_selector_controller.cc
index 9513def..86ec056 100644
--- a/ash/wm/overview/window_selector_controller.cc
+++ b/ash/wm/overview/window_selector_controller.cc
@@ -231,8 +231,10 @@
   // The transform will be reset later after the window is snapped.
   item_to_snap->RestoreWindow(/*reset_transform=*/false);
   aura::Window* window = item_to_snap->GetWindow();
+  const gfx::Rect item_bounds = item_to_snap->target_bounds();
   window_selector_->RemoveWindowSelectorItem(item_to_snap);
-  split_view_controller->SnapWindow(window, SplitViewController::LEFT);
+  split_view_controller->SnapWindow(window, SplitViewController::LEFT,
+                                    item_bounds);
   window_selector_->SetBoundsForWindowGridsInScreen(
       split_view_controller->GetSnappedWindowBoundsInScreen(
           window, SplitViewController::RIGHT));
diff --git a/ash/wm/overview/window_selector_item.cc b/ash/wm/overview/window_selector_item.cc
index bbaa558..5c755977 100644
--- a/ash/wm/overview/window_selector_item.cc
+++ b/ash/wm/overview/window_selector_item.cc
@@ -299,6 +299,7 @@
   const int length = IsNewOverviewUi() ? kHeaderHeightDp : kOldHeaderHeightDp;
   SetMinimumImageSize(gfx::Size(length, length));
   SetAccessibleName(l10n_util::GetStringUTF16(IDS_APP_ACCNAME_CLOSE));
+  SetTooltipText(l10n_util::GetStringUTF16(IDS_APP_ACCNAME_CLOSE));
 }
 
 WindowSelectorItem::OverviewCloseButton::~OverviewCloseButton() = default;
@@ -1359,7 +1360,7 @@
   scaled_bounds.Inset(-target_bounds_.width() * kDragWindowScale,
                       -target_bounds_.height() * kDragWindowScale);
   OverviewAnimationType animation_type =
-      OverviewAnimationType::OVERVIEW_ANIMATION_DRAGGING_SELECTOR_ITEM;
+      OverviewAnimationType::OVERVIEW_ANIMATION_NONE;
   SetBounds(scaled_bounds, animation_type);
 
   aura::Window* widget_window = item_widget_->GetNativeWindow();
diff --git a/ash/wm/overview/window_selector_unittest.cc b/ash/wm/overview/window_selector_unittest.cc
index b73a12f4..0cfe4d2 100644
--- a/ash/wm/overview/window_selector_unittest.cc
+++ b/ash/wm/overview/window_selector_unittest.cc
@@ -2761,18 +2761,35 @@
   EXPECT_TRUE(HasMaskForItem(item1));
   EXPECT_TRUE(HasMaskForItem(item2));
 
-  // Drag the first window. Verify that the mask disappears.
+  ui::ScopedAnimationDurationScaleMode test_duration_mode(
+      ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
+
+  // Drag the first window. Verify that the mask still exists for both items as
+  // we do not apply any animation to the window items at this point.
   const gfx::Point start_drag = item1->target_bounds().CenterPoint();
   GetEventGenerator().MoveMouseTo(start_drag);
   GetEventGenerator().PressLeftButton();
-  EXPECT_FALSE(HasMaskForItem(item1));
+  EXPECT_FALSE(window1->layer()->GetAnimator()->is_animating());
+  EXPECT_FALSE(window2->layer()->GetAnimator()->is_animating());
+  RunAllPendingInMessageLoop();
+  EXPECT_TRUE(HasMaskForItem(item1));
   EXPECT_TRUE(HasMaskForItem(item2));
 
   // Drag to origin and then back to the start to avoid activating the window or
-  // entering splitview. Verify that the mask is visible on both items.
+  // entering splitview. Verify that the mask is invisible on both items during
+  // animation.
   GetEventGenerator().MoveMouseTo(gfx::Point());
   GetEventGenerator().MoveMouseTo(start_drag);
   GetEventGenerator().ReleaseLeftButton();
+  EXPECT_TRUE(window1->layer()->GetAnimator()->is_animating());
+  EXPECT_TRUE(window2->layer()->GetAnimator()->is_animating());
+  EXPECT_FALSE(HasMaskForItem(item1));
+  EXPECT_FALSE(HasMaskForItem(item2));
+
+  // Verify that the mask is visble again after animation is finished.
+  window1->layer()->GetAnimator()->StopAnimating();
+  window2->layer()->GetAnimator()->StopAnimating();
+  RunAllPendingInMessageLoop();
   EXPECT_TRUE(HasMaskForItem(item1));
   EXPECT_TRUE(HasMaskForItem(item2));
 
diff --git a/ash/wm/splitview/split_view_controller.cc b/ash/wm/splitview/split_view_controller.cc
index cc80014..fb9d5ca1 100644
--- a/ash/wm/splitview/split_view_controller.cc
+++ b/ash/wm/splitview/split_view_controller.cc
@@ -17,11 +17,11 @@
 #include "ash/system/toast/toast_data.h"
 #include "ash/system/toast/toast_manager.h"
 #include "ash/wm/mru_window_tracker.h"
-#include "ash/wm/overview/scoped_overview_animation_settings.h"
 #include "ash/wm/overview/window_grid.h"
 #include "ash/wm/overview/window_selector_controller.h"
 #include "ash/wm/overview/window_selector_item.h"
 #include "ash/wm/splitview/split_view_divider.h"
+#include "ash/wm/splitview/split_view_utils.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_transient_descendant_iterator.h"
@@ -192,6 +192,9 @@
 }
 
 OrientationLockType SplitViewController::GetCurrentScreenOrientation() const {
+  // ScreenOrientationController might be nullptr during shutdown.
+  if (!Shell::Get()->screen_orientation_controller())
+    return OrientationLockType::kAny;
   return Shell::Get()->screen_orientation_controller()->GetCurrentOrientation();
 }
 
@@ -204,7 +207,8 @@
 }
 
 void SplitViewController::SnapWindow(aura::Window* window,
-                                     SnapPosition snap_position) {
+                                     SnapPosition snap_position,
+                                     const gfx::Rect& window_item_bounds) {
   DCHECK(window && CanSnap(window));
   DCHECK_NE(snap_position, NONE);
 
@@ -237,6 +241,9 @@
   }
   StartObserving(window);
 
+  if (!window_item_bounds.IsEmpty())
+    overview_window_item_bounds_map_[window] = window_item_bounds;
+
   // Update the divider position and window bounds before snapping a new window.
   // Since the minimum size of |window| maybe larger than currently bounds in
   // |snap_position|.
@@ -474,6 +481,7 @@
   black_scrim_layer_.reset();
   default_snap_position_ = NONE;
   divider_position_ = -1;
+  overview_window_item_bounds_map_.clear();
 
   UpdateSplitViewStateAndNotifyObservers();
   base::RecordAction(base::UserMetricsAction("SplitView_EndSplitView"));
@@ -500,6 +508,9 @@
   DCHECK(window == left_window_ || window == right_window_);
   if (smooth_resize_window_ == window)
     smooth_resize_window_ = nullptr;
+  auto iter = overview_window_item_bounds_map_.find(window);
+  if (iter != overview_window_item_bounds_map_.end())
+    overview_window_item_bounds_map_.erase(iter);
   OnSnappedWindowMinimizedOrDestroyed(window);
 }
 
@@ -555,12 +566,28 @@
     return;
   }
 
+  // If the to-be-snapped window comes from the overview grid, get its overview
+  // window item bounds before trying to snap it.
+  gfx::Rect window_item_bounds;
+  if (Shell::Get()->window_selector_controller()->IsSelecting()) {
+    WindowSelector* window_selector =
+        Shell::Get()->window_selector_controller()->window_selector();
+    WindowGrid* current_grid = window_selector->GetGridWithRootWindow(
+        GetDefaultSnappedWindow()->GetRootWindow());
+    if (current_grid) {
+      WindowSelectorItem* item =
+          current_grid->GetWindowSelectorItemContaining(gained_active);
+      if (item) {
+        window_item_bounds = item->target_bounds();
+        window_selector->RemoveWindowSelectorItem(item);
+      }
+    }
+  }
+
   // Snap the window on the non-default side of the screen if split view mode
   // is active.
-  if (default_snap_position_ == LEFT)
-    SnapWindow(gained_active, SplitViewController::RIGHT);
-  else if (default_snap_position_ == RIGHT)
-    SnapWindow(gained_active, SplitViewController::LEFT);
+  SnapWindow(gained_active, (default_snap_position_ == LEFT) ? RIGHT : LEFT,
+             window_item_bounds);
 }
 
 void SplitViewController::OnOverviewModeStarting() {
@@ -602,11 +629,10 @@
     for (const auto& window_selector_item : windows) {
       aura::Window* window = window_selector_item->GetWindow();
       if (CanSnap(window) && window != GetDefaultSnappedWindow()) {
+        const gfx::Rect item_bounds = window_selector_item->target_bounds();
         window_selector->RemoveWindowSelectorItem(window_selector_item.get());
-        if (default_snap_position_ == LEFT)
-          SnapWindow(window, SplitViewController::RIGHT);
-        else if (default_snap_position_ == RIGHT)
-          SnapWindow(window, SplitViewController::LEFT);
+        SnapWindow(window, (default_snap_position_ == LEFT) ? RIGHT : LEFT,
+                   item_bounds);
         return;
       }
     }
@@ -1136,14 +1162,30 @@
     aura::Window* window) {
   DCHECK(window == left_window_ || window == right_window_);
 
-  // Restore the window's transform first if its transform is not identity. In
-  // this case the window must come from the overview window grid.
+  // If the snapped window comes from the overview window grid, calculate a good
+  // starting transform based on the overview window item's bounds.
+  gfx::Transform starting_transform;
+  auto iter = overview_window_item_bounds_map_.find(window);
+  if (iter != overview_window_item_bounds_map_.end()) {
+    const gfx::Rect item_bounds = iter->second;
+    overview_window_item_bounds_map_.erase(iter);
+
+    // Calculate the starting transform based on the window's expected snapped
+    // bounds and its window item bounds in overview.
+    const gfx::Rect snapped_bounds = GetSnappedWindowBoundsInScreen(
+        window, (window == left_window_) ? LEFT : RIGHT);
+    starting_transform = ScopedTransformOverviewWindow::GetTransformForRect(
+        snapped_bounds, item_bounds);
+  }
+
+  // Restore the window's transform first if it's not identity.
   if (!window->layer()->GetTargetTransform().IsIdentity()) {
     for (auto* window_iter : wm::GetTransientTreeIterator(window)) {
-      ScopedOverviewAnimationSettings animation_settings(
-          ash::OverviewAnimationType::OVERVIEW_ANIMATION_RESTORE_WINDOW,
-          window_iter);
-      window_iter->SetTransform(gfx::Transform());
+      if (!starting_transform.IsIdentity())
+        window_iter->SetTransform(starting_transform);
+      DoSplitviewTransformAnimation(window_iter->layer(),
+                                    SPLITVIEW_ANIMATION_RESTORE_OVERVIEW_WINDOW,
+                                    gfx::Transform(), nullptr);
     }
   }
   wm::ActivateWindow(window);
diff --git a/ash/wm/splitview/split_view_controller.h b/ash/wm/splitview/split_view_controller.h
index d3f51be..eb1fd0f 100644
--- a/ash/wm/splitview/split_view_controller.h
+++ b/ash/wm/splitview/split_view_controller.h
@@ -11,6 +11,7 @@
 #include "ash/shell_observer.h"
 #include "ash/wm/tablet_mode/tablet_mode_observer.h"
 #include "ash/wm/window_state_observer.h"
+#include "base/containers/flat_map.h"
 #include "base/macros.h"
 #include "base/observer_list.h"
 #include "base/time/time.h"
@@ -90,8 +91,12 @@
   // primary orientation.
   bool IsCurrentScreenOrientationPrimary() const;
 
-  // Snaps window to left/right.
-  void SnapWindow(aura::Window* window, SnapPosition snap_position);
+  // Snaps window to left/right. |window_item_bounds| is the bounds of the
+  // overview window item in overview. It's empty if the snapped window doesn't
+  // come from overview grid.
+  void SnapWindow(aura::Window* window,
+                  SnapPosition snap_position,
+                  const gfx::Rect& window_item_bounds = gfx::Rect());
 
   // Swaps the left and right windows. This will do nothing if one of the
   // windows is not snapped.
@@ -350,6 +355,10 @@
   // details.
   aura::Window* smooth_resize_window_ = nullptr;
 
+  // The map from a to-be-snapped window to its overview item's bounds if the
+  // window comes from the overview.
+  base::flat_map<aura::Window*, gfx::Rect> overview_window_item_bounds_map_;
+
   base::ObserverList<Observer> observers_;
   mojo::InterfacePtrSet<mojom::SplitViewObserver> mojo_observers_;
 
diff --git a/ash/wm/splitview/split_view_drag_indicators.cc b/ash/wm/splitview/split_view_drag_indicators.cc
index 0048040..2f1cc880 100644
--- a/ash/wm/splitview/split_view_drag_indicators.cc
+++ b/ash/wm/splitview/split_view_drag_indicators.cc
@@ -247,12 +247,13 @@
                   ? IDS_ASH_SPLIT_VIEW_CANNOT_SNAP
                   : IDS_ASH_SPLIT_VIEW_GUIDANCE));
           SplitviewAnimationType animation_type;
-          if (IsPreviewAreaState(previous_indicator_state_)) {
-            animation_type = SPLITVIEW_ANIMATION_TEXT_FADE_IN;
+          if (!show) {
+            animation_type = SPLITVIEW_ANIMATION_TEXT_FADE_OUT_WITH_HIGHLIGHT;
           } else {
             animation_type =
-                show ? SPLITVIEW_ANIMATION_TEXT_FADE_IN_WITH_HIGHLIGHT
-                     : SPLITVIEW_ANIMATION_TEXT_FADE_OUT_WITH_HIGHLIGHT;
+                IsPreviewAreaState(previous_indicator_state_)
+                    ? SPLITVIEW_ANIMATION_TEXT_FADE_IN_WITH_HIGHLIGHT
+                    : SPLITVIEW_ANIMATION_TEXT_FADE_IN;
           }
           DoSplitviewOpacityAnimation(view->layer(), animation_type);
         }
diff --git a/ash/wm/splitview/split_view_utils.cc b/ash/wm/splitview/split_view_utils.cc
index 6ffee79..d9db72f 100644
--- a/ash/wm/splitview/split_view_utils.cc
+++ b/ash/wm/splitview/split_view_utils.cc
@@ -29,15 +29,21 @@
 // The delay before the indicator labels start animating.
 constexpr base::TimeDelta kLabelAnimationDelayMs =
     base::TimeDelta::FromMilliseconds(167);
+// The time duration for the window transformation animations.
+constexpr base::TimeDelta kWindowTransformMs =
+    base::TimeDelta::FromMilliseconds(300);
 
 constexpr float kHighlightOpacity = 0.3f;
 constexpr float kPreviewAreaHighlightOpacity = 0.18f;
 
 // Gets the duration, tween type and delay before animation based on |type|.
-void GetAnimationValuesForType(SplitviewAnimationType type,
-                               base::TimeDelta* out_duration,
-                               gfx::Tween::Type* out_tween_type,
-                               base::TimeDelta* out_delay) {
+void GetAnimationValuesForType(
+    SplitviewAnimationType type,
+    base::TimeDelta* out_duration,
+    gfx::Tween::Type* out_tween_type,
+    ui::LayerAnimator::PreemptionStrategy* out_preemption_strategy,
+    base::TimeDelta* out_delay) {
+  *out_preemption_strategy = ui::LayerAnimator::IMMEDIATELY_SET_NEW_TARGET;
   switch (type) {
     case SPLITVIEW_ANIMATION_HIGHLIGHT_FADE_IN:
     case SPLITVIEW_ANIMATION_HIGHLIGHT_FADE_OUT:
@@ -71,20 +77,29 @@
       *out_duration = kOtherFadeInOutMs;
       *out_tween_type = gfx::Tween::LINEAR_OUT_SLOW_IN;
       return;
+    case SPLITVIEW_ANIMATION_RESTORE_OVERVIEW_WINDOW:
+      *out_duration = kWindowTransformMs;
+      *out_tween_type = gfx::Tween::EASE_OUT;
+      *out_preemption_strategy =
+          ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET;
+      return;
   }
 
   NOTREACHED();
 }
 
 // Helper function to apply animation values to |settings|.
-void ApplyAnimationSettings(ui::ScopedLayerAnimationSettings* settings,
-                            ui::LayerAnimator* animator,
-                            base::TimeDelta duration,
-                            gfx::Tween::Type tween,
-                            base::TimeDelta delay) {
+void ApplyAnimationSettings(
+    ui::ScopedLayerAnimationSettings* settings,
+    ui::LayerAnimator* animator,
+    base::TimeDelta duration,
+    gfx::Tween::Type tween,
+    ui::LayerAnimator::PreemptionStrategy preemption_strategy,
+    base::TimeDelta delay) {
   DCHECK_EQ(settings->GetAnimator(), animator);
   settings->SetTransitionDuration(duration);
   settings->SetTweenType(tween);
+  settings->SetPreemptionStrategy(preemption_strategy);
   if (!delay.is_zero()) {
     settings->SetPreemptionStrategy(
         ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
@@ -130,12 +145,15 @@
 
   base::TimeDelta duration;
   gfx::Tween::Type tween;
+  ui::LayerAnimator::PreemptionStrategy preemption_strategy;
   base::TimeDelta delay;
-  GetAnimationValuesForType(type, &duration, &tween, &delay);
+  GetAnimationValuesForType(type, &duration, &tween, &preemption_strategy,
+                            &delay);
 
   ui::LayerAnimator* animator = layer->GetAnimator();
   ui::ScopedLayerAnimationSettings settings(animator);
-  ApplyAnimationSettings(&settings, animator, duration, tween, delay);
+  ApplyAnimationSettings(&settings, animator, duration, tween,
+                         preemption_strategy, delay);
   layer->SetOpacity(target_opacity);
 }
 
@@ -150,6 +168,7 @@
     case SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_SLIDE_IN:
     case SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_SLIDE_OUT:
     case SPLITVIEW_ANIMATION_PREVIEW_AREA_SLIDE_IN_OUT:
+    case SPLITVIEW_ANIMATION_RESTORE_OVERVIEW_WINDOW:
     case SPLITVIEW_ANIMATION_TEXT_SLIDE_IN:
     case SPLITVIEW_ANIMATION_TEXT_SLIDE_OUT:
       break;
@@ -160,12 +179,15 @@
 
   base::TimeDelta duration;
   gfx::Tween::Type tween;
+  ui::LayerAnimator::PreemptionStrategy preemption_strategy;
   base::TimeDelta delay;
-  GetAnimationValuesForType(type, &duration, &tween, &delay);
+  GetAnimationValuesForType(type, &duration, &tween, &preemption_strategy,
+                            &delay);
 
   ui::LayerAnimator* animator = layer->GetAnimator();
   ui::ScopedLayerAnimationSettings settings(animator);
-  ApplyAnimationSettings(&settings, animator, duration, tween, delay);
+  ApplyAnimationSettings(&settings, animator, duration, tween,
+                         preemption_strategy, delay);
   if (observer)
     settings.AddObserver(observer);
   layer->SetTransform(target_transform);
diff --git a/ash/wm/splitview/split_view_utils.h b/ash/wm/splitview/split_view_utils.h
index ab44a78b..0cf04763 100644
--- a/ash/wm/splitview/split_view_utils.h
+++ b/ash/wm/splitview/split_view_utils.h
@@ -55,6 +55,8 @@
   // Used to slide in the text labels.
   SPLITVIEW_ANIMATION_TEXT_SLIDE_IN,
   SPLITVIEW_ANIMATION_TEXT_SLIDE_OUT,
+  // Used to apply window transform on the selector item after it gets snapped.
+  SPLITVIEW_ANIMATION_RESTORE_OVERVIEW_WINDOW,
 };
 
 // Animates |layer|'s opacity based on |type|.
diff --git a/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc b/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc
index 77e0ab1..ccad40a 100644
--- a/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc
+++ b/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc
@@ -931,6 +931,31 @@
   EXPECT_TRUE(window_state->IsMaximized());
 }
 
+// Tests unminimizing in tablet mode and then existing tablet mode should have
+// pre-minimized window show state.
+TEST_F(TabletModeWindowManagerTest, UnminimizeInTabletMode) {
+  // Tests restoring to maximized show state.
+  gfx::Rect rect(10, 10, 100, 100);
+  std::unique_ptr<aura::Window> window(
+      CreateWindow(aura::client::WINDOW_TYPE_NORMAL, rect));
+  wm::WindowState* window_state = wm::GetWindowState(window.get());
+  window_state->Maximize();
+  window_state->Minimize();
+  Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(true);
+  window_state->Unminimize();
+  Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(false);
+  EXPECT_TRUE(window_state->IsMaximized());
+
+  // Tests restoring to normal show state.
+  window_state->Restore();
+  EXPECT_EQ(gfx::Rect(10, 10, 100, 100), window->GetBoundsInScreen());
+  window_state->Minimize();
+  Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(true);
+  window_state->Unminimize();
+  Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(false);
+  EXPECT_EQ(gfx::Rect(10, 10, 100, 100), window->GetBoundsInScreen());
+}
+
 // Check that a full screen window remains full screen upon entering maximize
 // mode. Furthermore, checks that this window is not full screen upon exiting
 // tablet mode if it was un-full-screened while in tablet mode.
diff --git a/base/BUILD.gn b/base/BUILD.gn
index f6f871e..6f366789 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -322,7 +322,6 @@
     "deferred_sequenced_task_runner.h",
     "environment.cc",
     "environment.h",
-    "event_types.h",
     "export_template.h",
     "feature_list.cc",
     "feature_list.h",
@@ -563,6 +562,8 @@
     "message_loop/timer_slack.h",
     "metrics/bucket_ranges.cc",
     "metrics/bucket_ranges.h",
+    "metrics/dummy_histogram.cc",
+    "metrics/dummy_histogram.h",
     "metrics/field_trial.cc",
     "metrics/field_trial.h",
     "metrics/field_trial_param_associator.cc",
@@ -1420,11 +1421,19 @@
         "allocator/partition_allocator/oom.h",
         "allocator/partition_allocator/page_allocator.cc",
         "allocator/partition_allocator/page_allocator.h",
+        "allocator/partition_allocator/page_allocator_internal.h",
         "allocator/partition_allocator/partition_alloc.cc",
         "allocator/partition_allocator/partition_alloc.h",
         "allocator/partition_allocator/spin_lock.cc",
         "allocator/partition_allocator/spin_lock.h",
       ]
+      if (is_win) {
+        sources +=
+            [ "allocator/partition_allocator/page_allocator_internals_win.h" ]
+      } else if (is_posix) {
+        sources +=
+            [ "allocator/partition_allocator/page_allocator_internals_posix.h" ]
+      }
     }
   }
 
@@ -3020,3 +3029,12 @@
     "//base",
   ]
 }
+
+fuzzer_test("utf_string_conversions_fuzzer") {
+  sources = [
+    "strings/utf_string_conversions_fuzzer.cc",
+  ]
+  deps = [
+    "//base",
+  ]
+}
diff --git a/base/allocator/partition_allocator/address_space_randomization.h b/base/allocator/partition_allocator/address_space_randomization.h
index 8bea1f7d..d5d497d 100644
--- a/base/allocator/partition_allocator/address_space_randomization.h
+++ b/base/allocator/partition_allocator/address_space_randomization.h
@@ -29,113 +29,164 @@
   return AslrAddress((1ULL << bits) - 1ULL);
 }
 
+// Turn off formatting, because the thicket of nested ifdefs below is
+// incomprehensible without indentation. It is also incomprehensible with
+// indentation, but the only other option is a combinatorial explosion of
+// *_{win,linux,mac,foo}_{32,64}.h files.
+//
+// clang-format off
+
 #if defined(ARCH_CPU_64_BITS)
-#if defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
-// We shouldn't be allocating system pages at all for sanitizer builds. However,
-// we do, and if random hint addresses interfere with address ranges hard coded
-// in those tools, bad things happen. This address range is copied from TSAN
-// source but works with all tools.
-// See crbug.com/539863.
-constexpr uintptr_t kASLRMask = AslrAddress(0x007fffffffffULL);
-constexpr uintptr_t kASLROffset = AslrAddress(0x7e8000000000ULL);
-#elif defined(OS_WIN)
-// Windows 8.10 and newer support the full 48 bit address range. Older versions
-// of Windows only support 44 bits. Since kASLROffset is non-zero and may cause
-// a carry, use 47 and 43 bit masks.
-// See http://www.alex-ionescu.com/?p=246
-constexpr uintptr_t kASLRMask = AslrMask(47);
-constexpr uintptr_t kASLRMaskBefore8_10 = AslrMask(43);
-// Try not to map pages into the range where Windows loads DLLs by default.
-constexpr uintptr_t kASLROffset = 0x80000000ULL;
-#elif defined(OS_MACOSX)
-// macOS as of 10.12.5 does not clean up entries in page map levels 3/4
-// [PDP/PML4] created from mmap or mach_vm_allocate, even after the region is
-// destroyed. Using a virtual address space that is too large causes a leak of
-// about 1 wired [can never be paged out] page per call to mmap(). The page is
-// only reclaimed when the process is killed. Confine the hint to a 39-bit
-// section of the virtual address space.
-//
-// This implementation adapted from
-// https://chromium-review.googlesource.com/c/v8/v8/+/557958. The difference
-// is that here we clamp to 39 bits, not 32.
-//
-// TODO(crbug.com/738925): Remove this limitation if/when the macOS behavior
-// changes.
-constexpr uintptr_t kASLRMask = AslrMask(38);
-constexpr uintptr_t kASLROffset = AslrAddress(0x1000000000ULL);
-#else  // defined(OS_POSIX)
-#if defined(ARCH_CPU_X86_64)
-// Linux and OS X support the full 47-bit user space of x64 processors. Use
-// only 46 to allow kernel a chance to fulfill request.
-constexpr uintptr_t kASLRMask = AslrMask(46);
-constexpr uintptr_t kASLROffset = AslrAddress(0);
-#elif defined(ARCH_CPU_ARM64)
-// ARM64 on Linux has 39-bit user space. Use 38 bits since kASLROffset could
-// cause a carry.
-constexpr uintptr_t kASLRMask = AslrMask(38);
-constexpr uintptr_t kASLROffset = AslrAddress(0x1000000000ULL);
-#elif defined(ARCH_CPU_PPC64)
-#if defined(OS_AIX)
-// AIX: 64 bits of virtual addressing, but we limit address range to:
-//   a) minimize Segment Lookaside Buffer (SLB) misses and
-//   b) use extra address space to isolate the mmap regions.
-constexpr uintptr_t kASLRMask = AslrMask(30);
-constexpr uintptr_t kASLROffset = AslrAddress(0x400000000000ULL);
-#elif defined(ARCH_CPU_BIG_ENDIAN)
-// Big-endian Linux: 44 bits of virtual addressing. Use 42.
-constexpr uintptr_t kASLRMask = AslrMask(42);
-constexpr uintptr_t kASLROffset = AslrAddress(0);
-#else   // !defined(OS_AIX) && !defined(ARCH_CPU_BIG_ENDIAN)
-// Little-endian Linux: 48 bits of virtual addressing. Use 46.
-constexpr uintptr_t kASLRMask = AslrMask(46);
-constexpr uintptr_t kASLROffset = AslrAddress(0);
-#endif  // !defined(OS_AIX) && !defined(ARCH_CPU_BIG_ENDIAN)
-#elif defined(ARCH_CPU_S390X)
-// Linux on Z uses bits 22-32 for Region Indexing, which translates to 42 bits
-// of virtual addressing.  Truncate to 40 bits to allow kernel chance to
-// fulfill request.
-constexpr uintptr_t kASLRMask = AslrMask(40);
-constexpr uintptr_t kASLROffset = AslrAddress(0);
-#elif defined(ARCH_CPU_S390)
-// 31 bits of virtual addressing.  Truncate to 29 bits to allow kernel a chance
-// to fulfill request.
-constexpr uintptr_t kASLRMask = AslrMask(29);
-constexpr uintptr_t kASLROffset = AslrAddress(0);
-#else  // !defined(ARCH_CPU_X86_64) && !defined(ARCH_CPU_PPC64) &&
-// !defined(ARCH_CPU_S390X) && !defined(ARCH_CPU_S390)
-// All other POSIX variants, use 30 bits.
-constexpr uintptr_t kASLRMask = AslrMask(30);
-#if defined(OS_SOLARIS)
-// For our Solaris/illumos mmap hint, we pick a random address in the bottom
-// half of the top half of the address space (that is, the third quarter).
-// Because we do not MAP_FIXED, this will be treated only as a hint -- the
-// system will not fail to mmap() because something else happens to already
-// be mapped at our random address. We deliberately set the hint high enough
-// to get well above the system's break (that is, the heap); Solaris and
-// illumos will try the hint and if that fails allocate as if there were
-// no hint at all. The high hint prevents the break from getting hemmed in
-// at low values, ceding half of the address space to the system heap.
-constexpr uintptr_t kASLROffset = AslrAddress(0x80000000ULL);
-#elif defined(OS_AIX)
-// The range 0x30000000 - 0xD0000000 is available on AIX;
-// choose the upper range.
-constexpr uintptr_t kASLROffset = AslrAddress(0x90000000ULL);
-#else   // !defined(OS_SOLARIS) && !defined(OS_AIX)
-// The range 0x20000000 - 0x60000000 is relatively unpopulated across a
-// variety of ASLR modes (PAE kernel, NX compat mode, etc) and on macos
-// 10.6 and 10.7.
-constexpr uintptr_t kASLROffset = AslrAddress(0x20000000ULL);
-#endif  // !defined(OS_SOLARIS) && !defined(OS_AIX)
-#endif  // !defined(ARCH_CPU_X86_64) && !defined(ARCH_CPU_PPC64) &&
-// !defined(ARCH_CPU_S390X) && !defined(ARCH_CPU_S390)
-#endif  // defined(OS_POSIX)
-#else   // defined(ARCH_CPU_32_BITS)
-// This is a good range on 32 bit Windows, Linux and Mac.
-// Allocates in the 0.5-1.5GB region. There is no issue with carries here.
-constexpr uintptr_t kASLRMask = AslrMask(30);
-constexpr uintptr_t kASLROffset = AslrAddress(0x20000000ULL);
+
+  #if defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
+
+    // We shouldn't allocate system pages at all for sanitizer builds. However,
+    // we do, and if random hint addresses interfere with address ranges
+    // hard-coded in those tools, bad things happen. This address range is
+    // copied from TSAN source but works with all tools. See
+    // https://crbug.com/539863.
+    constexpr uintptr_t kASLRMask = AslrAddress(0x007fffffffffULL);
+    constexpr uintptr_t kASLROffset = AslrAddress(0x7e8000000000ULL);
+
+  #elif defined(OS_WIN)
+
+    // Windows 8.10 and newer support the full 48 bit address range. Older
+    // versions of Windows only support 44 bits. Since kASLROffset is non-zero
+    // and may cause a carry, use 47 and 43 bit masks. See
+    // http://www.alex-ionescu.com/?p=246
+    constexpr uintptr_t kASLRMask = AslrMask(47);
+    constexpr uintptr_t kASLRMaskBefore8_10 = AslrMask(43);
+    // Try not to map pages into the range where Windows loads DLLs by default.
+    constexpr uintptr_t kASLROffset = 0x80000000ULL;
+
+  #elif defined(OS_MACOSX)
+
+    // macOS as of 10.12.5 does not clean up entries in page map levels 3/4
+    // [PDP/PML4] created from mmap or mach_vm_allocate, even after the region
+    // is destroyed. Using a virtual address space that is too large causes a
+    // leak of about 1 wired [can never be paged out] page per call to mmap. The
+    // page is only reclaimed when the process is killed. Confine the hint to a
+    // 39-bit section of the virtual address space.
+    //
+    // This implementation adapted from
+    // https://chromium-review.googlesource.com/c/v8/v8/+/557958. The difference
+    // is that here we clamp to 39 bits, not 32.
+    //
+    // TODO(crbug.com/738925): Remove this limitation if/when the macOS behavior
+    // changes.
+    constexpr uintptr_t kASLRMask = AslrMask(38);
+    constexpr uintptr_t kASLROffset = AslrAddress(0x1000000000ULL);
+
+  #elif defined(OS_POSIX)
+
+    #if defined(ARCH_CPU_X86_64)
+
+      // Linux (and macOS) support the full 47-bit user space of x64 processors.
+      // Use only 46 to allow the kernel a chance to fulfill the request.
+      constexpr uintptr_t kASLRMask = AslrMask(46);
+      constexpr uintptr_t kASLROffset = AslrAddress(0);
+
+    #elif defined(ARCH_CPU_ARM64)
+
+      // ARM64 on Linux has 39-bit user space. Use 38 bits since kASLROffset
+      // could cause a carry.
+      constexpr uintptr_t kASLRMask = AslrMask(38);
+      constexpr uintptr_t kASLROffset = AslrAddress(0x1000000000ULL);
+
+    #elif defined(ARCH_CPU_PPC64)
+
+      #if defined(OS_AIX)
+
+        // AIX has 64 bits of virtual addressing, but we limit the address range
+        // to (a) minimize segment lookaside buffer (SLB) misses; and (b) use
+        // extra address space to isolate the mmap regions.
+        constexpr uintptr_t kASLRMask = AslrMask(30);
+        constexpr uintptr_t kASLROffset = AslrAddress(0x400000000000ULL);
+
+      #elif defined(ARCH_CPU_BIG_ENDIAN)
+
+        // Big-endian Linux PPC has 44 bits of virtual addressing. Use 42.
+        constexpr uintptr_t kASLRMask = AslrMask(42);
+        constexpr uintptr_t kASLROffset = AslrAddress(0);
+
+      #else  // !defined(OS_AIX) && !defined(ARCH_CPU_BIG_ENDIAN)
+
+        // Little-endian Linux PPC has 48 bits of virtual addressing. Use 46.
+        constexpr uintptr_t kASLRMask = AslrMask(46);
+        constexpr uintptr_t kASLROffset = AslrAddress(0);
+
+      #endif  // !defined(OS_AIX) && !defined(ARCH_CPU_BIG_ENDIAN)
+
+    #elif defined(ARCH_CPU_S390X)
+
+      // Linux on Z uses bits 22 - 32 for Region Indexing, which translates to
+      // 42 bits of virtual addressing. Truncate to 40 bits to allow kernel a
+      // chance to fulfill the request.
+      constexpr uintptr_t kASLRMask = AslrMask(40);
+      constexpr uintptr_t kASLROffset = AslrAddress(0);
+
+    #elif defined(ARCH_CPU_S390)
+
+      // 31 bits of virtual addressing. Truncate to 29 bits to allow the kernel
+      // a chance to fulfill the request.
+      constexpr uintptr_t kASLRMask = AslrMask(29);
+      constexpr uintptr_t kASLROffset = AslrAddress(0);
+
+    #else  // !defined(ARCH_CPU_X86_64) && !defined(ARCH_CPU_PPC64) &&
+           // !defined(ARCH_CPU_S390X) && !defined(ARCH_CPU_S390)
+
+      // For all other POSIX variants, use 30 bits.
+      constexpr uintptr_t kASLRMask = AslrMask(30);
+
+      #if defined(OS_SOLARIS)
+
+        // For our Solaris/illumos mmap hint, we pick a random address in the
+        // bottom half of the top half of the address space (that is, the third
+        // quarter). Because we do not MAP_FIXED, this will be treated only as a
+        // hint -- the system will not fail to mmap because something else
+        // happens to already be mapped at our random address. We deliberately
+        // set the hint high enough to get well above the system's break (that
+        // is, the heap); Solaris and illumos will try the hint and if that
+        // fails allocate as if there were no hint at all. The high hint
+        // prevents the break from getting hemmed in at low values, ceding half
+        // of the address space to the system heap.
+        constexpr uintptr_t kASLROffset = AslrAddress(0x80000000ULL);
+
+      #elif defined(OS_AIX)
+
+        // The range 0x30000000 - 0xD0000000 is available on AIX; choose the
+        // upper range.
+        constexpr uintptr_t kASLROffset = AslrAddress(0x90000000ULL);
+
+      #else  // !defined(OS_SOLARIS) && !defined(OS_AIX)
+
+        // The range 0x20000000 - 0x60000000 is relatively unpopulated across a
+        // variety of ASLR modes (PAE kernel, NX compat mode, etc) and on macOS
+        // 10.6 and 10.7.
+        constexpr uintptr_t kASLROffset = AslrAddress(0x20000000ULL);
+
+      #endif  // !defined(OS_SOLARIS) && !defined(OS_AIX)
+
+    #endif  // !defined(ARCH_CPU_X86_64) && !defined(ARCH_CPU_PPC64) && !defined(ARCH_CPU_S390X) && !defined(ARCH_CPU_S390)
+
+  #endif  // defined(OS_POSIX)
+
+#elif defined(ARCH_CPU_32_BITS)
+
+  // This is a good range on 32-bit Windows and Android (the only platforms on
+  // which we support 32-bitness). Allocates in the 0.5 - 1.5 GiB region. There
+  // is no issue with carries here.
+  constexpr uintptr_t kASLRMask = AslrMask(30);
+  constexpr uintptr_t kASLROffset = AslrAddress(0x20000000ULL);
+
+#else
+
+  #error Please tell us about your exotic hardware! Sounds interesting.
+
 #endif  // defined(ARCH_CPU_32_BITS)
 
+// clang-format on
+
 }  // namespace internal
 
 }  // namespace base
diff --git a/base/allocator/partition_allocator/page_allocator.cc b/base/allocator/partition_allocator/page_allocator.cc
index 1056830..b73e2b7 100644
--- a/base/allocator/partition_allocator/page_allocator.cc
+++ b/base/allocator/partition_allocator/page_allocator.cc
@@ -6,9 +6,8 @@
 
 #include <limits.h>
 
-#include <atomic>
-
 #include "base/allocator/partition_allocator/address_space_randomization.h"
+#include "base/allocator/partition_allocator/page_allocator_internal.h"
 #include "base/allocator/partition_allocator/spin_lock.h"
 #include "base/base_export.h"
 #include "base/compiler_specific.h"
@@ -17,221 +16,90 @@
 #include "base/numerics/checked_math.h"
 #include "build/build_config.h"
 
-#if defined(OS_POSIX)
+#include <atomic>
 
-#include <errno.h>
-#include <sys/mman.h>
-
-#if defined(OS_MACOSX)
-#include <mach/mach.h>
-#endif
-#if defined(OS_LINUX)
-#include <sys/resource.h>
-#endif
-
-#ifndef MADV_FREE
-#define MADV_FREE MADV_DONTNEED
-#endif
-
-#ifndef MAP_ANONYMOUS
-#define MAP_ANONYMOUS MAP_ANON
-#endif
-
-namespace base {
-
-namespace {
-
-// On POSIX |mmap| uses a nearby address if the hint address is blocked.
-const bool kHintIsAdvisory = true;
-std::atomic<int32_t> s_allocPageErrorCode{0};
-
-int GetAccessFlags(PageAccessibilityConfiguration page_accessibility) {
-  switch (page_accessibility) {
-    case PageReadWrite:
-      return PROT_READ | PROT_WRITE;
-    case PageReadExecute:
-      return PROT_READ | PROT_EXEC;
-    case PageReadWriteExecute:
-      return PROT_READ | PROT_WRITE | PROT_EXEC;
-    default:
-      NOTREACHED();
-      FALLTHROUGH;
-    case PageInaccessible:
-      return PROT_NONE;
-  }
-}
-
-#if defined(OS_LINUX) && defined(ARCH_CPU_64_BITS)
-// On Linux, multiple guarded memory regions may exceed the process address
-// space limit. This function will raise or lower the limit by |amount|.
-bool AdjustAddressSpaceLimit(int64_t amount) {
-  struct rlimit old_rlimit;
-  if (getrlimit(RLIMIT_AS, &old_rlimit))
-    return false;
-  const rlim_t new_limit =
-      CheckAdd(old_rlimit.rlim_cur, amount).ValueOrDefault(old_rlimit.rlim_max);
-  const struct rlimit new_rlimit = {std::min(new_limit, old_rlimit.rlim_max),
-                                    old_rlimit.rlim_max};
-  // setrlimit will fail if limit > old_rlimit.rlim_max.
-  return setrlimit(RLIMIT_AS, &new_rlimit) == 0;
-}
-
-// Current WASM guarded memory regions have 8 GiB of address space. There are
-// schemes that reduce that to 4 GiB.
-constexpr size_t kMinimumGuardedMemorySize = 1ULL << 32;  // 4 GiB
-
-#endif  // defined(OS_LINUX) && defined(ARCH_CPU_64_BITS)
-
-#elif defined(OS_WIN)
-
+#if defined(OS_WIN)
 #include <windows.h>
+#endif
+
+#if defined(OS_POSIX)
+#include "base/allocator/partition_allocator/page_allocator_internals_posix.h"
+#elif defined(OS_WIN)
+#include "base/allocator/partition_allocator/page_allocator_internals_win.h"
+#else
+#error Platform not supported.
+#endif
 
 namespace base {
 
 namespace {
 
-// |VirtualAlloc| will fail if allocation at the hint address is blocked.
-const bool kHintIsAdvisory = false;
-std::atomic<int32_t> s_allocPageErrorCode{ERROR_SUCCESS};
+// We may reserve/release address space on different threads.
+LazyInstance<subtle::SpinLock>::Leaky s_reserveLock = LAZY_INSTANCE_INITIALIZER;
 
-int GetAccessFlags(PageAccessibilityConfiguration page_accessibility) {
-  switch (page_accessibility) {
-    case PageReadWrite:
-      return PAGE_READWRITE;
-    case PageReadExecute:
-      return PAGE_EXECUTE_READ;
-    case PageReadWriteExecute:
-      return PAGE_EXECUTE_READWRITE;
-    default:
-      NOTREACHED();
-      FALLTHROUGH;
-    case PageInaccessible:
-      return PAGE_NOACCESS;
-  }
-}
-
-#else
-#error Unknown OS
-#endif  // defined(OS_POSIX)
-
-// We may reserve / release address space on different threads.
-static LazyInstance<subtle::SpinLock>::Leaky s_reserveLock =
-    LAZY_INSTANCE_INITIALIZER;
 // We only support a single block of reserved address space.
 void* s_reservation_address = nullptr;
 size_t s_reservation_size = 0;
 
-// This internal function wraps the OS-specific page allocation call:
-// |VirtualAlloc| on Windows, and |mmap| on POSIX.
-static void* SystemAllocPages(void* hint,
-                              size_t length,
-                              PageAccessibilityConfiguration page_accessibility,
-                              PageTag page_tag,
-                              bool commit) {
-  DCHECK(!(length & kPageAllocationGranularityOffsetMask));
-  DCHECK(!(reinterpret_cast<uintptr_t>(hint) &
-           kPageAllocationGranularityOffsetMask));
-  DCHECK(commit || page_accessibility == PageInaccessible);
-
-  void* ret;
-#if defined(OS_WIN)
-  DWORD access_flag = GetAccessFlags(page_accessibility);
-  const DWORD type_flags = commit ? (MEM_RESERVE | MEM_COMMIT) : MEM_RESERVE;
-  ret = VirtualAlloc(hint, length, type_flags, access_flag);
-  if (ret == nullptr)
-    s_allocPageErrorCode = GetLastError();
-#else
-
-#if defined(OS_MACOSX)
-  // Use a custom tag to make it easier to distinguish partition alloc regions
-  // in vmmap. Tags between 240-255 are supported.
-  DCHECK_LE(PageTag::kFirst, page_tag);
-  DCHECK_GE(PageTag::kLast, page_tag);
-  int fd = VM_MAKE_TAG(static_cast<int>(page_tag));
-#else
-  int fd = -1;
-#endif
-  int access_flag = GetAccessFlags(page_accessibility);
-  ret = mmap(hint, length, access_flag, MAP_ANONYMOUS | MAP_PRIVATE, fd, 0);
-  if (ret == MAP_FAILED) {
-    s_allocPageErrorCode = errno;
-    ret = nullptr;
-  }
-#endif
-  return ret;
-}
-
-static void* AllocPagesIncludingReserved(
-    void* address,
-    size_t length,
-    PageAccessibilityConfiguration page_accessibility,
-    PageTag page_tag,
-    bool commit) {
+void* AllocPagesIncludingReserved(void* address,
+                                  size_t length,
+                                  PageAccessibilityConfiguration accessibility,
+                                  PageTag page_tag,
+                                  bool commit) {
   void* ret =
-      SystemAllocPages(address, length, page_accessibility, page_tag, commit);
+      SystemAllocPages(address, length, accessibility, page_tag, commit);
   if (ret == nullptr) {
     const bool cant_alloc_length = kHintIsAdvisory || address == nullptr;
     if (cant_alloc_length) {
       // The system cannot allocate |length| bytes. Release any reserved address
       // space and try once more.
       ReleaseReservation();
-      ret = SystemAllocPages(address, length, page_accessibility, page_tag,
-                             commit);
+      ret = SystemAllocPages(address, length, accessibility, page_tag, commit);
     }
   }
   return ret;
 }
 
-// Trims base to given length and alignment. Windows returns null on failure and
-// frees base.
-static void* TrimMapping(void* base,
-                         size_t base_length,
-                         size_t trim_length,
-                         uintptr_t align,
-                         PageAccessibilityConfiguration page_accessibility,
-                         bool commit) {
-  size_t pre_slack = reinterpret_cast<uintptr_t>(base) & (align - 1);
-  if (pre_slack)
-    pre_slack = align - pre_slack;
+// Trims |base| to given |trim_length| and |alignment|.
+//
+// On failure, on Windows, this function returns nullptr and frees |base|.
+void* TrimMapping(void* base,
+                  size_t base_length,
+                  size_t trim_length,
+                  uintptr_t alignment,
+                  PageAccessibilityConfiguration accessibility,
+                  bool commit) {
+  size_t pre_slack = reinterpret_cast<uintptr_t>(base) & (alignment - 1);
+  if (pre_slack) {
+    pre_slack = alignment - pre_slack;
+  }
   size_t post_slack = base_length - pre_slack - trim_length;
   DCHECK(base_length >= trim_length || pre_slack || post_slack);
   DCHECK(pre_slack < base_length);
   DCHECK(post_slack < base_length);
-  void* ret = base;
-
-#if defined(OS_POSIX)
-  // On POSIX we can resize the allocation run. Release unneeded memory before
-  // and after the aligned range.
-  (void)page_accessibility;
-  if (pre_slack) {
-    int res = munmap(base, pre_slack);
-    CHECK(!res);
-    ret = reinterpret_cast<char*>(base) + pre_slack;
-  }
-  if (post_slack) {
-    int res = munmap(reinterpret_cast<char*>(ret) + trim_length, post_slack);
-    CHECK(!res);
-  }
-#else
-  if (pre_slack || post_slack) {
-    // On Windows we can't resize the allocation run. Free it and retry at the
-    // aligned address within the freed range.
-    ret = reinterpret_cast<char*>(base) + pre_slack;
-    FreePages(base, base_length);
-    ret = SystemAllocPages(ret, trim_length, page_accessibility,
-                           PageTag::kChromium, commit);
-  }
-#endif
-
-  return ret;
+  return TrimMappingInternal(base, base_length, trim_length, accessibility,
+                             commit, pre_slack, post_slack);
 }
 
 }  // namespace
 
+void* SystemAllocPages(void* hint,
+                       size_t length,
+                       PageAccessibilityConfiguration accessibility,
+                       PageTag page_tag,
+                       bool commit) {
+  DCHECK(!(length & kPageAllocationGranularityOffsetMask));
+  DCHECK(!(reinterpret_cast<uintptr_t>(hint) &
+           kPageAllocationGranularityOffsetMask));
+  DCHECK(commit || accessibility == PageInaccessible);
+  return SystemAllocPagesInternal(hint, length, accessibility, page_tag,
+                                  commit);
+}
+
 void* AllocPages(void* address,
                  size_t length,
                  size_t align,
-                 PageAccessibilityConfiguration page_accessibility,
+                 PageAccessibilityConfiguration accessibility,
                  PageTag page_tag,
                  bool commit) {
   DCHECK(length >= kPageAllocationGranularity);
@@ -249,7 +117,7 @@
   // On 64 bit Linux, we may need to adjust the address space limit for
   // guarded allocations.
   if (length >= kMinimumGuardedMemorySize) {
-    CHECK_EQ(PageInaccessible, page_accessibility);
+    CHECK_EQ(PageInaccessible, accessibility);
     CHECK(!commit);
     if (AdjustAddressSpaceLimit(base::checked_cast<int64_t>(length))) {
       DLOG(WARNING) << "Could not address space by " << length;
@@ -274,8 +142,9 @@
   // On 64 bit systems, try 3 random aligned addresses.
   constexpr int kExactSizeTries = 3;
 #endif
+
   for (int i = 0; i < kExactSizeTries; ++i) {
-    void* ret = AllocPagesIncludingReserved(address, length, page_accessibility,
+    void* ret = AllocPagesIncludingReserved(address, length, accessibility,
                                             page_tag, commit);
     if (ret != nullptr) {
       // If the alignment is to our liking, we're done.
@@ -311,13 +180,13 @@
   do {
     // Continue randomizing only on POSIX.
     address = kHintIsAdvisory ? GetRandomPageBase() : nullptr;
-    ret = AllocPagesIncludingReserved(address, try_length, page_accessibility,
+    ret = AllocPagesIncludingReserved(address, try_length, accessibility,
                                       page_tag, commit);
     // The retries are for Windows, where a race can steal our mapping on
     // resize.
   } while (ret != nullptr &&
-           (ret = TrimMapping(ret, try_length, length, align,
-                              page_accessibility, commit)) == nullptr);
+           (ret = TrimMapping(ret, try_length, length, align, accessibility,
+                              commit)) == nullptr);
 
   return ret;
 }
@@ -326,112 +195,32 @@
   DCHECK(!(reinterpret_cast<uintptr_t>(address) &
            kPageAllocationGranularityOffsetMask));
   DCHECK(!(length & kPageAllocationGranularityOffsetMask));
-#if defined(OS_POSIX)
-  int ret = munmap(address, length);
-  CHECK(!ret);
-#if defined(OS_LINUX) && defined(ARCH_CPU_64_BITS)
-  // On 64 bit Linux, restore the address space limit.
-  if (length >= kMinimumGuardedMemorySize) {
-    CHECK(AdjustAddressSpaceLimit(-base::checked_cast<int64_t>(length)));
-  }
-#endif
-#else
-  BOOL ret = VirtualFree(address, 0, MEM_RELEASE);
-  CHECK(ret);
-#endif
+  FreePagesInternal(address, length);
 }
 
 bool SetSystemPagesAccess(void* address,
                           size_t length,
-                          PageAccessibilityConfiguration page_accessibility) {
+                          PageAccessibilityConfiguration accessibility) {
   DCHECK(!(length & kSystemPageOffsetMask));
-#if defined(OS_POSIX)
-  int access_flag = GetAccessFlags(page_accessibility);
-  return !mprotect(address, length, access_flag);
-#else
-  if (page_accessibility == PageInaccessible) {
-    return VirtualFree(address, length, MEM_DECOMMIT) != 0;
-  } else {
-    DWORD access_flag = GetAccessFlags(page_accessibility);
-    return !!VirtualAlloc(address, length, MEM_COMMIT, access_flag);
-  }
-#endif
+  return SetSystemPagesAccessInternal(address, length, accessibility);
 }
 
 void DecommitSystemPages(void* address, size_t length) {
   DCHECK_EQ(0UL, length & kSystemPageOffsetMask);
-#if defined(OS_POSIX)
-  // In POSIX, there is no decommit concept. Discarding is an effective way of
-  // implementing the Windows semantics where the OS is allowed to not swap the
-  // pages in the region.
-  //
-  // TODO(ajwong): Also explore setting PageInaccessible to make the protection
-  // semantics consistent between Windows and POSIX. This might have a perf cost
-  // though as both decommit and recommit would incur an extra syscall.
-  // http://crbug.com/766882
-  DiscardSystemPages(address, length);
-#else
-  CHECK(SetSystemPagesAccess(address, length, PageInaccessible));
-#endif
+  DecommitSystemPagesInternal(address, length);
 }
 
 bool RecommitSystemPages(void* address,
                          size_t length,
-                         PageAccessibilityConfiguration page_accessibility) {
+                         PageAccessibilityConfiguration accessibility) {
   DCHECK_EQ(0UL, length & kSystemPageOffsetMask);
-  DCHECK_NE(PageInaccessible, page_accessibility);
-#if defined(OS_POSIX)
-  // On POSIX systems, read the memory to recommit. This has the correct
-  // behavior because the API requires the permissions to be the same as before
-  // decommitting and all configurations can read.
-  (void)address;
-  return true;
-#endif
-  return SetSystemPagesAccess(address, length, page_accessibility);
+  DCHECK_NE(PageInaccessible, accessibility);
+  return RecommitSystemPagesInternal(address, length, accessibility);
 }
 
 void DiscardSystemPages(void* address, size_t length) {
   DCHECK_EQ(0UL, length & kSystemPageOffsetMask);
-#if defined(OS_POSIX)
-#if defined(OS_MACOSX)
-  // On macOS, MADV_FREE_REUSABLE has comparable behavior to MADV_FREE, but also
-  // marks the pages with the reusable bit, which allows both Activity Monitor
-  // and memory-infra to correctly track the pages.
-  int ret = madvise(address, length, MADV_FREE_REUSABLE);
-#else
-  int ret = madvise(address, length, MADV_FREE);
-#endif
-  if (ret != 0 && errno == EINVAL) {
-    // MADV_FREE only works on Linux 4.5+ . If request failed,
-    // retry with older MADV_DONTNEED . Note that MADV_FREE
-    // being defined at compile time doesn't imply runtime support.
-    ret = madvise(address, length, MADV_DONTNEED);
-  }
-  CHECK(!ret);
-#else
-  // On Windows discarded pages are not returned to the system immediately and
-  // not guaranteed to be zeroed when returned to the application.
-  using DiscardVirtualMemoryFunction =
-      DWORD(WINAPI*)(PVOID virtualAddress, SIZE_T size);
-  static DiscardVirtualMemoryFunction discard_virtual_memory =
-      reinterpret_cast<DiscardVirtualMemoryFunction>(-1);
-  if (discard_virtual_memory ==
-      reinterpret_cast<DiscardVirtualMemoryFunction>(-1))
-    discard_virtual_memory =
-        reinterpret_cast<DiscardVirtualMemoryFunction>(GetProcAddress(
-            GetModuleHandle(L"Kernel32.dll"), "DiscardVirtualMemory"));
-  // Use DiscardVirtualMemory when available because it releases faster than
-  // MEM_RESET.
-  DWORD ret = 1;
-  if (discard_virtual_memory)
-    ret = discard_virtual_memory(address, length);
-  // DiscardVirtualMemory is buggy in Win10 SP0, so fall back to MEM_RESET on
-  // failure.
-  if (ret) {
-    void* ptr = VirtualAlloc(address, length, MEM_RESET, PAGE_READWRITE);
-    CHECK(ptr);
-  }
-#endif
+  DiscardSystemPagesInternal(address, length);
 }
 
 bool ReserveAddressSpace(size_t size) {
diff --git a/base/allocator/partition_allocator/page_allocator_internal.h b/base/allocator/partition_allocator/page_allocator_internal.h
new file mode 100644
index 0000000..c8c003d
--- /dev/null
+++ b/base/allocator/partition_allocator/page_allocator_internal.h
@@ -0,0 +1,18 @@
+// Copyright (c) 2018 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 BASE_ALLOCATOR_PARTITION_ALLOCATOR_PAGE_ALLOCATOR_INTERNAL_H_
+#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_PAGE_ALLOCATOR_INTERNAL_H_
+
+namespace base {
+
+void* SystemAllocPages(void* hint,
+                       size_t length,
+                       PageAccessibilityConfiguration accessibility,
+                       PageTag page_tag,
+                       bool commit);
+
+}  // namespace base
+
+#endif  // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PAGE_ALLOCATOR_INTERNAL_H_
diff --git a/base/allocator/partition_allocator/page_allocator_internals_posix.h b/base/allocator/partition_allocator/page_allocator_internals_posix.h
new file mode 100644
index 0000000..4ef1346
--- /dev/null
+++ b/base/allocator/partition_allocator/page_allocator_internals_posix.h
@@ -0,0 +1,180 @@
+// Copyright (c) 2018 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 BASE_ALLOCATOR_PARTITION_ALLOCATOR_PAGE_ALLOCATOR_INTERNALS_POSIX_H_
+#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_PAGE_ALLOCATOR_INTERNALS_POSIX_H_
+
+#include <errno.h>
+#include <sys/mman.h>
+
+#if defined(OS_MACOSX)
+#include <mach/mach.h>
+#endif
+#if defined(OS_LINUX)
+#include <sys/resource.h>
+#endif
+
+#include "build/build_config.h"
+
+#ifndef MADV_FREE
+#define MADV_FREE MADV_DONTNEED
+#endif
+
+#ifndef MAP_ANONYMOUS
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
+namespace base {
+
+// |mmap| uses a nearby address if the hint address is blocked.
+const bool kHintIsAdvisory = true;
+std::atomic<int32_t> s_allocPageErrorCode{0};
+
+int GetAccessFlags(PageAccessibilityConfiguration accessibility) {
+  switch (accessibility) {
+    case PageReadWrite:
+      return PROT_READ | PROT_WRITE;
+    case PageReadExecute:
+      return PROT_READ | PROT_EXEC;
+    case PageReadWriteExecute:
+      return PROT_READ | PROT_WRITE | PROT_EXEC;
+    default:
+      NOTREACHED();
+      FALLTHROUGH;
+    case PageInaccessible:
+      return PROT_NONE;
+  }
+}
+
+#if defined(OS_LINUX) && defined(ARCH_CPU_64_BITS)
+
+// Multiple guarded memory regions may exceed the process address space limit.
+// This function will raise or lower the limit by |amount|.
+bool AdjustAddressSpaceLimit(int64_t amount) {
+  struct rlimit old_rlimit;
+  if (getrlimit(RLIMIT_AS, &old_rlimit))
+    return false;
+  const rlim_t new_limit =
+      CheckAdd(old_rlimit.rlim_cur, amount).ValueOrDefault(old_rlimit.rlim_max);
+  const struct rlimit new_rlimit = {std::min(new_limit, old_rlimit.rlim_max),
+                                    old_rlimit.rlim_max};
+  // setrlimit will fail if limit > old_rlimit.rlim_max.
+  return setrlimit(RLIMIT_AS, &new_rlimit) == 0;
+}
+
+// Current WASM guarded memory regions have 8 GiB of address space. There are
+// schemes that reduce that to 4 GiB.
+constexpr size_t kMinimumGuardedMemorySize = 1ULL << 32;  // 4 GiB
+
+#endif  // defined(OS_LINUX) && defined(ARCH_CPU_64_BITS)
+
+void* SystemAllocPagesInternal(void* hint,
+                               size_t length,
+                               PageAccessibilityConfiguration accessibility,
+                               PageTag page_tag,
+                               bool commit) {
+#if defined(OS_MACOSX)
+  // Use a custom tag to make it easier to distinguish Partition Alloc regions
+  // in vmmap(1). Tags between 240-255 are supported.
+  DCHECK_LE(PageTag::kFirst, page_tag);
+  DCHECK_GE(PageTag::kLast, page_tag);
+  int fd = VM_MAKE_TAG(static_cast<int>(page_tag));
+#else
+  int fd = -1;
+#endif
+
+  int access_flag = GetAccessFlags(accessibility);
+  void* ret =
+      mmap(hint, length, access_flag, MAP_ANONYMOUS | MAP_PRIVATE, fd, 0);
+  if (ret == MAP_FAILED) {
+    s_allocPageErrorCode = errno;
+    ret = nullptr;
+  }
+  return ret;
+}
+
+void* TrimMappingInternal(void* base,
+                          size_t base_length,
+                          size_t trim_length,
+                          PageAccessibilityConfiguration accessibility,
+                          bool commit,
+                          size_t pre_slack,
+                          size_t post_slack) {
+  void* ret = base;
+  // We can resize the allocation run. Release unneeded memory before and after
+  // the aligned range.
+  if (pre_slack) {
+    int res = munmap(base, pre_slack);
+    CHECK(!res);
+    ret = reinterpret_cast<char*>(base) + pre_slack;
+  }
+  if (post_slack) {
+    int res = munmap(reinterpret_cast<char*>(ret) + trim_length, post_slack);
+    CHECK(!res);
+  }
+  return ret;
+}
+
+bool SetSystemPagesAccessInternal(
+    void* address,
+    size_t length,
+    PageAccessibilityConfiguration accessibility) {
+  return 0 == mprotect(address, length, GetAccessFlags(accessibility));
+}
+
+void FreePagesInternal(void* address, size_t length) {
+  CHECK(!munmap(address, length));
+
+#if defined(OS_LINUX) && defined(ARCH_CPU_64_BITS)
+  // Restore the address space limit.
+  if (length >= kMinimumGuardedMemorySize) {
+    CHECK(AdjustAddressSpaceLimit(-base::checked_cast<int64_t>(length)));
+  }
+#endif
+}
+
+void DecommitSystemPagesInternal(void* address, size_t length) {
+  // In POSIX, there is no decommit concept. Discarding is an effective way of
+  // implementing the Windows semantics where the OS is allowed to not swap the
+  // pages in the region.
+  //
+  // TODO(ajwong): Also explore setting PageInaccessible to make the protection
+  // semantics consistent between Windows and POSIX. This might have a perf cost
+  // though as both decommit and recommit would incur an extra syscall.
+  // http://crbug.com/766882
+  DiscardSystemPages(address, length);
+}
+
+bool RecommitSystemPagesInternal(void* address,
+                                 size_t length,
+                                 PageAccessibilityConfiguration accessibility) {
+  // On POSIX systems, the caller need simply read the memory to recommit it.
+  // This has the correct behavior because the API requires the permissions to
+  // be the same as before decommitting and all configurations can read.
+  return true;
+}
+
+void DiscardSystemPagesInternal(void* address, size_t length) {
+#if defined(OS_MACOSX)
+  // On macOS, MADV_FREE_REUSABLE has comparable behavior to MADV_FREE, but also
+  // marks the pages with the reusable bit, which allows both Activity Monitor
+  // and memory-infra to correctly track the pages.
+  int flags = MADV_FREE_REUSABLE;
+#else
+  int flags = MADV_FREE;
+#endif
+
+  int ret = madvise(address, length, flags);
+  if (ret != 0 && errno == EINVAL) {
+    // MADV_FREE only works on Linux 4.5+. If request failed, retry with older
+    // MADV_DONTNEED. Note that MADV_FREE being defined at compile time doesn't
+    // imply runtime support.
+    ret = madvise(address, length, MADV_DONTNEED);
+  }
+  CHECK(!ret);
+}
+
+}  // namespace base
+
+#endif  // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PAGE_ALLOCATOR_INTERNALS_POSIX_H_
diff --git a/base/allocator/partition_allocator/page_allocator_internals_win.h b/base/allocator/partition_allocator/page_allocator_internals_win.h
new file mode 100644
index 0000000..9769784e
--- /dev/null
+++ b/base/allocator/partition_allocator/page_allocator_internals_win.h
@@ -0,0 +1,119 @@
+// Copyright (c) 2018 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 BASE_ALLOCATOR_PARTITION_ALLOCATOR_PAGE_ALLOCATOR_INTERNALS_WIN_H_
+#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_PAGE_ALLOCATOR_INTERNALS_WIN_H_
+
+#include "base/allocator/partition_allocator/page_allocator_internal.h"
+
+namespace base {
+
+// |VirtualAlloc| will fail if allocation at the hint address is blocked.
+const bool kHintIsAdvisory = false;
+std::atomic<int32_t> s_allocPageErrorCode{ERROR_SUCCESS};
+
+int GetAccessFlags(PageAccessibilityConfiguration accessibility) {
+  switch (accessibility) {
+    case PageReadWrite:
+      return PAGE_READWRITE;
+    case PageReadExecute:
+      return PAGE_EXECUTE_READ;
+    case PageReadWriteExecute:
+      return PAGE_EXECUTE_READWRITE;
+    default:
+      NOTREACHED();
+      FALLTHROUGH;
+    case PageInaccessible:
+      return PAGE_NOACCESS;
+  }
+}
+
+void* SystemAllocPagesInternal(void* hint,
+                               size_t length,
+                               PageAccessibilityConfiguration accessibility,
+                               PageTag page_tag,
+                               bool commit) {
+  DWORD access_flag = GetAccessFlags(accessibility);
+  const DWORD type_flags = commit ? (MEM_RESERVE | MEM_COMMIT) : MEM_RESERVE;
+  void* ret = VirtualAlloc(hint, length, type_flags, access_flag);
+  if (ret == nullptr) {
+    s_allocPageErrorCode = GetLastError();
+  }
+  return ret;
+}
+
+void* TrimMappingInternal(void* base,
+                          size_t base_length,
+                          size_t trim_length,
+                          PageAccessibilityConfiguration accessibility,
+                          bool commit,
+                          size_t pre_slack,
+                          size_t post_slack) {
+  void* ret = base;
+  if (pre_slack || post_slack) {
+    // We cannot resize the allocation run. Free it and retry at the aligned
+    // address within the freed range.
+    ret = reinterpret_cast<char*>(base) + pre_slack;
+    FreePages(base, base_length);
+    ret = SystemAllocPages(ret, trim_length, accessibility, PageTag::kChromium,
+                           commit);
+  }
+  return ret;
+}
+
+bool SetSystemPagesAccessInternal(
+    void* address,
+    size_t length,
+    PageAccessibilityConfiguration accessibility) {
+  if (accessibility == PageInaccessible) {
+    return VirtualFree(address, length, MEM_DECOMMIT) != 0;
+  } else {
+    return nullptr != VirtualAlloc(address, length, MEM_COMMIT,
+                                   GetAccessFlags(accessibility));
+  }
+}
+
+void FreePagesInternal(void* address, size_t length) {
+  CHECK(VirtualFree(address, 0, MEM_RELEASE));
+}
+
+void DecommitSystemPagesInternal(void* address, size_t length) {
+  CHECK(SetSystemPagesAccess(address, length, PageInaccessible));
+}
+
+bool RecommitSystemPagesInternal(void* address,
+                                 size_t length,
+                                 PageAccessibilityConfiguration accessibility) {
+  return SetSystemPagesAccess(address, length, accessibility);
+}
+
+void DiscardSystemPagesInternal(void* address, size_t length) {
+  // On Windows, discarded pages are not returned to the system immediately and
+  // not guaranteed to be zeroed when returned to the application.
+  using DiscardVirtualMemoryFunction =
+      DWORD(WINAPI*)(PVOID virtualAddress, SIZE_T size);
+  static DiscardVirtualMemoryFunction discard_virtual_memory =
+      reinterpret_cast<DiscardVirtualMemoryFunction>(-1);
+  if (discard_virtual_memory ==
+      reinterpret_cast<DiscardVirtualMemoryFunction>(-1))
+    discard_virtual_memory =
+        reinterpret_cast<DiscardVirtualMemoryFunction>(GetProcAddress(
+            GetModuleHandle(L"Kernel32.dll"), "DiscardVirtualMemory"));
+  // Use DiscardVirtualMemory when available because it releases faster than
+  // MEM_RESET.
+  DWORD ret = 1;
+  if (discard_virtual_memory) {
+    ret = discard_virtual_memory(address, length);
+  }
+  // DiscardVirtualMemory is buggy in Win10 SP0, so fall back to MEM_RESET on
+  // failure.
+  if (ret) {
+    void* ptr = VirtualAlloc(address, length, MEM_RESET, PAGE_READWRITE);
+    CHECK(ptr);
+  }
+}
+
+}  // namespace base
+
+#endif  // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PAGE_ALLOCATOR_INTERNALS_WIN_H_
diff --git a/base/android/record_histogram.cc b/base/android/record_histogram.cc
index 0bc8423..f41ec99 100644
--- a/base/android/record_histogram.cc
+++ b/base/android/record_histogram.cc
@@ -42,6 +42,7 @@
         break;
       }
       case SPARSE_HISTOGRAM:
+      case DUMMY_HISTOGRAM:
         break;
     }
     return params_str;
diff --git a/base/event_types.h b/base/event_types.h
deleted file mode 100644
index 9905800d..0000000
--- a/base/event_types.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_EVENT_TYPES_H_
-#define BASE_EVENT_TYPES_H_
-
-#include "build/build_config.h"
-
-#if defined(OS_WIN)
-#include <windows.h>
-#elif defined(USE_X11)
-typedef union _XEvent XEvent;
-#elif defined(OS_MACOSX)
-#if defined(__OBJC__)
-@class NSEvent;
-#else  // __OBJC__
-class NSEvent;
-#endif // __OBJC__
-#endif
-
-namespace base {
-
-// Cross platform typedefs for native event types.
-#if defined(OS_WIN)
-typedef MSG NativeEvent;
-#elif defined(USE_X11)
-typedef XEvent* NativeEvent;
-#elif defined(OS_MACOSX)
-typedef NSEvent* NativeEvent;
-#else
-typedef void* NativeEvent;
-#endif
-
-} // namespace base
-
-#endif  // BASE_EVENT_TYPES_H_
diff --git a/base/feature_list.cc b/base/feature_list.cc
index e38e164..1610eec 100644
--- a/base/feature_list.cc
+++ b/base/feature_list.cc
@@ -76,10 +76,10 @@
 
 }  // namespace
 
-#if DCHECK_IS_ON() && defined(SYZYASAN)
-const Feature kSyzyAsanDCheckIsFatalFeature{"DcheckIsFatal",
-                                            base::FEATURE_DISABLED_BY_DEFAULT};
-#endif  // defined(SYZYASAN)
+#if DCHECK_IS_CONFIGURABLE
+const Feature kDCheckIsFatalFeature{"DcheckIsFatal",
+                                    base::FEATURE_DISABLED_BY_DEFAULT};
+#endif  // DCHECK_IS_CONFIGURABLE
 
 FeatureList::FeatureList() = default;
 
@@ -263,19 +263,19 @@
   // Note: Intentional leak of global singleton.
   g_feature_list_instance = instance.release();
 
-#if DCHECK_IS_ON() && defined(SYZYASAN)
+#if DCHECK_IS_CONFIGURABLE
   // Update the behaviour of LOG_DCHECK to match the Feature configuration.
   // DCHECK is also forced to be FATAL if we are running a death-test.
   // TODO(asvitkine): If we find other use-cases that need integrating here
   // then define a proper API/hook for the purpose.
-  if (base::FeatureList::IsEnabled(kSyzyAsanDCheckIsFatalFeature) ||
+  if (base::FeatureList::IsEnabled(kDCheckIsFatalFeature) ||
       base::CommandLine::ForCurrentProcess()->HasSwitch(
           "gtest_internal_run_death_test")) {
     logging::LOG_DCHECK = logging::LOG_FATAL;
   } else {
     logging::LOG_DCHECK = logging::LOG_INFO;
   }
-#endif  // DCHECK_IS_ON() && defined(SYZYASAN)
+#endif  // DCHECK_IS_CONFIGURABLE
 }
 
 // static
diff --git a/base/feature_list.h b/base/feature_list.h
index 0c89e3c..b317ee64 100644
--- a/base/feature_list.h
+++ b/base/feature_list.h
@@ -43,12 +43,12 @@
   const FeatureState default_state;
 };
 
-#if DCHECK_IS_ON() && defined(SYZYASAN)
-// SyzyASAN builds have DCHECKs built-in, but configurable at run-time to been
-// fatal, or not, via a DcheckIsFatal feature. We define the Feature here since
-// it is checked in FeatureList::SetInstance(). See crbug.com/596231.
-extern const Feature kSyzyAsanDCheckIsFatalFeature;
-#endif  // defined(SYZYASAN)
+#if DCHECK_IS_CONFIGURABLE
+// DCHECKs have been built-in, and are configurable at run-time to be fatal, or
+// not, via a DcheckIsFatal feature. We define the Feature here since it is
+// checked in FeatureList::SetInstance(). See https://crbug.com/596231.
+extern const Feature kDCheckIsFatalFeature;
+#endif  // DCHECK_IS_CONFIGURABLE
 
 // The FeatureList class is used to determine whether a given feature is on or
 // off. It provides an authoritative answer, taking into account command-line
diff --git a/base/json/json_parser.cc b/base/json/json_parser.cc
index 223cd4e..3e77b99 100644
--- a/base/json/json_parser.cc
+++ b/base/json/json_parser.cc
@@ -11,6 +11,7 @@
 #include "base/debug/alias.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
@@ -48,6 +49,8 @@
   DISALLOW_COPY_AND_ASSIGN(StackMarker);
 };
 
+constexpr uint32_t kUnicodeReplacementPoint = 0xFFFD;
+
 }  // namespace
 
 // This is U+FFFD.
@@ -56,9 +59,6 @@
 JSONParser::JSONParser(int options, int max_depth)
     : options_(options),
       max_depth_(max_depth),
-      start_pos_(nullptr),
-      pos_(nullptr),
-      end_pos_(nullptr),
       index_(0),
       stack_depth_(0),
       line_number_(0),
@@ -72,9 +72,7 @@
 JSONParser::~JSONParser() = default;
 
 Optional<Value> JSONParser::Parse(StringPiece input) {
-  start_pos_ = input.data();
-  pos_ = start_pos_;
-  end_pos_ = start_pos_ + input.length();
+  input_ = input;
   index_ = 0;
   line_number_ = 1;
   index_last_line_ = 0;
@@ -83,14 +81,19 @@
   error_line_ = 0;
   error_column_ = 0;
 
+  // ICU and ReadUnicodeCharacter() use int32_t for lengths, so ensure
+  // that the index_ will not overflow when parsing.
+  if (!base::IsValueInRangeForNumericType<int32_t>(input.length())) {
+    ReportError(JSONReader::JSON_TOO_LARGE, 0);
+    return nullopt;
+  }
+
   // When the input JSON string starts with a UTF-8 Byte-Order-Mark
   // <0xEF 0xBB 0xBF>, advance the start position to avoid the
   // ParseNextToken function mis-treating a Unicode BOM as an invalid
   // character and returning NULL.
-  if (CanConsume(3) && static_cast<uint8_t>(*pos_) == 0xEF &&
-      static_cast<uint8_t>(*(pos_ + 1)) == 0xBB &&
-      static_cast<uint8_t>(*(pos_ + 2)) == 0xBF) {
-    NextNChars(3);
+  if (ConsumeIfMatch("\xEF\xBB\xBF")) {
+    NextChar();  // Advance past the last byte of the BOM.
   }
 
   // Parse the first and any nested tokens.
@@ -100,7 +103,12 @@
 
   // Make sure the input stream is at an end.
   if (GetNextToken() != T_END_OF_INPUT) {
-    if (!CanConsume(1) || (NextChar() && GetNextToken() != T_END_OF_INPUT)) {
+    // There may be trailing whitespace or comments, so advance the parser
+    // and consume that via GetNextToken().
+    if (CanConsume(1)) {
+      NextChar();
+    }
+    if (GetNextToken() != T_END_OF_INPUT) {
       ReportError(JSONReader::JSON_UNEXPECTED_DATA_AFTER_ROOT, 1);
       return nullopt;
     }
@@ -138,40 +146,28 @@
 JSONParser::StringBuilder& JSONParser::StringBuilder::operator=(
     StringBuilder&& other) = default;
 
-void JSONParser::StringBuilder::Append(const char& c) {
-  DCHECK_GE(c, 0);
-  DCHECK_LT(static_cast<unsigned char>(c), 128);
+void JSONParser::StringBuilder::Append(uint32_t point) {
+  DCHECK(IsValidCharacter(point));
 
-  if (string_)
-    string_->push_back(c);
-  else
+  if (point < kExtendedASCIIStart && !string_) {
+    DCHECK_EQ(static_cast<char>(point), pos_[length_]);
     ++length_;
-}
-
-void JSONParser::StringBuilder::AppendString(const char* str, size_t len) {
-  DCHECK(string_);
-  string_->append(str, len);
+  } else {
+    Convert();
+    if (UNLIKELY(point == kUnicodeReplacementPoint)) {
+      string_->append(kUnicodeReplacementString);
+    } else {
+      WriteUnicodeCharacter(point, &*string_);
+    }
+  }
 }
 
 void JSONParser::StringBuilder::Convert() {
   if (string_)
     return;
-
   string_.emplace(pos_, length_);
 }
 
-StringPiece JSONParser::StringBuilder::AsStringPiece() {
-  if (string_)
-    return *string_;
-  return StringPiece(pos_, length_);
-}
-
-const std::string& JSONParser::StringBuilder::AsString() {
-  if (!string_)
-    Convert();
-  return *string_;
-}
-
 std::string JSONParser::StringBuilder::DestructiveAsString() {
   if (string_)
     return std::move(*string_);
@@ -181,20 +177,27 @@
 // JSONParser private //////////////////////////////////////////////////////////
 
 inline bool JSONParser::CanConsume(int length) {
-  return pos_ + length <= end_pos_;
+  return static_cast<size_t>(index_) + length <= input_.length();
 }
 
-const char* JSONParser::NextChar() {
-  DCHECK(CanConsume(1));
+void JSONParser::NextChar() {
+  CHECK(CanConsume(1));
   ++index_;
-  ++pos_;
-  return pos_;
 }
 
 void JSONParser::NextNChars(int n) {
-  DCHECK(CanConsume(n));
+  CHECK(CanConsume(n));
   index_ += n;
-  pos_ += n;
+}
+
+const char* JSONParser::pos() {
+  CHECK_LE(static_cast<size_t>(index_), input_.length());
+  return input_.data() + index_;
+}
+
+char JSONParser::current_char() {
+  // StringPiece internally bounds-checks.
+  return input_[index_];
 }
 
 JSONParser::Token JSONParser::GetNextToken() {
@@ -202,7 +205,7 @@
   if (!CanConsume(1))
     return T_END_OF_INPUT;
 
-  switch (*pos_) {
+  switch (current_char()) {
     case '{':
       return T_OBJECT_BEGIN;
     case '}':
@@ -241,14 +244,16 @@
 }
 
 void JSONParser::EatWhitespaceAndComments() {
-  while (pos_ < end_pos_) {
-    switch (*pos_) {
+  while (CanConsume(1)) {
+    switch (current_char()) {
       case '\r':
       case '\n':
         index_last_line_ = index_;
         // Don't increment line_number_ twice for "\r\n".
-        if (!(*pos_ == '\n' && pos_ > start_pos_ && *(pos_ - 1) == '\r'))
+        if (!(current_char() == '\n' &&
+              index_ > 0 && input_[index_ - 1] == '\r')) {
           ++line_number_;
+        }
         FALLTHROUGH;
       case ' ':
       case '\t':
@@ -265,7 +270,7 @@
 }
 
 bool JSONParser::EatComment() {
-  if (*pos_ != '/' || !CanConsume(1))
+  if (current_char() != '/' || !CanConsume(1))
     return false;
 
   NextChar();
@@ -273,25 +278,25 @@
   if (!CanConsume(1))
     return false;
 
-  if (*pos_ == '/') {
+  if (current_char() == '/') {
     // Single line comment, read to newline.
     while (CanConsume(1)) {
-      if (*pos_ == '\n' || *pos_ == '\r')
+      if (current_char() == '\n' || current_char() == '\r')
         return true;
       NextChar();
     }
-  } else if (*pos_ == '*') {
+  } else if (current_char() == '*') {
     char previous_char = '\0';
     // Block comment, read until end marker.
     while (CanConsume(1)) {
-      if (previous_char == '*' && *pos_ == '/') {
-        // EatWhitespaceAndComments will inspect pos_, which will still be on
+      if (previous_char == '*' && current_char() == '/') {
+        // EatWhitespaceAndComments will inspect pos(), which will still be on
         // the last / of the comment, so advance once more (which may also be
         // end of input).
         NextChar();
         return true;
       }
-      previous_char = *pos_;
+      previous_char = current_char();
       NextChar();
     }
 
@@ -333,10 +338,10 @@
   // complete.
   const char* initial_pos[16];
   for (size_t i = 0; i < arraysize(initial_pos); ++i)
-    initial_pos[i] = pos_ + i * 256;
+    initial_pos[i] = pos() + i * 256;
   debug::Alias(&initial_pos);
 
-  if (*pos_ != '{') {
+  if (current_char() != '{') {
     ReportError(JSONReader::JSON_UNEXPECTED_TOKEN, 1);
     return nullopt;
   }
@@ -401,7 +406,7 @@
 }
 
 Optional<Value> JSONParser::ConsumeList() {
-  if (*pos_ != '[') {
+  if (current_char() != '[') {
     ReportError(JSONReader::JSON_UNEXPECTED_TOKEN, 1);
     return nullopt;
   }
@@ -452,7 +457,7 @@
 }
 
 bool JSONParser::ConsumeStringRaw(StringBuilder* out) {
-  if (*pos_ != '"') {
+  if (current_char() != '"') {
     ReportError(JSONReader::JSON_UNEXPECTED_TOKEN, 1);
     return false;
   }
@@ -462,51 +467,37 @@
     ReportError(JSONReader::JSON_SYNTAX_ERROR, 1);
     return false;
   }
+  NextChar();  // Read past opening quote.
 
   // StringBuilder will internally build a StringPiece unless a UTF-16
   // conversion occurs, at which point it will perform a copy into a
   // std::string.
-  StringBuilder string(NextChar());
-
-  // Handle the empty string case early.
-  if (*pos_ == '"') {
-    *out = std::move(string);
-    return true;
-  }
-
-  int length = end_pos_ - start_pos_;
-  int32_t next_char = 0;
+  StringBuilder string(pos());
 
   // There must always be at least two characters left in the stream: the next
   // string character and the terminating closing quote.
-  while (CanConsume(2)) {
-    int start_index = index_;
-    pos_ = start_pos_ + index_;  // CBU8_NEXT is postcrement.
-    CBU8_NEXT(start_pos_, index_, length, next_char);
-    if (next_char < 0 || !IsValidCharacter(next_char)) {
+  for (uint32_t next_char = 0; CanConsume(1); ++index_) {
+    if (!ReadUnicodeCharacter(input_.data(),
+                              static_cast<int32_t>(input_.length()),
+                              &index_,
+                              &next_char) ||
+        !IsValidCharacter(next_char)) {
       if ((options_ & JSON_REPLACE_INVALID_CHARACTERS) == 0) {
         ReportError(JSONReader::JSON_UNSUPPORTED_ENCODING, 1);
         return false;
       }
-      CBU8_NEXT(start_pos_, start_index, length, next_char);
-      string.Convert();
-      string.AppendString(kUnicodeReplacementString,
-                          arraysize(kUnicodeReplacementString) - 1);
+      string.Append(kUnicodeReplacementPoint);
       continue;
     }
 
     if (next_char == '"') {
-      --index_;  // Rewind by one because of CBU8_NEXT.
       *out = std::move(string);
       return true;
     }
 
     // If this character is not an escape sequence...
     if (next_char != '\\') {
-      if (next_char < kExtendedASCIIStart)
-        string.Append(static_cast<char>(next_char));
-      else
-        DecodeUTF8(next_char, &string);
+      string.Append(next_char);
     } else {
       // And if it is an escape sequence, the input string will be adjusted
       // (either by combining the two characters of an encoded escape sequence,
@@ -514,58 +505,47 @@
       // a conversion.
       string.Convert();
 
+      // Read past the escape '\' and ensure there's a character following.
       if (!CanConsume(1)) {
         ReportError(JSONReader::JSON_INVALID_ESCAPE, 0);
         return false;
       }
-
       NextChar();
-      if (!CanConsume(1)) {
-        ReportError(JSONReader::JSON_INVALID_ESCAPE, 0);
-        return false;
-      }
 
-      switch (*pos_) {
+      switch (current_char()) {
         // Allowed esape sequences:
         case 'x': {  // UTF-8 sequence.
           // UTF-8 \x escape sequences are not allowed in the spec, but they
           // are supported here for backwards-compatiblity with the old parser.
           if (!CanConsume(3)) {
-            ReportError(JSONReader::JSON_INVALID_ESCAPE, 1);
+            ReportError(JSONReader::JSON_INVALID_ESCAPE, 0);
             return false;
           }
+          NextChar();  // Read past 'x'.
 
           int hex_digit = 0;
-          if (!HexStringToInt(StringPiece(NextChar(), 2), &hex_digit) ||
+          if (!HexStringToInt(StringPiece(pos(), 2), &hex_digit) ||
               !IsValidCharacter(hex_digit)) {
-            ReportError(JSONReader::JSON_INVALID_ESCAPE, -1);
+            ReportError(JSONReader::JSON_INVALID_ESCAPE, 0);
             return false;
           }
           NextChar();
 
-          if (hex_digit < kExtendedASCIIStart)
-            string.Append(static_cast<char>(hex_digit));
-          else
-            DecodeUTF8(hex_digit, &string);
+          string.Append(hex_digit);
           break;
         }
         case 'u': {  // UTF-16 sequence.
           // UTF units are of the form \uXXXX.
-          if (!CanConsume(5)) {  // 5 being 'u' and four HEX digits.
+          // Read past the 'u'.
+          NextChar();
+
+          uint32_t code_point;
+          if (!DecodeUTF16(&code_point)) {
             ReportError(JSONReader::JSON_INVALID_ESCAPE, 0);
             return false;
           }
+          string.Append(code_point);
 
-          // Skip the 'u'.
-          NextChar();
-
-          std::string utf8_units;
-          if (!DecodeUTF16(&utf8_units)) {
-            ReportError(JSONReader::JSON_INVALID_ESCAPE, -1);
-            return false;
-          }
-
-          string.AppendString(utf8_units.data(), utf8_units.length());
           break;
         }
         case '"':
@@ -597,7 +577,7 @@
           break;
         // All other escape squences are illegal.
         default:
-          ReportError(JSONReader::JSON_INVALID_ESCAPE, 0);
+          ReportError(JSONReader::JSON_INVALID_ESCAPE, 1);
           return false;
       }
     }
@@ -608,16 +588,13 @@
 }
 
 // Entry is at the first X in \uXXXX.
-bool JSONParser::DecodeUTF16(std::string* dest_string) {
+bool JSONParser::DecodeUTF16(uint32_t* out_code_point) {
   if (!CanConsume(4))
     return false;
 
-  // This is a 32-bit field because the shift operations in the
-  // conversion process below cause MSVC to error about "data loss."
-  // This only stores UTF-16 code units, though.
   // Consume the UTF-16 code unit, which may be a high surrogate.
   int code_unit16_high = 0;
-  if (!HexStringToInt(StringPiece(pos_, 4), &code_unit16_high))
+  if (!HexStringToInt(StringPiece(pos(), 4), &code_unit16_high))
     return false;
 
   // Only add 3, not 4, because at the end of this iteration, the parser has
@@ -625,11 +602,6 @@
   // the next iteration will advance to the next byte.
   NextNChars(3);
 
-  // Used to convert the UTF-16 code units to a code point and then to a UTF-8
-  // code unit sequence.
-  char code_unit8[8] = { 0 };
-  size_t offset = 0;
-
   // If this is a high surrogate, consume the next code unit to get the
   // low surrogate.
   if (CBU16_IS_SURROGATE(code_unit16_high)) {
@@ -638,16 +610,21 @@
     if (!CBU16_IS_SURROGATE_LEAD(code_unit16_high))
       return false;
 
+    NextChar();  // Read past last HEX digit.
+
     // Make sure that the token has more characters to consume the
     // lower surrogate.
-    if (!CanConsume(6))  // 6 being '\' 'u' and four HEX digits.
+    if (!ConsumeIfMatch("\\u")) {
       return false;
-    if (*NextChar() != '\\' || *NextChar() != 'u')
+    }
+    NextChar();  // Read past 'u'.
+
+    // Expect 4 HEX digits for the actual character.
+    if (!CanConsume(4))
       return false;
 
-    NextChar();  // Read past 'u'.
     int code_unit16_low = 0;
-    if (!HexStringToInt(StringPiece(pos_, 4), &code_unit16_low))
+    if (!HexStringToInt(StringPiece(pos(), 4), &code_unit16_low))
       return false;
 
     NextNChars(3);
@@ -661,8 +638,7 @@
     if (!IsValidCharacter(code_point))
       return false;
 
-    offset = 0;
-    CBU8_APPEND_UNSAFE(code_unit8, offset, code_point);
+    *out_code_point = code_point;
   } else {
     // Not a surrogate.
     DCHECK(CBU16_IS_SINGLE(code_unit16_high));
@@ -670,41 +646,22 @@
       if ((options_ & JSON_REPLACE_INVALID_CHARACTERS) == 0) {
         return false;
       }
-      dest_string->append(kUnicodeReplacementString);
+      *out_code_point = kUnicodeReplacementPoint;
       return true;
     }
 
-    CBU8_APPEND_UNSAFE(code_unit8, offset, code_unit16_high);
+    *out_code_point = code_unit16_high;
   }
 
-  dest_string->append(code_unit8, offset);
   return true;
 }
 
-void JSONParser::DecodeUTF8(const int32_t& point, StringBuilder* dest) {
-  DCHECK(IsValidCharacter(point));
-
-  // Anything outside of the basic ASCII plane will need to be decoded from
-  // int32_t to a multi-byte sequence.
-  if (point < kExtendedASCIIStart) {
-    dest->Append(static_cast<char>(point));
-  } else {
-    char utf8_units[4] = { 0 };
-    int offset = 0;
-    CBU8_APPEND_UNSAFE(utf8_units, offset, point);
-    dest->Convert();
-    // CBU8_APPEND_UNSAFE can overwrite up to 4 bytes, so utf8_units may not be
-    // zero terminated at this point.  |offset| contains the correct length.
-    dest->AppendString(utf8_units, offset);
-  }
-}
-
 Optional<Value> JSONParser::ConsumeNumber() {
-  const char* num_start = pos_;
+  const char* num_start = pos();
   const int start_index = index_;
   int end_index = start_index;
 
-  if (*pos_ == '-')
+  if (current_char() == '-')
     NextChar();
 
   if (!ReadInt(false)) {
@@ -714,7 +671,7 @@
   end_index = index_;
 
   // The optional fraction part.
-  if (CanConsume(1) && *pos_ == '.') {
+  if (CanConsume(1) && current_char() == '.') {
     NextChar();
     if (!ReadInt(true)) {
       ReportError(JSONReader::JSON_SYNTAX_ERROR, 1);
@@ -724,13 +681,13 @@
   }
 
   // Optional exponent part.
-  if (CanConsume(1) && (*pos_ == 'e' || *pos_ == 'E')) {
+  if (CanConsume(1) && (current_char() == 'e' || current_char() == 'E')) {
     NextChar();
     if (!CanConsume(1)) {
       ReportError(JSONReader::JSON_SYNTAX_ERROR, 1);
       return nullopt;
     }
-    if (*pos_ == '-' || *pos_ == '+') {
+    if (current_char() == '-' || current_char() == '+') {
       NextChar();
     }
     if (!ReadInt(true)) {
@@ -744,7 +701,6 @@
   // so save off where the parser should be on exit (see Consume invariant at
   // the top of the header), then make sure the next token is one which is
   // valid.
-  const char* exit_pos = pos_ - 1;
   int exit_index = index_ - 1;
 
   switch (GetNextToken()) {
@@ -758,7 +714,6 @@
       return nullopt;
   }
 
-  pos_ = exit_pos;
   index_ = exit_index;
 
   StringPiece num_string(num_start, end_index - start_index);
@@ -781,11 +736,11 @@
   char first = 0;
 
   while (CanConsume(1)) {
-    if (!IsAsciiDigit(*pos_))
+    if (!IsAsciiDigit(current_char()))
       break;
 
     if (len == 0)
-      first = *pos_;
+      first = current_char();
 
     ++len;
     NextChar();
@@ -801,38 +756,26 @@
 }
 
 Optional<Value> JSONParser::ConsumeLiteral() {
-  switch (*pos_) {
+  switch (current_char()) {
     case 't': {
-      const char kTrueLiteral[] = "true";
-      const int kTrueLen = static_cast<int>(strlen(kTrueLiteral));
-      if (!CanConsume(kTrueLen) ||
-          !StringsAreEqual(pos_, kTrueLiteral, kTrueLen)) {
+      if (!ConsumeIfMatch("true")) {
         ReportError(JSONReader::JSON_SYNTAX_ERROR, 1);
         return nullopt;
       }
-      NextNChars(kTrueLen - 1);
       return Value(true);
     }
     case 'f': {
-      const char kFalseLiteral[] = "false";
-      const int kFalseLen = static_cast<int>(strlen(kFalseLiteral));
-      if (!CanConsume(kFalseLen) ||
-          !StringsAreEqual(pos_, kFalseLiteral, kFalseLen)) {
+      if (!ConsumeIfMatch("false")) {
         ReportError(JSONReader::JSON_SYNTAX_ERROR, 1);
         return nullopt;
       }
-      NextNChars(kFalseLen - 1);
       return Value(false);
     }
     case 'n': {
-      const char kNullLiteral[] = "null";
-      const int kNullLen = static_cast<int>(strlen(kNullLiteral));
-      if (!CanConsume(kNullLen) ||
-          !StringsAreEqual(pos_, kNullLiteral, kNullLen)) {
+      if (!ConsumeIfMatch("null")) {
         ReportError(JSONReader::JSON_SYNTAX_ERROR, 1);
         return nullopt;
       }
-      NextNChars(kNullLen - 1);
       return Value(Value::Type::NONE);
     }
     default:
@@ -841,9 +784,14 @@
   }
 }
 
-// static
-bool JSONParser::StringsAreEqual(const char* one, const char* two, size_t len) {
-  return strncmp(one, two, len) == 0;
+bool JSONParser::ConsumeIfMatch(StringPiece match) {
+  if (!CanConsume(match.size()) || match != StringPiece(pos(), match.size())) {
+    return false;
+  }
+  // Per the Consume invariant, the parser state must be at the last byte of
+  // the token on exit.
+  NextNChars(match.size() - 1);
+  return true;
 }
 
 void JSONParser::ReportError(JSONReader::JsonParseError code,
diff --git a/base/json/json_parser.h b/base/json/json_parser.h
index 3fb87003..c43542e 100644
--- a/base/json/json_parser.h
+++ b/base/json/json_parser.h
@@ -101,26 +101,16 @@
 
     StringBuilder& operator=(StringBuilder&& other);
 
-    // Either increases the |length_| of the string or copies the character if
-    // the StringBuilder has been converted. |c| must be in the basic ASCII
-    // plane; all other characters need to be in UTF-8 units, appended with
-    // AppendString below.
-    void Append(const char& c);
-
-    // Appends a string to the std::string. Must be Convert()ed to use.
-    void AppendString(const char* str, size_t len);
+    // Appends the Unicode code point |point| to the string, either by
+    // increasing the |length_| of the string if the string has not been
+    // converted, or by appending the UTF8 bytes for the code point.
+    void Append(uint32_t point);
 
     // Converts the builder from its default StringPiece to a full std::string,
     // performing a copy. Once a builder is converted, it cannot be made a
     // StringPiece again.
     void Convert();
 
-    // Returns the builder as a StringPiece.
-    StringPiece AsStringPiece();
-
-    // Returns the builder as a std::string.
-    const std::string& AsString();
-
     // Returns the builder as a string, invalidating all state. This allows
     // the internal string buffer representation to be destructively moved
     // in cases where the builder will not be needed any more.
@@ -141,13 +131,18 @@
   // Quick check that the stream has capacity to consume |length| more bytes.
   bool CanConsume(int length);
 
-  // The basic way to consume a single character in the stream. Consumes one
-  // byte of the input stream and returns a pointer to the rest of it.
-  const char* NextChar();
+  // Consumes one byte of the input stream by advancing the parser's position.
+  void NextChar();
 
   // Performs the equivalent of NextChar N times.
   void NextNChars(int n);
 
+  // Returns a pointer to the current character position.
+  const char* pos();
+
+  // Returns the character at the current position.
+  char current_char();
+
   // Skips over whitespace and comments to find the next token in the stream.
   // This does not advance the parser for non-whitespace or comment chars.
   Token GetNextToken();
@@ -185,13 +180,8 @@
   // Helper function for ConsumeStringRaw() that consumes the next four or 10
   // bytes (parser is wound to the first character of a HEX sequence, with the
   // potential for consuming another \uXXXX for a surrogate). Returns true on
-  // success and places the UTF8 code units in |dest_string|, and false on
-  // failure.
-  bool DecodeUTF16(std::string* dest_string);
-  // Helper function for ConsumeStringRaw() that takes a single code point,
-  // decodes it into UTF-8 units, and appends it to the given builder. The
-  // point must be valid.
-  void DecodeUTF8(const int32_t& point, StringBuilder* dest);
+  // success and places the code point |out_code_point|, and false on failure.
+  bool DecodeUTF16(uint32_t* out_code_point);
 
   // Assuming that the parser is wound to the start of a valid JSON number,
   // this parses and converts it to either an int or double value.
@@ -204,8 +194,11 @@
   // parser is wound to the first character of any of those.
   Optional<Value> ConsumeLiteral();
 
-  // Compares two string buffers of a given length.
-  static bool StringsAreEqual(const char* left, const char* right, size_t len);
+  // Helper function that returns true if the byte squence |match| can be
+  // consumed at the current parser position. Returns false if there are fewer
+  // than |match|-length bytes or if the sequence does not match, and the
+  // parser state is unchanged.
+  bool ConsumeIfMatch(StringPiece match);
 
   // Sets the error information to |code| at the current column, based on
   // |index_| and |index_last_line_|, with an optional positive/negative
@@ -223,15 +216,8 @@
   // Maximum depth to parse.
   const int max_depth_;
 
-  // Pointer to the start of the input data.
-  const char* start_pos_;
-
-  // Pointer to the current position in the input data. Equivalent to
-  // |start_pos_ + index_|.
-  const char* pos_;
-
-  // Pointer to the last character of the input data.
-  const char* end_pos_;
+  // The input stream being parsed. Note: Not guaranteed to NUL-terminated.
+  StringPiece input_;
 
   // The index in the input stream to which the parser is wound.
   int index_;
diff --git a/base/json/json_parser_unittest.cc b/base/json/json_parser_unittest.cc
index e2f9e32e..eabcc381 100644
--- a/base/json/json_parser_unittest.cc
+++ b/base/json/json_parser_unittest.cc
@@ -23,9 +23,8 @@
   JSONParser* NewTestParser(const std::string& input,
                             int options = JSON_PARSE_RFC) {
     JSONParser* parser = new JSONParser(options);
-    parser->start_pos_ = input.data();
-    parser->pos_ = parser->start_pos_;
-    parser->end_pos_ = parser->start_pos_ + input.length();
+    parser->input_ = input;
+    parser->index_ = 0;
     return parser;
   }
 
@@ -41,10 +40,13 @@
   }
 
   void TestLastThree(JSONParser* parser) {
-    EXPECT_EQ(',', *parser->NextChar());
-    EXPECT_EQ('|', *parser->NextChar());
-    EXPECT_EQ('\0', *parser->NextChar());
-    EXPECT_EQ(parser->end_pos_, parser->pos_);
+    parser->NextChar();
+    EXPECT_EQ(',', parser->current_char());
+    parser->NextChar();
+    EXPECT_EQ('|', parser->current_char());
+    parser->NextChar();
+    EXPECT_EQ('\0', *parser->pos());
+    EXPECT_EQ(static_cast<size_t>(parser->index_), parser->input_.length());
   }
 };
 
@@ -52,18 +54,21 @@
   std::string input("Hello world");
   std::unique_ptr<JSONParser> parser(NewTestParser(input));
 
-  EXPECT_EQ('H', *parser->pos_);
+  EXPECT_EQ('H', *parser->pos());
   for (size_t i = 1; i < input.length(); ++i) {
-    EXPECT_EQ(input[i], *parser->NextChar());
+    parser->NextChar();
+    EXPECT_EQ(input[i], parser->current_char());
   }
-  EXPECT_EQ(parser->end_pos_, parser->NextChar());
+  parser->NextChar();
+  EXPECT_EQ('\0', *parser->pos());
+  EXPECT_EQ(static_cast<size_t>(parser->index_), parser->input_.length());
 }
 
 TEST_F(JSONParserTest, ConsumeString) {
   std::string input("\"test\",|");
   std::unique_ptr<JSONParser> parser(NewTestParser(input));
   Optional<Value> value(parser->ConsumeString());
-  EXPECT_EQ('"', *parser->pos_);
+  EXPECT_EQ('"', *parser->pos());
 
   TestLastThree(parser.get());
 
@@ -77,7 +82,7 @@
   std::string input("[true, false],|");
   std::unique_ptr<JSONParser> parser(NewTestParser(input));
   Optional<Value> value(parser->ConsumeList());
-  EXPECT_EQ(']', *parser->pos_);
+  EXPECT_EQ(']', *parser->pos());
 
   TestLastThree(parser.get());
 
@@ -91,7 +96,7 @@
   std::string input("{\"abc\":\"def\"},|");
   std::unique_ptr<JSONParser> parser(NewTestParser(input));
   Optional<Value> value(parser->ConsumeDictionary());
-  EXPECT_EQ('}', *parser->pos_);
+  EXPECT_EQ('}', *parser->pos());
 
   TestLastThree(parser.get());
 
@@ -108,7 +113,7 @@
   std::string input("true,|");
   std::unique_ptr<JSONParser> parser(NewTestParser(input));
   Optional<Value> value(parser->ConsumeLiteral());
-  EXPECT_EQ('e', *parser->pos_);
+  EXPECT_EQ('e', *parser->pos());
 
   TestLastThree(parser.get());
 
@@ -121,7 +126,7 @@
   input = "false,|";
   parser.reset(NewTestParser(input));
   value = parser->ConsumeLiteral();
-  EXPECT_EQ('e', *parser->pos_);
+  EXPECT_EQ('e', *parser->pos());
 
   TestLastThree(parser.get());
 
@@ -133,7 +138,7 @@
   input = "null,|";
   parser.reset(NewTestParser(input));
   value = parser->ConsumeLiteral();
-  EXPECT_EQ('l', *parser->pos_);
+  EXPECT_EQ('l', *parser->pos());
 
   TestLastThree(parser.get());
 
@@ -146,7 +151,7 @@
   std::string input("1234,|");
   std::unique_ptr<JSONParser> parser(NewTestParser(input));
   Optional<Value> value(parser->ConsumeNumber());
-  EXPECT_EQ('4', *parser->pos_);
+  EXPECT_EQ('4', *parser->pos());
 
   TestLastThree(parser.get());
 
@@ -159,7 +164,7 @@
   input = "-1234,|";
   parser.reset(NewTestParser(input));
   value = parser->ConsumeNumber();
-  EXPECT_EQ('4', *parser->pos_);
+  EXPECT_EQ('4', *parser->pos());
 
   TestLastThree(parser.get());
 
@@ -171,7 +176,7 @@
   input = "12.34,|";
   parser.reset(NewTestParser(input));
   value = parser->ConsumeNumber();
-  EXPECT_EQ('4', *parser->pos_);
+  EXPECT_EQ('4', *parser->pos());
 
   TestLastThree(parser.get());
 
@@ -184,7 +189,7 @@
   input = "42e3,|";
   parser.reset(NewTestParser(input));
   value = parser->ConsumeNumber();
-  EXPECT_EQ('3', *parser->pos_);
+  EXPECT_EQ('3', *parser->pos());
 
   TestLastThree(parser.get());
 
@@ -196,7 +201,7 @@
   input = "314159e-5,|";
   parser.reset(NewTestParser(input));
   value = parser->ConsumeNumber();
-  EXPECT_EQ('5', *parser->pos_);
+  EXPECT_EQ('5', *parser->pos());
 
   TestLastThree(parser.get());
 
@@ -208,7 +213,7 @@
   input = "0.42e+3,|";
   parser.reset(NewTestParser(input));
   value = parser->ConsumeNumber();
-  EXPECT_EQ('3', *parser->pos_);
+  EXPECT_EQ('3', *parser->pos());
 
   TestLastThree(parser.get());
 
diff --git a/base/json/json_reader.cc b/base/json/json_reader.cc
index 40ada3d..bf2a18a5 100644
--- a/base/json/json_reader.cc
+++ b/base/json/json_reader.cc
@@ -38,6 +38,8 @@
     "Unsupported encoding. JSON must be UTF-8.";
 const char JSONReader::kUnquotedDictionaryKey[] =
     "Dictionary keys must be quoted.";
+const char JSONReader::kInputTooLarge[] =
+    "Input string is too large (>2GB).";
 
 JSONReader::JSONReader(int options, int max_depth)
     : parser_(new internal::JSONParser(options, max_depth)) {}
@@ -99,10 +101,13 @@
       return kUnsupportedEncoding;
     case JSON_UNQUOTED_DICTIONARY_KEY:
       return kUnquotedDictionaryKey;
-    default:
-      NOTREACHED();
-      return std::string();
+    case JSON_TOO_LARGE:
+      return kInputTooLarge;
+    case JSON_PARSE_ERROR_COUNT:
+      break;
   }
+  NOTREACHED();
+  return std::string();
 }
 
 std::unique_ptr<Value> JSONReader::ReadToValue(StringPiece json) {
diff --git a/base/json/json_reader.h b/base/json/json_reader.h
index 1277a49..2c6bd3e 100644
--- a/base/json/json_reader.h
+++ b/base/json/json_reader.h
@@ -71,6 +71,7 @@
     JSON_UNEXPECTED_DATA_AFTER_ROOT,
     JSON_UNSUPPORTED_ENCODING,
     JSON_UNQUOTED_DICTIONARY_KEY,
+    JSON_TOO_LARGE,
     JSON_PARSE_ERROR_COUNT
   };
 
@@ -83,6 +84,7 @@
   static const char kUnexpectedDataAfterRoot[];
   static const char kUnsupportedEncoding[];
   static const char kUnquotedDictionaryKey[];
+  static const char kInputTooLarge[];
 
   // Constructs a reader.
   JSONReader(int options = JSON_PARSE_RFC, int max_depth = kStackMaxDepth);
diff --git a/base/logging.cc b/base/logging.cc
index 20550a7b..ea253b5 100644
--- a/base/logging.cc
+++ b/base/logging.cc
@@ -385,12 +385,12 @@
 
 }  // namespace
 
-#if DCHECK_IS_ON() && defined(SYZYASAN)
+#if DCHECK_IS_CONFIGURABLE
 // In DCHECK-enabled SyzyASAN builds, allow the meaning of LOG_DCHECK to be
 // determined at run-time. We default it to INFO, to avoid it triggering
 // crashes before the run-time has explicitly chosen the behaviour.
 BASE_EXPORT logging::LogSeverity LOG_DCHECK = LOG_INFO;
-#endif
+#endif  // DCHECK_IS_CONFIGURABLE
 
 // This is never instantiated, it's just used for EAT_STREAM_PARAMETERS to have
 // an object of the correct type on the LHS of the unused part of the ternary
diff --git a/base/logging.h b/base/logging.h
index 9f0c46a..1b97a4a 100644
--- a/base/logging.h
+++ b/base/logging.h
@@ -836,7 +836,7 @@
 
 #if DCHECK_IS_ON()
 
-#if defined(SYZYASAN)
+#if DCHECK_IS_CONFIGURABLE
 BASE_EXPORT extern LogSeverity LOG_DCHECK;
 #else
 const LogSeverity LOG_DCHECK = LOG_FATAL;
diff --git a/base/logging_unittest.cc b/base/logging_unittest.cc
index 7482a9e2..9025aaf4 100644
--- a/base/logging_unittest.cc
+++ b/base/logging_unittest.cc
@@ -412,7 +412,7 @@
 }
 void DcheckEmptyFunction2() {}
 
-#if DCHECK_IS_ON() && defined(SYZYASAN)
+#if DCHECK_IS_CONFIGURABLE
 class ScopedDcheckSeverity {
  public:
   ScopedDcheckSeverity(LogSeverity new_severity) : old_severity_(LOG_DCHECK) {
@@ -424,7 +424,7 @@
  private:
   LogSeverity old_severity_;
 };
-#endif  // DCHECK_IS_ON() && defined(SYZYASAN)
+#endif  // DCHECK_IS_CONFIGURABLE
 
 // https://crbug.com/709067 tracks test flakiness on iOS.
 #if defined(OS_IOS)
@@ -433,12 +433,12 @@
 #define MAYBE_Dcheck Dcheck
 #endif
 TEST_F(LoggingTest, MAYBE_Dcheck) {
-#if DCHECK_IS_ON() && defined(SYZYASAN)
-  // When DCHECKs are enabled in SyzyASAN builds, LOG_DCHECK is mutable but
-  // defaults to non-fatal. Set it to LOG_FATAL to get the expected behavior
-  // from the rest of this test.
+#if DCHECK_IS_CONFIGURABLE
+  // DCHECKs are enabled, and LOG_DCHECK is mutable, but defaults to non-fatal.
+  // Set it to LOG_FATAL to get the expected behavior from the rest of this
+  // test.
   ScopedDcheckSeverity dcheck_severity(LOG_FATAL);
-#endif  // DCHECK_IS_ON() && defined(SYZYASAN)
+#endif  // DCHECK_IS_CONFIGURABLE
 
 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
   // Release build.
@@ -599,9 +599,9 @@
   }
 }  // namespace nested_test
 
-#if DCHECK_IS_ON() && defined(SYZYASAN)
-TEST_F(LoggingTest, AsanConditionalDCheck) {
-  // Verify that DCHECKs default to non-fatal in SyzyASAN builds.
+#if DCHECK_IS_CONFIGURABLE
+TEST_F(LoggingTest, ConfigurableDCheck) {
+  // Verify that DCHECKs default to non-fatal in configurable-DCHECK builds.
   // Note that we require only that DCHECK is non-fatal by default, rather
   // than requiring that it be exactly INFO, ERROR, etc level.
   EXPECT_LT(LOG_DCHECK, LOG_FATAL);
@@ -625,8 +625,7 @@
   }
 }
 
-TEST_F(LoggingTest, AsanConditionalDCheckFeature) {
-  // Enable fatal DCHECKs, so that preconditions in
+TEST_F(LoggingTest, ConfigurableDCheckFeature) {
   // Initialize FeatureList with and without DcheckIsFatal, and verify the
   // value of LOG_DCHECK. Note that we don't require that DCHECK take a
   // specific value when the feature is off, only that it is non-fatal.
@@ -650,7 +649,7 @@
     EXPECT_LT(LOG_DCHECK, LOG_FATAL);
   }
 }
-#endif  // DCHECK_IS_ON() && defined(SYZYASAN)
+#endif  // DCHECK_IS_CONFIGURABLE
 
 #if defined(OS_FUCHSIA)
 TEST_F(LoggingTest, FuchsiaLogging) {
diff --git a/base/memory/discardable_shared_memory.cc b/base/memory/discardable_shared_memory.cc
index e9a2d63..2c14053c 100644
--- a/base/memory/discardable_shared_memory.cc
+++ b/base/memory/discardable_shared_memory.cc
@@ -112,11 +112,11 @@
 // base address at which |memory| is mapped, and that |offset| and |length|
 // are page-aligned by the caller.
 
+#if defined(OS_ANDROID)
 // Returns SUCCESS on platforms which do not support discardable pages.
 DiscardableSharedMemory::LockResult LockPages(const SharedMemory& memory,
                                               size_t offset,
                                               size_t length) {
-#if defined(OS_ANDROID)
   SharedMemoryHandle handle = memory.handle();
   if (handle.IsValid()) {
     int pin_result = ashmem_pin_region(handle.GetHandle(), offset, length);
@@ -125,9 +125,9 @@
     if (pin_result < 0)
       return DiscardableSharedMemory::FAILED;
   }
-#endif
   return DiscardableSharedMemory::SUCCESS;
 }
+#endif
 
 // UnlockPages() is a no-op on platforms not supporting discardable pages.
 void UnlockPages(const SharedMemory& memory, size_t offset, size_t length) {
@@ -265,9 +265,32 @@
   if (!length)
       return PURGED;
 
+#if defined(OS_ANDROID)
   // Ensure that the platform won't discard the required pages.
   return LockPages(shared_memory_,
                    AlignToPageSize(sizeof(SharedState)) + offset, length);
+#elif defined(OS_MACOSX)
+  // On macOS, there is no mechanism to lock pages. However, we do need to call
+  // madvise(MADV_FREE_REUSE) in order to correctly update accounting for memory
+  // footprint via task_info().
+  //
+  // Note that calling madvise(MADV_FREE_REUSE) on regions that haven't had
+  // madvise(MADV_FREE_REUSABLE) called on them has no effect.
+  //
+  // Note that the corresponding call to MADV_FREE_REUSABLE is in Purge(), since
+  // that's where the memory is actually released, rather than Unlock(), which
+  // is a no-op on macOS.
+  //
+  // For more information, see
+  // https://bugs.chromium.org/p/chromium/issues/detail?id=823915.
+  if (madvise(reinterpret_cast<char*>(shared_memory_.memory()) +
+                  AlignToPageSize(sizeof(SharedState)),
+              AlignToPageSize(mapped_size_), MADV_FREE_REUSE))
+    ;
+  return DiscardableSharedMemory::SUCCESS;
+#else
+  return DiscardableSharedMemory::SUCCESS;
+#endif
 }
 
 void DiscardableSharedMemory::Unlock(size_t offset, size_t length) {
diff --git a/base/memory/ref_counted_memory.cc b/base/memory/ref_counted_memory.cc
index c46bb9a..be981e32 100644
--- a/base/memory/ref_counted_memory.cc
+++ b/base/memory/ref_counted_memory.cc
@@ -42,7 +42,7 @@
 
 scoped_refptr<RefCountedBytes> RefCountedBytes::TakeVector(
     std::vector<unsigned char>* to_destroy) {
-  scoped_refptr<RefCountedBytes> bytes(new RefCountedBytes);
+  auto bytes = MakeRefCounted<RefCountedBytes>();
   bytes->data_.swap(*to_destroy);
   return bytes;
 }
@@ -66,7 +66,7 @@
 // static
 scoped_refptr<RefCountedString> RefCountedString::TakeString(
     std::string* to_destroy) {
-  scoped_refptr<RefCountedString> self(new RefCountedString);
+  auto self = MakeRefCounted<RefCountedString>();
   to_destroy->swap(self->data_);
   return self;
 }
diff --git a/base/memory/ref_counted_memory.h b/base/memory/ref_counted_memory.h
index ca7c371..9d29922 100644
--- a/base/memory/ref_counted_memory.h
+++ b/base/memory/ref_counted_memory.h
@@ -11,17 +11,16 @@
 #include <vector>
 
 #include "base/base_export.h"
-#include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 
 namespace base {
 
-// A generic interface to memory. This object is reference counted because one
-// of its two subclasses own the data they carry, and we need to have
-// heterogeneous containers of these two types of memory.
+// A generic interface to memory. This object is reference counted because most
+// of its subclasses own the data they carry, and this interface needs to
+// support heterogeneous containers of these different types of memory.
 class BASE_EXPORT RefCountedMemory
-    : public base::RefCountedThreadSafe<RefCountedMemory> {
+    : public RefCountedThreadSafe<RefCountedMemory> {
  public:
   // Retrieves a pointer to the beginning of the data we point to. If the data
   // is empty, this will return NULL.
@@ -39,7 +38,7 @@
   }
 
  protected:
-  friend class base::RefCountedThreadSafe<RefCountedMemory>;
+  friend class RefCountedThreadSafe<RefCountedMemory>;
   RefCountedMemory();
   virtual ~RefCountedMemory();
 };
@@ -48,13 +47,12 @@
 // matter.
 class BASE_EXPORT RefCountedStaticMemory : public RefCountedMemory {
  public:
-  RefCountedStaticMemory()
-      : data_(NULL), length_(0) {}
+  RefCountedStaticMemory() : data_(nullptr), length_(0) {}
   RefCountedStaticMemory(const void* data, size_t length)
-      : data_(static_cast<const unsigned char*>(length ? data : NULL)),
+      : data_(static_cast<const unsigned char*>(length ? data : nullptr)),
         length_(length) {}
 
-  // Overridden from RefCountedMemory:
+  // RefCountedMemory:
   const unsigned char* front() const override;
   size_t size() const override;
 
@@ -67,12 +65,13 @@
   DISALLOW_COPY_AND_ASSIGN(RefCountedStaticMemory);
 };
 
-// An implementation of RefCountedMemory, where we own the data in a vector.
+// An implementation of RefCountedMemory, where the data is stored in a STL
+// vector.
 class BASE_EXPORT RefCountedBytes : public RefCountedMemory {
  public:
   RefCountedBytes();
 
-  // Constructs a RefCountedBytes object by _copying_ from |initializer|.
+  // Constructs a RefCountedBytes object by copying from |initializer|.
   explicit RefCountedBytes(const std::vector<unsigned char>& initializer);
 
   // Constructs a RefCountedBytes object by copying |size| bytes from |p|.
@@ -88,7 +87,7 @@
   static scoped_refptr<RefCountedBytes> TakeVector(
       std::vector<unsigned char>* to_destroy);
 
-  // Overridden from RefCountedMemory:
+  // RefCountedMemory:
   const unsigned char* front() const override;
   size_t size() const override;
 
@@ -111,7 +110,7 @@
   DISALLOW_COPY_AND_ASSIGN(RefCountedBytes);
 };
 
-// An implementation of RefCountedMemory, where the bytes are stored in an STL
+// An implementation of RefCountedMemory, where the bytes are stored in a STL
 // string. Use this if your data naturally arrives in that format.
 class BASE_EXPORT RefCountedString : public RefCountedMemory {
  public:
@@ -122,7 +121,7 @@
   // copy into object->data()).
   static scoped_refptr<RefCountedString> TakeString(std::string* to_destroy);
 
-  // Overridden from RefCountedMemory:
+  // RefCountedMemory:
   const unsigned char* front() const override;
   size_t size() const override;
 
diff --git a/base/metrics/dummy_histogram.cc b/base/metrics/dummy_histogram.cc
new file mode 100644
index 0000000..2707733
--- /dev/null
+++ b/base/metrics/dummy_histogram.cc
@@ -0,0 +1,102 @@
+// 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 "base/metrics/dummy_histogram.h"
+
+#include <memory>
+
+#include "base/logging.h"
+#include "base/metrics/histogram_samples.h"
+#include "base/metrics/metrics_hashes.h"
+
+namespace base {
+
+namespace {
+
+// Helper classes for DummyHistogram.
+class DummySampleCountIterator : public SampleCountIterator {
+ public:
+  DummySampleCountIterator() {}
+  ~DummySampleCountIterator() override {}
+
+  // SampleCountIterator:
+  bool Done() const override { return true; }
+  void Next() override { NOTREACHED(); }
+  void Get(HistogramBase::Sample* min,
+           int64_t* max,
+           HistogramBase::Count* count) const override {
+    NOTREACHED();
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DummySampleCountIterator);
+};
+
+class DummyHistogramSamples : public HistogramSamples {
+ public:
+  explicit DummyHistogramSamples() : HistogramSamples(0, new LocalMetadata()) {}
+  ~DummyHistogramSamples() override {
+    delete static_cast<LocalMetadata*>(meta());
+  }
+
+  // HistogramSamples:
+  void Accumulate(HistogramBase::Sample value,
+                  HistogramBase::Count count) override {}
+  HistogramBase::Count GetCount(HistogramBase::Sample value) const override {
+    return HistogramBase::Count();
+  }
+  HistogramBase::Count TotalCount() const override {
+    return HistogramBase::Count();
+  }
+  std::unique_ptr<SampleCountIterator> Iterator() const override {
+    return std::make_unique<DummySampleCountIterator>();
+  }
+  bool AddSubtractImpl(SampleCountIterator* iter, Operator op) override {
+    return true;
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DummyHistogramSamples);
+};
+
+}  // namespace
+
+// static
+DummyHistogram* DummyHistogram::GetInstance() {
+  static base::NoDestructor<DummyHistogram> dummy_histogram;
+  return dummy_histogram.get();
+}
+
+uint64_t DummyHistogram::name_hash() const {
+  return HashMetricName(histogram_name());
+}
+
+HistogramType DummyHistogram::GetHistogramType() const {
+  return DUMMY_HISTOGRAM;
+}
+
+bool DummyHistogram::HasConstructionArguments(
+    Sample expected_minimum,
+    Sample expected_maximum,
+    uint32_t expected_bucket_count) const {
+  return true;
+}
+
+bool DummyHistogram::AddSamplesFromPickle(PickleIterator* iter) {
+  return true;
+}
+
+std::unique_ptr<HistogramSamples> DummyHistogram::SnapshotSamples() const {
+  return std::make_unique<DummyHistogramSamples>();
+}
+
+std::unique_ptr<HistogramSamples> DummyHistogram::SnapshotDelta() {
+  return std::make_unique<DummyHistogramSamples>();
+}
+
+std::unique_ptr<HistogramSamples> DummyHistogram::SnapshotFinalDelta() const {
+  return std::make_unique<DummyHistogramSamples>();
+}
+
+}  // namespace base
diff --git a/base/metrics/dummy_histogram.h b/base/metrics/dummy_histogram.h
new file mode 100644
index 0000000..e2cb64e
--- /dev/null
+++ b/base/metrics/dummy_histogram.h
@@ -0,0 +1,61 @@
+// 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 BASE_METRICS_DUMMY_HISTOGRAM_H_
+#define BASE_METRICS_DUMMY_HISTOGRAM_H_
+
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+
+#include "base/base_export.h"
+#include "base/metrics/histogram_base.h"
+#include "base/no_destructor.h"
+
+namespace base {
+
+// DummyHistogram is used for mocking histogram objects for histograms that
+// shouldn't be recorded. It doesn't do any actual processing.
+class BASE_EXPORT DummyHistogram : public HistogramBase {
+ public:
+  static DummyHistogram* GetInstance();
+
+  // HistogramBase:
+  void CheckName(const StringPiece& name) const override {}
+  uint64_t name_hash() const override;
+  HistogramType GetHistogramType() const override;
+  bool HasConstructionArguments(Sample expected_minimum,
+                                Sample expected_maximum,
+                                uint32_t expected_bucket_count) const override;
+  void Add(Sample value) override {}
+  void AddCount(Sample value, int count) override {}
+  void AddSamples(const HistogramSamples& samples) override {}
+  bool AddSamplesFromPickle(PickleIterator* iter) override;
+  std::unique_ptr<HistogramSamples> SnapshotSamples() const override;
+  std::unique_ptr<HistogramSamples> SnapshotDelta() override;
+  std::unique_ptr<HistogramSamples> SnapshotFinalDelta() const override;
+  void WriteHTMLGraph(std::string* output) const override {}
+  void WriteAscii(std::string* output) const override {}
+
+ protected:
+  // HistogramBase:
+  void SerializeInfoImpl(Pickle* pickle) const override {}
+  void GetParameters(DictionaryValue* params) const override {}
+  void GetCountAndBucketData(Count* count,
+                             int64_t* sum,
+                             ListValue* buckets) const override {}
+
+ private:
+  friend class NoDestructor<DummyHistogram>;
+
+  DummyHistogram() : HistogramBase("dummy_histogram") {}
+  ~DummyHistogram() override {}
+
+  DISALLOW_COPY_AND_ASSIGN(DummyHistogram);
+};
+
+}  // namespace base
+
+#endif  // BASE_METRICS_DUMMY_HISTOGRAM_H_
diff --git a/base/metrics/field_trial.cc b/base/metrics/field_trial.cc
index 8e3a21b..1eb90a1 100644
--- a/base/metrics/field_trial.cc
+++ b/base/metrics/field_trial.cc
@@ -1443,15 +1443,14 @@
   FieldTrialAllocator* allocator = global_->field_trial_allocator_.get();
 
   // Check if we're in the child process and return early if so.
-  if (allocator && allocator->IsReadonly())
+  if (!allocator || allocator->IsReadonly())
     return;
 
   FieldTrial::FieldTrialRef ref = field_trial->ref_;
   if (ref == FieldTrialAllocator::kReferenceNull) {
     // It's fine to do this even if the allocator hasn't been instantiated
     // yet -- it'll just return early.
-    AddToAllocatorWhileLocked(global_->field_trial_allocator_.get(),
-                              field_trial);
+    AddToAllocatorWhileLocked(allocator, field_trial);
   } else {
     // It's also okay to do this even though the callee doesn't have a lock --
     // the only thing that happens on a stale read here is a slight performance
diff --git a/base/metrics/histogram.cc b/base/metrics/histogram.cc
index 91d1a78..5960905 100644
--- a/base/metrics/histogram.cc
+++ b/base/metrics/histogram.cc
@@ -21,6 +21,7 @@
 #include "base/debug/alias.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
+#include "base/metrics/dummy_histogram.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/metrics_hashes.h"
 #include "base/metrics/persistent_histogram_allocator.h"
@@ -75,6 +76,11 @@
 
 bool ValidateRangeChecksum(const HistogramBase& histogram,
                            uint32_t range_checksum) {
+  // Normally, |histogram| should have type HISTOGRAM or be inherited from it.
+  // However, if it's expired, it will actually be a DUMMY_HISTOGRAM.
+  // Skip the checks in that case.
+  if (histogram.GetHistogramType() == DUMMY_HISTOGRAM)
+    return true;
   const Histogram& casted_histogram =
       static_cast<const Histogram&>(histogram);
 
@@ -152,6 +158,12 @@
 HistogramBase* Histogram::Factory::Build() {
   HistogramBase* histogram = StatisticsRecorder::FindHistogram(name_);
   if (!histogram) {
+    // TODO(gayane): |HashMetricName()| is called again in Histogram
+    // constructor. Refactor code to avoid the additional call.
+    bool should_record =
+        StatisticsRecorder::ShouldRecordHistogram(HashMetricName(name_));
+    if (!should_record)
+      return DummyHistogram::GetInstance();
     // To avoid racy destruction at shutdown, the following will be leaked.
     const BucketRanges* created_ranges = CreateRanges();
     const BucketRanges* registered_ranges =
@@ -807,6 +819,11 @@
 
   void FillHistogram(HistogramBase* base_histogram) override {
     Histogram::Factory::FillHistogram(base_histogram);
+    // Normally, |base_histogram| should have type LINEAR_HISTOGRAM or be
+    // inherited from it. However, if it's expired, it will actually be a
+    // DUMMY_HISTOGRAM. Skip filling in that case.
+    if (base_histogram->GetHistogramType() == DUMMY_HISTOGRAM)
+      return;
     LinearHistogram* histogram = static_cast<LinearHistogram*>(base_histogram);
     // Set range descriptions.
     if (descriptions_) {
diff --git a/base/metrics/histogram_base.cc b/base/metrics/histogram_base.cc
index 868e0cb5..d8ae483b 100644
--- a/base/metrics/histogram_base.cc
+++ b/base/metrics/histogram_base.cc
@@ -39,6 +39,8 @@
       return "CUSTOM_HISTOGRAM";
     case SPARSE_HISTOGRAM:
       return "SPARSE_HISTOGRAM";
+    case DUMMY_HISTOGRAM:
+      return "DUMMY_HISTOGRAM";
   }
   NOTREACHED();
   return "UNKNOWN";
diff --git a/base/metrics/histogram_base.h b/base/metrics/histogram_base.h
index ab8a1b8..1971a65 100644
--- a/base/metrics/histogram_base.h
+++ b/base/metrics/histogram_base.h
@@ -39,6 +39,7 @@
   BOOLEAN_HISTOGRAM,
   CUSTOM_HISTOGRAM,
   SPARSE_HISTOGRAM,
+  DUMMY_HISTOGRAM,
 };
 
 // Controls the verbosity of the information when the histogram is serialized to
@@ -150,10 +151,10 @@
 
   const char* histogram_name() const { return histogram_name_; }
 
-  // Comapres |name| to the histogram name and triggers a DCHECK if they do not
+  // Compares |name| to the histogram name and triggers a DCHECK if they do not
   // match. This is a helper function used by histogram macros, which results in
   // in more compact machine code being generated by the macros.
-  void CheckName(const StringPiece& name) const;
+  virtual void CheckName(const StringPiece& name) const;
 
   // Get a unique ID for this histogram's samples.
   virtual uint64_t name_hash() const = 0;
diff --git a/base/metrics/histogram_samples.h b/base/metrics/histogram_samples.h
index 23237b0..6908873c 100644
--- a/base/metrics/histogram_samples.h
+++ b/base/metrics/histogram_samples.h
@@ -199,6 +199,9 @@
   Metadata* meta() { return meta_; }
 
  private:
+  // Depending on derived class meta values can come from local stoarge or
+  // external storage in which case HistogramSamples class cannot take ownership
+  // of Metadata*.
   Metadata* meta_;
 
   DISALLOW_COPY_AND_ASSIGN(HistogramSamples);
diff --git a/base/metrics/histogram_unittest.cc b/base/metrics/histogram_unittest.cc
index c824eb7..97e7ad3 100644
--- a/base/metrics/histogram_unittest.cc
+++ b/base/metrics/histogram_unittest.cc
@@ -16,8 +16,10 @@
 #include "base/logging.h"
 #include "base/metrics/bucket_ranges.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/metrics/metrics_hashes.h"
 #include "base/metrics/persistent_histogram_allocator.h"
 #include "base/metrics/persistent_memory_allocator.h"
+#include "base/metrics/record_histogram_checker.h"
 #include "base/metrics/sample_vector.h"
 #include "base/metrics/statistics_recorder.h"
 #include "base/pickle.h"
@@ -27,6 +29,22 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace base {
+namespace {
+
+const char kExpiredHistogramName[] = "ExpiredHistogram";
+
+// Test implementation of RecordHistogramChecker interface.
+class TestRecordHistogramChecker : public RecordHistogramChecker {
+ public:
+  ~TestRecordHistogramChecker() override = default;
+
+  // RecordHistogramChecker:
+  bool ShouldRecord(uint64_t histogram_hash) const override {
+    return histogram_hash != HashMetricName(kExpiredHistogramName);
+  }
+};
+
+}  // namespace
 
 // Test parameter indicates if a persistent memory allocator should be used
 // for histogram allocation. False will allocate histograms from the process
@@ -58,6 +76,8 @@
   void InitializeStatisticsRecorder() {
     DCHECK(!statistics_recorder_);
     statistics_recorder_ = StatisticsRecorder::CreateTemporaryForTesting();
+    auto record_checker = std::make_unique<TestRecordHistogramChecker>();
+    StatisticsRecorder::SetRecordChecker(std::move(record_checker));
   }
 
   void UninitializeStatisticsRecorder() {
@@ -769,4 +789,57 @@
                "");
 }
 
+TEST_P(HistogramTest, ExpiredHistogramTest) {
+  HistogramBase* expired = Histogram::FactoryGet(kExpiredHistogramName, 1, 1000,
+                                                 10, HistogramBase::kNoFlags);
+  ASSERT_TRUE(expired);
+  expired->Add(5);
+  expired->Add(500);
+  auto samples = expired->SnapshotDelta();
+  EXPECT_EQ(0, samples->TotalCount());
+
+  HistogramBase* linear_expired = LinearHistogram::FactoryGet(
+      kExpiredHistogramName, 1, 1000, 10, HistogramBase::kNoFlags);
+  ASSERT_TRUE(linear_expired);
+  linear_expired->Add(5);
+  linear_expired->Add(500);
+  samples = linear_expired->SnapshotDelta();
+  EXPECT_EQ(0, samples->TotalCount());
+
+  std::vector<int> custom_ranges;
+  custom_ranges.push_back(1);
+  custom_ranges.push_back(5);
+  HistogramBase* custom_expired = CustomHistogram::FactoryGet(
+      kExpiredHistogramName, custom_ranges, HistogramBase::kNoFlags);
+  ASSERT_TRUE(custom_expired);
+  custom_expired->Add(2);
+  custom_expired->Add(4);
+  samples = custom_expired->SnapshotDelta();
+  EXPECT_EQ(0, samples->TotalCount());
+
+  HistogramBase* valid = Histogram::FactoryGet("ValidHistogram", 1, 1000, 10,
+                                               HistogramBase::kNoFlags);
+  ASSERT_TRUE(valid);
+  valid->Add(5);
+  valid->Add(500);
+  samples = valid->SnapshotDelta();
+  EXPECT_EQ(2, samples->TotalCount());
+
+  HistogramBase* linear_valid = LinearHistogram::FactoryGet(
+      "LinearHistogram", 1, 1000, 10, HistogramBase::kNoFlags);
+  ASSERT_TRUE(linear_valid);
+  linear_valid->Add(5);
+  linear_valid->Add(500);
+  samples = linear_valid->SnapshotDelta();
+  EXPECT_EQ(2, samples->TotalCount());
+
+  HistogramBase* custom_valid = CustomHistogram::FactoryGet(
+      "CustomHistogram", custom_ranges, HistogramBase::kNoFlags);
+  ASSERT_TRUE(custom_valid);
+  custom_valid->Add(2);
+  custom_valid->Add(4);
+  samples = custom_valid->SnapshotDelta();
+  EXPECT_EQ(2, samples->TotalCount());
+}
+
 }  // namespace base
diff --git a/base/metrics/sparse_histogram.cc b/base/metrics/sparse_histogram.cc
index e33fd3c8..30175a0 100644
--- a/base/metrics/sparse_histogram.cc
+++ b/base/metrics/sparse_histogram.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/memory/ptr_util.h"
+#include "base/metrics/dummy_histogram.h"
 #include "base/metrics/metrics_hashes.h"
 #include "base/metrics/persistent_histogram_allocator.h"
 #include "base/metrics/persistent_sample_map.h"
@@ -26,6 +27,12 @@
                                            int32_t flags) {
   HistogramBase* histogram = StatisticsRecorder::FindHistogram(name);
   if (!histogram) {
+    // TODO(gayane): |HashMetricName| is called again in Histogram constructor.
+    // Refactor code to avoid the additional call.
+    bool should_record =
+        StatisticsRecorder::ShouldRecordHistogram(HashMetricName(name));
+    if (!should_record)
+      return DummyHistogram::GetInstance();
     // Try to create the histogram using a "persistent" allocator. As of
     // 2016-02-25, the availability of such is controlled by a base::Feature
     // that is off by default. If the allocator doesn't exist or if
diff --git a/base/metrics/statistics_recorder.h b/base/metrics/statistics_recorder.h
index 03651a9..87a9311 100644
--- a/base/metrics/statistics_recorder.h
+++ b/base/metrics/statistics_recorder.h
@@ -200,9 +200,6 @@
   // method must be called very early, before any threads have started.
   // Record checker methods can be called on any thread, so they shouldn't
   // mutate any state.
-  //
-  // TODO(iburak): This is not yet hooked up to histogram recording
-  // infrastructure.
   static void SetRecordChecker(
       std::unique_ptr<RecordHistogramChecker> record_checker);
 
diff --git a/base/optional.h b/base/optional.h
index d7c2122..1192940 100644
--- a/base/optional.h
+++ b/base/optional.h
@@ -153,7 +153,8 @@
       Init(other.value_);
   }
 
-  OptionalStorage(OptionalStorage&& other) {
+  OptionalStorage(OptionalStorage&& other) noexcept(
+      std::is_nothrow_move_constructible<T>::value) {
     if (other.is_populated_)
       Init(std::move(other.value_));
   }
@@ -172,7 +173,8 @@
   OptionalStorage() = default;
   OptionalStorage(const OptionalStorage& other) = default;
 
-  OptionalStorage(OptionalStorage&& other) {
+  OptionalStorage(OptionalStorage&& other) noexcept(
+      std::is_nothrow_move_constructible<T>::value) {
     if (other.is_populated_)
       Init(std::move(other.value_));
   }
diff --git a/base/optional_unittest.cc b/base/optional_unittest.cc
index 18025f06..7bdb46b 100644
--- a/base/optional_unittest.cc
+++ b/base/optional_unittest.cc
@@ -2115,27 +2115,58 @@
 }
 
 TEST(OptionalTest, Noexcept) {
-  // non-noexcept move-constructible.
+  // Trivial copy ctor, non-trivial move ctor, nothrow move assign.
   struct Test1 {
+    Test1(const Test1&) = default;
     Test1(Test1&&) {}
     Test1& operator=(Test1&&) = default;
   };
-  // non-noexcept move-assignable.
+  // Non-trivial copy ctor, trivial move ctor, throw move assign.
   struct Test2 {
+    Test2(const Test2&) {}
     Test2(Test2&&) = default;
     Test2& operator=(Test2&&) { return *this; }
   };
+  // Trivial copy ctor, non-trivial nothrow move ctor.
+  struct Test3 {
+    Test3(const Test3&) = default;
+    Test3(Test3&&) noexcept {}
+  };
+  // Non-trivial copy ctor, non-trivial nothrow move ctor.
+  struct Test4 {
+    Test4(const Test4&) {}
+    Test4(Test4&&) noexcept {}
+  };
+  // Non-trivial copy ctor, non-trivial move ctor.
+  struct Test5 {
+    Test5(const Test5&) {}
+    Test5(Test5&&) {}
+  };
 
   static_assert(
       noexcept(Optional<int>(std::declval<Optional<int>>())),
-      "move constructor for noexcept move-constructible T must be noexcept");
+      "move constructor for noexcept move-constructible T must be noexcept "
+      "(trivial copy, trivial move)");
   static_assert(
       !noexcept(Optional<Test1>(std::declval<Optional<Test1>>())),
       "move constructor for non-noexcept move-constructible T must not be "
-      "noexcept");
+      "noexcept (trivial copy)");
   static_assert(
       noexcept(Optional<Test2>(std::declval<Optional<Test2>>())),
-      "move constructor for noexcept move-constructible T must be noexcept");
+      "move constructor for noexcept move-constructible T must be noexcept "
+      "(non-trivial copy, trivial move)");
+  static_assert(
+      noexcept(Optional<Test3>(std::declval<Optional<Test3>>())),
+      "move constructor for noexcept move-constructible T must be noexcept "
+      "(trivial copy, non-trivial move)");
+  static_assert(
+      noexcept(Optional<Test4>(std::declval<Optional<Test4>>())),
+      "move constructor for noexcept move-constructible T must be noexcept "
+      "(non-trivial copy, non-trivial move)");
+  static_assert(
+      !noexcept(Optional<Test5>(std::declval<Optional<Test5>>())),
+      "move constructor for non-noexcept move-constructible T must not be "
+      "noexcept (non-trivial copy)");
 
   static_assert(
       noexcept(std::declval<Optional<int>>() = std::declval<Optional<int>>()),
diff --git a/base/process/process_metrics.h b/base/process/process_metrics.h
index 45e9f07..3ae373f 100644
--- a/base/process/process_metrics.h
+++ b/base/process/process_metrics.h
@@ -41,58 +41,6 @@
 // Full declaration is in process_metrics_iocounters.h.
 struct IoCounters;
 
-// Working Set (resident) memory usage broken down by
-//
-// On Windows:
-// priv (private): These pages (kbytes) cannot be shared with any other process.
-// shareable:      These pages (kbytes) can be shared with other processes under
-//                 the right circumstances.
-// shared :        These pages (kbytes) are currently shared with at least one
-//                 other process.
-//
-// On Linux:
-// priv:           Pages mapped only by this process.
-// shared:         PSS or 0 if the kernel doesn't support this.
-// shareable:      0
-
-// On ChromeOS:
-// priv:           Pages mapped only by this process.
-// shared:         PSS or 0 if the kernel doesn't support this.
-// shareable:      0
-// swapped         Pages swapped out to zram.
-//
-// On macOS:
-// priv:           Resident size (RSS) including shared memory. Warning: This
-//                 does not include compressed size and does not always
-//                 accurately account for shared memory due to things like
-//                 copy-on-write. TODO(erikchen): Revamp this with something
-//                 more accurate.
-// shared:         0
-// shareable:      0
-//
-struct WorkingSetKBytes {
-  WorkingSetKBytes() : priv(0), shareable(0), shared(0) {}
-  size_t priv;
-  size_t shareable;
-  size_t shared;
-#if defined(OS_CHROMEOS)
-  size_t swapped;
-#endif
-};
-
-// Committed (resident + paged) memory usage broken down by
-// private: These pages cannot be shared with any other process.
-// mapped:  These pages are mapped into the view of a section (backed by
-//          pagefile.sys)
-// image:   These pages are mapped into the view of an image section (backed by
-//          file system)
-struct CommittedKBytes {
-  CommittedKBytes() : priv(0), mapped(0), image(0) {}
-  size_t priv;
-  size_t mapped;
-  size_t image;
-};
-
 #if defined(OS_LINUX) || defined(OS_ANDROID)
 // Minor and major page fault counts since the process creation.
 // Both counts are process-wide, and exclude child processes.
@@ -108,11 +56,20 @@
 // Convert a POSIX timeval to microseconds.
 BASE_EXPORT int64_t TimeValToMicroseconds(const struct timeval& tv);
 
-// Provides performance metrics for a specified process (CPU usage, memory and
-// IO counters). Use CreateCurrentProcessMetrics() to get an instance for the
+// Provides performance metrics for a specified process (CPU usage and IO
+// counters). Use CreateCurrentProcessMetrics() to get an instance for the
 // current process, or CreateProcessMetrics() to get an instance for an
 // arbitrary process. Then, access the information with the different get
 // methods.
+//
+// This class exposes a few platform-specific APIs for parsing memory usage, but
+// these are not intended to generalize to other platforms, since the memory
+// models differ substantially.
+//
+// To obtain consistent memory metrics, use the memory_instrumentation service.
+//
+// For further documentation on memory, see
+// https://chromium.googlesource.com/chromium/src/+/HEAD/docs/README.md
 class BASE_EXPORT ProcessMetrics {
  public:
   ~ProcessMetrics();
@@ -135,27 +92,27 @@
   // convenience wrapper for CreateProcessMetrics().
   static std::unique_ptr<ProcessMetrics> CreateCurrentProcessMetrics();
 
-  // Fills a CommittedKBytes with both resident and paged
-  // memory usage as per definition of CommittedBytes.
-  void GetCommittedKBytes(CommittedKBytes* usage) const;
-  // Fills a WorkingSetKBytes containing resident private and shared memory
-  // usage in bytes, as per definition of WorkingSetBytes. Note that this
-  // function is somewhat expensive on Windows (a few ms per process).
-  bool GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const;
-
 #if defined(OS_LINUX) || defined(OS_ANDROID)
   // Resident Set Size is a Linux/Android specific memory concept. Do not
   // attempt to extend this to other platforms.
   BASE_EXPORT size_t GetResidentSetSize() const;
 #endif
 
-#if defined(OS_MACOSX)
-  // Fills both CommitedKBytes and WorkingSetKBytes in a single operation. This
-  // is more efficient on Mac OS X, as the two can be retrieved with a single
-  // system call.
-  bool GetCommittedAndWorkingSetKBytes(CommittedKBytes* usage,
-                                       WorkingSetKBytes* ws_usage) const;
+#if defined(OS_CHROMEOS)
+  // /proc/<pid>/totmaps is a syscall that returns memory summary statistics for
+  // the process.
+  // totmaps is a Linux specific concept, currently only being used on ChromeOS.
+  // Do not attempt to extend this to other platforms.
+  //
+  struct TotalsSummary {
+    size_t private_clean_kb;
+    size_t private_dirty_kb;
+    size_t swap_kb;
+  };
+  BASE_EXPORT TotalsSummary GetTotalsSummary() const;
+#endif
 
+#if defined(OS_MACOSX)
   struct TaskVMInfo {
     // Only available on macOS 10.12+.
     // Anonymous, non-discardable memory, including non-volatile IOKit.
@@ -243,14 +200,6 @@
   ProcessMetrics(ProcessHandle process, PortProvider* port_provider);
 #endif  // !defined(OS_MACOSX) || defined(OS_IOS)
 
-#if defined(OS_LINUX) || defined(OS_ANDROID) | defined(OS_AIX)
-  bool GetWorkingSetKBytesStatm(WorkingSetKBytes* ws_usage) const;
-#endif
-
-#if defined(OS_CHROMEOS)
-  bool GetWorkingSetKBytesTotmaps(WorkingSetKBytes *ws_usage) const;
-#endif
-
 #if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_AIX)
   int CalculateIdleWakeupsPerSecond(uint64_t absolute_idle_wakeups);
 #endif
@@ -270,7 +219,9 @@
   // Used to store the previous times and CPU usage counts so we can
   // compute the CPU usage between calls.
   TimeTicks last_cpu_time_;
+#if defined(OS_WIN) || defined(OS_MACOSX)
   int64_t last_system_time_;
+#endif
 
 #if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_AIX)
   // Same thing for idle wakeups.
diff --git a/base/process/process_metrics_freebsd.cc b/base/process/process_metrics_freebsd.cc
index 45385e16..4dee9980 100644
--- a/base/process/process_metrics_freebsd.cc
+++ b/base/process/process_metrics_freebsd.cc
@@ -17,7 +17,6 @@
 
 ProcessMetrics::ProcessMetrics(ProcessHandle process)
     : process_(process),
-      last_system_time_(0),
       last_cpu_(0) {}
 
 // static
@@ -26,31 +25,6 @@
   return WrapUnique(new ProcessMetrics(process));
 }
 
-namespace {
-size_t GetWorkingSetSize() {
-  struct kinfo_proc info;
-  int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, process_ };
-  size_t length = sizeof(info);
-
-  if (sysctl(mib, arraysize(mib), &info, &length, NULL, 0) < 0)
-    return 0;
-
-  return info.ki_rssize * getpagesize();
-}
-}  // namespace
-
-bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const {
-// TODO(bapt) be sure we can't be precise
-  size_t priv = GetWorkingSetSize();
-  if (!priv)
-    return false;
-  ws_usage->priv = priv / 1024;
-  ws_usage->shareable = 0;
-  ws_usage->shared = 0;
-
-  return true;
-}
-
 double ProcessMetrics::GetPlatformIndependentCPUUsage() {
   struct kinfo_proc info;
   int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, process_ };
diff --git a/base/process/process_metrics_fuchsia.cc b/base/process/process_metrics_fuchsia.cc
index 5cad1fb..3710c30 100644
--- a/base/process/process_metrics_fuchsia.cc
+++ b/base/process/process_metrics_fuchsia.cc
@@ -30,11 +30,6 @@
   return 0.0;
 }
 
-bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const {
-  NOTIMPLEMENTED();  // TODO(fuchsia): https://crbug.com/706592.
-  return false;
-}
-
 bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo) {
   NOTIMPLEMENTED();  // TODO(fuchsia): https://crbug.com/706592.
   return false;
diff --git a/base/process/process_metrics_linux.cc b/base/process/process_metrics_linux.cc
index aec4f625f..e13f9e7 100644
--- a/base/process/process_metrics_linux.cc
+++ b/base/process/process_metrics_linux.cc
@@ -216,14 +216,6 @@
       getpagesize();
 }
 
-bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const {
-#if defined(OS_CHROMEOS)
-  if (GetWorkingSetKBytesTotmaps(ws_usage))
-    return true;
-#endif
-  return GetWorkingSetKBytesStatm(ws_usage);
-}
-
 double ProcessMetrics::GetPlatformIndependentCPUUsage() {
   TimeTicks time = TimeTicks::Now();
 
@@ -366,7 +358,6 @@
 
 ProcessMetrics::ProcessMetrics(ProcessHandle process)
     : process_(process),
-      last_system_time_(0),
 #if defined(OS_LINUX) || defined(OS_AIX)
       last_absolute_idle_wakeups_(0),
 #endif
@@ -376,8 +367,7 @@
 #if defined(OS_CHROMEOS)
 // Private, Shared and Proportional working set sizes are obtained from
 // /proc/<pid>/totmaps
-bool ProcessMetrics::GetWorkingSetKBytesTotmaps(WorkingSetKBytes *ws_usage)
-  const {
+ProcessMetrics::TotalsSummary ProcessMetrics::GetTotalsSummary() const {
   // The format of /proc/<pid>/totmaps is:
   //
   // Rss:                6120 kB
@@ -391,7 +381,8 @@
   // AnonHugePages:       XXX kB
   // Swap:                XXX kB
   // Locked:              XXX kB
-  const size_t kPssIndex = (1 * 3) + 1;
+  ProcessMetrics::TotalsSummary summary = {};
+
   const size_t kPrivate_CleanIndex = (4 * 3) + 1;
   const size_t kPrivate_DirtyIndex = (5 * 3) + 1;
   const size_t kSwapIndex = (9 * 3) + 1;
@@ -402,86 +393,37 @@
     ThreadRestrictions::ScopedAllowIO allow_io;
     bool ret = ReadFileToString(totmaps_file, &totmaps_data);
     if (!ret || totmaps_data.length() == 0)
-      return false;
+      return summary;
   }
 
   std::vector<std::string> totmaps_fields = SplitString(
       totmaps_data, kWhitespaceASCII, KEEP_WHITESPACE, SPLIT_WANT_NONEMPTY);
 
-  DCHECK_EQ("Pss:", totmaps_fields[kPssIndex-1]);
   DCHECK_EQ("Private_Clean:", totmaps_fields[kPrivate_CleanIndex - 1]);
   DCHECK_EQ("Private_Dirty:", totmaps_fields[kPrivate_DirtyIndex - 1]);
   DCHECK_EQ("Swap:", totmaps_fields[kSwapIndex-1]);
 
-  int pss = 0;
-  int private_clean = 0;
-  int private_dirty = 0;
-  int swap = 0;
-  bool ret = true;
-  ret &= StringToInt(totmaps_fields[kPssIndex], &pss);
-  ret &= StringToInt(totmaps_fields[kPrivate_CleanIndex], &private_clean);
-  ret &= StringToInt(totmaps_fields[kPrivate_DirtyIndex], &private_dirty);
-  ret &= StringToInt(totmaps_fields[kSwapIndex], &swap);
+  int private_clean_kb = 0;
+  int private_dirty_kb = 0;
+  int swap_kb = 0;
+  bool success = true;
+  success &=
+      StringToInt(totmaps_fields[kPrivate_CleanIndex], &private_clean_kb);
+  success &=
+      StringToInt(totmaps_fields[kPrivate_DirtyIndex], &private_dirty_kb);
+  success &= StringToInt(totmaps_fields[kSwapIndex], &swap_kb);
 
-  // On ChromeOS, swap goes to zram. Count this as private / shared, as
-  // increased swap decreases available RAM to user processes, which would
-  // otherwise create surprising results.
-  ws_usage->priv = private_clean + private_dirty + swap;
-  ws_usage->shared = pss + swap;
-  ws_usage->shareable = 0;
-  ws_usage->swapped = swap;
-  return ret;
+  if (!success)
+    return summary;
+
+  summary.private_clean_kb = private_clean_kb;
+  summary.private_dirty_kb = private_dirty_kb;
+  summary.swap_kb = swap_kb;
+
+  return summary;
 }
 #endif
 
-// Private and Shared working set sizes are obtained from /proc/<pid>/statm.
-bool ProcessMetrics::GetWorkingSetKBytesStatm(WorkingSetKBytes* ws_usage)
-    const {
-  // Use statm instead of smaps because smaps is:
-  // a) Large and slow to parse.
-  // b) Unavailable in the SUID sandbox.
-
-  // First get the page size, since everything is measured in pages.
-  // For details, see: man 5 proc.
-  const int page_size_kb = getpagesize() / 1024;
-  if (page_size_kb <= 0)
-    return false;
-
-  std::string statm;
-  {
-    FilePath statm_file = internal::GetProcPidDir(process_).Append("statm");
-    // Synchronously reading files in /proc does not hit the disk.
-    ThreadRestrictions::ScopedAllowIO allow_io;
-    bool ret = ReadFileToString(statm_file, &statm);
-    if (!ret || statm.length() == 0)
-      return false;
-  }
-
-  std::vector<StringPiece> statm_vec =
-      SplitStringPiece(statm, " ", TRIM_WHITESPACE, SPLIT_WANT_ALL);
-  if (statm_vec.size() != 7)
-    return false;  // Not the expected format.
-
-  int statm_rss;
-  int statm_shared;
-  bool ret = true;
-  ret &= StringToInt(statm_vec[1], &statm_rss);
-  ret &= StringToInt(statm_vec[2], &statm_shared);
-
-  ws_usage->priv = (statm_rss - statm_shared) * page_size_kb;
-  ws_usage->shared = statm_shared * page_size_kb;
-
-  // Sharable is not calculated, as it does not provide interesting data.
-  ws_usage->shareable = 0;
-
-#if defined(OS_CHROMEOS)
-  // Can't get swapped memory from statm.
-  ws_usage->swapped = 0;
-#endif
-
-  return ret;
-}
-
 size_t GetSystemCommitCharge() {
   SystemMemoryInfoKB meminfo;
   if (!GetSystemMemoryInfo(&meminfo))
diff --git a/base/process/process_metrics_mac.cc b/base/process/process_metrics_mac.cc
index 91e249d..148253f 100644
--- a/base/process/process_metrics_mac.cc
+++ b/base/process/process_metrics_mac.cc
@@ -105,36 +105,6 @@
   return WrapUnique(new ProcessMetrics(process, port_provider));
 }
 
-void ProcessMetrics::GetCommittedKBytes(CommittedKBytes* usage) const {
-  WorkingSetKBytes unused;
-  if (!GetCommittedAndWorkingSetKBytes(usage, &unused)) {
-    *usage = CommittedKBytes();
-  }
-}
-
-bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const {
-  CommittedKBytes unused;
-  return GetCommittedAndWorkingSetKBytes(&unused, ws_usage);
-}
-
-bool ProcessMetrics::GetCommittedAndWorkingSetKBytes(
-    CommittedKBytes* usage,
-    WorkingSetKBytes* ws_usage) const {
-  task_basic_info_64 task_info_data;
-  if (!GetTaskInfo(TaskForPid(process_), &task_info_data))
-    return false;
-
-  usage->priv = task_info_data.virtual_size / 1024;
-  usage->mapped = 0;
-  usage->image = 0;
-
-  ws_usage->priv = task_info_data.resident_size / 1024;
-  ws_usage->shareable = 0;
-  ws_usage->shared = 0;
-
-  return true;
-}
-
 ProcessMetrics::TaskVMInfo ProcessMetrics::GetTaskVMInfo() const {
   TaskVMInfo info;
   ChromeTaskVMInfo task_vm_info;
diff --git a/base/process/process_metrics_openbsd.cc b/base/process/process_metrics_openbsd.cc
index 40d810f..3bb1ac5c 100644
--- a/base/process/process_metrics_openbsd.cc
+++ b/base/process/process_metrics_openbsd.cc
@@ -21,37 +21,6 @@
   return WrapUnique(new ProcessMetrics(process));
 }
 
-namespace {
-size_t GetWorkingSetSize() {
-  struct kinfo_proc info;
-  size_t length;
-  int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, process_,
-                sizeof(struct kinfo_proc), 0 };
-
-  if (sysctl(mib, arraysize(mib), NULL, &length, NULL, 0) < 0)
-    return -1;
-
-  mib[5] = (length / sizeof(struct kinfo_proc));
-
-  if (sysctl(mib, arraysize(mib), &info, &length, NULL, 0) < 0)
-    return -1;
-
-  return info.p_vm_rssize * getpagesize();
-}
-}  // namespace
-
-bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const {
-  // TODO(bapt): be sure we can't be precise
-  size_t priv = GetWorkingSetSize();
-  if (!priv)
-    return false;
-  ws_usage->priv = priv / 1024;
-  ws_usage->shareable = 0;
-  ws_usage->shared = 0;
-
-  return true;
-}
-
 bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const {
   return false;
 }
@@ -101,7 +70,6 @@
 
 ProcessMetrics::ProcessMetrics(ProcessHandle process)
     : process_(process),
-      last_system_time_(0),
       last_cpu_(0) {}
 
 size_t GetSystemCommitCharge() {
diff --git a/base/process/process_metrics_win.cc b/base/process/process_metrics_win.cc
index 32b9282..faabdbf 100644
--- a/base/process/process_metrics_win.cc
+++ b/base/process/process_metrics_win.cc
@@ -46,42 +46,6 @@
   return WrapUnique(new ProcessMetrics(process));
 }
 
-void ProcessMetrics::GetCommittedKBytes(CommittedKBytes* usage) const {
-  MEMORY_BASIC_INFORMATION mbi = {0};
-  size_t committed_private = 0;
-  size_t committed_mapped = 0;
-  size_t committed_image = 0;
-  void* base_address = NULL;
-  while (VirtualQueryEx(process_.Get(), base_address, &mbi, sizeof(mbi)) ==
-         sizeof(mbi)) {
-    if (mbi.State == MEM_COMMIT) {
-      if (mbi.Type == MEM_PRIVATE) {
-        committed_private += mbi.RegionSize;
-      } else if (mbi.Type == MEM_MAPPED) {
-        committed_mapped += mbi.RegionSize;
-      } else if (mbi.Type == MEM_IMAGE) {
-        committed_image += mbi.RegionSize;
-      } else {
-        NOTREACHED();
-      }
-    }
-    void* new_base = (static_cast<BYTE*>(mbi.BaseAddress)) + mbi.RegionSize;
-    // Avoid infinite loop by weird MEMORY_BASIC_INFORMATION.
-    // If we query 64bit processes in a 32bit process, VirtualQueryEx()
-    // returns such data.
-    if (new_base <= base_address) {
-      usage->image = 0;
-      usage->mapped = 0;
-      usage->priv = 0;
-      return;
-    }
-    base_address = new_base;
-  }
-  usage->image = committed_image / 1024;
-  usage->mapped = committed_mapped / 1024;
-  usage->priv = committed_private / 1024;
-}
-
 namespace {
 
 class WorkingSetInformationBuffer {
@@ -164,36 +128,6 @@
 
 }  // namespace
 
-bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const {
-  size_t ws_private = 0;
-  size_t ws_shareable = 0;
-  size_t ws_shared = 0;
-
-  DCHECK(ws_usage);
-  memset(ws_usage, 0, sizeof(*ws_usage));
-
-  WorkingSetInformationBuffer buffer;
-  if (!buffer.QueryPageEntries(process_.Get()))
-    return false;
-
-  size_t num_page_entries = buffer.GetPageEntryCount();
-  for (size_t i = 0; i < num_page_entries; i++) {
-    if (buffer->WorkingSetInfo[i].Shared) {
-      ws_shareable++;
-      if (buffer->WorkingSetInfo[i].ShareCount > 1)
-        ws_shared++;
-    } else {
-      ws_private++;
-    }
-  }
-
-  ws_usage->priv = ws_private * PAGESIZE_KB;
-  ws_usage->shareable = ws_shareable * PAGESIZE_KB;
-  ws_usage->shared = ws_shared * PAGESIZE_KB;
-
-  return true;
-}
-
 static uint64_t FileTimeToUTC(const FILETIME& ftime) {
   LARGE_INTEGER li;
   li.LowPart = ftime.dwLowDateTime;
@@ -244,11 +178,11 @@
 
 ProcessMetrics::ProcessMetrics(ProcessHandle process) : last_system_time_(0) {
   if (process) {
-    HANDLE duplicate_handle;
+    HANDLE duplicate_handle = INVALID_HANDLE_VALUE;
     BOOL result = ::DuplicateHandle(::GetCurrentProcess(), process,
                                     ::GetCurrentProcess(), &duplicate_handle,
                                     PROCESS_QUERY_INFORMATION, FALSE, 0);
-    DCHECK(result);
+    DPCHECK(result);
     process_.Set(duplicate_handle);
   }
 }
diff --git a/base/strings/utf_string_conversions_fuzzer.cc b/base/strings/utf_string_conversions_fuzzer.cc
new file mode 100644
index 0000000..37d4be2
--- /dev/null
+++ b/base/strings/utf_string_conversions_fuzzer.cc
@@ -0,0 +1,56 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+
+std::string output_std_string;
+std::wstring output_std_wstring;
+base::string16 output_string16;
+
+// Entry point for LibFuzzer.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  base::StringPiece string_piece_input(reinterpret_cast<const char*>(data),
+                                       size);
+
+  base::UTF8ToWide(string_piece_input);
+  base::UTF8ToWide(reinterpret_cast<const char*>(data), size,
+                   &output_std_wstring);
+  base::UTF8ToUTF16(string_piece_input);
+  base::UTF8ToUTF16(reinterpret_cast<const char*>(data), size,
+                    &output_string16);
+
+  // Test for char16.
+  if (size % 2 == 0) {
+    base::StringPiece16 string_piece_input16(
+        reinterpret_cast<const base::char16*>(data), size / 2);
+    base::UTF16ToWide(output_string16);
+    base::UTF16ToWide(reinterpret_cast<const base::char16*>(data), size / 2,
+                      &output_std_wstring);
+    base::UTF16ToUTF8(string_piece_input16);
+    base::UTF16ToUTF8(reinterpret_cast<const base::char16*>(data), size / 2,
+                      &output_std_string);
+  }
+
+  // Test for wchar_t.
+  size_t wchar_t_size = sizeof(wchar_t);
+  if (size % wchar_t_size == 0) {
+    base::WideToUTF8(output_std_wstring);
+    base::WideToUTF8(reinterpret_cast<const wchar_t*>(data),
+                     size / wchar_t_size, &output_std_string);
+    base::WideToUTF16(output_std_wstring);
+    base::WideToUTF16(reinterpret_cast<const wchar_t*>(data),
+                      size / wchar_t_size, &output_string16);
+  }
+
+  // Test for ASCII. This condition is needed to avoid hitting instant CHECK
+  // failures.
+  if (base::IsStringASCII(string_piece_input)) {
+    output_string16 = base::ASCIIToUTF16(string_piece_input);
+    base::StringPiece16 string_piece_input16(output_string16);
+    base::UTF16ToASCII(string_piece_input16);
+  }
+
+  return 0;
+}
diff --git a/base/sys_info.h b/base/sys_info.h
index 6e58715..a2f20c7 100644
--- a/base/sys_info.h
+++ b/base/sys_info.h
@@ -64,6 +64,16 @@
   // on failure.
   static int64_t AmountOfTotalDiskSpace(const FilePath& path);
 
+#if defined(OS_POSIX) && !defined(OS_ANDROID)
+  // Returns the total number of inodes on the volume containing |path|, or -1
+  // on failure.
+  static int64_t AmountOfMaxDiskInode(const FilePath& path);
+
+  // Returns the number of inodes available to non-root on the volume containing
+  // |path|, or -1 on failure.
+  static int64_t AmountOfAvailableDiskInode(const FilePath& path);
+#endif
+
   // Returns system uptime.
   static TimeDelta Uptime();
 
diff --git a/base/sys_info_posix.cc b/base/sys_info_posix.cc
index f6fcd10..27de28a 100644
--- a/base/sys_info_posix.cc
+++ b/base/sys_info_posix.cc
@@ -237,4 +237,20 @@
   return getpagesize();
 }
 
+#if !defined(OS_ANDROID)
+int64_t SysInfo::AmountOfMaxDiskInode(const FilePath& path) {
+  struct statvfs stats;
+  if (HANDLE_EINTR(statvfs(path.value().c_str(), &stats)) != 0)
+    return -1;
+  return static_cast<int64_t>(stats.f_files);
+}
+
+int64_t SysInfo::AmountOfAvailableDiskInode(const FilePath& path) {
+  struct statvfs stats;
+  if (HANDLE_EINTR(statvfs(path.value().c_str(), &stats)) != 0)
+    return -1;
+  return static_cast<int64_t>(stats.f_favail);
+}
+#endif  // !defined(OS_ANDROID)
+
 }  // namespace base
diff --git a/base/test/android/javatests/src/org/chromium/base/test/BaseChromiumAndroidJUnitRunner.java b/base/test/android/javatests/src/org/chromium/base/test/BaseChromiumAndroidJUnitRunner.java
index d36e847f87..ce898611 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/BaseChromiumAndroidJUnitRunner.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/BaseChromiumAndroidJUnitRunner.java
@@ -22,6 +22,7 @@
 
 import dalvik.system.DexFile;
 
+import org.chromium.base.BuildConfig;
 import org.chromium.base.Log;
 import org.chromium.base.multidex.ChromiumMultiDexInstaller;
 
@@ -70,9 +71,25 @@
     @Override
     public Application newApplication(ClassLoader cl, String className, Context context)
             throws ClassNotFoundException, IllegalAccessException, InstantiationException {
-        ChromiumMultiDexInstaller.install(new BaseChromiumRunnerCommon.MultiDexContextWrapper(
-                getContext(), getTargetContext()));
-        BaseChromiumRunnerCommon.reorderDexPathElements(cl, getContext(), getTargetContext());
+        // The multidex support library doesn't currently support having the test apk be multidex
+        // as well as the under-test apk being multidex. If MultiDex.install() is called for both,
+        // then re-extraction is triggered every time due to the support library caching only a
+        // single timestamp & crc.
+        //
+        // Attempt to install test apk multidex only if the apk-under-test is not multidex.
+        // It will likely continue to be true that the two are mutually exclusive because:
+        // * ProGuard enabled =>
+        //      Under-test apk is single dex.
+        //      Test apk duplicates under-test classes, so may need multidex.
+        // * ProGuard disabled =>
+        //      Under-test apk might be multidex
+        //      Test apk does not duplicate classes, so does not need multidex.
+        // https://crbug.com/824523
+        if (!BuildConfig.IS_MULTIDEX_ENABLED) {
+            ChromiumMultiDexInstaller.install(new BaseChromiumRunnerCommon.MultiDexContextWrapper(
+                    getContext(), getTargetContext()));
+            BaseChromiumRunnerCommon.reorderDexPathElements(cl, getContext(), getTargetContext());
+        }
         return super.newApplication(cl, className, context);
     }
 
diff --git a/base/threading/thread.h b/base/threading/thread.h
index a88d70f7..8237a23 100644
--- a/base/threading/thread.h
+++ b/base/threading/thread.h
@@ -271,9 +271,6 @@
   static bool GetThreadWasQuitProperly();
 
   // Bind this Thread to an existing MessageLoop instead of starting a new one.
-  // TODO(gab): Remove this after ios/ has undergone the same surgery as
-  // BrowserThreadImpl (ref.
-  // https://chromium-review.googlesource.com/c/chromium/src/+/969104).
   void SetMessageLoop(MessageLoop* message_loop);
 
   bool using_external_message_loop() const {
diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h
index 0cc506c..fa97031 100644
--- a/base/threading/thread_restrictions.h
+++ b/base/threading/thread_restrictions.h
@@ -38,7 +38,6 @@
 class BrowserGpuChannelHostFactory;
 class BrowserGpuMemoryBufferManager;
 class BrowserMainLoop;
-class BrowserProcessSubThread;
 class BrowserShutdownProfileDumper;
 class BrowserSurfaceViewManager;
 class BrowserTestBase;
@@ -212,7 +211,6 @@
   // in unit tests to avoid the friend requirement.
   FRIEND_TEST_ALL_PREFIXES(ThreadRestrictionsTest, ScopedAllowBlocking);
   friend class android_webview::ScopedAllowInitGLBindings;
-  friend class content::BrowserProcessSubThread;
   friend class cronet::CronetPrefsManager;
   friend class cronet::CronetURLRequestContext;
   friend class resource_coordinator::TabManagerDelegate;  // crbug.com/778703
diff --git a/base/trace_event/memory_dump_manager.h b/base/trace_event/memory_dump_manager.h
index 331f931..d6237fd 100644
--- a/base/trace_event/memory_dump_manager.h
+++ b/base/trace_event/memory_dump_manager.h
@@ -240,7 +240,6 @@
   virtual ~MemoryDumpManager();
 
   static void SetInstanceForTesting(MemoryDumpManager* instance);
-  static uint32_t GetDumpsSumKb(const std::string&, const ProcessMemoryDump*);
 
   // Lazily initializes dump_thread_ and returns its TaskRunner.
   scoped_refptr<base::SequencedTaskRunner> GetOrCreateBgTaskRunnerLocked();
diff --git a/base/trace_event/memory_infra_background_whitelist.cc b/base/trace_event/memory_infra_background_whitelist.cc
index df33eb4..22330ce 100644
--- a/base/trace_event/memory_infra_background_whitelist.cc
+++ b/base/trace_event/memory_infra_background_whitelist.cc
@@ -79,6 +79,7 @@
     "blink_objects/V8PerContextData",
     "blink_objects/WorkerGlobalScope",
     "blink_objects/UACSSResource",
+    "blink_objects/ResourceFetcher",
     "components/download/controller_0x?",
     "discardable",
     "discardable/child_0x?",
diff --git a/build/android/PRESUBMIT.py b/build/android/PRESUBMIT.py
index be0c6dca..dcd53468 100644
--- a/build/android/PRESUBMIT.py
+++ b/build/android/PRESUBMIT.py
@@ -35,7 +35,8 @@
           J('..', '..', 'third_party', 'catapult', 'common', 'py_trace_event'),
           J('..', '..', 'third_party', 'catapult', 'common', 'py_utils'),
           J('..', '..', 'third_party', 'catapult', 'devil'),
-          J('..', '..', 'third_party', 'catapult', 'tracing')
+          J('..', '..', 'third_party', 'catapult', 'tracing'),
+          J('..', '..', 'third_party', 'depot_tools'),
       ]))
   output.extend(input_api.canned_checks.RunPylint(
       input_api,
diff --git a/build/android/apk_operations.py b/build/android/apk_operations.py
index 740ae5c..3119e49 100755
--- a/build/android/apk_operations.py
+++ b/build/android/apk_operations.py
@@ -123,7 +123,10 @@
         flags = []
         if argv:
           flags = shlex.split(argv)
-        changer.ReplaceFlags(flags)
+        try:
+          changer.ReplaceFlags(flags)
+        except device_errors.AdbShellCommandFailedError:
+          logging.exception('Failed to set flags')
 
     if url is None:
       # Simulate app icon click if no url is present.
diff --git a/build/android/gyp/compile_resources.py b/build/android/gyp/compile_resources.py
new file mode 100755
index 0000000..9426024
--- /dev/null
+++ b/build/android/gyp/compile_resources.py
@@ -0,0 +1,632 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Compile Android resources into an intermediate APK.
+
+This can also generate an R.txt, and an .srcjar file containing the proper
+final R.java class for all resource packages the APK depends on.
+
+This will crunch images with aapt2.
+"""
+
+import argparse
+import collections
+import multiprocessing.pool
+import os
+import re
+import shutil
+import subprocess
+import sys
+import zipfile
+from xml.etree import ElementTree
+
+
+from util import build_utils
+from util import resource_utils
+
+_SOURCE_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(
+    __file__))))
+# Import jinja2 from third_party/jinja2
+sys.path.insert(1, os.path.join(_SOURCE_ROOT, 'third_party'))
+from jinja2 import Template # pylint: disable=F0401
+
+# A variation of this lists also exists in:
+# //base/android/java/src/org/chromium/base/LocaleUtils.java
+_CHROME_TO_ANDROID_LOCALE_MAP = {
+    'en-GB': 'en-rGB',
+    'en-US': 'en-rUS',
+    'es-419': 'es-rUS',
+    'fil': 'tl',
+    'he': 'iw',
+    'id': 'in',
+    'pt-PT': 'pt-rPT',
+    'pt-BR': 'pt-rBR',
+    'yi': 'ji',
+    'zh-CN': 'zh-rCN',
+    'zh-TW': 'zh-rTW',
+}
+
+# Pngs that we shouldn't convert to webp. Please add rationale when updating.
+_PNG_WEBP_BLACKLIST_PATTERN = re.compile('|'.join([
+    # Crashes on Galaxy S5 running L (https://crbug.com/807059).
+    r'.*star_gray\.png',
+    # Android requires pngs for 9-patch images.
+    r'.*\.9\.png',
+    # Daydream (*.dd) requires pngs for icon files.
+    r'.*\.dd\.png']))
+
+# Regular expression for package declaration in 'aapt dump resources' output.
+_RE_PACKAGE_DECLARATION = re.compile(
+    r'^Package Group ([0-9]+) id=0x([0-9a-fA-F]+)')
+
+
+def _PackageIdArgument(x):
+  """Convert a string into a package ID while checking its range.
+
+  Args:
+    x: argument string.
+  Returns:
+    the package ID as an int, or -1 in case of error.
+  """
+  try:
+    x = int(x, 0)
+    if x < 0 or x > 127:
+      x = -1
+  except ValueError:
+    x = -1
+  return x
+
+
+def _ParseArgs(args):
+  """Parses command line options.
+
+  Returns:
+    An options object as from argparse.ArgumentParser.parse_args()
+  """
+  parser, input_opts, output_opts = resource_utils.ResourceArgsParser()
+
+  input_opts.add_argument('--android-manifest', required=True,
+                          help='AndroidManifest.xml path')
+
+  input_opts.add_argument(
+      '--shared-resources',
+      action='store_true',
+      help='Make all resources in R.java non-final and allow the resource IDs '
+           'to be reset to a different package index when the apk is loaded by '
+           'another application at runtime.')
+
+  input_opts.add_argument(
+      '--app-as-shared-lib',
+      action='store_true',
+      help='Same as --shared-resources, but also ensures all resource IDs are '
+           'directly usable from the APK loaded as an application.')
+
+  input_opts.add_argument(
+      '--shared-resources-whitelist',
+      help='An R.txt file acting as a whitelist for resources that should be '
+           'non-final and have their package ID changed at runtime in R.java. '
+           'Implies and overrides --shared-resources.')
+
+  input_opts.add_argument('--support-zh-hk', action='store_true',
+                          help='Use zh-rTW resources for zh-rHK.')
+
+  input_opts.add_argument('--debuggable',
+                          action='store_true',
+                          help='Whether to add android:debuggable="true"')
+
+  input_opts.add_argument('--version-code', help='Version code for apk.')
+  input_opts.add_argument('--version-name', help='Version name for apk.')
+
+  input_opts.add_argument(
+      '--no-compress',
+      help='disables compression for the given comma-separated list of '
+           'extensions')
+
+  input_opts.add_argument(
+      '--locale-whitelist',
+      default='[]',
+      help='GN list of languages to include. All other language configs will '
+          'be stripped out. List may include a combination of Android locales '
+          'or Chrome locales.')
+
+  input_opts.add_argument('--exclude-xxxhdpi', action='store_true',
+                          help='Do not include xxxhdpi drawables.')
+
+  input_opts.add_argument(
+      '--xxxhdpi-whitelist',
+      default='[]',
+      help='GN list of globs that say which xxxhdpi images to include even '
+           'when --exclude-xxxhdpi is set.')
+
+  input_opts.add_argument('--png-to-webp', action='store_true',
+                          help='Convert png files to webp format.')
+
+  input_opts.add_argument('--webp-binary', default='',
+                          help='Path to the cwebp binary.')
+
+  input_opts.add_argument('--no-xml-namespaces',
+                          action='store_true',
+                          help='Whether to strip xml namespaces from processed '
+                               'xml resources')
+
+  input_opts.add_argument(
+      '--check-resources-pkg-id', type=_PackageIdArgument,
+      help='Check the package ID of the generated resources table. '
+           'Value must be integer in [0..127] range.')
+
+  output_opts.add_argument('--apk-path', required=True,
+                           help='Path to output (partial) apk.')
+
+  output_opts.add_argument('--srcjar-out',
+                           help='Path to srcjar to contain generated R.java.')
+
+  output_opts.add_argument('--r-text-out',
+                           help='Path to store the generated R.txt file.')
+
+  output_opts.add_argument('--proguard-file',
+                           help='Path to proguard.txt generated file')
+
+  output_opts.add_argument(
+      '--proguard-file-main-dex',
+      help='Path to proguard.txt generated file for main dex')
+
+  options = parser.parse_args(args)
+
+  resource_utils.HandleCommonOptions(options)
+
+  options.locale_whitelist = build_utils.ParseGnList(options.locale_whitelist)
+  options.xxxhdpi_whitelist = build_utils.ParseGnList(options.xxxhdpi_whitelist)
+
+  if options.check_resources_pkg_id is not None:
+    if options.check_resources_pkg_id < 0:
+      raise Exception(
+          'Package resource id should be integer in [0..127] range.')
+
+  if options.shared_resources and options.app_as_shared_lib:
+    raise Exception('Only one of --app-as-shared-lib or --shared-resources '
+                    'can be used.')
+
+  return options
+
+
+def _ExtractPackageIdFromApk(apk_path, aapt_path):
+  """Extract the package ID of a given APK (even intermediate ones).
+
+  Args:
+    apk_path: Input apk path.
+    aapt_path: Path to aapt tool.
+  Returns:
+    An integer corresponding to the APK's package id.
+  Raises:
+    Exception if there is no resources table in the input file.
+  """
+  cmd_args = [ aapt_path, 'dump', 'resources', apk_path ]
+  output = build_utils.CheckOutput(cmd_args)
+
+  for line in output.splitlines():
+    m = _RE_PACKAGE_DECLARATION.match(line)
+    if m:
+      return int(m.group(2), 16)
+
+  raise Exception("No resources in this APK!")
+
+
+def _SortZip(original_path, sorted_path):
+  """Generate new zip archive by sorting all files in the original by name."""
+  with zipfile.ZipFile(sorted_path, 'w') as sorted_zip, \
+      zipfile.ZipFile(original_path, 'r') as original_zip:
+    for info in sorted(original_zip.infolist(), key=lambda i: i.filename):
+      sorted_zip.writestr(info, original_zip.read(info))
+
+
+def _DuplicateZhResources(resource_dirs):
+  """Duplicate Taiwanese resources into Hong-Kong specific directory."""
+  for resource_dir in resource_dirs:
+    # We use zh-TW resources for zh-HK (if we have zh-TW resources).
+    for path in build_utils.IterFiles(resource_dir):
+      if 'zh-rTW' in path:
+        hk_path = path.replace('zh-rTW', 'zh-rHK')
+        build_utils.MakeDirectory(os.path.dirname(hk_path))
+        shutil.copyfile(path, hk_path)
+
+
+def _ToAaptLocales(locale_whitelist, support_zh_hk):
+  """Converts the list of Chrome locales to aapt config locales."""
+  ret = set()
+  for locale in locale_whitelist:
+    locale = _CHROME_TO_ANDROID_LOCALE_MAP.get(locale, locale)
+    if locale is None or ('-' in locale and '-r' not in locale):
+      raise Exception('_CHROME_TO_ANDROID_LOCALE_MAP needs updating.'
+                      ' Found: %s' % locale)
+    ret.add(locale)
+    # Always keep non-regional fall-backs.
+    language = locale.split('-')[0]
+    ret.add(language)
+
+  # We don't actually support zh-HK in Chrome on Android, but we mimic the
+  # native side behavior where we use zh-TW resources when the locale is set to
+  # zh-HK. See https://crbug.com/780847.
+  if support_zh_hk:
+    assert not any('HK' in l for l in locale_whitelist), (
+        'Remove special logic if zh-HK is now supported (crbug.com/780847).')
+    ret.add('zh-rHK')
+  return sorted(ret)
+
+
+def _MoveImagesToNonMdpiFolders(res_root):
+  """Move images from drawable-*-mdpi-* folders to drawable-* folders.
+
+  Why? http://crbug.com/289843
+  """
+  for src_dir_name in os.listdir(res_root):
+    src_components = src_dir_name.split('-')
+    if src_components[0] != 'drawable' or 'mdpi' not in src_components:
+      continue
+    src_dir = os.path.join(res_root, src_dir_name)
+    if not os.path.isdir(src_dir):
+      continue
+    dst_components = [c for c in src_components if c != 'mdpi']
+    assert dst_components != src_components
+    dst_dir_name = '-'.join(dst_components)
+    dst_dir = os.path.join(res_root, dst_dir_name)
+    build_utils.MakeDirectory(dst_dir)
+    for src_file_name in os.listdir(src_dir):
+      if not os.path.splitext(src_file_name)[1] in ('.png', '.webp'):
+        continue
+      src_file = os.path.join(src_dir, src_file_name)
+      dst_file = os.path.join(dst_dir, src_file_name)
+      assert not os.path.lexists(dst_file)
+      shutil.move(src_file, dst_file)
+
+
+def _CreateLinkApkArgs(options):
+  """Create command-line arguments list to invoke 'aapt2 link'.
+
+  Args:
+    options: The command-line options tuple.
+  Returns:
+    A list of strings corresponding to the command-line invokation for
+    the command, matching the arguments from |options|.
+  """
+  link_command = [
+    options.aapt_path + '2',
+    'link',
+    '--version-code', options.version_code,
+    '--version-name', options.version_name,
+    '--auto-add-overlay',
+    '--no-version-vectors',
+    '-I', options.android_sdk_jar,
+    '-o', options.apk_path,
+  ]
+
+  if options.proguard_file:
+    link_command += ['--proguard', options.proguard_file]
+  if options.proguard_file_main_dex:
+    link_command += ['--proguard-main-dex', options.proguard_file_main_dex]
+
+  if options.no_compress:
+    for ext in options.no_compress.split(','):
+      link_command += ['-0', ext]
+
+  if options.shared_resources:
+    link_command.append('--shared-lib')
+
+  if options.locale_whitelist:
+    aapt_locales = _ToAaptLocales(
+        options.locale_whitelist, options.support_zh_hk)
+    link_command += ['-c', ','.join(aapt_locales)]
+
+  if options.no_xml_namespaces:
+    link_command.append('--no-xml-namespaces')
+
+  return link_command
+
+
+def _ExtractVersionFromSdk(aapt_path, sdk_path):
+  """Extract version code and name from Android SDK .jar file.
+
+  Args:
+    aapt_path: Path to 'aapt' build tool.
+    sdk_path: Path to SDK-specific android.jar file.
+  Returns:
+    A (version_code, version_name) pair of strings.
+  """
+  output = subprocess.check_output([aapt_path, 'dump', 'badging', sdk_path])
+  version_code = re.search(r"versionCode='(.*?)'", output).group(1)
+  version_name = re.search(r"versionName='(.*?)'", output).group(1)
+  return version_code, version_name,
+
+
+def _FixManifest(options, temp_dir):
+  """Fix the APK's AndroidManifest.xml.
+
+  This adds any missing namespaces for 'android' and 'tools', and
+  sets certains elements like 'platformBuildVersionCode' or
+  'android:debuggable' depending on the content of |options|.
+
+  Args:
+    options: The command-line arguments tuple.
+    temp_dir: A temporary directory where the fixed manifest will be written to.
+  Returns:
+    Path to the fixed manifest within |temp_dir|.
+  """
+  debug_manifest_path = os.path.join(temp_dir, 'AndroidManifest.xml')
+  _ANDROID_NAMESPACE = 'http://schemas.android.com/apk/res/android'
+  _TOOLS_NAMESPACE = 'http://schemas.android.com/tools'
+  ElementTree.register_namespace('android', _ANDROID_NAMESPACE)
+  ElementTree.register_namespace('tools', _TOOLS_NAMESPACE)
+  original_manifest = ElementTree.parse(options.android_manifest)
+
+  version_code, version_name = _ExtractVersionFromSdk(
+      options.aapt_path, options.android_sdk_jar)
+
+  # ElementTree.find does not work if the required tag is the root.
+  if original_manifest.getroot().tag == 'manifest':
+    manifest_node = original_manifest.getroot()
+  else:
+    manifest_node = original_manifest.find('manifest')
+
+  manifest_node.set('platformBuildVersionCode', version_code)
+  manifest_node.set('platformBuildVersionName', version_name)
+
+  if options.debuggable:
+    app_node = original_manifest.find('application')
+    app_node.set('{%s}%s' % (_ANDROID_NAMESPACE, 'debuggable'), 'true')
+
+  with open(debug_manifest_path, 'w') as debug_manifest:
+    debug_manifest.write(ElementTree.tostring(
+        original_manifest.getroot(), encoding='UTF-8'))
+
+  return debug_manifest_path
+
+
+def _ResourceNameFromPath(path):
+  return os.path.splitext(os.path.basename(path))[0]
+
+
+def _CreateKeepPredicate(resource_dirs, exclude_xxxhdpi, xxxhdpi_whitelist):
+  """Return a predicate lambda to determine which resource files to keep."""
+  if not exclude_xxxhdpi:
+    # Do not extract dotfiles (e.g. ".gitkeep"). aapt ignores them anyways.
+    return lambda path: os.path.basename(path)[0] != '.'
+
+  # Returns False only for xxxhdpi non-mipmap, non-whitelisted drawables.
+  naive_predicate = lambda path: (
+      not re.search(r'[/-]xxxhdpi[/-]', path) or
+      re.search(r'[/-]mipmap[/-]', path) or
+      build_utils.MatchesGlob(path, xxxhdpi_whitelist))
+
+  # Build a set of all non-xxxhdpi drawables to ensure that we never exclude any
+  # xxxhdpi drawable that does not exist in other densities.
+  non_xxxhdpi_drawables = set()
+  for resource_dir in resource_dirs:
+    for path in build_utils.IterFiles(resource_dir):
+      if re.search(r'[/-]drawable[/-]', path) and naive_predicate(path):
+        non_xxxhdpi_drawables.add(_ResourceNameFromPath(path))
+
+  return lambda path: (naive_predicate(path) or
+                       _ResourceNameFromPath(path) not in non_xxxhdpi_drawables)
+
+
+def _ConvertToWebP(webp_binary, png_files):
+  pool = multiprocessing.pool.ThreadPool(10)
+  def convert_image(png_path):
+    root = os.path.splitext(png_path)[0]
+    webp_path = root + '.webp'
+    args = [webp_binary, png_path, '-mt', '-quiet', '-m', '6', '-q', '100',
+        '-lossless', '-o', webp_path]
+    subprocess.check_call(args)
+    os.remove(png_path)
+
+  pool.map(convert_image, [f for f in png_files
+                           if not _PNG_WEBP_BLACKLIST_PATTERN.match(f)])
+  pool.close()
+  pool.join()
+
+
+def _CompileDeps(aapt_path, dep_subdirs, temp_dir):
+  partials_dir = os.path.join(temp_dir, 'partials')
+  build_utils.MakeDirectory(partials_dir)
+  partial_compile_command = [
+      aapt_path + '2',
+      'compile',
+      # TODO(wnwen): Turn this on once aapt2 forces 9-patch to be crunched.
+      # '--no-crunch',
+  ]
+  pool = multiprocessing.pool.ThreadPool(10)
+  def compile_partial(directory):
+    dirname = os.path.basename(directory)
+    partial_path = os.path.join(partials_dir, dirname + '.zip')
+    compile_command = (partial_compile_command +
+                       ['--dir', directory, '-o', partial_path])
+    build_utils.CheckOutput(compile_command)
+
+    # Sorting the files in the partial ensures deterministic output from the
+    # aapt2 link step which uses order of files in the partial.
+    sorted_partial_path = os.path.join(partials_dir, dirname + '.sorted.zip')
+    _SortZip(partial_path, sorted_partial_path)
+
+    return sorted_partial_path
+
+  partials = pool.map(compile_partial, dep_subdirs)
+  pool.close()
+  pool.join()
+  return partials
+
+
+def _PackageApk(options, dep_subdirs, temp_dir, gen_dir, r_txt_path):
+  """Compile resources with aapt2 and generate intermediate .ap_ file.
+
+  Args:
+    options: The command-line options tuple. E.g. the generated apk
+      will be written to |options.apk_path|.
+    dep_subdirs: The list of directories where dependency resource zips
+      were extracted (its content will be altered by this function).
+    temp_dir: A temporary directory.
+    gen_dir: Another temp directory where some intermediate files are
+      generated.
+    r_txt_path: The path where the R.txt file will written to.
+  """
+  _DuplicateZhResources(dep_subdirs)
+
+  keep_predicate = _CreateKeepPredicate(
+      dep_subdirs, options.exclude_xxxhdpi, options.xxxhdpi_whitelist)
+  png_paths = []
+  for directory in dep_subdirs:
+    for f in build_utils.IterFiles(directory):
+      if not keep_predicate(f):
+        os.remove(f)
+      elif f.endswith('.png'):
+        png_paths.append(f)
+  if png_paths and options.png_to_webp:
+    _ConvertToWebP(options.webp_binary, png_paths)
+  for directory in dep_subdirs:
+    _MoveImagesToNonMdpiFolders(directory)
+
+  link_command = _CreateLinkApkArgs(options)
+  link_command += ['--output-text-symbols', r_txt_path]
+  # TODO(digit): Is this below actually required for R.txt generation?
+  link_command += ['--java', gen_dir]
+
+  fixed_manifest = _FixManifest(options, temp_dir)
+  link_command += ['--manifest', fixed_manifest]
+
+  partials = _CompileDeps(options.aapt_path, dep_subdirs, temp_dir)
+  for partial in partials:
+    link_command += ['-R', partial]
+
+  # Creates a .zip with AndroidManifest.xml, resources.arsc, res/*
+  # Also creates R.txt
+  build_utils.CheckOutput(
+      link_command, print_stdout=False, print_stderr=False)
+
+
+def _WriteFinalRTxtFile(options, aapt_r_txt_path):
+  """Determine final R.txt and return its location.
+
+  This handles --r-text-in and --r-text-out options at the same time.
+
+  Args:
+    options: The command-line options tuple.
+    aapt_r_txt_path: The path to the R.txt generated by aapt.
+  Returns:
+    Path to the final R.txt file.
+  """
+  if options.r_text_in:
+    r_txt_file = options.r_text_in
+  else:
+    # When an empty res/ directory is passed, aapt does not write an R.txt.
+    r_txt_file = aapt_r_txt_path
+    if not os.path.exists(r_txt_file):
+      build_utils.Touch(r_txt_file)
+
+  if options.r_text_out:
+    shutil.copyfile(r_txt_file, options.r_text_out)
+
+  return r_txt_file
+
+
+def _OnStaleMd5(options):
+  with resource_utils.BuildContext() as build:
+    dep_subdirs = resource_utils.ExtractDeps(options.dependencies_res_zips,
+                                             build.deps_dir)
+
+    _PackageApk(options, dep_subdirs, build.temp_dir, build.gen_dir,
+                build.r_txt_path)
+
+    r_txt_path = _WriteFinalRTxtFile(options, build.r_txt_path)
+
+    package = resource_utils.ExtractPackageFromManifest(
+        options.android_manifest)
+
+    # If --shared-resources-whitelist is used, the all resources listed in
+    # the corresponding R.txt file will be non-final, and an onResourcesLoaded()
+    # will be generated to adjust them at runtime.
+    #
+    # Otherwise, if --shared-resources is used, the all resources will be
+    # non-final, and an onResourcesLoaded() method will be generated too.
+    #
+    # Otherwise, all resources will be final, and no method will be generated.
+    #
+    rjava_build_options = resource_utils.RJavaBuildOptions()
+    if options.shared_resources_whitelist:
+      rjava_build_options.ExportSomeResources(
+          options.shared_resources_whitelist)
+      rjava_build_options.GenerateOnResourcesLoaded()
+    elif options.shared_resources or options.app_as_shared_lib:
+      rjava_build_options.ExportAllResources()
+      rjava_build_options.GenerateOnResourcesLoaded()
+
+    resource_utils.CreateRJavaFiles(
+        build.srcjar_dir, package, r_txt_path,
+        options.extra_res_packages,
+        options.extra_r_text_files,
+        rjava_build_options)
+
+    if options.srcjar_out:
+      build_utils.ZipDir(options.srcjar_out, build.srcjar_dir)
+
+    if options.check_resources_pkg_id is not None:
+      expected_id = options.check_resources_pkg_id
+      package_id = _ExtractPackageIdFromApk(options.apk_path,
+                                            options.aapt_path)
+      if package_id != expected_id:
+        raise Exception('Invalid package ID 0x%x (expected 0x%x)' %
+                        (package_id, expected_id))
+
+
+def main(args):
+  args = build_utils.ExpandFileArgs(args)
+  options = _ParseArgs(args)
+
+  # Order of these must match order specified in GN so that the correct one
+  # appears first in the depfile.
+  possible_output_paths = [
+    options.apk_path,
+    options.r_text_out,
+    options.srcjar_out,
+    options.proguard_file,
+    options.proguard_file_main_dex,
+  ]
+  output_paths = [x for x in possible_output_paths if x]
+
+  # List python deps in input_strings rather than input_paths since the contents
+  # of them does not change what gets written to the depsfile.
+  input_strings = options.extra_res_packages + [
+    options.shared_resources,
+    options.exclude_xxxhdpi,
+    options.xxxhdpi_whitelist,
+    str(options.debuggable),
+    str(options.png_to_webp),
+    str(options.support_zh_hk),
+    str(options.no_xml_namespaces),
+  ]
+
+  input_strings.extend(_CreateLinkApkArgs(options))
+
+  possible_input_paths = [
+    options.aapt_path,
+    options.android_manifest,
+    options.android_sdk_jar,
+    options.shared_resources_whitelist,
+  ]
+  input_paths = [x for x in possible_input_paths if x]
+  input_paths.extend(options.dependencies_res_zips)
+  input_paths.extend(options.extra_r_text_files)
+
+  if options.webp_binary:
+    input_paths.append(options.webp_binary)
+
+  build_utils.CallAndWriteDepfileIfStale(
+      lambda: _OnStaleMd5(options),
+      options,
+      input_paths=input_paths,
+      input_strings=input_strings,
+      output_paths=output_paths)
+
+
+if __name__ == '__main__':
+  main(sys.argv[1:])
diff --git a/build/android/gyp/prepare_resources.py b/build/android/gyp/prepare_resources.py
new file mode 100755
index 0000000..fee7932
--- /dev/null
+++ b/build/android/gyp/prepare_resources.py
@@ -0,0 +1,285 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Process Android resource directories to generate .resources.zip, R.txt and
+.srcjar files."""
+
+import argparse
+import collections
+import os
+import re
+import shutil
+import sys
+
+import generate_v14_compatible_resources
+
+from util import build_utils
+from util import resource_utils
+
+
+def _ParseArgs(args):
+  """Parses command line options.
+
+  Returns:
+    An options object as from argparse.ArgumentParser.parse_args()
+  """
+  parser, input_opts, output_opts = resource_utils.ResourceArgsParser()
+
+  input_opts.add_argument('--resource-dirs',
+                        default='[]',
+                        help='A list of input directories containing resources '
+                             'for this target.')
+
+  input_opts.add_argument(
+      '--shared-resources',
+      action='store_true',
+      help='Make resources shareable by generating an onResourcesLoaded() '
+           'method in the R.java source file.')
+
+  input_opts.add_argument('--custom-package',
+                          help='Optional Java package for main R.java.')
+
+  input_opts.add_argument(
+      '--android-manifest',
+      help='Optional AndroidManifest.xml path. Only used to extract a package '
+           'name for R.java if a --custom-package is not provided.')
+
+  output_opts.add_argument(
+      '--resource-zip-out',
+      help='Path to a zip archive containing all resources from '
+           '--resource-dirs, merged into a single directory tree. This will '
+           'also include auto-generated v14-compatible resources unless '
+           '--v14-skip is used.')
+
+  output_opts.add_argument('--srcjar-out',
+                    help='Path to .srcjar to contain the generated R.java.')
+
+  output_opts.add_argument('--r-text-out',
+                    help='Path to store the generated R.txt file.')
+
+  input_opts.add_argument(
+      '--v14-skip',
+      action="store_true",
+      help='Do not generate nor verify v14 resources.')
+
+  options = parser.parse_args(args)
+
+  resource_utils.HandleCommonOptions(options)
+
+  options.resource_dirs = build_utils.ParseGnList(options.resource_dirs)
+
+  return options
+
+
+def _GenerateGlobs(pattern):
+  # This function processes the aapt ignore assets pattern into a list of globs
+  # to be used to exclude files on the python side. It removes the '!', which is
+  # used by aapt to mean 'not chatty' so it does not output if the file is
+  # ignored (we dont output anyways, so it is not required). This function does
+  # not handle the <dir> and <file> prefixes used by aapt and are assumed not to
+  # be included in the pattern string.
+  return pattern.replace('!', '').split(':')
+
+
+def _ZipResources(resource_dirs, zip_path, ignore_pattern):
+  # Python zipfile does not provide a way to replace a file (it just writes
+  # another file with the same name). So, first collect all the files to put
+  # in the zip (with proper overriding), and then zip them.
+  # ignore_pattern is a string of ':' delimited list of globs used to ignore
+  # files that should not be part of the final resource zip.
+  files_to_zip = dict()
+  globs = _GenerateGlobs(ignore_pattern)
+  for d in resource_dirs:
+    for root, _, files in os.walk(d):
+      for f in files:
+        archive_path = f
+        parent_dir = os.path.relpath(root, d)
+        if parent_dir != '.':
+          archive_path = os.path.join(parent_dir, f)
+        path = os.path.join(root, f)
+        if build_utils.MatchesGlob(archive_path, globs):
+          continue
+        files_to_zip[archive_path] = path
+  build_utils.DoZip(files_to_zip.iteritems(), zip_path)
+
+
+def _GenerateRTxt(options, dep_subdirs, gen_dir):
+  """Generate R.txt file.
+
+  Args:
+    options: The command-line options tuple.
+    dep_subdirs: List of directories containing extracted dependency resources.
+    gen_dir: Locates where the aapt-generated files will go. In particular
+      the output file is always generated as |{gen_dir}/R.txt|.
+  """
+  # NOTE: This uses aapt rather than aapt2 because 'aapt2 compile' does not
+  # support the --output-text-symbols option yet (https://crbug.com/820460).
+  package_command = [options.aapt_path,
+                     'package',
+                     '-m',
+                     '-M', resource_utils.EMPTY_ANDROID_MANIFEST_PATH,
+                     '--no-crunch',
+                     '--auto-add-overlay',
+                     '--no-version-vectors',
+                     '-I', options.android_sdk_jar,
+                     '--output-text-symbols', gen_dir,
+                     '-J', gen_dir,  # Required for R.txt generation.
+                     '--ignore-assets', build_utils.AAPT_IGNORE_PATTERN]
+
+  # Adding all dependencies as sources is necessary for @type/foo references
+  # to symbols within dependencies to resolve. However, it has the side-effect
+  # that all Java symbols from dependencies are copied into the new R.java.
+  # E.g.: It enables an arguably incorrect usage of
+  # "mypackage.R.id.lib_symbol" where "libpackage.R.id.lib_symbol" would be
+  # more correct. This is just how Android works.
+  for d in dep_subdirs:
+    package_command += ['-S', d]
+
+  for d in options.resource_dirs:
+    package_command += ['-S', d]
+
+  # Only creates an R.txt
+  build_utils.CheckOutput(
+      package_command, print_stdout=False, print_stderr=False)
+
+
+def _GenerateResourcesZip(output_resource_zip, input_resource_dirs,
+                          v14_skip, temp_dir):
+  """Generate a .resources.zip file fron a list of input resource dirs.
+
+  Args:
+    output_resource_zip: Path to the output .resources.zip file.
+    input_resource_dirs: A list of input resource directories.
+    v14_skip: If False, then v14-compatible resource will also be
+      generated in |{temp_dir}/v14| and added to the final zip.
+    temp_dir: Path to temporary directory.
+  """
+  if not v14_skip:
+    # Generate v14-compatible resources in temp_dir.
+    v14_dir = os.path.join(temp_dir, 'v14')
+    build_utils.MakeDirectory(v14_dir)
+
+    for resource_dir in input_resource_dirs:
+      generate_v14_compatible_resources.GenerateV14Resources(
+          resource_dir,
+          v14_dir)
+
+    input_resource_dirs.append(v14_dir)
+
+  _ZipResources(input_resource_dirs, output_resource_zip,
+                  build_utils.AAPT_IGNORE_PATTERN)
+
+
+def _OnStaleMd5(options):
+  with resource_utils.BuildContext() as build:
+    if options.r_text_in:
+      r_txt_path = options.r_text_in
+    else:
+      # Extract dependencies to resolve @foo/type references into
+      # dependent packages.
+      dep_subdirs = resource_utils.ExtractDeps(options.dependencies_res_zips,
+                                               build.deps_dir)
+
+      _GenerateRTxt(options, dep_subdirs, build.gen_dir)
+      r_txt_path = build.r_txt_path
+
+      # 'aapt' doesn't generate any R.txt file if res/ was empty.
+      if not os.path.exists(r_txt_path):
+        build_utils.Touch(r_txt_path)
+
+    if options.r_text_out:
+      shutil.copyfile(r_txt_path, options.r_text_out)
+
+    if options.srcjar_out:
+      package = options.custom_package
+      if not package and options.android_manifest:
+        package = resource_utils.ExtractPackageFromManifest(
+            options.android_manifest)
+
+      # Don't create a .java file for the current resource target when no
+      # package name was provided (either by manifest or build rules).
+      if package:
+        # All resource IDs should be non-final here, but the
+        # onResourcesLoaded() method should only be generated if
+        # --shared-resources is used.
+        rjava_build_options = resource_utils.RJavaBuildOptions()
+        rjava_build_options.ExportAllResources()
+        rjava_build_options.ExportAllStyleables()
+        if options.shared_resources:
+          rjava_build_options.GenerateOnResourcesLoaded()
+
+        resource_utils.CreateRJavaFiles(
+            build.srcjar_dir, package, r_txt_path,
+            options.extra_res_packages,
+            options.extra_r_text_files,
+            rjava_build_options)
+
+      build_utils.ZipDir(options.srcjar_out, build.srcjar_dir)
+
+    if options.resource_zip_out:
+      _GenerateResourcesZip(options.resource_zip_out, options.resource_dirs,
+                            options.v14_skip, build.temp_dir)
+
+
+def main(args):
+  args = build_utils.ExpandFileArgs(args)
+  options = _ParseArgs(args)
+
+  # Order of these must match order specified in GN so that the correct one
+  # appears first in the depfile.
+  possible_output_paths = [
+    options.resource_zip_out,
+    options.r_text_out,
+    options.srcjar_out,
+  ]
+  output_paths = [x for x in possible_output_paths if x]
+
+  # List python deps in input_strings rather than input_paths since the contents
+  # of them does not change what gets written to the depsfile.
+  input_strings = options.extra_res_packages + [
+    options.custom_package,
+    options.shared_resources,
+    options.v14_skip,
+  ]
+
+  possible_input_paths = [
+    options.aapt_path,
+    options.android_manifest,
+    options.android_sdk_jar,
+  ]
+  input_paths = [x for x in possible_input_paths if x]
+  input_paths.extend(options.dependencies_res_zips)
+  input_paths.extend(options.extra_r_text_files)
+
+  # Resource files aren't explicitly listed in GN. Listing them in the depfile
+  # ensures the target will be marked stale when resource files are removed.
+  depfile_deps = []
+  resource_names = []
+  for resource_dir in options.resource_dirs:
+    for resource_file in build_utils.FindInDirectory(resource_dir, '*'):
+      # Don't list the empty .keep file in depfile. Since it doesn't end up
+      # included in the .zip, it can lead to -w 'dupbuild=err' ninja errors
+      # if ever moved.
+      if not resource_file.endswith(os.path.join('empty', '.keep')):
+        input_paths.append(resource_file)
+        depfile_deps.append(resource_file)
+      resource_names.append(os.path.relpath(resource_file, resource_dir))
+
+  # Resource filenames matter to the output, so add them to strings as well.
+  # This matters if a file is renamed but not changed (http://crbug.com/597126).
+  input_strings.extend(sorted(resource_names))
+
+  build_utils.CallAndWriteDepfileIfStale(
+      lambda: _OnStaleMd5(options),
+      options,
+      input_paths=input_paths,
+      input_strings=input_strings,
+      output_paths=output_paths,
+      depfile_deps=depfile_deps)
+
+
+if __name__ == '__main__':
+  main(sys.argv[1:])
diff --git a/build/android/gyp/process_resources.py b/build/android/gyp/process_resources.py
deleted file mode 100755
index 6a9a941..0000000
--- a/build/android/gyp/process_resources.py
+++ /dev/null
@@ -1,890 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Process Android resources to generate R.java, and prepare for packaging.
-
-This will crunch images with aapt2 and generate v14 compatible resources
-(see generate_v14_compatible_resources.py).
-"""
-
-import codecs
-import collections
-import multiprocessing.pool
-import optparse
-import os
-import re
-import shutil
-import subprocess
-import sys
-import zipfile
-from xml.etree import ElementTree
-
-
-import generate_v14_compatible_resources
-
-from util import build_utils
-
-_SOURCE_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(
-    __file__))))
-# Import jinja2 from third_party/jinja2
-sys.path.insert(1, os.path.join(_SOURCE_ROOT, 'third_party'))
-from jinja2 import Template # pylint: disable=F0401
-
-
-_EMPTY_ANDROID_MANIFEST_PATH = os.path.join(
-    _SOURCE_ROOT, 'build', 'android', 'AndroidManifest.xml')
-
-
-# Represents a line from a R.txt file.
-TextSymbolsEntry = collections.namedtuple('RTextEntry',
-    ('java_type', 'resource_type', 'name', 'value'))
-
-
-# A variation of this lists also exists in:
-# //base/android/java/src/org/chromium/base/LocaleUtils.java
-_CHROME_TO_ANDROID_LOCALE_MAP = {
-    'en-GB': 'en-rGB',
-    'en-US': 'en-rUS',
-    'es-419': 'es-rUS',
-    'fil': 'tl',
-    'he': 'iw',
-    'id': 'in',
-    'pt-PT': 'pt-rPT',
-    'pt-BR': 'pt-rBR',
-    'yi': 'ji',
-    'zh-CN': 'zh-rCN',
-    'zh-TW': 'zh-rTW',
-}
-
-# Pngs that we shouldn't convert to webp. Please add rationale when updating.
-_PNG_WEBP_BLACKLIST_PATTERN = re.compile('|'.join([
-    # Crashes on Galaxy S5 running L (https://crbug.com/807059).
-    r'.*star_gray\.png',
-    # Android requires pngs for 9-patch images.
-    r'.*\.9\.png',
-    # Daydream (*.dd) requires pngs for icon files.
-    r'.*\.dd\.png']))
-
-
-class _ResourceWhitelist(object):
-  def __init__(self, entries=None):
-    self._entries = None
-    if entries:
-      self._entries = set(self._Key(x) for x in entries)
-
-  def __contains__(self, entry):
-    return self._entries is None or self._Key(entry) in self._entries
-
-  @staticmethod
-  def _Key(entry):
-    # Whitelists should only care about the name of the resource rather than the
-    # resource ID (since the whitelist is from another compilation unit, the
-    # resource IDs may not match).
-    return (entry.java_type, entry.resource_type, entry.name)
-
-
-def _ParseArgs(args):
-  """Parses command line options.
-
-  Returns:
-    An options object as from optparse.OptionsParser.parse_args()
-  """
-  parser = optparse.OptionParser()
-  build_utils.AddDepfileOption(parser)
-
-  parser.add_option('--android-sdk-jar',
-                    help='the path to android jar file.')
-  parser.add_option('--aapt-path',
-                    help='path to the Android aapt tool')
-  parser.add_option('--non-constant-id', action='store_true')
-
-  parser.add_option('--android-manifest', help='AndroidManifest.xml path')
-  parser.add_option('--custom-package', help='Java package for R.java')
-  parser.add_option(
-      '--shared-resources',
-      action='store_true',
-      help='Make a resource package that can be loaded by a different'
-      'application at runtime to access the package\'s resources.')
-  parser.add_option(
-      '--app-as-shared-lib',
-      action='store_true',
-      help='Make a resource package that can be loaded as shared library.')
-  parser.add_option(
-      '--shared-resources-whitelist',
-      help='An R.txt file acting as a whitelist for resources that should be '
-      'non-final and have their package ID changed at runtime in R.java. If no '
-      'whitelist is provided, then everything is whitelisted.')
-
-  parser.add_option('--resource-dirs',
-                    default='[]',
-                    help='Directories containing resources of this target.')
-  parser.add_option('--dependencies-res-zips',
-                    help='Resources from dependents.')
-
-  parser.add_option('--resource-zip-out',
-                    help='Path for output zipped resources.')
-
-  parser.add_option('--srcjar-out',
-                    help='Path to srcjar to contain generated R.java.')
-  parser.add_option('--r-text-out',
-                    help='Path to store the generated R.txt file.')
-  parser.add_option('--r-text-in',
-                    help='Path to pre-existing R.txt for these resources. '
-                    'Resource names from it will be used to generate R.java '
-                    'instead of aapt-generated R.txt.')
-
-  parser.add_option('--proguard-file',
-                    help='Path to proguard.txt generated file')
-  parser.add_option('--proguard-file-main-dex',
-                    help='Path to proguard.txt generated file for main dex')
-
-  parser.add_option(
-      '--v14-skip',
-      action="store_true",
-      help='Do not generate nor verify v14 resources')
-
-  parser.add_option(
-      '--extra-res-packages',
-      help='Additional package names to generate R.java files for')
-  parser.add_option(
-      '--extra-r-text-files',
-      help='For each additional package, the R.txt file should contain a '
-      'list of resources to be included in the R.java file in the format '
-      'generated by aapt')
-
-  parser.add_option('--support-zh-hk', action='store_true',
-                    help='Use zh-rTW resources for zh-rHK.')
-
-  parser.add_option('--stamp', help='File to touch on success')
-
-  parser.add_option('--debuggable',
-                    action='store_true',
-                    help='Whether to add android:debuggable="true"')
-  parser.add_option('--version-code', help='Version code for apk.')
-  parser.add_option('--version-name', help='Version name for apk.')
-  parser.add_option('--no-compress', help='disables compression for the '
-                    'given comma separated list of extensions')
-  parser.add_option('--locale-whitelist',
-                    default='[]',
-                    help='GN list of languages to include. All other language '
-                         'configs will be stripped out. List may include '
-                         'a combination of Android locales or Chrome locales.')
-  parser.add_option('--apk-path',
-                    help='Path to output (partial) apk.')
-  parser.add_option('--exclude-xxxhdpi', action='store_true',
-                    help='Do not include xxxhdpi drawables.')
-  parser.add_option('--xxxhdpi-whitelist',
-                    default='[]',
-                    help='GN list of globs that say which xxxhdpi images to '
-                         'include even when --exclude-xxxhdpi is set.')
-  parser.add_option('--png-to-webp', action='store_true',
-                    help='Convert png files to webp format.')
-  parser.add_option('--webp-binary', default='',
-                    help='Path to the cwebp binary.')
-  parser.add_option('--no-xml-namespaces',
-                    action='store_true',
-                    help='Whether to strip xml namespaces from processed xml '
-                    'resources')
-
-  options, positional_args = parser.parse_args(args)
-
-  if positional_args:
-    parser.error('No positional arguments should be given.')
-
-  # Check that required options have been provided.
-  required_options = (
-      'android_sdk_jar',
-      'aapt_path',
-      'dependencies_res_zips',
-      )
-  build_utils.CheckOptions(options, parser, required=required_options)
-
-  options.resource_dirs = build_utils.ParseGnList(options.resource_dirs)
-  options.dependencies_res_zips = (
-      build_utils.ParseGnList(options.dependencies_res_zips))
-
-  options.locale_whitelist = build_utils.ParseGnList(options.locale_whitelist)
-  options.xxxhdpi_whitelist = build_utils.ParseGnList(options.xxxhdpi_whitelist)
-
-  # Don't use [] as default value since some script explicitly pass "".
-  if options.extra_res_packages:
-    options.extra_res_packages = (
-        build_utils.ParseGnList(options.extra_res_packages))
-  else:
-    options.extra_res_packages = []
-
-  if options.extra_r_text_files:
-    options.extra_r_text_files = (
-        build_utils.ParseGnList(options.extra_r_text_files))
-  else:
-    options.extra_r_text_files = []
-
-  return options
-
-
-def _CreateRJavaFiles(srcjar_dir, main_r_txt_file, packages, r_txt_files,
-      shared_resources, non_constant_id, whitelist_r_txt_file, is_apk):
-  assert len(packages) == len(r_txt_files), 'Need one R.txt file per package'
-
-  # Map of (resource_type, name) -> Entry.
-  # Contains the correct values for resources.
-  all_resources = {}
-  for entry in _ParseTextSymbolsFile(main_r_txt_file):
-    entry = entry._replace(value=_FixPackageIds(entry.value))
-    all_resources[(entry.resource_type, entry.name)] = entry
-
-  if whitelist_r_txt_file:
-    whitelisted_resources = _ResourceWhitelist(
-        _ParseTextSymbolsFile(whitelist_r_txt_file))
-  else:
-    whitelisted_resources = _ResourceWhitelist()
-
-  # Map of package_name->resource_type->entry
-  resources_by_package = (
-      collections.defaultdict(lambda: collections.defaultdict(list)))
-  # Build the R.java files using each package's R.txt file, but replacing
-  # each entry's placeholder value with correct values from all_resources.
-  for package, r_txt_file in zip(packages, r_txt_files):
-    if package in resources_by_package:
-      raise Exception(('Package name "%s" appeared twice. All '
-                       'android_resources() targets must use unique package '
-                       'names, or no package name at all.') % package)
-    resources_by_type = resources_by_package[package]
-    # The sub-R.txt files have the wrong values at this point. Read them to
-    # figure out which entries belong to them, but use the values from the
-    # main R.txt file.
-    for entry in _ParseTextSymbolsFile(r_txt_file):
-      entry = all_resources.get((entry.resource_type, entry.name))
-      # For most cases missing entry here is an error. It means that some
-      # library claims to have or depend on a resource that isn't included into
-      # the APK. There is one notable exception: Google Play Services (GMS).
-      # GMS is shipped as a bunch of AARs. One of them - basement - contains
-      # R.txt with ids of all resources, but most of the resources are in the
-      # other AARs. However, all other AARs reference their resources via
-      # basement's R.java so the latter must contain all ids that are in its
-      # R.txt. Most targets depend on only a subset of GMS AARs so some
-      # resources are missing, which is okay because the code that references
-      # them is missing too. We can't get an id for a resource that isn't here
-      # so the only solution is to skip the resource entry entirely.
-      #
-      # We can verify that all entries referenced in the code were generated
-      # correctly by running Proguard on the APK: it will report missing
-      # fields.
-      if entry:
-        resources_by_type[entry.resource_type].append(entry)
-
-  for package, resources_by_type in resources_by_package.iteritems():
-    package_r_java_dir = os.path.join(srcjar_dir, *package.split('.'))
-    build_utils.MakeDirectory(package_r_java_dir)
-    package_r_java_path = os.path.join(package_r_java_dir, 'R.java')
-    java_file_contents = _CreateRJavaFile(package, resources_by_type,
-        shared_resources, non_constant_id, whitelisted_resources, is_apk)
-    with open(package_r_java_path, 'w') as f:
-      f.write(java_file_contents)
-
-
-def _ParseTextSymbolsFile(path):
-  """Given an R.txt file, returns a list of TextSymbolsEntry."""
-  ret = []
-  with open(path) as f:
-    for line in f:
-      m = re.match(r'(int(?:\[\])?) (\w+) (\w+) (.+)$', line)
-      if not m:
-        raise Exception('Unexpected line in R.txt: %s' % line)
-      java_type, resource_type, name, value = m.groups()
-      ret.append(TextSymbolsEntry(java_type, resource_type, name, value))
-  return ret
-
-
-def _FixPackageIds(resource_value):
-  # Resource IDs for resources belonging to regular APKs have their first byte
-  # as 0x7f (package id). However with webview, since it is not a regular apk
-  # but used as a shared library, aapt is passed the --shared-resources flag
-  # which changes some of the package ids to 0x02 and 0x00.  This function just
-  # normalises all package ids to 0x7f, which the generated code in R.java
-  # changes to the correct package id at runtime.
-  # resource_value is a string with either, a single value '0x12345678', or an
-  # array of values like '{ 0xfedcba98, 0x01234567, 0x56789abc }'
-  return re.sub(r'0x(?!01)[0-9a-f]{2}', r'0x7f', resource_value)
-
-
-def _CreateRJavaFile(package, resources_by_type, shared_resources,
-                     non_constant_id, whitelisted_resources, is_apk):
-  """Generates the contents of a R.java file."""
-  final_resources_by_type = collections.defaultdict(list)
-  non_final_resources_by_type = collections.defaultdict(list)
-  if shared_resources or non_constant_id:
-    for res_type, resources in resources_by_type.iteritems():
-      for entry in resources:
-        # Entries in stylable that are not int[] are not actually resource ids
-        # but constants. If we are creating an apk there is no reason for them
-        # to be non-final. However for libraries, they may be clobbered later on
-        # and thus should remain non-final. This is regardless of the
-        # whitelisting rules (since they are not actually resources).
-        if entry.resource_type == 'styleable' and entry.java_type != 'int[]':
-          if is_apk:
-            final_resources_by_type[res_type].append(entry)
-          else:
-            non_final_resources_by_type[res_type].append(entry)
-        elif entry in whitelisted_resources:
-          non_final_resources_by_type[res_type].append(entry)
-        else:
-          final_resources_by_type[res_type].append(entry)
-  else:
-    final_resources_by_type = resources_by_type
-
-  def _UnrollArray(entry):
-    res_ids = re.findall(r'0x[0-9a-f]{8}', entry.value)
-    qualified_array_name = '%s.%s' % (entry.resource_type, entry.name)
-    unrolled = []
-    for i, res_id in enumerate(res_ids):
-      if res_id.startswith('0x7f'):
-        unrolled.append("%s[%d] ^= packageIdTransform;" %
-                        (qualified_array_name, i))
-    return unrolled
-
-  # Keep these assignments all on one line to make diffing against regular
-  # aapt-generated files easier.
-  create_id = ('{{ e.resource_type }}.{{ e.name }} ^= packageIdTransform;')
-  # Here we diverge from what aapt does. Because we have so many
-  # resources, the onResourcesLoaded method was exceeding the 64KB limit that
-  # Java imposes. For this reason we split onResourcesLoaded into different
-  # methods for each resource type.
-  template = Template("""/* AUTO-GENERATED FILE.  DO NOT MODIFY. */
-
-package {{ package }};
-
-public final class R {
-    private static boolean sResourcesDidLoad;
-    {% for resource_type in resource_types %}
-    public static final class {{ resource_type }} {
-        {% for e in final_resources[resource_type] %}
-        public static final {{ e.java_type }} {{ e.name }} = {{ e.value }};
-        {% endfor %}
-        {% for e in non_final_resources[resource_type] %}
-        public static {{ e.java_type }} {{ e.name }} = {{ e.value }};
-        {% endfor %}
-    }
-    {% endfor %}
-    {% if shared_resources %}
-    public static void onResourcesLoaded(int packageId) {
-        assert !sResourcesDidLoad;
-        sResourcesDidLoad = true;
-        int packageIdTransform = (packageId ^ 0x7f) << 24;
-        {% for resource_type in resource_types %}
-        onResourcesLoaded{{ resource_type|title }}(packageIdTransform);
-        {% for e in non_final_resources[resource_type] %}
-        {% if e.java_type == 'int[]' %}
-        {% for line in unrollArray(e) %}
-        {{ line }}
-        {% endfor %}
-        {% endif %}
-        {% endfor %}
-        {% endfor %}
-    }
-    {% for res_type in resource_types %}
-    private static void onResourcesLoaded{{ res_type|title }} (
-            int packageIdTransform) {
-        {% for e in non_final_resources[res_type] %}
-        {% if res_type != 'styleable' and e.java_type != 'int[]' %}
-        """ + create_id + """
-        {% endif %}
-        {% endfor %}
-    }
-    {% endfor %}
-    {% endif %}
-}
-""", trim_blocks=True, lstrip_blocks=True)
-
-  return template.render(package=package,
-                         resource_types=sorted(resources_by_type),
-                         shared_resources=shared_resources,
-                         final_resources=final_resources_by_type,
-                         non_final_resources=non_final_resources_by_type,
-                         unrollArray=_UnrollArray)
-
-
-def _GenerateGlobs(pattern):
-  # This function processes the aapt ignore assets pattern into a list of globs
-  # to be used to exclude files on the python side. It removes the '!', which is
-  # used by aapt to mean 'not chatty' so it does not output if the file is
-  # ignored (we dont output anyways, so it is not required). This function does
-  # not handle the <dir> and <file> prefixes used by aapt and are assumed not to
-  # be included in the pattern string.
-  return pattern.replace('!', '').split(':')
-
-
-def _ZipResources(resource_dirs, zip_path, ignore_pattern):
-  # Python zipfile does not provide a way to replace a file (it just writes
-  # another file with the same name). So, first collect all the files to put
-  # in the zip (with proper overriding), and then zip them.
-  # ignore_pattern is a string of ':' delimited list of globs used to ignore
-  # files that should not be part of the final resource zip.
-  files_to_zip = dict()
-  globs = _GenerateGlobs(ignore_pattern)
-  for d in resource_dirs:
-    for root, _, files in os.walk(d):
-      for f in files:
-        archive_path = f
-        parent_dir = os.path.relpath(root, d)
-        if parent_dir != '.':
-          archive_path = os.path.join(parent_dir, f)
-        path = os.path.join(root, f)
-        if build_utils.MatchesGlob(archive_path, globs):
-          continue
-        files_to_zip[archive_path] = path
-  build_utils.DoZip(files_to_zip.iteritems(), zip_path)
-
-def _SortZip(original_path, sorted_path):
-  with zipfile.ZipFile(sorted_path, 'w') as sorted_zip, \
-      zipfile.ZipFile(original_path, 'r') as original_zip:
-    for info in sorted(original_zip.infolist(), key=lambda i: i.filename):
-      sorted_zip.writestr(info, original_zip.read(info))
-
-
-
-def _DuplicateZhResources(resource_dirs):
-  for resource_dir in resource_dirs:
-    # We use zh-TW resources for zh-HK (if we have zh-TW resources).
-    for path in build_utils.IterFiles(resource_dir):
-      if 'zh-rTW' in path:
-        hk_path = path.replace('zh-rTW', 'zh-rHK')
-        build_utils.MakeDirectory(os.path.dirname(hk_path))
-        shutil.copyfile(path, hk_path)
-
-def _ExtractPackageFromManifest(manifest_path):
-  doc = ElementTree.parse(manifest_path)
-  return doc.getroot().get('package')
-
-
-def _ToAaptLocales(locale_whitelist, support_zh_hk):
-  """Converts the list of Chrome locales to aapt config locales."""
-  ret = set()
-  for locale in locale_whitelist:
-    locale = _CHROME_TO_ANDROID_LOCALE_MAP.get(locale, locale)
-    if locale is None or ('-' in locale and '-r' not in locale):
-      raise Exception('_CHROME_TO_ANDROID_LOCALE_MAP needs updating.'
-                      ' Found: %s' % locale)
-    ret.add(locale)
-    # Always keep non-regional fall-backs.
-    language = locale.split('-')[0]
-    ret.add(language)
-
-  # We don't actually support zh-HK in Chrome on Android, but we mimic the
-  # native side behavior where we use zh-TW resources when the locale is set to
-  # zh-HK. See https://crbug.com/780847.
-  if support_zh_hk:
-    assert not any('HK' in l for l in locale_whitelist), (
-        'Remove special logic if zh-HK is now supported (crbug.com/780847).')
-    ret.add('zh-rHK')
-  return sorted(ret)
-
-
-def _MoveImagesToNonMdpiFolders(res_root):
-  """Move images from drawable-*-mdpi-* folders to drawable-* folders.
-
-  Why? http://crbug.com/289843
-  """
-  for src_dir_name in os.listdir(res_root):
-    src_components = src_dir_name.split('-')
-    if src_components[0] != 'drawable' or 'mdpi' not in src_components:
-      continue
-    src_dir = os.path.join(res_root, src_dir_name)
-    if not os.path.isdir(src_dir):
-      continue
-    dst_components = [c for c in src_components if c != 'mdpi']
-    assert dst_components != src_components
-    dst_dir_name = '-'.join(dst_components)
-    dst_dir = os.path.join(res_root, dst_dir_name)
-    build_utils.MakeDirectory(dst_dir)
-    for src_file_name in os.listdir(src_dir):
-      if not os.path.splitext(src_file_name)[1] in ('.png', '.webp'):
-        continue
-      src_file = os.path.join(src_dir, src_file_name)
-      dst_file = os.path.join(dst_dir, src_file_name)
-      assert not os.path.lexists(dst_file)
-      shutil.move(src_file, dst_file)
-
-
-def _CreateLinkApkArgs(options):
-  link_command = [
-    options.aapt_path + '2',
-    'link',
-    '--version-code', options.version_code,
-    '--version-name', options.version_name,
-    '--auto-add-overlay',
-    '--no-version-vectors',
-    '-I', options.android_sdk_jar,
-    '-o', options.apk_path,
-  ]
-
-  if options.proguard_file:
-    link_command += ['--proguard', options.proguard_file]
-  if options.proguard_file_main_dex:
-    link_command += ['--proguard-main-dex', options.proguard_file_main_dex]
-
-  if options.no_compress:
-    for ext in options.no_compress.split(','):
-      link_command += ['-0', ext]
-
-  if options.shared_resources:
-    link_command.append('--shared-lib')
-
-  if options.locale_whitelist:
-    aapt_locales = _ToAaptLocales(
-        options.locale_whitelist, options.support_zh_hk)
-    link_command += ['-c', ','.join(aapt_locales)]
-
-  if options.no_xml_namespaces:
-    link_command.append('--no-xml-namespaces')
-
-  return link_command
-
-
-def _ExtractVersionFromSdk(aapt_path, sdk_path):
-  output = subprocess.check_output([aapt_path, 'dump', 'badging', sdk_path])
-  version_code = re.search(r"versionCode='(.*?)'", output).group(1)
-  version_name = re.search(r"versionName='(.*?)'", output).group(1)
-  return version_code, version_name,
-
-
-def _FixManifest(options, temp_dir):
-  debug_manifest_path = os.path.join(temp_dir, 'AndroidManifest.xml')
-  _ANDROID_NAMESPACE = 'http://schemas.android.com/apk/res/android'
-  _TOOLS_NAMESPACE = 'http://schemas.android.com/tools'
-  ElementTree.register_namespace('android', _ANDROID_NAMESPACE)
-  ElementTree.register_namespace('tools', _TOOLS_NAMESPACE)
-  original_manifest = ElementTree.parse(options.android_manifest)
-
-  version_code, version_name = _ExtractVersionFromSdk(
-      options.aapt_path, options.android_sdk_jar)
-
-  # ElementTree.find does not work if the required tag is the root.
-  if original_manifest.getroot().tag == 'manifest':
-    manifest_node = original_manifest.getroot()
-  else:
-    manifest_node = original_manifest.find('manifest')
-
-  manifest_node.set('platformBuildVersionCode', version_code)
-  manifest_node.set('platformBuildVersionName', version_name)
-
-  if options.debuggable:
-    app_node = original_manifest.find('application')
-    app_node.set('{%s}%s' % (_ANDROID_NAMESPACE, 'debuggable'), 'true')
-
-  with open(debug_manifest_path, 'w') as debug_manifest:
-    debug_manifest.write(ElementTree.tostring(
-        original_manifest.getroot(), encoding='UTF-8'))
-
-  return debug_manifest_path
-
-
-def _ResourceNameFromPath(path):
-  return os.path.splitext(os.path.basename(path))[0]
-
-
-def _CreateKeepPredicate(resource_dirs, exclude_xxxhdpi, xxxhdpi_whitelist):
-  if not exclude_xxxhdpi:
-    # Do not extract dotfiles (e.g. ".gitkeep"). aapt ignores them anyways.
-    return lambda path: os.path.basename(path)[0] != '.'
-
-  # Returns False only for xxxhdpi non-mipmap, non-whitelisted drawables.
-  naive_predicate = lambda path: (
-      not re.search(r'[/-]xxxhdpi[/-]', path) or
-      re.search(r'[/-]mipmap[/-]', path) or
-      build_utils.MatchesGlob(path, xxxhdpi_whitelist))
-
-  # Build a set of all non-xxxhdpi drawables to ensure that we never exclude any
-  # xxxhdpi drawable that does not exist in other densities.
-  non_xxxhdpi_drawables = set()
-  for resource_dir in resource_dirs:
-    for path in build_utils.IterFiles(resource_dir):
-      if re.search(r'[/-]drawable[/-]', path) and naive_predicate(path):
-        non_xxxhdpi_drawables.add(_ResourceNameFromPath(path))
-
-  return lambda path: (naive_predicate(path) or
-                       _ResourceNameFromPath(path) not in non_xxxhdpi_drawables)
-
-
-def _ConvertToWebP(webp_binary, png_files):
-  pool = multiprocessing.pool.ThreadPool(10)
-  def convert_image(png_path):
-    root = os.path.splitext(png_path)[0]
-    webp_path = root + '.webp'
-    args = [webp_binary, png_path, '-mt', '-quiet', '-m', '6', '-q', '100',
-        '-lossless', '-o', webp_path]
-    subprocess.check_call(args)
-    os.remove(png_path)
-
-  pool.map(convert_image, [f for f in png_files
-                           if not _PNG_WEBP_BLACKLIST_PATTERN.match(f)])
-  pool.close()
-  pool.join()
-
-
-def _CompileDeps(aapt_path, dep_subdirs, temp_dir):
-  partials_dir = os.path.join(temp_dir, 'partials')
-  build_utils.MakeDirectory(partials_dir)
-  partial_compile_command = [
-      aapt_path + '2',
-      'compile',
-      # TODO(wnwen): Turn this on once aapt2 forces 9-patch to be crunched.
-      # '--no-crunch',
-  ]
-  pool = multiprocessing.pool.ThreadPool(10)
-  def compile_partial(directory):
-    dirname = os.path.basename(directory)
-    partial_path = os.path.join(partials_dir, dirname + '.zip')
-    compile_command = (partial_compile_command +
-                       ['--dir', directory, '-o', partial_path])
-    build_utils.CheckOutput(compile_command)
-
-    # Sorting the files in the partial ensures deterministic output from the
-    # aapt2 link step which uses order of files in the partial.
-    sorted_partial_path = os.path.join(partials_dir, dirname + '.sorted.zip')
-    _SortZip(partial_path, sorted_partial_path)
-
-    return sorted_partial_path
-
-  partials = pool.map(compile_partial, dep_subdirs)
-  pool.close()
-  pool.join()
-  return partials
-
-
-def _PackageApk(options, dep_subdirs, temp_dir, gen_dir, r_txt_path):
-  _DuplicateZhResources(dep_subdirs)
-
-  keep_predicate = _CreateKeepPredicate(
-      dep_subdirs, options.exclude_xxxhdpi, options.xxxhdpi_whitelist)
-  png_paths = []
-  for directory in dep_subdirs:
-    for f in build_utils.IterFiles(directory):
-      if not keep_predicate(f):
-        os.remove(f)
-      elif f.endswith('.png'):
-        png_paths.append(f)
-  if png_paths and options.png_to_webp:
-    _ConvertToWebP(options.webp_binary, png_paths)
-  for directory in dep_subdirs:
-    _MoveImagesToNonMdpiFolders(directory)
-
-  link_command = _CreateLinkApkArgs(options)
-  link_command += ['--output-text-symbols', r_txt_path]
-  link_command += ['--java', gen_dir]
-
-  fixed_manifest = _FixManifest(options, temp_dir)
-  link_command += ['--manifest', fixed_manifest]
-
-  partials = _CompileDeps(options.aapt_path, dep_subdirs, temp_dir)
-  for partial in partials:
-    link_command += ['-R', partial]
-
-  # Creates a .zip with AndroidManifest.xml, resources.arsc, res/*
-  # Also creates R.txt
-  build_utils.CheckOutput(
-      link_command, print_stdout=False, print_stderr=False)
-
-
-# _PackageLibrary uses aapt rather than aapt2 because aapt2 compile does not
-# support outputting an R.txt file.
-def _PackageLibrary(options, dep_subdirs, temp_dir, gen_dir):
-  v14_dir = os.path.join(temp_dir, 'v14')
-  build_utils.MakeDirectory(v14_dir)
-
-  # Generate R.java. This R.java contains non-final constants and is used only
-  # while compiling the library jar (e.g. chromium_content.jar). When building
-  # an apk, a new R.java file with the correct resource -> ID mappings will be
-  # generated by merging the resources from all libraries and the main apk
-  # project.
-  package_command = [options.aapt_path,
-                     'package',
-                     '-m',
-                     '-M', _EMPTY_ANDROID_MANIFEST_PATH,
-                     '--no-crunch',
-                     '--auto-add-overlay',
-                     '--no-version-vectors',
-                     '-I', options.android_sdk_jar,
-                     '--output-text-symbols', gen_dir,
-                     '-J', gen_dir,  # Required for R.txt generation.
-                     '--ignore-assets', build_utils.AAPT_IGNORE_PATTERN]
-
-  # Adding all dependencies as sources is necessary for @type/foo references
-  # to symbols within dependencies to resolve. However, it has the side-effect
-  # that all Java symbols from dependencies are copied into the new R.java.
-  # E.g.: It enables an arguably incorrect usage of
-  # "mypackage.R.id.lib_symbol" where "libpackage.R.id.lib_symbol" would be
-  # more correct. This is just how Android works.
-  for d in dep_subdirs:
-    package_command += ['-S', d]
-
-  input_resource_dirs = options.resource_dirs
-
-  for d in input_resource_dirs:
-    package_command += ['-S', d]
-
-  if not options.v14_skip:
-    for resource_dir in input_resource_dirs:
-      generate_v14_compatible_resources.GenerateV14Resources(
-          resource_dir,
-          v14_dir)
-
-  # This is the list of directories with resources to put in the final .zip
-  zip_resource_dirs = input_resource_dirs + [v14_dir]
-
-  if options.resource_zip_out:
-    _ZipResources(zip_resource_dirs, options.resource_zip_out,
-                  build_utils.AAPT_IGNORE_PATTERN)
-
-  # Only creates an R.txt
-  build_utils.CheckOutput(
-      package_command, print_stdout=False, print_stderr=False)
-
-
-def _CreateRTxtAndSrcJar(options, r_txt_path, srcjar_dir):
-  # When an empty res/ directory is passed, aapt does not write an R.txt.
-  if not os.path.exists(r_txt_path):
-    build_utils.Touch(r_txt_path)
-
-  if options.r_text_in:
-    r_txt_path = options.r_text_in
-
-  packages = list(options.extra_res_packages)
-  r_txt_files = list(options.extra_r_text_files)
-
-  cur_package = options.custom_package
-  if not options.custom_package and options.android_manifest:
-    cur_package = _ExtractPackageFromManifest(options.android_manifest)
-
-  # Don't create a .java file for the current resource target when:
-  # - no package name was provided (either by manifest or build rules),
-  # - there was already a dependent android_resources() with the same
-  #   package (occurs mostly when an apk target and resources target share
-  #   an AndroidManifest.xml)
-  if cur_package and cur_package not in packages:
-    packages.append(cur_package)
-    r_txt_files.append(r_txt_path)
-
-  if packages:
-    shared_resources = options.shared_resources or options.app_as_shared_lib
-    _CreateRJavaFiles(srcjar_dir, r_txt_path, packages, r_txt_files,
-        shared_resources, options.non_constant_id,
-        options.shared_resources_whitelist, bool(options.apk_path))
-
-  if options.srcjar_out:
-    build_utils.ZipDir(options.srcjar_out, srcjar_dir)
-
-  if options.r_text_out:
-    shutil.copyfile(r_txt_path, options.r_text_out)
-
-
-def _ExtractDeps(dep_zips, deps_dir):
-  dep_subdirs = []
-  for z in dep_zips:
-    subdir = os.path.join(deps_dir, os.path.basename(z))
-    if os.path.exists(subdir):
-      raise Exception('Resource zip name conflict: ' + os.path.basename(z))
-    build_utils.ExtractAll(z, path=subdir)
-    dep_subdirs.append(subdir)
-  return dep_subdirs
-
-
-def _OnStaleMd5(options):
-  with build_utils.TempDir() as temp_dir:
-    deps_dir = os.path.join(temp_dir, 'deps')
-    build_utils.MakeDirectory(deps_dir)
-    gen_dir = os.path.join(temp_dir, 'gen')
-    build_utils.MakeDirectory(gen_dir)
-    r_txt_path = os.path.join(gen_dir, 'R.txt')
-    srcjar_dir = os.path.join(temp_dir, 'java')
-
-    dep_subdirs = _ExtractDeps(options.dependencies_res_zips, deps_dir)
-
-    if options.apk_path:
-      _PackageApk(options, dep_subdirs, temp_dir, gen_dir, r_txt_path)
-    else:
-      _PackageLibrary(options, dep_subdirs, temp_dir, gen_dir)
-
-    _CreateRTxtAndSrcJar(options, r_txt_path, srcjar_dir)
-
-
-def main(args):
-  args = build_utils.ExpandFileArgs(args)
-  options = _ParseArgs(args)
-
-  # Order of these must match order specified in GN so that the correct one
-  # appears first in the depfile.
-  possible_output_paths = [
-    options.apk_path,
-    options.resource_zip_out,
-    options.r_text_out,
-    options.srcjar_out,
-    options.proguard_file,
-    options.proguard_file_main_dex,
-  ]
-  output_paths = [x for x in possible_output_paths if x]
-
-  # List python deps in input_strings rather than input_paths since the contents
-  # of them does not change what gets written to the depsfile.
-  input_strings = options.extra_res_packages + [
-    options.app_as_shared_lib,
-    options.custom_package,
-    options.non_constant_id,
-    options.shared_resources,
-    options.v14_skip,
-    options.exclude_xxxhdpi,
-    options.xxxhdpi_whitelist,
-    str(options.debuggable),
-    str(options.png_to_webp),
-    str(options.support_zh_hk),
-    str(options.no_xml_namespaces),
-  ]
-
-  if options.apk_path:
-    input_strings.extend(_CreateLinkApkArgs(options))
-
-  possible_input_paths = [
-    options.aapt_path,
-    options.android_manifest,
-    options.android_sdk_jar,
-    options.shared_resources_whitelist,
-  ]
-  input_paths = [x for x in possible_input_paths if x]
-  input_paths.extend(options.dependencies_res_zips)
-  input_paths.extend(options.extra_r_text_files)
-
-  if options.webp_binary:
-    input_paths.append(options.webp_binary)
-
-  # Resource files aren't explicitly listed in GN. Listing them in the depfile
-  # ensures the target will be marked stale when resource files are removed.
-  depfile_deps = []
-  resource_names = []
-  for resource_dir in options.resource_dirs:
-    for resource_file in build_utils.FindInDirectory(resource_dir, '*'):
-      # Don't list the empty .keep file in depfile. Since it doesn't end up
-      # included in the .zip, it can lead to -w 'dupbuild=err' ninja errors
-      # if ever moved.
-      if not resource_file.endswith(os.path.join('empty', '.keep')):
-        input_paths.append(resource_file)
-        depfile_deps.append(resource_file)
-      resource_names.append(os.path.relpath(resource_file, resource_dir))
-
-  # Resource filenames matter to the output, so add them to strings as well.
-  # This matters if a file is renamed but not changed (http://crbug.com/597126).
-  input_strings.extend(sorted(resource_names))
-
-  build_utils.CallAndWriteDepfileIfStale(
-      lambda: _OnStaleMd5(options),
-      options,
-      input_paths=input_paths,
-      input_strings=input_strings,
-      output_paths=output_paths,
-      depfile_deps=depfile_deps)
-
-
-if __name__ == '__main__':
-  main(sys.argv[1:])
diff --git a/build/android/gyp/util/resource_utils.py b/build/android/gyp/util/resource_utils.py
new file mode 100644
index 0000000..973c2d5
--- /dev/null
+++ b/build/android/gyp/util/resource_utils.py
@@ -0,0 +1,459 @@
+# Copyright 2018 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 argparse
+import collections
+import contextlib
+import os
+import re
+import shutil
+import sys
+import tempfile
+from xml.etree import ElementTree
+
+import util.build_utils as build_utils
+
+_SOURCE_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(
+    os.path.dirname(__file__)))))
+# Import jinja2 from third_party/jinja2
+sys.path.insert(1, os.path.join(_SOURCE_ROOT, 'third_party'))
+from jinja2 import Template # pylint: disable=F0401
+
+
+EMPTY_ANDROID_MANIFEST_PATH = os.path.join(
+    _SOURCE_ROOT, 'build', 'android', 'AndroidManifest.xml')
+
+
+# Represents a line from a R.txt file.
+_TextSymbolEntry = collections.namedtuple('RTextEntry',
+    ('java_type', 'resource_type', 'name', 'value'))
+
+
+def _ParseTextSymbolsFile(path, fix_package_ids=False):
+  """Given an R.txt file, returns a list of _TextSymbolEntry.
+
+  Args:
+    path: Input file path.
+    fix_package_ids: if True, all packaged IDs read from the file
+      will be fixed to 0x7f.
+  Returns:
+    A list of _TextSymbolEntry instances.
+  Raises:
+    Exception: An unexpected line was detected in the input.
+  """
+  ret = []
+  with open(path) as f:
+    for line in f:
+      m = re.match(r'(int(?:\[\])?) (\w+) (\w+) (.+)$', line)
+      if not m:
+        raise Exception('Unexpected line in R.txt: %s' % line)
+      java_type, resource_type, name, value = m.groups()
+      if fix_package_ids:
+        value = _FixPackageIds(value)
+      ret.append(_TextSymbolEntry(java_type, resource_type, name, value))
+  return ret
+
+
+def _FixPackageIds(resource_value):
+  # Resource IDs for resources belonging to regular APKs have their first byte
+  # as 0x7f (package id). However with webview, since it is not a regular apk
+  # but used as a shared library, aapt is passed the --shared-resources flag
+  # which changes some of the package ids to 0x02 and 0x00.  This function just
+  # normalises all package ids to 0x7f, which the generated code in R.java
+  # changes to the correct package id at runtime.
+  # resource_value is a string with either, a single value '0x12345678', or an
+  # array of values like '{ 0xfedcba98, 0x01234567, 0x56789abc }'
+  return re.sub(r'0x(?!01)\d\d', r'0x7f', resource_value)
+
+
+def _GetRTxtResourceNames(r_txt_path):
+  """Parse an R.txt file and extract the set of resource names from it."""
+  result = set()
+  for entry in _ParseTextSymbolsFile(r_txt_path):
+    result.add(entry.name)
+  return result
+
+
+class RJavaBuildOptions:
+  """A class used to model the various ways to build an R.java file.
+
+  This is used to control which resource ID variables will be final or
+  non-final, and whether an onResourcesLoaded() method will be generated
+  to adjust the non-final ones, when the corresponding library is loaded
+  at runtime.
+
+  Note that by default, all resources are final, and there is no
+  method generated, which corresponds to calling ExportNoResources().
+  """
+  def __init__(self):
+    self.has_constant_ids = True
+    self.resources_whitelist = None
+    self.has_on_resources_loaded = False
+    self.export_const_styleable = False
+
+  def ExportNoResources(self):
+    """Make all resource IDs final, and don't generate a method."""
+    self.has_constant_ids = True
+    self.resources_whitelist = None
+    self.has_on_resources_loaded = False
+    self.export_const_styleable = False
+
+  def ExportAllResources(self):
+    """Make all resource IDs non-final in the R.java file."""
+    self.has_constant_ids = False
+    self.resources_whitelist = None
+
+  def ExportSomeResources(self, r_txt_file_path):
+    """Only select specific resource IDs to be non-final.
+
+    Args:
+      r_txt_file_path: The path to an R.txt file. All resources named
+        int it will be non-final in the generated R.java file, all others
+        will be final.
+    """
+    self.has_constant_ids = True
+    self.resources_whitelist = _GetRTxtResourceNames(r_txt_file_path)
+
+  def ExportAllStyleables(self):
+    """Make all styleable constants non-final, even non-resources ones.
+
+    Resources that are styleable but not of int[] type are not actually
+    resource IDs but constants. By default they are always final. Call this
+    method to make them non-final anyway in the final R.java file.
+    """
+    self.export_const_styleable = True
+
+  def GenerateOnResourcesLoaded(self):
+    """Generate an onResourcesLoaded() method.
+
+    This Java method will be called at runtime by the framework when
+    the corresponding library (which includes the R.java source file)
+    will be loaded at runtime. This corresponds to the --shared-resources
+    or --app-as-shared-lib flags of 'aapt package'.
+    """
+    self.has_on_resources_loaded = True
+
+  def _IsResourceFinal(self, entry):
+    """Determines whether a resource should be final or not.
+
+  Args:
+    entry: A _TextSymbolEntry instance.
+  Returns:
+    True iff the corresponding entry should be final.
+  """
+    if entry.resource_type == 'styleable' and entry.java_type != 'int[]':
+      # A styleable constant may be exported as non-final after all.
+      return not self.export_const_styleable
+    elif not self.has_constant_ids:
+      # Every resource is non-final
+      return False
+    elif not self.resources_whitelist:
+      # No whitelist means all IDs are non-final.
+      return True
+    else:
+      # Otherwise, only those in the
+      return entry.name not in self.resources_whitelist
+
+
+def CreateRJavaFiles(srcjar_dir, package, main_r_txt_file,
+                     extra_res_packages, extra_r_txt_files,
+                     rjava_build_options):
+  """Create all R.java files for a set of packages and R.txt files.
+
+  Args:
+    srcjar_dir: The top-level output directory for the generated files.
+    package: Top-level package name.
+    main_r_txt_file: The main R.txt file containing the valid values
+      of _all_ resource IDs.
+    extra_res_packages: A list of extra package names.
+    extra_r_txt_files: A list of extra R.txt files. One per item in
+      |extra_res_packages|. Note that all resource IDs in them will be ignored,
+      |and replaced by the values extracted from |main_r_txt_file|.
+    rjava_build_options: An RJavaBuildOptions instance that controls how
+      exactly the R.java file is generated.
+  Raises:
+    Exception if a package name appears several times in |extra_res_packages|
+  """
+  assert len(extra_res_packages) == len(extra_r_txt_files), \
+         'Need one R.txt file per package'
+
+  packages = list(extra_res_packages)
+  r_txt_files = list(extra_r_txt_files)
+
+  if package not in packages:
+    # Sometimes, an apk target and a resources target share the same
+    # AndroidManifest.xml and thus |package| will already be in |packages|.
+    packages.append(package)
+    r_txt_files.append(main_r_txt_file)
+
+  # Map of (resource_type, name) -> Entry.
+  # Contains the correct values for resources.
+  all_resources = {}
+  for entry in _ParseTextSymbolsFile(main_r_txt_file, fix_package_ids=True):
+    all_resources[(entry.resource_type, entry.name)] = entry
+
+  # Map of package_name->resource_type->entry
+  resources_by_package = (
+      collections.defaultdict(lambda: collections.defaultdict(list)))
+  # Build the R.java files using each package's R.txt file, but replacing
+  # each entry's placeholder value with correct values from all_resources.
+  for package, r_txt_file in zip(packages, r_txt_files):
+    if package in resources_by_package:
+      raise Exception(('Package name "%s" appeared twice. All '
+                       'android_resources() targets must use unique package '
+                       'names, or no package name at all.') % package)
+    resources_by_type = resources_by_package[package]
+    # The sub-R.txt files have the wrong values at this point. Read them to
+    # figure out which entries belong to them, but use the values from the
+    # main R.txt file.
+    for entry in _ParseTextSymbolsFile(r_txt_file):
+      entry = all_resources.get((entry.resource_type, entry.name))
+      # For most cases missing entry here is an error. It means that some
+      # library claims to have or depend on a resource that isn't included into
+      # the APK. There is one notable exception: Google Play Services (GMS).
+      # GMS is shipped as a bunch of AARs. One of them - basement - contains
+      # R.txt with ids of all resources, but most of the resources are in the
+      # other AARs. However, all other AARs reference their resources via
+      # basement's R.java so the latter must contain all ids that are in its
+      # R.txt. Most targets depend on only a subset of GMS AARs so some
+      # resources are missing, which is okay because the code that references
+      # them is missing too. We can't get an id for a resource that isn't here
+      # so the only solution is to skip the resource entry entirely.
+      #
+      # We can verify that all entries referenced in the code were generated
+      # correctly by running Proguard on the APK: it will report missing
+      # fields.
+      if entry:
+        resources_by_type[entry.resource_type].append(entry)
+
+  for package, resources_by_type in resources_by_package.iteritems():
+    _CreateRJavaSourceFile(srcjar_dir, package, resources_by_type,
+                           rjava_build_options)
+
+
+def _CreateRJavaSourceFile(srcjar_dir, package, resources_by_type,
+                           rjava_build_options):
+  """Generates an R.java source file."""
+  package_r_java_dir = os.path.join(srcjar_dir, *package.split('.'))
+  build_utils.MakeDirectory(package_r_java_dir)
+  package_r_java_path = os.path.join(package_r_java_dir, 'R.java')
+  java_file_contents = _RenderRJavaSource(package, resources_by_type,
+                                          rjava_build_options)
+  with open(package_r_java_path, 'w') as f:
+    f.write(java_file_contents)
+
+
+def _RenderRJavaSource(package, resources_by_type, rjava_build_options):
+  """Render an R.java source file. See _CreateRJaveSourceFile for args info."""
+  final_resources_by_type = collections.defaultdict(list)
+  non_final_resources_by_type = collections.defaultdict(list)
+  for res_type, resources in resources_by_type.iteritems():
+    for entry in resources:
+      # Entries in stylable that are not int[] are not actually resource ids
+      # but constants.
+      if rjava_build_options._IsResourceFinal(entry):
+        final_resources_by_type[res_type].append(entry)
+      else:
+        non_final_resources_by_type[res_type].append(entry)
+
+  def _UnrollArray(entry):
+    res_ids = re.findall(r'0x[0-9a-f]{8}', entry.value)
+    qualified_array_name = '%s.%s' % (entry.resource_type, entry.name)
+    unrolled = []
+    for i, res_id in enumerate(res_ids):
+      if res_id.startswith('0x7f'):
+        unrolled.append("%s[%d] ^= packageIdTransform;" %
+                        (qualified_array_name, i))
+
+    return unrolled
+  # Keep these assignments all on one line to make diffing against regular
+  # aapt-generated files easier.
+  create_id = ('{{ e.resource_type }}.{{ e.name }} ^= packageIdTransform;')
+  # Here we diverge from what aapt does. Because we have so many
+  # resources, the onResourcesLoaded method was exceeding the 64KB limit that
+  # Java imposes. For this reason we split onResourcesLoaded into different
+  # methods for each resource type.
+  template = Template("""/* AUTO-GENERATED FILE.  DO NOT MODIFY. */
+
+package {{ package }};
+
+public final class R {
+    private static boolean sResourcesDidLoad;
+    {% for resource_type in resource_types %}
+    public static final class {{ resource_type }} {
+        {% for e in final_resources[resource_type] %}
+        public static final {{ e.java_type }} {{ e.name }} = {{ e.value }};
+        {% endfor %}
+        {% for e in non_final_resources[resource_type] %}
+        public static {{ e.java_type }} {{ e.name }} = {{ e.value }};
+        {% endfor %}
+    }
+    {% endfor %}
+    {% if has_on_resources_loaded %}
+    public static void onResourcesLoaded(int packageId) {
+        assert !sResourcesDidLoad;
+        sResourcesDidLoad = true;
+        int packageIdTransform = (packageId ^ 0x7f) << 24;
+        {% for resource_type in resource_types %}
+        onResourcesLoaded{{ resource_type|title }}(packageIdTransform);
+        {% for e in non_final_resources[resource_type] %}
+        {% if e.java_type == 'int[]' %}
+        {% for line in unrollArray(e) %}
+        {{ line }}
+        {% endfor %}
+        {% endif %}
+        {% endfor %}
+        {% endfor %}
+    }
+    {% for res_type in resource_types %}
+    private static void onResourcesLoaded{{ res_type|title }} (
+            int packageIdTransform) {
+        {% for e in non_final_resources[res_type] %}
+        {% if res_type != 'styleable' and e.java_type != 'int[]' %}
+        """ + create_id + """
+        {% endif %}
+        {% endfor %}
+    }
+    {% endfor %}
+    {% endif %}
+}
+""", trim_blocks=True, lstrip_blocks=True)
+
+  return template.render(
+      package=package,
+      resource_types=sorted(resources_by_type),
+      has_on_resources_loaded=rjava_build_options.has_on_resources_loaded,
+      final_resources=final_resources_by_type,
+      non_final_resources=non_final_resources_by_type,
+      unrollArray=_UnrollArray)
+
+
+def ExtractPackageFromManifest(manifest_path):
+  """Extract package name from Android manifest file."""
+  doc = ElementTree.parse(manifest_path)
+  return doc.getroot().get('package')
+
+
+def ExtractDeps(dep_zips, deps_dir):
+  """Extract a list of resource dependency zip files.
+
+  Args:
+     dep_zips: A list of zip file paths, each one will be extracted to
+       a subdirectory of |deps_dir|, named after the zip file (e.g.
+       '/some/path/foo.zip' -> '{deps_dir}/foo/').
+    deps_dir: Top-level extraction directory.
+  Returns:
+    The list of all sub-directory paths, relative to |deps_dir|.
+  Raises:
+    Exception: If a sub-directory already exists with the same name before
+      extraction.
+  """
+  dep_subdirs = []
+  for z in dep_zips:
+    subdir = os.path.join(deps_dir, os.path.basename(z))
+    if os.path.exists(subdir):
+      raise Exception('Resource zip name conflict: ' + os.path.basename(z))
+    build_utils.ExtractAll(z, path=subdir)
+    dep_subdirs.append(subdir)
+  return dep_subdirs
+
+
+class _ResourceBuildContext(object):
+  """A temporary directory for packaging and compiling Android resources."""
+  def __init__(self):
+    """Initialized the context."""
+    # The top-level temporary directory.
+    self.temp_dir = tempfile.mkdtemp()
+    # A location to store resources extracted form dependency zip files.
+    self.deps_dir = os.path.join(self.temp_dir, 'deps')
+    os.mkdir(self.deps_dir)
+    # A location to place aapt-generated files.
+    self.gen_dir = os.path.join(self.temp_dir, 'gen')
+    os.mkdir(self.gen_dir)
+    # Location of the generated R.txt file.
+    self.r_txt_path = os.path.join(self.gen_dir, 'R.txt')
+    # A location to place generated R.java files.
+    self.srcjar_dir = os.path.join(self.temp_dir, 'java')
+    os.mkdir(self.srcjar_dir)
+
+  def Close(self):
+    """Close the context and destroy all temporary files."""
+    shutil.rmtree(self.temp_dir)
+
+
+@contextlib.contextmanager
+def BuildContext():
+  """Generator for a _ResourceBuildContext instance."""
+  try:
+    context = _ResourceBuildContext()
+    yield context
+  finally:
+    context.Close()
+
+
+def ResourceArgsParser():
+  """Create an argparse.ArgumentParser instance with common argument groups.
+
+  Returns:
+    A tuple of (parser, in_group, out_group) corresponding to the parser
+    instance, and the input and output argument groups for it, respectively.
+  """
+  parser = argparse.ArgumentParser(description=__doc__)
+
+  input_opts = parser.add_argument_group('Input options')
+  output_opts = parser.add_argument_group('Output options')
+
+  build_utils.AddDepfileOption(output_opts)
+
+  input_opts.add_argument('--android-sdk-jar', required=True,
+                        help='Path to the android.jar file.')
+
+  input_opts.add_argument('--aapt-path', required=True,
+                         help='Path to the Android aapt tool')
+
+  input_opts.add_argument('--dependencies-res-zips', required=True,
+                    help='Resources zip archives from dependents. Required to '
+                         'resolve @type/foo references into dependent '
+                         'libraries.')
+
+  input_opts.add_argument(
+      '--r-text-in',
+       help='Path to pre-existing R.txt. Its resource IDs override those found '
+            'in the aapt-generated R.txt when generating R.java.')
+
+  input_opts.add_argument(
+      '--extra-res-packages',
+      help='Additional package names to generate R.java files for.')
+
+  input_opts.add_argument(
+      '--extra-r-text-files',
+      help='For each additional package, the R.txt file should contain a '
+           'list of resources to be included in the R.java file in the format '
+           'generated by aapt.')
+
+  return (parser, input_opts, output_opts)
+
+
+def HandleCommonOptions(options):
+  """Handle common command-line options after parsing.
+
+  Args:
+    options: the result of parse_args() on the parser returned by
+        ResourceArgsParser(). This function updates a few common fields.
+  """
+  options.dependencies_res_zips = (
+      build_utils.ParseGnList(options.dependencies_res_zips))
+
+  # Don't use [] as default value since some script explicitly pass "".
+  if options.extra_res_packages:
+    options.extra_res_packages = (
+        build_utils.ParseGnList(options.extra_res_packages))
+  else:
+    options.extra_res_packages = []
+
+  if options.extra_r_text_files:
+    options.extra_r_text_files = (
+        build_utils.ParseGnList(options.extra_r_text_files))
+  else:
+    options.extra_r_text_files = []
diff --git a/build/android/pylib/symbols/deobfuscator.py b/build/android/pylib/symbols/deobfuscator.py
index 67347c4..9d4f5fd 100644
--- a/build/android/pylib/symbols/deobfuscator.py
+++ b/build/android/pylib/symbols/deobfuscator.py
@@ -124,6 +124,7 @@
     # self._proc is None when Popen() fails.
     if not self._closed_called and self._proc:
       logging.error('deobfuscator: Forgot to Close()')
+      self.Close()
 
 
 class DeobfuscatorPool(object):
diff --git a/build/check_gn_headers_whitelist.txt b/build/check_gn_headers_whitelist.txt
index c66acfc0..843fcbf 100644
--- a/build/check_gn_headers_whitelist.txt
+++ b/build/check_gn_headers_whitelist.txt
@@ -122,7 +122,6 @@
 components/user_manager/user_manager.h
 components/viz/display_compositor/display_provider.h
 components/viz/viz_export.h
-components/wallpaper/wallpaper_export.h
 components/wifi/wifi_export.h
 components/wifi/wifi_service.h
 content/browser/background_fetch/background_fetch_constants.h
diff --git a/build/cipd/android/OWNERS b/build/cipd/android/OWNERS
deleted file mode 100644
index 72e8ffc..0000000
--- a/build/cipd/android/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-*
diff --git a/build/cipd/android/android.ensure b/build/cipd/android/android.ensure
deleted file mode 100644
index 42e2bda..0000000
--- a/build/cipd/android/android.ensure
+++ /dev/null
@@ -1,137 +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.
-
-# Dependencies for Android target OS.
-
-# -crX indicates the chromium-specific revision of a package at a given version.
-
-@Subdir third_party/accessibility_test_framework
-chromium/third_party/accessibility-test-framework version:2.1-cr0
-
-# Three unchanging lines
-# avoid the horror that is
-# endless merge conflicts
-
-@Subdir third_party/android_support_test_runner
-chromium/third_party/android_support_test_runner version:0.5-cr0
-
-# Three unchanging lines
-# avoid the horror that is
-# endless merge conflicts
-
-@Subdir third_party/android_system_sdk
-chromium/third_party/android_system_sdk version:27-cr0
-
-# Three unchanging lines
-# avoid the horror that is
-# endless merge conflicts
-
-@Subdir third_party/apk-patch-size-estimator
-chromium/third_party/apk-patch-size-estimator version:0.2-cr0
-
-# Three unchanging lines
-# avoid the horror that is
-# endless merge conflicts
-
-@Subdir third_party/bazel
-chromium/third_party/bazel version:0.10.0
-
-# Three unchanging lines
-# avoid the horror that is
-# endless merge conflicts
-
-@Subdir third_party/bouncycastle
-chromium/third_party/bouncycastle version:1.46-cr0
-
-# Three unchanging lines
-# avoid the horror that is
-# endless merge conflicts
-
-@Subdir third_party/byte_buddy
-chromium/third_party/byte_buddy version:1.4.17-cr0
-
-# Three unchanging lines
-# avoid the horror that is
-# endless merge conflicts
-
-@Subdir third_party/espresso
-chromium/third_party/espresso version:2.2.1-cr0
-
-# Three unchanging lines
-# avoid the horror that is
-# endless merge conflicts
-
-@Subdir third_party/gson
-chromium/third_party/gson version:2.8.0-cr0
-
-# Three unchanging lines
-# avoid the horror that is
-# endless merge conflicts
-
-@Subdir third_party/guava
-chromium/third_party/guava version:23.0-cr0
-
-# Three unchanging lines
-# avoid the horror that is
-# endless merge conflicts
-
-@Subdir third_party/hamcrest
-chromium/third_party/hamcrest version:1.3-cr0
-
-# Three unchanging lines
-# avoid the horror that is
-# endless merge conflicts
-
-@Subdir third_party/icu4j
-chromium/third_party/icu4j version:53.1-cr0
-
-# Three unchanging lines
-# avoid the horror that is
-# endless merge conflicts
-
-@Subdir third_party/intellij
-chromium/third_party/intellij version:12.0-cr0
-
-# Three unchanging lines
-# avoid the horror that is
-# endless merge conflicts
-
-@Subdir third_party/javax_inject
-chromium/third_party/javax_inject version:1-cr0
-
-# Three unchanging lines
-# avoid the horror that is
-# endless merge conflicts
-
-@Subdir third_party/objenesis
-chromium/third_party/objenesis version:2.4-cr0
-
-# Three unchanging lines
-# avoid the horror that is
-# endless merge conflicts
-
-@Subdir third_party/ow2_asm
-chromium/third_party/ow2_asm version:5.0.1-cr0
-
-# Three unchanging lines
-# avoid the horror that is
-# endless merge conflicts
-
-@Subdir third_party/robolectric
-chromium/third_party/robolectric version:3.5.1
-
-# Three unchanging lines
-# avoid the horror that is
-# endless merge conflicts
-
-@Subdir third_party/sqlite4java
-chromium/third_party/sqlite4java version:0.282-cr0
-
-# Three unchanging lines
-# avoid the horror that is
-# endless merge conflicts
-
-@Subdir third_party/xstream
-chromium/third_party/xstream version:1.4.8-cr0
-
diff --git a/build/cipd/cipd_wrapper.py b/build/cipd/cipd_wrapper.py
deleted file mode 100755
index 73b1366..0000000
--- a/build/cipd/cipd_wrapper.py
+++ /dev/null
@@ -1,102 +0,0 @@
-#!/usr/bin/env python
-#
-# 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.
-
-"""Updates dependencies managed by CIPD."""
-
-import argparse
-import os
-import subprocess
-import sys
-import tempfile
-
-_SRC_ROOT = os.path.realpath(
-    os.path.join(os.path.dirname(__file__), '..', '..'))
-
-
-def cipd_ensure(root, service_url, ensure_file):
-
-  def is_windows():
-    return sys.platform in ('cygwin', 'win32')
-
-  cipd_binary = 'cipd'
-  if is_windows():
-    cipd_binary = 'cipd.bat'
-
-  with tempfile.NamedTemporaryFile() as tmp_stdouterr:
-    retcode = subprocess.call(
-        [cipd_binary, 'ensure',
-         '-ensure-file', ensure_file,
-         '-root', root,
-         '-service-url', service_url],
-        shell=is_windows(),
-        stderr=subprocess.STDOUT,
-        stdout=tmp_stdouterr)
-    if retcode:
-      tmp_stdouterr.seek(0)
-      for line in tmp_stdouterr:
-        print line,
-    return retcode
-
-
-def build_ensure_file(sub_files):
-  pieces = []
-  for sub in sub_files:
-    pieces.append('### Sourced from //%s' % os.path.relpath(sub, _SRC_ROOT))
-    with open(sub) as f:
-      pieces.append(f.read())
-  return '\n'.join(pieces)
-
-
-def main():
-  parser = argparse.ArgumentParser(
-      description='Updates CIPD-managed dependencies based on the given OS.')
-
-  parser.add_argument(
-      '--keep-generated-file',
-      action='store_true',
-      help='Don\'t delete the generated ensure file, if any, on success.')
-  parser.add_argument(
-      '--chromium-root',
-      required=True,
-      help='Root directory for dependency.')
-  parser.add_argument(
-      '--service-url',
-      help='The url of the CIPD service.',
-      default='https://chrome-infra-packages.appspot.com')
-  parser.add_argument(
-      '--ensure-file',
-      action='append',
-      type=os.path.realpath,
-      required=True,
-      help='The path to the ensure file. If given multiple times, this will '
-           'concatenate the given ensure files before passing them to cipd.')
-  args = parser.parse_args()
-
-  build_own_ensure_file = len(args.ensure_file) > 1
-  if build_own_ensure_file:
-    ensure_file_contents = build_ensure_file(args.ensure_file)
-    with tempfile.NamedTemporaryFile(suffix='.ensure') as ensure_file:
-      ensure_file.write(ensure_file_contents)
-      ensure_file_name = ensure_file.name
-      ensure_file.delete = False
-  else:
-    ensure_file_name = args.ensure_file[0]
-
-  retcode = cipd_ensure(args.chromium_root, args.service_url, ensure_file_name)
-  if retcode:
-    if build_own_ensure_file:
-      print 'Ensure failed; generated input file is at', ensure_file_name
-    return retcode
-
-  if build_own_ensure_file:
-    if args.keep_generated_file:
-      print 'Leaving the generated .ensure file at', ensure_file_name
-    else:
-      os.unlink(ensure_file_name)
-  return 0
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/build/cipd/clobber_cipd_root.py b/build/cipd/clobber_cipd_root.py
new file mode 100755
index 0000000..5d36c72
--- /dev/null
+++ b/build/cipd/clobber_cipd_root.py
@@ -0,0 +1,33 @@
+#!/usr/bin/env python
+#
+# Copyright 2018 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.
+
+"""Clobbers a CIPD root."""
+
+import argparse
+import os
+import shutil
+import sys
+
+
+def main():
+  parser = argparse.ArgumentParser(
+      description='Clobbers the CIPD root in the given directory.')
+
+  parser.add_argument(
+      '--root',
+      required=True,
+      help='Root directory for dependency.')
+  args = parser.parse_args()
+
+  cipd_root_dir = os.path.join(args.root, '.cipd')
+  if os.path.exists(cipd_root_dir):
+    shutil.rmtree(cipd_root_dir)
+
+  return 0
+
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/build/config/BUILD.gn b/build/config/BUILD.gn
index 04eaffc..2c8747f 100644
--- a/build/config/BUILD.gn
+++ b/build/config/BUILD.gn
@@ -61,6 +61,9 @@
   defines = [ "V8_DEPRECATION_WARNINGS" ]
   if (dcheck_always_on) {
     defines += [ "DCHECK_ALWAYS_ON=1" ]
+    if (dcheck_is_configurable) {
+      defines += [ "DCHECK_IS_CONFIGURABLE=1" ]
+    }
   }
   if (use_udev) {
     # TODO(brettw) should probably be "=1".
@@ -205,14 +208,11 @@
       "advapi32.lib",
       "comdlg32.lib",
       "dbghelp.lib",
-      "delayimp.lib",
       "dnsapi.lib",
       "gdi32.lib",
-      "kernel32.lib",
       "msimg32.lib",
       "odbc32.lib",
       "odbccp32.lib",
-      "ole32.lib",
       "oleaut32.lib",
       "psapi.lib",
       "shell32.lib",
@@ -231,6 +231,20 @@
       # some extra libraries, please just add a libs = [ "foo.lib" ] to your
       # target that needs it.
     ]
+    if (current_os == "winuwp") {
+      # These libraries are needed for Windows UWP (i.e. store apps).
+      libs += [
+        "dloadhelper.lib",
+        "WindowsApp.lib",
+      ]
+    } else {
+      # These libraries are not compatible with Windows UWP (i.e. store apps.)
+      libs += [
+        "delayimp.lib",
+        "kernel32.lib",
+        "ole32.lib",
+      ]
+    }
   } else if (is_android) {
     libs = [
       "dl",
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn
index 7d0a385..3856800 100644
--- a/build/config/BUILDCONFIG.gn
+++ b/build/config/BUILDCONFIG.gn
@@ -250,11 +250,14 @@
   } else {
     _default_toolchain = "//build/toolchain/win:$target_cpu"
   }
+} else if (target_os == "winuwp") {
+  # Only target WinUWP on for a Windows store application and only
+  # x86, x64 and arm are supported target CPUs.
+  assert(target_cpu == "x86" || target_cpu == "x64" || target_cpu == "arm" ||
+         target_cpu == "arm64")
+  _default_toolchain = "//build/toolchain/win:uwp_$target_cpu"
 } else if (target_os == "aix") {
   _default_toolchain = "//build/toolchain/aix:$target_cpu"
-} else if (target_os == "winrt_81" || target_os == "winrt_81_phone" ||
-           target_os == "winrt_10") {
-  _default_toolchain = "//build/toolchain/win:winrt_$target_cpu"
 } else {
   assert(false, "Unsupported target_os: $target_os")
 }
@@ -285,8 +288,7 @@
 # aix or one of the BSDs. If you need to check these, just check the
 # current_os value directly.
 
-if (current_os == "win" || current_os == "winrt_81" ||
-    current_os == "winrt_81_phone" || current_os == "winrt_10") {
+if (current_os == "win" || current_os == "winuwp") {
   is_android = false
   is_chromeos = false
   is_fuchsia = false
@@ -536,6 +538,7 @@
   "//build/config/coverage:default_coverage",
   "//build/config/sanitizers:default_sanitizer_flags",
 ]
+
 if (is_win) {
   default_compiler_configs += [
     "//build/config/win:default_crt",
@@ -546,10 +549,6 @@
     "//build/config/win:vs_code_analysis",
   ]
 }
-if (current_os == "winrt_81" || current_os == "winrt_81_phone" ||
-    current_os == "winrt_10") {
-  default_compiler_configs += [ "//build/config/win:target_winrt" ]
-}
 
 if (is_posix) {
   if (current_os != "aix") {
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index 81c502bd..2076549 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -1449,22 +1449,65 @@
     }
   }
 
-  template("process_resources") {
-    _process_resources_target_name = target_name
+  # This template is used to parse a set of resource directories and
+  # create the R.txt, .srcjar and .resources.zip for it.
+  #
+  # Input variables:
+  #   deps: Specifies the input dependencies for this target.
+  #
+  #   build_config: Path to the .build_config file corresponding to the target.
+  #
+  #   resource_dirs:
+  #     List of directories containing Android resources, layout should be
+  #     similar to what aapt -S <dir> expects.
+  #
+  #   generated_resource_dirs: (optional)
+  #     List of directories containing generated resources.
+  #
+  #   generated_resource_files: (optional)
+  #     If generated_resources_dirs is not empty, must list all the files
+  #     within these directories (the directory must appear at the start of
+  #     the file path).
+  #
+  #   custom_package: (optional)
+  #     Package name for the generated R.java source file. Optional if
+  #     android_manifest is not provided.
+  #
+  #   android_manifest: (optional)
+  #     If custom_package is not provided, path to an AndroidManifest.xml file
+  #     that is only used to extract a package name out of it.
+  #
+  #   r_text_in_path: (optional)
+  #     Path to an input R.txt file to use to generate the R.java file.
+  #     The default is to use 'aapt' to generate the file from the content
+  #     of the resource directories.
+  #
+  #   alternative_android_sdk_jar: Alternative android.jar to use.
+  #     TODO(digit): Not sure this is needed here.
+  #
+  #   shared_resources: (optional)
+  #     If true, generate an R.java file that uses non-final resource ID
+  #     variables and an onResourcesLoaded() method.
+  #
+  #   v14_skip: (optional)
+  #     If true, skip generation of v14 compatible resources.
+  #     (see generate_v14_compatible_resources.py for details).
+  #
+  # Output variables:
+  #   zip_path: (optional)
+  #     Path to a .resources.zip that will simply contain all the
+  #     input resources, collected in a single archive.
+  #
+  #   r_text_out_path: (optional): Path for the generated R.txt file.
+  #
+  #   srcjar_path: (optional) Path to a generated .srcjar containing the
+  #                           generated R.java source file.
+  #
+  template("prepare_resources") {
     if (defined(invoker.srcjar_path)) {
       _srcjar_path = invoker.srcjar_path
     }
-    if (defined(invoker.output)) {
-      _packaged_resources_path = invoker.output
-    }
-    if (defined(invoker.post_process_script)) {
-      _process_resources_target_name = "${target_name}__intermediate"
-      _packaged_resources_path =
-          get_path_info(_packaged_resources_path, "dir") + "/" +
-          get_path_info(_packaged_resources_path, "name") + ".intermediate.ap_"
-      _srcjar_path = "${_srcjar_path}.intermediate.srcjar"
-    }
-    action(_process_resources_target_name) {
+    action(target_name) {
       set_sources_assignment_filter([])
       forward_variables_from(invoker,
                              [
@@ -1472,9 +1515,9 @@
                                "testonly",
                                "visibility",
                              ])
-      script = "//build/android/gyp/process_resources.py"
+      script = "//build/android/gyp/prepare_resources.py"
 
-      depfile = "$target_gen_dir/${invoker.target_name}_1.d"
+      depfile = "$target_gen_dir/${invoker.target_name}.d"
       outputs = []
       _all_resource_dirs = []
       sources = []
@@ -1507,7 +1550,6 @@
       }
 
       inputs = [
-        android_default_aapt_path,
         invoker.build_config,
         _android_aapt_path,
         _android_sdk_jar,
@@ -1541,44 +1583,6 @@
         args += [ "--resource-dirs=$_rebased_all_resource_dirs" ]
       }
 
-      if (defined(invoker.shared_resources_whitelist)) {
-        inputs += [ invoker.shared_resources_whitelist ]
-        args += [
-          "--shared-resources-whitelist",
-          rebase_path(invoker.shared_resources_whitelist, root_build_dir),
-        ]
-      }
-
-      if (defined(invoker.no_xml_namespaces) && invoker.no_xml_namespaces) {
-        args += [ "--no-xml-namespaces" ]
-      }
-
-      if (defined(invoker.version_code)) {
-        args += [
-          "--version-code",
-          invoker.version_code,
-        ]
-      }
-      if (defined(invoker.version_name)) {
-        args += [
-          "--version-name",
-          invoker.version_name,
-        ]
-      }
-      if (defined(_packaged_resources_path)) {
-        outputs += [ _packaged_resources_path ]
-        args += [
-          "--apk-path",
-          rebase_path(_packaged_resources_path, root_build_dir),
-        ]
-      }
-
-      # Useful to have android:debuggable in the manifest even for Release
-      # builds. Just omit it for officai
-      if (debuggable_apks) {
-        args += [ "--debuggable" ]
-      }
-
       if (defined(invoker.zip_path)) {
         outputs += [ invoker.zip_path ]
         args += [
@@ -1612,9 +1616,202 @@
         ]
       }
 
-      if (!defined(invoker.generate_constant_ids) ||
-          !invoker.generate_constant_ids) {
-        args += [ "--non-constant-id" ]
+      if (defined(invoker.custom_package)) {
+        args += [
+          "--custom-package",
+          invoker.custom_package,
+        ]
+      }
+
+      if (defined(invoker.shared_resources) && invoker.shared_resources) {
+        args += [ "--shared-resources" ]
+      }
+
+      if (defined(invoker.v14_skip) && invoker.v14_skip) {
+        args += [ "--v14-skip" ]
+      }
+    }
+  }
+
+  # A template that is used to compile all resources needed by a binary
+  # (e.g. an android_apk or a junit_binary) into an intermediate .ar_
+  # archive. It can also generate an associated .srcjar that contains the
+  # final R.java sources for all resource packages the binary depends on.
+  #
+  # Input variables:
+  #   deps: Specifies the input dependencies for this target.
+  #
+  #   build_config: Path to the .build_config file corresponding to the target.
+  #
+  #   android_manifest: Path to root manifest for the binary.
+  #
+  #   version_code: (optional)
+  #
+  #   version_name: (optional)
+  #
+  #   alternative_android_sdk_jar: Alternative system android.jar to use.
+  #
+  #   shared_resources: (optional)
+  #     If true, make all variables in each generated R.java file non-final,
+  #     and provide an onResourcesLoaded() method that can be used to reset
+  #     their package index at load time. Useful when the APK corresponds to
+  #     a library that is loaded at runtime, like system_webview_apk or
+  #     monochrome_apk.
+  #
+  #   app_as_shared_lib: (optional)
+  #     If true, same effect as shared_resources, but also ensures that the
+  #     resources can be used by the APK when it is loaded as a regular
+  #     application as well. Useful for the monochrome_public_apk target
+  #     which is both an application and a shared runtime library that
+  #     implements the system webview feature.
+  #
+  #   shared_resources_whitelist: (optional)
+  #     Path to an R.txt file. If provided, acts similar to shared_resources
+  #     except that it restricts the list of non-final resource variables
+  #     to the list from the input R.txt file. Overrides shared_resources
+  #     when both are specified.
+  #
+  #   support_zh_hk: (optional)
+  #     If true, support zh-HK in Chrome on Android by using the resources
+  #     from zh-TW. See https://crbug.com/780847.
+  #
+  #   aapt_locale_whitelist: (optional)
+  #     Restrict compiled locale-dependent resources to a specific whitelist.
+  #     NOTE: This is a list of Chromium locale names, not Android ones.
+  #
+  #   exclude_xxxhdpi: (optional)
+  #
+  #   xxxhdpi_whitelist: (optional)
+  #
+  #   no_xml_namespaces: (optional)
+  #
+  #   png_to_webp: (optional)
+  #     If true, convert all PNG resources (except 9-patch files) to WebP.
+  #
+  #   post_process_script: (optional)
+  #
+  #
+  # Output variables:
+  #   output:  Path to a zip file containing the compiled resources.
+  #
+  #   r_text_out_path: (optional):
+  #       Path for the corresponding generated R.txt file.
+  #
+  #   srcjar_path: (optional)
+  #       Path to a generated .srcjar containing the generated R.java sources
+  #       for all dependent resource libraries.
+  #
+  #   proguard_file: (optional)
+  #       Path to proguard configuration file for this apk target.
+  #
+  #   proguard_file_main_dex: (optional)
+  #
+  #
+  template("compile_resources") {
+    _compile_resources_target_name = target_name
+    _compiled_resources_path = invoker.output
+
+    if (defined(invoker.srcjar_path)) {
+      _srcjar_path = invoker.srcjar_path
+    }
+    if (defined(invoker.post_process_script)) {
+      _compile_resources_target_name = "${target_name}__intermediate"
+      _compiled_resources_path =
+          get_path_info(_compiled_resources_path, "dir") + "/" +
+          get_path_info(_compiled_resources_path, "name") + ".intermediate.ap_"
+      _srcjar_path = "${_srcjar_path}.intermediate.srcjar"
+    }
+
+    action(_compile_resources_target_name) {
+      set_sources_assignment_filter([])
+      forward_variables_from(invoker,
+                             [
+                               "deps",
+                               "testonly",
+                               "visibility",
+                             ])
+      script = "//build/android/gyp/compile_resources.py"
+
+      depfile = "$target_gen_dir/${invoker.target_name}_1.d"
+      outputs = []
+
+      _android_aapt_path = android_default_aapt_path
+
+      _android_sdk_jar = android_sdk_jar
+      if (defined(invoker.alternative_android_sdk_jar)) {
+        _android_sdk_jar = invoker.alternative_android_sdk_jar
+      }
+
+      inputs = [
+        invoker.build_config,
+        _android_aapt_path,
+        _android_sdk_jar,
+      ]
+
+      _rebased_build_config = rebase_path(invoker.build_config, root_build_dir)
+
+      args = [
+        "--depfile",
+        rebase_path(depfile, root_build_dir),
+        "--android-sdk-jar",
+        rebase_path(_android_sdk_jar, root_build_dir),
+        "--aapt-path",
+        rebase_path(_android_aapt_path, root_build_dir),
+        "--dependencies-res-zips=@FileArg($_rebased_build_config:resources:dependency_zips)",
+        "--extra-res-packages=@FileArg($_rebased_build_config:resources:extra_package_names)",
+        "--extra-r-text-files=@FileArg($_rebased_build_config:resources:extra_r_text_files)",
+      ]
+
+      inputs += [ invoker.android_manifest ]
+      args += [
+        "--android-manifest",
+        rebase_path(invoker.android_manifest, root_build_dir),
+      ]
+
+      if (defined(invoker.no_xml_namespaces) && invoker.no_xml_namespaces) {
+        args += [ "--no-xml-namespaces" ]
+      }
+
+      if (defined(invoker.version_code)) {
+        args += [
+          "--version-code",
+          invoker.version_code,
+        ]
+      }
+      if (defined(invoker.version_name)) {
+        args += [
+          "--version-name",
+          invoker.version_name,
+        ]
+      }
+      if (defined(_compiled_resources_path)) {
+        outputs += [ _compiled_resources_path ]
+        args += [
+          "--apk-path",
+          rebase_path(_compiled_resources_path, root_build_dir),
+        ]
+      }
+
+      # Useful to have android:debuggable in the manifest even for Release
+      # builds. Just omit it for officai
+      if (debuggable_apks) {
+        args += [ "--debuggable" ]
+      }
+
+      if (defined(invoker.r_text_out_path)) {
+        outputs += [ invoker.r_text_out_path ]
+        args += [
+          "--r-text-out",
+          rebase_path(invoker.r_text_out_path, root_build_dir),
+        ]
+      }
+
+      if (defined(_srcjar_path)) {
+        outputs += [ _srcjar_path ]
+        args += [
+          "--srcjar-out",
+          rebase_path(_srcjar_path, root_build_dir),
+        ]
       }
 
       if (defined(invoker.custom_package)) {
@@ -1624,16 +1821,29 @@
         ]
       }
 
-      if (defined(invoker.v14_skip) && invoker.v14_skip) {
-        args += [ "--v14-skip" ]
-      }
+      # Define the flags related to shared resources.
+      #
+      # Note the small sanity check to ensure that the package ID of the
+      # generated resources table is correct. It should be 0x02 for runtime
+      # shared libraries, and 0x7f otherwise.
 
+      _expected_resources_pkg_id = "0x7f"
       if (defined(invoker.shared_resources) && invoker.shared_resources) {
         args += [ "--shared-resources" ]
+        _expected_resources_pkg_id = "0x02"
+      } else if (defined(invoker.app_as_shared_lib) &&
+                 invoker.app_as_shared_lib) {
+        args += [ "--app-as-shared-lib" ]
       }
 
-      if (defined(invoker.app_as_shared_lib) && invoker.app_as_shared_lib) {
-        args += [ "--app-as-shared-lib" ]
+      args += [ "--check-resources-pkg-id=$_expected_resources_pkg_id" ]
+
+      if (defined(invoker.shared_resources_whitelist)) {
+        inputs += [ invoker.shared_resources_whitelist ]
+        args += [
+          "--shared-resources-whitelist",
+          rebase_path(invoker.shared_resources_whitelist, root_build_dir),
+        ]
       }
 
       if (defined(invoker.proguard_file)) {
@@ -1690,7 +1900,7 @@
           "--depfile",
           rebase_path(depfile, root_build_dir),
           "--apk-path",
-          rebase_path(_packaged_resources_path, root_build_dir),
+          rebase_path(_compiled_resources_path, root_build_dir),
           "--output",
           rebase_path(invoker.output, root_build_dir),
           "--srcjar-in",
@@ -1708,14 +1918,14 @@
         }
         inputs = [
           _srcjar_path,
-          _packaged_resources_path,
+          _compiled_resources_path,
         ]
         outputs = [
           invoker.output,
           invoker.srcjar_path,
         ]
         public_deps = [
-          ":${_process_resources_target_name}",
+          ":${_compile_resources_target_name}",
         ]
       }
     }
@@ -1764,14 +1974,14 @@
         invoker.output_apk_path,
       ]
 
-      _rebased_packaged_resources_path =
+      _rebased_compiled_resources_path =
           rebase_path(invoker.packaged_resources_path, root_build_dir)
       _rebased_packaged_apk_path =
           rebase_path(invoker.output_apk_path, root_build_dir)
       args = [
         "--depfile",
         rebase_path(depfile, root_build_dir),
-        "--resource-apk=$_rebased_packaged_resources_path",
+        "--resource-apk=$_rebased_compiled_resources_path",
         "--output-apk=$_rebased_packaged_apk_path",
       ]
       if (defined(invoker.assets_build_config)) {
@@ -1936,27 +2146,23 @@
           invoker.native_libs_even_when_incremental
     }
 
-    _incremental_packaged_resources_path = "${_base_path}_incremental.ap_"
+    _incremental_compiled_resources_path = "${_base_path}_incremental.ap_"
     _packaged_apk_path = "${_base_path}_unsigned.apk"
     _incremental_packaged_apk_path = "${_base_path}_incremental_unsigned.apk"
     _shared_resources =
         defined(invoker.shared_resources) && invoker.shared_resources
     assert(_shared_resources || true)  # Mark as used.
-    _app_as_shared_lib =
-        defined(invoker.app_as_shared_lib) && invoker.app_as_shared_lib
-    assert(_app_as_shared_lib || true)  # Mark as used.
-    assert(!(_shared_resources && _app_as_shared_lib))
 
     _keystore_path = invoker.keystore_path
     _keystore_name = invoker.keystore_name
     _keystore_password = invoker.keystore_password
 
-    _incremental_package_resources_target_name =
-        "${target_name}_incremental__package_resources"
+    _incremental_compile_resources_target_name =
+        "${target_name}_incremental__compile_resources"
     _incremental_android_manifest =
-        get_label_info(_incremental_package_resources_target_name,
+        get_label_info(_incremental_compile_resources_target_name,
                        "target_gen_dir") + "/AndroidManifest.xml"
-    action(_incremental_package_resources_target_name) {
+    action(_incremental_compile_resources_target_name) {
       deps = _incremental_deps
       script =
           "//build/android/incremental_install/generate_android_manifest.py"
@@ -1970,7 +2176,7 @@
         # Output the non-compiled manifest for easy debugging (as opposed to
         # generating to a temp file).
         _incremental_android_manifest,
-        _incremental_packaged_resources_path,
+        _incremental_compiled_resources_path,
       ]
 
       _android_sdk_jar = android_sdk_jar
@@ -1985,7 +2191,7 @@
         "--in-apk",
         rebase_path(invoker.packaged_resources_path, root_build_dir),
         "--out-apk",
-        rebase_path(_incremental_packaged_resources_path, root_build_dir),
+        rebase_path(_incremental_compiled_resources_path, root_build_dir),
         "--aapt-path",
         rebase_path(android_default_aapt_path, root_build_dir),
         "--android-sdk-jar",
@@ -2036,7 +2242,7 @@
       }
       _dex_target = "//build/android/incremental_install:bootstrap_java__dex"
       deps = _incremental_deps + [
-               ":${_incremental_package_resources_target_name}",
+               ":${_incremental_compile_resources_target_name}",
                _dex_target,
              ]
 
@@ -2055,7 +2261,7 @@
       }
 
       output_apk_path = _incremental_packaged_apk_path
-      packaged_resources_path = _incremental_packaged_resources_path
+      packaged_resources_path = _incremental_compiled_resources_path
     }
 
     finalize_apk(target_name) {
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni
index 6db38cf..7467ef001 100644
--- a/build/config/android/rules.gni
+++ b/build/config/android/rules.gni
@@ -723,8 +723,6 @@
   #     false. (see build/android/gyp/generate_v14_compatible_resources.py)
   #   shared_resources: If true make a resource package that can be loaded by a
   #     different application at runtime to access the package's resources.
-  #   app_as_shared_lib: If true make a resource package that can be loaded as
-  #     both shared_resources and normal application.
   #   r_text_file: (optional) path to pre-generated R.txt to be used when
   #     generating R.java instead of resource-based aapt-generated one.
   #   create_srcjar: If false, does not create an R.java file. Needed only for
@@ -792,17 +790,15 @@
       }
     }
 
-    process_resources(target_name) {
+    prepare_resources(target_name) {
       forward_variables_from(invoker,
                              [
-                               "app_as_shared_lib",
                                "android_manifest",
                                "custom_package",
                                "deps",
                                "generated_resource_dirs",
                                "generated_resource_files",
                                "resource_dirs",
-                               "shared_resources",
                                "v14_skip",
                              ])
       if (!defined(deps)) {
@@ -1151,8 +1147,8 @@
       _deps += invoker.deps
     }
 
-    _process_resources_target = "${target_name}__process_resources"
-    process_resources(_process_resources_target) {
+    _prepare_resources_target = "${target_name}__prepare_resources"
+    prepare_resources(_prepare_resources_target) {
       deps = _deps + [ ":$_build_config_target_name" ]
       build_config = _build_config
       srcjar_path = "${target_gen_dir}/${target_name}.srcjar"
@@ -1182,7 +1178,7 @@
         srcjar_deps = []
       }
       srcjar_deps += [
-        ":$_process_resources_target",
+        ":$_prepare_resources_target",
 
         # This dep is required for any targets that depend on //base:base_java.
         "//base:base_build_config_gen",
@@ -1769,6 +1765,16 @@
   #     (mipmaps are still included).
   #   xxxhdpi_whitelist: A list of globs used when exclude_xxxhdpi=true. Files
   #     that match this whitelist will still be included.
+  #   shared_resources: True if this is a runtime shared library APK, like
+  #     the system_webview_apk target. Ensures that its resources can be
+  #     used by the loading application process.
+  #   app_as_shared_lib: True if this is a regular application apk that can
+  #     also serve as a runtime shared library, like the monochrome_public_apk
+  #     target. Ensures that the resources are usable both by the APK running
+  #     as an application, or by another process that loads it at runtime.
+  #   shared_resources_whitelist_target: Optional name of a target specifying
+  #     an input R.txt file that lists the resources that can be exported
+  #     by the APK when shared_resources or app_as_shared_lib is defined.
   #
   # Example
   #   android_apk("foo_apk") {
@@ -2014,8 +2020,8 @@
           "$_base_path.resources.main-dex-proguard.txt"
     }
     _generated_proguard_config = "$_base_path.resources.proguard.txt"
-    _process_resources_target = "${_template_name}__process_resources"
-    process_resources(_process_resources_target) {
+    _compile_resources_target = "${_template_name}__compile_resources"
+    compile_resources(_compile_resources_target) {
       forward_variables_from(invoker,
                              [
                                "alternative_android_sdk_jar",
@@ -2036,7 +2042,6 @@
       }
       srcjar_path = "${target_gen_dir}/${target_name}.srcjar"
       r_text_out_path = "${target_gen_dir}/${target_name}_R.txt"
-      generate_constant_ids = true
       proguard_file = _generated_proguard_config
       if (_enable_multidex) {
         proguard_file_main_dex = _generated_proguard_main_dex_config
@@ -2056,13 +2061,13 @@
             get_label_info(invoker.shared_resources_whitelist_target, "name")
         shared_resources_whitelist =
             "${_whitelist_gen_dir}/${_whitelist_target_name}" +
-            "__process_resources_R.txt"
+            "__compile_resources_R.txt"
         deps += [
-          "${invoker.shared_resources_whitelist_target}__process_resources",
+          "${invoker.shared_resources_whitelist_target}__compile_resources",
         ]
       }
     }
-    _srcjar_deps += [ ":$_process_resources_target" ]
+    _srcjar_deps += [ ":$_compile_resources_target" ]
 
     if (_native_libs_deps != []) {
       _enable_chromium_linker_tests = false
@@ -2240,7 +2245,7 @@
                                ])
         deps = _deps + [
                  ":$_build_config_target",
-                 ":$_process_resources_target",
+                 ":$_compile_resources_target",
                  ":$_java_target",
                ]
         inputs = [
@@ -2298,7 +2303,7 @@
 
       if (_enable_multidex) {
         extra_main_dex_proguard_config = _generated_proguard_main_dex_config
-        deps += [ ":$_process_resources_target" ]
+        deps += [ ":$_compile_resources_target" ]
       }
 
       # All deps are already included in _dex_sources when proguard is used.
@@ -2426,7 +2431,7 @@
       incremental_deps = _deps + [
                            ":$_merge_manifest_target",
                            ":$_build_config_target",
-                           ":$_process_resources_target",
+                           ":$_compile_resources_target",
                          ]
 
       # This target generates the input file _all_resources_zip_path.
@@ -2434,7 +2439,7 @@
                ":$_merge_manifest_target",
                ":$_build_config_target",
                ":$_final_dex_target_name",
-               ":$_process_resources_target",
+               ":$_compile_resources_target",
              ]
 
       if (_native_libs_deps != [] ||
diff --git a/build/config/dcheck_always_on.gni b/build/config/dcheck_always_on.gni
index b5eb503..e58cfce 100644
--- a/build/config/dcheck_always_on.gni
+++ b/build/config/dcheck_always_on.gni
@@ -2,10 +2,14 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build/config/sanitizers/sanitizers.gni")
+declare_args() {
+  # Enables DCHECKs to be built-in, but to default to being non-fatal/log-only.
+  # DCHECKS can then be set as fatal/non-fatal via the DCheckIsFatal feature.
+  # See crbug.com/596231 for details on how this is used.
+  dcheck_is_configurable = false
+}
 
 declare_args() {
   # Set to true to enable dcheck in Release builds.
-  # is_syzyasan defaults to logging/non-fatal DCHECKs - see crbug.com/596231.
-  dcheck_always_on = is_syzyasan
+  dcheck_always_on = dcheck_is_configurable
 }
diff --git a/build/config/fuchsia/rules.gni b/build/config/fuchsia/rules.gni
index f72ab7a..24d04237 100644
--- a/build/config/fuchsia/rules.gni
+++ b/build/config/fuchsia/rules.gni
@@ -144,6 +144,8 @@
       rebase_path(_package_path, root_out_dir, root_build_dir),
       "--package-name",
       invoker.package_name,
+      "--package-manifest",
+      rebase_path(_manifest_path),
     ]
   }
 }
diff --git a/build/config/win/BUILD.gn b/build/config/win/BUILD.gn
index b5719de3..568b55d 100644
--- a/build/config/win/BUILD.gn
+++ b/build/config/win/BUILD.gn
@@ -8,10 +8,17 @@
 import("//build/config/compiler/compiler.gni")
 import("//build/config/sanitizers/sanitizers.gni")
 import("//build/config/win/visual_studio_version.gni")
+import("//build/toolchain/goma.gni")
 import("//build/toolchain/toolchain.gni")
 
 assert(is_win)
 
+if (disable_goma) {
+  goma_disabled = "true"
+} else {
+  goma_disabled = "false"
+}
+
 declare_args() {
   # Set this to true to enable static analysis through Visual Studio's
   # /analyze. This dramatically slows compiles and reports thousands of
@@ -24,6 +31,20 @@
 
   # Turn this on to have the compiler output extra timing information.
   win_compiler_timing = false
+
+  # possible values for target_winuwp_version:
+  #   "10" - Windows UWP 10
+  #   "8.1" - Windows RT 8.1
+  #   "8.0" - Windows RT 8.0
+  target_winuwp_version = "10"
+
+  # possible values:
+  #   "app" - Windows Store Applications
+  #   "phone" - Windows Phone Applications
+  #   "system" - Windows Drivers and Tools
+  #   "server" - Windows Server Applications
+  #   "desktop" - Windows Desktop Applications
+  target_winuwp_family = "app"
 }
 
 # This is included by reference in the //build/config/compiler config that
@@ -239,6 +260,50 @@
     # not match ours.
     defines += [ "_LIBCPP_NO_AUTO_LINK" ]
   }
+
+  if (current_os == "winuwp") {
+    # When targeting Windows Runtime, certain compiler/linker flags are
+    # necessary.
+    defines += [
+      "WINUWP",
+      "__WRL_NO_DEFAULT_LIB__",
+    ]
+    if (target_winuwp_family == "app") {
+      defines += [ "WINAPI_FAMILY=WINAPI_FAMILY_PC_APP" ]
+    } else if (target_winuwp_family == "phone") {
+      defines += [ "WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP" ]
+    } else if (target_winuwp_family == "system") {
+      defines += [ "WINAPI_FAMILY=WINAPI_FAMILY_SYSTEM" ]
+    } else if (target_winuwp_family == "server") {
+      defines += [ "WINAPI_FAMILY=WINAPI_FAMILY_SERVER" ]
+    } else {
+      defines += [ "WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP" ]
+    }
+    cflags_cc += [
+      "/ZW",
+      "/EHsc",
+    ]
+
+    # This warning is given because the linker cannot tell the difference
+    # between consuming WinRT APIs versus authoring WinRT within static
+    # libraries as such this warning is always given by the linker. Since
+    # consuming WinRT APIs within a library is legitimate but authoring
+    # WinRT APis is not allowed, this warning is disabled to ignore the
+    # legitimate consumption of WinRT APIs within static library builds.
+    arflags = [ "/IGNORE:4264" ]
+
+    if (target_winuwp_version == "10") {
+      defines += [ "WIN10=_WIN32_WINNT_WIN10" ]
+    } else if (target_winuwp_version == "8.1") {
+      defines += [ "WIN8_1=_WIN32_WINNT_WINBLUE" ]
+    } else if (target_winuwp_version == "8.0") {
+      defines += [ "WIN8=_WIN32_WINNT_WIN8" ]
+    }
+  } else {
+    # When not targeting Windows Runtime, make sure the WINAPI family is set
+    # to desktop.
+    defines += [ "WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP" ]
+  }
 }
 
 # Sets the default Windows build version. This is separated because some
@@ -253,24 +318,47 @@
 
 # Linker flags for Windows SDK setup, this is applied only to EXEs and DLLs.
 config("sdk_link") {
+  assert(current_cpu == "x64" || current_cpu == "x86" || current_cpu == "arm" ||
+             current_cpu == "arm64",
+         "Only supports x64, x86, arm and arm64 CPUs")
   if (current_cpu == "x64") {
     ldflags = [ "/MACHINE:X64" ]
-    lib_dirs = [
-      "$windows_sdk_path\Lib\winv6.3\um\x64",
-      "$visual_studio_path\VC\lib\amd64",
-      "$visual_studio_path\VC\atlmfc\lib\amd64",
-    ]
-  } else {
+  } else if (current_cpu == "x86") {
     ldflags = [
       "/MACHINE:X86",
       "/SAFESEH",  # Not compatible with x64 so use only for x86.
       "/largeaddressaware",
     ]
-    lib_dirs = [
-      "$windows_sdk_path\Lib\winv6.3\um\x86",
-      "$visual_studio_path\VC\lib",
-      "$visual_studio_path\VC\atlmfc\lib",
-    ]
+  } else if (current_cpu == "arm") {
+    ldflags = [ "/MACHINE:ARM" ]
+  } else if (current_cpu == "arm64") {
+    ldflags = [ "/MACHINE:ARM64" ]
+  }
+
+  vcvars_toolchain_data = exec_script("../../toolchain/win/setup_toolchain.py",
+                                      [
+                                        visual_studio_path,
+                                        windows_sdk_path,
+                                        visual_studio_runtime_dirs,
+                                        current_os,
+                                        current_cpu,
+                                        "none",
+                                        goma_disabled,
+                                      ],
+                                      "scope")
+
+  vc_lib_path = vcvars_toolchain_data.vc_lib_path
+  if (defined(vcvars_toolchain_data.vc_lib_atlmfc_path)) {
+    vc_lib_atlmfc_path = vcvars_toolchain_data.vc_lib_atlmfc_path
+  }
+  vc_lib_um_path = vcvars_toolchain_data.vc_lib_um_path
+
+  lib_dirs = [
+    "$vc_lib_um_path",
+    "$vc_lib_path",
+  ]
+  if (defined(vc_lib_atlmfc_path)) {
+    lib_dirs += [ "$vc_lib_atlmfc_path" ]
   }
 }
 
@@ -328,8 +416,10 @@
     # exceptions on.
     configs = [ ":dynamic_crt" ]
   } else {
-    if (current_os != "win") {
-      # WindowsRT: use the dynamic CRT.
+    if (current_os == "winuwp") {
+      # https://blogs.msdn.microsoft.com/vcblog/2014/06/10/the-great-c-runtime-crt-refactoring/
+      # contains a details explanation of what is happening with the Windows
+      # CRT in Visual Studio releases related to Windows store applications.
       configs = [ ":dynamic_crt" ]
     } else {
       # Desktop Windows: static CRT.
@@ -458,21 +548,6 @@
   defines = [ "NOMINMAX" ]
 }
 
-# Target WinRT ----------------------------------------------------------------
-
-# When targeting Windows Runtime, certain compiler/linker flags are necessary.
-
-config("target_winrt") {
-  defines = [
-    "WINRT",
-    "WINAPI_FAMILY=WINAPI_FAMILY_PC_APP",
-  ]
-  cflags_cc = [
-    "/ZW",
-    "/EHsc",
-  ]
-}
-
 # Generating order files -------------------------------------------------------
 
 config("default_cygprofile_instrumentation") {
diff --git a/build/fuchsia/runner_v2/common_args.py b/build/fuchsia/runner_v2/common_args.py
index 62552dda..fdd7101 100644
--- a/build/fuchsia/runner_v2/common_args.py
+++ b/build/fuchsia/runner_v2/common_args.py
@@ -21,6 +21,9 @@
   common_args.add_argument('--package-name', required=True,
                            help='Name of the package to execute, defined in ' +
                                 'package metadata.')
+  common_args.add_argument('--package-manifest',
+                           type=os.path.realpath, required=True,
+                           help='Path to the Fuchsia package manifest file.')
   common_args.add_argument('--output-directory',
                            type=os.path.realpath, required=True,
                            help=('Path to the directory in which build files are'
diff --git a/build/fuchsia/runner_v2/create_runner_script.py b/build/fuchsia/runner_v2/create_runner_script.py
index e008d12..80fd16d 100755
--- a/build/fuchsia/runner_v2/create_runner_script.py
+++ b/build/fuchsia/runner_v2/create_runner_script.py
@@ -55,6 +55,7 @@
   group = parser.add_argument_group('Test runner path arguments.')
   group.add_argument('--output-directory')
   group.add_argument('--package')
+  group.add_argument('--package-manifest')
   args, runner_args = parser.parse_known_args(args)
 
   def RelativizePathToScript(path):
@@ -70,6 +71,8 @@
       ('--output-directory', RelativizePathToScript(args.output_directory)))
   runner_path_args.append(
       ('--package', RelativizePathToScript(args.package)))
+  runner_path_args.append(
+      ('--package-manifest', RelativizePathToScript(args.package_manifest)))
 
   with open(args.script_output_path, 'w') as script:
     script.write(SCRIPT_TEMPLATE.format(
diff --git a/build/fuchsia/runner_v2/exe_runner.py b/build/fuchsia/runner_v2/exe_runner.py
index d934810..17b1cb6 100755
--- a/build/fuchsia/runner_v2/exe_runner.py
+++ b/build/fuchsia/runner_v2/exe_runner.py
@@ -28,7 +28,7 @@
   with GetDeploymentTargetForArgs(args) as target:
     target.Start()
     RunPackage(args.output_directory, target, args.package,
-               args.package_name, args.child_args)
+               args.package_name, args.child_args, args.package_manifest)
 
 
 if __name__ == '__main__':
diff --git a/build/fuchsia/runner_v2/run_package.py b/build/fuchsia/runner_v2/run_package.py
index b05ec44..9afae34 100644
--- a/build/fuchsia/runner_v2/run_package.py
+++ b/build/fuchsia/runner_v2/run_package.py
@@ -63,6 +63,7 @@
     output = FilterStream(process.stdout, package_name,
                           symbolizer_config, output_dir)
   else:
+    logging.warn('Symbolization is DISABLED.')
     output = process.stdout
 
   for next_line in output:
diff --git a/build/fuchsia/runner_v2/test_runner.py b/build/fuchsia/runner_v2/test_runner.py
index 36c8a71c..a939d6b4 100755
--- a/build/fuchsia/runner_v2/test_runner.py
+++ b/build/fuchsia/runner_v2/test_runner.py
@@ -101,7 +101,7 @@
       test_server, forwarder = SetupTestServer(target, test_concurrency)
 
     RunPackage(args.output_directory, target, args.package, args.package_name,
-               child_args)
+               child_args, args.package_manifest)
 
     if forwarder:
       forwarder.terminate()
diff --git a/build/fuchsia/sdk.sha1 b/build/fuchsia/sdk.sha1
new file mode 100644
index 0000000..ca42ae5
--- /dev/null
+++ b/build/fuchsia/sdk.sha1
@@ -0,0 +1 @@
+32a56ad54471732034ba802cbfc3c9ff277b9d1c
diff --git a/build/fuchsia/update_sdk.py b/build/fuchsia/update_sdk.py
index eef823b..4b515ba 100755
--- a/build/fuchsia/update_sdk.py
+++ b/build/fuchsia/update_sdk.py
@@ -13,7 +13,7 @@
 import tarfile
 import tempfile
 
-SDK_HASH = '32a56ad54471732034ba802cbfc3c9ff277b9d1c'
+SDK_HASH_FILE = os.path.join(os.path.dirname(__file__), 'sdk.sha1')
 
 REPOSITORY_ROOT = os.path.abspath(os.path.join(
     os.path.dirname(__file__), '..', '..'))
@@ -33,16 +33,23 @@
     print >>sys.stderr, 'usage: %s' % sys.argv[0]
     return 1
 
+  with open(SDK_HASH_FILE, 'r') as f:
+    sdk_hash = f.read().strip()
+
+  if not sdk_hash:
+    print >>sys.stderr, 'No SHA1 found in %s' % SDK_HASH_FILE
+    return 1
+
   output_dir = os.path.join(REPOSITORY_ROOT, 'third_party', 'fuchsia-sdk')
 
   hash_filename = os.path.join(output_dir, '.hash')
   if os.path.exists(hash_filename):
     with open(hash_filename, 'r') as f:
-      if f.read().strip() == SDK_HASH:
+      if f.read().strip() == sdk_hash:
         # Nothing to do.
         return 0
 
-  print 'Downloading SDK %s...' % SDK_HASH
+  print 'Downloading SDK %s...' % sdk_hash
 
   if os.path.isdir(output_dir):
     shutil.rmtree(output_dir)
@@ -53,7 +60,7 @@
   try:
     bucket = 'gs://fuchsia/sdk/linux-amd64/'
     cmd = [os.path.join(find_depot_tools.DEPOT_TOOLS_PATH, 'gsutil.py'),
-           'cp', bucket + SDK_HASH, tmp]
+           'cp', bucket + sdk_hash, tmp]
     subprocess.check_call(cmd)
     with open(tmp, 'rb') as f:
       EnsureDirExists(output_dir)
@@ -62,7 +69,7 @@
     os.remove(tmp)
 
   with open(hash_filename, 'w') as f:
-    f.write(SDK_HASH)
+    f.write(sdk_hash)
 
   return 0
 
diff --git a/build/linux/unbundle/icu.gn b/build/linux/unbundle/icu.gn
index 5bdd915..4450e40 100644
--- a/build/linux/unbundle/icu.gn
+++ b/build/linux/unbundle/icu.gn
@@ -17,6 +17,24 @@
     "USING_SYSTEM_ICU=1",
     "ICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC",
     "UCHAR_TYPE=uint16_t",
+
+    # U_EXPORT (defined in unicode/platform.h) is used to set public visibility
+    # on classes through the U_COMMON_API and U_I18N_API macros (among others).
+    # When linking against the system ICU library, we want its symbols to have
+    # public LTO visibility. This disables CFI checks for the ICU classes and
+    # allows whole-program optimization to be applied to the rest of Chromium.
+    #
+    # Both U_COMMON_API and U_I18N_API macros would be defined to U_EXPORT only
+    # when U_COMBINED_IMPLEMENTATION is defined (see unicode/utypes.h). Because
+    # we override the default system UCHAR_TYPE (char16_t), it is not possible
+    # to use U_COMBINED_IMPLEMENTATION at this moment, meaning the U_COMMON_API
+    # and U_I18N_API macros are set to U_IMPORT which is an empty definition.
+    #
+    # Until building with UCHAR_TYPE=char16_t is supported, one way to apply
+    # public visibility (and thus public LTO visibility) to all ICU classes is
+    # to define U_IMPORT to have the same value as U_EXPORT. For more details,
+    # please see: https://crbug.com/822820
+    "U_IMPORT=U_EXPORT",
   ]
 }
 
diff --git a/build/linux/unbundle/libjpeg.gn b/build/linux/unbundle/libjpeg.gn
index 51c352c2..17398ea6 100644
--- a/build/linux/unbundle/libjpeg.gn
+++ b/build/linux/unbundle/libjpeg.gn
@@ -1,26 +1,12 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
+# Copyright 2018 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/shim_headers.gni")
+declare_args() {
+  # Uses system libjpeg. If true, overrides use_libjpeg_turbo.
+  use_system_libjpeg = true
 
-shim_headers("libjpeg_shim") {
-  root_path = "."
-  headers = [ "jpeglib.h" ]
-}
-
-source_set("libjpeg") {
-  deps = [
-    ":libjpeg_shim",
-  ]
-  libs = [ "jpeg" ]
-}
-
-source_set("simd") {
-}
-
-source_set("simd_asm") {
-}
-
-config("libjpeg_config") {
+  # Uses libjpeg_turbo as the jpeg implementation. Has no effect if
+  # use_system_libjpeg is set.
+  use_libjpeg_turbo = true
 }
diff --git a/build/linux/unbundle/replace_gn_files.py b/build/linux/unbundle/replace_gn_files.py
index 76b79c4..d4d07f2 100755
--- a/build/linux/unbundle/replace_gn_files.py
+++ b/build/linux/unbundle/replace_gn_files.py
@@ -25,7 +25,7 @@
   'icu': 'third_party/icu/BUILD.gn',
   'libdrm': 'third_party/libdrm/BUILD.gn',
   'libevent': 'base/third_party/libevent/BUILD.gn',
-  'libjpeg': 'build/secondary/third_party/libjpeg_turbo/BUILD.gn',
+  'libjpeg': 'third_party/libjpeg.gni',
   'libpng': 'third_party/libpng/BUILD.gn',
   'libvpx': 'third_party/libvpx/BUILD.gn',
   'libwebp': 'third_party/libwebp/BUILD.gn',
diff --git a/build/toolchain/win/BUILD.gn b/build/toolchain/win/BUILD.gn
index 53f767a0..142982a 100644
--- a/build/toolchain/win/BUILD.gn
+++ b/build/toolchain/win/BUILD.gn
@@ -73,8 +73,6 @@
 
       # This value needs to be passed through unchanged.
       host_toolchain = host_toolchain
-
-      current_os = "win"
     }
 
     # Make these apply to all tools below.
@@ -356,37 +354,43 @@
   clang_cl = "clang-cl"
 }
 
-# 32-bit toolchains. Only define these when the target architecture is 32-bit
-# since we don't do any 32-bit cross compiles when targeting 64-bit (the
-# build does generate some 64-bit stuff from 32-bit target builds).
-if (target_cpu == "x86") {
-  x86_toolchain_data = exec_script("setup_toolchain.py",
-                                   [
-                                     visual_studio_path,
-                                     windows_sdk_path,
-                                     visual_studio_runtime_dirs,
-                                     "x86",
-                                     goma_disabled,
-                                   ],
-                                   "scope")
+# x86, arm and arm64 toolchains for Windows (not WinUWP). Only define when the
+# target architecture is one of these architectures since we don't do any arm
+# cross compiles when targeting 64-bit (the build does generate some 64-bit
+# stuff from 32-bit/arm/arm64 target builds).
+if (target_os == "win" &&
+    (target_cpu == "x86" || target_cpu == "arm" || target_cpu == "arm64")) {
+  target_cpu_toolchain_data = exec_script("setup_toolchain.py",
+                                          [
+                                            visual_studio_path,
+                                            windows_sdk_path,
+                                            visual_studio_runtime_dirs,
+                                            target_os,
+                                            target_cpu,
+                                            "environment." + target_cpu,
+                                            goma_disabled,
+                                          ],
+                                          "scope")
 
-  msvc_toolchain("x86") {
-    environment = "environment.x86"
-    cl = "${goma_prefix}\"${x86_toolchain_data.vc_bin_dir}/cl.exe\""
+  msvc_toolchain(target_cpu) {
+    environment = "environment." + target_cpu
+    cl = "${goma_prefix}\"${target_cpu_toolchain_data.vc_bin_dir}/cl.exe\""
     toolchain_args = {
-      current_cpu = "x86"
+      current_os = "win"
+      current_cpu = target_cpu
       is_clang = false
     }
   }
 
-  msvc_toolchain("win_clang_x86") {
-    environment = "environment.x86"
+  msvc_toolchain("win_clang_" + target_cpu) {
+    environment = "environment." + target_cpu
     prefix = rebase_path("$clang_base_path/bin", root_build_dir)
     cl = "${goma_prefix}$prefix/${clang_cl}"
-    sys_include_flags = "${x86_toolchain_data.include_flags_imsvc}"
+    sys_include_flags = "${target_cpu_toolchain_data.include_flags_imsvc}"
 
     toolchain_args = {
-      current_cpu = "x86"
+      current_os = "win"
+      current_cpu = target_cpu
       is_clang = true
     }
   }
@@ -398,7 +402,9 @@
                                    visual_studio_path,
                                    windows_sdk_path,
                                    visual_studio_runtime_dirs,
+                                   "win",
                                    "x64",
+                                   "environment.x64",
                                    goma_disabled,
                                  ],
                                  "scope")
@@ -413,6 +419,7 @@
         forward_variables_from(invoker.toolchain_args, "*")
       }
       is_clang = false
+      current_os = "win"
       current_cpu = "x64"
     }
   }
@@ -428,6 +435,7 @@
         forward_variables_from(invoker.toolchain_args, "*")
       }
       is_clang = true
+      current_os = "win"
       current_cpu = "x64"
     }
   }
@@ -450,30 +458,30 @@
   }
 }
 
-# WinRT toolchains. Only define these when targeting them.
-#
-# NOTE: This is currently broken because it references vc_bin_dir. brettw@
-# changed this around a bit, and I don't know what this should be set to
-# in terms of what setup_toolchain returns for a certain CPU architecture.
-if (target_os == "winrt_81" || target_os == "winrt_81_phone" ||
-    target_os == "winrt_10") {
-  msvc_toolchain("winrt_x86") {
-    environment = "environment.winrt_x86"
-    cl = "${goma_prefix}\"${vc_bin_dir}/cl.exe\""
+# WinUWP toolchains. Only define these when targeting them.
 
+if (target_os == "winuwp") {
+  assert(target_cpu == "x64" || target_cpu == "x86" || target_cpu == "arm" ||
+         target_cpu == "arm64")
+  store_cpu_toolchain_data = exec_script("setup_toolchain.py",
+                                         [
+                                           visual_studio_path,
+                                           windows_sdk_path,
+                                           visual_studio_runtime_dirs,
+                                           target_os,
+                                           target_cpu,
+                                           "environment.store_" + target_cpu,
+                                           goma_disabled,
+                                         ],
+                                         "scope")
+
+  msvc_toolchain("uwp_" + target_cpu) {
+    environment = "environment.store_" + target_cpu
+    cl = "${goma_prefix}\"${store_cpu_toolchain_data.vc_bin_dir}/cl.exe\""
     toolchain_args = {
+      current_os = "winuwp"
+      current_cpu = target_cpu
       is_clang = false
-      current_cpu = "x86"
-    }
-  }
-
-  msvc_toolchain("winrt_x64") {
-    environment = "environment.winrt_x64"
-    cl = "${goma_prefix}\"${vc_bin_dir}/cl.exe\""
-
-    toolchain_args = {
-      is_clang = false
-      current_cpu = "x64"
     }
   }
 }
diff --git a/build/toolchain/win/setup_toolchain.py b/build/toolchain/win/setup_toolchain.py
index a1d2ea4b..5c56f6a 100644
--- a/build/toolchain/win/setup_toolchain.py
+++ b/build/toolchain/win/setup_toolchain.py
@@ -83,13 +83,13 @@
   return variables
 
 
-def _LoadToolchainEnv(cpu, sdk_dir):
+def _LoadToolchainEnv(cpu, sdk_dir, target_store):
   """Returns a dictionary with environment variables that must be set while
   running binaries from the toolchain (e.g. INCLUDE and PATH for cl.exe)."""
   # Check if we are running in the SDK command line environment and use
   # the setup script from the SDK if so. |cpu| should be either
-  # 'x86' or 'x64'.
-  assert cpu in ('x86', 'x64')
+  # 'x86' or 'x64' or 'arm' or 'arm64'.
+  assert cpu in ('x86', 'x64', 'arm', 'arm64')
   if bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', 1))) and sdk_dir:
     # Load environment from json file.
     env = os.path.normpath(os.path.join(sdk_dir, 'bin/SetEnv.%s.json' % cpu))
@@ -139,11 +139,18 @@
         raise Exception('%s is missing - make sure VC++ tools are installed.' %
                         script_path)
       script_path = other_path
+    cpu_arg = "amd64"
+    if (cpu != 'x64'):
+      # x64 is default target CPU thus any other CPU requires a target set
+      cpu_arg += '_' + cpu
+    args = [script_path, cpu_arg]
+    # Store target must come before any SDK version declaration
+    if (target_store):
+      args.append(['store'])
     # Chromium requires the 10.0.15063.468 SDK - previous versions don't have
     # all of the required declarations and 10.0.16299.0 has some
     # incompatibilities (crbug.com/773476).
-    args = [script_path, 'amd64_x86' if cpu == 'x86' else 'amd64',
-            '10.0.15063.0']
+    args.append('10.0.15063.0')
     variables = _LoadEnvFromBat(args)
   return _ExtractImportantEnvironment(variables)
 
@@ -161,53 +168,74 @@
 
 
 def main():
-  if len(sys.argv) != 6:
+  if len(sys.argv) != 8:
     print('Usage setup_toolchain.py '
           '<visual studio path> <win sdk path> '
-          '<runtime dirs> <target_cpu> <goma_disabled>')
+          '<runtime dirs> <target_os> <target_cpu> '
+          '<environment block name|none> <goma_disabled>')
     sys.exit(2)
   win_sdk_path = sys.argv[2]
   runtime_dirs = sys.argv[3]
-  target_cpu = sys.argv[4]
-  goma_disabled = sys.argv[5]
+  target_os = sys.argv[4]
+  target_cpu = sys.argv[5]
+  environment_block_name = sys.argv[6]
+  if (environment_block_name == 'none'):
+    environment_block_name = ''
+  goma_disabled = sys.argv[7]
 
-  cpus = ('x86', 'x64')
+  if (target_os == 'winuwp'):
+    target_store = True
+  else:
+    target_store = False
+
+  cpus = ('x86', 'x64', 'arm', 'arm64')
   assert target_cpu in cpus
   vc_bin_dir = ''
+  vc_lib_path = ''
+  vc_lib_atlmfc_path = ''
+  vc_lib_um_path = ''
   include = ''
 
   # TODO(scottmg|goma): Do we need an equivalent of
   # ninja_use_custom_environment_files?
 
   for cpu in cpus:
-    # Extract environment variables for subprocesses.
-    env = _LoadToolchainEnv(cpu, win_sdk_path)
-    env['PATH'] = runtime_dirs + os.pathsep + env['PATH']
-    env['GOMA_DISABLED'] = goma_disabled
-
     if cpu == target_cpu:
+      # Extract environment variables for subprocesses.
+      env = _LoadToolchainEnv(cpu, win_sdk_path, target_store)
+      env['PATH'] = runtime_dirs + os.pathsep + env['PATH']
+      env['GOMA_DISABLED'] = goma_disabled
+
       for path in env['PATH'].split(os.pathsep):
         if os.path.exists(os.path.join(path, 'cl.exe')):
           vc_bin_dir = os.path.realpath(path)
           break
+
+      for path in env['LIB'].split(os.pathsep):
+        if os.path.exists(os.path.join(path, 'msvcrt.lib')):
+          vc_lib_path = os.path.realpath(path)
+          break
+
+      for path in env['LIB'].split(os.pathsep):
+        if os.path.exists(os.path.join(path, 'atls.lib')):
+          vc_lib_atlmfc_path = os.path.realpath(path)
+          break
+
+      for path in env['LIB'].split(os.pathsep):
+        if os.path.exists(os.path.join(path, 'User32.Lib')):
+          vc_lib_um_path = os.path.realpath(path)
+          break
+
       # The separator for INCLUDE here must match the one used in
       # _LoadToolchainEnv() above.
       include = [p.replace('"', r'\"') for p in env['INCLUDE'].split(';') if p]
       include_I = ' '.join(['"/I' + i + '"' for i in include])
       include_imsvc = ' '.join(['"-imsvc' + i + '"' for i in include])
 
-    env_block = _FormatAsEnvironmentBlock(env)
-    with open('environment.' + cpu, 'wb') as f:
-      f.write(env_block)
-
-    # Create a store app version of the environment.
-    if 'LIB' in env:
-      env['LIB']     = env['LIB']    .replace(r'\VC\LIB', r'\VC\LIB\STORE')
-    if 'LIBPATH' in env:
-      env['LIBPATH'] = env['LIBPATH'].replace(r'\VC\LIB', r'\VC\LIB\STORE')
-    env_block = _FormatAsEnvironmentBlock(env)
-    with open('environment.winrt_' + cpu, 'wb') as f:
-      f.write(env_block)
+      if (environment_block_name != ''):
+        env_block = _FormatAsEnvironmentBlock(env)
+        with open(environment_block_name, 'wb') as f:
+          f.write(env_block)
 
   assert vc_bin_dir
   print 'vc_bin_dir = ' + gn_helpers.ToGNString(vc_bin_dir)
@@ -215,6 +243,17 @@
   print 'include_flags_I = ' + gn_helpers.ToGNString(include_I)
   assert include_imsvc
   print 'include_flags_imsvc = ' + gn_helpers.ToGNString(include_imsvc)
+  assert vc_lib_path
+  print 'vc_lib_path = ' + gn_helpers.ToGNString(vc_lib_path)
+  if (target_store != True):
+    # Path is assumed not to exist for desktop applications
+    assert vc_lib_atlmfc_path
+  # Possible atlmfc library path gets introduced in the future for store thus
+  # output result if a result exists.
+  if (vc_lib_atlmfc_path != ''):
+    print 'vc_lib_atlmfc_path = ' + gn_helpers.ToGNString(vc_lib_atlmfc_path)
+  assert vc_lib_um_path
+  print 'vc_lib_um_path = ' + gn_helpers.ToGNString(vc_lib_um_path)
 
 if __name__ == '__main__':
   main()
diff --git a/build/vs_toolchain.py b/build/vs_toolchain.py
index 5f9541e..6060415b 100755
--- a/build/vs_toolchain.py
+++ b/build/vs_toolchain.py
@@ -93,8 +93,8 @@
     bitness = platform.architecture()[0]
     # When running 64-bit python the x64 DLLs will be in System32
     x64_path = 'System32' if bitness == '64bit' else 'Sysnative'
-    x64_path = os.path.join(r'C:\Windows', x64_path)
-    vs_runtime_dll_dirs = [x64_path, r'C:\Windows\SysWOW64']
+    x64_path = os.path.join(os.path.expandvars('%windir%'), x64_path)
+    vs_runtime_dll_dirs = [x64_path, os.path.expandvars('%windir%/SysWOW64')]
 
   return vs_runtime_dll_dirs
 
@@ -154,9 +154,12 @@
     # For now we use a hardcoded default with an environment variable override.
     for path in (
         os.environ.get('vs2017_install'),
-        r'C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise',
-        r'C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional',
-        r'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community'):
+        os.path.expandvars('%ProgramFiles(x86)%'
+                           '/Microsoft Visual Studio/2017/Enterprise'),
+        os.path.expandvars('%ProgramFiles(x86)%'
+                           '/Microsoft Visual Studio/2017/Professional'),
+        os.path.expandvars('%ProgramFiles(x86)%'
+                           '/Microsoft Visual Studio/2017/Community')):
       if path and os.path.exists(path):
         return path
 
@@ -431,7 +434,8 @@
 
   # If WINDOWSSDKDIR is not set, search the default SDK path and set it.
   if not 'WINDOWSSDKDIR' in os.environ:
-    default_sdk_path = 'C:\\Program Files (x86)\\Windows Kits\\10'
+    default_sdk_path = os.path.expandvars('%ProgramFiles(x86)%'
+                                          '\\Windows Kits\\10')
     if os.path.isdir(default_sdk_path):
       os.environ['WINDOWSSDKDIR'] = default_sdk_path
 
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index ed0afe6f..67db085 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -373,7 +373,7 @@
     "//gpu/command_buffer/client:raster_interface",
     "//gpu/ipc:gl_in_process_context",
     "//gpu/skia_bindings:skia_bindings",
-    "//gpu/vulkan:features",
+    "//gpu/vulkan:buildflags",
     "//media",
     "//mojo/public/cpp/bindings:struct_traits",
     "//services/metrics/public/cpp:ukm_builders",
diff --git a/cc/blink/web_external_texture_layer_impl.cc b/cc/blink/web_external_texture_layer_impl.cc
index b6d042bc..64fbf26 100644
--- a/cc/blink/web_external_texture_layer_impl.cc
+++ b/cc/blink/web_external_texture_layer_impl.cc
@@ -54,4 +54,12 @@
       ->SetNearestNeighbor(nearest_neighbor);
 }
 
+void WebExternalTextureLayerImpl::SetUV(
+    const blink::WebFloatPoint left_top,
+    const blink::WebFloatPoint right_bottom) {
+  static_cast<TextureLayer*>(layer_->layer())
+      ->SetUV(gfx::PointF(left_top.x, left_top.y),
+              gfx::PointF(right_bottom.x, right_bottom.y));
+}
+
 }  // namespace cc_blink
diff --git a/cc/blink/web_external_texture_layer_impl.h b/cc/blink/web_external_texture_layer_impl.h
index e7bea81..e5f712f 100644
--- a/cc/blink/web_external_texture_layer_impl.h
+++ b/cc/blink/web_external_texture_layer_impl.h
@@ -31,6 +31,8 @@
   void SetPremultipliedAlpha(bool premultiplied) override;
   void SetBlendBackgroundColor(bool blend) override;
   void SetNearestNeighbor(bool nearest_neighbor) override;
+  void SetUV(const blink::WebFloatPoint left_top,
+             const blink::WebFloatPoint right_bottom) override;
 
  private:
   std::unique_ptr<WebLayerImpl> layer_;
diff --git a/cc/input/input_handler.h b/cc/input/input_handler.h
index 04c27fc..8971085 100644
--- a/cc/input/input_handler.h
+++ b/cc/input/input_handler.h
@@ -49,6 +49,8 @@
   // How the browser should handle the overscroll navigation based on the css
   // property scroll-boundary-behavior.
   OverscrollBehavior overscroll_behavior;
+  // The current offset of the currently scrolling node.
+  gfx::Vector2dF current_offset;
 };
 
 class CC_EXPORT InputHandlerClient {
@@ -231,6 +233,15 @@
 
   virtual bool ScrollingShouldSwitchtoMainThread() = 0;
 
+  // Sets the initial and target offset for scroll snapping for the currently
+  // scrolling node and the given natural displacement.
+  // Natural displacement is the estimated total scrolling for the active scroll
+  // sequence.
+  // Returns false if their is no position to snap to.
+  virtual bool GetSnapFlingInfo(const gfx::Vector2dF& natural_displacement,
+                                gfx::Vector2dF* initial_offset,
+                                gfx::Vector2dF* target_offset) const = 0;
+
  protected:
   InputHandler() {}
   virtual ~InputHandler() {}
diff --git a/cc/input/scroll_snap_data.cc b/cc/input/scroll_snap_data.cc
index 8c1948d..58b2258 100644
--- a/cc/input/scroll_snap_data.cc
+++ b/cc/input/scroll_snap_data.cc
@@ -120,19 +120,18 @@
   snap_area_list_.push_back(snap_area_data);
 }
 
-gfx::ScrollOffset SnapContainerData::FindSnapPosition(
+bool SnapContainerData::FindSnapPosition(
     const gfx::ScrollOffset& current_position,
     bool should_snap_on_x,
-    bool should_snap_on_y) const {
+    bool should_snap_on_y,
+    gfx::ScrollOffset* snap_position) const {
   SnapAxis axis = scroll_snap_type_.axis;
   should_snap_on_x &= (axis == SnapAxis::kX || axis == SnapAxis::kBoth);
   should_snap_on_y &= (axis == SnapAxis::kY || axis == SnapAxis::kBoth);
   if (!should_snap_on_x && !should_snap_on_y)
-    return current_position;
+    return false;
 
-  gfx::ScrollOffset snap_position = current_position;
   base::Optional<SnapAreaData> closest_x, closest_y;
-
   // A region that includes every reachable scroll position.
   gfx::RectF scrollable_region(0, 0, max_position_.x(), max_position_.y());
   if (should_snap_on_x) {
@@ -146,6 +145,9 @@
                                      proximity_range_, snap_area_list_);
   }
 
+  if (!closest_x.has_value() && !closest_y.has_value())
+    return false;
+
   // If snapping in one axis pushes off-screen the other snap area, this snap
   // position is invalid. https://drafts.csswg.org/css-scroll-snap-1/#snap-scope
   // In this case, we choose the axis whose snap area is closer, and find a
@@ -169,12 +171,14 @@
           closest_y.value().visible_region, proximity_range_, snap_area_list_);
     }
   }
-  if (closest_x.has_value())
-    snap_position.set_x(closest_x.value().snap_position.x());
-  if (closest_y.has_value())
-    snap_position.set_y(closest_y.value().snap_position.y());
 
-  return snap_position;
+  *snap_position = current_position;
+  if (closest_x.has_value())
+    snap_position->set_x(closest_x.value().snap_position.x());
+  if (closest_y.has_value())
+    snap_position->set_y(closest_y.value().snap_position.y());
+
+  return true;
 }
 
 std::ostream& operator<<(std::ostream& ostream, const SnapAreaData& area_data) {
diff --git a/cc/input/scroll_snap_data.h b/cc/input/scroll_snap_data.h
index 7eb3580..dbc0b91 100644
--- a/cc/input/scroll_snap_data.h
+++ b/cc/input/scroll_snap_data.h
@@ -167,9 +167,10 @@
     return !(*this == other);
   }
 
-  gfx::ScrollOffset FindSnapPosition(const gfx::ScrollOffset& current_position,
-                                     bool should_snap_on_x,
-                                     bool should_snap_on_y) const;
+  bool FindSnapPosition(const gfx::ScrollOffset& current_position,
+                        bool should_snap_on_x,
+                        bool should_snap_on_y,
+                        gfx::ScrollOffset* snap_position) const;
 
   void AddSnapAreaData(SnapAreaData snap_area_data);
   size_t size() const { return snap_area_list_.size(); }
diff --git a/cc/input/scroll_snap_data_unittest.cc b/cc/input/scroll_snap_data_unittest.cc
index 0551446..794f83fa 100644
--- a/cc/input/scroll_snap_data_unittest.cc
+++ b/cc/input/scroll_snap_data_unittest.cc
@@ -26,8 +26,9 @@
   data.AddSnapAreaData(snap_x_only);
   data.AddSnapAreaData(snap_y_only);
   data.AddSnapAreaData(snap_on_both);
-  gfx::ScrollOffset snap_position =
-      data.FindSnapPosition(current_position, true, true);
+  gfx::ScrollOffset snap_position;
+  EXPECT_TRUE(
+      data.FindSnapPosition(current_position, true, true, &snap_position));
   EXPECT_EQ(80, snap_position.x());
   EXPECT_EQ(70, snap_position.y());
 }
@@ -48,8 +49,9 @@
   data.AddSnapAreaData(snap_x_only);
   data.AddSnapAreaData(snap_y_only);
   data.AddSnapAreaData(snap_on_both);
-  gfx::ScrollOffset snap_position =
-      data.FindSnapPosition(current_position, true, true);
+  gfx::ScrollOffset snap_position;
+  EXPECT_TRUE(
+      data.FindSnapPosition(current_position, true, true, &snap_position));
   EXPECT_EQ(50, snap_position.x());
   EXPECT_EQ(150, snap_position.y());
 }
@@ -67,8 +69,9 @@
       gfx::RectF(0, 0, 360, 380), false);
   data.AddSnapAreaData(snap_x_only);
   data.AddSnapAreaData(snap_y_only);
-  gfx::ScrollOffset snap_position =
-      data.FindSnapPosition(current_position, true, false);
+  gfx::ScrollOffset snap_position;
+  EXPECT_TRUE(
+      data.FindSnapPosition(current_position, true, false, &snap_position));
   EXPECT_EQ(80, snap_position.x());
   EXPECT_EQ(100, snap_position.y());
 }
@@ -84,10 +87,9 @@
                              gfx::RectF(0, 0, 200, 90), false);
   data.AddSnapAreaData(non_visible_x);
   data.AddSnapAreaData(non_visible_y);
-  gfx::ScrollOffset snap_position =
-      data.FindSnapPosition(current_position, true, true);
-  EXPECT_EQ(100, snap_position.x());
-  EXPECT_EQ(100, snap_position.y());
+  gfx::ScrollOffset snap_position;
+  EXPECT_FALSE(
+      data.FindSnapPosition(current_position, true, true, &snap_position));
 }
 
 TEST_F(ScrollSnapDataTest, SnapOnClosestAxisFirstIfVisibilityConflicts) {
@@ -114,8 +116,9 @@
   data.AddSnapAreaData(snap_x);
   data.AddSnapAreaData(snap_y1);
   data.AddSnapAreaData(snap_y2);
-  gfx::ScrollOffset snap_position =
-      data.FindSnapPosition(current_position, true, true);
+  gfx::ScrollOffset snap_position;
+  EXPECT_TRUE(
+      data.FindSnapPosition(current_position, true, true, &snap_position));
   EXPECT_EQ(80, snap_position.x());
   EXPECT_EQ(60, snap_position.y());
 }
@@ -130,8 +133,9 @@
   SnapAreaData area(SnapAxis::kBoth, gfx::ScrollOffset(80, 160),
                     gfx::RectF(50, 50, 200, 200), false);
   data.AddSnapAreaData(area);
-  gfx::ScrollOffset snap_position =
-      data.FindSnapPosition(current_position, true, true);
+  gfx::ScrollOffset snap_position;
+  EXPECT_TRUE(
+      data.FindSnapPosition(current_position, true, true, &snap_position));
 
   // The snap position on x, 80, is within the proximity range of [50, 150].
   // However, the snap position on y, 160, is outside the proximity range of
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc
index e5da816..8230494 100644
--- a/cc/layers/layer.cc
+++ b/cc/layers/layer.cc
@@ -290,7 +290,9 @@
   if (!layer_tree_host_)
     return;
 
-  if (masks_to_bounds()) {
+  // Both bounds clipping and mask clipping can result in new areas of subtrees
+  // being exposed on a bounds change. Ensure the damaged areas are updated.
+  if (masks_to_bounds() || inputs_.mask_layer.get()) {
     SetSubtreePropertyChanged();
     SetPropertyTreesNeedRebuild();
   }
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc
index 53edef6a..909dfd1 100644
--- a/cc/layers/layer_impl.cc
+++ b/cc/layers/layer_impl.cc
@@ -939,4 +939,8 @@
   DCHECK(GetScrollTree().Node(scroll_tree_index()));
 }
 
+bool LayerImpl::is_surface_layer() const {
+  return false;
+}
+
 }  // namespace cc
diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h
index 65c13a2..6eb7daab 100644
--- a/cc/layers/layer_impl.h
+++ b/cc/layers/layer_impl.h
@@ -446,6 +446,9 @@
 
   void EnsureValidPropertyTreeIndices() const;
 
+  // TODO(sunxd): Remove this function and replace it with visitor pattern.
+  virtual bool is_surface_layer() const;
+
  protected:
   LayerImpl(LayerTreeImpl* layer_impl,
             int id,
diff --git a/cc/layers/layer_unittest.cc b/cc/layers/layer_unittest.cc
index 53e5874..e7573ac 100644
--- a/cc/layers/layer_unittest.cc
+++ b/cc/layers/layer_unittest.cc
@@ -255,6 +255,13 @@
   std::unique_ptr<LayerImpl> dummy_layer1_impl =
       LayerImpl::Create(host_impl_.active_tree(), dummy_layer1->id());
 
+  // Resizing without a mask layer or masks_to_bounds, should only require a
+  // regular commit. Note that a layer and its mask should match sizes, but
+  // the mask isn't in the tree yet, so won't need its own commit.
+  gfx::Size arbitrary_size = gfx::Size(1, 2);
+  EXPECT_SET_NEEDS_COMMIT(1, root->SetBounds(arbitrary_size));
+  EXPECT_SET_NEEDS_COMMIT(0, dummy_layer1->SetBounds(arbitrary_size));
+
   EXPECT_CALL(*layer_tree_host_, SetNeedsFullTreeSync()).Times(1);
   EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetMaskLayer(dummy_layer1.get()));
   EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET(
@@ -264,6 +271,12 @@
       grand_child->PushPropertiesTo(grand_child_impl.get());
       dummy_layer1->PushPropertiesTo(dummy_layer1_impl.get()));
 
+  // Once there is a mask layer, resizes require subtree properties to update.
+  arbitrary_size = gfx::Size(11, 22);
+  EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(2);
+  EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetBounds(arbitrary_size));
+  EXECUTE_AND_VERIFY_SUBTREE_CHANGED(dummy_layer1->SetBounds(arbitrary_size));
+
   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1);
   EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetMasksToBounds(true));
   EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET(
@@ -322,7 +335,7 @@
 
   // Should be a different size than previous call, to ensure it marks tree
   // changed.
-  gfx::Size arbitrary_size = gfx::Size(111, 222);
+  arbitrary_size = gfx::Size(111, 222);
   EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(2);
   EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetBounds(arbitrary_size));
   EXECUTE_AND_VERIFY_SUBTREE_CHANGED(dummy_layer1->SetBounds(arbitrary_size));
diff --git a/cc/layers/surface_layer.cc b/cc/layers/surface_layer.cc
index 2aae0de3..e311043c 100644
--- a/cc/layers/surface_layer.cc
+++ b/cc/layers/surface_layer.cc
@@ -60,6 +60,13 @@
   SetNeedsPushProperties();
 }
 
+void SurfaceLayer::SetHitTestable(bool hit_testable) {
+  if (hit_testable_ == hit_testable)
+    return;
+  hit_testable_ = hit_testable;
+  SetNeedsPushProperties();
+}
+
 std::unique_ptr<LayerImpl> SurfaceLayer::CreateLayerImpl(
     LayerTreeImpl* tree_impl) {
   return SurfaceLayerImpl::Create(tree_impl, id());
@@ -94,6 +101,7 @@
   deadline_in_frames_ = 0u;
   layer_impl->SetFallbackSurfaceId(fallback_surface_id_);
   layer_impl->SetStretchContentToFillBounds(stretch_content_to_fill_bounds_);
+  layer_impl->SetHitTestable(hit_testable_);
 }
 
 }  // namespace cc
diff --git a/cc/layers/surface_layer.h b/cc/layers/surface_layer.h
index 7ffeb923..3ed0b9a 100644
--- a/cc/layers/surface_layer.h
+++ b/cc/layers/surface_layer.h
@@ -32,6 +32,9 @@
     return stretch_content_to_fill_bounds_;
   }
 
+  void SetHitTestable(bool hit_testable);
+  bool hit_testable() const { return hit_testable_; }
+
   // Layer overrides.
   std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
   void SetLayerTreeHost(LayerTreeHost* host) override;
@@ -61,6 +64,7 @@
   base::Optional<uint32_t> deadline_in_frames_ = 0u;
 
   bool stretch_content_to_fill_bounds_ = false;
+  bool hit_testable_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(SurfaceLayer);
 };
diff --git a/cc/layers/surface_layer_impl.cc b/cc/layers/surface_layer_impl.cc
index e42794a7..d90e233bf 100644
--- a/cc/layers/surface_layer_impl.cc
+++ b/cc/layers/surface_layer_impl.cc
@@ -54,6 +54,14 @@
   NoteLayerPropertyChanged();
 }
 
+void SurfaceLayerImpl::SetHitTestable(bool hit_testable) {
+  if (hit_testable_ == hit_testable)
+    return;
+
+  hit_testable_ = hit_testable;
+  NoteLayerPropertyChanged();
+}
+
 void SurfaceLayerImpl::PushPropertiesTo(LayerImpl* layer) {
   LayerImpl::PushPropertiesTo(layer);
   SurfaceLayerImpl* layer_impl = static_cast<SurfaceLayerImpl*>(layer);
@@ -63,6 +71,7 @@
   deadline_in_frames_ = 0u;
   layer_impl->SetFallbackSurfaceId(fallback_surface_id_);
   layer_impl->SetStretchContentToFillBounds(stretch_content_to_fill_bounds_);
+  layer_impl->SetHitTestable(hit_testable_);
 }
 
 void SurfaceLayerImpl::AppendQuads(viz::RenderPass* render_pass,
@@ -93,6 +102,10 @@
   deadline_in_frames_ = 0u;
 }
 
+bool SurfaceLayerImpl::is_surface_layer() const {
+  return true;
+}
+
 viz::SurfaceDrawQuad* SurfaceLayerImpl::CreateSurfaceDrawQuad(
     viz::RenderPass* render_pass,
     const viz::SurfaceId& primary_surface_id,
diff --git a/cc/layers/surface_layer_impl.h b/cc/layers/surface_layer_impl.h
index 380e8b9..d51dd6a 100644
--- a/cc/layers/surface_layer_impl.h
+++ b/cc/layers/surface_layer_impl.h
@@ -50,11 +50,15 @@
     return stretch_content_to_fill_bounds_;
   }
 
+  void SetHitTestable(bool hit_testable);
+  bool hit_testable() const { return hit_testable_; }
+
   // LayerImpl overrides.
   std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
   void PushPropertiesTo(LayerImpl* layer) override;
   void AppendQuads(viz::RenderPass* render_pass,
                    AppendQuadsData* append_quads_data) override;
+  bool is_surface_layer() const override;
 
  protected:
   SurfaceLayerImpl(LayerTreeImpl* tree_impl, int id);
@@ -75,6 +79,7 @@
   base::Optional<uint32_t> deadline_in_frames_;
 
   bool stretch_content_to_fill_bounds_ = false;
+  bool hit_testable_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(SurfaceLayerImpl);
 };
diff --git a/cc/layers/video_layer_impl.cc b/cc/layers/video_layer_impl.cc
index 05bbba2..d431a96 100644
--- a/cc/layers/video_layer_impl.cc
+++ b/cc/layers/video_layer_impl.cc
@@ -101,10 +101,13 @@
     return false;
 
   if (!updater_) {
-    updater_.reset(new VideoResourceUpdater(
+    const LayerTreeSettings& settings = layer_tree_impl()->settings();
+    updater_ = std::make_unique<VideoResourceUpdater>(
         layer_tree_impl()->context_provider(),
+        layer_tree_impl()->layer_tree_frame_sink(),
         layer_tree_impl()->resource_provider(),
-        layer_tree_impl()->settings().use_stream_video_draw_quad));
+        settings.use_stream_video_draw_quad,
+        settings.resource_settings.use_gpu_memory_buffer_resources);
   }
   updater_->ObtainFrameResources(frame_);
   return true;
diff --git a/cc/paint/display_item_list.h b/cc/paint/display_item_list.h
index a7a211a..935f643 100644
--- a/cc/paint/display_item_list.h
+++ b/cc/paint/display_item_list.h
@@ -83,9 +83,9 @@
   }
 
   // Called by blink::PaintChunksToCcLayer when an effect ends, to update the
-  // bounds of a SaveLayerOp which was emitted when the effect started. This is
-  // needed because blink doesn't know the bounds when an effect starts. Don't
-  // add other mutation methods like this if there is better alternative.
+  // bounds of a SaveLayer[Alpha]Op which was emitted when the effect started.
+  // This is needed because blink doesn't know the bounds when an effect starts.
+  // Don't add other mutation methods like this if there is better alternative.
   void UpdateSaveLayerBounds(size_t id, const SkRect& bounds) {
     paint_op_buffer_.UpdateSaveLayerBounds(id, bounds);
   }
diff --git a/cc/paint/paint_op_buffer.h b/cc/paint/paint_op_buffer.h
index 26ca2e30..0b3951a 100644
--- a/cc/paint/paint_op_buffer.h
+++ b/cc/paint/paint_op_buffer.h
@@ -896,14 +896,21 @@
 
   void UpdateSaveLayerBounds(size_t offset, const SkRect& bounds) {
     CHECK_LT(offset, used_);
-    CHECK_LE(offset + sizeof(SaveLayerOp), used_);
+    CHECK_LE(offset + sizeof(PaintOp), used_);
 
-    auto* op = reinterpret_cast<SaveLayerOp*>(data_.get() + offset);
-    CHECK_EQ(op->type, static_cast<uint32_t>(SaveLayerOp::kType));
-    size_t skip = op->skip;
-    DCHECK_EQ(skip, ComputeOpSkip(sizeof(SaveLayerOp)));
-
-    op->bounds = bounds;
+    auto* op = reinterpret_cast<PaintOp*>(data_.get() + offset);
+    switch (op->GetType()) {
+      case SaveLayerOp::kType:
+        CHECK_LE(offset + sizeof(SaveLayerOp), used_);
+        static_cast<SaveLayerOp*>(op)->bounds = bounds;
+        break;
+      case SaveLayerAlphaOp::kType:
+        CHECK_LE(offset + sizeof(SaveLayerAlphaOp), used_);
+        static_cast<SaveLayerAlphaOp*>(op)->bounds = bounds;
+        break;
+      default:
+        NOTREACHED();
+    }
   }
 
   template <typename T>
diff --git a/cc/resources/display_resource_provider.cc b/cc/resources/display_resource_provider.cc
index 024c6f3c..5938413 100644
--- a/cc/resources/display_resource_provider.cc
+++ b/cc/resources/display_resource_provider.cc
@@ -496,6 +496,48 @@
   return resource->lock_for_read_count > 0 || resource->lost;
 }
 
+viz::ResourceMetadata
+DisplayResourceProvider::GetResourceMetadataForExternalUse(
+    viz::ResourceId id,
+    const gpu::SyncToken& release_sync_token) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  ResourceMap::iterator it = resources_.find(id);
+  DCHECK(it != resources_.end());
+
+  viz::internal::Resource* resource = &it->second;
+  viz::ResourceMetadata metadata;
+  // TODO(xing.xu): remove locked_for_write.
+  DCHECK(!resource->locked_for_write)
+      << "locked for write: " << resource->locked_for_write;
+  DCHECK_EQ(resource->exported_count, 0);
+  // Uninitialized! Call SetPixels or LockForWrite first.
+  DCHECK(resource->allocated);
+  // TODO(penghuang): support software resource.
+  DCHECK(resource->is_gpu_resource_type());
+
+  metadata.mailbox = resource->mailbox;
+  metadata.backend_format = GrBackendFormat::MakeGL(
+      TextureStorageFormat(resource->format), resource->target);
+  metadata.size = resource->size;
+  metadata.mip_mapped = GrMipMapped::kNo;
+  metadata.origin = kTopLeft_GrSurfaceOrigin;
+  metadata.color_type = ResourceFormatToClosestSkColorType(resource->format);
+  metadata.alpha_type = kPremul_SkAlphaType;
+  metadata.color_space = nullptr;
+  metadata.sync_token = resource->sync_token();
+
+  // Update the resource sync token to |release_sync_token|. When the next frame
+  // is being composited, the DeclareUsedResourcesFromChild() will be called
+  // with resources belong to every child for the next frame. If the resource
+  // is not used by the next frame, the resource will be returned to a child
+  // which owns it with the |release_sync_token|. The child is responsible for
+  // issuing a WaitSyncToken GL command with the |release_sync_token| before
+  // reusing it.
+  resource->UpdateSyncToken(release_sync_token);
+
+  return metadata;
+}
+
 DisplayResourceProvider::ScopedReadLockGL::ScopedReadLockGL(
     DisplayResourceProvider* resource_provider,
     viz::ResourceId resource_id)
diff --git a/cc/resources/display_resource_provider.h b/cc/resources/display_resource_provider.h
index 7f09f529..48288bd 100644
--- a/cc/resources/display_resource_provider.h
+++ b/cc/resources/display_resource_provider.h
@@ -9,6 +9,7 @@
 #include "cc/output/overlay_candidate.h"
 #include "cc/resources/resource_provider.h"
 #include "components/viz/common/resources/resource_fence.h"
+#include "components/viz/common/resources/resource_metadata.h"
 
 namespace viz {
 class SharedBitmapManager;
@@ -56,6 +57,14 @@
   // Checks whether a resource is in use.
   bool InUse(viz::ResourceId id);
 
+  // Get the resource metadata for external use.
+  // The |release_sync_token| should be one that can be waited on in a command
+  // buffer to ensure that any external use of it is completed, before reusing
+  // the resource's backing.
+  viz::ResourceMetadata GetResourceMetadataForExternalUse(
+      viz::ResourceId id,
+      const gpu::SyncToken& release_sync_token);
+
   // The following lock classes are part of the DisplayResourceProvider API and
   // are needed to read the resource contents. The user must ensure that they
   // only use GL locks on GL resources, etc, and this is enforced by assertions.
diff --git a/cc/resources/video_resource_updater.cc b/cc/resources/video_resource_updater.cc
index e644324..bd01caf 100644
--- a/cc/resources/video_resource_updater.cc
+++ b/cc/resources/video_resource_updater.cc
@@ -8,20 +8,31 @@
 #include <stdint.h>
 
 #include <algorithm>
+#include <string>
 
+#include "base/atomic_sequence_num.h"
 #include "base/bind.h"
 #include "base/bit_cast.h"
+#include "base/memory/shared_memory.h"
+#include "base/strings/stringprintf.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/trace_event/memory_dump_manager.h"
+#include "base/trace_event/process_memory_dump.h"
 #include "base/trace_event/trace_event.h"
 #include "cc/base/math_util.h"
 #include "cc/paint/skia_paint_canvas.h"
 #include "cc/resources/layer_tree_resource_provider.h"
+#include "cc/trees/layer_tree_frame_sink.h"
 #include "components/viz/common/gpu/context_provider.h"
+#include "components/viz/common/gpu/texture_allocation.h"
 #include "components/viz/common/quads/render_pass.h"
 #include "components/viz/common/quads/stream_video_draw_quad.h"
 #include "components/viz/common/quads/texture_draw_quad.h"
 #include "components/viz/common/quads/yuv_video_draw_quad.h"
+#include "components/viz/common/resources/bitmap_allocation.h"
 #include "components/viz/common/resources/resource_sizes.h"
 #include "gpu/GLES2/gl2extchromium.h"
+#include "gpu/command_buffer/client/context_support.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
 #include "media/base/video_frame.h"
 #include "media/renderers/paint_canvas_video_renderer.h"
@@ -31,11 +42,15 @@
 #include "third_party/libyuv/include/libyuv.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "ui/gfx/geometry/size_conversions.h"
+#include "ui/gfx/skia_util.h"
+#include "ui/gl/trace_util.h"
 
 namespace cc {
-
 namespace {
 
+// Generates process-unique IDs to use for tracing video resources.
+base::AtomicSequenceNumber g_next_video_resource_updater_id;
+
 VideoFrameExternalResources::ResourceType ExternalResourceTypeForHardwarePlanes(
     media::VideoPixelFormat format,
     GLuint target,
@@ -164,42 +179,187 @@
 VideoFrameExternalResources& VideoFrameExternalResources::operator=(
     VideoFrameExternalResources&& other) = default;
 
-VideoResourceUpdater::PlaneResource::PlaneResource(
-    viz::ResourceId resource_id,
-    const gfx::Size& resource_size,
-    viz::ResourceFormat resource_format,
-    gpu::Mailbox mailbox)
-    : resource_id_(resource_id),
-      resource_size_(resource_size),
-      resource_format_(resource_format),
-      mailbox_(mailbox) {}
+// Resource for a video plane allocated and owned by VideoResourceUpdater. There
+// can be multiple plane resources for each video frame, depending on the
+// format. These will be reused when possible.
+class VideoResourceUpdater::PlaneResource {
+ public:
+  PlaneResource(uint32_t plane_resource_id,
+                const gfx::Size& resource_size,
+                viz::ResourceFormat resource_format,
+                bool is_software)
+      : plane_resource_id_(plane_resource_id),
+        resource_size_(resource_size),
+        resource_format_(resource_format),
+        is_software_(is_software) {}
+  virtual ~PlaneResource() = default;
 
-bool VideoResourceUpdater::PlaneResource::Matches(int unique_frame_id,
-                                                  size_t plane_index) {
-  return has_unique_frame_id_and_plane_index_ &&
-         unique_frame_id_ == unique_frame_id && plane_index_ == plane_index;
+  // Casts |this| to SoftwarePlaneResource for software compositing.
+  SoftwarePlaneResource* AsSoftware();
+
+  // Casts |this| to HardwarePlaneResource for GPU compositing.
+  HardwarePlaneResource* AsHardware();
+
+  // Returns true if this resource matches the unique identifiers of another
+  // VideoFrame resource.
+  bool Matches(int unique_frame_id, size_t plane_index) {
+    return has_unique_frame_id_and_plane_index_ &&
+           unique_frame_id_ == unique_frame_id && plane_index_ == plane_index;
+  }
+
+  // Sets the unique identifiers for this resource, may only be called when
+  // there is a single reference to the resource (i.e. |ref_count_| == 1).
+  void SetUniqueId(int unique_frame_id, size_t plane_index) {
+    DCHECK_EQ(ref_count_, 1);
+    plane_index_ = plane_index;
+    unique_frame_id_ = unique_frame_id;
+    has_unique_frame_id_and_plane_index_ = true;
+  }
+
+  // Accessors for resource identifiers provided at construction time.
+  uint32_t plane_resource_id() const { return plane_resource_id_; }
+  const gfx::Size& resource_size() const { return resource_size_; }
+  viz::ResourceFormat resource_format() const { return resource_format_; }
+
+  // Various methods for managing references. See |ref_count_| for details.
+  void add_ref() { ++ref_count_; }
+  void remove_ref() { --ref_count_; }
+  void clear_refs() { ref_count_ = 0; }
+  bool has_refs() const { return ref_count_ != 0; }
+
+ private:
+  const uint32_t plane_resource_id_;
+  const gfx::Size resource_size_;
+  const viz::ResourceFormat resource_format_;
+  const bool is_software_;
+
+  // The number of times this resource has been imported vs number of times this
+  // resource has returned.
+  int ref_count_ = 0;
+
+  // These two members are used for identifying the data stored in this
+  // resource; they uniquely identify a media::VideoFrame plane.
+  int unique_frame_id_ = 0;
+  size_t plane_index_ = 0u;
+  // Indicates if the above two members have been set or not.
+  bool has_unique_frame_id_and_plane_index_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(PlaneResource);
+};
+
+class VideoResourceUpdater::SoftwarePlaneResource
+    : public VideoResourceUpdater::PlaneResource {
+ public:
+  SoftwarePlaneResource(uint32_t plane_resource_id,
+                        const gfx::Size& size,
+                        LayerTreeFrameSink* layer_tree_frame_sink)
+      : PlaneResource(plane_resource_id,
+                      size,
+                      viz::ResourceFormat::RGBA_8888,
+                      /*is_software=*/true),
+        layer_tree_frame_sink_(layer_tree_frame_sink),
+        shared_bitmap_id_(viz::SharedBitmap::GenerateId()) {
+    DCHECK(layer_tree_frame_sink_);
+
+    // Allocate SharedMemory and notify display compositor of the allocation.
+    shared_memory_ = viz::bitmap_allocation::AllocateMappedBitmap(
+        resource_size(), viz::ResourceFormat::RGBA_8888);
+    mojo::ScopedSharedBufferHandle handle =
+        viz::bitmap_allocation::DuplicateAndCloseMappedBitmap(
+            shared_memory_.get(), resource_size(),
+            viz::ResourceFormat::RGBA_8888);
+    layer_tree_frame_sink_->DidAllocateSharedBitmap(std::move(handle),
+                                                    shared_bitmap_id_);
+  }
+  ~SoftwarePlaneResource() override {
+    layer_tree_frame_sink_->DidDeleteSharedBitmap(shared_bitmap_id_);
+  }
+
+  const viz::SharedBitmapId& shared_bitmap_id() const {
+    return shared_bitmap_id_;
+  }
+  void* pixels() { return shared_memory_->memory(); }
+
+  // Returns a memory dump GUID consistent across processes.
+  base::UnguessableToken GetSharedMemoryGuid() const {
+    return shared_memory_->mapped_id();
+  }
+
+ private:
+  LayerTreeFrameSink* const layer_tree_frame_sink_;
+  const viz::SharedBitmapId shared_bitmap_id_;
+  std::unique_ptr<base::SharedMemory> shared_memory_;
+
+  DISALLOW_COPY_AND_ASSIGN(SoftwarePlaneResource);
+};
+
+class VideoResourceUpdater::HardwarePlaneResource
+    : public VideoResourceUpdater::PlaneResource {
+ public:
+  HardwarePlaneResource(uint32_t plane_resource_id,
+                        const gfx::Size& size,
+                        viz::ResourceFormat format,
+                        viz::ContextProvider* context_provider,
+                        viz::TextureAllocation allocation)
+      : PlaneResource(plane_resource_id, size, format, /*is_software=*/false),
+        context_provider_(context_provider),
+        mailbox_(gpu::Mailbox::Generate()),
+        allocation_(std::move(allocation)) {
+    DCHECK(context_provider_);
+    context_provider_->ContextGL()->ProduceTextureDirectCHROMIUM(
+        allocation_.texture_id, mailbox_.name);
+  }
+  ~HardwarePlaneResource() override {
+    context_provider_->ContextGL()->DeleteTextures(1, &allocation_.texture_id);
+  }
+
+  const gpu::Mailbox& mailbox() const { return mailbox_; }
+  GLuint texture_id() const { return allocation_.texture_id; }
+  GLenum texture_target() const { return allocation_.texture_target; }
+  bool overlay_candidate() const { return allocation_.overlay_candidate; }
+
+ private:
+  viz::ContextProvider* const context_provider_;
+  const gpu::Mailbox mailbox_;
+  const viz::TextureAllocation allocation_;
+
+  DISALLOW_COPY_AND_ASSIGN(HardwarePlaneResource);
+};
+
+VideoResourceUpdater::SoftwarePlaneResource*
+VideoResourceUpdater::PlaneResource::AsSoftware() {
+  DCHECK(is_software_);
+  return static_cast<SoftwarePlaneResource*>(this);
 }
 
-void VideoResourceUpdater::PlaneResource::SetUniqueId(int unique_frame_id,
-                                                      size_t plane_index) {
-  DCHECK_EQ(ref_count_, 1);
-  plane_index_ = plane_index;
-  unique_frame_id_ = unique_frame_id;
-  has_unique_frame_id_and_plane_index_ = true;
+VideoResourceUpdater::HardwarePlaneResource*
+VideoResourceUpdater::PlaneResource::AsHardware() {
+  DCHECK(!is_software_);
+  return static_cast<HardwarePlaneResource*>(this);
 }
 
 VideoResourceUpdater::VideoResourceUpdater(
     viz::ContextProvider* context_provider,
+    LayerTreeFrameSink* layer_tree_frame_sink,
     LayerTreeResourceProvider* resource_provider,
-    bool use_stream_video_draw_quad)
+    bool use_stream_video_draw_quad,
+    bool use_gpu_memory_buffer_resources)
     : context_provider_(context_provider),
+      layer_tree_frame_sink_(layer_tree_frame_sink),
       resource_provider_(resource_provider),
       use_stream_video_draw_quad_(use_stream_video_draw_quad),
-      weak_ptr_factory_(this) {}
+      use_gpu_memory_buffer_resources_(use_gpu_memory_buffer_resources),
+      tracing_id_(g_next_video_resource_updater_id.GetNext()),
+      weak_ptr_factory_(this) {
+  DCHECK(context_provider_ || layer_tree_frame_sink_);
+
+  base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
+      this, "cc::VideoResourceUpdater", base::ThreadTaskRunnerHandle::Get());
+}
 
 VideoResourceUpdater::~VideoResourceUpdater() {
-  for (const PlaneResource& plane_resource : all_resources_)
-    resource_provider_->DeleteResource(plane_resource.resource_id());
+  base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
+      this);
 }
 
 void VideoResourceUpdater::ObtainFrameResources(
@@ -208,27 +368,21 @@
       CreateExternalResourcesFromVideoFrame(video_frame);
   frame_resource_type_ = external_resources.type;
 
-  if (external_resources.type ==
-      VideoFrameExternalResources::SOFTWARE_RESOURCE) {
-    DCHECK_GT(external_resources.software_resource, viz::kInvalidResourceId);
-    software_resource_ = external_resources.software_resource;
-    software_release_callback_ =
-        std::move(external_resources.software_release_callback);
-  } else {
+  if (external_resources.type == VideoFrameExternalResources::YUV_RESOURCE) {
     frame_resource_offset_ = external_resources.offset;
     frame_resource_multiplier_ = external_resources.multiplier;
     frame_bits_per_channel_ = external_resources.bits_per_channel;
+  }
 
-    DCHECK_EQ(external_resources.resources.size(),
-              external_resources.release_callbacks.size());
-    for (size_t i = 0; i < external_resources.resources.size(); ++i) {
-      viz::ResourceId resource_id = resource_provider_->ImportResource(
-          external_resources.resources[i],
-          viz::SingleReleaseCallback::Create(
-              std::move(external_resources.release_callbacks[i])));
-      frame_resources_.push_back(
-          {resource_id, external_resources.resources[i].size});
-    }
+  DCHECK_EQ(external_resources.resources.size(),
+            external_resources.release_callbacks.size());
+  for (size_t i = 0; i < external_resources.resources.size(); ++i) {
+    viz::ResourceId resource_id = resource_provider_->ImportResource(
+        external_resources.resources[i],
+        viz::SingleReleaseCallback::Create(
+            std::move(external_resources.release_callbacks[i])));
+    frame_resources_.push_back(
+        {resource_id, external_resources.resources[i].size});
   }
   TRACE_EVENT_INSTANT1("media", "VideoResourceUpdater::ObtainFrameResources",
                        TRACE_EVENT_SCOPE_THREAD, "Timestamp",
@@ -236,15 +390,9 @@
 }
 
 void VideoResourceUpdater::ReleaseFrameResources() {
-  if (frame_resource_type_ == VideoFrameExternalResources::SOFTWARE_RESOURCE) {
-    DCHECK_GT(software_resource_, viz::kInvalidResourceId);
-    std::move(software_release_callback_).Run(gpu::SyncToken(), false);
-    software_resource_ = viz::kInvalidResourceId;
-  } else {
-    for (auto& frame_resource : frame_resources_)
-      resource_provider_->RemoveImportedResource(frame_resource.id);
-    frame_resources_.clear();
-  }
+  for (auto& frame_resource : frame_resources_)
+    resource_provider_->RemoveImportedResource(frame_resource.id);
+  frame_resources_.clear();
 }
 
 void VideoResourceUpdater::AppendQuads(viz::RenderPass* render_pass,
@@ -278,27 +426,6 @@
       static_cast<float>(visible_rect.height()) / coded_size.height();
 
   switch (frame_resource_type_) {
-    // TODO(danakj): Remove this, hide it in the hardware path.
-    case VideoFrameExternalResources::SOFTWARE_RESOURCE: {
-      DCHECK_EQ(frame_resources_.size(), 0u);
-      DCHECK_GT(software_resource_, viz::kInvalidResourceId);
-      bool premultiplied_alpha = true;
-      gfx::PointF uv_top_left(0.f, 0.f);
-      gfx::PointF uv_bottom_right(tex_width_scale, tex_height_scale);
-      float opacity[] = {1.0f, 1.0f, 1.0f, 1.0f};
-      bool flipped = false;
-      bool nearest_neighbor = false;
-      auto* texture_quad =
-          render_pass->CreateAndAppendDrawQuad<viz::TextureDrawQuad>();
-      texture_quad->SetNew(
-          shared_quad_state, quad_rect, visible_quad_rect, needs_blending,
-          software_resource_, premultiplied_alpha, uv_top_left, uv_bottom_right,
-          SK_ColorTRANSPARENT, opacity, flipped, nearest_neighbor, false);
-      for (viz::ResourceId resource_id : texture_quad->resources) {
-        resource_provider_->ValidateResource(resource_id);
-      }
-      break;
-    }
     case VideoFrameExternalResources::YUV_RESOURCE: {
       const gfx::Size ya_tex_size = coded_size;
 
@@ -417,91 +544,74 @@
     return CreateForSoftwarePlanes(std::move(video_frame));
 }
 
-VideoResourceUpdater::ResourceList::iterator
+VideoResourceUpdater::PlaneResource*
 VideoResourceUpdater::RecycleOrAllocateResource(
     const gfx::Size& resource_size,
     viz::ResourceFormat resource_format,
     const gfx::ColorSpace& color_space,
-    bool software_resource,
     int unique_id,
     int plane_index) {
-  ResourceList::iterator recyclable_resource = all_resources_.end();
-  for (auto it = all_resources_.begin(); it != all_resources_.end(); ++it) {
+  PlaneResource* recyclable_resource = nullptr;
+  for (auto& resource : all_resources_) {
     // If the plane index is valid (positive, or 0, meaning all planes)
     // then we are allowed to return a referenced resource that already
     // contains the right frame data. It's safe to reuse it even if
     // resource_provider_ holds some references to it, because those
     // references are read-only.
-    if (plane_index != -1 && it->Matches(unique_id, plane_index)) {
-      DCHECK(it->resource_size() == resource_size);
-      DCHECK(it->resource_format() == resource_format);
-      DCHECK(it->mailbox().IsZero() == software_resource);
-      return it;
+    if (plane_index != -1 && resource->Matches(unique_id, plane_index)) {
+      DCHECK(resource->resource_size() == resource_size);
+      DCHECK(resource->resource_format() == resource_format);
+      return resource.get();
     }
 
     // Otherwise check whether this is an unreferenced resource of the right
     // format that we can recycle. Remember it, but don't return immediately,
     // because we still want to find any reusable resources.
-    // Resources backed by SharedMemory are not ref-counted, unlike mailboxes,
-    // so the definition of |in_use| must take this into account. Full
-    // discussion in codereview.chromium.org/145273021.
-    const bool in_use =
-        it->has_refs() ||
-        (software_resource &&
-         resource_provider_->InUseByConsumer(it->resource_id()));
+    const bool in_use = resource->has_refs();
 
-    if (!in_use && it->resource_size() == resource_size &&
-        it->resource_format() == resource_format &&
-        it->mailbox().IsZero() == software_resource) {
-      recyclable_resource = it;
+    if (!in_use && resource->resource_size() == resource_size &&
+        resource->resource_format() == resource_format) {
+      recyclable_resource = resource.get();
     }
   }
 
-  if (recyclable_resource != all_resources_.end())
+  if (recyclable_resource)
     return recyclable_resource;
 
   // There was nothing available to reuse or recycle. Allocate a new resource.
-  return AllocateResource(resource_size, resource_format, color_space,
-                          software_resource);
+  return AllocateResource(resource_size, resource_format, color_space);
 }
 
-VideoResourceUpdater::ResourceList::iterator
-VideoResourceUpdater::AllocateResource(const gfx::Size& plane_size,
-                                       viz::ResourceFormat format,
-                                       const gfx::ColorSpace& color_space,
-                                       bool software_resource) {
-  viz::ResourceId resource_id;
-  gpu::Mailbox mailbox;
+VideoResourceUpdater::PlaneResource* VideoResourceUpdater::AllocateResource(
+    const gfx::Size& plane_size,
+    viz::ResourceFormat format,
+    const gfx::ColorSpace& color_space) {
+  const uint32_t plane_resource_id = next_plane_resource_id_++;
 
-  // TODO(danakj): Abstract out hw/sw resource create/delete from
-  // ResourceProvider and stop using ResourceProvider in this class.
-  if (software_resource) {
-    DCHECK_EQ(format, viz::RGBA_8888);
-    resource_id = resource_provider_->CreateBitmapResource(
-        plane_size, color_space, viz::RGBA_8888);
+  if (software_compositor()) {
+    DCHECK_EQ(format, viz::ResourceFormat::RGBA_8888);
+
+    all_resources_.push_back(std::make_unique<SoftwarePlaneResource>(
+        plane_resource_id, plane_size, layer_tree_frame_sink_));
   } else {
-    DCHECK(context_provider_);
+    // Video textures get composited into the display frame, the GPU doesn't
+    // draw to them directly.
+    constexpr bool kForFrameBufferAttachment = false;
 
-    resource_id = resource_provider_->CreateGpuTextureResource(
-        plane_size, viz::ResourceTextureHint::kDefault, format, color_space);
+    viz::TextureAllocation alloc = viz::TextureAllocation::MakeTextureId(
+        context_provider_->ContextGL(),
+        context_provider_->ContextCapabilities(), format,
+        use_gpu_memory_buffer_resources_, kForFrameBufferAttachment);
+    viz::TextureAllocation::AllocateStorage(
+        context_provider_->ContextGL(),
+        context_provider_->ContextCapabilities(), format, plane_size, alloc,
+        color_space);
 
-    gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
-
-    gl->GenMailboxCHROMIUM(mailbox.name);
-    LayerTreeResourceProvider::ScopedWriteLockGL lock(resource_provider_,
-                                                      resource_id);
-    gl->ProduceTextureDirectCHROMIUM(
-        lock.GetTexture(),
-        mailbox.name);
+    all_resources_.push_back(std::make_unique<HardwarePlaneResource>(
+        plane_resource_id, plane_size, format, context_provider_,
+        std::move(alloc)));
   }
-  all_resources_.emplace_front(resource_id, plane_size, format, mailbox);
-  return all_resources_.begin();
-}
-
-void VideoResourceUpdater::DeleteResource(ResourceList::iterator resource_it) {
-  DCHECK(!resource_it->has_refs());
-  resource_provider_->DeleteResource(resource_it->resource_id());
-  all_resources_.erase(resource_it);
+  return all_resources_.back().get();
 }
 
 void VideoResourceUpdater::CopyHardwarePlane(
@@ -516,17 +626,14 @@
 
   const int no_unique_id = 0;
   const int no_plane_index = -1;  // Do not recycle referenced textures.
-  VideoResourceUpdater::ResourceList::iterator resource =
-      RecycleOrAllocateResource(output_plane_resource_size, copy_target_format,
-                                resource_color_space, false, no_unique_id,
-                                no_plane_index);
-  resource->add_ref();
+  PlaneResource* plane_resource = RecycleOrAllocateResource(
+      output_plane_resource_size, copy_target_format, resource_color_space,
+      no_unique_id, no_plane_index);
+  HardwarePlaneResource* hardware_resource = plane_resource->AsHardware();
+  hardware_resource->add_ref();
 
-  LayerTreeResourceProvider::ScopedWriteLockGL lock(resource_provider_,
-                                                    resource->resource_id());
-  DCHECK_EQ(
-      resource_provider_->GetResourceTextureTarget(resource->resource_id()),
-      (GLenum)GL_TEXTURE_2D);
+  DCHECK_EQ(hardware_resource->texture_target(),
+            static_cast<GLenum>(GL_TEXTURE_2D));
 
   gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
 
@@ -534,9 +641,9 @@
   uint32_t src_texture_id =
       gl->CreateAndConsumeTextureCHROMIUM(mailbox_holder.mailbox.name);
   gl->CopySubTextureCHROMIUM(
-      src_texture_id, 0, GL_TEXTURE_2D, lock.GetTexture(), 0, 0, 0, 0, 0,
-      output_plane_resource_size.width(), output_plane_resource_size.height(),
-      false, false, false);
+      src_texture_id, 0, GL_TEXTURE_2D, hardware_resource->texture_id(), 0, 0,
+      0, 0, 0, output_plane_resource_size.width(),
+      output_plane_resource_size.height(), false, false, false);
   gl->DeleteTextures(1, &src_texture_id);
 
   // Pass an empty sync token to force generation of a new sync token.
@@ -544,13 +651,13 @@
   gpu::SyncToken sync_token = video_frame->UpdateReleaseSyncToken(&client);
 
   auto transfer_resource = viz::TransferableResource::MakeGL(
-      resource->mailbox(), GL_LINEAR, GL_TEXTURE_2D, sync_token);
+      hardware_resource->mailbox(), GL_LINEAR, GL_TEXTURE_2D, sync_token);
   transfer_resource.color_space = resource_color_space;
   external_resources->resources.push_back(std::move(transfer_resource));
 
-  external_resources->release_callbacks.push_back(
-      base::BindOnce(&VideoResourceUpdater::RecycleResource,
-                     weak_ptr_factory_.GetWeakPtr(), resource->resource_id()));
+  external_resources->release_callbacks.push_back(base::BindOnce(
+      &VideoResourceUpdater::RecycleResource, weak_ptr_factory_.GetWeakPtr(),
+      hardware_resource->plane_resource_id()));
 }
 
 VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes(
@@ -634,8 +741,6 @@
   DCHECK(media::IsYuvPlanar(input_frame_format) ||
          input_frame_format == media::PIXEL_FORMAT_Y16);
 
-  const bool software_compositor = context_provider_ == nullptr;
-
   viz::ResourceFormat output_resource_format;
   gfx::ColorSpace output_color_space = video_frame->ColorSpace();
   if (input_frame_format == media::PIXEL_FORMAT_Y16) {
@@ -654,7 +759,7 @@
   // bug workaround requires that YUV frames must be converted to RGB
   // before texture upload.
   bool texture_needs_rgb_conversion =
-      !software_compositor &&
+      !software_compositor() &&
       output_resource_format == viz::ResourceFormat::RGBA_8888;
 
   size_t output_plane_count = media::VideoFrame::NumPlanes(input_frame_format);
@@ -663,7 +768,7 @@
   // conversion here. That involves an extra copy of each frame to a bitmap.
   // Obviously, this is suboptimal and should be addressed once ubercompositor
   // starts shaping up.
-  if (software_compositor || texture_needs_rgb_conversion) {
+  if (software_compositor() || texture_needs_rgb_conversion) {
     output_resource_format = viz::RGBA_8888;
     output_plane_count = 1;
     bits_per_channel = 8;
@@ -675,61 +780,69 @@
   }
 
   // Drop recycled resources that are the wrong format.
-  for (auto it = all_resources_.begin(); it != all_resources_.end();) {
-    if (!it->has_refs() && it->resource_format() != output_resource_format)
-      DeleteResource(it++);
-    else
-      ++it;
-  }
+  auto can_delete_resource_fn =
+      [output_resource_format](const std::unique_ptr<PlaneResource>& resource) {
+        return !resource->has_refs() &&
+               resource->resource_format() != output_resource_format;
+      };
+  base::EraseIf(all_resources_, can_delete_resource_fn);
+  // TODO(kylechar): Delete resources that are the wrong size for all output
+  // planes.
 
   const int max_resource_size = resource_provider_->max_texture_size();
-  std::vector<ResourceList::iterator> plane_resources;
+  std::vector<PlaneResource*> plane_resources;
   for (size_t i = 0; i < output_plane_count; ++i) {
     gfx::Size output_plane_resource_size =
-        SoftwarePlaneDimension(video_frame.get(), software_compositor, i);
+        SoftwarePlaneDimension(video_frame.get(), software_compositor(), i);
     if (output_plane_resource_size.IsEmpty() ||
         output_plane_resource_size.width() > max_resource_size ||
         output_plane_resource_size.height() > max_resource_size) {
       // This output plane has invalid geometry. Clean up and return an empty
       // external resources.
-      for (ResourceList::iterator resource_it : plane_resources)
-        resource_it->remove_ref();
+      for (auto* plane_resource : plane_resources)
+        plane_resource->remove_ref();
       return VideoFrameExternalResources();
     }
 
-    ResourceList::iterator resource_it = RecycleOrAllocateResource(
+    PlaneResource* plane_resource = RecycleOrAllocateResource(
         output_plane_resource_size, output_resource_format, output_color_space,
-        software_compositor, video_frame->unique_id(), i);
+        video_frame->unique_id(), i);
 
-    resource_it->add_ref();
-    plane_resources.push_back(resource_it);
+    plane_resource->add_ref();
+    plane_resources.push_back(plane_resource);
   }
 
   VideoFrameExternalResources external_resources;
 
   external_resources.bits_per_channel = bits_per_channel;
 
-  if (software_compositor || texture_needs_rgb_conversion) {
+  if (software_compositor() || texture_needs_rgb_conversion) {
     DCHECK_EQ(plane_resources.size(), 1u);
-    PlaneResource& plane_resource = *plane_resources[0];
-    DCHECK_EQ(plane_resource.resource_format(), viz::RGBA_8888);
-    DCHECK(!software_compositor ||
-           plane_resource.resource_id() > viz::kInvalidResourceId);
-    DCHECK_EQ(software_compositor, plane_resource.mailbox().IsZero());
+    PlaneResource* plane_resource = plane_resources[0];
+    DCHECK_EQ(plane_resource->resource_format(), viz::RGBA_8888);
 
-    if (!plane_resource.Matches(video_frame->unique_id(), 0)) {
+    if (!plane_resource->Matches(video_frame->unique_id(), 0)) {
       // We need to transfer data from |video_frame| to the plane resource.
-      if (software_compositor) {
+      if (software_compositor()) {
         if (!video_renderer_)
           video_renderer_ = std::make_unique<media::PaintCanvasVideoRenderer>();
 
-        LayerTreeResourceProvider::ScopedWriteLockSoftware lock(
-            resource_provider_, plane_resource.resource_id());
-        SkiaPaintCanvas canvas(lock.sk_bitmap());
+        SoftwarePlaneResource* software_resource = plane_resource->AsSoftware();
+
+        // We know the format is RGBA_8888 from check above.
+        SkImageInfo info = SkImageInfo::MakeN32Premul(
+            gfx::SizeToSkISize(software_resource->resource_size()));
+
+        SkBitmap sk_bitmap;
+        sk_bitmap.installPixels(info, software_resource->pixels(),
+                                info.minRowBytes());
+        SkiaPaintCanvas canvas(sk_bitmap);
+
         // This is software path, so canvas and video_frame are always backed
         // by software.
         video_renderer_->Copy(video_frame, &canvas, media::Context3D());
       } else {
+        HardwarePlaneResource* hardware_resource = plane_resource->AsHardware();
         size_t bytes_per_row = viz::ResourceSizes::CheckedWidthInBytes<size_t>(
             video_frame->coded_size().width(), viz::ResourceFormat::RGBA_8888);
         size_t needed_size = bytes_per_row * video_frame->coded_size().height();
@@ -742,35 +855,46 @@
         media::PaintCanvasVideoRenderer::ConvertVideoFrameToRGBPixels(
             video_frame.get(), &upload_pixels_[0], bytes_per_row);
 
-        resource_provider_->CopyToResource(plane_resource.resource_id(),
-                                           &upload_pixels_[0],
-                                           plane_resource.resource_size());
+        // Copy pixels into texture.
+        auto* gl = context_provider_->ContextGL();
+        gl->BindTexture(hardware_resource->texture_target(),
+                        hardware_resource->texture_id());
+        const gfx::Size& plane_size = hardware_resource->resource_size();
+        gl->TexSubImage2D(
+            hardware_resource->texture_target(), 0, 0, 0, plane_size.width(),
+            plane_size.height(), GLDataFormat(viz::ResourceFormat::RGBA_8888),
+            GLDataType(viz::ResourceFormat::RGBA_8888), &upload_pixels_[0]);
       }
-      plane_resource.SetUniqueId(video_frame->unique_id(), 0);
+      plane_resource->SetUniqueId(video_frame->unique_id(), 0);
     }
 
-    if (software_compositor) {
-      external_resources.software_resource = plane_resource.resource_id();
-      external_resources.software_release_callback = base::BindOnce(
-          &VideoResourceUpdater::RecycleResource,
-          weak_ptr_factory_.GetWeakPtr(), plane_resource.resource_id());
-      external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE;
+    if (software_compositor()) {
+      SoftwarePlaneResource* software_resource = plane_resource->AsSoftware();
+      external_resources.type =
+          VideoFrameExternalResources::RGBA_PREMULTIPLIED_RESOURCE;
+      external_resources.resources.push_back(
+          viz::TransferableResource::MakeSoftware(
+              software_resource->shared_bitmap_id(), 0 /* sequence_number */,
+              software_resource->resource_size(),
+              plane_resource->resource_format()));
     } else {
+      HardwarePlaneResource* hardware_resource = plane_resource->AsHardware();
+      external_resources.type = VideoFrameExternalResources::RGBA_RESOURCE;
       gpu::SyncToken sync_token;
       GenerateCompositorSyncToken(context_provider_->ContextGL(), &sync_token);
-
-      GLuint target = resource_provider_->GetResourceTextureTarget(
-          plane_resource.resource_id());
-      auto transfer_resource = viz::TransferableResource::MakeGL(
-          plane_resource.mailbox(), GL_LINEAR, target, sync_token);
-      transfer_resource.color_space = output_color_space;
-
-      external_resources.resources.push_back(std::move(transfer_resource));
-      external_resources.release_callbacks.push_back(base::BindOnce(
-          &VideoResourceUpdater::RecycleResource,
-          weak_ptr_factory_.GetWeakPtr(), plane_resource.resource_id()));
-      external_resources.type = VideoFrameExternalResources::RGBA_RESOURCE;
+      external_resources.resources.push_back(
+          viz::TransferableResource::MakeGLOverlay(
+              hardware_resource->mailbox(), GL_LINEAR,
+              hardware_resource->texture_target(), sync_token,
+              hardware_resource->resource_size(),
+              hardware_resource->overlay_candidate()));
     }
+
+    external_resources.resources.back().color_space = output_color_space;
+    external_resources.release_callbacks.push_back(base::BindOnce(
+        &VideoResourceUpdater::RecycleResource, weak_ptr_factory_.GetWeakPtr(),
+        plane_resource->plane_resource_id()));
+
     return external_resources;
   }
 
@@ -795,13 +919,14 @@
 
   // We need to transfer data from |video_frame| to the plane resources.
   for (size_t i = 0; i < plane_resources.size(); ++i) {
-    PlaneResource& plane_resource = *plane_resources[i];
+    HardwarePlaneResource* plane_resource = plane_resources[i]->AsHardware();
+
     // Skip the transfer if this |video_frame|'s plane has been processed.
-    if (plane_resource.Matches(video_frame->unique_id(), i))
+    if (plane_resource->Matches(video_frame->unique_id(), i))
       continue;
 
     const viz::ResourceFormat plane_resource_format =
-        plane_resource.resource_format();
+        plane_resource->resource_format();
     DCHECK_EQ(plane_resource_format, yuv_resource_format);
 
     // TODO(hubbe): Move upload code to media/.
@@ -812,7 +937,7 @@
     const int video_stride_bytes = video_frame->stride(i);
 
     // |resource_size_pixels| is the size of the destination resource.
-    const gfx::Size resource_size_pixels = plane_resource.resource_size();
+    const gfx::Size resource_size_pixels = plane_resource->resource_size();
 
     const size_t bytes_per_row =
         viz::ResourceSizes::CheckedWidthInBytes<size_t>(
@@ -883,9 +1008,17 @@
       pixels = &upload_pixels_[0];
     }
 
-    resource_provider_->CopyToResource(plane_resource.resource_id(), pixels,
-                                       resource_size_pixels);
-    plane_resource.SetUniqueId(video_frame->unique_id(), i);
+    // Copy pixels into texture. TexSubImage2D() is applicable because
+    // |yuv_resource_format| is LUMINANCE_F16, R16_EXT, LUMINANCE_8 or RED_8.
+    auto* gl = context_provider_->ContextGL();
+    gl->BindTexture(plane_resource->texture_target(),
+                    plane_resource->texture_id());
+    gl->TexSubImage2D(
+        plane_resource->texture_target(), 0, 0, 0, resource_size_pixels.width(),
+        resource_size_pixels.height(), GLDataFormat(plane_resource_format),
+        GLDataType(plane_resource_format), pixels);
+
+    plane_resource->SetUniqueId(video_frame->unique_id(), i);
   }
 
   // Set the sync token otherwise resource is assumed to be synchronized.
@@ -893,16 +1026,16 @@
   GenerateCompositorSyncToken(context_provider_->ContextGL(), &sync_token);
 
   for (size_t i = 0; i < plane_resources.size(); ++i) {
-    PlaneResource& plane_resource = *plane_resources[i];
-    GLuint target = resource_provider_->GetResourceTextureTarget(
-        plane_resource.resource_id());
-    auto transfer_resource = viz::TransferableResource::MakeGL(
-        plane_resource.mailbox(), GL_LINEAR, target, sync_token);
+    HardwarePlaneResource* plane_resource = plane_resources[i]->AsHardware();
+    auto transfer_resource = viz::TransferableResource::MakeGLOverlay(
+        plane_resource->mailbox(), GL_LINEAR, plane_resource->texture_target(),
+        sync_token, plane_resource->resource_size(),
+        plane_resource->overlay_candidate());
     transfer_resource.color_space = output_color_space;
     external_resources.resources.push_back(std::move(transfer_resource));
     external_resources.release_callbacks.push_back(base::BindOnce(
         &VideoResourceUpdater::RecycleResource, weak_ptr_factory_.GetWeakPtr(),
-        plane_resource.resource_id()));
+        plane_resource->plane_resource_id()));
   }
 
   external_resources.type = VideoFrameExternalResources::YUV_RESOURCE;
@@ -922,14 +1055,15 @@
   video_frame->UpdateReleaseSyncToken(&client);
 }
 
-void VideoResourceUpdater::RecycleResource(viz::ResourceId resource_id,
+void VideoResourceUpdater::RecycleResource(uint32_t plane_resource_id,
                                            const gpu::SyncToken& sync_token,
                                            bool lost_resource) {
+  auto matches_id_fn =
+      [plane_resource_id](const std::unique_ptr<PlaneResource>& resource) {
+        return resource->plane_resource_id() == plane_resource_id;
+      };
   auto resource_it =
-      std::find_if(all_resources_.begin(), all_resources_.end(),
-                   [resource_id](const PlaneResource& plane_resource) {
-                     return plane_resource.resource_id() == resource_id;
-                   });
+      std::find_if(all_resources_.begin(), all_resources_.end(), matches_id_fn);
   if (resource_it == all_resources_.end())
     return;
 
@@ -939,11 +1073,51 @@
   }
 
   if (lost_resource) {
-    resource_it->clear_refs();
-    DeleteResource(resource_it);
+    all_resources_.erase(resource_it);
   } else {
-    resource_it->remove_ref();
+    (*resource_it)->remove_ref();
   }
 }
 
+bool VideoResourceUpdater::OnMemoryDump(
+    const base::trace_event::MemoryDumpArgs& args,
+    base::trace_event::ProcessMemoryDump* pmd) {
+  for (auto& resource : all_resources_) {
+    std::string dump_name =
+        base::StringPrintf("cc/video_memory/updater_%d/resource_%d",
+                           tracing_id_, resource->plane_resource_id());
+    base::trace_event::MemoryAllocatorDump* dump =
+        pmd->CreateAllocatorDump(dump_name);
+
+    const uint64_t total_bytes =
+        viz::ResourceSizes::UncheckedSizeInBytesAligned<uint64_t>(
+            resource->resource_size(), resource->resource_format());
+    dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
+                    base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+                    total_bytes);
+
+    // The importance value assigned to the GUID here must be greater than the
+    // importance value assigned elsewhere so that resource ownership is
+    // attributed to VideoResourceUpdater.
+    constexpr int kImportance = 2;
+
+    // Resources are shared across processes and require a shared GUID to
+    // prevent double counting the memory.
+    if (software_compositor()) {
+      base::UnguessableToken shm_guid =
+          resource->AsSoftware()->GetSharedMemoryGuid();
+      pmd->CreateSharedMemoryOwnershipEdge(dump->guid(), shm_guid, kImportance);
+    } else {
+      base::trace_event::MemoryAllocatorDumpGuid guid =
+          gl::GetGLTextureClientGUIDForTracing(
+              context_provider_->ContextSupport()->ShareGroupTracingGUID(),
+              resource->AsHardware()->texture_id());
+      pmd->CreateSharedGlobalAllocatorDump(guid);
+      pmd->AddOwnershipEdge(dump->guid(), guid, kImportance);
+    }
+  }
+
+  return true;
+}
+
 }  // namespace cc
diff --git a/cc/resources/video_resource_updater.h b/cc/resources/video_resource_updater.h
index 61b769a..da30385 100644
--- a/cc/resources/video_resource_updater.h
+++ b/cc/resources/video_resource_updater.h
@@ -16,6 +16,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
+#include "base/trace_event/memory_dump_provider.h"
 #include "cc/cc_export.h"
 #include "components/viz/common/resources/release_callback.h"
 #include "components/viz/common/resources/resource_format.h"
@@ -40,6 +41,7 @@
 }
 
 namespace cc {
+class LayerTreeFrameSink;
 class LayerTreeResourceProvider;
 
 class CC_EXPORT VideoFrameExternalResources {
@@ -53,18 +55,11 @@
     RGBA_PREMULTIPLIED_RESOURCE,
     RGBA_RESOURCE,
     STREAM_TEXTURE_RESOURCE,
-
-    SOFTWARE_RESOURCE
   };
   ResourceType type = NONE;
   std::vector<viz::TransferableResource> resources;
   std::vector<viz::ReleaseCallback> release_callbacks;
 
-  // TODO(danakj): Remove these and use TransferableResources to send
-  // software things too.
-  unsigned software_resource = viz::kInvalidResourceId;
-  viz::ReleaseCallback software_release_callback;
-
   // Used by hardware textures which do not return values in the 0-1 range.
   // After a lookup, subtract offset and multiply by multiplier.
   float offset = 0.f;
@@ -79,12 +74,22 @@
 
 // VideoResourceUpdater is used by the video system to produce frame content as
 // resources consumable by the compositor.
-class CC_EXPORT VideoResourceUpdater {
+class CC_EXPORT VideoResourceUpdater
+    : public base::trace_event::MemoryDumpProvider {
  public:
+  // For GPU compositing |context_provider| should be provided and for software
+  // compositing |layer_tree_frame_sink| should be provided. If there is a
+  // non-null |context_provider| we assume GPU compositing.
+  // TODO(kylechar): Don't use LayerTreeFrameSink for the software compositing
+  // path. The UseSurfaceLayerForVideo path isn't compatible with this. We can
+  // maybe use mojom::CompositorFrameSink instead.
   VideoResourceUpdater(viz::ContextProvider* context_provider,
+                       LayerTreeFrameSink* layer_tree_frame_sink,
                        LayerTreeResourceProvider* resource_provider,
-                       bool use_stream_video_draw_quad);
-  ~VideoResourceUpdater();
+                       bool use_stream_video_draw_quad,
+                       bool use_gpu_memory_buffer_resources);
+
+  ~VideoResourceUpdater() override;
 
   // For each CompositorFrame the following sequence is expected:
   // 1. ObtainFrameResources(): Import resources for the next video frame with
@@ -111,60 +116,10 @@
   VideoFrameExternalResources CreateExternalResourcesFromVideoFrame(
       scoped_refptr<media::VideoFrame> video_frame);
 
-  void SetUseR16ForTesting(bool use_r16_for_testing) {
-    use_r16_for_testing_ = use_r16_for_testing;
-  }
-
  private:
-  // Resource for a video plane allocated and owned by VideResourceUpdater.
-  // There can be multiple plane resources for each video frame, depending on
-  // the format. These will be reused when possible.
-  class PlaneResource {
-   public:
-    PlaneResource(viz::ResourceId resource_id,
-                  const gfx::Size& resource_size,
-                  viz::ResourceFormat resource_format,
-                  gpu::Mailbox mailbox);
-
-    // Returns true if this resource matches the unique identifiers of another
-    // VideoFrame resource.
-    bool Matches(int unique_frame_id, size_t plane_index);
-
-    // Sets the unique identifiers for this resource, may only be called when
-    // there is a single reference to the resource (i.e. |ref_count_| == 1).
-    void SetUniqueId(int unique_frame_id, size_t plane_index);
-
-    // Accessors for resource identifiers provided at construction time.
-    viz::ResourceId resource_id() const { return resource_id_; }
-    const gfx::Size& resource_size() const { return resource_size_; }
-    viz::ResourceFormat resource_format() const { return resource_format_; }
-    const gpu::Mailbox& mailbox() const { return mailbox_; }
-
-    // Various methods for managing references. See |ref_count_| for details.
-    void add_ref() { ++ref_count_; }
-    void remove_ref() { --ref_count_; }
-    void clear_refs() { ref_count_ = 0; }
-    bool has_refs() const { return ref_count_ != 0; }
-
-   private:
-    // The balance between the number of times this resource has been returned
-    // from CreateForSoftwarePlanes vs released in RecycleResource.
-    int ref_count_ = 0;
-
-    // These two members are used for identifying the data stored in this
-    // resource; they uniquely identify a media::VideoFrame plane.
-    int unique_frame_id_ = 0;
-    size_t plane_index_ = 0u;
-    // Indicates if the above two members have been set or not.
-    bool has_unique_frame_id_and_plane_index_ = false;
-
-    const viz::ResourceId resource_id_;
-    const gfx::Size resource_size_;
-    const viz::ResourceFormat resource_format_;
-    const gpu::Mailbox mailbox_;
-
-    DISALLOW_COPY_AND_ASSIGN(PlaneResource);
-  };
+  class PlaneResource;
+  class HardwarePlaneResource;
+  class SoftwarePlaneResource;
 
   // A resource that will be embedded in a DrawQuad in the next CompositorFrame.
   // Each video plane will correspond to one FrameResource.
@@ -173,9 +128,7 @@
     gfx::Size size_in_pixels;
   };
 
-  // This needs to be a container where iterators can be erased without
-  // invalidating other iterators.
-  typedef std::list<PlaneResource> ResourceList;
+  bool software_compositor() const { return context_provider_ == nullptr; }
 
   // Obtain a resource of the right format by either recycling an
   // unreferenced but appropriately formatted resource, or by
@@ -185,18 +138,14 @@
   // used for reading, and so is returned even if it is still referenced.
   // Passing -1 for |plane_index| avoids returning referenced
   // resources.
-  ResourceList::iterator RecycleOrAllocateResource(
-      const gfx::Size& resource_size,
-      viz::ResourceFormat resource_format,
-      const gfx::ColorSpace& color_space,
-      bool software_resource,
-      int unique_id,
-      int plane_index);
-  ResourceList::iterator AllocateResource(const gfx::Size& plane_size,
-                                          viz::ResourceFormat format,
-                                          const gfx::ColorSpace& color_space,
-                                          bool software_resource);
-  void DeleteResource(ResourceList::iterator resource_it);
+  PlaneResource* RecycleOrAllocateResource(const gfx::Size& resource_size,
+                                           viz::ResourceFormat resource_format,
+                                           const gfx::ColorSpace& color_space,
+                                           int unique_id,
+                                           int plane_index);
+  PlaneResource* AllocateResource(const gfx::Size& plane_size,
+                                  viz::ResourceFormat format,
+                                  const gfx::ColorSpace& color_space);
 
   // Create a copy of a texture-backed source video frame in a new GL_TEXTURE_2D
   // texture. This is used when there are multiple GPU threads (Android WebView)
@@ -219,25 +168,30 @@
   VideoFrameExternalResources CreateForSoftwarePlanes(
       scoped_refptr<media::VideoFrame> video_frame);
 
-  void RecycleResource(viz::ResourceId resource_id,
+  void RecycleResource(uint32_t plane_resource_id,
                        const gpu::SyncToken& sync_token,
                        bool lost_resource);
   void ReturnTexture(const scoped_refptr<media::VideoFrame>& video_frame,
                      const gpu::SyncToken& sync_token,
                      bool lost_resource);
 
+  // base::trace_event::MemoryDumpProvider implementation.
+  bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
+                    base::trace_event::ProcessMemoryDump* pmd) override;
+
   viz::ContextProvider* const context_provider_;
+  LayerTreeFrameSink* const layer_tree_frame_sink_;
   LayerTreeResourceProvider* const resource_provider_;
   const bool use_stream_video_draw_quad_;
+  const bool use_gpu_memory_buffer_resources_;
+  const int tracing_id_;
   std::unique_ptr<media::PaintCanvasVideoRenderer> video_renderer_;
+  uint32_t next_plane_resource_id_ = 1;
+
+  // Temporary pixel buffer when converting between formats.
   std::vector<uint8_t> upload_pixels_;
-  bool use_r16_for_testing_ = false;
 
   VideoFrameExternalResources::ResourceType frame_resource_type_;
-  // TODO(danakj): Remove these, use TransferableResource for software path too.
-  viz::ResourceId software_resource_;
-  // Called once for |software_resource_|.
-  viz::ReleaseCallback software_release_callback_;
 
   float frame_resource_offset_;
   float frame_resource_multiplier_;
@@ -249,7 +203,7 @@
 
   // Resources allocated by VideoResourceUpdater. Used to recycle resources so
   // we can reduce the number of allocations and data transfers.
-  ResourceList all_resources_;
+  std::vector<std::unique_ptr<PlaneResource>> all_resources_;
 
   base::WeakPtrFactory<VideoResourceUpdater> weak_ptr_factory_;
 
diff --git a/cc/resources/video_resource_updater_unittest.cc b/cc/resources/video_resource_updater_unittest.cc
index b5f3584..6c1ec994 100644
--- a/cc/resources/video_resource_updater_unittest.cc
+++ b/cc/resources/video_resource_updater_unittest.cc
@@ -10,10 +10,10 @@
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
 #include "cc/resources/resource_provider.h"
+#include "cc/test/fake_layer_tree_frame_sink.h"
 #include "cc/test/fake_output_surface_client.h"
 #include "cc/test/fake_resource_provider.h"
 #include "components/viz/test/fake_output_surface.h"
-#include "components/viz/test/test_shared_bitmap_manager.h"
 #include "components/viz/test/test_web_graphics_context_3d.h"
 #include "gpu/GLES2/gl2extchromium.h"
 #include "media/base/video_frame.h"
@@ -22,6 +22,8 @@
 namespace cc {
 namespace {
 
+constexpr bool kUseGpuMemoryBufferResources = false;
+
 class WebGraphicsContext3DUploadCounter : public viz::TestWebGraphicsContext3D {
  public:
   void texSubImage2D(GLenum target,
@@ -101,15 +103,13 @@
 
   void SetUp() override {
     testing::Test::SetUp();
-    shared_bitmap_manager_.reset(new SharedBitmapManagerAllocationCounter());
+    layer_tree_frame_sink_software_ = FakeLayerTreeFrameSink::CreateSoftware();
     resource_provider3d_ =
         FakeResourceProvider::CreateLayerTreeResourceProvider(
-            context_provider_.get(), shared_bitmap_manager_.get(), nullptr,
-            high_bit_for_testing_);
+            context_provider_.get(), nullptr, nullptr, high_bit_for_testing_);
     resource_provider_software_ =
         FakeResourceProvider::CreateLayerTreeResourceProvider(
-            nullptr, shared_bitmap_manager_.get(), nullptr,
-            high_bit_for_testing_);
+            nullptr, nullptr, nullptr, high_bit_for_testing_);
   }
 
   scoped_refptr<media::VideoFrame> CreateTestYUVVideoFrame() {
@@ -246,7 +246,7 @@
 
   WebGraphicsContext3DUploadCounter* context3d_;
   scoped_refptr<viz::TestContextProvider> context_provider_;
-  std::unique_ptr<SharedBitmapManagerAllocationCounter> shared_bitmap_manager_;
+  std::unique_ptr<FakeLayerTreeFrameSink> layer_tree_frame_sink_software_;
   std::unique_ptr<LayerTreeResourceProvider> resource_provider3d_;
   std::unique_ptr<LayerTreeResourceProvider> resource_provider_software_;
   gpu::SyncToken release_sync_token_;
@@ -260,9 +260,9 @@
 
 TEST_F(VideoResourceUpdaterTest, SoftwareFrame) {
   bool use_stream_video_draw_quad = false;
-  VideoResourceUpdater updater(context_provider_.get(),
-                               resource_provider3d_.get(),
-                               use_stream_video_draw_quad);
+  VideoResourceUpdater updater(
+      context_provider_.get(), nullptr, resource_provider3d_.get(),
+      use_stream_video_draw_quad, kUseGpuMemoryBufferResources);
   scoped_refptr<media::VideoFrame> video_frame = CreateTestYUVVideoFrame();
 
   VideoFrameExternalResources resources =
@@ -272,9 +272,9 @@
 
 TEST_F(VideoResourceUpdaterTest, HighBitFrameNoF16) {
   bool use_stream_video_draw_quad = false;
-  VideoResourceUpdater updater(context_provider_.get(),
-                               resource_provider3d_.get(),
-                               use_stream_video_draw_quad);
+  VideoResourceUpdater updater(
+      context_provider_.get(), nullptr, resource_provider3d_.get(),
+      use_stream_video_draw_quad, kUseGpuMemoryBufferResources);
   scoped_refptr<media::VideoFrame> video_frame = CreateTestHighBitFrame();
 
   VideoFrameExternalResources resources =
@@ -291,9 +291,9 @@
 
 TEST_F(VideoResourceUpdaterTestWithF16, HighBitFrame) {
   bool use_stream_video_draw_quad = false;
-  VideoResourceUpdater updater(context_provider_.get(),
-                               resource_provider3d_.get(),
-                               use_stream_video_draw_quad);
+  VideoResourceUpdater updater(
+      context_provider_.get(), nullptr, resource_provider3d_.get(),
+      use_stream_video_draw_quad, kUseGpuMemoryBufferResources);
   scoped_refptr<media::VideoFrame> video_frame = CreateTestHighBitFrame();
 
   VideoFrameExternalResources resources =
@@ -321,10 +321,9 @@
 
 TEST_F(VideoResourceUpdaterTestWithR16, HighBitFrame) {
   bool use_stream_video_draw_quad = false;
-  VideoResourceUpdater updater(context_provider_.get(),
-                               resource_provider3d_.get(),
-                               use_stream_video_draw_quad);
-  updater.SetUseR16ForTesting(true);
+  VideoResourceUpdater updater(
+      context_provider_.get(), nullptr, resource_provider3d_.get(),
+      use_stream_video_draw_quad, kUseGpuMemoryBufferResources);
   scoped_refptr<media::VideoFrame> video_frame = CreateTestHighBitFrame();
 
   VideoFrameExternalResources resources =
@@ -347,20 +346,23 @@
 
 TEST_F(VideoResourceUpdaterTest, HighBitFrameSoftwareCompositor) {
   bool use_stream_video_draw_quad = false;
-  VideoResourceUpdater updater(nullptr, resource_provider_software_.get(),
-                               use_stream_video_draw_quad);
+  VideoResourceUpdater updater(nullptr, layer_tree_frame_sink_software_.get(),
+                               resource_provider_software_.get(),
+                               use_stream_video_draw_quad,
+                               kUseGpuMemoryBufferResources);
   scoped_refptr<media::VideoFrame> video_frame = CreateTestHighBitFrame();
 
   VideoFrameExternalResources resources =
       updater.CreateExternalResourcesFromVideoFrame(video_frame);
-  EXPECT_EQ(VideoFrameExternalResources::SOFTWARE_RESOURCE, resources.type);
+  EXPECT_EQ(VideoFrameExternalResources::RGBA_PREMULTIPLIED_RESOURCE,
+            resources.type);
 }
 
 TEST_F(VideoResourceUpdaterTest, WonkySoftwareFrame) {
   bool use_stream_video_draw_quad = false;
-  VideoResourceUpdater updater(context_provider_.get(),
-                               resource_provider3d_.get(),
-                               use_stream_video_draw_quad);
+  VideoResourceUpdater updater(
+      context_provider_.get(), nullptr, resource_provider3d_.get(),
+      use_stream_video_draw_quad, kUseGpuMemoryBufferResources);
   scoped_refptr<media::VideoFrame> video_frame = CreateWonkyTestYUVVideoFrame();
 
   VideoFrameExternalResources resources =
@@ -370,20 +372,23 @@
 
 TEST_F(VideoResourceUpdaterTest, WonkySoftwareFrameSoftwareCompositor) {
   bool use_stream_video_draw_quad = false;
-  VideoResourceUpdater updater(nullptr, resource_provider_software_.get(),
-                               use_stream_video_draw_quad);
+  VideoResourceUpdater updater(nullptr, layer_tree_frame_sink_software_.get(),
+                               resource_provider_software_.get(),
+                               use_stream_video_draw_quad,
+                               kUseGpuMemoryBufferResources);
   scoped_refptr<media::VideoFrame> video_frame = CreateWonkyTestYUVVideoFrame();
 
   VideoFrameExternalResources resources =
       updater.CreateExternalResourcesFromVideoFrame(video_frame);
-  EXPECT_EQ(VideoFrameExternalResources::SOFTWARE_RESOURCE, resources.type);
+  EXPECT_EQ(VideoFrameExternalResources::RGBA_PREMULTIPLIED_RESOURCE,
+            resources.type);
 }
 
 TEST_F(VideoResourceUpdaterTest, ReuseResource) {
   bool use_stream_video_draw_quad = false;
-  VideoResourceUpdater updater(context_provider_.get(),
-                               resource_provider3d_.get(),
-                               use_stream_video_draw_quad);
+  VideoResourceUpdater updater(
+      context_provider_.get(), nullptr, resource_provider3d_.get(),
+      use_stream_video_draw_quad, kUseGpuMemoryBufferResources);
   scoped_refptr<media::VideoFrame> video_frame = CreateTestYUVVideoFrame();
   video_frame->set_timestamp(base::TimeDelta::FromSeconds(1234));
 
@@ -394,7 +399,6 @@
   EXPECT_EQ(VideoFrameExternalResources::YUV_RESOURCE, resources.type);
   EXPECT_EQ(3u, resources.resources.size());
   EXPECT_EQ(3u, resources.release_callbacks.size());
-  EXPECT_EQ(viz::kInvalidResourceId, resources.software_resource);
   // Expect exactly three texture uploads, one for each plane.
   EXPECT_EQ(3, context3d_->UploadCount());
 
@@ -415,9 +419,9 @@
 
 TEST_F(VideoResourceUpdaterTest, ReuseResourceNoDelete) {
   bool use_stream_video_draw_quad = false;
-  VideoResourceUpdater updater(context_provider_.get(),
-                               resource_provider3d_.get(),
-                               use_stream_video_draw_quad);
+  VideoResourceUpdater updater(
+      context_provider_.get(), nullptr, resource_provider3d_.get(),
+      use_stream_video_draw_quad, kUseGpuMemoryBufferResources);
   scoped_refptr<media::VideoFrame> video_frame = CreateTestYUVVideoFrame();
   video_frame->set_timestamp(base::TimeDelta::FromSeconds(1234));
 
@@ -428,7 +432,6 @@
   EXPECT_EQ(VideoFrameExternalResources::YUV_RESOURCE, resources.type);
   EXPECT_EQ(3u, resources.resources.size());
   EXPECT_EQ(3u, resources.release_callbacks.size());
-  EXPECT_EQ(viz::kInvalidResourceId, resources.software_resource);
   // Expect exactly three texture uploads, one for each plane.
   EXPECT_EQ(3, context3d_->UploadCount());
 
@@ -444,82 +447,85 @@
 
 TEST_F(VideoResourceUpdaterTest, SoftwareFrameSoftwareCompositor) {
   bool use_stream_video_draw_quad = false;
-  VideoResourceUpdater updater(nullptr, resource_provider_software_.get(),
-                               use_stream_video_draw_quad);
+  VideoResourceUpdater updater(nullptr, layer_tree_frame_sink_software_.get(),
+                               resource_provider_software_.get(),
+                               use_stream_video_draw_quad,
+                               kUseGpuMemoryBufferResources);
   scoped_refptr<media::VideoFrame> video_frame = CreateTestYUVVideoFrame();
 
   VideoFrameExternalResources resources =
       updater.CreateExternalResourcesFromVideoFrame(video_frame);
-  EXPECT_EQ(VideoFrameExternalResources::SOFTWARE_RESOURCE, resources.type);
+  EXPECT_EQ(VideoFrameExternalResources::RGBA_PREMULTIPLIED_RESOURCE,
+            resources.type);
 }
 
 TEST_F(VideoResourceUpdaterTest, ReuseResourceSoftwareCompositor) {
   bool use_stream_video_draw_quad = false;
-  VideoResourceUpdater updater(nullptr, resource_provider_software_.get(),
-                               use_stream_video_draw_quad);
+  VideoResourceUpdater updater(nullptr, layer_tree_frame_sink_software_.get(),
+                               resource_provider_software_.get(),
+                               use_stream_video_draw_quad,
+                               kUseGpuMemoryBufferResources);
   scoped_refptr<media::VideoFrame> video_frame = CreateTestYUVVideoFrame();
   video_frame->set_timestamp(base::TimeDelta::FromSeconds(1234));
 
   // Allocate the resources for a software video frame.
-  shared_bitmap_manager_->ResetAllocationCount();
   VideoFrameExternalResources resources =
       updater.CreateExternalResourcesFromVideoFrame(video_frame);
-  EXPECT_EQ(VideoFrameExternalResources::SOFTWARE_RESOURCE, resources.type);
-  EXPECT_EQ(0u, resources.resources.size());
-  EXPECT_EQ(0u, resources.release_callbacks.size());
-  EXPECT_LT(viz::kInvalidResourceId, resources.software_resource);
+  EXPECT_EQ(VideoFrameExternalResources::RGBA_PREMULTIPLIED_RESOURCE,
+            resources.type);
+  EXPECT_EQ(1u, resources.resources.size());
+  EXPECT_EQ(1u, resources.release_callbacks.size());
   // Expect exactly one allocated shared bitmap.
-  EXPECT_EQ(1, shared_bitmap_manager_->AllocationCount());
+  EXPECT_EQ(1u, layer_tree_frame_sink_software_->shared_bitmaps().size());
 
   // Simulate the ResourceProvider releasing the resource back to the video
   // updater.
-  std::move(resources.software_release_callback).Run(gpu::SyncToken(), false);
+  std::move(resources.release_callbacks.back()).Run(gpu::SyncToken(), false);
 
   // Allocate resources for the same frame.
-  shared_bitmap_manager_->ResetAllocationCount();
   resources = updater.CreateExternalResourcesFromVideoFrame(video_frame);
-  EXPECT_EQ(VideoFrameExternalResources::SOFTWARE_RESOURCE, resources.type);
-  EXPECT_EQ(0u, resources.resources.size());
-  EXPECT_EQ(0u, resources.release_callbacks.size());
-  EXPECT_LT(viz::kInvalidResourceId, resources.software_resource);
+  EXPECT_EQ(VideoFrameExternalResources::RGBA_PREMULTIPLIED_RESOURCE,
+            resources.type);
+  EXPECT_EQ(1u, resources.resources.size());
+  EXPECT_EQ(1u, resources.release_callbacks.size());
   // The data should be reused so expect no new allocations.
-  EXPECT_EQ(0, shared_bitmap_manager_->AllocationCount());
+  EXPECT_EQ(1u, layer_tree_frame_sink_software_->shared_bitmaps().size());
 }
 
 TEST_F(VideoResourceUpdaterTest, ReuseResourceNoDeleteSoftwareCompositor) {
   bool use_stream_video_draw_quad = false;
-  VideoResourceUpdater updater(nullptr, resource_provider_software_.get(),
-                               use_stream_video_draw_quad);
+  VideoResourceUpdater updater(nullptr, layer_tree_frame_sink_software_.get(),
+                               resource_provider_software_.get(),
+                               use_stream_video_draw_quad,
+                               kUseGpuMemoryBufferResources);
   scoped_refptr<media::VideoFrame> video_frame = CreateTestYUVVideoFrame();
   video_frame->set_timestamp(base::TimeDelta::FromSeconds(1234));
 
   // Allocate the resources for a software video frame.
-  shared_bitmap_manager_->ResetAllocationCount();
   VideoFrameExternalResources resources =
       updater.CreateExternalResourcesFromVideoFrame(video_frame);
-  EXPECT_EQ(VideoFrameExternalResources::SOFTWARE_RESOURCE, resources.type);
-  EXPECT_EQ(0u, resources.resources.size());
-  EXPECT_EQ(0u, resources.release_callbacks.size());
-  EXPECT_LT(viz::kInvalidResourceId, resources.software_resource);
+  EXPECT_EQ(VideoFrameExternalResources::RGBA_PREMULTIPLIED_RESOURCE,
+            resources.type);
+  EXPECT_EQ(1u, resources.resources.size());
+  EXPECT_EQ(1u, resources.release_callbacks.size());
   // Expect exactly one allocated shared bitmap.
-  EXPECT_EQ(1, shared_bitmap_manager_->AllocationCount());
+  EXPECT_EQ(1u, layer_tree_frame_sink_software_->shared_bitmaps().size());
 
   // Allocate resources for the same frame.
-  shared_bitmap_manager_->ResetAllocationCount();
   resources = updater.CreateExternalResourcesFromVideoFrame(video_frame);
-  EXPECT_EQ(VideoFrameExternalResources::SOFTWARE_RESOURCE, resources.type);
-  EXPECT_EQ(0u, resources.resources.size());
-  EXPECT_EQ(0u, resources.release_callbacks.size());
-  EXPECT_NE(viz::kInvalidResourceId, resources.software_resource);
+  EXPECT_EQ(VideoFrameExternalResources::RGBA_PREMULTIPLIED_RESOURCE,
+            resources.type);
+  EXPECT_EQ(1u, resources.resources.size());
+  EXPECT_EQ(1u, resources.release_callbacks.size());
   // The data should be reused so expect no new allocations.
-  EXPECT_EQ(0, shared_bitmap_manager_->AllocationCount());
+  EXPECT_EQ(1u, layer_tree_frame_sink_software_->shared_bitmaps().size());
 }
 
 TEST_F(VideoResourceUpdaterTest, CreateForHardwarePlanes) {
   bool use_stream_video_draw_quad = false;
-  VideoResourceUpdater updater(context_provider_.get(),
-                               resource_provider3d_.get(),
-                               use_stream_video_draw_quad);
+  VideoResourceUpdater updater(
+      context_provider_.get(), nullptr, resource_provider3d_.get(),
+      use_stream_video_draw_quad, kUseGpuMemoryBufferResources);
 
   scoped_refptr<media::VideoFrame> video_frame =
       CreateTestRGBAHardwareVideoFrame();
@@ -530,7 +536,6 @@
             resources.type);
   EXPECT_EQ(1u, resources.resources.size());
   EXPECT_EQ(1u, resources.release_callbacks.size());
-  EXPECT_EQ(viz::kInvalidResourceId, resources.software_resource);
 
   video_frame = CreateTestYuvHardwareVideoFrame(media::PIXEL_FORMAT_I420, 3,
                                                 GL_TEXTURE_RECTANGLE_ARB);
@@ -539,7 +544,6 @@
   EXPECT_EQ(VideoFrameExternalResources::YUV_RESOURCE, resources.type);
   EXPECT_EQ(3u, resources.resources.size());
   EXPECT_EQ(3u, resources.release_callbacks.size());
-  EXPECT_EQ(viz::kInvalidResourceId, resources.software_resource);
   EXPECT_FALSE(resources.resources[0].read_lock_fences_enabled);
   EXPECT_FALSE(resources.resources[1].read_lock_fences_enabled);
   EXPECT_FALSE(resources.resources[2].read_lock_fences_enabled);
@@ -557,9 +561,9 @@
 
 TEST_F(VideoResourceUpdaterTest, CreateForHardwarePlanes_StreamTexture) {
   bool use_stream_video_draw_quad = true;
-  VideoResourceUpdater updater(context_provider_.get(),
-                               resource_provider3d_.get(),
-                               use_stream_video_draw_quad);
+  VideoResourceUpdater updater(
+      context_provider_.get(), nullptr, resource_provider3d_.get(),
+      use_stream_video_draw_quad, kUseGpuMemoryBufferResources);
   context3d_->ResetTextureCreationCount();
   scoped_refptr<media::VideoFrame> video_frame =
       CreateTestStreamTextureHardwareVideoFrame(false);
@@ -572,7 +576,6 @@
   EXPECT_EQ((GLenum)GL_TEXTURE_EXTERNAL_OES,
             resources.resources[0].mailbox_holder.texture_target);
   EXPECT_EQ(1u, resources.release_callbacks.size());
-  EXPECT_EQ(viz::kInvalidResourceId, resources.software_resource);
   EXPECT_EQ(0, context3d_->TextureCreationCount());
 
   // A copied stream texture should return an RGBA resource in a new
@@ -586,15 +589,14 @@
   EXPECT_EQ((GLenum)GL_TEXTURE_2D,
             resources.resources[0].mailbox_holder.texture_target);
   EXPECT_EQ(1u, resources.release_callbacks.size());
-  EXPECT_EQ(viz::kInvalidResourceId, resources.software_resource);
   EXPECT_EQ(1, context3d_->TextureCreationCount());
 }
 
 TEST_F(VideoResourceUpdaterTest, CreateForHardwarePlanes_TextureQuad) {
   bool use_stream_video_draw_quad = false;
-  VideoResourceUpdater updater(context_provider_.get(),
-                               resource_provider3d_.get(),
-                               use_stream_video_draw_quad);
+  VideoResourceUpdater updater(
+      context_provider_.get(), nullptr, resource_provider3d_.get(),
+      use_stream_video_draw_quad, kUseGpuMemoryBufferResources);
   context3d_->ResetTextureCreationCount();
   scoped_refptr<media::VideoFrame> video_frame =
       CreateTestStreamTextureHardwareVideoFrame(false);
@@ -607,16 +609,15 @@
   EXPECT_EQ((GLenum)GL_TEXTURE_EXTERNAL_OES,
             resources.resources[0].mailbox_holder.texture_target);
   EXPECT_EQ(1u, resources.release_callbacks.size());
-  EXPECT_EQ(viz::kInvalidResourceId, resources.software_resource);
   EXPECT_EQ(0, context3d_->TextureCreationCount());
 }
 
 // Passthrough the sync token returned by the compositor if we don't have an
 // existing release sync token.
 TEST_F(VideoResourceUpdaterTest, PassReleaseSyncToken) {
-  VideoResourceUpdater updater(context_provider_.get(),
-                               resource_provider3d_.get(),
-                               false /* use_stream_video_draw_quad */);
+  VideoResourceUpdater updater(
+      context_provider_.get(), nullptr, resource_provider3d_.get(),
+      false /* use_stream_video_draw_quad */, kUseGpuMemoryBufferResources);
 
   const gpu::SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO,
                                   gpu::CommandBufferId::FromUnsafeValue(0x123),
@@ -638,9 +639,9 @@
 
 // Generate new sync token because video frame has an existing sync token.
 TEST_F(VideoResourceUpdaterTest, GenerateReleaseSyncToken) {
-  VideoResourceUpdater updater(context_provider_.get(),
-                               resource_provider3d_.get(),
-                               false /* use_stream_video_draw_quad */);
+  VideoResourceUpdater updater(
+      context_provider_.get(), nullptr, resource_provider3d_.get(),
+      false /* use_stream_video_draw_quad */, kUseGpuMemoryBufferResources);
 
   const gpu::SyncToken sync_token1(gpu::CommandBufferNamespace::GPU_IO,
                                    gpu::CommandBufferId::FromUnsafeValue(0x123),
@@ -673,9 +674,9 @@
 // Pass mailbox sync token as is if no GL operations are performed before frame
 // resources are handed off to the compositor.
 TEST_F(VideoResourceUpdaterTest, PassMailboxSyncToken) {
-  VideoResourceUpdater updater(context_provider_.get(),
-                               resource_provider3d_.get(),
-                               false /* use_stream_video_draw_quad */);
+  VideoResourceUpdater updater(
+      context_provider_.get(), nullptr, resource_provider3d_.get(),
+      false /* use_stream_video_draw_quad */, kUseGpuMemoryBufferResources);
 
   scoped_refptr<media::VideoFrame> video_frame =
       CreateTestRGBAHardwareVideoFrame();
@@ -691,9 +692,9 @@
 
 // Generate new sync token for compositor when copying the texture.
 TEST_F(VideoResourceUpdaterTest, GenerateSyncTokenOnTextureCopy) {
-  VideoResourceUpdater updater(context_provider_.get(),
-                               resource_provider3d_.get(),
-                               false /* use_stream_video_draw_quad */);
+  VideoResourceUpdater updater(
+      context_provider_.get(), nullptr, resource_provider3d_.get(),
+      false /* use_stream_video_draw_quad */, kUseGpuMemoryBufferResources);
 
   scoped_refptr<media::VideoFrame> video_frame =
       CreateTestStreamTextureHardwareVideoFrame(true /* needs_copy */);
@@ -712,9 +713,9 @@
 // of the underlying buffer, that is YUV_420_BIPLANAR.
 TEST_F(VideoResourceUpdaterTest, CreateForHardwarePlanes_SingleNV12) {
   bool use_stream_video_draw_quad = false;
-  VideoResourceUpdater updater(context_provider_.get(),
-                               resource_provider3d_.get(),
-                               use_stream_video_draw_quad);
+  VideoResourceUpdater updater(
+      context_provider_.get(), nullptr, resource_provider3d_.get(),
+      use_stream_video_draw_quad, kUseGpuMemoryBufferResources);
   context3d_->ResetTextureCreationCount();
   scoped_refptr<media::VideoFrame> video_frame = CreateTestHardwareVideoFrame(
       media::PIXEL_FORMAT_NV12, GL_TEXTURE_EXTERNAL_OES);
@@ -743,9 +744,9 @@
 
 TEST_F(VideoResourceUpdaterTest, CreateForHardwarePlanes_DualNV12) {
   bool use_stream_video_draw_quad = false;
-  VideoResourceUpdater updater(context_provider_.get(),
-                               resource_provider3d_.get(),
-                               use_stream_video_draw_quad);
+  VideoResourceUpdater updater(
+      context_provider_.get(), nullptr, resource_provider3d_.get(),
+      use_stream_video_draw_quad, kUseGpuMemoryBufferResources);
   context3d_->ResetTextureCreationCount();
   scoped_refptr<media::VideoFrame> video_frame =
       CreateTestYuvHardwareVideoFrame(media::PIXEL_FORMAT_NV12, 2,
@@ -756,7 +757,6 @@
   EXPECT_EQ(VideoFrameExternalResources::YUV_RESOURCE, resources.type);
   EXPECT_EQ(2u, resources.resources.size());
   EXPECT_EQ(2u, resources.release_callbacks.size());
-  EXPECT_EQ(viz::kInvalidResourceId, resources.software_resource);
   EXPECT_EQ((GLenum)GL_TEXTURE_EXTERNAL_OES,
             resources.resources[0].mailbox_holder.texture_target);
   // |updater| doesn't set |buffer_format| in this case.
diff --git a/cc/tiles/software_image_decode_cache.cc b/cc/tiles/software_image_decode_cache.cc
index 899f461..22d6ecb 100644
--- a/cc/tiles/software_image_decode_cache.cc
+++ b/cc/tiles/software_image_decode_cache.cc
@@ -303,7 +303,8 @@
   auto decoded_image_it = decoded_images_.Peek(key);
   DCHECK(decoded_image_it != decoded_images_.end());
   auto* entry = decoded_image_it->second.get();
-  DCHECK_GT(entry->ref_count, 0);
+  // TODO(khushalsagar): Temp CHECK to diagnose crbug.com/802976.
+  CHECK_GT(entry->ref_count, 0);
   if (--entry->ref_count == 0) {
     if (entry->is_budgeted)
       RemoveBudgetForImage(key, entry);
diff --git a/cc/tiles/software_image_decode_cache_utils.h b/cc/tiles/software_image_decode_cache_utils.h
index 875a889..663af1f8 100644
--- a/cc/tiles/software_image_decode_cache_utils.h
+++ b/cc/tiles/software_image_decode_cache_utils.h
@@ -122,7 +122,8 @@
     sk_sp<SkImage> image() const {
       if (!memory)
         return nullptr;
-      DCHECK(is_locked);
+      // TODO(khushalsagar): Temp CHECK to diagnose crbug.com/802976.
+      CHECK(is_locked);
       return image_;
     }
     const SkSize& src_rect_offset() const { return src_rect_offset_; }
diff --git a/cc/trees/layer_tree_frame_sink.h b/cc/trees/layer_tree_frame_sink.h
index c0971b5..f61c7a6c 100644
--- a/cc/trees/layer_tree_frame_sink.h
+++ b/cc/trees/layer_tree_frame_sink.h
@@ -35,6 +35,7 @@
 
 namespace cc {
 class LayerTreeFrameSinkClient;
+class LayerTreeHostImpl;
 
 // An interface for submitting CompositorFrames to a display compositor
 // which will compose frames from multiple clients to show on screen to the
@@ -114,6 +115,10 @@
     return shared_bitmap_manager_;
   }
 
+  // Generate hit test region list based on LayerTreeHostImpl, the data will be
+  // submitted with compositor frame.
+  virtual void UpdateHitTestData(const LayerTreeHostImpl* host_impl) {}
+
   // If supported, this sets the viz::LocalSurfaceId the LayerTreeFrameSink will
   // use to submit a CompositorFrame.
   virtual void SetLocalSurfaceId(const viz::LocalSurfaceId& local_surface_id) {}
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 2922dc6..b09d0f70 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -78,6 +78,7 @@
 #include "cc/trees/single_thread_proxy.h"
 #include "cc/trees/transform_node.h"
 #include "cc/trees/tree_synchronizer.h"
+#include "components/viz/common/features.h"
 #include "components/viz/common/frame_sinks/copy_output_request.h"
 #include "components/viz/common/frame_sinks/delay_based_time_source.h"
 #include "components/viz/common/gpu/texture_allocation.h"
@@ -2826,6 +2827,8 @@
         ResourcePool::kDefaultExpirationDelay, ResourcePool::Mode::kGpu,
         settings_.disallow_non_exact_resource_reuse);
   }
+  if (features::IsVizHitTestingSurfaceLayerEnabled())
+    layer_tree_frame_sink_->UpdateHitTestData(this);
 
   // Since the new context may be capable of MSAA, update status here. We don't
   // need to check the return value since we are recreating all resources
@@ -3869,6 +3872,9 @@
     UpdateRootLayerStateForSynchronousInputHandler();
   }
 
+  scroll_result.current_offset = ScrollOffsetToVector2dF(
+      scroll_tree.current_scroll_offset(scroll_node->element_id));
+
   // Run animations which need to respond to updated scroll offset.
   mutator_host_->TickScrollAnimations(
       CurrentBeginFrameArgs().frame_time,
@@ -3906,11 +3912,12 @@
   gfx::ScrollOffset current_position =
       scroll_tree.current_scroll_offset(scroll_node->element_id);
 
-  gfx::ScrollOffset snap_position =
-      data.FindSnapPosition(current_position, did_scroll_x_for_scroll_gesture_,
-                            did_scroll_y_for_scroll_gesture_);
-  if (snap_position == current_position)
+  gfx::ScrollOffset snap_position;
+  if (!data.FindSnapPosition(current_position, did_scroll_x_for_scroll_gesture_,
+                             did_scroll_y_for_scroll_gesture_,
+                             &snap_position)) {
     return false;
+  }
 
   ScrollAnimationCreate(
       scroll_node, ScrollOffsetToVector2dF(snap_position - current_position),
@@ -3918,6 +3925,33 @@
   return true;
 }
 
+bool LayerTreeHostImpl::GetSnapFlingInfo(
+    const gfx::Vector2dF& natural_displacement,
+    gfx::Vector2dF* initial_offset,
+    gfx::Vector2dF* target_offset) const {
+  const ScrollNode* scroll_node = CurrentlyScrollingNode();
+  if (!scroll_node || !scroll_node->snap_container_data.has_value())
+    return false;
+
+  const SnapContainerData& data = scroll_node->snap_container_data.value();
+  const ScrollTree& scroll_tree = active_tree()->property_trees()->scroll_tree;
+  *initial_offset = ScrollOffsetToVector2dF(
+      scroll_tree.current_scroll_offset(scroll_node->element_id));
+  bool did_scroll_x =
+      did_scroll_x_for_scroll_gesture_ || natural_displacement.x() != 0;
+  bool did_scroll_y =
+      did_scroll_y_for_scroll_gesture_ || natural_displacement.y() != 0;
+  gfx::ScrollOffset snap_offset;
+  if (!data.FindSnapPosition(
+          gfx::ScrollOffset(*initial_offset + natural_displacement),
+          did_scroll_x, did_scroll_y, &snap_offset)) {
+    return false;
+  }
+
+  *target_offset = ScrollOffsetToVector2dF(snap_offset);
+  return true;
+}
+
 void LayerTreeHostImpl::ClearCurrentlyScrollingNode() {
   active_tree_->ClearCurrentlyScrollingNode();
   did_lock_scrolling_layer_ = false;
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index a5f0fe3..9280879 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -596,6 +596,10 @@
 
   virtual bool IsUIResourceOpaque(UIResourceId uid) const;
 
+  bool GetSnapFlingInfo(const gfx::Vector2dF& natural_displacement,
+                        gfx::Vector2dF* initial_offset,
+                        gfx::Vector2dF* target_offset) const override;
+
   // Returns the amount of delta that can be applied to scroll_node, taking
   // page scale into account.
   gfx::Vector2dF ComputeScrollDelta(const ScrollNode& scroll_node,
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index 52fcfd3a..fa670fe 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -577,6 +577,14 @@
   return layer_list_.cend();
 }
 
+LayerImplList::const_reverse_iterator LayerTreeImpl::rbegin() const {
+  return layer_list_.crbegin();
+}
+
+LayerImplList::const_reverse_iterator LayerTreeImpl::rend() const {
+  return layer_list_.crend();
+}
+
 LayerImplList::reverse_iterator LayerTreeImpl::rbegin() {
   return layer_list_.rbegin();
 }
@@ -1364,6 +1372,10 @@
   return host_impl_->task_runner_provider();
 }
 
+LayerTreeFrameSink* LayerTreeImpl::layer_tree_frame_sink() {
+  return host_impl_->layer_tree_frame_sink();
+}
+
 const LayerTreeSettings& LayerTreeImpl::settings() const {
   return host_impl_->settings();
 }
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h
index cc0360d..3815722 100644
--- a/cc/trees/layer_tree_impl.h
+++ b/cc/trees/layer_tree_impl.h
@@ -44,6 +44,7 @@
 class ImageDecodeCache;
 class LayerTreeDebugState;
 class LayerTreeImpl;
+class LayerTreeFrameSink;
 class LayerTreeResourceProvider;
 class LayerTreeSettings;
 class MemoryHistory;
@@ -105,6 +106,7 @@
 
   // Methods called by the layer tree that pass-through or access LTHI.
   // ---------------------------------------------------------------------------
+  LayerTreeFrameSink* layer_tree_frame_sink();
   const LayerTreeSettings& settings() const;
   const LayerTreeDebugState& debug_state() const;
   viz::ContextProvider* context_provider() const;
@@ -186,6 +188,8 @@
 
   LayerImplList::const_iterator begin() const;
   LayerImplList::const_iterator end() const;
+  LayerImplList::const_reverse_iterator rbegin() const;
+  LayerImplList::const_reverse_iterator rend() const;
   LayerImplList::reverse_iterator rbegin();
   LayerImplList::reverse_iterator rend();
 
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn
index d7be7791..e0b8e12 100644
--- a/chrome/BUILD.gn
+++ b/chrome/BUILD.gn
@@ -1605,6 +1605,7 @@
 
   if (is_chromeos) {
     public_deps += [
+      "//chrome/browser/resources/chromeos:multidevice_setup_resources",
       "//chrome/browser/resources/chromeos/chromevox",
       "//chrome/browser/resources/chromeos/select_to_speak",
       "//chrome/browser/resources/chromeos/switch_access",
diff --git a/chrome/DEPS b/chrome/DEPS
index ee44536..68fab23 100644
--- a/chrome/DEPS
+++ b/chrome/DEPS
@@ -24,7 +24,7 @@
   "+components/variations",
   "+content/public/common",
   "+content/public/test",
-  "+media/media_features.h",
+  "+media/media_buildflags.h",
   "+mojo/common",
   "+mojo/public",
   "+ppapi/features",
diff --git a/chrome/VERSION b/chrome/VERSION
index 19053f6b..30173c2 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=67
 MINOR=0
-BUILD=3379
+BUILD=3380
 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index d356efc..144a692 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -635,6 +635,7 @@
       "javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java",
       "javatests/src/org/chromium/chrome/browser/media/RouterTestUtils.java",
       "javatests/src/org/chromium/chrome/browser/vr_shell/EmulatedVrController.java",
+      "javatests/src/org/chromium/chrome/browser/vr_shell/mock/MockBrowserKeyboardInterface.java",
       "javatests/src/org/chromium/chrome/browser/vr_shell/mock/MockVrCoreVersionCheckerImpl.java",
       "javatests/src/org/chromium/chrome/browser/vr_shell/mock/MockVrDaydreamApi.java",
       "javatests/src/org/chromium/chrome/browser/vr_shell/mock/MockVrIntentHandler.java",
@@ -661,6 +662,7 @@
       "javatests/src/org/chromium/chrome/browser/vr_shell/VrShellNativeUiTest.java",
       "javatests/src/org/chromium/chrome/browser/vr_shell/VrShellNavigationTest.java",
       "javatests/src/org/chromium/chrome/browser/vr_shell/VrShellTransitionTest.java",
+      "javatests/src/org/chromium/chrome/browser/vr_shell/VrShellWebInputEditingTest.java",
       "javatests/src/org/chromium/chrome/browser/vr_shell/VrTestFramework.java",
       "javatests/src/org/chromium/chrome/browser/vr_shell/WebVrDeviceTest.java",
       "javatests/src/org/chromium/chrome/browser/vr_shell/WebVrInputTest.java",
@@ -1291,6 +1293,7 @@
     "sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncTest.java",
     "sync_shell/javatests/src/org/chromium/chrome/browser/sync/SyncTestRule.java",
     "sync_shell/javatests/src/org/chromium/chrome/browser/sync/TypedUrlsTest.java",
+    "sync_shell/javatests/src/org/chromium/chrome/browser/sync/UkmTest.java",
     "sync_shell/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragmentTest.java",
   ]
 
diff --git a/chrome/android/android.ensure b/chrome/android/android.ensure
deleted file mode 100644
index dc23627..0000000
--- a/chrome/android/android.ensure
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright 2018 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.
-
-# Chromium-specific dependencies for Android target OS.
-
-# -crX indicates the chromium-specific revision of a package at a given version.
-
-@Subdir chrome/android/profiles
-chromium/afdo/profiles/android version:3309
-
-# Three unchanging lines
-# avoid the horror that is
-# endless merge conflicts
-
diff --git a/chrome/android/feed/feed_java_sources.gni b/chrome/android/feed/feed_java_sources.gni
index 35d2a44..691366e5 100644
--- a/chrome/android/feed/feed_java_sources.gni
+++ b/chrome/android/feed/feed_java_sources.gni
@@ -6,7 +6,7 @@
 
 if (enable_feed_in_chrome) {
   # TODO(twellington): Add a dependency on //components/feed when an appropriate target is defined.
-  feed_deps = [ "//third_party/feed:feed_java" ]
+  feed_deps = [ "//third_party/feed:feed_lib_java" ]
 
   feed_java_sources = [
     "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java",
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml
index 01c7b889..ce79b9a 100644
--- a/chrome/android/java/AndroidManifest.xml
+++ b/chrome/android/java/AndroidManifest.xml
@@ -182,6 +182,7 @@
             <!-- Matches the common case of intents with no MIME type.
                  Make sure to keep in sync with the next filter.  -->
             <intent-filter>
+                {% block common_view_intent_shared_filter_body %}
                 <action android:name="android.intent.action.VIEW" />
                 <category android:name="android.intent.category.DEFAULT" />
                 <category android:name="android.intent.category.BROWSABLE" />
@@ -190,22 +191,17 @@
                 <data android:scheme="https" />
                 <data android:scheme="about" />
                 <data android:scheme="javascript" />
+                {% endblock %}
             </intent-filter>
             <!-- Same filter as above but with MIME types.  Intents that
                  do not specify a MIME type won't match. -->
             <intent-filter>
-                <action android:name="android.intent.action.VIEW" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.BROWSABLE" />
-                {% if channel in ['stable', 'default'] %}<data android:scheme="googlechrome" />{% endif %}
-                <data android:scheme="http" />
-                <data android:scheme="https" />
-                <data android:scheme="about" />
-                <data android:scheme="content" />
-                <data android:scheme="javascript" />
+                {% block common_view_intent_shared_filter_with_mime_body %}
+                {{ self.common_view_intent_shared_filter_body() }}
                 <data android:mimeType="text/html"/>
                 <data android:mimeType="text/plain"/>
                 <data android:mimeType="application/xhtml+xml"/>
+                {% endblock %}
             </intent-filter>
             <!-- MHTML support, used for snapshots -->
             <intent-filter>
@@ -223,6 +219,7 @@
                 <data android:mimeType="message/rfc822"/>
             </intent-filter>
             <intent-filter>
+                {% block mhtml_view_intent_shared_filter_body %}
                 <action android:name="android.intent.action.VIEW" />
                 <category android:name="android.intent.category.DEFAULT" />
                 <category android:name="android.intent.category.BROWSABLE" />
@@ -231,19 +228,15 @@
                 <data android:host="*" />
                 <data android:pathPattern="/.*\\.mhtml"/>
                 <data android:pathPattern="/.*\\.mht"/>
+                {% endblock %}
             </intent-filter>
             <!-- Same filter as above but with mimeType="*/*". Used for
                  handling intent send by ShareIt. -->
             <intent-filter>
-                <action android:name="android.intent.action.VIEW" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.BROWSABLE" />
-                <data android:scheme="file"/>
-                <data android:scheme="content"/>
-                <data android:host="*" />
+                {% block mhtml_view_intent_shared_filter_with_mime_body %}
+                {{ self.mhtml_view_intent_shared_filter_body() }}
                 <data android:mimeType="*/*"/>
-                <data android:pathPattern="/.*\\.mhtml"/>
-                <data android:pathPattern="/.*\\.mht"/>
+                {% endblock %}
             </intent-filter>
             <intent-filter>
                 <action android:name="android.intent.action.MEDIA_SEARCH" />
@@ -267,8 +260,6 @@
             </intent-filter>
             <meta-data android:name="android.app.searchable"
                 android:resource="@xml/searchable" />
-
-            {{ self.supports_vr() }}
         </activity-alias>
 
         <activity android:name="org.chromium.chrome.browser.LauncherShortcutActivity"
@@ -358,10 +349,12 @@
         </activity>
         {% endfor %}
         {% if enable_vr == "true" %}
+        <!-- Needs to be exported for Daydream deep-links. Also note that we explicitly don't set
+             VR mode here as it actually doesn't matter for VR launches given that we set it
+             within the timeout in onCreate, and it makes launches from 2D much smoother. -->
         <activity android:name="org.chromium.chrome.browser.vr.VrMainActivity"
             android:theme="@style/VrSupportThemeLauncher"
             android:exported="true"
-            android:enableVrMode="@string/gvr_vr_mode_component"
             android:taskAffinity=""
             android:relinquishTaskIdentity="true"
             android:excludeFromRecents="true"
@@ -376,8 +369,11 @@
                 android:resource="@drawable/daydream_icon_background" />
             {{ self.supports_vr() }}
         </activity>
-        <!-- This alias allows us to dynamically toggle whether the Chrome icon shows up in Daydream
-             home. It defaults to enabled, but can be turned off via a feature flag. -->
+
+        <!-- The VrIntentDispatcher handles many of the same intents as the non-vr
+             IntentDispatcher, and should be kept in sync where applicable. Intents that should
+             not be handled in VR include all intents that don't launch ChromeTabbedActivity.
+             Custom Tabs are a complicated special case, which are kind of supported. -->
         <activity-alias android:name="com.google.android.apps.chrome.VrIntentDispatcher"
             android:targetActivity="org.chromium.chrome.browser.vr.VrMainActivity"
             android:enabled="true"
@@ -386,11 +382,35 @@
                 android:resource="@drawable/daydream_icon_foreground" />
             <meta-data android:name="com.google.android.vr.icon_background"
                 android:resource="@drawable/daydream_icon_background" />
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
+
+            <!-- The Intent filters must all have lower priority than the non-VR intent filters
+                 so that intents without the Daydream flag aren't erroneously routed to the
+                 VrIntentDispatcher. -->
+            <intent-filter android:priority="-1">
                 <!-- Show icon in Daydream app launcher. -->
+                <action android:name="android.intent.action.MAIN" />
                 <category android:name="com.google.intent.category.DAYDREAM" />
             </intent-filter>
+
+            <!-- Intent filters below are copied from IntentDispatcher, but with the added
+                 Daydream flag. -->
+
+            <intent-filter android:priority="-1">
+                <category android:name="com.google.intent.category.DAYDREAM" />
+                {{ self.common_view_intent_shared_filter_body() }}
+            </intent-filter>
+            <intent-filter android:priority="-1">
+                <category android:name="com.google.intent.category.DAYDREAM" />
+                {{ self.common_view_intent_shared_filter_with_mime_body() }}
+            </intent-filter>
+            <intent-filter android:priority="-1">
+                <category android:name="com.google.intent.category.DAYDREAM" />
+                {{ self.mhtml_view_intent_shared_filter_body() }}
+            </intent-filter>
+            <intent-filter android:priority="-1">
+                <category android:name="com.google.intent.category.DAYDREAM" />
+                {{ self.mhtml_view_intent_shared_filter_with_mime_body() }}
+            </intent-filter>
         </activity-alias>
         <activity android:name="org.chromium.chrome.browser.vr.CustomTabVrActivity"
             android:theme="@style/VrSupportTheme"
diff --git a/chrome/android/java/res/drawable/ic_assistant_16dp.xml b/chrome/android/java/res/drawable/ic_assistant_16dp.xml
new file mode 100644
index 0000000..8c84c51
--- /dev/null
+++ b/chrome/android/java/res/drawable/ic_assistant_16dp.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2018 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. -->
+<vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:width="16dp"
+    android:height="16dp"
+    android:viewportHeight="24"
+    android:viewportWidth="24"
+    tools:targetApi="21">
+
+    <path android:fillColor="#366AD3"
+          android:pathData="M19 2H5c-1.1 0-2 0.9-2 2v14c0 1.1 0.9 2 2 2h4l3 3 3-3h4c1.1 0 2-0.9 2-2V4c0-1.1-0.9-2-2-2z"/>
+    <path android:fillColor="#FFFFFF"
+          android:pathData="M12 17l-1.88-4.12L6 11l4.12-1.88L12 5l1.88 4.12L18 11l-4.12 1.88z"/>
+</vector>
diff --git a/chrome/android/java/res/drawable/ic_logo_googleg_16dp.xml b/chrome/android/java/res/drawable/ic_logo_googleg_16dp.xml
new file mode 100644
index 0000000..6d6c9e9
--- /dev/null
+++ b/chrome/android/java/res/drawable/ic_logo_googleg_16dp.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2018 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. -->
+<vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:width="16dp"
+    android:height="16dp"
+    android:viewportHeight="24"
+    android:viewportWidth="24"
+    tools:targetApi="21">
+
+    <path android:fillColor="#4285F4"
+          android:pathData="M22.56,12.25c0,-0.78 -0.07,-1.53 -0.2,-2.25H12v4.26h5.92c-0.26,1.37 -1.04,2.53 -2.21,3.31v2.77h3.57c2.08,-1.92 3.28,-4.74 3.28,-8.09z"/>
+    <path android:fillColor="#34A853"
+          android:pathData="M12,23c2.97,0 5.46,-0.98 7.28,-2.66l-3.57,-2.77c-0.98,0.66 -2.23,1.06 -3.71,1.06 -2.86,0 -5.29,-1.93 -6.16,-4.53H2.18v2.84C3.99,20.53 7.7,23 12,23z"/>
+    <path android:fillColor="#FBBC05"
+          android:pathData="M5.84,14.09c-0.22,-0.66 -0.35,-1.36 -0.35,-2.09s0.13,-1.43 0.35,-2.09V7.07H2.18C1.43,8.55 1,10.22 1,12s0.43,3.45 1.18,4.93l2.85,-2.22 0.81,-0.62z"/>
+    <path android:fillColor="#EA4335"
+          android:pathData="M12,5.38c1.62,0 3.06,0.56 4.21,1.64l3.15,-3.15C17.45,2.09 14.97,1 12,1 7.7,1 3.99,3.47 2.18,7.07l3.66,2.84c0.87,-2.6 3.3,-4.53 6.16,-4.53z"/>
+</vector>
diff --git a/chrome/android/java/res/drawable/ic_settings_grey_16dp.xml b/chrome/android/java/res/drawable/ic_settings_grey_16dp.xml
new file mode 100644
index 0000000..5a0ebec
--- /dev/null
+++ b/chrome/android/java/res/drawable/ic_settings_grey_16dp.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2018 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. -->
+<vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:width="16dp"
+    android:height="16dp"
+    android:viewportHeight="20"
+    android:viewportWidth="20"
+    tools:targetApi="21">
+
+    <path android:fillColor="@color/google_grey_600"
+          android:pathData="M15.95,10.78c0.03,-0.25 0.05,-0.51 0.05,-0.78s-0.02,-0.53 -0.06,-0.78l1.69,-1.32c0.15,-0.12 0.19,-0.34 0.1,-0.51l-1.6,-2.77c-0.1,-0.18 -0.31,-0.24 -0.49,-0.18l-1.99,0.8c-0.42,-0.32 -0.86,-0.58 -1.35,-0.78L12,2.34c-0.03,-0.2 -0.2,-0.34 -0.4,-0.34H8.4c-0.2,0 -0.36,0.14 -0.39,0.34l-0.3,2.12c-0.49,0.2 -0.94,0.47 -1.35,0.78l-1.99,-0.8c-0.18,-0.07 -0.39,0 -0.49,0.18l-1.6,2.77c-0.1,0.18 -0.06,0.39 0.1,0.51l1.69,1.32c-0.04,0.25 -0.07,0.52 -0.07,0.78s0.02,0.53 0.06,0.78L2.37,12.1c-0.15,0.12 -0.19,0.34 -0.1,0.51l1.6,2.77c0.1,0.18 0.31,0.24 0.49,0.18l1.99,-0.8c0.42,0.32 0.86,0.58 1.35,0.78l0.3,2.12c0.04,0.2 0.2,0.34 0.4,0.34h3.2c0.2,0 0.37,-0.14 0.39,-0.34l0.3,-2.12c0.49,-0.2 0.94,-0.47 1.35,-0.78l1.99,0.8c0.18,0.07 0.39,0 0.49,-0.18l1.6,-2.77c0.1,-0.18 0.06,-0.39 -0.1,-0.51l-1.67,-1.32zM10,13c-1.65,0 -3,-1.35 -3,-3s1.35,-3 3,-3 3,1.35 3,3 -1.35,3 -3,3z"/>
+</vector>
diff --git a/chrome/android/java/res/drawable/ic_sync_circle_green_16dp.xml b/chrome/android/java/res/drawable/ic_sync_circle_green_16dp.xml
new file mode 100644
index 0000000..3b3199e
--- /dev/null
+++ b/chrome/android/java/res/drawable/ic_sync_circle_green_16dp.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2018 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. -->
+<vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:width="16dp"
+    android:height="16dp"
+    android:viewportWidth="16"
+    android:viewportHeight="16"
+    tools:targetApi="21">
+
+    <path android:fillColor="#0B8043"
+          android:pathData="M8,8m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0"/>
+    <path android:fillColor="#FFFFFF"
+          android:pathData="M8,11C6.345,11 5,9.655 5,8C5,7.495 5.125,7.015 5.35,6.6L4.62,5.87C4.23,6.485 4,7.215 4,8C4,10.21 5.79,12 8,12L8,13.5L10,11.5L8,9.5L8,11ZM8,4L8,2.5L6,4.5L8,6.5L8,5C9.655,5 11,6.345 11,8C11,8.505 10.875,8.985 10.65,9.4L11.38,10.13C11.77,9.515 12,8.785 12,8C12,5.79 10.21,4 8,4L8,4Z"/>
+</vector>
diff --git a/chrome/android/java/res/layout/chrome_home_iph_header.xml b/chrome/android/java/res/layout/chrome_home_iph_header.xml
deleted file mode 100644
index 226118b9..0000000
--- a/chrome/android/java/res/layout/chrome_home_iph_header.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-
-<org.chromium.chrome.browser.widget.bottomsheet.ChromeHomeIphMenuHeader
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    style="@style/OverflowMenuHeaderLayout"
-    android:id="@+id/chrome_home_iph_menu_header" >
-
-    <TextView
-        style="@style/OverflowMenuHeaderText"
-        android:text="@string/bottom_sheet_app_menu_iph" />
-
-    <include layout="@layout/chrome_home_menu_header_icon" />
-
-</org.chromium.chrome.browser.widget.bottomsheet.ChromeHomeIphMenuHeader>
diff --git a/chrome/android/java/res/layout/chrome_home_menu_header_icon.xml b/chrome/android/java/res/layout/chrome_home_menu_header_icon.xml
deleted file mode 100644
index b5253a9..0000000
--- a/chrome/android/java/res/layout/chrome_home_menu_header_icon.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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. -->
-
-<merge
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto">
-
-    <FrameLayout
-        android:layout_width="40dp"
-        android:layout_height="40dp"
-        android:layout_gravity="center_vertical" >
-
-        <org.chromium.chrome.browser.widget.TintedImageView
-            android:layout_width="18dp"
-            android:layout_height="18dp"
-            android:layout_gravity="center_vertical|center_horizontal"
-            android:scaleType="centerInside"
-            android:src="@drawable/ic_help_white_24dp"
-            chrome:chrometint="@color/black_alpha_38" />
-
-    </FrameLayout>
-
-</merge>
diff --git a/chrome/android/java/res/layout/contextual_suggestions_layout.xml b/chrome/android/java/res/layout/contextual_suggestions_layout.xml
index 0839813..1d5c540 100644
--- a/chrome/android/java/res/layout/contextual_suggestions_layout.xml
+++ b/chrome/android/java/res/layout/contextual_suggestions_layout.xml
@@ -8,4 +8,5 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:scrollbars="vertical"
-    android:paddingTop="@dimen/bottom_control_container_height" />
\ No newline at end of file
+    android:paddingTop="@dimen/contextual_suggestions_expanded_toolbar_height"
+    android:background="@android:color/white" />
\ No newline at end of file
diff --git a/chrome/android/java/res/layout/contextual_suggestions_toolbar.xml b/chrome/android/java/res/layout/contextual_suggestions_toolbar.xml
new file mode 100644
index 0000000..8a12e6ae
--- /dev/null
+++ b/chrome/android/java/res/layout/contextual_suggestions_toolbar.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2018 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. -->
+
+<org.chromium.chrome.browser.contextual_suggestions.ToolbarView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="horizontal"
+    android:gravity="center_vertical"
+    android:background="@android:color/white" >
+
+    <!-- Use 48dp width and 16dp end/start padding to produce a 16dp, centered icon. -->
+    <ImageView
+        android:layout_height="match_parent"
+        android:layout_width="48dp"
+        android:src="@drawable/ic_logo_googleg_24dp"
+        android:scaleType="centerInside"
+        android:paddingStart="16dp"
+        android:paddingEnd="16dp"
+        android:contentDescription="@null" />
+
+     <TextView
+         android:id="@+id/title"
+         android:layout_height="wrap_content"
+         android:layout_width="0dp"
+         android:layout_weight="1"
+         android:gravity="center"
+         android:singleLine="true"
+         android:ellipsize="end"
+         android:textAppearance="@style/BlackBodyDefault" />
+
+    <!-- Use 50dp width and 16dp end/start padding to produce an 18dp, centered icon. -->
+    <ImageView
+        android:id="@+id/close_button"
+        android:layout_height="match_parent"
+        android:layout_width="50dp"
+        android:src="@drawable/btn_close"
+        android:scaleType="centerInside"
+        android:paddingStart="16dp"
+        android:paddingEnd="16dp"
+        android:contentDescription="@string/close" />
+
+</org.chromium.chrome.browser.contextual_suggestions.ToolbarView>
\ No newline at end of file
diff --git a/chrome/android/java/res/layout/signin_view.xml b/chrome/android/java/res/layout/signin_view.xml
index 1c3ced8..7341c2b 100644
--- a/chrome/android/java/res/layout/signin_view.xml
+++ b/chrome/android/java/res/layout/signin_view.xml
@@ -13,8 +13,8 @@
         android:id="@+id/signin_scroll_view"
         android:layout_width="match_parent"
         android:layout_height="0dp"
-        android:fadingEdgeLength="48dp"
         android:layout_weight="1"
+        android:fadingEdgeLength="48dp"
         android:requiresFadingEdge="vertical"
         android:scrollbars="none">
         <RelativeLayout
@@ -25,17 +25,17 @@
                 android:id="@+id/signin_header_image"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
+                android:layout_alignParentTop="true"
                 android:adjustViewBounds="true"
                 android:contentDescription="@null"
-                android:layout_alignParentTop="true"
                 android:scaleType="fitCenter"/>
             <TextView
                 android:id="@+id/signin_title"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginStart="@dimen/signin_margin_start"
-                android:layout_marginEnd="@dimen/signin_margin_end"
                 android:layout_below="@id/signin_header_image"
+                android:layout_marginEnd="@dimen/signin_margin_end"
+                android:layout_marginStart="@dimen/signin_margin_start"
                 android:layout_marginTop="26dp"
                 android:textAppearance="@style/BlackHeadline1"
                 tools:text="@string/signin_title"/>
@@ -43,11 +43,11 @@
                 android:id="@+id/signin_account_picker"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:layout_marginStart="@dimen/signin_margin_start"
-                android:layout_marginEnd="@dimen/signin_margin_end"
-                android:background="@drawable/account_picker_background"
                 android:layout_below="@id/signin_title"
+                android:layout_marginEnd="@dimen/signin_margin_end"
+                android:layout_marginStart="@dimen/signin_margin_start"
                 android:layout_marginTop="26dp"
+                android:background="@drawable/account_picker_background"
                 android:orientation="horizontal"
                 android:paddingBottom="12dp"
                 android:paddingEnd="12dp"
@@ -57,41 +57,137 @@
                     android:id="@+id/account_image"
                     android:layout_width="40dp"
                     android:layout_height="40dp"
+                    android:layout_alignParentStart="true"
                     android:layout_marginEnd="16dp"
                     android:contentDescription="@null"
-                    android:layout_alignParentStart="true"
-                    chrome:srcCompat="@drawable/logo_avatar_anonymous"/>
+                    tools:src="@drawable/logo_avatar_anonymous"/>
                 <TextView
                     android:id="@+id/account_name"
                     android:layout_width="match_parent"
                     android:layout_height="20dp"
-                    android:gravity="center_vertical"
                     android:layout_toEndOf="@id/account_image"
                     android:layout_toStartOf="@id/expand_icon"
+                    android:gravity="center_vertical"
                     android:textAppearance="@style/BlackBodyDefault"
                     tools:text="John Doe"/>
                 <TextView
                     android:id="@+id/account_email"
                     android:layout_width="match_parent"
                     android:layout_height="20dp"
-                    android:gravity="center_vertical"
                     android:layout_below="@id/account_name"
                     android:layout_toEndOf="@id/account_image"
                     android:layout_toStartOf="@id/expand_icon"
+                    android:gravity="center_vertical"
                     android:textAppearance="@style/BlackCaption"
                     tools:text="john.doe@example.com"/>
                 <ImageView
                     android:id="@+id/expand_icon"
                     android:layout_width="24dp"
                     android:layout_height="24dp"
+                    android:layout_alignParentEnd="true"
+                    android:layout_centerVertical="true"
                     android:layout_marginStart="16dp"
                     android:alpha="0.54"
                     android:contentDescription="@null"
-                    android:layout_alignParentEnd="true"
-                    android:layout_centerVertical="true"
                     android:src="@drawable/ic_expand_more_black_24dp"/>
             </RelativeLayout>
-            <!-- TODO(https://crbug.com/819142): Add the rest of the layout. -->
+            <ImageView
+                android:id="@+id/signin_sync_icon"
+                android:layout_width="16dp"
+                android:layout_height="16dp"
+                android:layout_alignBottom="@+id/signin_sync_description"
+                android:layout_alignParentStart="true"
+                android:layout_alignTop="@+id/signin_sync_description"
+                android:layout_centerVertical="true"
+                android:layout_marginStart="@dimen/signin_margin_start"
+                android:contentDescription="@null"
+                chrome:srcCompat="@drawable/ic_sync_circle_green_16dp"/>
+            <TextView
+                android:id="@+id/signin_sync_description"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_alignParentEnd="true"
+                android:layout_below="@id/signin_account_picker"
+                android:layout_marginEnd="@dimen/signin_margin_end"
+                android:layout_marginStart="@dimen/signin_drawable_padding"
+                android:layout_marginTop="@dimen/signin_description_blocks_margin"
+                android:layout_toEndOf="@id/signin_sync_icon"
+                android:textAppearance="@style/BlackHint2"
+                tools:text="@string/signin_sync_description"/>
+            <ImageView
+                android:id="@+id/signin_personalization_icon"
+                android:layout_width="16dp"
+                android:layout_height="16dp"
+                android:layout_alignBottom="@+id/signin_personalization_description"
+                android:layout_alignParentStart="true"
+                android:layout_alignTop="@+id/signin_personalization_description"
+                android:layout_centerVertical="true"
+                android:layout_marginStart="@dimen/signin_margin_start"
+                android:contentDescription="@null"
+                chrome:srcCompat="@drawable/ic_assistant_16dp"/>
+            <TextView
+                android:id="@+id/signin_personalization_description"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_alignParentEnd="true"
+                android:layout_below="@id/signin_sync_description"
+                android:layout_marginEnd="@dimen/signin_margin_end"
+                android:layout_marginStart="@dimen/signin_drawable_padding"
+                android:layout_marginTop="@dimen/signin_description_blocks_margin"
+                android:layout_toEndOf="@id/signin_sync_icon"
+                android:textAppearance="@style/BlackHint2"
+                tools:text="@string/signin_personalization_description"/>
+            <ImageView
+                android:id="@+id/signin_google_services_icon"
+                android:layout_width="16dp"
+                android:layout_height="16dp"
+                android:layout_alignBottom="@+id/signin_google_services_description"
+                android:layout_alignParentStart="true"
+                android:layout_alignTop="@+id/signin_google_services_description"
+                android:layout_centerVertical="true"
+                android:layout_marginStart="@dimen/signin_margin_start"
+                android:contentDescription="@null"
+                chrome:srcCompat="@drawable/ic_logo_googleg_16dp"/>
+            <TextView
+                android:id="@+id/signin_google_services_description"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/signin_personalization_description"
+                android:layout_marginEnd="@dimen/signin_margin_end"
+                android:layout_marginStart="@dimen/signin_drawable_padding"
+                android:layout_marginTop="@dimen/signin_description_blocks_margin"
+                android:layout_toEndOf="@id/signin_google_services_icon"
+                android:textAppearance="@style/BlackHint2"
+                tools:text="@string/signin_google_services_description"/>
+            <View
+                android:id="@+id/signin_divider"
+                style="@style/Divider"
+                android:layout_below="@id/signin_google_services_description"
+                android:layout_marginBottom="22dp"
+                android:layout_marginEnd="@dimen/signin_margin_end"
+                android:layout_marginStart="@dimen/signin_divider_margin_start"
+                android:layout_marginTop="32dp"/>
+            <ImageView
+                android:id="@+id/signin_details_icon"
+                android:layout_width="16dp"
+                android:layout_height="16dp"
+                android:layout_alignBaseline="@+id/signin_details_description"
+                android:layout_alignParentStart="true"
+                android:layout_marginStart="@dimen/signin_margin_start"
+                android:baseline="12dp"
+                android:contentDescription="@null"
+                chrome:srcCompat="@drawable/ic_settings_grey_16dp"/>
+            <TextView
+                android:id="@+id/signin_details_description"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/signin_divider"
+                android:layout_marginEnd="@dimen/signin_margin_end"
+                android:layout_marginStart="@dimen/signin_drawable_padding"
+                android:layout_marginTop="@dimen/signin_description_blocks_margin"
+                android:layout_toEndOf="@id/signin_details_icon"
+                android:textAppearance="@style/BlackHint2"
+                tools:text="@string/signin_details_description"/>
         </RelativeLayout>
     </org.chromium.chrome.browser.signin.SigninScrollView>
     <LinearLayout
diff --git a/chrome/android/java/res/values-v17/styles.xml b/chrome/android/java/res/values-v17/styles.xml
index 3d56b52..06f4d2b 100644
--- a/chrome/android/java/res/values-v17/styles.xml
+++ b/chrome/android/java/res/values-v17/styles.xml
@@ -310,28 +310,6 @@
             @drawable/distilled_page_prefs_button_bg
         </item>
     </style>
-    <style name="OverflowMenuHeaderLayout">
-        <item name="android:layout_width">match_parent</item>
-        <item name="android:layout_height">wrap_content</item>
-        <item name="android:background">@color/modern_light_grey</item>
-        <item name="android:orientation">horizontal</item>
-        <item name="android:paddingStart">16dp</item>
-    </style>
-        <!-- Top and bottom padding is used to achieve layout that best matches
-         UX spec. While the text matches @style/BlankHint2, text size and color
-         are set explicitly. When shown in the overflow menu, the header
-         is inflated using the OverflowMenuTheme. The theme's textAppearance
-         will override any textAppearance set on this element. -->
-    <style name="OverflowMenuHeaderText">
-        <item name="android:layout_weight">1</item>
-        <item name="android:layout_width">0dp</item>
-        <item name="android:layout_height">wrap_content</item>
-        <item name="android:layout_gravity">center_vertical</item>
-        <item name="android:paddingTop">9dp</item>
-        <item name="android:paddingBottom">9dp</item>
-        <item name="android:textColor">@color/black_alpha_54</item>
-        <item name="android:textSize">@dimen/text_size_medium</item>
-    </style>
 
     <!-- Button bar styles -->
     <style name="ButtonBarTopSpacerLight">
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml
index febfcc5..1077572 100644
--- a/chrome/android/java/res/values/dimens.xml
+++ b/chrome/android/java/res/values/dimens.xml
@@ -179,6 +179,9 @@
 
     <dimen name="signin_margin_start">16dp</dimen>
     <dimen name="signin_margin_end">16dp</dimen>
+    <dimen name="signin_divider_margin_start">48dp</dimen>
+    <dimen name="signin_drawable_padding">16dp</dimen>
+    <dimen name="signin_description_blocks_margin">16dp</dimen>
 
     <!-- Signin promo dimensions -->
     <dimen name="signin_promo_account_image_size">48dp</dimen>
@@ -204,7 +207,7 @@
     <!-- Full Screen Dimensions -->
     <!-- Should match toolbar_height_no_shadow -->
     <dimen name="control_container_height">56dp</dimen>
-    <dimen name="bottom_control_container_height">56dp</dimen>
+    <dimen name="bottom_control_container_height">40dp</dimen>
     <dimen name="custom_tabs_control_container_height">56dp</dimen>
     <dimen name="fullscreen_activity_control_container_height">0dp</dimen>
 
@@ -546,4 +549,7 @@
     <item type="dimen" name="dialog_fixed_width_minor">100%</item>
     <item type="dimen" name="dialog_fixed_height_major">100%</item>
     <item type="dimen" name="dialog_fixed_height_minor">100%</item>
+
+    <!-- Contextual suggestions dimensions -->
+    <dimen name="contextual_suggestions_expanded_toolbar_height">56dp</dimen>
 </resources>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
index a9d3207..8eee0b9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -1726,10 +1726,7 @@
     }
 
     private static boolean isInVrUiMode(int uiMode) {
-        // TODO(mthiesse): Use Configuration.UI_MODE_TYPE_VR_HEADSET when building against the O
-        // sdk.
-        final int uiModeTypeVrHeadset = 0x07;
-        return (uiMode & Configuration.UI_MODE_TYPE_MASK) == uiModeTypeVrHeadset;
+        return (uiMode & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_VR_HEADSET;
     }
 
     /**
@@ -2297,4 +2294,15 @@
         if (VrShellDelegate.isInVr() && !VrIntentUtils.isVrIntent(intent)) return false;
         return super.startActivityIfNeeded(intent, requestCode, options);
     }
+
+    /**
+     * If the density of the device changes while Chrome is in the background (not resumed), we
+     * won't have received an onConfigurationChanged yet for this new density. In this case, the
+     * density this Activity thinks it's in, and the actual display density will differ.
+     * @return The density this Activity thinks it's in (the density it was in last time it was in
+     *         the resumed state).
+     */
+    public float getLastActiveDensity() {
+        return mDensityDpi;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
index be2a3bb..4d61f6f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
@@ -230,6 +230,8 @@
     public static final String NTP_SNIPPETS_INCREASED_VISIBILITY = "NTPSnippetsIncreasedVisibility";
     public static final String OFFLINE_PAGES_DESCRIPTIVE_PENDING_STATUS =
             "OfflinePagesDescriptivePendingStatus";
+    public static final String OMNIBOX_HIDE_SCHEME_DOMAIN_IN_STEADY_STATE =
+            "OmniboxUIExperimentHideSteadyStateUrlSchemeAndSubdomains";
     public static final String OMNIBOX_SPARE_RENDERER = "OmniboxSpareRenderer";
     public static final String OMNIBOX_VOICE_SEARCH_ALWAYS_VISIBLE =
             "OmniboxVoiceSearchAlwaysVisible";
@@ -250,7 +252,6 @@
     public static final String TRUSTED_WEB_ACTIVITY = "TrustedWebActivity";
     public static final String VIDEO_PERSISTENCE = "VideoPersistence";
     public static final String UNIFIED_CONSENT = "UnifiedConsent";
-    public static final String VR_BROWSING = "VrBrowsing";
     public static final String VR_BROWSING_FEEDBACK = "VrBrowsingFeedback";
     public static final String VR_BROWSING_IN_CUSTOM_TAB = "VrBrowsingInCustomTab";
     public static final String VR_BROWSING_NATIVE_ANDROID_UI = "VrBrowsingNativeAndroidUi";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index cf09ce1..67d1582 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -130,7 +130,6 @@
 import org.chromium.chrome.browser.widget.ViewHighlighter;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet.StateChangeReason;
-import org.chromium.chrome.browser.widget.bottomsheet.ChromeHomeIphMenuHeader;
 import org.chromium.chrome.browser.widget.emptybackground.EmptyBackgroundViewWrapper;
 import org.chromium.chrome.browser.widget.textbubble.TextBubble;
 import org.chromium.components.feature_engagement.EventConstants;
@@ -1525,24 +1524,12 @@
     @Override
     protected AppMenuPropertiesDelegate createAppMenuPropertiesDelegate() {
         return new AppMenuPropertiesDelegate(this) {
-            private ChromeHomeIphMenuHeader mChromeHomeIphMenuHeader;
-
             private boolean showDataSaverFooter() {
                 return DataReductionProxySettings.getInstance()
                         .shouldUseDataReductionMainMenuItem();
             }
 
             @Override
-            public void onMenuDismissed() {
-                super.onMenuDismissed();
-
-                if (mChromeHomeIphMenuHeader != null) {
-                    mChromeHomeIphMenuHeader.onMenuDismissed();
-                    mChromeHomeIphMenuHeader = null;
-                }
-            }
-
-            @Override
             public int getFooterResourceId() {
                 return showDataSaverFooter() ? R.layout.data_reduction_main_menu_item : 0;
             }
@@ -1565,14 +1552,6 @@
                 LayoutInflater inflater = LayoutInflater.from(ChromeTabbedActivity.this);
                 Tracker tracker = TrackerFactory.getTrackerForProfile(Profile.getLastUsedProfile());
 
-                // Show the Chrome Home menu header if the Tracker allows it.
-                if (tracker.shouldTriggerHelpUI(FeatureConstants.CHROME_HOME_MENU_HEADER_FEATURE)) {
-                    mChromeHomeIphMenuHeader = (ChromeHomeIphMenuHeader) inflater.inflate(
-                            R.layout.chrome_home_iph_header, null);
-                    mChromeHomeIphMenuHeader.initialize(ChromeTabbedActivity.this);
-                    return mChromeHomeIphMenuHeader;
-                }
-
                 // Default is no header.
                 return null;
             }
@@ -1590,9 +1569,6 @@
                 if (getBottomSheet() == null) return super.shouldShowHeader(maxMenuHeight);
 
                 Tracker tracker = TrackerFactory.getTrackerForProfile(Profile.getLastUsedProfile());
-                if (tracker.wouldTriggerHelpUI(FeatureConstants.CHROME_HOME_MENU_HEADER_FEATURE)) {
-                    return true;
-                }
 
                 if (DataReductionProxySettings.getInstance().shouldUseDataReductionMainMenuItem()) {
                     return canShowDataReductionItem(maxMenuHeight);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
index f6318a5..c064d77 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
@@ -1164,4 +1164,11 @@
     public static TabLaunchType getTabLaunchType(Intent intent) {
         return IntentUtils.safeGetSerializableExtra(intent, EXTRA_TAB_LAUNCH_TYPE);
     }
+
+    /**
+     * @param intent An Intent to remove any TrustedIntent extras from.
+     */
+    public static void removeTrustedIntentExtras(Intent intent) {
+        intent.removeExtra(IntentHandler.TRUSTED_APPLICATION_CODE_EXTRA);
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkModel.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkModel.java
index efe6989..19d1702 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkModel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkModel.java
@@ -10,6 +10,7 @@
 import org.chromium.components.bookmarks.BookmarkId;
 import org.chromium.components.bookmarks.BookmarkType;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -87,25 +88,21 @@
     void deleteBookmarks(BookmarkId... bookmarks) {
         assert bookmarks != null && bookmarks.length > 0;
         // Store all titles of bookmarks.
-        String[] titles = new String[bookmarks.length];
+        List<String> titles = new ArrayList<>();
         boolean isUndoable = true;
-        for (int i = 0; i < bookmarks.length; i++) {
-            titles[i] = getBookmarkTitle(bookmarks[i]);
-            isUndoable &= (bookmarks[i].getType() == BookmarkType.NORMAL);
-        }
 
-        if (bookmarks.length == 1) {
-            deleteBookmark(bookmarks[0]);
-        } else {
-            startGroupingUndos();
-            for (BookmarkId bookmark : bookmarks) {
-                deleteBookmark(bookmark);
-            }
-            endGroupingUndos();
+        startGroupingUndos();
+        for (BookmarkId bookmarkId : bookmarks) {
+            BookmarkItem bookmarkItem = getBookmarkById(bookmarkId);
+            if (bookmarkItem == null) continue;
+            isUndoable &= (bookmarkId.getType() == BookmarkType.NORMAL);
+            titles.add(bookmarkItem.getTitle());
+            deleteBookmark(bookmarkId);
         }
+        endGroupingUndos();
 
         for (BookmarkDeleteObserver observer : mDeleteObservers) {
-            observer.onDeleteBookmarks(titles, isUndoable);
+            observer.onDeleteBookmarks(titles.toArray(new String[titles.size()]), isUndoable);
         }
     }
 
@@ -124,7 +121,9 @@
      * @see org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem#getTitle()
      */
     String getBookmarkTitle(BookmarkId bookmarkId) {
-        return getBookmarkById(bookmarkId).getTitle();
+        BookmarkItem bookmarkItem = getBookmarkById(bookmarkId);
+        if (bookmarkItem == null) return "";
+        return bookmarkItem.getTitle();
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuHelper.java
index 745a73c..d3e0442 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuHelper.java
@@ -16,6 +16,7 @@
 import android.content.res.Resources.NotFoundException;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
+import android.os.Build;
 import android.support.annotation.IntDef;
 import android.support.customtabs.browseractions.BrowserActionItem;
 import android.support.customtabs.browseractions.BrowserActionsIntent;
@@ -128,6 +129,7 @@
     private BrowserActionsTestDelegate mTestDelegate;
     private int mPendingItemId;
     private boolean mIsNativeInitialized;
+    private boolean mShouldFinishActivity;
 
     public BrowserActionsContextMenuHelper(Activity activity, ContextMenuParams params,
             List<BrowserActionItem> customItems, String sourcePackageName,
@@ -135,6 +137,8 @@
         mActivity = activity;
         mCurrentContextMenuParams = params;
         mOnMenuShownListener = listener;
+        mShouldFinishActivity = true;
+
         mOnMenuShown = new Runnable() {
             @Override
             public void run() {
@@ -147,7 +151,7 @@
         mOnMenuClosed = new Runnable() {
             @Override
             public void run() {
-                if (mPendingItemId == 0) {
+                if (mPendingItemId == 0 && mShouldFinishActivity) {
                     mActivity.finish();
                 }
             }
@@ -161,7 +165,7 @@
         mOnShareClickedRunnable = new Callback<Boolean>() {
             @Override
             public void onResult(Boolean isShareLink) {
-                mMenuItemDelegate.share(true, mCurrentContextMenuParams.getLinkUrl());
+                mMenuItemDelegate.share(true, mCurrentContextMenuParams.getLinkUrl(), false);
             }
         };
         ShareContextMenuItem shareItem = new ShareContextMenuItem(R.drawable.ic_share_white_24dp,
@@ -274,7 +278,11 @@
             mMenuItemDelegate.onSaveToClipboard(mCurrentContextMenuParams.getLinkUrl());
             notifyBrowserActionSelected(BrowserActionsIntent.ITEM_COPY);
         } else if (itemId == R.id.browser_actions_share) {
-            mMenuItemDelegate.share(false, mCurrentContextMenuParams.getLinkUrl());
+            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {
+                mShouldFinishActivity = false;
+            }
+            mMenuItemDelegate.share(
+                    false, mCurrentContextMenuParams.getLinkUrl(), !mShouldFinishActivity);
             notifyBrowserActionSelected(BrowserActionsIntent.ITEM_SHARE);
         } else if (mCustomItemActionMap.indexOfKey(itemId) >= 0) {
             mMenuItemDelegate.onCustomItemSelected(mCustomItemActionMap.get(itemId));
@@ -379,7 +387,7 @@
             dismissProgressDialog();
             onItemSelected(mPendingItemId, false);
             mPendingItemId = 0;
-            mActivity.finish();
+            if (mShouldFinishActivity) mActivity.finish();
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuItemDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuItemDelegate.java
index a8f1689b..1ed18aa 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuItemDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browseractions/BrowserActionsContextMenuItemDelegate.java
@@ -108,13 +108,16 @@
      * Called when the {@code linkUrl} should be shared.
      * @param shareDirectly Whether to share directly with the previous app shared with.
      * @param linkUrl The url to share.
+     * @param shouldCloseActivity Whether to close activity after sharing.
      */
-    public void share(Boolean shareDirectly, String linkUrl) {
+    public void share(Boolean shareDirectly, String linkUrl, boolean shouldCloseActivity) {
+        Runnable onShareDialogDismissed = shouldCloseActivity ? mActivity::finish : null;
         ShareParams params = new ShareParams.Builder(mActivity, linkUrl, linkUrl)
                                      .setShareDirectly(shareDirectly)
                                      .setSaveLastUsed(!shareDirectly)
                                      .setSourcePackageName(mSourcePackageName)
                                      .setIsExternalUrl(true)
+                                     .setOnDialogDismissed(onShareDialogDismissed)
                                      .build();
         ShareHelper.share(params);
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayoutBase.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayoutBase.java
index 3d02c6b..95b17eb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayoutBase.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayoutBase.java
@@ -324,7 +324,7 @@
      */
     protected void setTabLists(List<TabList> lists) {
         if (mStacks.size() > lists.size()) {
-            mStacks.subList(lists.size(), lists.size()).clear();
+            mStacks.subList(lists.size(), mStacks.size()).clear();
         }
         while (mStacks.size() < lists.size()) {
             Stack stack = new Stack(getContext(), this);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutTab.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutTab.java
index 7d9ea65f..4b1d0b6a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutTab.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutTab.java
@@ -266,6 +266,9 @@
      */
     public void setVisible(boolean visible) {
         mVisible = visible;
+        if (!visible) {
+            mUpdateHost.releaseResourcesForTab(mId);
+        }
         for (Observer observer : mObservers) {
             observer.onVisibilityChanged(mVisible);
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContentCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContentCoordinator.java
index 1098bc68a..face4af 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContentCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContentCoordinator.java
@@ -19,7 +19,7 @@
 
 /**
  * Coordinator for the content sub-component. Responsible for communication with the parent
- * {@link ContextualSuggestionsCoordinator} and lifecycle of component objects.
+ * {@link ContextualSuggestionsCoordinator} and lifecycle of sub-component objects.
  */
 class ContentCoordinator {
     private final ContextualSuggestionsModel mModel;
@@ -49,7 +49,7 @@
         mRecyclerView.setAdapter(adapter);
 
         mModelChangeProcessor = new RecyclerViewModelChangeProcessor<>(adapter);
-        mModel.addObserver(mModelChangeProcessor);
+        mModel.mSuggestionsList.addObserver(mModelChangeProcessor);
     }
 
     /** @return The content {@link View}. */
@@ -64,12 +64,8 @@
 
     /** Destroy the content component. */
     void destroy() {
-        if (mRecyclerView == null) return;
-
-        mRecyclerView.setAdapter(null);
-        mRecyclerView = null;
-
-        mModel.removeObserver(mModelChangeProcessor);
-        mModelChangeProcessor = null;
+        // The model outlives the content sub-component. Remove the observer so that this object
+        // can be garbage collected.
+        mModel.mSuggestionsList.removeObserver(mModelChangeProcessor);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsAdapter.java
index 7d1a5e5a..62d91cb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsAdapter.java
@@ -8,7 +8,6 @@
 import android.support.v7.widget.RecyclerView;
 import android.view.ViewGroup;
 
-import org.chromium.chrome.R;
 import org.chromium.chrome.browser.modelutil.RecyclerViewAdapter;
 import org.chromium.chrome.browser.ntp.cards.ItemViewType;
 import org.chromium.chrome.browser.ntp.cards.SuggestionsCategoryInfo;
@@ -64,7 +63,7 @@
      */
     ContextualSuggestionsAdapter(Context context, Profile profile, UiConfig uiConfig,
             SuggestionsUiDelegate uiDelegate, ContextualSuggestionsModel model) {
-        super(model);
+        super(model.mSuggestionsList);
 
         setViewBinder(new ContextualSuggestionsViewBinder());
 
@@ -72,8 +71,7 @@
         mUiConfig = uiConfig;
         mUiDelegate = uiDelegate;
 
-        mCategoryInfo = new SuggestionsCategoryInfo(KnownCategories.CONTEXTUAL,
-                context.getString(R.string.contextual_suggestions_title),
+        mCategoryInfo = new SuggestionsCategoryInfo(KnownCategories.CONTEXTUAL, "",
                 ContentSuggestionsCardLayout.FULL_CARD, ContentSuggestionsAdditionalAction.NONE,
                 false, "");
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsBottomSheetContent.java b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsBottomSheetContent.java
index 2518a34..4ee0abf 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsBottomSheetContent.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsBottomSheetContent.java
@@ -7,18 +7,24 @@
 import android.view.View;
 
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet.BottomSheetContent;
+import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet.ContentPriority;
 
 /** A {@link BottomSheetContent} that displays contextual suggestions. */
 public class ContextualSuggestionsBottomSheetContent implements BottomSheetContent {
-    private ContentCoordinator mContentCoordinator;
+    private final ContentCoordinator mContentCoordinator;
+    private final ToolbarCoordinator mToolbarCoordinator;
 
     /**
      * Construct a new {@link ContextualSuggestionsBottomSheetContent}.
      * @param contentCoordinator The {@link ContentCoordinator} that manages content to be
      *                           displayed.
+     * @param toolbarCoordinator The {@link ToolbarCoordinator} that manages the toolbar to be
+     *                           displayed.
      */
-    ContextualSuggestionsBottomSheetContent(ContentCoordinator contentCoordinator) {
+    ContextualSuggestionsBottomSheetContent(
+            ContentCoordinator contentCoordinator, ToolbarCoordinator toolbarCoordinator) {
         mContentCoordinator = contentCoordinator;
+        mToolbarCoordinator = toolbarCoordinator;
     }
 
     @Override
@@ -28,7 +34,7 @@
 
     @Override
     public View getToolbarView() {
-        return null;
+        return mToolbarCoordinator.getView();
     }
 
     @Override
@@ -37,12 +43,15 @@
     }
 
     @Override
-    public void destroy() {
-        mContentCoordinator = null;
-    }
+    public void destroy() {}
 
     @Override
     public boolean applyDefaultTopPadding() {
         return false;
     }
+
+    @Override
+    public @ContentPriority int getPriority() {
+        return ContentPriority.LOW;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsBridge.java
new file mode 100644
index 0000000..b0ccf7f
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsBridge.java
@@ -0,0 +1,106 @@
+// Copyright 2018 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.
+
+package org.chromium.chrome.browser.contextual_suggestions;
+
+import android.graphics.Bitmap;
+
+import org.chromium.base.Callback;
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.JNINamespace;
+import org.chromium.chrome.browser.ntp.snippets.KnownCategories;
+import org.chromium.chrome.browser.ntp.snippets.SnippetArticle;
+import org.chromium.chrome.browser.profiles.Profile;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Provides access to contextual suggestions.
+ */
+@JNINamespace("contextual_suggestions")
+public class ContextualSuggestionsBridge {
+    private long mNativeContextualSuggestionsBridge;
+
+    /**
+     * Creates a ContextualSuggestionsBridge for getting snippet data for the current user.
+     *
+     * @param profile Profile of the user that we will retrieve snippets for.
+     */
+    public ContextualSuggestionsBridge(Profile profile) {
+        mNativeContextualSuggestionsBridge = nativeInit(profile);
+    }
+
+    /** Destroys the brige. */
+    public void destroy() {
+        assert mNativeContextualSuggestionsBridge != 0;
+        nativeDestroy(mNativeContextualSuggestionsBridge);
+        mNativeContextualSuggestionsBridge = 0;
+    }
+
+    /** Fetches a thumbnail for the suggestion. */
+    public void fetchSuggestionImage(SnippetArticle suggestion, Callback<Bitmap> callback) {
+        assert mNativeContextualSuggestionsBridge != 0;
+        nativeFetchSuggestionImage(
+                mNativeContextualSuggestionsBridge, suggestion.mIdWithinCategory, callback);
+    }
+
+    /** Fetches a favicon for the suggestion. */
+    public void fetchSuggestionFavicon(SnippetArticle suggestion, Callback<Bitmap> callback) {
+        assert mNativeContextualSuggestionsBridge != 0;
+        nativeFetchSuggestionFavicon(
+                mNativeContextualSuggestionsBridge, suggestion.mIdWithinCategory, callback);
+    }
+
+    /**
+     * Reports an event happening in the context of the current URL.
+     *
+     * @param eventId Id of the reported event.
+     */
+    public void reportEvent(int eventId) {
+        assert mNativeContextualSuggestionsBridge != 0;
+        nativeReportEvent(mNativeContextualSuggestionsBridge, eventId);
+    }
+
+    @CalledByNative
+    private static List<ContextualSuggestionsCluster> createContextualSuggestionsClusterList() {
+        return new ArrayList<>();
+    }
+
+    @CalledByNative
+    private static void addNewClusterToList(
+            List<ContextualSuggestionsCluster> clusters, String title) {
+        clusters.add(new ContextualSuggestionsCluster(title));
+    }
+
+    @CalledByNative
+    private static void addSuggestionToLastCluster(List<ContextualSuggestionsCluster> clusters,
+            String id, String title, String publisher, String url, long timestamp, float score,
+            long fetchTime, boolean isVideoSuggestion, int thumbnailDominantColor) {
+        assert clusters.size() > 0;
+        clusters.get(clusters.size() - 1)
+                .getSuggestions()
+                .add(new SnippetArticle(KnownCategories.CONTEXTUAL, id, title, publisher, url,
+                        timestamp, score, fetchTime, isVideoSuggestion,
+                        thumbnailDominantColor == 0 ? null : thumbnailDominantColor));
+    }
+
+    @CalledByNative
+    private void onSuggestionsAvailable(List<ContextualSuggestionsCluster> clusters) {
+        // Pass this to UI (could be through observer).
+    }
+
+    @CalledByNative
+    private void onStateCleared() {
+        // Pass this to UI (could be through observer).
+    }
+
+    private native long nativeInit(Profile profile);
+    private native void nativeDestroy(long nativeContextualSuggestionsBridge);
+    private native void nativeFetchSuggestionImage(
+            long nativeContextualSuggestionsBridge, String suggestionId, Callback<Bitmap> callback);
+    private native void nativeFetchSuggestionFavicon(
+            long nativeContextualSuggestionsBridge, String suggestionId, Callback<Bitmap> callback);
+    private native void nativeReportEvent(long nativeContextualSuggestionsBridge, int eventId);
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsCluster.java b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsCluster.java
new file mode 100644
index 0000000..e0a1e86
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsCluster.java
@@ -0,0 +1,31 @@
+// Copyright 2018 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.
+
+package org.chromium.chrome.browser.contextual_suggestions;
+
+import org.chromium.chrome.browser.ntp.snippets.SnippetArticle;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/** Class to group contextual suggestions in a cluser of related items. */
+public class ContextualSuggestionsCluster {
+    private final String mTitle;
+    private final List<SnippetArticle> mSuggestions = new ArrayList<>();
+
+    /** Creates a new contextual suggestions cluster with provided title. */
+    public ContextualSuggestionsCluster(String title) {
+        mTitle = title;
+    }
+
+    /** @return a title related to this cluster */
+    public String getTitle() {
+        return mTitle;
+    }
+
+    /** @return a list of suggestions in this cluster */
+    public List<SnippetArticle> getSuggestions() {
+        return mSuggestions;
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsCoordinator.java
index 38bb44ab..b263a674 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsCoordinator.java
@@ -4,6 +4,8 @@
 
 package org.chromium.chrome.browser.contextual_suggestions;
 
+import android.support.annotation.Nullable;
+
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ntp.snippets.SuggestionsSource;
 import org.chromium.chrome.browser.profiles.Profile;
@@ -22,17 +24,16 @@
  * They share a {@link ContextualSuggestionsMediator} and {@link ContextualSuggestionsModel}.
  */
 public class ContextualSuggestionsCoordinator {
-    private ChromeActivity mActivity;
-    private BottomSheet mBottomSheet;
-    private Profile mProfile;
+    private final ChromeActivity mActivity;
+    private final BottomSheet mBottomSheet;
+    private final Profile mProfile;
+    private final ContextualSuggestionsModel mModel;
+    private final ContextualSuggestionsMediator mMediator;
+    private final SuggestionsUiDelegateImpl mUiDelegate;
 
-    private ContextualSuggestionsModel mModel;
-    private ContextualSuggestionsMediator mMediator;
-    private ContentCoordinator mContentCoordinator;
-
-    private SuggestionsUiDelegateImpl mUiDelegate;
-
-    private ContextualSuggestionsBottomSheetContent mBottomSheetContent;
+    private @Nullable ToolbarCoordinator mToolbarCoordinator;
+    private @Nullable ContentCoordinator mContentCoordinator;
+    private @Nullable ContextualSuggestionsBottomSheetContent mBottomSheetContent;
 
     /**
      * Construct a new {@link ContextualSuggestionsCoordinator}.
@@ -47,7 +48,8 @@
         mProfile = Profile.getLastUsedProfile().getOriginalProfile();
 
         mModel = new ContextualSuggestionsModel();
-        mMediator = new ContextualSuggestionsMediator(mProfile, tabModelSelector, this, mModel);
+        mMediator = new ContextualSuggestionsMediator(
+                mActivity, mProfile, tabModelSelector, this, mModel);
 
         SuggestionsSource suggestionsSource = mMediator.getSuggestionsSource();
         SuggestionsNavigationDelegate navigationDelegate = new SuggestionsNavigationDelegateImpl(
@@ -62,6 +64,7 @@
     public void destroy() {
         mMediator.destroy();
 
+        if (mToolbarCoordinator != null) mToolbarCoordinator.destroy();
         if (mContentCoordinator != null) mContentCoordinator.destroy();
         if (mBottomSheetContent != null) mBottomSheetContent.destroy();
     }
@@ -73,24 +76,30 @@
         // TODO(twellington): Introduce another method that creates bottom sheet content with only
         // a toolbar view when suggestions are fist available, and use this method to construct the
         // content view when the sheet is opened.
+        mToolbarCoordinator = new ToolbarCoordinator(mActivity, mBottomSheet, mModel);
         mContentCoordinator =
                 new ContentCoordinator(mActivity, mBottomSheet, mProfile, mUiDelegate, mModel);
-        mBottomSheetContent = new ContextualSuggestionsBottomSheetContent(mContentCoordinator);
+        mBottomSheetContent = new ContextualSuggestionsBottomSheetContent(
+                mContentCoordinator, mToolbarCoordinator);
         mBottomSheet.showContent(mBottomSheetContent);
     }
 
     /** Removes contextual suggestions from the {@link BottomSheet}. */
     void removeSuggestions() {
+        if (mToolbarCoordinator != null) {
+            mToolbarCoordinator.destroy();
+            mToolbarCoordinator = null;
+        }
+
         if (mContentCoordinator != null) {
             mContentCoordinator.destroy();
             mContentCoordinator = null;
         }
 
-        if (mBottomSheetContent == null) return;
-
-        mBottomSheet.showContent(null);
-
-        mBottomSheetContent.destroy();
-        mBottomSheetContent = null;
+        if (mBottomSheetContent != null) {
+            mBottomSheet.showContent(null);
+            mBottomSheetContent.destroy();
+            mBottomSheetContent = null;
+        }
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsMediator.java
index f42db7b4..48adf2c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsMediator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsMediator.java
@@ -4,11 +4,13 @@
 
 package org.chromium.chrome.browser.contextual_suggestions;
 
+import android.content.Context;
 import android.support.annotation.Nullable;
 import android.text.TextUtils;
 import android.webkit.URLUtil;
 
 import org.chromium.base.ContextUtils;
+import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ntp.snippets.SnippetArticle;
 import org.chromium.chrome.browser.ntp.snippets.SnippetsBridge;
 import org.chromium.chrome.browser.ntp.snippets.SuggestionsSource;
@@ -23,6 +25,7 @@
 import org.chromium.ui.widget.Toast;
 
 import java.util.ArrayList;
+import java.util.List;
 
 /**
  * A mediator for the contextual suggestions UI component responsible for interacting with
@@ -30,10 +33,10 @@
  * component coordinator(s).
  */
 class ContextualSuggestionsMediator {
-    private ContextualSuggestionsCoordinator mCoordinator;
-    private ContextualSuggestionsModel mModel;
-
-    private SnippetsBridge mBridge;
+    private final Context mContext;
+    private final ContextualSuggestionsCoordinator mCoordinator;
+    private final ContextualSuggestionsModel mModel;
+    private final SnippetsBridge mBridge;
 
     private final TabModelSelectorTabModelObserver mTabModelObserver;
     private final TabObserver mTabObserver;
@@ -44,13 +47,16 @@
 
     /**
      * Construct a new {@link ContextualSuggestionsMediator}.
+     * @param context The {@link Context} used to retrieve resources.
      * @param profile The regular {@link Profile}.
      * @param tabModelSelector The {@link TabModelSelector} for the containing activity.
      * @param coordinator The {@link ContextualSuggestionsCoordinator} for the component.
      * @param model The {@link ContextualSuggestionsModel} for the component.
      */
-    ContextualSuggestionsMediator(Profile profile, TabModelSelector tabModelSelector,
-            ContextualSuggestionsCoordinator coordinator, ContextualSuggestionsModel model) {
+    ContextualSuggestionsMediator(Context context, Profile profile,
+            TabModelSelector tabModelSelector, ContextualSuggestionsCoordinator coordinator,
+            ContextualSuggestionsModel model) {
+        mContext = context;
         mCoordinator = coordinator;
         mModel = model;
 
@@ -120,18 +126,28 @@
                          suggestions.size() + " suggestions fetched", Toast.LENGTH_SHORT)
                     .show();
 
-            if (suggestions.size() > 0) {
-                mModel.setSuggestions(suggestions);
-                mCoordinator.displaySuggestions();
-            };
+            if (suggestions.size() > 0) displaySuggestions(suggestions);
         });
     }
 
     private void clearSuggestions() {
         mModel.setSuggestions(new ArrayList<SnippetArticle>());
+        mModel.setCloseButtonOnClickListener(null);
+        mModel.setTitle(null);
         mCoordinator.removeSuggestions();
     }
 
+    private void displaySuggestions(List<SnippetArticle> suggestions) {
+        mModel.setSuggestions(suggestions);
+        mModel.setCloseButtonOnClickListener(view -> { clearSuggestions(); });
+
+        // TODO(twellington): Replace this with the first cluster title.
+        mModel.setTitle(mContext.getString(
+                R.string.contextual_suggestions_toolbar_title, suggestions.get(0).mTitle));
+
+        mCoordinator.displaySuggestions();
+    }
+
     private boolean isContextTheSame(String newUrl) {
         return UrlUtilities.urlsMatchIgnoringFragments(newUrl, mCurrentContextUrl);
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsModel.java b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsModel.java
index 3abeb49..bcaf79d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsModel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsModel.java
@@ -4,48 +4,82 @@
 
 package org.chromium.chrome.browser.contextual_suggestions;
 
+import android.view.View.OnClickListener;
+
 import org.chromium.chrome.browser.modelutil.ListObservable;
+import org.chromium.chrome.browser.modelutil.PropertyObservable;
 import org.chromium.chrome.browser.ntp.snippets.SnippetArticle;
 
 import java.util.ArrayList;
 import java.util.List;
 
 /** A model for the contextual suggestions UI component. */
-class ContextualSuggestionsModel extends ListObservable<SnippetArticle> {
-    private List<SnippetArticle> mSuggestions = new ArrayList<>();
+class ContextualSuggestionsModel extends PropertyObservable<PropertyKey> {
+    /** A {@link ListObservable} containing the current list of suggestions. */
+    class SuggestionsList extends ListObservable<SnippetArticle> {
+        private List<SnippetArticle> mSuggestions = new ArrayList<>();
+
+        private void setSuggestions(List<SnippetArticle> suggestions) {
+            assert suggestions != null;
+
+            int oldLength = getItemCount();
+            mSuggestions = suggestions;
+
+            if (oldLength != 0) notifyItemRangeRemoved(0, oldLength);
+            if (mSuggestions.size() != 0) {
+                notifyItemRangeInserted(0, mSuggestions.size());
+            }
+        }
+
+        @Override
+        public int getItemCount() {
+            return mSuggestions.size();
+        }
+
+        @Override
+        public SnippetArticle getItem(int position) {
+            assert position < mSuggestions.size();
+
+            return mSuggestions.get(position);
+        }
+    }
+
+    SuggestionsList mSuggestionsList = new SuggestionsList();
+    private OnClickListener mCloseButtonOnClickListener;
+    private String mTitle;
 
     /**
      * @param suggestions The list of current suggestions. May be an empty list if no
      *                    suggestions are available.
      */
     void setSuggestions(List<SnippetArticle> suggestions) {
-        assert suggestions != null;
-
-        if (suggestions.size() == 0 && mSuggestions.size() == 0) return;
-
-        int oldLength = getItemCount();
-        mSuggestions = suggestions;
-
-        if (oldLength != 0) notifyItemRangeRemoved(0, oldLength);
-        if (mSuggestions.size() != 0) {
-            notifyItemRangeInserted(0, mSuggestions.size());
-        }
+        mSuggestionsList.setSuggestions(suggestions);
     }
 
     /** @return The list of current suggestions. */
     List<SnippetArticle> getSuggestions() {
-        return mSuggestions;
+        return mSuggestionsList.mSuggestions;
     }
 
-    @Override
-    public int getItemCount() {
-        return mSuggestions.size();
+    /** @param listener The {@link OnClickListener} for the close button. */
+    void setCloseButtonOnClickListener(OnClickListener listener) {
+        mCloseButtonOnClickListener = listener;
+        notifyPropertyChanged(new PropertyKey(PropertyKey.CLOSE_BUTTON_ON_CLICK_LISTENER));
     }
 
-    @Override
-    public SnippetArticle getItem(int position) {
-        assert position < mSuggestions.size();
+    /** @return The {@link OnClickListener} for the close button. */
+    OnClickListener getCloseButtonOnClickListener() {
+        return mCloseButtonOnClickListener;
+    }
 
-        return mSuggestions.get(position);
+    /** @param title The title to display in the toolbar. */
+    void setTitle(String title) {
+        mTitle = title;
+        notifyPropertyChanged(new PropertyKey(PropertyKey.TITLE));
+    }
+
+    /** @return title The title to display in the toolbar. */
+    String getTitle() {
+        return mTitle;
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/PropertyKey.java b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/PropertyKey.java
new file mode 100644
index 0000000..0eb5226
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/PropertyKey.java
@@ -0,0 +1,29 @@
+// Copyright 2018 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.
+
+package org.chromium.chrome.browser.contextual_suggestions;
+
+import android.support.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Contains a key uniquely identifying properties held in the {@link ContextualSuggestionsModel}.
+ */
+class PropertyKey {
+    /** The unique identifiers for properties held in the model. */
+    @IntDef({CLOSE_BUTTON_ON_CLICK_LISTENER, TITLE})
+    @Retention(RetentionPolicy.SOURCE)
+    @interface Key {}
+    static final int CLOSE_BUTTON_ON_CLICK_LISTENER = 0;
+    static final int TITLE = 1;
+
+    @Key
+    Integer mKey;
+
+    PropertyKey(@Key Integer key) {
+        mKey = key;
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ToolbarCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ToolbarCoordinator.java
new file mode 100644
index 0000000..d8ace1b
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ToolbarCoordinator.java
@@ -0,0 +1,50 @@
+// Copyright 2018 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.
+
+package org.chromium.chrome.browser.contextual_suggestions;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import org.chromium.chrome.R;
+
+/**
+ * Coordinator for the toolbar sub-component. Responsible for communication with the parent
+ * {@link ContextualSuggestionsCoordinator} and lifecycle of sub-component objects.
+ */
+class ToolbarCoordinator {
+    private final ContextualSuggestionsModel mModel;
+    private ToolbarView mToolbarView;
+    private ToolbarModelChangeProcessor mModelChangeProcessor;
+
+    /**
+     * Construct a new {@link ToolbarCoordinator}.
+     * @param context The {@link Context} used to retrieve resources.
+     * @param parentView The parent {@link View} to which the content will eventually be attached.
+     * @param model The {@link ContextualSuggestionsModel} for the component.
+     */
+    ToolbarCoordinator(Context context, ViewGroup parentView, ContextualSuggestionsModel model) {
+        mModel = model;
+
+        mToolbarView = (ToolbarView) LayoutInflater.from(context).inflate(
+                R.layout.contextual_suggestions_toolbar, parentView, false);
+
+        mModelChangeProcessor = new ToolbarModelChangeProcessor(mToolbarView, mModel);
+        mModel.addObserver(mModelChangeProcessor);
+    }
+
+    /** @return The content {@link View}. */
+    View getView() {
+        return mToolbarView;
+    }
+
+    /** Destroy the toolbar component. */
+    void destroy() {
+        // The model outlives the toolbar sub-component. Remove the observer so that this object
+        // can be garbage collected.
+        mModel.removeObserver(mModelChangeProcessor);
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ToolbarModelChangeProcessor.java b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ToolbarModelChangeProcessor.java
new file mode 100644
index 0000000..64d17c15
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ToolbarModelChangeProcessor.java
@@ -0,0 +1,62 @@
+// Copyright 2018 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.
+
+package org.chromium.chrome.browser.contextual_suggestions;
+
+import org.chromium.chrome.browser.modelutil.PropertyObservable;
+import org.chromium.chrome.browser.modelutil.PropertyObservable.PropertyObserver;
+
+/**
+ * A model change processor for use with a {@link ToolbarView}. The
+ * {@link ToolbarModelChangeProcessor} should be registered as a property observer of
+ * {@link ContextualSuggestionsModel}. Internally uses a view binder to bind model
+ * properties to the toolbar view.
+ */
+class ToolbarModelChangeProcessor implements PropertyObserver<PropertyKey> {
+    private static class ViewBinder {
+        /**
+         * Bind the changed property to the toolbar view.
+         * @param view The {@link ToolbarView} to which data will be bound.
+         * @param model The {@link ContextualSuggestionsModel} containing the data to be bound.
+         * @param propertyKey The {@link PropertyKey} of the property that has changed.
+         */
+        private static void bindProperty(
+                ToolbarView view, ContextualSuggestionsModel model, PropertyKey propertyKey) {
+            switch (propertyKey.mKey) {
+                case PropertyKey.CLOSE_BUTTON_ON_CLICK_LISTENER:
+                    view.setOnClickListener(model.getCloseButtonOnClickListener());
+                    break;
+                case PropertyKey.TITLE:
+                    view.setTitle(model.getTitle());
+                    break;
+                default:
+                    assert false;
+            }
+        }
+    }
+
+    private final ToolbarView mToolbarView;
+    private final ContextualSuggestionsModel mModel;
+
+    /**
+     * Construct a new ToolbarModelChangeProcessor.
+     * @param view The {@link ToolbarView} to which data will be bound.
+     * @param model The {@link ContextualSuggestionsModel} containing the data to be bound.
+     */
+    ToolbarModelChangeProcessor(ToolbarView view, ContextualSuggestionsModel model) {
+        mToolbarView = view;
+        mModel = model;
+
+        // The ToolbarCoordinator is created dynamically as needed, so the initial model state
+        // needs to be bound on creation.
+        ViewBinder.bindProperty(
+                mToolbarView, mModel, new PropertyKey(PropertyKey.CLOSE_BUTTON_ON_CLICK_LISTENER));
+        ViewBinder.bindProperty(mToolbarView, mModel, new PropertyKey(PropertyKey.TITLE));
+    }
+
+    @Override
+    public void onPropertyChanged(PropertyObservable<PropertyKey> source, PropertyKey propertyKey) {
+        ViewBinder.bindProperty(mToolbarView, mModel, propertyKey);
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ToolbarView.java b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ToolbarView.java
new file mode 100644
index 0000000..970e8fa
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ToolbarView.java
@@ -0,0 +1,39 @@
+// Copyright 2018 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.
+
+package org.chromium.chrome.browser.contextual_suggestions;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import org.chromium.chrome.R;
+
+/** The toolbar view, containing an icon, title and close button. */
+public class ToolbarView extends LinearLayout {
+    private View mCloseButton;
+    private TextView mTitle;
+
+    public ToolbarView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        mCloseButton = findViewById(R.id.close_button);
+        mTitle = (TextView) findViewById(R.id.title);
+    }
+
+    void setCloseButtonOnClickListener(OnClickListener listener) {
+        mCloseButton.setOnClickListener(listener);
+    }
+
+    void setTitle(String title) {
+        mTitle.setText(title);
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java
index 8813851..831ea0a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchFieldTrial.java
@@ -52,6 +52,9 @@
     private static final String SHORT_WORD_SUPPRESSION_ENABLED = "enable_short_word_suppression";
     private static final String NOT_LONG_WORD_SUPPRESSION_ENABLED =
             "enable_not_long_word_suppression";
+    private static final String SHORT_TEXT_RUN_SUPPRESSION_ENABLED =
+            "enable_short_text_run_suppression";
+    private static final String SMALL_TEXT_SUPPRESSION_ENABLED = "enable_small_text_suppression";
     @VisibleForTesting
     static final String NOT_AN_ENTITY_SUPPRESSION_ENABLED = "enable_not_an_entity_suppression";
     // The threshold for tap suppression based on duration.
@@ -96,6 +99,8 @@
     private static Boolean sIsShortWordSuppressionEnabled;
     private static Boolean sIsNotLongWordSuppressionEnabled;
     private static Boolean sIsNotAnEntitySuppressionEnabled;
+    private static Boolean sIsShortTextRunSuppressionEnabled;
+    private static Boolean sIsSmallTextSuppressionEnabled;
     private static Integer sMinimumSelectionLength;
     private static Boolean sIsOnlineDetectionDisabled;
     private static Boolean sIsAmpAsSeparateTabDisabled;
@@ -276,6 +281,26 @@
     }
 
     /**
+     * @return Whether triggering is suppressed for a tap that has a short element run-length.
+     */
+    static boolean isShortTextRunSuppressionEnabled() {
+        if (sIsShortTextRunSuppressionEnabled == null) {
+            sIsShortTextRunSuppressionEnabled = getBooleanParam(SHORT_TEXT_RUN_SUPPRESSION_ENABLED);
+        }
+        return sIsShortTextRunSuppressionEnabled.booleanValue();
+    }
+
+    /**
+     * @return Whether triggering is suppressed for a tap on small-looking text.
+     */
+    static boolean isSmallTextSuppressionEnabled() {
+        if (sIsSmallTextSuppressionEnabled == null) {
+            sIsSmallTextSuppressionEnabled = getBooleanParam(SMALL_TEXT_SUPPRESSION_ENABLED);
+        }
+        return sIsSmallTextSuppressionEnabled.booleanValue();
+    }
+
+    /**
      * @return The minimum valid selection length.
      */
     static int getMinimumSelectionLength() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchHeuristic.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchHeuristic.java
index 751b926..3b7f3a8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchHeuristic.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchHeuristic.java
@@ -85,4 +85,13 @@
     protected boolean shouldOverrideMlTapSuppression() {
         return false;
     }
+
+    /**
+     * Clamps an input value into a range of 1-10 inclusive.
+     * @param value The value to limit.
+     * @return A value that's at least 1 and at most 10.
+     */
+    protected int clamp(int value) {
+        return Math.max(1, Math.min(10, value));
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
index 9a0953a0..128a8c5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
@@ -1321,9 +1321,10 @@
     }
 
     /** Shows the Unhandled Tap UI.  Called by {@link ContextualSearchTabHelper}. */
-    void onShowUnhandledTapUIIfNeeded(int x, int y) {
+    void onShowUnhandledTapUIIfNeeded(int x, int y, int fontSizeDips, int textRunLength) {
         if (!isOverlayVideoMode()) {
-            mSelectionController.handleShowUnhandledTapUIIfNeeded(x, y);
+            mSelectionController.handleShowUnhandledTapUIIfNeeded(
+                    x, y, fontSizeDips, textRunLength);
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRankerLogger.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRankerLogger.java
index 19ce6e04..6a14a76 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRankerLogger.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRankerLogger.java
@@ -40,10 +40,12 @@
         IS_ENTITY,
         TAP_DURATION_MS,
         // UKM CS v3 features (see go/ukm-cs-3).
+        FONT_SIZE,
         IS_SECOND_TAP_OVERRIDE,
         IS_HTTP,
         IS_ENTITY_ELIGIBLE,
-        IS_LANGUAGE_MISMATCH
+        IS_LANGUAGE_MISMATCH,
+        PORTION_OF_ELEMENT
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRankerLoggerImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRankerLoggerImpl.java
index bb6a30a..f0edd22 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRankerLoggerImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRankerLoggerImpl.java
@@ -53,10 +53,12 @@
         features.put(Feature.IS_ENTITY, "IsEntity");
         features.put(Feature.TAP_DURATION_MS, "TapDurationMs");
         // UKM CS v3 features.
-        features.put(Feature.IS_SECOND_TAP_OVERRIDE, "IsSecondTapOverride");
+        features.put(Feature.FONT_SIZE, "FontSize");
         features.put(Feature.IS_HTTP, "IsHttp");
+        features.put(Feature.IS_SECOND_TAP_OVERRIDE, "IsSecondTapOverride");
         features.put(Feature.IS_ENTITY_ELIGIBLE, "IsEntityEligible");
         features.put(Feature.IS_LANGUAGE_MISMATCH, "IsLanguageMismatch");
+        features.put(Feature.PORTION_OF_ELEMENT, "PortionOfElement");
         FEATURES = Collections.unmodifiableMap(features);
 
         Map<Feature, String> allNames = new HashMap<Feature, String>();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionController.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionController.java
index 8443b98..b0183f7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSelectionController.java
@@ -71,6 +71,10 @@
     private float mX;
     private float mY;
 
+    // Additional tap info from Mojo.
+    int mFontSizeDips;
+    int mTextRunLength;
+
     // The time of the most last scroll activity, or 0 if none.
     private long mLastScrollTimeNs;
 
@@ -312,6 +316,8 @@
         mTapTimeNanoseconds = 0;
         mTapDurationMs = INVALID_DURATION;
         mDidExpandSelection = false;
+        mFontSizeDips = 0;
+        mTextRunLength = 0;
     }
 
     /**
@@ -336,8 +342,10 @@
      * Handles an unhandled tap gesture.
      * @param x The x coordinate in px.
      * @param y The y coordinate in px.
+     * @param fontSizeDips The font size in DPs.
+     * @param textRunLength The run-length of the text of the tapped element.
      */
-    void handleShowUnhandledTapUIIfNeeded(int x, int y) {
+    void handleShowUnhandledTapUIIfNeeded(int x, int y, int fontSizeDips, int textRunLength) {
         mWasTapGestureDetected = false;
         // TODO(donnd): refactor to avoid needing a new handler API method as suggested by Pedro.
         if (mSelectionType != SelectionType.LONG_PRESS) {
@@ -349,6 +357,8 @@
             mSelectionType = SelectionType.TAP;
             mX = x;
             mY = y;
+            mFontSizeDips = fontSizeDips;
+            mTextRunLength = textRunLength;
             mHandler.handleValidTap();
         } else {
             // Long press; reset last tap state.
@@ -373,8 +383,9 @@
 
         // TODO(donnd): Remove tap counters.
         if (mTapDurationMs == INVALID_DURATION) mTapDurationMs = DEFAULT_DURATION;
-        TapSuppressionHeuristics tapHeuristics = new TapSuppressionHeuristics(this, mLastTapState,
-                x, y, contextualSearchContext, mTapDurationMs, mWasSelectionEmptyBeforeTap);
+        TapSuppressionHeuristics tapHeuristics =
+                new TapSuppressionHeuristics(this, mLastTapState, x, y, contextualSearchContext,
+                        mTapDurationMs, mWasSelectionEmptyBeforeTap, mFontSizeDips, mTextRunLength);
         // TODO(donnd): Move to be called when the panel closes to work with states that change.
         tapHeuristics.logConditionState();
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTabHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTabHelper.java
index a0edbba..366fa335 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTabHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTabHelper.java
@@ -317,10 +317,11 @@
      * coordinates.
      */
     @CalledByNative
-    void onShowUnhandledTapUIIfNeeded(int x, int y) {
+    void onShowUnhandledTapUIIfNeeded(int x, int y, int fontSizeDips, int textRunLength) {
         // Only notify the manager if we currently have a valid listener.
         if (mGestureStateListener != null && getContextualSearchManager(mTab) != null) {
-            getContextualSearchManager(mTab).onShowUnhandledTapUIIfNeeded(x, y);
+            getContextualSearchManager(mTab).onShowUnhandledTapUIIfNeeded(
+                    x, y, fontSizeDips, textRunLength);
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ShortTextRunSuppression.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ShortTextRunSuppression.java
new file mode 100644
index 0000000..b8fe88a
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ShortTextRunSuppression.java
@@ -0,0 +1,73 @@
+// Copyright 2018 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.
+
+package org.chromium.chrome.browser.contextualsearch;
+
+/**
+ * Implements a policy that a Tap on a word that's part of a short text run should be suppressed.
+ * Computes the ratio of the tapped word to the entire run of text in the element (which includes
+ * style changes).  This means that short navigational elements will have a high score, and a tap
+ * in a longer paragraph will have a smaller score.
+ */
+class ShortTextRunSuppression extends ContextualSearchHeuristic {
+    // Threshold for a "large" ratio of word to element.
+    private static final int LARGE_WORD_ELEMENT_RATIO = 3;
+
+    // Value to use when the word or element length is unavailable.
+    private static final int DEFAULT_WORD_ELEMENT_RATIO = 0;
+
+    private final boolean mIsSuppressionEnabled;
+    private final boolean mIsConditionSatisfied;
+    private final int mWordElementRatioDecile;
+
+    /**
+     * Constructs a heuristic to determine if the current Tap is in a short text run.
+     * @param contextualSearchContext The current {@link ContextualSearchContext}, so we can get
+     *        the length of the word tapped.
+     * @param elementRunLength The length of the text in the element tapped, in characters.
+     */
+    ShortTextRunSuppression(ContextualSearchContext contextualSearchContext, int elementRunLength) {
+        mIsSuppressionEnabled = ContextualSearchFieldTrial.isShortTextRunSuppressionEnabled();
+        mWordElementRatioDecile = wordElementRatio(contextualSearchContext, elementRunLength);
+        mIsConditionSatisfied = mWordElementRatioDecile >= LARGE_WORD_ELEMENT_RATIO;
+    }
+
+    @Override
+    protected boolean isConditionSatisfiedAndEnabled() {
+        return mIsSuppressionEnabled && mIsConditionSatisfied;
+    }
+
+    @Override
+    protected boolean shouldAggregateLogForTapSuppression() {
+        return true;
+    }
+
+    @Override
+    protected boolean isConditionSatisfiedForAggregateLogging() {
+        return mIsConditionSatisfied;
+    }
+
+    @Override
+    protected void logRankerTapSuppression(ContextualSearchRankerLogger logger) {
+        logger.logFeature(
+                ContextualSearchRankerLogger.Feature.PORTION_OF_ELEMENT, mWordElementRatioDecile);
+    }
+
+    /**
+     * Returns the ratio of word-length to the element-length scaled to a range from 1 to 10.
+     * @param contextualSearchContext The {@link ContextualSearchContext} that knows about the word
+     *        tapped.
+     * @param elementRunLength The length of the element containing the tapped word, in characters.
+     * @return A value in the range 0-10 with 0 meaning no ratio could be computed and larger values
+     *         reflecting higher word/element ratios.
+     */
+    private int wordElementRatio(
+            ContextualSearchContext contextualSearchContext, int elementRunLength) {
+        // If setup failed, don't suppress.
+        String wordTapped = contextualSearchContext.getWordTapped();
+        if (wordTapped == null || elementRunLength == 0) return DEFAULT_WORD_ELEMENT_RATIO;
+
+        return clamp((int) ((float) wordTapped.length() / elementRunLength * 10));
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/SmallTextSuppression.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/SmallTextSuppression.java
new file mode 100644
index 0000000..5d5805bf
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/SmallTextSuppression.java
@@ -0,0 +1,70 @@
+// Copyright 2018 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.
+
+package org.chromium.chrome.browser.contextualsearch;
+
+/**
+ * Implements a policy that a Tap on a relatively small font should be ignored.
+ */
+class SmallTextSuppression extends ContextualSearchHeuristic {
+    private static final int SMALL_SIZE_THRESHOLD_DIPS = 15;
+    private static final int DEFAULT_DECILIZED_VALUE = 0;
+    private static final float DECILIZE_SCALE_FACTOR = 0.5f;
+    private static final int DECILIZE_MINIMUM_INPUT = 8;
+
+    private final boolean mIsSuppressionEnabled;
+    private final boolean mIsConditionSatisfied;
+    private final int mDecilizedFontSize;
+
+    /**
+     * Constructs a heuristic to determine if the current Tap is on text with a small height.
+     * @param fontSizeDips The size of the font from Blink in dips.
+     */
+    SmallTextSuppression(int fontSizeDips) {
+        mIsSuppressionEnabled = ContextualSearchFieldTrial.isSmallTextSuppressionEnabled();
+        mIsConditionSatisfied = isConditionSatisfied(fontSizeDips);
+        mDecilizedFontSize = decilizedFontSize(fontSizeDips);
+    }
+
+    @Override
+    protected boolean isConditionSatisfiedAndEnabled() {
+        return mIsSuppressionEnabled && mIsConditionSatisfied;
+    }
+
+    @Override
+    protected boolean shouldAggregateLogForTapSuppression() {
+        return true;
+    }
+
+    @Override
+    protected boolean isConditionSatisfiedForAggregateLogging() {
+        return mIsConditionSatisfied;
+    }
+
+    @Override
+    protected void logRankerTapSuppression(ContextualSearchRankerLogger logger) {
+        logger.logFeature(ContextualSearchRankerLogger.Feature.FONT_SIZE, mDecilizedFontSize);
+    }
+
+    /**
+     * Whether the conditions are satisfied to suppress the tap based on the given params:
+     * @param fontSizeDips The size of the font in DIPs.
+     * @return whether the conditions are satisfied to suppress (but might not actually do so).
+     */
+    private boolean isConditionSatisfied(int fontSizeDips) {
+        return fontSizeDips != 0 && fontSizeDips < SMALL_SIZE_THRESHOLD_DIPS;
+    }
+
+    /**
+     * Converts the input value into a "decile", an int in the range 0-10 inclusive.
+     * @param value Any value to be scaled.  Very large values will pin at 10. Only an input of
+     *        0 will return 0.
+     * @return A value that's 0 if the input is zero and least 1 and at most 10 otherwise.
+     */
+    private int decilizedFontSize(int value) {
+        if (value == 0) return DEFAULT_DECILIZED_VALUE;
+
+        return clamp(Math.round(DECILIZE_SCALE_FACTOR * (value - DECILIZE_MINIMUM_INPUT)));
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/TapSuppressionHeuristics.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/TapSuppressionHeuristics.java
index b9ee3c6..ae4b611 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/TapSuppressionHeuristics.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/TapSuppressionHeuristics.java
@@ -21,11 +21,13 @@
      * @param contextualSearchContext The {@link ContextualSearchContext} of this tap.
      * @param tapDurationMs The duration of this tap in milliseconds.
      * @param wasSelectionEmptyBeforeTap Whether the selection was empty before this tap.
+     * @param fontSizeDips The font size from Blink in dips.
+     * @param elementRunLength The length of the text in the element tapped, in characters.
      */
     TapSuppressionHeuristics(ContextualSearchSelectionController selectionController,
             @Nullable ContextualSearchTapState previousTapState, int x, int y,
             ContextualSearchContext contextualSearchContext, int tapDurationMs,
-            boolean wasSelectionEmptyBeforeTap) {
+            boolean wasSelectionEmptyBeforeTap, int fontSizeDips, int elementRunLength) {
         super();
         mCtrSuppression = new CtrSuppression();
         mHeuristics.add(mCtrSuppression);
@@ -38,6 +40,8 @@
         mHeuristics.add(new ContextualSearchEntityHeuristic(contextualSearchContext));
         mHeuristics.add(new NearTopTapSuppression(selectionController, y));
         mHeuristics.add(new BarOverlapTapSuppression(selectionController, y));
+        mHeuristics.add(new ShortTextRunSuppression(contextualSearchContext, elementRunLength));
+        mHeuristics.add(new SmallTextSuppression(fontSizeDips));
         // Second Tap ML Override.
         mHeuristics.add(new SecondTapMlOverride(selectionController, previousTapState, x, y));
         // Quick Answer that appears in the Caption via the JS API.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/document/ChromeLauncherActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/document/ChromeLauncherActivity.java
index b4f65955..0c6b2762 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/document/ChromeLauncherActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/document/ChromeLauncherActivity.java
@@ -11,6 +11,7 @@
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.TraceEvent;
 import org.chromium.chrome.browser.LaunchIntentDispatcher;
+import org.chromium.chrome.browser.vr_shell.VrIntentUtils;
 
 /**
  * Dispatches incoming intents to the appropriate activity based on the current configuration and
@@ -25,6 +26,9 @@
         try {
             super.onCreate(savedInstanceState);
 
+            // VR Intents should only ever get routed through the VrMainActivity.
+            assert !VrIntentUtils.isVrIntent(getIntent());
+
             @LaunchIntentDispatcher.Action
             int dispatchAction = LaunchIntentDispatcher.dispatch(this, getIntent());
             switch (dispatchAction) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java
index 1c17561..1a43d68 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java
@@ -885,6 +885,12 @@
             notifyDownloadFailed(id, fileName, icon);
             return;
         }
+        // Download is already paused.
+        if (entry != null && !entry.isAutoResumable) {
+            // Shutdown the service in case it was restarted unnecessarily.
+            stopTrackingInProgressDownload(id, true);
+            return;
+        }
         boolean canDownloadWhileMetered = entry == null ? false : entry.canDownloadWhileMetered;
         // If download is interrupted due to network disconnection, show download pending state.
         if (isAutoResumable) {
@@ -893,12 +899,6 @@
             stopTrackingInProgressDownload(id, true);
             return;
         }
-        // Download is already paused.
-        if (entry != null && !entry.isAutoResumable) {
-            // Shutdown the service in case it was restarted unnecessarily.
-            stopTrackingInProgressDownload(id, true);
-            return;
-        }
 
         String contentText =
                 mContext.getResources().getString(R.string.download_notification_paused);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService2.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService2.java
index f831309d..49f6d1a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService2.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService2.java
@@ -304,6 +304,8 @@
             notifyDownloadFailed(id, fileName, icon);
             return;
         }
+        // If download is already paused, do nothing.
+        if (entry != null && !entry.isAutoResumable && !forceRebuild) return;
         boolean canDownloadWhileMetered = entry == null ? false : entry.canDownloadWhileMetered;
         // If download is interrupted due to network disconnection, show download pending state.
         if (isAutoResumable) {
@@ -312,8 +314,6 @@
             stopTrackingInProgressDownload(id);
             return;
         }
-        // If download is already paused, do nothing.
-        if (entry != null && !entry.isAutoResumable && !forceRebuild) return;
         int notificationId = entry == null ? getNotificationId(id) : entry.notificationId;
         Context context = ContextUtils.getApplicationContext();
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/PermissionUpdateInfoBarDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/PermissionUpdateInfoBarDelegate.java
index 62e7f45..d77a706 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/PermissionUpdateInfoBarDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/PermissionUpdateInfoBarDelegate.java
@@ -15,7 +15,6 @@
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.chrome.browser.metrics.WebApkUma;
 import org.chromium.chrome.browser.webapps.WebApkActivity;
-import org.chromium.content_public.browser.ContentViewCore;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.ui.base.WindowAndroid;
 
@@ -23,8 +22,7 @@
  * Handles requesting the android runtime permissions for the permission update infobar.
  */
 class PermissionUpdateInfoBarDelegate implements WindowAndroid.PermissionCallback {
-
-    private final ContentViewCore mContentViewCore;
+    private final WebContents mWebContents;
     private final String[] mAndroidPermisisons;
     private long mNativePtr;
     private ActivityStateListener mActivityStateListener;
@@ -39,7 +37,7 @@
             long nativePtr, WebContents webContents, String[] permissions) {
         mNativePtr = nativePtr;
         mAndroidPermisisons = permissions;
-        mContentViewCore = ContentViewCore.fromWebContents(webContents);
+        mWebContents = webContents;
     }
 
     @CalledByNative
@@ -53,7 +51,7 @@
 
     @CalledByNative
     private void requestPermissions() {
-        WindowAndroid windowAndroid = mContentViewCore.getWindowAndroid();
+        WindowAndroid windowAndroid = mWebContents.getTopLevelNativeWindow();
         if (windowAndroid == null) {
             nativeOnPermissionResult(mNativePtr, false);
             return;
@@ -111,7 +109,7 @@
 
     private void notifyPermissionResult() {
         boolean hasAllPermissions = true;
-        WindowAndroid windowAndroid = mContentViewCore.getWindowAndroid();
+        WindowAndroid windowAndroid = mWebContents.getTopLevelNativeWindow();
         if (windowAndroid == null) {
             hasAllPermissions = false;
         } else {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaSessionStats.java b/chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaSessionStats.java
index 3e5cf04..c43a347 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaSessionStats.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaSessionStats.java
@@ -173,6 +173,27 @@
     }
 
     /**
+     * Initializes the metrics consent bit to false. Used only for testing.
+     */
+    public static void initMetricsAndCrashReportingForTesting() {
+        nativeInitMetricsAndCrashReportingForTesting();
+    }
+
+    /**
+     * Clears the metrics consent bit used for testing to original setting. Used only for testing.
+     */
+    public static void unSetMetricsAndCrashReportingForTesting() {
+        nativeUnsetMetricsAndCrashReportingForTesting();
+    }
+
+    /**
+     * Updates the metrics consent bit to |consent|. Used only for testing.
+     */
+    public static void updateMetricsAndCrashReportingForTesting(boolean consent) {
+        nativeUpdateMetricsAndCrashReportingForTesting(consent);
+    }
+
+    /**
      * Updates the state of MetricsService to account for the user's preferences.
      */
     public static void updateMetricsServiceState() {
@@ -212,6 +233,9 @@
 
     private static native long nativeInit();
     private static native void nativeChangeMetricsReportingConsent(boolean consent);
+    private static native void nativeInitMetricsAndCrashReportingForTesting();
+    private static native void nativeUnsetMetricsAndCrashReportingForTesting();
+    private static native void nativeUpdateMetricsAndCrashReportingForTesting(boolean consent);
     private static native void nativeUpdateMetricsServiceState(boolean mayUpload);
     private native void nativeUmaResumeSession(long nativeUmaSessionStats);
     private native void nativeUmaEndSession(long nativeUmaSessionStats);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/modelutil/PropertyObservable.java b/chrome/android/java/src/org/chromium/chrome/browser/modelutil/PropertyObservable.java
new file mode 100644
index 0000000..5d8a1929
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/modelutil/PropertyObservable.java
@@ -0,0 +1,57 @@
+// Copyright 2018 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.
+
+package org.chromium.chrome.browser.modelutil;
+
+import android.support.annotation.Nullable;
+
+import org.chromium.base.ObserverList;
+
+/**
+ * A base class for models maintaining a set of properties.
+ *
+ * @param <T> The type of the property key used for uniquely identifying properties.
+ */
+public class PropertyObservable<T> {
+    /**
+     * An observer to be notified of changes to a {@link PropertyObservable}.
+     *
+     * @param <T> The type of the property key used for uniquely identifying properties.
+     */
+    public interface PropertyObserver<T> {
+        /**
+         * Notifies that the given {@code property} of the observed {@code source} has changed.
+         * @param source The object whose property has changed
+         * @param property The key of the property that has changed.
+         */
+        void onPropertyChanged(PropertyObservable<T> source, @Nullable T propertyKey);
+    }
+
+    private final ObserverList<PropertyObserver<T>> mObservers = new ObserverList<>();
+
+    /**
+     * @param observer An observer to be notified of changes to the model.
+     */
+    public void addObserver(PropertyObserver<T> observer) {
+        mObservers.addObserver(observer);
+    }
+
+    /**
+     * @param observer The observer to remove.
+     */
+    public void removeObserver(PropertyObserver<T> observer) {
+        mObservers.removeObserver(observer);
+    }
+
+    /**
+     * Notifies observers that the property identified by {@code propertyKey} has changed.
+     *
+     * @param propertyKey The key of the property that has changed.
+     */
+    protected void notifyPropertyChanged(T propertyKey) {
+        for (PropertyObserver<T> observer : mObservers) {
+            observer.onPropertyChanged(this, propertyKey);
+        }
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java
index 6561f9a..63b0a28a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java
@@ -9,6 +9,7 @@
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Environment;
+import android.text.TextUtils;
 
 import org.chromium.base.ActivityState;
 import org.chromium.base.ApplicationStatus;
@@ -369,19 +370,27 @@
         OfflinePageItem offlinePage = offlinePageBridge.getOfflinePage(tab.getWebContents());
         String offlinePath = offlinePage.getFilePath();
 
-        if (!isOfflinePageShareable(offlinePageBridge, offlinePage)) return false;
+        final String pageUrl = tab.getUrl();
+
+        if (!isOfflinePageShareable(offlinePageBridge, offlinePage, pageUrl)) return false;
 
         final String tabTitle = tab.getTitle();
-        final String tabUrl = tab.getUrl();
         final File offlinePageFile = new File(offlinePath);
         AsyncTask<Void, Void, Uri> task = new AsyncTask<Void, Void, Uri>() {
             @Override
             protected Uri doInBackground(Void... v) {
+                // If we have a content or file URI, we will not have a filename, just return the
+                // URI.
+                if (offlinePath.isEmpty()) {
+                    Uri uri = Uri.parse(pageUrl);
+                    assert(isSchemeContentOrFile(uri));
+                    return uri;
+                }
                 return ChromeFileProvider.generateUri(activity, offlinePageFile);
             }
             @Override
             protected void onPostExecute(Uri uri) {
-                ShareParams shareParams = new ShareParams.Builder(activity, tabTitle, tabUrl)
+                ShareParams shareParams = new ShareParams.Builder(activity, tabTitle, pageUrl)
                                                   .setShareDirectly(false)
                                                   .setOfflineUri(uri)
                                                   .build();
@@ -396,17 +405,29 @@
     /**
      * Check to see if the offline page is sharable.
      * @param offlinePage Page to check for sharability.
+     * @param pageUri Uri of the page to check
      * @return true if this page can be shared.
      */
     public static boolean isOfflinePageShareable(
-            OfflinePageBridge offlinePageBridge, OfflinePageItem offlinePage) {
+            OfflinePageBridge offlinePageBridge, OfflinePageItem offlinePage, String pageUri) {
         // Return false if there is no offline page or sharing is not enabled.
         if (offlinePage == null || !OfflinePageBridge.isPageSharingEnabled()) return false;
 
-        // We cannot share a file without a file path, so return false.
-        // TODO(petewil) Allow sharing if there is a content or file URI, even if there is no path.
-        // https://crbug.com/817608
         String offlinePath = offlinePage.getFilePath();
+        Uri uri = Uri.parse(pageUri);
+
+        // If we have a content or file Uri, then we can share the page.
+        if (isSchemeContentOrFile(uri)) {
+            assert offlinePath.isEmpty();
+            return true;
+        }
+
+        // If the scheme is not one we recognize, return false.
+        if (!TextUtils.equals(uri.getScheme(), UrlConstants.HTTP_SCHEME)
+                && !TextUtils.equals(uri.getScheme(), UrlConstants.HTTPS_SCHEME))
+            return false;
+
+        // If we have a http or https page with no file path, we cannot share it.
         if (offlinePath.isEmpty()) {
             Log.w(TAG, "Tried to share a page with no path.");
             return false;
@@ -418,6 +439,14 @@
         return true;
     }
 
+    // Returns true if the scheme of the URI is either content or file.
+    private static boolean isSchemeContentOrFile(Uri uri) {
+        boolean isContentScheme = TextUtils.equals(uri.getScheme(), UrlConstants.CONTENT_SCHEME);
+        boolean isFileScheme = TextUtils.equals(uri.getScheme(), UrlConstants.FILE_SCHEME);
+
+        return isContentScheme || isFileScheme;
+    }
+
     /**
      * Retrieves the extra request header to reload the offline page.
      * @param tab The current tab.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
index 519c458..7987743 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -1014,7 +1014,7 @@
             if (NativePageFactory.isNativePageUrl(currentUrl, mToolbarDataProvider.isIncognito())) {
                 setUrlBarText("", null);
             } else {
-                setUrlBarText(mToolbarDataProvider.getText(), currentUrl);
+                setUrlBarText(mToolbarDataProvider.getDisplayText(), currentUrl);
                 selectAll();
             }
             hideSuggestions();
@@ -1055,10 +1055,13 @@
         updateNavigationButton();
         if (hasFocus) {
             if (mNativeInitialized) RecordUserAction.record("FocusLocation");
-            if (mToolbarDataProvider.isShowingUntrustedOfflinePage()) {
-                setUrlBarText("", null);
+            String editingText = mToolbarDataProvider.getEditingText();
+            if (editingText == null
+                    || !setUrlBarText(mToolbarDataProvider.getCurrentUrl(), editingText)) {
+                mUrlBar.deEmphasizeUrl();
+            } else if (editingText != null) {
+                mUrlBar.selectAll();
             }
-            mUrlBar.deEmphasizeUrl();
 
             // Explicitly tell InputMethodManager that the url bar is focused before any callbacks
             // so that it updates the active view accordingly. Otherwise, it may fail to update
@@ -1400,6 +1403,7 @@
     }
 
     private void emphasizeUrl() {
+        if (mToolbarDataProvider.isDisplayingQueryTerms()) return;
         mUrlBar.emphasizeUrl();
     }
 
@@ -2125,7 +2129,7 @@
      * @return A pair where the first item is the text without any path content (if the path was
      *         successfully found), and the second item is the path content (or null if no path
      *         was found or parsing the path failed).
-     * @see ToolbarDataProvider#getText()
+     * @see ToolbarDataProvider#getDisplayText()
      */
     // TODO(tedchoc): Move this logic into the original display text calculation.
     @VisibleForTesting
@@ -2203,13 +2207,7 @@
     private String getDisplayText() {
         if (!mToolbarDataProvider.hasTab()) return "";
 
-        String url = mToolbarDataProvider.getCurrentUrl();
-        if (NativePageFactory.isNativePageUrl(url, getCurrentTab().isIncognito())
-                || NewTabPage.isNTPUrl(url)) {
-            return "";
-        }
-
-        String displayText = mToolbarDataProvider.getText();
+        String displayText = mToolbarDataProvider.getDisplayText();
         // Because Android versions 4.2 and before lack proper RTL support,
         // force the formatted URL to render as LTR using an LRM character.
         // See: https://www.ietf.org/rfc/rfc3987.txt and crbug.com/709417
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/ExportFlow.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/ExportFlow.java
new file mode 100644
index 0000000..30d7115
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/ExportFlow.java
@@ -0,0 +1,635 @@
+// Copyright 2018 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.
+
+package org.chromium.chrome.browser.preferences.password;
+
+import android.app.Activity;
+import android.app.FragmentManager;
+import android.content.ActivityNotFoundException;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.support.annotation.IntDef;
+import android.support.annotation.Nullable;
+import android.support.v7.app.AlertDialog;
+import android.text.TextUtils;
+
+import org.chromium.base.ContentUriUtils;
+import org.chromium.base.ContextUtils;
+import org.chromium.base.VisibleForTesting;
+import org.chromium.base.metrics.RecordHistogram;
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.ChromeFeatureList;
+import org.chromium.ui.widget.Toast;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * This class allows to trigger and complete the UX flow for exporting passwords. A {@link Fragment}
+ * can use it to display the flow UI over the fragment.
+ *
+ * Internally, the flow is represented by the following calls:
+ * (1)  {@link #startExporting}, which triggers both preparing of stored passwords in the background
+ *      and reauthentication of the user.
+ * (2a) {@link #shareSerializedPasswords}, which is part of the preparation of passwords. It is
+ *      invoked when the native code sends the serialised passwords in CSV format. This method
+ *      continues with saving that data into a cache file and producing a sharing URI ({@link
+ *      mExportFileUri}) for that file.
+ * (2b) {@link #exportAfterReauth} is the user-visible next step after reauthentication. It displays
+ *      a warning dialog, requesting the user to confirm that they indeed want to export the
+ *      passwords.
+ * (3)  {@link #tryExporting} merges the flow of the in-parallel-running (2a) and (2b). In the rare
+ *      case when (2b) finishes before (2a), it also displays a progress bar.
+ * (4)  {@link #sendExportIntent} creates an intent chooser for sharing the exported passwords with
+ *      an app of user's choice.
+ */
+public class ExportFlow {
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({EXPORT_STATE_INACTIVE, EXPORT_STATE_REQUESTED, EXPORT_STATE_CONFIRMED})
+    private @interface ExportState {}
+    /**
+     * EXPORT_STATE_INACTIVE: there is no currently running export. Either the user did not request
+     * one, or the last one completed (i.e., a share intent picker or an error message were
+     * displayed or the user cancelled it).
+     */
+    private static final int EXPORT_STATE_INACTIVE = 0;
+    /**
+     * EXPORT_STATE_REQUESTED: the user requested the export in the menu but did not authenticate
+     * and confirm it yet.
+     */
+    private static final int EXPORT_STATE_REQUESTED = 1;
+    /**
+     * EXPORT_STATE_CONFIRMED: the user confirmed the export and Chrome is still busy preparing the
+     * data for the share intent.
+     */
+    private static final int EXPORT_STATE_CONFIRMED = 2;
+
+    /** Describes at which state the password export flow is. */
+    @ExportState
+    private int mExportState;
+
+    /** Name of the feature controlling the password export functionality. */
+    private static final String EXPORT_PASSWORDS = "PasswordExport";
+
+    /** Name of the subdirectory in cache which stores the exported passwords file. */
+    private static final String PASSWORDS_CACHE_DIR = "/passwords";
+
+    /** The key for saving {@link #mExportState} to instance bundle. */
+    private static final String SAVED_STATE_EXPORT_STATE = "saved-state-export-state";
+
+    /** The key for saving {@link #mEntriesCount}|to instance bundle. */
+    private static final String SAVED_STATE_ENTRIES_COUNT = "saved-state-entries-count";
+
+    /** The key for saving {@link #mExportFileUri} to instance bundle. */
+    private static final String SAVED_STATE_EXPORT_FILE_URI = "saved-state-export-file-uri";
+
+    // Potential values of the histogram recording the result of exporting. This needs to match
+    // ExportPasswordsResult from
+    // //components/password_manager/core/browser/password_manager_metrics_util.h.
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({EXPORT_RESULT_SUCCESS, EXPORT_RESULT_USER_ABORTED, EXPORT_RESULT_WRITE_FAILED,
+            EXPORT_RESULT_NO_CONSUMER})
+    @VisibleForTesting
+    public @interface HistogramExportResult {}
+    @VisibleForTesting
+    public static final int EXPORT_RESULT_SUCCESS = 0;
+    @VisibleForTesting
+    public static final int EXPORT_RESULT_USER_ABORTED = 1;
+    @VisibleForTesting
+    public static final int EXPORT_RESULT_WRITE_FAILED = 2;
+    @VisibleForTesting
+    public static final int EXPORT_RESULT_NO_CONSUMER = 3;
+    // If you add new values to HistogramExportResult, also update EXPORT_RESULT_COUNT to match its
+    // new size.
+    private static final int EXPORT_RESULT_COUNT = 4;
+
+    /**
+     * When the user requests that passwords are exported and once the passwords are sent over from
+     * native code and stored in a cache file, this variable contains the content:// URI for that
+     * cache file, or an empty URI if there was a problem with storing to that file. During all
+     * other times, this variable is null. In particular, after the export is requested, the
+     * variable being null means that the passwords have not arrived from the native code yet.
+     */
+    @Nullable
+    private Uri mExportFileUri;
+
+    /**
+     * Just before the exporting flow requests the passwords to be serialized by the native code,
+     * this timestamp is assigned the result of System.currentTimeMillis().
+     */
+    private long mExportPreparationStart;
+
+    /**
+     * The number of password entries contained in the most recent serialized data for password
+     * export.
+     */
+    private int mEntriesCount;
+
+    // Histogram values for "PasswordManager.Android.ExportPasswordsProgressBarUsage". Never remove
+    // or reuse them, only add new ones if needed (and update PROGRESS_COUNT), to keep past and
+    // future UMA reports compatible.
+    @VisibleForTesting
+    public static final int PROGRESS_NOT_SHOWN = 0;
+    @VisibleForTesting
+    public static final int PROGRESS_HIDDEN_DIRECTLY = 1;
+    @VisibleForTesting
+    public static final int PROGRESS_HIDDEN_DELAYED = 2;
+    // The number of the other PROGRESS_* constants.
+    private static final int PROGRESS_COUNT = 3;
+
+    /**
+     * Converts a {@link DialogManager.HideActions} value to a value for the
+     * "PasswordManager.Android.ExportPasswordsProgressBarUsage" histogram.
+     */
+    private int actionToHistogramValue(@DialogManager.HideActions int action) {
+        switch (action) {
+            case DialogManager.ACTION_NO_OP:
+                return PROGRESS_NOT_SHOWN;
+            case DialogManager.ACTION_HIDDEN_IMMEDIATELY:
+                return PROGRESS_HIDDEN_DIRECTLY;
+            case DialogManager.ACTION_HIDING_DELAYED:
+                return PROGRESS_HIDDEN_DELAYED;
+        }
+        // All cases should be covered by the above switch statement.
+        assert false;
+        return PROGRESS_NOT_SHOWN;
+    }
+
+    // Takes care of displaying and hiding the progress bar for exporting, while avoiding
+    // flickering.
+    private final DialogManager mProgressBarManager =
+            new DialogManager((@DialogManager.HideActions int action) -> {
+                RecordHistogram.recordEnumeratedHistogram(
+                        "PasswordManager.Android.ExportPasswordsProgressBarUsage",
+                        actionToHistogramValue(action), PROGRESS_COUNT);
+            });
+
+    /**
+     * If an error dialog should be shown, this contains the arguments for it, such as the error
+     * message. If no error dialog should be shown, this is null.
+     */
+    @Nullable
+    private ExportErrorDialogFragment.ErrorDialogParams mErrorDialogParams;
+
+    /**
+     * Contains the reference to the export warning dialog when it is displayed, so that the dialog
+     * can be dismissed if Chrome goes to background (without being killed) and is restored too late
+     * for the reauthentication time window to still allow exporting. It is null during all other
+     * times.
+     */
+    @Nullable
+    private ExportWarningDialogFragment mExportWarningDialogFragment;
+
+    public DialogManager getDialogManagerForTesting() {
+        return mProgressBarManager;
+    }
+
+    /** The delegate to provide ExportFlow with essential information from the owning fragment. */
+    public interface Delegate {
+        /**
+         * @return The activity associated with the owning fragment.
+         */
+        Activity getActivity();
+
+        /**
+         * @return The fragment manager associated with the owning fragment.
+         */
+        FragmentManager getFragmentManager();
+
+        /**
+         * @return The ID of the root view of the owning fragment.
+         */
+        int getViewId();
+    }
+
+    /** The concrete delegate instance. It is (re)set in {@link #onCreate}. */
+    private Delegate mDelegate;
+
+    /**
+     * A hook to be used in the onCreate method of the owning {@link Fragment}. I restores the state
+     * of the flow.
+     * @param savedInstanceState The {@link Bundle} passed from the fragment's onCreate
+     * method.
+     * @param delegate The {@link Delegate} for this ExportFlow.
+     */
+    public void onCreate(Bundle savedInstanceState, Delegate delegate) {
+        mDelegate = delegate;
+
+        if (savedInstanceState == null) return;
+
+        if (savedInstanceState.containsKey(SAVED_STATE_EXPORT_STATE)) {
+            mExportState = savedInstanceState.getInt(SAVED_STATE_EXPORT_STATE);
+            if (mExportState == EXPORT_STATE_CONFIRMED) {
+                // If export is underway, ensure that the UI is updated.
+                tryExporting();
+            }
+        }
+        if (savedInstanceState.containsKey(SAVED_STATE_EXPORT_FILE_URI)) {
+            String uriString = savedInstanceState.getString(SAVED_STATE_EXPORT_FILE_URI);
+            if (uriString.isEmpty()) {
+                mExportFileUri = Uri.EMPTY;
+            } else {
+                mExportFileUri = Uri.parse(uriString);
+            }
+        }
+        mEntriesCount = savedInstanceState.getInt(SAVED_STATE_ENTRIES_COUNT);
+    }
+
+    /**
+     * Returns true if the export flow is in progress, i.e., when the user interacts with some of
+     * its UI.
+     * @return True if in progress, false otherwise.
+     */
+    public boolean isActive() {
+        return mExportState != EXPORT_STATE_INACTIVE;
+    }
+
+    /**
+     * An encapsulation of a URI and an error string, used by the processing in
+     * exportPasswordsIntoFile.
+     */
+    private static class ExportResult {
+        /** URI representing a successful result. It is invalid when the result is an error.*/
+        public final Uri mUri;
+
+        /** The description of an error result. Null if the result is a success. */
+        @Nullable
+        public final String mError;
+
+        /** Constructs the successful result: a valid URI and no error. */
+        public ExportResult(Uri uri) {
+            assert uri != null && !uri.equals(Uri.EMPTY);
+            mUri = uri;
+            mError = null;
+        }
+
+        /** Constructs the failed result: an empty URI and a non-empty error string. */
+        public ExportResult(String error) {
+            assert !TextUtils.isEmpty(error);
+            mUri = Uri.EMPTY;
+            mError = error;
+        }
+    }
+
+    /**
+     * A helper method which first fires an {@link AsyncTask} to turn the string with serialized
+     * passwords into a cache file with a shareable URI, and then, depending on success, either
+     * calls the code for firing the share intent or displays an error.
+     * @param serializedPasswords A string with a CSV representation of the user's passwords.
+     */
+    private void shareSerializedPasswords(byte[] serializedPasswords) {
+        AsyncTask<byte[], Void, ExportResult> task = new AsyncTask<byte[], Void, ExportResult>() {
+            @Override
+            protected ExportResult doInBackground(byte[]... serializedPasswords) {
+                assert serializedPasswords.length == 1;
+                // Record the time it took to read and serialise the passwords. This excludes the
+                // time to write them into a file, to be consistent with desktop (where writing is
+                // blocked on the user choosing a file destination).
+                RecordHistogram.recordMediumTimesHistogram(
+                        "PasswordManager.TimeReadingExportedPasswords",
+                        System.currentTimeMillis() - mExportPreparationStart,
+                        TimeUnit.MILLISECONDS);
+                return exportPasswordsIntoFile(serializedPasswords[0]);
+            }
+
+            @Override
+            protected void onPostExecute(ExportResult result) {
+                // Don't display any UI if the user cancelled the export in the meantime.
+                if (mExportState == EXPORT_STATE_INACTIVE) return;
+
+                if (result.mError != null) {
+                    showExportErrorAndAbort(R.string.save_password_preferences_export_tips,
+                            result.mError, R.string.try_again, EXPORT_RESULT_WRITE_FAILED);
+                } else {
+                    mExportFileUri = result.mUri;
+                    tryExporting();
+                }
+            }
+        };
+        task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, serializedPasswords);
+    }
+
+    /** Starts the password export flow.
+     * Current state of export flow: the user just tapped the menu item for export
+     * The next steps are: passing reauthentication, confirming the export, waiting for exported
+     * data (if needed) and choosing a consumer app for the data.
+     */
+    public void startExporting() {
+        assert mExportState == EXPORT_STATE_INACTIVE;
+        // Disable re-triggering exporting until the current exporting finishes.
+        mExportState = EXPORT_STATE_REQUESTED;
+
+        // Start fetching the serialized passwords now to use the time the user spends
+        // reauthenticating and reading the warning message. If the user cancels the export or
+        // fails the reauthentication, the serialised passwords will simply get ignored when
+        // they arrive.
+        mExportPreparationStart = System.currentTimeMillis();
+        PasswordManagerHandlerProvider.getInstance().getPasswordManagerHandler().serializePasswords(
+                new ByteArrayIntCallback() {
+                    @Override
+                    public void onResult(byte[] byteArray, int number) {
+                        mEntriesCount = number;
+                        shareSerializedPasswords(byteArray);
+                    }
+                });
+        if (!ReauthenticationManager.isScreenLockSetUp(
+                    mDelegate.getActivity().getApplicationContext())) {
+            Toast.makeText(mDelegate.getActivity().getApplicationContext(),
+                         R.string.password_export_set_lock_screen, Toast.LENGTH_LONG)
+                    .show();
+            // Re-enable exporting, the current one was cancelled by Chrome.
+            mExportState = EXPORT_STATE_INACTIVE;
+        } else {
+            // Always trigger reauthentication at the start of the exporting flow, even if the last
+            // one succeeded recently.
+            ReauthenticationManager.displayReauthenticationFragment(
+                    R.string.lockscreen_description_export, mDelegate.getViewId(),
+                    mDelegate.getFragmentManager(), ReauthenticationManager.REAUTH_SCOPE_BULK);
+        }
+    }
+
+    /**
+     * Continues with the password export flow after the user successfully reauthenticated.
+     * Current state of export flow: the user tapped the menu item for export and passed
+     * reauthentication. The next steps are: confirming the export, waiting for exported data (if
+     * needed) and choosing a consumer app for the data.
+     */
+    private void exportAfterReauth() {
+        assert mExportWarningDialogFragment == null;
+        mExportWarningDialogFragment = new ExportWarningDialogFragment();
+        mExportWarningDialogFragment.setExportWarningHandler(
+                new ExportWarningDialogFragment.Handler() {
+                    /**
+                     * On positive button response asks the parent to continue with the export flow.
+                     */
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        if (which == AlertDialog.BUTTON_POSITIVE) {
+                            mExportState = EXPORT_STATE_CONFIRMED;
+                            // If the error dialog has been waiting, display it now, otherwise
+                            // continue the export flow.
+                            if (mErrorDialogParams != null) {
+                                showExportErrorDialogFragment();
+                            } else {
+                                tryExporting();
+                            }
+                        } else if (which == AlertDialog.BUTTON_NEGATIVE) {
+                            RecordHistogram.recordEnumeratedHistogram(
+                                    "PasswordManager.ExportPasswordsToCSVResult",
+                                    EXPORT_RESULT_USER_ABORTED, EXPORT_RESULT_COUNT);
+                        }
+                    }
+
+                    /**
+                     * Mark the dismissal of the dialog, so that waiting UI (such as error
+                     * reporting) can be shown.
+                     */
+                    @Override
+                    public void onDismiss() {
+                        // Unless the positive button action moved the exporting state forward,
+                        // cancel the export. This happens both when the user taps the negative
+                        // button or when they tap outside of the dialog to dismiss it.
+                        if (mExportState != EXPORT_STATE_CONFIRMED) {
+                            mExportState = EXPORT_STATE_INACTIVE;
+                        }
+
+                        mExportWarningDialogFragment = null;
+                        // If the error dialog has been waiting, display it now.
+                        if (mErrorDialogParams != null) showExportErrorDialogFragment();
+                    }
+                });
+        mExportWarningDialogFragment.show(mDelegate.getFragmentManager(), null);
+    }
+
+    /**
+     * Starts the exporting intent if both blocking events are completed: serializing and the
+     * confirmation flow.
+     * At this point, the user the user has tapped the menu item for export and passed
+     * reauthentication. Upon calling this method, the user has either also confirmed the export, or
+     * the exported data have been prepared. The method is called twice, once for each of those
+     * events. The next step after both the export is confirmed and the data is ready is to offer
+     * the user an intent chooser for sharing the exported passwords.
+     */
+    private void tryExporting() {
+        if (mExportState != EXPORT_STATE_CONFIRMED) return;
+        if (mExportFileUri == null) {
+            // The serialization has not finished. Until this finishes, a progress bar is
+            // displayed with an option to cancel the export.
+            ProgressBarDialogFragment progressBarDialogFragment = new ProgressBarDialogFragment();
+            progressBarDialogFragment.setCancelProgressHandler(
+                    new DialogInterface.OnClickListener() {
+                        @Override
+                        public void onClick(DialogInterface dialog, int which) {
+                            if (which == AlertDialog.BUTTON_NEGATIVE) {
+                                mExportState = EXPORT_STATE_INACTIVE;
+                                RecordHistogram.recordEnumeratedHistogram(
+                                        "PasswordManager.ExportPasswordsToCSVResult",
+                                        EXPORT_RESULT_USER_ABORTED, EXPORT_RESULT_COUNT);
+                            }
+                        }
+                    });
+            mProgressBarManager.show(progressBarDialogFragment, mDelegate.getFragmentManager());
+        } else {
+            // Note: if the serialization is quicker than the user interacting with the
+            // confirmation dialog, then there is no progress bar shown, in which case hide() is
+            // just calling the callback synchronously.
+            // TODO(crbug.com/821377) -- remove clang-format pragmas
+            // clang-format off
+            mProgressBarManager.hide(this::sendExportIntent);
+            // clang-format on
+        }
+    }
+
+    /**
+     * Call this to abort the export UI flow and display an error description to the user.
+     * @param descriptionId The resource ID of a string with a brief explanation of the error.
+     * @param detailedDescription An optional string with more technical details about the error.
+     * @param positiveButtonLabelId The resource ID of the label of the positive button in the error
+     * dialog.
+     */
+    @VisibleForTesting
+    public void showExportErrorAndAbort(int descriptionId, @Nullable String detailedDescription,
+            int positiveButtonLabelId, @HistogramExportResult int histogramExportResult) {
+        assert mErrorDialogParams == null;
+        mProgressBarManager.hide(() -> {
+            showExportErrorAndAbortImmediately(descriptionId, detailedDescription,
+                    positiveButtonLabelId, histogramExportResult);
+        });
+    }
+
+    public void showExportErrorAndAbortImmediately(int descriptionId,
+            @Nullable String detailedDescription, int positiveButtonLabelId,
+            @HistogramExportResult int histogramExportResult) {
+        RecordHistogram.recordEnumeratedHistogram("PasswordManager.ExportPasswordsToCSVResult",
+                histogramExportResult, EXPORT_RESULT_COUNT);
+
+        mErrorDialogParams = new ExportErrorDialogFragment.ErrorDialogParams();
+        mErrorDialogParams.positiveButtonLabelId = positiveButtonLabelId;
+        mErrorDialogParams.description =
+                mDelegate.getActivity().getResources().getString(descriptionId);
+
+        if (detailedDescription != null) {
+            mErrorDialogParams.detailedDescription =
+                    mDelegate.getActivity().getResources().getString(
+                            R.string.save_password_preferences_export_error_details,
+                            detailedDescription);
+        }
+
+        if (mExportWarningDialogFragment == null) showExportErrorDialogFragment();
+    }
+
+    /**
+     * This is a helper method to {@link #showExportErrorAndAbort}, responsible for showing the
+     * actual UI.
+     */
+    private void showExportErrorDialogFragment() {
+        assert mErrorDialogParams != null;
+
+        ExportErrorDialogFragment exportErrorDialogFragment = new ExportErrorDialogFragment();
+        int positiveButtonLabelId = mErrorDialogParams.positiveButtonLabelId;
+        exportErrorDialogFragment.initialize(mErrorDialogParams);
+        mErrorDialogParams = null;
+
+        exportErrorDialogFragment.setExportErrorHandler(new DialogInterface.OnClickListener() {
+            @Override
+            public void onClick(DialogInterface dialog, int which) {
+                if (which == AlertDialog.BUTTON_POSITIVE) {
+                    if (positiveButtonLabelId
+                            == R.string.save_password_preferences_export_learn_google_drive) {
+                        // Link to the help article about how to use Google Drive.
+                        Intent intent = new Intent(Intent.ACTION_VIEW,
+                                Uri.parse("https://support.google.com/drive/answer/2424384"));
+                        intent.setPackage(mDelegate.getActivity().getPackageName());
+                        mDelegate.getActivity().startActivity(intent);
+                    } else if (positiveButtonLabelId == R.string.try_again) {
+                        mExportState = EXPORT_STATE_REQUESTED;
+                        exportAfterReauth();
+                    }
+                } else if (which == AlertDialog.BUTTON_NEGATIVE) {
+                    // Re-enable exporting, the current one was just cancelled.
+                    mExportState = EXPORT_STATE_INACTIVE;
+                }
+            }
+        });
+        exportErrorDialogFragment.show(mDelegate.getFragmentManager(), null);
+    }
+
+    /**
+     * This method saves the contents of |serializedPasswords| into a temporary file and returns a
+     * sharing URI for it. In case of failure, returns EMPTY. It should only be run on the
+     * background thread of an AsyncTask, because it does I/O operations.
+     * @param serializedPasswords A byte array with serialized passwords in CSV format
+     */
+    private ExportResult exportPasswordsIntoFile(byte[] serializedPasswords) {
+        // First ensure that the PASSWORDS_CACHE_DIR cache directory exists.
+        File passwordsDir =
+                new File(ContextUtils.getApplicationContext().getCacheDir() + PASSWORDS_CACHE_DIR);
+        passwordsDir.mkdir();
+        // Now create or overwrite the temporary file for exported passwords there and return its
+        // content:// URI.
+        File tempFile;
+        try {
+            tempFile = File.createTempFile("pwd-export", ".csv", passwordsDir);
+        } catch (IOException e) {
+            return new ExportResult(e.getMessage());
+        }
+        tempFile.deleteOnExit();
+        try (BufferedOutputStream outputStream =
+                        new BufferedOutputStream(new FileOutputStream(tempFile))) {
+            outputStream.write(serializedPasswords);
+        } catch (IOException e) {
+            return new ExportResult(e.getMessage());
+        }
+        try {
+            return new ExportResult(ContentUriUtils.getContentUriFromFile(tempFile));
+        } catch (IllegalArgumentException e) {
+            return new ExportResult(e.getMessage());
+        }
+    }
+
+    /**
+     * If the URI of the file with exported passwords is not null, passes it into an implicit
+     * intent, so that the user can use a storage app to save the exported passwords.
+     */
+    private void sendExportIntent() {
+        assert mExportState == EXPORT_STATE_CONFIRMED;
+        mExportState = EXPORT_STATE_INACTIVE;
+
+        if (mExportFileUri.equals(Uri.EMPTY)) return;
+
+        Intent send = new Intent(Intent.ACTION_SEND);
+        send.setType("text/csv");
+        send.putExtra(Intent.EXTRA_STREAM, mExportFileUri);
+        send.putExtra(Intent.EXTRA_SUBJECT,
+                mDelegate.getActivity().getResources().getString(
+                        R.string.save_password_preferences_export_subject));
+
+        try {
+            Intent chooser = Intent.createChooser(send, null);
+            chooser.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            ContextUtils.getApplicationContext().startActivity(chooser);
+            RecordHistogram.recordEnumeratedHistogram("PasswordManager.ExportPasswordsToCSVResult",
+                    EXPORT_RESULT_SUCCESS, EXPORT_RESULT_COUNT);
+            RecordHistogram.recordCountHistogram(
+                    "PasswordManager.ExportedPasswordsPerUserInCSV", mEntriesCount);
+        } catch (ActivityNotFoundException e) {
+            showExportErrorAndAbort(R.string.save_password_preferences_export_no_app, null,
+                    R.string.save_password_preferences_export_learn_google_drive,
+                    EXPORT_RESULT_NO_CONSUMER);
+        }
+        mExportFileUri = null;
+    }
+
+    /**
+     * A hook to be used in a {@link Fragment}'s onResume method. I processes the result of the
+     * reauthentication.
+     */
+    public void onResume() {
+        if (mExportState == EXPORT_STATE_REQUESTED) {
+            // If Chrome returns to foreground from being paused (but without being killed), and
+            // exportAfterReauth was called before pausing, the warning dialog is still
+            // displayed and ready to be used, and this is indicated by
+            // |mExportWarningDialogFragment| being non-null.
+            if (ReauthenticationManager.authenticationStillValid(
+                        ReauthenticationManager.REAUTH_SCOPE_BULK)) {
+                if (mExportWarningDialogFragment == null) exportAfterReauth();
+            } else {
+                if (mExportWarningDialogFragment != null) mExportWarningDialogFragment.dismiss();
+                RecordHistogram.recordEnumeratedHistogram(
+                        "PasswordManager.ExportPasswordsToCSVResult", EXPORT_RESULT_USER_ABORTED,
+                        EXPORT_RESULT_COUNT);
+                mExportState = EXPORT_STATE_INACTIVE;
+            }
+        }
+    }
+
+    /**
+     * A hook to be used in a {@link Fragment}'s onSaveInstanceState method. I saves the state of
+     * the flow.
+     */
+    public void onSaveInstanceState(Bundle outState) {
+        outState.putInt(SAVED_STATE_EXPORT_STATE, mExportState);
+        outState.putInt(SAVED_STATE_ENTRIES_COUNT, mEntriesCount);
+        if (mExportFileUri != null) {
+            outState.putString(SAVED_STATE_EXPORT_FILE_URI, mExportFileUri.toString());
+        }
+    }
+
+    /**
+     * Returns whether the password export feature is ready to use.
+     * @return Returns true if the flag is set and the Reauthentication Api is available.
+     */
+    public static boolean providesPasswordExport() {
+        return ChromeFeatureList.isEnabled(EXPORT_PASSWORDS)
+                && ReauthenticationManager.isReauthenticationApiAvailable();
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferences.java
index 43a3b7e..62d817c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferences.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferences.java
@@ -4,14 +4,13 @@
 
 package org.chromium.chrome.browser.preferences.password;
 
-import android.content.ActivityNotFoundException;
-import android.content.DialogInterface;
+import android.app.Activity;
+import android.app.FragmentManager;
 import android.content.Intent;
 import android.graphics.Color;
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
-import android.os.AsyncTask;
 import android.os.Bundle;
 import android.preference.Preference;
 import android.preference.Preference.OnPreferenceChangeListener;
@@ -19,12 +18,8 @@
 import android.preference.PreferenceFragment;
 import android.preference.PreferenceGroup;
 import android.preference.PreferenceScreen;
-import android.support.annotation.IntDef;
-import android.support.annotation.Nullable;
-import android.support.v7.app.AlertDialog;
 import android.support.v7.widget.SearchView;
 import android.text.SpannableString;
-import android.text.TextUtils;
 import android.text.style.ForegroundColorSpan;
 import android.view.Menu;
 import android.view.MenuInflater;
@@ -33,8 +28,6 @@
 import android.view.inputmethod.EditorInfo;
 
 import org.chromium.base.ApiCompatibilityUtils;
-import org.chromium.base.ContentUriUtils;
-import org.chromium.base.ContextUtils;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.chrome.R;
@@ -48,16 +41,8 @@
 import org.chromium.chrome.browser.preferences.PreferencesLauncher;
 import org.chromium.chrome.browser.preferences.TextMessagePreference;
 import org.chromium.ui.text.SpanApplier;
-import org.chromium.ui.widget.Toast;
 
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 import java.util.Locale;
-import java.util.concurrent.TimeUnit;
 
 /**
  * The "Save passwords" screen in Settings, which allows the user to enable or disable password
@@ -66,27 +51,6 @@
 public class SavePasswordsPreferences
         extends PreferenceFragment implements PasswordManagerHandler.PasswordListObserver,
                                               Preference.OnPreferenceClickListener {
-    // ExportState describes at which state a password export is.
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({EXPORT_STATE_INACTIVE, EXPORT_STATE_REQUESTED, EXPORT_STATE_CONFIRMED})
-    private @interface ExportState {}
-    /**
-     * EXPORT_STATE_INACTIVE: there is no currently running export. Either the user did not request
-     * one, or the last one completed (i.e., a share intent picker or an error message were
-     * displayed or the user cancelled it).
-     */
-    private static final int EXPORT_STATE_INACTIVE = 0;
-    /**
-     * EXPORT_STATE_REQUESTED: the user requested the export in the menu but did not authenticate
-     * and confirm it yet.
-     */
-    private static final int EXPORT_STATE_REQUESTED = 1;
-    /**
-     * EXPORT_STATE_CONFIRMED: the user confirmed the export and Chrome is still busy preparing the
-     * data for the share intent.
-     */
-    private static final int EXPORT_STATE_CONFIRMED = 2;
-
     // Keys for name/password dictionaries.
     public static final String PASSWORD_LIST_URL = "url";
     public static final String PASSWORD_LIST_NAME = "name";
@@ -98,15 +62,6 @@
     // The key for saving |mSearchQuery| to instance bundle.
     private static final String SAVED_STATE_SEARCH_QUERY = "saved-state-search-query";
 
-    // The key for saving |mExportState| to instance bundle.
-    private static final String SAVED_STATE_EXPORT_STATE = "saved-state-export-state";
-
-    // The key for saving |mEntriesCount| to instance bundle.
-    private static final String SAVED_STATE_ENTRIES_COUNT = "saved-state-entries-count";
-
-    // The key for saving |mExportFileUri| to instance bundle.
-    private static final String SAVED_STATE_EXPORT_FILE_URI = "saved-state-export-file-uri";
-
     public static final String PREF_SAVE_PASSWORDS_SWITCH = "save_passwords_switch";
     public static final String PREF_AUTOSIGNIN_SWITCH = "autosignin_switch";
 
@@ -119,32 +74,6 @@
     private static final String PREF_KEY_MANAGE_ACCOUNT_LINK = "manage_account_link";
     private static final String PREF_KEY_SAVED_PASSWORDS_NO_TEXT = "saved_passwords_no_text";
 
-    // Name of the feature controlling the password export functionality.
-    private static final String EXPORT_PASSWORDS = "PasswordExport";
-
-    // Name of the subdirectory in cache which stores the exported passwords file.
-    private static final String PASSWORDS_CACHE_DIR = "/passwords";
-
-    // Potential values of the histogram recording the result of exporting. This needs to match
-    // ExportPasswordsResult from
-    // //components/password_manager/core/browser/password_manager_metrics_util.h.
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({EXPORT_RESULT_SUCCESS, EXPORT_RESULT_USER_ABORTED, EXPORT_RESULT_WRITE_FAILED,
-            EXPORT_RESULT_NO_CONSUMER})
-    @VisibleForTesting
-    public @interface HistogramExportResult {}
-    @VisibleForTesting
-    public static final int EXPORT_RESULT_SUCCESS = 0;
-    @VisibleForTesting
-    public static final int EXPORT_RESULT_USER_ABORTED = 1;
-    @VisibleForTesting
-    public static final int EXPORT_RESULT_WRITE_FAILED = 2;
-    @VisibleForTesting
-    public static final int EXPORT_RESULT_NO_CONSUMER = 3;
-    // If you add new values to HistogramExportResult, also update EXPORT_RESULT_COUNT to match its
-    // new size.
-    private static final int EXPORT_RESULT_COUNT = 4;
-
     private static final int ORDER_SWITCH = 0;
     private static final int ORDER_AUTO_SIGNIN_CHECKBOX = 1;
     private static final int ORDER_MANAGE_ACCOUNT_LINK = 2;
@@ -155,25 +84,6 @@
     private boolean mNoPasswords;
     private boolean mNoPasswordExceptions;
 
-    @ExportState
-    private int mExportState;
-
-    // When the user requests that passwords are exported and once the passwords are sent over from
-    // native code and stored in a cache file, this variable contains the content:// URI for that
-    // cache file, or an empty URI if there was a problem with storing to that file. During all
-    // other times, this variable is null. In particular, after the export is requested, the
-    // variable being null means that the passwords have not arrived from the native code yet.
-    @Nullable
-    private Uri mExportFileUri;
-
-    // Just before the exporting flow requests the passwords to be serialized by the native code,
-    // this timestamp is assigned the result of System.currentTimeMillis().
-    private Long mExportPreparationStart;
-
-    // The number of password entries contained in the most recent serialized data for password
-    // export.
-    private int mEntriesCount;
-
     private MenuItem mHelpItem;
 
     private String mSearchQuery;
@@ -184,91 +94,46 @@
     private boolean mSearchRecorded;
     private Menu mMenuForTesting;
 
-    // Histogram values for "PasswordManager.Android.ExportPasswordsProgressBarUsage". Never remove
-    // or reuse them, only add new ones if needed (and update PROGRESS_COUNT), to keep past and
-    // future UMA reports compatible.
-    @VisibleForTesting
-    public static final int PROGRESS_NOT_SHOWN = 0;
-    @VisibleForTesting
-    public static final int PROGRESS_HIDDEN_DIRECTLY = 1;
-    @VisibleForTesting
-    public static final int PROGRESS_HIDDEN_DELAYED = 2;
-    // The number of the other PROGRESS_* constants.
-    private static final int PROGRESS_COUNT = 3;
-
     /**
-     * Converts a {@link DialogManager.HideActions} value to a value for the
-     * "PasswordManager.Android.ExportPasswordsProgressBarUsage" histogram.
+     * For controlling the UX flow of exporting passwords.
      */
-    private int actionToHistogramValue(@DialogManager.HideActions int action) {
-        switch (action) {
-            case DialogManager.ACTION_NO_OP:
-                return PROGRESS_NOT_SHOWN;
-            case DialogManager.ACTION_HIDDEN_IMMEDIATELY:
-                return PROGRESS_HIDDEN_DIRECTLY;
-            case DialogManager.ACTION_HIDING_DELAYED:
-                return PROGRESS_HIDDEN_DELAYED;
-        }
-        // All cases should be covered by the above switch statement.
-        assert false;
-        return PROGRESS_NOT_SHOWN;
-    }
+    private ExportFlow mExportFlow = new ExportFlow();
 
-    // Takes care of displaying and hiding the progress bar for exporting, while avoiding
-    // flickering.
-    private final DialogManager mProgressBarManager =
-            new DialogManager((@DialogManager.HideActions int action) -> {
-                RecordHistogram.recordEnumeratedHistogram(
-                        "PasswordManager.Android.ExportPasswordsProgressBarUsage",
-                        actionToHistogramValue(action), PROGRESS_COUNT);
-            });
-
-    // If an error dialog should be shown, this contains the arguments for it, such as the error
-    // message. If no error dialog should be shown, this is null.
-    @Nullable
-    private ExportErrorDialogFragment.ErrorDialogParams mErrorDialogParams;
-
-    // Contains the reference to the export warning dialog when it is displayed, so that the dialog
-    // can be dismissed if Chrome goes to background (without being killed) and is restored too late
-    // for the reauthentication time window to still allow exporting. It is null during all other
-    // times.
-    private ExportWarningDialogFragment mExportWarningDialogFragment;
-
-    public DialogManager getDialogManagerForTesting() {
-        return mProgressBarManager;
+    public ExportFlow getExportFlowForTesting() {
+        return mExportFlow;
     }
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        mExportFlow.onCreate(savedInstanceState, new ExportFlow.Delegate() {
+            @Override
+            public Activity getActivity() {
+                return SavePasswordsPreferences.this.getActivity();
+            }
+
+            @Override
+            public FragmentManager getFragmentManager() {
+                return SavePasswordsPreferences.this.getFragmentManager();
+            }
+
+            @Override
+            public int getViewId() {
+                return getView().getId();
+            }
+        });
         getActivity().setTitle(R.string.prefs_saved_passwords_title);
         setPreferenceScreen(getPreferenceManager().createPreferenceScreen(getActivity()));
         PasswordManagerHandlerProvider.getInstance().addObserver(this);
 
-        setHasOptionsMenu(providesPasswordExport() || providesPasswordSearch());
+        setHasOptionsMenu(ExportFlow.providesPasswordExport() || providesPasswordSearch());
 
         if (savedInstanceState == null) return;
 
-        if (savedInstanceState.containsKey(SAVED_STATE_EXPORT_STATE)) {
-            mExportState = savedInstanceState.getInt(SAVED_STATE_EXPORT_STATE);
-            if (mExportState == EXPORT_STATE_CONFIRMED) {
-                // If export is underway, ensure that the UI is updated.
-                tryExporting();
-            }
-        }
-        if (savedInstanceState.containsKey(SAVED_STATE_EXPORT_FILE_URI)) {
-            String uriString = savedInstanceState.getString(SAVED_STATE_EXPORT_FILE_URI);
-            if (uriString.isEmpty()) {
-                mExportFileUri = Uri.EMPTY;
-            } else {
-                mExportFileUri = Uri.parse(uriString);
-            }
-        }
         if (savedInstanceState.containsKey(SAVED_STATE_SEARCH_QUERY)) {
             mSearchQuery = savedInstanceState.getString(SAVED_STATE_SEARCH_QUERY);
             mSearchRecorded = mSearchQuery != null; // We record a search when a query is set.
         }
-        mEntriesCount = savedInstanceState.getInt(SAVED_STATE_ENTRIES_COUNT);
     }
 
     @Override
@@ -276,7 +141,7 @@
         menu.clear();
         mMenuForTesting = menu;
         inflater.inflate(R.menu.save_password_preferences_action_bar_menu, menu);
-        menu.findItem(R.id.export_passwords).setVisible(providesPasswordExport());
+        menu.findItem(R.id.export_passwords).setVisible(ExportFlow.providesPasswordExport());
         menu.findItem(R.id.export_passwords).setEnabled(false);
         MenuItem searchItem = menu.findItem(R.id.menu_id_search);
         searchItem.setVisible(providesPasswordSearch());
@@ -339,346 +204,20 @@
 
     @Override
     public void onPrepareOptionsMenu(Menu menu) {
-        menu.findItem(R.id.export_passwords)
-                .setEnabled(!mNoPasswords && mExportState == EXPORT_STATE_INACTIVE);
+        menu.findItem(R.id.export_passwords).setEnabled(!mNoPasswords && !mExportFlow.isActive());
         super.onPrepareOptionsMenu(menu);
     }
 
-    // An encapsulation of a URI and an error string, used by the processing in
-    // exportPasswordsIntoFile.
-    private static class ExportResult {
-        public final Uri mUri;
-        @Nullable
-        public final String mError;
-
-        // Constructs the successful result: a valid URI and no error.
-        public ExportResult(Uri uri) {
-            assert uri != null && !uri.equals(Uri.EMPTY);
-            mUri = uri;
-            mError = null;
-        }
-
-        // Constructs the failed result: an empty URI and a non-empty error string.
-        public ExportResult(String error) {
-            assert !TextUtils.isEmpty(error);
-            mUri = Uri.EMPTY;
-            mError = error;
-        }
-    }
-
-    /**
-     * A helper method which first fires an AsyncTask to turn the string with serialized passwords
-     * into a cache file with a shareable URI, and then, depending on success, either calls the code
-     * for firing the share intent or displays an error.
-     * @param serializedPasswords A string with a CSV representation of the user's passwords.
-     */
-    private void shareSerializedPasswords(byte[] serializedPasswords) {
-        AsyncTask<byte[], Void, ExportResult> task = new AsyncTask<byte[], Void, ExportResult>() {
-            @Override
-            protected ExportResult doInBackground(byte[]... serializedPasswords) {
-                assert serializedPasswords.length == 1;
-                // Record the time it took to read and serialise the passwords. This excludes the
-                // time to write them into a file, to be consistent with desktop (where writing is
-                // blocked on the user choosing a file destination).
-                RecordHistogram.recordMediumTimesHistogram(
-                        "PasswordManager.TimeReadingExportedPasswords",
-                        System.currentTimeMillis() - mExportPreparationStart,
-                        TimeUnit.MILLISECONDS);
-                return exportPasswordsIntoFile(serializedPasswords[0]);
-            }
-
-            @Override
-            protected void onPostExecute(ExportResult result) {
-                // Don't display any UI if the user cancelled the export in the meantime.
-                if (mExportState == EXPORT_STATE_INACTIVE) return;
-
-                if (result.mError != null) {
-                    showExportErrorAndAbort(R.string.save_password_preferences_export_tips,
-                            result.mError, R.string.try_again, EXPORT_RESULT_WRITE_FAILED);
-                } else {
-                    mExportFileUri = result.mUri;
-                    tryExporting();
-                }
-            }
-        };
-        task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, serializedPasswords);
-    }
-
-    /** Starts the password export flow.
-     * Current state of export flow: the user just tapped the menu item for export
-     * The next steps are: passing reauthentication, confirming the export, waiting for exported
-     * data (if needed) and choosing a consumer app for the data.
-     */
-    private void startExporting() {
-        assert mExportState == EXPORT_STATE_INACTIVE;
-        // Disable re-triggering exporting until the current exporting finishes.
-        mExportState = EXPORT_STATE_REQUESTED;
-
-        // Start fetching the serialized passwords now to use the time the user spends
-        // reauthenticating and reading the warning message. If the user cancels the export or
-        // fails the reauthentication, the serialised passwords will simply get ignored when
-        // they arrive.
-        mExportPreparationStart = System.currentTimeMillis();
-        PasswordManagerHandlerProvider.getInstance().getPasswordManagerHandler().serializePasswords(
-                new ByteArrayIntCallback() {
-                    @Override
-                    public void onResult(byte[] byteArray, int number) {
-                        mEntriesCount = number;
-                        shareSerializedPasswords(byteArray);
-                    }
-                });
-        if (!ReauthenticationManager.isScreenLockSetUp(getActivity().getApplicationContext())) {
-            Toast.makeText(getActivity().getApplicationContext(),
-                         R.string.password_export_set_lock_screen, Toast.LENGTH_LONG)
-                    .show();
-            // Re-enable exporting, the current one was cancelled by Chrome.
-            mExportState = EXPORT_STATE_INACTIVE;
-        } else {
-            // Always trigger reauthentication at the start of the exporting flow, even if the last
-            // one succeeded recently.
-            ReauthenticationManager.displayReauthenticationFragment(
-                    R.string.lockscreen_description_export, getView().getId(), getFragmentManager(),
-                    ReauthenticationManager.REAUTH_SCOPE_BULK);
-        }
-    }
-
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         int id = item.getItemId();
         if (id == R.id.export_passwords) {
-            startExporting();
+            mExportFlow.startExporting();
             return true;
         }
         return super.onOptionsItemSelected(item);
     }
 
-    /**
-     * Continues with the password export flow after the user successfully reauthenticated.
-     * Current state of export flow: the user tapped the menu item for export and passed
-     * reauthentication. The next steps are: confirming the export, waiting for exported data (if
-     * needed) and choosing a consumer app for the data.
-     */
-    private void exportAfterReauth() {
-        assert mExportWarningDialogFragment == null;
-        mExportWarningDialogFragment = new ExportWarningDialogFragment();
-        mExportWarningDialogFragment.setExportWarningHandler(
-                new ExportWarningDialogFragment.Handler() {
-                    /**
-                     * On positive button response asks the parent to continue with the export flow.
-                     */
-                    @Override
-                    public void onClick(DialogInterface dialog, int which) {
-                        if (which == AlertDialog.BUTTON_POSITIVE) {
-                            mExportState = EXPORT_STATE_CONFIRMED;
-                            // If the error dialog has been waiting, display it now, otherwise
-                            // continue the export flow.
-                            if (mErrorDialogParams != null) {
-                                showExportErrorDialogFragment();
-                            } else {
-                                tryExporting();
-                            }
-                        } else if (which == AlertDialog.BUTTON_NEGATIVE) {
-                            RecordHistogram.recordEnumeratedHistogram(
-                                    "PasswordManager.ExportPasswordsToCSVResult",
-                                    EXPORT_RESULT_USER_ABORTED, EXPORT_RESULT_COUNT);
-                        }
-                    }
-
-                    /**
-                     * Mark the dismissal of the dialog, so that waiting UI (such as error
-                     * reporting) can be shown.
-                     */
-                    @Override
-                    public void onDismiss() {
-                        // Unless the positive button action moved the exporting state forward,
-                        // cancel the export. This happens both when the user taps the negative
-                        // button or when they tap outside of the dialog to dismiss it.
-                        if (mExportState != EXPORT_STATE_CONFIRMED) {
-                            mExportState = EXPORT_STATE_INACTIVE;
-                        }
-
-                        mExportWarningDialogFragment = null;
-                        // If the error dialog has been waiting, display it now.
-                        if (mErrorDialogParams != null) showExportErrorDialogFragment();
-                    }
-                });
-        mExportWarningDialogFragment.show(getFragmentManager(), null);
-    }
-
-    /**
-     * Starts the exporting intent if both blocking events are completed: serializing and the
-     * confirmation flow.
-     * At this point, the user the user has tapped the menu item for export and passed
-     * reauthentication. Upon calling this method, the user has either also confirmed the export, or
-     * the exported data have been prepared. The method is called twice, once for each of those
-     * events. The next step after both the export is confirmed and the data is ready is to offer
-     * the user an intent chooser for sharing the exported passwords.
-     */
-    private void tryExporting() {
-        if (mExportState != EXPORT_STATE_CONFIRMED) return;
-        if (mExportFileUri == null) {
-            // The serialization has not finished. Until this finishes, a progress bar is
-            // displayed with an option to cancel the export.
-            ProgressBarDialogFragment progressBarDialogFragment = new ProgressBarDialogFragment();
-            progressBarDialogFragment.setCancelProgressHandler(
-                    new DialogInterface.OnClickListener() {
-                        @Override
-                        public void onClick(DialogInterface dialog, int which) {
-                            if (which == AlertDialog.BUTTON_NEGATIVE) {
-                                mExportState = EXPORT_STATE_INACTIVE;
-                                RecordHistogram.recordEnumeratedHistogram(
-                                        "PasswordManager.ExportPasswordsToCSVResult",
-                                        EXPORT_RESULT_USER_ABORTED, EXPORT_RESULT_COUNT);
-                            }
-                        }
-                    });
-            mProgressBarManager.show(progressBarDialogFragment, getFragmentManager());
-        } else {
-            // Note: if the serialization is quicker than the user interacting with the
-            // confirmation dialog, then there is no progress bar shown, in which case hide() is
-            // just calling the callback synchronously.
-            // TODO(crbug.com/821377) -- remove clang-format pragmas
-            // clang-format off
-            mProgressBarManager.hide(this::sendExportIntent);
-            // clang-format on
-        }
-    }
-
-    /**
-     * Call this to abort the export UI flow and display an error description to the user.
-     * @param descriptionId The resource ID of a string with a brief explanation of the error.
-     * @param detailedDescription An optional string with more technical details about the error.
-     * @param positiveButtonLabelId The resource ID of the label of the positive button in the error
-     * dialog.
-     */
-    @VisibleForTesting
-    public void showExportErrorAndAbort(int descriptionId, @Nullable String detailedDescription,
-            int positiveButtonLabelId, @HistogramExportResult int histogramExportResult) {
-        assert mErrorDialogParams == null;
-        mProgressBarManager.hide(() -> {
-            showExportErrorAndAbortImmediately(descriptionId, detailedDescription,
-                    positiveButtonLabelId, histogramExportResult);
-        });
-    }
-
-    public void showExportErrorAndAbortImmediately(int descriptionId,
-            @Nullable String detailedDescription, int positiveButtonLabelId,
-            @HistogramExportResult int histogramExportResult) {
-        RecordHistogram.recordEnumeratedHistogram("PasswordManager.ExportPasswordsToCSVResult",
-                histogramExportResult, EXPORT_RESULT_COUNT);
-
-        mErrorDialogParams = new ExportErrorDialogFragment.ErrorDialogParams();
-        mErrorDialogParams.positiveButtonLabelId = positiveButtonLabelId;
-        mErrorDialogParams.description = getActivity().getResources().getString(descriptionId);
-
-        if (detailedDescription != null) {
-            mErrorDialogParams.detailedDescription = getActivity().getResources().getString(
-                    R.string.save_password_preferences_export_error_details, detailedDescription);
-        }
-
-        if (mExportWarningDialogFragment == null) showExportErrorDialogFragment();
-    }
-
-    /**
-     * This is a helper method to {@link showExportErrorAndAbort}, responsible for showing the
-     * actual UI.*/
-    private void showExportErrorDialogFragment() {
-        assert mErrorDialogParams != null;
-
-        ExportErrorDialogFragment exportErrorDialogFragment = new ExportErrorDialogFragment();
-        int positiveButtonLabelId = mErrorDialogParams.positiveButtonLabelId;
-        exportErrorDialogFragment.initialize(mErrorDialogParams);
-        mErrorDialogParams = null;
-
-        exportErrorDialogFragment.setExportErrorHandler(new DialogInterface.OnClickListener() {
-            @Override
-            public void onClick(DialogInterface dialog, int which) {
-                if (which == AlertDialog.BUTTON_POSITIVE) {
-                    if (positiveButtonLabelId
-                            == R.string.save_password_preferences_export_learn_google_drive) {
-                        // Link to the help article about how to use Google Drive.
-                        Intent intent = new Intent(Intent.ACTION_VIEW,
-                                Uri.parse("https://support.google.com/drive/answer/2424384"));
-                        intent.setPackage(getActivity().getPackageName());
-                        getActivity().startActivity(intent);
-                    } else if (positiveButtonLabelId == R.string.try_again) {
-                        mExportState = EXPORT_STATE_REQUESTED;
-                        exportAfterReauth();
-                    }
-                } else if (which == AlertDialog.BUTTON_NEGATIVE) {
-                    // Re-enable exporting, the current one was just cancelled.
-                    mExportState = EXPORT_STATE_INACTIVE;
-                }
-            }
-        });
-        exportErrorDialogFragment.show(getFragmentManager(), null);
-    }
-
-    /**
-     * This method saves the contents of |serializedPasswords| into a temporary file and returns a
-     * sharing URI for it. In case of failure, returns EMPTY. It should only be run on the
-     * background thread of an AsyncTask, because it does I/O operations.
-     * @param serializedPasswords A byte array with serialized passwords in CSV format
-     */
-    private ExportResult exportPasswordsIntoFile(byte[] serializedPasswords) {
-        // First ensure that the PASSWORDS_CACHE_DIR cache directory exists.
-        File passwordsDir =
-                new File(ContextUtils.getApplicationContext().getCacheDir() + PASSWORDS_CACHE_DIR);
-        passwordsDir.mkdir();
-        // Now create or overwrite the temporary file for exported passwords there and return its
-        // content:// URI.
-        File tempFile;
-        try {
-            tempFile = File.createTempFile("pwd-export", ".csv", passwordsDir);
-        } catch (IOException e) {
-            return new ExportResult(e.getMessage());
-        }
-        tempFile.deleteOnExit();
-        try (BufferedOutputStream outputStream =
-                        new BufferedOutputStream(new FileOutputStream(tempFile))) {
-            outputStream.write(serializedPasswords);
-        } catch (IOException e) {
-            return new ExportResult(e.getMessage());
-        }
-        try {
-            return new ExportResult(ContentUriUtils.getContentUriFromFile(tempFile));
-        } catch (IllegalArgumentException e) {
-            return new ExportResult(e.getMessage());
-        }
-    }
-
-    /**
-     * If the URI of the file with exported passwords is not null, passes it into an implicit
-     * intent, so that the user can use a storage app to save the exported passwords.
-     */
-    private void sendExportIntent() {
-        assert mExportState == EXPORT_STATE_CONFIRMED;
-        mExportState = EXPORT_STATE_INACTIVE;
-
-        if (mExportFileUri.equals(Uri.EMPTY)) return;
-
-        Intent send = new Intent(Intent.ACTION_SEND);
-        send.setType("text/csv");
-        send.putExtra(Intent.EXTRA_STREAM, mExportFileUri);
-        send.putExtra(
-                Intent.EXTRA_SUBJECT, getString(R.string.save_password_preferences_export_subject));
-
-        try {
-            Intent chooser = Intent.createChooser(send, null);
-            chooser.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            ContextUtils.getApplicationContext().startActivity(chooser);
-            RecordHistogram.recordEnumeratedHistogram("PasswordManager.ExportPasswordsToCSVResult",
-                    EXPORT_RESULT_SUCCESS, EXPORT_RESULT_COUNT);
-            RecordHistogram.recordCountHistogram(
-                    "PasswordManager.ExportedPasswordsPerUserInCSV", mEntriesCount);
-        } catch (ActivityNotFoundException e) {
-            showExportErrorAndAbort(R.string.save_password_preferences_export_no_app, null,
-                    R.string.save_password_preferences_export_learn_google_drive,
-                    EXPORT_RESULT_NO_CONSUMER);
-        }
-        mExportFileUri = null;
-    }
-
     private boolean filterPasswords(String query) {
         mSearchQuery = query;
         // Hide the help option. It's not useful during search but might be clicked by accident.
@@ -849,33 +388,14 @@
     @Override
     public void onResume() {
         super.onResume();
-        if (mExportState == EXPORT_STATE_REQUESTED) {
-            // If Chrome returns to foreground from being paused (but without being killed), and
-            // exportAfterReauth was called before pausing, the warning dialog is still
-            // displayed and ready to be used, and this is indicated by
-            // |mExportWarningDialogFragment| being non-null.
-            if (ReauthenticationManager.authenticationStillValid(
-                        ReauthenticationManager.REAUTH_SCOPE_BULK)) {
-                if (mExportWarningDialogFragment == null) exportAfterReauth();
-            } else {
-                if (mExportWarningDialogFragment != null) mExportWarningDialogFragment.dismiss();
-                RecordHistogram.recordEnumeratedHistogram(
-                        "PasswordManager.ExportPasswordsToCSVResult", EXPORT_RESULT_USER_ABORTED,
-                        EXPORT_RESULT_COUNT);
-                mExportState = EXPORT_STATE_INACTIVE;
-            }
-        }
+        mExportFlow.onResume();
         rebuildPasswordLists();
     }
 
     @Override
     public void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
-        outState.putInt(SAVED_STATE_EXPORT_STATE, mExportState);
-        outState.putInt(SAVED_STATE_ENTRIES_COUNT, mEntriesCount);
-        if (mExportFileUri != null) {
-            outState.putString(SAVED_STATE_EXPORT_FILE_URI, mExportFileUri.toString());
-        }
+        mExportFlow.onSaveInstanceState(outState);
         if (mSearchQuery != null) {
             outState.putString(SAVED_STATE_SEARCH_QUERY, mSearchQuery);
         }
@@ -1010,15 +530,6 @@
     }
 
     /**
-     * Returns whether the password export feature is ready to use.
-     * @return Returns true if the flag is set and the Reauthentication Api is available.
-     */
-    private boolean providesPasswordExport() {
-        return ChromeFeatureList.isEnabled(EXPORT_PASSWORDS)
-                && ReauthenticationManager.isReauthenticationApiAvailable();
-    }
-
-    /**
      * Returns whether the password search feature is ready to use.
      * @return Returns true if the flag is set.
      */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchBoxDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchBoxDataProvider.java
index 2ec619c..b54000e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchBoxDataProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchBoxDataProvider.java
@@ -41,7 +41,12 @@
     }
 
     @Override
-    public String getText() {
+    public String getDisplayText() {
+        return null;
+    }
+
+    @Override
+    public String getEditingText() {
         return null;
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java
index a63e83f8..efbfd26 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java
@@ -462,17 +462,18 @@
             }
         });
 
-        if (callback != null) {
-            dialog.setOnDismissListener(new OnDismissListener() {
-                @Override
-                public void onDismiss(DialogInterface dialog) {
-                    if (!callbackCalled[0]) {
-                        callback.onCancel();
-                        callbackCalled[0] = true;
-                    }
+        dialog.setOnDismissListener(new OnDismissListener() {
+            @Override
+            public void onDismiss(DialogInterface dialog) {
+                if (callback != null && !callbackCalled[0]) {
+                    callback.onCancel();
+                    callbackCalled[0] = true;
                 }
-            });
-        }
+                if (params.getOnDialogDismissed() != null) {
+                    params.getOnDialogDismissed().run();
+                }
+            }
+        });
 
         if (sFakeIntentReceiverForTesting != null) {
             sFakeIntentReceiverForTesting.onCustomChooserShown(dialog);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareParams.java b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareParams.java
index ba55170f..ad186c30 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareParams.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareParams.java
@@ -56,10 +56,14 @@
     /** The package name of the app who requests for share. If Null, it is requested by Chrome */
     private final String mSourcePackageName;
 
+    /** The {@link Runnable} called when the share dialog is dismissed. */
+    @Nullable
+    private final Runnable mOnDialogDismissed;
+
     private ShareParams(boolean shareDirectly, boolean saveLastUsed, Activity activity,
             String title, String text, String url, @Nullable Uri offlineUri,
             @Nullable Uri screenshotUri, @Nullable TargetChosenCallback callback,
-            @Nullable String sourcePackageName) {
+            @Nullable String sourcePackageName, @Nullable Runnable onDialogDismissed) {
         mShareDirectly = shareDirectly;
         mSaveLastUsed = saveLastUsed;
         mActivity = activity;
@@ -70,6 +74,7 @@
         mScreenshotUri = screenshotUri;
         mCallback = callback;
         mSourcePackageName = sourcePackageName;
+        mOnDialogDismissed = onDialogDismissed;
     }
 
     /**
@@ -146,6 +151,14 @@
         return mSourcePackageName;
     }
 
+    /**
+     * @return The {@link Runnable} to be called when the share dialog is dismissed.
+     */
+    @Nullable
+    public Runnable getOnDialogDismissed() {
+        return mOnDialogDismissed;
+    }
+
     /** The builder for {@link ShareParams} objects. */
     public static class Builder {
         private boolean mShareDirectly;
@@ -159,6 +172,7 @@
         private TargetChosenCallback mCallback;
         private String mSourcePackageName;
         private boolean mIsExternalUrl;
+        private Runnable mOnDialogDismissed;
 
         public Builder(@NonNull Activity activity, @NonNull String title, @NonNull String url) {
             mActivity = activity;
@@ -239,6 +253,14 @@
             return this;
         }
 
+        /**
+         * Set a runnable to be called when the share dialog is dismissed.
+         */
+        public Builder setOnDialogDismissed(Runnable onDialogDismised) {
+            mOnDialogDismissed = onDialogDismised;
+            return this;
+        }
+
         /** @return A fully constructed {@link ShareParams} object. */
         public ShareParams build() {
             if (!TextUtils.isEmpty(mUrl)) {
@@ -253,7 +275,7 @@
                 }
             }
             return new ShareParams(mShareDirectly, mSaveLastUsed, mActivity, mTitle, mText, mUrl,
-                    mOfflineUri, mScreenshotUri, mCallback, mSourcePackageName);
+                    mOfflineUri, mScreenshotUri, mCallback, mSourcePackageName, mOnDialogDismissed);
         }
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFragmentBase.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFragmentBase.java
index 140b567..e7e5b807 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFragmentBase.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFragmentBase.java
@@ -11,6 +11,7 @@
 import android.support.annotation.Nullable;
 import android.support.annotation.StringRes;
 import android.support.v7.content.res.AppCompatResources;
+import android.text.method.LinkMovementMethod;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -19,6 +20,8 @@
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.consent_auditor.ConsentAuditorFeature;
+import org.chromium.ui.text.NoUnderlineClickableSpan;
+import org.chromium.ui.text.SpanApplier;
 
 /**
  * This fragment implements sign-in screen with account picker and descriptions of signin-related
@@ -28,6 +31,9 @@
 public abstract class SigninFragmentBase extends Fragment {
     private static final String TAG = "SigninFragmentBase";
 
+    private static final String SETTINGS_LINK_OPEN = "<LINK1>";
+    private static final String SETTINGS_LINK_CLOSE = "</LINK1>";
+
     private static final String ARGUMENT_ACCESS_POINT = "SigninFragmentBase.AccessPoint";
 
     private @SigninAccessPoint int mSigninAccessPoint;
@@ -35,6 +41,9 @@
     private SigninView mView;
     private ConsentTextTracker mConsentTextTracker;
     private @StringRes int mCancelButtonTextId = R.string.cancel;
+    // TODO(https://crbug.com/814728): Implement account picker and set these variables.
+    private String mSelectedAccountName;
+    private boolean mIsDefaultAccountSelected;
 
     /**
      * Creates an argument bundle to start AccountSigninView from the account selection page.
@@ -123,9 +132,34 @@
 
     private void updateConsentText() {
         mConsentTextTracker.setText(mView.getTitleView(), R.string.signin_title);
+        mConsentTextTracker.setText(
+                mView.getSyncDescriptionView(), R.string.signin_sync_description);
+        mConsentTextTracker.setText(mView.getPersonalizationDescriptionView(),
+                R.string.signin_personalization_description);
+        mConsentTextTracker.setText(mView.getGoogleServicesDescriptionView(),
+                R.string.signin_google_services_description);
         mConsentTextTracker.setText(mView.getRefuseButton(), mCancelButtonTextId);
         mConsentTextTracker.setText(mView.getAcceptButton(), R.string.signin_accept_button);
         mConsentTextTracker.setText(mView.getMoreButton(), R.string.more);
+
+        // The clickable "Settings" link.
+        mView.getDetailsDescriptionView().setMovementMethod(LinkMovementMethod.getInstance());
+        NoUnderlineClickableSpan settingsSpan = new NoUnderlineClickableSpan() {
+            @Override
+            public void onClick(View widget) {
+                onSigninAccepted(mSelectedAccountName, mIsDefaultAccountSelected, true);
+                RecordUserAction.record("Signin_Signin_WithAdvancedSyncSettings");
+
+                // Record the fact that the user consented to the consent text by clicking on a link
+                recordConsent((TextView) widget);
+            }
+        };
+        mConsentTextTracker.setText(
+                mView.getDetailsDescriptionView(), R.string.signin_details_description, input -> {
+                    return SpanApplier.applySpans(input.toString(),
+                            new SpanApplier.SpanInfo(
+                                    SETTINGS_LINK_OPEN, SETTINGS_LINK_CLOSE, settingsSpan));
+                });
     }
 
     // TODO(https://crbug.com/814728): Get real profile data and remove SuppressLint.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninView.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninView.java
index 952cdf6b4..7b6e496 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninView.java
@@ -23,6 +23,10 @@
     private ImageView mAccountImage;
     private TextView mAccountName;
     private TextView mAccountEmail;
+    private TextView mSyncDescription;
+    private TextView mPersonalizationDescription;
+    private TextView mGoogleServicesDescription;
+    private TextView mDetailsDescription;
     private ButtonCompat mAcceptButton;
     private Button mRefuseButton;
     private Button mMoreButton;
@@ -41,6 +45,12 @@
         mAccountImage = (ImageView) findViewById(R.id.account_image);
         mAccountName = (TextView) findViewById(R.id.account_name);
         mAccountEmail = (TextView) findViewById(R.id.account_email);
+        mSyncDescription = (TextView) findViewById(R.id.signin_sync_description);
+        mPersonalizationDescription =
+                (TextView) findViewById(R.id.signin_personalization_description);
+        mGoogleServicesDescription =
+                (TextView) findViewById(R.id.signin_google_services_description);
+        mDetailsDescription = (TextView) findViewById(R.id.signin_details_description);
         mAcceptButton = (ButtonCompat) findViewById(R.id.positive_button);
         mRefuseButton = (Button) findViewById(R.id.negative_button);
         mMoreButton = (Button) findViewById(R.id.more_button);
@@ -67,6 +77,22 @@
         return mAccountEmail;
     }
 
+    public TextView getSyncDescriptionView() {
+        return mSyncDescription;
+    }
+
+    public TextView getPersonalizationDescriptionView() {
+        return mPersonalizationDescription;
+    }
+
+    public TextView getGoogleServicesDescriptionView() {
+        return mGoogleServicesDescription;
+    }
+
+    public TextView getDetailsDescriptionView() {
+        return mDetailsDescription;
+    }
+
     public ButtonCompat getAcceptButton() {
         return mAcceptButton;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
index c4fec6d..cd383a38 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
@@ -1848,7 +1848,15 @@
 
             mDownloadDelegate = new ChromeDownloadDelegate(mThemedApplicationContext, this);
 
-            initWebContents(mContentViewCore.getWebContents());
+            WebContents parentWebContents = null;
+            if (getParentId() != INVALID_TAB_ID) {
+                Tab parentTab = getTabModelSelector().getTabById(getParentId());
+                if (parentTab != null && parentTab.isIncognito() == isIncognito()) {
+                    parentWebContents = parentTab.getWebContents();
+                }
+            }
+
+            initWebContents(mContentViewCore.getWebContents(), parentWebContents);
 
             // In the case where restoring a Tab or showing a prerendered one we already have a
             // valid infobar container, no need to recreate one.
@@ -1901,10 +1909,10 @@
         }
     }
 
-    private void initWebContents(WebContents webContents) {
+    private void initWebContents(WebContents webContents, WebContents parentWebContents) {
         assert mNativeTabAndroid != 0;
         nativeInitWebContents(mNativeTabAndroid, mIncognito, mIsDetached, webContents,
-                mWebContentsDelegate,
+                parentWebContents, mWebContentsDelegate,
                 new TabContextMenuPopulator(
                         mDelegateFactory.createContextMenuPopulator(this), this));
 
@@ -3510,7 +3518,7 @@
     private native void nativeInit();
     private native void nativeDestroy(long nativeTabAndroid);
     private native void nativeInitWebContents(long nativeTabAndroid, boolean incognito,
-            boolean isBackgroundTab, WebContents webContents,
+            boolean isBackgroundTab, WebContents webContents, WebContents parentWebContents,
             TabWebContentsDelegateAndroid delegate, ContextMenuPopulator contextMenuPopulator);
     private native void nativeUpdateDelegates(long nativeTabAndroid,
             TabWebContentsDelegateAndroid delegate, ContextMenuPopulator contextMenuPopulator);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/CustomTabToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/CustomTabToolbar.java
index 0c25ceb..1abd316 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/CustomTabToolbar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/CustomTabToolbar.java
@@ -380,7 +380,7 @@
             mUrlBar.setUrl("", null);
             return;
         }
-        String displayText = getToolbarDataProvider().getText();
+        String displayText = getToolbarDataProvider().getDisplayText();
         Pair<String, String> urlText = LocationBarLayout.splitPathFromUrlDisplayText(displayText);
         displayText = urlText.first;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarDataProvider.java
index 1be231c5..58775e0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarDataProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarDataProvider.java
@@ -52,7 +52,13 @@
     /**
      * @return The formatted text (URL or search terms) for display.
      */
-    String getText();
+    String getDisplayText();
+
+    /**
+     * @return The formatted text for editing.  Returning null will leave the display text untouched
+     *         when entering the edit state.
+     */
+    String getEditingText();
 
     /**
      * @return The title of the current tab, or the empty string if there is currently no tab.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java
index eeb12fe..2fa6fb8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java
@@ -174,7 +174,12 @@
             }
 
             @Override
-            public String getText() {
+            public String getDisplayText() {
+                return null;
+            }
+
+            @Override
+            public String getEditingText() {
                 return null;
             }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModel.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModel.java
index e133984..e41efc2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModel.java
@@ -42,13 +42,20 @@
         mNativeToolbarModelAndroid = 0;
     }
 
-    /** @return The formatted text (URL or search terms) for display. */
-    public String getText() {
+    /** @return The formatted URL suitable for editing. */
+    public String getFormattedFullUrl() {
         if (mNativeToolbarModelAndroid == 0) return null;
-        return nativeGetText(mNativeToolbarModelAndroid);
+        return nativeGetFormattedFullURL(mNativeToolbarModelAndroid);
+    }
+
+    /** @return The formatted URL suitable for display only. */
+    public String getUrlForDisplay() {
+        if (mNativeToolbarModelAndroid == 0) return null;
+        return nativeGetURLForDisplay(mNativeToolbarModelAndroid);
     }
 
     private native long nativeInit(ToolbarModelDelegate delegate);
     private native void nativeDestroy(long nativeToolbarModelAndroid);
-    private native String nativeGetText(long nativeToolbarModelAndroid);
+    private native String nativeGetFormattedFullURL(long nativeToolbarModelAndroid);
+    private native String nativeGetURLForDisplay(long nativeToolbarModelAndroid);
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModelImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModelImpl.java
index c248f00a..47b3ac2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModelImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModelImpl.java
@@ -16,6 +16,7 @@
 import org.chromium.chrome.browser.dom_distiller.DomDistillerServiceFactory;
 import org.chromium.chrome.browser.dom_distiller.DomDistillerTabUtils;
 import org.chromium.chrome.browser.locale.LocaleManager;
+import org.chromium.chrome.browser.ntp.NativePageFactory;
 import org.chromium.chrome.browser.ntp.NewTabPage;
 import org.chromium.chrome.browser.offlinepages.OfflinePageUtils;
 import org.chromium.chrome.browser.profiles.Profile;
@@ -115,37 +116,88 @@
         return null;
     }
 
-    @Override
-    public String getText() {
-        String displayText = super.getText();
+    /**
+     * @return Whether a truncated URL should be shown in the display (non-editing) state of the
+     *         omnibox.
+     */
+    private boolean useTruncatedUrlForDisplay() {
+        if (!hasTab() || mTab.isFrozen()) return false;
 
-        if (!hasTab() || mTab.isFrozen()) return displayText;
+        if (!ChromeFeatureList.isEnabled(
+                    ChromeFeatureList.OMNIBOX_HIDE_SCHEME_DOMAIN_IN_STEADY_STATE)) {
+            return false;
+        }
 
         String url = getCurrentUrl();
-        if (DomDistillerUrlUtils.isDistilledPage(url)) {
+        if (DomDistillerUrlUtils.isDistilledPage(url)) return false;
+        if (isOfflinePage()) return false;
+        if (isDisplayingQueryTerms()) return false;
+        if (NativePageFactory.isNativePageUrl(url, isIncognito()) || NewTabPage.isNTPUrl(url)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public String getDisplayText() {
+        if (useTruncatedUrlForDisplay()) {
+            return getUrlForDisplay();
+        } else {
+            return getTextSuitableForEditing(false);
+        }
+    }
+
+    @Override
+    public String getEditingText() {
+        return getTextSuitableForEditing(true);
+    }
+
+    /**
+     * Generate the text that would be suitable to be shown while the user is editing the omnibox.
+     * This should be a closer approximation to the actual URL than that shown as the display URL.
+     *
+     * @param isEditing Whether the user is currently editing the omnibox.  A null return value
+     *                  while in editing, will ensure the original display text will be untouched.
+     * @return The more verbose text that is suitable for editing.
+     */
+    private String getTextSuitableForEditing(boolean isEditing) {
+        if (!hasTab()) return isEditing ? null : "";
+
+        String url = getCurrentUrl();
+        if (NativePageFactory.isNativePageUrl(url, isIncognito()) || NewTabPage.isNTPUrl(url)) {
+            return isEditing ? null : "";
+        }
+
+        String editingText = getFormattedFullUrl();
+        if (mTab.isFrozen()) return editingText;
+
+        if (isEditing && isShowingUntrustedOfflinePage()) {
+            editingText = "";
+        } else if (DomDistillerUrlUtils.isDistilledPage(url)) {
             if (isStoredArticle(url)) {
                 DomDistillerService domDistillerService =
                         DomDistillerServiceFactory.getForProfile(getProfile());
                 String originalUrl = domDistillerService.getUrlForEntry(
                         DomDistillerUrlUtils.getValueForKeyInUrl(url, "entry_id"));
-                displayText =
+                editingText =
                         DomDistillerTabUtils.getFormattedUrlFromOriginalDistillerUrl(originalUrl);
             } else if (DomDistillerUrlUtils.getOriginalUrlFromDistillerUrl(url) != null) {
                 String originalUrl = DomDistillerUrlUtils.getOriginalUrlFromDistillerUrl(url);
-                displayText =
+                editingText =
                         DomDistillerTabUtils.getFormattedUrlFromOriginalDistillerUrl(originalUrl);
             }
         } else if (isOfflinePage()) {
             String originalUrl = mTab.getOriginalUrl();
-            displayText = OfflinePageUtils.stripSchemeFromOnlineUrl(
-                  DomDistillerTabUtils.getFormattedUrlFromOriginalDistillerUrl(originalUrl));
+            editingText = OfflinePageUtils.stripSchemeFromOnlineUrl(
+                    DomDistillerTabUtils.getFormattedUrlFromOriginalDistillerUrl(originalUrl));
         } else {
             String searchTerms = extractSearchTermsFromUrl(url);
             // Show the search terms in the omnibox instead of the URL if this is a DSE search URL.
-            if (searchTerms != null) displayText = searchTerms;
+            if (searchTerms != null) editingText = searchTerms;
         }
 
-        return displayText;
+        return editingText;
     }
 
     private boolean isStoredArticle(String url) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrMainActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/vr/VrMainActivity.java
index 26c34f58b..c2bf69d7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrMainActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr/VrMainActivity.java
@@ -4,29 +4,102 @@
 
 package org.chromium.chrome.browser.vr;
 
+import android.app.Activity;
+import android.content.res.Configuration;
+import android.os.Build;
 import android.os.Bundle;
 
+import org.chromium.base.ApiCompatibilityUtils;
+import org.chromium.base.ApplicationStatus;
+import org.chromium.base.TraceEvent;
+import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.LaunchIntentDispatcher;
 import org.chromium.chrome.browser.document.ChromeLauncherActivity;
+import org.chromium.chrome.browser.vr_shell.VrIntentUtils;
 import org.chromium.chrome.browser.vr_shell.VrShellDelegate;
 
+import java.lang.ref.WeakReference;
+
 /**
- * This is the VR equivalent of {@link ChromeLauncherActivity}. It exists only because the Android
- * platform doesn't inherently support hybrid VR apps (like Chrome). All VR intents for Chrome
- * should eventually be routed through this activity as its manifest entry contains VR specific
- * attributes to ensure a smooth transition into Chrome VR.
+ * This is the VR equivalent of {@link ChromeLauncherActivity}. It exists because the Android
+ * platform doesn't inherently support hybrid VR Activities (like Chrome uses). All VR intents for
+ * Chrome are routed through this activity as its manifest entry contains VR specific attributes to
+ * ensure a smooth transition into Chrome VR, and allows us to properly handle both implicit and
+ * explicit VR intents that may be missing VR categories when they get sent.
  *
- * More specifically, a special VR theme disables the Preview Window feature to prevent the system
- * UI from showing up while Chrome prepares to enter VR mode. The android:enabledVrMode attribute
- * ensures that the system doesn't kick us out of VR mode during the transition as this as this can
- * result in a screen brightness flicker. Both of these sound minor but look jarring from a VR
- * headset.
+ * This Activity doesn't inherit from ChromeLauncherActivity because we need to be able to finish
+ * and relaunch this Launcher without calling ChromeLauncherActivity#onCreate which would fire the
+ * intent we don't yet want to fire.
  */
-public class VrMainActivity extends ChromeLauncherActivity {
+public class VrMainActivity extends Activity {
     @Override
     public void onCreate(Bundle savedInstanceState) {
-        // This Launcher may be launched through an alias, which leads to vrmode not being correctly
-        // set, so we need to set it here as a fallback. b/65271215
-        VrShellDelegate.setVrModeEnabled(this);
-        super.onCreate(savedInstanceState);
+        TraceEvent.begin("VrMainActivity.onCreate");
+        try {
+            super.onCreate(savedInstanceState);
+
+            // If the launcher was launched from a 2D context (without calling
+            // DaydreamApi#launchInVr), then we need to relaunch the launcher in VR to allow
+            // downstream Activities to make assumptions about whether they're in VR or not, and
+            // ensure the VR configuration is set before launching Activities as they use the VR
+            // configuration to set style attributes.
+            boolean needsRelaunch;
+            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
+                needsRelaunch = !VrShellDelegate.isInVrSession(this);
+            } else {
+                Configuration config = getResources().getConfiguration();
+                int uiMode = config.uiMode & Configuration.UI_MODE_TYPE_MASK;
+                needsRelaunch = uiMode != Configuration.UI_MODE_TYPE_VR_HEADSET;
+            }
+            if (needsRelaunch) {
+                VrIntentUtils.launchInVr(getIntent(), this);
+                finish();
+                return;
+            }
+
+            // We don't set VrMode for the launcher in the manifest because that causes weird things
+            // to happen when you send a VR intent to Chrome from a non-VR app, so we need to set it
+            // here.
+            VrShellDelegate.setVrModeEnabled(this);
+
+            // Daydream likes to remove the Daydream category from explicit intents for some reason.
+            // Since only implicit intents with the Daydream category can be routed here, it's safe
+            // to assume that the intent *should* have the Daydream category, which simplifies our
+            // intent handling.
+            getIntent().addCategory(VrIntentUtils.DAYDREAM_CATEGORY);
+
+            for (WeakReference<Activity> weakActivity : ApplicationStatus.getRunningActivities()) {
+                final Activity activity = weakActivity.get();
+                if (activity == null) continue;
+                if (activity instanceof ChromeActivity) {
+                    if (VrShellDelegate.willChangeDensityInVr((ChromeActivity) activity)) {
+                        // In the rare case that entering VR will trigger a density change (and
+                        // hence an Activity recreation), just return to Daydream home and kill the
+                        // process, as there's no good way to recreate without showing 2D UI
+                        // in-headset.
+                        finish();
+                        System.exit(0);
+                    }
+                }
+            }
+
+            @LaunchIntentDispatcher.Action
+            int dispatchAction = LaunchIntentDispatcher.dispatch(this, getIntent());
+            switch (dispatchAction) {
+                case LaunchIntentDispatcher.Action.FINISH_ACTIVITY:
+                    finish();
+                    break;
+                case LaunchIntentDispatcher.Action.FINISH_ACTIVITY_REMOVE_TASK:
+                    ApiCompatibilityUtils.finishAndRemoveTask(this);
+                    break;
+                default:
+                    assert false : "Intent dispatcher finished with action " + dispatchAction
+                                   + ", finishing anyway";
+                    finish();
+                    break;
+            }
+        } finally {
+            TraceEvent.end("VrMainActivity.onCreate");
+        }
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrDaydreamApi.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrDaydreamApi.java
index f0b2910..92287da 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrDaydreamApi.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrDaydreamApi.java
@@ -78,12 +78,19 @@
     Intent setupVrIntent(Intent intent);
 
     /**
-     * Closes this DaydreamApi instance.
-     */
-    void close();
-
-    /**
      * Launch the Daydream Settings Activity.
      */
     void launchGvrSettings();
+
+    /**
+     * Whether the user is currently in a VR session. Note that this should be treated as heuristic,
+     * and may at times be wrong as there's a timeout before this state is cleared after the user
+     * has taken off their headset.
+     */
+    boolean isInVrSession();
+
+    /**
+     * Closes this DaydreamApi instance.
+     */
+    void close();
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrDaydreamApiImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrDaydreamApiImpl.java
index dbfdc05..642230e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrDaydreamApiImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrDaydreamApiImpl.java
@@ -145,6 +145,11 @@
     }
 
     @Override
+    public boolean isInVrSession() {
+        return DaydreamApi.isInVrSession(mContext);
+    }
+
+    @Override
     public void close() {
         if (mDaydreamApi == null) return;
         mDaydreamApi.close();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrIntentUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrIntentUtils.java
index d1aada7c..88047e74 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrIntentUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrIntentUtils.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.vr_shell;
 
+import android.app.Activity;
 import android.app.ActivityOptions;
 import android.content.Context;
 import android.content.Intent;
@@ -12,8 +13,8 @@
 import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.IntentHandler;
-import org.chromium.chrome.browser.document.ChromeLauncherActivity;
 import org.chromium.chrome.browser.util.IntentUtils;
+import org.chromium.chrome.browser.vr.VrMainActivity;
 
 /**
  * Utilities dealing with extracting information about VR intents.
@@ -22,7 +23,6 @@
     private static final String DAYDREAM_HOME_PACKAGE = "com.google.android.vr.home";
     // The Daydream Home app adds this extra to auto-present intents.
     public static final String AUTOPRESENT_WEVBVR_EXTRA = "browser.vr.AUTOPRESENT_WEBVR";
-    public static final String DAYDREAM_VR_EXTRA = "android.intent.extra.VR_LAUNCH";
     public static final String DAYDREAM_CATEGORY = "com.google.intent.category.DAYDREAM";
 
     static final String VR_FRE_INTENT_EXTRA = "org.chromium.chrome.browser.vr_shell.VR_FRE";
@@ -117,9 +117,7 @@
         // Note that Daydream removes the Daydream category for deep-links (for no real reason). In
         // addition to the category, DAYDREAM_VR_EXTRA tells us that this intent is coming directly
         // from VR.
-        return intent != null
-                && (intent.hasCategory(DAYDREAM_CATEGORY)
-                           || IntentUtils.safeGetBooleanExtra(intent, DAYDREAM_VR_EXTRA, false))
+        return intent != null && intent.hasCategory(DAYDREAM_CATEGORY)
                 && !launchedFromRecentApps(intent) && VrShellDelegate.isVrEnabled();
     }
 
@@ -143,10 +141,9 @@
 
     /**
      * This function returns an intent that will launch a VR activity that will prompt the
-     * user to take off their headset and foward the freIntent to the standard
+     * user to take off their headset and forward the freIntent to the standard
      * 2D FRE activity.
      *
-     * @param caller          Activity instance that is checking if first run is necessary.
      * @param freCallerIntent The intent that is used to launch the caller.
      * @param freIntent       The intent that will be used to start the first run in 2D mode.
      * @return The intermediate VR activity intent.
@@ -156,20 +153,20 @@
         if (!VrShellDelegate.isVrEnabled()) return freIntent;
         Intent intent = new Intent();
         intent.setClassName(context, VrFirstRunActivity.class.getName());
+        intent.addCategory(DAYDREAM_CATEGORY);
         intent.putExtra(VR_FRE_CALLER_INTENT_EXTRA, new Intent(freCallerIntent));
         intent.putExtra(VR_FRE_INTENT_EXTRA, new Intent(freIntent));
-        intent.putExtra(DAYDREAM_VR_EXTRA, true);
         return intent;
     }
 
     /*
-     * Remove VR-specific extras from the given intent so that we don't auto-present
+     * Remove deeplink-specific extras from the given intent so that we don't auto-present
      * WebVR content after FRE completion.
      */
     public static void updateFreCallerIntent(Context context, Intent intent) {
-        // Let the caller intent be handeled by the standard laucher.
-        intent.setClassName(context, ChromeLauncherActivity.class.getName());
-        intent.removeExtra(DAYDREAM_VR_EXTRA);
+        intent.setClassName(context, VrMainActivity.class.getName());
+        IntentHandler.removeTrustedIntentExtras(intent);
+        intent.removeExtra(AUTOPRESENT_WEVBVR_EXTRA);
     }
 
     /**
@@ -177,16 +174,29 @@
      */
     public static Bundle getVrIntentOptions(Context context) {
         // These options are used to start the Activity with a custom animation to keep it hidden
-        // for a few hundread milliseconds - enough time for us to draw the first black view.
+        // for a few hundred milliseconds - enough time for us to draw the first black view.
         // The animation is sufficient to hide the 2D screenshot but not to the 2D UI while the
         // WebVR page is being loaded because the animation is somehow cancelled when we try to
-        // enter VR (I don't know what's cancelling it). To hide the 2D UI, we resort to the black
+        // enter VR (I don't know what's canceling it). To hide the 2D UI, we resort to the black
         // overlay view added in {@link startWithVrIntentPreNative}.
         int animation = VrShellDelegate.USE_HIDE_ANIMATION ? R.anim.stay_hidden : 0;
         return ActivityOptions.makeCustomAnimation(context, animation, 0).toBundle();
     }
 
     /**
+     * @param intent The intent to launch in VR after going through the DON (Device On) flow.
+     * @param activity The activity context to launch the intent from.
+     */
+    public static void launchInVr(Intent intent, Activity activity) {
+        VrClassesWrapper wrapper = VrShellDelegate.getVrClassesWrapper();
+        if (wrapper == null) return;
+        VrDaydreamApi api = wrapper.createVrDaydreamApi(activity);
+        if (api == null) return;
+        api.launchInVr(intent);
+        api.close();
+    }
+
+    /**
      * @return Whether the intent is fired from the recent apps overview.
      */
     /* package */ static boolean launchedFromRecentApps(Intent intent) {
@@ -198,7 +208,6 @@
      */
     /* package */ static void removeVrExtras(Intent intent) {
         if (intent == null) return;
-        intent.removeExtra(DAYDREAM_VR_EXTRA);
         intent.removeCategory(DAYDREAM_CATEGORY);
         assert !isVrIntent(intent);
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
index 1d7802a..d1ddebca 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
@@ -26,6 +26,7 @@
 import android.provider.Settings;
 import android.support.annotation.IntDef;
 import android.util.DisplayMetrics;
+import android.util.Pair;
 import android.view.Display;
 import android.view.View;
 import android.view.ViewGroup;
@@ -35,6 +36,7 @@
 
 import org.chromium.base.ActivityState;
 import org.chromium.base.ApplicationStatus;
+import org.chromium.base.CollectionUtil;
 import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
 import org.chromium.base.PackageUtils;
@@ -66,7 +68,9 @@
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
+import java.util.Set;
 
 /**
  * Manages interactions with the VR Shell.
@@ -122,6 +126,13 @@
     private static final String GVR_KEYBOARD_MARKET_URI =
             "market://details?id=" + GVR_KEYBOARD_PACKAGE_ID;
 
+    private static final String SAMSUNG_GALAXY_PREFIX = "SM-";
+    private static final Set<String> SAMSUNG_GALAXY_8_MODELS =
+            Collections.unmodifiableSet(CollectionUtil.newHashSet("G950", "N950", "G955", "G892"));
+
+    private static final Set<String> SAMSUNG_GALAXY_8_ALT_MODELS = Collections.unmodifiableSet(
+            CollectionUtil.newHashSet("SC-02J", "SCV36", "SC-03J", "SCV35", "SC-01K", "SCV37"));
+
     // This value is intentionally probably overkill. This is the time we need to wait from when
     // Chrome is resumed, to when Chrome actually renders a black frame, so that we can cancel the
     // stay_hidden animation and not see a white monoscopic frame in-headset. 150ms is definitely
@@ -417,30 +428,34 @@
         if (!activitySupportsVrBrowsing(activity) && sRegisteredVrAssetsComponent) return;
 
         // Reading VR support level and version can be slow, so do it asynchronously.
-        new AsyncTask<Void, Void, VrDaydreamApi>() {
+        new AsyncTask<Void, Void, Pair<VrDaydreamApi, Integer>>() {
             @Override
-            protected VrDaydreamApi doInBackground(Void... params) {
+            protected Pair<VrDaydreamApi, Integer> doInBackground(Void... params) {
+                updateDayreamIconComponentState(activity);
                 VrClassesWrapper wrapper = getVrClassesWrapper();
-                if (wrapper == null) return null;
+                if (wrapper == null) return Pair.create(null, VrSupportLevel.VR_NOT_AVAILABLE);
                 VrDaydreamApi api = wrapper.createVrDaydreamApi(activity);
-                if (api == null) return null;
+                if (api == null) return Pair.create(null, VrSupportLevel.VR_NOT_AVAILABLE);
                 int vrSupportLevel =
                         getVrSupportLevel(api, wrapper.createVrCoreVersionChecker(), null);
-                if (!isVrShellEnabled(vrSupportLevel)) return null;
-                updateDayreamIconComponentState(activity);
-                return api;
+                return Pair.create(api, vrSupportLevel);
             }
 
             @Override
-            protected void onPostExecute(VrDaydreamApi api) {
+            protected void onPostExecute(Pair<VrDaydreamApi, Integer> results) {
+                VrDaydreamApi api = results.first;
+                int vrSupportLevel = results.second;
+                if (api == null || vrSupportLevel != VrSupportLevel.VR_DAYDREAM) return;
+
+                if (!sRegisteredVrAssetsComponent) {
+                    registerVrAssetsComponentIfDaydreamUser(isDaydreamCurrentViewer(api));
+                }
+
                 // Registering the daydream intent has to be done on the UI thread. Note that this
                 // call is slow (~10ms at time of writing).
-                if (api == null) return;
-                if (!sRegisteredVrAssetsComponent) {
-                    registerVrAssetsComponentIfDaydreamUser(api.isDaydreamCurrentViewer());
-                }
-                if (ApplicationStatus.getStateForActivity(activity) == ActivityState.RESUMED
-                        && activitySupportsVrBrowsing(activity)) {
+                if (isVrBrowsingEnabled(activity, vrSupportLevel, api)
+                        && ApplicationStatus.getStateForActivity(activity)
+                                == ActivityState.RESUMED) {
                     registerDaydreamIntent(api, activity);
                 }
                 api.close();
@@ -539,6 +554,52 @@
         sInstance.mVrShell.rawTopContentOffsetChanged(topContentOffset);
     }
 
+    /**
+     * This is called every time ChromeActivity gets a new intent.
+     */
+    public static void onNewIntentWithNative(ChromeActivity activity, Intent intent) {
+        if (!VrIntentUtils.isVrIntent(intent)) return;
+
+        VrShellDelegate instance = getInstance(activity);
+        if (instance == null) return;
+        instance.onNewIntentWithNativeInternal(activity, intent);
+    }
+
+    /**
+     * This is called when ChromeTabbedActivity gets a new intent before native is initialized.
+     */
+    public static void maybeHandleVrIntentPreNative(ChromeActivity activity, Intent intent) {
+        if (!VrIntentUtils.isVrIntent(intent)) return;
+
+        // We add a black overlay view so that we can show black while the VR UI is loading.
+        // Note that this alone isn't sufficient to prevent 2D UI from showing when
+        // auto-presenting WebVR. See comment about the custom animation in {@link
+        // getVrIntentOptions}.
+        // TODO(crbug.com/775574): This hack doesn't really work to hide the 2D UI on Samsung
+        // devices since Chrome gets paused and we prematurely remove the overlay.
+        if (sInstance == null || !sInstance.mInVr) addBlackOverlayViewForActivity(activity);
+
+        // If we're already in VR, or launching from an internal intent, we don't want to set system
+        // ui visibility here, or we'll incorrectly restore window mode later.
+        if (sInstance != null && (sInstance.mInVr || sInstance.mInternalIntentUsedToStartVr)) {
+            return;
+        }
+        if (DEBUG_LOGS) Log.i(TAG, "maybeHandleVrIntentPreNative: preparing for transition");
+
+        // Enable VR mode and hide system UI. We do this here so we don't get kicked out of
+        // VR mode and to prevent seeing a flash of system UI.
+        getVrClassesWrapper().setVrModeEnabled(activity, true);
+        activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+        activity.getWindow().getDecorView().setSystemUiVisibility(VR_SYSTEM_UI_FLAGS);
+    }
+
+    /**
+     * Asynchronously enable VR mode.
+     */
+    public static void setVrModeEnabled(Activity activity) {
+        getVrClassesWrapper().setVrModeEnabled(activity, true);
+    }
+
     @CalledByNative
     private static VrShellDelegate getInstance() {
         Activity activity = ApplicationStatus.getLastTrackedFocusedActivity();
@@ -657,17 +718,36 @@
     }
 
     /**
-     * @return Whether or not VR Shell is currently enabled.
+     * @return Whether or not VR Browsing is currently enabled for the given Activity.
      */
-    /* package */ static boolean isVrShellEnabled(int vrSupportLevel) {
-        // Only enable ChromeVR (VrShell) on Daydream devices as it currently needs a Daydream
-        // controller.
-        if (vrSupportLevel != VrSupportLevel.VR_DAYDREAM) return false;
-        if (deviceChangesDensityInVr()) return false;
-        return ChromeFeatureList.isEnabled(ChromeFeatureList.VR_BROWSING);
+    /* package */ static boolean isVrBrowsingEnabled(
+            ChromeActivity activity, int vrSupportLevel, VrDaydreamApi api) {
+        return vrSupportLevel == VrSupportLevel.VR_DAYDREAM && activitySupportsVrBrowsing(activity)
+                && !willChangeDensityInVr(activity) && isDaydreamCurrentViewer(api);
     }
 
-    private static boolean deviceChangesDensityInVr() {
+    /* package */ static boolean isDaydreamCurrentViewer(VrDaydreamApi api) {
+        if (sInstance != null) return sInstance.isDaydreamCurrentViewer();
+        return api.isDaydreamCurrentViewer();
+    }
+
+    // TODO(mthiesse): Should have package visibility only. We need to unify our vr and vr_shell
+    // packages.
+    public static boolean isInVrSession(Activity activty) {
+        if (sInstance != null) return sInstance.mVrDaydreamApi.isInVrSession();
+        VrClassesWrapper wrapper = getVrClassesWrapper();
+        if (wrapper == null) return false;
+        VrDaydreamApi api = wrapper.createVrDaydreamApi(activty);
+        if (api == null) return false;
+        return api.isInVrSession();
+    }
+
+    // TODO(mthiesse): Should have package visibility only. We need to unify our vr and vr_shell
+    // packages.
+    public static boolean willChangeDensityInVr(ChromeActivity activity) {
+        // Only N+ support launching in VR at all, other OS versions don't care about this.
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) return false;
+
         // If the screen density changed while in VR, we have to disable the VR browser as java UI
         // used or created by VR browsing will be broken.
         if (sInstance != null) {
@@ -675,9 +755,18 @@
             if (sInstance.mVrSupportLevel != VrSupportLevel.VR_DAYDREAM) return false;
         }
 
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return false;
         Display display = DisplayAndroidManager.getDefaultDisplayForContext(
                 ContextUtils.getApplicationContext());
+        DisplayMetrics metrics = new DisplayMetrics();
+        display.getRealMetrics(metrics);
+
+        if (activity.getLastActiveDensity() != 0
+                && (int) activity.getLastActiveDensity() != metrics.densityDpi) {
+            return true;
+        }
+
+        if (!deviceCanChangeResolutionForVr()) return false;
+
         Display.Mode[] modes = display.getSupportedModes();
         // Devices with only one mode won't switch modes while in VR.
         if (modes.length <= 1) return false;
@@ -690,8 +779,6 @@
         // We actually can't use display.getMode() to get the current mode as that just always
         // returns the same mode ignoring the override, so we just check that our current display
         // size is not equal to the vr mode size.
-        DisplayMetrics metrics = new DisplayMetrics();
-        display.getRealMetrics(metrics);
         if (vr_mode.getPhysicalWidth() != metrics.widthPixels
                 && vr_mode.getPhysicalWidth() != metrics.heightPixels) {
             return true;
@@ -703,6 +790,20 @@
         return false;
     }
 
+    private static boolean deviceCanChangeResolutionForVr() {
+        // Samsung devices no longer change density when entering VR on O+.
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) return false;
+        String model = android.os.Build.MODEL;
+        if (SAMSUNG_GALAXY_8_ALT_MODELS.contains(model)) return true;
+
+        // Only Samsung devices change resolution in VR.
+        if (!model.startsWith(SAMSUNG_GALAXY_PREFIX)) return false;
+        CharSequence modelNumber = model.subSequence(3, 7);
+        // Only S8(+) and Note 8 models change resolution in VR.
+        if (!SAMSUNG_GALAXY_8_MODELS.contains(modelNumber)) return false;
+        return true;
+    }
+
     /**
      *  @return Whether or not VR is supported on this platform.
      */
@@ -717,6 +818,110 @@
         sVrBroadcastReceiver = null;
     }
 
+    private static void addBlackOverlayViewForActivity(ChromeActivity activity) {
+        if (sAddedBlackOverlayView) return;
+        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
+                WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);
+        View v = new View(activity);
+        v.setId(R.id.vr_overlay_view);
+        v.setBackgroundColor(Color.BLACK);
+        activity.getWindow().addContentView(v, params);
+        sAddedBlackOverlayView = true;
+    }
+
+    private static void removeBlackOverlayView(ChromeActivity activity) {
+        if (!sAddedBlackOverlayView) return;
+        View v = activity.getWindow().findViewById(R.id.vr_overlay_view);
+        assert v != null;
+        UiUtils.removeViewFromParent(v);
+        sAddedBlackOverlayView = false;
+    }
+
+    private static boolean isVrCoreCompatible(
+            final VrCoreVersionChecker versionChecker, final Tab tabToShowInfobarIn) {
+        final int vrCoreCompatibility = versionChecker.getVrCoreCompatibility();
+        boolean needsUpdate = vrCoreCompatibility == VrCoreCompatibility.VR_NOT_AVAILABLE
+                || vrCoreCompatibility == VrCoreCompatibility.VR_OUT_OF_DATE;
+        if (tabToShowInfobarIn != null && needsUpdate) {
+            ThreadUtils.assertOnUiThread();
+            new Handler().post(new Runnable() {
+                @Override
+                public void run() {
+                    promptToUpdateVrServices(vrCoreCompatibility, tabToShowInfobarIn);
+                }
+            });
+        }
+
+        return vrCoreCompatibility == VrCoreCompatibility.VR_READY;
+    }
+
+    private static void promptToUpdateVrServices(int vrCoreCompatibility, Tab tab) {
+        final Activity activity = tab.getActivity();
+        String infobarText;
+        String buttonText;
+        if (vrCoreCompatibility == VrCoreCompatibility.VR_NOT_AVAILABLE) {
+            // Supported, but not installed. Ask user to install instead of upgrade.
+            infobarText = activity.getString(R.string.vr_services_check_infobar_install_text);
+            buttonText = activity.getString(R.string.vr_services_check_infobar_install_button);
+        } else if (vrCoreCompatibility == VrCoreCompatibility.VR_OUT_OF_DATE) {
+            infobarText = activity.getString(R.string.vr_services_check_infobar_update_text);
+            buttonText = activity.getString(R.string.vr_services_check_infobar_update_button);
+        } else {
+            Log.e(TAG, "Unknown VrCore compatibility: " + vrCoreCompatibility);
+            return;
+        }
+
+        SimpleConfirmInfoBarBuilder.Listener listener = new SimpleConfirmInfoBarBuilder.Listener() {
+            @Override
+            public void onInfoBarDismissed() {}
+
+            @Override
+            public boolean onInfoBarButtonClicked(boolean isPrimary) {
+                activity.startActivityForResult(
+                        new Intent(Intent.ACTION_VIEW, Uri.parse(VR_CORE_MARKET_URI)),
+                        VR_SERVICES_UPDATE_RESULT);
+                return false;
+            }
+        };
+        SimpleConfirmInfoBarBuilder.create(tab, listener,
+                InfoBarIdentifier.VR_SERVICES_UPGRADE_ANDROID, R.drawable.vr_services, infobarText,
+                buttonText, null, true);
+    }
+
+    private static void startFeedback(Tab tab) {
+        // TODO(ymalik): This call will connect to the Google Services api which can be slow. Can we
+        // connect to it beforehand when we know that we'll be prompting for feedback?
+        HelpAndFeedback.getInstance(tab.getActivity())
+                .showFeedback(tab.getActivity(), tab.getProfile(), tab.getUrl(),
+                        ContextUtils.getApplicationContext().getPackageName() + "."
+                                + FEEDBACK_REPORT_TYPE);
+    }
+
+    private static void promptForFeedback(final Tab tab) {
+        if (tab == null) return;
+        final ChromeActivity activity = tab.getActivity();
+        SimpleConfirmInfoBarBuilder.Listener listener = new SimpleConfirmInfoBarBuilder.Listener() {
+            @Override
+            public void onInfoBarDismissed() {}
+
+            @Override
+            public boolean onInfoBarButtonClicked(boolean isPrimary) {
+                if (isPrimary) {
+                    startFeedback(tab);
+                } else {
+                    VrFeedbackStatus.setFeedbackOptOut(true);
+                }
+                return false;
+            }
+        };
+
+        SimpleConfirmInfoBarBuilder.create(tab, listener,
+                InfoBarIdentifier.VR_FEEDBACK_INFOBAR_ANDROID, R.drawable.vr_services,
+                activity.getString(R.string.vr_shell_feedback_infobar_description),
+                activity.getString(R.string.vr_shell_feedback_infobar_feedback_button),
+                activity.getString(R.string.no_thanks), true /* autoExpire  */);
+    }
+
     protected VrShellDelegate(ChromeActivity activity, VrClassesWrapper wrapper) {
         mActivity = activity;
         mVrClassesWrapper = wrapper;
@@ -833,6 +1038,10 @@
         return mVrSupportLevel;
     }
 
+    protected boolean isVrBrowsingEnabled() {
+        return isVrBrowsingEnabled(mActivity, mVrSupportLevel, mVrDaydreamApi);
+    }
+
     private void onVrServicesMaybeUpdated() {
         if (mCachedVrCorePackageVersion == getVrCorePackageVersion()) return;
         ApplicationLifetime.terminate(true);
@@ -902,11 +1111,6 @@
         return true;
     }
 
-    /* package */ boolean isVrBrowsingEnabled() {
-        return isVrShellEnabled(mVrSupportLevel) && activitySupportsVrBrowsing(mActivity)
-                && isDaydreamCurrentViewer();
-    }
-
     private void enterVr(final boolean tentativeWebVrMode) {
         // We can't enter VR before the application resumes, or we encounter bizarre crashes
         // related to gpu surfaces.
@@ -970,25 +1174,6 @@
         for (VrModeObserver observer : sVrModeObservers) observer.onEnterVr();
     }
 
-    private static void addBlackOverlayViewForActivity(ChromeActivity activity) {
-        if (sAddedBlackOverlayView) return;
-        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
-                WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);
-        View v = new View(activity);
-        v.setId(R.id.vr_overlay_view);
-        v.setBackgroundColor(Color.BLACK);
-        activity.getWindow().addContentView(v, params);
-        sAddedBlackOverlayView = true;
-    }
-
-    private static void removeBlackOverlayView(ChromeActivity activity) {
-        if (!sAddedBlackOverlayView) return;
-        View v = activity.getWindow().findViewById(R.id.vr_overlay_view);
-        assert v != null;
-        UiUtils.removeViewFromParent(v);
-        sAddedBlackOverlayView = false;
-    }
-
     private void onVrIntent() {
         if (mInVr) return;
 
@@ -1037,49 +1222,42 @@
         VrIntentUtils.removeVrExtras(mActivity.getIntent());
     }
 
-    /**
-     * This is called every time ChromeActivity gets a new intent.
-     */
-    public static void onNewIntentWithNative(ChromeActivity activity, Intent intent) {
-        if (!VrIntentUtils.isVrIntent(intent)) return;
-
-        VrShellDelegate instance = getInstance(activity);
-        if (instance == null) return;
-
+    private void onNewIntentWithNativeInternal(ChromeActivity activity, Intent intent) {
         // Nothing to do if we were launched by an internal intent.
-        if (instance.mInternalIntentUsedToStartVr) {
-            instance.mInternalIntentUsedToStartVr = false;
+        if (mInternalIntentUsedToStartVr) {
+            mInternalIntentUsedToStartVr = false;
             return;
         }
 
         // TODO(ymalik): We should cache whether or not VR mode is set so we don't set it
         // needlessly.
-        setVrModeEnabled(activity);
+        mVrClassesWrapper.setVrModeEnabled(mActivity, true);
+
         // TODO(ymalik): This should use isTrustedAutopresentIntent once the Daydream Home change
         // that adds the autopresent intent extra rolls out on most devices. This will allow us to
         // differentiate trusted auto-present intents from other VR intents.
         if (VrIntentUtils.getHandlerInstance().isTrustedDaydreamIntent(intent)) {
             if (DEBUG_LOGS) Log.i(TAG, "onNewIntentWithNative: autopresent");
             assert activitySupportsAutopresentation(activity);
-            assert instance.getVrSupportLevel() == VrSupportLevel.VR_DAYDREAM;
+            assert mVrSupportLevel == VrSupportLevel.VR_DAYDREAM;
 
             // TODO(mthiesse): This needs to be set here to correctly close the CCT when we early
             // exit here. We should use a different variable or refactor or something to make this
             // more clear.
-            instance.mAutopresentWebVr = true;
+            mAutopresentWebVr = true;
             if (!ChromeFeatureList.isEnabled(ChromeFeatureList.WEBVR_AUTOPRESENT_FROM_INTENT)) {
-                instance.onEnterVrUnsupported();
+                onEnterVrUnsupported();
                 return;
             }
-            instance.onAutopresentIntent();
-        } else if (isVrShellEnabled(instance.mVrSupportLevel)) {
+            onAutopresentIntent();
+        } else if (isVrBrowsingEnabled()) {
             if (DEBUG_LOGS) Log.i(TAG, "onNewIntentWithNative: vr");
-            instance.onVrIntent();
+            onVrIntent();
         } else {
             if (DEBUG_LOGS) Log.i(TAG, "onNewIntentWithNative: unsupported");
             // TODO(ymalik): Currently we always return to Daydream home, this makes less sense if
             // a non-VR app sends an intent, perhaps just ignoring the intent is better.
-            instance.onEnterVrUnsupported();
+            onEnterVrUnsupported();
             return;
         }
 
@@ -1089,42 +1267,7 @@
         // mEnterVrOnStartup bit above). If Chrome is already running, onResume which will be called
         // after VrShellDelegate#onNewIntentWithNative which will cancel the animation and enter VR
         // after that.
-        if (!instance.mPaused) instance.cancelStartupAnimationIfNeeded();
-    }
-
-    /**
-     * This is called when ChromeTabbedActivity gets a new intent before native is initialized.
-     */
-    public static void maybeHandleVrIntentPreNative(ChromeActivity activity, Intent intent) {
-        if (!VrIntentUtils.isVrIntent(intent)) return;
-
-        // We add a black overlay view so that we can show black while the VR UI is loading.
-        // Note that this alone isn't sufficient to prevent 2D UI from showing when
-        // auto-presenting WebVR. See comment about the custom animation in {@link
-        // getVrIntentOptions}.
-        // TODO(crbug.com/775574): This hack doesn't really work to hide the 2D UI on Samsung
-        // devices since Chrome gets paused and we prematurely remove the overlay.
-        if (sInstance == null || !sInstance.mInVr) addBlackOverlayViewForActivity(activity);
-
-        // If we're already in VR, or launching from an internal intent, we don't want to set system
-        // ui visibility here, or we'll incorrectly restore window mode later.
-        if (sInstance != null && (sInstance.mInVr || sInstance.mInternalIntentUsedToStartVr)) {
-            return;
-        }
-        if (DEBUG_LOGS) Log.i(TAG, "maybeHandleVrIntentPreNative: preparing for transition");
-
-        // Enable VR mode and hide system UI. We do this here so we don't get kicked out of
-        // VR mode and to prevent seeing a flash of system UI.
-        getVrClassesWrapper().setVrModeEnabled(activity, true);
-        activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
-        activity.getWindow().getDecorView().setSystemUiVisibility(VR_SYSTEM_UI_FLAGS);
-    }
-
-    /**
-     * Asynchronously enable VR mode.
-     */
-    public static void setVrModeEnabled(Activity activity) {
-        getVrClassesWrapper().setVrModeEnabled(activity, true);
+        if (!mPaused) cancelStartupAnimationIfNeeded();
     }
 
     @Override
@@ -1216,7 +1359,7 @@
         // If vr shell is not enabled and this is not a web vr request, then return false.
         boolean presenting = mRequestedWebVr || mListeningForWebVrActivate
                 || (justCompletedDon && mListeningForWebVrActivateBeforePause) || mAutopresentWebVr;
-        if (!isVrShellEnabled(mVrSupportLevel) && !presenting) return false;
+        if (!isVrBrowsingEnabled() && !presenting) return false;
         return true;
     }
 
@@ -1367,7 +1510,7 @@
         }
 
         if (mVrSupportLevel != VrSupportLevel.VR_DAYDREAM) return;
-        if (isVrShellEnabled(mVrSupportLevel) && activitySupportsVrBrowsing(mActivity)) {
+        if (isVrBrowsingEnabled()) {
             // Perform slow initialization asynchronously.
             new Handler().post(new Runnable() {
                 @Override
@@ -1385,14 +1528,11 @@
 
         if (mEnterVrOnStartup) {
             // This means that Chrome was started with a VR intent, so we should enter VR.
-            // TODO(crbug.com/776235): VR intents are dispatched to ChromeActivity via a launcher
-            // which should handle the DON flow to simplify the logic in VrShellDelegate.
+            // TODO(crbug.com/776235): The launcher should ensure that the DON flow has been run
+            // prior to starting Chrome.
             assert !mProbablyInDon;
             if (DEBUG_LOGS) Log.i(TAG, "onResume: entering VR mode for VR intent");
-
-            if (enterVrInternal() == ENTER_VR_CANCELLED) {
-                cancelPendingVrEntry();
-            }
+            enterVrAfterDon();
         } else if (mDonSucceeded) {
             handleDonFlowSuccess();
         } else {
@@ -1728,40 +1868,6 @@
         return true;
     }
 
-    private static void startFeedback(Tab tab) {
-        // TODO(ymalik): This call will connect to the Google Services api which can be slow. Can we
-        // connect to it beforehand when we know that we'll be prompting for feedback?
-        HelpAndFeedback.getInstance(tab.getActivity())
-                .showFeedback(tab.getActivity(), tab.getProfile(), tab.getUrl(),
-                        ContextUtils.getApplicationContext().getPackageName() + "."
-                                + FEEDBACK_REPORT_TYPE);
-    }
-
-    private static void promptForFeedback(final Tab tab) {
-        if (tab == null) return;
-        final ChromeActivity activity = tab.getActivity();
-        SimpleConfirmInfoBarBuilder.Listener listener = new SimpleConfirmInfoBarBuilder.Listener() {
-            @Override
-            public void onInfoBarDismissed() {}
-
-            @Override
-            public boolean onInfoBarButtonClicked(boolean isPrimary) {
-                if (isPrimary) {
-                    startFeedback(tab);
-                } else {
-                    VrFeedbackStatus.setFeedbackOptOut(true);
-                }
-                return false;
-            }
-        };
-
-        SimpleConfirmInfoBarBuilder.create(tab, listener,
-                InfoBarIdentifier.VR_FEEDBACK_INFOBAR_ANDROID, R.drawable.vr_services,
-                activity.getString(R.string.vr_shell_feedback_infobar_description),
-                activity.getString(R.string.vr_shell_feedback_infobar_feedback_button),
-                activity.getString(R.string.no_thanks), true /* autoExpire  */);
-    }
-
     /**
      * Prompts the user to enter feedback for their VR Browsing experience.
      */
@@ -1787,57 +1893,6 @@
         promptForFeedback(mActivity.getActivityTab());
     }
 
-    private static boolean isVrCoreCompatible(
-            final VrCoreVersionChecker versionChecker, final Tab tabToShowInfobarIn) {
-        final int vrCoreCompatibility = versionChecker.getVrCoreCompatibility();
-        boolean needsUpdate = vrCoreCompatibility == VrCoreCompatibility.VR_NOT_AVAILABLE
-                || vrCoreCompatibility == VrCoreCompatibility.VR_OUT_OF_DATE;
-        if (tabToShowInfobarIn != null && needsUpdate) {
-            ThreadUtils.assertOnUiThread();
-            new Handler().post(new Runnable() {
-                @Override
-                public void run() {
-                    promptToUpdateVrServices(vrCoreCompatibility, tabToShowInfobarIn);
-                }
-            });
-        }
-
-        return vrCoreCompatibility == VrCoreCompatibility.VR_READY;
-    }
-
-    private static void promptToUpdateVrServices(int vrCoreCompatibility, Tab tab) {
-        final Activity activity = tab.getActivity();
-        String infobarText;
-        String buttonText;
-        if (vrCoreCompatibility == VrCoreCompatibility.VR_NOT_AVAILABLE) {
-            // Supported, but not installed. Ask user to install instead of upgrade.
-            infobarText = activity.getString(R.string.vr_services_check_infobar_install_text);
-            buttonText = activity.getString(R.string.vr_services_check_infobar_install_button);
-        } else if (vrCoreCompatibility == VrCoreCompatibility.VR_OUT_OF_DATE) {
-            infobarText = activity.getString(R.string.vr_services_check_infobar_update_text);
-            buttonText = activity.getString(R.string.vr_services_check_infobar_update_button);
-        } else {
-            Log.e(TAG, "Unknown VrCore compatibility: " + vrCoreCompatibility);
-            return;
-        }
-
-        SimpleConfirmInfoBarBuilder.Listener listener = new SimpleConfirmInfoBarBuilder.Listener() {
-            @Override
-            public void onInfoBarDismissed() {}
-
-            @Override
-            public boolean onInfoBarButtonClicked(boolean isPrimary) {
-                activity.startActivityForResult(
-                        new Intent(Intent.ACTION_VIEW, Uri.parse(VR_CORE_MARKET_URI)),
-                        VR_SERVICES_UPDATE_RESULT);
-                return false;
-            }
-        };
-        SimpleConfirmInfoBarBuilder.create(tab, listener,
-                InfoBarIdentifier.VR_SERVICES_UPGRADE_ANDROID, R.drawable.vr_services, infobarText,
-                buttonText, null, true);
-    }
-
     /* package */ void promptForKeyboardUpdate() {
         mCachedGvrKeyboardPackageVersion = getGvrKeyboardPackageVersion();
         mActivity.startActivityForResult(
@@ -1845,7 +1900,7 @@
                 GVR_KEYBOARD_UPDATE_RESULT);
     }
 
-    private boolean createVrShell() {
+    protected boolean createVrShell() {
         assert mVrShell == null;
         if (mVrClassesWrapper == null) return false;
         if (mActivity.getCompositorViewHolder() == null) return false;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java
index 49ccf46c5..58a279d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java
@@ -111,6 +111,7 @@
     private AndroidUiGestureTarget mAndroidDialogGestureTarget;
 
     private OnDispatchTouchEventCallback mOnDispatchTouchEventForTesting;
+    private Runnable mOnVSyncPausedForTesting;
 
     private Surface mContentSurface;
     private VrViewContainer mNonVrViews;
@@ -120,6 +121,8 @@
     private ModalDialogManager mVrModalDialogManager;
     private VrModalPresenter mVrModalPresenter;
 
+    private VrInputMethodManagerWrapper mInputMethodManagerWrapper;
+
     public VrShellImpl(
             ChromeActivity activity, VrShellDelegate delegate, TabModelSelector tabModelSelector) {
         super(activity);
@@ -421,8 +424,8 @@
         if (mTab.getWebContents() == null) return;
         ImeAdapter imeAdapter = ImeAdapter.fromWebContents(mTab.getWebContents());
         if (imeAdapter != null) {
-            imeAdapter.setInputMethodManagerWrapper(
-                    new VrInputMethodManagerWrapper(mActivity, this));
+            mInputMethodManagerWrapper = new VrInputMethodManagerWrapper(mActivity, this);
+            imeAdapter.setInputMethodManagerWrapper(mInputMethodManagerWrapper);
         }
     }
 
@@ -434,6 +437,7 @@
             imeAdapter.setInputMethodManagerWrapper(
                     ImeAdapter.createDefaultInputMethodManagerWrapper(mActivity));
         }
+        mInputMethodManagerWrapper = null;
     }
 
     private void restoreTabFromVR() {
@@ -792,6 +796,9 @@
             if (mPendingVSyncPause) {
                 mContentVrWindowAndroid.setVSyncPaused(true);
                 mPendingVSyncPause = false;
+                if (mOnVSyncPausedForTesting != null) {
+                    mOnVSyncPausedForTesting.run();
+                }
             }
         });
     }
@@ -808,6 +815,12 @@
         return nativeIsDisplayingUrlForTesting(mNativeVrShell);
     }
 
+    @VisibleForTesting
+    public VrInputConnection getVrInputConnectionForTesting() {
+        assert mNativeVrShell != 0;
+        return nativeGetVrInputConnectionForTesting(mNativeVrShell);
+    }
+
     @Override
     public FrameLayout getContainer() {
         return this;
@@ -988,6 +1001,16 @@
         mOnDispatchTouchEventForTesting = callback;
     }
 
+    /**
+     * Sets that callback that will be run when VrShellImpl has issued the request to pause the
+     * Android Window's VSyncs.
+     * @param callback The Runnable to be run.
+     */
+    @VisibleForTesting
+    public void setOnVSyncPausedForTesting(Runnable callback) {
+        mOnVSyncPausedForTesting = callback;
+    }
+
     @VisibleForTesting
     @Override
     public Boolean isBackButtonEnabled() {
@@ -1034,6 +1057,11 @@
                 mNativeVrShell, selectionStart, selectionEnd, compositionStart, compositionEnd);
     }
 
+    @VisibleForTesting
+    public VrInputMethodManagerWrapper getInputMethodManageWrapperForTesting() {
+        return mInputMethodManagerWrapper;
+    }
+
     @Override
     public void acceptDoffPromptForTesting() {
         nativeAcceptDoffPromptForTesting(mNativeVrShell);
@@ -1076,6 +1104,7 @@
     private native void nativeShowSoftInput(long nativeVrShell, boolean show);
     private native void nativeUpdateWebInputIndices(long nativeVrShell, int selectionStart,
             int selectionEnd, int compositionStart, int compositionEnd);
+    private native VrInputConnection nativeGetVrInputConnectionForTesting(long nativeVrShell);
     private native void nativeAcceptDoffPromptForTesting(long nativeVrShell);
     private native void nativeResumeContentRendering(long nativeVrShell);
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/keyboard/GvrKeyboardLoaderClient.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/keyboard/GvrKeyboardLoaderClient.java
index 33e339b..5daf521a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/keyboard/GvrKeyboardLoaderClient.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/keyboard/GvrKeyboardLoaderClient.java
@@ -72,7 +72,7 @@
             ClassLoader remoteClassLoader = (ClassLoader) getRemoteClassLoader();
             if (remoteClassLoader != null) {
                 IBinder binder = newBinder(remoteClassLoader, LOADER_NAME);
-                sLoader = IGvrKeyboardLoader.Stub.asInterface(binder);
+                if (binder != null) sLoader = IGvrKeyboardLoader.Stub.asInterface(binder);
             }
         }
         return sLoader;
@@ -115,7 +115,10 @@
             Class<?> clazz = classLoader.loadClass(className);
             return (IBinder) clazz.getConstructor().newInstance();
         } catch (ClassNotFoundException e) {
-            throw new IllegalStateException("Unable to find dynamic class " + className);
+            // This could happen if the user has a really old version of the keyboard installed when
+            // dynamic loading was not supported.
+            Log.e(TAG, "Unable to find dynamic class " + className);
+            return null;
         } catch (InstantiationException e) {
             throw new IllegalStateException("Unable to instantiate the remote class " + className);
         } catch (IllegalAccessException e) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/keyboard/TextEditAction.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/keyboard/TextEditAction.java
index c115908..2d7174e9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/keyboard/TextEditAction.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/keyboard/TextEditAction.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.vr_shell.keyboard;
 
+import org.chromium.base.VisibleForTesting;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.chrome.browser.vr_shell.TextEditActionType;
@@ -25,8 +26,9 @@
         return new TextEditAction[size];
     }
 
+    @VisibleForTesting
     @CalledByNative
-    private TextEditAction(@TextEditActionType int type, String text, int newCursorPosition) {
+    public TextEditAction(@TextEditActionType int type, String text, int newCursorPosition) {
         mType = type;
         mText = text;
         mNewCursorPosition = newCursorPosition;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/keyboard/VrInputMethodManagerWrapper.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/keyboard/VrInputMethodManagerWrapper.java
index 8e83b66..795ec9c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/keyboard/VrInputMethodManagerWrapper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/keyboard/VrInputMethodManagerWrapper.java
@@ -12,6 +12,7 @@
 import android.view.inputmethod.EditorInfo;
 
 import org.chromium.base.Log;
+import org.chromium.base.VisibleForTesting;
 import org.chromium.content_public.browser.InputMethodManagerWrapper;
 
 /**
@@ -47,6 +48,11 @@
         mKeyboard = keyboard;
     }
 
+    @VisibleForTesting
+    public void setBrowserKeyboardInterfaceForTesting(BrowserKeyboardInterface keyboard) {
+        mKeyboard = keyboard;
+    }
+
     @Override
     public void restartInput(View view) {
         if (DEBUG_LOGS) Log.i(TAG, "restartInput");
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java
index 3506330d..57ac584 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java
@@ -96,6 +96,14 @@
         int NAVIGATION = 4;
     }
 
+    /** The different priorities that the sheet's content can have. */
+    @IntDef({ContentPriority.HIGH, ContentPriority.LOW})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ContentPriority {
+        int HIGH = 0;
+        int LOW = 1;
+    }
+
     /**
      * The base duration of the settling animation of the sheet. 218 ms is a spec for material
      * design (this is the minimum time a user is guaranteed to pay attention to something).
@@ -171,6 +179,13 @@
     /** The height of the view that contains the bottom sheet. */
     private float mContainerHeight;
 
+    /**
+     * The current offset of the sheet from the bottom of the screen in px. This does not include
+     * added offset from the scrolling of the browser controls which allows the sheet's toolbar to
+     * show and hide in-sync with the top toolbar.
+     */
+    private float mCurrentOffsetPx;
+
     /** The current state that the sheet is in. */
     @SheetState
     private int mCurrentState = SHEET_STATE_HIDDEN;
@@ -278,6 +293,12 @@
          * @return Whether the default top padding should be applied to the content view.
          */
         boolean applyDefaultTopPadding();
+
+        /**
+         * @return The priority of this content.
+         */
+        @ContentPriority
+        int getPriority();
     }
 
     /**
@@ -305,7 +326,10 @@
     public boolean shouldGestureMoveSheet(MotionEvent initialEvent, MotionEvent currentEvent) {
         // If the sheet is scrolling off-screen or in the process of hiding, gestures should not
         // affect it.
-        if (getCurrentOffsetPx() < getSheetHeightForState(SHEET_STATE_PEEK)) return false;
+        if (getCurrentOffsetPx() < getSheetHeightForState(SHEET_STATE_PEEK)
+                || getOffsetFromBrowserControls() > 0) {
+            return false;
+        }
 
         // If the sheet is already open, the experiment is not enabled, or accessibility is enabled
         // there is no need to restrict the swipe area.
@@ -495,7 +519,8 @@
         mToolbarHolder =
                 (TouchRestrictingFrameLayout) findViewById(R.id.bottom_sheet_toolbar_container);
         mDefaultToolbarView = mToolbarHolder.findViewById(R.id.bottom_sheet_toolbar);
-        mToolbarHeight = mDefaultToolbarView.getHeight();
+        mToolbarHeight = activity.getResources().getDimensionPixelSize(
+                R.dimen.bottom_control_container_height);
 
         mActivity = activity;
         mActionBarDelegate = new ViewShiftingActionBarDelegate(mActivity, this);
@@ -591,9 +616,6 @@
                     return;
                 }
 
-                mToolbarHeight = bottom - top;
-                updateSheetStateRatios();
-
                 if (!mGestureDetector.isScrolling()) {
                     cancelAnimation();
 
@@ -622,10 +644,8 @@
                 if (getSheetState() == SHEET_STATE_HIDDEN) return;
                 if (getCurrentOffsetPx() > getSheetHeightForState(SHEET_STATE_PEEK)) return;
 
-                float hiddenRatio = -topOffset / mFullscreenManager.getTopControlsHeight();
-                float peekHeight = getPeekRatio() * mContainerHeight;
-
-                setSheetOffsetFromBottom(peekHeight - hiddenRatio * peekHeight);
+                // Updating the offset will automatically account for the browser controls.
+                setSheetOffsetFromBottom(getCurrentOffsetPx());
             }
 
             @Override
@@ -695,7 +715,7 @@
 
     @Override
     public float getCurrentOffsetPx() {
-        return mContainerHeight - getTranslationY();
+        return mCurrentOffsetPx;
     }
 
     @Override
@@ -1015,13 +1035,27 @@
     }
 
     /**
+     * @return Get the height in px that the peeking bar is offset due to the browser controls.
+     */
+    private float getOffsetFromBrowserControls() {
+        float peekHeight = getPeekRatio() * mContainerHeight;
+        return peekHeight * mFullscreenManager.getBrowserControlHiddenRatio();
+    }
+
+    /**
      * Sets the sheet's offset relative to the bottom of the screen.
      * @param offset The offset that the sheet should be.
      */
     private void setSheetOffsetFromBottom(float offset) {
-        if (MathUtils.areFloatsEqual(offset, getCurrentOffsetPx())) return;
+        mCurrentOffsetPx = offset;
 
-        setTranslationY(mContainerHeight - offset);
+        // The browser controls offset is added here so that the sheet's toolbar behaves like the
+        // browser controls do.
+        float translationY = (mContainerHeight - mCurrentOffsetPx) + getOffsetFromBrowserControls();
+
+        if (MathUtils.areFloatsEqual(translationY, getTranslationY())) return;
+
+        setTranslationY(translationY);
         sendOffsetChangeEvents();
     }
 
@@ -1350,7 +1384,7 @@
 
         float threshold =
                 shouldSkipHalfState ? THRESHOLD_TO_NEXT_STATE_2 : THRESHOLD_TO_NEXT_STATE_3;
-        float thresholdToNextState = yVelocity < 0.0f ? 1.0f - threshold : threshold;
+        float thresholdToNextState = yVelocity < 0.0f ? 1 - threshold : threshold;
 
         if ((sheetHeight - lowerBound) / distance > thresholdToNextState) {
             return nextState;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetController.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetController.java
new file mode 100644
index 0000000..4a6c66cf
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetController.java
@@ -0,0 +1,220 @@
+// Copyright 2018 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.
+
+package org.chromium.chrome.browser.widget.bottomsheet;
+
+import org.chromium.chrome.browser.compositor.layouts.Layout;
+import org.chromium.chrome.browser.compositor.layouts.LayoutManager;
+import org.chromium.chrome.browser.compositor.layouts.SceneChangeObserver;
+import org.chromium.chrome.browser.compositor.layouts.StaticLayout;
+import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tabmodel.TabModelSelector;
+import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver;
+import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet.BottomSheetContent;
+
+import java.util.PriorityQueue;
+
+/**
+ * This class is responsible for managing the content shown by the {@link BottomSheet}. Features
+ * wishing to show content in the {@link BottomSheet} UI must implement {@link BottomSheetContent}
+ * and call {@link #requestShowContent(BottomSheetContent, boolean)} which will return true if the
+ * content was actually shown (see full doc on method).
+ */
+public class BottomSheetController {
+    /** The initial capacity for the priority queue handling pending content show requests. */
+    private static final int INITIAL_QUEUE_CAPACITY = 1;
+
+    /** A handle to the {@link LayoutManager} to determine what state the browser is in. */
+    private final LayoutManager mLayoutManager;
+
+    /** A handle to the {@link BottomSheet} that this class controls. */
+    private final BottomSheet mBottomSheet;
+
+    /** A queue for content that is waiting to be shown in the {@link BottomSheet}. */
+    private PriorityQueue<BottomSheetContent> mContentQueue;
+
+    /** Whether the controller is already processing a hide request for the tab. */
+    private boolean mIsProcessingHideRequest;
+
+    /** Track whether the sheet was shown for the current tab. */
+    private boolean mWasShownForCurrentTab;
+
+    /**
+     * Build a new controller of the bottom sheet.
+     * @param tabModelSelector A tab model selector to track events on tabs open in the browser.
+     * @param layoutManager A layout manager for detecting changes in the active layout.
+     * @param bottomSheet The bottom sheet that this class will be controlling.
+     */
+    public BottomSheetController(final TabModelSelector tabModelSelector,
+            final LayoutManager layoutManager, BottomSheet bottomSheet) {
+        mBottomSheet = bottomSheet;
+        mLayoutManager = layoutManager;
+
+        // Watch for navigation and tab switching that close the sheet.
+        new TabModelSelectorTabObserver(tabModelSelector) {
+            @Override
+            public void onShown(Tab tab) {
+                if (tab != tabModelSelector.getCurrentTab()) return;
+                clearRequestsAndHide();
+            }
+
+            @Override
+            public void onPageLoadStarted(Tab tab, String url) {
+                if (tab != tabModelSelector.getCurrentTab()) return;
+                clearRequestsAndHide();
+            }
+        };
+
+        // If the layout changes (to tab switcher, toolbar swipe, etc.) hide the sheet.
+        mLayoutManager.addSceneChangeObserver(new SceneChangeObserver() {
+            @Override
+            public void onTabSelectionHinted(int tabId) {}
+
+            @Override
+            public void onSceneChange(Layout layout) {
+                // If the tab did not change, reshow the existing content. Once the tab actually
+                // changes, existing content and requests will be cleared.
+                if (layout instanceof StaticLayout && mWasShownForCurrentTab
+                        && mBottomSheet.getCurrentSheetContent() != null) {
+                    mBottomSheet.setSheetState(BottomSheet.SHEET_STATE_PEEK, true);
+                } else {
+                    mBottomSheet.setSheetState(BottomSheet.SHEET_STATE_HIDDEN, false);
+                }
+            }
+        });
+
+        // Initialize the queue with a comparator that checks content priority.
+        mContentQueue = new PriorityQueue<>(INITIAL_QUEUE_CAPACITY,
+                (content1, content2) -> content2.getPriority() - content1.getPriority());
+    }
+
+    /**
+     * Request that some content be shown in the bottom sheet.
+     * @param content The content to be shown in the bottom sheet.
+     * @param animate Whether the appearance of the bottom sheet should be animated.
+     * @return True if the content was shown, false if it was suppressed. Content is suppressed if
+     *         higher priority content is in the sheet, the sheet is expanded beyond the peeking
+     *         state, or the browser is in a mode that does not support showing the sheet.
+     */
+    public boolean requestShowContent(BottomSheetContent content, boolean animate) {
+        // If pre-load failed, do nothing. The content will automatically be queued.
+        if (!requestContentPreload(content)) return false;
+        if (!mBottomSheet.isSheetOpen()) {
+            mBottomSheet.setSheetState(BottomSheet.SHEET_STATE_PEEK, animate);
+        }
+        mWasShownForCurrentTab = true;
+        return true;
+    }
+
+    /**
+     * Request content start loading in the bottom sheet without actually showing the
+     * {@link BottomSheet}. Another call to {@link #requestShowContent(BottomSheetContent, boolean)}
+     * is required to actually make the sheet appear.
+     * @param content The content to pre-load.
+     * @return True if the content started loading.
+     */
+    public boolean requestContentPreload(BottomSheetContent content) {
+        if (content == mBottomSheet.getCurrentSheetContent()) return true;
+        if (!isValidLayoutShowing()) return false;
+
+        boolean shouldSuppressExistingContent = mBottomSheet.getCurrentSheetContent() != null
+                && mBottomSheet.getSheetState() <= BottomSheet.SHEET_STATE_PEEK
+                && content.getPriority() < mBottomSheet.getCurrentSheetContent().getPriority()
+                && canBottomSheetSwitchContent();
+
+        BottomSheetContent shownContent = mBottomSheet.getCurrentSheetContent();
+        if (shouldSuppressExistingContent) {
+            mContentQueue.add(mBottomSheet.getCurrentSheetContent());
+            shownContent = content;
+        } else if (mBottomSheet.getCurrentSheetContent() == null) {
+            shownContent = content;
+        } else {
+            mContentQueue.add(content);
+        }
+
+        assert shownContent != null;
+        mBottomSheet.showContent(shownContent);
+
+        return shownContent == content;
+    }
+
+    /**
+     * Hide content shown in the bottom sheet. If the content is not showing, this call retracts the
+     * request to show it.
+     * @param content The content to be hidden.
+     * @param animate Whether the sheet should animate when hiding.
+     */
+    public void hideContent(BottomSheetContent content, boolean animate) {
+        if (content != mBottomSheet.getCurrentSheetContent()) {
+            mContentQueue.remove(content);
+            return;
+        }
+
+        // If the sheet is already processing a request to hide visible content, do nothing.
+        if (mIsProcessingHideRequest) return;
+
+        // Handle showing the next content if it exists.
+        if (mBottomSheet.getSheetState() == BottomSheet.SHEET_STATE_HIDDEN) {
+            // If the sheet is already hidden, simply show the next content.
+            showNextContent();
+        } else {
+            // If the sheet wasn't hidden, wait for it to be before showing the next content.
+            BottomSheetObserver hiddenSheetObserver = new EmptyBottomSheetObserver() {
+                @Override
+                public void onSheetStateChanged(int currentState) {
+                    // Don't do anything until the sheet is completely hidden.
+                    if (currentState != BottomSheet.SHEET_STATE_HIDDEN) return;
+
+                    showNextContent();
+                    mBottomSheet.removeObserver(this);
+                    mIsProcessingHideRequest = false;
+                }
+            };
+
+            mIsProcessingHideRequest = true;
+            mBottomSheet.addObserver(hiddenSheetObserver);
+            mBottomSheet.setSheetState(BottomSheet.SHEET_STATE_HIDDEN, animate);
+        }
+    }
+
+    /**
+     * Show the next {@link BottomSheetContent} if it is available and peek the sheet. If no content
+     * is available the sheet's content is set to null.
+     */
+    private void showNextContent() {
+        if (mContentQueue.isEmpty()) {
+            mBottomSheet.showContent(null);
+            return;
+        }
+
+        mBottomSheet.showContent(mContentQueue.poll());
+        mBottomSheet.setSheetState(BottomSheet.SHEET_STATE_PEEK, true);
+    }
+
+    /**
+     * Clear all the content show requests and hide the current content.
+     */
+    private void clearRequestsAndHide() {
+        mContentQueue.clear();
+        // TODO(mdjones): Replace usages of bottom sheet with a model in line with MVC.
+        // TODO(mdjones): It would probably be useful to expose an observer method that notifies
+        //                objects when all content requests are cleared.
+        hideContent(mBottomSheet.getCurrentSheetContent(), true);
+        mWasShownForCurrentTab = false;
+    }
+
+    /**
+     * @return Whether the browser is in a layout that supports showing the bottom sheet.
+     */
+    protected boolean isValidLayoutShowing() {
+        return mLayoutManager.getActiveLayout() instanceof StaticLayout;
+    }
+
+    /**
+     * @return Whether the sheet currently supports switching its content.
+     */
+    protected boolean canBottomSheetSwitchContent() {
+        return mBottomSheet.isSheetOpen();
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/ChromeHomeIphMenuHeader.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/ChromeHomeIphMenuHeader.java
deleted file mode 100644
index 2f904df..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/ChromeHomeIphMenuHeader.java
+++ /dev/null
@@ -1,91 +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.
-
-package org.chromium.chrome.browser.widget.bottomsheet;
-
-import android.content.Context;
-import android.support.annotation.VisibleForTesting;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.LinearLayout;
-
-import org.chromium.base.ThreadUtils;
-import org.chromium.chrome.browser.ChromeActivity;
-import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
-import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.components.feature_engagement.EventConstants;
-import org.chromium.components.feature_engagement.FeatureConstants;
-
-/**
- * A menu header helping users find where their content moved when Chrome Home is enabled.
- * The Chrome Home in-product help bubble pointing toward the bottom sheet is displayed on click.
- */
-public class ChromeHomeIphMenuHeader extends LinearLayout implements OnClickListener {
-    /** Notified about events related to the menu header. */
-    public static interface ChromeHomeIphMenuHeaderTestObserver {
-        void onMenuItemClicked();
-        void onMenuDismissed(boolean dimissIph);
-    }
-
-    private static ChromeHomeIphMenuHeaderTestObserver sTestObserver;
-
-    private ChromeActivity mActivity;
-    private boolean mDismissIPHOnMenuDismissed;
-
-    public ChromeHomeIphMenuHeader(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    /**
-     * Initializes the menu header.
-     * @param activity The {@link ChromeActivity} that will display the app menu containing this
-     *                 header.
-     */
-    public void initialize(ChromeActivity activity) {
-        mActivity = activity;
-        mDismissIPHOnMenuDismissed = true;
-        setOnClickListener(this);
-    }
-
-    @Override
-    public void onClick(View v) {
-        mDismissIPHOnMenuDismissed = false;
-
-        TrackerFactory.getTrackerForProfile(Profile.getLastUsedProfile())
-                .notifyEvent(EventConstants.CHROME_HOME_MENU_HEADER_CLICKED);
-
-        mActivity.getBottomSheet().getBottomSheetMetrics().recordInProductHelpMenuItemClicked();
-
-        mActivity.getAppMenuHandler().hideAppMenu();
-
-        if (sTestObserver != null) sTestObserver.onMenuItemClicked();
-    }
-
-    /**
-     * Must be called when the app menu is dismissed. Used to notify the IPH system that the menu
-     * header is no longer showing.
-     */
-    public void onMenuDismissed() {
-        if (sTestObserver != null) {
-            sTestObserver.onMenuDismissed(mDismissIPHOnMenuDismissed);
-        }
-
-        if (!mDismissIPHOnMenuDismissed) return;
-
-        TrackerFactory.getTrackerForProfile(Profile.getLastUsedProfile())
-                .dismissed(FeatureConstants.CHROME_HOME_MENU_HEADER_FEATURE);
-        mDismissIPHOnMenuDismissed = false;
-    }
-
-    /**
-     * An observer to be notified about events related to the menu header. Used for testing. Must be
-     * called on the UI thread.
-     */
-    @VisibleForTesting
-    public static void setObserverForTests(ChromeHomeIphMenuHeaderTestObserver observer) {
-        ThreadUtils.assertOnUiThread();
-        sTestObserver = observer;
-    }
-}
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index 41e15b6..7d6c2837 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -2301,6 +2301,20 @@
       <message name="IDS_SIGNIN_TITLE" desc="Title for the screen that asks users to sign-in and turn on Sync and personalization. [CHAR-LIMIT=27]" translateable="false">
         Get even more from Chrome
       </message>
+      <message name="IDS_SIGNIN_SYNC_DESCRIPTION" desc="Description of Sync feature for the screen that asks users to sign-in and turn on Sync and personalization." translateable="false">
+        Sync your bookmarks, passwords, history, and more on all your devices
+      </message>
+      <message name="IDS_SIGNIN_PERSONALIZATION_DESCRIPTION" desc="Description of personalization feature for the screen that asks users to sign-in and turn on Sync and personalization." translateable="false">
+        Get more personalized experiences, such as better content suggestions and smarter Translate
+      </message>
+      <message name="IDS_SIGNIN_GOOGLE_SERVICES_DESCRIPTION" desc="Description of Google Services for the screen that asks users to sign-in and turn on Sync and personalization." translateable="false">
+        Bring powerful Google services to Chrome, like Google Pay and tap to search
+      </message>
+      <message name="IDS_SIGNIN_DETAILS_DESCRIPTION" desc="Message explaining that user can customize Sync and personalization and explains what data is shared with Google. This message is shown in the screen that asks users to sign-in and turn on Sync and personalization." translateable="false">
+        You can customize what information Google collects in <ph name="BEGIN_LINK1">&lt;LINK1&gt;</ph>Settings<ph name="END_LINK1">&lt;/LINK1&gt;</ph> anytime.
+
+Google may use your browsing activity, content on some sites you visit, and other browser interactions to personalize Chrome and other Google services like Translate, Search and ads.
+      </message>
       <message name="IDS_SIGNIN_ACCEPT_BUTTON" desc="Text for the confirmation button in the sign-in screen. By clicking this button users signs in and turns on Sync and personalization. [CHAR-LIMIT=20]" translateable="false">
         Yes, I'm in
       </message>
@@ -2433,8 +2447,8 @@
       <message name="IDS_NTP_ALL_DISMISSED_REFRESH" desc="Text label for button to refresh the New Tab Page when all suggested content has been dismissed. [CHAR-LIMIT=20]">
         Refresh
       </message>
-      <message name="IDS_CONTEXTUAL_SUGGESTIONS_TITLE" desc="The title for a section containing a list of article suggestions based on the user's current webpage. The title tells users that the list contains articles viewed by people who also viewed the current webpage.">
-        People also viewed
+      <message name="IDS_CONTEXTUAL_SUGGESTIONS_TOOLBAR_TITLE" desc="The title displayed above a list of content suggestions based on the user's current webpage. The title tells the user that the list contains more suggestions related to the topic they are currently viewing.">
+        More about <ph name="TOPIC">%1$s<ex>Game of Thrones</ex></ph>
       </message>
 
       <!-- Toolbar button strings -->
@@ -3221,9 +3235,6 @@
       <message name="IDS_BOTTOM_SHEET_CLOSED" desc="Accessibility string read when the bottom navigation panel is closed.">
         Navigation panel closed
       </message>
-      <message name="IDS_BOTTOM_SHEET_APP_MENU_IPH" desc="Label for in-product help that appears in the Chrome three-dot menu (navigation menu). In previous versions of Chrome, the menu contained Downloads, Bookmarks, and History. In this version of Chrome, these three items have been moved out of the menu. Tapping this help text will show the user where they can find these three items. 'Downloads', 'Bookmarks', and 'History' should use the same translations as in Chrome settings and menu items. The tone of this string is that of the user asking Chrome, 'where are these 3 things?'">
-        Where are downloads, bookmarks, and history?
-      </message>
 
       <!-- Photo picker -->
       <message name="IDS_PHOTO_PICKER_SELECT_IMAGES" desc="The label in the title bar of the Photo Picker dialog, suggesting which action the user should take.">
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index 831035d..b1be6b8 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -283,6 +283,8 @@
   "java/src/org/chromium/chrome/browser/contextualsearch/RecentScrollTapSuppression.java",
   "java/src/org/chromium/chrome/browser/contextualsearch/SecondTapMlOverride.java",
   "java/src/org/chromium/chrome/browser/contextualsearch/SelectionClientManager.java",
+  "java/src/org/chromium/chrome/browser/contextualsearch/ShortTextRunSuppression.java",
+  "java/src/org/chromium/chrome/browser/contextualsearch/SmallTextSuppression.java",
   "java/src/org/chromium/chrome/browser/contextualsearch/SwipeRecognizer.java",
   "java/src/org/chromium/chrome/browser/contextualsearch/TapDurationSuppression.java",
   "java/src/org/chromium/chrome/browser/contextualsearch/TapFarFromPreviousSuppression.java",
@@ -292,11 +294,17 @@
   "java/src/org/chromium/chrome/browser/contextual_suggestions/ContentCoordinator.java",
   "java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsAdapter.java",
   "java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsBottomSheetContent.java",
+  "java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsBridge.java",
   "java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionCardViewHolder.java",
+  "java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsCluster.java",
   "java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsCoordinator.java",
   "java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsMediator.java",
   "java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsModel.java",
   "java/src/org/chromium/chrome/browser/contextual_suggestions/DummyEventReporter.java",
+  "java/src/org/chromium/chrome/browser/contextual_suggestions/PropertyKey.java",
+  "java/src/org/chromium/chrome/browser/contextual_suggestions/ToolbarCoordinator.java",
+  "java/src/org/chromium/chrome/browser/contextual_suggestions/ToolbarModelChangeProcessor.java",
+  "java/src/org/chromium/chrome/browser/contextual_suggestions/ToolbarView.java",
   "java/src/org/chromium/chrome/browser/cookies/CanonicalCookie.java",
   "java/src/org/chromium/chrome/browser/cookies/CookiesFetcher.java",
   "java/src/org/chromium/chrome/browser/coordinator/CoordinatorLayoutForPointer.java",
@@ -660,6 +668,7 @@
   "java/src/org/chromium/chrome/browser/modaldialog/TabModalLifetimeHandler.java",
   "java/src/org/chromium/chrome/browser/modaldialog/TabModalPresenter.java",
   "java/src/org/chromium/chrome/browser/modelutil/ListObservable.java",
+  "java/src/org/chromium/chrome/browser/modelutil/PropertyObservable.java",
   "java/src/org/chromium/chrome/browser/modelutil/RecyclerViewModelChangeProcessor.java",
   "java/src/org/chromium/chrome/browser/modelutil/RecyclerViewAdapter.java",
   "java/src/org/chromium/chrome/browser/mojo/ChromeInterfaceRegistrar.java",
@@ -1007,6 +1016,7 @@
   "java/src/org/chromium/chrome/browser/preferences/password/CallbackDelayer.java",
   "java/src/org/chromium/chrome/browser/preferences/password/DialogManager.java",
   "java/src/org/chromium/chrome/browser/preferences/password/ExportErrorDialogFragment.java",
+  "java/src/org/chromium/chrome/browser/preferences/password/ExportFlow.java",
   "java/src/org/chromium/chrome/browser/preferences/password/ExportWarningDialogFragment.java",
   "java/src/org/chromium/chrome/browser/preferences/password/ManualCallbackDelayer.java",
   "java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryEditor.java",
@@ -1417,10 +1427,10 @@
   "java/src/org/chromium/chrome/browser/widget/animation/CancelAwareAnimatorListener.java",
   "java/src/org/chromium/chrome/browser/widget/animation/FocusAnimator.java",
   "java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java",
+  "java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetController.java",
   "java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetSwipeDetector.java",
   "java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetMetrics.java",
   "java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetObserver.java",
-  "java/src/org/chromium/chrome/browser/widget/bottomsheet/ChromeHomeIphMenuHeader.java",
   "java/src/org/chromium/chrome/browser/widget/bottomsheet/EmptyBottomSheetObserver.java",
   "java/src/org/chromium/chrome/browser/widget/bottomsheet/TouchRestrictingFrameLayout.java",
   "java/src/org/chromium/chrome/browser/widget/displaystyle/MarginResizer.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkModelTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkModelTest.java
index c2129f7..8595e42f5 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkModelTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkModelTest.java
@@ -134,6 +134,64 @@
     @SmallTest
     @UiThreadTest
     @Feature({"Bookmark"})
+    public void testDeleteBookmarks() throws Throwable {
+        BookmarkId bookmarkA = addBookmark(mDesktopNode, 0, "a", "http://a.com");
+        BookmarkId bookmarkB = addBookmark(mOtherNode, 0, "b", "http://b.com");
+        BookmarkId bookmarkC = addBookmark(mMobileNode, 0, "c", "http://c.com");
+
+        // Dete a single bookmark
+        mBookmarkModel.deleteBookmarks(bookmarkA);
+        Assert.assertNull(mBookmarkModel.getBookmarkById(bookmarkA));
+        Assert.assertNotNull(mBookmarkModel.getBookmarkById(bookmarkB));
+        Assert.assertNotNull(mBookmarkModel.getBookmarkById(bookmarkC));
+
+        mBookmarkModel.undo();
+        Assert.assertNotNull(mBookmarkModel.getBookmarkById(bookmarkA));
+
+        // Delete and undo deletion of multiple bookmarks.
+        mBookmarkModel.deleteBookmarks(bookmarkA, bookmarkB);
+
+        Assert.assertNull(mBookmarkModel.getBookmarkById(bookmarkA));
+        Assert.assertNull(mBookmarkModel.getBookmarkById(bookmarkB));
+        Assert.assertNotNull(mBookmarkModel.getBookmarkById(bookmarkC));
+
+        mBookmarkModel.undo();
+
+        Assert.assertNotNull(mBookmarkModel.getBookmarkById(bookmarkA));
+        Assert.assertNotNull(mBookmarkModel.getBookmarkById(bookmarkB));
+        Assert.assertNotNull(mBookmarkModel.getBookmarkById(bookmarkC));
+    }
+
+    @Test
+    @SmallTest
+    @UiThreadTest
+    @Feature({"Bookmark"})
+    public void testDeleteBookmarksRepeatedly() throws Throwable {
+        BookmarkId bookmarkA = addBookmark(mDesktopNode, 0, "a", "http://a.com");
+        BookmarkId bookmarkB = addBookmark(mOtherNode, 0, "b", "http://b.com");
+        BookmarkId bookmarkC = addBookmark(mMobileNode, 0, "c", "http://c.com");
+
+        mBookmarkModel.deleteBookmarks(bookmarkA);
+
+        // This line is problematic, see: https://crbug.com/824559
+        mBookmarkModel.deleteBookmarks(bookmarkA, bookmarkB);
+
+        Assert.assertNull(mBookmarkModel.getBookmarkById(bookmarkA));
+        Assert.assertNull(mBookmarkModel.getBookmarkById(bookmarkB));
+        Assert.assertNotNull(mBookmarkModel.getBookmarkById(bookmarkC));
+
+        // Only bookmark B should be undeleted here.
+        mBookmarkModel.undo();
+
+        Assert.assertNull(mBookmarkModel.getBookmarkById(bookmarkA));
+        Assert.assertNotNull(mBookmarkModel.getBookmarkById(bookmarkB));
+        Assert.assertNotNull(mBookmarkModel.getBookmarkById(bookmarkC));
+    }
+
+    @Test
+    @SmallTest
+    @UiThreadTest
+    @Feature({"Bookmark"})
     public void testGetChildIDs() throws Throwable {
         BookmarkId folderA = mBookmarkModel.addFolder(mMobileNode, 0, "fa");
         HashSet<BookmarkId> expectedChildren = new HashSet<>();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTapEventTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTapEventTest.java
index 311f5dee..ef09d37 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTapEventTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTapEventTest.java
@@ -200,7 +200,7 @@
             @Override
             public void run() {
                 mContextualSearchManager.getGestureStateListener().onTouchDown();
-                mContextualSearchManager.onShowUnhandledTapUIIfNeeded(0, 0);
+                mContextualSearchManager.onShowUnhandledTapUIIfNeeded(0, 0, 12, 100);
             }
         });
     }
@@ -212,7 +212,7 @@
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                mContextualSearchManager.onShowUnhandledTapUIIfNeeded(0, 0);
+                mContextualSearchManager.onShowUnhandledTapUIIfNeeded(0, 0, 0, 0);
                 mContextualSearchClient.onSelectionEvent(
                         SelectionEventType.SELECTION_HANDLES_CLEARED, 0, 0);
             }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
index 420b38c..94189b8 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -2851,7 +2851,7 @@
         }));
         Assert.assertEquals(newActivity.getWindowAndroid(), tabToBeReparented.getWindowAndroid());
         Assert.assertEquals(newActivity.getWindowAndroid(),
-                tabToBeReparented.getContentViewCore().getWindowAndroid());
+                tabToBeReparented.getWebContents().getTopLevelNativeWindow());
         Assert.assertFalse(
                 tabToBeReparented.getDelegateFactory() instanceof CustomTabDelegateFactory);
         Assert.assertEquals("The tab should never be hidden during the reparenting process", 0,
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/DetachedResourceRequestTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/DetachedResourceRequestTest.java
index 59ddf79..34794a1d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/DetachedResourceRequestTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/DetachedResourceRequestTest.java
@@ -27,6 +27,7 @@
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.blink_public.web.WebReferrerPolicy;
 import org.chromium.chrome.browser.ChromeFeatureList;
+import org.chromium.chrome.browser.MockSafeBrowsingApiHandler;
 import org.chromium.chrome.browser.browserservices.Origin;
 import org.chromium.chrome.browser.browserservices.OriginVerifier;
 import org.chromium.chrome.browser.firstrun.FirstRunStatus;
@@ -35,6 +36,7 @@
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
+import org.chromium.components.safe_browsing.SafeBrowsingApiBridge;
 import org.chromium.content.browser.test.util.JavaScriptUtils;
 import org.chromium.net.test.EmbeddedTestServer;
 
@@ -116,16 +118,13 @@
     @EnableFeatures(ChromeFeatureList.CCT_PARALLEL_REQUEST)
     public void testCanStartParallelRequest() throws Exception {
         CustomTabsSessionToken session = prepareSession();
-        mServer = new EmbeddedTestServer();
         final CallbackHelper cb = new CallbackHelper();
-        mServer.initializeNative(mContext, EmbeddedTestServer.ServerHTTPSSetting.USE_HTTP);
-        mServer.setConnectionListener(new EmbeddedTestServer.ConnectionListener() {
+        setUpTestServerWithListener(new EmbeddedTestServer.ConnectionListener() {
             @Override
             public void readFromSocket(long socketId) {
                 cb.notifyCalled();
             }
         });
-        mServer.start();
 
         Uri url = Uri.parse(mServer.getURL("/echotitle"));
         ThreadUtils.runOnUiThread(() -> {
@@ -157,6 +156,55 @@
         Assert.assertEquals("\"acookie\"", content);
     }
 
+    /** Tests that cached detached resource requests that are forbidden by SafeBrowsing don't end up
+     *  in the content area.
+     */
+    @Test
+    @SmallTest
+    @EnableFeatures(ChromeFeatureList.CCT_PARALLEL_REQUEST)
+    public void testSafeBrowsing() throws Exception {
+        SafeBrowsingApiBridge.setSafeBrowsingHandlerType(
+                new MockSafeBrowsingApiHandler().getClass());
+        CustomTabsSessionToken session = prepareSession();
+
+        // Count the number of times data is read from the socket.
+        // We expect:
+        // - 1 read for the detached request
+        // - 0 from the page load, as the response comes from the cache, and SafeBrowsing blocks it.
+        //
+        // Cannot count connections as Chrome opens multiple sockets at page load time.
+        CallbackHelper readFromSocketCallback = new CallbackHelper();
+        setUpTestServerWithListener(new EmbeddedTestServer.ConnectionListener() {
+            @Override
+            public void readFromSocket(long socketId) {
+                readFromSocketCallback.notifyCalled();
+            }
+        });
+
+        Uri url = Uri.parse(mServer.getURL("/cachetime")); // Cacheable response.
+        String urlString = url.toString();
+        ThreadUtils.runOnUiThreadBlocking(() -> {
+            Assert.assertTrue(mConnection.startParallelRequest(
+                    session, url, ORIGIN, WebReferrerPolicy.DEFAULT));
+        });
+        readFromSocketCallback.waitForCallback(0, 1);
+
+        try {
+            MockSafeBrowsingApiHandler.addMockResponse(
+                    urlString, "{\"matches\":[{\"threat_type\":\"5\"}]}");
+
+            Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(mContext, urlString);
+            mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
+
+            Tab tab = mCustomTabActivityTestRule.getActivity().getActivityTab();
+            ThreadUtils.runOnUiThreadBlocking(
+                    () -> Assert.assertTrue(tab.getWebContents().isShowingInterstitialPage()));
+            Assert.assertEquals(1, readFromSocketCallback.getCallCount());
+        } finally {
+            MockSafeBrowsingApiHandler.clearMockResponses();
+        }
+    }
+
     @Test
     @SmallTest
     @EnableFeatures(ChromeFeatureList.CCT_PARALLEL_REQUEST)
@@ -230,4 +278,14 @@
         });
         return session;
     }
+
+    private void setUpTestServerWithListener(EmbeddedTestServer.ConnectionListener listener)
+            throws InterruptedException {
+        mServer = new EmbeddedTestServer();
+        final CallbackHelper readFromSocketCallback = new CallbackHelper();
+        mServer.initializeNative(mContext, EmbeddedTestServer.ServerHTTPSSetting.USE_HTTP);
+        mServer.setConnectionListener(listener);
+        mServer.addDefaultHandlers("");
+        Assert.assertTrue(mServer.start());
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/UkmIncognitoTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/UkmIncognitoTest.java
index 233d396..2adcf3d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/UkmIncognitoTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/UkmIncognitoTest.java
@@ -41,6 +41,10 @@
         mActivityTestRule.startMainActivityOnBlankPage();
     }
 
+    /*
+     * These helper method should stay in sync with the tests within
+     * sync_shell/.../chrome/browser/sync/UkmTest.java.
+     */
     public String getElementContent(Tab normalTab, String elementId) throws Exception {
         mActivityTestRule.loadUrlInTab(
                 DEBUG_PAGE, PageTransition.TYPED | PageTransition.FROM_ADDRESS_BAR, normalTab);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsTest.java
index 371a15ad..415b652 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsTest.java
@@ -59,6 +59,10 @@
     private static final ClientId ASYNC_ID =
             new ClientId(OfflinePageBridge.ASYNC_NAMESPACE, "5678");
     private static final String SHARED_URI = "http://127.0.0.1/chrome/test/data/android/about.html";
+    private static final String CONTENT_URI = "content://chromium/some-content-id";
+    private static final String FILE_URI = "file://some-dir/some-file.mhtml";
+    private static final String INVALID_URI = "This is not a uri.";
+    private static final String EMPTY_URI = "";
     private static final String EMPTY_PATH = "";
     private static final String CACHE_SUBDIR = "/Offline Pages/archives";
     private static final String NEW_FILE = "/newfile.mhtml";
@@ -323,18 +327,19 @@
     }
 
     // Checks on the UI thread if an offline path corresponds to a sharable file.
-    private void checkIfOfflinePageIsSharable(final String filePath, boolean sharable) {
+    private void checkIfOfflinePageIsSharable(
+            final String filePath, final String uriPath, boolean sharable) {
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                OfflinePageItem privateOfflinePageItem = new OfflinePageItem(SHARED_URI, OFFLINE_ID,
-                        OfflinePageBridge.ASYNC_NAMESPACE, PAGE_ID, TITLE, filePath, FILE_SIZE, 0,
-                        0, 0, REQUEST_ORIGIN);
+                OfflinePageItem privateOfflinePageItem =
+                        new OfflinePageItem(uriPath, OFFLINE_ID, OfflinePageBridge.ASYNC_NAMESPACE,
+                                PAGE_ID, TITLE, filePath, FILE_SIZE, 0, 0, 0, REQUEST_ORIGIN);
                 OfflinePageBridge offlinePageBridge = OfflinePageBridge.getForProfile(
                         mActivityTestRule.getActivity().getActivityTab().getProfile());
 
                 boolean isSharable = OfflinePageUtils.isOfflinePageShareable(
-                        offlinePageBridge, privateOfflinePageItem);
+                        offlinePageBridge, privateOfflinePageItem, uriPath);
                 Assert.assertEquals(sharable, isSharable);
             }
         });
@@ -350,14 +355,26 @@
 
         // Check that an offline page item in the private directory is not sharable.
         final String fullPrivatePath = privatePath + CACHE_SUBDIR + NEW_FILE;
-        checkIfOfflinePageIsSharable(fullPrivatePath, false);
+        checkIfOfflinePageIsSharable(fullPrivatePath, SHARED_URI, false);
 
         // Check that an offline page item with no file path is not sharable.
-        checkIfOfflinePageIsSharable("", false);
+        checkIfOfflinePageIsSharable(EMPTY_PATH, SHARED_URI, false);
 
         // Check that a public offline page item with a file path is sharable.
         final String fullPublicPath = publicPath + NEW_FILE;
-        checkIfOfflinePageIsSharable(fullPublicPath, true);
+        checkIfOfflinePageIsSharable(fullPublicPath, SHARED_URI, true);
+
+        // Check that a page with a content URI and no file path is sharable.
+        checkIfOfflinePageIsSharable(EMPTY_PATH, CONTENT_URI, true);
+
+        // Check that a page with a file URI and no file path is sharable.
+        checkIfOfflinePageIsSharable(EMPTY_PATH, FILE_URI, true);
+
+        // Check that a malformed URI is not sharable.
+        checkIfOfflinePageIsSharable(EMPTY_PATH, INVALID_URI, false);
+
+        // Check that an empty URL is not sharable.
+        checkIfOfflinePageIsSharable(fullPublicPath, EMPTY_URI, false);
     }
 
     private void loadPageAndSave(ClientId clientId) throws Exception {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/LocationBarLayoutTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/LocationBarLayoutTest.java
index 2ee84c6..e1158531 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/LocationBarLayoutTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/LocationBarLayoutTest.java
@@ -57,10 +57,15 @@
     private static final String GOOGLE_SRP_URL = "https://www.google.com/search?q=machine+learning";
     private static final String BING_SRP_URL = "https://www.bing.com/search?q=machine+learning";
 
+    private static final String VERBOSE_URL = "https://www.suchwowveryyes.edu";
+    private static final String TRIMMED_URL = "suchwowveryyes.edu";
+
     private TestToolbarModel mTestToolbarModel;
 
     private class TestToolbarModel extends ToolbarModelImpl {
         private String mCurrentUrl;
+        private String mEditingText;
+        private String mDisplayText;
         private Integer mSecurityLevel;
 
         public TestToolbarModel() {
@@ -90,6 +95,16 @@
         }
 
         @Override
+        public String getDisplayText() {
+            return mDisplayText == null ? super.getDisplayText() : mDisplayText;
+        }
+
+        @Override
+        public String getEditingText() {
+            return mEditingText == null ? super.getEditingText() : mEditingText;
+        }
+
+        @Override
         public boolean shouldShowGoogleG(String urlBarText) {
             return false;
         }
@@ -109,6 +124,14 @@
         ThreadUtils.runOnUiThreadBlocking(() -> { getLocationBar().updateLoadingState(true); });
     }
 
+    private String getUrlText(UrlBar urlBar) {
+        try {
+            return ThreadUtils.runOnUiThreadBlocking(() -> urlBar.getText().toString());
+        } catch (ExecutionException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
     // Partially lifted from TemplateUrlServiceTest.
     private void setSearchEngine(String keyword)
             throws ExecutionException, InterruptedException, TimeoutException {
@@ -153,8 +176,8 @@
         ThreadUtils.runOnUiThreadBlocking(new Callable<Void>() {
             @Override
             public Void call() throws InterruptedException {
-                mActivityTestRule.typeInOmnibox(text, false);
                 getLocationBar().onUrlFocusChange(true);
+                mActivityTestRule.typeInOmnibox(text, false);
                 return null;
             }
         });
@@ -312,6 +335,28 @@
         mTestToolbarModel.setSecurityLevel(ConnectionSecurityLevel.SECURE);
         setUrlToPageUrl(locationBar);
 
-        Assert.assertNotEquals(SEARCH_TERMS, urlBar.getText().toString());
+        Assert.assertNotEquals(SEARCH_TERMS, getUrlText(urlBar));
+    }
+
+    @Test
+    @SmallTest
+    public void testEditingTextShownOnFocus() {
+        final UrlBar urlBar = getUrlBar();
+        final LocationBarLayout locationBar = getLocationBar();
+
+        mTestToolbarModel.mDisplayText = TRIMMED_URL;
+        mTestToolbarModel.mEditingText = VERBOSE_URL;
+        setUrlToPageUrl(locationBar);
+
+        Assert.assertEquals(TRIMMED_URL, getUrlText(urlBar));
+
+        ThreadUtils.runOnUiThreadBlocking(() -> { urlBar.requestFocus(); });
+
+        Assert.assertEquals(VERBOSE_URL, getUrlText(urlBar));
+
+        ThreadUtils.runOnUiThreadBlocking(() -> {
+            Assert.assertEquals(0, urlBar.getSelectionStart());
+            Assert.assertEquals(VERBOSE_URL.length(), urlBar.getSelectionEnd());
+        });
     }
 }
\ No newline at end of file
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferencesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferencesTest.java
index bed29ee6e..de41801 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferencesTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferencesTest.java
@@ -296,8 +296,9 @@
                 // Disable the timer for progress bar.
                 SavePasswordsPreferences fragment =
                         (SavePasswordsPreferences) preferences.getFragmentForTest();
-                fragment.getDialogManagerForTesting().replaceCallbackDelayerForTesting(
-                        mManualDelayer);
+                fragment.getExportFlowForTesting()
+                        .getDialogManagerForTesting()
+                        .replaceCallbackDelayerForTesting(mManualDelayer);
                 // Now call onResume to nudge Chrome into continuing the export flow.
                 preferences.getFragmentForTest().onResume();
             }
@@ -342,9 +343,9 @@
                 // To show an error, the error type for UMA needs to be specified. Because it is not
                 // relevant for cases when the error is forcibly displayed in tests,
                 // EXPORT_RESULT_NO_CONSUMER is passed as an arbitrarily chosen value.
-                fragment.showExportErrorAndAbort(R.string.save_password_preferences_export_no_app,
-                        null, positiveButtonLabelId,
-                        SavePasswordsPreferences.EXPORT_RESULT_NO_CONSUMER);
+                fragment.getExportFlowForTesting().showExportErrorAndAbort(
+                        R.string.save_password_preferences_export_no_app, null,
+                        positiveButtonLabelId, ExportFlow.EXPORT_RESULT_NO_CONSUMER);
             }
         });
     }
@@ -627,7 +628,7 @@
 
         MetricsUtils.HistogramDelta userAbortedDelta =
                 new MetricsUtils.HistogramDelta("PasswordManager.ExportPasswordsToCSVResult",
-                        SavePasswordsPreferences.EXPORT_RESULT_USER_ABORTED);
+                        ExportFlow.EXPORT_RESULT_USER_ABORTED);
 
         // Hit the Cancel button to cancel the flow.
         Espresso.onView(withText(R.string.cancel)).perform(click());
@@ -852,16 +853,15 @@
         intending(hasAction(equalTo(Intent.ACTION_CHOOSER)))
                 .respondWith(new Instrumentation.ActivityResult(Activity.RESULT_OK, null));
 
-        MetricsUtils.HistogramDelta successDelta =
-                new MetricsUtils.HistogramDelta("PasswordManager.ExportPasswordsToCSVResult",
-                        SavePasswordsPreferences.EXPORT_RESULT_SUCCESS);
+        MetricsUtils.HistogramDelta successDelta = new MetricsUtils.HistogramDelta(
+                "PasswordManager.ExportPasswordsToCSVResult", ExportFlow.EXPORT_RESULT_SUCCESS);
 
         MetricsUtils.HistogramDelta countDelta = new MetricsUtils.HistogramDelta(
                 "PasswordManager.ExportedPasswordsPerUserInCSV", 123);
 
         MetricsUtils.HistogramDelta progressBarDelta = new MetricsUtils.HistogramDelta(
                 "PasswordManager.Android.ExportPasswordsProgressBarUsage",
-                SavePasswordsPreferences.PROGRESS_NOT_SHOWN);
+                ExportFlow.PROGRESS_NOT_SHOWN);
 
         // Confirm the export warning to fire the sharing intent.
         Espresso.onView(withText(R.string.save_password_preferences_export_action_title))
@@ -918,9 +918,8 @@
         intending(hasAction(equalTo(Intent.ACTION_CHOOSER)))
                 .respondWith(new Instrumentation.ActivityResult(Activity.RESULT_OK, null));
 
-        MetricsUtils.HistogramDelta successDelta =
-                new MetricsUtils.HistogramDelta("PasswordManager.ExportPasswordsToCSVResult",
-                        SavePasswordsPreferences.EXPORT_RESULT_SUCCESS);
+        MetricsUtils.HistogramDelta successDelta = new MetricsUtils.HistogramDelta(
+                "PasswordManager.ExportPasswordsToCSVResult", ExportFlow.EXPORT_RESULT_SUCCESS);
 
         MetricsUtils.HistogramDelta countDelta = new MetricsUtils.HistogramDelta(
                 "PasswordManager.ExportedPasswordsPerUserInCSV", 56);
@@ -1128,7 +1127,7 @@
 
         MetricsUtils.HistogramDelta progressBarDelta = new MetricsUtils.HistogramDelta(
                 "PasswordManager.Android.ExportPasswordsProgressBarUsage",
-                SavePasswordsPreferences.PROGRESS_HIDDEN_DELAYED);
+                ExportFlow.PROGRESS_HIDDEN_DELAYED);
 
         // Now pretend that passwords have been serialized.
         mHandler.getExportCallback().onResult(new byte[] {5, 6, 7}, 12);
@@ -1190,7 +1189,7 @@
 
         MetricsUtils.HistogramDelta progressBarDelta = new MetricsUtils.HistogramDelta(
                 "PasswordManager.Android.ExportPasswordsProgressBarUsage",
-                SavePasswordsPreferences.PROGRESS_HIDDEN_DIRECTLY);
+                ExportFlow.PROGRESS_HIDDEN_DIRECTLY);
 
         // Now pretend that passwords have been serialized.
         allowProgressBarToBeHidden(preferences);
@@ -1243,7 +1242,7 @@
 
         MetricsUtils.HistogramDelta userAbortedDelta =
                 new MetricsUtils.HistogramDelta("PasswordManager.ExportPasswordsToCSVResult",
-                        SavePasswordsPreferences.EXPORT_RESULT_USER_ABORTED);
+                        ExportFlow.EXPORT_RESULT_USER_ABORTED);
 
         // Hit the Cancel button.
         Espresso.onView(withText(R.string.cancel)).perform(click());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/ToolbarModelTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/ToolbarModelTest.java
index 7b3cad8..3b1c05a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/ToolbarModelTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/ToolbarModelTest.java
@@ -6,23 +6,31 @@
 
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.MediumTest;
+import android.support.test.filters.SmallTest;
 
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 import org.junit.runner.RunWith;
 
+import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.ChromeTabbedActivity;
+import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ChromeTabUtils;
+import org.chromium.chrome.test.util.browser.Features;
+import org.chromium.chrome.test.util.browser.Features.DisableFeatures;
+import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
 
 /**
  * Tests for ToolbarModel.
@@ -33,6 +41,11 @@
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
 
+    @Rule
+    public TestRule mProcessor = new Features.InstrumentationProcessor();
+
+    private static final String TEST_PAGE = "/chrome/test/data/android/test.html";
+
     @Before
     public void setUp() throws InterruptedException {
         mActivityTestRule.startMainActivityOnBlankPage();
@@ -58,6 +71,58 @@
                 getCurrentTabId(mActivityTestRule.getActivity()));
     }
 
+    @Test
+    @SmallTest
+    @DisableFeatures(ChromeFeatureList.OMNIBOX_HIDE_SCHEME_DOMAIN_IN_STEADY_STATE)
+    public void testDisplayAndEditText_DisabledExperiment() throws Exception {
+        ThreadUtils.runOnUiThreadBlocking(() -> {
+            TestToolbarModel model = new TestToolbarModel();
+            model.mUrl = UrlConstants.NTP_URL;
+            assertDisplayAndEditText(model, "", null);
+
+            model.mUrl = "chrome://about";
+            model.mDisplayUrl = "chrome://about";
+            model.mFullUrl = "chrome://about";
+            assertDisplayAndEditText(model, "chrome://about", "chrome://about");
+
+            model.mUrl = "https://www.foo.com";
+            model.mDisplayUrl = "foo.com";
+            model.mFullUrl = "https://foo.com";
+            assertDisplayAndEditText(model, "https://foo.com", "https://foo.com");
+        });
+    }
+
+    @Test
+    @SmallTest
+    @EnableFeatures(ChromeFeatureList.OMNIBOX_HIDE_SCHEME_DOMAIN_IN_STEADY_STATE)
+    public void testDisplayAndEditText_EnabledExperiment() throws Exception {
+        ThreadUtils.runOnUiThreadBlocking(() -> {
+            TestToolbarModel model = new TestToolbarModel();
+            model.mUrl = UrlConstants.NTP_URL;
+            assertDisplayAndEditText(model, "", null);
+
+            model.mUrl = "chrome://about";
+            model.mDisplayUrl = "chrome://about";
+            model.mFullUrl = "chrome://about";
+            assertDisplayAndEditText(model, "chrome://about", "chrome://about");
+
+            model.mUrl = "https://www.foo.com";
+            model.mDisplayUrl = "foo.com";
+            model.mFullUrl = "https://foo.com";
+            assertDisplayAndEditText(model, "foo.com", "https://foo.com");
+        });
+    }
+
+    private void assertDisplayAndEditText(
+            ToolbarDataProvider dataProvider, String displayText, String editText) {
+        ThreadUtils.runOnUiThreadBlocking(() -> {
+            Assert.assertEquals(
+                    "Display text did not match", displayText, dataProvider.getDisplayText());
+            Assert.assertEquals(
+                    "Editing text did not match", editText, dataProvider.getEditingText());
+        });
+    }
+
     /**
      * @param activity A reference to {@link ChromeTabbedActivity} to pull
      *            {@link android.view.View} data from.
@@ -71,4 +136,43 @@
         Tab tab = dataProvider.getTab();
         return tab != null ? tab.getId() : Tab.INVALID_TAB_ID;
     }
+
+    private class TestToolbarModel extends ToolbarModelImpl {
+        private String mDisplayUrl;
+        private String mFullUrl;
+        private String mUrl;
+
+        public TestToolbarModel() {
+            super(null /* bottomSheet */, false /* useModernDesign */);
+            initializeWithNative();
+
+            Tab tab = new Tab(0, false, null) {
+                @Override
+                public boolean isInitialized() {
+                    return true;
+                }
+
+                @Override
+                public boolean isFrozen() {
+                    return false;
+                }
+            };
+            setTab(tab, false);
+        }
+
+        @Override
+        public String getCurrentUrl() {
+            return mUrl == null ? super.getCurrentUrl() : mUrl;
+        }
+
+        @Override
+        public String getFormattedFullUrl() {
+            return mFullUrl == null ? super.getFormattedFullUrl() : mFullUrl;
+        }
+
+        @Override
+        public String getUrlForDisplay() {
+            return mDisplayUrl == null ? super.getUrlForDisplay() : mDisplayUrl;
+        }
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/EmulatedVrController.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/EmulatedVrController.java
index 25f05b9..cf0b5b2d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/EmulatedVrController.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/EmulatedVrController.java
@@ -192,5 +192,16 @@
                 new float[] {startAngles[2], endAngles[2]}, steps, delayBetweenSteps);
     }
 
+    /**
+     * Touch and release the touchpad to perform a controller click.
+     */
+    public void performControllerClick() {
+        // pressReleaseTouchpadButton() appears to be flaky for clicking on things, as sometimes
+        // it happens too fast for Chrome to register. So, manually press and release with a delay
+        sendClickButtonToggleEvent();
+        SystemClock.sleep(50);
+        sendClickButtonToggleEvent();
+    }
+
     // TODO(bsheedy): Add support for more complex actions, e.g. click/drag/release
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/TestVrShellDelegate.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/TestVrShellDelegate.java
index f08cff5f..52cbad4 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/TestVrShellDelegate.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/TestVrShellDelegate.java
@@ -22,7 +22,9 @@
     // running into crbug.com/762724
     private static final int DON_CANCEL_DELAY_MS = 200;
     private boolean mOnResumeCalled;
+    private Runnable mOnVSyncPausedCallback;
     private static TestVrShellDelegate sInstance;
+    private boolean mDisableVrBrowsing;
 
     protected TestVrShellDelegate(ChromeActivity activity) {
         super(activity, VrShellDelegate.getVrClassesWrapper());
@@ -91,6 +93,20 @@
         super.acceptDoffPromptForTesting();
     }
 
+    @Override
+    protected boolean isVrBrowsingEnabled() {
+        if (mDisableVrBrowsing) return false;
+        return super.isVrBrowsingEnabled();
+    }
+
+    public void setVrBrowsingDisabled(boolean disabled) {
+        mDisableVrBrowsing = disabled;
+    }
+
+    public void setVrShellOnVSyncPausedCallback(Runnable callback) {
+        mOnVSyncPausedCallback = callback;
+    }
+
     /**
      * Wait a short period of time before running if we think the DON flow was cancelled.
      *
@@ -127,4 +143,19 @@
         mOnResumeCalled = false;
         super.onPause();
     }
+
+    /**
+     * If we need to know when the normal VSync gets paused, we have a small window between when
+     * the VrShell is created and we actually enter VR to set the callback. So, do it immediately
+     * after creation here.
+     */
+    @Override
+    protected boolean createVrShell() {
+        boolean result = super.createVrShell();
+        if (result && mOnVSyncPausedCallback != null) {
+            ((VrShellImpl) getVrShellForTesting())
+                    .setOnVSyncPausedForTesting(mOnVSyncPausedCallback);
+        }
+        return result;
+    }
 }
\ No newline at end of file
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrFeedbackInfoBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrFeedbackInfoBarTest.java
index ab87e6c..f213c28 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrFeedbackInfoBarTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrFeedbackInfoBarTest.java
@@ -79,6 +79,7 @@
      */
     @Test
     @MediumTest
+    @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
     public void testFeedbackFrequency() throws InterruptedException, TimeoutException {
         mVrTestFramework.loadUrlAndAwaitInitialization(TEST_PAGE_2D_URL, PAGE_LOAD_TIMEOUT_S);
         // Set frequency of infobar to every 2nd time.
@@ -104,6 +105,7 @@
      */
     @Test
     @MediumTest
+    @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
     public void testFeedbackOptOut() throws InterruptedException, TimeoutException {
         mVrTestFramework.loadUrlAndAwaitInitialization(TEST_PAGE_2D_URL, PAGE_LOAD_TIMEOUT_S);
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellControllerInputTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellControllerInputTest.java
index 0c2080ee..4c0ce69 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellControllerInputTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellControllerInputTest.java
@@ -11,7 +11,6 @@
 import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_DEVICE_DAYDREAM;
 import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_VIEWER_DAYDREAM;
 
-import android.os.SystemClock;
 import android.support.test.filters.MediumTest;
 import android.support.v7.widget.RecyclerView;
 
@@ -207,11 +206,7 @@
                 VrTestFramework.getHtmlTestFile("test_controller_clicks_register_on_webpage"),
                 PAGE_LOAD_TIMEOUT_S);
 
-        // pressReleaseTouchpadButton() appears to be flaky for clicking on things, as sometimes
-        // it happens too fast for Chrome to register. So, manually press and release with a delay
-        mController.sendClickButtonToggleEvent();
-        SystemClock.sleep(50);
-        mController.sendClickButtonToggleEvent();
+        mController.performControllerClick();
         ChromeTabUtils.waitForTabPageLoaded(mVrTestRule.getActivity().getActivityTab(),
                 VrTestFramework.getHtmlTestFile("test_navigation_2d_page"));
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellNativeUiTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellNativeUiTest.java
index 4811fd5..099e322 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellNativeUiTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellNativeUiTest.java
@@ -7,7 +7,7 @@
 import static org.chromium.chrome.browser.vr_shell.VrTestFramework.NATIVE_URLS_OF_INTEREST;
 import static org.chromium.chrome.browser.vr_shell.VrTestFramework.PAGE_LOAD_TIMEOUT_S;
 import static org.chromium.chrome.browser.vr_shell.VrTestFramework.POLL_TIMEOUT_LONG_MS;
-import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_DEVICE_DAYDREAM;
+import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_VIEWER_DAYDREAM;
 
 import android.support.test.filters.MediumTest;
 
@@ -31,7 +31,7 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "enable-webvr"})
-@Restriction(RESTRICTION_TYPE_DEVICE_DAYDREAM)
+@Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
 public class VrShellNativeUiTest {
     // We explicitly instantiate a rule here instead of using parameterization since this class
     // only ever runs in ChromeTabbedActivity.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellNavigationTest.java
index 48ae7bcb1..44f49d69 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellNavigationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellNavigationTest.java
@@ -8,7 +8,6 @@
 import static org.chromium.chrome.browser.vr_shell.VrTestFramework.PAGE_LOAD_TIMEOUT_S;
 import static org.chromium.chrome.browser.vr_shell.VrTestFramework.POLL_TIMEOUT_LONG_MS;
 import static org.chromium.chrome.browser.vr_shell.VrTestFramework.POLL_TIMEOUT_SHORT_MS;
-import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_DEVICE_DAYDREAM;
 import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_VIEWER_DAYDREAM;
 
 import android.support.test.InstrumentationRegistry;
@@ -50,7 +49,7 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "enable-webvr"})
-@Restriction(RESTRICTION_TYPE_DEVICE_DAYDREAM)
+@Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
 public class VrShellNavigationTest {
     // We explicitly instantiate a rule here instead of using parameterization since this class
     // only ever runs in ChromeTabbedActivity.
@@ -240,7 +239,6 @@
      */
     @Test
     @MediumTest
-    @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
     public void testWebVrTo2d()
             throws IllegalArgumentException, InterruptedException, TimeoutException {
         webTo2dImpl(Page.PAGE_WEBVR, mVrTestFramework);
@@ -253,7 +251,6 @@
     @MediumTest
     @CommandLineFlags.Remove({"enable-webvr"})
     @CommandLineFlags.Add({"enable-features=WebXR"})
-    @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
     public void testWebXrTo2d()
             throws IllegalArgumentException, InterruptedException, TimeoutException {
         webTo2dImpl(Page.PAGE_WEBXR, mXrTestFramework);
@@ -274,7 +271,6 @@
      */
     @Test
     @MediumTest
-    @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
     public void testWebVrToWebVr()
             throws IllegalArgumentException, InterruptedException, TimeoutException {
         webToWebImpl(Page.PAGE_WEBVR, mVrTestFramework);
@@ -287,7 +283,6 @@
     @MediumTest
     @CommandLineFlags.Remove({"enable-webvr"})
     @CommandLineFlags.Add({"enable-features=WebXR"})
-    @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
     public void testWebXrToWebXr()
             throws IllegalArgumentException, InterruptedException, TimeoutException {
         webToWebImpl(Page.PAGE_WEBXR, mXrTestFramework);
@@ -308,7 +303,6 @@
      */
     @Test
     @MediumTest
-    @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
     public void testWebVrPresentingTo2d()
             throws IllegalArgumentException, InterruptedException, TimeoutException {
         webPresentingTo2dImpl(Page.PAGE_WEBVR, mVrTestFramework);
@@ -321,7 +315,6 @@
     @MediumTest
     @CommandLineFlags.Remove({"enable-webvr"})
     @CommandLineFlags.Add({"enable-features=WebXR"})
-    @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
     public void testWebXrPresentingTo2d()
             throws IllegalArgumentException, InterruptedException, TimeoutException {
         webPresentingTo2dImpl(Page.PAGE_WEBXR, mXrTestFramework);
@@ -343,7 +336,6 @@
      */
     @Test
     @MediumTest
-    @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
     public void testWebVrPresentingToWebVr()
             throws IllegalArgumentException, InterruptedException, TimeoutException {
         webPresentingToWebImpl(Page.PAGE_WEBVR, mVrTestFramework);
@@ -356,7 +348,6 @@
     @MediumTest
     @CommandLineFlags.Remove({"enable-webvr"})
     @CommandLineFlags.Add({"enable-features=WebXR"})
-    @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
     public void testWebXrPresentingToWebXr()
             throws IllegalArgumentException, InterruptedException, TimeoutException {
         webPresentingToWebImpl(Page.PAGE_WEBXR, mXrTestFramework);
@@ -378,7 +369,6 @@
      */
     @Test
     @MediumTest
-    @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
     public void testWebVrFullscreenTo2d()
             throws IllegalArgumentException, InterruptedException, TimeoutException {
         webFullscreenTo2dImpl(Page.PAGE_WEBVR, mVrTestFramework);
@@ -391,7 +381,6 @@
     @MediumTest
     @CommandLineFlags.Remove({"enable-webvr"})
     @CommandLineFlags.Add({"enable-features=WebXR"})
-    @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
     public void testWebXrFullscreenTo2d()
             throws IllegalArgumentException, InterruptedException, TimeoutException {
         webFullscreenTo2dImpl(Page.PAGE_WEBXR, mXrTestFramework);
@@ -413,7 +402,6 @@
      */
     @Test
     @MediumTest
-    @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
     public void testWebVrFullscreenToWebVr()
             throws IllegalArgumentException, InterruptedException, TimeoutException {
         webFullscreenToWebImpl(Page.PAGE_WEBVR, mVrTestFramework);
@@ -426,7 +414,6 @@
     @MediumTest
     @CommandLineFlags.Remove({"enable-webvr"})
     @CommandLineFlags.Add({"enable-features=WebXR"})
-    @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
     public void testWebXrFullscreenToWebXr()
             throws IllegalArgumentException, InterruptedException, TimeoutException {
         webFullscreenToWebImpl(Page.PAGE_WEBXR, mXrTestFramework);
@@ -449,7 +436,6 @@
      */
     @Test
     @MediumTest
-    @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
     public void testBackDoesntBackgroundChrome()
             throws IllegalArgumentException, InterruptedException {
         Assert.assertFalse("Back button isn't disabled.", VrTransitionUtils.isBackButtonEnabled());
@@ -472,7 +458,6 @@
      */
     @Test
     @MediumTest
-    @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
     public void testNavigationButtons() throws IllegalArgumentException, InterruptedException {
         Assert.assertFalse("Back button isn't disabled.", VrTransitionUtils.isBackButtonEnabled());
         Assert.assertFalse(
@@ -509,7 +494,6 @@
      */
     @Test
     @MediumTest
-    @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
     public void testNativeNavigationAndInteraction()
             throws IllegalArgumentException, InterruptedException {
         for (String url : NATIVE_URLS_OF_INTEREST) {
@@ -526,7 +510,6 @@
      */
     @Test
     @MediumTest
-    @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
     public void testRendererKilledInFullscreenStaysInVr()
             throws IllegalArgumentException, InterruptedException, TimeoutException {
         mVrTestFramework.loadUrlAndAwaitInitialization(TEST_PAGE_2D_URL, PAGE_LOAD_TIMEOUT_S);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellTransitionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellTransitionTest.java
index d6e445fc..c4223efc 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellTransitionTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellTransitionTest.java
@@ -9,7 +9,6 @@
 import static org.chromium.chrome.browser.vr_shell.VrTestFramework.POLL_CHECK_INTERVAL_SHORT_MS;
 import static org.chromium.chrome.browser.vr_shell.VrTestFramework.POLL_TIMEOUT_LONG_MS;
 import static org.chromium.chrome.browser.vr_shell.VrTestFramework.POLL_TIMEOUT_SHORT_MS;
-import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_DEVICE_DAYDREAM;
 import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_DEVICE_NON_DAYDREAM;
 import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_VIEWER_DAYDREAM;
 
@@ -30,6 +29,7 @@
 import org.chromium.base.ApplicationStatus;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Restriction;
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.R;
@@ -111,7 +111,7 @@
      * browser when the Daydream View NFC tag is scanned on a Daydream-ready device.
      */
     @Test
-    @Restriction({RESTRICTION_TYPE_DEVICE_DAYDREAM, RESTRICTION_TYPE_VIEWER_DAYDREAM})
+    @Restriction({RESTRICTION_TYPE_VIEWER_DAYDREAM})
     @RetryOnFailure(message = "crbug.com/736527")
     @LargeTest
     public void test2dtoVrShellNfcSupported() {
@@ -136,7 +136,7 @@
      * device.
      */
     @Test
-    @Restriction(RESTRICTION_TYPE_DEVICE_DAYDREAM)
+    @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
     @MediumTest
     public void test2dtoVrShellto2dSupported() {
         enterExitVrShell(true /* supported */);
@@ -147,7 +147,7 @@
      * browser when Chrome gets a VR intent.
      */
     @Test
-    @Restriction(RESTRICTION_TYPE_DEVICE_DAYDREAM)
+    @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
     @MediumTest
     public void testVrIntentStartsVrShell() {
         // Send a VR intent, which will open the link in a CTA.
@@ -341,6 +341,7 @@
     @Test
     @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
     @MediumTest
+    @DisabledTest(message = "crbug.com/825248")
     public void testEnterVrInOverviewMode() throws InterruptedException, TimeoutException {
         final ChromeTabbedActivity activity = mTestRule.getActivity();
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellWebInputEditingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellWebInputEditingTest.java
new file mode 100644
index 0000000..37dc50ea
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellWebInputEditingTest.java
@@ -0,0 +1,110 @@
+// Copyright 2018 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.
+
+package org.chromium.chrome.browser.vr_shell;
+
+import static org.chromium.chrome.browser.vr_shell.VrTestFramework.PAGE_LOAD_TIMEOUT_S;
+import static org.chromium.chrome.browser.vr_shell.VrTestFramework.POLL_CHECK_INTERVAL_SHORT_MS;
+import static org.chromium.chrome.browser.vr_shell.VrTestFramework.POLL_TIMEOUT_LONG_MS;
+import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_DEVICE_DAYDREAM;
+import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_VIEWER_DAYDREAM;
+
+import android.support.test.filters.MediumTest;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.Restriction;
+import org.chromium.chrome.browser.ChromeSwitches;
+import org.chromium.chrome.browser.vr_shell.keyboard.TextEditAction;
+import org.chromium.chrome.browser.vr_shell.mock.MockBrowserKeyboardInterface;
+import org.chromium.chrome.browser.vr_shell.rules.ChromeTabbedActivityVrTestRule;
+import org.chromium.chrome.browser.vr_shell.util.VrTransitionUtils;
+import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.content.browser.test.util.Criteria;
+import org.chromium.content.browser.test.util.CriteriaHelper;
+
+/**
+ * End-to-end tests for Daydream controller input while in the VR browser.
+ */
+@RunWith(ChromeJUnit4ClassRunner.class)
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
+@Restriction({RESTRICTION_TYPE_DEVICE_DAYDREAM, RESTRICTION_TYPE_VIEWER_DAYDREAM})
+public class VrShellWebInputEditingTest {
+    // We explicitly instantiate a rule here instead of using parameterization since this class
+    // only ever runs in ChromeTabbedActivity.
+    @Rule
+    public ChromeTabbedActivityVrTestRule mVrTestRule = new ChromeTabbedActivityVrTestRule();
+
+    private VrTestFramework mVrTestFramework;
+    private EmulatedVrController mController;
+
+    @Before
+    public void setUp() throws Exception {
+        mVrTestFramework = new VrTestFramework(mVrTestRule);
+        mController = new EmulatedVrController(mVrTestRule.getActivity());
+    }
+
+    /**
+     * Verifies that when a web input field is focused, the VrInputMethodManagerWrapper is asked to
+     * spawn the keyboard. Moreover, we verify that an edit sent to web contents via the
+     * VrInputConnection updates indices on the VrInputMethodManagerWrapper.
+     */
+    @Test
+    @MediumTest
+    @CommandLineFlags.Add("enable-features=VrLaunchIntents")
+    public void testWebInputFocus() throws InterruptedException {
+        // Load page in VR and make sure the controller is pointed at the content quad.
+        mVrTestRule.loadUrl(
+                VrTestFramework.getHtmlTestFile("test_web_input_editing"), PAGE_LOAD_TIMEOUT_S);
+        VrTransitionUtils.forceEnterVr();
+        VrTransitionUtils.waitForVrEntry(POLL_TIMEOUT_LONG_MS);
+        mController.recenterView();
+
+        VrShellImpl vrShellImpl = (VrShellImpl) TestVrShellDelegate.getVrShellForTesting();
+        MockBrowserKeyboardInterface keyboard = new MockBrowserKeyboardInterface();
+        vrShellImpl.getInputMethodManageWrapperForTesting().setBrowserKeyboardInterfaceForTesting(
+                keyboard);
+
+        // The webpage reacts to the first controller click by focusing its input field. Verify that
+        // focus gain spawns the keyboard.
+        mController.performControllerClick();
+        CriteriaHelper.pollInstrumentationThread(new Criteria() {
+            @Override
+            public boolean isSatisfied() {
+                Boolean visible = keyboard.getLastKeyboardVisibility();
+                return visible != null && visible;
+            }
+        }, POLL_TIMEOUT_LONG_MS, POLL_CHECK_INTERVAL_SHORT_MS);
+
+        // Add text to the input field via the input connection and verify that the keyboard
+        // interface is called to update the indices.
+        VrInputConnection ic = vrShellImpl.getVrInputConnectionForTesting();
+        TextEditAction[] edits = {new TextEditAction(TextEditActionType.COMMIT_TEXT, "i", 1)};
+        ic.onKeyboardEdit(edits);
+        // Inserting 'i' should move the cursor by one character and there should be no composition.
+        MockBrowserKeyboardInterface.Indices expectedIndices =
+                new MockBrowserKeyboardInterface.Indices(1, 1, -1, -1);
+        CriteriaHelper.pollInstrumentationThread(new Criteria() {
+            @Override
+            public boolean isSatisfied() {
+                MockBrowserKeyboardInterface.Indices indices = keyboard.getLastIndices();
+                return indices.equals(expectedIndices);
+            }
+        }, POLL_TIMEOUT_LONG_MS, POLL_CHECK_INTERVAL_SHORT_MS);
+
+        // The second click should result in a focus loss and should hide the keyboard.
+        mController.performControllerClick();
+        CriteriaHelper.pollInstrumentationThread(new Criteria() {
+            @Override
+            public boolean isSatisfied() {
+                Boolean visible = keyboard.getLastKeyboardVisibility();
+                return visible != null && !visible;
+            }
+        }, POLL_TIMEOUT_LONG_MS, POLL_CHECK_INTERVAL_SHORT_MS);
+    }
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrInputTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrInputTest.java
index 25947c5..8b8d720 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrInputTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrInputTest.java
@@ -37,7 +37,6 @@
 import org.chromium.base.test.util.MinAndroidSdkLevel;
 import org.chromium.base.test.util.Restriction;
 import org.chromium.base.test.util.RetryOnFailure;
-import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.customtabs.CustomTabActivity;
 import org.chromium.chrome.browser.vr_shell.mock.MockVrDaydreamApi;
@@ -405,7 +404,6 @@
     @MediumTest
     @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
     @VrActivityRestriction({VrActivityRestriction.SupportedActivity.ALL})
-    @CommandLineFlags.Add({"disable-features=" + ChromeFeatureList.VR_BROWSING})
     public void testAppButtonNoopsWhenBrowsingDisabled()
             throws InterruptedException, ExecutionException {
         appButtonNoopsTestImpl(
@@ -435,10 +433,10 @@
     @MediumTest
     @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM)
     @VrActivityRestriction({VrActivityRestriction.SupportedActivity.ALL})
-    @CommandLineFlags.Remove({"enable-webvr"})
-    @CommandLineFlags.Add({"disable-features=" + ChromeFeatureList.VR_BROWSING,
-            "enable-features=WebXR"})
-    public void testAppButtonNoopsWhenBrowsingDisabled_WebXr()
+    @CommandLineFlags
+            .Remove({"enable-webvr"})
+            @CommandLineFlags.Add({"enable-features=WebXR"})
+            public void testAppButtonNoopsWhenBrowsingDisabled_WebXr()
             throws InterruptedException, ExecutionException {
         appButtonNoopsTestImpl(
                 XrTestFramework.getHtmlTestFile("generic_webxr_page"), mXrTestFramework);
@@ -463,6 +461,7 @@
 
     private void appButtonNoopsTestImpl(String url, TestFramework framework)
             throws InterruptedException, ExecutionException {
+        VrShellDelegateUtils.getDelegateInstance().setVrBrowsingDisabled(true);
         framework.loadUrlAndAwaitInitialization(url, PAGE_LOAD_TIMEOUT_S);
         TransitionUtils.enterPresentationOrFail(framework);
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTransitionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTransitionTest.java
index 45b557a6..10969971 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTransitionTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/WebVrTransitionTest.java
@@ -39,6 +39,7 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.MinAndroidSdkLevel;
 import org.chromium.base.test.util.Restriction;
+import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.customtabs.CustomTabActivity;
@@ -57,6 +58,8 @@
 import java.lang.ref.WeakReference;
 import java.util.List;
 import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicReference;
 
@@ -403,6 +406,7 @@
     @Test
     @MediumTest
     @VrActivityRestriction({VrActivityRestriction.SupportedActivity.ALL})
+    @RetryOnFailure
     public void testWindowRafStopsFiringWhilePresenting() throws InterruptedException {
         windowRafStopsFiringWhilePresentingImpl(
                 VrTestFramework.getHtmlTestFile("test_window_raf_stops_firing_while_presenting"),
@@ -431,7 +435,12 @@
         framework.loadUrlAndAwaitInitialization(url, PAGE_LOAD_TIMEOUT_S);
         TestFramework.executeStepAndWait(
                 "stepVerifyBeforePresent()", framework.getFirstTabWebContents());
+        // Pausing of window.rAF is done asynchronously, so wait until that's done.
+        final CountDownLatch vsyncPausedLatch = new CountDownLatch(1);
+        TestVrShellDelegate.getInstance().setVrShellOnVSyncPausedCallback(
+                () -> { vsyncPausedLatch.countDown(); });
         TransitionUtils.enterPresentationOrFail(framework);
+        vsyncPausedLatch.await(POLL_TIMEOUT_SHORT_MS, TimeUnit.MILLISECONDS);
         TestFramework.executeStepAndWait(
                 "stepVerifyDuringPresent()", framework.getFirstTabWebContents());
         TransitionUtils.forceExitVr();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/mock/MockBrowserKeyboardInterface.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/mock/MockBrowserKeyboardInterface.java
new file mode 100644
index 0000000..a685f64a
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/mock/MockBrowserKeyboardInterface.java
@@ -0,0 +1,63 @@
+// Copyright 2018 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.
+
+package org.chromium.chrome.browser.vr_shell.mock;
+
+import org.chromium.chrome.browser.vr_shell.keyboard.VrInputMethodManagerWrapper;
+
+/**
+ * Mock version of BrowserKeyboardInterface.
+ */
+public class MockBrowserKeyboardInterface
+        implements VrInputMethodManagerWrapper.BrowserKeyboardInterface {
+    /**
+     * A convenience class holding text input indices.
+     */
+    public static class Indices {
+        private final int mSelectionStart;
+        private final int mSelectionEnd;
+        private final int mCompositionStart;
+        private final int mCompositionEnd;
+
+        public Indices(
+                int selectionStart, int selectionEnd, int compositionStart, int compositionEnd) {
+            mSelectionStart = selectionStart;
+            mSelectionEnd = selectionEnd;
+            mCompositionStart = compositionStart;
+            mCompositionEnd = compositionEnd;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (!(o instanceof Indices)) return false;
+            Indices i = (Indices) o;
+            return this.mSelectionStart == i.mSelectionStart
+                    && this.mSelectionEnd == i.mSelectionEnd
+                    && this.mCompositionStart == i.mCompositionStart
+                    && this.mCompositionEnd == i.mCompositionEnd;
+        }
+    }
+
+    private Boolean mLastKeyboardVisibility;
+    private Indices mLastIndices;
+
+    @Override
+    public void showSoftInput(boolean show) {
+        mLastKeyboardVisibility = show;
+    }
+
+    @Override
+    public void updateIndices(
+            int selectionStart, int selectionEnd, int compositionStart, int compositionEnd) {
+        mLastIndices = new Indices(selectionEnd, selectionEnd, compositionStart, compositionEnd);
+    }
+
+    public Boolean getLastKeyboardVisibility() {
+        return mLastKeyboardVisibility;
+    }
+
+    public Indices getLastIndices() {
+        return mLastIndices;
+    }
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/mock/MockVrDaydreamApi.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/mock/MockVrDaydreamApi.java
index 949ad1b..e0ddf0723 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/mock/MockVrDaydreamApi.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/mock/MockVrDaydreamApi.java
@@ -87,9 +87,6 @@
     }
 
     @Override
-    public void close() {}
-
-    @Override
     public Intent setupVrIntent(Intent intent) {
         if (mForwardSetupIntent) {
             return DaydreamApi.setupVrIntent(intent);
@@ -103,4 +100,12 @@
 
     @Override
     public void launchGvrSettings() {}
+
+    @Override
+    public boolean isInVrSession() {
+        return true;
+    }
+
+    @Override
+    public void close() {}
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/util/TransitionUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/util/TransitionUtils.java
index 1127ea5..a6e164e8 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/util/TransitionUtils.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/util/TransitionUtils.java
@@ -205,8 +205,9 @@
         final Intent intent =
                 new Intent(ContextUtils.getApplicationContext(), VrMainActivity.class);
         intent.setData(Uri.parse(url));
-        intent.putExtra(VrIntentUtils.DAYDREAM_VR_EXTRA, true);
+        intent.addCategory(VrIntentUtils.DAYDREAM_CATEGORY);
         DaydreamApi.setupVrIntent(intent);
+
         if (autopresent) {
             // Daydream removes this category for deep-linked URLs for legacy reasons.
             intent.removeCategory(VrIntentUtils.DAYDREAM_CATEGORY);
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt
index a47d0be..f1e763f1 100644
--- a/chrome/android/profiles/newest.txt
+++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-67.0.3376.0_rc-r1.afdo.bz2
\ No newline at end of file
+chromeos-chrome-amd64-67.0.3379.0_rc-r1.afdo.bz2
\ No newline at end of file
diff --git a/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/UkmTest.java b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/UkmTest.java
new file mode 100644
index 0000000..b142438b
--- /dev/null
+++ b/chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/UkmTest.java
@@ -0,0 +1,133 @@
+// Copyright 2018 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.
+
+package org.chromium.chrome.browser.sync;
+
+import android.accounts.Account;
+import android.support.test.filters.SmallTest;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.ThreadUtils;
+import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.chrome.browser.ChromeSwitches;
+import org.chromium.chrome.browser.metrics.UmaSessionStats;
+import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.content.browser.test.util.JavaScriptUtils;
+import org.chromium.ui.base.PageTransition;
+
+/**
+ * Tests for UKM Sync integration.
+ */
+@RunWith(ChromeJUnit4ClassRunner.class)
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
+// Note we do not use the 'force-enable-metrics-reporting' flag for these tests as they would
+// ignore the Sync setting we are verifying.
+
+public class UkmTest {
+    @Rule
+    public SyncTestRule mSyncTestRule = new SyncTestRule();
+
+    private static final String DEBUG_PAGE = "chrome://ukm";
+
+    @Before
+    public void setUp() throws InterruptedException {
+        mSyncTestRule.startMainActivityOnBlankPage();
+
+        ThreadUtils.runOnUiThreadBlocking(
+                () -> UmaSessionStats.initMetricsAndCrashReportingForTesting());
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        ThreadUtils.runOnUiThreadBlocking(
+                () -> UmaSessionStats.unSetMetricsAndCrashReportingForTesting());
+    }
+
+    /*
+     * These helper method should stay in sync with
+     * chrome/browser/metrics/UkmIncognitoTest.java.
+     */
+    public String getElementContent(Tab normalTab, String elementId) throws Exception {
+        mSyncTestRule.loadUrlInTab(
+                DEBUG_PAGE, PageTransition.TYPED | PageTransition.FROM_ADDRESS_BAR, normalTab);
+        return JavaScriptUtils.executeJavaScriptAndWaitForResult(
+                normalTab.getContentViewCore().getWebContents(),
+                "document.getElementById('" + elementId + "').textContent");
+    }
+
+    public boolean isUkmEnabled(Tab normalTab) throws Exception {
+        String state = getElementContent(normalTab, "state");
+        Assert.assertTrue(
+                "UKM state: " + state, state.equals("\"True\"") || state.equals("\"False\""));
+        return state.equals("\"True\"");
+    }
+
+    public String getUkmClientId(Tab normalTab) throws Exception {
+        return getElementContent(normalTab, "clientid");
+    }
+
+    @Test
+    @SmallTest
+    public void testMetricConsent() throws Exception {
+        // Keep in sync with UkmBrowserTest.MetricsConsentCheck in
+        // chrome/browser/metrics/ukm_browsertest.cc.
+        // Make sure that UKM is disabled when metrics consent is revoked.
+
+        ThreadUtils.runOnUiThreadBlocking(
+                () -> UmaSessionStats.updateMetricsAndCrashReportingForTesting(true));
+
+        // Enable a Syncing account.
+        Account account = mSyncTestRule.setUpTestAccountAndSignIn();
+        Tab normalTab = mSyncTestRule.getActivity().getActivityTab();
+
+        Assert.assertTrue("UKM Enabled:", isUkmEnabled(normalTab));
+
+        String clientId = getUkmClientId(normalTab);
+
+        // Ideally we should verify that unsent logs are cleared, which we do via HasUnsentUkmLogs()
+        // in the ukm_browsertest.cc version.
+
+        // Verify that after revoking consent, UKM is disabled.
+        ThreadUtils.runOnUiThreadBlocking(
+                () -> UmaSessionStats.updateMetricsAndCrashReportingForTesting(false));
+        Assert.assertFalse("UKM Enabled:", isUkmEnabled(normalTab));
+
+        // Re-enable consent, UKM is re-enabled.
+        ThreadUtils.runOnUiThreadBlocking(
+                () -> UmaSessionStats.updateMetricsAndCrashReportingForTesting(true));
+        Assert.assertTrue("UKM Enabled:", isUkmEnabled(normalTab));
+
+        // Client ID should have been reset.
+        Assert.assertNotEquals("Client id:", clientId, getUkmClientId(normalTab));
+    }
+
+    @Test
+    @SmallTest
+    public void consentAddedButNoSyncCheck() throws Exception {
+        // Keep in sync with UkmBrowserTest.ConsentAddedButNoSyncCheck in
+        // chrome/browser/metrics/ukm_browsertest.cc.
+        // Make sure that providing consent doesn't enable UKM when sync is disabled.
+
+        ThreadUtils.runOnUiThreadBlocking(
+                () -> UmaSessionStats.updateMetricsAndCrashReportingForTesting(false));
+        Tab normalTab = mSyncTestRule.getActivity().getActivityTab();
+        Assert.assertFalse("UKM Enabled:", isUkmEnabled(normalTab));
+
+        // Enable consent, Sync still not enabled so UKM should be disabled.
+        ThreadUtils.runOnUiThreadBlocking(
+                () -> UmaSessionStats.updateMetricsAndCrashReportingForTesting(true));
+        Assert.assertFalse("UKM Enabled:", isUkmEnabled(normalTab));
+
+        // Finally, sign in and UKM is enabled.
+        Account account = mSyncTestRule.setUpTestAccountAndSignIn();
+        Assert.assertTrue("UKM Enabled:", isUkmEnabled(normalTab));
+    }
+}
diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc
index efcb4b9..a148b595 100644
--- a/chrome/app/chrome_main_delegate.cc
+++ b/chrome/app/chrome_main_delegate.cc
@@ -57,7 +57,7 @@
 #include "content/public/common/content_switches.h"
 #include "content/public/common/service_names.mojom.h"
 #include "extensions/common/constants.h"
-#include "pdf/features.h"
+#include "pdf/buildflags.h"
 #include "ppapi/features/features.h"
 #include "printing/features/features.h"
 #include "services/service_manager/embedder/switches.h"
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index 87d4002c8..0dcf639a9 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -119,6 +119,10 @@
     Cancel
   </message>
 
+  <!-- MultiDevice setup dialog. -->
+  <message name="IDS_MULTIDEVICE_SETUP_DIALOG_TITLE" desc="Title for the MultiDevice setup dialog, which allows users to enable features which involve communication between multiple devices (e.g., a Chromebook and a phone).">
+    MultiDevice Setup
+  </message>
 
   <!-- File Manager -->
   <message name="IDS_FILE_SYSTEM_PROVIDER_UNRESPONSIVE_WARNING" desc="A warning shown in a notification that an operation is taking longer than expected.">
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 6189311..44c880bf 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -10835,14 +10835,14 @@
     </message>
 
     <!-- Security Key permission -->
-    <message name="IDS_SECURITY_KEY_ATTESTATION_PERMISSION_FRAGMENT" desc="A permission prompt shown to a user when a website wants to see information that uniquely identifies the user's Security Key, such as make and model number. The text '[website URL] wants to:' precedes this string. The word 'identifying' modifies 'information'.">
-      See identifying information about your Security Key
+    <message name="IDS_SECURITY_KEY_ATTESTATION_PERMISSION_FRAGMENT" desc="A permission prompt shown to a user when a website wants to see information that identifies the user's Security Key, such as make and model number. The text '[website URL] wants to:' precedes this string. The 'make' of a device is the brand name of the manufacturer, e.g. Yubikey is a make of Security Key. The 'model' of a device is the specific product, e.g. Yubikey Neo is a model of Security Key.">
+      See the make and model of your Security Key
     </message>
     <if expr="is_android">
-      <message name="IDS_SECURITY_KEY_ATTESTATION_INFOBAR_QUESTION" desc="An infobar prompt shown to a user when a website wants to see information that uniquely identifies the user's Security Key, such as make and model number. The word 'identifying' modifies 'information'.">
+      <message name="IDS_SECURITY_KEY_ATTESTATION_INFOBAR_QUESTION" desc="An infobar prompt shown to a user when a website wants to see information that identifies the user's Security Key, such as make and model number. The 'make' of a device is the brand name of the manufacturer, e.g. Yubikey is a make of Security Key. The 'model' of a device is the specific product, e.g. Yubikey Neo is a model of Security Key.">
         <ph name="URL">
           $1<ex>maps.google.com</ex>
-        </ph> wants to see identifying information about your Security Key
+        </ph> wants to see the make and model of your Security Key
       </message>
     </if>
 
@@ -10863,11 +10863,45 @@
     </if>
 
     <!-- Strings that are only used when VR devices are supported -->
-      <!-- TODO(ddorwin): Use consistent naming schemes for VR strings. -->
+    <!-- TODO(ddorwin): Use consistent naming schemes for VR strings. -->
     <if expr="enable_vr">
-      <message name="IDS_PRESS_APP_TO_EXIT" desc="Text displayed in a transient bubble to tell users how to return from cinema mode (where the page displayed in a cinema like environment) or presentation mode (where the WebVR page occupies the entire screen) to normal mode.">
+      <message name="IDS_PRESS_APP_TO_EXIT" desc="Text displayed in a transient bubble to tell users how to return from presentation mode (where the WebVR page occupies the entire screen) to normal mode.">
         Press App button to exit
       </message>
+      <message name="IDS_PRESS_APP_TO_EXIT_FULLSCREEN" desc="Text displayed in a transient bubble to tell users how to return from cinema mode (where the page displayed in a cinema like environment).">
+        Press App button to exit fullscreen
+      </message>
+      <message name="IDS_VR_SHELL_SITE_IS_TRACKING_LOCATION" desc="Text displayed in a transient bubble to inform the user that the page is tracking location.">
+        Site is tracking your location
+      </message>
+      <message name="IDS_VR_SHELL_SITE_IS_USING_MICROPHONE" desc="Text displayed in a transient bubble to inform the user that the page is using the microphone.">
+        Site is using your microphone
+      </message>
+      <message name="IDS_VR_SHELL_SITE_IS_USING_BLUETOOTH" desc="Text displayed in a transient bubble to inform the user that the page is using bluetooth.">
+        Site is using bluetooth
+      </message>
+      <message name="IDS_VR_SHELL_SITE_IS_USING_CAMERA" desc="Text displayed in a transient bubble to inform the user that the page is using the camera.">
+        Site is using your camera
+      </message>
+      <message name="IDS_VR_SHELL_SITE_IS_SHARING_SCREEN" desc="Text displayed in a transient bubble to inform the user that the page is sharing the screen.">
+        Site is sharing your screen
+      </message>
+
+      <message name="IDS_VR_SHELL_SITE_CAN_TRACK_LOCATION" desc="Text displayed in a transient bubble to inform the user that the page may track location, but isn't doing so yet.">
+        Site can track your location
+      </message>
+      <message name="IDS_VR_SHELL_SITE_CAN_USE_MICROPHONE" desc="Text displayed in a transient bubble to inform the user that the page may use the microphone, but isn't doing so yet.">
+        Site can use your microphone
+      </message>
+      <message name="IDS_VR_SHELL_SITE_CAN_USE_BLUETOOTH" desc="Text displayed in a transient bubble to inform the user that the page may use bluetooth, but isn't doing so yet.">
+        Site can use bluetooth
+      </message>
+      <message name="IDS_VR_SHELL_SITE_CAN_USE_CAMERA" desc="Text displayed in a transient bubble to inform the user that the page may use the camera, but isn't doing so yet.">
+        Site can use your camera
+      </message>
+      <message name="IDS_VR_SHELL_SITE_CAN_SHARE_SCREEN" desc="Text displayed in a transient bubble to inform the user that the page may share your screen, but isn't doing so yet.">
+        Site can share your screen
+      </message>
 
       <!-- VR browser -->
       <!-- TODO(https://crbug.com/731802): Only build these when the VR browser is supported. -->
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index 2ce25524..d929737 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -314,8 +314,8 @@
     <message name="IDS_SETTINGS_ACCESSIBILITY_MOUSE_SETTINGS_TITLE" desc="In the settings tab, the title of a link to open mouse and touchpad settings.">
       Open mouse and touchpad device settings
     </message>
-    <message name="IDS_SETTINGS_ACCESSIBILITY_MOUSE_SETTINGS_DESCRIPTION" desc="In the settings tab, an explanation that the mouse and touchpad settings allows you to turn the tap-to-click feature on and off.">
-      Allows you to enable/disable tap-to-click
+    <message name="IDS_SETTINGS_ACCESSIBILITY_MOUSE_SETTINGS_DESCRIPTION" desc="In the settings tab, an explanation that the mouse and touchpad settings allows you to turn the tap-to-click and tap dragging features on and off.">
+      Allows you to enable/disable tap-to-click and tap dragging
     </message>
     <message name="IDS_SETTINGS_ACCESSIBILITY_SELECT_TO_SPEAK_TITLE" desc="In the settings tab, the text next to the checkbox to enable an option to hold a key and click to speak any on-screen text out loud.">
       Enable select-to-speak
@@ -3168,6 +3168,9 @@
   <message name="IDS_SETTINGS_SYNC" desc="Name of the sync service.">
     Sync
   </message>
+  <message name="IDS_SETTINGS_SYNC_SYNC_AND_PERSONALIZATION" desc="The label of button that takes the user to manage their sync and personalization settings.">
+    Sync and personalization
+  </message>
   <message name="IDS_SETTINGS_SYNC_PAGE_TITLE" desc="Name of the settings page which manages syncing data between multiple browser instances with the same Google profile.">
     Advanced sync settings
   </message>
diff --git a/chrome/app/vector_icons/BUILD.gn b/chrome/app/vector_icons/BUILD.gn
index 9a82af2..ca6194d 100644
--- a/chrome/app/vector_icons/BUILD.gn
+++ b/chrome/app/vector_icons/BUILD.gn
@@ -18,15 +18,11 @@
     "apps.icon",
     "blocked_badge.icon",
     "blocked_redirect.icon",
-    "browser_tools.1x.icon",
     "browser_tools.icon",
-    "browser_tools_animated.1x.icon",
     "browser_tools_animated.icon",
     "browser_tools_error.icon",
     "browser_tools_update.icon",
-    "caret_down.1x.icon",
     "caret_down.icon",
-    "caret_up.1x.icon",
     "caret_up.icon",
     "certificate.icon",
     "close_all.icon",
@@ -42,7 +38,6 @@
     "content_paste.icon",
     "cookie.icon",
     "crashed_tab.icon",
-    "credit_card.1x.icon",
     "credit_card.icon",
     "default_touch_favicon.icon",
     "default_touch_favicon_mask.icon",
@@ -52,29 +47,23 @@
     "file_download.icon",
     "file_download_shelf.icon",
     "folder.icon",
-    "folder_supervised.1x.icon",
     "folder_supervised.icon",
     "forward_arrow_touch.icon",
     "globe.icon",
     "google_pay_logo_with_vertical_separator.icon",
-    "horizontal_menu.1x.icon",
     "horizontal_menu.icon",
-    "incognito.1x.icon",
     "incognito.icon",
     "key.icon",
     "laptop.icon",
     "launch.icon",
     "mixed_content.icon",
     "my_location.icon",
-    "navigate_home.1x.icon",
     "navigate_home.icon",
     "navigate_home_touch.icon",
-    "navigate_stop.1x.icon",
     "navigate_stop.icon",
     "navigate_stop_touch.icon",
     "new_tab_button_incognito.icon",
     "new_tab_button_plus.icon",
-    "overflow_chevron.1x.icon",
     "overflow_chevron.icon",
     "page_info_content_paste.icon",
     "paintbrush.icon",
@@ -98,9 +87,7 @@
     "sync_problem.icon",
     "sync_switch_account.icon",
     "tab.icon",
-    "tab_audio.1x.icon",
     "tab_audio.icon",
-    "tab_audio_muting.1x.icon",
     "tab_audio_muting.icon",
     "tab_audio_muting_rounded.icon",
     "tab_audio_rounded.icon",
@@ -108,14 +95,11 @@
     "tab_close_button_touch.icon",
     "tab_close_button_touch_hovered_pressed.icon",
     "tab_close_button_touch_incognito_hovered_pressed.icon",
-    "tab_close_hovered_pressed.1x.icon",
     "tab_close_hovered_pressed.icon",
-    "tab_close_normal.1x.icon",
     "tab_close_normal.icon",
     "tab_media_capturing.icon",
     "tab_media_capturing_with_arrow.icon",
     "tab_media_recording.icon",
-    "tab_usb_connected.1x.icon",
     "tab_usb_connected.icon",
     "tablet.icon",
     "translate.icon",
@@ -150,10 +134,7 @@
   }
 
   if (is_chromeos) {
-    icons += [
-      "warning_badge_circle.1x.icon",
-      "warning_badge_circle.icon",
-    ]
+    icons += [ "warning_badge_circle.icon" ]
   }
 }
 
diff --git a/chrome/app/vector_icons/browser_tools.1x.icon b/chrome/app/vector_icons/browser_tools.1x.icon
deleted file mode 100644
index 7115751..0000000
--- a/chrome/app/vector_icons/browser_tools.1x.icon
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 7, 3.5f,
-CUBIC_TO, 7, 2.67f, 7.67f, 2, 8.5f, 2,
-CUBIC_TO, 9.33f, 2, 10, 2.67f, 10, 3.5f,
-CUBIC_TO, 10, 4.33f, 9.33f, 5, 8.5f, 5,
-CUBIC_TO, 7.67f, 5, 7, 4.33f, 7, 3.5f,
-CLOSE,
-MOVE_TO, 7, 8.5f,
-CUBIC_TO, 7, 7.67f, 7.67f, 7, 8.5f, 7,
-CUBIC_TO, 9.33f, 7, 10, 7.67f, 10, 8.5f,
-CUBIC_TO, 10, 9.33f, 9.33f, 10, 8.5f, 10,
-CUBIC_TO, 7.67f, 10, 7, 9.33f, 7, 8.5f,
-CLOSE,
-MOVE_TO, 7, 13.5f,
-CUBIC_TO, 7, 12.67f, 7.67f, 12, 8.5f, 12,
-CUBIC_TO, 9.33f, 12, 10, 12.67f, 10, 13.5f,
-CUBIC_TO, 10, 14.33f, 9.33f, 15, 8.5f, 15,
-CUBIC_TO, 7.67f, 15, 7, 14.33f, 7, 13.5f,
-CLOSE
diff --git a/chrome/app/vector_icons/browser_tools.icon b/chrome/app/vector_icons/browser_tools.icon
index 6fd494e..6a6ad464 100644
--- a/chrome/app/vector_icons/browser_tools.icon
+++ b/chrome/app/vector_icons/browser_tools.icon
@@ -21,3 +21,23 @@
 CUBIC_TO, 14.34f, 23, 13, 24.34f, 13, 26,
 CUBIC_TO, 13, 27.66f, 14.34f, 29, 16, 29,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 7, 3.5f,
+CUBIC_TO, 7, 2.67f, 7.67f, 2, 8.5f, 2,
+CUBIC_TO, 9.33f, 2, 10, 2.67f, 10, 3.5f,
+CUBIC_TO, 10, 4.33f, 9.33f, 5, 8.5f, 5,
+CUBIC_TO, 7.67f, 5, 7, 4.33f, 7, 3.5f,
+CLOSE,
+MOVE_TO, 7, 8.5f,
+CUBIC_TO, 7, 7.67f, 7.67f, 7, 8.5f, 7,
+CUBIC_TO, 9.33f, 7, 10, 7.67f, 10, 8.5f,
+CUBIC_TO, 10, 9.33f, 9.33f, 10, 8.5f, 10,
+CUBIC_TO, 7.67f, 10, 7, 9.33f, 7, 8.5f,
+CLOSE,
+MOVE_TO, 7, 13.5f,
+CUBIC_TO, 7, 12.67f, 7.67f, 12, 8.5f, 12,
+CUBIC_TO, 9.33f, 12, 10, 12.67f, 10, 13.5f,
+CUBIC_TO, 10, 14.33f, 9.33f, 15, 8.5f, 15,
+CUBIC_TO, 7.67f, 15, 7, 14.33f, 7, 13.5f,
+CLOSE
diff --git a/chrome/app/vector_icons/browser_tools_animated.1x.icon b/chrome/app/vector_icons/browser_tools_animated.1x.icon
deleted file mode 100644
index 5897c1c..0000000
--- a/chrome/app/vector_icons/browser_tools_animated.1x.icon
+++ /dev/null
@@ -1,106 +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.
-
-CANVAS_DIMENSIONS, 16,
-
-// Top dot.
-TRANSITION_FROM,
-TRANSITION_FROM,
-MOVE_TO, 7, 3.5f,
-CUBIC_TO, 7, 2.67f, 7.67f, 2, 8.5f, 2,
-R_H_LINE_TO, 0,
-CUBIC_TO, 9.33f, 2, 10, 2.67f, 10, 3.5f,
-CUBIC_TO, 10, 4.33f, 9.33f, 5, 8.5f, 5,
-R_H_LINE_TO, 0,
-CUBIC_TO, 7.67f, 5, 7, 4.33f, 7, 3.5f,
-
-TRANSITION_TO,
-MOVE_TO, 4.68f, 3.5f,
-CUBIC_TO, 4.68f, 2.95f, 5.13f, 2.5f, 5.68f, 2.5f,
-R_H_LINE_TO, 5.65f,
-CUBIC_TO, 11.87f, 2.5f, 12.32f, 2.95f, 12.32f, 3.5f,
-CUBIC_TO, 12.32f, 4.05f, 11.87f, 4.5f, 11.32f, 4.5f,
-R_H_LINE_TO, -5.65f,
-CUBIC_TO, 5.13f, 4.5f, 4.68f, 4.05f, 4.68f, 2.5f,
-TRANSITION_END, 133, 150, gfx::Tween::FAST_OUT_SLOW_IN,
-
-TRANSITION_TO,
-MOVE_TO, 7, 3.5f,
-CUBIC_TO, 7, 2.67f, 7.67f, 2, 8.5f, 2,
-R_H_LINE_TO, 0,
-CUBIC_TO, 9.33f, 2, 10, 2.67f, 10, 3.5f,
-CUBIC_TO, 10, 4.33f, 9.33f, 5, 8.5f, 5,
-R_H_LINE_TO, 0,
-CUBIC_TO, 7.67f, 5, 7, 4.33f, 7, 3.5f,
-TRANSITION_END, 416, 533, gfx::Tween::FAST_OUT_SLOW_IN,
-
-CLOSE,
-NEW_PATH,
-
-// Middle dot.
-TRANSITION_FROM,
-TRANSITION_FROM,
-MOVE_TO, 7, 8.5f,
-CUBIC_TO, 7, 7.67f, 7.67f, 7, 8.5f, 7,
-R_H_LINE_TO, 0,
-CUBIC_TO, 9.33f, 7, 10, 7.67f, 10, 8.5f,
-CUBIC_TO, 10, 9.33f, 9.33f, 10, 8.5f, 10,
-R_H_LINE_TO, 0,
-CUBIC_TO, 7.67f, 10, 7, 9.33f, 7, 8.5f,
-
-TRANSITION_TO,
-MOVE_TO, 4.68f, 8.5f,
-CUBIC_TO, 4.68f, 7.95f, 5.13f, 7.5f, 5.68f, 7.5f,
-R_H_LINE_TO, 5.65f,
-CUBIC_TO, 11.87f, 7.5f, 12.32f, 7.95f, 12.32f, 8.5f,
-CUBIC_TO, 12.32f, 9.05f, 11.87f, 9.5f, 11.32f, 9.5f,
-R_H_LINE_TO, -5.65f,
-CUBIC_TO, 5.13f, 9.5f, 4.68f, 9.05f, 4.68f, 7.5f,
-TRANSITION_END, 67, 150, gfx::Tween::FAST_OUT_SLOW_IN,
-
-TRANSITION_TO,
-MOVE_TO, 7, 8.5f,
-CUBIC_TO, 7, 7.67f, 7.67f, 7, 8.5f, 7,
-R_H_LINE_TO, 0,
-CUBIC_TO, 9.33f, 7, 10, 7.67f, 10, 8.5f,
-CUBIC_TO, 10, 9.33f, 9.33f, 10, 8.5f, 10,
-R_H_LINE_TO, 0,
-CUBIC_TO, 7.67f, 10, 7, 9.33f, 7, 8.5f,
-TRANSITION_END, 350, 383, gfx::Tween::FAST_OUT_SLOW_IN,
-
-CLOSE,
-NEW_PATH,
-
-// Bottom dot.
-TRANSITION_FROM,
-TRANSITION_FROM,
-MOVE_TO, 7, 13.5f,
-CUBIC_TO, 7, 12.67f, 7.67f, 12, 8.5f, 12,
-R_H_LINE_TO, 0,
-CUBIC_TO, 9.33f, 12, 10, 12.67f, 10, 13.5f,
-CUBIC_TO, 10, 14.33f, 9.33f, 15, 8.5f, 15,
-R_H_LINE_TO, 0,
-CUBIC_TO, 7.67f, 15, 7, 14.33f, 7, 13.5f,
-
-TRANSITION_TO,
-MOVE_TO, 4.68f, 13.5f,
-CUBIC_TO, 4.68f, 12.95f, 5.13f, 12.5f, 5.68f, 12.5f,
-R_H_LINE_TO, 5.65f,
-CUBIC_TO, 11.87f, 12.5f, 12.32f, 12.95f, 12.32f, 13.5f,
-CUBIC_TO, 12.32f, 14.05f, 11.87f, 14.5f, 11.32f, 14.5f,
-R_H_LINE_TO, -5.65f,
-CUBIC_TO, 5.13f, 14.5f, 4.68f, 14.05f, 4.68f, 12.5f,
-TRANSITION_END, 0, 150, gfx::Tween::FAST_OUT_SLOW_IN,
-
-TRANSITION_TO,
-MOVE_TO, 7, 13.5f,
-CUBIC_TO, 7, 12.67f, 7.67f, 12, 8.5f, 12,
-R_H_LINE_TO, 0,
-CUBIC_TO, 9.33f, 12, 10, 12.67f, 10, 13.5f,
-CUBIC_TO, 10, 14.33f, 9.33f, 15, 8.5f, 15,
-R_H_LINE_TO, 0,
-CUBIC_TO, 7.67f, 15, 7, 14.33f, 7, 13.5f,
-TRANSITION_END, 283, 400, gfx::Tween::FAST_OUT_SLOW_IN,
-
-CLOSE
diff --git a/chrome/app/vector_icons/browser_tools_animated.icon b/chrome/app/vector_icons/browser_tools_animated.icon
index 89af1169..bd94e1af 100644
--- a/chrome/app/vector_icons/browser_tools_animated.icon
+++ b/chrome/app/vector_icons/browser_tools_animated.icon
@@ -95,3 +95,106 @@
 TRANSITION_END, 283, 400, gfx::Tween::FAST_OUT_SLOW_IN,
 
 CLOSE,
+
+CANVAS_DIMENSIONS, 16,
+
+// Top dot.
+TRANSITION_FROM,
+TRANSITION_FROM,
+MOVE_TO, 7, 3.5f,
+CUBIC_TO, 7, 2.67f, 7.67f, 2, 8.5f, 2,
+R_H_LINE_TO, 0,
+CUBIC_TO, 9.33f, 2, 10, 2.67f, 10, 3.5f,
+CUBIC_TO, 10, 4.33f, 9.33f, 5, 8.5f, 5,
+R_H_LINE_TO, 0,
+CUBIC_TO, 7.67f, 5, 7, 4.33f, 7, 3.5f,
+
+TRANSITION_TO,
+MOVE_TO, 4.68f, 3.5f,
+CUBIC_TO, 4.68f, 2.95f, 5.13f, 2.5f, 5.68f, 2.5f,
+R_H_LINE_TO, 5.65f,
+CUBIC_TO, 11.87f, 2.5f, 12.32f, 2.95f, 12.32f, 3.5f,
+CUBIC_TO, 12.32f, 4.05f, 11.87f, 4.5f, 11.32f, 4.5f,
+R_H_LINE_TO, -5.65f,
+CUBIC_TO, 5.13f, 4.5f, 4.68f, 4.05f, 4.68f, 2.5f,
+TRANSITION_END, 133, 150, gfx::Tween::FAST_OUT_SLOW_IN,
+
+TRANSITION_TO,
+MOVE_TO, 7, 3.5f,
+CUBIC_TO, 7, 2.67f, 7.67f, 2, 8.5f, 2,
+R_H_LINE_TO, 0,
+CUBIC_TO, 9.33f, 2, 10, 2.67f, 10, 3.5f,
+CUBIC_TO, 10, 4.33f, 9.33f, 5, 8.5f, 5,
+R_H_LINE_TO, 0,
+CUBIC_TO, 7.67f, 5, 7, 4.33f, 7, 3.5f,
+TRANSITION_END, 416, 533, gfx::Tween::FAST_OUT_SLOW_IN,
+
+CLOSE,
+NEW_PATH,
+
+// Middle dot.
+TRANSITION_FROM,
+TRANSITION_FROM,
+MOVE_TO, 7, 8.5f,
+CUBIC_TO, 7, 7.67f, 7.67f, 7, 8.5f, 7,
+R_H_LINE_TO, 0,
+CUBIC_TO, 9.33f, 7, 10, 7.67f, 10, 8.5f,
+CUBIC_TO, 10, 9.33f, 9.33f, 10, 8.5f, 10,
+R_H_LINE_TO, 0,
+CUBIC_TO, 7.67f, 10, 7, 9.33f, 7, 8.5f,
+
+TRANSITION_TO,
+MOVE_TO, 4.68f, 8.5f,
+CUBIC_TO, 4.68f, 7.95f, 5.13f, 7.5f, 5.68f, 7.5f,
+R_H_LINE_TO, 5.65f,
+CUBIC_TO, 11.87f, 7.5f, 12.32f, 7.95f, 12.32f, 8.5f,
+CUBIC_TO, 12.32f, 9.05f, 11.87f, 9.5f, 11.32f, 9.5f,
+R_H_LINE_TO, -5.65f,
+CUBIC_TO, 5.13f, 9.5f, 4.68f, 9.05f, 4.68f, 7.5f,
+TRANSITION_END, 67, 150, gfx::Tween::FAST_OUT_SLOW_IN,
+
+TRANSITION_TO,
+MOVE_TO, 7, 8.5f,
+CUBIC_TO, 7, 7.67f, 7.67f, 7, 8.5f, 7,
+R_H_LINE_TO, 0,
+CUBIC_TO, 9.33f, 7, 10, 7.67f, 10, 8.5f,
+CUBIC_TO, 10, 9.33f, 9.33f, 10, 8.5f, 10,
+R_H_LINE_TO, 0,
+CUBIC_TO, 7.67f, 10, 7, 9.33f, 7, 8.5f,
+TRANSITION_END, 350, 383, gfx::Tween::FAST_OUT_SLOW_IN,
+
+CLOSE,
+NEW_PATH,
+
+// Bottom dot.
+TRANSITION_FROM,
+TRANSITION_FROM,
+MOVE_TO, 7, 13.5f,
+CUBIC_TO, 7, 12.67f, 7.67f, 12, 8.5f, 12,
+R_H_LINE_TO, 0,
+CUBIC_TO, 9.33f, 12, 10, 12.67f, 10, 13.5f,
+CUBIC_TO, 10, 14.33f, 9.33f, 15, 8.5f, 15,
+R_H_LINE_TO, 0,
+CUBIC_TO, 7.67f, 15, 7, 14.33f, 7, 13.5f,
+
+TRANSITION_TO,
+MOVE_TO, 4.68f, 13.5f,
+CUBIC_TO, 4.68f, 12.95f, 5.13f, 12.5f, 5.68f, 12.5f,
+R_H_LINE_TO, 5.65f,
+CUBIC_TO, 11.87f, 12.5f, 12.32f, 12.95f, 12.32f, 13.5f,
+CUBIC_TO, 12.32f, 14.05f, 11.87f, 14.5f, 11.32f, 14.5f,
+R_H_LINE_TO, -5.65f,
+CUBIC_TO, 5.13f, 14.5f, 4.68f, 14.05f, 4.68f, 12.5f,
+TRANSITION_END, 0, 150, gfx::Tween::FAST_OUT_SLOW_IN,
+
+TRANSITION_TO,
+MOVE_TO, 7, 13.5f,
+CUBIC_TO, 7, 12.67f, 7.67f, 12, 8.5f, 12,
+R_H_LINE_TO, 0,
+CUBIC_TO, 9.33f, 12, 10, 12.67f, 10, 13.5f,
+CUBIC_TO, 10, 14.33f, 9.33f, 15, 8.5f, 15,
+R_H_LINE_TO, 0,
+CUBIC_TO, 7.67f, 15, 7, 14.33f, 7, 13.5f,
+TRANSITION_END, 283, 400, gfx::Tween::FAST_OUT_SLOW_IN,
+
+CLOSE
diff --git a/chrome/app/vector_icons/caret_down.1x.icon b/chrome/app/vector_icons/caret_down.1x.icon
deleted file mode 100644
index 1359d50..0000000
--- a/chrome/app/vector_icons/caret_down.1x.icon
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// A variant of ic_expand_more with rounded corners and optimized for 1x
-// scale factor devices.
-CANVAS_DIMENSIONS, 16,
-STROKE, 1.765f,
-MOVE_TO, 4, 6,
-R_LINE_TO, 4, 4,
-R_LINE_TO, 4, -4,
diff --git a/chrome/app/vector_icons/caret_down.icon b/chrome/app/vector_icons/caret_down.icon
index b4a1696f..e281716f9 100644
--- a/chrome/app/vector_icons/caret_down.icon
+++ b/chrome/app/vector_icons/caret_down.icon
@@ -10,3 +10,11 @@
 R_LINE_TO, 7.5f, -8,
 // Hard clip at path points +- half the stroke.
 CLIP, 7, 11, 18, 11,
+
+// A variant of ic_expand_more with rounded corners and optimized for 1x
+// scale factor devices.
+CANVAS_DIMENSIONS, 16,
+STROKE, 1.765f,
+MOVE_TO, 4, 6,
+R_LINE_TO, 4, 4,
+R_LINE_TO, 4, -4,
diff --git a/chrome/app/vector_icons/caret_up.1x.icon b/chrome/app/vector_icons/caret_up.1x.icon
deleted file mode 100644
index 5bd4153..0000000
--- a/chrome/app/vector_icons/caret_up.1x.icon
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// A variant of ic_expand_less with rounded corners and optimized for 1x
-// scale factor devices.
-CANVAS_DIMENSIONS, 16,
-STROKE, 1.765f,
-MOVE_TO, 4, 10,
-R_LINE_TO, 4, -4,
-R_LINE_TO, 4, 4,
diff --git a/chrome/app/vector_icons/caret_up.icon b/chrome/app/vector_icons/caret_up.icon
index 09b08e0..91082812 100644
--- a/chrome/app/vector_icons/caret_up.icon
+++ b/chrome/app/vector_icons/caret_up.icon
@@ -10,3 +10,11 @@
 MOVE_TO, 8.5f, 19.5f,
 R_LINE_TO, 7.5f, -8,
 R_LINE_TO, 7.5f, 8,
+
+// A variant of ic_expand_less with rounded corners and optimized for 1x
+// scale factor devices.
+CANVAS_DIMENSIONS, 16,
+STROKE, 1.765f,
+MOVE_TO, 4, 10,
+R_LINE_TO, 4, -4,
+R_LINE_TO, 4, 4,
diff --git a/chrome/app/vector_icons/credit_card.1x.icon b/chrome/app/vector_icons/credit_card.1x.icon
deleted file mode 100644
index b3e5a647..0000000
--- a/chrome/app/vector_icons/credit_card.1x.icon
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 13, 7,
-V_LINE_TO, 5,
-H_LINE_TO, 3,
-R_V_LINE_TO, 2,
-R_H_LINE_TO, 10,
-CLOSE,
-R_MOVE_TO, 0, 2,
-R_V_LINE_TO, 3,
-H_LINE_TO, 3,
-V_LINE_TO, 9,
-R_H_LINE_TO, 10,
-CLOSE,
-MOVE_TO, 1, 4.99f,
-CUBIC_TO, 1, 3.89f, 1.9f, 3, 3.01f, 3,
-R_H_LINE_TO, 9.99f,
-CUBIC_TO, 14.1f, 3, 15, 3.9f, 15, 4.99f,
-R_V_LINE_TO, 7.02f,
-R_CUBIC_TO, 0, 1.1f, -0.9f, 1.99f, -2.01f, 1.99f,
-H_LINE_TO, 3.01f,
-CUBIC_TO, 1.9f, 14, 1, 13.1f, 1, 12.01f,
-V_LINE_TO, 4.99f,
-CLOSE
diff --git a/chrome/app/vector_icons/credit_card.icon b/chrome/app/vector_icons/credit_card.icon
index b0b43cb7..cba5419 100644
--- a/chrome/app/vector_icons/credit_card.icon
+++ b/chrome/app/vector_icons/credit_card.icon
@@ -25,3 +25,27 @@
 R_H_LINE_TO, 22,
 R_V_LINE_TO, 3,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 13, 7,
+V_LINE_TO, 5,
+H_LINE_TO, 3,
+R_V_LINE_TO, 2,
+R_H_LINE_TO, 10,
+CLOSE,
+R_MOVE_TO, 0, 2,
+R_V_LINE_TO, 3,
+H_LINE_TO, 3,
+V_LINE_TO, 9,
+R_H_LINE_TO, 10,
+CLOSE,
+MOVE_TO, 1, 4.99f,
+CUBIC_TO, 1, 3.89f, 1.9f, 3, 3.01f, 3,
+R_H_LINE_TO, 9.99f,
+CUBIC_TO, 14.1f, 3, 15, 3.9f, 15, 4.99f,
+R_V_LINE_TO, 7.02f,
+R_CUBIC_TO, 0, 1.1f, -0.9f, 1.99f, -2.01f, 1.99f,
+H_LINE_TO, 3.01f,
+CUBIC_TO, 1.9f, 14, 1, 13.1f, 1, 12.01f,
+V_LINE_TO, 4.99f,
+CLOSE
diff --git a/chrome/app/vector_icons/folder_supervised.1x.icon b/chrome/app/vector_icons/folder_supervised.1x.icon
deleted file mode 100644
index 2245267..0000000
--- a/chrome/app/vector_icons/folder_supervised.1x.icon
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 2.5f, 2,
-CUBIC_TO, 1.73f, 2, 1.01f, 3.15f, 1.01f, 3.94f,
-LINE_TO, 1, 12.56f,
-CUBIC_TO, 1, 13.35f, 1.63f, 14, 2.4f, 14,
-LINE_TO, 13.6f, 14,
-CUBIC_TO, 14.37f, 14, 15, 13.35f, 15, 12.56f,
-LINE_TO, 15, 5.38f,
-CUBIC_TO, 15, 4.58f, 14.27f, 4, 13.5f, 4,
-LINE_TO, 9, 4,
-LINE_TO, 7, 2,
-LINE_TO, 2.5f, 2,
-CLOSE,
-MOVE_TO, 8, 11.06f,
-CUBIC_TO, 8.54f, 11.18f, 9, 11.47f, 9, 11.83f,
-LINE_TO, 9, 12.69f,
-CUBIC_TO, 9.58f, 12.44f, 10, 12.06f, 10, 11.61f,
-LINE_TO, 10, 9.39f,
-CUBIC_TO, 10, 8.6f, 8.68f, 8, 7.5f, 8,
-CUBIC_TO, 6.32f, 8, 5, 8.6f, 5, 9.39f,
-LINE_TO, 5, 11.61f,
-CUBIC_TO, 5, 12.06f, 5.42f, 12.44f, 6, 12.7f,
-CUBIC_TO, 6.45f, 12.89f, 6.99f, 13, 7.5f, 13,
-CUBIC_TO, 7.67f, 13, 7.84f, 12.99f, 8, 12.96f,
-LINE_TO, 8, 11.96f,
-CUBIC_TO, 7.84f, 11.99f, 7.67f, 12, 7.5f, 12,
-CUBIC_TO, 7, 12, 6.47f, 11.89f, 6.03f, 11.7f,
-CUBIC_TO, 6.15f, 11.3f, 6.86f, 11, 7.5f, 11,
-CUBIC_TO, 7.67f, 11, 7.84f, 11.02f, 8, 11.06f,
-CLOSE,
-MOVE_TO, 7.5f, 10.5f,
-CUBIC_TO, 7.91f, 10.5f, 8.25f, 10.16f, 8.25f, 9.75f,
-CUBIC_TO, 8.25f, 9.34f, 7.91f, 9, 7.5f, 9,
-CUBIC_TO, 7.09f, 9, 6.75f, 9.34f, 6.75f, 9.75f,
-CUBIC_TO, 6.75f, 10.16f, 7.09f, 10.5f, 7.5f, 10.5f,
-CLOSE,
-MOVE_TO, 7.5f, 7.5f,
-CUBIC_TO, 8.19f, 7.5f, 8.75f, 6.94f, 8.75f, 6.25f,
-CUBIC_TO, 8.75f, 5.56f, 8.19f, 5, 7.5f, 5,
-CUBIC_TO, 6.81f, 5, 6.25f, 5.56f, 6.25f, 6.25f,
-CUBIC_TO, 6.25f, 6.94f, 6.81f, 7.5f, 7.5f, 7.5f,
-CLOSE
diff --git a/chrome/app/vector_icons/folder_supervised.icon b/chrome/app/vector_icons/folder_supervised.icon
index da6f86f1d..1ec13b8a 100644
--- a/chrome/app/vector_icons/folder_supervised.icon
+++ b/chrome/app/vector_icons/folder_supervised.icon
@@ -44,3 +44,46 @@
 CUBIC_TO, 15.17f, 18, 14.5f, 18.67f, 14.5f, 19.5f,
 CUBIC_TO, 14.5f, 20.33f, 15.17f, 21, 16, 21,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 2.5f, 2,
+CUBIC_TO, 1.73f, 2, 1.01f, 3.15f, 1.01f, 3.94f,
+LINE_TO, 1, 12.56f,
+CUBIC_TO, 1, 13.35f, 1.63f, 14, 2.4f, 14,
+LINE_TO, 13.6f, 14,
+CUBIC_TO, 14.37f, 14, 15, 13.35f, 15, 12.56f,
+LINE_TO, 15, 5.38f,
+CUBIC_TO, 15, 4.58f, 14.27f, 4, 13.5f, 4,
+LINE_TO, 9, 4,
+LINE_TO, 7, 2,
+LINE_TO, 2.5f, 2,
+CLOSE,
+MOVE_TO, 8, 11.06f,
+CUBIC_TO, 8.54f, 11.18f, 9, 11.47f, 9, 11.83f,
+LINE_TO, 9, 12.69f,
+CUBIC_TO, 9.58f, 12.44f, 10, 12.06f, 10, 11.61f,
+LINE_TO, 10, 9.39f,
+CUBIC_TO, 10, 8.6f, 8.68f, 8, 7.5f, 8,
+CUBIC_TO, 6.32f, 8, 5, 8.6f, 5, 9.39f,
+LINE_TO, 5, 11.61f,
+CUBIC_TO, 5, 12.06f, 5.42f, 12.44f, 6, 12.7f,
+CUBIC_TO, 6.45f, 12.89f, 6.99f, 13, 7.5f, 13,
+CUBIC_TO, 7.67f, 13, 7.84f, 12.99f, 8, 12.96f,
+LINE_TO, 8, 11.96f,
+CUBIC_TO, 7.84f, 11.99f, 7.67f, 12, 7.5f, 12,
+CUBIC_TO, 7, 12, 6.47f, 11.89f, 6.03f, 11.7f,
+CUBIC_TO, 6.15f, 11.3f, 6.86f, 11, 7.5f, 11,
+CUBIC_TO, 7.67f, 11, 7.84f, 11.02f, 8, 11.06f,
+CLOSE,
+MOVE_TO, 7.5f, 10.5f,
+CUBIC_TO, 7.91f, 10.5f, 8.25f, 10.16f, 8.25f, 9.75f,
+CUBIC_TO, 8.25f, 9.34f, 7.91f, 9, 7.5f, 9,
+CUBIC_TO, 7.09f, 9, 6.75f, 9.34f, 6.75f, 9.75f,
+CUBIC_TO, 6.75f, 10.16f, 7.09f, 10.5f, 7.5f, 10.5f,
+CLOSE,
+MOVE_TO, 7.5f, 7.5f,
+CUBIC_TO, 8.19f, 7.5f, 8.75f, 6.94f, 8.75f, 6.25f,
+CUBIC_TO, 8.75f, 5.56f, 8.19f, 5, 7.5f, 5,
+CUBIC_TO, 6.81f, 5, 6.25f, 5.56f, 6.25f, 6.25f,
+CUBIC_TO, 6.25f, 6.94f, 6.81f, 7.5f, 7.5f, 7.5f,
+CLOSE
diff --git a/chrome/app/vector_icons/horizontal_menu.1x.icon b/chrome/app/vector_icons/horizontal_menu.1x.icon
deleted file mode 100644
index 5b82051..0000000
--- a/chrome/app/vector_icons/horizontal_menu.1x.icon
+++ /dev/null
@@ -1,23 +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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 3, 6.5f,
-CUBIC_TO, 2.17f, 6.5f, 1.5f, 7.17f, 1.5f, 8,
-CUBIC_TO, 1.5f, 8.83f, 2.17f, 9.5f, 3, 9.5f,
-CUBIC_TO, 3.83f, 9.5f, 4.5f, 8.83f, 4.5f, 8,
-CUBIC_TO, 4.5f, 7.17f, 3.83f, 6.5, 3, 6.5f,
-CLOSE,
-MOVE_TO, 8, 6.5f,
-CUBIC_TO, 7.17f, 6.5f, 6.5f, 7.17f, 6.5f, 8,
-CUBIC_TO, 6.5f, 8.83f, 7.17f, 9.5f, 8, 9.5f,
-CUBIC_TO, 8.83f, 9.5f, 9.5f, 8.83f, 9.5f, 8,
-CUBIC_TO, 9.5f, 7.17f, 8.83f, 6.5f, 8, 6.5f,
-CLOSE,
-MOVE_TO, 13, 6.5f,
-CUBIC_TO, 12.17f, 6.5f, 11.5f, 7.17f, 11.5f, 8,
-CUBIC_TO, 11.5f, 8.83f, 12.17f, 9.5f, 13, 9.5f,
-CUBIC_TO, 13.83f, 9.5f, 14.5f, 8.83f, 14.5f, 8,
-CUBIC_TO, 14.5f, 7.17f, 13.83f, 6.5f, 13, 6.5f,
-CLOSE
diff --git a/chrome/app/vector_icons/horizontal_menu.icon b/chrome/app/vector_icons/horizontal_menu.icon
index 33b5698..7abf8f44 100644
--- a/chrome/app/vector_icons/horizontal_menu.icon
+++ b/chrome/app/vector_icons/horizontal_menu.icon
@@ -21,3 +21,23 @@
 CUBIC_TO, 21, 14.34f, 22.34f, 13, 24, 13,
 CUBIC_TO, 25.66f, 13, 27, 14.34f, 27, 16,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 3, 6.5f,
+CUBIC_TO, 2.17f, 6.5f, 1.5f, 7.17f, 1.5f, 8,
+CUBIC_TO, 1.5f, 8.83f, 2.17f, 9.5f, 3, 9.5f,
+CUBIC_TO, 3.83f, 9.5f, 4.5f, 8.83f, 4.5f, 8,
+CUBIC_TO, 4.5f, 7.17f, 3.83f, 6.5, 3, 6.5f,
+CLOSE,
+MOVE_TO, 8, 6.5f,
+CUBIC_TO, 7.17f, 6.5f, 6.5f, 7.17f, 6.5f, 8,
+CUBIC_TO, 6.5f, 8.83f, 7.17f, 9.5f, 8, 9.5f,
+CUBIC_TO, 8.83f, 9.5f, 9.5f, 8.83f, 9.5f, 8,
+CUBIC_TO, 9.5f, 7.17f, 8.83f, 6.5f, 8, 6.5f,
+CLOSE,
+MOVE_TO, 13, 6.5f,
+CUBIC_TO, 12.17f, 6.5f, 11.5f, 7.17f, 11.5f, 8,
+CUBIC_TO, 11.5f, 8.83f, 12.17f, 9.5f, 13, 9.5f,
+CUBIC_TO, 13.83f, 9.5f, 14.5f, 8.83f, 14.5f, 8,
+CUBIC_TO, 14.5f, 7.17f, 13.83f, 6.5f, 13, 6.5f,
+CLOSE
diff --git a/chrome/app/vector_icons/incognito.1x.icon b/chrome/app/vector_icons/incognito.1x.icon
deleted file mode 100644
index 420a90e..0000000
--- a/chrome/app/vector_icons/incognito.1x.icon
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 24,
-MOVE_TO, 11, 17,
-R_CUBIC_TO, 0, 1.66f, -1.34f, 3, -3, 3,
-R_CUBIC_TO, -1.66f, 0, -3, -1.34f, -3, -3,
-R_CUBIC_TO, 0, -1.66f, 1.34f, -3, 3, -3,
-R_CUBIC_TO, 1.66f, 0, 3, 1.34f, 3, 3,
-CLOSE,
-R_MOVE_TO, -3, 2,
-R_CUBIC_TO, 1.11f, 0, 2, -0.89f, 2, -2,
-R_CUBIC_TO, 0, -1.11f, -0.89f, -2, -2, -2,
-R_CUBIC_TO, -1.11f, 0, -2, 0.9f, -2, 2,
-R_CUBIC_TO, 0, 1.1f, 0.9f, 2, 2, 2,
-CLOSE,
-MOVE_TO, 19, 17,
-R_CUBIC_TO, 0, 1.66f, -1.34f, 3, -3, 3,
-R_CUBIC_TO, -1.66f, 0, -3, -1.34f, -3, -3,
-R_CUBIC_TO, 0, -1.66f, 1.34f, -3, 3, -3,
-R_CUBIC_TO, 1.66f, 0, 3, 1.34f, 3, 3,
-CLOSE,
-R_MOVE_TO, -3, -2,
-R_CUBIC_TO, -1.1f, 0, -2, 0.89f, -2, 2,
-R_CUBIC_TO, 0, 1.11f, 0.89f, 2, 2, 2,
-R_CUBIC_TO, 1.11f, 0, 2, -0.89f, 2, -2,
-R_CUBIC_TO, 0, -1.1f, -0.89f, -2, -2, -2,
-CLOSE,
-NEW_PATH,
-MOVE_TO, 12, 17,
-R_CUBIC_TO, 0.93f, 0, 1.71f, 0.64f, 1.93f, 1.5f,
-R_CUBIC_TO, 0.04f, -0.16f, 0.07f, -0.33f, 0.07f, -0.5f,
-R_CUBIC_TO, 0, -1.1f, -0.9f, -2, -2, -2,
-R_CUBIC_TO, -1.1f, 0, -2, 0.9f, -2, 2,
-R_CUBIC_TO, 0, 0.17f, 0.03f, 0.34f, 0.07f, 0.5f,
-R_CUBIC_TO, 0.22f, -0.86f, 1, -1.5f, 1.93f, -1.5f,
-NEW_PATH,
-MOVE_TO, 16.39f, 8,
-LINE_TO, 15, 4,
-R_LINE_TO, -3, 1,
-R_LINE_TO, -3, -1,
-R_LINE_TO, -1.3f, 4,
-R_H_LINE_TO, 8.7f,
-CLOSE,
-R_MOVE_TO, -9.46f, 2,
-LINE_TO, 3, 12,
-R_H_LINE_TO, 18,
-R_LINE_TO, -3.8f, -2,
-H_LINE_TO, 6.93f,
-CLOSE
diff --git a/chrome/app/vector_icons/incognito.icon b/chrome/app/vector_icons/incognito.icon
index 5ebf9d94..f5c71093e 100644
--- a/chrome/app/vector_icons/incognito.icon
+++ b/chrome/app/vector_icons/incognito.icon
@@ -50,3 +50,51 @@
 LINE_TO, 16.26f, 16,
 R_H_LINE_TO, 15.64f,
 CLOSE
+
+CANVAS_DIMENSIONS, 24,
+MOVE_TO, 11, 17,
+R_CUBIC_TO, 0, 1.66f, -1.34f, 3, -3, 3,
+R_CUBIC_TO, -1.66f, 0, -3, -1.34f, -3, -3,
+R_CUBIC_TO, 0, -1.66f, 1.34f, -3, 3, -3,
+R_CUBIC_TO, 1.66f, 0, 3, 1.34f, 3, 3,
+CLOSE,
+R_MOVE_TO, -3, 2,
+R_CUBIC_TO, 1.11f, 0, 2, -0.89f, 2, -2,
+R_CUBIC_TO, 0, -1.11f, -0.89f, -2, -2, -2,
+R_CUBIC_TO, -1.11f, 0, -2, 0.9f, -2, 2,
+R_CUBIC_TO, 0, 1.1f, 0.9f, 2, 2, 2,
+CLOSE,
+MOVE_TO, 19, 17,
+R_CUBIC_TO, 0, 1.66f, -1.34f, 3, -3, 3,
+R_CUBIC_TO, -1.66f, 0, -3, -1.34f, -3, -3,
+R_CUBIC_TO, 0, -1.66f, 1.34f, -3, 3, -3,
+R_CUBIC_TO, 1.66f, 0, 3, 1.34f, 3, 3,
+CLOSE,
+R_MOVE_TO, -3, -2,
+R_CUBIC_TO, -1.1f, 0, -2, 0.89f, -2, 2,
+R_CUBIC_TO, 0, 1.11f, 0.89f, 2, 2, 2,
+R_CUBIC_TO, 1.11f, 0, 2, -0.89f, 2, -2,
+R_CUBIC_TO, 0, -1.1f, -0.89f, -2, -2, -2,
+CLOSE,
+NEW_PATH,
+MOVE_TO, 12, 17,
+R_CUBIC_TO, 0.93f, 0, 1.71f, 0.64f, 1.93f, 1.5f,
+R_CUBIC_TO, 0.04f, -0.16f, 0.07f, -0.33f, 0.07f, -0.5f,
+R_CUBIC_TO, 0, -1.1f, -0.9f, -2, -2, -2,
+R_CUBIC_TO, -1.1f, 0, -2, 0.9f, -2, 2,
+R_CUBIC_TO, 0, 0.17f, 0.03f, 0.34f, 0.07f, 0.5f,
+R_CUBIC_TO, 0.22f, -0.86f, 1, -1.5f, 1.93f, -1.5f,
+NEW_PATH,
+MOVE_TO, 16.39f, 8,
+LINE_TO, 15, 4,
+R_LINE_TO, -3, 1,
+R_LINE_TO, -3, -1,
+R_LINE_TO, -1.3f, 4,
+R_H_LINE_TO, 8.7f,
+CLOSE,
+R_MOVE_TO, -9.46f, 2,
+LINE_TO, 3, 12,
+R_H_LINE_TO, 18,
+R_LINE_TO, -3.8f, -2,
+H_LINE_TO, 6.93f,
+CLOSE
diff --git a/chrome/app/vector_icons/navigate_home.1x.icon b/chrome/app/vector_icons/navigate_home.1x.icon
deleted file mode 100644
index d140ec70..0000000
--- a/chrome/app/vector_icons/navigate_home.1x.icon
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 3.35f, 7,
-LINE_TO, 8, 2.5f,
-LINE_TO, 12.65f, 7,
-LINE_TO, 12, 7,
-LINE_TO, 12, 14,
-LINE_TO, 4, 14,
-LINE_TO, 4, 7,
-LINE_TO, 3.35f, 7,
-LINE_TO, 3.35f, 7,
-CLOSE,
-MOVE_TO, 2, 8.3f,
-LINE_TO, 1.54f, 8.74f,
-CUBIC_TO, 1.19f, 9.09f, 0.62f, 9.09f, 0.26f, 8.74f,
-CUBIC_TO, -0.09f, 8.4f, -0.09f, 7.85f, 0.26f, 7.51f,
-LINE_TO, 8, 0,
-LINE_TO, 15.74f, 7.51f,
-CUBIC_TO, 16.09f, 7.85f, 16.09f, 8.4f, 15.74f, 8.74f,
-CUBIC_TO, 15.38f, 9.09f, 14.81f, 9.09f, 14.46f, 8.74f,
-LINE_TO, 14, 8.3f,
-LINE_TO, 14, 14.5f,
-CUBIC_TO, 14, 15.5f, 13.5f, 16, 12.5f, 16,
-LINE_TO, 3.5f, 16,
-CUBIC_TO, 2.5f, 16, 2, 15.5f, 2, 14.5f,
-LINE_TO, 2, 8.3f,
-LINE_TO, 2, 8.3f,
-CLOSE
diff --git a/chrome/app/vector_icons/navigate_home.icon b/chrome/app/vector_icons/navigate_home.icon
index 42aa6e0f..91506db 100644
--- a/chrome/app/vector_icons/navigate_home.icon
+++ b/chrome/app/vector_icons/navigate_home.icon
@@ -34,3 +34,31 @@
 LINE_TO, 6, 17.39f,
 LINE_TO, 6, 17.39f,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 3.35f, 7,
+LINE_TO, 8, 2.5f,
+LINE_TO, 12.65f, 7,
+LINE_TO, 12, 7,
+LINE_TO, 12, 14,
+LINE_TO, 4, 14,
+LINE_TO, 4, 7,
+LINE_TO, 3.35f, 7,
+LINE_TO, 3.35f, 7,
+CLOSE,
+MOVE_TO, 2, 8.3f,
+LINE_TO, 1.54f, 8.74f,
+CUBIC_TO, 1.19f, 9.09f, 0.62f, 9.09f, 0.26f, 8.74f,
+CUBIC_TO, -0.09f, 8.4f, -0.09f, 7.85f, 0.26f, 7.51f,
+LINE_TO, 8, 0,
+LINE_TO, 15.74f, 7.51f,
+CUBIC_TO, 16.09f, 7.85f, 16.09f, 8.4f, 15.74f, 8.74f,
+CUBIC_TO, 15.38f, 9.09f, 14.81f, 9.09f, 14.46f, 8.74f,
+LINE_TO, 14, 8.3f,
+LINE_TO, 14, 14.5f,
+CUBIC_TO, 14, 15.5f, 13.5f, 16, 12.5f, 16,
+LINE_TO, 3.5f, 16,
+CUBIC_TO, 2.5f, 16, 2, 15.5f, 2, 14.5f,
+LINE_TO, 2, 8.3f,
+LINE_TO, 2, 8.3f,
+CLOSE
diff --git a/chrome/app/vector_icons/navigate_stop.1x.icon b/chrome/app/vector_icons/navigate_stop.1x.icon
deleted file mode 100644
index 7e86af5..0000000
--- a/chrome/app/vector_icons/navigate_stop.1x.icon
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 8, 9.19f,
-LINE_TO, 3.43f, 13.75f,
-CUBIC_TO, 3.1f, 14.08f, 2.57f, 14.08f, 2.25f, 13.75f,
-CUBIC_TO, 1.92f, 13.43f, 1.92f, 12.9f, 2.25f, 12.57f,
-LINE_TO, 6.81f, 8,
-LINE_TO, 2.25f, 3.43f,
-CUBIC_TO, 1.92f, 3.1f, 1.92f, 2.57f, 2.25f, 2.25f,
-CUBIC_TO, 2.57f, 1.92f, 3.1f, 1.92f, 3.43f, 2.25f,
-LINE_TO, 8, 6.81f,
-LINE_TO, 12.57f, 2.25f,
-CUBIC_TO, 12.9f, 1.92f, 13.43f, 1.92f, 13.75f, 2.25f,
-CUBIC_TO, 14.08f, 2.57f, 14.08f, 3.1f, 13.75f, 3.43f,
-LINE_TO, 9.19f, 8,
-LINE_TO, 13.75f, 12.57f,
-CUBIC_TO, 14.08f, 12.9f, 14.08f, 13.43f, 13.75f, 13.75f,
-CUBIC_TO, 13.43f, 14.08f, 12.9f, 14.08f, 12.57f, 13.75f,
-CLOSE
diff --git a/chrome/app/vector_icons/navigate_stop.icon b/chrome/app/vector_icons/navigate_stop.icon
index a8bcead..0dcb9b76 100644
--- a/chrome/app/vector_icons/navigate_stop.icon
+++ b/chrome/app/vector_icons/navigate_stop.icon
@@ -20,3 +20,22 @@
 CUBIC_TO, 28.16f, 25.79f, 28.16f, 26.85f, 27.51f, 27.51f,
 CUBIC_TO, 26.85f, 28.16f, 25.79f, 28.16f, 25.14f, 27.51f,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 8, 9.19f,
+LINE_TO, 3.43f, 13.75f,
+CUBIC_TO, 3.1f, 14.08f, 2.57f, 14.08f, 2.25f, 13.75f,
+CUBIC_TO, 1.92f, 13.43f, 1.92f, 12.9f, 2.25f, 12.57f,
+LINE_TO, 6.81f, 8,
+LINE_TO, 2.25f, 3.43f,
+CUBIC_TO, 1.92f, 3.1f, 1.92f, 2.57f, 2.25f, 2.25f,
+CUBIC_TO, 2.57f, 1.92f, 3.1f, 1.92f, 3.43f, 2.25f,
+LINE_TO, 8, 6.81f,
+LINE_TO, 12.57f, 2.25f,
+CUBIC_TO, 12.9f, 1.92f, 13.43f, 1.92f, 13.75f, 2.25f,
+CUBIC_TO, 14.08f, 2.57f, 14.08f, 3.1f, 13.75f, 3.43f,
+LINE_TO, 9.19f, 8,
+LINE_TO, 13.75f, 12.57f,
+CUBIC_TO, 14.08f, 12.9f, 14.08f, 13.43f, 13.75f, 13.75f,
+CUBIC_TO, 13.43f, 14.08f, 12.9f, 14.08f, 12.57f, 13.75f,
+CLOSE
diff --git a/chrome/app/vector_icons/overflow_chevron.1x.icon b/chrome/app/vector_icons/overflow_chevron.1x.icon
deleted file mode 100644
index a0b8ef1..0000000
--- a/chrome/app/vector_icons/overflow_chevron.1x.icon
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 8,
-MOVE_TO, 1.41f, 1.23f,
-CUBIC_TO, 1.09f, 0.92f, 0.57f, 0.92f, 0.24f, 1.23f,
-CUBIC_TO, -0.08f, 1.54f, -0.08f, 2.03f, 0.24f, 2.34f,
-LINE_TO, 2, 4,
-LINE_TO, 0.24f, 5.66f,
-CUBIC_TO, -0.08f, 5.97f, -0.08f, 6.46f, 0.24f, 6.77f,
-CUBIC_TO, 0.57f, 7.08f, 1.09f, 7.08f, 1.41f, 6.77f,
-LINE_TO, 3.76f, 4.55f,
-CUBIC_TO, 4.08f, 4.25f, 4.08f, 3.75f, 3.76f, 3.45f,
-LINE_TO, 1.41f, 1.23f,
-CLOSE,
-MOVE_TO, 5.41f, 1.23f,
-CUBIC_TO, 5.09f, 0.92f, 4.57f, 0.92f, 4.24f, 1.23f,
-CUBIC_TO, 3.92f, 1.54f, 3.92f, 2.03f, 4.24f, 2.34f,
-LINE_TO, 6, 4,
-LINE_TO, 4.24f, 5.66f,
-CUBIC_TO, 3.92f, 5.97f, 3.92f, 6.46f, 4.24f, 6.77f,
-CUBIC_TO, 4.57f, 7.08f, 5.09f, 7.08f, 5.41f, 6.77f,
-LINE_TO, 7.76f, 4.55f,
-CUBIC_TO, 8.08f, 4.25f, 8.08f, 3.75f, 7.76f, 3.45f,
-LINE_TO, 5.41f, 1.23f,
-CLOSE
diff --git a/chrome/app/vector_icons/overflow_chevron.icon b/chrome/app/vector_icons/overflow_chevron.icon
index 542ec32..8365052 100644
--- a/chrome/app/vector_icons/overflow_chevron.icon
+++ b/chrome/app/vector_icons/overflow_chevron.icon
@@ -25,3 +25,27 @@
 CUBIC_TO, 14.12f, 7.95f, 14.12f, 7.05f, 13.64f, 6.48f,
 LINE_TO, 10.12f, 2.42f,
 CLOSE
+
+CANVAS_DIMENSIONS, 8,
+MOVE_TO, 1.41f, 1.23f,
+CUBIC_TO, 1.09f, 0.92f, 0.57f, 0.92f, 0.24f, 1.23f,
+CUBIC_TO, -0.08f, 1.54f, -0.08f, 2.03f, 0.24f, 2.34f,
+LINE_TO, 2, 4,
+LINE_TO, 0.24f, 5.66f,
+CUBIC_TO, -0.08f, 5.97f, -0.08f, 6.46f, 0.24f, 6.77f,
+CUBIC_TO, 0.57f, 7.08f, 1.09f, 7.08f, 1.41f, 6.77f,
+LINE_TO, 3.76f, 4.55f,
+CUBIC_TO, 4.08f, 4.25f, 4.08f, 3.75f, 3.76f, 3.45f,
+LINE_TO, 1.41f, 1.23f,
+CLOSE,
+MOVE_TO, 5.41f, 1.23f,
+CUBIC_TO, 5.09f, 0.92f, 4.57f, 0.92f, 4.24f, 1.23f,
+CUBIC_TO, 3.92f, 1.54f, 3.92f, 2.03f, 4.24f, 2.34f,
+LINE_TO, 6, 4,
+LINE_TO, 4.24f, 5.66f,
+CUBIC_TO, 3.92f, 5.97f, 3.92f, 6.46f, 4.24f, 6.77f,
+CUBIC_TO, 4.57f, 7.08f, 5.09f, 7.08f, 5.41f, 6.77f,
+LINE_TO, 7.76f, 4.55f,
+CUBIC_TO, 8.08f, 4.25f, 8.08f, 3.75f, 7.76f, 3.45f,
+LINE_TO, 5.41f, 1.23f,
+CLOSE
diff --git a/chrome/app/vector_icons/tab_audio.1x.icon b/chrome/app/vector_icons/tab_audio.1x.icon
deleted file mode 100644
index f2689701..0000000
--- a/chrome/app/vector_icons/tab_audio.1x.icon
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 16,
-DISABLE_AA,
-MOVE_TO, 9, 2,
-R_V_LINE_TO, 11,
-R_LINE_TO, -4, -4,
-R_H_LINE_TO, -1,
-R_V_LINE_TO, -3,
-R_H_LINE_TO, 1,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-MOVE_TO, 10.5f, 6,
-R_V_LINE_TO, 3,
-MOVE_TO, 12.5f, 5,
-R_V_LINE_TO, 5
diff --git a/chrome/app/vector_icons/tab_audio.icon b/chrome/app/vector_icons/tab_audio.icon
index 1ed5205e..04975d4 100644
--- a/chrome/app/vector_icons/tab_audio.icon
+++ b/chrome/app/vector_icons/tab_audio.icon
@@ -20,3 +20,19 @@
 R_H_LINE_TO, 2,
 R_V_LINE_TO, -10,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+DISABLE_AA,
+MOVE_TO, 9, 2,
+R_V_LINE_TO, 11,
+R_LINE_TO, -4, -4,
+R_H_LINE_TO, -1,
+R_V_LINE_TO, -3,
+R_H_LINE_TO, 1,
+CLOSE,
+NEW_PATH,
+STROKE, 1,
+MOVE_TO, 10.5f, 6,
+R_V_LINE_TO, 3,
+MOVE_TO, 12.5f, 5,
+R_V_LINE_TO, 5
diff --git a/chrome/app/vector_icons/tab_audio_muting.1x.icon b/chrome/app/vector_icons/tab_audio_muting.1x.icon
deleted file mode 100644
index b81d3044..0000000
--- a/chrome/app/vector_icons/tab_audio_muting.1x.icon
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 16,
-DISABLE_AA,
-MOVE_TO, 3, 2,
-R_LINE_TO, 10, 10,
-R_V_LINE_TO, 2,
-R_LINE_TO, -4, -4,
-R_V_LINE_TO, 3,
-R_LINE_TO, -4, -4,
-R_H_LINE_TO, -1,
-R_V_LINE_TO, -3,
-R_H_LINE_TO, 1,
-R_LINE_TO, -3, -3,
-CLOSE,
-NEW_PATH,
-STROKE, 1,
-MOVE_TO, 8.5f, 3,
-R_V_LINE_TO, 2.5f,
-MOVE_TO, 10.5f, 6,
-R_V_LINE_TO, 1.5f,
-MOVE_TO, 12.5f, 5,
-R_V_LINE_TO, 4.5f
diff --git a/chrome/app/vector_icons/tab_audio_muting.icon b/chrome/app/vector_icons/tab_audio_muting.icon
index 166a98b..fb8c844 100644
--- a/chrome/app/vector_icons/tab_audio_muting.icon
+++ b/chrome/app/vector_icons/tab_audio_muting.icon
@@ -29,3 +29,25 @@
 R_V_LINE_TO, -9,
 R_H_LINE_TO, -2,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+DISABLE_AA,
+MOVE_TO, 3, 2,
+R_LINE_TO, 10, 10,
+R_V_LINE_TO, 2,
+R_LINE_TO, -4, -4,
+R_V_LINE_TO, 3,
+R_LINE_TO, -4, -4,
+R_H_LINE_TO, -1,
+R_V_LINE_TO, -3,
+R_H_LINE_TO, 1,
+R_LINE_TO, -3, -3,
+CLOSE,
+NEW_PATH,
+STROKE, 1,
+MOVE_TO, 8.5f, 3,
+R_V_LINE_TO, 2.5f,
+MOVE_TO, 10.5f, 6,
+R_V_LINE_TO, 1.5f,
+MOVE_TO, 12.5f, 5,
+R_V_LINE_TO, 4.5f
diff --git a/chrome/app/vector_icons/tab_close_hovered_pressed.1x.icon b/chrome/app/vector_icons/tab_close_hovered_pressed.1x.icon
deleted file mode 100644
index 1673116..0000000
--- a/chrome/app/vector_icons/tab_close_hovered_pressed.1x.icon
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// The close "X" for a tab when hovered/pressed, optimized for 1x scale factor
-// devices.
-CANVAS_DIMENSIONS, 16,
-CIRCLE, 8, 8, 7.05f,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0xFF, 0xFF, 0xFF,
-STROKE, 1.415f,
-MOVE_TO, 4.75f, 4.75f,
-R_LINE_TO, 6.5f, 6.5f,
-MOVE_TO, 4.75f, 11.25f,
-R_LINE_TO, 6.5f, -6.5f
diff --git a/chrome/app/vector_icons/tab_close_hovered_pressed.icon b/chrome/app/vector_icons/tab_close_hovered_pressed.icon
index f8b979e2..9c0216f 100644
--- a/chrome/app/vector_icons/tab_close_hovered_pressed.icon
+++ b/chrome/app/vector_icons/tab_close_hovered_pressed.icon
@@ -12,3 +12,15 @@
 R_LINE_TO, 11.5f, 11.5f,
 MOVE_TO, 10.25f, 21.75f,
 R_LINE_TO, 11.5f, -11.5f
+
+// The close "X" for a tab when hovered/pressed, optimized for 1x scale factor
+// devices.
+CANVAS_DIMENSIONS, 16,
+CIRCLE, 8, 8, 7.05f,
+NEW_PATH,
+PATH_COLOR_ARGB, 0xFF, 0xFF, 0xFF, 0xFF,
+STROKE, 1.415f,
+MOVE_TO, 4.75f, 4.75f,
+R_LINE_TO, 6.5f, 6.5f,
+MOVE_TO, 4.75f, 11.25f,
+R_LINE_TO, 6.5f, -6.5f
diff --git a/chrome/app/vector_icons/tab_close_normal.1x.icon b/chrome/app/vector_icons/tab_close_normal.1x.icon
deleted file mode 100644
index 9df4bd8..0000000
--- a/chrome/app/vector_icons/tab_close_normal.1x.icon
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// The close "X" for a tab when not hovered/pressed, optimized for 1x scale
-// factor devices.
-CANVAS_DIMENSIONS, 16,
-STROKE, 1.415f,
-MOVE_TO, 4.75f, 4.75f,
-R_LINE_TO, 6.5f, 6.5f,
-MOVE_TO, 4.75f, 11.25f,
-R_LINE_TO, 6.5f, -6.5f
diff --git a/chrome/app/vector_icons/tab_close_normal.icon b/chrome/app/vector_icons/tab_close_normal.icon
index fe6a968..c56b8c3 100644
--- a/chrome/app/vector_icons/tab_close_normal.icon
+++ b/chrome/app/vector_icons/tab_close_normal.icon
@@ -9,3 +9,12 @@
 R_LINE_TO, 11.5f, 11.5f,
 MOVE_TO, 10.25f, 21.75f,
 R_LINE_TO, 11.5f, -11.5f
+
+// The close "X" for a tab when not hovered/pressed, optimized for 1x scale
+// factor devices.
+CANVAS_DIMENSIONS, 16,
+STROKE, 1.415f,
+MOVE_TO, 4.75f, 4.75f,
+R_LINE_TO, 6.5f, 6.5f,
+MOVE_TO, 4.75f, 11.25f,
+R_LINE_TO, 6.5f, -6.5f
diff --git a/chrome/app/vector_icons/tab_usb_connected.1x.icon b/chrome/app/vector_icons/tab_usb_connected.1x.icon
deleted file mode 100644
index dcf4c40..0000000
--- a/chrome/app/vector_icons/tab_usb_connected.1x.icon
+++ /dev/null
@@ -1,37 +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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 10, 8,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 1,
-H_LINE_TO, 9,
-V_LINE_TO, 5,
-R_H_LINE_TO, 1,
-LINE_TO, 8.5f, 3,
-LINE_TO, 7, 5,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 4,
-H_LINE_TO, 7,
-V_LINE_TO, 8,
-R_CUBIC_TO, -0.08f, -0.04f, 0, -0.5f, 0, -1,
-R_CUBIC_TO, 0, -0.5f, -0.5f, -1, -1, -1,
-R_CUBIC_TO, -0.5f, 0, -1, 0.5f, -1, 1,
-R_CUBIC_TO, 0, 0.5f, 0.25f, 0.96f, 1, 1,
-R_V_LINE_TO, 1,
-R_CUBIC_TO, 0, 0.5f, 0.5f, 1, 1, 1,
-R_H_LINE_TO, 1,
-R_V_LINE_TO, 2,
-R_LINE_TO, -1, 1,
-R_LINE_TO, 1, 1,
-R_H_LINE_TO, 1,
-R_LINE_TO, 1, -1,
-R_LINE_TO, -1, -1,
-R_V_LINE_TO, -2,
-R_H_LINE_TO, 2,
-R_CUBIC_TO, 0.5f, 0, 1, -0.5f, 1, -1,
-V_LINE_TO, 6,
-R_H_LINE_TO, -2,
-R_V_LINE_TO, 2,
-CLOSE
diff --git a/chrome/app/vector_icons/tab_usb_connected.icon b/chrome/app/vector_icons/tab_usb_connected.icon
index 19978a3..96d27efa 100644
--- a/chrome/app/vector_icons/tab_usb_connected.icon
+++ b/chrome/app/vector_icons/tab_usb_connected.icon
@@ -36,3 +36,37 @@
 R_H_LINE_TO, -4,
 R_V_LINE_TO, 4,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 10, 8,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 1,
+H_LINE_TO, 9,
+V_LINE_TO, 5,
+R_H_LINE_TO, 1,
+LINE_TO, 8.5f, 3,
+LINE_TO, 7, 5,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 4,
+H_LINE_TO, 7,
+V_LINE_TO, 8,
+R_CUBIC_TO, -0.08f, -0.04f, 0, -0.5f, 0, -1,
+R_CUBIC_TO, 0, -0.5f, -0.5f, -1, -1, -1,
+R_CUBIC_TO, -0.5f, 0, -1, 0.5f, -1, 1,
+R_CUBIC_TO, 0, 0.5f, 0.25f, 0.96f, 1, 1,
+R_V_LINE_TO, 1,
+R_CUBIC_TO, 0, 0.5f, 0.5f, 1, 1, 1,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 2,
+R_LINE_TO, -1, 1,
+R_LINE_TO, 1, 1,
+R_H_LINE_TO, 1,
+R_LINE_TO, 1, -1,
+R_LINE_TO, -1, -1,
+R_V_LINE_TO, -2,
+R_H_LINE_TO, 2,
+R_CUBIC_TO, 0.5f, 0, 1, -0.5f, 1, -1,
+V_LINE_TO, 6,
+R_H_LINE_TO, -2,
+R_V_LINE_TO, 2,
+CLOSE
diff --git a/chrome/app/vector_icons/warning_badge_circle.1x.icon b/chrome/app/vector_icons/warning_badge_circle.1x.icon
deleted file mode 100644
index ae8b2b3..0000000
--- a/chrome/app/vector_icons/warning_badge_circle.1x.icon
+++ /dev/null
@@ -1,22 +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.
-
-CANVAS_DIMENSIONS, 40,
-MOVE_TO, 32.93f, 26,
-CUBIC_TO, 29.11f, 26, 26, 29.11f, 26, 32.95f,
-R_CUBIC_TO, 0, 3.83f, 3.11f, 6.95f, 6.93f, 6.95f,
-R_CUBIC_TO, 3.83f, 0, 6.93f, -3.11f, 6.93f, -6.94f,
-CUBIC_TO_SHORTHAND, 36.76f, 26, 32.93f, 26,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0xFF, 0xFF, 0xFF,
-MOVE_TO, 33.5f, 36.04f,
-H_LINE_TO, 32,
-V_LINE_TO, 34.5f,
-R_H_LINE_TO, 1.5f,
-MOVE_TO, 33.5f, 33.5f,
-H_LINE_TO, 32,
-V_LINE_TO, 30,
-R_H_LINE_TO, 1.5f,
-CLOSE
diff --git a/chrome/app/vector_icons/warning_badge_circle.icon b/chrome/app/vector_icons/warning_badge_circle.icon
index c1d9f7e..65410521 100644
--- a/chrome/app/vector_icons/warning_badge_circle.icon
+++ b/chrome/app/vector_icons/warning_badge_circle.icon
@@ -20,3 +20,22 @@
 R_V_LINE_TO, -7,
 R_H_LINE_TO, 3,
 CLOSE
+
+CANVAS_DIMENSIONS, 40,
+MOVE_TO, 32.93f, 26,
+CUBIC_TO, 29.11f, 26, 26, 29.11f, 26, 32.95f,
+R_CUBIC_TO, 0, 3.83f, 3.11f, 6.95f, 6.93f, 6.95f,
+R_CUBIC_TO, 3.83f, 0, 6.93f, -3.11f, 6.93f, -6.94f,
+CUBIC_TO_SHORTHAND, 36.76f, 26, 32.93f, 26,
+CLOSE,
+NEW_PATH,
+PATH_COLOR_ARGB, 0xFF, 0xFF, 0xFF, 0xFF,
+MOVE_TO, 33.5f, 36.04f,
+H_LINE_TO, 32,
+V_LINE_TO, 34.5f,
+R_H_LINE_TO, 1.5f,
+MOVE_TO, 33.5f, 33.5f,
+H_LINE_TO, 32,
+V_LINE_TO, 30,
+R_H_LINE_TO, 1.5f,
+CLOSE
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index ad051b1a..d7d163b 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1008,6 +1008,9 @@
     "plugins/pdf_iframe_navigation_throttle.h",
     "plugins/pdf_plugin_placeholder_observer.cc",
     "plugins/pdf_plugin_placeholder_observer.h",
+    "policy/browser_dm_token_storage.h",
+    "policy/browser_dm_token_storage_win.cc",
+    "policy/browser_dm_token_storage_win.h",
     "policy/chrome_browser_policy_connector.cc",
     "policy/chrome_browser_policy_connector.h",
     "policy/cloud/cloud_policy_invalidator.cc",
@@ -1753,11 +1756,11 @@
     "//google_apis",
     "//gpu/config",
     "//media",
-    "//media:media_features",
+    "//media:media_buildflags",
     "//media/capture",
     "//media/cast:net",
     "//media/midi",
-    "//media/mojo:features",
+    "//media/mojo:buildflags",
     "//media/mojo/common",
     "//media/mojo/interfaces:mirror_service_remoting",
     "//media/mojo/interfaces:remoting",
@@ -1910,6 +1913,8 @@
       "android/compositor/tab_content_manager.h",
       "android/consent_auditor/consent_auditor_bridge.cc",
       "android/content/content_utils.cc",
+      "android/contextual_suggestions/contextual_suggestions_bridge.cc",
+      "android/contextual_suggestions/contextual_suggestions_bridge.h",
       "android/contextualsearch/contextual_search_context.cc",
       "android/contextualsearch/contextual_search_context.h",
       "android/contextualsearch/contextual_search_delegate.cc",
@@ -2963,6 +2968,8 @@
   } else {
     # Non-Windows.
     sources += [
+      "policy/browser_dm_token_storage_stub.cc",
+      "policy/browser_dm_token_storage_stub.h",
       "profile_resetter/triggered_profile_resetter_stub.cc",
       "profiles/profile_shortcut_manager_stub.cc",
     ]
@@ -2993,12 +3000,6 @@
       "QuartzCore.framework",
       "SecurityInterface.framework",
     ]
-
-    if (mac_views_browser) {
-      sources += [ "global_keyboard_shortcuts_views_mac.mm" ]
-    } else {
-      sources += [ "global_keyboard_shortcuts_cocoa_mac.mm" ]
-    }
   }
 
   if (is_linux) {
@@ -3856,7 +3857,7 @@
     ]
     deps += [
       "//components/pdf/browser",
-      "//media:media_features",
+      "//media:media_buildflags",
       "//ppapi/features",
       "//ppapi/proxy:ipc",
       "//services/device/public/mojom",
@@ -4235,6 +4236,7 @@
       "../android/java/src/org/chromium/chrome/browser/content/ContentUtils.java",
       "../android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuHelper.java",
       "../android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuParams.java",
+      "../android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsBridge.java",
       "../android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchContext.java",
       "../android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java",
       "../android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRankerLoggerImpl.java",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 0f53056..9fa5f83 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -73,6 +73,7 @@
 #include "components/payments/core/features.h"
 #include "components/previews/core/previews_features.h"
 #include "components/previews/core/previews_switches.h"
+#include "components/printing/browser/features.h"
 #include "components/proximity_auth/switches.h"
 #include "components/search_provider_logos/features.h"
 #include "components/search_provider_logos/switches.h"
@@ -104,7 +105,7 @@
 #include "gpu/config/gpu_switches.h"
 #include "media/audio/audio_features.h"
 #include "media/base/media_switches.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "media/midi/midi_switches.h"
 #include "net/cert/cert_verify_proc_android.h"
 #include "net/nqe/effective_connection_type.h"
@@ -778,23 +779,26 @@
 const FeatureEntry::Choice kForceEffectiveConnectionTypeChoices[] = {
     {flags_ui::kGenericExperimentChoiceDefault, "", ""},
     {flag_descriptions::kEffectiveConnectionTypeUnknownDescription,
-     switches::kForceEffectiveConnectionType,
+     network::switches::kForceEffectiveConnectionType,
      net::kEffectiveConnectionTypeUnknown},
     {flag_descriptions::kEffectiveConnectionTypeOfflineDescription,
-     switches::kForceEffectiveConnectionType,
+     network::switches::kForceEffectiveConnectionType,
      net::kEffectiveConnectionTypeOffline},
     {flag_descriptions::kEffectiveConnectionTypeSlow2GDescription,
-     switches::kForceEffectiveConnectionType,
+     network::switches::kForceEffectiveConnectionType,
      net::kEffectiveConnectionTypeSlow2G},
     {flag_descriptions::kEffectiveConnectionTypeSlow2GOnCellularDescription,
-     switches::kForceEffectiveConnectionType,
+     network::switches::kForceEffectiveConnectionType,
      net::kEffectiveConnectionTypeSlow2GOnCellular},
     {flag_descriptions::kEffectiveConnectionType2GDescription,
-     switches::kForceEffectiveConnectionType, net::kEffectiveConnectionType2G},
+     network::switches::kForceEffectiveConnectionType,
+     net::kEffectiveConnectionType2G},
     {flag_descriptions::kEffectiveConnectionType3GDescription,
-     switches::kForceEffectiveConnectionType, net::kEffectiveConnectionType3G},
+     network::switches::kForceEffectiveConnectionType,
+     net::kEffectiveConnectionType3G},
     {flag_descriptions::kEffectiveConnectionType4GDescription,
-     switches::kForceEffectiveConnectionType, net::kEffectiveConnectionType4G},
+     network::switches::kForceEffectiveConnectionType,
+     net::kEffectiveConnectionType4G},
 };
 
 // Ensure that all effective connection types returned by Network Quality
@@ -1548,6 +1552,9 @@
     {"mash", flag_descriptions::kUseMashName,
      flag_descriptions::kUseMashDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(features::kMash)},
+    {"newblue", flag_descriptions::kNewblueName,
+     flag_descriptions::kNewblueDescription, kOsCrOS,
+     FEATURE_VALUE_TYPE(device::kNewblueDaemon)},
     {"show-taps", flag_descriptions::kShowTapsName,
      flag_descriptions::kShowTapsDescription, kOsCrOS,
      SINGLE_VALUE_TYPE(ash::switches::kShowTaps)},
@@ -2193,6 +2200,9 @@
      flag_descriptions::kAppWindowCyclingDescription, kOsMac,
      ENABLE_DISABLE_VALUE_TYPE(switches::kEnableAppWindowCycling,
                                switches::kDisableAppWindowCycling)},
+    {"views-browser-windows", flag_descriptions::kViewsBrowserWindowsName,
+     flag_descriptions::kViewsBrowserWindowsDescription, kOsMac,
+     FEATURE_VALUE_TYPE(features::kViewsBrowserWindows)},
 #endif  // OS_MACOSX
     {"enable-gamepad-extensions", flag_descriptions::kGamepadExtensionsName,
      flag_descriptions::kGamepadExtensionsDescription, kOsAll,
@@ -2217,10 +2227,6 @@
      FEATURE_WITH_PARAMS_VALUE_TYPE(features::kWebXrRenderPath,
                                     kWebXrRenderPathVariations,
                                     "WebXrRenderPath")},
-    // TODO(crbug.com/731802): Use #if BUILDFLAG(ENABLE_VR_BROWSING) instead.
-    {"vr-browsing", flag_descriptions::kVrBrowsingName,
-     flag_descriptions::kVrBrowsingDescription, kOsAndroid,
-     FEATURE_VALUE_TYPE(features::kVrBrowsing)},
     {"vr-browser-keyboard", flag_descriptions::kVrBrowserKeyboardName,
      flag_descriptions::kVrBrowserKeyboardDescription, kOsAndroid,
      FEATURE_VALUE_TYPE(features::kVrBrowserKeyboard)},
@@ -2334,6 +2340,12 @@
      flag_descriptions::kOfflinePagesRenovationsName,
      flag_descriptions::kOfflinePagesRenovationsDescription, kOsAndroid,
      FEATURE_VALUE_TYPE(offline_pages::kOfflinePagesRenovationsFeature)},
+    {"offline-pages-in-downloads-home-open-in-cct",
+     flag_descriptions::kOfflinePagesInDownloadHomeOpenInCctName,
+     flag_descriptions::kOfflinePagesInDownloadHomeOpenInCctDescription,
+     kOsAndroid,
+     FEATURE_VALUE_TYPE(
+         offline_pages::kOfflinePagesInDownloadHomeOpenInCctFeature)},
 #endif  // OS_ANDROID
     {"disallow-doc-written-script-loads",
      flag_descriptions::kDisallowDocWrittenScriptsUiName,
@@ -2902,6 +2914,10 @@
      flag_descriptions::kEnableAutofillCreditCardAblationExperimentDescription,
      kOsAll,
      FEATURE_VALUE_TYPE(autofill::kAutofillCreditCardAblationExperiment)},
+    {"enable-autofill-credit-card-bank-name-display",
+     flag_descriptions::kEnableAutofillCreditCardBankNameDisplayName,
+     flag_descriptions::kEnableAutofillCreditCardBankNameDisplayDescription,
+     kOsAll, FEATURE_VALUE_TYPE(autofill::kAutofillCreditCardBankNameDisplay)},
     {"enable-autofill-credit-card-last-used-date-display",
      flag_descriptions::kEnableAutofillCreditCardLastUsedDateDisplayName,
      flag_descriptions::kEnableAutofillCreditCardLastUsedDateDisplayDescription,
@@ -3412,11 +3428,11 @@
      flag_descriptions::kSoundContentSettingDescription, kOsAll,
      FEATURE_VALUE_TYPE(features::kSoundContentSetting)},
 
-#if DCHECK_IS_ON() && defined(SYZYASAN)
-    {"dcheck-is-fatal", flag_descriptions::kSyzyAsanDcheckIsFatalName,
-     flag_descriptions::kSyzyAsanDcheckIsFatalDescription, kOsWin,
-     FEATURE_VALUE_TYPE(base::kSyzyAsanDCheckIsFatalFeature)},
-#endif  // DCHECK_IS_ON() && defined(SYZYASAN)
+#if DCHECK_IS_CONFIGURABLE
+    {"dcheck-is-fatal", flag_descriptions::kDcheckIsFatalName,
+     flag_descriptions::kDcheckIsFatalDescription, kOsWin,
+     FEATURE_VALUE_TYPE(base::kDCheckIsFatalFeature)},
+#endif  // DCHECK_IS_CONFIGURABLE
 
 #if defined(OS_CHROMEOS)
     {"sys-internals", flag_descriptions::kSysInternalsName,
@@ -3725,6 +3741,11 @@
      flag_descriptions::kPdfIsolationDescription, kOsDesktop,
      FEATURE_VALUE_TYPE(features::kPdfIsolation)},
 
+    {"use-pdf-compositor-service-for-print",
+     flag_descriptions::kUsePdfCompositorServiceName,
+     flag_descriptions::kUsePdfCompositorServiceDescription, kOsDesktop,
+     FEATURE_VALUE_TYPE(printing::features::kUsePdfCompositorServiceForPrint)},
+
     // NOTE: Adding a new flag requires adding a corresponding entry to enum
     // "LoginCustomFlags" in tools/metrics/histograms/enums.xml. See "Flag
     // Histograms" in tools/metrics/histograms/README.md (run the
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc
index 128296b..8f9976a5 100644
--- a/chrome/browser/android/chrome_feature_list.cc
+++ b/chrome/browser/android/chrome_feature_list.cc
@@ -19,6 +19,7 @@
 #include "components/ntp_snippets/features.h"
 #include "components/ntp_tiles/constants.h"
 #include "components/offline_pages/core/offline_page_feature.h"
+#include "components/omnibox/browser/omnibox_field_trial.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 #include "components/payments/core/features.h"
 #include "components/safe_browsing/features.h"
@@ -54,7 +55,6 @@
     &features::kSimplifiedFullscreenUI,
     &features::kSoundContentSetting,
     &features::kUnifiedConsent,
-    &features::kVrBrowsing,
     &features::kWebPayments,
     &feed::kInterestFeedContentSuggestions,
     &kAdjustWebApkInstallationSpace,
@@ -142,6 +142,7 @@
     &offline_pages::kOfflinePagesCTV2Feature,  // See crbug.com/734753.
     &offline_pages::kOfflinePagesDescriptivePendingStatusFeature,
     &offline_pages::kOfflinePagesSharingFeature,
+    &omnibox::kUIExperimentHideSteadyStateUrlSchemeAndSubdomains,
     &password_manager::features::kPasswordExport,
     &password_manager::features::kPasswordSearchMobile,
     &subresource_filter::kSafeBrowsingSubresourceFilterExperimentalUI,
diff --git a/chrome/browser/android/contextual_suggestions/DEPS b/chrome/browser/android/contextual_suggestions/DEPS
new file mode 100644
index 0000000..8d770a02
--- /dev/null
+++ b/chrome/browser/android/contextual_suggestions/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+components/ntp_snippets/contextual",
+]
diff --git a/chrome/browser/android/contextual_suggestions/OWNERS b/chrome/browser/android/contextual_suggestions/OWNERS
new file mode 100644
index 0000000..5c3a603
--- /dev/null
+++ b/chrome/browser/android/contextual_suggestions/OWNERS
@@ -0,0 +1,4 @@
+fgorski@chromium.org
+twellington@chromium.org
+
+# COMPONENT: UI>Browser>ContentSuggestions>Explore
diff --git a/chrome/browser/android/contextual_suggestions/contextual_suggestions_bridge.cc b/chrome/browser/android/contextual_suggestions/contextual_suggestions_bridge.cc
new file mode 100644
index 0000000..a65285f1
--- /dev/null
+++ b/chrome/browser/android/contextual_suggestions/contextual_suggestions_bridge.cc
@@ -0,0 +1,95 @@
+// Copyright 2018 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/android/contextual_suggestions/contextual_suggestions_bridge.h"
+
+#include "base/android/jni_string.h"
+#include "chrome/browser/ntp_snippets/contextual_content_suggestions_service_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_android.h"
+#include "jni/ContextualSuggestionsBridge_jni.h"
+
+using base::android::AttachCurrentThread;
+using base::android::ConvertUTF16ToJavaString;
+using base::android::ConvertUTF8ToJavaString;
+using base::android::JavaParamRef;
+using base::android::ScopedJavaLocalRef;
+using Cluster = ntp_snippets::ContextualContentSuggestionsService::Cluster;
+
+namespace contextual_suggestions {
+
+static jlong JNI_ContextualSuggestionsBridge_Init(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& j_bridge,
+    const JavaParamRef<jobject>& j_profile) {
+  ContextualSuggestionsBridge* contextual_suggestions_bridge =
+      new ContextualSuggestionsBridge(env, j_bridge, j_profile);
+  return reinterpret_cast<intptr_t>(contextual_suggestions_bridge);
+}
+
+ContextualSuggestionsBridge::ContextualSuggestionsBridge(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& j_bridge,
+    const JavaParamRef<jobject>& j_profile)
+    : bridge_(env, j_bridge), weak_ptr_factory_(this) {
+  Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile);
+  contextual_content_suggestions_service_ =
+      ContextualContentSuggestionsServiceFactory::GetForProfile(profile);
+}
+
+ContextualSuggestionsBridge::~ContextualSuggestionsBridge() {}
+
+void ContextualSuggestionsBridge::Destroy(JNIEnv* env,
+                                          const JavaParamRef<jobject>& obj) {
+  delete this;
+}
+
+void ContextualSuggestionsBridge::FetchSuggestionImage(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jstring>& j_suggestion_id,
+    const JavaParamRef<jobject>& j_callback) {}
+
+void ContextualSuggestionsBridge::FetchSuggestionFavicon(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    const JavaParamRef<jstring>& j_suggestion_id,
+    const JavaParamRef<jobject>& j_callback) {}
+
+void ContextualSuggestionsBridge::ReportEvent(JNIEnv* env,
+                                              const JavaParamRef<jobject>& obj,
+                                              jint j_event_id) {}
+
+void ContextualSuggestionsBridge::OnSuggestionsAvailable(
+    std::vector<Cluster> clusters) {
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jobject> j_clusters =
+      Java_ContextualSuggestionsBridge_createContextualSuggestionsClusterList(
+          env);
+  for (auto& cluster : clusters) {
+    Java_ContextualSuggestionsBridge_addNewClusterToList(
+        env, j_clusters, ConvertUTF8ToJavaString(env, cluster.title));
+    for (auto& suggestion : cluster.suggestions) {
+      Java_ContextualSuggestionsBridge_addSuggestionToLastCluster(
+          env, j_clusters,
+          ConvertUTF8ToJavaString(env, suggestion.id().id_within_category()),
+          ConvertUTF16ToJavaString(env, suggestion.title()),
+          ConvertUTF16ToJavaString(env, suggestion.publisher_name()),
+          ConvertUTF8ToJavaString(env, suggestion.url().spec()),
+          suggestion.publish_date().ToJavaTime(), suggestion.score(),
+          suggestion.fetch_date().ToJavaTime(),
+          suggestion.is_video_suggestion(),
+          suggestion.optional_image_dominant_color().value_or(0));
+    }
+  }
+  Java_ContextualSuggestionsBridge_onSuggestionsAvailable(env, bridge_,
+                                                          j_clusters);
+}
+
+void ContextualSuggestionsBridge::OnStateCleared() {
+  JNIEnv* env = AttachCurrentThread();
+  Java_ContextualSuggestionsBridge_onStateCleared(env, bridge_);
+}
+
+}  // namespace contextual_suggestions
diff --git a/chrome/browser/android/contextual_suggestions/contextual_suggestions_bridge.h b/chrome/browser/android/contextual_suggestions/contextual_suggestions_bridge.h
new file mode 100644
index 0000000..75ab442
--- /dev/null
+++ b/chrome/browser/android/contextual_suggestions/contextual_suggestions_bridge.h
@@ -0,0 +1,62 @@
+// Copyright 2018 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_ANDROID_CONTEXTUAL_SUGGESTIONS_CONTEXTUAL_SUGGESTIONS_BRIDGE_H_
+#define CHROME_BROWSER_ANDROID_CONTEXTUAL_SUGGESTIONS_CONTEXTUAL_SUGGESTIONS_BRIDGE_H_
+
+#include "base/android/scoped_java_ref.h"
+#include "base/memory/weak_ptr.h"
+#include "components/ntp_snippets/contextual/contextual_content_suggestions_service.h"
+
+namespace contextual_suggestions {
+
+class ContextualSuggestionsBridge
+    : public ntp_snippets::ContextualContentSuggestionsService::Delegate {
+ public:
+  ContextualSuggestionsBridge(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& j_bridge,
+      const base::android::JavaParamRef<jobject>& j_profile);
+
+  void Destroy(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+
+  void FetchSuggestionImage(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      const base::android::JavaParamRef<jstring>& j_suggestion_id,
+      const base::android::JavaParamRef<jobject>& j_callback);
+
+  void FetchSuggestionFavicon(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      const base::android::JavaParamRef<jstring>& j_suggestion_id,
+      const base::android::JavaParamRef<jobject>& j_callback);
+
+  void ReportEvent(JNIEnv* env,
+                   const base::android::JavaParamRef<jobject>& obj,
+                   jint j_event_id);
+
+  // ContextualContentSuggestionsService::Delegate implementation:
+  void OnSuggestionsAvailable(
+      std::vector<ntp_snippets::ContextualContentSuggestionsService::Cluster>
+          clusters) override;
+  void OnStateCleared() override;
+
+ private:
+  ~ContextualSuggestionsBridge() override;
+
+  ntp_snippets::ContextualContentSuggestionsService*
+      contextual_content_suggestions_service_;
+
+  // The Java SnippetsBridge.
+  base::android::ScopedJavaGlobalRef<jobject> bridge_;
+
+  base::WeakPtrFactory<ContextualSuggestionsBridge> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(ContextualSuggestionsBridge);
+};
+
+}  // namespace contextual_suggestions
+
+#endif  // CHROME_BROWSER_ANDROID_CONTEXTUAL_SUGGESTIONS_CONTEXTUAL_SUGGESTIONS_BRIDGE_H_
diff --git a/chrome/browser/android/contextualsearch/contextual_search_tab_helper.cc b/chrome/browser/android/contextualsearch/contextual_search_tab_helper.cc
index 9f4644e..f7e4c736 100644
--- a/chrome/browser/android/contextualsearch/contextual_search_tab_helper.cc
+++ b/chrome/browser/android/contextualsearch/contextual_search_tab_helper.cc
@@ -42,12 +42,15 @@
   Java_ContextualSearchTabHelper_onContextualSearchPrefChanged(env, jobj);
 }
 
-void ContextualSearchTabHelper::OnShowUnhandledTapUIIfNeeded(int x_px,
-                                                             int y_px) {
+void ContextualSearchTabHelper::OnShowUnhandledTapUIIfNeeded(
+    int x_px,
+    int y_px,
+    int font_size_dips,
+    int text_run_length) {
   JNIEnv* env = base::android::AttachCurrentThread();
   ScopedJavaLocalRef<jobject> jobj = weak_java_ref_.get(env);
-  Java_ContextualSearchTabHelper_onShowUnhandledTapUIIfNeeded(env, jobj, x_px,
-                                                              y_px);
+  Java_ContextualSearchTabHelper_onShowUnhandledTapUIIfNeeded(
+      env, jobj, x_px, y_px, font_size_dips, text_run_length);
 }
 
 void ContextualSearchTabHelper::InstallUnhandledTapNotifierIfNeeded(
diff --git a/chrome/browser/android/contextualsearch/contextual_search_tab_helper.h b/chrome/browser/android/contextualsearch/contextual_search_tab_helper.h
index c7832e8..71baae6 100644
--- a/chrome/browser/android/contextualsearch/contextual_search_tab_helper.h
+++ b/chrome/browser/android/contextualsearch/contextual_search_tab_helper.h
@@ -40,8 +40,12 @@
   // Call when the preferences change.
   void OnContextualSearchPrefChanged();
   // Call when an unhandled tap needs to show the UI for a tap at the given
-  // position.
-  void OnShowUnhandledTapUIIfNeeded(int x_px, int y_px);
+  // position, with the given |font_size_dips|, and |text_run_length| of the
+  // enclosing element.
+  void OnShowUnhandledTapUIIfNeeded(int x_px,
+                                    int y_px,
+                                    int font_size_dips,
+                                    int text_run_length);
 
   JavaObjectWeakGlobalRef weak_java_ref_;
   std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_;
diff --git a/chrome/browser/android/contextualsearch/unhandled_tap_notifier_impl.cc b/chrome/browser/android/contextualsearch/unhandled_tap_notifier_impl.cc
index 36fa718..b4103ec 100644
--- a/chrome/browser/android/contextualsearch/unhandled_tap_notifier_impl.cc
+++ b/chrome/browser/android/contextualsearch/unhandled_tap_notifier_impl.cc
@@ -29,9 +29,14 @@
     x_px /= device_scale_factor_;
     y_px /= device_scale_factor_;
   }
+
+  // Pixel from Blink are DIPs.
+  int font_size_dips = unhandled_tap_info->font_size_in_pixels;
+
   // Call back through the callback if possible.  (The callback uses a weakptr
   // that might make this a NOP).
-  unhandled_tap_callback_.Run(x_px, y_px);
+  unhandled_tap_callback_.Run(x_px, y_px, font_size_dips,
+                              unhandled_tap_info->element_text_run_length);
 }
 
 // static
diff --git a/chrome/browser/android/contextualsearch/unhandled_tap_web_contents_observer.h b/chrome/browser/android/contextualsearch/unhandled_tap_web_contents_observer.h
index d5bbd4b..be4a599 100644
--- a/chrome/browser/android/contextualsearch/unhandled_tap_web_contents_observer.h
+++ b/chrome/browser/android/contextualsearch/unhandled_tap_web_contents_observer.h
@@ -12,7 +12,9 @@
 
 namespace contextual_search {
 
-typedef base::RepeatingCallback<void(int x_px, int y_px)> UnhandledTapCallback;
+typedef base::RepeatingCallback<
+    void(int x_px, int y_px, int font_size_dips, int text_run_length)>
+    UnhandledTapCallback;
 
 // Binds a Mojo unhandled-tap notifier message-handler to the frame host
 // observed by this observer.
diff --git a/chrome/browser/android/customtabs/detached_resource_request.h b/chrome/browser/android/customtabs/detached_resource_request.h
index 5b90ac1..e1bcc1c 100644
--- a/chrome/browser/android/customtabs/detached_resource_request.h
+++ b/chrome/browser/android/customtabs/detached_resource_request.h
@@ -35,6 +35,8 @@
 // It is intended to provide "detached" request capabilities from the browser
 // process, that is like <a ping> or <link rel="prefetch">.
 //
+// DO NOT USE for anything that would end up in the content area.
+//
 // This is a UI thread class.
 class DetachedResourceRequest {
  public:
diff --git a/chrome/browser/android/customtabs/detached_resource_request_unittest.cc b/chrome/browser/android/customtabs/detached_resource_request_unittest.cc
index fa6a6fb..eb8df5a 100644
--- a/chrome/browser/android/customtabs/detached_resource_request_unittest.cc
+++ b/chrome/browser/android/customtabs/detached_resource_request_unittest.cc
@@ -38,6 +38,7 @@
 constexpr const char kHttpNoContent[] = "/nocontent";
 constexpr const char kEchoTitle[] = "/echotitle";
 constexpr const char kManyRedirects[] = "/many-redirects";
+constexpr const char kCacheable[] = "/cachetime";
 constexpr const char kCookieKey[] = "cookie";
 constexpr const char kUrlKey[] = "url";
 constexpr const char kCookieFromNoContent[] = "no-content-cookie";
@@ -502,4 +503,40 @@
       "CustomTabs.DetachedResourceRequest.RedirectsCount.Failure", 20, 1);
 }
 
+TEST_F(DetachedResourceRequestTest, CachedResponse) {
+  int two_minus_requests_count = 2;
+  base::RunLoop dummy_run_loop;
+  embedded_test_server()->RegisterRequestMonitor(base::BindRepeating(
+      &WatchPathAndReportHeaders, kCacheable, &two_minus_requests_count,
+      nullptr, dummy_run_loop.QuitClosure()));
+
+  base::RunLoop first_request_waiter;
+  base::RunLoop second_request_waiter;
+  ASSERT_TRUE(embedded_test_server()->Start());
+
+  GURL url(embedded_test_server()->GetURL(kCacheable));
+  GURL site_for_cookies(embedded_test_server()->base_url());
+
+  DetachedResourceRequest::CreateAndStart(
+      browser_context(), url, site_for_cookies,
+      content::Referrer::GetDefaultReferrerPolicy(),
+      base::BindLambdaForTesting([&](bool success) {
+        EXPECT_TRUE(success);
+        first_request_waiter.Quit();
+      }));
+  first_request_waiter.Run();
+
+  DetachedResourceRequest::CreateAndStart(
+      browser_context(), url, site_for_cookies,
+      content::Referrer::GetDefaultReferrerPolicy(),
+      base::BindLambdaForTesting([&](bool success) {
+        EXPECT_TRUE(success);
+        second_request_waiter.Quit();
+      }));
+  second_request_waiter.Run();
+
+  // Only one request, HTTP cache hit for the second one.
+  EXPECT_EQ(1, two_minus_requests_count);
+}
+
 }  // namespace customtabs
diff --git a/chrome/browser/android/metrics/uma_session_stats.cc b/chrome/browser/android/metrics/uma_session_stats.cc
index 74e0596b..ef0544a3 100644
--- a/chrome/browser/android/metrics/uma_session_stats.cc
+++ b/chrome/browser/android/metrics/uma_session_stats.cc
@@ -32,6 +32,10 @@
 
 namespace {
 UmaSessionStats* g_uma_session_stats = NULL;
+
+// Used to keep the state of whether we should consider metric consent enabled.
+// This is used/read only within the ChromeMetricsServiceAccessor methods.
+bool g_metrics_consent_for_testing = false;
 }  // namespace
 
 UmaSessionStats::UmaSessionStats()
@@ -121,6 +125,41 @@
                             consent));
 }
 
+// Initialize the local consent bool variable to false. Used only for testing.
+static void JNI_UmaSessionStats_InitMetricsAndCrashReportingForTesting(
+    JNIEnv*,
+    const JavaParamRef<jclass>&) {
+  DCHECK(g_browser_process);
+
+  g_metrics_consent_for_testing = false;
+  ChromeMetricsServiceAccessor::SetMetricsAndCrashReportingForTesting(
+      &g_metrics_consent_for_testing);
+}
+
+// Clears the boolean consent pointer for ChromeMetricsServiceAccessor to
+// original setting. Used only for testing.
+static void JNI_UmaSessionStats_UnsetMetricsAndCrashReportingForTesting(
+    JNIEnv*,
+    const JavaParamRef<jclass>&) {
+  DCHECK(g_browser_process);
+
+  g_metrics_consent_for_testing = false;
+  ChromeMetricsServiceAccessor::SetMetricsAndCrashReportingForTesting(nullptr);
+}
+
+// Updates the metrics consent bit to |consent|. This is separate from
+// InitMetricsAndCrashReportingForTesting as the Set isn't meant to be used
+// repeatedly. Used only for testing.
+static void JNI_UmaSessionStats_UpdateMetricsAndCrashReportingForTesting(
+    JNIEnv*,
+    const JavaParamRef<jclass>&,
+    jboolean consent) {
+  DCHECK(g_browser_process);
+
+  g_metrics_consent_for_testing = consent;
+  g_browser_process->GetMetricsServicesManager()->UpdateUploadPermissions(true);
+}
+
 // Starts/stops the MetricsService based on existing consent and upload
 // preferences.
 // There are three possible states:
diff --git a/chrome/browser/android/tab_android.cc b/chrome/browser/android/tab_android.cc
index 4653f91..9a5052a 100644
--- a/chrome/browser/android/tab_android.cc
+++ b/chrome/browser/android/tab_android.cc
@@ -386,6 +386,7 @@
     jboolean incognito,
     jboolean is_background_tab,
     const JavaParamRef<jobject>& jweb_contents,
+    const JavaParamRef<jobject>& jparent_web_contents,
     const JavaParamRef<jobject>& jweb_contents_delegate,
     const JavaParamRef<jobject>& jcontext_menu_populator) {
   web_contents_.reset(content::WebContents::FromJavaWebContents(jweb_contents));
@@ -420,7 +421,9 @@
   if (favicon_driver)
     favicon_driver->AddObserver(this);
 
-  synced_tab_delegate_->SetWebContents(web_contents());
+  WebContents* parent_web_contents =
+      content::WebContents::FromJavaWebContents(jparent_web_contents);
+  synced_tab_delegate_->SetWebContents(web_contents(), parent_web_contents);
 
   // Verify that the WebContents this tab represents matches the expected
   // off the record state.
diff --git a/chrome/browser/android/tab_android.h b/chrome/browser/android/tab_android.h
index 42270ed6..2c115bb 100644
--- a/chrome/browser/android/tab_android.h
+++ b/chrome/browser/android/tab_android.h
@@ -158,6 +158,7 @@
       jboolean incognito,
       jboolean is_background_tab,
       const base::android::JavaParamRef<jobject>& jweb_contents,
+      const base::android::JavaParamRef<jobject>& jparent_web_contents,
       const base::android::JavaParamRef<jobject>& jweb_contents_delegate,
       const base::android::JavaParamRef<jobject>& jcontext_menu_populator);
   void UpdateDelegates(
diff --git a/chrome/browser/android/vr/vr_gl_thread.cc b/chrome/browser/android/vr/vr_gl_thread.cc
index dda310a..d52f84f 100644
--- a/chrome/browser/android/vr/vr_gl_thread.cc
+++ b/chrome/browser/android/vr/vr_gl_thread.cc
@@ -359,39 +359,11 @@
                                 weak_browser_ui_, enabled, show_toast));
 }
 
-void VrGLThread::SetAudioCaptureEnabled(bool enabled) {
+void VrGLThread::SetCapturingState(const CapturingStateModel& state) {
   DCHECK(OnMainThread());
-  task_runner()->PostTask(
-      FROM_HERE, base::BindOnce(&BrowserUiInterface::SetAudioCaptureEnabled,
-                                weak_browser_ui_, enabled));
-}
-
-void VrGLThread::SetLocationAccessEnabled(bool enabled) {
-  DCHECK(OnMainThread());
-  task_runner()->PostTask(
-      FROM_HERE, base::BindOnce(&BrowserUiInterface::SetLocationAccessEnabled,
-                                weak_browser_ui_, enabled));
-}
-
-void VrGLThread::SetVideoCaptureEnabled(bool enabled) {
-  DCHECK(OnMainThread());
-  task_runner()->PostTask(
-      FROM_HERE, base::BindOnce(&BrowserUiInterface::SetVideoCaptureEnabled,
-                                weak_browser_ui_, enabled));
-}
-
-void VrGLThread::SetScreenCaptureEnabled(bool enabled) {
-  DCHECK(OnMainThread());
-  task_runner()->PostTask(
-      FROM_HERE, base::BindOnce(&BrowserUiInterface::SetScreenCaptureEnabled,
-                                weak_browser_ui_, enabled));
-}
-
-void VrGLThread::SetBluetoothConnected(bool enabled) {
-  DCHECK(OnMainThread());
-  task_runner()->PostTask(
-      FROM_HERE, base::BindOnce(&BrowserUiInterface::SetBluetoothConnected,
-                                weak_browser_ui_, enabled));
+  task_runner()->PostTask(FROM_HERE,
+                          base::BindOnce(&BrowserUiInterface::SetCapturingState,
+                                         weak_browser_ui_, state));
 }
 
 void VrGLThread::SetIsExiting() {
diff --git a/chrome/browser/android/vr/vr_gl_thread.h b/chrome/browser/android/vr/vr_gl_thread.h
index 013ea6a..c7eca7bfe 100644
--- a/chrome/browser/android/vr/vr_gl_thread.h
+++ b/chrome/browser/android/vr/vr_gl_thread.h
@@ -104,11 +104,7 @@
   void SetLoadProgress(float progress) override;
   void SetIsExiting() override;
   void SetHistoryButtonsEnabled(bool can_go_back, bool can_go_forward) override;
-  void SetVideoCaptureEnabled(bool enabled) override;
-  void SetScreenCaptureEnabled(bool enabled) override;
-  void SetAudioCaptureEnabled(bool enabled) override;
-  void SetBluetoothConnected(bool enabled) override;
-  void SetLocationAccessEnabled(bool enabled) override;
+  void SetCapturingState(const CapturingStateModel& state) override;
   void ShowExitVrPrompt(UiUnsupportedMode reason) override;
   void SetSpeechRecognitionEnabled(bool enabled) override;
   void SetRecognitionResult(const base::string16& result) override;
diff --git a/chrome/browser/android/vr/vr_input_connection.cc b/chrome/browser/android/vr/vr_input_connection.cc
index 0936f21..2aa981e 100644
--- a/chrome/browser/android/vr/vr_input_connection.cc
+++ b/chrome/browser/android/vr/vr_input_connection.cc
@@ -72,4 +72,8 @@
       .Run(base::UTF8ToUTF16(text));
 }
 
+base::android::ScopedJavaLocalRef<jobject> VrInputConnection::GetJavaObject() {
+  return base::android::ScopedJavaLocalRef<jobject>(j_object_);
+}
+
 }  // namespace vr
diff --git a/chrome/browser/android/vr/vr_input_connection.h b/chrome/browser/android/vr/vr_input_connection.h
index 4fe3f248..df5d31d 100644
--- a/chrome/browser/android/vr/vr_input_connection.h
+++ b/chrome/browser/android/vr/vr_input_connection.h
@@ -35,6 +35,8 @@
                        const base::android::JavaParamRef<jobject>& obj,
                        jstring jtext);
 
+  base::android::ScopedJavaLocalRef<jobject> GetJavaObject();
+
  private:
   base::android::ScopedJavaGlobalRef<jobject> j_object_;
   std::queue<vr::TextStateUpdateCallback> text_state_update_callbacks_;
diff --git a/chrome/browser/android/vr/vr_shell.cc b/chrome/browser/android/vr/vr_shell.cc
index d109cd2..907826eb 100644
--- a/chrome/browser/android/vr/vr_shell.cc
+++ b/chrome/browser/android/vr/vr_shell.cc
@@ -82,7 +82,7 @@
 namespace {
 vr::VrShell* g_vr_shell_instance;
 
-constexpr base::TimeDelta poll_media_access_interval_ =
+constexpr base::TimeDelta kPollCapturingStateInterval =
     base::TimeDelta::FromSecondsD(0.2);
 
 constexpr base::TimeDelta kExitVrDueToUnsupportedModeDelay =
@@ -140,8 +140,7 @@
                  int display_width_pixels,
                  int display_height_pixels,
                  bool pause_content)
-    : vr_shell_enabled_(base::FeatureList::IsEnabled(features::kVrBrowsing)),
-      web_vr_autopresentation_expected_(
+    : web_vr_autopresentation_expected_(
           ui_initial_state.web_vr_autopresentation_expected),
       delegate_provider_(delegate),
       main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
@@ -280,7 +279,6 @@
   DVLOG(1) << __FUNCTION__ << "=" << this;
   content_surface_texture_ = nullptr;
   overlay_surface_texture_ = nullptr;
-  poll_capturing_media_task_.Cancel();
   if (gvr_gamepad_source_active_) {
     device::GamepadDataFetcherManager::GetInstance()->RemoveSourceFactory(
         device::GAMEPAD_SOURCE_GVR);
@@ -317,8 +315,6 @@
 }
 
 void VrShell::OnContentPaused(bool paused) {
-  if (!vr_shell_enabled_)
-    return;
   device::VRDevice* device = delegate_provider_->GetDevice();
   if (!device)
     return;
@@ -459,7 +455,7 @@
     metrics_helper->SetVRActive(false);
   SetIsInVR(GetNonNativePageWebContents(), false);
 
-  poll_capturing_media_task_.Cancel();
+  poll_capturing_state_task_.Cancel();
 }
 
 void VrShell::OnResume(JNIEnv* env, const JavaParamRef<jobject>& obj) {
@@ -472,7 +468,7 @@
     metrics_helper->SetVRActive(true);
   SetIsInVR(GetNonNativePageWebContents(), true);
 
-  PollMediaAccessFlag();
+  PollCapturingState();
 }
 
 void VrShell::SetSurface(JNIEnv* env,
@@ -524,6 +520,16 @@
   return ShouldDisplayURL();
 }
 
+base::android::ScopedJavaLocalRef<jobject>
+VrShell::GetVrInputConnectionForTesting(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jobject>& obj) {
+  if (!vr_input_connection_)
+    return nullptr;
+
+  return vr_input_connection_->GetJavaObject();
+}
+
 void VrShell::OnLoadProgressChanged(JNIEnv* env,
                                     const JavaParamRef<jobject>& obj,
                                     double progress) {
@@ -550,16 +556,20 @@
                            jboolean incognito,
                            jint id,
                            jstring jtitle) {
-  incognito_tab_ids_.insert(id);
-  ui_->SetIncognitoTabsOpen(!incognito_tab_ids_.empty());
+  if (incognito) {
+    incognito_tab_ids_.insert(id);
+    ui_->SetIncognitoTabsOpen(!incognito_tab_ids_.empty());
+  }
 }
 
 void VrShell::OnTabRemoved(JNIEnv* env,
                            const JavaParamRef<jobject>& obj,
                            jboolean incognito,
                            jint id) {
-  incognito_tab_ids_.erase(id);
-  ui_->SetIncognitoTabsOpen(!incognito_tab_ids_.empty());
+  if (incognito) {
+    incognito_tab_ids_.erase(id);
+    ui_->SetIncognitoTabsOpen(!incognito_tab_ids_.empty());
+  }
 }
 
 void VrShell::SetAlertDialog(JNIEnv* env,
@@ -881,14 +891,12 @@
   return Java_VrShellImpl_hasAudioPermission(env, j_vr_shell_);
 }
 
-void VrShell::PollMediaAccessFlag() {
-  poll_capturing_media_task_.Cancel();
-
-  poll_capturing_media_task_.Reset(base::BindRepeating(
-      &VrShell::PollMediaAccessFlag, base::Unretained(this)));
+void VrShell::PollCapturingState() {
+  poll_capturing_state_task_.Reset(base::BindRepeating(
+      &VrShell::PollCapturingState, base::Unretained(this)));
   main_thread_task_runner_->PostDelayedTask(
-      FROM_HERE, poll_capturing_media_task_.callback(),
-      poll_media_access_interval_);
+      FROM_HERE, poll_capturing_state_task_.callback(),
+      kPollCapturingStateInterval);
 
   int num_tabs_capturing_audio = 0;
   int num_tabs_capturing_video = 0;
@@ -922,36 +930,19 @@
       num_tabs_bluetooth_connected++;
   }
 
+  capturing_state_.audio_capture_enabled = num_tabs_capturing_audio > 0;
+  capturing_state_.video_capture_enabled = num_tabs_capturing_video > 0;
+  capturing_state_.screen_capture_enabled = num_tabs_capturing_screen > 0;
+  capturing_state_.bluetooth_connected = num_tabs_bluetooth_connected > 0;
+
   geolocation_config_->IsHighAccuracyLocationBeingCaptured(base::BindRepeating(
-      &VrShell::SetHighAccuracyLocation, base::Unretained(this)));
-
-  bool is_capturing_audio = num_tabs_capturing_audio > 0;
-  bool is_capturing_video = num_tabs_capturing_video > 0;
-  bool is_capturing_screen = num_tabs_capturing_screen > 0;
-  bool is_bluetooth_connected = num_tabs_bluetooth_connected > 0;
-  if (is_capturing_audio != is_capturing_audio_) {
-    ui_->SetAudioCaptureEnabled(is_capturing_audio);
-    is_capturing_audio_ = is_capturing_audio;
-  }
-  if (is_capturing_video != is_capturing_video_) {
-    ui_->SetVideoCaptureEnabled(is_capturing_video);
-    is_capturing_video_ = is_capturing_video;
-  }
-  if (is_capturing_screen != is_capturing_screen_) {
-    ui_->SetScreenCaptureEnabled(is_capturing_screen);
-    is_capturing_screen_ = is_capturing_screen;
-  }
-  if (is_bluetooth_connected != is_bluetooth_connected_) {
-    ui_->SetBluetoothConnected(is_bluetooth_connected);
-    is_bluetooth_connected_ = is_bluetooth_connected;
-  }
-}
-
-void VrShell::SetHighAccuracyLocation(bool high_accuracy_location) {
-  if (high_accuracy_location == high_accuracy_location_)
-    return;
-  ui_->SetLocationAccessEnabled(high_accuracy_location);
-  high_accuracy_location_ = high_accuracy_location;
+      [](VrShell* shell, BrowserUiInterface* ui,
+         CapturingStateModel* capturing_state, bool high_accuracy_location) {
+        capturing_state->location_access_enabled = high_accuracy_location;
+        ui->SetCapturingState(*capturing_state);
+      },
+      base::Unretained(this), base::Unretained(ui_),
+      base::Unretained(&capturing_state_)));
 }
 
 void VrShell::ClearFocusedElement() {
diff --git a/chrome/browser/android/vr/vr_shell.h b/chrome/browser/android/vr/vr_shell.h
index c416af3..9b16e0e7 100644
--- a/chrome/browser/android/vr/vr_shell.h
+++ b/chrome/browser/android/vr/vr_shell.h
@@ -19,6 +19,7 @@
 #include "chrome/browser/vr/assets_load_status.h"
 #include "chrome/browser/vr/content_input_delegate.h"
 #include "chrome/browser/vr/exit_vr_prompt_choice.h"
+#include "chrome/browser/vr/model/capturing_state_model.h"
 #include "chrome/browser/vr/speech_recognizer.h"
 #include "chrome/browser/vr/ui.h"
 #include "chrome/browser/vr/ui_browser_interface.h"
@@ -105,6 +106,9 @@
   bool IsDisplayingUrlForTesting(
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& obj);
+  base::android::ScopedJavaLocalRef<jobject> GetVrInputConnectionForTesting(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
   void OnFullscreenChanged(bool enabled);
   void OnLoadProgressChanged(JNIEnv* env,
                              const base::android::JavaParamRef<jobject>& obj,
@@ -176,8 +180,6 @@
                            jint overlay_width,
                            jint overlay_height);
 
-  void SetHighAccuracyLocation(bool high_accuracy_location);
-
   void ForceExitVr();
   void ExitPresent();
   void ExitFullscreen();
@@ -241,7 +243,7 @@
   void PostToGlThread(const base::Location& from_here, base::OnceClosure task);
   void SetUiState();
 
-  void PollMediaAccessFlag();
+  void PollCapturingState();
 
   bool HasDaydreamSupport(JNIEnv* env);
 
@@ -253,8 +255,6 @@
   void OnAssetsComponentReady();
   void OnAssetsComponentWaitTimeout();
 
-  bool vr_shell_enabled_;
-
   bool webvr_mode_ = false;
   bool web_vr_autopresentation_expected_ = false;
 
@@ -285,12 +285,8 @@
 
   device::mojom::GeolocationConfigPtr geolocation_config_;
 
-  base::CancelableClosure poll_capturing_media_task_;
-  bool is_capturing_audio_ = false;
-  bool is_capturing_video_ = false;
-  bool is_capturing_screen_ = false;
-  bool is_bluetooth_connected_ = false;
-  bool high_accuracy_location_ = false;
+  base::CancelableClosure poll_capturing_state_task_;
+  CapturingStateModel capturing_state_;
 
   // Are we currently providing a gamepad factory to the gamepad manager?
   bool gvr_gamepad_source_active_ = false;
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc
index 1587a1c0..852dfdb 100644
--- a/chrome/browser/apps/guest_view/web_view_browsertest.cc
+++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -3937,25 +3937,6 @@
   }
 };
 
-namespace {
-
-class ScrollWaiter {
- public:
-  explicit ScrollWaiter(content::RenderWidgetHostView* host_view)
-      : host_view_(host_view) {}
-  ~ScrollWaiter() {}
-
-  void WaitForScrollChange(gfx::Vector2dF target_offset) {
-    while (target_offset != host_view_->GetLastScrollOffset())
-      base::RunLoop().RunUntilIdle();
-  }
-
- private:
-  content::RenderWidgetHostView* host_view_;
-};
-
-}  // namespace
-
 // Tests that scrolls bubble from guest to embedder.
 // Create two test instances, one where the guest body is scrollable and the
 // other where the body is not scrollable: fast-path scrolling will generate
@@ -3973,6 +3954,8 @@
     SendMessageToGuestAndWait("set_overflow_hidden", "overflow_is_hidden");
 
   content::WebContents* embedder_contents = GetEmbedderWebContents();
+  content::RenderFrameSubmissionObserver embedder_frame_observer(
+      embedder_contents);
 
   std::vector<content::WebContents*> guest_web_contents_list;
   GetGuestViewManager()->WaitForNumGuestsCreated(1u);
@@ -3980,6 +3963,7 @@
   ASSERT_EQ(1u, guest_web_contents_list.size());
 
   content::WebContents* guest_contents = guest_web_contents_list[0];
+  content::RenderFrameSubmissionObserver guest_frame_observer(guest_contents);
 
   gfx::Rect embedder_rect = embedder_contents->GetContainerBounds();
   gfx::Rect guest_rect = guest_contents->GetContainerBounds();
@@ -3989,11 +3973,10 @@
   embedder_rect.set_x(0);
   embedder_rect.set_y(0);
 
-  // Send scroll gesture to embedder & verify.
-  content::RenderWidgetHostView* embedder_host_view =
-      embedder_contents->GetRenderWidgetHostView();
-  EXPECT_EQ(gfx::Vector2dF(), embedder_host_view->GetLastScrollOffset());
+  gfx::Vector2dF default_offset;
+  embedder_frame_observer.WaitForScrollOffset(default_offset);
 
+  // Send scroll gesture to embedder & verify.
   // Make sure wheel events don't get filtered.
   float scroll_magnitude = 15.f;
 
@@ -4006,8 +3989,6 @@
 
     gfx::Vector2dF expected_offset(0.f, scroll_magnitude);
 
-    ScrollWaiter waiter(embedder_host_view);
-
     content::SimulateMouseEvent(embedder_contents,
                                 blink::WebInputEvent::kMouseMove,
                                 embedder_scroll_location);
@@ -4015,12 +3996,11 @@
                                      embedder_scroll_location,
                                      gfx::Vector2d(0, -scroll_magnitude),
                                      blink::WebMouseWheelEvent::kPhaseBegan);
-    waiter.WaitForScrollChange(expected_offset);
+
+    embedder_frame_observer.WaitForScrollOffset(expected_offset);
   }
 
-  content::RenderWidgetHostView* guest_host_view =
-      guest_contents->GetRenderWidgetHostView();
-  EXPECT_EQ(gfx::Vector2dF(), guest_host_view->GetLastScrollOffset());
+  guest_frame_observer.WaitForScrollOffset(default_offset);
 
   // Send scroll gesture to guest and verify embedder scrolls.
   // Perform a scroll gesture of the same magnitude, but in the opposite
@@ -4032,7 +4012,6 @@
   {
     gfx::Point guest_scroll_location(guest_rect.x() + guest_rect.width() / 2,
                                      guest_rect.y());
-    ScrollWaiter waiter(embedder_host_view);
 
     content::SimulateMouseEvent(embedder_contents,
                                 blink::WebInputEvent::kMouseMove,
@@ -4040,8 +4019,7 @@
     content::SimulateMouseWheelEvent(embedder_contents, guest_scroll_location,
                                      gfx::Vector2d(0, scroll_magnitude),
                                      blink::WebMouseWheelEvent::kPhaseChanged);
-
-    waiter.WaitForScrollChange(gfx::Vector2dF());
+    embedder_frame_observer.WaitForScrollOffset(default_offset);
   }
 }
 
@@ -4075,6 +4053,8 @@
   LoadAppWithGuest("web_view/scrollable_embedder_and_guest");
 
   content::WebContents* embedder_contents = GetEmbedderWebContents();
+  content::RenderFrameSubmissionObserver embedder_frame_observer(
+      embedder_contents);
 
   std::vector<content::WebContents*> guest_web_contents_list;
   GetGuestViewManager()->WaitForNumGuestsCreated(1u);
@@ -4082,13 +4062,13 @@
   ASSERT_EQ(1u, guest_web_contents_list.size());
 
   content::WebContents* guest_contents = guest_web_contents_list[0];
+  content::RenderFrameSubmissionObserver guest_frame_observer(guest_contents);
   content::RenderWidgetHostView* guest_host_view =
       guest_contents->GetRenderWidgetHostView();
 
-  content::RenderWidgetHostView* embedder_host_view =
-      embedder_contents->GetRenderWidgetHostView();
-  ASSERT_EQ(gfx::Vector2dF(), guest_host_view->GetLastScrollOffset());
-  ASSERT_EQ(gfx::Vector2dF(), embedder_host_view->GetLastScrollOffset());
+  gfx::Vector2dF default_offset;
+  guest_frame_observer.WaitForScrollOffset(default_offset);
+  embedder_frame_observer.WaitForScrollOffset(default_offset);
 
   gfx::PointF guest_scroll_location(1, 1);
   gfx::PointF guest_scroll_location_in_root =
@@ -4134,7 +4114,12 @@
   update_waiter.Wait();
   update_waiter.Reset();
 
-  ASSERT_EQ(gfx::Vector2dF(), guest_host_view->GetLastScrollOffset());
+  // TODO(jonross): This test is only waiting on InputEventAckWaiter, but has an
+  // implicit wait on frame submission. InputEventAckWaiter needs to be updated
+  // to support VizDisplayCompositor, when it is, it should be tied to frame
+  // tokens which will allow for synchronizing with frame submission for further
+  // verifying metadata (crbug.com/812012)
+  guest_frame_observer.WaitForScrollOffset(default_offset);
 
   // Now we switch directions and scroll down. The guest can scroll in this
   // direction, but since we're bubbling, the guest should not consume this.
@@ -4143,7 +4128,7 @@
                                 ui::LatencyInfo(ui::SourceEventType::WHEEL));
   update_waiter.Wait();
 
-  EXPECT_EQ(gfx::Vector2dF(), guest_host_view->GetLastScrollOffset());
+  guest_frame_observer.WaitForScrollOffset(default_offset);
 }
 
 INSTANTIATE_TEST_CASE_P(WebViewScrollBubbling,
@@ -4257,6 +4242,8 @@
     SendMessageToGuestAndWait("set_overflow_hidden", "overflow_is_hidden");
 
   content::WebContents* embedder_contents = GetEmbedderWebContents();
+  content::RenderFrameSubmissionObserver embedder_frame_observer(
+      embedder_contents);
 
   std::vector<content::WebContents*> guest_web_contents_list;
   GetGuestViewManager()->WaitForNumGuestsCreated(1u);
@@ -4264,6 +4251,7 @@
   ASSERT_EQ(1u, guest_web_contents_list.size());
 
   content::WebContents* guest_contents = guest_web_contents_list[0];
+  content::RenderFrameSubmissionObserver guest_frame_observer(guest_contents);
 
   gfx::Rect embedder_rect = embedder_contents->GetContainerBounds();
   gfx::Rect guest_rect = guest_contents->GetContainerBounds();
@@ -4273,11 +4261,10 @@
   embedder_rect.set_x(0);
   embedder_rect.set_y(0);
 
-  // Send scroll gesture to embedder & verify.
-  content::RenderWidgetHostView* embedder_host_view =
-      embedder_contents->GetRenderWidgetHostView();
-  EXPECT_EQ(gfx::Vector2dF(), embedder_host_view->GetLastScrollOffset());
+  gfx::Vector2dF default_offset;
+  embedder_frame_observer.WaitForScrollOffset(default_offset);
 
+  // Send scroll gesture to embedder & verify.
   float gesture_distance = 15.f;
   {
     // Scroll the embedder from a position in the embedder that is not over
@@ -4292,14 +4279,11 @@
         embedder_contents, embedder_scroll_location,
         gfx::Vector2dF(0, -gesture_distance));
 
-    ScrollWaiter waiter(embedder_host_view);
-
-    waiter.WaitForScrollChange(expected_offset);
+    embedder_frame_observer.WaitForScrollOffset(expected_offset);
   }
 
-  content::RenderWidgetHostView* guest_host_view =
-      guest_contents->GetRenderWidgetHostView();
-  EXPECT_EQ(gfx::Vector2dF(), guest_host_view->GetLastScrollOffset());
+  // Check that the guest has not scrolled.
+  guest_frame_observer.WaitForScrollOffset(default_offset);
 
   // Send scroll gesture to guest and verify embedder scrolls.
   // Perform a scroll gesture of the same magnitude, but in the opposite
@@ -4309,13 +4293,11 @@
     gfx::Point guest_scroll_location(guest_rect.width() / 2,
                                      guest_rect.height() / 2);
 
-    ScrollWaiter waiter(embedder_host_view);
-
     content::SimulateGestureScrollSequence(guest_contents,
                                            guest_scroll_location,
                                            gfx::Vector2dF(0, gesture_distance));
 
-    waiter.WaitForScrollChange(gfx::Vector2dF());
+    embedder_frame_observer.WaitForScrollOffset(default_offset);
   }
 }
 
@@ -4346,6 +4328,8 @@
   LoadAppWithGuest("web_view/scrollable_embedder_and_guest");
 
   content::WebContents* embedder_contents = GetEmbedderWebContents();
+  content::RenderFrameSubmissionObserver embedder_frame_observer(
+      embedder_contents);
 
   std::vector<content::WebContents*> guest_web_contents_list;
   GetGuestViewManager()->WaitForNumGuestsCreated(1u);
@@ -4353,18 +4337,16 @@
   ASSERT_EQ(1u, guest_web_contents_list.size());
 
   content::WebContents* guest_contents = guest_web_contents_list[0];
-  content::RenderWidgetHostView* guest_host_view =
-      guest_contents->GetRenderWidgetHostView();
+  content::RenderFrameSubmissionObserver guest_frame_observer(guest_contents);
 
   gfx::Rect embedder_rect = embedder_contents->GetContainerBounds();
   gfx::Rect guest_rect = guest_contents->GetContainerBounds();
   guest_rect.set_x(guest_rect.x() - embedder_rect.x());
   guest_rect.set_y(guest_rect.y() - embedder_rect.y());
 
-  content::RenderWidgetHostView* embedder_host_view =
-      embedder_contents->GetRenderWidgetHostView();
-  EXPECT_EQ(gfx::Vector2dF(), guest_host_view->GetLastScrollOffset());
-  EXPECT_EQ(gfx::Vector2dF(), embedder_host_view->GetLastScrollOffset());
+  gfx::Vector2dF default_offset;
+  guest_frame_observer.WaitForScrollOffset(default_offset);
+  embedder_frame_observer.WaitForScrollOffset(default_offset);
 
   gfx::Point guest_scroll_location(guest_rect.width() / 2, 0);
 
@@ -4372,30 +4354,27 @@
   {
     gfx::Vector2dF expected_offset(0.f, gesture_distance);
 
-    ScrollWaiter waiter(guest_host_view);
-
     content::SimulateGestureScrollSequence(
         guest_contents, guest_scroll_location,
         gfx::Vector2dF(0, -gesture_distance));
 
-    waiter.WaitForScrollChange(expected_offset);
+    guest_frame_observer.WaitForScrollOffset(expected_offset);
   }
-  EXPECT_EQ(gfx::Vector2dF(), embedder_host_view->GetLastScrollOffset());
+
+  embedder_frame_observer.WaitForScrollOffset(default_offset);
 
   // Use fling gesture to scroll back, velocity should be big enough to scroll
   // content back.
   float fling_velocity = 300.f;
   {
-    ScrollWaiter waiter(guest_host_view);
-
     content::SimulateGestureFlingSequence(
         guest_contents, guest_scroll_location,
         gfx::Vector2dF(0, fling_velocity));
 
-    waiter.WaitForScrollChange(gfx::Vector2dF());
+    guest_frame_observer.WaitForScrollOffset(default_offset);
   }
 
-  EXPECT_EQ(gfx::Vector2dF(), embedder_host_view->GetLastScrollOffset());
+  embedder_frame_observer.WaitForScrollOffset(default_offset);
 }
 
 #if defined(USE_AURA)
@@ -4410,6 +4389,8 @@
   LoadAppWithGuest("web_view/scrollable_embedder_and_guest");
 
   content::WebContents* embedder_contents = GetEmbedderWebContents();
+  content::RenderFrameSubmissionObserver embedder_frame_observer(
+      embedder_contents);
 
   std::vector<content::WebContents*> guest_web_contents_list;
   GetGuestViewManager()->WaitForNumGuestsCreated(1u);
@@ -4417,8 +4398,7 @@
   ASSERT_EQ(1u, guest_web_contents_list.size());
 
   content::WebContents* guest_contents = guest_web_contents_list[0];
-  content::RenderWidgetHostView* guest_host_view =
-      guest_contents->GetRenderWidgetHostView();
+  content::RenderFrameSubmissionObserver guest_frame_observer(guest_contents);
 
   gfx::Rect embedder_rect = embedder_contents->GetContainerBounds();
   gfx::Rect guest_rect = guest_contents->GetContainerBounds();
@@ -4427,8 +4407,9 @@
 
   content::RenderWidgetHostView* embedder_host_view =
       embedder_contents->GetRenderWidgetHostView();
-  EXPECT_EQ(gfx::Vector2dF(), guest_host_view->GetLastScrollOffset());
-  EXPECT_EQ(gfx::Vector2dF(), embedder_host_view->GetLastScrollOffset());
+  gfx::Vector2dF default_offset;
+  guest_frame_observer.WaitForScrollOffset(default_offset);
+  embedder_frame_observer.WaitForScrollOffset(default_offset);
 
   // If we scroll the guest, the OverscrollController for the
   // RenderWidgetHostViewAura should see that the scroll was consumed.
diff --git a/chrome/browser/browser_process.h b/chrome/browser/browser_process.h
index 40131e1..9eb095e 100644
--- a/chrome/browser/browser_process.h
+++ b/chrome/browser/browser_process.h
@@ -20,7 +20,7 @@
 #include "build/build_config.h"
 #include "chrome/browser/browser_process_platform_part.h"
 #include "chrome/browser/shell_integration.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 class BackgroundModeManager;
 class DownloadRequestLimiter;
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index 1cb4066..57d435c6 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -126,7 +126,7 @@
 #include "content/public/common/network_connection_tracker.h"
 #include "extensions/buildflags/buildflags.h"
 #include "extensions/common/constants.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "net/socket/client_socket_pool_manager.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "ppapi/features/features.h"
@@ -309,6 +309,11 @@
       std::max(std::min(max_per_proxy, 99),
                net::ClientSocketPoolManager::max_sockets_per_group(
                    net::HttpNetworkSession::NORMAL_SOCKET_POOL)));
+
+#if BUILDFLAG(ENABLE_WEBRTC)
+  DCHECK(!webrtc_event_log_manager_);
+  webrtc_event_log_manager_ = WebRtcEventLogManager::CreateSingletonInstance();
+#endif
 }
 
 BrowserProcessImpl::~BrowserProcessImpl() {
@@ -1165,11 +1170,6 @@
         base::WrapUnique(new base::DefaultTickClock()), local_state(),
         system_request_context());
   }
-
-#if BUILDFLAG(ENABLE_WEBRTC)
-  DCHECK(!webrtc_event_log_manager_);
-  webrtc_event_log_manager_ = WebRtcEventLogManager::CreateSingletonInstance();
-#endif
 }
 
 void BrowserProcessImpl::CreateIconManager() {
diff --git a/chrome/browser/browser_process_impl.h b/chrome/browser/browser_process_impl.h
index 4d72c39..a345d42 100644
--- a/chrome/browser/browser_process_impl.h
+++ b/chrome/browser/browser_process_impl.h
@@ -27,7 +27,7 @@
 #include "components/nacl/common/buildflags.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "extensions/buildflags/buildflags.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "ppapi/features/features.h"
 #include "printing/features/features.h"
 #include "services/network/public/mojom/network_service.mojom.h"
diff --git a/chrome/browser/browser_process_impl_unittest.cc b/chrome/browser/browser_process_impl_unittest.cc
index bd647ec..84dccef 100644
--- a/chrome/browser/browser_process_impl_unittest.cc
+++ b/chrome/browser/browser_process_impl_unittest.cc
@@ -31,9 +31,10 @@
       : stashed_browser_process_(g_browser_process),
         loop_(base::MessageLoop::TYPE_UI),
         ui_thread_(content::BrowserThread::UI, &loop_),
+        io_thread_(new content::TestBrowserThread(content::BrowserThread::IO)),
         command_line_(base::CommandLine::NO_PROGRAM),
-        browser_process_impl_(
-            new BrowserProcessImpl(base::ThreadTaskRunnerHandle::Get().get())) {
+        browser_process_impl_(std::make_unique<BrowserProcessImpl>(
+            base::ThreadTaskRunnerHandle::Get().get())) {
     // Create() and StartWithDefaultParams() TaskScheduler in seperate steps to
     // properly simulate the browser process' lifecycle.
     base::TaskScheduler::Create("BrowserProcessImplTest");
@@ -48,20 +49,17 @@
     g_browser_process = stashed_browser_process_;
   }
 
-  // Creates the IO thread (unbound) and task scheduler threads. The UI thread
-  // needs to be alive while BrowserProcessImpl is alive, and is managed
-  // separately.
+  // Creates the secondary thread (IO thread).
+  // The UI thread needs to be alive while BrowserProcessImpl is alive, and is
+  // managed separately.
   void StartSecondaryThreads() {
     base::TaskScheduler::GetInstance()->StartWithDefaultParams();
-
-    io_thread_ = std::make_unique<content::TestBrowserThread>(
-        content::BrowserThread::IO);
-    io_thread_->StartIOThreadUnregistered();
+    io_thread_->StartIOThread();
   }
 
-  // Binds the IO thread to BrowserThread::IO and starts the ServiceManager.
+  // Initializes the IO thread delegate and starts the ServiceManager.
   void Initialize() {
-    io_thread_->RegisterAsBrowserThread();
+    io_thread_->InitIOThreadDelegate();
 
     // TestServiceManagerContext creation requires the task scheduler to be
     // started.
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
index 00fc38c..46a3f2c 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
@@ -87,7 +87,7 @@
 #include "media/mojo/services/video_decode_perf_history.h"
 #include "net/cookies/cookie_store.h"
 #include "net/http/http_transaction_factory.h"
-#include "net/net_features.h"
+#include "net/net_buildflags.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "url/url_util.h"
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h
index 022d994..6e6daf85 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h
@@ -23,7 +23,7 @@
 #include "content/public/browser/browsing_data_remover.h"
 #include "content/public/browser/browsing_data_remover_delegate.h"
 #include "extensions/buildflags/buildflags.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "ppapi/features/features.h"
 
 #if BUILDFLAG(ENABLE_PLUGINS)
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
index d04fc8d5..f27f7a8 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
@@ -84,7 +84,7 @@
 #include "net/cookies/canonical_cookie.h"
 #include "net/cookies/cookie_store.h"
 #include "net/http/http_transaction_factory.h"
-#include "net/net_features.h"
+#include "net/net_buildflags.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "third_party/skia/include/core/SkBitmap.h"
diff --git a/chrome/browser/chrome_browser_field_trials_desktop.cc b/chrome/browser/chrome_browser_field_trials_desktop.cc
index 982f72c..0fbc3c4c 100644
--- a/chrome/browser/chrome_browser_field_trials_desktop.cc
+++ b/chrome/browser/chrome_browser_field_trials_desktop.cc
@@ -30,7 +30,7 @@
 #include "components/metrics/persistent_system_profile.h"
 #include "components/variations/variations_associated_data.h"
 #include "content/public/common/content_switches.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 #if defined(OS_WIN)
 #include "base/win/pe_image.h"
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index 3ff7098..93710f1 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -179,7 +179,7 @@
 #include "device/vr/buildflags/buildflags.h"
 #include "extensions/buildflags/buildflags.h"
 #include "media/base/localized_strings.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "net/base/net_module.h"
 #include "net/cookies/cookie_monster.h"
 #include "net/http/http_network_layer.h"
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 3caabcd..b30517a 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -232,8 +232,8 @@
 #include "gpu/config/gpu_switches.h"
 #include "media/audio/audio_manager.h"
 #include "media/base/media_switches.h"
-#include "media/media_features.h"
-#include "media/mojo/features.h"
+#include "media/media_buildflags.h"
+#include "media/mojo/buildflags.h"
 #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
 #include "net/base/mime_util.h"
 #include "net/cookies/canonical_cookie.h"
@@ -1615,6 +1615,10 @@
   return isolated_origin_list;
 }
 
+bool ChromeContentBrowserClient::ShouldEnableStrictSiteIsolation() {
+  return base::FeatureList::IsEnabled(features::kSitePerProcess);
+}
+
 bool ChromeContentBrowserClient::IsFileAccessAllowed(
     const base::FilePath& path,
     const base::FilePath& absolute_path,
@@ -3903,9 +3907,23 @@
   // This logic should match
   // ChromeExtensionWebContentsObserver::RenderFrameCreated.
   WebContents* web_contents = WebContents::FromRenderFrameHost(frame_host);
-  if (!web_contents) {
+  if (!web_contents)
     return;
+
+  Profile* profile =
+      Profile::FromBrowserContext(web_contents->GetBrowserContext());
+  InstantService* instant_service =
+      InstantServiceFactory::GetForProfile(profile);
+  // The test below matches what's done by ShouldServiceRequestIOThread in
+  // local_ntp_source.cc.
+  if (instant_service->IsInstantProcess(frame_host->GetProcess()->GetID())) {
+    factories->emplace(
+        chrome::kChromeSearchScheme,
+        content::CreateWebUIURLLoader(
+            frame_host, chrome::kChromeSearchScheme,
+            /*allowed_webui_hosts=*/base::flat_set<std::string>()));
   }
+
   extensions::ChromeExtensionWebContentsObserver* web_observer =
       extensions::ChromeExtensionWebContentsObserver::FromWebContents(
           web_contents);
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index 7fd8a17..61fd92f 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -22,7 +22,7 @@
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/common/resource_type.h"
 #include "extensions/buildflags/buildflags.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "ppapi/features/features.h"
 #include "services/network/public/mojom/network_service.mojom.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
@@ -147,6 +147,7 @@
       const GURL& new_url) override;
   bool ShouldAssignSiteForURL(const GURL& url) override;
   std::vector<url::Origin> GetOriginsRequiringDedicatedProcess() override;
+  bool ShouldEnableStrictSiteIsolation() override;
   bool IsFileAccessAllowed(const base::FilePath& path,
                            const base::FilePath& absolute_path,
                            const base::FilePath& profile_path) override;
diff --git a/chrome/browser/chrome_content_browser_client_unittest.cc b/chrome/browser/chrome_content_browser_client_unittest.cc
index 85e70d4e..df3c4f6e 100644
--- a/chrome/browser/chrome_content_browser_client_unittest.cc
+++ b/chrome/browser/chrome_content_browser_client_unittest.cc
@@ -35,7 +35,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/test_browser_thread_bundle.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 4b812d2..c93b57e 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -30,7 +30,6 @@
     "//chrome/app/theme:theme_resources",
     "//chromeos:power_manager_proto",
     "//components/policy/proto",
-    "//components/wallpaper",
     "//content/app/resources",
     "//ui/chromeos/resources",
     "//ui/chromeos/strings",
diff --git a/chrome/browser/chromeos/DEPS b/chrome/browser/chromeos/DEPS
index c779c1f7..91e6cde 100644
--- a/chrome/browser/chromeos/DEPS
+++ b/chrome/browser/chromeos/DEPS
@@ -18,7 +18,6 @@
   "+components/ownership",
   "+components/session_manager/core",
   "+components/user_manager",
-  "+components/wallpaper",
   "+cros",
   "+dbus",
   "+device/bluetooth",
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.cc b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
index a3b6b006..c351727 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager.cc
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
@@ -238,7 +238,6 @@
           ash::prefs::kAccessibilityCursorHighlightEnabled),
       focus_highlight_pref_handler_(
           ash::prefs::kAccessibilityFocusHighlightEnabled),
-      tap_dragging_pref_handler_(ash::prefs::kTapDraggingEnabled),
       select_to_speak_pref_handler_(
           ash::prefs::kAccessibilitySelectToSpeakEnabled),
       switch_access_pref_handler_(
@@ -362,8 +361,7 @@
         prefs->GetBoolean(ash::prefs::kAccessibilityMonoAudioEnabled) ||
         prefs->GetBoolean(ash::prefs::kAccessibilityCaretHighlightEnabled) ||
         prefs->GetBoolean(ash::prefs::kAccessibilityCursorHighlightEnabled) ||
-        prefs->GetBoolean(ash::prefs::kAccessibilityFocusHighlightEnabled) ||
-        prefs->GetBoolean(ash::prefs::kTapDraggingEnabled))
+        prefs->GetBoolean(ash::prefs::kAccessibilityFocusHighlightEnabled))
       return true;
   }
   return false;
@@ -756,27 +754,6 @@
   NotifyAccessibilityStatusChanged(details);
 }
 
-void AccessibilityManager::EnableTapDragging(bool enabled) {
-  if (!profile_)
-    return;
-
-  PrefService* pref_service = profile_->GetPrefs();
-  pref_service->SetBoolean(ash::prefs::kTapDraggingEnabled, enabled);
-  pref_service->CommitPendingWrite();
-}
-
-bool AccessibilityManager::IsTapDraggingEnabled() const {
-  return profile_ &&
-         profile_->GetPrefs()->GetBoolean(ash::prefs::kTapDraggingEnabled);
-}
-
-void AccessibilityManager::OnTapDraggingChanged() {
-  AccessibilityStatusEventDetails details(ACCESSIBILITY_TOGGLE_TAP_DRAGGING,
-                                          IsTapDraggingEnabled(),
-                                          ash::A11Y_NOTIFICATION_NONE);
-  NotifyAccessibilityStatusChanged(details);
-}
-
 void AccessibilityManager::SetSelectToSpeakEnabled(bool enabled) {
   if (!profile_)
     return;
@@ -1005,10 +982,6 @@
         base::Bind(&AccessibilityManager::OnFocusHighlightChanged,
                    base::Unretained(this)));
     pref_change_registrar_->Add(
-        ash::prefs::kTapDraggingEnabled,
-        base::Bind(&AccessibilityManager::OnTapDraggingChanged,
-                   base::Unretained(this)));
-    pref_change_registrar_->Add(
         ash::prefs::kAccessibilitySelectToSpeakEnabled,
         base::Bind(&AccessibilityManager::OnSelectToSpeakChanged,
                    base::Unretained(this)));
@@ -1045,7 +1018,6 @@
   caret_highlight_pref_handler_.HandleProfileChanged(profile_, profile);
   cursor_highlight_pref_handler_.HandleProfileChanged(profile_, profile);
   focus_highlight_pref_handler_.HandleProfileChanged(profile_, profile);
-  tap_dragging_pref_handler_.HandleProfileChanged(profile_, profile);
   select_to_speak_pref_handler_.HandleProfileChanged(profile_, profile);
   switch_access_pref_handler_.HandleProfileChanged(profile_, profile);
 
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.h b/chrome/browser/chromeos/accessibility/accessibility_manager.h
index 9712390..ad5ba4a 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager.h
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager.h
@@ -57,7 +57,6 @@
   ACCESSIBILITY_TOGGLE_CARET_HIGHLIGHT,
   ACCESSIBILITY_TOGGLE_CURSOR_HIGHLIGHT,
   ACCESSIBILITY_TOGGLE_FOCUS_HIGHLIGHT,
-  ACCESSIBILITY_TOGGLE_TAP_DRAGGING,
 };
 
 struct AccessibilityStatusEventDetails {
@@ -409,7 +408,6 @@
   PrefHandler caret_highlight_pref_handler_;
   PrefHandler cursor_highlight_pref_handler_;
   PrefHandler focus_highlight_pref_handler_;
-  PrefHandler tap_dragging_pref_handler_;
   PrefHandler select_to_speak_pref_handler_;
   PrefHandler switch_access_pref_handler_;
 
diff --git a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc
index d66a241..92ef992b 100644
--- a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc
+++ b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc
@@ -385,7 +385,9 @@
     cached_computed_bounds_[node] = ComputeEnclosingBounds(node);
   }
 
-  ExtensionMsg_AccessibilityEventParams params;
+  std::vector<ExtensionMsg_AccessibilityEventParams> events;
+  events.emplace_back();
+  ExtensionMsg_AccessibilityEventParams& params = events.back();
   params.event_type = ToAXEvent(event_data->event_type);
 
   params.tree_id = tree_id();
@@ -404,7 +406,7 @@
 
   extensions::AutomationEventRouter* router =
       extensions::AutomationEventRouter::GetInstance();
-  router->DispatchAccessibilityEvent(params);
+  router->DispatchAccessibilityEvents(events);
 }
 
 void AXTreeSourceArc::NotifyActionResult(const ui::AXActionData& data,
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_async_file_util.cc b/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_async_file_util.cc
index b267fb3..a852bee 100644
--- a/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_async_file_util.cc
+++ b/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_async_file_util.cc
@@ -15,7 +15,7 @@
 
 namespace {
 
-void OnGetFileSize(const storage::AsyncFileUtil::GetFileInfoCallback& callback,
+void OnGetFileSize(storage::AsyncFileUtil::GetFileInfoCallback callback,
                    int64_t size) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   base::File::Info info;
@@ -25,7 +25,7 @@
   } else {
     info.size = size;
   }
-  callback.Run(error, info);
+  std::move(callback).Run(error, info);
 }
 
 }  // namespace
@@ -40,21 +40,21 @@
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
     int file_flags,
-    const CreateOrOpenCallback& callback) {
+    CreateOrOpenCallback callback) {
   NOTIMPLEMENTED();
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE,
-      base::BindOnce(callback, base::Passed(base::File()), base::Closure()));
+      FROM_HERE, base::BindOnce(std::move(callback), base::Passed(base::File()),
+                                base::Closure()));
 }
 
 void ArcContentFileSystemAsyncFileUtil::EnsureFileExists(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const EnsureFileExistsCallback& callback) {
+    EnsureFileExistsCallback callback) {
   NOTIMPLEMENTED();
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE,
-      base::BindOnce(callback, base::File::FILE_ERROR_FAILED, false));
+      FROM_HERE, base::BindOnce(std::move(callback),
+                                base::File::FILE_ERROR_FAILED, false));
 }
 
 void ArcContentFileSystemAsyncFileUtil::CreateDirectory(
@@ -62,30 +62,33 @@
     const storage::FileSystemURL& url,
     bool exclusive,
     bool recursive,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   NOTIMPLEMENTED();
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(callback, base::File::FILE_ERROR_FAILED));
+      FROM_HERE,
+      base::BindOnce(std::move(callback), base::File::FILE_ERROR_FAILED));
 }
 
 void ArcContentFileSystemAsyncFileUtil::GetFileInfo(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
     int fields,
-    const GetFileInfoCallback& callback) {
+    GetFileInfoCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   file_system_operation_runner_util::GetFileSizeOnIOThread(
-      FileSystemUrlToArcUrl(url), base::Bind(&OnGetFileSize, callback));
+      FileSystemUrlToArcUrl(url),
+      base::BindOnce(&OnGetFileSize, std::move(callback)));
 }
 
 void ArcContentFileSystemAsyncFileUtil::ReadDirectory(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const ReadDirectoryCallback& callback) {
+    ReadDirectoryCallback callback) {
   NOTIMPLEMENTED();
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(callback, base::File::FILE_ERROR_FAILED,
-                                EntryList(), false));
+      FROM_HERE,
+      base::BindOnce(std::move(callback), base::File::FILE_ERROR_FAILED,
+                     EntryList(), false));
 }
 
 void ArcContentFileSystemAsyncFileUtil::Touch(
@@ -93,20 +96,22 @@
     const storage::FileSystemURL& url,
     const base::Time& last_access_time,
     const base::Time& last_modified_time,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   NOTIMPLEMENTED();
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(callback, base::File::FILE_ERROR_FAILED));
+      FROM_HERE,
+      base::BindOnce(std::move(callback), base::File::FILE_ERROR_FAILED));
 }
 
 void ArcContentFileSystemAsyncFileUtil::Truncate(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
     int64_t length,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   NOTIMPLEMENTED();
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(callback, base::File::FILE_ERROR_FAILED));
+      FROM_HERE,
+      base::BindOnce(std::move(callback), base::File::FILE_ERROR_FAILED));
 }
 
 void ArcContentFileSystemAsyncFileUtil::CopyFileLocal(
@@ -114,11 +119,12 @@
     const storage::FileSystemURL& src_url,
     const storage::FileSystemURL& dest_url,
     CopyOrMoveOption option,
-    const CopyFileProgressCallback& progress_callback,
-    const StatusCallback& callback) {
+    CopyFileProgressCallback progress_callback,
+    StatusCallback callback) {
   NOTIMPLEMENTED();
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(callback, base::File::FILE_ERROR_FAILED));
+      FROM_HERE,
+      base::BindOnce(std::move(callback), base::File::FILE_ERROR_FAILED));
 }
 
 void ArcContentFileSystemAsyncFileUtil::MoveFileLocal(
@@ -126,57 +132,62 @@
     const storage::FileSystemURL& src_url,
     const storage::FileSystemURL& dest_url,
     CopyOrMoveOption option,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   NOTIMPLEMENTED();
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(callback, base::File::FILE_ERROR_FAILED));
+      FROM_HERE,
+      base::BindOnce(std::move(callback), base::File::FILE_ERROR_FAILED));
 }
 
 void ArcContentFileSystemAsyncFileUtil::CopyInForeignFile(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const base::FilePath& src_file_path,
     const storage::FileSystemURL& dest_url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   NOTIMPLEMENTED();
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(callback, base::File::FILE_ERROR_FAILED));
+      FROM_HERE,
+      base::BindOnce(std::move(callback), base::File::FILE_ERROR_FAILED));
 }
 
 void ArcContentFileSystemAsyncFileUtil::DeleteFile(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   NOTIMPLEMENTED();
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(callback, base::File::FILE_ERROR_FAILED));
+      FROM_HERE,
+      base::BindOnce(std::move(callback), base::File::FILE_ERROR_FAILED));
 }
 
 void ArcContentFileSystemAsyncFileUtil::DeleteDirectory(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   NOTIMPLEMENTED();
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(callback, base::File::FILE_ERROR_FAILED));
+      FROM_HERE,
+      base::BindOnce(std::move(callback), base::File::FILE_ERROR_FAILED));
 }
 
 void ArcContentFileSystemAsyncFileUtil::DeleteRecursively(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   NOTIMPLEMENTED();
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(callback, base::File::FILE_ERROR_FAILED));
+      FROM_HERE,
+      base::BindOnce(std::move(callback), base::File::FILE_ERROR_FAILED));
 }
 
 void ArcContentFileSystemAsyncFileUtil::CreateSnapshotFile(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const CreateSnapshotFileCallback& callback) {
+    CreateSnapshotFileCallback callback) {
   NOTIMPLEMENTED();
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE,
-      base::BindOnce(callback, base::File::FILE_ERROR_FAILED,
+      base::BindOnce(std::move(callback), base::File::FILE_ERROR_FAILED,
                      base::File::Info(), base::FilePath(),
                      scoped_refptr<storage::ShareableFileReference>()));
 }
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_async_file_util.h b/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_async_file_util.h
index 2bcf74f..3d1e647 100644
--- a/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_async_file_util.h
+++ b/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_async_file_util.h
@@ -21,67 +21,67 @@
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
       int file_flags,
-      const CreateOrOpenCallback& callback) override;
+      CreateOrOpenCallback callback) override;
   void EnsureFileExists(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const EnsureFileExistsCallback& callback) override;
+      EnsureFileExistsCallback callback) override;
   void CreateDirectory(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
       bool exclusive,
       bool recursive,
-      const StatusCallback& callback) override;
+      StatusCallback callback) override;
   void GetFileInfo(std::unique_ptr<storage::FileSystemOperationContext> context,
                    const storage::FileSystemURL& url,
                    int fields,
-                   const GetFileInfoCallback& callback) override;
+                   GetFileInfoCallback callback) override;
   void ReadDirectory(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const ReadDirectoryCallback& callback) override;
+      ReadDirectoryCallback callback) override;
   void Touch(std::unique_ptr<storage::FileSystemOperationContext> context,
              const storage::FileSystemURL& url,
              const base::Time& last_access_time,
              const base::Time& last_modified_time,
-             const StatusCallback& callback) override;
+             StatusCallback callback) override;
   void Truncate(std::unique_ptr<storage::FileSystemOperationContext> context,
                 const storage::FileSystemURL& url,
                 int64_t length,
-                const StatusCallback& callback) override;
+                StatusCallback callback) override;
   void CopyFileLocal(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& src_url,
       const storage::FileSystemURL& dest_url,
       CopyOrMoveOption option,
-      const CopyFileProgressCallback& progress_callback,
-      const StatusCallback& callback) override;
+      CopyFileProgressCallback progress_callback,
+      StatusCallback callback) override;
   void MoveFileLocal(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& src_url,
       const storage::FileSystemURL& dest_url,
       CopyOrMoveOption option,
-      const StatusCallback& callback) override;
+      StatusCallback callback) override;
   void CopyInForeignFile(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const base::FilePath& src_file_path,
       const storage::FileSystemURL& dest_url,
-      const StatusCallback& callback) override;
+      StatusCallback callback) override;
   void DeleteFile(std::unique_ptr<storage::FileSystemOperationContext> context,
                   const storage::FileSystemURL& url,
-                  const StatusCallback& callback) override;
+                  StatusCallback callback) override;
   void DeleteDirectory(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const StatusCallback& callback) override;
+      StatusCallback callback) override;
   void DeleteRecursively(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const StatusCallback& callback) override;
+      StatusCallback callback) override;
   void CreateSnapshotFile(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const CreateSnapshotFileCallback& callback) override;
+      CreateSnapshotFileCallback callback) override;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ArcContentFileSystemAsyncFileUtil);
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_async_file_util.cc b/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_async_file_util.cc
index 8580d4f..33e2b5f6 100644
--- a/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_async_file_util.cc
+++ b/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_async_file_util.cc
@@ -36,7 +36,7 @@
 }
 
 void OnReadDirectoryOnUIThread(
-    const storage::AsyncFileUtil::ReadDirectoryCallback& callback,
+    storage::AsyncFileUtil::ReadDirectoryCallback callback,
     base::File::Error result,
     std::vector<ArcDocumentsProviderRoot::ThinFileInfo> files) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -48,9 +48,9 @@
                                         ? storage::DirectoryEntry::DIRECTORY
                                         : storage::DirectoryEntry::FILE);
 
-  BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      base::BindOnce(callback, result, entries, false /* has_more */));
+  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+                          base::BindOnce(std::move(callback), result, entries,
+                                         false /* has_more */));
 }
 
 void GetFileInfoOnUIThread(
@@ -80,25 +80,27 @@
 
 void ReadDirectoryOnUIThread(
     const storage::FileSystemURL& url,
-    const storage::AsyncFileUtil::ReadDirectoryCallback& callback) {
+    storage::AsyncFileUtil::ReadDirectoryCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   ArcDocumentsProviderRootMap* roots =
       ArcDocumentsProviderRootMap::GetForArcBrowserContext();
   if (!roots) {
-    OnReadDirectoryOnUIThread(callback, base::File::FILE_ERROR_SECURITY, {});
+    OnReadDirectoryOnUIThread(std::move(callback),
+                              base::File::FILE_ERROR_SECURITY, {});
     return;
   }
 
   base::FilePath path;
   ArcDocumentsProviderRoot* root = roots->ParseAndLookup(url, &path);
   if (!root) {
-    OnReadDirectoryOnUIThread(callback, base::File::FILE_ERROR_NOT_FOUND, {});
+    OnReadDirectoryOnUIThread(std::move(callback),
+                              base::File::FILE_ERROR_NOT_FOUND, {});
     return;
   }
 
-  root->ReadDirectory(path,
-                      base::BindOnce(&OnReadDirectoryOnUIThread, callback));
+  root->ReadDirectory(
+      path, base::BindOnce(&OnReadDirectoryOnUIThread, std::move(callback)));
 }
 
 }  // namespace
@@ -113,21 +115,21 @@
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
     int file_flags,
-    const CreateOrOpenCallback& callback) {
+    CreateOrOpenCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   // TODO(nya): Implement this function if it is ever called.
   NOTIMPLEMENTED();
-  callback.Run(base::File(base::File::FILE_ERROR_INVALID_OPERATION),
-               base::Closure());
+  std::move(callback).Run(base::File(base::File::FILE_ERROR_INVALID_OPERATION),
+                          base::Closure());
 }
 
 void ArcDocumentsProviderAsyncFileUtil::EnsureFileExists(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const EnsureFileExistsCallback& callback) {
+    EnsureFileExistsCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   NOTREACHED();  // Read-only file system.
-  callback.Run(base::File::FILE_ERROR_ACCESS_DENIED, false);
+  std::move(callback).Run(base::File::FILE_ERROR_ACCESS_DENIED, false);
 }
 
 void ArcDocumentsProviderAsyncFileUtil::CreateDirectory(
@@ -135,29 +137,29 @@
     const storage::FileSystemURL& url,
     bool exclusive,
     bool recursive,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   NOTREACHED();  // Read-only file system.
-  callback.Run(base::File::FILE_ERROR_ACCESS_DENIED);
+  std::move(callback).Run(base::File::FILE_ERROR_ACCESS_DENIED);
 }
 
 void ArcDocumentsProviderAsyncFileUtil::GetFileInfo(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
     int fields,
-    const GetFileInfoCallback& callback) {
+    GetFileInfoCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK_EQ(storage::kFileSystemTypeArcDocumentsProvider, url.type());
 
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
-      base::BindOnce(&GetFileInfoOnUIThread, url, fields, callback));
+      base::BindOnce(&GetFileInfoOnUIThread, url, fields, std::move(callback)));
 }
 
 void ArcDocumentsProviderAsyncFileUtil::ReadDirectory(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const ReadDirectoryCallback& callback) {
+    ReadDirectoryCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK_EQ(storage::kFileSystemTypeArcDocumentsProvider, url.type());
 
@@ -171,20 +173,20 @@
     const storage::FileSystemURL& url,
     const base::Time& last_access_time,
     const base::Time& last_modified_time,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   NOTREACHED();  // Read-only file system.
-  callback.Run(base::File::FILE_ERROR_ACCESS_DENIED);
+  std::move(callback).Run(base::File::FILE_ERROR_ACCESS_DENIED);
 }
 
 void ArcDocumentsProviderAsyncFileUtil::Truncate(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
     int64_t length,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   NOTREACHED();  // Read-only file system.
-  callback.Run(base::File::FILE_ERROR_ACCESS_DENIED);
+  std::move(callback).Run(base::File::FILE_ERROR_ACCESS_DENIED);
 }
 
 void ArcDocumentsProviderAsyncFileUtil::CopyFileLocal(
@@ -192,11 +194,11 @@
     const storage::FileSystemURL& src_url,
     const storage::FileSystemURL& dest_url,
     CopyOrMoveOption option,
-    const CopyFileProgressCallback& progress_callback,
-    const StatusCallback& callback) {
+    CopyFileProgressCallback progress_callback,
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   NOTREACHED();  // Read-only file system.
-  callback.Run(base::File::FILE_ERROR_ACCESS_DENIED);
+  std::move(callback).Run(base::File::FILE_ERROR_ACCESS_DENIED);
 }
 
 void ArcDocumentsProviderAsyncFileUtil::MoveFileLocal(
@@ -204,58 +206,58 @@
     const storage::FileSystemURL& src_url,
     const storage::FileSystemURL& dest_url,
     CopyOrMoveOption option,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   NOTREACHED();  // Read-only file system.
-  callback.Run(base::File::FILE_ERROR_ACCESS_DENIED);
+  std::move(callback).Run(base::File::FILE_ERROR_ACCESS_DENIED);
 }
 
 void ArcDocumentsProviderAsyncFileUtil::CopyInForeignFile(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const base::FilePath& src_file_path,
     const storage::FileSystemURL& dest_url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   NOTREACHED();  // Read-only file system.
-  callback.Run(base::File::FILE_ERROR_ACCESS_DENIED);
+  std::move(callback).Run(base::File::FILE_ERROR_ACCESS_DENIED);
 }
 
 void ArcDocumentsProviderAsyncFileUtil::DeleteFile(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   NOTREACHED();  // Read-only file system.
-  callback.Run(base::File::FILE_ERROR_ACCESS_DENIED);
+  std::move(callback).Run(base::File::FILE_ERROR_ACCESS_DENIED);
 }
 
 void ArcDocumentsProviderAsyncFileUtil::DeleteDirectory(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   NOTREACHED();  // Read-only file system.
-  callback.Run(base::File::FILE_ERROR_ACCESS_DENIED);
+  std::move(callback).Run(base::File::FILE_ERROR_ACCESS_DENIED);
 }
 
 void ArcDocumentsProviderAsyncFileUtil::DeleteRecursively(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   NOTREACHED();  // Read-only file system.
-  callback.Run(base::File::FILE_ERROR_ACCESS_DENIED);
+  std::move(callback).Run(base::File::FILE_ERROR_ACCESS_DENIED);
 }
 
 void ArcDocumentsProviderAsyncFileUtil::CreateSnapshotFile(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const CreateSnapshotFileCallback& callback) {
+    CreateSnapshotFileCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   NOTIMPLEMENTED();  // TODO(crbug.com/671511): Implement this function.
-  callback.Run(base::File::FILE_ERROR_FAILED, base::File::Info(),
-               base::FilePath(),
-               scoped_refptr<storage::ShareableFileReference>());
+  std::move(callback).Run(base::File::FILE_ERROR_FAILED, base::File::Info(),
+                          base::FilePath(),
+                          scoped_refptr<storage::ShareableFileReference>());
 }
 
 }  // namespace arc
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_async_file_util.h b/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_async_file_util.h
index 24037e2..0a69c49a 100644
--- a/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_async_file_util.h
+++ b/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_async_file_util.h
@@ -26,67 +26,67 @@
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
       int file_flags,
-      const CreateOrOpenCallback& callback) override;
+      CreateOrOpenCallback callback) override;
   void EnsureFileExists(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const EnsureFileExistsCallback& callback) override;
+      EnsureFileExistsCallback callback) override;
   void CreateDirectory(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
       bool exclusive,
       bool recursive,
-      const StatusCallback& callback) override;
+      StatusCallback callback) override;
   void GetFileInfo(std::unique_ptr<storage::FileSystemOperationContext> context,
                    const storage::FileSystemURL& url,
                    int fields,
-                   const GetFileInfoCallback& callback) override;
+                   GetFileInfoCallback callback) override;
   void ReadDirectory(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const ReadDirectoryCallback& callback) override;
+      ReadDirectoryCallback callback) override;
   void Touch(std::unique_ptr<storage::FileSystemOperationContext> context,
              const storage::FileSystemURL& url,
              const base::Time& last_access_time,
              const base::Time& last_modified_time,
-             const StatusCallback& callback) override;
+             StatusCallback callback) override;
   void Truncate(std::unique_ptr<storage::FileSystemOperationContext> context,
                 const storage::FileSystemURL& url,
                 int64_t length,
-                const StatusCallback& callback) override;
+                StatusCallback callback) override;
   void CopyFileLocal(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& src_url,
       const storage::FileSystemURL& dest_url,
       CopyOrMoveOption option,
-      const CopyFileProgressCallback& progress_callback,
-      const StatusCallback& callback) override;
+      CopyFileProgressCallback progress_callback,
+      StatusCallback callback) override;
   void MoveFileLocal(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& src_url,
       const storage::FileSystemURL& dest_url,
       CopyOrMoveOption option,
-      const StatusCallback& callback) override;
+      StatusCallback callback) override;
   void CopyInForeignFile(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const base::FilePath& src_file_path,
       const storage::FileSystemURL& dest_url,
-      const StatusCallback& callback) override;
+      StatusCallback callback) override;
   void DeleteFile(std::unique_ptr<storage::FileSystemOperationContext> context,
                   const storage::FileSystemURL& url,
-                  const StatusCallback& callback) override;
+                  StatusCallback callback) override;
   void DeleteDirectory(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const StatusCallback& callback) override;
+      StatusCallback callback) override;
   void DeleteRecursively(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const StatusCallback& callback) override;
+      StatusCallback callback) override;
   void CreateSnapshotFile(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const CreateSnapshotFileCallback& callback) override;
+      CreateSnapshotFileCallback callback) override;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ArcDocumentsProviderAsyncFileUtil);
diff --git a/chrome/browser/chromeos/arc/print/arc_print_service.cc b/chrome/browser/chromeos/arc/print/arc_print_service.cc
index 41b23a6..c11d256 100644
--- a/chrome/browser/chromeos/arc/print/arc_print_service.cc
+++ b/chrome/browser/chromeos/arc/print/arc_print_service.cc
@@ -71,10 +71,10 @@
 
  protected:
   // chromeos::CupsPrintJobManager::Observer:
-  void OnPrintJobCreated(chromeos::CupsPrintJob* job) override;
-  void OnPrintJobCancelled(chromeos::CupsPrintJob* job) override;
-  void OnPrintJobError(chromeos::CupsPrintJob* job) override;
-  void OnPrintJobDone(chromeos::CupsPrintJob* job) override;
+  void OnPrintJobCreated(base::WeakPtr<chromeos::CupsPrintJob> job) override;
+  void OnPrintJobCancelled(base::WeakPtr<chromeos::CupsPrintJob> job) override;
+  void OnPrintJobError(base::WeakPtr<chromeos::CupsPrintJob> job) override;
+  void OnPrintJobDone(base::WeakPtr<chromeos::CupsPrintJob> job) override;
 
  private:
   Profile* const profile_;                      // Owned by ProfileManager.
@@ -504,25 +504,37 @@
       ->RemoveObserver(this);
 }
 
-void ArcPrintServiceImpl::OnPrintJobCreated(chromeos::CupsPrintJob* job) {
+void ArcPrintServiceImpl::OnPrintJobCreated(
+    base::WeakPtr<chromeos::CupsPrintJob> job) {
+  if (!job)
+    return;
   auto it = jobs_by_id_.find(job->GetUniqueId());
   if (it != jobs_by_id_.end())
-    it->second->CupsJobCreated(job);
+    it->second->CupsJobCreated(job.get());
 }
 
-void ArcPrintServiceImpl::OnPrintJobCancelled(chromeos::CupsPrintJob* job) {
+void ArcPrintServiceImpl::OnPrintJobCancelled(
+    base::WeakPtr<chromeos::CupsPrintJob> job) {
+  if (!job)
+    return;
   auto it = jobs_by_id_.find(job->GetUniqueId());
   if (it != jobs_by_id_.end())
     it->second->JobCanceled();
 }
 
-void ArcPrintServiceImpl::OnPrintJobError(chromeos::CupsPrintJob* job) {
+void ArcPrintServiceImpl::OnPrintJobError(
+    base::WeakPtr<chromeos::CupsPrintJob> job) {
+  if (!job)
+    return;
   auto it = jobs_by_id_.find(job->GetUniqueId());
   if (it != jobs_by_id_.end())
     it->second->JobError();
 }
 
-void ArcPrintServiceImpl::OnPrintJobDone(chromeos::CupsPrintJob* job) {
+void ArcPrintServiceImpl::OnPrintJobDone(
+    base::WeakPtr<chromeos::CupsPrintJob> job) {
+  if (!job)
+    return;
   auto it = jobs_by_id_.find(job->GetUniqueId());
   if (it != jobs_by_id_.end())
     it->second->JobDone();
diff --git a/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service.cc b/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service.cc
index 5043e11..8ea4acd 100644
--- a/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service.cc
+++ b/chrome/browser/chromeos/arc/wallpaper/arc_wallpaper_service.cc
@@ -17,8 +17,6 @@
 #include "components/signin/core/account_id/account_id.h"
 #include "components/user_manager/user.h"
 #include "components/user_manager/user_manager.h"
-#include "components/wallpaper/wallpaper_files_id.h"
-#include "components/wallpaper/wallpaper_info.h"
 #include "content/public/browser/browser_thread.h"
 #include "ui/gfx/codec/png_codec.h"
 #include "ui/gfx/geometry/size.h"
@@ -206,12 +204,12 @@
                                              int32_t android_id) {
   const AccountId account_id =
       UserManager::Get()->GetPrimaryUser()->GetAccountId();
-  const wallpaper::WallpaperFilesId wallpaper_files_id =
+  const std::string wallpaper_files_id =
       WallpaperControllerClient::Get()->GetFilesId(account_id);
 
   WallpaperControllerClient::Get()->SetThirdPartyWallpaper(
       account_id, wallpaper_files_id, kAndroidWallpaperFilename,
-      wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED, image,
+      ash::WALLPAPER_LAYOUT_CENTER_CROPPED, image,
       base::BindOnce(&ArcWallpaperService::OnSetThirdPartyWallpaperCallback,
                      weak_ptr_factory_.GetWeakPtr(), android_id));
 }
diff --git a/chrome/browser/chromeos/customization/customization_wallpaper_util.cc b/chrome/browser/chromeos/customization/customization_wallpaper_util.cc
index fb73ea8..2f3eeb7d 100644
--- a/chrome/browser/chromeos/customization/customization_wallpaper_util.cc
+++ b/chrome/browser/chromeos/customization/customization_wallpaper_util.cc
@@ -39,13 +39,13 @@
   bool success = true;
 
   success &= ash::WallpaperController::ResizeAndSaveWallpaper(
-      *image, resized_small_path, wallpaper::WALLPAPER_LAYOUT_STRETCH,
+      *image, resized_small_path, ash::WALLPAPER_LAYOUT_STRETCH,
       ash::WallpaperController::kSmallWallpaperMaxWidth,
       ash::WallpaperController::kSmallWallpaperMaxHeight,
       nullptr /*output_skia=*/);
 
   success &= ash::WallpaperController::ResizeAndSaveWallpaper(
-      *image, resized_large_path, wallpaper::WALLPAPER_LAYOUT_STRETCH,
+      *image, resized_large_path, ash::WALLPAPER_LAYOUT_STRETCH,
       ash::WallpaperController::kLargeWallpaperMaxWidth,
       ash::WallpaperController::kLargeWallpaperMaxHeight,
       nullptr /*output_skia=*/);
diff --git a/chrome/browser/chromeos/drive/fileapi/async_file_util.cc b/chrome/browser/chromeos/drive/fileapi/async_file_util.cc
index 3f746055..0aab2442 100644
--- a/chrome/browser/chromeos/drive/fileapi/async_file_util.cc
+++ b/chrome/browser/chromeos/drive/fileapi/async_file_util.cc
@@ -49,7 +49,7 @@
 
 // Runs CreateOrOpenFile callback based on the given |error| and |file|.
 void RunCreateOrOpenFileCallback(
-    const AsyncFileUtil::CreateOrOpenCallback& callback,
+    AsyncFileUtil::CreateOrOpenCallback callback,
     base::File file,
     const base::Closure& close_callback_on_ui_thread) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -57,7 +57,7 @@
   // It is necessary to make a closure, which runs on file closing here.
   // It will be provided as a FileSystem::OpenFileCallback's argument later.
   // (crbug.com/259184).
-  callback.Run(
+  std::move(callback).Run(
       std::move(file),
       base::Bind(&google_apis::RunTaskWithTaskRunner,
                  BrowserThread::GetTaskRunnerForThread(BrowserThread::UI),
@@ -66,14 +66,14 @@
 
 // Runs CreateOrOpenFile when the error happens.
 void RunCreateOrOpenFileCallbackOnError(
-    const AsyncFileUtil::CreateOrOpenCallback& callback,
+    AsyncFileUtil::CreateOrOpenCallback callback,
     base::File::Error error) {
-  callback.Run(base::File(error), base::Closure());
+  std::move(callback).Run(base::File(error), base::Closure());
 }
 
 // Runs EnsureFileExistsCallback based on the given |error|.
 void RunEnsureFileExistsCallback(
-    const AsyncFileUtil::EnsureFileExistsCallback& callback,
+    AsyncFileUtil::EnsureFileExistsCallback callback,
     base::File::Error error) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
@@ -84,12 +84,12 @@
   if (error == base::File::FILE_ERROR_EXISTS)
     error = base::File::FILE_OK;
 
-  callback.Run(error, created);
+  std::move(callback).Run(error, created);
 }
 
 // Runs |callback| with the arguments based on the given arguments.
 void RunCreateSnapshotFileCallback(
-    const AsyncFileUtil::CreateSnapshotFileCallback& callback,
+    AsyncFileUtil::CreateSnapshotFileCallback callback,
     base::File::Error error,
     const base::File::Info& file_info,
     const base::FilePath& local_path,
@@ -104,7 +104,8 @@
           local_path, scope_out_policy,
           base::CreateSequencedTaskRunnerWithTraits(
               {base::MayBlock(), base::TaskPriority::USER_BLOCKING})));
-  callback.Run(error, file_info, local_path, file_reference);
+  std::move(callback).Run(error, file_info, local_path,
+                          std::move(file_reference));
 }
 
 }  // namespace
@@ -119,12 +120,13 @@
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
     int file_flags,
-    const CreateOrOpenCallback& callback) {
+    CreateOrOpenCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   base::FilePath file_path = util::ExtractDrivePathFromFileSystemUrl(url);
   if (file_path.empty()) {
-    callback.Run(base::File(base::File::FILE_ERROR_NOT_FOUND), base::Closure());
+    std::move(callback).Run(base::File(base::File::FILE_ERROR_NOT_FOUND),
+                            base::Closure());
     return;
   }
 
@@ -143,12 +145,12 @@
 void AsyncFileUtil::EnsureFileExists(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const EnsureFileExistsCallback& callback) {
+    EnsureFileExistsCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   base::FilePath file_path = util::ExtractDrivePathFromFileSystemUrl(url);
   if (file_path.empty()) {
-    callback.Run(base::File::FILE_ERROR_NOT_FOUND, false);
+    std::move(callback).Run(base::File::FILE_ERROR_NOT_FOUND, false);
     return;
   }
 
@@ -166,12 +168,12 @@
     const storage::FileSystemURL& url,
     bool exclusive,
     bool recursive,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   base::FilePath file_path = util::ExtractDrivePathFromFileSystemUrl(url);
   if (file_path.empty()) {
-    callback.Run(base::File::FILE_ERROR_NOT_FOUND);
+    std::move(callback).Run(base::File::FILE_ERROR_NOT_FOUND);
     return;
   }
 
@@ -187,12 +189,13 @@
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
     int /* fields */,
-    const GetFileInfoCallback& callback) {
+    GetFileInfoCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   base::FilePath file_path = util::ExtractDrivePathFromFileSystemUrl(url);
   if (file_path.empty()) {
-    callback.Run(base::File::FILE_ERROR_NOT_FOUND, base::File::Info());
+    std::move(callback).Run(base::File::FILE_ERROR_NOT_FOUND,
+                            base::File::Info());
     return;
   }
 
@@ -207,7 +210,7 @@
 void AsyncFileUtil::ReadDirectory(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const ReadDirectoryCallback& callback) {
+    ReadDirectoryCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   base::FilePath file_path = util::ExtractDrivePathFromFileSystemUrl(url);
@@ -229,12 +232,12 @@
     const storage::FileSystemURL& url,
     const base::Time& last_access_time,
     const base::Time& last_modified_time,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   base::FilePath file_path = util::ExtractDrivePathFromFileSystemUrl(url);
   if (file_path.empty()) {
-    callback.Run(base::File::FILE_ERROR_NOT_FOUND);
+    std::move(callback).Run(base::File::FILE_ERROR_NOT_FOUND);
     return;
   }
 
@@ -250,12 +253,12 @@
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
     int64_t length,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   base::FilePath file_path = util::ExtractDrivePathFromFileSystemUrl(url);
   if (file_path.empty()) {
-    callback.Run(base::File::FILE_ERROR_NOT_FOUND);
+    std::move(callback).Run(base::File::FILE_ERROR_NOT_FOUND);
     return;
   }
 
@@ -271,14 +274,14 @@
     const storage::FileSystemURL& src_url,
     const storage::FileSystemURL& dest_url,
     CopyOrMoveOption option,
-    const CopyFileProgressCallback& progress_callback,
-    const StatusCallback& callback) {
+    CopyFileProgressCallback progress_callback,
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   base::FilePath src_path = util::ExtractDrivePathFromFileSystemUrl(src_url);
   base::FilePath dest_path = util::ExtractDrivePathFromFileSystemUrl(dest_url);
   if (src_path.empty() || dest_path.empty()) {
-    callback.Run(base::File::FILE_ERROR_NOT_FOUND);
+    std::move(callback).Run(base::File::FILE_ERROR_NOT_FOUND);
     return;
   }
 
@@ -304,13 +307,13 @@
     const storage::FileSystemURL& src_url,
     const storage::FileSystemURL& dest_url,
     CopyOrMoveOption option,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   base::FilePath src_path = util::ExtractDrivePathFromFileSystemUrl(src_url);
   base::FilePath dest_path = util::ExtractDrivePathFromFileSystemUrl(dest_url);
   if (src_path.empty() || dest_path.empty()) {
-    callback.Run(base::File::FILE_ERROR_NOT_FOUND);
+    std::move(callback).Run(base::File::FILE_ERROR_NOT_FOUND);
     return;
   }
 
@@ -329,12 +332,12 @@
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const base::FilePath& src_file_path,
     const storage::FileSystemURL& dest_url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   base::FilePath dest_path = util::ExtractDrivePathFromFileSystemUrl(dest_url);
   if (dest_path.empty()) {
-    callback.Run(base::File::FILE_ERROR_NOT_FOUND);
+    std::move(callback).Run(base::File::FILE_ERROR_NOT_FOUND);
     return;
   }
 
@@ -349,12 +352,12 @@
 void AsyncFileUtil::DeleteFile(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   base::FilePath file_path = util::ExtractDrivePathFromFileSystemUrl(url);
   if (file_path.empty()) {
-    callback.Run(base::File::FILE_ERROR_NOT_FOUND);
+    std::move(callback).Run(base::File::FILE_ERROR_NOT_FOUND);
     return;
   }
 
@@ -369,12 +372,12 @@
 void AsyncFileUtil::DeleteDirectory(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   base::FilePath file_path = util::ExtractDrivePathFromFileSystemUrl(url);
   if (file_path.empty()) {
-    callback.Run(base::File::FILE_ERROR_NOT_FOUND);
+    std::move(callback).Run(base::File::FILE_ERROR_NOT_FOUND);
     return;
   }
 
@@ -389,12 +392,12 @@
 void AsyncFileUtil::DeleteRecursively(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   base::FilePath file_path = util::ExtractDrivePathFromFileSystemUrl(url);
   if (file_path.empty()) {
-    callback.Run(base::File::FILE_ERROR_NOT_FOUND);
+    std::move(callback).Run(base::File::FILE_ERROR_NOT_FOUND);
     return;
   }
 
@@ -409,15 +412,14 @@
 void AsyncFileUtil::CreateSnapshotFile(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const CreateSnapshotFileCallback& callback) {
+    CreateSnapshotFileCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   base::FilePath file_path = util::ExtractDrivePathFromFileSystemUrl(url);
   if (file_path.empty()) {
-    callback.Run(base::File::FILE_ERROR_NOT_FOUND,
-                 base::File::Info(),
-                 base::FilePath(),
-                 scoped_refptr<storage::ShareableFileReference>());
+    std::move(callback).Run(base::File::FILE_ERROR_NOT_FOUND,
+                            base::File::Info(), base::FilePath(),
+                            scoped_refptr<storage::ShareableFileReference>());
     return;
   }
 
diff --git a/chrome/browser/chromeos/drive/fileapi/async_file_util.h b/chrome/browser/chromeos/drive/fileapi/async_file_util.h
index 1297d25..24bd1f5 100644
--- a/chrome/browser/chromeos/drive/fileapi/async_file_util.h
+++ b/chrome/browser/chromeos/drive/fileapi/async_file_util.h
@@ -28,67 +28,67 @@
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
       int file_flags,
-      const CreateOrOpenCallback& callback) override;
+      CreateOrOpenCallback callback) override;
   void EnsureFileExists(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const EnsureFileExistsCallback& callback) override;
+      EnsureFileExistsCallback callback) override;
   void CreateDirectory(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
       bool exclusive,
       bool recursive,
-      const StatusCallback& callback) override;
+      StatusCallback callback) override;
   void GetFileInfo(std::unique_ptr<storage::FileSystemOperationContext> context,
                    const storage::FileSystemURL& url,
                    int fields,
-                   const GetFileInfoCallback& callback) override;
+                   GetFileInfoCallback callback) override;
   void ReadDirectory(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const ReadDirectoryCallback& callback) override;
+      ReadDirectoryCallback callback) override;
   void Touch(std::unique_ptr<storage::FileSystemOperationContext> context,
              const storage::FileSystemURL& url,
              const base::Time& last_access_time,
              const base::Time& last_modified_time,
-             const StatusCallback& callback) override;
+             StatusCallback callback) override;
   void Truncate(std::unique_ptr<storage::FileSystemOperationContext> context,
                 const storage::FileSystemURL& url,
                 int64_t length,
-                const StatusCallback& callback) override;
+                StatusCallback callback) override;
   void CopyFileLocal(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& src_url,
       const storage::FileSystemURL& dest_url,
       CopyOrMoveOption option,
-      const CopyFileProgressCallback& progress_callback,
-      const StatusCallback& callback) override;
+      CopyFileProgressCallback progress_callback,
+      StatusCallback callback) override;
   void MoveFileLocal(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& src_url,
       const storage::FileSystemURL& dest_url,
       CopyOrMoveOption option,
-      const StatusCallback& callback) override;
+      StatusCallback callback) override;
   void CopyInForeignFile(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const base::FilePath& src_file_path,
       const storage::FileSystemURL& dest_url,
-      const StatusCallback& callback) override;
+      StatusCallback callback) override;
   void DeleteFile(std::unique_ptr<storage::FileSystemOperationContext> context,
                   const storage::FileSystemURL& url,
-                  const StatusCallback& callback) override;
+                  StatusCallback callback) override;
   void DeleteDirectory(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const StatusCallback& callback) override;
+      StatusCallback callback) override;
   void DeleteRecursively(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const StatusCallback& callback) override;
+      StatusCallback callback) override;
   void CreateSnapshotFile(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const CreateSnapshotFileCallback& callback) override;
+      CreateSnapshotFileCallback callback) override;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(AsyncFileUtil);
diff --git a/chrome/browser/chromeos/extensions/DEPS b/chrome/browser/chromeos/extensions/DEPS
index fb9b35c..ee65a39 100644
--- a/chrome/browser/chromeos/extensions/DEPS
+++ b/chrome/browser/chromeos/extensions/DEPS
@@ -1,5 +1,4 @@
 include_rules = [
-  "+components/wallpaper",
   # TODO(tfarina): Get rid of this dependency. crbug.com/125846.
   # DO NOT ADD ANY MORE ITEMS TO THE LIST BELOW!
   "!chrome/browser/ui/views/select_file_dialog_extension.h",
diff --git a/chrome/browser/chromeos/extensions/wallpaper_api.cc b/chrome/browser/chromeos/extensions/wallpaper_api.cc
index 6b983a3..a08cd6ef 100644
--- a/chrome/browser/chromeos/extensions/wallpaper_api.cc
+++ b/chrome/browser/chromeos/extensions/wallpaper_api.cc
@@ -8,6 +8,7 @@
 #include <utility>
 #include <vector>
 
+#include "ash/public/cpp/wallpaper_types.h"
 #include "ash/wallpaper/wallpaper_controller.h"
 #include "base/files/file_util.h"
 #include "base/lazy_instance.h"
@@ -20,19 +21,20 @@
 #include "chrome/browser/chromeos/extensions/wallpaper_private_api.h"
 #include "chrome/browser/chromeos/file_manager/app_id.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/net/system_network_context_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/ash/wallpaper_controller_client.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "components/user_manager/user.h"
 #include "components/user_manager/user_manager.h"
-#include "components/wallpaper/wallpaper_info.h"
 #include "content/public/browser/browser_thread.h"
 #include "extensions/browser/event_router.h"
 #include "net/base/load_flags.h"
-#include "net/http/http_status_code.h"
-#include "net/url_request/url_fetcher.h"
-#include "net/url_request/url_fetcher_delegate.h"
+#include "net/http/http_response_headers.h"
+#include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/cpp/simple_url_loader.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
 #include "url/gurl.h"
 
 using base::Value;
@@ -44,52 +46,81 @@
 
 namespace {
 
-class WallpaperFetcher : public net::URLFetcherDelegate {
+class WallpaperFetcher {
  public:
   WallpaperFetcher() {}
 
-  ~WallpaperFetcher() override {}
-
   void FetchWallpaper(const GURL& url, FetchCallback callback) {
     CancelPreviousFetch();
+    original_url_ = url;
     callback_ = callback;
-    url_fetcher_ = net::URLFetcher::Create(url, net::URLFetcher::GET, this);
-    url_fetcher_->SetRequestContext(
-        g_browser_process->system_request_context());
-    url_fetcher_->SetLoadFlags(net::LOAD_DISABLE_CACHE);
-    url_fetcher_->Start();
+
+    net::NetworkTrafficAnnotationTag traffic_annotation =
+        net::DefineNetworkTrafficAnnotation("wallpaper_fetcher", R"(
+          semantics {
+            sender: "Wallpaper Fetcher"
+            description:
+              "Chrome OS downloads wallpaper upon user request."
+            trigger:
+              "When an app or extension requests to download "
+              "a wallpaper from a remote URL."
+            data:
+              "User-selected image."
+            destination: WEBSITE
+          }
+          policy {
+            cookies_allowed: YES
+            cookies_store: "user"
+            setting:
+              "This feature cannot be disabled by settings, but it is only "
+              "triggered by user request."
+            policy_exception_justification: "Not implemented."
+          })");
+    auto resource_request = std::make_unique<network::ResourceRequest>();
+    resource_request->url = original_url_;
+    resource_request->load_flags = net::LOAD_DISABLE_CACHE;
+    simple_loader_ = network::SimpleURLLoader::Create(
+        std::move(resource_request), traffic_annotation);
+    network::mojom::URLLoaderFactory* loader_factory =
+        g_browser_process->system_network_context_manager()
+            ->GetURLLoaderFactory();
+    simple_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
+        loader_factory,
+        base::BindOnce(&WallpaperFetcher::OnSimpleLoaderComplete,
+                       base::Unretained(this)));
   }
 
  private:
-  // URLFetcherDelegate overrides:
-  void OnURLFetchComplete(const net::URLFetcher* source) override {
-    DCHECK(url_fetcher_.get() == source);
-
-    bool success = source->GetStatus().is_success() &&
-                   source->GetResponseCode() == net::HTTP_OK;
+  void OnSimpleLoaderComplete(std::unique_ptr<std::string> response_body) {
     std::string response;
-    if (success) {
-      source->GetResponseAsString(&response);
-    } else {
+    bool success = false;
+    if (response_body) {
+      response = std::move(*response_body);
+      success = true;
+    } else if (simple_loader_->ResponseInfo() &&
+               simple_loader_->ResponseInfo()->headers) {
+      int response_code =
+          simple_loader_->ResponseInfo()->headers->response_code();
       response = base::StringPrintf(
           "Downloading wallpaper %s failed. The response code is %d.",
-          source->GetOriginalURL().ExtractFileName().c_str(),
-          source->GetResponseCode());
+          original_url_.ExtractFileName().c_str(), response_code);
     }
-    url_fetcher_.reset();
+
+    simple_loader_.reset();
     callback_.Run(success, response);
     callback_.Reset();
   }
 
   void CancelPreviousFetch() {
-    if (url_fetcher_.get()) {
+    if (simple_loader_.get()) {
       callback_.Run(false, wallpaper_api_util::kCancelWallpaperMessage);
       callback_.Reset();
-      url_fetcher_.reset();
+      simple_loader_.reset();
     }
   }
 
-  std::unique_ptr<net::URLFetcher> url_fetcher_;
+  GURL original_url_;
+  std::unique_ptr<network::SimpleURLLoader> simple_loader_;
   FetchCallback callback_;
 };
 
@@ -151,16 +182,16 @@
   base::FilePath thumbnail_path =
       ash::WallpaperController::GetCustomWallpaperPath(
           ash::WallpaperController::kThumbnailWallpaperSubDir,
-          wallpaper_files_id_.id(), params_->details.filename);
+          wallpaper_files_id_, params_->details.filename);
 
-  wallpaper::WallpaperLayout layout = wallpaper_api_util::GetLayoutEnum(
+  ash::WallpaperLayout layout = wallpaper_api_util::GetLayoutEnum(
       extensions::api::wallpaper::ToString(params_->details.layout));
   wallpaper_api_util::RecordCustomWallpaperLayout(layout);
 
   WallpaperControllerClient::Get()->SetCustomWallpaper(
       account_id_, wallpaper_files_id_, params_->details.filename, layout,
       image, false /*preview_mode=*/);
-  unsafe_wallpaper_decoder_ = NULL;
+  unsafe_wallpaper_decoder_ = nullptr;
 
   if (!params_->details.thumbnail)
     SendResponse(true);
@@ -186,14 +217,14 @@
 
   scoped_refptr<base::RefCountedBytes> original_data;
   scoped_refptr<base::RefCountedBytes> thumbnail_data;
+  ash::WallpaperController::ResizeImage(*image, ash::WALLPAPER_LAYOUT_STRETCH,
+                                        image->width(), image->height(),
+                                        &original_data, nullptr);
   ash::WallpaperController::ResizeImage(
-      *image, wallpaper::WALLPAPER_LAYOUT_STRETCH, image->width(),
-      image->height(), &original_data, NULL);
-  ash::WallpaperController::ResizeImage(
-      *image, wallpaper::WALLPAPER_LAYOUT_STRETCH,
+      *image, ash::WALLPAPER_LAYOUT_STRETCH,
       ash::WallpaperController::kWallpaperThumbnailWidth,
       ash::WallpaperController::kWallpaperThumbnailHeight, &thumbnail_data,
-      NULL);
+      nullptr);
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
       base::BindOnce(&WallpaperSetWallpaperFunction::ThumbnailGenerated, this,
diff --git a/chrome/browser/chromeos/extensions/wallpaper_api.h b/chrome/browser/chromeos/extensions/wallpaper_api.h
index e3f4e58..2592b1d8 100644
--- a/chrome/browser/chromeos/extensions/wallpaper_api.h
+++ b/chrome/browser/chromeos/extensions/wallpaper_api.h
@@ -10,7 +10,6 @@
 #include "chrome/browser/chromeos/extensions/wallpaper_function_base.h"
 #include "chrome/common/extensions/api/wallpaper.h"
 #include "components/signin/core/account_id/account_id.h"
-#include "components/wallpaper/wallpaper_files_id.h"
 #include "net/url_request/url_request_status.h"
 
 namespace base {
@@ -62,7 +61,7 @@
   AccountId account_id_ = EmptyAccountId();
 
   // Id used to identify user wallpaper files on hard drive.
-  wallpaper::WallpaperFilesId wallpaper_files_id_;
+  std::string wallpaper_files_id_;
 };
 
 #endif  // CHROME_BROWSER_CHROMEOS_EXTENSIONS_WALLPAPER_API_H_
diff --git a/chrome/browser/chromeos/extensions/wallpaper_function_base.cc b/chrome/browser/chromeos/extensions/wallpaper_function_base.cc
index c07991c..abf51a5 100644
--- a/chrome/browser/chromeos/extensions/wallpaper_function_base.cc
+++ b/chrome/browser/chromeos/extensions/wallpaper_function_base.cc
@@ -45,18 +45,18 @@
 
 const char kCancelWallpaperMessage[] = "Set wallpaper was canceled.";
 
-wallpaper::WallpaperLayout GetLayoutEnum(const std::string& layout) {
+ash::WallpaperLayout GetLayoutEnum(const std::string& layout) {
   for (int i = 0; i < kWallpaperLayoutCount; i++) {
     if (layout.compare(kWallpaperLayoutArrays[i]) == 0)
-      return static_cast<wallpaper::WallpaperLayout>(i);
+      return static_cast<ash::WallpaperLayout>(i);
   }
   // Default to use CENTER layout.
-  return wallpaper::WALLPAPER_LAYOUT_CENTER;
+  return ash::WALLPAPER_LAYOUT_CENTER;
 }
 
-void RecordCustomWallpaperLayout(const wallpaper::WallpaperLayout& layout) {
+void RecordCustomWallpaperLayout(const ash::WallpaperLayout& layout) {
   UMA_HISTOGRAM_ENUMERATION("Ash.Wallpaper.CustomLayout", layout,
-                            wallpaper::NUM_WALLPAPER_LAYOUT);
+                            ash::NUM_WALLPAPER_LAYOUT);
 }
 
 }  // namespace wallpaper_api_util
diff --git a/chrome/browser/chromeos/extensions/wallpaper_function_base.h b/chrome/browser/chromeos/extensions/wallpaper_function_base.h
index da726818..cc282cec 100644
--- a/chrome/browser/chromeos/extensions/wallpaper_function_base.h
+++ b/chrome/browser/chromeos/extensions/wallpaper_function_base.h
@@ -8,7 +8,7 @@
 #include <string>
 #include <vector>
 
-#include "components/wallpaper/wallpaper_info.h"
+#include "ash/public/cpp/wallpaper_types.h"
 #include "extensions/browser/extension_function.h"
 #include "ui/gfx/image/image_skia.h"
 
@@ -20,11 +20,11 @@
 
 extern const char kCancelWallpaperMessage[];
 
-wallpaper::WallpaperLayout GetLayoutEnum(const std::string& layout);
+ash::WallpaperLayout GetLayoutEnum(const std::string& layout);
 
 // This is used to record the wallpaper layout when the user sets a custom
 // wallpaper or changes the existing custom wallpaper's layout.
-void RecordCustomWallpaperLayout(const wallpaper::WallpaperLayout& layout);
+void RecordCustomWallpaperLayout(const ash::WallpaperLayout& layout);
 
 }  // namespace wallpaper_api_util
 
diff --git a/chrome/browser/chromeos/extensions/wallpaper_private_api.cc b/chrome/browser/chromeos/extensions/wallpaper_private_api.cc
index ca9641a..3461c5b 100644
--- a/chrome/browser/chromeos/extensions/wallpaper_private_api.cc
+++ b/chrome/browser/chromeos/extensions/wallpaper_private_api.cc
@@ -41,7 +41,6 @@
 #include "components/strings/grit/components_strings.h"
 #include "components/user_manager/user.h"
 #include "components/user_manager/user_manager.h"
-#include "components/wallpaper/wallpaper_info.h"
 #include "content/public/browser/browser_thread.h"
 #include "extensions/browser/event_router.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -153,21 +152,20 @@
   return user;
 }
 
-wallpaper::WallpaperType getWallpaperType(
-    wallpaper_private::WallpaperSource source) {
+ash::WallpaperType getWallpaperType(wallpaper_private::WallpaperSource source) {
   switch (source) {
     case wallpaper_private::WALLPAPER_SOURCE_ONLINE:
-      return wallpaper::ONLINE;
+      return ash::ONLINE;
     case wallpaper_private::WALLPAPER_SOURCE_DAILY:
-      return wallpaper::DAILY;
+      return ash::DAILY;
     case wallpaper_private::WALLPAPER_SOURCE_CUSTOM:
-      return wallpaper::CUSTOMIZED;
+      return ash::CUSTOMIZED;
     case wallpaper_private::WALLPAPER_SOURCE_OEM:
-      return wallpaper::DEFAULT;
+      return ash::DEFAULT;
     case wallpaper_private::WALLPAPER_SOURCE_THIRDPARTY:
-      return wallpaper::THIRDPARTY;
+      return ash::THIRDPARTY;
     default:
-      return wallpaper::ONLINE;
+      return ash::ONLINE;
   }
 }
 
@@ -393,9 +391,9 @@
 void WallpaperPrivateSetWallpaperIfExistsFunction::OnWallpaperDecoded(
     const gfx::ImageSkia& image) {
   // Set unsafe_wallpaper_decoder_ to null since the decoding already finished.
-  unsafe_wallpaper_decoder_ = NULL;
+  unsafe_wallpaper_decoder_ = nullptr;
 
-  wallpaper::WallpaperLayout layout = wallpaper_api_util::GetLayoutEnum(
+  ash::WallpaperLayout layout = wallpaper_api_util::GetLayoutEnum(
       wallpaper_base::ToString(params->layout));
 
   WallpaperControllerClient::Get()->SetOnlineWallpaper(
@@ -432,7 +430,7 @@
     const gfx::ImageSkia& image) {
   wallpaper_ = image;
   // Set unsafe_wallpaper_decoder_ to null since the decoding already finished.
-  unsafe_wallpaper_decoder_ = NULL;
+  unsafe_wallpaper_decoder_ = nullptr;
 
   GetBlockingTaskRunner()->PostTask(
       FROM_HERE,
@@ -463,9 +461,9 @@
     // Generates and saves small resolution wallpaper. Uses CENTER_CROPPED to
     // maintain the aspect ratio after resize.
     ash::WallpaperController::ResizeAndSaveWallpaper(
-        wallpaper_, file_path, wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED,
+        wallpaper_, file_path, ash::WALLPAPER_LAYOUT_CENTER_CROPPED,
         ash::WallpaperController::kSmallWallpaperMaxWidth,
-        ash::WallpaperController::kSmallWallpaperMaxHeight, NULL);
+        ash::WallpaperController::kSmallWallpaperMaxHeight, nullptr);
   } else {
     std::string error = base::StringPrintf(
         "Failed to create/write wallpaper to %s.", file_name.c_str());
@@ -478,7 +476,7 @@
 
 void WallpaperPrivateSetWallpaperFunction::SetDecodedWallpaper(
     std::unique_ptr<gfx::ImageSkia> image) {
-  wallpaper::WallpaperLayout layout = wallpaper_api_util::GetLayoutEnum(
+  ash::WallpaperLayout layout = wallpaper_api_util::GetLayoutEnum(
       wallpaper_base::ToString(params->layout));
 
   WallpaperControllerClient::Get()->SetOnlineWallpaper(
@@ -527,16 +525,16 @@
   base::FilePath thumbnail_path =
       ash::WallpaperController::GetCustomWallpaperPath(
           ash::WallpaperController::kThumbnailWallpaperSubDir,
-          wallpaper_files_id_.id(), params->file_name);
+          wallpaper_files_id_, params->file_name);
 
-  wallpaper::WallpaperLayout layout = wallpaper_api_util::GetLayoutEnum(
+  ash::WallpaperLayout layout = wallpaper_api_util::GetLayoutEnum(
       wallpaper_base::ToString(params->layout));
   wallpaper_api_util::RecordCustomWallpaperLayout(layout);
 
   WallpaperControllerClient::Get()->SetCustomWallpaper(
       account_id_, wallpaper_files_id_, params->file_name, layout, image,
       params->preview_mode);
-  unsafe_wallpaper_decoder_ = NULL;
+  unsafe_wallpaper_decoder_ = nullptr;
 
   if (params->generate_thumbnail) {
     image.EnsureRepsForSupportedScales();
@@ -562,9 +560,9 @@
 
   scoped_refptr<base::RefCountedBytes> data;
   ash::WallpaperController::ResizeImage(
-      *image, wallpaper::WALLPAPER_LAYOUT_STRETCH,
+      *image, ash::WALLPAPER_LAYOUT_STRETCH,
       ash::WallpaperController::kWallpaperThumbnailWidth,
-      ash::WallpaperController::kWallpaperThumbnailHeight, &data, NULL);
+      ash::WallpaperController::kWallpaperThumbnailHeight, &data, nullptr);
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
       base::BindOnce(
@@ -590,7 +588,7 @@
       set_custom_wallpaper_layout::Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params);
 
-  wallpaper::WallpaperLayout new_layout = wallpaper_api_util::GetLayoutEnum(
+  ash::WallpaperLayout new_layout = wallpaper_api_util::GetLayoutEnum(
       wallpaper_base::ToString(params->layout));
   wallpaper_api_util::RecordCustomWallpaperLayout(new_layout);
   WallpaperControllerClient::Get()->UpdateCustomWallpaperLayout(
@@ -815,9 +813,9 @@
       record_wallpaper_uma::Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params);
 
-  wallpaper::WallpaperType source = getWallpaperType(params->source);
+  ash::WallpaperType source = getWallpaperType(params->source);
   UMA_HISTOGRAM_ENUMERATION("Ash.Wallpaper.Source", source,
-                            wallpaper::WALLPAPER_TYPE_COUNT);
+                            ash::WALLPAPER_TYPE_COUNT);
   return RespondNow(NoArguments());
 }
 
diff --git a/chrome/browser/chromeos/extensions/wallpaper_private_api.h b/chrome/browser/chromeos/extensions/wallpaper_private_api.h
index 02d044a..4d6b0f0 100644
--- a/chrome/browser/chromeos/extensions/wallpaper_private_api.h
+++ b/chrome/browser/chromeos/extensions/wallpaper_private_api.h
@@ -12,7 +12,6 @@
 #include "chrome/browser/chromeos/extensions/wallpaper_function_base.h"
 #include "chrome/common/extensions/api/wallpaper_private.h"
 #include "components/signin/core/account_id/account_id.h"
-#include "components/wallpaper/wallpaper_files_id.h"
 #include "net/url_request/url_fetcher_delegate.h"
 
 namespace backdrop_wallpaper_handlers {
@@ -173,7 +172,7 @@
   AccountId account_id_ = EmptyAccountId();
 
   // User id hash of the logged in user.
-  wallpaper::WallpaperFilesId wallpaper_files_id_;
+  std::string wallpaper_files_id_;
 };
 
 class WallpaperPrivateSetCustomWallpaperLayoutFunction
diff --git a/chrome/browser/chromeos/file_system_provider/fake_provided_file_system.cc b/chrome/browser/chromeos/file_system_provider/fake_provided_file_system.cc
index 7704b99..5803c13f 100644
--- a/chrome/browser/chromeos/file_system_provider/fake_provided_file_system.cc
+++ b/chrome/browser/chromeos/file_system_provider/fake_provided_file_system.cc
@@ -84,20 +84,22 @@
 }
 
 AbortCallback FakeProvidedFileSystem::RequestUnmount(
-    const storage::AsyncFileUtil::StatusCallback& callback) {
-  return PostAbortableTask(base::Bind(callback, base::File::FILE_OK));
+    storage::AsyncFileUtil::StatusCallback callback) {
+  return PostAbortableTask(
+      base::BindOnce(std::move(callback), base::File::FILE_OK));
 }
 
 AbortCallback FakeProvidedFileSystem::GetMetadata(
     const base::FilePath& entry_path,
     ProvidedFileSystemInterface::MetadataFieldMask fields,
-    const ProvidedFileSystemInterface::GetMetadataCallback& callback) {
+    ProvidedFileSystemInterface::GetMetadataCallback callback) {
   const Entries::const_iterator entry_it = entries_.find(entry_path);
 
   if (entry_it == entries_.end()) {
-    return PostAbortableTask(base::Bind(
-        callback, base::Passed(base::WrapUnique<EntryMetadata>(NULL)),
-        base::File::FILE_ERROR_NOT_FOUND));
+    return PostAbortableTask(
+        base::BindOnce(std::move(callback),
+                       base::Passed(base::WrapUnique<EntryMetadata>(NULL)),
+                       base::File::FILE_ERROR_NOT_FOUND));
   }
 
   std::unique_ptr<EntryMetadata> metadata(new EntryMetadata);
@@ -124,29 +126,31 @@
         new std::string(*entry_it->second->metadata->thumbnail));
   }
 
-  return PostAbortableTask(
-      base::Bind(callback, base::Passed(&metadata), base::File::FILE_OK));
+  return PostAbortableTask(base::BindOnce(
+      std::move(callback), base::Passed(&metadata), base::File::FILE_OK));
 }
 
 AbortCallback FakeProvidedFileSystem::GetActions(
     const std::vector<base::FilePath>& entry_paths,
-    const ProvidedFileSystemInterface::GetActionsCallback& callback) {
+    ProvidedFileSystemInterface::GetActionsCallback callback) {
   // TODO(mtomasz): Implement it once needed.
   const std::vector<Action> actions;
-  return PostAbortableTask(base::Bind(callback, actions, base::File::FILE_OK));
+  return PostAbortableTask(
+      base::BindOnce(std::move(callback), actions, base::File::FILE_OK));
 }
 
 AbortCallback FakeProvidedFileSystem::ExecuteAction(
     const std::vector<base::FilePath>& entry_paths,
     const std::string& action_id,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   // TODO(mtomasz): Implement it once needed.
-  return PostAbortableTask(base::Bind(callback, base::File::FILE_OK));
+  return PostAbortableTask(
+      base::BindOnce(std::move(callback), base::File::FILE_OK));
 }
 
 AbortCallback FakeProvidedFileSystem::ReadDirectory(
     const base::FilePath& directory_path,
-    const storage::AsyncFileUtil::ReadDirectoryCallback& callback) {
+    storage::AsyncFileUtil::ReadDirectoryCallback callback) {
   storage::AsyncFileUtil::EntryList entry_list;
 
   for (Entries::const_iterator it = entries_.begin(); it != entries_.end();
@@ -165,35 +169,36 @@
       callback, base::File::FILE_OK, entry_list, false /* has_more */));
 }
 
-AbortCallback FakeProvidedFileSystem::OpenFile(
-    const base::FilePath& entry_path,
-    OpenFileMode mode,
-    const OpenFileCallback& callback) {
+AbortCallback FakeProvidedFileSystem::OpenFile(const base::FilePath& entry_path,
+                                               OpenFileMode mode,
+                                               OpenFileCallback callback) {
   const Entries::const_iterator entry_it = entries_.find(entry_path);
 
   if (entry_it == entries_.end()) {
-    return PostAbortableTask(base::Bind(
-        callback, 0 /* file_handle */, base::File::FILE_ERROR_NOT_FOUND));
+    return PostAbortableTask(base::BindOnce(std::move(callback),
+                                            0 /* file_handle */,
+                                            base::File::FILE_ERROR_NOT_FOUND));
   }
 
   const int file_handle = ++last_file_handle_;
   opened_files_[file_handle] = OpenedFile(entry_path, mode);
   return PostAbortableTask(
-      base::Bind(callback, file_handle, base::File::FILE_OK));
+      base::BindOnce(std::move(callback), file_handle, base::File::FILE_OK));
 }
 
 AbortCallback FakeProvidedFileSystem::CloseFile(
     int file_handle,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   const auto opened_file_it = opened_files_.find(file_handle);
 
   if (opened_file_it == opened_files_.end()) {
     return PostAbortableTask(
-        base::Bind(callback, base::File::FILE_ERROR_NOT_FOUND));
+        base::BindOnce(std::move(callback), base::File::FILE_ERROR_NOT_FOUND));
   }
 
   opened_files_.erase(opened_file_it);
-  return PostAbortableTask(base::Bind(callback, base::File::FILE_OK));
+  return PostAbortableTask(
+      base::BindOnce(std::move(callback), base::File::FILE_OK));
 }
 
 AbortCallback FakeProvidedFileSystem::ReadFile(
@@ -201,7 +206,7 @@
     net::IOBuffer* buffer,
     int64_t offset,
     int length,
-    const ProvidedFileSystemInterface::ReadChunkReceivedCallback& callback) {
+    ProvidedFileSystemInterface::ReadChunkReceivedCallback callback) {
   const auto opened_file_it = opened_files_.find(file_handle);
 
   if (opened_file_it == opened_files_.end() ||
@@ -258,51 +263,56 @@
 AbortCallback FakeProvidedFileSystem::CreateDirectory(
     const base::FilePath& directory_path,
     bool recursive,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   // TODO(mtomasz): Implement it once needed.
-  return PostAbortableTask(base::Bind(callback, base::File::FILE_OK));
+  return PostAbortableTask(
+      base::BindOnce(std::move(callback), base::File::FILE_OK));
 }
 
 AbortCallback FakeProvidedFileSystem::DeleteEntry(
     const base::FilePath& entry_path,
     bool recursive,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   // TODO(mtomasz): Implement it once needed.
-  return PostAbortableTask(base::Bind(callback, base::File::FILE_OK));
+  return PostAbortableTask(
+      base::BindOnce(std::move(callback), base::File::FILE_OK));
 }
 
 AbortCallback FakeProvidedFileSystem::CreateFile(
     const base::FilePath& file_path,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   const base::File::Error result = file_path.AsUTF8Unsafe() != kFakeFilePath
                                        ? base::File::FILE_ERROR_EXISTS
                                        : base::File::FILE_OK;
 
-  return PostAbortableTask(base::Bind(callback, result));
+  return PostAbortableTask(base::BindOnce(std::move(callback), result));
 }
 
 AbortCallback FakeProvidedFileSystem::CopyEntry(
     const base::FilePath& source_path,
     const base::FilePath& target_path,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   // TODO(mtomasz): Implement it once needed.
-  return PostAbortableTask(base::Bind(callback, base::File::FILE_OK));
+  return PostAbortableTask(
+      base::BindOnce(std::move(callback), base::File::FILE_OK));
 }
 
 AbortCallback FakeProvidedFileSystem::MoveEntry(
     const base::FilePath& source_path,
     const base::FilePath& target_path,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   // TODO(mtomasz): Implement it once needed.
-  return PostAbortableTask(base::Bind(callback, base::File::FILE_OK));
+  return PostAbortableTask(
+      base::BindOnce(std::move(callback), base::File::FILE_OK));
 }
 
 AbortCallback FakeProvidedFileSystem::Truncate(
     const base::FilePath& file_path,
     int64_t length,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   // TODO(mtomasz): Implement it once needed.
-  return PostAbortableTask(base::Bind(callback, base::File::FILE_OK));
+  return PostAbortableTask(
+      base::BindOnce(std::move(callback), base::File::FILE_OK));
 }
 
 AbortCallback FakeProvidedFileSystem::WriteFile(
@@ -310,26 +320,26 @@
     net::IOBuffer* buffer,
     int64_t offset,
     int length,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   const auto opened_file_it = opened_files_.find(file_handle);
 
   if (opened_file_it == opened_files_.end() ||
       opened_file_it->second.file_path.AsUTF8Unsafe() != kFakeFilePath) {
-    return PostAbortableTask(
-        base::Bind(callback, base::File::FILE_ERROR_INVALID_OPERATION));
+    return PostAbortableTask(base::BindOnce(
+        std::move(callback), base::File::FILE_ERROR_INVALID_OPERATION));
   }
 
   const Entries::iterator entry_it =
       entries_.find(opened_file_it->second.file_path);
   if (entry_it == entries_.end()) {
-    return PostAbortableTask(
-        base::Bind(callback, base::File::FILE_ERROR_INVALID_OPERATION));
+    return PostAbortableTask(base::BindOnce(
+        std::move(callback), base::File::FILE_ERROR_INVALID_OPERATION));
   }
 
   FakeEntry* const entry = entry_it->second.get();
   if (offset > *entry->metadata->size) {
-    return PostAbortableTask(
-        base::Bind(callback, base::File::FILE_ERROR_INVALID_OPERATION));
+    return PostAbortableTask(base::BindOnce(
+        std::move(callback), base::File::FILE_ERROR_INVALID_OPERATION));
   }
 
   // Allocate the string size in advance.
@@ -340,7 +350,8 @@
 
   entry->contents.replace(offset, length, buffer->data(), length);
 
-  return PostAbortableTask(base::Bind(callback, base::File::FILE_OK));
+  return PostAbortableTask(
+      base::BindOnce(std::move(callback), base::File::FILE_OK));
 }
 
 AbortCallback FakeProvidedFileSystem::AddWatcher(
@@ -348,20 +359,21 @@
     const base::FilePath& entry_watcher,
     bool recursive,
     bool persistent,
-    const storage::AsyncFileUtil::StatusCallback& callback,
+    storage::AsyncFileUtil::StatusCallback callback,
     const storage::WatcherManager::NotificationCallback&
         notification_callback) {
   // TODO(mtomasz): Implement it once needed.
-  return PostAbortableTask(base::Bind(callback, base::File::FILE_OK));
+  return PostAbortableTask(
+      base::BindOnce(std::move(callback), base::File::FILE_OK));
 }
 
 void FakeProvidedFileSystem::RemoveWatcher(
     const GURL& origin,
     const base::FilePath& entry_path,
     bool recursive,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   // TODO(mtomasz): Implement it once needed.
-  callback.Run(base::File::FILE_OK);
+  std::move(callback).Run(base::File::FILE_OK);
 }
 
 const ProvidedFileSystemInfo& FakeProvidedFileSystem::GetFileSystemInfo()
@@ -399,15 +411,15 @@
     storage::WatcherManager::ChangeType change_type,
     std::unique_ptr<ProvidedFileSystemObserver::Changes> changes,
     const std::string& tag,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   NOTREACHED();
-  callback.Run(base::File::FILE_ERROR_SECURITY);
+  std::move(callback).Run(base::File::FILE_ERROR_SECURITY);
 }
 
 void FakeProvidedFileSystem::Configure(
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   NOTREACHED();
-  callback.Run(base::File::FILE_ERROR_SECURITY);
+  std::move(callback).Run(base::File::FILE_ERROR_SECURITY);
 }
 
 base::WeakPtr<ProvidedFileSystemInterface>
@@ -416,9 +428,10 @@
 }
 
 AbortCallback FakeProvidedFileSystem::PostAbortableTask(
-    const base::Closure& callback) {
-  const int task_id = tracker_.PostTask(
-      base::ThreadTaskRunnerHandle::Get().get(), FROM_HERE, callback);
+    base::OnceClosure callback) {
+  const int task_id =
+      tracker_.PostTask(base::ThreadTaskRunnerHandle::Get().get(), FROM_HERE,
+                        std::move(callback));
   return base::Bind(
       &FakeProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), task_id);
 }
diff --git a/chrome/browser/chromeos/file_system_provider/fake_provided_file_system.h b/chrome/browser/chromeos/file_system_provider/fake_provided_file_system.h
index 9f277f2f..84793a9 100644
--- a/chrome/browser/chromeos/file_system_provider/fake_provided_file_system.h
+++ b/chrome/browser/chromeos/file_system_provider/fake_provided_file_system.h
@@ -82,74 +82,71 @@
 
   // ProvidedFileSystemInterface overrides.
   AbortCallback RequestUnmount(
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
   AbortCallback GetMetadata(
       const base::FilePath& entry_path,
       ProvidedFileSystemInterface::MetadataFieldMask fields,
-      const ProvidedFileSystemInterface::GetMetadataCallback& callback)
-      override;
+      ProvidedFileSystemInterface::GetMetadataCallback callback) override;
   AbortCallback GetActions(const std::vector<base::FilePath>& entry_paths,
-                           const GetActionsCallback& callback) override;
+                           GetActionsCallback callback) override;
   AbortCallback ExecuteAction(
       const std::vector<base::FilePath>& entry_paths,
       const std::string& action_id,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
   AbortCallback ReadDirectory(
       const base::FilePath& directory_path,
-      const storage::AsyncFileUtil::ReadDirectoryCallback& callback) override;
+      storage::AsyncFileUtil::ReadDirectoryCallback callback) override;
   AbortCallback OpenFile(const base::FilePath& file_path,
                          OpenFileMode mode,
-                         const OpenFileCallback& callback) override;
+                         OpenFileCallback callback) override;
   AbortCallback CloseFile(
       int file_handle,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
   AbortCallback ReadFile(int file_handle,
                          net::IOBuffer* buffer,
                          int64_t offset,
                          int length,
-                         const ReadChunkReceivedCallback& callback) override;
+                         ReadChunkReceivedCallback callback) override;
   AbortCallback CreateDirectory(
       const base::FilePath& directory_path,
       bool recursive,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
   AbortCallback DeleteEntry(
       const base::FilePath& entry_path,
       bool recursive,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
   AbortCallback CreateFile(
       const base::FilePath& file_path,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
   AbortCallback CopyEntry(
       const base::FilePath& source_path,
       const base::FilePath& target_path,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
   AbortCallback MoveEntry(
       const base::FilePath& source_path,
       const base::FilePath& target_path,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
   AbortCallback Truncate(
       const base::FilePath& file_path,
       int64_t length,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
   AbortCallback WriteFile(
       int file_handle,
       net::IOBuffer* buffer,
       int64_t offset,
       int length,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
-  AbortCallback AddWatcher(
-      const GURL& origin,
-      const base::FilePath& entry_path,
-      bool recursive,
-      bool persistent,
-      const storage::AsyncFileUtil::StatusCallback& callback,
-      const storage::WatcherManager::NotificationCallback&
-          notification_callback) override;
-  void RemoveWatcher(
-      const GURL& origin,
-      const base::FilePath& entry_path,
-      bool recursive,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
+  AbortCallback AddWatcher(const GURL& origin,
+                           const base::FilePath& entry_path,
+                           bool recursive,
+                           bool persistent,
+                           storage::AsyncFileUtil::StatusCallback callback,
+                           const storage::WatcherManager::NotificationCallback&
+                               notification_callback) override;
+  void RemoveWatcher(const GURL& origin,
+                     const base::FilePath& entry_path,
+                     bool recursive,
+                     storage::AsyncFileUtil::StatusCallback callback) override;
   const ProvidedFileSystemInfo& GetFileSystemInfo() const override;
   RequestManager* GetRequestManager() override;
   Watchers* GetWatchers() override;
@@ -161,9 +158,8 @@
               storage::WatcherManager::ChangeType change_type,
               std::unique_ptr<ProvidedFileSystemObserver::Changes> changes,
               const std::string& tag,
-              const storage::AsyncFileUtil::StatusCallback& callback) override;
-  void Configure(
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+              storage::AsyncFileUtil::StatusCallback callback) override;
+  void Configure(storage::AsyncFileUtil::StatusCallback callback) override;
   base::WeakPtr<ProvidedFileSystemInterface> GetWeakPtr() override;
 
  private:
@@ -171,7 +167,7 @@
 
   // Utility function for posting a task which can be aborted by calling the
   // returned callback.
-  AbortCallback PostAbortableTask(const base::Closure& callback);
+  AbortCallback PostAbortableTask(base::OnceClosure callback);
 
   // Aborts a request. |task_id| refers to a posted callback returning a
   // response for the operation, which will be cancelled, hence not called.
diff --git a/chrome/browser/chromeos/file_system_provider/fileapi/file_stream_reader.cc b/chrome/browser/chromeos/file_system_provider/fileapi/file_stream_reader.cc
index c63dff5..7e156a0 100644
--- a/chrome/browser/chromeos/file_system_provider/fileapi/file_stream_reader.cc
+++ b/chrome/browser/chromeos/file_system_provider/fileapi/file_stream_reader.cc
@@ -38,9 +38,8 @@
 
   // Opens a file for reading and calls the completion callback. Must be called
   // on UI thread.
-  void OpenFileOnUIThread(
-      const storage::FileSystemURL& url,
-      const storage::AsyncFileUtil::StatusCallback& callback) {
+  void OpenFileOnUIThread(const storage::FileSystemURL& url,
+                          storage::AsyncFileUtil::StatusCallback callback) {
     DCHECK_CURRENTLY_ON(BrowserThread::UI);
     DCHECK(abort_callback_.is_null());
 
@@ -48,7 +47,7 @@
     if (!parser.Parse()) {
       BrowserThread::PostTask(
           BrowserThread::IO, FROM_HERE,
-          base::BindOnce(callback, base::File::FILE_ERROR_SECURITY));
+          base::BindOnce(std::move(callback), base::File::FILE_ERROR_SECURITY));
       return;
     }
 
@@ -57,7 +56,7 @@
     file_opener_.reset(new ScopedFileOpener(
         parser.file_system(), parser.file_path(), OPEN_FILE_MODE_READ,
         base::Bind(&OperationRunner::OnOpenFileCompletedOnUIThread, this,
-                   callback)));
+                   std::move(callback))));
   }
 
   // Requests reading contents of a file. |callback| will always run eventually.
@@ -68,7 +67,7 @@
       scoped_refptr<net::IOBuffer> buffer,
       int64_t offset,
       int length,
-      const ProvidedFileSystemInterface::ReadChunkReceivedCallback& callback) {
+      ProvidedFileSystemInterface::ReadChunkReceivedCallback callback) {
     DCHECK_CURRENTLY_ON(BrowserThread::UI);
     DCHECK(abort_callback_.is_null());
 
@@ -92,7 +91,7 @@
   // Requests metadata of a file. |callback| will always run eventually.
   // Must be called on UI thread.
   void GetMetadataOnUIThread(
-      const ProvidedFileSystemInterface::GetMetadataCallback& callback) {
+      ProvidedFileSystemInterface::GetMetadataCallback callback) {
     DCHECK_CURRENTLY_ON(BrowserThread::UI);
     DCHECK(abort_callback_.is_null());
 
@@ -100,7 +99,7 @@
     if (!file_system_.get()) {
       BrowserThread::PostTask(
           BrowserThread::IO, FROM_HERE,
-          base::BindOnce(callback,
+          base::BindOnce(std::move(callback),
                          base::Passed(base::WrapUnique<EntryMetadata>(NULL)),
                          base::File::FILE_ERROR_ABORT));
       return;
@@ -111,7 +110,7 @@
         ProvidedFileSystemInterface::METADATA_FIELD_SIZE |
             ProvidedFileSystemInterface::METADATA_FIELD_MODIFICATION_TIME,
         base::Bind(&OperationRunner::OnGetMetadataCompletedOnUIThread, this,
-                   callback));
+                   std::move(callback)));
   }
 
   // Aborts the most recent operation (if exists) and closes a file if opened.
@@ -139,7 +138,7 @@
   // Remembers a file handle for further operations and forwards the result to
   // the IO thread.
   void OnOpenFileCompletedOnUIThread(
-      const storage::AsyncFileUtil::StatusCallback& callback,
+      storage::AsyncFileUtil::StatusCallback callback,
       int file_handle,
       base::File::Error result) {
     DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -149,12 +148,12 @@
       file_handle_ = file_handle;
 
     BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
-                            base::BindOnce(callback, result));
+                            base::BindOnce(std::move(callback), result));
   }
 
   // Forwards a metadata to the IO thread.
   void OnGetMetadataCompletedOnUIThread(
-      const ProvidedFileSystemInterface::GetMetadataCallback& callback,
+      ProvidedFileSystemInterface::GetMetadataCallback callback,
       std::unique_ptr<EntryMetadata> metadata,
       base::File::Error result) {
     DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -162,12 +161,12 @@
 
     BrowserThread::PostTask(
         BrowserThread::IO, FROM_HERE,
-        base::BindOnce(callback, base::Passed(&metadata), result));
+        base::BindOnce(std::move(callback), base::Passed(&metadata), result));
   }
 
   // Forwards a response of reading from a file to the IO thread.
   void OnReadFileCompletedOnUIThread(
-      const ProvidedFileSystemInterface::ReadChunkReceivedCallback&
+      ProvidedFileSystemInterface::ReadChunkReceivedCallback
           chunk_received_callback,
       int chunk_length,
       bool has_more,
diff --git a/chrome/browser/chromeos/file_system_provider/fileapi/file_stream_writer.cc b/chrome/browser/chromeos/file_system_provider/fileapi/file_stream_writer.cc
index 1029fef..73d65621 100644
--- a/chrome/browser/chromeos/file_system_provider/fileapi/file_stream_writer.cc
+++ b/chrome/browser/chromeos/file_system_provider/fileapi/file_stream_writer.cc
@@ -31,9 +31,8 @@
 
   // Opens a file for writing and calls the completion callback. Must be called
   // on UI thread.
-  void OpenFileOnUIThread(
-      const storage::FileSystemURL& url,
-      const storage::AsyncFileUtil::StatusCallback& callback) {
+  void OpenFileOnUIThread(const storage::FileSystemURL& url,
+                          storage::AsyncFileUtil::StatusCallback callback) {
     DCHECK_CURRENTLY_ON(BrowserThread::UI);
     DCHECK(abort_callback_.is_null());
 
@@ -41,7 +40,7 @@
     if (!parser.Parse()) {
       BrowserThread::PostTask(
           BrowserThread::IO, FROM_HERE,
-          base::BindOnce(callback, base::File::FILE_ERROR_SECURITY));
+          base::BindOnce(std::move(callback), base::File::FILE_ERROR_SECURITY));
       return;
     }
 
@@ -49,16 +48,15 @@
     file_opener_.reset(new ScopedFileOpener(
         parser.file_system(), parser.file_path(), OPEN_FILE_MODE_WRITE,
         base::Bind(&OperationRunner::OnOpenFileCompletedOnUIThread, this,
-                   callback)));
+                   std::move(callback))));
   }
 
   // Requests writing bytes to the file. In case of either success or a failure
   // |callback| is executed. Must be called on UI thread.
-  void WriteFileOnUIThread(
-      scoped_refptr<net::IOBuffer> buffer,
-      int64_t offset,
-      int length,
-      const storage::AsyncFileUtil::StatusCallback& callback) {
+  void WriteFileOnUIThread(scoped_refptr<net::IOBuffer> buffer,
+                           int64_t offset,
+                           int length,
+                           storage::AsyncFileUtil::StatusCallback callback) {
     DCHECK_CURRENTLY_ON(BrowserThread::UI);
     DCHECK(abort_callback_.is_null());
 
@@ -66,17 +64,14 @@
     if (!file_system_.get()) {
       BrowserThread::PostTask(
           BrowserThread::IO, FROM_HERE,
-          base::BindOnce(callback, base::File::FILE_ERROR_ABORT));
+          base::BindOnce(std::move(callback), base::File::FILE_ERROR_ABORT));
       return;
     }
 
     abort_callback_ = file_system_->WriteFile(
-        file_handle_,
-        buffer.get(),
-        offset,
-        length,
-        base::Bind(
-            &OperationRunner::OnWriteFileCompletedOnUIThread, this, callback));
+        file_handle_, buffer.get(), offset, length,
+        base::Bind(&OperationRunner::OnWriteFileCompletedOnUIThread, this,
+                   std::move(callback)));
   }
 
   // Aborts the most recent operation (if exists) and closes a file if opened.
@@ -104,7 +99,7 @@
   // Remembers a file handle for further operations and forwards the result to
   // the IO thread.
   void OnOpenFileCompletedOnUIThread(
-      const storage::AsyncFileUtil::StatusCallback& callback,
+      storage::AsyncFileUtil::StatusCallback callback,
       int file_handle,
       base::File::Error result) {
     DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -114,18 +109,18 @@
       file_handle_ = file_handle;
 
     BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
-                            base::BindOnce(callback, result));
+                            base::BindOnce(std::move(callback), result));
   }
 
   // Forwards a response of writing to a file to the IO thread.
   void OnWriteFileCompletedOnUIThread(
-      const storage::AsyncFileUtil::StatusCallback& callback,
+      storage::AsyncFileUtil::StatusCallback callback,
       base::File::Error result) {
     DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
     abort_callback_ = AbortCallback();
     BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
-                            base::BindOnce(callback, result));
+                            base::BindOnce(std::move(callback), result));
   }
 
   AbortCallback abort_callback_;
diff --git a/chrome/browser/chromeos/file_system_provider/fileapi/provider_async_file_util.cc b/chrome/browser/chromeos/file_system_provider/fileapi/provider_async_file_util.cc
index 9ad1324..3063c8bd 100644
--- a/chrome/browser/chromeos/file_system_provider/fileapi/provider_async_file_util.cc
+++ b/chrome/browser/chromeos/file_system_provider/fileapi/provider_async_file_util.cc
@@ -28,11 +28,11 @@
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
     int fields,
-    const ProvidedFileSystemInterface::GetMetadataCallback& callback) {
+    ProvidedFileSystemInterface::GetMetadataCallback callback) {
   util::FileSystemURLParser parser(url);
   if (!parser.Parse()) {
-    callback.Run(base::WrapUnique<EntryMetadata>(NULL),
-                 base::File::FILE_ERROR_INVALID_OPERATION);
+    std::move(callback).Run(base::WrapUnique<EntryMetadata>(NULL),
+                            base::File::FILE_ERROR_INVALID_OPERATION);
     return;
   }
 
@@ -44,19 +44,20 @@
   if (fields & storage::FileSystemOperation::GET_METADATA_FIELD_LAST_MODIFIED)
     fsp_fields |= ProvidedFileSystemInterface::METADATA_FIELD_MODIFICATION_TIME;
 
-  parser.file_system()->GetMetadata(parser.file_path(), fsp_fields, callback);
+  parser.file_system()->GetMetadata(parser.file_path(), fsp_fields,
+                                    std::move(callback));
 }
 
 // Routes the response of GetFileInfo back to the IO thread with a type
 // conversion.
 void OnGetFileInfo(int fields,
-                   const storage::AsyncFileUtil::GetFileInfoCallback& callback,
+                   storage::AsyncFileUtil::GetFileInfoCallback callback,
                    std::unique_ptr<EntryMetadata> metadata,
                    base::File::Error result) {
   if (result != base::File::FILE_OK) {
     BrowserThread::PostTask(
         BrowserThread::IO, FROM_HERE,
-        base::BindOnce(callback, result, base::File::Info()));
+        base::BindOnce(std::move(callback), result, base::File::Info()));
     return;
   }
 
@@ -80,14 +81,14 @@
 
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
-      base::BindOnce(callback, base::File::FILE_OK, file_info));
+      base::BindOnce(std::move(callback), base::File::FILE_OK, file_info));
 }
 
 // Executes ReadDirectory on the UI thread.
 void ReadDirectoryOnUIThread(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const storage::AsyncFileUtil::ReadDirectoryCallback& callback) {
+    storage::AsyncFileUtil::ReadDirectoryCallback callback) {
   util::FileSystemURLParser parser(url);
   if (!parser.Parse()) {
     callback.Run(base::File::FILE_ERROR_INVALID_OPERATION,
@@ -100,11 +101,10 @@
 }
 
 // Routes the response of ReadDirectory back to the IO thread.
-void OnReadDirectory(
-    const storage::AsyncFileUtil::ReadDirectoryCallback& callback,
-    base::File::Error result,
-    storage::AsyncFileUtil::EntryList entry_list,
-    bool has_more) {
+void OnReadDirectory(storage::AsyncFileUtil::ReadDirectoryCallback callback,
+                     base::File::Error result,
+                     storage::AsyncFileUtil::EntryList entry_list,
+                     bool has_more) {
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
       base::BindOnce(callback, result, std::move(entry_list), has_more));
@@ -116,20 +116,20 @@
     const storage::FileSystemURL& url,
     bool exclusive,
     bool recursive,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   util::FileSystemURLParser parser(url);
   if (!parser.Parse()) {
-    callback.Run(base::File::FILE_ERROR_INVALID_OPERATION);
+    std::move(callback).Run(base::File::FILE_ERROR_INVALID_OPERATION);
     return;
   }
 
-  parser.file_system()->CreateDirectory(
-      parser.file_path(), recursive, callback);
+  parser.file_system()->CreateDirectory(parser.file_path(), recursive,
+                                        std::move(callback));
 }
 
 // Routes the response of CreateDirectory back to the IO thread.
 void OnCreateDirectory(bool exclusive,
-                       const storage::AsyncFileUtil::StatusCallback& callback,
+                       storage::AsyncFileUtil::StatusCallback callback,
                        base::File::Error result) {
   // If the directory already existed and the operation wasn't exclusive, then
   // return success anyway, since it is not an error.
@@ -139,7 +139,7 @@
           : result;
 
   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
-                          base::BindOnce(callback, error));
+                          base::BindOnce(std::move(callback), error));
 }
 
 // Executes DeleteEntry on the UI thread.
@@ -147,41 +147,42 @@
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
     bool recursive,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   util::FileSystemURLParser parser(url);
   if (!parser.Parse()) {
-    callback.Run(base::File::FILE_ERROR_INVALID_OPERATION);
+    std::move(callback).Run(base::File::FILE_ERROR_INVALID_OPERATION);
     return;
   }
 
-  parser.file_system()->DeleteEntry(parser.file_path(), recursive, callback);
+  parser.file_system()->DeleteEntry(parser.file_path(), recursive,
+                                    std::move(callback));
 }
 
 // Routes the response of DeleteEntry back to the IO thread.
-void OnDeleteEntry(const storage::AsyncFileUtil::StatusCallback& callback,
+void OnDeleteEntry(storage::AsyncFileUtil::StatusCallback callback,
                    base::File::Error result) {
   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
-                          base::BindOnce(callback, result));
+                          base::BindOnce(std::move(callback), result));
 }
 
 // Executes CreateFile on the UI thread.
 void CreateFileOnUIThread(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   util::FileSystemURLParser parser(url);
   if (!parser.Parse()) {
-    callback.Run(base::File::FILE_ERROR_INVALID_OPERATION);
+    std::move(callback).Run(base::File::FILE_ERROR_INVALID_OPERATION);
     return;
   }
 
-  parser.file_system()->CreateFile(parser.file_path(), callback);
+  parser.file_system()->CreateFile(parser.file_path(), std::move(callback));
 }
 
 // Routes the response of CreateFile to a callback of EnsureFileExists() on the
 // IO thread.
 void OnCreateFileForEnsureFileExists(
-    const storage::AsyncFileUtil::EnsureFileExistsCallback& callback,
+    storage::AsyncFileUtil::EnsureFileExistsCallback callback,
     base::File::Error result) {
   const bool created = result == base::File::FILE_OK;
 
@@ -191,7 +192,7 @@
       result == base::File::FILE_ERROR_EXISTS ? base::File::FILE_OK : result;
 
   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
-                          base::BindOnce(callback, error, created));
+                          base::BindOnce(std::move(callback), error, created));
 }
 
 // Executes CopyEntry on the UI thread.
@@ -199,26 +200,27 @@
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& source_url,
     const storage::FileSystemURL& target_url,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   util::FileSystemURLParser source_parser(source_url);
   util::FileSystemURLParser target_parser(target_url);
 
   if (!source_parser.Parse() || !target_parser.Parse() ||
       source_parser.file_system() != target_parser.file_system()) {
-    callback.Run(base::File::FILE_ERROR_INVALID_OPERATION);
+    std::move(callback).Run(base::File::FILE_ERROR_INVALID_OPERATION);
     return;
   }
 
-  target_parser.file_system()->CopyEntry(
-      source_parser.file_path(), target_parser.file_path(), callback);
+  target_parser.file_system()->CopyEntry(source_parser.file_path(),
+                                         target_parser.file_path(),
+                                         std::move(callback));
 }
 
 // Routes the response of CopyEntry to a callback of CopyLocalFile() on the
 // IO thread.
-void OnCopyEntry(const storage::AsyncFileUtil::StatusCallback& callback,
+void OnCopyEntry(storage::AsyncFileUtil::StatusCallback callback,
                  base::File::Error result) {
   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
-                          base::BindOnce(callback, result));
+                          base::BindOnce(std::move(callback), result));
 }
 
 // Executes MoveEntry on the UI thread.
@@ -226,26 +228,27 @@
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& source_url,
     const storage::FileSystemURL& target_url,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   util::FileSystemURLParser source_parser(source_url);
   util::FileSystemURLParser target_parser(target_url);
 
   if (!source_parser.Parse() || !target_parser.Parse() ||
       source_parser.file_system() != target_parser.file_system()) {
-    callback.Run(base::File::FILE_ERROR_INVALID_OPERATION);
+    std::move(callback).Run(base::File::FILE_ERROR_INVALID_OPERATION);
     return;
   }
 
-  target_parser.file_system()->MoveEntry(
-      source_parser.file_path(), target_parser.file_path(), callback);
+  target_parser.file_system()->MoveEntry(source_parser.file_path(),
+                                         target_parser.file_path(),
+                                         std::move(callback));
 }
 
 // Routes the response of CopyEntry to a callback of MoveLocalFile() on the
 // IO thread.
-void OnMoveEntry(const storage::AsyncFileUtil::StatusCallback& callback,
+void OnMoveEntry(storage::AsyncFileUtil::StatusCallback callback,
                  base::File::Error result) {
   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
-                          base::BindOnce(callback, result));
+                          base::BindOnce(std::move(callback), result));
 }
 
 // Executes Truncate on the UI thread.
@@ -253,21 +256,22 @@
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
     int64_t length,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   util::FileSystemURLParser parser(url);
   if (!parser.Parse()) {
-    callback.Run(base::File::FILE_ERROR_INVALID_OPERATION);
+    std::move(callback).Run(base::File::FILE_ERROR_INVALID_OPERATION);
     return;
   }
 
-  parser.file_system()->Truncate(parser.file_path(), length, callback);
+  parser.file_system()->Truncate(parser.file_path(), length,
+                                 std::move(callback));
 }
 
 // Routes the response of Truncate back to the IO thread.
-void OnTruncate(const storage::AsyncFileUtil::StatusCallback& callback,
+void OnTruncate(storage::AsyncFileUtil::StatusCallback callback,
                 base::File::Error result) {
   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
-                          base::BindOnce(callback, result));
+                          base::BindOnce(std::move(callback), result));
 }
 
 }  // namespace
@@ -280,31 +284,32 @@
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
     int file_flags,
-    const CreateOrOpenCallback& callback) {
+    CreateOrOpenCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if ((file_flags & base::File::FLAG_CREATE) ||
       (file_flags & base::File::FLAG_OPEN_ALWAYS) ||
       (file_flags & base::File::FLAG_CREATE_ALWAYS) ||
       (file_flags & base::File::FLAG_OPEN_TRUNCATED)) {
-    callback.Run(base::File(base::File::FILE_ERROR_ACCESS_DENIED),
-                 base::Closure());
+    std::move(callback).Run(base::File(base::File::FILE_ERROR_ACCESS_DENIED),
+                            base::Closure());
     return;
   }
 
   NOTIMPLEMENTED();
-  callback.Run(base::File(base::File::FILE_ERROR_INVALID_OPERATION),
-               base::Closure());
+  std::move(callback).Run(base::File(base::File::FILE_ERROR_INVALID_OPERATION),
+                          base::Closure());
 }
 
 void ProviderAsyncFileUtil::EnsureFileExists(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const EnsureFileExistsCallback& callback) {
+    EnsureFileExistsCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
-      base::BindOnce(&CreateFileOnUIThread, base::Passed(&context), url,
-                     base::Bind(&OnCreateFileForEnsureFileExists, callback)));
+      base::BindOnce(
+          &CreateFileOnUIThread, base::Passed(&context), url,
+          base::Bind(&OnCreateFileForEnsureFileExists, std::move(callback))));
 }
 
 void ProviderAsyncFileUtil::CreateDirectory(
@@ -312,31 +317,33 @@
     const storage::FileSystemURL& url,
     bool exclusive,
     bool recursive,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
-      base::BindOnce(&CreateDirectoryOnUIThread, base::Passed(&context), url,
-                     exclusive, recursive,
-                     base::Bind(&OnCreateDirectory, exclusive, callback)));
+      base::BindOnce(
+          &CreateDirectoryOnUIThread, base::Passed(&context), url, exclusive,
+          recursive,
+          base::Bind(&OnCreateDirectory, exclusive, std::move(callback))));
 }
 
 void ProviderAsyncFileUtil::GetFileInfo(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
     int fields,
-    const GetFileInfoCallback& callback) {
+    GetFileInfoCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
       base::BindOnce(&GetFileInfoOnUIThread, base::Passed(&context), url,
-                     fields, base::Bind(&OnGetFileInfo, fields, callback)));
+                     fields,
+                     base::Bind(&OnGetFileInfo, fields, std::move(callback))));
 }
 
 void ProviderAsyncFileUtil::ReadDirectory(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const ReadDirectoryCallback& callback) {
+    ReadDirectoryCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
@@ -349,21 +356,21 @@
     const storage::FileSystemURL& url,
     const base::Time& last_access_time,
     const base::Time& last_modified_time,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  callback.Run(base::File::FILE_ERROR_ACCESS_DENIED);
+  std::move(callback).Run(base::File::FILE_ERROR_ACCESS_DENIED);
 }
 
 void ProviderAsyncFileUtil::Truncate(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
     int64_t length,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
       base::BindOnce(&TruncateOnUIThread, base::Passed(&context), url, length,
-                     base::Bind(&OnTruncate, callback)));
+                     base::Bind(&OnTruncate, std::move(callback))));
 }
 
 void ProviderAsyncFileUtil::CopyFileLocal(
@@ -371,15 +378,15 @@
     const storage::FileSystemURL& src_url,
     const storage::FileSystemURL& dest_url,
     CopyOrMoveOption option,
-    const CopyFileProgressCallback& progress_callback,
-    const StatusCallback& callback) {
+    CopyFileProgressCallback progress_callback,
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   // TODO(mtomasz): Consier adding support for options (preserving last modified
   // time) as well as the progress callback.
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
       base::BindOnce(&CopyEntryOnUIThread, base::Passed(&context), src_url,
-                     dest_url, base::Bind(&OnCopyEntry, callback)));
+                     dest_url, base::Bind(&OnCopyEntry, std::move(callback))));
 }
 
 void ProviderAsyncFileUtil::MoveFileLocal(
@@ -387,71 +394,70 @@
     const storage::FileSystemURL& src_url,
     const storage::FileSystemURL& dest_url,
     CopyOrMoveOption option,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   // TODO(mtomasz): Consier adding support for options (preserving last modified
   // time) as well as the progress callback.
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
       base::BindOnce(&MoveEntryOnUIThread, base::Passed(&context), src_url,
-                     dest_url, base::Bind(&OnMoveEntry, callback)));
+                     dest_url, base::Bind(&OnMoveEntry, std::move(callback))));
 }
 
 void ProviderAsyncFileUtil::CopyInForeignFile(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const base::FilePath& src_file_path,
     const storage::FileSystemURL& dest_url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  callback.Run(base::File::FILE_ERROR_ACCESS_DENIED);
+  std::move(callback).Run(base::File::FILE_ERROR_ACCESS_DENIED);
 }
 
 void ProviderAsyncFileUtil::DeleteFile(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
       base::BindOnce(&DeleteEntryOnUIThread, base::Passed(&context), url,
                      false,  // recursive
-                     base::Bind(&OnDeleteEntry, callback)));
+                     base::Bind(&OnDeleteEntry, std::move(callback))));
 }
 
 void ProviderAsyncFileUtil::DeleteDirectory(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
       base::BindOnce(&DeleteEntryOnUIThread, base::Passed(&context), url,
                      false,  // recursive
-                     base::Bind(&OnDeleteEntry, callback)));
+                     base::Bind(&OnDeleteEntry, std::move(callback))));
 }
 
 void ProviderAsyncFileUtil::DeleteRecursively(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
       base::BindOnce(&DeleteEntryOnUIThread, base::Passed(&context), url,
                      true,  // recursive
-                     base::Bind(&OnDeleteEntry, callback)));
+                     base::Bind(&OnDeleteEntry, std::move(callback))));
 }
 
 void ProviderAsyncFileUtil::CreateSnapshotFile(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const CreateSnapshotFileCallback& callback) {
+    CreateSnapshotFileCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   NOTIMPLEMENTED();
-  callback.Run(base::File::FILE_ERROR_INVALID_OPERATION,
-               base::File::Info(),
-               base::FilePath(),
-               scoped_refptr<storage::ShareableFileReference>());
+  std::move(callback).Run(base::File::FILE_ERROR_INVALID_OPERATION,
+                          base::File::Info(), base::FilePath(),
+                          scoped_refptr<storage::ShareableFileReference>());
 }
 
 }  // namespace internal
diff --git a/chrome/browser/chromeos/file_system_provider/fileapi/provider_async_file_util.h b/chrome/browser/chromeos/file_system_provider/fileapi/provider_async_file_util.h
index 3b9f4e39..05858298 100644
--- a/chrome/browser/chromeos/file_system_provider/fileapi/provider_async_file_util.h
+++ b/chrome/browser/chromeos/file_system_provider/fileapi/provider_async_file_util.h
@@ -39,67 +39,67 @@
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
       int file_flags,
-      const CreateOrOpenCallback& callback) override;
+      CreateOrOpenCallback callback) override;
   void EnsureFileExists(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const EnsureFileExistsCallback& callback) override;
+      EnsureFileExistsCallback callback) override;
   void CreateDirectory(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
       bool exclusive,
       bool recursive,
-      const StatusCallback& callback) override;
+      StatusCallback callback) override;
   void GetFileInfo(std::unique_ptr<storage::FileSystemOperationContext> context,
                    const storage::FileSystemURL& url,
                    int fields,
-                   const GetFileInfoCallback& callback) override;
+                   GetFileInfoCallback callback) override;
   void ReadDirectory(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const ReadDirectoryCallback& callback) override;
+      ReadDirectoryCallback callback) override;
   void Touch(std::unique_ptr<storage::FileSystemOperationContext> context,
              const storage::FileSystemURL& url,
              const base::Time& last_access_time,
              const base::Time& last_modified_time,
-             const StatusCallback& callback) override;
+             StatusCallback callback) override;
   void Truncate(std::unique_ptr<storage::FileSystemOperationContext> context,
                 const storage::FileSystemURL& url,
                 int64_t length,
-                const StatusCallback& callback) override;
+                StatusCallback callback) override;
   void CopyFileLocal(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& src_url,
       const storage::FileSystemURL& dest_url,
       CopyOrMoveOption option,
-      const CopyFileProgressCallback& progress_callback,
-      const StatusCallback& callback) override;
+      CopyFileProgressCallback progress_callback,
+      StatusCallback callback) override;
   void MoveFileLocal(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& src_url,
       const storage::FileSystemURL& dest_url,
       CopyOrMoveOption option,
-      const StatusCallback& callback) override;
+      StatusCallback callback) override;
   void CopyInForeignFile(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const base::FilePath& src_file_path,
       const storage::FileSystemURL& dest_url,
-      const StatusCallback& callback) override;
+      StatusCallback callback) override;
   void DeleteFile(std::unique_ptr<storage::FileSystemOperationContext> context,
                   const storage::FileSystemURL& url,
-                  const StatusCallback& callback) override;
+                  StatusCallback callback) override;
   void DeleteDirectory(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const StatusCallback& callback) override;
+      StatusCallback callback) override;
   void DeleteRecursively(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const StatusCallback& callback) override;
+      StatusCallback callback) override;
   void CreateSnapshotFile(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const CreateSnapshotFileCallback& callback) override;
+      CreateSnapshotFileCallback callback) override;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ProviderAsyncFileUtil);
diff --git a/chrome/browser/chromeos/file_system_provider/operations/read_file.cc b/chrome/browser/chromeos/file_system_provider/operations/read_file.cc
index 9a7ef0b..568a37c 100644
--- a/chrome/browser/chromeos/file_system_provider/operations/read_file.cc
+++ b/chrome/browser/chromeos/file_system_provider/operations/read_file.cc
@@ -52,14 +52,14 @@
     scoped_refptr<net::IOBuffer> buffer,
     int64_t offset,
     int length,
-    const ProvidedFileSystemInterface::ReadChunkReceivedCallback& callback)
+    ProvidedFileSystemInterface::ReadChunkReceivedCallback callback)
     : Operation(event_router, file_system_info),
       file_handle_(file_handle),
       buffer_(buffer),
       offset_(offset),
       length_(length),
       current_offset_(0),
-      callback_(callback) {}
+      callback_(std::move(callback)) {}
 
 ReadFile::~ReadFile() {
 }
diff --git a/chrome/browser/chromeos/file_system_provider/operations/read_file.h b/chrome/browser/chromeos/file_system_provider/operations/read_file.h
index 536e0511..f633865 100644
--- a/chrome/browser/chromeos/file_system_provider/operations/read_file.h
+++ b/chrome/browser/chromeos/file_system_provider/operations/read_file.h
@@ -31,14 +31,13 @@
 // Created per request.
 class ReadFile : public Operation {
  public:
-  ReadFile(
-      extensions::EventRouter* event_router,
-      const ProvidedFileSystemInfo& file_system_info,
-      int file_handle,
-      scoped_refptr<net::IOBuffer> buffer,
-      int64_t offset,
-      int length,
-      const ProvidedFileSystemInterface::ReadChunkReceivedCallback& callback);
+  ReadFile(extensions::EventRouter* event_router,
+           const ProvidedFileSystemInfo& file_system_info,
+           int file_handle,
+           scoped_refptr<net::IOBuffer> buffer,
+           int64_t offset,
+           int length,
+           ProvidedFileSystemInterface::ReadChunkReceivedCallback callback);
   ~ReadFile() override;
 
   // Operation overrides.
@@ -56,7 +55,7 @@
   int64_t offset_;
   int length_;
   int64_t current_offset_;
-  const ProvidedFileSystemInterface::ReadChunkReceivedCallback callback_;
+  ProvidedFileSystemInterface::ReadChunkReceivedCallback callback_;
 
   DISALLOW_COPY_AND_ASSIGN(ReadFile);
 };
diff --git a/chrome/browser/chromeos/file_system_provider/provided_file_system.cc b/chrome/browser/chromeos/file_system_provider/provided_file_system.cc
index 5a99942..fb28e2b 100644
--- a/chrome/browser/chromeos/file_system_provider/provided_file_system.cc
+++ b/chrome/browser/chromeos/file_system_provider/provided_file_system.cc
@@ -76,7 +76,7 @@
                         const base::FilePath& entry_path,
                         bool recursive,
                         bool persistent,
-                        const storage::AsyncFileUtil::StatusCallback& callback,
+                        storage::AsyncFileUtil::StatusCallback callback,
                         const storage::WatcherManager::NotificationCallback&
                             notification_callback)
       : token(token),
@@ -84,16 +84,17 @@
         entry_path(entry_path),
         recursive(recursive),
         persistent(persistent),
-        callback(callback),
+        callback(std::move(callback)),
         notification_callback(notification_callback) {}
   ~AddWatcherInQueueArgs() {}
+  AddWatcherInQueueArgs(AddWatcherInQueueArgs&&) = default;
 
   const size_t token;
   const GURL origin;
   const base::FilePath entry_path;
   const bool recursive;
   const bool persistent;
-  const storage::AsyncFileUtil::StatusCallback callback;
+  storage::AsyncFileUtil::StatusCallback callback;
   const storage::WatcherManager::NotificationCallback notification_callback;
 };
 
@@ -105,14 +106,14 @@
       storage::WatcherManager::ChangeType change_type,
       std::unique_ptr<ProvidedFileSystemObserver::Changes> changes,
       const std::string& tag,
-      const storage::AsyncFileUtil::StatusCallback& callback)
+      storage::AsyncFileUtil::StatusCallback callback)
       : token(token),
         entry_path(entry_path),
         recursive(recursive),
         change_type(change_type),
         changes(std::move(changes)),
         tag(tag),
-        callback(callback) {}
+        callback(std::move(callback)) {}
   ~NotifyInQueueArgs() {}
 
   const size_t token;
@@ -121,7 +122,7 @@
   const storage::WatcherManager::ChangeType change_type;
   const std::unique_ptr<ProvidedFileSystemObserver::Changes> changes;
   const std::string tag;
-  const storage::AsyncFileUtil::StatusCallback callback;
+  storage::AsyncFileUtil::StatusCallback callback;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(NotifyInQueueArgs);
@@ -165,7 +166,7 @@
 }
 
 AbortCallback ProvidedFileSystem::RequestUnmount(
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   const int request_id = request_manager_->CreateRequest(
       REQUEST_UNMOUNT,
       std::unique_ptr<RequestManager::HandlerInterface>(
@@ -179,10 +180,9 @@
       &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
 }
 
-AbortCallback ProvidedFileSystem::GetMetadata(
-    const base::FilePath& entry_path,
-    MetadataFieldMask fields,
-    const GetMetadataCallback& callback) {
+AbortCallback ProvidedFileSystem::GetMetadata(const base::FilePath& entry_path,
+                                              MetadataFieldMask fields,
+                                              GetMetadataCallback callback) {
   const int request_id = request_manager_->CreateRequest(
       GET_METADATA,
       std::unique_ptr<RequestManager::HandlerInterface>(
@@ -200,7 +200,7 @@
 
 AbortCallback ProvidedFileSystem::GetActions(
     const std::vector<base::FilePath>& entry_paths,
-    const GetActionsCallback& callback) {
+    GetActionsCallback callback) {
   const int request_id = request_manager_->CreateRequest(
       GET_ACTIONS,
       std::unique_ptr<RequestManager::HandlerInterface>(
@@ -218,7 +218,7 @@
 AbortCallback ProvidedFileSystem::ExecuteAction(
     const std::vector<base::FilePath>& entry_paths,
     const std::string& action_id,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   const int request_id = request_manager_->CreateRequest(
       EXECUTE_ACTION,
       std::unique_ptr<RequestManager::HandlerInterface>(
@@ -235,7 +235,7 @@
 
 AbortCallback ProvidedFileSystem::ReadDirectory(
     const base::FilePath& directory_path,
-    const storage::AsyncFileUtil::ReadDirectoryCallback& callback) {
+    storage::AsyncFileUtil::ReadDirectoryCallback callback) {
   const int request_id = request_manager_->CreateRequest(
       READ_DIRECTORY,
       std::unique_ptr<RequestManager::HandlerInterface>(
@@ -252,12 +252,11 @@
       &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
 }
 
-AbortCallback ProvidedFileSystem::ReadFile(
-    int file_handle,
-    net::IOBuffer* buffer,
-    int64_t offset,
-    int length,
-    const ReadChunkReceivedCallback& callback) {
+AbortCallback ProvidedFileSystem::ReadFile(int file_handle,
+                                           net::IOBuffer* buffer,
+                                           int64_t offset,
+                                           int length,
+                                           ReadChunkReceivedCallback callback) {
   TRACE_EVENT1(
       "file_system_provider", "ProvidedFileSystem::ReadFile", "length", length);
   const int request_id = request_manager_->CreateRequest(
@@ -278,7 +277,7 @@
 
 AbortCallback ProvidedFileSystem::OpenFile(const base::FilePath& file_path,
                                            OpenFileMode mode,
-                                           const OpenFileCallback& callback) {
+                                           OpenFileCallback callback) {
   const int request_id = request_manager_->CreateRequest(
       OPEN_FILE, std::unique_ptr<RequestManager::HandlerInterface>(
                      new operations::OpenFile(
@@ -297,7 +296,7 @@
 
 AbortCallback ProvidedFileSystem::CloseFile(
     int file_handle,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   const int request_id = request_manager_->CreateRequest(
       CLOSE_FILE, std::unique_ptr<RequestManager::HandlerInterface>(
                       new operations::CloseFile(
@@ -317,7 +316,7 @@
 AbortCallback ProvidedFileSystem::CreateDirectory(
     const base::FilePath& directory_path,
     bool recursive,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   const int request_id = request_manager_->CreateRequest(
       CREATE_DIRECTORY, std::unique_ptr<RequestManager::HandlerInterface>(
                             new operations::CreateDirectory(
@@ -335,7 +334,7 @@
 AbortCallback ProvidedFileSystem::DeleteEntry(
     const base::FilePath& entry_path,
     bool recursive,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   const int request_id = request_manager_->CreateRequest(
       DELETE_ENTRY,
       std::unique_ptr<RequestManager::HandlerInterface>(
@@ -352,7 +351,7 @@
 
 AbortCallback ProvidedFileSystem::CreateFile(
     const base::FilePath& file_path,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   const int request_id = request_manager_->CreateRequest(
       CREATE_FILE,
       std::unique_ptr<RequestManager::HandlerInterface>(
@@ -370,7 +369,7 @@
 AbortCallback ProvidedFileSystem::CopyEntry(
     const base::FilePath& source_path,
     const base::FilePath& target_path,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   const int request_id = request_manager_->CreateRequest(
       COPY_ENTRY,
       std::unique_ptr<RequestManager::HandlerInterface>(
@@ -390,7 +389,7 @@
     net::IOBuffer* buffer,
     int64_t offset,
     int length,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   TRACE_EVENT1("file_system_provider",
                "ProvidedFileSystem::WriteFile",
                "length",
@@ -413,7 +412,7 @@
 AbortCallback ProvidedFileSystem::MoveEntry(
     const base::FilePath& source_path,
     const base::FilePath& target_path,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   const int request_id = request_manager_->CreateRequest(
       MOVE_ENTRY,
       std::unique_ptr<RequestManager::HandlerInterface>(
@@ -431,7 +430,7 @@
 AbortCallback ProvidedFileSystem::Truncate(
     const base::FilePath& file_path,
     int64_t length,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   const int request_id = request_manager_->CreateRequest(
       TRUNCATE, std::unique_ptr<RequestManager::HandlerInterface>(
                     new operations::Truncate(event_router_, file_system_info_,
@@ -450,16 +449,17 @@
     const base::FilePath& entry_path,
     bool recursive,
     bool persistent,
-    const storage::AsyncFileUtil::StatusCallback& callback,
+    storage::AsyncFileUtil::StatusCallback callback,
     const storage::WatcherManager::NotificationCallback&
         notification_callback) {
   const size_t token = watcher_queue_.NewToken();
   watcher_queue_.Enqueue(
-      token, base::Bind(&ProvidedFileSystem::AddWatcherInQueue,
-                        base::Unretained(this),  // Outlived by the queue.
-                        AddWatcherInQueueArgs(token, origin, entry_path,
-                                              recursive, persistent, callback,
-                                              notification_callback)));
+      token,
+      base::BindOnce(&ProvidedFileSystem::AddWatcherInQueue,
+                     base::Unretained(this),  // Outlived by the queue.
+                     AddWatcherInQueueArgs(token, origin, entry_path, recursive,
+                                           persistent, std::move(callback),
+                                           notification_callback)));
   return AbortCallback();
 }
 
@@ -467,12 +467,13 @@
     const GURL& origin,
     const base::FilePath& entry_path,
     bool recursive,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   const size_t token = watcher_queue_.NewToken();
   watcher_queue_.Enqueue(
-      token, base::Bind(&ProvidedFileSystem::RemoveWatcherInQueue,
-                        base::Unretained(this),  // Outlived by the queue.
-                        token, origin, entry_path, recursive, callback));
+      token, base::BindOnce(&ProvidedFileSystem::RemoveWatcherInQueue,
+                            base::Unretained(this),  // Outlived by the queue.
+                            token, origin, entry_path, recursive,
+                            std::move(callback)));
 }
 
 const ProvidedFileSystemInfo& ProvidedFileSystem::GetFileSystemInfo() const {
@@ -507,18 +508,18 @@
     storage::WatcherManager::ChangeType change_type,
     std::unique_ptr<ProvidedFileSystemObserver::Changes> changes,
     const std::string& tag,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   const size_t token = watcher_queue_.NewToken();
   watcher_queue_.Enqueue(
-      token, base::Bind(&ProvidedFileSystem::NotifyInQueue,
-                        base::Unretained(this),  // Outlived by the queue.
-                        base::Passed(std::make_unique<NotifyInQueueArgs>(
-                            token, entry_path, recursive, change_type,
-                            std::move(changes), tag, callback))));
+      token, base::BindOnce(&ProvidedFileSystem::NotifyInQueue,
+                            base::Unretained(this),  // Outlived by the queue.
+                            std::make_unique<NotifyInQueueArgs>(
+                                token, entry_path, recursive, change_type,
+                                std::move(changes), tag, std::move(callback))));
 }
 
 void ProvidedFileSystem::Configure(
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   const int request_id = request_manager_->CreateRequest(
       CONFIGURE, std::unique_ptr<RequestManager::HandlerInterface>(
                      new operations::Configure(event_router_, file_system_info_,
@@ -557,11 +558,11 @@
 }
 
 AbortCallback ProvidedFileSystem::AddWatcherInQueue(
-    const AddWatcherInQueueArgs& args) {
+    AddWatcherInQueueArgs args) {
   if (args.persistent && (!file_system_info_.supports_notify_tag() ||
                           !args.notification_callback.is_null())) {
     OnAddWatcherInQueueCompleted(args.token, args.entry_path, args.recursive,
-                                 Subscriber(), args.callback,
+                                 Subscriber(), std::move(args.callback),
                                  base::File::FILE_ERROR_INVALID_OPERATION);
     return AbortCallback();
   }
@@ -579,7 +580,8 @@
     const bool exists = it->second.subscribers.find(args.origin) !=
                         it->second.subscribers.end();
     OnAddWatcherInQueueCompleted(
-        args.token, args.entry_path, args.recursive, subscriber, args.callback,
+        args.token, args.entry_path, args.recursive, subscriber,
+        std::move(args.callback),
         exists ? base::File::FILE_ERROR_EXISTS : base::File::FILE_OK);
     return AbortCallback();
   }
@@ -608,12 +610,12 @@
     const GURL& origin,
     const base::FilePath& entry_path,
     bool recursive,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   const WatcherKey key(entry_path, recursive);
   const Watchers::iterator it = watchers_.find(key);
   if (it == watchers_.end() ||
       it->second.subscribers.find(origin) == it->second.subscribers.end()) {
-    OnRemoveWatcherInQueueCompleted(token, origin, key, callback,
+    OnRemoveWatcherInQueueCompleted(token, origin, key, std::move(callback),
                                     false /* extension_response */,
                                     base::File::FILE_ERROR_NOT_FOUND);
     return AbortCallback();
@@ -622,7 +624,7 @@
   // If there are other subscribers, then do not remove the observer, but simply
   // return a success.
   if (it->second.subscribers.size() > 1) {
-    OnRemoveWatcherInQueueCompleted(token, origin, key, callback,
+    OnRemoveWatcherInQueueCompleted(token, origin, key, std::move(callback),
                                     false /* extension_response */,
                                     base::File::FILE_OK);
     return AbortCallback();
@@ -636,7 +638,7 @@
               event_router_, file_system_info_, entry_path, recursive,
               base::Bind(&ProvidedFileSystem::OnRemoveWatcherInQueueCompleted,
                          weak_ptr_factory_.GetWeakPtr(), token, origin, key,
-                         callback, true /* extension_response */))));
+                         std::move(callback), true /* extension_response */))));
 
   return AbortCallback();
 }
@@ -701,10 +703,10 @@
     const base::FilePath& entry_path,
     bool recursive,
     const Subscriber& subscriber,
-    const storage::AsyncFileUtil::StatusCallback& callback,
+    storage::AsyncFileUtil::StatusCallback callback,
     base::File::Error result) {
   if (result != base::File::FILE_OK) {
-    callback.Run(result);
+    std::move(callback).Run(result);
     watcher_queue_.Complete(token);
     return;
   }
@@ -712,7 +714,7 @@
   const WatcherKey key(entry_path, recursive);
   const Watchers::iterator it = watchers_.find(key);
   if (it != watchers_.end()) {
-    callback.Run(base::File::FILE_OK);
+    std::move(callback).Run(base::File::FILE_OK);
     watcher_queue_.Complete(token);
     return;
   }
@@ -725,7 +727,7 @@
   for (auto& observer : observers_)
     observer.OnWatcherListChanged(file_system_info_, watchers_);
 
-  callback.Run(base::File::FILE_OK);
+  std::move(callback).Run(base::File::FILE_OK);
   watcher_queue_.Complete(token);
 }
 
@@ -733,12 +735,12 @@
     size_t token,
     const GURL& origin,
     const WatcherKey& key,
-    const storage::AsyncFileUtil::StatusCallback& callback,
+    storage::AsyncFileUtil::StatusCallback callback,
     bool extension_response,
     base::File::Error result) {
   if (!extension_response && result != base::File::FILE_OK) {
     watcher_queue_.Complete(token);
-    callback.Run(result);
+    std::move(callback).Run(result);
     return;
   }
 
@@ -757,7 +759,7 @@
   if (it->second.subscribers.empty())
     watchers_.erase(it);
 
-  callback.Run(base::File::FILE_OK);
+  std::move(callback).Run(base::File::FILE_OK);
   watcher_queue_.Complete(token);
 }
 
@@ -765,7 +767,7 @@
     std::unique_ptr<NotifyInQueueArgs> args,
     base::File::Error result) {
   if (result != base::File::FILE_OK) {
-    args->callback.Run(result);
+    std::move(args->callback).Run(result);
     watcher_queue_.Complete(args->token);
     return;
   }
@@ -774,7 +776,7 @@
   const WatcherKey key(args->entry_path, args->recursive);
   const Watchers::iterator it = watchers_.find(key);
   if (it == watchers_.end()) {
-    args->callback.Run(base::File::FILE_ERROR_NOT_FOUND);
+    std::move(args->callback).Run(base::File::FILE_ERROR_NOT_FOUND);
     watcher_queue_.Complete(args->token);
     return;
   }
@@ -795,32 +797,32 @@
     }
   }
 
-  args->callback.Run(base::File::FILE_OK);
+  std::move(args->callback).Run(base::File::FILE_OK);
   watcher_queue_.Complete(args->token);
 }
 
 void ProvidedFileSystem::OnOpenFileCompleted(const base::FilePath& file_path,
                                              OpenFileMode mode,
-                                             const OpenFileCallback& callback,
+                                             OpenFileCallback callback,
                                              int file_handle,
                                              base::File::Error result) {
   if (result != base::File::FILE_OK) {
-    callback.Run(file_handle, result);
+    std::move(callback).Run(file_handle, result);
     return;
   }
 
   opened_files_[file_handle] = OpenedFile(file_path, mode);
-  callback.Run(file_handle, base::File::FILE_OK);
+  std::move(callback).Run(file_handle, base::File::FILE_OK);
 }
 
 void ProvidedFileSystem::OnCloseFileCompleted(
     int file_handle,
-    const storage::AsyncFileUtil::StatusCallback& callback,
+    storage::AsyncFileUtil::StatusCallback callback,
     base::File::Error result) {
   // Closing files is final. Even if an error happened, we remove it from the
   // list of opened files.
   opened_files_.erase(file_handle);
-  callback.Run(result);
+  std::move(callback).Run(result);
 }
 
 }  // namespace file_system_provider
diff --git a/chrome/browser/chromeos/file_system_provider/provided_file_system.h b/chrome/browser/chromeos/file_system_provider/provided_file_system.h
index 08902a4..63b7db9 100644
--- a/chrome/browser/chromeos/file_system_provider/provided_file_system.h
+++ b/chrome/browser/chromeos/file_system_provider/provided_file_system.h
@@ -95,72 +95,70 @@
 
   // ProvidedFileSystemInterface overrides.
   AbortCallback RequestUnmount(
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
   AbortCallback GetMetadata(const base::FilePath& entry_path,
                             MetadataFieldMask fields,
-                            const GetMetadataCallback& callback) override;
+                            GetMetadataCallback callback) override;
   AbortCallback GetActions(const std::vector<base::FilePath>& entry_paths,
-                           const GetActionsCallback& callback) override;
+                           GetActionsCallback callback) override;
   AbortCallback ExecuteAction(
       const std::vector<base::FilePath>& entry_paths,
       const std::string& action_id,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
   AbortCallback ReadDirectory(
       const base::FilePath& directory_path,
-      const storage::AsyncFileUtil::ReadDirectoryCallback& callback) override;
+      storage::AsyncFileUtil::ReadDirectoryCallback callback) override;
   AbortCallback OpenFile(const base::FilePath& file_path,
                          OpenFileMode mode,
-                         const OpenFileCallback& callback) override;
+                         OpenFileCallback callback) override;
   AbortCallback CloseFile(
       int file_handle,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
   AbortCallback ReadFile(int file_handle,
                          net::IOBuffer* buffer,
                          int64_t offset,
                          int length,
-                         const ReadChunkReceivedCallback& callback) override;
+                         ReadChunkReceivedCallback callback) override;
   AbortCallback CreateDirectory(
       const base::FilePath& directory_path,
       bool recursive,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
   AbortCallback DeleteEntry(
       const base::FilePath& entry_path,
       bool recursive,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
   AbortCallback CreateFile(
       const base::FilePath& file_path,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
   AbortCallback CopyEntry(
       const base::FilePath& source_path,
       const base::FilePath& target_path,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
   AbortCallback MoveEntry(
       const base::FilePath& source_path,
       const base::FilePath& target_path,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
   AbortCallback Truncate(
       const base::FilePath& file_path,
       int64_t length,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
   AbortCallback WriteFile(
       int file_handle,
       net::IOBuffer* buffer,
       int64_t offset,
       int length,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
-  AbortCallback AddWatcher(
-      const GURL& origin,
-      const base::FilePath& entry_path,
-      bool recursive,
-      bool persistent,
-      const storage::AsyncFileUtil::StatusCallback& callback,
-      const storage::WatcherManager::NotificationCallback&
-          notification_callback) override;
-  void RemoveWatcher(
-      const GURL& origin,
-      const base::FilePath& entry_path,
-      bool recursive,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
+  AbortCallback AddWatcher(const GURL& origin,
+                           const base::FilePath& entry_path,
+                           bool recursive,
+                           bool persistent,
+                           storage::AsyncFileUtil::StatusCallback callback,
+                           const storage::WatcherManager::NotificationCallback&
+                               notification_callback) override;
+  void RemoveWatcher(const GURL& origin,
+                     const base::FilePath& entry_path,
+                     bool recursive,
+                     storage::AsyncFileUtil::StatusCallback callback) override;
   const ProvidedFileSystemInfo& GetFileSystemInfo() const override;
   RequestManager* GetRequestManager() override;
   Watchers* GetWatchers() override;
@@ -172,9 +170,8 @@
               storage::WatcherManager::ChangeType change_type,
               std::unique_ptr<ProvidedFileSystemObserver::Changes> changes,
               const std::string& tag,
-              const storage::AsyncFileUtil::StatusCallback& callback) override;
-  void Configure(
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+              storage::AsyncFileUtil::StatusCallback callback) override;
+  void Configure(storage::AsyncFileUtil::StatusCallback callback) override;
   base::WeakPtr<ProvidedFileSystemInterface> GetWeakPtr() override;
 
  private:
@@ -195,7 +192,7 @@
   void OnAbortCompleted(int operation_request_id, base::File::Error result);
 
   // Adds a watcher within |watcher_queue_|.
-  AbortCallback AddWatcherInQueue(const AddWatcherInQueueArgs& args);
+  AbortCallback AddWatcherInQueue(AddWatcherInQueueArgs args);
 
   // Removes a watcher within |watcher_queue_|.
   AbortCallback RemoveWatcherInQueue(
@@ -203,7 +200,7 @@
       const GURL& origin,
       const base::FilePath& entry_path,
       bool recursive,
-      const storage::AsyncFileUtil::StatusCallback& callback);
+      storage::AsyncFileUtil::StatusCallback callback);
 
   // Notifies about a notifier even within |watcher_queue_|.
   AbortCallback NotifyInQueue(std::unique_ptr<NotifyInQueueArgs> args);
@@ -214,7 +211,7 @@
       const base::FilePath& entry_path,
       bool recursive,
       const Subscriber& subscriber,
-      const storage::AsyncFileUtil::StatusCallback& callback,
+      storage::AsyncFileUtil::StatusCallback callback,
       base::File::Error result);
 
   // Called when adding a watcher is completed with either a success or an
@@ -223,7 +220,7 @@
       size_t token,
       const GURL& origin,
       const WatcherKey& key,
-      const storage::AsyncFileUtil::StatusCallback& callback,
+      storage::AsyncFileUtil::StatusCallback callback,
       bool extension_response,
       base::File::Error result);
 
@@ -235,15 +232,14 @@
   // Called when opening a file is completed with either a success or an error.
   void OnOpenFileCompleted(const base::FilePath& file_path,
                            OpenFileMode mode,
-                           const OpenFileCallback& callback,
+                           OpenFileCallback callback,
                            int file_handle,
                            base::File::Error result);
 
   // Called when closing a file is completed with either a success or an error.
-  void OnCloseFileCompleted(
-      int file_handle,
-      const storage::AsyncFileUtil::StatusCallback& callback,
-      base::File::Error result);
+  void OnCloseFileCompleted(int file_handle,
+                            storage::AsyncFileUtil::StatusCallback callback,
+                            base::File::Error result);
 
   Profile* profile_;                       // Not owned.
   extensions::EventRouter* event_router_;  // Not owned. May be NULL.
diff --git a/chrome/browser/chromeos/file_system_provider/provided_file_system_interface.h b/chrome/browser/chromeos/file_system_provider/provided_file_system_interface.h
index a18101fc..86a9bcab0 100644
--- a/chrome/browser/chromeos/file_system_provider/provided_file_system_interface.h
+++ b/chrome/browser/chromeos/file_system_provider/provided_file_system_interface.h
@@ -105,7 +105,7 @@
   typedef base::Callback<void(int file_handle, base::File::Error result)>
       OpenFileCallback;
 
-  typedef base::Callback<
+  typedef base::RepeatingCallback<
       void(int chunk_length, bool has_more, base::File::Error result)>
       ReadChunkReceivedCallback;
 
@@ -124,44 +124,44 @@
   // Requests unmounting of the file system. The callback is called when the
   // request is accepted or rejected, with an error code.
   virtual AbortCallback RequestUnmount(
-      const storage::AsyncFileUtil::StatusCallback& callback) = 0;
+      storage::AsyncFileUtil::StatusCallback callback) = 0;
 
   // Requests metadata of the passed |entry_path|. It can be either a file
   // or a directory. All |fields| will be returned if supported. Note, that
   // default fields are always returned.
   virtual AbortCallback GetMetadata(const base::FilePath& entry_path,
                                     MetadataFieldMask fields,
-                                    const GetMetadataCallback& callback) = 0;
+                                    GetMetadataCallback callback) = 0;
 
   // Requests list of actions for the passed list of entries at |entry_paths|.
   // They can be either files or directories.
   virtual AbortCallback GetActions(
       const std::vector<base::FilePath>& entry_paths,
-      const GetActionsCallback& callback) = 0;
+      GetActionsCallback callback) = 0;
 
   // Executes the |action_id| action on the list of entries at |entry_paths|.
   virtual AbortCallback ExecuteAction(
       const std::vector<base::FilePath>& entry_paths,
       const std::string& action_id,
-      const storage::AsyncFileUtil::StatusCallback& callback) = 0;
+      storage::AsyncFileUtil::StatusCallback callback) = 0;
 
   // Requests enumerating entries from the passed |directory_path|. The callback
   // can be called multiple times until |has_more| is set to false.
   virtual AbortCallback ReadDirectory(
       const base::FilePath& directory_path,
-      const storage::AsyncFileUtil::ReadDirectoryCallback& callback) = 0;
+      storage::AsyncFileUtil::ReadDirectoryCallback callback) = 0;
 
   // Requests opening a file at |file_path|. If the file doesn't exist, then the
   // operation will fail. In case of any error, the returned file handle is 0.
   virtual AbortCallback OpenFile(const base::FilePath& file_path,
                                  OpenFileMode mode,
-                                 const OpenFileCallback& callback) = 0;
+                                 OpenFileCallback callback) = 0;
 
   // Requests closing a file, previously opened with OpenFile() as a file with
   // |file_handle|. The |callback| must be called.
   virtual AbortCallback CloseFile(
       int file_handle,
-      const storage::AsyncFileUtil::StatusCallback& callback) = 0;
+      storage::AsyncFileUtil::StatusCallback callback) = 0;
 
   // Requests reading a file previously opened with |file_handle|. The callback
   // can be called multiple times until |has_more| is set to false. On success
@@ -171,7 +171,7 @@
                                  net::IOBuffer* buffer,
                                  int64_t offset,
                                  int length,
-                                 const ReadChunkReceivedCallback& callback) = 0;
+                                 ReadChunkReceivedCallback callback) = 0;
 
   // Requests creating a directory. If |recursive| is passed, then all non
   // existing directories on the path will be created. The operation will fail
@@ -179,40 +179,40 @@
   virtual AbortCallback CreateDirectory(
       const base::FilePath& directory_path,
       bool recursive,
-      const storage::AsyncFileUtil::StatusCallback& callback) = 0;
+      storage::AsyncFileUtil::StatusCallback callback) = 0;
 
   // Requests creating a file. If the entry already exists, then the
   // FILE_ERROR_EXISTS error must be returned.
   virtual AbortCallback CreateFile(
       const base::FilePath& file_path,
-      const storage::AsyncFileUtil::StatusCallback& callback) = 0;
+      storage::AsyncFileUtil::StatusCallback callback) = 0;
 
   // Requests deleting a directory. If |recursive| is passed and the entry is
   // a directory, then all contents of it (recursively) will be deleted too.
   virtual AbortCallback DeleteEntry(
       const base::FilePath& entry_path,
       bool recursive,
-      const storage::AsyncFileUtil::StatusCallback& callback) = 0;
+      storage::AsyncFileUtil::StatusCallback callback) = 0;
 
   // Requests copying an entry (recursively in case of a directory) within the
   // same file system.
   virtual AbortCallback CopyEntry(
       const base::FilePath& source_path,
       const base::FilePath& target_path,
-      const storage::AsyncFileUtil::StatusCallback& callback) = 0;
+      storage::AsyncFileUtil::StatusCallback callback) = 0;
 
   // Requests moving an entry (recursively in case of a directory) within the
   // same file system.
   virtual AbortCallback MoveEntry(
       const base::FilePath& source_path,
       const base::FilePath& target_path,
-      const storage::AsyncFileUtil::StatusCallback& callback) = 0;
+      storage::AsyncFileUtil::StatusCallback callback) = 0;
 
   // Requests truncating a file to the desired length.
   virtual AbortCallback Truncate(
       const base::FilePath& file_path,
       int64_t length,
-      const storage::AsyncFileUtil::StatusCallback& callback) = 0;
+      storage::AsyncFileUtil::StatusCallback callback) = 0;
 
   // Requests writing to a file previously opened with |file_handle|.
   virtual AbortCallback WriteFile(
@@ -220,7 +220,7 @@
       net::IOBuffer* buffer,
       int64_t offset,
       int length,
-      const storage::AsyncFileUtil::StatusCallback& callback) = 0;
+      storage::AsyncFileUtil::StatusCallback callback) = 0;
 
   // Requests adding a watcher on an entry. |recursive| must not be true for
   // files. |callback| is optional, but it can't be used for persistent
@@ -230,7 +230,7 @@
       const base::FilePath& entry_path,
       bool recursive,
       bool persistent,
-      const storage::AsyncFileUtil::StatusCallback& callback,
+      storage::AsyncFileUtil::StatusCallback callback,
       const storage::WatcherManager::NotificationCallback&
           notification_callback) = 0;
 
@@ -240,7 +240,7 @@
       const GURL& origin,
       const base::FilePath& entry_path,
       bool recursive,
-      const storage::AsyncFileUtil::StatusCallback& callback) = 0;
+      storage::AsyncFileUtil::StatusCallback callback) = 0;
 
   // Notifies about changes related to the watcher within the file system.
   // Invoked by the file system implementation. Returns an error code via the
@@ -253,13 +253,12 @@
       storage::WatcherManager::ChangeType change_type,
       std::unique_ptr<ProvidedFileSystemObserver::Changes> changes,
       const std::string& tag,
-      const storage::AsyncFileUtil::StatusCallback& callback) = 0;
+      storage::AsyncFileUtil::StatusCallback callback) = 0;
 
   // Requests showing UI for configuring the file system by user. Once the
   // configuration process is completed, base::File::FILE_OK or an error code is
   // returned via the |callback|.
-  virtual void Configure(
-      const storage::AsyncFileUtil::StatusCallback& callback) = 0;
+  virtual void Configure(storage::AsyncFileUtil::StatusCallback callback) = 0;
 
   // Returns a provided file system info for this file system.
   virtual const ProvidedFileSystemInfo& GetFileSystemInfo() const = 0;
diff --git a/chrome/browser/chromeos/file_system_provider/scoped_file_opener.cc b/chrome/browser/chromeos/file_system_provider/scoped_file_opener.cc
index 8437f74..a60159f5 100644
--- a/chrome/browser/chromeos/file_system_provider/scoped_file_opener.cc
+++ b/chrome/browser/chromeos/file_system_provider/scoped_file_opener.cc
@@ -20,9 +20,9 @@
   Runner(ProvidedFileSystemInterface* file_system,
          const base::FilePath& file_path,
          OpenFileMode mode,
-         const OpenFileCallback& callback)
+         OpenFileCallback callback)
       : file_system_(file_system->GetWeakPtr()),
-        open_callback_(callback),
+        open_callback_(std::move(callback)),
         aborting_requested_(false),
         open_completed_(false),
         file_handle_(0) {
@@ -112,9 +112,7 @@
     if (open_callback_.is_null())
       return;
 
-    OpenFileCallback open_callback = open_callback_;
-    open_callback_ = OpenFileCallback();
-    open_callback.Run(file_handle, result);
+    std::move(open_callback_).Run(file_handle, result);
   }
 
   base::WeakPtr<ProvidedFileSystemInterface> file_system_;
@@ -128,8 +126,8 @@
 ScopedFileOpener::ScopedFileOpener(ProvidedFileSystemInterface* file_system,
                                    const base::FilePath& file_path,
                                    OpenFileMode mode,
-                                   const OpenFileCallback& callback)
-    : runner_(new Runner(file_system, file_path, mode, callback)) {}
+                                   OpenFileCallback callback)
+    : runner_(new Runner(file_system, file_path, mode, std::move(callback))) {}
 
 ScopedFileOpener::~ScopedFileOpener() {
   runner_->AbortOrClose();
diff --git a/chrome/browser/chromeos/file_system_provider/scoped_file_opener.h b/chrome/browser/chromeos/file_system_provider/scoped_file_opener.h
index 90af30d6..16f741a4 100644
--- a/chrome/browser/chromeos/file_system_provider/scoped_file_opener.h
+++ b/chrome/browser/chromeos/file_system_provider/scoped_file_opener.h
@@ -23,11 +23,10 @@
 // aborted.
 class ScopedFileOpener {
  public:
-  ScopedFileOpener(
-      ProvidedFileSystemInterface* file_system,
-      const base::FilePath& file_path,
-      OpenFileMode mode,
-      const ProvidedFileSystemInterface::OpenFileCallback& callback);
+  ScopedFileOpener(ProvidedFileSystemInterface* file_system,
+                   const base::FilePath& file_path,
+                   OpenFileMode mode,
+                   ProvidedFileSystemInterface::OpenFileCallback callback);
   ~ScopedFileOpener();
 
  private:
diff --git a/chrome/browser/chromeos/file_system_provider/scoped_file_opener_unittest.cc b/chrome/browser/chromeos/file_system_provider/scoped_file_opener_unittest.cc
index f87e6ce..5ba2518 100644
--- a/chrome/browser/chromeos/file_system_provider/scoped_file_opener_unittest.cc
+++ b/chrome/browser/chromeos/file_system_provider/scoped_file_opener_unittest.cc
@@ -29,30 +29,37 @@
 
   AbortCallback OpenFile(const base::FilePath& file_path,
                          OpenFileMode mode,
-                         const OpenFileCallback& callback) override {
-    open_callback_ = callback;
+                         OpenFileCallback callback) override {
+    open_callback_ = std::move(callback);
     return base::Bind(&TestingProvidedFileSystem::AbortOpen,
                       base::Unretained(this));
   }
 
   AbortCallback CloseFile(
       int file_handle,
-      const storage::AsyncFileUtil::StatusCallback& callback) override {
+      storage::AsyncFileUtil::StatusCallback callback) override {
     close_requests_.push_back(file_handle);
-    callback.Run(base::File::FILE_OK);
+    std::move(callback).Run(base::File::FILE_OK);
     return AbortCallback();
   }
 
-  const OpenFileCallback& open_callback() const { return open_callback_; }
+  bool has_open_callback() const { return !!open_callback_; }
+  OpenFileCallback open_callback() {
+    return base::Bind(&TestingProvidedFileSystem::CompleteOpen,
+                      base::Unretained(this));
+  }
   const std::vector<int> close_requests() const { return close_requests_; }
 
  private:
   OpenFileCallback open_callback_;
   std::vector<int> close_requests_;
 
+  void CompleteOpen(int file_handle, base::File::Error result) {
+    std::move(open_callback_).Run(file_handle, result);
+  }
+
   void AbortOpen() {
-    open_callback_.Run(0, base::File::FILE_ERROR_ABORT);
-    open_callback_ = OpenFileCallback();
+    std::move(open_callback_).Run(0, base::File::FILE_ERROR_ABORT);
   }
 };
 
@@ -73,7 +80,7 @@
                                  OPEN_FILE_MODE_READ,
                                  base::Bind(&LogOpen, &log));
     base::RunLoop().RunUntilIdle();
-    EXPECT_FALSE(file_system.open_callback().is_null());
+    EXPECT_TRUE(file_system.has_open_callback());
   }
   ASSERT_EQ(1u, log.size());
   EXPECT_EQ(0, log[0].first);
@@ -83,34 +90,6 @@
   EXPECT_EQ(0u, file_system.close_requests().size());
 }
 
-TEST(ScopedFileOpenerTest, CloseWhileOpening) {
-  TestingProvidedFileSystem file_system;
-  content::TestBrowserThreadBundle thread_bundle;
-  OpenLog log;
-  {
-    ScopedFileOpener file_opener(&file_system, base::FilePath(),
-                                 OPEN_FILE_MODE_READ,
-                                 base::Bind(&LogOpen, &log));
-    base::RunLoop().RunUntilIdle();
-    ASSERT_FALSE(file_system.open_callback().is_null());
-    // Complete opening asynchronously, so after trying to abort.
-    const ProvidedFileSystemInterface::OpenFileCallback open_callback =
-        file_system.open_callback();
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::BindOnce(open_callback, 123, base::File::FILE_OK));
-  }
-
-  // Wait until the open callback is called asynchonously.
-  base::RunLoop().RunUntilIdle();
-
-  ASSERT_EQ(1u, log.size());
-  EXPECT_EQ(0, log[0].first);
-  EXPECT_EQ(base::File::FILE_ERROR_ABORT, log[0].second);
-
-  ASSERT_EQ(1u, file_system.close_requests().size());
-  EXPECT_EQ(123, file_system.close_requests()[0]);
-}
-
 TEST(ScopedFileOpenerTest, CloseAfterOpening) {
   TestingProvidedFileSystem file_system;
   content::TestBrowserThreadBundle thread_bundle;
@@ -120,7 +99,7 @@
                                  OPEN_FILE_MODE_READ,
                                  base::Bind(&LogOpen, &log));
     base::RunLoop().RunUntilIdle();
-    ASSERT_FALSE(file_system.open_callback().is_null());
+    ASSERT_TRUE(file_system.has_open_callback());
     file_system.open_callback().Run(123, base::File::FILE_OK);
   }
 
@@ -141,7 +120,7 @@
                                  OPEN_FILE_MODE_READ,
                                  base::Bind(&LogOpen, &log));
     base::RunLoop().RunUntilIdle();
-    ASSERT_FALSE(file_system.open_callback().is_null());
+    ASSERT_TRUE(file_system.has_open_callback());
     file_system.open_callback().Run(0, base::File::FILE_ERROR_ABORT);
   }
 
diff --git a/chrome/browser/chromeos/file_system_provider/throttled_file_system.cc b/chrome/browser/chromeos/file_system_provider/throttled_file_system.cc
index b486235..050b6d0b 100644
--- a/chrome/browser/chromeos/file_system_provider/throttled_file_system.cc
+++ b/chrome/browser/chromeos/file_system_provider/throttled_file_system.cc
@@ -30,33 +30,33 @@
 }
 
 AbortCallback ThrottledFileSystem::RequestUnmount(
-    const storage::AsyncFileUtil::StatusCallback& callback) {
-  return file_system_->RequestUnmount(callback);
+    storage::AsyncFileUtil::StatusCallback callback) {
+  return file_system_->RequestUnmount(std::move(callback));
 }
 
-AbortCallback ThrottledFileSystem::GetMetadata(
-    const base::FilePath& entry_path,
-    MetadataFieldMask fields,
-    const GetMetadataCallback& callback) {
-  return file_system_->GetMetadata(entry_path, fields, callback);
+AbortCallback ThrottledFileSystem::GetMetadata(const base::FilePath& entry_path,
+                                               MetadataFieldMask fields,
+                                               GetMetadataCallback callback) {
+  return file_system_->GetMetadata(entry_path, fields, std::move(callback));
 }
 
 AbortCallback ThrottledFileSystem::GetActions(
     const std::vector<base::FilePath>& entry_paths,
-    const GetActionsCallback& callback) {
-  return file_system_->GetActions(entry_paths, callback);
+    GetActionsCallback callback) {
+  return file_system_->GetActions(entry_paths, std::move(callback));
 }
 
 AbortCallback ThrottledFileSystem::ExecuteAction(
     const std::vector<base::FilePath>& entry_paths,
     const std::string& action_id,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
-  return file_system_->ExecuteAction(entry_paths, action_id, callback);
+    storage::AsyncFileUtil::StatusCallback callback) {
+  return file_system_->ExecuteAction(entry_paths, action_id,
+                                     std::move(callback));
 }
 
 AbortCallback ThrottledFileSystem::ReadDirectory(
     const base::FilePath& directory_path,
-    const storage::AsyncFileUtil::ReadDirectoryCallback& callback) {
+    storage::AsyncFileUtil::ReadDirectoryCallback callback) {
   return file_system_->ReadDirectory(directory_path, callback);
 }
 
@@ -65,60 +65,62 @@
     net::IOBuffer* buffer,
     int64_t offset,
     int length,
-    const ReadChunkReceivedCallback& callback) {
+    ReadChunkReceivedCallback callback) {
   return file_system_->ReadFile(file_handle, buffer, offset, length, callback);
 }
 
 AbortCallback ThrottledFileSystem::OpenFile(const base::FilePath& file_path,
                                             OpenFileMode mode,
-                                            const OpenFileCallback& callback) {
+                                            OpenFileCallback callback) {
   const size_t task_token = open_queue_->NewToken();
   open_queue_->Enqueue(
       task_token,
-      base::Bind(
+      base::BindOnce(
           &ProvidedFileSystemInterface::OpenFile,
           base::Unretained(file_system_.get()),  // Outlives the queue.
           file_path, mode,
           base::Bind(&ThrottledFileSystem::OnOpenFileCompleted,
-                     weak_ptr_factory_.GetWeakPtr(), task_token, callback)));
+                     weak_ptr_factory_.GetWeakPtr(), task_token,
+                     std::move(callback))));
   return base::Bind(&ThrottledFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(),
                     task_token);
 }
 
 AbortCallback ThrottledFileSystem::CloseFile(
     int file_handle,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   return file_system_->CloseFile(
-      file_handle,
-      base::Bind(&ThrottledFileSystem::OnCloseFileCompleted,
-                 weak_ptr_factory_.GetWeakPtr(), file_handle, callback));
+      file_handle, base::Bind(&ThrottledFileSystem::OnCloseFileCompleted,
+                              weak_ptr_factory_.GetWeakPtr(), file_handle,
+                              std::move(callback)));
 }
 
 AbortCallback ThrottledFileSystem::CreateDirectory(
     const base::FilePath& directory_path,
     bool recursive,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
-  return file_system_->CreateDirectory(directory_path, recursive, callback);
+    storage::AsyncFileUtil::StatusCallback callback) {
+  return file_system_->CreateDirectory(directory_path, recursive,
+                                       std::move(callback));
 }
 
 AbortCallback ThrottledFileSystem::DeleteEntry(
     const base::FilePath& entry_path,
     bool recursive,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
-  return file_system_->DeleteEntry(entry_path, recursive, callback);
+    storage::AsyncFileUtil::StatusCallback callback) {
+  return file_system_->DeleteEntry(entry_path, recursive, std::move(callback));
 }
 
 AbortCallback ThrottledFileSystem::CreateFile(
     const base::FilePath& file_path,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
-  return file_system_->CreateFile(file_path, callback);
+    storage::AsyncFileUtil::StatusCallback callback) {
+  return file_system_->CreateFile(file_path, std::move(callback));
 }
 
 AbortCallback ThrottledFileSystem::CopyEntry(
     const base::FilePath& source_path,
     const base::FilePath& target_path,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
-  return file_system_->CopyEntry(source_path, target_path, callback);
+    storage::AsyncFileUtil::StatusCallback callback) {
+  return file_system_->CopyEntry(source_path, target_path, std::move(callback));
 }
 
 AbortCallback ThrottledFileSystem::WriteFile(
@@ -126,22 +128,23 @@
     net::IOBuffer* buffer,
     int64_t offset,
     int length,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
-  return file_system_->WriteFile(file_handle, buffer, offset, length, callback);
+    storage::AsyncFileUtil::StatusCallback callback) {
+  return file_system_->WriteFile(file_handle, buffer, offset, length,
+                                 std::move(callback));
 }
 
 AbortCallback ThrottledFileSystem::MoveEntry(
     const base::FilePath& source_path,
     const base::FilePath& target_path,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
-  return file_system_->MoveEntry(source_path, target_path, callback);
+    storage::AsyncFileUtil::StatusCallback callback) {
+  return file_system_->MoveEntry(source_path, target_path, std::move(callback));
 }
 
 AbortCallback ThrottledFileSystem::Truncate(
     const base::FilePath& file_path,
     int64_t length,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
-  return file_system_->Truncate(file_path, length, callback);
+    storage::AsyncFileUtil::StatusCallback callback) {
+  return file_system_->Truncate(file_path, length, std::move(callback));
 }
 
 AbortCallback ThrottledFileSystem::AddWatcher(
@@ -149,19 +152,20 @@
     const base::FilePath& entry_path,
     bool recursive,
     bool persistent,
-    const storage::AsyncFileUtil::StatusCallback& callback,
+    storage::AsyncFileUtil::StatusCallback callback,
     const storage::WatcherManager::NotificationCallback&
         notification_callback) {
   return file_system_->AddWatcher(origin, entry_path, recursive, persistent,
-                                  callback, notification_callback);
+                                  std::move(callback), notification_callback);
 }
 
 void ThrottledFileSystem::RemoveWatcher(
     const GURL& origin,
     const base::FilePath& entry_path,
     bool recursive,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
-  file_system_->RemoveWatcher(origin, entry_path, recursive, callback);
+    storage::AsyncFileUtil::StatusCallback callback) {
+  file_system_->RemoveWatcher(origin, entry_path, recursive,
+                              std::move(callback));
 }
 
 const ProvidedFileSystemInfo& ThrottledFileSystem::GetFileSystemInfo() const {
@@ -194,14 +198,14 @@
     storage::WatcherManager::ChangeType change_type,
     std::unique_ptr<ProvidedFileSystemObserver::Changes> changes,
     const std::string& tag,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   return file_system_->Notify(entry_path, recursive, change_type,
-                              std::move(changes), tag, callback);
+                              std::move(changes), tag, std::move(callback));
 }
 
 void ThrottledFileSystem::Configure(
-    const storage::AsyncFileUtil::StatusCallback& callback) {
-  return file_system_->Configure(callback);
+    storage::AsyncFileUtil::StatusCallback callback) {
+  return file_system_->Configure(std::move(callback));
 }
 
 base::WeakPtr<ProvidedFileSystemInterface> ThrottledFileSystem::GetWeakPtr() {
@@ -213,7 +217,7 @@
 }
 
 void ThrottledFileSystem::OnOpenFileCompleted(int queue_token,
-                                              const OpenFileCallback& callback,
+                                              OpenFileCallback callback,
                                               int file_handle,
                                               base::File::Error result) {
   // If the file is opened successfully then hold the queue token until the file
@@ -223,12 +227,12 @@
   else
     open_queue_->Complete(queue_token);
 
-  callback.Run(file_handle, result);
+  std::move(callback).Run(file_handle, result);
 }
 
 void ThrottledFileSystem::OnCloseFileCompleted(
     int file_handle,
-    const storage::AsyncFileUtil::StatusCallback& callback,
+    storage::AsyncFileUtil::StatusCallback callback,
     base::File::Error result) {
   // Closing is always final. Even if an error happened, the file is considered
   // closed on the C++ side. Release the task from the queue, so other files
@@ -240,7 +244,7 @@
   open_queue_->Complete(queue_token);
   opened_files_.erase(file_handle);
 
-  callback.Run(result);
+  std::move(callback).Run(result);
 }
 
 }  // namespace file_system_provider
diff --git a/chrome/browser/chromeos/file_system_provider/throttled_file_system.h b/chrome/browser/chromeos/file_system_provider/throttled_file_system.h
index f923212..cf647ebe 100644
--- a/chrome/browser/chromeos/file_system_provider/throttled_file_system.h
+++ b/chrome/browser/chromeos/file_system_provider/throttled_file_system.h
@@ -46,72 +46,70 @@
 
   // ProvidedFileSystemInterface overrides.
   AbortCallback RequestUnmount(
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
   AbortCallback GetMetadata(const base::FilePath& entry_path,
                             MetadataFieldMask fields,
-                            const GetMetadataCallback& callback) override;
+                            GetMetadataCallback callback) override;
   AbortCallback GetActions(const std::vector<base::FilePath>& entry_paths,
-                           const GetActionsCallback& callback) override;
+                           GetActionsCallback callback) override;
   AbortCallback ExecuteAction(
       const std::vector<base::FilePath>& entry_paths,
       const std::string& action_id,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
   AbortCallback ReadDirectory(
       const base::FilePath& directory_path,
-      const storage::AsyncFileUtil::ReadDirectoryCallback& callback) override;
+      storage::AsyncFileUtil::ReadDirectoryCallback callback) override;
   AbortCallback OpenFile(const base::FilePath& file_path,
                          OpenFileMode mode,
-                         const OpenFileCallback& callback) override;
+                         OpenFileCallback callback) override;
   AbortCallback CloseFile(
       int file_handle,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
   AbortCallback ReadFile(int file_handle,
                          net::IOBuffer* buffer,
                          int64_t offset,
                          int length,
-                         const ReadChunkReceivedCallback& callback) override;
+                         ReadChunkReceivedCallback callback) override;
   AbortCallback CreateDirectory(
       const base::FilePath& directory_path,
       bool recursive,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
   AbortCallback DeleteEntry(
       const base::FilePath& entry_path,
       bool recursive,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
   AbortCallback CreateFile(
       const base::FilePath& file_path,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
   AbortCallback CopyEntry(
       const base::FilePath& source_path,
       const base::FilePath& target_path,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
   AbortCallback MoveEntry(
       const base::FilePath& source_path,
       const base::FilePath& target_path,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
   AbortCallback Truncate(
       const base::FilePath& file_path,
       int64_t length,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
   AbortCallback WriteFile(
       int file_handle,
       net::IOBuffer* buffer,
       int64_t offset,
       int length,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
-  AbortCallback AddWatcher(
-      const GURL& origin,
-      const base::FilePath& entry_path,
-      bool recursive,
-      bool persistent,
-      const storage::AsyncFileUtil::StatusCallback& callback,
-      const storage::WatcherManager::NotificationCallback&
-          notification_callback) override;
-  void RemoveWatcher(
-      const GURL& origin,
-      const base::FilePath& entry_path,
-      bool recursive,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
+  AbortCallback AddWatcher(const GURL& origin,
+                           const base::FilePath& entry_path,
+                           bool recursive,
+                           bool persistent,
+                           storage::AsyncFileUtil::StatusCallback callback,
+                           const storage::WatcherManager::NotificationCallback&
+                               notification_callback) override;
+  void RemoveWatcher(const GURL& origin,
+                     const base::FilePath& entry_path,
+                     bool recursive,
+                     storage::AsyncFileUtil::StatusCallback callback) override;
   const ProvidedFileSystemInfo& GetFileSystemInfo() const override;
   RequestManager* GetRequestManager() override;
   Watchers* GetWatchers() override;
@@ -123,9 +121,8 @@
               storage::WatcherManager::ChangeType change_type,
               std::unique_ptr<ProvidedFileSystemObserver::Changes> changes,
               const std::string& tag,
-              const storage::AsyncFileUtil::StatusCallback& callback) override;
-  void Configure(
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+              storage::AsyncFileUtil::StatusCallback callback) override;
+  void Configure(storage::AsyncFileUtil::StatusCallback callback) override;
   base::WeakPtr<ProvidedFileSystemInterface> GetWeakPtr() override;
 
  private:
@@ -134,15 +131,14 @@
 
   // Called when opening a file is completed with either a success or an error.
   void OnOpenFileCompleted(int queue_token,
-                           const OpenFileCallback& callback,
+                           OpenFileCallback callback,
                            int file_handle,
                            base::File::Error result);
 
   // Called when closing a file is completed with either a success or an error.
-  void OnCloseFileCompleted(
-      int file_handle,
-      const storage::AsyncFileUtil::StatusCallback& callback,
-      base::File::Error result);
+  void OnCloseFileCompleted(int file_handle,
+                            storage::AsyncFileUtil::StatusCallback callback,
+                            base::File::Error result);
 
   std::unique_ptr<ProvidedFileSystemInterface> file_system_;
   std::unique_ptr<Queue> open_queue_;
diff --git a/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc b/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc
index 27ed89c3..8bae0a8 100644
--- a/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc
+++ b/chrome/browser/chromeos/input_method/input_method_engine_browsertests.cc
@@ -568,13 +568,13 @@
 
     ASSERT_EQ(2U, ime_text_spans.size());
     // single underline
-    EXPECT_EQ(SK_ColorBLACK, ime_text_spans[0].underline_color);
+    EXPECT_EQ(SK_ColorTRANSPARENT, ime_text_spans[0].underline_color);
     EXPECT_EQ(ui::ImeTextSpan::Thickness::kThin, ime_text_spans[0].thickness);
     EXPECT_EQ(0U, ime_text_spans[0].start_offset);
     EXPECT_EQ(5U, ime_text_spans[0].end_offset);
 
     // double underline
-    EXPECT_EQ(SK_ColorBLACK, ime_text_spans[1].underline_color);
+    EXPECT_EQ(SK_ColorTRANSPARENT, ime_text_spans[1].underline_color);
     EXPECT_EQ(ui::ImeTextSpan::Thickness::kThick, ime_text_spans[1].thickness);
     EXPECT_EQ(6U, ime_text_spans[1].start_offset);
     EXPECT_EQ(10U, ime_text_spans[1].end_offset);
@@ -1032,7 +1032,7 @@
 
     ASSERT_EQ(1U, ime_text_spans.size());
     // single underline
-    EXPECT_EQ(SK_ColorBLACK, ime_text_spans[0].underline_color);
+    EXPECT_EQ(SK_ColorTRANSPARENT, ime_text_spans[0].underline_color);
     EXPECT_EQ(ui::ImeTextSpan::Thickness::kThin, ime_text_spans[0].thickness);
     EXPECT_EQ(0U, ime_text_spans[0].start_offset);
     EXPECT_EQ(1U, ime_text_spans[0].end_offset);
diff --git a/chrome/browser/chromeos/login/DEPS b/chrome/browser/chromeos/login/DEPS
index 5daf5c89..5bd2d83 100644
--- a/chrome/browser/chromeos/login/DEPS
+++ b/chrome/browser/chromeos/login/DEPS
@@ -5,7 +5,6 @@
   "+components/login",
   "+components/toolbar",
   "+components/user_manager",
-  "+components/wallpaper",
   "+extensions/components/native_app_window",
   "+services/audio/public/cpp",
   "+services/device/public/mojom",
diff --git a/chrome/browser/chromeos/login/chrome_restart_request.cc b/chrome/browser/chromeos/login/chrome_restart_request.cc
index 78a4a219..1f23a720 100644
--- a/chrome/browser/chromeos/login/chrome_restart_request.cc
+++ b/chrome/browser/chromeos/login/chrome_restart_request.cc
@@ -43,7 +43,7 @@
 #include "gpu/ipc/host/gpu_switches.h"
 #include "gpu/ipc/service/switches.h"
 #include "media/base/media_switches.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "services/service_manager/sandbox/switches.h"
 #include "third_party/cros_system_api/switches/chrome_switches.h"
 #include "ui/app_list/app_list_switches.h"
diff --git a/chrome/browser/chromeos/login/lock/views_screen_locker.cc b/chrome/browser/chromeos/login/lock/views_screen_locker.cc
index 2695b17..c445f9e 100644
--- a/chrome/browser/chromeos/login/lock/views_screen_locker.cc
+++ b/chrome/browser/chromeos/login/lock/views_screen_locker.cc
@@ -245,6 +245,13 @@
   NOTREACHED();
 }
 
+void ViewsScreenLocker::HandleLaunchPublicSession(
+    const AccountId& account_id,
+    const std::string& locale,
+    const std::string& input_method) {
+  NOTREACHED();
+}
+
 void ViewsScreenLocker::SuspendDone(const base::TimeDelta& sleep_duration) {
   for (user_manager::User* user :
        user_manager::UserManager::Get()->GetUnlockUsers()) {
diff --git a/chrome/browser/chromeos/login/lock/views_screen_locker.h b/chrome/browser/chromeos/login/lock/views_screen_locker.h
index fbf9d52..dcbf2233 100644
--- a/chrome/browser/chromeos/login/lock/views_screen_locker.h
+++ b/chrome/browser/chromeos/login/lock/views_screen_locker.h
@@ -62,6 +62,9 @@
   void HandleOnNoPodFocused() override;
   bool HandleFocusLockScreenApps(bool reverse) override;
   void HandleLoginAsGuest() override;
+  void HandleLaunchPublicSession(const AccountId& account_id,
+                                 const std::string& locale,
+                                 const std::string& input_method) override;
 
   // PowerManagerClient::Observer:
   void SuspendDone(const base::TimeDelta& sleep_duration) override;
diff --git a/chrome/browser/chromeos/login/ui/gaia_dialog_delegate.cc b/chrome/browser/chromeos/login/ui/gaia_dialog_delegate.cc
index 8f3de54c..cee6427 100644
--- a/chrome/browser/chromeos/login/ui/gaia_dialog_delegate.cc
+++ b/chrome/browser/chromeos/login/ui/gaia_dialog_delegate.cc
@@ -41,7 +41,7 @@
     controller_->OnDialogDestroyed(this);
 }
 
-void GaiaDialogDelegate::Show() {
+void GaiaDialogDelegate::Init() {
   DCHECK(!dialog_view_ && !dialog_widget_);
   // Life cycle of |dialog_view_| is managed by the widget:
   // Widget owns a root view which has |dialog_view_| as its child view.
@@ -68,10 +68,18 @@
 
   extensions::ChromeExtensionWebContentsObserver::CreateForWebContents(
       dialog_view_->web_contents());
+}
 
+void GaiaDialogDelegate::Show(bool closable_by_esc) {
+  closable_by_esc_ = closable_by_esc;
   dialog_widget_->Show();
 }
 
+void GaiaDialogDelegate::Hide() {
+  if (dialog_widget_)
+    dialog_widget_->Hide();
+}
+
 void GaiaDialogDelegate::Close() {
   if (dialog_widget_)
     dialog_widget_->Close();
@@ -156,4 +164,18 @@
   return std::vector<ui::Accelerator>();
 }
 
+bool GaiaDialogDelegate::AcceleratorPressed(
+    const ui::Accelerator& accelerator) {
+  if (ui::VKEY_ESCAPE == accelerator.key_code()) {
+    // The widget should not be closed until the login is done.
+    // Consume the escape key here so WebDialogView won't have a chance to
+    // close the widget.
+    if (closable_by_esc_)
+      dialog_widget_->Hide();
+    return true;
+  }
+
+  return false;
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/ui/gaia_dialog_delegate.h b/chrome/browser/chromeos/login/ui/gaia_dialog_delegate.h
index 601200e..1b5e6bab 100644
--- a/chrome/browser/chromeos/login/ui/gaia_dialog_delegate.h
+++ b/chrome/browser/chromeos/login/ui/gaia_dialog_delegate.h
@@ -38,8 +38,20 @@
   explicit GaiaDialogDelegate(base::WeakPtr<LoginDisplayHostViews> controller);
   ~GaiaDialogDelegate() override;
 
-  void Show();
+  // Show the dialog widget.
+  // |closable_by_esc|: Whether the widget will be hidden after press escape
+  // key.
+  void Show(bool closable_by_esc);
+
+  // Close the widget, and it will delete this object.
   void Close();
+
+  // Hide the dialog widget.
+  void Hide();
+
+  // Initialize the dialog widget.
+  void Init();
+
   void SetSize(int width, int height);
   OobeUI* GetOobeUI() const;
 
@@ -60,6 +72,7 @@
   bool ShouldShowDialogTitle() const override;
   bool HandleContextMenu(const content::ContextMenuParams& params) override;
   std::vector<ui::Accelerator> GetAccelerators() override;
+  bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
 
   base::WeakPtr<LoginDisplayHostViews> controller_;
 
@@ -68,6 +81,7 @@
   views::Widget* dialog_widget_ = nullptr;
   views::WebDialogView* dialog_view_ = nullptr;
   gfx::Size size_;
+  bool closable_by_esc_ = true;
 
   DISALLOW_COPY_AND_ASSIGN(GaiaDialogDelegate);
 };
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_views.cc b/chrome/browser/chromeos/login/ui/login_display_host_views.cc
index 4c1935e..12b5265 100644
--- a/chrome/browser/chromeos/login/ui/login_display_host_views.cc
+++ b/chrome/browser/chromeos/login/ui/login_display_host_views.cc
@@ -20,10 +20,15 @@
 
 namespace chromeos {
 
-LoginDisplayHostViews::LoginDisplayHostViews() : weak_factory_(this) {}
+LoginDisplayHostViews::LoginDisplayHostViews() : weak_factory_(this) {
+  // Preload the WebUI for post-login screens.
+  InitWidgetAndView();
+}
 
 LoginDisplayHostViews::~LoginDisplayHostViews() {
   LoginScreenClient::Get()->SetDelegate(nullptr);
+  if (dialog_)
+    dialog_->Close();
 }
 
 LoginDisplay* LoginDisplayHostViews::CreateLoginDisplay(
@@ -59,11 +64,16 @@
 }
 
 void LoginDisplayHostViews::StartWizard(OobeScreen first_screen) {
-  if (!GetOobeUI())
-    return;
+  DCHECK(GetOobeUI());
 
+  // Dtor of the old WizardController should be called before ctor of the
+  // new one to ensure only one |ExistingUserController| instance at a time.
+  wizard_controller_.reset();
   wizard_controller_.reset(new WizardController(this, GetOobeUI()));
   wizard_controller_->Init(first_screen);
+
+  // Post login screens should not be closable by escape key.
+  dialog_->Show(false /*closable_by_esc*/);
 }
 
 WizardController* LoginDisplayHostViews::GetWizardController() {
@@ -129,12 +139,9 @@
 }
 
 void LoginDisplayHostViews::UpdateGaiaDialogVisibility(bool visible) {
-  if (visible == !!dialog_)
-    return;
-
+  DCHECK(dialog_);
   if (visible) {
-    dialog_ = new GaiaDialogDelegate(weak_factory_.GetWeakPtr());
-    dialog_->Show();
+    dialog_->Show(true /*closable_by_esc*/);
     return;
   }
 
@@ -145,7 +152,7 @@
     return;
   }
 
-  dialog_->Close();
+  dialog_->Hide();
 }
 
 void LoginDisplayHostViews::UpdateGaiaDialogSize(int width, int height) {
@@ -211,6 +218,16 @@
                                    chromeos::SigninSpecifics());
 }
 
+void LoginDisplayHostViews::HandleLaunchPublicSession(
+    const AccountId& account_id,
+    const std::string& locale,
+    const std::string& input_method) {
+  UserContext context(user_manager::USER_TYPE_PUBLIC_ACCOUNT, account_id);
+  context.SetPublicSessionLocale(locale);
+  context.SetPublicSessionInputMethod(input_method);
+  existing_user_controller_->Login(context, chromeos::SigninSpecifics());
+}
+
 void LoginDisplayHostViews::OnAuthFailure(const AuthFailure& error) {
   if (on_authenticated_)
     std::move(on_authenticated_).Run(false);
@@ -233,4 +250,12 @@
   users_ = users;
 }
 
+void LoginDisplayHostViews::InitWidgetAndView() {
+  if (dialog_)
+    return;
+
+  dialog_ = new GaiaDialogDelegate(weak_factory_.GetWeakPtr());
+  dialog_->Init();
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_views.h b/chrome/browser/chromeos/login/ui/login_display_host_views.h
index 89ee683..4058c9cc 100644
--- a/chrome/browser/chromeos/login/ui/login_display_host_views.h
+++ b/chrome/browser/chromeos/login/ui/login_display_host_views.h
@@ -65,6 +65,9 @@
   void HandleOnNoPodFocused() override;
   bool HandleFocusLockScreenApps(bool reverse) override;
   void HandleLoginAsGuest() override;
+  void HandleLaunchPublicSession(const AccountId& account_id,
+                                 const std::string& locale,
+                                 const std::string& input_method) override;
 
   // AuthStatusConsumer:
   void OnAuthFailure(const AuthFailure& error) override;
@@ -77,6 +80,9 @@
   void SetUsers(const user_manager::UserList& users);
 
  private:
+  // Initialize the dialog widget for webui (for gaia and post login screens).
+  void InitWidgetAndView();
+
   // Callback that should be executed the authentication result is available.
   AuthenticateUserCallback on_authenticated_;
 
diff --git a/chrome/browser/chromeos/login/users/wallpaper/OWNERS b/chrome/browser/chromeos/login/users/wallpaper/OWNERS
deleted file mode 100644
index 663b89a..0000000
--- a/chrome/browser/chromeos/login/users/wallpaper/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-bshe@chromium.org
-wzang@chromium.org
-xdai@chromium.org
-
-# COMPONENT: UI>Shell>Wallpaper
diff --git a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_policy_browsertest.cc b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_policy_browsertest.cc
deleted file mode 100644
index 16af64c..0000000
--- a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager_policy_browsertest.cc
+++ /dev/null
@@ -1,455 +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.
-
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "ash/shell.h"
-#include "ash/wallpaper/wallpaper_controller.h"
-#include "ash/wallpaper/wallpaper_controller_observer.h"
-#include "base/command_line.h"
-#include "base/compiler_specific.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/json/json_writer.h"
-#include "base/macros.h"
-#include "base/numerics/safe_conversions.h"
-#include "base/path_service.h"
-#include "base/run_loop.h"
-#include "chrome/browser/chromeos/login/login_manager_test.h"
-#include "chrome/browser/chromeos/login/startup_utils.h"
-#include "chrome/browser/chromeos/login/ui/login_display_host.h"
-#include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h"
-#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
-#include "chrome/browser/chromeos/policy/cloud_external_data_manager_base_test_util.h"
-#include "chrome/browser/chromeos/policy/device_policy_builder.h"
-#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h"
-#include "chrome/browser/chromeos/policy/user_policy_manager_factory_chromeos.h"
-#include "chrome/browser/chromeos/profiles/profile_helper.h"
-#include "chrome/browser/chromeos/settings/stub_install_attributes.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
-#include "chrome/common/chrome_paths.h"
-#include "chromeos/chromeos_paths.h"
-#include "chromeos/chromeos_switches.h"
-#include "chromeos/cryptohome/system_salt_getter.h"
-#include "chromeos/dbus/cryptohome_client.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/fake_session_manager_client.h"
-#include "chromeos/dbus/session_manager_client.h"
-#include "components/ownership/mock_owner_key_util.h"
-#include "components/policy/core/common/cloud/cloud_policy_core.h"
-#include "components/policy/core/common/cloud/cloud_policy_store.h"
-#include "components/policy/core/common/cloud/cloud_policy_validator.h"
-#include "components/policy/core/common/cloud/policy_builder.h"
-#include "components/policy/proto/cloud_policy.pb.h"
-#include "components/user_manager/user.h"
-#include "components/user_manager/user_manager.h"
-#include "components/user_manager/user_names.h"
-#include "components/wallpaper/wallpaper_info.h"
-#include "content/public/test/browser_test_utils.h"
-#include "crypto/rsa_private_key.h"
-#include "net/test/embedded_test_server/embedded_test_server.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/skia/include/core/SkColor.h"
-#include "ui/gfx/image/image_skia.h"
-#include "url/gurl.h"
-
-namespace chromeos {
-
-namespace {
-
-const char kRedImageFileName[] = "chromeos/wallpapers/red.jpg";
-const char kGreenImageFileName[] = "chromeos/wallpapers/green.jpg";
-const char kBlueImageFileName[] = "chromeos/wallpapers/blue.jpg";
-
-const SkColor kRedImageColor = SkColorSetARGB(255, 199, 6, 7);
-const SkColor kGreenImageColor = SkColorSetARGB(255, 38, 196, 15);
-
-policy::CloudPolicyStore* GetStoreForUser(const user_manager::User* user) {
-  Profile* profile = ProfileHelper::Get()->GetProfileByUserUnsafe(user);
-  if (!profile) {
-    ADD_FAILURE();
-    return NULL;
-  }
-  policy::UserCloudPolicyManagerChromeOS* policy_manager =
-      policy::UserPolicyManagerFactoryChromeOS::GetCloudPolicyManagerForProfile(
-          profile);
-  if (!policy_manager) {
-    ADD_FAILURE();
-    return NULL;
-  }
-  return policy_manager->core()->store();
-}
-
-// Compute the average ARGB color of |bitmap|.
-SkColor ComputeAverageColor(const SkBitmap& bitmap) {
-  if (bitmap.empty() || bitmap.width() < 1 || bitmap.height() < 1) {
-    ADD_FAILURE() << "Empty or invalid bitmap.";
-    return SkColorSetARGB(0, 0, 0, 0);
-  }
-  if (bitmap.isNull()) {
-    ADD_FAILURE() << "Bitmap has no pixelref.";
-    return SkColorSetARGB(0, 0, 0, 0);
-  }
-  if (bitmap.colorType() == kUnknown_SkColorType) {
-    ADD_FAILURE() << "Bitmap has not been configured.";
-    return SkColorSetARGB(0, 0, 0, 0);
-  }
-  uint64_t a = 0, r = 0, g = 0, b = 0;
-  for (int x = 0; x < bitmap.width(); ++x) {
-    for (int y = 0; y < bitmap.height(); ++y) {
-      const SkColor color = bitmap.getColor(x, y);
-      a += SkColorGetA(color);
-      r += SkColorGetR(color);
-      g += SkColorGetG(color);
-      b += SkColorGetB(color);
-    }
-  }
-  uint64_t pixel_number = bitmap.width() * bitmap.height();
-  return SkColorSetARGB((a + pixel_number / 2) / pixel_number,
-                        (r + pixel_number / 2) / pixel_number,
-                        (g + pixel_number / 2) / pixel_number,
-                        (b + pixel_number / 2) / pixel_number);
-}
-
-// Obtain wallpaper image and return its average ARGB color.
-SkColor GetAverageWallpaperColor() {
-  const gfx::ImageSkia image =
-      ash::Shell::Get()->wallpaper_controller()->GetWallpaper();
-
-  const gfx::ImageSkiaRep& representation = image.GetRepresentation(1.);
-  if (representation.is_null()) {
-    ADD_FAILURE() << "No image representation.";
-    return SkColorSetARGB(0, 0, 0, 0);
-  }
-
-  const SkBitmap& bitmap = representation.sk_bitmap();
-  return ComputeAverageColor(bitmap);
-}
-
-// Initialize system salt to calculate wallpaper file names.
-void SetSystemSalt() {
-  chromeos::SystemSaltGetter::Get()->SetRawSaltForTesting(
-      chromeos::SystemSaltGetter::RawSalt({1, 2, 3, 4, 5, 6, 7, 8}));
-}
-
-}  // namespace
-
-class WallpaperManagerPolicyTest : public LoginManagerTest,
-                                   public ash::WallpaperControllerObserver {
- protected:
-  WallpaperManagerPolicyTest()
-      : LoginManagerTest(true),
-        wallpaper_change_count_(0),
-        owner_key_util_(new ownership::MockOwnerKeyUtil()),
-        fake_session_manager_client_(new FakeSessionManagerClient) {
-    testUsers_.push_back(AccountId::FromUserEmailGaiaId(
-        LoginManagerTest::kEnterpriseUser1,
-        LoginManagerTest::kEnterpriseUser1GaiaId));
-    testUsers_.push_back(AccountId::FromUserEmailGaiaId(
-        LoginManagerTest::kEnterpriseUser2,
-        LoginManagerTest::kEnterpriseUser2GaiaId));
-  }
-
-  std::unique_ptr<policy::UserPolicyBuilder> GetUserPolicyBuilder(
-      const AccountId& account_id) {
-    std::unique_ptr<policy::UserPolicyBuilder> user_policy_builder(
-        new policy::UserPolicyBuilder());
-    base::FilePath user_keys_dir;
-    EXPECT_TRUE(PathService::Get(DIR_USER_POLICY_KEYS, &user_keys_dir));
-    const std::string sanitized_user_id =
-        CryptohomeClient::GetStubSanitizedUsername(
-            cryptohome::Identification(account_id));
-    const base::FilePath user_key_file =
-        user_keys_dir.AppendASCII(sanitized_user_id).AppendASCII("policy.pub");
-    std::string user_key_bits =
-        user_policy_builder->GetPublicSigningKeyAsString();
-    EXPECT_FALSE(user_key_bits.empty());
-    EXPECT_TRUE(base::CreateDirectory(user_key_file.DirName()));
-    EXPECT_EQ(base::WriteFile(user_key_file, user_key_bits.data(),
-                              user_key_bits.length()),
-              base::checked_cast<int>(user_key_bits.length()));
-    user_policy_builder->policy_data().set_username(account_id.GetUserEmail());
-    return user_policy_builder;
-  }
-
-  // LoginManagerTest:
-  void SetUpInProcessBrowserTestFixture() override {
-    device_policy_.Build();
-    OwnerSettingsServiceChromeOSFactory::GetInstance()
-        ->SetOwnerKeyUtilForTesting(owner_key_util_);
-    owner_key_util_->SetPublicKeyFromPrivateKey(
-        *device_policy_.GetSigningKey());
-    fake_session_manager_client_->set_device_policy(device_policy_.GetBlob());
-    DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
-        std::unique_ptr<SessionManagerClient>(fake_session_manager_client_));
-
-    // Set up fake install attributes.
-    std::unique_ptr<chromeos::StubInstallAttributes> attributes =
-        std::make_unique<chromeos::StubInstallAttributes>();
-    attributes->SetCloudManaged("fake-domain", "fake-id");
-    policy::BrowserPolicyConnectorChromeOS::SetInstallAttributesForTesting(
-        attributes.release());
-
-    LoginManagerTest::SetUpInProcessBrowserTestFixture();
-    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_));
-  }
-
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    // Set the same switches as LoginManagerTest, except that kMultiProfiles is
-    // only set when GetParam() is true and except that kLoginProfile is set
-    // when GetParam() is false.  The latter seems to be required for the sane
-    // start-up of user profiles.
-    command_line->AppendSwitch(switches::kLoginManager);
-    command_line->AppendSwitch(switches::kForceLoginManagerInTests);
-
-    // Allow policy fetches to fail - these tests instead invoke InjectPolicy()
-    // to directly inject and modify policy dynamically.
-    command_line->AppendSwitch(switches::kAllowFailedPolicyFetchForTest);
-
-    LoginManagerTest::SetUpCommandLine(command_line);
-  }
-
-  void SetUpOnMainThread() override {
-    LoginManagerTest::SetUpOnMainThread();
-    ash::Shell::Get()->wallpaper_controller()->AddObserver(this);
-
-    // Set up policy signing.
-    user_policy_builders_[0] = GetUserPolicyBuilder(testUsers_[0]);
-    user_policy_builders_[1] = GetUserPolicyBuilder(testUsers_[1]);
-  }
-
-  void TearDownOnMainThread() override {
-    ash::Shell::Get()->wallpaper_controller()->RemoveObserver(this);
-    LoginManagerTest::TearDownOnMainThread();
-  }
-
-  // ash::WallpaperControllerObserver:
-  void OnWallpaperDataChanged() override {
-    ++wallpaper_change_count_;
-    if (run_loop_)
-      run_loop_->Quit();
-  }
-
-  // Runs the loop until wallpaper has changed at least |count| times in total.
-  void RunUntilWallpaperChangeCount(int count) {
-    while (wallpaper_change_count_ < count) {
-      run_loop_.reset(new base::RunLoop);
-      run_loop_->Run();
-    }
-  }
-
-  // Runs the loop until wallpaper has changed to the specified type.
-  void RunUntilWallpaperChangeType(wallpaper::WallpaperType type) {
-    while (ash::Shell::Get()->wallpaper_controller()->GetWallpaperType() !=
-           type) {
-      run_loop_.reset(new base::RunLoop);
-      run_loop_->Run();
-    }
-  }
-
-  std::string ConstructPolicy(const std::string& relative_path) const {
-    std::string image_data;
-    if (!base::ReadFileToString(test_data_dir_.Append(relative_path),
-                                &image_data)) {
-      ADD_FAILURE();
-    }
-    std::string policy;
-    base::JSONWriter::Write(*policy::test::ConstructExternalDataReference(
-                                embedded_test_server()
-                                    ->GetURL(std::string("/") + relative_path)
-                                    .spec(),
-                                image_data),
-                            &policy);
-    return policy;
-  }
-
-  // Inject |filename| as wallpaper policy for test user |user_number|.  Set
-  // empty |filename| to clear policy.
-  void InjectPolicy(int user_number, const std::string& filename) {
-    ASSERT_TRUE(user_number == 0 || user_number == 1);
-    const AccountId& account_id = testUsers_[user_number];
-    policy::UserPolicyBuilder* builder =
-        user_policy_builders_[user_number].get();
-    if (!filename.empty()) {
-      builder->payload().mutable_wallpaperimage()->set_value(
-          ConstructPolicy(filename));
-    } else {
-      builder->payload().Clear();
-    }
-    builder->Build();
-    fake_session_manager_client_->set_user_policy(
-        cryptohome::Identification(account_id), builder->GetBlob());
-    const user_manager::User* user =
-        user_manager::UserManager::Get()->FindUser(account_id);
-    ASSERT_TRUE(user);
-    policy::CloudPolicyStore* store = GetStoreForUser(user);
-    ASSERT_TRUE(store);
-    store->Load();
-    ASSERT_EQ(policy::CloudPolicyStore::STATUS_OK, store->status());
-    ASSERT_EQ(policy::CloudPolicyValidatorBase::VALIDATION_OK,
-              store->validation_status());
-  }
-
-  // Inject |filename| as the device wallpaper policy. Set empty |filename| to
-  // clear policy.
-  void InjectDevicePolicy(const std::string& filename) {
-    if (!filename.empty()) {
-      device_policy_.payload()
-          .mutable_device_wallpaper_image()
-          ->set_device_wallpaper_image(ConstructPolicy(filename));
-    } else {
-      device_policy_.payload().Clear();
-    }
-    device_policy_.Build();
-    fake_session_manager_client_->set_device_policy(device_policy_.GetBlob());
-    fake_session_manager_client_->OnPropertyChangeComplete(true /* success */);
-  }
-
-  bool ShouldSetDeviceWallpaper() {
-    return ash::Shell::Get()
-        ->wallpaper_controller()
-        ->ShouldSetDevicePolicyWallpaper();
-  }
-
-  // A wrapper of |WallpaperController::GetUserWallpaperInfo|.
-  void GetUserWallpaperInfo(int user_number,
-                            wallpaper::WallpaperInfo* wallpaper_info) {
-    ash::Shell::Get()->wallpaper_controller()->GetUserWallpaperInfo(
-        testUsers_[user_number], wallpaper_info,
-        user_manager::UserManager::Get()->IsUserNonCryptohomeDataEphemeral(
-            testUsers_[user_number]) /*is_ephemeral=*/);
-  }
-
-  base::FilePath test_data_dir_;
-  std::unique_ptr<base::RunLoop> run_loop_;
-  int wallpaper_change_count_;
-  std::unique_ptr<policy::UserPolicyBuilder> user_policy_builders_[2];
-  policy::DevicePolicyBuilder device_policy_;
-  scoped_refptr<ownership::MockOwnerKeyUtil> owner_key_util_;
-  FakeSessionManagerClient* fake_session_manager_client_;
-  std::vector<AccountId> testUsers_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(WallpaperManagerPolicyTest);
-};
-
-IN_PROC_BROWSER_TEST_F(WallpaperManagerPolicyTest, PRE_SetResetClear) {
-  RegisterUser(testUsers_[0]);
-  RegisterUser(testUsers_[1]);
-  StartupUtils::MarkOobeCompleted();
-}
-
-// Verifies that the wallpaper can be set and re-set through policy and that
-// setting policy for a user that is not logged in doesn't affect the current
-// user.  Also verifies that after the policy has been cleared, the wallpaper
-// reverts to default.
-IN_PROC_BROWSER_TEST_F(WallpaperManagerPolicyTest, SetResetClear) {
-  SetSystemSalt();
-  wallpaper::WallpaperInfo info;
-  LoginUser(testUsers_[0]);
-
-  // First user: Stores the average color of the default wallpaper (set
-  // automatically) to be compared against later.
-  const SkColor original_wallpaper_color = GetAverageWallpaperColor();
-
-  // Second user: Set wallpaper policy to blue image.  This should not result in
-  // a wallpaper change, which is checked at the very end of this test.
-  InjectPolicy(1, kBlueImageFileName);
-
-  // First user: Set wallpaper policy to red image and verify average color.
-  InjectPolicy(0, kRedImageFileName);
-  RunUntilWallpaperChangeCount(1);
-  GetUserWallpaperInfo(0, &info);
-  ASSERT_EQ(wallpaper::POLICY, info.type);
-  ASSERT_EQ(kRedImageColor, GetAverageWallpaperColor());
-
-  // First user: Set wallpaper policy to green image and verify average color.
-  InjectPolicy(0, kGreenImageFileName);
-  RunUntilWallpaperChangeCount(2);
-  GetUserWallpaperInfo(0, &info);
-  ASSERT_EQ(wallpaper::POLICY, info.type);
-  ASSERT_EQ(kGreenImageColor, GetAverageWallpaperColor());
-
-  // First user: Clear wallpaper policy and verify that the default wallpaper is
-  // set again.
-  InjectPolicy(0, "");
-  RunUntilWallpaperChangeCount(3);
-  GetUserWallpaperInfo(0, &info);
-  ASSERT_EQ(wallpaper::DEFAULT, info.type);
-  ASSERT_EQ(original_wallpaper_color, GetAverageWallpaperColor());
-
-  // Check wallpaper change count to ensure that setting the second user's
-  // wallpaper didn't have any effect.
-  ASSERT_EQ(3, wallpaper_change_count_);
-}
-
-IN_PROC_BROWSER_TEST_F(WallpaperManagerPolicyTest, PRE_PRE_PersistOverLogout) {
-  SetSystemSalt();
-  RegisterUser(testUsers_[0]);
-  StartupUtils::MarkOobeCompleted();
-}
-
-IN_PROC_BROWSER_TEST_F(WallpaperManagerPolicyTest, PRE_PersistOverLogout) {
-  SetSystemSalt();
-  LoginUser(testUsers_[0]);
-
-  // Set wallpaper policy to red image.
-  InjectPolicy(0, kRedImageFileName);
-
-  // Run until wallpaper has changed.
-  RunUntilWallpaperChangeCount(1);
-  ASSERT_EQ(kRedImageColor, GetAverageWallpaperColor());
-  StartupUtils::MarkOobeCompleted();
-}
-
-IN_PROC_BROWSER_TEST_F(WallpaperManagerPolicyTest, PersistOverLogout) {
-  LoginUser(testUsers_[0]);
-
-  ASSERT_EQ(kRedImageColor, GetAverageWallpaperColor());
-}
-
-IN_PROC_BROWSER_TEST_F(WallpaperManagerPolicyTest, PRE_DevicePolicyTest) {
-  SetSystemSalt();
-  RegisterUser(testUsers_[0]);
-  StartupUtils::MarkOobeCompleted();
-}
-
-// Test that if device policy wallpaper and user policy wallpaper are both
-// specified, the device policy wallpaper is used in the login screen and the
-// user policy wallpaper is used inside of a user session.
-IN_PROC_BROWSER_TEST_F(WallpaperManagerPolicyTest, DevicePolicyTest) {
-  SetSystemSalt();
-
-  // Set the device wallpaper policy. Test that the device policy controlled
-  // wallpaper shows up in the login screen.
-  InjectDevicePolicy(kRedImageFileName);
-  RunUntilWallpaperChangeType(wallpaper::DEVICE);
-  EXPECT_TRUE(ShouldSetDeviceWallpaper());
-  EXPECT_EQ(kRedImageColor, GetAverageWallpaperColor());
-
-  // Log in a test user. The default wallpaper should be shown to replace the
-  // device policy wallpaper.
-  LoginUser(testUsers_[0]);
-  RunUntilWallpaperChangeType(wallpaper::DEFAULT);
-
-  // Now set the user wallpaper policy. The user policy controlled wallpaper
-  // should show up in the user session.
-  InjectPolicy(0, kGreenImageFileName);
-  RunUntilWallpaperChangeType(wallpaper::POLICY);
-  EXPECT_EQ(kGreenImageColor, GetAverageWallpaperColor());
-
-  // Set the device wallpaper policy inside the user session. That that the
-  // user wallpaper doesn't change.
-  InjectDevicePolicy(kBlueImageFileName);
-  EXPECT_FALSE(ShouldSetDeviceWallpaper());
-  EXPECT_EQ(kGreenImageColor, GetAverageWallpaperColor());
-}
-
-}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/users/wallpaper_policy_browsertest.cc b/chrome/browser/chromeos/login/users/wallpaper_policy_browsertest.cc
new file mode 100644
index 0000000..d23de169
--- /dev/null
+++ b/chrome/browser/chromeos/login/users/wallpaper_policy_browsertest.cc
@@ -0,0 +1,434 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "ash/public/interfaces/wallpaper.mojom.h"
+#include "base/command_line.h"
+#include "base/compiler_specific.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/json/json_writer.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/path_service.h"
+#include "base/run_loop.h"
+#include "chrome/browser/chromeos/login/login_manager_test.h"
+#include "chrome/browser/chromeos/login/startup_utils.h"
+#include "chrome/browser/chromeos/login/ui/login_display_host.h"
+#include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h"
+#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
+#include "chrome/browser/chromeos/policy/cloud_external_data_manager_base_test_util.h"
+#include "chrome/browser/chromeos/policy/device_policy_builder.h"
+#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h"
+#include "chrome/browser/chromeos/policy/user_policy_manager_factory_chromeos.h"
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/chromeos/settings/stub_install_attributes.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/ash/wallpaper_controller_client.h"
+#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
+#include "chrome/common/chrome_paths.h"
+#include "chromeos/chromeos_paths.h"
+#include "chromeos/chromeos_switches.h"
+#include "chromeos/cryptohome/system_salt_getter.h"
+#include "chromeos/dbus/cryptohome_client.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/fake_session_manager_client.h"
+#include "chromeos/dbus/session_manager_client.h"
+#include "components/ownership/mock_owner_key_util.h"
+#include "components/policy/core/common/cloud/cloud_policy_core.h"
+#include "components/policy/core/common/cloud/cloud_policy_store.h"
+#include "components/policy/core/common/cloud/cloud_policy_validator.h"
+#include "components/policy/core/common/cloud/policy_builder.h"
+#include "components/policy/proto/cloud_policy.pb.h"
+#include "components/user_manager/user.h"
+#include "components/user_manager/user_manager.h"
+#include "components/user_manager/user_names.h"
+#include "content/public/test/browser_test_utils.h"
+#include "crypto/rsa_private_key.h"
+#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/image/image_skia.h"
+#include "url/gurl.h"
+
+namespace chromeos {
+
+namespace {
+
+const char kRedImageFileName[] = "chromeos/wallpapers/red.jpg";
+const char kGreenImageFileName[] = "chromeos/wallpapers/green.jpg";
+const char kBlueImageFileName[] = "chromeos/wallpapers/blue.jpg";
+
+const SkColor kRedImageColor = SkColorSetARGB(255, 199, 6, 7);
+const SkColor kGreenImageColor = SkColorSetARGB(255, 38, 196, 15);
+
+policy::CloudPolicyStore* GetStoreForUser(const user_manager::User* user) {
+  Profile* profile = ProfileHelper::Get()->GetProfileByUserUnsafe(user);
+  if (!profile) {
+    ADD_FAILURE();
+    return NULL;
+  }
+  policy::UserCloudPolicyManagerChromeOS* policy_manager =
+      policy::UserPolicyManagerFactoryChromeOS::GetCloudPolicyManagerForProfile(
+          profile);
+  if (!policy_manager) {
+    ADD_FAILURE();
+    return NULL;
+  }
+  return policy_manager->core()->store();
+}
+
+// Compute the average ARGB color of |bitmap|.
+SkColor ComputeAverageColor(const SkBitmap& bitmap) {
+  if (bitmap.empty() || bitmap.width() < 1 || bitmap.height() < 1) {
+    ADD_FAILURE() << "Empty or invalid bitmap.";
+    return SkColorSetARGB(0, 0, 0, 0);
+  }
+  if (bitmap.isNull()) {
+    ADD_FAILURE() << "Bitmap has no pixelref.";
+    return SkColorSetARGB(0, 0, 0, 0);
+  }
+  if (bitmap.colorType() == kUnknown_SkColorType) {
+    ADD_FAILURE() << "Bitmap has not been configured.";
+    return SkColorSetARGB(0, 0, 0, 0);
+  }
+  uint64_t a = 0, r = 0, g = 0, b = 0;
+  for (int x = 0; x < bitmap.width(); ++x) {
+    for (int y = 0; y < bitmap.height(); ++y) {
+      const SkColor color = bitmap.getColor(x, y);
+      a += SkColorGetA(color);
+      r += SkColorGetR(color);
+      g += SkColorGetG(color);
+      b += SkColorGetB(color);
+    }
+  }
+  uint64_t pixel_number = bitmap.width() * bitmap.height();
+  return SkColorSetARGB((a + pixel_number / 2) / pixel_number,
+                        (r + pixel_number / 2) / pixel_number,
+                        (g + pixel_number / 2) / pixel_number,
+                        (b + pixel_number / 2) / pixel_number);
+}
+
+// Initialize system salt to calculate wallpaper file names.
+void SetSystemSalt() {
+  chromeos::SystemSaltGetter::Get()->SetRawSaltForTesting(
+      chromeos::SystemSaltGetter::RawSalt({1, 2, 3, 4, 5, 6, 7, 8}));
+}
+
+}  // namespace
+
+class WallpaperPolicyTest : public LoginManagerTest,
+                            public ash::mojom::WallpaperObserver {
+ protected:
+  WallpaperPolicyTest()
+      : LoginManagerTest(true),
+        wallpaper_change_count_(0),
+        owner_key_util_(new ownership::MockOwnerKeyUtil()),
+        fake_session_manager_client_(new FakeSessionManagerClient),
+        observer_binding_(this),
+        weak_ptr_factory_(this) {
+    testUsers_.push_back(AccountId::FromUserEmailGaiaId(
+        LoginManagerTest::kEnterpriseUser1,
+        LoginManagerTest::kEnterpriseUser1GaiaId));
+    testUsers_.push_back(AccountId::FromUserEmailGaiaId(
+        LoginManagerTest::kEnterpriseUser2,
+        LoginManagerTest::kEnterpriseUser2GaiaId));
+  }
+
+  std::unique_ptr<policy::UserPolicyBuilder> GetUserPolicyBuilder(
+      const AccountId& account_id) {
+    std::unique_ptr<policy::UserPolicyBuilder> user_policy_builder(
+        new policy::UserPolicyBuilder());
+    base::FilePath user_keys_dir;
+    EXPECT_TRUE(PathService::Get(DIR_USER_POLICY_KEYS, &user_keys_dir));
+    const std::string sanitized_user_id =
+        CryptohomeClient::GetStubSanitizedUsername(
+            cryptohome::Identification(account_id));
+    const base::FilePath user_key_file =
+        user_keys_dir.AppendASCII(sanitized_user_id).AppendASCII("policy.pub");
+    std::string user_key_bits =
+        user_policy_builder->GetPublicSigningKeyAsString();
+    EXPECT_FALSE(user_key_bits.empty());
+    EXPECT_TRUE(base::CreateDirectory(user_key_file.DirName()));
+    EXPECT_EQ(base::WriteFile(user_key_file, user_key_bits.data(),
+                              user_key_bits.length()),
+              base::checked_cast<int>(user_key_bits.length()));
+    user_policy_builder->policy_data().set_username(account_id.GetUserEmail());
+    return user_policy_builder;
+  }
+
+  // LoginManagerTest:
+  void SetUpInProcessBrowserTestFixture() override {
+    device_policy_.Build();
+    OwnerSettingsServiceChromeOSFactory::GetInstance()
+        ->SetOwnerKeyUtilForTesting(owner_key_util_);
+    owner_key_util_->SetPublicKeyFromPrivateKey(
+        *device_policy_.GetSigningKey());
+    fake_session_manager_client_->set_device_policy(device_policy_.GetBlob());
+    DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient(
+        std::unique_ptr<SessionManagerClient>(fake_session_manager_client_));
+
+    // Set up fake install attributes.
+    std::unique_ptr<chromeos::StubInstallAttributes> attributes =
+        std::make_unique<chromeos::StubInstallAttributes>();
+    attributes->SetCloudManaged("fake-domain", "fake-id");
+    policy::BrowserPolicyConnectorChromeOS::SetInstallAttributesForTesting(
+        attributes.release());
+
+    LoginManagerTest::SetUpInProcessBrowserTestFixture();
+    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_));
+  }
+
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    // Set the same switches as LoginManagerTest, except that kMultiProfiles is
+    // only set when GetParam() is true and except that kLoginProfile is set
+    // when GetParam() is false.  The latter seems to be required for the sane
+    // start-up of user profiles.
+    command_line->AppendSwitch(switches::kLoginManager);
+    command_line->AppendSwitch(switches::kForceLoginManagerInTests);
+
+    // Allow policy fetches to fail - these tests instead invoke InjectPolicy()
+    // to directly inject and modify policy dynamically.
+    command_line->AppendSwitch(switches::kAllowFailedPolicyFetchForTest);
+
+    LoginManagerTest::SetUpCommandLine(command_line);
+  }
+
+  void SetUpOnMainThread() override {
+    LoginManagerTest::SetUpOnMainThread();
+    ash::mojom::WallpaperObserverAssociatedPtrInfo ptr_info;
+    observer_binding_.Bind(mojo::MakeRequest(&ptr_info));
+    WallpaperControllerClient::Get()->AddObserver(std::move(ptr_info));
+
+    // Set up policy signing.
+    user_policy_builders_[0] = GetUserPolicyBuilder(testUsers_[0]);
+    user_policy_builders_[1] = GetUserPolicyBuilder(testUsers_[1]);
+  }
+
+  void TearDownOnMainThread() override {
+    LoginManagerTest::TearDownOnMainThread();
+  }
+
+  // Obtain wallpaper image and return its average ARGB color.
+  SkColor GetAverageWallpaperColor() {
+    average_color_.reset();
+    WallpaperControllerClient::Get()->GetWallpaperImage(
+        base::BindOnce(&WallpaperPolicyTest::OnGetWallpaperImageCallback,
+                       weak_ptr_factory_.GetWeakPtr()));
+    while (!average_color_.has_value()) {
+      run_loop_.reset(new base::RunLoop);
+      run_loop_->Run();
+    }
+    return average_color_.value();
+  }
+
+  void OnGetWallpaperImageCallback(const gfx::ImageSkia& image) {
+    const gfx::ImageSkiaRep& representation = image.GetRepresentation(1.0f);
+    if (representation.is_null()) {
+      ADD_FAILURE() << "No image representation.";
+      average_color_ = SkColorSetARGB(0, 0, 0, 0);
+    }
+    average_color_ = ComputeAverageColor(representation.sk_bitmap());
+    if (run_loop_)
+      run_loop_->Quit();
+  }
+
+  // ash::mojom::WallpaperObserver:
+  void OnWallpaperChanged(uint32_t image_id) override {
+    ++wallpaper_change_count_;
+    if (run_loop_)
+      run_loop_->Quit();
+  }
+
+  void OnWallpaperColorsChanged(
+      const std::vector<SkColor>& prominent_colors) override {}
+
+  // Runs the loop until wallpaper has changed to the expected color.
+  void RunUntilWallpaperChangeToColor(const SkColor& expected_color) {
+    while (expected_color != GetAverageWallpaperColor()) {
+      run_loop_.reset(new base::RunLoop);
+      run_loop_->Run();
+    }
+  }
+
+  std::string ConstructPolicy(const std::string& relative_path) const {
+    std::string image_data;
+    if (!base::ReadFileToString(test_data_dir_.Append(relative_path),
+                                &image_data)) {
+      ADD_FAILURE();
+    }
+    std::string policy;
+    base::JSONWriter::Write(*policy::test::ConstructExternalDataReference(
+                                embedded_test_server()
+                                    ->GetURL(std::string("/") + relative_path)
+                                    .spec(),
+                                image_data),
+                            &policy);
+    return policy;
+  }
+
+  // Inject |filename| as wallpaper policy for test user |user_number|.  Set
+  // empty |filename| to clear policy.
+  void InjectPolicy(int user_number, const std::string& filename) {
+    ASSERT_TRUE(user_number == 0 || user_number == 1);
+    const AccountId& account_id = testUsers_[user_number];
+    policy::UserPolicyBuilder* builder =
+        user_policy_builders_[user_number].get();
+    if (!filename.empty()) {
+      builder->payload().mutable_wallpaperimage()->set_value(
+          ConstructPolicy(filename));
+    } else {
+      builder->payload().Clear();
+    }
+    builder->Build();
+    fake_session_manager_client_->set_user_policy(
+        cryptohome::Identification(account_id), builder->GetBlob());
+    const user_manager::User* user =
+        user_manager::UserManager::Get()->FindUser(account_id);
+    ASSERT_TRUE(user);
+    policy::CloudPolicyStore* store = GetStoreForUser(user);
+    ASSERT_TRUE(store);
+    store->Load();
+    ASSERT_EQ(policy::CloudPolicyStore::STATUS_OK, store->status());
+    ASSERT_EQ(policy::CloudPolicyValidatorBase::VALIDATION_OK,
+              store->validation_status());
+  }
+
+  // Inject |filename| as the device wallpaper policy. Set empty |filename| to
+  // clear policy.
+  void InjectDevicePolicy(const std::string& filename) {
+    if (!filename.empty()) {
+      device_policy_.payload()
+          .mutable_device_wallpaper_image()
+          ->set_device_wallpaper_image(ConstructPolicy(filename));
+    } else {
+      device_policy_.payload().Clear();
+    }
+    device_policy_.Build();
+    fake_session_manager_client_->set_device_policy(device_policy_.GetBlob());
+    fake_session_manager_client_->OnPropertyChangeComplete(true /* success */);
+  }
+
+  base::FilePath test_data_dir_;
+  std::unique_ptr<base::RunLoop> run_loop_;
+  int wallpaper_change_count_;
+  std::unique_ptr<policy::UserPolicyBuilder> user_policy_builders_[2];
+  policy::DevicePolicyBuilder device_policy_;
+  scoped_refptr<ownership::MockOwnerKeyUtil> owner_key_util_;
+  FakeSessionManagerClient* fake_session_manager_client_;
+  std::vector<AccountId> testUsers_;
+
+ private:
+  // The binding this instance uses to implement ash::mojom::WallpaperObserver.
+  mojo::AssociatedBinding<ash::mojom::WallpaperObserver> observer_binding_;
+
+  // The average ARGB color of the current wallpaper.
+  base::Optional<SkColor> average_color_;
+
+  base::WeakPtrFactory<WallpaperPolicyTest> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(WallpaperPolicyTest);
+};
+
+IN_PROC_BROWSER_TEST_F(WallpaperPolicyTest, PRE_SetResetClear) {
+  RegisterUser(testUsers_[0]);
+  RegisterUser(testUsers_[1]);
+  StartupUtils::MarkOobeCompleted();
+}
+
+// Verifies that the wallpaper can be set and re-set through policy and that
+// setting policy for a user that is not logged in doesn't affect the current
+// user.  Also verifies that after the policy has been cleared, the wallpaper
+// reverts to default.
+IN_PROC_BROWSER_TEST_F(WallpaperPolicyTest, SetResetClear) {
+  SetSystemSalt();
+  LoginUser(testUsers_[0]);
+
+  // First user: Stores the average color of the default wallpaper (set
+  // automatically) to be compared against later.
+  const SkColor original_wallpaper_color = GetAverageWallpaperColor();
+
+  // Second user: Set wallpaper policy to blue image.  This should not result in
+  // a wallpaper change, which is checked at the very end of this test.
+  InjectPolicy(1, kBlueImageFileName);
+
+  // First user: Set wallpaper policy to red image and verify average color.
+  InjectPolicy(0, kRedImageFileName);
+  RunUntilWallpaperChangeToColor(kRedImageColor);
+
+  // First user: Set wallpaper policy to green image and verify average color.
+  InjectPolicy(0, kGreenImageFileName);
+  RunUntilWallpaperChangeToColor(kGreenImageColor);
+
+  // First user: Clear wallpaper policy and verify that the default wallpaper is
+  // set again.
+  InjectPolicy(0, "");
+  RunUntilWallpaperChangeToColor(original_wallpaper_color);
+
+  // Check wallpaper change count to ensure that setting the second user's
+  // wallpaper didn't have any effect.
+  ASSERT_EQ(3, wallpaper_change_count_);
+}
+
+IN_PROC_BROWSER_TEST_F(WallpaperPolicyTest, PRE_PRE_PersistOverLogout) {
+  SetSystemSalt();
+  RegisterUser(testUsers_[0]);
+  StartupUtils::MarkOobeCompleted();
+}
+
+IN_PROC_BROWSER_TEST_F(WallpaperPolicyTest, PRE_PersistOverLogout) {
+  SetSystemSalt();
+  LoginUser(testUsers_[0]);
+
+  // Set wallpaper policy to red image.
+  InjectPolicy(0, kRedImageFileName);
+
+  // Run until wallpaper has changed to expected color.
+  RunUntilWallpaperChangeToColor(kRedImageColor);
+  StartupUtils::MarkOobeCompleted();
+}
+
+IN_PROC_BROWSER_TEST_F(WallpaperPolicyTest, PersistOverLogout) {
+  LoginUser(testUsers_[0]);
+  RunUntilWallpaperChangeToColor(kRedImageColor);
+}
+
+IN_PROC_BROWSER_TEST_F(WallpaperPolicyTest, PRE_DevicePolicyTest) {
+  SetSystemSalt();
+  RegisterUser(testUsers_[0]);
+  StartupUtils::MarkOobeCompleted();
+}
+
+// Test that if device policy wallpaper and user policy wallpaper are both
+// specified, the device policy wallpaper is used in the login screen and the
+// user policy wallpaper is used inside of a user session.
+IN_PROC_BROWSER_TEST_F(WallpaperPolicyTest, DevicePolicyTest) {
+  SetSystemSalt();
+  const SkColor original_wallpaper_color = GetAverageWallpaperColor();
+
+  // Set the device wallpaper policy. Test that the device policy controlled
+  // wallpaper shows up in the login screen.
+  InjectDevicePolicy(kRedImageFileName);
+  RunUntilWallpaperChangeToColor(kRedImageColor);
+
+  // Log in a test user. The default wallpaper should be shown to replace the
+  // device policy wallpaper.
+  LoginUser(testUsers_[0]);
+  RunUntilWallpaperChangeToColor(original_wallpaper_color);
+
+  // Now set the user wallpaper policy. The user policy controlled wallpaper
+  // should show up in the user session.
+  InjectPolicy(0, kGreenImageFileName);
+  RunUntilWallpaperChangeToColor(kGreenImageColor);
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/policy/status_uploader_unittest.cc b/chrome/browser/chromeos/policy/status_uploader_unittest.cc
index c50ce03..c548912 100644
--- a/chrome/browser/chromeos/policy/status_uploader_unittest.cc
+++ b/chrome/browser/chromeos/policy/status_uploader_unittest.cc
@@ -30,7 +30,7 @@
 #include "ui/events/event.h"
 #include "ui/events/event_utils.h"
 #include "ui/events/platform/platform_event_source.h"
-#include "ui/events/platform/platform_event_types.h"
+#include "ui/events/platform_event.h"
 
 using ::testing::_;
 using ::testing::Invoke;
diff --git a/chrome/browser/chromeos/power/ml/user_activity_manager_unittest.cc b/chrome/browser/chromeos/power/ml/user_activity_manager_unittest.cc
index 2b3c68c6f3..55fef8b0 100644
--- a/chrome/browser/chromeos/power/ml/user_activity_manager_unittest.cc
+++ b/chrome/browser/chromeos/power/ml/user_activity_manager_unittest.cc
@@ -28,6 +28,7 @@
 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
 #include "chromeos/dbus/power_manager_client.h"
 #include "components/session_manager/session_manager_types.h"
+#include "components/ukm/content/source_url_recorder.h"
 #include "components/ukm/test_ukm_recorder.h"
 #include "components/ukm/ukm_source.h"
 #include "content/public/browser/web_contents.h"
@@ -181,10 +182,10 @@
   // If |mime_type| is an empty string, the content has a default text type.
   // TODO(jiameng): there doesn't seem to be a way to set form entry (via
   // page importance signal). Check if there's some other way to set it.
-  void CreateTestWebContents(TabStripModel* const tab_strip_model,
-                             const GURL& url,
-                             bool is_active,
-                             const std::string& mime_type = "") {
+  ukm::SourceId CreateTestWebContents(TabStripModel* const tab_strip_model,
+                                      const GURL& url,
+                                      bool is_active,
+                                      const std::string& mime_type = "") {
     DCHECK(tab_strip_model);
     DCHECK(!url.is_empty());
     content::WebContents* contents =
@@ -196,12 +197,7 @@
       WebContentsTester::For(contents)->SetMainFrameMimeType(mime_type);
 
     WebContentsTester::For(contents)->TestSetIsLoading(false);
-  }
-
-  ukm::SourceId GetSourceIdForUrl(const GURL& url) {
-    const ukm::UkmSource* source = ukm_recorder_.GetSourceForUrl(url);
-    DCHECK(source);
-    return source->id();
+    return ukm::GetSourceIdForWebContentsDocument(contents);
   }
 
   void CheckTabsProperties(
@@ -656,13 +652,12 @@
       CreateTestBrowser(true /* is_visible */, true /* is_focused */);
   BrowserList::GetInstance()->SetLastActive(browser.get());
   TabStripModel* tab_strip_model = browser->tab_strip_model();
-  CreateTestWebContents(tab_strip_model, url1_, true /* is_active */,
-                        "application/pdf");
+  const ukm::SourceId source_id1 = CreateTestWebContents(
+      tab_strip_model, url1_, true /* is_active */, "application/pdf");
   SiteEngagementService::Get(profile())->ResetBaseScoreForURL(url1_, 95);
-  const ukm::SourceId source_id1 = GetSourceIdForUrl(url1_);
 
-  CreateTestWebContents(tab_strip_model, url2_, false /* is_active */);
-  const ukm::SourceId source_id2 = GetSourceIdForUrl(url2_);
+  const ukm::SourceId source_id2 =
+      CreateTestWebContents(tab_strip_model, url2_, false /* is_active */);
 
   UpdateOpenTabsURLs();
 
@@ -709,18 +704,18 @@
   BrowserList::GetInstance()->SetLastActive(browser1.get());
 
   TabStripModel* tab_strip_model1 = browser1->tab_strip_model();
-  CreateTestWebContents(tab_strip_model1, url1_, false /* is_active */);
-  CreateTestWebContents(tab_strip_model1, url2_, true /* is_active */);
-  const ukm::SourceId source_id1 = GetSourceIdForUrl(url1_);
-  const ukm::SourceId source_id2 = GetSourceIdForUrl(url2_);
+  const ukm::SourceId source_id1 =
+      CreateTestWebContents(tab_strip_model1, url1_, false /* is_active */);
+  const ukm::SourceId source_id2 =
+      CreateTestWebContents(tab_strip_model1, url2_, true /* is_active */);
 
   TabStripModel* tab_strip_model2 = browser2->tab_strip_model();
-  CreateTestWebContents(tab_strip_model2, url3_, true /* is_active */);
-  const ukm::SourceId source_id3 = GetSourceIdForUrl(url3_);
+  const ukm::SourceId source_id3 =
+      CreateTestWebContents(tab_strip_model2, url3_, true /* is_active */);
 
   TabStripModel* tab_strip_model3 = browser3->tab_strip_model();
-  CreateTestWebContents(tab_strip_model3, url4_, true /* is_active */);
-  const ukm::SourceId source_id4 = GetSourceIdForUrl(url4_);
+  const ukm::SourceId source_id4 =
+      CreateTestWebContents(tab_strip_model3, url4_, true /* is_active */);
 
   UpdateOpenTabsURLs();
 
diff --git a/chrome/browser/chromeos/printing/cups_print_job.cc b/chrome/browser/chromeos/printing/cups_print_job.cc
index 32b5fbe..f9310a0 100644
--- a/chrome/browser/chromeos/printing/cups_print_job.cc
+++ b/chrome/browser/chromeos/printing/cups_print_job.cc
@@ -15,7 +15,8 @@
     : printer_(printer),
       job_id_(job_id),
       document_title_(document_title),
-      total_page_number_(total_page_number) {}
+      total_page_number_(total_page_number),
+      weak_factory_(this) {}
 
 CupsPrintJob::~CupsPrintJob() {}
 
@@ -23,6 +24,10 @@
   return GetUniqueId(printer_.id(), job_id_);
 }
 
+base::WeakPtr<CupsPrintJob> CupsPrintJob::GetWeakPtr() {
+  return weak_factory_.GetWeakPtr();
+}
+
 // static
 std::string CupsPrintJob::GetUniqueId(const std::string& printer_id,
                                       int job_id) {
diff --git a/chrome/browser/chromeos/printing/cups_print_job.h b/chrome/browser/chromeos/printing/cups_print_job.h
index df2f1d9..33544f0e 100644
--- a/chrome/browser/chromeos/printing/cups_print_job.h
+++ b/chrome/browser/chromeos/printing/cups_print_job.h
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "base/macros.h"
+#include "base/memory/weak_ptr.h"
 #include "chromeos/printing/printer_configuration.h"
 
 namespace chromeos {
@@ -47,6 +48,9 @@
   // Returns a unique id for the print job.
   std::string GetUniqueId() const;
 
+  // Returns weak pointer to |this| CupsPrintJob
+  base::WeakPtr<CupsPrintJob> GetWeakPtr();
+
   // Getters.
   const Printer& printer() const { return printer_; }
   int job_id() const { return job_id_; }
@@ -80,6 +84,8 @@
   State state_ = State::STATE_NONE;
   ErrorCode error_code_ = ErrorCode::NO_ERROR;
 
+  base::WeakPtrFactory<CupsPrintJob> weak_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(CupsPrintJob);
 };
 
diff --git a/chrome/browser/chromeos/printing/cups_print_job_manager.cc b/chrome/browser/chromeos/printing/cups_print_job_manager.cc
index 8404774..65d1444 100644
--- a/chrome/browser/chromeos/printing/cups_print_job_manager.cc
+++ b/chrome/browser/chromeos/printing/cups_print_job_manager.cc
@@ -30,42 +30,42 @@
   observers_.RemoveObserver(observer);
 }
 
-void CupsPrintJobManager::NotifyJobCreated(CupsPrintJob* job) {
+void CupsPrintJobManager::NotifyJobCreated(base::WeakPtr<CupsPrintJob> job) {
   for (Observer& observer : observers_)
     observer.OnPrintJobCreated(job);
 }
 
-void CupsPrintJobManager::NotifyJobStarted(CupsPrintJob* job) {
+void CupsPrintJobManager::NotifyJobStarted(base::WeakPtr<CupsPrintJob> job) {
   for (Observer& observer : observers_)
     observer.OnPrintJobStarted(job);
 }
 
-void CupsPrintJobManager::NotifyJobUpdated(CupsPrintJob* job) {
+void CupsPrintJobManager::NotifyJobUpdated(base::WeakPtr<CupsPrintJob> job) {
   for (Observer& observer : observers_)
     observer.OnPrintJobUpdated(job);
 }
 
-void CupsPrintJobManager::NotifyJobResumed(CupsPrintJob* job) {
+void CupsPrintJobManager::NotifyJobResumed(base::WeakPtr<CupsPrintJob> job) {
   for (Observer& observer : observers_)
     observer.OnPrintJobResumed(job);
 }
 
-void CupsPrintJobManager::NotifyJobSuspended(CupsPrintJob* job) {
+void CupsPrintJobManager::NotifyJobSuspended(base::WeakPtr<CupsPrintJob> job) {
   for (Observer& observer : observers_)
     observer.OnPrintJobSuspended(job);
 }
 
-void CupsPrintJobManager::NotifyJobCanceled(CupsPrintJob* job) {
+void CupsPrintJobManager::NotifyJobCanceled(base::WeakPtr<CupsPrintJob> job) {
   for (Observer& observer : observers_)
     observer.OnPrintJobCancelled(job);
 }
 
-void CupsPrintJobManager::NotifyJobError(CupsPrintJob* job) {
+void CupsPrintJobManager::NotifyJobError(base::WeakPtr<CupsPrintJob> job) {
   for (Observer& observer : observers_)
     observer.OnPrintJobError(job);
 }
 
-void CupsPrintJobManager::NotifyJobDone(CupsPrintJob* job) {
+void CupsPrintJobManager::NotifyJobDone(base::WeakPtr<CupsPrintJob> job) {
   for (Observer& observer : observers_)
     observer.OnPrintJobDone(job);
 }
diff --git a/chrome/browser/chromeos/printing/cups_print_job_manager.h b/chrome/browser/chromeos/printing/cups_print_job_manager.h
index 06885f1..3cb1659e 100644
--- a/chrome/browser/chromeos/printing/cups_print_job_manager.h
+++ b/chrome/browser/chromeos/printing/cups_print_job_manager.h
@@ -22,23 +22,23 @@
  public:
   class Observer {
    public:
-    virtual void OnPrintJobCreated(CupsPrintJob* job) {}
-    virtual void OnPrintJobStarted(CupsPrintJob* job) {}
-    virtual void OnPrintJobUpdated(CupsPrintJob* job) {}
-    virtual void OnPrintJobSuspended(CupsPrintJob* job) {}
-    virtual void OnPrintJobResumed(CupsPrintJob* job) {}
+    virtual void OnPrintJobCreated(base::WeakPtr<CupsPrintJob> job) {}
+    virtual void OnPrintJobStarted(base::WeakPtr<CupsPrintJob> job) {}
+    virtual void OnPrintJobUpdated(base::WeakPtr<CupsPrintJob> job) {}
+    virtual void OnPrintJobSuspended(base::WeakPtr<CupsPrintJob> job) {}
+    virtual void OnPrintJobResumed(base::WeakPtr<CupsPrintJob> job) {}
 
     // Handle print job completion.  Note, |job| will be deleted after
     // notification is complete.
-    virtual void OnPrintJobDone(CupsPrintJob* job) {}
+    virtual void OnPrintJobDone(base::WeakPtr<CupsPrintJob> job) {}
 
     // Handle print job error.  Note, |job| will be deleted after
     // notification is complete.
-    virtual void OnPrintJobError(CupsPrintJob* job) {}
+    virtual void OnPrintJobError(base::WeakPtr<CupsPrintJob> job) {}
 
     // Handle print job cancellation.  Note, |job| will be deleted after
     // notification is complete.
-    virtual void OnPrintJobCancelled(CupsPrintJob* job) {}
+    virtual void OnPrintJobCancelled(base::WeakPtr<CupsPrintJob> job) {}
 
    protected:
     virtual ~Observer() {}
@@ -62,14 +62,14 @@
   void RemoveObserver(Observer* observer);
 
  protected:
-  void NotifyJobCreated(CupsPrintJob* job);
-  void NotifyJobStarted(CupsPrintJob* job);
-  void NotifyJobUpdated(CupsPrintJob* job);
-  void NotifyJobResumed(CupsPrintJob* job);
-  void NotifyJobSuspended(CupsPrintJob* job);
-  void NotifyJobCanceled(CupsPrintJob* job);
-  void NotifyJobError(CupsPrintJob* job);
-  void NotifyJobDone(CupsPrintJob* job);
+  void NotifyJobCreated(base::WeakPtr<CupsPrintJob> job);
+  void NotifyJobStarted(base::WeakPtr<CupsPrintJob> job);
+  void NotifyJobUpdated(base::WeakPtr<CupsPrintJob> job);
+  void NotifyJobResumed(base::WeakPtr<CupsPrintJob> job);
+  void NotifyJobSuspended(base::WeakPtr<CupsPrintJob> job);
+  void NotifyJobCanceled(base::WeakPtr<CupsPrintJob> job);
+  void NotifyJobError(base::WeakPtr<CupsPrintJob> job);
+  void NotifyJobDone(base::WeakPtr<CupsPrintJob> job);
 
   Profile* profile_;
   std::unique_ptr<CupsPrintJobNotificationManager> notification_manager_;
diff --git a/chrome/browser/chromeos/printing/cups_print_job_manager_impl.cc b/chrome/browser/chromeos/printing/cups_print_job_manager_impl.cc
index 5325295..2a8863c 100644
--- a/chrome/browser/chromeos/printing/cups_print_job_manager_impl.cc
+++ b/chrome/browser/chromeos/printing/cups_print_job_manager_impl.cc
@@ -273,7 +273,7 @@
   void CancelPrintJob(CupsPrintJob* job) override {
     DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
     job->set_state(CupsPrintJob::State::STATE_CANCELLED);
-    NotifyJobCanceled(job);
+    NotifyJobCanceled(job->GetWeakPtr());
     // Ideally we should wait for IPP response.
     FinishPrintJob(job);
   }
@@ -338,11 +338,11 @@
     jobs_[key] = std::move(cpj);
 
     CupsPrintJob* job = jobs_[key].get();
-    NotifyJobCreated(job);
+    NotifyJobCreated(job->GetWeakPtr());
 
     // Always start jobs in the waiting state.
     job->set_state(CupsPrintJob::State::STATE_WAITING);
-    NotifyJobUpdated(job);
+    NotifyJobUpdated(job->GetWeakPtr());
 
     // Run a query now.
     content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::UI)
@@ -439,7 +439,7 @@
 
         if (UpdatePrintJob(queue.printer_status, job, print_job)) {
           // The state of the job changed, notify observers.
-          NotifyJobStateUpdate(print_job);
+          NotifyJobStateUpdate(print_job->GetWeakPtr());
         }
 
         if (print_job->PipelineDead()) {
@@ -477,16 +477,19 @@
       RecordJobResult(LOST);
       CupsPrintJob* job = entry.second.get();
       job->set_state(CupsPrintJob::State::STATE_ERROR);
-      NotifyJobStateUpdate(job);
+      NotifyJobStateUpdate(job->GetWeakPtr());
     }
 
     jobs_.clear();
   }
 
   // Notify observers that a state update has occured for |job|.
-  void NotifyJobStateUpdate(CupsPrintJob* job) {
+  void NotifyJobStateUpdate(base::WeakPtr<CupsPrintJob> job) {
     DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
+    if (!job)
+      return;
+
     switch (job->state()) {
       case State::STATE_NONE:
         // State does not require notification.
diff --git a/chrome/browser/chromeos/printing/cups_print_job_notification.cc b/chrome/browser/chromeos/printing/cups_print_job_notification.cc
index 9c97961..000c931 100644
--- a/chrome/browser/chromeos/printing/cups_print_job_notification.cc
+++ b/chrome/browser/chromeos/printing/cups_print_job_notification.cc
@@ -37,7 +37,7 @@
 
 CupsPrintJobNotification::CupsPrintJobNotification(
     CupsPrintJobNotificationManager* manager,
-    CupsPrintJob* print_job,
+    base::WeakPtr<CupsPrintJob> print_job,
     Profile* profile)
     : notification_manager_(manager),
       notification_id_(print_job->GetUniqueId()),
@@ -89,9 +89,12 @@
   CupsPrintJobManager* print_job_manager =
       CupsPrintJobManagerFactory::GetForBrowserContext(profile_);
 
+  if (!print_job_)
+    return;
+
   switch (button_commands_[button_index]) {
     case ButtonCommand::CANCEL_PRINTING:
-      print_job_manager->CancelPrintJob(print_job_);
+      print_job_manager->CancelPrintJob(print_job_.get());
       // print_job_ was deleted in CancelPrintJob.  Forget the pointer.
       print_job_ = nullptr;
 
@@ -102,10 +105,10 @@
       notification_manager_->OnPrintJobNotificationRemoved(this);
       break;
     case ButtonCommand::PAUSE_PRINTING:
-      print_job_manager->SuspendPrintJob(print_job_);
+      print_job_manager->SuspendPrintJob(print_job_.get());
       break;
     case ButtonCommand::RESUME_PRINTING:
-      print_job_manager->ResumePrintJob(print_job_);
+      print_job_manager->ResumePrintJob(print_job_.get());
       break;
     case ButtonCommand::GET_HELP:
       break;
@@ -113,6 +116,8 @@
 }
 
 void CupsPrintJobNotification::UpdateNotification() {
+  if (!print_job_)
+    return;
   UpdateNotificationTitle();
   UpdateNotificationIcon();
   UpdateNotificationBodyMessage();
@@ -148,6 +153,8 @@
 }
 
 void CupsPrintJobNotification::UpdateNotificationTitle() {
+  if (!print_job_)
+    return;
   base::string16 title;
   switch (print_job_->state()) {
     case CupsPrintJob::State::STATE_WAITING:
@@ -177,6 +184,8 @@
 }
 
 void CupsPrintJobNotification::UpdateNotificationIcon() {
+  if (!print_job_)
+    return;
   switch (print_job_->state()) {
     case CupsPrintJob::State::STATE_WAITING:
     case CupsPrintJob::State::STATE_STARTED:
@@ -205,6 +214,8 @@
 }
 
 void CupsPrintJobNotification::UpdateNotificationBodyMessage() {
+  if (!print_job_)
+    return;
   base::string16 message;
   if (print_job_->total_page_number() > 1) {
     message = l10n_util::GetStringFUTF16(
@@ -220,6 +231,8 @@
 }
 
 void CupsPrintJobNotification::UpdateNotificationType() {
+  if (!print_job_)
+    return;
   switch (print_job_->state()) {
     case CupsPrintJob::State::STATE_WAITING:
     case CupsPrintJob::State::STATE_STARTED:
@@ -253,6 +266,8 @@
 
 std::vector<CupsPrintJobNotification::ButtonCommand>
 CupsPrintJobNotification::GetButtonCommands() const {
+  if (!print_job_)
+    return {};
   std::vector<CupsPrintJobNotification::ButtonCommand> commands;
   switch (print_job_->state()) {
     case CupsPrintJob::State::STATE_WAITING:
diff --git a/chrome/browser/chromeos/printing/cups_print_job_notification.h b/chrome/browser/chromeos/printing/cups_print_job_notification.h
index 6a815d82e..8531386b 100644
--- a/chrome/browser/chromeos/printing/cups_print_job_notification.h
+++ b/chrome/browser/chromeos/printing/cups_print_job_notification.h
@@ -36,7 +36,7 @@
   };
 
   CupsPrintJobNotification(CupsPrintJobNotificationManager* manager,
-                           CupsPrintJob* print_job,
+                           base::WeakPtr<CupsPrintJob> print_job,
                            Profile* profile);
   virtual ~CupsPrintJobNotification();
 
@@ -63,7 +63,7 @@
   CupsPrintJobNotificationManager* notification_manager_;
   std::unique_ptr<message_center::Notification> notification_;
   std::string notification_id_;
-  CupsPrintJob* print_job_;
+  base::WeakPtr<CupsPrintJob> print_job_;
   Profile* profile_;
 
   // If the notification has been closed in the middle of printing or not. If it
diff --git a/chrome/browser/chromeos/printing/cups_print_job_notification_manager.cc b/chrome/browser/chromeos/printing/cups_print_job_notification_manager.cc
index 53bf08a..98cee8c 100644
--- a/chrome/browser/chromeos/printing/cups_print_job_notification_manager.cc
+++ b/chrome/browser/chromeos/printing/cups_print_job_notification_manager.cc
@@ -22,45 +22,55 @@
   print_job_manager_->RemoveObserver(this);
 }
 
-void CupsPrintJobNotificationManager::OnPrintJobCreated(CupsPrintJob* job) {
-  if (base::ContainsKey(notification_map_, job))
+void CupsPrintJobNotificationManager::OnPrintJobCreated(
+    base::WeakPtr<CupsPrintJob> job) {
+  if (!job)
     return;
-  notification_map_[job] =
+  if (base::ContainsKey(notification_map_, job.get()))
+    return;
+  notification_map_[job.get()] =
       std::make_unique<CupsPrintJobNotification>(this, job, profile_);
 }
 
-void CupsPrintJobNotificationManager::OnPrintJobStarted(CupsPrintJob* job) {
+void CupsPrintJobNotificationManager::OnPrintJobStarted(
+    base::WeakPtr<CupsPrintJob> job) {
   UpdateNotification(job);
 }
 
-void CupsPrintJobNotificationManager::OnPrintJobUpdated(CupsPrintJob* job) {
+void CupsPrintJobNotificationManager::OnPrintJobUpdated(
+    base::WeakPtr<CupsPrintJob> job) {
   UpdateNotification(job);
 }
 
-void CupsPrintJobNotificationManager::OnPrintJobSuspended(CupsPrintJob* job) {
+void CupsPrintJobNotificationManager::OnPrintJobSuspended(
+    base::WeakPtr<CupsPrintJob> job) {
   UpdateNotification(job);
 }
 
-void CupsPrintJobNotificationManager::OnPrintJobResumed(CupsPrintJob* job) {
+void CupsPrintJobNotificationManager::OnPrintJobResumed(
+    base::WeakPtr<CupsPrintJob> job) {
   UpdateNotification(job);
 }
 
-void CupsPrintJobNotificationManager::OnPrintJobDone(CupsPrintJob* job) {
+void CupsPrintJobNotificationManager::OnPrintJobDone(
+    base::WeakPtr<CupsPrintJob> job) {
   UpdateNotification(job);
 }
 
-void CupsPrintJobNotificationManager::OnPrintJobError(CupsPrintJob* job) {
+void CupsPrintJobNotificationManager::OnPrintJobError(
+    base::WeakPtr<CupsPrintJob> job) {
   UpdateNotification(job);
 }
 
-void CupsPrintJobNotificationManager::OnPrintJobCancelled(CupsPrintJob* job) {
+void CupsPrintJobNotificationManager::OnPrintJobCancelled(
+    base::WeakPtr<CupsPrintJob> job) {
   UpdateNotification(job);
 }
 
 void CupsPrintJobNotificationManager::OnPrintJobNotificationRemoved(
     CupsPrintJobNotification* notification) {
-  // |job| might be a nullptr at this moment, so we iterate through
-  // |notification_map_| to find |notification|.
+  // |notification|.print_job_ might be a nullptr at this moment, so we iterate
+  // through |notification_map_| to find |notification|.
   auto it = notification_map_.begin();
   for (; it != notification_map_.end(); it++) {
     if (it->second.get() == notification)
@@ -71,9 +81,12 @@
     notification_map_.erase(it);
 }
 
-void CupsPrintJobNotificationManager::UpdateNotification(CupsPrintJob* job) {
-  DCHECK(base::ContainsKey(notification_map_, job));
-  notification_map_[job]->OnPrintJobStatusUpdated();
+void CupsPrintJobNotificationManager::UpdateNotification(
+    base::WeakPtr<CupsPrintJob> job) {
+  if (!job)
+    return;
+  DCHECK(base::ContainsKey(notification_map_, job.get()));
+  notification_map_[job.get()]->OnPrintJobStatusUpdated();
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/printing/cups_print_job_notification_manager.h b/chrome/browser/chromeos/printing/cups_print_job_notification_manager.h
index c5f0cd64..15fe14f 100644
--- a/chrome/browser/chromeos/printing/cups_print_job_notification_manager.h
+++ b/chrome/browser/chromeos/printing/cups_print_job_notification_manager.h
@@ -30,19 +30,19 @@
   ~CupsPrintJobNotificationManager() override;
 
   // CupsPrintJobManager::Observer overrides:
-  void OnPrintJobCreated(CupsPrintJob* job) override;
-  void OnPrintJobStarted(CupsPrintJob* job) override;
-  void OnPrintJobUpdated(CupsPrintJob* job) override;
-  void OnPrintJobSuspended(CupsPrintJob* job) override;
-  void OnPrintJobResumed(CupsPrintJob* job) override;
-  void OnPrintJobDone(CupsPrintJob* job) override;
-  void OnPrintJobError(CupsPrintJob* job) override;
-  void OnPrintJobCancelled(CupsPrintJob* job) override;
+  void OnPrintJobCreated(base::WeakPtr<CupsPrintJob> job) override;
+  void OnPrintJobStarted(base::WeakPtr<CupsPrintJob> job) override;
+  void OnPrintJobUpdated(base::WeakPtr<CupsPrintJob> job) override;
+  void OnPrintJobSuspended(base::WeakPtr<CupsPrintJob> job) override;
+  void OnPrintJobResumed(base::WeakPtr<CupsPrintJob> job) override;
+  void OnPrintJobDone(base::WeakPtr<CupsPrintJob> job) override;
+  void OnPrintJobError(base::WeakPtr<CupsPrintJob> job) override;
+  void OnPrintJobCancelled(base::WeakPtr<CupsPrintJob> job) override;
 
   void OnPrintJobNotificationRemoved(CupsPrintJobNotification* notification);
 
  private:
-  void UpdateNotification(CupsPrintJob* job);
+  void UpdateNotification(base::WeakPtr<CupsPrintJob> job);
 
   PrintJobNotificationMap notification_map_;
   CupsPrintJobManager* print_job_manager_;
diff --git a/chrome/browser/chromeos/printing/fake_cups_print_job_manager.cc b/chrome/browser/chromeos/printing/fake_cups_print_job_manager.cc
index 2c086d1..93bf2ffa 100644
--- a/chrome/browser/chromeos/printing/fake_cups_print_job_manager.cc
+++ b/chrome/browser/chromeos/printing/fake_cups_print_job_manager.cc
@@ -49,7 +49,7 @@
 
 void FakeCupsPrintJobManager::CancelPrintJob(CupsPrintJob* job) {
   job->set_state(CupsPrintJob::State::STATE_CANCELLED);
-  NotifyJobCanceled(job);
+  NotifyJobCanceled(job->GetWeakPtr());
 
   // Note: |job| is deleted here.
   for (auto iter = print_jobs_.begin(); iter != print_jobs_.end(); ++iter) {
@@ -62,13 +62,13 @@
 
 bool FakeCupsPrintJobManager::SuspendPrintJob(CupsPrintJob* job) {
   job->set_state(CupsPrintJob::State::STATE_SUSPENDED);
-  NotifyJobSuspended(job);
+  NotifyJobSuspended(job->GetWeakPtr());
   return true;
 }
 
 bool FakeCupsPrintJobManager::ResumePrintJob(CupsPrintJob* job) {
   job->set_state(CupsPrintJob::State::STATE_RESUMED);
-  NotifyJobResumed(job);
+  NotifyJobResumed(job->GetWeakPtr());
 
   base::SequencedTaskRunnerHandle::Get()->PostNonNestableDelayedTask(
       FROM_HERE, base::Bind(&FakeCupsPrintJobManager::ChangePrintJobState,
@@ -96,26 +96,26 @@
   switch (job->state()) {
     case CupsPrintJob::State::STATE_NONE:
       job->set_state(CupsPrintJob::State::STATE_WAITING);
-      NotifyJobCreated(job);
+      NotifyJobCreated(job->GetWeakPtr());
       break;
     case CupsPrintJob::State::STATE_WAITING:
       job->set_state(CupsPrintJob::State::STATE_STARTED);
-      NotifyJobStarted(job);
+      NotifyJobStarted(job->GetWeakPtr());
       break;
     case CupsPrintJob::State::STATE_STARTED:
       job->set_printed_page_number(job->printed_page_number() + 1);
       job->set_state(CupsPrintJob::State::STATE_PAGE_DONE);
-      NotifyJobStarted(job);
+      NotifyJobStarted(job->GetWeakPtr());
       break;
     case CupsPrintJob::State::STATE_PAGE_DONE:
     case CupsPrintJob::State::STATE_RESUMED:
       if (job->printed_page_number() == job->total_page_number()) {
         job->set_state(CupsPrintJob::State::STATE_DOCUMENT_DONE);
-        NotifyJobDone(job);
+        NotifyJobDone(job->GetWeakPtr());
       } else {
         job->set_printed_page_number(job->printed_page_number() + 1);
         job->set_state(CupsPrintJob::State::STATE_PAGE_DONE);
-        NotifyJobUpdated(job);
+        NotifyJobUpdated(job->GetWeakPtr());
       }
       break;
     case CupsPrintJob::State::STATE_DOCUMENT_DONE:
diff --git a/chrome/browser/chromeos/smb_client/discovery/host_locator.h b/chrome/browser/chromeos/smb_client/discovery/host_locator.h
index 07cff00..f99a375 100644
--- a/chrome/browser/chromeos/smb_client/discovery/host_locator.h
+++ b/chrome/browser/chromeos/smb_client/discovery/host_locator.h
@@ -16,7 +16,11 @@
 using Hostname = std::string;
 using Address = std::string;
 using HostMap = std::map<Hostname, Address>;
-using FindHostsCallback = base::OnceCallback<void(const HostMap& hosts)>;
+
+// |success| will be false if an error occurred when finding hosts. |success|
+// can be true even if |hosts| is empty.
+using FindHostsCallback =
+    base::OnceCallback<void(bool success, const HostMap& hosts)>;
 
 // Interface that abstracts the multiple methods of finding SMB hosts in a
 // network. (e.g. mDNS, NetBIOS over TCP, LMHosts, DNS)
diff --git a/chrome/browser/chromeos/smb_client/discovery/in_memory_host_locator.cc b/chrome/browser/chromeos/smb_client/discovery/in_memory_host_locator.cc
index d47f6a0..519595c 100644
--- a/chrome/browser/chromeos/smb_client/discovery/in_memory_host_locator.cc
+++ b/chrome/browser/chromeos/smb_client/discovery/in_memory_host_locator.cc
@@ -29,7 +29,7 @@
 }
 
 void InMemoryHostLocator::FindHosts(FindHostsCallback callback) {
-  std::move(callback).Run(host_map_);
+  std::move(callback).Run(true /* success */, host_map_);
 }
 
 }  // namespace smb_client
diff --git a/chrome/browser/chromeos/smb_client/discovery/in_memory_host_locator_unittest.cc b/chrome/browser/chromeos/smb_client/discovery/in_memory_host_locator_unittest.cc
index aadcace..3c9ca8ae 100644
--- a/chrome/browser/chromeos/smb_client/discovery/in_memory_host_locator_unittest.cc
+++ b/chrome/browser/chromeos/smb_client/discovery/in_memory_host_locator_unittest.cc
@@ -17,13 +17,17 @@
 
 // Expects |actual_hosts| to not equal |hosts|.
 void ExpectMapEntriesNotEqual(const HostMap& hosts,
+                              bool success,
                               const HostMap& actual_hosts) {
+  EXPECT_TRUE(success);
   EXPECT_NE(hosts, actual_hosts);
 }
 
 // Expects |actual_hosts| to equal |expected_hosts|.
-void ExpectMapEntries(const HostMap& expected_hosts,
-                      const HostMap& actual_hosts) {
+void ExpectMapEntriesEqual(const HostMap& expected_hosts,
+                           bool success,
+                           const HostMap& actual_hosts) {
+  EXPECT_TRUE(success);
   EXPECT_EQ(expected_hosts, actual_hosts);
 }
 
@@ -36,7 +40,7 @@
 
  protected:
   void ExpectHostMapEqual(const HostMap& hosts) {
-    locator_.FindHosts(base::BindOnce(&ExpectMapEntries, hosts));
+    locator_.FindHosts(base::BindOnce(&ExpectMapEntriesEqual, hosts));
   }
 
   void ExpectHostMapNotEqual(const HostMap& hosts) {
diff --git a/chrome/browser/chromeos/smb_client/discovery/network_scanner.cc b/chrome/browser/chromeos/smb_client/discovery/network_scanner.cc
index ff6f538..b10a2c9 100644
--- a/chrome/browser/chromeos/smb_client/discovery/network_scanner.cc
+++ b/chrome/browser/chromeos/smb_client/discovery/network_scanner.cc
@@ -38,7 +38,7 @@
 void NetworkScanner::FindHostsInNetwork(FindHostsCallback callback) {
   if (locators_.empty()) {
     // Fire the callback immediately if there are no registered HostLocators.
-    std::move(callback).Run(HostMap());
+    std::move(callback).Run(false /* success */, HostMap());
     return;
   }
 
@@ -54,10 +54,14 @@
 }
 
 void NetworkScanner::OnHostsFound(uint32_t request_id,
+                                  bool success,
                                   const HostMap& host_map) {
   DCHECK_GT(requests_.count(request_id), 0u);
 
-  AddHostsToResults(request_id, host_map);
+  if (success) {
+    AddHostsToResults(request_id, host_map);
+  }
+
   FireCallbackIfFinished(request_id);
 }
 
@@ -98,7 +102,7 @@
     RequestInfo info = std::move(request_iter->second);
     requests_.erase(request_iter);
 
-    std::move(info.callback).Run(info.hosts_found);
+    std::move(info.callback).Run(true /* success */, info.hosts_found);
   }
 }
 
diff --git a/chrome/browser/chromeos/smb_client/discovery/network_scanner.h b/chrome/browser/chromeos/smb_client/discovery/network_scanner.h
index 4a3511b6..ce5d4b7f 100644
--- a/chrome/browser/chromeos/smb_client/discovery/network_scanner.h
+++ b/chrome/browser/chromeos/smb_client/discovery/network_scanner.h
@@ -40,7 +40,7 @@
   // Query the registered HostLocators and return all the hosts found.
   // |callback| is called once all the HostLocators have responded with their
   // results. If there are no locators, the callback is fired immediately with
-  // an empty result.
+  // an empty result and success set to false.
   void FindHostsInNetwork(FindHostsCallback callback);
 
   // Registeres a |locator| to be queried when FindHostsInNetwork() is called.
@@ -48,7 +48,7 @@
 
  private:
   // Callback handler for HostLocator::FindHosts().
-  void OnHostsFound(uint32_t request_id, const HostMap& host_map);
+  void OnHostsFound(uint32_t request_id, bool success, const HostMap& host_map);
 
   // Adds |host_map| hosts to current results. The host will not be added if the
   // hostname already exists in results, and if the IP address does not match,
diff --git a/chrome/browser/chromeos/smb_client/discovery/network_scanner_unittest.cc b/chrome/browser/chromeos/smb_client/discovery/network_scanner_unittest.cc
index 4992951..014232c 100644
--- a/chrome/browser/chromeos/smb_client/discovery/network_scanner_unittest.cc
+++ b/chrome/browser/chromeos/smb_client/discovery/network_scanner_unittest.cc
@@ -19,10 +19,17 @@
 
 // Expects |actual_hosts| to equal |expected_hosts|.
 void ExpectMapEntriesEqual(const HostMap& expected_hosts,
+                           bool success,
                            const HostMap& actual_hosts) {
+  EXPECT_TRUE(success);
   EXPECT_EQ(expected_hosts, actual_hosts);
 }
 
+void ExpectFailure(bool success, const HostMap& actual_hosts) {
+  EXPECT_FALSE(success);
+  EXPECT_TRUE(actual_hosts.empty());
+}
+
 }  // namespace
 
 class NetworkScannerTest : public testing::Test {
@@ -43,14 +50,18 @@
         base::BindOnce(&ExpectMapEntriesEqual, expected_hosts));
   }
 
+  void ExpectCallFailure() {
+    scanner_.FindHostsInNetwork(base::BindOnce(&ExpectFailure));
+  }
+
  private:
   NetworkScanner scanner_;
 
   DISALLOW_COPY_AND_ASSIGN(NetworkScannerTest);
 };
 
-TEST_F(NetworkScannerTest, ShouldFindNoHostsWithNoLocator) {
-  ExpectHostMapEqual(HostMap());
+TEST_F(NetworkScannerTest, SuccessIsFalseAndHostsMapIsEmptyWithNoLocator) {
+  ExpectCallFailure();
 }
 
 TEST_F(NetworkScannerTest, ShouldFindNoHostsWithOneLocator) {
diff --git a/chrome/browser/chromeos/smb_client/smb_file_system.cc b/chrome/browser/chromeos/smb_client/smb_file_system.cc
index bc6cc06..2b1a0ec 100644
--- a/chrome/browser/chromeos/smb_client/smb_file_system.cc
+++ b/chrome/browser/chromeos/smb_client/smb_file_system.cc
@@ -184,7 +184,7 @@
 }
 
 AbortCallback SmbFileSystem::RequestUnmount(
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   auto reply = base::BindOnce(&SmbFileSystem::HandleRequestUnmountCallback,
                               AsWeakPtr(), callback);
   SmbTask task =
@@ -195,7 +195,7 @@
 }
 
 void SmbFileSystem::HandleRequestUnmountCallback(
-    const storage::AsyncFileUtil::StatusCallback& callback,
+    storage::AsyncFileUtil::StatusCallback callback,
     smbprovider::ErrorType error) {
   task_queue_.TaskFinished();
   base::File::Error result = TranslateError(error);
@@ -204,13 +204,13 @@
         file_system_info_.provider_id(), file_system_info_.file_system_id(),
         file_system_provider::Service::UNMOUNT_REASON_USER);
   }
-  callback.Run(result);
+  std::move(callback).Run(result);
 }
 
 AbortCallback SmbFileSystem::GetMetadata(
     const base::FilePath& entry_path,
     ProvidedFileSystemInterface::MetadataFieldMask fields,
-    const ProvidedFileSystemInterface::GetMetadataCallback& callback) {
+    ProvidedFileSystemInterface::GetMetadataCallback callback) {
   auto reply =
       base::BindOnce(&SmbFileSystem::HandleRequestGetMetadataEntryCallback,
                      AsWeakPtr(), fields, callback);
@@ -223,24 +223,24 @@
 
 AbortCallback SmbFileSystem::GetActions(
     const std::vector<base::FilePath>& entry_paths,
-    const GetActionsCallback& callback) {
+    GetActionsCallback callback) {
   const std::vector<file_system_provider::Action> actions;
   // No actions are currently supported.
-  callback.Run(actions, base::File::FILE_OK);
+  std::move(callback).Run(actions, base::File::FILE_OK);
   return CreateAbortCallback();
 }
 
 AbortCallback SmbFileSystem::ExecuteAction(
     const std::vector<base::FilePath>& entry_paths,
     const std::string& action_id,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   NOTIMPLEMENTED();
   return CreateAbortCallback();
 }
 
 AbortCallback SmbFileSystem::ReadDirectory(
     const base::FilePath& directory_path,
-    const storage::AsyncFileUtil::ReadDirectoryCallback& callback) {
+    storage::AsyncFileUtil::ReadDirectoryCallback callback) {
   auto reply =
       base::BindOnce(&SmbFileSystem::HandleRequestReadDirectoryCallback,
                      AsWeakPtr(), callback);
@@ -253,7 +253,7 @@
 
 AbortCallback SmbFileSystem::OpenFile(const base::FilePath& file_path,
                                       file_system_provider::OpenFileMode mode,
-                                      const OpenFileCallback& callback) {
+                                      OpenFileCallback callback) {
   bool writeable =
       mode == file_system_provider::OPEN_FILE_MODE_WRITE ? true : false;
 
@@ -267,7 +267,7 @@
 }
 
 void SmbFileSystem::HandleRequestOpenFileCallback(
-    const OpenFileCallback& callback,
+    OpenFileCallback callback,
     smbprovider::ErrorType error,
     int32_t file_id) const {
   task_queue_.TaskFinished();
@@ -276,7 +276,7 @@
 
 AbortCallback SmbFileSystem::CloseFile(
     int file_handle,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   auto reply = base::BindOnce(&SmbFileSystem::HandleStatusCallback, AsWeakPtr(),
                               callback);
   SmbTask task =
@@ -286,12 +286,11 @@
   return EnqueueTaskAndGetCallback(std::move(task));
 }
 
-AbortCallback SmbFileSystem::ReadFile(
-    int file_handle,
-    net::IOBuffer* buffer,
-    int64_t offset,
-    int length,
-    const ReadChunkReceivedCallback& callback) {
+AbortCallback SmbFileSystem::ReadFile(int file_handle,
+                                      net::IOBuffer* buffer,
+                                      int64_t offset,
+                                      int length,
+                                      ReadChunkReceivedCallback callback) {
   auto reply =
       base::BindOnce(&SmbFileSystem::HandleRequestReadFileCallback, AsWeakPtr(),
                      length, scoped_refptr<net::IOBuffer>(buffer), callback);
@@ -306,7 +305,7 @@
 AbortCallback SmbFileSystem::CreateDirectory(
     const base::FilePath& directory_path,
     bool recursive,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   auto reply = base::BindOnce(&SmbFileSystem::HandleStatusCallback, AsWeakPtr(),
                               callback);
 
@@ -319,9 +318,9 @@
 
 AbortCallback SmbFileSystem::CreateFile(
     const base::FilePath& file_path,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   auto reply = base::BindOnce(&SmbFileSystem::HandleStatusCallback, AsWeakPtr(),
-                              callback);
+                              std::move(callback));
   SmbTask task =
       base::BindOnce(&SmbProviderClient::CreateFile, GetWeakSmbProviderClient(),
                      GetMountId(), file_path, std::move(reply));
@@ -332,7 +331,7 @@
 AbortCallback SmbFileSystem::DeleteEntry(
     const base::FilePath& entry_path,
     bool recursive,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   OperationId operation_id = task_queue_.GetNextOperationId();
 
   auto reply = base::BindOnce(&SmbFileSystem::HandleGetDeleteListCallback,
@@ -348,7 +347,7 @@
 AbortCallback SmbFileSystem::CopyEntry(
     const base::FilePath& source_path,
     const base::FilePath& target_path,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   auto reply = base::BindOnce(&SmbFileSystem::HandleStatusCallback, AsWeakPtr(),
                               callback);
   SmbTask task =
@@ -361,7 +360,7 @@
 AbortCallback SmbFileSystem::MoveEntry(
     const base::FilePath& source_path,
     const base::FilePath& target_path,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   auto reply = base::BindOnce(&SmbFileSystem::HandleStatusCallback, AsWeakPtr(),
                               callback);
   SmbTask task =
@@ -374,7 +373,7 @@
 AbortCallback SmbFileSystem::Truncate(
     const base::FilePath& file_path,
     int64_t length,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   auto reply = base::BindOnce(&SmbFileSystem::HandleStatusCallback, AsWeakPtr(),
                               callback);
   SmbTask task =
@@ -389,7 +388,7 @@
     net::IOBuffer* buffer,
     int64_t offset,
     int length,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   const std::vector<uint8_t> data(buffer->data(), buffer->data() + length);
   base::ScopedFD temp_fd = temp_file_manager_.CreateTempFile(data);
 
@@ -407,13 +406,12 @@
     const base::FilePath& entry_path,
     bool recursive,
     bool persistent,
-    const storage::AsyncFileUtil::StatusCallback& callback,
+    storage::AsyncFileUtil::StatusCallback callback,
     const storage::WatcherManager::NotificationCallback&
         notification_callback) {
   // Watchers are not supported.
-  // This method should not be getting called since watchable is set to false.
-  // crbug.com/796334.
-  callback.Run(base::File::FILE_ERROR_INVALID_OPERATION);
+  NOTIMPLEMENTED();
+  std::move(callback).Run(base::File::FILE_ERROR_INVALID_OPERATION);
   return CreateAbortCallback();
 }
 
@@ -421,11 +419,10 @@
     const GURL& origin,
     const base::FilePath& entry_path,
     bool recursive,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   // Watchers are not supported.
-  // This method should not be getting called since watchable is set to false.
-  // http://www.crbug.com/796334.
-  callback.Run(base::File::FILE_ERROR_INVALID_OPERATION);
+  NOTIMPLEMENTED();
+  std::move(callback).Run(base::File::FILE_ERROR_INVALID_OPERATION);
 }
 
 const file_system_provider::ProvidedFileSystemInfo&
@@ -440,9 +437,8 @@
 
 file_system_provider::Watchers* SmbFileSystem::GetWatchers() {
   // Watchers are not supported.
-  // This method should not be getting called since watchable is set to false.
-  // http://www.crbug.com/796334.
-  return &watchers_;
+  NOTIMPLEMENTED();
+  return nullptr;
 }
 
 const file_system_provider::OpenedFiles& SmbFileSystem::GetOpenedFiles() const {
@@ -467,17 +463,16 @@
     std::unique_ptr<file_system_provider::ProvidedFileSystemObserver::Changes>
         changes,
     const std::string& tag,
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+    storage::AsyncFileUtil::StatusCallback callback) {
   NOTIMPLEMENTED();
 }
 
-void SmbFileSystem::Configure(
-    const storage::AsyncFileUtil::StatusCallback& callback) {
+void SmbFileSystem::Configure(storage::AsyncFileUtil::StatusCallback callback) {
   NOTIMPLEMENTED();
 }
 
 void SmbFileSystem::HandleRequestReadDirectoryCallback(
-    const storage::AsyncFileUtil::ReadDirectoryCallback& callback,
+    storage::AsyncFileUtil::ReadDirectoryCallback callback,
     smbprovider::ErrorType error,
     const smbprovider::DirectoryEntryListProto& entries) const {
   task_queue_.TaskFinished();
@@ -545,13 +540,12 @@
 
 void SmbFileSystem::HandleRequestGetMetadataEntryCallback(
     ProvidedFileSystemInterface::MetadataFieldMask fields,
-    const ProvidedFileSystemInterface::GetMetadataCallback& callback,
+    ProvidedFileSystemInterface::GetMetadataCallback callback,
     smbprovider::ErrorType error,
     const smbprovider::DirectoryEntryProto& entry) const {
   task_queue_.TaskFinished();
   if (error != smbprovider::ERROR_OK) {
-    callback.Run(std::unique_ptr<file_system_provider::EntryMetadata>(),
-                 TranslateError(error));
+    std::move(callback).Run(nullptr, TranslateError(error));
     return;
   }
   std::unique_ptr<file_system_provider::EntryMetadata> metadata =
@@ -573,7 +567,7 @@
     metadata->thumbnail = std::make_unique<std::string>(kUnknownImageDataUri);
   }
   // Mime types are not supported.
-  callback.Run(std::move(metadata), base::File::FILE_OK);
+  std::move(callback).Run(std::move(metadata), base::File::FILE_OK);
 }
 
 base::File::Error SmbFileSystem::RunUnmountCallback(
@@ -588,7 +582,7 @@
 void SmbFileSystem::HandleRequestReadFileCallback(
     int32_t length,
     scoped_refptr<net::IOBuffer> buffer,
-    const ReadChunkReceivedCallback& callback,
+    ReadChunkReceivedCallback callback,
     smbprovider::ErrorType error,
     const base::ScopedFD& fd) const {
   task_queue_.TaskFinished();
@@ -620,11 +614,11 @@
 }
 
 void SmbFileSystem::HandleStatusCallback(
-    const storage::AsyncFileUtil::StatusCallback& callback,
+    storage::AsyncFileUtil::StatusCallback callback,
     smbprovider::ErrorType error) const {
   task_queue_.TaskFinished();
 
-  callback.Run(TranslateError(error));
+  std::move(callback).Run(TranslateError(error));
 }
 
 base::WeakPtr<file_system_provider::ProvidedFileSystemInterface>
diff --git a/chrome/browser/chromeos/smb_client/smb_file_system.h b/chrome/browser/chromeos/smb_client/smb_file_system.h
index 516f848..df79612 100644
--- a/chrome/browser/chromeos/smb_client/smb_file_system.h
+++ b/chrome/browser/chromeos/smb_client/smb_file_system.h
@@ -59,93 +59,91 @@
 
   // ProvidedFileSystemInterface overrides.
   file_system_provider::AbortCallback RequestUnmount(
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
 
   file_system_provider::AbortCallback GetMetadata(
       const base::FilePath& entry_path,
       ProvidedFileSystemInterface::MetadataFieldMask fields,
-      const ProvidedFileSystemInterface::GetMetadataCallback& callback)
-      override;
+      ProvidedFileSystemInterface::GetMetadataCallback callback) override;
 
   file_system_provider::AbortCallback GetActions(
       const std::vector<base::FilePath>& entry_paths,
-      const GetActionsCallback& callback) override;
+      GetActionsCallback callback) override;
 
   file_system_provider::AbortCallback ExecuteAction(
       const std::vector<base::FilePath>& entry_paths,
       const std::string& action_id,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
 
   file_system_provider::AbortCallback ReadDirectory(
       const base::FilePath& directory_path,
-      const storage::AsyncFileUtil::ReadDirectoryCallback& callback) override;
+      storage::AsyncFileUtil::ReadDirectoryCallback callback) override;
 
   file_system_provider::AbortCallback OpenFile(
       const base::FilePath& file_path,
       file_system_provider::OpenFileMode mode,
-      const OpenFileCallback& callback) override;
+      OpenFileCallback callback) override;
 
   file_system_provider::AbortCallback CloseFile(
       int file_handle,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
 
   file_system_provider::AbortCallback ReadFile(
       int file_handle,
       net::IOBuffer* buffer,
       int64_t offset,
       int length,
-      const ReadChunkReceivedCallback& callback) override;
+      ReadChunkReceivedCallback callback) override;
 
   file_system_provider::AbortCallback CreateDirectory(
       const base::FilePath& directory_path,
       bool recursive,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
 
   file_system_provider::AbortCallback CreateFile(
       const base::FilePath& file_path,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
 
   file_system_provider::AbortCallback DeleteEntry(
       const base::FilePath& entry_path,
       bool recursive,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
 
   file_system_provider::AbortCallback CopyEntry(
       const base::FilePath& source_path,
       const base::FilePath& target_path,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
 
   file_system_provider::AbortCallback MoveEntry(
       const base::FilePath& source_path,
       const base::FilePath& target_path,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
 
   file_system_provider::AbortCallback Truncate(
       const base::FilePath& file_path,
       int64_t length,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
 
   file_system_provider::AbortCallback WriteFile(
       int file_handle,
       net::IOBuffer* buffer,
       int64_t offset,
       int length,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
 
   file_system_provider::AbortCallback AddWatcher(
       const GURL& origin,
       const base::FilePath& entry_path,
       bool recursive,
       bool persistent,
-      const storage::AsyncFileUtil::StatusCallback& callback,
+      storage::AsyncFileUtil::StatusCallback callback,
       const storage::WatcherManager::NotificationCallback&
           notification_callback) override;
 
-  void RemoveWatcher(
-      const GURL& origin,
-      const base::FilePath& entry_path,
-      bool recursive,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+  void RemoveWatcher(const GURL& origin,
+                     const base::FilePath& entry_path,
+                     bool recursive,
+                     storage::AsyncFileUtil::StatusCallback callback) override;
 
   const file_system_provider::ProvidedFileSystemInfo& GetFileSystemInfo()
       const override;
@@ -169,10 +167,9 @@
       std::unique_ptr<file_system_provider::ProvidedFileSystemObserver::Changes>
           changes,
       const std::string& tag,
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+      storage::AsyncFileUtil::StatusCallback callback) override;
 
-  void Configure(
-      const storage::AsyncFileUtil::StatusCallback& callback) override;
+  void Configure(storage::AsyncFileUtil::StatusCallback callback) override;
 
   base::WeakPtr<ProvidedFileSystemInterface> GetWeakPtr() override;
 
@@ -185,27 +182,26 @@
   file_system_provider::AbortCallback CreateAbortCallback();
 
   void HandleRequestUnmountCallback(
-      const storage::AsyncFileUtil::StatusCallback& callback,
+      storage::AsyncFileUtil::StatusCallback callback,
       smbprovider::ErrorType error);
 
   void HandleRequestReadDirectoryCallback(
-      const storage::AsyncFileUtil::ReadDirectoryCallback& callback,
+      storage::AsyncFileUtil::ReadDirectoryCallback callback,
       smbprovider::ErrorType error,
       const smbprovider::DirectoryEntryListProto& entries) const;
 
   void HandleRequestGetMetadataEntryCallback(
       ProvidedFileSystemInterface::MetadataFieldMask fields,
-      const ProvidedFileSystemInterface::GetMetadataCallback& callback,
+      ProvidedFileSystemInterface::GetMetadataCallback callback,
       smbprovider::ErrorType error,
       const smbprovider::DirectoryEntryProto& entry) const;
 
-  void HandleRequestOpenFileCallback(const OpenFileCallback& callback,
+  void HandleRequestOpenFileCallback(OpenFileCallback callback,
                                      smbprovider::ErrorType error,
                                      int32_t file_id) const;
 
-  void HandleStatusCallback(
-      const storage::AsyncFileUtil::StatusCallback& callback,
-      smbprovider::ErrorType error) const;
+  void HandleStatusCallback(storage::AsyncFileUtil::StatusCallback callback,
+                            smbprovider::ErrorType error) const;
 
   base::File::Error RunUnmountCallback(
       const ProviderId& provider_id,
@@ -214,7 +210,7 @@
 
   void HandleRequestReadFileCallback(int32_t length,
                                      scoped_refptr<net::IOBuffer> buffer,
-                                     const ReadChunkReceivedCallback& callback,
+                                     ReadChunkReceivedCallback callback,
                                      smbprovider::ErrorType error,
                                      const base::ScopedFD& fd) const;
 
@@ -246,10 +242,9 @@
   // the OperationId for the newly created Operation.
   OperationId EnqueueTaskAndGetOperationId(SmbTask task);
 
-  file_system_provider::ProvidedFileSystemInfo file_system_info_;
-  file_system_provider::OpenedFiles opened_files_;
-  storage::AsyncFileUtil::EntryList entry_list_;
-  file_system_provider::Watchers watchers_;
+  const file_system_provider::ProvidedFileSystemInfo file_system_info_;
+  // opened_files_ is marked const since is currently unsupported.
+  const file_system_provider::OpenedFiles opened_files_;
 
   UnmountCallback unmount_callback_;
   TempFileManager temp_file_manager_;
diff --git a/chrome/browser/chromeos/system/tray_accessibility_browsertest.cc b/chrome/browser/chromeos/system/tray_accessibility_browsertest.cc
index 175f4b2..5e913a2 100644
--- a/chrome/browser/chromeos/system/tray_accessibility_browsertest.cc
+++ b/chrome/browser/chromeos/system/tray_accessibility_browsertest.cc
@@ -119,11 +119,6 @@
   base::RunLoop().RunUntilIdle();
 }
 
-void EnableTapDragging(bool enabled) {
-  AccessibilityManager::Get()->EnableTapDragging(enabled);
-  base::RunLoop().RunUntilIdle();
-}
-
 // Uses InProcessBrowserTest instead of OobeBaseTest because most of the tests
 // don't need to test the login screen.
 class TrayAccessibilityTest
@@ -279,12 +274,6 @@
     base::RunLoop().RunUntilIdle();
   }
 
-  void ClickTapDraggingOnDetailMenu() {
-    ash::HoverHighlightView* view = tray()->detailed_menu_->tap_dragging_view_;
-    tray()->detailed_menu_->OnViewClicked(view);
-    base::RunLoop().RunUntilIdle();
-  }
-
   void ClickSelectToSpeakOnDetailMenu() {
     ash::HoverHighlightView* view =
         tray()->detailed_menu_->select_to_speak_view_;
@@ -340,10 +329,6 @@
     return tray()->detailed_menu_->sticky_keys_enabled_;
   }
 
-  bool IsTapDraggingEnabledOnDetailMenu() const {
-    return tray()->detailed_menu_->tap_dragging_enabled_;
-  }
-
   // In material design we show the help button but theme it as disabled if
   // it is not possible to load the help page.
   static bool IsHelpAvailableOnDetailMenu() {
@@ -463,12 +448,6 @@
   EnableStickyKeys(false);
   EXPECT_FALSE(IsTrayIconVisible());
 
-  // Toggling tap dragging changes the visibility of the icon.
-  EnableTapDragging(true);
-  EXPECT_TRUE(IsTrayIconVisible());
-  EnableTapDragging(false);
-  EXPECT_FALSE(IsTrayIconVisible());
-
   // Toggling select-to-speak changes the visibility of the icon.
   EnableSelectToSpeak(true);
   EXPECT_TRUE(IsTrayIconVisible());
@@ -498,8 +477,6 @@
   EXPECT_TRUE(IsTrayIconVisible());
   EnableStickyKeys(true);
   EXPECT_TRUE(IsTrayIconVisible());
-  EnableTapDragging(true);
-  EXPECT_TRUE(IsTrayIconVisible());
   EnableSpokenFeedback(false, ash::A11Y_NOTIFICATION_NONE);
   EXPECT_TRUE(IsTrayIconVisible());
   EnableSelectToSpeak(false);
@@ -521,8 +498,6 @@
   SetFocusHighlightEnabled(false);
   EXPECT_TRUE(IsTrayIconVisible());
   EnableStickyKeys(false);
-  EXPECT_TRUE(IsTrayIconVisible());
-  EnableTapDragging(false);
   EXPECT_FALSE(IsTrayIconVisible());
 
   // Confirms that ash::prefs::kShouldAlwaysShowAccessibilityMenu doesn't affect
@@ -606,12 +581,6 @@
   EnableStickyKeys(false);
   EXPECT_FALSE(CanCreateMenuItem());
 
-  // Toggling tap dragging changes the visibility of the menu.
-  EnableTapDragging(true);
-  EXPECT_TRUE(CanCreateMenuItem());
-  EnableTapDragging(false);
-  EXPECT_FALSE(CanCreateMenuItem());
-
   // Toggling select-to-speak dragging changes the visibility of the menu.
   EnableSelectToSpeak(true);
   EXPECT_TRUE(CanCreateMenuItem());
@@ -643,8 +612,6 @@
   EXPECT_TRUE(CanCreateMenuItem());
   EnableStickyKeys(true);
   EXPECT_TRUE(CanCreateMenuItem());
-  EnableTapDragging(true);
-  EXPECT_TRUE(CanCreateMenuItem());
   EnableVirtualKeyboard(false);
   EXPECT_TRUE(CanCreateMenuItem());
   EnableAutoclick(false);
@@ -668,8 +635,6 @@
   SetFocusHighlightEnabled(false);
   EXPECT_TRUE(CanCreateMenuItem());
   EnableStickyKeys(false);
-  EXPECT_TRUE(CanCreateMenuItem());
-  EnableTapDragging(false);
   EXPECT_FALSE(CanCreateMenuItem());
 }
 
@@ -745,12 +710,6 @@
   EnableStickyKeys(false);
   EXPECT_TRUE(CanCreateMenuItem());
 
-  // The menu remains visible regardless of the toggling tap dragging.
-  EnableTapDragging(true);
-  EXPECT_TRUE(CanCreateMenuItem());
-  EnableTapDragging(false);
-  EXPECT_TRUE(CanCreateMenuItem());
-
   // The menu remains visible regardless of toggling select-to-speak.
   EnableSelectToSpeak(true);
   EXPECT_TRUE(CanCreateMenuItem());
@@ -782,8 +741,6 @@
   EXPECT_TRUE(CanCreateMenuItem());
   EnableStickyKeys(true);
   EXPECT_TRUE(CanCreateMenuItem());
-  EnableTapDragging(true);
-  EXPECT_TRUE(CanCreateMenuItem());
   EnableVirtualKeyboard(false);
   EXPECT_TRUE(CanCreateMenuItem());
   EnableAutoclick(false);
@@ -808,8 +765,6 @@
   EXPECT_TRUE(CanCreateMenuItem());
   EnableStickyKeys(false);
   EXPECT_TRUE(CanCreateMenuItem());
-  EnableTapDragging(false);
-  EXPECT_TRUE(CanCreateMenuItem());
 
   SetShowAccessibilityOptionsInSystemTrayMenu(false);
 
@@ -883,12 +838,6 @@
   EnableStickyKeys(false);
   EXPECT_TRUE(CanCreateMenuItem());
 
-  // The menu remains visible regardless of toggling tap dragging.
-  EnableTapDragging(true);
-  EXPECT_TRUE(CanCreateMenuItem());
-  EnableTapDragging(false);
-  EXPECT_TRUE(CanCreateMenuItem());
-
   // Enabling all accessibility features.
   SetMagnifierEnabled(true);
   EXPECT_TRUE(CanCreateMenuItem());
@@ -910,8 +859,6 @@
   EXPECT_TRUE(CanCreateMenuItem());
   EnableStickyKeys(true);
   EXPECT_TRUE(CanCreateMenuItem());
-  EnableTapDragging(true);
-  EXPECT_TRUE(CanCreateMenuItem());
   EnableVirtualKeyboard(false);
   EXPECT_TRUE(CanCreateMenuItem());
   EnableSpokenFeedback(false, ash::A11Y_NOTIFICATION_NONE);
@@ -932,8 +879,6 @@
   EXPECT_TRUE(CanCreateMenuItem());
   EnableStickyKeys(false);
   EXPECT_TRUE(CanCreateMenuItem());
-  EnableTapDragging(false);
-  EXPECT_TRUE(CanCreateMenuItem());
 
   SetShowAccessibilityOptionsInSystemTrayMenu(true);
 
@@ -1088,17 +1033,6 @@
   ClickStickyKeysOnDetailMenu();
   EXPECT_FALSE(AccessibilityManager::Get()->IsStickyKeysEnabled());
 
-  // Confirms that the check item toggles tap dragging.
-  EXPECT_FALSE(AccessibilityManager::Get()->IsTapDraggingEnabled());
-
-  EXPECT_TRUE(CreateDetailedMenu());
-  ClickTapDraggingOnDetailMenu();
-  EXPECT_TRUE(AccessibilityManager::Get()->IsTapDraggingEnabled());
-
-  EXPECT_TRUE(CreateDetailedMenu());
-  ClickTapDraggingOnDetailMenu();
-  EXPECT_FALSE(AccessibilityManager::Get()->IsTapDraggingEnabled());
-
   // Confirms that the check item toggles select-to-speak.
   EXPECT_FALSE(AccessibilityManager::Get()->IsSelectToSpeakEnabled());
 
@@ -1129,7 +1063,6 @@
   EXPECT_FALSE(IsHighlightMouseCursorEnabledOnDetailMenu());
   EXPECT_FALSE(IsHighlightKeyboardFocusEnabledOnDetailMenu());
   EXPECT_FALSE(IsStickyKeysEnabledOnDetailMenu());
-  EXPECT_FALSE(IsTapDraggingEnabledOnDetailMenu());
   CloseDetailMenu();
 
   // Enabling spoken feedback.
@@ -1147,7 +1080,6 @@
   EXPECT_FALSE(IsHighlightMouseCursorEnabledOnDetailMenu());
   EXPECT_FALSE(IsHighlightKeyboardFocusEnabledOnDetailMenu());
   EXPECT_FALSE(IsStickyKeysEnabledOnDetailMenu());
-  EXPECT_FALSE(IsTapDraggingEnabledOnDetailMenu());
   CloseDetailMenu();
 
   // Disabling spoken feedback.
@@ -1165,7 +1097,6 @@
   EXPECT_FALSE(IsHighlightMouseCursorEnabledOnDetailMenu());
   EXPECT_FALSE(IsHighlightKeyboardFocusEnabledOnDetailMenu());
   EXPECT_FALSE(IsStickyKeysEnabledOnDetailMenu());
-  EXPECT_FALSE(IsTapDraggingEnabledOnDetailMenu());
   CloseDetailMenu();
 
   // Enabling high contrast.
@@ -1183,7 +1114,6 @@
   EXPECT_FALSE(IsHighlightMouseCursorEnabledOnDetailMenu());
   EXPECT_FALSE(IsHighlightKeyboardFocusEnabledOnDetailMenu());
   EXPECT_FALSE(IsStickyKeysEnabledOnDetailMenu());
-  EXPECT_FALSE(IsTapDraggingEnabledOnDetailMenu());
   CloseDetailMenu();
 
   // Disabling high contrast.
@@ -1201,7 +1131,6 @@
   EXPECT_FALSE(IsHighlightMouseCursorEnabledOnDetailMenu());
   EXPECT_FALSE(IsHighlightKeyboardFocusEnabledOnDetailMenu());
   EXPECT_FALSE(IsStickyKeysEnabledOnDetailMenu());
-  EXPECT_FALSE(IsTapDraggingEnabledOnDetailMenu());
   CloseDetailMenu();
 
   // Enabling full screen magnifier.
@@ -1219,7 +1148,6 @@
   EXPECT_FALSE(IsHighlightMouseCursorEnabledOnDetailMenu());
   EXPECT_FALSE(IsHighlightKeyboardFocusEnabledOnDetailMenu());
   EXPECT_FALSE(IsStickyKeysEnabledOnDetailMenu());
-  EXPECT_FALSE(IsTapDraggingEnabledOnDetailMenu());
   CloseDetailMenu();
 
   // Disabling screen magnifier.
@@ -1237,7 +1165,6 @@
   EXPECT_FALSE(IsHighlightMouseCursorEnabledOnDetailMenu());
   EXPECT_FALSE(IsHighlightKeyboardFocusEnabledOnDetailMenu());
   EXPECT_FALSE(IsStickyKeysEnabledOnDetailMenu());
-  EXPECT_FALSE(IsTapDraggingEnabledOnDetailMenu());
   CloseDetailMenu();
 
   // Enabling large cursor.
@@ -1255,7 +1182,6 @@
   EXPECT_FALSE(IsHighlightMouseCursorEnabledOnDetailMenu());
   EXPECT_FALSE(IsHighlightKeyboardFocusEnabledOnDetailMenu());
   EXPECT_FALSE(IsStickyKeysEnabledOnDetailMenu());
-  EXPECT_FALSE(IsTapDraggingEnabledOnDetailMenu());
   CloseDetailMenu();
 
   // Disabling large cursor.
@@ -1273,7 +1199,6 @@
   EXPECT_FALSE(IsHighlightMouseCursorEnabledOnDetailMenu());
   EXPECT_FALSE(IsHighlightKeyboardFocusEnabledOnDetailMenu());
   EXPECT_FALSE(IsStickyKeysEnabledOnDetailMenu());
-  EXPECT_FALSE(IsTapDraggingEnabledOnDetailMenu());
   CloseDetailMenu();
 
   // Enable on-screen keyboard.
@@ -1291,7 +1216,6 @@
   EXPECT_FALSE(IsHighlightMouseCursorEnabledOnDetailMenu());
   EXPECT_FALSE(IsHighlightKeyboardFocusEnabledOnDetailMenu());
   EXPECT_FALSE(IsStickyKeysEnabledOnDetailMenu());
-  EXPECT_FALSE(IsTapDraggingEnabledOnDetailMenu());
   CloseDetailMenu();
 
   // Disable on-screen keyboard.
@@ -1309,7 +1233,6 @@
   EXPECT_FALSE(IsHighlightMouseCursorEnabledOnDetailMenu());
   EXPECT_FALSE(IsHighlightKeyboardFocusEnabledOnDetailMenu());
   EXPECT_FALSE(IsStickyKeysEnabledOnDetailMenu());
-  EXPECT_FALSE(IsTapDraggingEnabledOnDetailMenu());
   CloseDetailMenu();
 
   // Enabling mono audio.
@@ -1327,7 +1250,6 @@
   EXPECT_FALSE(IsHighlightMouseCursorEnabledOnDetailMenu());
   EXPECT_FALSE(IsHighlightKeyboardFocusEnabledOnDetailMenu());
   EXPECT_FALSE(IsStickyKeysEnabledOnDetailMenu());
-  EXPECT_FALSE(IsTapDraggingEnabledOnDetailMenu());
   CloseDetailMenu();
 
   // Disabling mono audio.
@@ -1345,7 +1267,6 @@
   EXPECT_FALSE(IsHighlightMouseCursorEnabledOnDetailMenu());
   EXPECT_FALSE(IsHighlightKeyboardFocusEnabledOnDetailMenu());
   EXPECT_FALSE(IsStickyKeysEnabledOnDetailMenu());
-  EXPECT_FALSE(IsTapDraggingEnabledOnDetailMenu());
   CloseDetailMenu();
 
   // Enabling caret highlight.
@@ -1363,7 +1284,6 @@
   EXPECT_FALSE(IsHighlightMouseCursorEnabledOnDetailMenu());
   EXPECT_FALSE(IsHighlightKeyboardFocusEnabledOnDetailMenu());
   EXPECT_FALSE(IsStickyKeysEnabledOnDetailMenu());
-  EXPECT_FALSE(IsTapDraggingEnabledOnDetailMenu());
   CloseDetailMenu();
 
   // Disabling caret highlight.
@@ -1381,7 +1301,6 @@
   EXPECT_FALSE(IsHighlightMouseCursorEnabledOnDetailMenu());
   EXPECT_FALSE(IsHighlightKeyboardFocusEnabledOnDetailMenu());
   EXPECT_FALSE(IsStickyKeysEnabledOnDetailMenu());
-  EXPECT_FALSE(IsTapDraggingEnabledOnDetailMenu());
   CloseDetailMenu();
 
   // Enabling highlight mouse cursor.
@@ -1399,7 +1318,6 @@
   EXPECT_TRUE(IsHighlightMouseCursorEnabledOnDetailMenu());
   EXPECT_FALSE(IsHighlightKeyboardFocusEnabledOnDetailMenu());
   EXPECT_FALSE(IsStickyKeysEnabledOnDetailMenu());
-  EXPECT_FALSE(IsTapDraggingEnabledOnDetailMenu());
   CloseDetailMenu();
 
   // Disabling highlight mouse cursor.
@@ -1417,7 +1335,6 @@
   EXPECT_FALSE(IsHighlightMouseCursorEnabledOnDetailMenu());
   EXPECT_FALSE(IsHighlightKeyboardFocusEnabledOnDetailMenu());
   EXPECT_FALSE(IsStickyKeysEnabledOnDetailMenu());
-  EXPECT_FALSE(IsTapDraggingEnabledOnDetailMenu());
   CloseDetailMenu();
 
   // Enabling highlight keyboard focus.
@@ -1435,7 +1352,6 @@
   EXPECT_FALSE(IsHighlightMouseCursorEnabledOnDetailMenu());
   EXPECT_TRUE(IsHighlightKeyboardFocusEnabledOnDetailMenu());
   EXPECT_FALSE(IsStickyKeysEnabledOnDetailMenu());
-  EXPECT_FALSE(IsTapDraggingEnabledOnDetailMenu());
   CloseDetailMenu();
 
   // Disabling highlight keyboard focus.
@@ -1453,7 +1369,6 @@
   EXPECT_FALSE(IsHighlightMouseCursorEnabledOnDetailMenu());
   EXPECT_FALSE(IsHighlightKeyboardFocusEnabledOnDetailMenu());
   EXPECT_FALSE(IsStickyKeysEnabledOnDetailMenu());
-  EXPECT_FALSE(IsTapDraggingEnabledOnDetailMenu());
   CloseDetailMenu();
 
   // Enabling sticky keys.
@@ -1471,7 +1386,6 @@
   EXPECT_FALSE(IsHighlightMouseCursorEnabledOnDetailMenu());
   EXPECT_FALSE(IsHighlightKeyboardFocusEnabledOnDetailMenu());
   EXPECT_TRUE(IsStickyKeysEnabledOnDetailMenu());
-  EXPECT_FALSE(IsTapDraggingEnabledOnDetailMenu());
   CloseDetailMenu();
 
   // Disabling sticky keys.
@@ -1489,43 +1403,6 @@
   EXPECT_FALSE(IsHighlightMouseCursorEnabledOnDetailMenu());
   EXPECT_FALSE(IsHighlightKeyboardFocusEnabledOnDetailMenu());
   EXPECT_FALSE(IsStickyKeysEnabledOnDetailMenu());
-  EXPECT_FALSE(IsTapDraggingEnabledOnDetailMenu());
-  CloseDetailMenu();
-
-  // Enabling tap dragging.
-  EnableTapDragging(true);
-  EXPECT_TRUE(CreateDetailedMenu());
-  EXPECT_FALSE(IsSpokenFeedbackEnabledOnDetailMenu());
-  EXPECT_FALSE(IsSelectToSpeakEnabledOnDetailMenu());
-  EXPECT_FALSE(IsHighContrastEnabledOnDetailMenu());
-  EXPECT_FALSE(IsScreenMagnifierEnabledOnDetailMenu());
-  EXPECT_FALSE(IsLargeCursorEnabledOnDetailMenu());
-  EXPECT_FALSE(IsAutoclickEnabledOnDetailMenu());
-  EXPECT_FALSE(IsVirtualKeyboardEnabledOnDetailMenu());
-  EXPECT_FALSE(IsMonoAudioEnabledOnDetailMenu());
-  EXPECT_FALSE(IsCaretHighlightEnabledOnDetailMenu());
-  EXPECT_FALSE(IsHighlightMouseCursorEnabledOnDetailMenu());
-  EXPECT_FALSE(IsHighlightKeyboardFocusEnabledOnDetailMenu());
-  EXPECT_FALSE(IsStickyKeysEnabledOnDetailMenu());
-  EXPECT_TRUE(IsTapDraggingEnabledOnDetailMenu());
-  CloseDetailMenu();
-
-  // Disabling tap dragging.
-  EnableTapDragging(false);
-  EXPECT_TRUE(CreateDetailedMenu());
-  EXPECT_FALSE(IsSpokenFeedbackEnabledOnDetailMenu());
-  EXPECT_FALSE(IsSelectToSpeakEnabledOnDetailMenu());
-  EXPECT_FALSE(IsHighContrastEnabledOnDetailMenu());
-  EXPECT_FALSE(IsScreenMagnifierEnabledOnDetailMenu());
-  EXPECT_FALSE(IsLargeCursorEnabledOnDetailMenu());
-  EXPECT_FALSE(IsAutoclickEnabledOnDetailMenu());
-  EXPECT_FALSE(IsVirtualKeyboardEnabledOnDetailMenu());
-  EXPECT_FALSE(IsMonoAudioEnabledOnDetailMenu());
-  EXPECT_FALSE(IsCaretHighlightEnabledOnDetailMenu());
-  EXPECT_FALSE(IsHighlightMouseCursorEnabledOnDetailMenu());
-  EXPECT_FALSE(IsHighlightKeyboardFocusEnabledOnDetailMenu());
-  EXPECT_FALSE(IsStickyKeysEnabledOnDetailMenu());
-  EXPECT_FALSE(IsTapDraggingEnabledOnDetailMenu());
   CloseDetailMenu();
 
   // Enabling all of the a11y features.
@@ -1540,7 +1417,6 @@
   SetCursorHighlightEnabled(true);
   SetFocusHighlightEnabled(true);
   EnableStickyKeys(true);
-  EnableTapDragging(true);
   EXPECT_TRUE(CreateDetailedMenu());
   EXPECT_TRUE(IsSpokenFeedbackEnabledOnDetailMenu());
   EXPECT_TRUE(IsHighContrastEnabledOnDetailMenu());
@@ -1554,7 +1430,6 @@
   // Focus highlighting can't be on when spoken feedback is on
   EXPECT_FALSE(IsHighlightKeyboardFocusEnabledOnDetailMenu());
   EXPECT_TRUE(IsStickyKeysEnabledOnDetailMenu());
-  EXPECT_TRUE(IsTapDraggingEnabledOnDetailMenu());
   CloseDetailMenu();
 
   // Disabling all of the a11y features.
@@ -1569,7 +1444,6 @@
   SetCursorHighlightEnabled(false);
   SetFocusHighlightEnabled(false);
   EnableStickyKeys(false);
-  EnableTapDragging(false);
   EXPECT_TRUE(CreateDetailedMenu());
   EXPECT_FALSE(IsSpokenFeedbackEnabledOnDetailMenu());
   EXPECT_FALSE(IsHighContrastEnabledOnDetailMenu());
@@ -1582,7 +1456,6 @@
   EXPECT_FALSE(IsHighlightMouseCursorEnabledOnDetailMenu());
   EXPECT_FALSE(IsHighlightKeyboardFocusEnabledOnDetailMenu());
   EXPECT_FALSE(IsStickyKeysEnabledOnDetailMenu());
-  EXPECT_FALSE(IsTapDraggingEnabledOnDetailMenu());
   CloseDetailMenu();
 
   // Enabling autoclick.
@@ -1600,7 +1473,6 @@
   EXPECT_FALSE(IsHighlightMouseCursorEnabledOnDetailMenu());
   EXPECT_FALSE(IsHighlightKeyboardFocusEnabledOnDetailMenu());
   EXPECT_FALSE(IsStickyKeysEnabledOnDetailMenu());
-  EXPECT_FALSE(IsTapDraggingEnabledOnDetailMenu());
   CloseDetailMenu();
 
   // Disabling autoclick.
@@ -1618,7 +1490,6 @@
   EXPECT_FALSE(IsHighlightMouseCursorEnabledOnDetailMenu());
   EXPECT_FALSE(IsHighlightKeyboardFocusEnabledOnDetailMenu());
   EXPECT_FALSE(IsStickyKeysEnabledOnDetailMenu());
-  EXPECT_FALSE(IsTapDraggingEnabledOnDetailMenu());
   CloseDetailMenu();
 }
 
diff --git a/chrome/browser/conflicts/module_list_filter_win.cc b/chrome/browser/conflicts/module_list_filter_win.cc
index 220c4f8..4c605bd 100644
--- a/chrome/browser/conflicts/module_list_filter_win.cc
+++ b/chrome/browser/conflicts/module_list_filter_win.cc
@@ -6,12 +6,10 @@
 
 #include <string>
 
-#include "base/base_paths.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/i18n/case_conversion.h"
 #include "base/logging.h"
-#include "base/path_service.h"
 #include "base/sha1.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
@@ -63,15 +61,10 @@
 bool ModuleListFilter::Initialize(const base::FilePath& module_list_path) {
   DCHECK(!initialized_);
 
-  base::FilePath exe_path;
   std::string contents;
-  initialized_ = base::PathService::Get(base::FILE_EXE, &exe_path) &&
-                 base::ReadFileToString(module_list_path, &contents) &&
+  initialized_ = base::ReadFileToString(module_list_path, &contents) &&
                  module_list_.ParseFromString(contents);
 
-  if (initialized_)
-    GetCertificateInfo(exe_path, &exe_certificate_info_);
-
   return initialized_;
 }
 
@@ -100,15 +93,6 @@
                                 const ModuleInfoData& module_data) const {
   DCHECK(initialized_);
 
-  // Ignore modules whose signing cert's Subject field matches the one in the
-  // current executable. No attempt is made to check the validity of module
-  // signatures or of signing certs.
-  if (exe_certificate_info_.type != CertificateType::NO_CERTIFICATE &&
-      exe_certificate_info_.subject ==
-          module_data.inspection_result->certificate_info.subject) {
-    return nullptr;
-  }
-
   // Precompute the hash of the basename and of the code id.
   const std::string module_basename_hash =
       base::SHA1HashString(base::UTF16ToUTF8(
diff --git a/chrome/browser/conflicts/module_list_filter_win.h b/chrome/browser/conflicts/module_list_filter_win.h
index 9f26f99..cf640b3 100644
--- a/chrome/browser/conflicts/module_list_filter_win.h
+++ b/chrome/browser/conflicts/module_list_filter_win.h
@@ -8,7 +8,6 @@
 #include <memory>
 
 #include "base/macros.h"
-#include "chrome/browser/conflicts/module_info_util_win.h"
 #include "chrome/browser/conflicts/proto/module_list.pb.h"
 
 struct ModuleInfoKey;
@@ -50,9 +49,6 @@
       const ModuleInfoData& module_data) const;
 
  private:
-  // The certificate info of the current executable.
-  CertificateInfo exe_certificate_info_;
-
   chrome::conflicts::ModuleList module_list_;
 
   // Indicates if Initalize() has been succesfully called.
diff --git a/chrome/browser/conflicts/problematic_programs_updater_win.cc b/chrome/browser/conflicts/problematic_programs_updater_win.cc
index 805b2413..22c7d8f0 100644
--- a/chrome/browser/conflicts/problematic_programs_updater_win.cc
+++ b/chrome/browser/conflicts/problematic_programs_updater_win.cc
@@ -15,6 +15,7 @@
 #include "base/win/registry.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/conflicts/module_database_win.h"
+#include "chrome/browser/conflicts/module_info_util_win.h"
 #include "chrome/browser/conflicts/module_list_filter_win.h"
 #include "chrome/browser/conflicts/third_party_metrics_recorder_win.h"
 #include "chrome/common/pref_names.h"
@@ -159,9 +160,11 @@
 // ProblematicProgramsUpdater --------------------------------------------------
 
 ProblematicProgramsUpdater::ProblematicProgramsUpdater(
+    const CertificateInfo& exe_certificate_info,
     const ModuleListFilter& module_list_filter,
     const InstalledPrograms& installed_programs)
-    : module_list_filter_(module_list_filter),
+    : exe_certificate_info_(exe_certificate_info),
+      module_list_filter_(module_list_filter),
       installed_programs_(installed_programs) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 }
@@ -212,7 +215,16 @@
   if ((module_data.module_types & ModuleInfoData::kTypeLoadedModule) == 0)
     return;
 
-  // Skip explicitely whitelisted modules.
+  // Explicitly whitelist modules whose signing cert's Subject field matches the
+  // one in the current executable. No attempt is made to check the validity of
+  // module signatures or of signing certs.
+  if (exe_certificate_info_.type != CertificateType::NO_CERTIFICATE &&
+      exe_certificate_info_.subject ==
+          module_data.inspection_result->certificate_info.subject) {
+    return;
+  }
+
+  // Skip modules whitelisted by the Module List component.
   if (module_list_filter_.IsWhitelisted(module_key, module_data))
     return;
 
diff --git a/chrome/browser/conflicts/problematic_programs_updater_win.h b/chrome/browser/conflicts/problematic_programs_updater_win.h
index f0f579a..da7dd84 100644
--- a/chrome/browser/conflicts/problematic_programs_updater_win.h
+++ b/chrome/browser/conflicts/problematic_programs_updater_win.h
@@ -13,6 +13,7 @@
 #include "chrome/browser/conflicts/module_database_observer_win.h"
 #include "chrome/browser/conflicts/proto/module_list.pb.h"
 
+struct CertificateInfo;
 class ModuleListFilter;
 class PrefRegistrySimple;
 
@@ -37,9 +38,10 @@
     std::unique_ptr<chrome::conflicts::BlacklistAction> blacklist_action;
   };
 
-  // Creates an instance of the updater. |module_list_filter| and
-  // |installed_programs| must outlive the lifetime of this class.
-  ProblematicProgramsUpdater(const ModuleListFilter& module_list_filter,
+  // Creates an instance of the updater.
+  // The parameters must outlive the lifetime of this class.
+  ProblematicProgramsUpdater(const CertificateInfo& exe_certificate_info,
+                             const ModuleListFilter& module_list_filter,
                              const InstalledPrograms& installed_programs);
   ~ProblematicProgramsUpdater() override;
 
@@ -63,6 +65,8 @@
   void OnModuleDatabaseIdle() override;
 
  private:
+  const CertificateInfo& exe_certificate_info_;
+
   const ModuleListFilter& module_list_filter_;
 
   const InstalledPrograms& installed_programs_;
diff --git a/chrome/browser/conflicts/problematic_programs_updater_win_unittest.cc b/chrome/browser/conflicts/problematic_programs_updater_win_unittest.cc
index 719aeaf3..38977949 100644
--- a/chrome/browser/conflicts/problematic_programs_updater_win_unittest.cc
+++ b/chrome/browser/conflicts/problematic_programs_updater_win_unittest.cc
@@ -72,16 +72,34 @@
   DISALLOW_COPY_AND_ASSIGN(MockInstalledPrograms);
 };
 
+constexpr wchar_t kCertificatePath[] = L"CertificatePath";
+constexpr wchar_t kCertificateSubject[] = L"CertificateSubject";
+
+constexpr wchar_t kDllPath1[] = L"c:\\path\\to\\module.dll";
+constexpr wchar_t kDllPath2[] = L"c:\\some\\shellextension.dll";
+
 // Returns a new ModuleInfoData marked as loaded into the process but otherwise
 // empty.
 ModuleInfoData CreateLoadedModuleInfoData() {
   ModuleInfoData module_data;
   module_data.module_types |= ModuleInfoData::kTypeLoadedModule;
+  module_data.inspection_result = std::make_unique<ModuleInspectionResult>();
   return module_data;
 }
 
-constexpr wchar_t kDllPath1[] = L"c:\\path\\to\\module.dll";
-constexpr wchar_t kDllPath2[] = L"c:\\some\\shellextension.dll";
+// Returns a new ModuleInfoData marked as loaded into the process with a
+// CertificateInfo that matches kCertificateSubject.
+ModuleInfoData CreateSignedLoadedModuleInfoData() {
+  ModuleInfoData module_data = CreateLoadedModuleInfoData();
+
+  module_data.inspection_result->certificate_info.type =
+      CertificateType::CERTIFICATE_IN_FILE;
+  module_data.inspection_result->certificate_info.path =
+      base::FilePath(kCertificatePath);
+  module_data.inspection_result->certificate_info.subject = kCertificateSubject;
+
+  return module_data;
+}
 
 }  // namespace
 
@@ -90,7 +108,11 @@
   ProblematicProgramsUpdaterTest()
       : dll1_(kDllPath1),
         dll2_(kDllPath2),
-        scoped_testing_local_state_(TestingBrowserProcess::GetGlobal()) {}
+        scoped_testing_local_state_(TestingBrowserProcess::GetGlobal()) {
+    exe_certificate_info_.type = CertificateType::CERTIFICATE_IN_FILE;
+    exe_certificate_info_.path = base::FilePath(kCertificatePath);
+    exe_certificate_info_.subject = kCertificateSubject;
+  }
 
   void SetUp() override {
     ASSERT_NO_FATAL_FAILURE(
@@ -120,6 +142,7 @@
     }
   }
 
+  CertificateInfo& exe_certificate_info() { return exe_certificate_info_; }
   MockModuleListFilter& module_list_filter() { return module_list_filter_; }
   MockInstalledPrograms& installed_programs() { return installed_programs_; }
 
@@ -131,6 +154,7 @@
   ScopedTestingLocalState scoped_testing_local_state_;
   registry_util::RegistryOverrideManager registry_override_manager_;
 
+  CertificateInfo exe_certificate_info_;
   MockModuleListFilter module_list_filter_;
   MockInstalledPrograms installed_programs_;
 
@@ -148,8 +172,8 @@
 // installed programs.
 TEST_F(ProblematicProgramsUpdaterTest, NoProblematicPrograms) {
   auto problematic_programs_updater =
-      std::make_unique<ProblematicProgramsUpdater>(module_list_filter(),
-                                                   installed_programs());
+      std::make_unique<ProblematicProgramsUpdater>(
+          exe_certificate_info(), module_list_filter(), installed_programs());
 
   // Simulate some arbitrary module loading into the process.
   problematic_programs_updater->OnNewModuleFound(ModuleInfoKey(dll1_, 0, 0, 0),
@@ -164,8 +188,8 @@
   AddProblematicProgram(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY);
 
   auto problematic_programs_updater =
-      std::make_unique<ProblematicProgramsUpdater>(module_list_filter(),
-                                                   installed_programs());
+      std::make_unique<ProblematicProgramsUpdater>(
+          exe_certificate_info(), module_list_filter(), installed_programs());
 
   // Simulate the module loading into the process.
   problematic_programs_updater->OnNewModuleFound(ModuleInfoKey(dll1_, 0, 0, 0),
@@ -183,8 +207,8 @@
   AddProblematicProgram(dll2_, L"Bar", Option::ADD_REGISTRY_ENTRY);
 
   auto problematic_programs_updater =
-      std::make_unique<ProblematicProgramsUpdater>(module_list_filter(),
-                                                   installed_programs());
+      std::make_unique<ProblematicProgramsUpdater>(
+          exe_certificate_info(), module_list_filter(), installed_programs());
 
   // Simulate the module loading into the process.
   problematic_programs_updater->OnNewModuleFound(ModuleInfoKey(dll1_, 0, 0, 0),
@@ -211,8 +235,8 @@
   AddProblematicProgram(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY);
 
   auto problematic_programs_updater =
-      std::make_unique<ProblematicProgramsUpdater>(module_list_filter(),
-                                                   installed_programs());
+      std::make_unique<ProblematicProgramsUpdater>(
+          exe_certificate_info(), module_list_filter(), installed_programs());
 
   // Simulate the module loading into the process.
   problematic_programs_updater->OnNewModuleFound(ModuleInfoKey(dll1_, 0, 0, 0),
@@ -233,8 +257,8 @@
   AddProblematicProgram(dll2_, L"Bar", Option::NO_REGISTRY_ENTRY);
 
   auto problematic_programs_updater =
-      std::make_unique<ProblematicProgramsUpdater>(module_list_filter(),
-                                                   installed_programs());
+      std::make_unique<ProblematicProgramsUpdater>(
+          exe_certificate_info(), module_list_filter(), installed_programs());
 
   // Simulate the modules loading into the process.
   problematic_programs_updater->OnNewModuleFound(ModuleInfoKey(dll1_, 0, 0, 0),
@@ -248,3 +272,21 @@
   ASSERT_EQ(1u, program_names.size());
   EXPECT_EQ(L"Foo", program_names[0].info.name);
 }
+
+// Tests that modules with a matching certificate subject are whitelisted.
+TEST_F(ProblematicProgramsUpdaterTest, WhitelistMatchingCertificateSubject) {
+  AddProblematicProgram(dll1_, L"Foo", Option::ADD_REGISTRY_ENTRY);
+
+  auto problematic_programs_updater =
+      std::make_unique<ProblematicProgramsUpdater>(
+          exe_certificate_info(), module_list_filter(), installed_programs());
+
+  // Simulate the module loading into the process.
+  problematic_programs_updater->OnNewModuleFound(
+      ModuleInfoKey(dll1_, 0, 0, 0), CreateSignedLoadedModuleInfoData());
+  problematic_programs_updater->OnModuleDatabaseIdle();
+
+  EXPECT_FALSE(ProblematicProgramsUpdater::HasCachedPrograms());
+  auto program_names = ProblematicProgramsUpdater::GetCachedPrograms();
+  ASSERT_EQ(0u, program_names.size());
+}
diff --git a/chrome/browser/conflicts/third_party_conflicts_manager_win.cc b/chrome/browser/conflicts/third_party_conflicts_manager_win.cc
index 08b85293..90b39dd 100644
--- a/chrome/browser/conflicts/third_party_conflicts_manager_win.cc
+++ b/chrome/browser/conflicts/third_party_conflicts_manager_win.cc
@@ -6,16 +6,29 @@
 
 #include <utility>
 
+#include "base/base_paths.h"
 #include "base/bind.h"
 #include "base/location.h"
+#include "base/path_service.h"
 #include "base/task_scheduler/post_task.h"
 #include "chrome/browser/conflicts/installed_programs_win.h"
 #include "chrome/browser/conflicts/module_database_win.h"
+#include "chrome/browser/conflicts/module_info_util_win.h"
 #include "chrome/browser/conflicts/module_list_filter_win.h"
 #include "chrome/browser/conflicts/problematic_programs_updater_win.h"
 
 namespace {
 
+std::unique_ptr<CertificateInfo> CreateExeCertificateInfo() {
+  auto certificate_info = std::make_unique<CertificateInfo>();
+
+  base::FilePath exe_path;
+  if (base::PathService::Get(base::FILE_EXE, &exe_path))
+    GetCertificateInfo(exe_path, certificate_info.get());
+
+  return certificate_info;
+}
+
 std::unique_ptr<ModuleListFilter> CreateModuleListFilter(
     const base::FilePath& module_list_path) {
   auto module_list_filter = std::make_unique<ModuleListFilter>();
@@ -33,7 +46,15 @@
     : module_database_(module_database),
       module_list_received_(false),
       on_module_database_idle_called_(false),
-      weak_ptr_factory_(this) {}
+      weak_ptr_factory_(this) {
+  base::PostTaskWithTraitsAndReplyWithResult(
+      FROM_HERE,
+      {base::MayBlock(), base::TaskPriority::BACKGROUND,
+       base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+      base::BindOnce(&CreateExeCertificateInfo),
+      base::BindOnce(&ThirdPartyConflictsManager::OnExeCertificateCreated,
+                     weak_ptr_factory_.GetWeakPtr()));
+}
 
 ThirdPartyConflictsManager::~ThirdPartyConflictsManager() = default;
 
@@ -67,6 +88,14 @@
                      weak_ptr_factory_.GetWeakPtr()));
 }
 
+void ThirdPartyConflictsManager::OnExeCertificateCreated(
+    std::unique_ptr<CertificateInfo> exe_certificate_info) {
+  exe_certificate_info_ = std::move(exe_certificate_info);
+
+  if (module_list_filter_ && installed_programs_)
+    InitializeProblematicProgramsUpdater();
+}
+
 void ThirdPartyConflictsManager::OnModuleListFilterCreated(
     std::unique_ptr<ModuleListFilter> module_list_filter) {
   module_list_filter_ = std::move(module_list_filter);
@@ -82,7 +111,7 @@
     return;
   }
 
-  if (installed_programs_)
+  if (exe_certificate_info_ && installed_programs_)
     InitializeProblematicProgramsUpdater();
 }
 
@@ -90,15 +119,16 @@
     std::unique_ptr<InstalledPrograms> installed_programs) {
   installed_programs_ = std::move(installed_programs);
 
-  if (module_list_filter_)
+  if (exe_certificate_info_ && module_list_filter_)
     InitializeProblematicProgramsUpdater();
 }
 
 void ThirdPartyConflictsManager::InitializeProblematicProgramsUpdater() {
+  DCHECK(exe_certificate_info_);
   DCHECK(module_list_filter_);
   DCHECK(installed_programs_);
 
   problematic_programs_updater_ = std::make_unique<ProblematicProgramsUpdater>(
-      *module_list_filter_, *installed_programs_);
+      *exe_certificate_info_, *module_list_filter_, *installed_programs_);
   module_database_->AddObserver(problematic_programs_updater_.get());
 }
diff --git a/chrome/browser/conflicts/third_party_conflicts_manager_win.h b/chrome/browser/conflicts/third_party_conflicts_manager_win.h
index cce21115..faec1a3 100644
--- a/chrome/browser/conflicts/third_party_conflicts_manager_win.h
+++ b/chrome/browser/conflicts/third_party_conflicts_manager_win.h
@@ -11,9 +11,10 @@
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/conflicts/module_database_observer_win.h"
 
+struct CertificateInfo;
+class InstalledPrograms;
 class ModuleDatabase;
 class ModuleListFilter;
-class InstalledPrograms;
 class ProblematicProgramsUpdater;
 
 namespace base {
@@ -34,15 +35,20 @@
   void LoadModuleList(const base::FilePath& path);
 
  private:
+  // Called when |exe_certificate_info_| finishes its initialization.
+  void OnExeCertificateCreated(
+      std::unique_ptr<CertificateInfo> exe_certificate_info);
+
   // Called when |module_list_filter_| finishes its initialization.
-  void OnModuleListFilterCreated(std::unique_ptr<ModuleListFilter>);
+  void OnModuleListFilterCreated(
+      std::unique_ptr<ModuleListFilter> module_list_filter);
 
   // Called when |installed_programs_| finishes its initialization.
   void OnInstalledProgramsCreated(
       std::unique_ptr<InstalledPrograms> installed_programs);
 
-  // Initializes |problematic_programs_updater_| when both the ModuleListFilter
-  // and the InstalledPrograms are available.
+  // Initializes |problematic_programs_updater_| when the exe_certificate_info_,
+  // the module_list_filter_ and the installed_programs_ are available.
   void InitializeProblematicProgramsUpdater();
 
   ModuleDatabase* module_database_;
@@ -56,6 +62,9 @@
   // instances.
   bool on_module_database_idle_called_;
 
+  // The certificate info of the current executable.
+  std::unique_ptr<CertificateInfo> exe_certificate_info_;
+
   // Filters third-party modules against a whitelist and a blacklist.
   std::unique_ptr<ModuleListFilter> module_list_filter_;
 
diff --git a/chrome/browser/conflicts/uninstall_application_win.cc b/chrome/browser/conflicts/uninstall_application_win.cc
index 9f6fa39..d1104362 100644
--- a/chrome/browser/conflicts/uninstall_application_win.cc
+++ b/chrome/browser/conflicts/uninstall_application_win.cc
@@ -20,6 +20,7 @@
 #include "base/single_thread_task_runner.h"
 #include "base/strings/pattern.h"
 #include "base/strings/string_util.h"
+#include "base/synchronization/lock.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/win/scoped_variant.h"
 #include "chrome/browser/win/automation_controller.h"
@@ -150,8 +151,10 @@
   // The task runner on which the UninstallAppController lives.
   scoped_refptr<base::SequencedTaskRunner> controller_runner_;
 
-  // Called once when the automation work is done. Only used by
-  // OnFocusChangedEvent().
+  // Protect against concurrent accesses to |on_automation_finished_|.
+  mutable base::Lock on_automation_finished_lock_;
+
+  // Called once when the automation work is done.
   mutable base::OnceClosure on_automation_finished_;
 
   const base::string16 application_name_;
@@ -194,9 +197,15 @@
 void UninstallAppController::AutomationControllerDelegate::OnFocusChangedEvent(
     IUIAutomation* automation,
     IUIAutomationElement* sender) const {
+  base::OnceClosure callback;
+  {
+    base::AutoLock auto_lock(on_automation_finished_lock_);
+    callback = std::move(on_automation_finished_);
+  }
+
   // This callback can be null if the application name was already written in
   // the search box and this instance is awaiting destruction.
-  if (!on_automation_finished_)
+  if (!callback)
     return;
 
   base::string16 combo_box_id(
@@ -217,7 +226,7 @@
   CComBSTR bstr(application_name_.c_str());
   value_pattern->SetValue(bstr);
 
-  controller_runner_->PostTask(FROM_HERE, std::move(on_automation_finished_));
+  controller_runner_->PostTask(FROM_HERE, std::move(callback));
 }
 
 }  // namespace
diff --git a/chrome/browser/devtools/devtools_sanity_browsertest.cc b/chrome/browser/devtools/devtools_sanity_browsertest.cc
index 879b0da..88b3bf3 100644
--- a/chrome/browser/devtools/devtools_sanity_browsertest.cc
+++ b/chrome/browser/devtools/devtools_sanity_browsertest.cc
@@ -2164,7 +2164,20 @@
 
 IN_PROC_BROWSER_TEST_F(SitePerProcessDevToolsSanityTest, InspectElement) {
   GURL url(embedded_test_server()->GetURL("a.com", "/devtools/oopif.html"));
-  ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(browser(), url, 2);
+  GURL iframe_url(
+      embedded_test_server()->GetURL("b.com", "/devtools/oopif_frame.html"));
+
+  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
+
+  content::TestNavigationManager navigation_manager(tab, url);
+  content::TestNavigationManager navigation_manager_iframe(tab, iframe_url);
+
+  tab->GetController().LoadURL(url, content::Referrer(),
+                               ui::PAGE_TRANSITION_LINK, std::string());
+
+  navigation_manager.WaitForNavigationFinished();
+  navigation_manager_iframe.WaitForNavigationFinished();
+  content::WaitForLoadStop(tab);
 
   std::vector<RenderFrameHost*> frames = GetInspectedTab()->GetAllFrames();
   ASSERT_EQ(2u, frames.size());
@@ -2185,7 +2198,21 @@
                        DISABLED_InputDispatchEventsToOOPIF) {
   GURL url(
       embedded_test_server()->GetURL("a.com", "/devtools/oopif-input.html"));
-  ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(browser(), url, 2);
+  GURL iframe_url(embedded_test_server()->GetURL(
+      "b.com", "/devtools/oopif-input-frame.html"));
+
+  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
+
+  content::TestNavigationManager navigation_manager(tab, url);
+  content::TestNavigationManager navigation_manager_iframe(tab, iframe_url);
+
+  tab->GetController().LoadURL(url, content::Referrer(),
+                               ui::PAGE_TRANSITION_LINK, std::string());
+
+  navigation_manager.WaitForNavigationFinished();
+  navigation_manager_iframe.WaitForNavigationFinished();
+  content::WaitForLoadStop(tab);
+
   for (auto* frame : GetInspectedTab()->GetAllFrames())
     content::WaitForChildFrameSurfaceReady(frame);
   DevToolsWindow* window =
diff --git a/chrome/browser/download/download_shelf_context_menu.cc b/chrome/browser/download/download_shelf_context_menu.cc
index a0e7a9a..d0139e5 100644
--- a/chrome/browser/download/download_shelf_context_menu.cc
+++ b/chrome/browser/download/download_shelf_context_menu.cc
@@ -17,6 +17,11 @@
 
 using download::DownloadItem;
 
+bool DownloadShelfContextMenu::WantsContextMenu(
+    const DownloadItemModel& download_model) {
+  return !download_model.IsDangerous() || download_model.MightBeMalicious();
+}
+
 DownloadShelfContextMenu::~DownloadShelfContextMenu() {
   DetachFromDownloadItem();
 }
@@ -35,9 +40,8 @@
     return NULL;
 
   DownloadItemModel download_model(download_item_);
-  // We shouldn't be opening a context menu for a dangerous download, unless it
-  // is a malicious download.
-  DCHECK(!download_model.IsDangerous() || download_model.MightBeMalicious());
+
+  DCHECK(WantsContextMenu(download_model));
 
   if (download_model.IsMalicious())
     model = GetMaliciousMenuModel();
diff --git a/chrome/browser/download/download_shelf_context_menu.h b/chrome/browser/download/download_shelf_context_menu.h
index fcb7a02..827b8eb6 100644
--- a/chrome/browser/download/download_shelf_context_menu.h
+++ b/chrome/browser/download/download_shelf_context_menu.h
@@ -15,6 +15,8 @@
 #include "components/download/public/common/download_item.h"
 #include "ui/base/models/simple_menu_model.h"
 
+class DownloadItemModel;
+
 // This class is responsible for the download shelf context menu. Platform
 // specific subclasses are responsible for creating and running the menu.
 //
@@ -23,6 +25,9 @@
 class DownloadShelfContextMenu : public ui::SimpleMenuModel::Delegate,
                                  public download::DownloadItem::Observer {
  public:
+  // Only show a context menu for a dangerous download if it is malicious.
+  static bool WantsContextMenu(const DownloadItemModel&);
+
   ~DownloadShelfContextMenu() override;
 
   download::DownloadItem* download_item() const { return download_item_; }
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn
index 9f5dd3df..6ccda19 100644
--- a/chrome/browser/extensions/BUILD.gn
+++ b/chrome/browser/extensions/BUILD.gn
@@ -870,7 +870,7 @@
     "//extensions/common/api",
     "//extensions/strings",
     "//google_apis",
-    "//media:media_features",
+    "//media:media_buildflags",
     "//net",
     "//ppapi/features",
     "//printing/features",
diff --git a/chrome/browser/extensions/api/automation/automation_apitest.cc b/chrome/browser/extensions/api/automation/automation_apitest.cc
index 614f8369..965b7118 100644
--- a/chrome/browser/extensions/api/automation/automation_apitest.cc
+++ b/chrome/browser/extensions/api/automation/automation_apitest.cc
@@ -120,13 +120,7 @@
       << message_;
 }
 
-// TODO(https://crbug.com/622387): Disabled due to flakiness.
-#if defined(OS_CHROMEOS) && defined(NDEBUG)
-#define MAYBE_Location DISABLED_Location
-#else
-#define MAYBE_Location Location
-#endif
-IN_PROC_BROWSER_TEST_F(AutomationApiTest, MAYBE_Location) {
+IN_PROC_BROWSER_TEST_F(AutomationApiTest, Location) {
   StartEmbeddedTestServer();
   ASSERT_TRUE(RunExtensionSubtest("automation/tests/tabs", "location.html"))
       << message_;
diff --git a/chrome/browser/extensions/api/automation_internal/automation_event_router.cc b/chrome/browser/extensions/api/automation_internal/automation_event_router.cc
index b87d67a8..6e46468 100644
--- a/chrome/browser/extensions/api/automation_internal/automation_event_router.cc
+++ b/chrome/browser/extensions/api/automation_internal/automation_event_router.cc
@@ -65,8 +65,11 @@
            true);
 }
 
-void AutomationEventRouter::DispatchAccessibilityEvent(
-    const ExtensionMsg_AccessibilityEventParams& params) {
+void AutomationEventRouter::DispatchAccessibilityEvents(
+    const std::vector<ExtensionMsg_AccessibilityEventParams>& events) {
+  if (events.empty())
+    return;
+
   if (active_profile_ != ProfileManager::GetActiveUserProfile()) {
     active_profile_ = ProfileManager::GetActiveUserProfile();
     UpdateActiveProfile();
@@ -75,14 +78,14 @@
   for (const auto& listener : listeners_) {
     // Skip listeners that don't want to listen to this tree.
     if (!listener.desktop &&
-        listener.tree_ids.find(params.tree_id) == listener.tree_ids.end()) {
+        listener.tree_ids.find(events[0].tree_id) == listener.tree_ids.end()) {
       continue;
     }
 
     content::RenderProcessHost* rph =
         content::RenderProcessHost::FromID(listener.process_id);
-    rph->Send(new ExtensionMsg_AccessibilityEvent(params,
-                                                  listener.is_active_profile));
+    rph->Send(new ExtensionMsg_AccessibilityEvents(events,
+                                                   listener.is_active_profile));
   }
 }
 
diff --git a/chrome/browser/extensions/api/automation_internal/automation_event_router.h b/chrome/browser/extensions/api/automation_internal/automation_event_router.h
index 6e9d14af..aee6e344 100644
--- a/chrome/browser/extensions/api/automation_internal/automation_event_router.h
+++ b/chrome/browser/extensions/api/automation_internal/automation_event_router.h
@@ -50,8 +50,8 @@
   void RegisterListenerWithDesktopPermission(const ExtensionId& extension_id,
                                              int listener_process_id);
 
-  void DispatchAccessibilityEvent(
-      const ExtensionMsg_AccessibilityEventParams& params);
+  void DispatchAccessibilityEvents(
+      const std::vector<ExtensionMsg_AccessibilityEventParams>& events);
 
   void DispatchAccessibilityLocationChange(
       const ExtensionMsg_AccessibilityLocationChangeParams& params);
diff --git a/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc b/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc
index 228f865..207f2e8 100644
--- a/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc
+++ b/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc
@@ -167,8 +167,10 @@
   void AccessibilityEventReceived(
       const std::vector<content::AXEventNotificationDetails>& details)
       override {
+    std::vector<ExtensionMsg_AccessibilityEventParams> events;
     for (const auto& event : details) {
-      ExtensionMsg_AccessibilityEventParams params;
+      events.emplace_back();
+      ExtensionMsg_AccessibilityEventParams& params = events.back();
       params.tree_id = event.ax_tree_id;
       params.id = event.id;
       params.event_type = event.event_type;
@@ -178,10 +180,9 @@
 #if defined(USE_AURA)
       params.mouse_location = aura::Env::GetInstance()->last_mouse_location();
 #endif
-
-      AutomationEventRouter* router = AutomationEventRouter::GetInstance();
-      router->DispatchAccessibilityEvent(params);
     }
+    AutomationEventRouter* router = AutomationEventRouter::GetInstance();
+    router->DispatchAccessibilityEvents(events);
   }
 
   void AccessibilityLocationChangesReceived(
diff --git a/chrome/browser/extensions/api/media_galleries/media_galleries_apitest.cc b/chrome/browser/extensions/api/media_galleries/media_galleries_apitest.cc
index b2acf5e8..39bdf5e 100644
--- a/chrome/browser/extensions/api/media_galleries/media_galleries_apitest.cc
+++ b/chrome/browser/extensions/api/media_galleries/media_galleries_apitest.cc
@@ -38,7 +38,7 @@
 #include "extensions/common/extension.h"
 #include "extensions/test/result_catcher.h"
 #include "media/base/test_data_util.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 #if defined(OS_MACOSX)
 #include "base/mac/foundation_util.h"
diff --git a/chrome/browser/extensions/api/preference/preference_api.cc b/chrome/browser/extensions/api/preference/preference_api.cc
index e6ce843..fe98bbb 100644
--- a/chrome/browser/extensions/api/preference/preference_api.cc
+++ b/chrome/browser/extensions/api/preference/preference_api.cc
@@ -47,7 +47,7 @@
 #include "extensions/common/error_utils.h"
 #include "extensions/common/permissions/api_permission.h"
 #include "extensions/common/permissions/permissions_data.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 #if defined(OS_CHROMEOS)
 #include "ash/public/cpp/ash_pref_names.h"  // nogncheck
diff --git a/chrome/browser/extensions/api/preference/preference_apitest.cc b/chrome/browser/extensions/api/preference/preference_apitest.cc
index 51d8980..17b0bfd 100644
--- a/chrome/browser/extensions/api/preference/preference_apitest.cc
+++ b/chrome/browser/extensions/api/preference/preference_apitest.cc
@@ -33,7 +33,7 @@
 #include "extensions/browser/test_extension_registry_observer.h"
 #include "extensions/test/extension_test_message_listener.h"
 #include "extensions/test/result_catcher.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 class ExtensionPreferenceApiTest : public ExtensionApiTest {
  protected:
diff --git a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.h b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.h
index f268a18..8d84c2c 100644
--- a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.h
+++ b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.h
@@ -9,7 +9,7 @@
 
 #include "chrome/browser/extensions/chrome_extension_function.h"
 #include "chrome/common/extensions/api/webrtc_logging_private.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 #if BUILDFLAG(ENABLE_WEBRTC)
 #include "chrome/browser/media/webrtc/audio_debug_recordings_handler.h"
diff --git a/chrome/browser/extensions/content_script_apitest.cc b/chrome/browser/extensions/content_script_apitest.cc
index f6f1960e..debbfe23 100644
--- a/chrome/browser/extensions/content_script_apitest.cc
+++ b/chrome/browser/extensions/content_script_apitest.cc
@@ -29,6 +29,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_delegate.h"
 #include "content/public/test/browser_test_utils.h"
+#include "extensions/browser/browsertest_util.h"
 #include "extensions/browser/notification_types.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_features.h"
@@ -675,4 +676,88 @@
       did_script_inject(browser()->tab_strip_model()->GetActiveWebContents()));
 }
 
+IN_PROC_BROWSER_TEST_F(ContentScriptApiTest, ContentScriptSameSiteCookies) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  const Extension* extension = LoadExtension(
+      test_data_dir_.AppendASCII("content_scripts/request_cookies"));
+  ASSERT_TRUE(extension);
+  GURL url = embedded_test_server()->GetURL("a.com", "/extensions/body1.html");
+  ResultCatcher catcher;
+  constexpr char kScript[] =
+      R"(chrome.tabs.create({url: '%s'}, () => {
+           let message = 'success';
+           if (chrome.runtime.lastError)
+             message = chrome.runtime.lastError.message;
+           domAutomationController.send(message);
+         });)";
+  std::string result = browsertest_util::ExecuteScriptInBackgroundPage(
+      profile(), extension->id(),
+      base::StringPrintf(kScript, url.spec().c_str()));
+
+  EXPECT_EQ("success", result);
+  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
+}
+
+IN_PROC_BROWSER_TEST_F(ContentScriptApiTest, ExecuteScriptFileSameSiteCookies) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  const Extension* extension = LoadExtension(
+      test_data_dir_.AppendASCII("content_scripts/request_cookies"));
+  ASSERT_TRUE(extension);
+  GURL url = embedded_test_server()->GetURL("b.com", "/extensions/body1.html");
+  ResultCatcher catcher;
+  constexpr char kScript[] =
+      R"(chrome.tabs.create({url: '%s'}, (tab) => {
+           if (chrome.runtime.lastError) {
+             domAutomationController.send(chrome.runtime.lastError.message);
+             return;
+           }
+           chrome.tabs.executeScript(tab.id, {file: 'cookies.js'}, () => {
+             let message = 'success';
+             if (chrome.runtime.lastError)
+               message = chrome.runtime.lastError.message;
+             domAutomationController.send(message);
+           });
+         });)";
+  std::string result = browsertest_util::ExecuteScriptInBackgroundPage(
+      profile(), extension->id(),
+      base::StringPrintf(kScript, url.spec().c_str()));
+
+  EXPECT_EQ("success", result);
+  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
+}
+
+IN_PROC_BROWSER_TEST_F(ContentScriptApiTest, ExecuteScriptCodeSameSiteCookies) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
+  const Extension* extension = LoadExtension(
+      test_data_dir_.AppendASCII("content_scripts/request_cookies"));
+  ASSERT_TRUE(extension);
+  GURL url = embedded_test_server()->GetURL("b.com", "/extensions/body1.html");
+  ResultCatcher catcher;
+  constexpr char kScript[] =
+      R"(chrome.tabs.create({url: '%s'}, (tab) => {
+           if (chrome.runtime.lastError) {
+             domAutomationController.send(chrome.runtime.lastError.message);
+             return;
+           }
+           fetch(chrome.runtime.getURL('cookies.js')).then((response) => {
+             return response.text();
+           }).then((text) => {
+             chrome.tabs.executeScript(tab.id, {code: text}, () => {
+               let message = 'success';
+               if (chrome.runtime.lastError)
+                 message = chrome.runtime.lastError.message;
+               domAutomationController.send(message);
+             });
+           }).catch((e) => {
+             domAutomationController.send(e);
+           });
+         });)";
+  std::string result = browsertest_util::ExecuteScriptInBackgroundPage(
+      profile(), extension->id(),
+      base::StringPrintf(kScript, url.spec().c_str()));
+
+  EXPECT_EQ("success", result);
+  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/extensions/content_verifier_browsertest.cc b/chrome/browser/extensions/content_verifier_browsertest.cc
index ea1fedab..092ea7c5 100644
--- a/chrome/browser/extensions/content_verifier_browsertest.cc
+++ b/chrome/browser/extensions/content_verifier_browsertest.cc
@@ -264,7 +264,7 @@
   job_observer.ExpectJobResult(id, base::FilePath(FILE_PATH_LITERAL("cs2.js")),
                                Result::SUCCESS);
 
-  VerifierObserver verifier_observer;
+  auto verifier_observer = std::make_unique<VerifierObserver>();
 
   // Install a test extension we copied from the webstore that has actual
   // signatures, and contains paths with a leading "./" in various places.
@@ -277,8 +277,14 @@
   // The content scripts might fail verification the first time since the
   // one-time processing might not be finished yet - if that's the case then
   // we want to wait until that work is done.
-  if (!base::ContainsKey(verifier_observer.completed_fetches(), id))
-    verifier_observer.WaitForFetchComplete(id);
+  if (!base::ContainsKey(verifier_observer->completed_fetches(), id))
+    verifier_observer->WaitForFetchComplete(id);
+
+  // It is important to destroy |verifier_observer| here so that it doesn't see
+  // any fetch from EnableExtension call below (the observer pointer in
+  // content_verifier.cc isn't thread safe, so it might asynchronously call
+  // OnFetchComplete after this test's body executes).
+  verifier_observer.reset();
 
   // Now disable/re-enable the extension to cause the content scripts to be
   // read again.
diff --git a/chrome/browser/extensions/menu_manager.cc b/chrome/browser/extensions/menu_manager.cc
index fa08eac9..57fc8e5d 100644
--- a/chrome/browser/extensions/menu_manager.cc
+++ b/chrome/browser/extensions/menu_manager.cc
@@ -798,16 +798,12 @@
   MenuItem* menu_item = GetItemById(id);
   DCHECK(menu_item);
 
-  const extensions::MenuItem::OwnedList* list;
-  if (menu_item->parent_id()) {
-    list = &(GetItemById(*menu_item->parent_id())->children());
-  } else {
+  if (!menu_item->parent_id()) {
     auto i = context_items_.find(menu_item->id().extension_key);
     if (i == context_items_.end()) {
       NOTREACHED();
       return false;
     }
-    list = &(i->second);
   }
 
   // If we selected a radio item, unselect all other items in its group.
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index cc6052d..a3480e2 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -264,6 +264,11 @@
 const char kEnableAutofillCreditCardAblationExperimentDescription[] =
     "If enabled, credit card autofill suggestions will not display.";
 
+const char kEnableAutofillCreditCardBankNameDisplayName[] =
+    "Display the issuer bank name of a credit card in autofill.";
+const char kEnableAutofillCreditCardBankNameDisplayDescription[] =
+    "If enabled, displays the issuer bank name of a credit card in autofill.";
+
 const char kEnableAutofillCreditCardLastUsedDateDisplayName[] =
     "Display the last used date of a credit card in autofill.";
 const char kEnableAutofillCreditCardLastUsedDateDisplayDescription[] =
@@ -955,6 +960,10 @@
 const char kNewUsbBackendDescription[] =
     "Enables the new experimental USB backend for Windows.";
 
+const char kNewblueName[] = "Newblue";
+const char kNewblueDescription[] =
+    "Enables the use of newblue Bluetooth daemon.";
+
 const char kNostatePrefetchName[] = "No-State Prefetch";
 const char kNostatePrefetchDescription[] =
     R"*("No-State Prefetch" pre-downloads resources to improve load )*"
@@ -1335,7 +1344,8 @@
 
 const char kShowAutofillSignaturesName[] = "Show autofill signatures.";
 const char kShowAutofillSignaturesDescription[] =
-    "Annotates web forms with Autofill signatures as HTML attributes.";
+    "Annotates web forms with Autofill signatures as HTML attributes. Also "
+    "marks password fields suitable for password generation.";
 
 const char kShowAutofillTypePredictionsName[] = "Show Autofill predictions";
 const char kShowAutofillTypePredictionsDescription[] =
@@ -1613,6 +1623,14 @@
 const char kUseModernMediaControlsDescription[] =
     "Enables the new style native media controls.";
 
+const char kUsePdfCompositorServiceName[] =
+    "Use PDF compositor service for printing";
+const char kUsePdfCompositorServiceDescription[] =
+    "When enabled, use PDF compositor service to composite and generate PDF "
+    "files for printing. When site isolation is enabled, disabling this will "
+    "not stop using PDF compositor service since the service is required for "
+    "printing out-of-process iframes correctly.";
+
 const char kUserActivationV2Name[] = "User Activation v2";
 const char kUserActivationV2Description[] =
     "Enable simple user activation for APIs that are otherwise controlled by "
@@ -1656,6 +1674,11 @@
     "Enter/exit fullscreen when device is rotated to/from the orientation of "
     "the video. Only on phones.";
 
+const char kViewsBrowserWindowsName[] =
+    "Use Views browser windows instead of Cocoa.";
+const char kViewsBrowserWindowsDescription[] =
+    "Use Views browser windows instead of Cocoa, aka MacViews-Browser.";
+
 const char kWalletServiceUseSandboxName[] =
     "Use Google Payments sandbox servers";
 const char kWalletServiceUseSandboxDescription[] =
@@ -2140,6 +2163,12 @@
     "Enables pending download status text in notifications and Downloads Home "
     "to state the reason the request is pending.";
 
+const char kOfflinePagesInDownloadHomeOpenInCctName[] =
+    "Enables offline pages in the downloads home to be opened in CCT.";
+const char kOfflinePagesInDownloadHomeOpenInCctDescription[] =
+    "When enabled offline pages launched from the Downloads Home will be "
+    "opened in Chrome Custom Tabs (CCT) instead of regular tabs.";
+
 const char kOfflinePagesPrefetchingName[] =
     "Enables suggested offline pages to be prefetched.";
 const char kOfflinePagesPrefetchingDescription[] =
@@ -2402,12 +2431,12 @@
     "If enabled, Chrome will draw the titlebar and caption buttons instead of "
     "deferring to Windows.";
 
-#if DCHECK_IS_ON() && defined(SYZYASAN)
-const char kSyzyAsanDcheckIsFatalName[] = "DCHECKs are fatal";
-const char kSyzyAsanDcheckIsFatalDescription[] =
-    "By default Chrome will evaluate DCHECKs in SyzyASAN builds, but only log "
-    "failed DCHECKs. If enabled, DCHECKs will crash the calling process.";
-#endif  // DCHECK_IS_ON() && defined(SYZYASAN)
+#if DCHECK_IS_CONFIGURABLE
+const char kDcheckIsFatalName[] = "DCHECKs are fatal";
+const char kDcheckIsFatalDescription[] =
+    "By default Chrome will evaluate DCHECKs in some Canary builds, but only "
+    "log failed DCHECKs. If enabled, DCHECKs will crash the calling process.";
+#endif  // DCHECK_IS_CONFIGURABLE
 
 #endif  // defined(OS_WIN)
 
@@ -2882,10 +2911,6 @@
 
 #if defined(OS_ANDROID)
 
-const char kVrBrowsingName[] = "VR browsing";
-const char kVrBrowsingDescription[] =
-    "Browsing within a VR headset if available for this device.";
-
 const char kVrBrowserKeyboardName[] = "Chrome VR virtual keyboard.";
 const char kVrBrowserKeyboardDescription[] =
     "Enable a virtual keyboard for Chrome VR.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index c6cb413b..95d3d5e 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -12,7 +12,7 @@
 #include "chrome/common/buildflags.h"
 #include "components/nacl/common/buildflags.h"
 #include "device/vr/buildflags/buildflags.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 // This file declares strings used in chrome://flags. These messages are not
 // translated, because instead of end-users they target Chromium developers and
@@ -194,6 +194,9 @@
 extern const char kEnableAutofillCreditCardAblationExperimentDisplayName[];
 extern const char kEnableAutofillCreditCardAblationExperimentDescription[];
 
+extern const char kEnableAutofillCreditCardBankNameDisplayName[];
+extern const char kEnableAutofillCreditCardBankNameDisplayDescription[];
+
 extern const char kEnableAutofillCreditCardLastUsedDateDisplayName[];
 extern const char kEnableAutofillCreditCardLastUsedDateDisplayDescription[];
 
@@ -603,6 +606,9 @@
 extern const char kNewUsbBackendName[];
 extern const char kNewUsbBackendDescription[];
 
+extern const char kNewblueName[];
+extern const char kNewblueDescription[];
+
 extern const char kNostatePrefetchName[];
 extern const char kNostatePrefetchDescription[];
 
@@ -986,6 +992,9 @@
 extern const char kUseModernMediaControlsName[];
 extern const char kUseModernMediaControlsDescription[];
 
+extern const char kUsePdfCompositorServiceName[];
+extern const char kUsePdfCompositorServiceDescription[];
+
 extern const char kUserActivationV2Name[];
 extern const char kUserActivationV2Description[];
 
@@ -1012,6 +1021,9 @@
 extern const char kVideoRotateToFullscreenName[];
 extern const char kVideoRotateToFullscreenDescription[];
 
+extern const char kViewsBrowserWindowsName[];
+extern const char kViewsBrowserWindowsDescription[];
+
 extern const char kWalletServiceUseSandboxName[];
 extern const char kWalletServiceUseSandboxDescription[];
 
@@ -1303,6 +1315,9 @@
 extern const char kOfflinePagesDescriptivePendingStatusName[];
 extern const char kOfflinePagesDescriptivePendingStatusDescription[];
 
+extern const char kOfflinePagesInDownloadHomeOpenInCctName[];
+extern const char kOfflinePagesInDownloadHomeOpenInCctDescription[];
+
 extern const char kOfflinePagesPrefetchingName[];
 extern const char kOfflinePagesPrefetchingDescription[];
 
@@ -1466,10 +1481,10 @@
 extern const char kWindows10CustomTitlebarName[];
 extern const char kWindows10CustomTitlebarDescription[];
 
-#if DCHECK_IS_ON() && defined(SYZYASAN)
-extern const char kSyzyAsanDcheckIsFatalName[];
-extern const char kSyzyAsanDcheckIsFatalDescription[];
-#endif  // DCHECK_IS_ON() && defined(SYZYASAN)
+#if DCHECK_IS_CONFIGURABLE
+extern const char kDcheckIsFatalName[];
+extern const char kDcheckIsFatalDescription[];
+#endif  // DCHECK_IS_CONFIGURABLE
 
 #endif  // defined(OS_WIN)
 
@@ -1771,9 +1786,6 @@
 
 #if defined(OS_ANDROID)
 
-extern const char kVrBrowsingName[];
-extern const char kVrBrowsingDescription[];
-
 extern const char kVrBrowserKeyboardName[];
 extern const char kVrBrowserKeyboardDescription[];
 
diff --git a/chrome/browser/global_keyboard_shortcuts_cocoa_mac.mm b/chrome/browser/global_keyboard_shortcuts_cocoa_mac.mm
deleted file mode 100644
index d30256b..0000000
--- a/chrome/browser/global_keyboard_shortcuts_cocoa_mac.mm
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/macros.h"
-#include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/global_keyboard_shortcuts_mac.h"
-
-// Basically, there are two kinds of keyboard shortcuts: Ones that should work
-// only if the tab contents is focused (BrowserKeyboardShortcut), and ones that
-// should work in all other cases (WindowKeyboardShortcut). In the latter case,
-// we differentiate between shortcuts that are checked before any other view
-// gets the chance to handle them (WindowKeyboardShortcut) or after all views
-// had a chance but did not handle the keypress event
-// (DelayedWindowKeyboardShortcut).
-
-const std::vector<KeyboardShortcutData>& GetWindowKeyboardShortcutTable() {
-  // clang-format off
-  CR_DEFINE_STATIC_LOCAL(std::vector<KeyboardShortcutData>, result, ({
-    //cmd   shift  cntrl  option vkeycode               char command
-    //---   -----  -----  ------ --------               ---- -------
-    // '{' / '}' characters should be matched earlier than virtual key codes
-    // (so we can match alt-8 as '{' on German keyboards).
-    {true,  false, false, false, 0,                     '}', IDC_SELECT_NEXT_TAB},
-    {true,  false, false, false, 0,                     '{', IDC_SELECT_PREVIOUS_TAB},
-    {true,  true,  false, false, kVK_ANSI_RightBracket, 0,   IDC_SELECT_NEXT_TAB},
-    {true,  true,  false, false, kVK_ANSI_LeftBracket,  0,   IDC_SELECT_PREVIOUS_TAB},
-    {false, false, true,  false, kVK_PageDown,          0,   IDC_SELECT_NEXT_TAB},
-    {false, false, true,  false, kVK_Tab,               0,   IDC_SELECT_NEXT_TAB},
-    {false, false, true,  false, kVK_PageUp,            0,   IDC_SELECT_PREVIOUS_TAB},
-    {false, true,  true,  false, kVK_Tab,               0,   IDC_SELECT_PREVIOUS_TAB},
-
-    //cmd  shift  cntrl  option vkeycode                char command
-    //---  -----  -----  ------ --------                ---- -------
-    // Cmd-0..8 select the nth tab, with cmd-9 being "last tab".
-    {true, false, false, false, kVK_ANSI_1,             0,   IDC_SELECT_TAB_0},
-    {true, false, false, false, kVK_ANSI_Keypad1,       0,   IDC_SELECT_TAB_0},
-    {true, false, false, false, kVK_ANSI_2,             0,   IDC_SELECT_TAB_1},
-    {true, false, false, false, kVK_ANSI_Keypad2,       0,   IDC_SELECT_TAB_1},
-    {true, false, false, false, kVK_ANSI_3,             0,   IDC_SELECT_TAB_2},
-    {true, false, false, false, kVK_ANSI_Keypad3,       0,   IDC_SELECT_TAB_2},
-    {true, false, false, false, kVK_ANSI_4,             0,   IDC_SELECT_TAB_3},
-    {true, false, false, false, kVK_ANSI_Keypad4,       0,   IDC_SELECT_TAB_3},
-    {true, false, false, false, kVK_ANSI_5,             0,   IDC_SELECT_TAB_4},
-    {true, false, false, false, kVK_ANSI_Keypad5,       0,   IDC_SELECT_TAB_4},
-    {true, false, false, false, kVK_ANSI_6,             0,   IDC_SELECT_TAB_5},
-    {true, false, false, false, kVK_ANSI_Keypad6,       0,   IDC_SELECT_TAB_5},
-    {true, false, false, false, kVK_ANSI_7,             0,   IDC_SELECT_TAB_6},
-    {true, false, false, false, kVK_ANSI_Keypad7,       0,   IDC_SELECT_TAB_6},
-    {true, false, false, false, kVK_ANSI_8,             0,   IDC_SELECT_TAB_7},
-    {true, false, false, false, kVK_ANSI_Keypad8,       0,   IDC_SELECT_TAB_7},
-    {true, false, false, false, kVK_ANSI_9,             0,   IDC_SELECT_LAST_TAB},
-    {true, false, false, false, kVK_ANSI_Keypad9,       0,   IDC_SELECT_LAST_TAB},
-    {true, true,  false, false, kVK_ANSI_M,             0,   IDC_SHOW_AVATAR_MENU},
-    {true, false, false, true,  kVK_ANSI_L,             0,   IDC_SHOW_DOWNLOADS},
-  }));
-  // clang-format on
-  return result;
-}
-
-const std::vector<KeyboardShortcutData>&
-GetDelayedWindowKeyboardShortcutTable() {
-  // clang-format off
-  CR_DEFINE_STATIC_LOCAL(std::vector<KeyboardShortcutData>, result, ({
-    //cmd   shift  cntrl  option vkeycode    char command
-    //---   -----  -----  ------ --------    ---- -------
-    {false, false, false, false, kVK_Escape, 0,   IDC_STOP},
-  }));
-  // clang-format on
-  return result;
-}
-
-const std::vector<KeyboardShortcutData>& GetBrowserKeyboardShortcutTable() {
-  // clang-format off
-  CR_DEFINE_STATIC_LOCAL(std::vector<KeyboardShortcutData>, result, ({
-    //cmd   shift  cntrl  option vkeycode        char command
-    //---   -----  -----  ------ --------        ---- -------
-    {true,  false, false, false, kVK_LeftArrow,  0,   IDC_BACK},
-    {true,  false, false, false, kVK_RightArrow, 0,   IDC_FORWARD},
-    {true,  true,  false, false, 0,              'c', IDC_DEV_TOOLS_INSPECT},
-  }));
-  // clang-format on
-  return result;
-}
diff --git a/chrome/browser/global_keyboard_shortcuts_mac.mm b/chrome/browser/global_keyboard_shortcuts_mac.mm
index 4cc258d..3e36c20 100644
--- a/chrome/browser/global_keyboard_shortcuts_mac.mm
+++ b/chrome/browser/global_keyboard_shortcuts_mac.mm
@@ -7,9 +7,11 @@
 #import <AppKit/AppKit.h>
 
 #include "base/logging.h"
-#include "base/macros.h"
+#include "base/no_destructor.h"
+#include "build/buildflag.h"
 #include "chrome/app/chrome_command_ids.h"
 #import "chrome/browser/ui/cocoa/nsmenuitem_additions.h"
+#include "chrome/browser/ui/views_mode_controller.h"
 
 namespace {
 
@@ -91,8 +93,112 @@
   return -1;
 }
 
+// Given a set of Views keyboard shortcuts and a set of Cocoa keyboard
+// shortcuts, returns the appropriate set depending on which browser window is
+// in use.
+const std::vector<KeyboardShortcutData>& ViewsOrCocoaKeys(
+    const std::vector<KeyboardShortcutData>& views_keys,
+    const std::vector<KeyboardShortcutData>& cocoa_keys) {
+#if BUILDFLAG(MAC_VIEWS_BROWSER)
+  if (!views_mode_controller::IsViewsBrowserCocoa())
+    return views_keys;
+#endif
+  return cocoa_keys;
+}
+
 }  // namespace
 
+// Basically, there are two kinds of keyboard shortcuts: Ones that should work
+// only if the tab contents is focused (BrowserKeyboardShortcut), and ones that
+// should work in all other cases (WindowKeyboardShortcut). In the latter case,
+// we differentiate between shortcuts that are checked before any other view
+// gets the chance to handle them (WindowKeyboardShortcut) or after all views
+// had a chance but did not handle the keypress event
+// (DelayedWindowKeyboardShortcut).
+
+const std::vector<KeyboardShortcutData>& GetWindowKeyboardShortcutTable() {
+  // clang-format off
+  // Lists shortcuts that are impossible to migrate to accelerator_table.cc
+  // (https://crbug.com/25946). Most of the entries in cocoa_keys are already
+  // present in accelerator_table.cc, so for Views browser windows, those
+  // definitions are used.
+  static base::NoDestructor<std::vector<KeyboardShortcutData>> views_keys({
+    //cmd  shift  cntrl  option vkeycode char command
+    //---  -----  -----  ------ -------- ---- -------
+    // '{' / '}' characters should be matched earlier than virtual key codes
+    // (so we can match alt-8 as '{' on German keyboards).
+    {true, false, false, false, 0,       '}', IDC_SELECT_NEXT_TAB},
+    {true, false, false, false, 0,       '{', IDC_SELECT_PREVIOUS_TAB},
+  });
+  static base::NoDestructor<std::vector<KeyboardShortcutData>> cocoa_keys({
+    //cmd   shift  cntrl  option vkeycode               char command
+    //---   -----  -----  ------ --------               ---- -------
+    // '{' / '}' characters should be matched earlier than virtual key codes
+    // (so we can match alt-8 as '{' on German keyboards).
+    {true,  false, false, false, 0,                     '}', IDC_SELECT_NEXT_TAB},
+    {true,  false, false, false, 0,                     '{', IDC_SELECT_PREVIOUS_TAB},
+    {true,  true,  false, false, kVK_ANSI_RightBracket, 0,   IDC_SELECT_NEXT_TAB},
+    {true,  true,  false, false, kVK_ANSI_LeftBracket,  0,   IDC_SELECT_PREVIOUS_TAB},
+    {false, false, true,  false, kVK_PageDown,          0,   IDC_SELECT_NEXT_TAB},
+    {false, false, true,  false, kVK_Tab,               0,   IDC_SELECT_NEXT_TAB},
+    {false, false, true,  false, kVK_PageUp,            0,   IDC_SELECT_PREVIOUS_TAB},
+    {false, true,  true,  false, kVK_Tab,               0,   IDC_SELECT_PREVIOUS_TAB},
+
+    //cmd  shift  cntrl  option vkeycode                char command
+    //---  -----  -----  ------ --------                ---- -------
+    // Cmd-0..8 select the nth tab, with cmd-9 being "last tab".
+    {true, false, false, false, kVK_ANSI_1,             0,   IDC_SELECT_TAB_0},
+    {true, false, false, false, kVK_ANSI_Keypad1,       0,   IDC_SELECT_TAB_0},
+    {true, false, false, false, kVK_ANSI_2,             0,   IDC_SELECT_TAB_1},
+    {true, false, false, false, kVK_ANSI_Keypad2,       0,   IDC_SELECT_TAB_1},
+    {true, false, false, false, kVK_ANSI_3,             0,   IDC_SELECT_TAB_2},
+    {true, false, false, false, kVK_ANSI_Keypad3,       0,   IDC_SELECT_TAB_2},
+    {true, false, false, false, kVK_ANSI_4,             0,   IDC_SELECT_TAB_3},
+    {true, false, false, false, kVK_ANSI_Keypad4,       0,   IDC_SELECT_TAB_3},
+    {true, false, false, false, kVK_ANSI_5,             0,   IDC_SELECT_TAB_4},
+    {true, false, false, false, kVK_ANSI_Keypad5,       0,   IDC_SELECT_TAB_4},
+    {true, false, false, false, kVK_ANSI_6,             0,   IDC_SELECT_TAB_5},
+    {true, false, false, false, kVK_ANSI_Keypad6,       0,   IDC_SELECT_TAB_5},
+    {true, false, false, false, kVK_ANSI_7,             0,   IDC_SELECT_TAB_6},
+    {true, false, false, false, kVK_ANSI_Keypad7,       0,   IDC_SELECT_TAB_6},
+    {true, false, false, false, kVK_ANSI_8,             0,   IDC_SELECT_TAB_7},
+    {true, false, false, false, kVK_ANSI_Keypad8,       0,   IDC_SELECT_TAB_7},
+    {true, false, false, false, kVK_ANSI_9,             0,   IDC_SELECT_LAST_TAB},
+    {true, false, false, false, kVK_ANSI_Keypad9,       0,   IDC_SELECT_LAST_TAB},
+    {true, true,  false, false, kVK_ANSI_M,             0,   IDC_SHOW_AVATAR_MENU},
+    {true, false, false, true,  kVK_ANSI_L,             0,   IDC_SHOW_DOWNLOADS},
+  });
+  // clang-format on
+  return ViewsOrCocoaKeys(*views_keys, *cocoa_keys);
+}
+
+const std::vector<KeyboardShortcutData>&
+GetDelayedWindowKeyboardShortcutTable() {
+  // clang-format off
+  static base::NoDestructor<std::vector<KeyboardShortcutData>> views_keys({});
+  static base::NoDestructor<std::vector<KeyboardShortcutData>> cocoa_keys({
+    //cmd   shift  cntrl  option vkeycode    char command
+    //---   -----  -----  ------ --------    ---- -------
+    {false, false, false, false, kVK_Escape, 0,   IDC_STOP},
+  });
+  // clang-format on
+  return ViewsOrCocoaKeys(*views_keys, *cocoa_keys);
+}
+
+const std::vector<KeyboardShortcutData>& GetBrowserKeyboardShortcutTable() {
+  // clang-format off
+  static base::NoDestructor<std::vector<KeyboardShortcutData>> views_keys({});
+  static base::NoDestructor<std::vector<KeyboardShortcutData>> cocoa_keys({
+    //cmd   shift  cntrl  option vkeycode        char command
+    //---   -----  -----  ------ --------        ---- -------
+    {true,  false, false, false, kVK_LeftArrow,  0,   IDC_BACK},
+    {true,  false, false, false, kVK_RightArrow, 0,   IDC_FORWARD},
+    {true,  true,  false, false, 0,              'c', IDC_DEV_TOOLS_INSPECT},
+  });
+  // clang-format on
+  return ViewsOrCocoaKeys(*views_keys, *cocoa_keys);
+}
+
 int CommandForWindowKeyboardShortcut(
     bool command_key, bool shift_key, bool cntrl_key, bool opt_key,
     int vkey_code, unichar key_char) {
diff --git a/chrome/browser/global_keyboard_shortcuts_views_mac.mm b/chrome/browser/global_keyboard_shortcuts_views_mac.mm
deleted file mode 100644
index 0303ba5..0000000
--- a/chrome/browser/global_keyboard_shortcuts_views_mac.mm
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/macros.h"
-#include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/global_keyboard_shortcuts_mac.h"
-
-// Lists shortcuts that are impossible to migrate to accelerator_table.cc
-// (crbug.com/25946).
-
-const std::vector<KeyboardShortcutData>& GetWindowKeyboardShortcutTable() {
-  // clang-format off
-  CR_DEFINE_STATIC_LOCAL(std::vector<KeyboardShortcutData>, result, ({
-    //cmd  shift  cntrl  option vkeycode char command
-    //---  -----  -----  ------ -------- ---- -------
-    // '{' / '}' characters should be matched earlier than virtual key codes
-    // (so we can match alt-8 as '{' on German keyboards).
-    {true, false, false, false, 0,       '}', IDC_SELECT_NEXT_TAB},
-    {true, false, false, false, 0,       '{', IDC_SELECT_PREVIOUS_TAB},
-  }));
-  // clang-format on
-  return result;
-}
-
-const std::vector<KeyboardShortcutData>&
-GetDelayedWindowKeyboardShortcutTable() {
-  CR_DEFINE_STATIC_LOCAL(std::vector<KeyboardShortcutData>, result, ({}));
-  return result;
-}
-
-const std::vector<KeyboardShortcutData>& GetBrowserKeyboardShortcutTable() {
-  CR_DEFINE_STATIC_LOCAL(std::vector<KeyboardShortcutData>, result, ({}));
-  return result;
-}
diff --git a/chrome/browser/icon_loader_chromeos.cc b/chrome/browser/icon_loader_chromeos.cc
index 1cc4e45..9f45258f 100644
--- a/chrome/browser/icon_loader_chromeos.cc
+++ b/chrome/browser/icon_loader_chromeos.cc
@@ -20,7 +20,7 @@
 #include "base/strings/string_util.h"
 #include "chrome/grit/theme_resources.h"
 #include "content/public/browser/browser_thread.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/base/layout.h"
 #include "ui/base/resource/resource_bundle.h"
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc
index 29f5845b..19ee282 100644
--- a/chrome/browser/io_thread.cc
+++ b/chrome/browser/io_thread.cc
@@ -84,7 +84,8 @@
 #include "net/http/http_network_session.h"
 #include "net/http/http_server_properties_impl.h"
 #include "net/http/http_transaction_factory.h"
-#include "net/net_features.h"
+#include "net/net_buildflags.h"
+#include "net/nqe/network_quality_estimator.h"
 #include "net/nqe/network_quality_estimator_params.h"
 #include "net/proxy_resolution/pac_file_fetcher_impl.h"
 #include "net/proxy_resolution/proxy_config_service.h"
@@ -143,11 +144,6 @@
 
 namespace {
 
-// Field trial for network quality estimator. Seeds RTT and downstream
-// throughput observations with values that correspond to the connection type
-// determined by the operating system.
-const char kNetworkQualityEstimatorFieldTrialName[] = "NetworkQualityEstimator";
-
 #if defined(OS_MACOSX)
 void ObserveKeychainEvents() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -497,32 +493,6 @@
           BrowserThread::GetTaskRunnerForThread(BrowserThread::UI));
 #endif  // defined(OS_ANDROID)
 
-  std::map<std::string, std::string> network_quality_estimator_params;
-  variations::GetVariationParams(kNetworkQualityEstimatorFieldTrialName,
-                                 &network_quality_estimator_params);
-
-  if (command_line.HasSwitch(switches::kForceEffectiveConnectionType)) {
-    const std::string force_ect_value =
-        base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
-            switches::kForceEffectiveConnectionType);
-
-    if (!force_ect_value.empty()) {
-      // If the effective connection type is forced using command line switch,
-      // it overrides the one set by field trial.
-      network_quality_estimator_params[net::kForceEffectiveConnectionType] =
-          force_ect_value;
-    }
-  }
-
-  // Pass ownership.
-  globals_->network_quality_estimator =
-      std::make_unique<net::NetworkQualityEstimator>(
-          std::make_unique<net::NetworkQualityEstimatorParams>(
-              network_quality_estimator_params),
-          net_log_);
-  globals_->network_quality_observer = content::CreateNetworkQualityObserver(
-      globals_->network_quality_estimator.get());
-
   globals_->dns_probe_service =
       std::make_unique<chrome_browser_net::DnsProbeService>();
 
@@ -778,9 +748,6 @@
   std::unique_ptr<network::URLRequestContextBuilderMojo> builder =
       std::make_unique<network::URLRequestContextBuilderMojo>();
 
-  builder->set_network_quality_estimator(
-      globals_->network_quality_estimator.get());
-
   auto chrome_network_delegate = std::make_unique<ChromeNetworkDelegate>(
       extension_event_router_forwarder(), &system_enable_referrers_);
   // By default, data usage is considered off the record.
@@ -832,9 +799,14 @@
     globals_->quic_disabled = true;
 
   if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
-    globals_->system_request_context_owner =
-        std::move(builder)->Create(std::move(network_context_params_).get(),
-                                   !is_quic_allowed_on_init_, net_log_);
+    globals_->deprecated_network_quality_estimator =
+        std::make_unique<net::NetworkQualityEstimator>(
+            std::make_unique<net::NetworkQualityEstimatorParams>(
+                std::map<std::string, std::string>()),
+            net_log_);
+    globals_->system_request_context_owner = std::move(builder)->Create(
+        std::move(network_context_params_).get(), !is_quic_allowed_on_init_,
+        net_log_, globals_->deprecated_network_quality_estimator.get());
     globals_->system_request_context =
         globals_->system_request_context_owner.url_request_context_getter
             ->GetURLRequestContext();
@@ -846,6 +818,11 @@
             &globals_->system_request_context);
   }
 
+  // TODO(mmenke): This class currently requires an in-process
+  // NetworkQualityEstimator.  Fix that.
+  globals_->network_quality_observer = content::CreateNetworkQualityObserver(
+      globals_->system_request_context->network_quality_estimator());
+
 #if defined(USE_NSS_CERTS)
   net::SetURLRequestContextForNSSHttpIO(globals_->system_request_context);
 #endif
diff --git a/chrome/browser/io_thread.h b/chrome/browser/io_thread.h
index 12e8246..5b869c07 100644
--- a/chrome/browser/io_thread.h
+++ b/chrome/browser/io_thread.h
@@ -31,7 +31,6 @@
 #include "content/public/browser/browser_thread_delegate.h"
 #include "extensions/buildflags/buildflags.h"
 #include "net/base/network_change_notifier.h"
-#include "net/nqe/network_quality_estimator.h"
 #include "services/network/public/mojom/network_service.mojom.h"
 #include "services/network/url_request_context_owner.h"
 
@@ -131,7 +130,14 @@
     std::vector<scoped_refptr<const net::CTLogVerifier>> ct_logs;
     std::unique_ptr<net::HttpAuthPreferences> http_auth_preferences;
 
-    std::unique_ptr<net::NetworkQualityEstimator> network_quality_estimator;
+    // NetworkQualityEstimator only for use in dummy in-process
+    // URLRequestContext when network service is enabled.
+    // TODO(mmenke): Remove this, once all consumers only access the
+    // NetworkQualityEstimator through network service APIs. Then will no longer
+    // need to create an in-process one.
+    std::unique_ptr<net::NetworkQualityEstimator>
+        deprecated_network_quality_estimator;
+
     std::unique_ptr<net::RTTAndThroughputEstimatesObserver>
         network_quality_observer;
 
diff --git a/chrome/browser/io_thread_browsertest.cc b/chrome/browser/io_thread_browsertest.cc
index 499531c..3f5bfa9 100644
--- a/chrome/browser/io_thread_browsertest.cc
+++ b/chrome/browser/io_thread_browsertest.cc
@@ -108,9 +108,9 @@
 
 void CheckEffectiveConnectionType(IOThread* io_thread,
                                   net::EffectiveConnectionType expected) {
-  EXPECT_EQ(expected,
-            io_thread->globals()
-                ->network_quality_estimator->GetEffectiveConnectionType());
+  EXPECT_EQ(expected, io_thread->globals()
+                          ->system_request_context->network_quality_estimator()
+                          ->GetEffectiveConnectionType());
 }
 
 void CheckSCTsAreSentToTreeTracker(IOThread* io_thread) {
diff --git a/chrome/browser/load_library_perf_test.cc b/chrome/browser/load_library_perf_test.cc
index 8a40db3e..8dffe678 100644
--- a/chrome/browser/load_library_perf_test.cc
+++ b/chrome/browser/load_library_perf_test.cc
@@ -13,7 +13,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/perf/perf_test.h"
 
diff --git a/chrome/browser/local_discovery/service_discovery_shared_client.cc b/chrome/browser/local_discovery/service_discovery_shared_client.cc
index ff6fce65..cdaa3e55 100644
--- a/chrome/browser/local_discovery/service_discovery_shared_client.cc
+++ b/chrome/browser/local_discovery/service_discovery_shared_client.cc
@@ -7,7 +7,7 @@
 #include <memory>
 
 #include "build/build_config.h"
-#include "net/net_features.h"
+#include "net/net_buildflags.h"
 
 #if defined(OS_WIN)
 #include "base/bind.h"
diff --git a/chrome/browser/media/DEPS b/chrome/browser/media/DEPS
index 1a3fdc91..2c463fe8 100644
--- a/chrome/browser/media/DEPS
+++ b/chrome/browser/media/DEPS
@@ -2,7 +2,7 @@
   "+media/audio",
   "+media/base",
   "+media/cast",
-  "+media/media_features.h",
+  "+media/media_buildflags.h",
   "+media/mojo/interfaces",
   # safe_dial_device_description_parser_unittest.cc needs DataDecoderService.
   "+services/data_decoder/data_decoder_service.h",
diff --git a/chrome/browser/media/cdm_storage_id.cc b/chrome/browser/media/cdm_storage_id.cc
index 07a3fa52..f666cd6 100644
--- a/chrome/browser/media/cdm_storage_id.cc
+++ b/chrome/browser/media/cdm_storage_id.cc
@@ -11,7 +11,7 @@
 #include "chrome/browser/media/media_storage_id_salt.h"
 #include "crypto/secure_hash.h"
 #include "crypto/sha2.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "rlz/features/features.h"
 #include "url/origin.h"
 
diff --git a/chrome/browser/media/cdm_storage_id_key.cc b/chrome/browser/media/cdm_storage_id_key.cc
index c34d6f2f..f2c5360 100644
--- a/chrome/browser/media/cdm_storage_id_key.cc
+++ b/chrome/browser/media/cdm_storage_id_key.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/browser/media/cdm_storage_id_key.h"
 
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 #if !BUILDFLAG(ENABLE_CDM_STORAGE_ID)
 #error This should only be compiled if "enable_cdm_storage_id" specified.
diff --git a/chrome/browser/media/encrypted_media_browsertest.cc b/chrome/browser/media/encrypted_media_browsertest.cc
index 56ca283..56e9be8 100644
--- a/chrome/browser/media/encrypted_media_browsertest.cc
+++ b/chrome/browser/media/encrypted_media_browsertest.cc
@@ -27,7 +27,7 @@
 #include "content/public/test/browser_test_utils.h"
 #include "media/base/key_system_names.h"
 #include "media/base/media_switches.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "testing/gtest/include/gtest/gtest-spi.h"
 
 #if defined(OS_WIN)
diff --git a/chrome/browser/media/encrypted_media_supported_types_browsertest.cc b/chrome/browser/media/encrypted_media_supported_types_browsertest.cc
index 2f32e87..a06c58b 100644
--- a/chrome/browser/media/encrypted_media_supported_types_browsertest.cc
+++ b/chrome/browser/media/encrypted_media_supported_types_browsertest.cc
@@ -26,7 +26,7 @@
 #include "content/public/test/browser_test_utils.h"
 #include "media/base/media_switches.h"
 #include "media/base/test_data_util.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "url/gurl.h"
 
diff --git a/chrome/browser/media/platform_verification_impl.cc b/chrome/browser/media/platform_verification_impl.cc
index c4d08537..77febd8 100644
--- a/chrome/browser/media/platform_verification_impl.cc
+++ b/chrome/browser/media/platform_verification_impl.cc
@@ -9,7 +9,7 @@
 #include "base/memory/ptr_util.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_contents.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 #if BUILDFLAG(ENABLE_CDM_STORAGE_ID)
 #include "chrome/browser/media/cdm_storage_id.h"
diff --git a/chrome/browser/media/router/discovery/discovery_network_monitor.cc b/chrome/browser/media/router/discovery/discovery_network_monitor.cc
index bc932265..6d8aa35d 100644
--- a/chrome/browser/media/router/discovery/discovery_network_monitor.cc
+++ b/chrome/browser/media/router/discovery/discovery_network_monitor.cc
@@ -14,6 +14,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/task_runner_util.h"
+#include "base/task_scheduler/task_traits.h"
 #include "base/time/default_tick_clock.h"
 #include "chrome/browser/media/router/discovery/discovery_network_list.h"
 #include "chrome/browser/media/router/discovery/discovery_network_monitor_metric_observer.h"
@@ -94,7 +95,9 @@
     : network_id_(kNetworkIdDisconnected),
       observers_(new base::ObserverListThreadSafe<Observer>(
           base::ObserverListPolicy::EXISTING_ONLY)),
-      task_runner_(base::CreateSequencedTaskRunnerWithTraits(base::MayBlock())),
+      task_runner_(base::CreateSequencedTaskRunnerWithTraits(
+          {base::MayBlock(),
+           base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN})),
       network_info_function_(strategy),
       metric_observer_(std::make_unique<DiscoveryNetworkMonitorMetricObserver>(
           base::DefaultTickClock::GetInstance(),
@@ -139,6 +142,9 @@
   auto network_info_list = network_info_function_();
   auto network_id = ComputeNetworkId(network_info_list);
 
+  // Although we are called with CONTINUE_ON_SHUTDOWN, none of these fields will
+  // disappear out from under us since |g_discovery_monitor| is declared with
+  // LeakyLazyInstanceTraits, and is therefore never deleted.
   network_id_.swap(network_id);
 
   if (network_id_ != network_id) {
diff --git a/chrome/browser/media/router/mojo/media_router_mojo_metrics_unittest.cc b/chrome/browser/media/router/mojo/media_router_mojo_metrics_unittest.cc
index 3ca2d1e..07e982c 100644
--- a/chrome/browser/media/router/mojo/media_router_mojo_metrics_unittest.cc
+++ b/chrome/browser/media/router/mojo/media_router_mojo_metrics_unittest.cc
@@ -24,9 +24,9 @@
     base::RepeatingCallback<void(MediaRouteProviderId,
                                  RouteRequestResult::ResultCode)> record_cb,
     MediaRouteProviderId provider1,
-    const char (&histogram_provider1)[],
+    const char* const histogram_provider1,
     MediaRouteProviderId provider2,
-    const char (&histogram_provider2)[]) {
+    const char* const histogram_provider2) {
   base::HistogramTester tester;
   tester.ExpectTotalCount(histogram_provider1, 0);
   tester.ExpectTotalCount(histogram_provider2, 0);
diff --git a/chrome/browser/media/webrtc/native_desktop_media_list.cc b/chrome/browser/media/webrtc/native_desktop_media_list.cc
index fca51c97..0c9ba95 100644
--- a/chrome/browser/media/webrtc/native_desktop_media_list.cc
+++ b/chrome/browser/media/webrtc/native_desktop_media_list.cc
@@ -16,17 +16,11 @@
 #include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
 #include "ui/aura/window.h"
+#include "ui/aura/window_tree_host.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/native_widget_types.h"
 #include "ui/snapshot/snapshot.h"
 
-#if defined(OS_WIN)
-#include "ui/views/widget/desktop_aura/desktop_window_tree_host_win.h"
-#endif  // defined(OS_WIN)
-
-#if defined(USE_X11)
-#include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h"
-#endif  // defined(USE_X11)
-
 #if defined(USE_AURA)
 #include "ui/snapshot/snapshot_aura.h"
 #endif
@@ -250,14 +244,10 @@
     if (source.id.type != DesktopMediaID::TYPE_WINDOW)
       continue;
 
-    aura::Window* aura_window = NULL;
-#if defined(OS_WIN)
-    aura_window = views::DesktopWindowTreeHostWin::GetContentWindowForHWND(
-        reinterpret_cast<HWND>(source.id.id));
-#elif defined(USE_X11)
-    aura_window =
-        views::DesktopWindowTreeHostX11::GetContentWindowForXID(source.id.id);
-#endif  // defined(USE_X11)
+    aura::WindowTreeHost* const host =
+        aura::WindowTreeHost::GetForAcceleratedWidget(
+            *reinterpret_cast<gfx::AcceleratedWidget*>(&source.id.id));
+    aura::Window* const aura_window = host ? host->window() : nullptr;
     if (aura_window) {
       DesktopMediaID aura_id = DesktopMediaID::RegisterAuraWindow(
           DesktopMediaID::TYPE_WINDOW, aura_window);
diff --git a/chrome/browser/media/webrtc/native_desktop_media_list_unittest.cc b/chrome/browser/media/webrtc/native_desktop_media_list_unittest.cc
index 8af41fb7..e5bf097e 100644
--- a/chrome/browser/media/webrtc/native_desktop_media_list_unittest.cc
+++ b/chrome/browser/media/webrtc/native_desktop_media_list_unittest.cc
@@ -201,17 +201,21 @@
   void AddAuraWindow() {
     webrtc::DesktopCapturer::Source window;
     window.title = "Test window";
+
     // Create a aura native widow through a widget.
     desktop_widgets_.push_back(CreateDesktopWidget());
+    aura::WindowTreeHost* const host =
+        desktop_widgets_.back()->GetNativeWindow()->GetHost();
+    aura::Window* const aura_window = host->window();
+
     // Get the native window's id.
-    aura::Window* aura_window = desktop_widgets_.back()->GetNativeWindow();
-    gfx::AcceleratedWidget widget =
-        aura_window->GetHost()->GetAcceleratedWidget();
+    gfx::AcceleratedWidget widget = host->GetAcceleratedWidget();
 #if defined(OS_WIN)
     window.id = reinterpret_cast<DesktopMediaID::Id>(widget);
 #else
     window.id = widget;
 #endif
+
     // Get the aura window's id.
     DesktopMediaID aura_id = DesktopMediaID::RegisterAuraWindow(
         DesktopMediaID::TYPE_WINDOW, aura_window);
diff --git a/chrome/browser/media/webrtc/webrtc_event_log_manager.cc b/chrome/browser/media/webrtc/webrtc_event_log_manager.cc
index ef7555d..60da572 100644
--- a/chrome/browser/media/webrtc/webrtc_event_log_manager.cc
+++ b/chrome/browser/media/webrtc/webrtc_event_log_manager.cc
@@ -711,3 +711,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   return task_runner_;
 }
+
+void WebRtcEventLogManager::PostNullTaskForTesting(base::OnceClosure reply) {
+  task_runner_->PostTask(FROM_HERE, std::move(reply));
+}
diff --git a/chrome/browser/media/webrtc/webrtc_event_log_manager.h b/chrome/browser/media/webrtc/webrtc_event_log_manager.h
index 9123f7d..866d073 100644
--- a/chrome/browser/media/webrtc/webrtc_event_log_manager.h
+++ b/chrome/browser/media/webrtc/webrtc_event_log_manager.h
@@ -271,8 +271,11 @@
 
   // This allows unit tests that do not wish to change the task runner to still
   // check when certain operations are finished.
+  // TODO(crbug.com/775415): Remove this and use PostNullTaskForTesting instead.
   scoped_refptr<base::SequencedTaskRunner>& GetTaskRunnerForTesting();
 
+  void PostNullTaskForTesting(base::OnceClosure reply) override;
+
   static WebRtcEventLogManager* g_webrtc_event_log_manager;
 
   // Observer which will be informed whenever a local log file is started or
diff --git a/chrome/browser/media/webrtc/webrtc_internals_integration_browsertest.cc b/chrome/browser/media/webrtc/webrtc_internals_integration_browsertest.cc
new file mode 100644
index 0000000..7ea1f96
--- /dev/null
+++ b/chrome/browser/media/webrtc/webrtc_internals_integration_browsertest.cc
@@ -0,0 +1,76 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/run_loop.h"
+#include "base/threading/thread_restrictions.h"
+#include "chrome/browser/media/webrtc/webrtc_browsertest_base.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/webrtc_event_logger.h"
+#include "content/public/common/content_switches.h"
+#include "media/base/media_switches.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+const char kMainWebrtcTestHtmlPage[] = "/webrtc/webrtc_jsep01_test.html";
+}
+
+class WebRTCInternalsIntegrationBrowserTest : public WebRtcTestBase {
+ public:
+  ~WebRTCInternalsIntegrationBrowserTest() override = default;
+
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    InProcessBrowserTest::SetUpDefaultCommandLine(command_line);
+
+    command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
+
+    {
+      base::ScopedAllowBlockingForTesting allow_blocking;
+      ASSERT_TRUE(local_logs_dir_.CreateUniqueTempDir());
+    }
+    command_line->AppendSwitchASCII(switches::kWebRtcLocalEventLogging,
+                                    local_logs_dir_.GetPath().MaybeAsASCII());
+  }
+
+  // To avoid flaky tests, we need to synchronize with WebRtcEventLogger's
+  // internal task runners (if any exist) before we examine anything we
+  // expect to be produced by WebRtcEventLogger (files, etc.).
+  void WaitForEventLogProcessing() {
+    auto* webrtc_event_logger = content::WebRtcEventLogger::Get();
+    ASSERT_TRUE(webrtc_event_logger);
+
+    base::RunLoop run_loop;
+    webrtc_event_logger->PostNullTaskForTesting(run_loop.QuitWhenIdleClosure());
+    run_loop.Run();
+  }
+
+  bool IsDirectoryEmpty(const base::FilePath& path) {
+    base::ScopedAllowBlockingForTesting allow_blocking;
+    return base::IsDirectoryEmpty(path);
+  }
+
+  base::ScopedTempDir local_logs_dir_;
+};
+
+IN_PROC_BROWSER_TEST_F(WebRTCInternalsIntegrationBrowserTest,
+                       IntegrationWithWebRtcEventLogger) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+
+  content::WebContents* tab =
+      OpenTestPageAndGetUserMediaInNewTab(kMainWebrtcTestHtmlPage);
+
+  ASSERT_TRUE(IsDirectoryEmpty(local_logs_dir_.GetPath()));  // Sanity on test.
+
+  // Local WebRTC event logging turned on from command line using the
+  // kWebRtcLocalEventLogging flag. When we set up a peer connection, it
+  // will be logged to a file under |local_logs_dir_|.
+  SetupPeerconnectionWithLocalStream(tab);
+
+  WaitForEventLogProcessing();
+
+  EXPECT_FALSE(IsDirectoryEmpty(local_logs_dir_.GetPath()));
+}
diff --git a/chrome/browser/media_galleries/fileapi/device_media_async_file_util.cc b/chrome/browser/media_galleries/fileapi/device_media_async_file_util.cc
index 85b48c8..e42ad56 100644
--- a/chrome/browser/media_galleries/fileapi/device_media_async_file_util.cc
+++ b/chrome/browser/media_galleries/fileapi/device_media_async_file_util.cc
@@ -40,30 +40,29 @@
 // Called when GetFileInfo method call failed to get the details of file
 // specified by the requested url. |callback| is invoked to notify the
 // caller about the file |error|.
-void OnGetFileInfoError(const AsyncFileUtil::GetFileInfoCallback& callback,
+void OnGetFileInfoError(AsyncFileUtil::GetFileInfoCallback callback,
                         base::File::Error error) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  callback.Run(error, base::File::Info());
+  std::move(callback).Run(error, base::File::Info());
 }
 
 // Called after OnDidGetFileInfo finishes media check.
 // |callback| is invoked to complete the GetFileInfo request.
-void OnDidCheckMediaForGetFileInfo(
-    const AsyncFileUtil::GetFileInfoCallback& callback,
-    const base::File::Info& file_info,
-    bool is_valid_file) {
+void OnDidCheckMediaForGetFileInfo(AsyncFileUtil::GetFileInfoCallback callback,
+                                   const base::File::Info& file_info,
+                                   bool is_valid_file) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   if (!is_valid_file) {
-    OnGetFileInfoError(callback, base::File::FILE_ERROR_NOT_FOUND);
+    OnGetFileInfoError(std::move(callback), base::File::FILE_ERROR_NOT_FOUND);
     return;
   }
-  callback.Run(base::File::FILE_OK, file_info);
+  std::move(callback).Run(base::File::FILE_OK, file_info);
 }
 
 // Called after OnDidReadDirectory finishes media check.
 // |callback| is invoked to complete the ReadDirectory request.
 void OnDidCheckMediaForReadDirectory(
-    const AsyncFileUtil::ReadDirectoryCallback& callback,
+    AsyncFileUtil::ReadDirectoryCallback callback,
     bool has_more,
     AsyncFileUtil::EntryList file_list) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
@@ -71,54 +70,54 @@
 }
 
 // Called when CreateDirectory method call failed.
-void OnCreateDirectoryError(const AsyncFileUtil::StatusCallback& callback,
+void OnCreateDirectoryError(AsyncFileUtil::StatusCallback callback,
                             base::File::Error error) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  callback.Run(error);
+  std::move(callback).Run(error);
 }
 
 // Called when ReadDirectory method call failed to enumerate the directory
 // objects. |callback| is invoked to notify the caller about the |error|
 // that occured while reading the directory objects.
-void OnReadDirectoryError(const AsyncFileUtil::ReadDirectoryCallback& callback,
+void OnReadDirectoryError(AsyncFileUtil::ReadDirectoryCallback callback,
                           base::File::Error error) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   callback.Run(error, AsyncFileUtil::EntryList(), false /*no more*/);
 }
 
 // Called when CopyFileLocal method call failed.
-void OnCopyFileLocalError(const AsyncFileUtil::StatusCallback& callback,
+void OnCopyFileLocalError(AsyncFileUtil::StatusCallback callback,
                           base::File::Error error) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  callback.Run(error);
+  std::move(callback).Run(error);
 }
 
 // Called when MoveFileLocal method call failed.
-void OnMoveFileLocalError(const AsyncFileUtil::StatusCallback& callback,
+void OnMoveFileLocalError(AsyncFileUtil::StatusCallback callback,
                           base::File::Error error) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  callback.Run(error);
+  std::move(callback).Run(error);
 }
 
 // Called when CopyInForeignFile method call failed.
-void OnCopyInForeignFileError(const AsyncFileUtil::StatusCallback& callback,
+void OnCopyInForeignFileError(AsyncFileUtil::StatusCallback callback,
                               base::File::Error error) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  callback.Run(error);
+  std::move(callback).Run(error);
 }
 
 // Called when DeleteFile method call failed.
-void OnDeleteFileError(const AsyncFileUtil::StatusCallback& callback,
+void OnDeleteFileError(AsyncFileUtil::StatusCallback callback,
                        base::File::Error error) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  callback.Run(error);
+  std::move(callback).Run(error);
 }
 
 // Called when DeleteDirectory method call failed.
-void OnDeleteDirectoryError(const AsyncFileUtil::StatusCallback& callback,
+void OnDeleteDirectoryError(AsyncFileUtil::StatusCallback callback,
                             base::File::Error error) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  callback.Run(error);
+  std::move(callback).Run(error);
 }
 
 // Called on a blocking pool thread to create a snapshot file to hold the
@@ -143,7 +142,7 @@
 // Called after OnDidCreateSnapshotFile finishes media check.
 // |callback| is invoked to complete the CreateSnapshotFile request.
 void OnDidCheckMediaForCreateSnapshotFile(
-    const AsyncFileUtil::CreateSnapshotFileCallback& callback,
+    AsyncFileUtil::CreateSnapshotFileCallback callback,
     const base::File::Info& file_info,
     scoped_refptr<storage::ShareableFileReference> platform_file,
     base::File::Error error) {
@@ -151,18 +150,17 @@
   base::FilePath platform_path(platform_file.get()->path());
   if (error != base::File::FILE_OK)
     platform_file = NULL;
-  callback.Run(error, file_info, platform_path, platform_file);
+  std::move(callback).Run(error, file_info, platform_path, platform_file);
 }
 
 // Called when the snapshot file specified by the |platform_path| is
 // successfully created. |file_info| contains the device media file details
 // for which the snapshot file is created.
-void OnDidCreateSnapshotFile(
-    const AsyncFileUtil::CreateSnapshotFileCallback& callback,
-    base::SequencedTaskRunner* media_task_runner,
-    bool validate_media_files,
-    const base::File::Info& file_info,
-    const base::FilePath& platform_path) {
+void OnDidCreateSnapshotFile(AsyncFileUtil::CreateSnapshotFileCallback callback,
+                             base::SequencedTaskRunner* media_task_runner,
+                             bool validate_media_files,
+                             const base::File::Info& file_info,
+                             const base::FilePath& platform_path) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   scoped_refptr<storage::ShareableFileReference> file =
       ShareableFileReference::GetOrCreate(
@@ -172,15 +170,12 @@
 
   if (validate_media_files) {
     base::PostTaskAndReplyWithResult(
-        media_task_runner,
-        FROM_HERE,
-        base::Bind(&NativeMediaFileUtil::IsMediaFile, platform_path),
-        base::Bind(&OnDidCheckMediaForCreateSnapshotFile,
-                   callback,
-                   file_info,
-                   file));
+        media_task_runner, FROM_HERE,
+        base::BindOnce(&NativeMediaFileUtil::IsMediaFile, platform_path),
+        base::BindOnce(&OnDidCheckMediaForCreateSnapshotFile,
+                       std::move(callback), file_info, file));
   } else {
-    OnDidCheckMediaForCreateSnapshotFile(callback, file_info, file,
+    OnDidCheckMediaForCreateSnapshotFile(std::move(callback), file_info, file,
                                          base::File::FILE_OK);
   }
 }
@@ -188,11 +183,11 @@
 // Called when CreateSnapshotFile method call fails. |callback| is invoked to
 // notify the caller about the |error|.
 void OnCreateSnapshotFileError(
-    const AsyncFileUtil::CreateSnapshotFileCallback& callback,
+    AsyncFileUtil::CreateSnapshotFileCallback callback,
     base::File::Error error) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  callback.Run(error, base::File::Info(), base::FilePath(),
-               scoped_refptr<ShareableFileReference>());
+  std::move(callback).Run(error, base::File::Info(), base::FilePath(),
+                          scoped_refptr<ShareableFileReference>());
 }
 
 // Called when the snapshot file specified by the |snapshot_file_path| is
@@ -203,19 +198,21 @@
 // contents of url.path() to |snapshot_file_path|.
 void OnSnapshotFileCreatedRunTask(
     std::unique_ptr<FileSystemOperationContext> context,
-    const AsyncFileUtil::CreateSnapshotFileCallback& callback,
+    AsyncFileUtil::CreateSnapshotFileCallback callback,
     const FileSystemURL& url,
     bool validate_media_files,
     const base::FilePath& snapshot_file_path) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   if (snapshot_file_path.empty()) {
-    OnCreateSnapshotFileError(callback, base::File::FILE_ERROR_FAILED);
+    OnCreateSnapshotFileError(std::move(callback),
+                              base::File::FILE_ERROR_FAILED);
     return;
   }
   MTPDeviceAsyncDelegate* delegate =
       MTPDeviceMapService::GetInstance()->GetMTPDeviceAsyncDelegate(url);
   if (!delegate) {
-    OnCreateSnapshotFileError(callback, base::File::FILE_ERROR_NOT_FOUND);
+    OnCreateSnapshotFileError(std::move(callback),
+                              base::File::FILE_ERROR_NOT_FOUND);
     return;
   }
   delegate->CreateSnapshotFile(
@@ -303,29 +300,31 @@
     std::unique_ptr<FileSystemOperationContext> context,
     const FileSystemURL& url,
     int file_flags,
-    const CreateOrOpenCallback& callback) {
+    CreateOrOpenCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   // Returns an error if any unsupported flag is found.
   if (file_flags & ~(base::File::FLAG_OPEN |
                      base::File::FLAG_READ |
                      base::File::FLAG_WRITE_ATTRIBUTES)) {
-    callback.Run(base::File(base::File::FILE_ERROR_SECURITY), base::Closure());
+    std::move(callback).Run(base::File(base::File::FILE_ERROR_SECURITY),
+                            base::Closure());
     return;
   }
   auto* task_runner = context->task_runner();
   CreateSnapshotFile(
       std::move(context), url,
       base::Bind(&NativeMediaFileUtil::CreatedSnapshotFileForCreateOrOpen,
-                 base::RetainedRef(task_runner), file_flags, callback));
+                 base::RetainedRef(task_runner), file_flags,
+                 std::move(callback)));
 }
 
 void DeviceMediaAsyncFileUtil::EnsureFileExists(
     std::unique_ptr<FileSystemOperationContext> context,
     const FileSystemURL& url,
-    const EnsureFileExistsCallback& callback) {
+    EnsureFileExistsCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   NOTIMPLEMENTED();
-  callback.Run(base::File::FILE_ERROR_SECURITY, false);
+  std::move(callback).Run(base::File::FILE_ERROR_SECURITY, false);
 }
 
 void DeviceMediaAsyncFileUtil::CreateDirectory(
@@ -333,16 +332,18 @@
     const FileSystemURL& url,
     bool exclusive,
     bool recursive,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   MTPDeviceAsyncDelegate* delegate =
       MTPDeviceMapService::GetInstance()->GetMTPDeviceAsyncDelegate(url);
   if (!delegate) {
-    OnCreateDirectoryError(callback, base::File::FILE_ERROR_NOT_FOUND);
+    OnCreateDirectoryError(std::move(callback),
+                           base::File::FILE_ERROR_NOT_FOUND);
     return;
   }
   if (delegate->IsReadOnly()) {
-    OnCreateDirectoryError(callback, base::File::FILE_ERROR_SECURITY);
+    OnCreateDirectoryError(std::move(callback),
+                           base::File::FILE_ERROR_SECURITY);
     return;
   }
   delegate->CreateDirectory(
@@ -356,12 +357,12 @@
     std::unique_ptr<FileSystemOperationContext> context,
     const FileSystemURL& url,
     int /* flags */,
-    const GetFileInfoCallback& callback) {
+    GetFileInfoCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   MTPDeviceAsyncDelegate* delegate =
       MTPDeviceMapService::GetInstance()->GetMTPDeviceAsyncDelegate(url);
   if (!delegate) {
-    OnGetFileInfoError(callback, base::File::FILE_ERROR_NOT_FOUND);
+    OnGetFileInfoError(std::move(callback), base::File::FILE_ERROR_NOT_FOUND);
     return;
   }
   delegate->GetFileInfo(url.path(),
@@ -375,7 +376,7 @@
 void DeviceMediaAsyncFileUtil::ReadDirectory(
     std::unique_ptr<FileSystemOperationContext> context,
     const FileSystemURL& url,
-    const ReadDirectoryCallback& callback) {
+    ReadDirectoryCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   MTPDeviceAsyncDelegate* delegate =
       MTPDeviceMapService::GetInstance()->GetMTPDeviceAsyncDelegate(url);
@@ -397,20 +398,20 @@
     const FileSystemURL& url,
     const base::Time& last_access_time,
     const base::Time& last_modified_time,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   NOTIMPLEMENTED();
-  callback.Run(base::File::FILE_ERROR_SECURITY);
+  std::move(callback).Run(base::File::FILE_ERROR_SECURITY);
 }
 
 void DeviceMediaAsyncFileUtil::Truncate(
     std::unique_ptr<FileSystemOperationContext> context,
     const FileSystemURL& url,
     int64_t length,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   NOTIMPLEMENTED();
-  callback.Run(base::File::FILE_ERROR_SECURITY);
+  std::move(callback).Run(base::File::FILE_ERROR_SECURITY);
 }
 
 void DeviceMediaAsyncFileUtil::CopyFileLocal(
@@ -418,18 +419,18 @@
     const FileSystemURL& src_url,
     const FileSystemURL& dest_url,
     CopyOrMoveOption option,
-    const CopyFileProgressCallback& progress_callback,
-    const StatusCallback& callback) {
+    CopyFileProgressCallback progress_callback,
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
   MTPDeviceAsyncDelegate* delegate =
       MTPDeviceMapService::GetInstance()->GetMTPDeviceAsyncDelegate(dest_url);
   if (!delegate) {
-    OnCopyFileLocalError(callback, base::File::FILE_ERROR_NOT_FOUND);
+    OnCopyFileLocalError(std::move(callback), base::File::FILE_ERROR_NOT_FOUND);
     return;
   }
   if (delegate->IsReadOnly()) {
-    OnCopyFileLocalError(callback, base::File::FILE_ERROR_SECURITY);
+    OnCopyFileLocalError(std::move(callback), base::File::FILE_ERROR_SECURITY);
     return;
   }
 
@@ -447,17 +448,17 @@
     const FileSystemURL& src_url,
     const FileSystemURL& dest_url,
     CopyOrMoveOption option,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
   MTPDeviceAsyncDelegate* delegate =
       MTPDeviceMapService::GetInstance()->GetMTPDeviceAsyncDelegate(dest_url);
   if (!delegate) {
-    OnMoveFileLocalError(callback, base::File::FILE_ERROR_NOT_FOUND);
+    OnMoveFileLocalError(std::move(callback), base::File::FILE_ERROR_NOT_FOUND);
     return;
   }
   if (delegate->IsReadOnly()) {
-    OnMoveFileLocalError(callback, base::File::FILE_ERROR_SECURITY);
+    OnMoveFileLocalError(std::move(callback), base::File::FILE_ERROR_SECURITY);
     return;
   }
 
@@ -473,17 +474,19 @@
     std::unique_ptr<FileSystemOperationContext> context,
     const base::FilePath& src_file_path,
     const FileSystemURL& dest_url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
   MTPDeviceAsyncDelegate* delegate =
       MTPDeviceMapService::GetInstance()->GetMTPDeviceAsyncDelegate(dest_url);
   if (!delegate) {
-    OnCopyInForeignFileError(callback, base::File::FILE_ERROR_NOT_FOUND);
+    OnCopyInForeignFileError(std::move(callback),
+                             base::File::FILE_ERROR_NOT_FOUND);
     return;
   }
   if (delegate->IsReadOnly()) {
-    OnCopyInForeignFileError(callback, base::File::FILE_ERROR_SECURITY);
+    OnCopyInForeignFileError(std::move(callback),
+                             base::File::FILE_ERROR_SECURITY);
     return;
   }
 
@@ -497,17 +500,17 @@
 void DeviceMediaAsyncFileUtil::DeleteFile(
     std::unique_ptr<FileSystemOperationContext> context,
     const FileSystemURL& url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
   MTPDeviceAsyncDelegate* const delegate =
       MTPDeviceMapService::GetInstance()->GetMTPDeviceAsyncDelegate(url);
   if (!delegate) {
-    OnDeleteFileError(callback, base::File::FILE_ERROR_NOT_FOUND);
+    OnDeleteFileError(std::move(callback), base::File::FILE_ERROR_NOT_FOUND);
     return;
   }
   if (delegate->IsReadOnly()) {
-    OnDeleteFileError(callback, base::File::FILE_ERROR_SECURITY);
+    OnDeleteFileError(std::move(callback), base::File::FILE_ERROR_SECURITY);
     return;
   }
 
@@ -520,17 +523,19 @@
 void DeviceMediaAsyncFileUtil::DeleteDirectory(
     std::unique_ptr<FileSystemOperationContext> context,
     const FileSystemURL& url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
   MTPDeviceAsyncDelegate* const delegate =
       MTPDeviceMapService::GetInstance()->GetMTPDeviceAsyncDelegate(url);
   if (!delegate) {
-    OnDeleteDirectoryError(callback, base::File::FILE_ERROR_NOT_FOUND);
+    OnDeleteDirectoryError(std::move(callback),
+                           base::File::FILE_ERROR_NOT_FOUND);
     return;
   }
   if (delegate->IsReadOnly()) {
-    OnDeleteDirectoryError(callback, base::File::FILE_ERROR_SECURITY);
+    OnDeleteDirectoryError(std::move(callback),
+                           base::File::FILE_ERROR_SECURITY);
     return;
   }
 
@@ -543,29 +548,30 @@
 void DeviceMediaAsyncFileUtil::DeleteRecursively(
     std::unique_ptr<FileSystemOperationContext> context,
     const FileSystemURL& url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  callback.Run(base::File::FILE_ERROR_INVALID_OPERATION);
+  std::move(callback).Run(base::File::FILE_ERROR_INVALID_OPERATION);
 }
 
 void DeviceMediaAsyncFileUtil::CreateSnapshotFile(
     std::unique_ptr<FileSystemOperationContext> context,
     const FileSystemURL& url,
-    const CreateSnapshotFileCallback& callback) {
+    CreateSnapshotFileCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   MTPDeviceAsyncDelegate* delegate =
       MTPDeviceMapService::GetInstance()->GetMTPDeviceAsyncDelegate(url);
   if (!delegate) {
-    OnCreateSnapshotFileError(callback, base::File::FILE_ERROR_NOT_FOUND);
+    OnCreateSnapshotFileError(std::move(callback),
+                              base::File::FILE_ERROR_NOT_FOUND);
     return;
   }
 
   scoped_refptr<base::SequencedTaskRunner> task_runner(context->task_runner());
   base::PostTaskAndReplyWithResult(
       task_runner.get(), FROM_HERE,
-      base::Bind(&CreateSnapshotFileOnBlockingPool, profile_path_),
-      base::Bind(&OnSnapshotFileCreatedRunTask, base::Passed(&context),
-                 callback, url, validate_media_files()));
+      base::BindOnce(&CreateSnapshotFileOnBlockingPool, profile_path_),
+      base::BindOnce(&OnSnapshotFileCreatedRunTask, base::Passed(&context),
+                     std::move(callback), url, validate_media_files()));
 }
 
 std::unique_ptr<storage::FileStreamReader>
@@ -627,36 +633,35 @@
   }
 }
 
-void DeviceMediaAsyncFileUtil::OnDidCreateDirectory(
-    const StatusCallback& callback) {
+void DeviceMediaAsyncFileUtil::OnDidCreateDirectory(StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
-  callback.Run(base::File::FILE_OK);
+  std::move(callback).Run(base::File::FILE_OK);
 }
 
 void DeviceMediaAsyncFileUtil::OnDidGetFileInfo(
     base::SequencedTaskRunner* task_runner,
     const base::FilePath& path,
-    const AsyncFileUtil::GetFileInfoCallback& callback,
+    AsyncFileUtil::GetFileInfoCallback callback,
     const base::File::Info& file_info) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   if (file_info.is_directory || !validate_media_files()) {
-    OnDidCheckMediaForGetFileInfo(callback, file_info, true /* valid */);
+    OnDidCheckMediaForGetFileInfo(std::move(callback), file_info,
+                                  true /* valid */);
     return;
   }
 
   base::PostTaskAndReplyWithResult(
-      task_runner,
-      FROM_HERE,
-      base::Bind(&MediaPathFilterWrapper::CheckFilePath,
-                 media_path_filter_wrapper_,
-                 path),
-      base::Bind(&OnDidCheckMediaForGetFileInfo, callback, file_info));
+      task_runner, FROM_HERE,
+      base::BindOnce(&MediaPathFilterWrapper::CheckFilePath,
+                     media_path_filter_wrapper_, path),
+      base::BindOnce(&OnDidCheckMediaForGetFileInfo, std::move(callback),
+                     file_info));
 }
 
 void DeviceMediaAsyncFileUtil::OnDidReadDirectory(
     base::SequencedTaskRunner* task_runner,
-    const AsyncFileUtil::ReadDirectoryCallback& callback,
+    AsyncFileUtil::ReadDirectoryCallback callback,
     AsyncFileUtil::EntryList file_list,
     bool has_more) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
@@ -672,38 +677,34 @@
       base::BindOnce(&OnDidCheckMediaForReadDirectory, callback, has_more));
 }
 
-void DeviceMediaAsyncFileUtil::OnDidCopyFileLocal(
-    const StatusCallback& callback) {
+void DeviceMediaAsyncFileUtil::OnDidCopyFileLocal(StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
-  callback.Run(base::File::FILE_OK);
+  std::move(callback).Run(base::File::FILE_OK);
 }
 
-void DeviceMediaAsyncFileUtil::OnDidMoveFileLocal(
-    const StatusCallback& callback) {
+void DeviceMediaAsyncFileUtil::OnDidMoveFileLocal(StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
-  callback.Run(base::File::FILE_OK);
+  std::move(callback).Run(base::File::FILE_OK);
 }
 
-void DeviceMediaAsyncFileUtil::OnDidCopyInForeignFile(
-    const StatusCallback& callback) {
+void DeviceMediaAsyncFileUtil::OnDidCopyInForeignFile(StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
-  callback.Run(base::File::FILE_OK);
+  std::move(callback).Run(base::File::FILE_OK);
 }
 
-void DeviceMediaAsyncFileUtil::OnDidDeleteFile(const StatusCallback& callback) {
+void DeviceMediaAsyncFileUtil::OnDidDeleteFile(StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
-  callback.Run(base::File::FILE_OK);
+  std::move(callback).Run(base::File::FILE_OK);
 }
 
-void DeviceMediaAsyncFileUtil::OnDidDeleteDirectory(
-    const StatusCallback& callback) {
+void DeviceMediaAsyncFileUtil::OnDidDeleteDirectory(StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
-  callback.Run(base::File::FILE_OK);
+  std::move(callback).Run(base::File::FILE_OK);
 }
 
 bool DeviceMediaAsyncFileUtil::validate_media_files() const {
diff --git a/chrome/browser/media_galleries/fileapi/device_media_async_file_util.h b/chrome/browser/media_galleries/fileapi/device_media_async_file_util.h
index 664553b..d73638c5 100644
--- a/chrome/browser/media_galleries/fileapi/device_media_async_file_util.h
+++ b/chrome/browser/media_galleries/fileapi/device_media_async_file_util.h
@@ -48,67 +48,67 @@
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
       int file_flags,
-      const CreateOrOpenCallback& callback) override;
+      CreateOrOpenCallback callback) override;
   void EnsureFileExists(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const EnsureFileExistsCallback& callback) override;
+      EnsureFileExistsCallback callback) override;
   void CreateDirectory(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
       bool exclusive,
       bool recursive,
-      const StatusCallback& callback) override;
+      StatusCallback callback) override;
   void GetFileInfo(std::unique_ptr<storage::FileSystemOperationContext> context,
                    const storage::FileSystemURL& url,
                    int /* flags */,
-                   const GetFileInfoCallback& callback) override;
+                   GetFileInfoCallback callback) override;
   void ReadDirectory(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const ReadDirectoryCallback& callback) override;
+      ReadDirectoryCallback callback) override;
   void Touch(std::unique_ptr<storage::FileSystemOperationContext> context,
              const storage::FileSystemURL& url,
              const base::Time& last_access_time,
              const base::Time& last_modified_time,
-             const StatusCallback& callback) override;
+             StatusCallback callback) override;
   void Truncate(std::unique_ptr<storage::FileSystemOperationContext> context,
                 const storage::FileSystemURL& url,
                 int64_t length,
-                const StatusCallback& callback) override;
+                StatusCallback callback) override;
   void CopyFileLocal(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& src_url,
       const storage::FileSystemURL& dest_url,
       CopyOrMoveOption option,
-      const CopyFileProgressCallback& progress_callback,
-      const StatusCallback& callback) override;
+      CopyFileProgressCallback progress_callback,
+      StatusCallback callback) override;
   void MoveFileLocal(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& src_url,
       const storage::FileSystemURL& dest_url,
       CopyOrMoveOption option,
-      const StatusCallback& callback) override;
+      StatusCallback callback) override;
   void CopyInForeignFile(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const base::FilePath& src_file_path,
       const storage::FileSystemURL& dest_url,
-      const StatusCallback& callback) override;
+      StatusCallback callback) override;
   void DeleteFile(std::unique_ptr<storage::FileSystemOperationContext> context,
                   const storage::FileSystemURL& url,
-                  const StatusCallback& callback) override;
+                  StatusCallback callback) override;
   void DeleteDirectory(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const StatusCallback& callback) override;
+      StatusCallback callback) override;
   void DeleteRecursively(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const StatusCallback& callback) override;
+      StatusCallback callback) override;
   void CreateSnapshotFile(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const CreateSnapshotFileCallback& callback) override;
+      CreateSnapshotFileCallback callback) override;
 
   // This method is called when existing Blobs are read.
   // |expected_modification_time| indicates the expected snapshot state of the
@@ -142,16 +142,15 @@
 
   // Called when CreateDirectory method call succeeds. |callback| is invoked to
   // complete the CreateDirectory request.
-  void OnDidCreateDirectory(const StatusCallback& callback);
+  void OnDidCreateDirectory(StatusCallback callback);
 
   // Called when GetFileInfo method call succeeds. |file_info| contains the
   // file details of the requested url. |callback| is invoked to complete the
   // GetFileInfo request.
-  void OnDidGetFileInfo(
-      base::SequencedTaskRunner* task_runner,
-      const base::FilePath& path,
-      const GetFileInfoCallback& callback,
-      const base::File::Info& file_info);
+  void OnDidGetFileInfo(base::SequencedTaskRunner* task_runner,
+                        const base::FilePath& path,
+                        GetFileInfoCallback callback,
+                        const base::File::Info& file_info);
 
   // Called when ReadDirectory method call succeeds. |callback| is invoked to
   // complete the ReadDirectory request.
@@ -165,29 +164,29 @@
   // in any two calls are disjoint), and |has_more| will be true, except for
   // the last chunk.
   void OnDidReadDirectory(base::SequencedTaskRunner* task_runner,
-                          const ReadDirectoryCallback& callback,
+                          ReadDirectoryCallback callback,
                           EntryList file_list,
                           bool has_more);
 
   // Called when MoveFileLocal method call succeeds. |callback| is invoked to
   // complete the MoveFileLocal request.
-  void OnDidMoveFileLocal(const StatusCallback& callback);
+  void OnDidMoveFileLocal(StatusCallback callback);
 
   // Called when CopyFileLocal method call succeeds. |callback| is invoked to
   // complete the CopyFileLocal request.
-  void OnDidCopyFileLocal(const StatusCallback& callback);
+  void OnDidCopyFileLocal(StatusCallback callback);
 
   // Called when CopyInForeignFile method call succeeds. |callback| is invoked
   // to complete the CopyInForeignFile request.
-  void OnDidCopyInForeignFile(const StatusCallback& callback);
+  void OnDidCopyInForeignFile(StatusCallback callback);
 
   // Called when DeleteFile method call succeeeds. |callback| is invoked to
   // complete the DeleteFile request.
-  void OnDidDeleteFile(const StatusCallback& callback);
+  void OnDidDeleteFile(StatusCallback callback);
 
   // Called when DeleteDirectory method call succeeds. |callback| is invoked to
   // complete the DeleteDirectory request.
-  void OnDidDeleteDirectory(const StatusCallback& callback);
+  void OnDidDeleteDirectory(StatusCallback callback);
 
   bool validate_media_files() const;
 
diff --git a/chrome/browser/media_galleries/fileapi/native_media_file_util.cc b/chrome/browser/media_galleries/fileapi/native_media_file_util.cc
index 9da6857f..33acd4c 100644
--- a/chrome/browser/media_galleries/fileapi/native_media_file_util.cc
+++ b/chrome/browser/media_galleries/fileapi/native_media_file_util.cc
@@ -50,16 +50,16 @@
 
 void HoldFileRef(scoped_refptr<storage::ShareableFileReference> file_ref) {}
 
-void DidOpenSnapshot(
-    const storage::AsyncFileUtil::CreateOrOpenCallback& callback,
-    scoped_refptr<storage::ShareableFileReference> file_ref,
-    base::File file) {
+void DidOpenSnapshot(storage::AsyncFileUtil::CreateOrOpenCallback callback,
+                     scoped_refptr<storage::ShareableFileReference> file_ref,
+                     base::File file) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   if (!file.IsValid()) {
-    callback.Run(std::move(file), base::Closure());
+    std::move(callback).Run(std::move(file), base::Closure());
     return;
   }
-  callback.Run(std::move(file), base::Bind(&HoldFileRef, std::move(file_ref)));
+  std::move(callback).Run(std::move(file),
+                          base::Bind(&HoldFileRef, std::move(file_ref)));
 }
 
 }  // namespace
@@ -99,49 +99,52 @@
 void NativeMediaFileUtil::CreatedSnapshotFileForCreateOrOpen(
     base::SequencedTaskRunner* media_task_runner,
     int file_flags,
-    const storage::AsyncFileUtil::CreateOrOpenCallback& callback,
+    storage::AsyncFileUtil::CreateOrOpenCallback callback,
     base::File::Error result,
     const base::File::Info& file_info,
     const base::FilePath& platform_path,
     scoped_refptr<storage::ShareableFileReference> file_ref) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   if (result != base::File::FILE_OK) {
-    callback.Run(base::File(), base::Closure());
+    std::move(callback).Run(base::File(), base::Closure());
     return;
   }
   base::PostTaskAndReplyWithResult(
       media_task_runner, FROM_HERE,
-      base::Bind(&storage::NativeFileUtil::CreateOrOpen, platform_path,
-                 file_flags),
-      base::Bind(&DidOpenSnapshot, callback, std::move(file_ref)));
+      base::BindOnce(&storage::NativeFileUtil::CreateOrOpen, platform_path,
+                     file_flags),
+      base::BindOnce(&DidOpenSnapshot, std::move(callback),
+                     std::move(file_ref)));
 }
 
 void NativeMediaFileUtil::CreateOrOpen(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
     int file_flags,
-    const CreateOrOpenCallback& callback) {
+    CreateOrOpenCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   // Returns an error if any unsupported flag is found.
   if (file_flags & ~(base::File::FLAG_OPEN |
                      base::File::FLAG_READ |
                      base::File::FLAG_WRITE_ATTRIBUTES)) {
-    callback.Run(base::File(base::File::FILE_ERROR_SECURITY), base::Closure());
+    std::move(callback).Run(base::File(base::File::FILE_ERROR_SECURITY),
+                            base::Closure());
     return;
   }
   scoped_refptr<base::SequencedTaskRunner> task_runner = context->task_runner();
   CreateSnapshotFile(
       std::move(context), url,
       base::Bind(&NativeMediaFileUtil::CreatedSnapshotFileForCreateOrOpen,
-                 base::RetainedRef(task_runner), file_flags, callback));
+                 base::RetainedRef(task_runner), file_flags,
+                 std::move(callback)));
 }
 
 void NativeMediaFileUtil::EnsureFileExists(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const EnsureFileExistsCallback& callback) {
+    EnsureFileExistsCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  callback.Run(base::File::FILE_ERROR_SECURITY, false);
+  std::move(callback).Run(base::File::FILE_ERROR_SECURITY, false);
 }
 
 void NativeMediaFileUtil::CreateDirectory(
@@ -149,14 +152,14 @@
     const storage::FileSystemURL& url,
     bool exclusive,
     bool recursive,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   storage::FileSystemOperationContext* context_ptr = context.get();
   const bool success = context_ptr->task_runner()->PostTask(
       FROM_HERE,
       base::BindOnce(&NativeMediaFileUtil::CreateDirectoryOnTaskRunnerThread,
                      weak_factory_.GetWeakPtr(), std::move(context), url,
-                     exclusive, recursive, callback));
+                     exclusive, recursive, std::move(callback)));
   DCHECK(success);
 }
 
@@ -164,28 +167,28 @@
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
     int /* fields */,
-    const GetFileInfoCallback& callback) {
+    GetFileInfoCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   storage::FileSystemOperationContext* context_ptr = context.get();
   const bool success = context_ptr->task_runner()->PostTask(
       FROM_HERE,
       base::BindOnce(&NativeMediaFileUtil::GetFileInfoOnTaskRunnerThread,
                      weak_factory_.GetWeakPtr(), std::move(context), url,
-                     callback));
+                     std::move(callback)));
   DCHECK(success);
 }
 
 void NativeMediaFileUtil::ReadDirectory(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const ReadDirectoryCallback& callback) {
+    ReadDirectoryCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   storage::FileSystemOperationContext* context_ptr = context.get();
   const bool success = context_ptr->task_runner()->PostTask(
       FROM_HERE,
       base::BindOnce(&NativeMediaFileUtil::ReadDirectoryOnTaskRunnerThread,
                      weak_factory_.GetWeakPtr(), std::move(context), url,
-                     callback));
+                     std::move(callback)));
   DCHECK(success);
 }
 
@@ -194,18 +197,18 @@
     const storage::FileSystemURL& url,
     const base::Time& last_access_time,
     const base::Time& last_modified_time,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  callback.Run(base::File::FILE_ERROR_SECURITY);
+  std::move(callback).Run(base::File::FILE_ERROR_SECURITY);
 }
 
 void NativeMediaFileUtil::Truncate(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
     int64_t length,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  callback.Run(base::File::FILE_ERROR_SECURITY);
+  std::move(callback).Run(base::File::FILE_ERROR_SECURITY);
 }
 
 void NativeMediaFileUtil::CopyFileLocal(
@@ -213,8 +216,8 @@
     const storage::FileSystemURL& src_url,
     const storage::FileSystemURL& dest_url,
     CopyOrMoveOption option,
-    const CopyFileProgressCallback& progress_callback,
-    const StatusCallback& callback) {
+    CopyFileProgressCallback progress_callback,
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   storage::FileSystemOperationContext* context_ptr = context.get();
   const bool success = context_ptr->task_runner()->PostTask(
@@ -222,7 +225,7 @@
       base::BindOnce(
           &NativeMediaFileUtil::CopyOrMoveFileLocalOnTaskRunnerThread,
           weak_factory_.GetWeakPtr(), std::move(context), src_url, dest_url,
-          option, true /* copy */, callback));
+          option, true /* copy */, std::move(callback)));
   DCHECK(success);
 }
 
@@ -231,7 +234,7 @@
     const storage::FileSystemURL& src_url,
     const storage::FileSystemURL& dest_url,
     CopyOrMoveOption option,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   storage::FileSystemOperationContext* context_ptr = context.get();
   const bool success = context_ptr->task_runner()->PostTask(
@@ -239,7 +242,7 @@
       base::BindOnce(
           &NativeMediaFileUtil::CopyOrMoveFileLocalOnTaskRunnerThread,
           weak_factory_.GetWeakPtr(), std::move(context), src_url, dest_url,
-          option, false /* copy */, callback));
+          option, false /* copy */, std::move(callback)));
   DCHECK(success);
 }
 
@@ -247,28 +250,28 @@
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const base::FilePath& src_file_path,
     const storage::FileSystemURL& dest_url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   storage::FileSystemOperationContext* context_ptr = context.get();
   const bool success = context_ptr->task_runner()->PostTask(
       FROM_HERE,
       base::BindOnce(&NativeMediaFileUtil::CopyInForeignFileOnTaskRunnerThread,
                      weak_factory_.GetWeakPtr(), std::move(context),
-                     src_file_path, dest_url, callback));
+                     src_file_path, dest_url, std::move(callback)));
   DCHECK(success);
 }
 
 void NativeMediaFileUtil::DeleteFile(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   storage::FileSystemOperationContext* context_ptr = context.get();
   const bool success = context_ptr->task_runner()->PostTask(
       FROM_HERE,
       base::BindOnce(&NativeMediaFileUtil::DeleteFileOnTaskRunnerThread,
                      weak_factory_.GetWeakPtr(), std::move(context), url,
-                     callback));
+                     std::move(callback)));
   DCHECK(success);
 }
 
@@ -276,36 +279,36 @@
 void NativeMediaFileUtil::DeleteDirectory(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   storage::FileSystemOperationContext* context_ptr = context.get();
   const bool success = context_ptr->task_runner()->PostTask(
       FROM_HERE,
       base::BindOnce(&NativeMediaFileUtil::DeleteDirectoryOnTaskRunnerThread,
                      weak_factory_.GetWeakPtr(), std::move(context), url,
-                     callback));
+                     std::move(callback)));
   DCHECK(success);
 }
 
 void NativeMediaFileUtil::DeleteRecursively(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  callback.Run(base::File::FILE_ERROR_INVALID_OPERATION);
+  std::move(callback).Run(base::File::FILE_ERROR_INVALID_OPERATION);
 }
 
 void NativeMediaFileUtil::CreateSnapshotFile(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const CreateSnapshotFileCallback& callback) {
+    CreateSnapshotFileCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   storage::FileSystemOperationContext* context_ptr = context.get();
   const bool success = context_ptr->task_runner()->PostTask(
       FROM_HERE,
       base::BindOnce(&NativeMediaFileUtil::CreateSnapshotFileOnTaskRunnerThread,
                      weak_factory_.GetWeakPtr(), std::move(context), url,
-                     callback));
+                     std::move(callback)));
   DCHECK(success);
 }
 
@@ -314,37 +317,39 @@
     const storage::FileSystemURL& url,
     bool exclusive,
     bool recursive,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK(IsOnTaskRunnerThread(context.get()));
   base::File::Error error =
       CreateDirectorySync(context.get(), url, exclusive, recursive);
   content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
-                                   base::BindOnce(callback, error));
+                                   base::BindOnce(std::move(callback), error));
 }
 
 void NativeMediaFileUtil::GetFileInfoOnTaskRunnerThread(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const GetFileInfoCallback& callback) {
+    GetFileInfoCallback callback) {
   DCHECK(IsOnTaskRunnerThread(context.get()));
   base::File::Info file_info;
   base::File::Error error =
       GetFileInfoSync(context.get(), url, &file_info, NULL);
-  content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
-                                   base::BindOnce(callback, error, file_info));
+  content::BrowserThread::PostTask(
+      content::BrowserThread::IO, FROM_HERE,
+      base::BindOnce(std::move(callback), error, file_info));
 }
 
 void NativeMediaFileUtil::ReadDirectoryOnTaskRunnerThread(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const ReadDirectoryCallback& callback) {
+    ReadDirectoryCallback callback) {
   DCHECK(IsOnTaskRunnerThread(context.get()));
   EntryList entry_list;
   base::File::Error error =
       ReadDirectorySync(context.get(), url, &entry_list);
   content::BrowserThread::PostTask(
       content::BrowserThread::IO, FROM_HERE,
-      base::BindOnce(callback, error, entry_list, false /* has_more */));
+      base::BindOnce(std::move(callback), error, entry_list,
+                     false /* has_more */));
 }
 
 void NativeMediaFileUtil::CopyOrMoveFileLocalOnTaskRunnerThread(
@@ -353,50 +358,50 @@
     const storage::FileSystemURL& dest_url,
     CopyOrMoveOption option,
     bool copy,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK(IsOnTaskRunnerThread(context.get()));
   base::File::Error error =
       CopyOrMoveFileSync(context.get(), src_url, dest_url, option, copy);
   content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
-                                   base::BindOnce(callback, error));
+                                   base::BindOnce(std::move(callback), error));
 }
 
 void NativeMediaFileUtil::CopyInForeignFileOnTaskRunnerThread(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const base::FilePath& src_file_path,
     const storage::FileSystemURL& dest_url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK(IsOnTaskRunnerThread(context.get()));
   base::File::Error error =
       CopyInForeignFileSync(context.get(), src_file_path, dest_url);
   content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
-                                   base::BindOnce(callback, error));
+                                   base::BindOnce(std::move(callback), error));
 }
 
 void NativeMediaFileUtil::DeleteFileOnTaskRunnerThread(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK(IsOnTaskRunnerThread(context.get()));
   base::File::Error error = DeleteFileSync(context.get(), url);
   content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
-                                   base::BindOnce(callback, error));
+                                   base::BindOnce(std::move(callback), error));
 }
 
 void NativeMediaFileUtil::DeleteDirectoryOnTaskRunnerThread(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   DCHECK(IsOnTaskRunnerThread(context.get()));
   base::File::Error error = DeleteDirectorySync(context.get(), url);
   content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
-                                   base::BindOnce(callback, error));
+                                   base::BindOnce(std::move(callback), error));
 }
 
 void NativeMediaFileUtil::CreateSnapshotFileOnTaskRunnerThread(
     std::unique_ptr<storage::FileSystemOperationContext> context,
     const storage::FileSystemURL& url,
-    const CreateSnapshotFileCallback& callback) {
+    CreateSnapshotFileCallback callback) {
   DCHECK(IsOnTaskRunnerThread(context.get()));
   base::File::Info file_info;
   base::FilePath platform_path;
@@ -405,7 +410,8 @@
       context.get(), url, &file_info, &platform_path, &file_ref);
   content::BrowserThread::PostTask(
       content::BrowserThread::IO, FROM_HERE,
-      base::BindOnce(callback, error, file_info, platform_path, file_ref));
+      base::BindOnce(std::move(callback), error, file_info, platform_path,
+                     file_ref));
 }
 
 base::File::Error NativeMediaFileUtil::CreateDirectorySync(
diff --git a/chrome/browser/media_galleries/fileapi/native_media_file_util.h b/chrome/browser/media_galleries/fileapi/native_media_file_util.h
index 1a255adf..47f1302 100644
--- a/chrome/browser/media_galleries/fileapi/native_media_file_util.h
+++ b/chrome/browser/media_galleries/fileapi/native_media_file_util.h
@@ -40,7 +40,7 @@
   static void CreatedSnapshotFileForCreateOrOpen(
       base::SequencedTaskRunner* media_task_runner,
       int file_flags,
-      const storage::AsyncFileUtil::CreateOrOpenCallback& callback,
+      storage::AsyncFileUtil::CreateOrOpenCallback callback,
       base::File::Error result,
       const base::File::Info& file_info,
       const base::FilePath& platform_path,
@@ -51,67 +51,67 @@
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
       int file_flags,
-      const CreateOrOpenCallback& callback) override;
+      CreateOrOpenCallback callback) override;
   void EnsureFileExists(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const EnsureFileExistsCallback& callback) override;
+      EnsureFileExistsCallback callback) override;
   void CreateDirectory(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
       bool exclusive,
       bool recursive,
-      const StatusCallback& callback) override;
+      StatusCallback callback) override;
   void GetFileInfo(std::unique_ptr<storage::FileSystemOperationContext> context,
                    const storage::FileSystemURL& url,
                    int /* fields */,
-                   const GetFileInfoCallback& callback) override;
+                   GetFileInfoCallback callback) override;
   void ReadDirectory(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const ReadDirectoryCallback& callback) override;
+      ReadDirectoryCallback callback) override;
   void Touch(std::unique_ptr<storage::FileSystemOperationContext> context,
              const storage::FileSystemURL& url,
              const base::Time& last_access_time,
              const base::Time& last_modified_time,
-             const StatusCallback& callback) override;
+             StatusCallback callback) override;
   void Truncate(std::unique_ptr<storage::FileSystemOperationContext> context,
                 const storage::FileSystemURL& url,
                 int64_t length,
-                const StatusCallback& callback) override;
+                StatusCallback callback) override;
   void CopyFileLocal(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& src_url,
       const storage::FileSystemURL& dest_url,
       CopyOrMoveOption option,
-      const CopyFileProgressCallback& progress_callback,
-      const StatusCallback& callback) override;
+      CopyFileProgressCallback progress_callback,
+      StatusCallback callback) override;
   void MoveFileLocal(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& src_url,
       const storage::FileSystemURL& dest_url,
       CopyOrMoveOption option,
-      const StatusCallback& callback) override;
+      StatusCallback callback) override;
   void CopyInForeignFile(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const base::FilePath& src_file_path,
       const storage::FileSystemURL& dest_url,
-      const StatusCallback& callback) override;
+      StatusCallback callback) override;
   void DeleteFile(std::unique_ptr<storage::FileSystemOperationContext> context,
                   const storage::FileSystemURL& url,
-                  const StatusCallback& callback) override;
+                  StatusCallback callback) override;
   void DeleteDirectory(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const StatusCallback& callback) override;
+      StatusCallback callback) override;
   void DeleteRecursively(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const StatusCallback& callback) override;
+      StatusCallback callback) override;
   void CreateSnapshotFile(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const CreateSnapshotFileCallback& callback) override;
+      CreateSnapshotFileCallback callback) override;
 
  protected:
   virtual void CreateDirectoryOnTaskRunnerThread(
@@ -119,39 +119,39 @@
       const storage::FileSystemURL& url,
       bool exclusive,
       bool recursive,
-      const StatusCallback& callback);
+      StatusCallback callback);
   virtual void GetFileInfoOnTaskRunnerThread(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const GetFileInfoCallback& callback);
+      GetFileInfoCallback callback);
   virtual void ReadDirectoryOnTaskRunnerThread(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const ReadDirectoryCallback& callback);
+      ReadDirectoryCallback callback);
   virtual void CopyOrMoveFileLocalOnTaskRunnerThread(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& src_url,
       const storage::FileSystemURL& dest_url,
       CopyOrMoveOption option,
       bool copy,
-      const StatusCallback& callback);
+      StatusCallback callback);
   virtual void CopyInForeignFileOnTaskRunnerThread(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const base::FilePath& src_file_path,
       const storage::FileSystemURL& dest_url,
-      const StatusCallback& callback);
+      StatusCallback callback);
   virtual void DeleteFileOnTaskRunnerThread(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const StatusCallback& callback);
+      StatusCallback callback);
   virtual void DeleteDirectoryOnTaskRunnerThread(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const StatusCallback& callback);
+      StatusCallback callback);
   virtual void CreateSnapshotFileOnTaskRunnerThread(
       std::unique_ptr<storage::FileSystemOperationContext> context,
       const storage::FileSystemURL& url,
-      const CreateSnapshotFileCallback& callback);
+      CreateSnapshotFileCallback callback);
 
   // The following methods should only be called on the task runner thread.
 
diff --git a/chrome/browser/metrics/desktop_session_duration/chrome_visibility_observer.cc b/chrome/browser/metrics/desktop_session_duration/chrome_visibility_observer.cc
index 8af71356..03bf8f2b 100644
--- a/chrome/browser/metrics/desktop_session_duration/chrome_visibility_observer.cc
+++ b/chrome/browser/metrics/desktop_session_duration/chrome_visibility_observer.cc
@@ -41,12 +41,16 @@
 }
 
 void ChromeVisibilityObserver::OnBrowserNoLongerActive(Browser* browser) {
-  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-      FROM_HERE,
-      base::BindOnce(&ChromeVisibilityObserver::SendVisibilityChangeEvent,
-                     weak_factory_.GetWeakPtr(), false,
-                     visibility_gap_timeout_),
-      visibility_gap_timeout_);
+  if (visibility_gap_timeout_.InMicroseconds() == 0) {
+    SendVisibilityChangeEvent(false, base::TimeDelta());
+  } else {
+    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+        FROM_HERE,
+        base::BindOnce(&ChromeVisibilityObserver::SendVisibilityChangeEvent,
+                       weak_factory_.GetWeakPtr(), false,
+                       visibility_gap_timeout_),
+        visibility_gap_timeout_);
+  }
 }
 
 void ChromeVisibilityObserver::OnBrowserRemoved(Browser* browser) {
@@ -70,4 +74,9 @@
   visibility_gap_timeout_ = base::TimeDelta::FromSeconds(timeout_seconds);
 }
 
+void ChromeVisibilityObserver::SetVisibilityGapTimeoutForTesting(
+    base::TimeDelta timeout) {
+  visibility_gap_timeout_ = timeout;
+}
+
 }  // namespace metrics
diff --git a/chrome/browser/metrics/desktop_session_duration/chrome_visibility_observer.h b/chrome/browser/metrics/desktop_session_duration/chrome_visibility_observer.h
index a4da31e1..cf87ccc 100644
--- a/chrome/browser/metrics/desktop_session_duration/chrome_visibility_observer.h
+++ b/chrome/browser/metrics/desktop_session_duration/chrome_visibility_observer.h
@@ -16,12 +16,13 @@
   ChromeVisibilityObserver();
   ~ChromeVisibilityObserver() override;
 
- protected:
+ private:
+  friend class ChromeVisibilityObserverInteractiveTest;
+
   // Notifies |DesktopSessionDurationTracker| of visibility changes. Overridden
   // by tests.
   virtual void SendVisibilityChangeEvent(bool active, base::TimeDelta time_ago);
 
- private:
   // Cancels visibility change in case when the browser becomes visible after a
   // short gap.
   void CancelVisibilityChange();
@@ -34,6 +35,8 @@
   // Sets |visibility_gap_timeout_| based on variation params.
   void InitVisibilityGapTimeout();
 
+  void SetVisibilityGapTimeoutForTesting(base::TimeDelta timeout);
+
   // Timeout interval for waiting after loss of visibility. This allows merging
   // two visibility session if they happened very shortly after each other, for
   // example, when user switching between two browser windows.
diff --git a/chrome/browser/metrics/desktop_session_duration/chrome_visibility_observer_browsertest.cc b/chrome/browser/metrics/desktop_session_duration/chrome_visibility_observer_browsertest.cc
deleted file mode 100644
index 602759fd..0000000
--- a/chrome/browser/metrics/desktop_session_duration/chrome_visibility_observer_browsertest.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/metrics/desktop_session_duration/chrome_visibility_observer.h"
-
-#include "base/run_loop.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_window.h"
-#include "chrome/test/base/in_process_browser_test.h"
-#include "chrome/test/base/ui_test_utils.h"
-#include "content/public/test/test_utils.h"
-
-// Mock class for |ChromeVisibilityObserver| for testing.
-class MockChromeVisibilityObserver : public metrics::ChromeVisibilityObserver {
- public:
-  MockChromeVisibilityObserver() : is_active_(false) {}
-
-  bool is_active() const { return is_active_; }
-
- private:
-  void SendVisibilityChangeEvent(bool active,
-                                 base::TimeDelta time_ago) override {
-    is_active_ = active;
-  }
-
-  bool is_active_;
-
-  DISALLOW_COPY_AND_ASSIGN(MockChromeVisibilityObserver);
-};
-
-class ChromeVisibilityObserverBrowserTest : public InProcessBrowserTest {};
-
-// TODO(https://crbug.com/817172): This test is flaky.
-IN_PROC_BROWSER_TEST_F(ChromeVisibilityObserverBrowserTest,
-                       DISABLED_VisibilityTest) {
-  // Deactivate the initial browser window, to make observer start inactive.
-  browser()->window()->Deactivate();
-  base::RunLoop().RunUntilIdle();
-
-  MockChromeVisibilityObserver observer;
-
-  EXPECT_FALSE(observer.is_active());
-  Browser* new_browser = CreateBrowser(browser()->profile());
-  base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(observer.is_active());
-
-  Browser* incognito_browser = CreateIncognitoBrowser();
-  base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(observer.is_active());
-
-  CloseBrowserSynchronously(incognito_browser);
-  base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(observer.is_active());
-
-  CloseBrowserSynchronously(new_browser);
-  base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(observer.is_active());
-
-  CloseBrowserSynchronously(browser());
-  base::RunLoop().RunUntilIdle();
-  EXPECT_FALSE(observer.is_active());
-}
diff --git a/chrome/browser/metrics/desktop_session_duration/chrome_visibility_observer_interactive_uitest.cc b/chrome/browser/metrics/desktop_session_duration/chrome_visibility_observer_interactive_uitest.cc
new file mode 100644
index 0000000..ca326b6
--- /dev/null
+++ b/chrome/browser/metrics/desktop_session_duration/chrome_visibility_observer_interactive_uitest.cc
@@ -0,0 +1,78 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/metrics/desktop_session_duration/chrome_visibility_observer.h"
+
+#include "base/run_loop.h"
+#include "build/build_config.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/interactive_test_utils.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/test/test_utils.h"
+
+namespace metrics {
+// Test class for |ChromeVisibilityObserver|.
+class ChromeVisibilityObserverInteractiveTest
+    : public metrics::ChromeVisibilityObserver,
+      public InProcessBrowserTest {
+ public:
+  ChromeVisibilityObserverInteractiveTest() : is_active_(false) {
+    SetVisibilityGapTimeoutForTesting(base::TimeDelta());
+  }
+
+  bool is_active() const { return is_active_; }
+
+ private:
+  // metrics::ChromeVisibilityObserver:
+  void SendVisibilityChangeEvent(bool active,
+                                 base::TimeDelta time_ago) override {
+    is_active_ = active;
+  }
+
+  bool is_active_;
+
+  DISALLOW_COPY_AND_ASSIGN(ChromeVisibilityObserverInteractiveTest);
+};
+
+// This test doesn't check whether switching between browser windows results in
+// separate sessions or not.
+IN_PROC_BROWSER_TEST_F(ChromeVisibilityObserverInteractiveTest,
+                       VisibilityTest) {
+  // Observer should now be active as there is one active browser.
+  EXPECT_TRUE(is_active());
+
+// BrowserWindow::Deactivate() not implemented on Mac (https://crbug.com/51364).
+#if !defined(OS_MACOSX)
+  // Deactivating and activating the browser should affect the observer
+  // accordingly.
+  browser()->window()->Deactivate();
+  EXPECT_FALSE(is_active());
+  browser()->window()->Activate();
+  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
+  EXPECT_TRUE(is_active());
+#endif  // !defined(OS_MACOSX)
+
+  // Creating and closing new browsers should keep the observer active.
+  Browser* new_browser = CreateBrowser(browser()->profile());
+  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(new_browser));
+  EXPECT_TRUE(is_active());
+
+  Browser* incognito_browser = CreateIncognitoBrowser();
+  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(incognito_browser));
+  EXPECT_TRUE(is_active());
+
+  CloseBrowserSynchronously(incognito_browser);
+  EXPECT_TRUE(is_active());
+
+  CloseBrowserSynchronously(new_browser);
+  EXPECT_TRUE(is_active());
+
+  // Closing last browser should set observer not active.
+  CloseBrowserSynchronously(browser());
+  EXPECT_FALSE(is_active());
+}
+
+}  // namespace metrics
diff --git a/chrome/browser/metrics/metrics_memory_details.cc b/chrome/browser/metrics/metrics_memory_details.cc
index a67b3ffe..b57bedf 100644
--- a/chrome/browser/metrics/metrics_memory_details.cc
+++ b/chrome/browser/metrics/metrics_memory_details.cc
@@ -157,5 +157,10 @@
   SiteDetails::UpdateHistograms(browser.site_data, all_renderer_count,
                                 non_renderer_count);
 
+  UMA_HISTOGRAM_COUNTS_100("Memory.ProcessCount",
+                           static_cast<int>(browser.processes.size()));
+  UMA_HISTOGRAM_COUNTS_100("Memory.ExtensionProcessCount", extension_count);
+  UMA_HISTOGRAM_COUNTS_100("Memory.RendererProcessCount", renderer_count);
+
   leveldb_chrome::UpdateHistograms();
 }
diff --git a/chrome/browser/metrics/network_quality_estimator_provider_impl.cc b/chrome/browser/metrics/network_quality_estimator_provider_impl.cc
index d3c4a94..017803b 100644
--- a/chrome/browser/metrics/network_quality_estimator_provider_impl.cc
+++ b/chrome/browser/metrics/network_quality_estimator_provider_impl.cc
@@ -7,6 +7,7 @@
 #include "base/sequenced_task_runner.h"
 #include "chrome/browser/io_thread.h"
 #include "content/public/browser/browser_thread.h"
+#include "net/url_request/url_request_context.h"
 
 namespace net {
 class NetworkQualityEstimator;
@@ -21,8 +22,16 @@
     IOThread* io_thread) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
 
-  // It is safe to run |io_callback| here since it is guaranteed to be non-null.
-  io_callback.Run(io_thread->globals()->network_quality_estimator.get());
+  net::NetworkQualityEstimator* network_quality_estimator =
+      io_thread->globals()->system_request_context->network_quality_estimator();
+  // |network_quality_estimator| may be nullptr when running the network service
+  // out of process.
+  // TODO(mmenke):  Hook this up through a Mojo API.
+  if (network_quality_estimator) {
+    // It is safe to run |io_callback| here since it is guaranteed to be
+    // non-null.
+    io_callback.Run(network_quality_estimator);
+  }
 }
 
 }  // namespace
diff --git a/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc b/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc
index 03989bc..3f1723c 100644
--- a/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc
+++ b/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc
@@ -221,160 +221,134 @@
  protected:
   std::unique_ptr<ukm::TestAutoSetUkmRecorder> test_ukm_recorder_;
 
-  void CheckMetricWithName(ukm::SourceId source_id,
+  void CheckMetricWithName(const ukm::mojom::UkmEntry* entry,
                            const char* name,
-                           std::function<bool(int64_t)> check,
-                           size_t metric_count) {
-    std::vector<int64_t> metrics = test_ukm_recorder_->GetMetricValues(
-        source_id, UkmEntry::kEntryName, name);
-    EXPECT_EQ(metric_count, metrics.size()) << name;
-    if (metrics.size() > 0) {
-      // The check should be performed on the last entry.
-      int64_t metric = metrics.back();
-      EXPECT_TRUE(check(metric)) << name;
-    }
+                           std::function<bool(int64_t)> check) {
+    const int64_t* value = test_ukm_recorder_->GetEntryMetric(entry, name);
+    EXPECT_TRUE(value && check(*value)) << name;
   }
 
-  void CheckExactMetricWithName(ukm::SourceId source_id,
+  void CheckExactMetricWithName(const ukm::mojom::UkmEntry* entry,
                                 const char* name,
-                                int64_t expected_value,
-                                size_t metric_count) {
-    CheckMetricWithName(source_id, name,
-                        [expected_value](int64_t value) -> bool {
-                          return value == expected_value;
-                        },
-                        metric_count);
+                                int64_t expected_value) {
+    CheckMetricWithName(entry, name, [expected_value](int64_t value) -> bool {
+      return value == expected_value;
+    });
   }
 
-  void CheckMemoryMetricWithName(ukm::SourceId source_id,
+  void CheckMemoryMetricWithName(const ukm::mojom::UkmEntry* entry,
                                  const char* name,
-                                 bool can_be_zero,
-                                 size_t metric_count = 1u) {
-    CheckMetricWithName(source_id, name,
-                        [can_be_zero](int64_t value) -> bool {
-                          return value >= (can_be_zero ? 0 : 1) &&
-                                 value <= 4000;
-                        },
-                        metric_count);
+                                 bool can_be_zero) {
+    CheckMetricWithName(entry, name, [can_be_zero](int64_t value) -> bool {
+      return value >= (can_be_zero ? 0 : 1) && value <= 4000;
+    });
   }
 
-  void CheckTimeMetricWithName(ukm::SourceId source_id,
-                               const char* name,
-                               size_t metric_count = 1u) {
-    CheckMetricWithName(
-        source_id, name,
-        [](int64_t value) -> bool { return value >= 0 && value <= 10; },
-        metric_count);
+  void CheckTimeMetricWithName(const ukm::mojom::UkmEntry* entry,
+                               const char* name) {
+    CheckMetricWithName(entry, name, [](int64_t value) -> bool {
+      return value >= 0 && value <= 10;
+    });
   }
 
-  void CheckAllUkmSources(size_t metric_count = 1u) {
-    std::set<ukm::SourceId> source_ids = test_ukm_recorder_->GetSourceIds();
-    bool has_browser_source = false;
-    bool has_renderer_source = false;
-    bool has_total_source = false;
-    for (auto source_id : source_ids) {
-      // Ignore sources with no entries.
-      const ukm::UkmSource* source =
-          test_ukm_recorder_->GetSourceForSourceId(source_id);
-      if (source &&
-          !test_ukm_recorder_->HasEntry(*source, UkmEntry::kEntryName))
-        continue;
-      if (ProcessHasTypeForSource(source_id, ProcessType::BROWSER)) {
-        has_browser_source = true;
-        CheckUkmBrowserSource(source_id, 1);
-      } else if (ProcessHasTypeForSource(source_id, ProcessType::RENDERER)) {
-        // Renderer metrics associate with navigation's source, instead of
-        // creating a new one.
-        has_renderer_source = true;
-        CheckUkmRendererSource(source_id, metric_count);
-      } else if (ProcessHasTypeForSource(source_id, ProcessType::GPU)) {
-        CheckUkmGPUSource(source_id, 1);
+  void CheckAllUkmEntries(size_t entry_count = 1u) {
+    const auto& entries =
+        test_ukm_recorder_->GetEntriesByName(UkmEntry::kEntryName);
+    size_t browser_entry_count = 0;
+    size_t renderer_entry_count = 0;
+    size_t total_entry_count = 0;
+
+    for (const auto* entry : entries) {
+      if (ProcessHasTypeForEntry(entry, ProcessType::BROWSER)) {
+        browser_entry_count++;
+        CheckUkmBrowserEntry(entry);
+      } else if (ProcessHasTypeForEntry(entry, ProcessType::RENDERER)) {
+        renderer_entry_count++;
+        CheckUkmRendererEntry(entry);
+      } else if (ProcessHasTypeForEntry(entry, ProcessType::GPU)) {
+        CheckUkmGPUEntry(entry);
       } else {
         // This must be Total2.
-        has_total_source = true;
+        total_entry_count++;
         CheckMemoryMetricWithName(
-            source_id, UkmEntry::kTotal2_PrivateMemoryFootprintName, false, 1);
+            entry, UkmEntry::kTotal2_PrivateMemoryFootprintName, false);
       }
     }
-    EXPECT_TRUE(has_browser_source);
-    EXPECT_TRUE(has_renderer_source);
-    EXPECT_TRUE(has_total_source);
+    EXPECT_EQ(entry_count, browser_entry_count);
+    EXPECT_EQ(entry_count, total_entry_count);
+
+    EXPECT_GE(renderer_entry_count, entry_count);
   }
 
-  void CheckUkmRendererSource(ukm::SourceId source_id, size_t metric_count) {
+  void CheckUkmRendererEntry(const ukm::mojom::UkmEntry* entry) {
 #if !defined(OS_WIN)
-    CheckMemoryMetricWithName(source_id, UkmEntry::kMallocName, false,
-                              metric_count);
+    CheckMemoryMetricWithName(entry, UkmEntry::kMallocName, false);
 #endif
 #if !defined(OS_MACOSX)
-    CheckMemoryMetricWithName(source_id, UkmEntry::kResidentName, false,
-                              metric_count);
+    CheckMemoryMetricWithName(entry, UkmEntry::kResidentName, false);
 #endif
-    CheckMemoryMetricWithName(source_id, UkmEntry::kPrivateMemoryFootprintName,
-                              false, metric_count);
-    CheckMemoryMetricWithName(source_id, UkmEntry::kBlinkGCName, true,
-                              metric_count);
-    CheckMemoryMetricWithName(source_id, UkmEntry::kPartitionAllocName, true,
-                              metric_count);
-    CheckMemoryMetricWithName(source_id, UkmEntry::kV8Name, true, metric_count);
-    CheckMemoryMetricWithName(source_id, UkmEntry::kNumberOfExtensionsName,
-                              true, metric_count);
-    CheckTimeMetricWithName(source_id, UkmEntry::kUptimeName, metric_count);
+    CheckMemoryMetricWithName(entry, UkmEntry::kPrivateMemoryFootprintName,
+                              false);
+    CheckMemoryMetricWithName(entry, UkmEntry::kBlinkGCName, true);
+    CheckMemoryMetricWithName(entry, UkmEntry::kPartitionAllocName, true);
+    CheckMemoryMetricWithName(entry, UkmEntry::kV8Name, true);
+    CheckMemoryMetricWithName(entry, UkmEntry::kNumberOfExtensionsName, true);
+    CheckTimeMetricWithName(entry, UkmEntry::kUptimeName);
 
-    CheckMemoryMetricWithName(source_id, UkmEntry::kNumberOfDocumentsName, true,
-                              metric_count);
-    CheckMemoryMetricWithName(source_id, UkmEntry::kNumberOfFramesName, true,
-                              metric_count);
-    CheckMemoryMetricWithName(source_id, UkmEntry::kNumberOfLayoutObjectsName,
-                              true, metric_count);
-    CheckMemoryMetricWithName(source_id, UkmEntry::kNumberOfNodesName, true,
-                              metric_count);
+    CheckMemoryMetricWithName(entry, UkmEntry::kNumberOfDocumentsName, true);
+    CheckMemoryMetricWithName(entry, UkmEntry::kNumberOfFramesName, true);
+    CheckMemoryMetricWithName(entry, UkmEntry::kNumberOfLayoutObjectsName,
+                              true);
+    CheckMemoryMetricWithName(entry, UkmEntry::kNumberOfNodesName, true);
   }
 
-  void CheckUkmBrowserSource(ukm::SourceId source_id,
-                             size_t metric_count = 1u) {
+  void CheckUkmBrowserEntry(const ukm::mojom::UkmEntry* entry) {
 #if !defined(OS_WIN)
-    CheckMemoryMetricWithName(source_id, UkmEntry::kMallocName, false,
-                              metric_count);
+    CheckMemoryMetricWithName(entry, UkmEntry::kMallocName, false);
 #endif
 #if !defined(OS_MACOSX)
-    CheckMemoryMetricWithName(source_id, UkmEntry::kResidentName, false,
-                              metric_count);
+    CheckMemoryMetricWithName(entry, UkmEntry::kResidentName, false);
 #endif
-    CheckMemoryMetricWithName(source_id, UkmEntry::kPrivateMemoryFootprintName,
-                              false, metric_count);
+    CheckMemoryMetricWithName(entry, UkmEntry::kPrivateMemoryFootprintName,
+                              false);
 
-    CheckTimeMetricWithName(source_id, UkmEntry::kUptimeName, metric_count);
+    CheckTimeMetricWithName(entry, UkmEntry::kUptimeName);
   }
 
-  void CheckUkmGPUSource(ukm::SourceId source_id, size_t metric_count = 1u) {
-    CheckTimeMetricWithName(source_id, UkmEntry::kUptimeName, metric_count);
+  void CheckUkmGPUEntry(const ukm::mojom::UkmEntry* entry) {
+    CheckTimeMetricWithName(entry, UkmEntry::kUptimeName);
   }
 
-  bool ProcessHasTypeForSource(ukm::SourceId source_id,
-                               ProcessType process_type) {
-    std::vector<int64_t> metrics = test_ukm_recorder_->GetMetricValues(
-        source_id, UkmEntry::kEntryName, UkmEntry::kProcessTypeName);
-
-    return std::find(metrics.begin(), metrics.end(),
-                     static_cast<int64_t>(process_type)) != metrics.end();
+  bool ProcessHasTypeForEntry(const ukm::mojom::UkmEntry* entry,
+                              ProcessType process_type) {
+    const int64_t* value =
+        test_ukm_recorder_->GetEntryMetric(entry, UkmEntry::kProcessTypeName);
+    return value && *value == static_cast<int64_t>(process_type);
   }
 
   void CheckPageInfoUkmMetrics(GURL url,
                                bool is_visible,
-                               size_t metric_count = 1u) {
-    const ukm::UkmSource* source = test_ukm_recorder_->GetSourceForUrl(url);
-    EXPECT_TRUE(source) << "Ukm Source for Renderer URL not found";
-    // Only renderer processes has an associated URL.
-    EXPECT_TRUE(ProcessHasTypeForSource(source->id(), ProcessType::RENDERER));
-
-    CheckExactMetricWithName(source->id(), UkmEntry::kIsVisibleName, is_visible,
-                             metric_count);
-    CheckTimeMetricWithName(
-        source->id(), UkmEntry::kTimeSinceLastNavigationName, metric_count);
-    CheckTimeMetricWithName(source->id(),
-                            UkmEntry::kTimeSinceLastVisibilityChangeName,
-                            metric_count);
+                               size_t entry_count = 1u) {
+    const auto& entries =
+        test_ukm_recorder_->GetEntriesByName(UkmEntry::kEntryName);
+    size_t found_count = false;
+    const ukm::mojom::UkmEntry* last_entry = nullptr;
+    for (const auto* entry : entries) {
+      const ukm::UkmSource* source =
+          test_ukm_recorder_->GetSourceForSourceId(entry->source_id);
+      if (!source || source->url() != url)
+        continue;
+      if (!test_ukm_recorder_->EntryHasMetric(entry, UkmEntry::kIsVisibleName))
+        continue;
+      found_count++;
+      last_entry = entry;
+      EXPECT_TRUE(ProcessHasTypeForEntry(entry, ProcessType::RENDERER));
+      CheckTimeMetricWithName(entry, UkmEntry::kTimeSinceLastNavigationName);
+      CheckTimeMetricWithName(entry,
+                              UkmEntry::kTimeSinceLastVisibilityChangeName);
+    }
+    CheckExactMetricWithName(last_entry, UkmEntry::kIsVisibleName, is_visible);
+    EXPECT_EQ(entry_count, found_count);
   }
 
 #if BUILDFLAG(ENABLE_EXTENSIONS)
@@ -456,7 +430,7 @@
   run_loop.Run();
 
   CheckAllMemoryMetrics(histogram_tester, 1);
-  CheckAllUkmSources();
+  CheckAllUkmEntries();
   CheckPageInfoUkmMetrics(url, true);
 }
 
@@ -504,7 +478,7 @@
 
   CheckAllMemoryMetrics(histogram_tester, 1, 1, 2);
   // Extension processes do not have page_info.
-  CheckAllUkmSources();
+  CheckAllUkmEntries();
   CheckPageInfoUkmMetrics(url, true);
 }
 
@@ -549,7 +523,7 @@
 
   // No extensions should be observed
   CheckAllMemoryMetrics(histogram_tester, 1, 1, 0);
-  CheckAllUkmSources();
+  CheckAllUkmEntries();
   CheckPageInfoUkmMetrics(url, true);
 }
 
@@ -596,11 +570,15 @@
   run_loop.Run();
 
   CheckAllMemoryMetrics(histogram_tester, 1, 1, 1);
-  CheckAllUkmSources();
+  CheckAllUkmEntries();
   // When hosts share a process, no unique URL is identified, therefore no page
   // info.
-  EXPECT_FALSE(test_ukm_recorder_->HasEntry(
-      *test_ukm_recorder_->GetSourceForUrl(url), UkmEntry::kEntryName));
+  const auto& entries =
+      test_ukm_recorder_->GetEntriesByName(UkmEntry::kEntryName);
+  for (const auto* entry : entries) {
+    EXPECT_EQ(nullptr,
+              test_ukm_recorder_->GetSourceForSourceId(entry->source_id));
+  }
 }
 #endif  // BUILDFLAG(ENABLE_EXTENSIONS)
 
@@ -660,7 +638,7 @@
                   MemoryDumpType::EXPLICITLY_TRIGGERED))));
 
   CheckAllMemoryMetrics(histogram_tester, 1);
-  CheckAllUkmSources();
+  CheckAllUkmEntries();
   CheckPageInfoUkmMetrics(url, true);
 }
 
@@ -692,7 +670,7 @@
   run_loop.Run();
 
   CheckAllMemoryMetrics(histogram_tester, count);
-  CheckAllUkmSources(count);
+  CheckAllUkmEntries(count);
   CheckPageInfoUkmMetrics(url, true, count);
 }
 
@@ -733,9 +711,10 @@
   }
 
   CheckAllMemoryMetrics(histogram_tester, 1, 2);
-  CheckAllUkmSources();
+  CheckAllUkmEntries();
   CheckPageInfoUkmMetrics(url1, true /* is_visible */);
   CheckPageInfoUkmMetrics(url2, false /* is_visible */);
+
   tab1->WasHidden();
   tab2->WasShown();
   {
@@ -747,7 +726,7 @@
     run_loop.Run();
   }
   CheckAllMemoryMetrics(histogram_tester, 2, 2);
-  CheckAllUkmSources(2);
+  CheckAllUkmEntries(2);
   CheckPageInfoUkmMetrics(url1, false /* is_visible */, 2);
   CheckPageInfoUkmMetrics(url2, true /* is_visible */, 2);
 }
diff --git a/chrome/browser/metrics/process_memory_metrics_emitter_unittest.cc b/chrome/browser/metrics/process_memory_metrics_emitter_unittest.cc
index b9ed457..e80a483 100644
--- a/chrome/browser/metrics/process_memory_metrics_emitter_unittest.cc
+++ b/chrome/browser/metrics/process_memory_metrics_emitter_unittest.cc
@@ -83,12 +83,12 @@
                             const std::string& dump_name,
                             const std::string& metric_name,
                             uint64_t value) {
-  auto it = pmd->chrome_dump->entries_for_allocator_dumps.find(dump_name);
-  if (it == pmd->chrome_dump->entries_for_allocator_dumps.end()) {
+  auto it = pmd->chrome_allocator_dumps.find(dump_name);
+  if (it == pmd->chrome_allocator_dumps.end()) {
     memory_instrumentation::mojom::AllocatorMemDumpPtr amd(
         memory_instrumentation::mojom::AllocatorMemDump::New());
     amd->numeric_entries.insert(std::make_pair(metric_name, value));
-    pmd->chrome_dump->entries_for_allocator_dumps.insert(
+    pmd->chrome_allocator_dumps.insert(
         std::make_pair(dump_name, std::move(amd)));
   } else {
     it->second->numeric_entries.insert(std::make_pair(metric_name, value));
@@ -121,7 +121,6 @@
   ProcessMemoryDumpPtr pmd(
       memory_instrumentation::mojom::ProcessMemoryDump::New());
   pmd->process_type = ProcessType::BROWSER;
-  pmd->chrome_dump = memory_instrumentation::mojom::ChromeMemDump::New();
   SetAllocatorDumpMetric(pmd, "malloc", "effective_size",
                          metrics_mb["Malloc"] * 1024 * 1024);
   OSMemDumpPtr os_dump =
@@ -163,7 +162,6 @@
   ProcessMemoryDumpPtr pmd(
       memory_instrumentation::mojom::ProcessMemoryDump::New());
   pmd->process_type = ProcessType::RENDERER;
-  pmd->chrome_dump = memory_instrumentation::mojom::ChromeMemDump::New();
   SetAllocatorDumpMetric(pmd, "malloc", "effective_size",
                          metrics_mb_or_count["Malloc"] * 1024 * 1024);
   SetAllocatorDumpMetric(pmd, "partition_alloc", "effective_size",
@@ -233,7 +231,6 @@
   ProcessMemoryDumpPtr pmd(
       memory_instrumentation::mojom::ProcessMemoryDump::New());
   pmd->process_type = ProcessType::GPU;
-  pmd->chrome_dump = memory_instrumentation::mojom::ChromeMemDump::New();
   SetAllocatorDumpMetric(pmd, "malloc", "effective_size",
                          metrics_mb["Malloc"] * 1024 * 1024);
   SetAllocatorDumpMetric(pmd, "gpu/gl", "effective_size",
diff --git a/chrome/browser/metrics/ukm_browsertest.cc b/chrome/browser/metrics/ukm_browsertest.cc
index 841fc28..be7505f29 100644
--- a/chrome/browser/metrics/ukm_browsertest.cc
+++ b/chrome/browser/metrics/ukm_browsertest.cc
@@ -374,6 +374,10 @@
 }
 
 // Make sure that UKM is disabled when metrics consent is revoked.
+// Keep in sync with UkmTest.testMetricConsent in
+// chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/
+// UkmTest.java.
+
 IN_PROC_BROWSER_TEST_F(UkmBrowserTest, MetricsConsentCheck) {
   MetricsConsentOverride metrics_consent(true);
 
@@ -405,6 +409,9 @@
 }
 
 // Make sure that providing consent doesn't enable UKM when sync is disabled.
+// Keep in sync with UkmTest.consentAddedButNoSyncCheck in
+// chrome/android/sync_shell/javatests/src/org/chromium/chrome/browser/sync/
+// UkmTest.java.
 IN_PROC_BROWSER_TEST_F(UkmBrowserTest, ConsentAddedButNoSyncCheck) {
   MetricsConsentOverride metrics_consent(false);
 
diff --git a/chrome/browser/net/nqe/ui_network_quality_estimator_service.cc b/chrome/browser/net/nqe/ui_network_quality_estimator_service.cc
index 08cbedb..fc49bea5 100644
--- a/chrome/browser/net/nqe/ui_network_quality_estimator_service.cc
+++ b/chrome/browser/net/nqe/ui_network_quality_estimator_service.cc
@@ -24,6 +24,7 @@
 #include "net/nqe/network_qualities_prefs_manager.h"
 #include "net/nqe/network_quality.h"
 #include "net/nqe/rtt_throughput_estimates_observer.h"
+#include "net/url_request/url_request_context.h"
 
 namespace {
 
@@ -68,12 +69,17 @@
                       IOThread* io_thread) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
-  // Avoid null pointer referencing during browser shutdown.
-  if (!io_thread->globals()->network_quality_estimator)
+  // Avoid null pointer referencing during browser shutdown, or when the network
+  // service is running out of process.
+  if (!io_thread->globals()->system_request_context ||
+      !io_thread->globals()
+           ->system_request_context->network_quality_estimator()) {
     return;
+  }
 
   prefs_manager->InitializeOnNetworkThread(
-      io_thread->globals()->network_quality_estimator.get());
+      io_thread->globals()
+          ->system_request_context->network_quality_estimator());
 }
 
 }  // namespace
@@ -102,10 +108,15 @@
 
   void InitializeOnIOThread(IOThread* io_thread) {
     DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-    if (!io_thread->globals()->network_quality_estimator)
+
+    if (!io_thread->globals()->system_request_context ||
+        !io_thread->globals()
+             ->system_request_context->network_quality_estimator()) {
       return;
+    }
     network_quality_estimator_ =
-        io_thread->globals()->network_quality_estimator.get();
+        io_thread->globals()
+            ->system_request_context->network_quality_estimator();
     if (!network_quality_estimator_)
       return;
     network_quality_estimator_->AddEffectiveConnectionTypeObserver(this);
diff --git a/chrome/browser/net/nqe/ui_network_quality_estimator_service_test_util.cc b/chrome/browser/net/nqe/ui_network_quality_estimator_service_test_util.cc
index 24e9c53..175084b 100644
--- a/chrome/browser/net/nqe/ui_network_quality_estimator_service_test_util.cc
+++ b/chrome/browser/net/nqe/ui_network_quality_estimator_service_test_util.cc
@@ -10,6 +10,7 @@
 #include "chrome/browser/io_thread.h"
 #include "content/public/browser/browser_thread.h"
 #include "net/nqe/network_quality_estimator.h"
+#include "net/url_request/url_request_context.h"
 
 namespace nqe_test_util {
 
@@ -19,20 +20,16 @@
 // EffectiveConnectionTypeObservers.
 void OverrideEffectiveConnectionTypeOnIO(net::EffectiveConnectionType type,
                                          IOThread* io_thread) {
-  if (!io_thread->globals()->network_quality_estimator)
-    return;
   net::NetworkQualityEstimator* network_quality_estimator =
-      io_thread->globals()->network_quality_estimator.get();
+      io_thread->globals()->system_request_context->network_quality_estimator();
   if (!network_quality_estimator)
     return;
   network_quality_estimator->ReportEffectiveConnectionTypeForTesting(type);
 }
 
 void OverrideRTTsAndWaitOnIO(base::TimeDelta rtt, IOThread* io_thread) {
-  if (!io_thread->globals()->network_quality_estimator)
-    return;
   net::NetworkQualityEstimator* network_quality_estimator =
-      io_thread->globals()->network_quality_estimator.get();
+      io_thread->globals()->system_request_context->network_quality_estimator();
   if (!network_quality_estimator)
     return;
   network_quality_estimator->ReportRTTsAndThroughputForTesting(rtt, rtt, -1);
diff --git a/chrome/browser/net/profile_network_context_service.cc b/chrome/browser/net/profile_network_context_service.cc
index 3d418fcf..770545c 100644
--- a/chrome/browser/net/profile_network_context_service.cc
+++ b/chrome/browser/net/profile_network_context_service.cc
@@ -28,7 +28,7 @@
 #include "content/public/browser/storage_partition.h"
 #include "content/public/common/service_names.mojom.h"
 #include "mojo/public/cpp/bindings/associated_interface_ptr.h"
-#include "net/net_features.h"
+#include "net/net_buildflags.h"
 #include "services/network/public/cpp/features.h"
 
 ProfileNetworkContextService::ProfileNetworkContextService(Profile* profile)
diff --git a/chrome/browser/net/system_network_context_manager.cc b/chrome/browser/net/system_network_context_manager.cc
index b1976dd3..6f9e461 100644
--- a/chrome/browser/net/system_network_context_manager.cc
+++ b/chrome/browser/net/system_network_context_manager.cc
@@ -24,7 +24,7 @@
 #include "content/public/common/content_features.h"
 #include "content/public/common/service_names.mojom.h"
 #include "mojo/public/cpp/bindings/associated_interface_ptr.h"
-#include "net/net_features.h"
+#include "net/net_buildflags.h"
 #include "services/network/network_service.h"
 #include "services/network/public/cpp/features.h"
 
diff --git a/chrome/browser/page_load_metrics/observers/OWNERS b/chrome/browser/page_load_metrics/observers/use_counter/OWNERS
similarity index 100%
rename from chrome/browser/page_load_metrics/observers/OWNERS
rename to chrome/browser/page_load_metrics/observers/use_counter/OWNERS
diff --git a/chrome/browser/page_load_metrics/observers/use_counter/ukm_features.cc b/chrome/browser/page_load_metrics/observers/use_counter/ukm_features.cc
index 0ad00ff..0dff51d 100644
--- a/chrome/browser/page_load_metrics/observers/use_counter/ukm_features.cc
+++ b/chrome/browser/page_load_metrics/observers/use_counter/ukm_features.cc
@@ -25,6 +25,7 @@
           WebFeature::kMixedContentVideo, WebFeature::kMixedContentPlugin,
           WebFeature::kOpenerNavigationWithoutGesture,
           WebFeature::kUsbRequestDevice, WebFeature::kXMLHttpRequestSynchronous,
+          WebFeature::kPaymentHandler,
       }));
   return opt_in_features.count(feature);
 }
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
index 3c65857d..f2d7d2d 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
+++ b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
@@ -1302,10 +1302,10 @@
   std::vector<int64_t> ukm_features;
   for (const auto* entry : entries) {
     test_ukm_recorder_->ExpectEntrySourceHasUrl(entry, url);
-    const auto* metric =
-        test_ukm_recorder_->FindMetric(entry, internal::kUkmUseCounterFeature);
+    const auto* metric = test_ukm_recorder_->GetEntryMetric(
+        entry, internal::kUkmUseCounterFeature);
     EXPECT_TRUE(metric);
-    ukm_features.push_back(metric->value);
+    ukm_features.push_back(*metric);
   }
   EXPECT_THAT(
       ukm_features,
@@ -1340,10 +1340,10 @@
   std::vector<int64_t> ukm_features;
   for (const auto* entry : entries) {
     test_ukm_recorder_->ExpectEntrySourceHasUrl(entry, url);
-    const auto* metric =
-        test_ukm_recorder_->FindMetric(entry, internal::kUkmUseCounterFeature);
+    const auto* metric = test_ukm_recorder_->GetEntryMetric(
+        entry, internal::kUkmUseCounterFeature);
     EXPECT_TRUE(metric);
-    ukm_features.push_back(metric->value);
+    ukm_features.push_back(*metric);
   }
   EXPECT_THAT(ukm_features,
               UnorderedElementsAre(
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc
index d99cf7c..110ad68 100644
--- a/chrome/browser/pdf/pdf_extension_test.cc
+++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -947,7 +947,16 @@
   EXPECT_EQ(base::ASCIIToUTF16("test.pdf"), GetActiveWebContents()->GetTitle());
 }
 
-IN_PROC_BROWSER_TEST_F(PDFExtensionTest, MultipleDomains) {
+// For both PDFExtensionTest and PDFIsolatedExtensionTest, MultipleDomains case
+// flakily times out on Win7 Tests (dbg)(1) and win_chromium_dbg_ng bots.
+// https://crbug.com/825038
+#if defined(OS_WIN) && !defined(NDEBUG)
+#define MAYBE_MultipleDomains DISABLED_MultipleDomains
+#else
+#define MAYBE_MultipleDomains MultipleDomains
+#endif
+
+IN_PROC_BROWSER_TEST_F(PDFExtensionTest, MAYBE_MultipleDomains) {
   for (const auto& url :
        {embedded_test_server()->GetURL("a.com", "/pdf/test.pdf"),
         embedded_test_server()->GetURL("b.com", "/pdf/test.pdf"),
@@ -972,7 +981,8 @@
   base::test::ScopedFeatureList features_;
 };
 
-IN_PROC_BROWSER_TEST_F(PDFIsolatedExtensionTest, MultipleDomains) {
+// See MAYBE_MultipleDomains definition, above. https://crbug.com/825038
+IN_PROC_BROWSER_TEST_F(PDFIsolatedExtensionTest, MAYBE_MultipleDomains) {
   for (const auto& url :
        {embedded_test_server()->GetURL("a.com", "/pdf/test.pdf"),
         embedded_test_server()->GetURL("b.com", "/pdf/test.pdf"),
diff --git a/chrome/browser/plugins/plugin_info_host_impl.h b/chrome/browser/plugins/plugin_info_host_impl.h
index 32525858..e1683f3 100644
--- a/chrome/browser/plugins/plugin_info_host_impl.h
+++ b/chrome/browser/plugins/plugin_info_host_impl.h
@@ -23,7 +23,7 @@
 #include "content/public/browser/browser_message_filter.h"
 #include "content/public/browser/browser_thread.h"
 #include "extensions/buildflags/buildflags.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "mojo/public/cpp/bindings/associated_binding.h"
 
 class GURL;
diff --git a/chrome/browser/policy/browser_dm_token_storage.h b/chrome/browser/policy/browser_dm_token_storage.h
new file mode 100644
index 0000000..18a66f1
--- /dev/null
+++ b/chrome/browser/policy/browser_dm_token_storage.h
@@ -0,0 +1,51 @@
+// Copyright 2018 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_POLICY_BROWSER_DM_TOKEN_STORAGE_H_
+#define CHROME_BROWSER_POLICY_BROWSER_DM_TOKEN_STORAGE_H_
+
+#include <memory>
+#include <string>
+
+#include "base/callback_forward.h"
+#include "base/macros.h"
+
+namespace policy {
+
+// Manages storing and retrieving tokens and client ID used to enroll browser
+// instances for enterprise management. The tokens are read from disk or
+// registry once and cached values are returned in subsequent calls.
+//
+// All calls to member functions must be sequenced. It is an error to attempt
+// concurrent store operations.
+class BrowserDMTokenStorage {
+ public:
+  using StoreCallback = base::OnceCallback<void(bool success)>;
+
+  // Returns the global singleton object. Must be called from the UI thread.
+  static BrowserDMTokenStorage* Get();
+  // Returns a client ID unique to the machine.
+  virtual std::string RetrieveClientId() = 0;
+  // Returns the enrollment token, or an empty string if there is none.
+  virtual std::string RetrieveEnrollmentToken() = 0;
+  // Asynchronously stores |dm_token| in the registry and calls |callback| with
+  // a boolean to indicate success or failure. It is an error to attempt
+  // concurrent store operations.
+  virtual void StoreDMToken(const std::string& dm_token,
+                            StoreCallback callback) = 0;
+  // Returns an already stored DM token from the registry or from the cache in
+  // memory. An empty token is returned if no DM token exists on the system or
+  // an error is encountered.
+  virtual std::string RetrieveDMToken() = 0;
+
+ protected:
+  BrowserDMTokenStorage() = default;
+  virtual ~BrowserDMTokenStorage() = default;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(BrowserDMTokenStorage);
+};
+
+}  // namespace policy
+#endif  // CHROME_BROWSER_POLICY_BROWSER_DM_TOKEN_STORAGE_H_
diff --git a/chrome/browser/policy/browser_dm_token_storage_stub.cc b/chrome/browser/policy/browser_dm_token_storage_stub.cc
new file mode 100644
index 0000000..ac822dba
--- /dev/null
+++ b/chrome/browser/policy/browser_dm_token_storage_stub.cc
@@ -0,0 +1,42 @@
+// Copyright 2018 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/policy/browser_dm_token_storage_stub.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/callback.h"
+#include "base/task_scheduler/post_task.h"
+
+namespace policy {
+
+namespace {
+BrowserDMTokenStorage* g_browser_dm_token_storage = nullptr;
+}  // namespace
+
+BrowserDMTokenStorage* BrowserDMTokenStorage::Get() {
+  if (g_browser_dm_token_storage == nullptr)
+    g_browser_dm_token_storage = new BrowserDMTokenStorageStub();
+  return g_browser_dm_token_storage;
+}
+
+std::string BrowserDMTokenStorageStub::RetrieveClientId() {
+  return std::string();
+}
+
+std::string BrowserDMTokenStorageStub::RetrieveEnrollmentToken() {
+  return std::string();
+}
+
+void BrowserDMTokenStorageStub::StoreDMToken(const std::string& dm_token,
+                                             StoreCallback callback) {
+  base::PostTask(FROM_HERE, base::BindOnce(std::move(callback), false));
+}
+
+std::string BrowserDMTokenStorageStub::RetrieveDMToken() {
+  return std::string();
+}
+
+}  // namespace policy
diff --git a/chrome/browser/policy/browser_dm_token_storage_stub.h b/chrome/browser/policy/browser_dm_token_storage_stub.h
new file mode 100644
index 0000000..c4a6853
--- /dev/null
+++ b/chrome/browser/policy/browser_dm_token_storage_stub.h
@@ -0,0 +1,37 @@
+// Copyright 2018 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_POLICY_BROWSER_DM_TOKEN_STORAGE_STUB_H_
+#define CHROME_BROWSER_POLICY_BROWSER_DM_TOKEN_STORAGE_STUB_H_
+
+#include "chrome/browser/policy/browser_dm_token_storage.h"
+
+#include <string>
+
+#include "base/macros.h"
+
+namespace policy {
+
+// No-op implementation of BrowserDMTokenStorage. The global singleton instance
+// can be retrieved by calling BrowserDMTokenStorage::Get().
+class BrowserDMTokenStorageStub : public BrowserDMTokenStorage {
+ public:
+  // Get the global singleton instance by calling BrowserDMTokenStorage::Get().
+  BrowserDMTokenStorageStub() = default;
+  ~BrowserDMTokenStorageStub() override = default;
+
+  // override BrowserDMTokenStorage
+  std::string RetrieveClientId() override;
+  std::string RetrieveEnrollmentToken() override;
+  void StoreDMToken(const std::string& dm_token,
+                    StoreCallback callback) override;
+  std::string RetrieveDMToken() override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(BrowserDMTokenStorageStub);
+};
+
+}  // namespace policy
+
+#endif  // CHROME_BROWSER_POLICY_BROWSER_DM_TOKEN_STORAGE_STUB_H_
diff --git a/chrome/browser/policy/browser_dm_token_storage_win.cc b/chrome/browser/policy/browser_dm_token_storage_win.cc
new file mode 100644
index 0000000..0c6843f
--- /dev/null
+++ b/chrome/browser/policy/browser_dm_token_storage_win.cc
@@ -0,0 +1,283 @@
+// Copyright 2018 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/policy/browser_dm_token_storage_win.h"
+
+#include <windows.h>
+
+#include <comutil.h>
+#include <objbase.h>
+#include <oleauto.h>
+#include <unknwn.h>
+#include <winerror.h>
+#include <wrl/client.h>
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "base/base64.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/callback.h"
+#include "base/logging.h"
+#include "base/no_destructor.h"
+#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/task_runner_util.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "base/win/registry.h"
+#include "base/win/scoped_bstr.h"
+#include "chrome/install_static/install_util.h"
+#include "chrome/installer/util/install_util.h"
+#include "chrome/installer/util/util_constants.h"
+#include "content/public/browser/browser_thread.h"
+
+#if defined(GOOGLE_CHROME_BUILD)
+#include "google_update/google_update_idl.h"
+#endif  // defined(GOOGLE_CHROME_BUILD)
+
+namespace policy {
+
+namespace {
+
+std::string GetClientId() {
+  // For the client id, use the Windows machine GUID.
+  // TODO(crbug.com/821977): Need a backup plan if machine GUID doesn't exist.
+  base::win::RegKey key;
+  LSTATUS status = key.Open(HKEY_LOCAL_MACHINE,
+                            L"SOFTWARE\\Microsoft\\Cryptography", KEY_READ);
+  if (status != ERROR_SUCCESS)
+    return std::string();
+
+  base::string16 value;
+  status = key.ReadValue(L"MachineGuid", &value);
+  if (status != ERROR_SUCCESS)
+    return std::string();
+
+  std::string client_id;
+  if (!base::WideToUTF8(value.c_str(), value.length(), &client_id))
+    return std::string();
+  return client_id;
+}
+
+std::string GetDMToken() {
+  base::win::RegKey key;
+  base::string16 dm_token_key_path;
+  base::string16 dm_token_value_name;
+  InstallUtil::GetMachineLevelUserCloudPolicyDMTokenRegistryPath(
+      &dm_token_key_path, &dm_token_value_name);
+  LONG result = key.Open(HKEY_LOCAL_MACHINE, dm_token_key_path.c_str(),
+                         KEY_QUERY_VALUE | KEY_WOW64_64KEY);
+  if (result != ERROR_SUCCESS)
+    return std::string();
+
+  // At the time of writing (January 2018), the DM token is about 200 bytes
+  // long. The initial size of the buffer should be enough to cover most
+  // realistic future size-increase scenarios, although we still make an effort
+  // to support somewhat larger token sizes just to be safe.
+  constexpr size_t kInitialDMTokenSize = 512;
+  constexpr size_t kMaxDMTokenSize = 4096;
+
+  DWORD size = kInitialDMTokenSize;
+  std::vector<char> raw_value(size);
+  DWORD dtype = REG_NONE;
+  result = key.ReadValue(dm_token_value_name.c_str(), raw_value.data(), &size,
+                         &dtype);
+  if (result == ERROR_MORE_DATA && size <= kMaxDMTokenSize) {
+    raw_value.resize(size);
+    result = key.ReadValue(dm_token_value_name.c_str(), raw_value.data(), &size,
+                           &dtype);
+  }
+
+  if (result != ERROR_SUCCESS || dtype != REG_BINARY || size == 0) {
+    DVLOG(1) << "Failed to get DMToken from Registry.";
+    return std::string();
+  }
+  DCHECK_LE(size, kMaxDMTokenSize);
+  std::string dm_token;
+  dm_token.assign(raw_value.data(), size);
+  return dm_token;
+}
+
+#if defined(GOOGLE_CHROME_BUILD)
+// Explicitly allow DMTokenStorage impersonate the client since some COM code
+// elsewhere in the browser process may have previously used
+// CoInitializeSecurity to set the impersonation level to something other than
+// the default. Ignore errors since an attempt to use Google Update may succeed
+// regardless.
+void ConfigureProxyBlanket(IUnknown* interface_pointer) {
+  ::CoSetProxyBlanket(
+      interface_pointer, RPC_C_AUTHN_DEFAULT, RPC_C_AUTHZ_DEFAULT,
+      COLE_DEFAULT_PRINCIPAL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
+      RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_DYNAMIC_CLOAKING);
+}
+#endif  // defined(GOOGLE_CHROME_BUILD)
+
+bool StoreDMTokenInRegistry(const std::string& token) {
+#if defined(GOOGLE_CHROME_BUILD)
+  if (token.empty())
+    return false;
+
+  Microsoft::WRL::ComPtr<IGoogleUpdate3Web> google_update;
+  HRESULT hr = ::CoCreateInstance(CLSID_GoogleUpdate3WebServiceClass, nullptr,
+                                  CLSCTX_ALL, IID_PPV_ARGS(&google_update));
+  if (FAILED(hr))
+    return false;
+
+  ConfigureProxyBlanket(google_update.Get());
+  Microsoft::WRL::ComPtr<IDispatch> dispatch;
+  hr = google_update->createAppBundleWeb(dispatch.GetAddressOf());
+  if (FAILED(hr))
+    return false;
+
+  Microsoft::WRL::ComPtr<IAppBundleWeb> app_bundle;
+  hr = dispatch.CopyTo(app_bundle.GetAddressOf());
+  if (FAILED(hr))
+    return false;
+
+  dispatch.Reset();
+  ConfigureProxyBlanket(app_bundle.Get());
+  app_bundle->initialize();
+  const wchar_t* app_guid = install_static::GetAppGuid();
+  hr = app_bundle->createInstalledApp(base::win::ScopedBstr(app_guid));
+  if (FAILED(hr))
+    return false;
+
+  hr = app_bundle->get_appWeb(0, dispatch.GetAddressOf());
+  if (FAILED(hr))
+    return false;
+
+  Microsoft::WRL::ComPtr<IAppWeb> app;
+  hr = dispatch.CopyTo(app.GetAddressOf());
+  if (FAILED(hr))
+    return false;
+
+  dispatch.Reset();
+  ConfigureProxyBlanket(app.Get());
+  hr = app->get_command(base::win::ScopedBstr(installer::kCmdStoreDMToken),
+                        dispatch.GetAddressOf());
+  if (FAILED(hr) || !dispatch)
+    return false;
+
+  Microsoft::WRL::ComPtr<IAppCommandWeb> app_command;
+  hr = dispatch.CopyTo(app_command.GetAddressOf());
+  if (FAILED(hr))
+    return false;
+
+  ConfigureProxyBlanket(app_command.Get());
+  std::string token_base64;
+  base::Base64Encode(token, &token_base64);
+  VARIANT var;
+  VariantInit(&var);
+  _variant_t token_var = token_base64.c_str();
+  hr = app_command->execute(token_var, var, var, var, var, var, var, var, var);
+  if (FAILED(hr))
+    return false;
+
+  // TODO(crbug.com/823515): Get the status of the app command execution and
+  // return a corresponding value for |success|. For now, assume that the call
+  // to setup.exe succeeds.
+  return true;
+#else
+  return false;
+#endif  // defined(GOOGLE_CHROME_BUILD)
+}
+
+}  // namespace
+
+BrowserDMTokenStorage* BrowserDMTokenStorage::Get() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  static base::NoDestructor<BrowserDMTokenStorageWin> storage;
+  return storage.get();
+}
+
+BrowserDMTokenStorageWin::BrowserDMTokenStorageWin()
+    : com_sta_task_runner_(
+          base::CreateCOMSTATaskRunnerWithTraits({base::MayBlock()})),
+      is_initialized_(false),
+      weak_factory_(this) {
+  DETACH_FROM_SEQUENCE(sequence_checker_);
+
+  // We don't call InitIfNeeded() here so that the global instance can be
+  // created early during startup if needed. The tokens and client ID are read
+  // from the system as part of the first retrieve or store operation.
+}
+
+BrowserDMTokenStorageWin::~BrowserDMTokenStorageWin() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
+
+std::string BrowserDMTokenStorageWin::RetrieveClientId() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  InitIfNeeded();
+  return client_id_;
+}
+
+std::string BrowserDMTokenStorageWin::RetrieveEnrollmentToken() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  InitIfNeeded();
+  return enrollment_token_;
+}
+
+void BrowserDMTokenStorageWin::StoreDMToken(const std::string& dm_token,
+                                            StoreCallback callback) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(!store_callback_);
+
+  InitIfNeeded();
+
+  dm_token_ = dm_token;
+
+  store_callback_ = std::move(callback);
+
+  base::PostTaskAndReplyWithResult(
+      com_sta_task_runner_.get(), FROM_HERE,
+      base::BindOnce(&StoreDMTokenInRegistry, dm_token),
+      base::BindOnce(&BrowserDMTokenStorageWin::OnDMTokenStored,
+                     weak_factory_.GetWeakPtr()));
+}
+
+std::string BrowserDMTokenStorageWin::RetrieveDMToken() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(!store_callback_);
+
+  InitIfNeeded();
+  return dm_token_;
+}
+
+void BrowserDMTokenStorageWin::InitIfNeeded() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  if (is_initialized_)
+    return;
+
+  is_initialized_ = true;
+  client_id_ = GetClientId();
+  DVLOG(1) << "Client ID = " << client_id_;
+  if (client_id_.empty())
+    return;
+
+  enrollment_token_ = base::WideToUTF8(
+      InstallUtil::GetMachineLevelUserCloudPolicyEnrollmentToken());
+  DVLOG(1) << "Enrollment token = " << enrollment_token_;
+  if (enrollment_token_.empty())
+    return;
+
+  dm_token_ = GetDMToken();
+  DVLOG(1) << "DM Token = " << dm_token_;
+}
+
+void BrowserDMTokenStorageWin::OnDMTokenStored(bool success) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(store_callback_);
+
+  if (!store_callback_.is_null())
+    std::move(store_callback_).Run(success);
+}
+
+}  // namespace policy
diff --git a/chrome/browser/policy/browser_dm_token_storage_win.h b/chrome/browser/policy/browser_dm_token_storage_win.h
new file mode 100644
index 0000000..eeefd90
--- /dev/null
+++ b/chrome/browser/policy/browser_dm_token_storage_win.h
@@ -0,0 +1,60 @@
+// Copyright 2018 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_POLICY_BROWSER_DM_TOKEN_STORAGE_WIN_H_
+#define CHROME_BROWSER_POLICY_BROWSER_DM_TOKEN_STORAGE_WIN_H_
+
+#include "chrome/browser/policy/browser_dm_token_storage.h"
+
+#include <string>
+
+#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/sequence_checker.h"
+#include "base/single_thread_task_runner.h"
+
+namespace policy {
+
+// Implementation of BrowserDMTokenStorage for Windows. The global singleton
+// instance can be retrieved by calling BrowserDMTokenStorage::Get().
+class BrowserDMTokenStorageWin : public BrowserDMTokenStorage {
+ public:
+  // Get the global singleton instance by calling BrowserDMTokenStorage::Get().
+  BrowserDMTokenStorageWin();
+  ~BrowserDMTokenStorageWin() override;
+
+  // override BrowserDMTokenStorage
+  std::string RetrieveClientId() override;
+  std::string RetrieveEnrollmentToken() override;
+  void StoreDMToken(const std::string& dm_token,
+                    StoreCallback callback) override;
+  std::string RetrieveDMToken() override;
+
+ private:
+  // Initialize the DMTokenStorage, reads the |enrollment_token_| and
+  // |dm_token_| from Registry synchronously.
+  void InitIfNeeded();
+
+  void OnDMTokenStored(bool success);
+
+  scoped_refptr<base::SingleThreadTaskRunner> com_sta_task_runner_;
+  StoreCallback store_callback_;
+
+  bool is_initialized_;
+
+  std::string client_id_;
+  std::string enrollment_token_;
+  std::string dm_token_;
+
+  SEQUENCE_CHECKER(sequence_checker_);
+
+  // This should always be the last member of the class.
+  base::WeakPtrFactory<BrowserDMTokenStorageWin> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(BrowserDMTokenStorageWin);
+};
+
+}  // namespace policy
+#endif  // CHROME_BROWSER_POLICY_BROWSER_DM_TOKEN_STORAGE_WIN_H_
diff --git a/chrome/browser/policy/browser_dm_token_storage_win_unittest.cc b/chrome/browser/policy/browser_dm_token_storage_win_unittest.cc
new file mode 100644
index 0000000..c79aa769
--- /dev/null
+++ b/chrome/browser/policy/browser_dm_token_storage_win_unittest.cc
@@ -0,0 +1,125 @@
+// Copyright 2018 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/policy/browser_dm_token_storage_win.h"
+
+#include "base/macros.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/test_reg_util_win.h"
+#include "base/win/registry.h"
+#include "chrome/installer/util/install_util.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::IsEmpty;
+
+namespace policy {
+
+namespace {
+
+constexpr wchar_t kClientId1[] = L"fake-client-id-1";
+constexpr wchar_t kClientId2[] = L"fake-client-id-2";
+constexpr wchar_t kEnrollmentToken1[] = L"fake-enrollment-token-1";
+constexpr wchar_t kEnrollmentToken2[] = L"fake-enrollment-token-2";
+constexpr char kDMToken1[] = "fake-dm-token-1";
+constexpr char kDMToken2[] = "fake-dm-token-2";
+
+}  // namespace
+
+class BrowserDMTokenStorageWinTest : public testing::Test {
+ protected:
+  BrowserDMTokenStorageWinTest() {}
+  ~BrowserDMTokenStorageWinTest() override {}
+
+  void SetUp() override {
+    ASSERT_NO_FATAL_FAILURE(
+        registry_override_manager_.OverrideRegistry(HKEY_LOCAL_MACHINE));
+  }
+
+  bool SetMachineGuid(const wchar_t* machine_guid) {
+    base::win::RegKey key;
+    return (key.Create(HKEY_LOCAL_MACHINE, L"software\\microsoft\\cryptography",
+                       KEY_SET_VALUE) == ERROR_SUCCESS) &&
+           (key.WriteValue(L"MachineGuid", machine_guid) == ERROR_SUCCESS);
+  }
+
+  bool SetEnrollmentToken(const wchar_t* enrollment_token) {
+    base::string16 key_path;
+    base::string16 value_name;
+    InstallUtil::GetMachineLevelUserCloudPolicyEnrollmentTokenRegistryPath(
+        &key_path, &value_name);
+    base::win::RegKey key;
+    return (key.Create(HKEY_LOCAL_MACHINE, key_path.c_str(), KEY_SET_VALUE) ==
+            ERROR_SUCCESS) &&
+           (key.WriteValue(value_name.c_str(), enrollment_token) ==
+            ERROR_SUCCESS);
+  }
+
+  bool SetDMToken(const std::string& dm_token) {
+    base::win::RegKey key;
+    base::string16 dm_token_key_path;
+    base::string16 dm_token_value_name;
+    InstallUtil::GetMachineLevelUserCloudPolicyDMTokenRegistryPath(
+        &dm_token_key_path, &dm_token_value_name);
+    return (key.Create(HKEY_LOCAL_MACHINE, dm_token_key_path.c_str(),
+                       KEY_SET_VALUE | KEY_WOW64_64KEY) == ERROR_SUCCESS) &&
+           (key.WriteValue(dm_token_value_name.c_str(), dm_token.c_str(),
+                           dm_token.size(), REG_BINARY) == ERROR_SUCCESS);
+  }
+
+  content::TestBrowserThreadBundle thread_bundle_;
+  registry_util::RegistryOverrideManager registry_override_manager_;
+};
+
+TEST_F(BrowserDMTokenStorageWinTest, RetrieveClientId) {
+  ASSERT_TRUE(SetMachineGuid(kClientId1));
+  BrowserDMTokenStorageWin storage;
+  EXPECT_EQ(base::WideToUTF8(kClientId1), storage.RetrieveClientId());
+
+  // The client ID value should be cached in memory and not read from the system
+  // again.
+  ASSERT_TRUE(SetMachineGuid(kClientId2));
+  EXPECT_EQ(base::WideToUTF8(kClientId1), storage.RetrieveClientId());
+}
+
+TEST_F(BrowserDMTokenStorageWinTest, RetrieveEnrollmentToken) {
+  ASSERT_TRUE(SetMachineGuid(kClientId1));
+  ASSERT_TRUE(SetEnrollmentToken(kEnrollmentToken1));
+
+  BrowserDMTokenStorageWin storage;
+  EXPECT_EQ(base::WideToUTF8(kEnrollmentToken1),
+            storage.RetrieveEnrollmentToken());
+  // The enrollment token should be cached in memory and not read from the
+  // system again.
+  ASSERT_TRUE(SetEnrollmentToken(kEnrollmentToken2));
+  EXPECT_EQ(base::WideToUTF8(kEnrollmentToken1),
+            storage.RetrieveEnrollmentToken());
+}
+
+TEST_F(BrowserDMTokenStorageWinTest, RetrieveDMToken) {
+  ASSERT_TRUE(SetMachineGuid(kClientId1));
+
+  // The DM token will not be read from the system if there is no enrollment
+  // token.
+  ASSERT_TRUE(SetDMToken(kDMToken1));
+  BrowserDMTokenStorageWin storage;
+  EXPECT_THAT(storage.RetrieveDMToken(), IsEmpty());
+
+  // With the enrollment token now set, an already initialized
+  // BrowserDMTokenStorageWin should still return empty DM token because it
+  // should cache the value.
+  ASSERT_TRUE(SetEnrollmentToken(kEnrollmentToken1));
+  EXPECT_THAT(storage.RetrieveDMToken(), IsEmpty());
+
+  // But if enrollment token is set when BrowserDMTokenStorageWin is first used,
+  // it should return the DM token.
+  BrowserDMTokenStorageWin storage2;
+  EXPECT_EQ(std::string(kDMToken1), storage2.RetrieveDMToken());
+
+  // The DM token should be cached in memory and not read from the system again.
+  ASSERT_TRUE(SetDMToken(kDMToken2));
+  EXPECT_EQ(std::string(kDMToken1), storage2.RetrieveDMToken());
+}
+}  // namespace policy
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
index d8ff2ce..9cfb8fb 100644
--- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -60,7 +60,7 @@
 #include "components/translate/core/browser/translate_pref_names.h"
 #include "components/variations/pref_names.h"
 #include "extensions/buildflags/buildflags.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "ppapi/features/features.h"
 
 #if defined(OS_ANDROID)
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc
index 72fcff3..290dc6d6 100644
--- a/chrome/browser/policy/policy_browsertest.cc
+++ b/chrome/browser/policy/policy_browsertest.cc
@@ -184,7 +184,7 @@
 #include "extensions/common/manifest_handlers/shared_module_info.h"
 #include "extensions/common/switches.h"
 #include "extensions/common/value_builder.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "net/base/net_errors.h"
 #include "net/base/url_util.h"
 #include "net/dns/mock_host_resolver.h"
diff --git a/chrome/browser/printing/cloud_print/privet_http.h b/chrome/browser/printing/cloud_print/privet_http.h
index a5ab9f7..a17dc32 100644
--- a/chrome/browser/printing/cloud_print/privet_http.h
+++ b/chrome/browser/printing/cloud_print/privet_http.h
@@ -13,7 +13,7 @@
 #include "net/base/host_port_pair.h"
 
 namespace base {
-class RefCountedBytes;
+class RefCountedMemory;
 }
 
 namespace gfx {
@@ -156,10 +156,10 @@
 
   virtual void Start() = 0;
 
-  // Required print data. MUST be called before calling |Start()|.
-  virtual void SetData(const scoped_refptr<base::RefCountedBytes>& data) = 0;
+  // Required print data. MUST be called before calling Start().
+  virtual void SetData(const scoped_refptr<base::RefCountedMemory>& data) = 0;
 
-  // Optional attributes for /submitdoc. Call before calling |Start()|
+  // Optional attributes for /submitdoc. Call before calling Start().
   // |ticket| should be in CJT format.
   virtual void SetTicket(const std::string& ticket) = 0;
 
diff --git a/chrome/browser/printing/cloud_print/privet_http_impl.cc b/chrome/browser/printing/cloud_print/privet_http_impl.cc
index ec57fcf4..23d3d32 100644
--- a/chrome/browser/printing/cloud_print/privet_http_impl.cc
+++ b/chrome/browser/printing/cloud_print/privet_http_impl.cc
@@ -605,7 +605,7 @@
 }
 
 void PrivetLocalPrintOperationImpl::SetData(
-    const scoped_refptr<base::RefCountedBytes>& data) {
+    const scoped_refptr<base::RefCountedMemory>& data) {
   DCHECK(!started_);
   data_ = data;
 }
diff --git a/chrome/browser/printing/cloud_print/privet_http_impl.h b/chrome/browser/printing/cloud_print/privet_http_impl.h
index a3f9225..09308d3f 100644
--- a/chrome/browser/printing/cloud_print/privet_http_impl.h
+++ b/chrome/browser/printing/cloud_print/privet_http_impl.h
@@ -154,7 +154,7 @@
 
   // PrivetLocalPrintOperation:
   void Start() override;
-  void SetData(const scoped_refptr<base::RefCountedBytes>& data) override;
+  void SetData(const scoped_refptr<base::RefCountedMemory>& data) override;
   void SetTicket(const std::string& ticket) override;
   void SetCapabilities(const std::string& capabilities) override;
   void SetUsername(const std::string& user) override;
@@ -199,7 +199,7 @@
   cloud_devices::CloudDeviceDescription ticket_;
   cloud_devices::CloudDeviceDescription capabilities_;
 
-  scoped_refptr<base::RefCountedBytes> data_;
+  scoped_refptr<base::RefCountedMemory> data_;
   base::FilePath pwg_file_path_;
 
   bool use_pdf_ = false;
diff --git a/chrome/browser/printing/cloud_print/privet_notifications.cc b/chrome/browser/printing/cloud_print/privet_notifications.cc
index a9bca97..7b94ba8 100644
--- a/chrome/browser/printing/cloud_print/privet_notifications.cc
+++ b/chrome/browser/printing/cloud_print/privet_notifications.cc
@@ -39,7 +39,7 @@
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_contents.h"
-#include "net/net_features.h"
+#include "net/net_buildflags.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/page_transition_types.h"
 #include "ui/base/resource/resource_bundle.h"
diff --git a/chrome/browser/printing/cloud_print/privet_notifications.h b/chrome/browser/printing/cloud_print/privet_notifications.h
index 80477de..6b9bbcb 100644
--- a/chrome/browser/printing/cloud_print/privet_notifications.h
+++ b/chrome/browser/printing/cloud_print/privet_notifications.h
@@ -13,7 +13,7 @@
 #include "chrome/browser/printing/cloud_print/privet_http.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/prefs/pref_member.h"
-#include "net/net_features.h"
+#include "net/net_buildflags.h"
 #include "ui/message_center/public/cpp/notification_delegate.h"
 
 class Profile;
diff --git a/chrome/browser/printing/print_job.cc b/chrome/browser/printing/print_job.cc
index 0deb3d07..3d853dc 100644
--- a/chrome/browser/printing/print_job.cc
+++ b/chrome/browser/printing/print_job.cc
@@ -85,6 +85,25 @@
                  content::Source<PrintJob>(this));
 }
 
+#if defined(OS_WIN)
+// static
+std::vector<int> PrintJob::GetFullPageMapping(const std::vector<int>& pages,
+                                              int total_page_count) {
+  std::vector<int> mapping(total_page_count, -1);
+  for (int page_number : pages) {
+    // Make sure the page is in range.
+    if (page_number >= 0 && page_number < total_page_count)
+      mapping[page_number] = page_number;
+  }
+  return mapping;
+}
+
+void PrintJob::ResetPageMapping() {
+  pdf_page_mapping_ =
+      GetFullPageMapping(pdf_page_mapping_, document_->page_count());
+}
+#endif
+
 void PrintJob::Observe(int type,
                        const content::NotificationSource& source,
                        const content::NotificationDetails& details) {
@@ -297,10 +316,14 @@
     return;
   }
 
-  // Update the rendered document. It will send notifications to the listener.
-  document_->SetPage(pdf_page_mapping_[page_number], std::move(metafile),
-                     scale_factor, pdf_conversion_state_->page_size(),
-                     pdf_conversion_state_->content_area());
+  // Add the page to the document if it is one of the pages requested by the
+  // user. If it is not, ignore it.
+  if (pdf_page_mapping_[page_number] != -1) {
+    // Update the rendered document. It will send notifications to the listener.
+    document_->SetPage(pdf_page_mapping_[page_number], std::move(metafile),
+                       scale_factor, pdf_conversion_state_->page_size(),
+                       pdf_conversion_state_->content_area());
+  }
 
   pdf_conversion_state_->GetMorePages(
       base::Bind(&PrintJob::OnPdfPageConverted, this));
diff --git a/chrome/browser/printing/print_job.h b/chrome/browser/printing/print_job.h
index 1f46ada..6bed1ccf5 100644
--- a/chrome/browser/printing/print_job.h
+++ b/chrome/browser/printing/print_job.h
@@ -8,6 +8,7 @@
 #include <memory>
 #include <vector>
 
+#include "base/gtest_prod_util.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "build/build_config.h"
@@ -53,6 +54,15 @@
                   const base::string16& name,
                   int page_count);
 
+#if defined(OS_WIN)
+  // Overwrites the PDF page mapping to fill in values of -1 for all indices
+  // that are not selected. This is needed when the user opens the system
+  // dialog from the link in Print Preview on Windows and then sets a selection
+  // of pages, because all PDF pages will be converted, but only the user's
+  // selected pages should be sent to the printer. See https://crbug.com/823876.
+  void ResetPageMapping();
+#endif
+
   // content::NotificationObserver implementation.
   void Observe(int type,
                const content::NotificationSource& source,
@@ -116,6 +126,10 @@
   ~PrintJob() override;
 
  private:
+#if defined(OS_WIN)
+  FRIEND_TEST_ALL_PREFIXES(PrintJobTest, PageRangeMapping);
+#endif
+
   // Updates |document_| to a new instance.
   void UpdatePrintedDocument(PrintedDocument* new_document);
 
@@ -140,6 +154,10 @@
   void OnPdfPageConverted(int page_number,
                           float scale_factor,
                           std::unique_ptr<MetafilePlayer> metafile);
+
+  // Helper method to do the work for ResetPageMapping(). Split for unit tests.
+  static std::vector<int> GetFullPageMapping(const std::vector<int>& pages,
+                                             int total_page_count);
 #endif  // defined(OS_WIN)
 
   content::NotificationRegistrar registrar_;
diff --git a/chrome/browser/printing/print_job_unittest.cc b/chrome/browser/printing/print_job_unittest.cc
index fc49e35..ba69ad1 100644
--- a/chrome/browser/printing/print_job_unittest.cc
+++ b/chrome/browser/printing/print_job_unittest.cc
@@ -6,11 +6,13 @@
 
 #include <memory>
 #include <utility>
+#include <vector>
 
 #include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/string16.h"
+#include "build/build_config.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/printing/print_job_worker.h"
 #include "content/public/browser/notification_registrar.h"
@@ -143,4 +145,34 @@
   */
 }
 
+#if defined(OS_WIN)
+TEST(PrintJobTest, PageRangeMapping) {
+  int page_count = 4;
+  std::vector<int> input_full = {0, 1, 2, 3};
+  std::vector<int> expected_output_full = {0, 1, 2, 3};
+  EXPECT_EQ(expected_output_full,
+            PrintJob::GetFullPageMapping(input_full, page_count));
+
+  std::vector<int> input_12 = {1, 2};
+  std::vector<int> expected_output_12 = {-1, 1, 2, -1};
+  EXPECT_EQ(expected_output_12,
+            PrintJob::GetFullPageMapping(input_12, page_count));
+
+  std::vector<int> input_03 = {0, 3};
+  std::vector<int> expected_output_03 = {0, -1, -1, 3};
+  EXPECT_EQ(expected_output_03,
+            PrintJob::GetFullPageMapping(input_03, page_count));
+
+  std::vector<int> input_0 = {0};
+  std::vector<int> expected_output_0 = {0, -1, -1, -1};
+  EXPECT_EQ(expected_output_0,
+            PrintJob::GetFullPageMapping(input_0, page_count));
+
+  std::vector<int> input_invalid = {4, 100};
+  std::vector<int> expected_output_invalid = {-1, -1, -1, -1};
+  EXPECT_EQ(expected_output_invalid,
+            PrintJob::GetFullPageMapping(input_invalid, page_count));
+}
+#endif  // defined(OS_WIN)
+
 }  // namespace printing
diff --git a/chrome/browser/printing/print_job_worker.cc b/chrome/browser/printing/print_job_worker.cc
index ba99093..5bee7d3 100644
--- a/chrome/browser/printing/print_job_worker.cc
+++ b/chrome/browser/printing/print_job_worker.cc
@@ -322,8 +322,7 @@
     return;
   }
 
-  // Try to print already cached data. It may already have been generated for
-  // the print preview.
+  // This will start a loop to wait for the page data.
   OnNewPage();
   // Don't touch this anymore since the instance could be destroyed. It happens
   // if all the pages are printed a one sweep and the client doesn't have a
diff --git a/chrome/browser/printing/print_preview_data_service.cc b/chrome/browser/printing/print_preview_data_service.cc
index b26a6cf..a9e80fe 100644
--- a/chrome/browser/printing/print_preview_data_service.cc
+++ b/chrome/browser/printing/print_preview_data_service.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/printing/print_preview_data_service.h"
 
+#include <utility>
+
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted_memory.h"
@@ -34,7 +36,7 @@
   // Get the preview page for the specified |index|.
   void GetPreviewDataForIndex(
       int index,
-      scoped_refptr<base::RefCountedBytes>* data) const {
+      scoped_refptr<base::RefCountedMemory>* data) const {
     if (IsInvalidIndex(index))
       return;
 
@@ -45,7 +47,7 @@
 
   // Set/Update the preview data entry for the specified |index|.
   void SetPreviewDataForIndex(int index,
-                              scoped_refptr<base::RefCountedBytes> data) {
+                              scoped_refptr<base::RefCountedMemory> data) {
     if (IsInvalidIndex(index))
       return;
 
@@ -68,7 +70,7 @@
   // document.
   // Value: Preview data.
   using PreviewPageDataMap =
-      std::map<int, scoped_refptr<base::RefCountedBytes>>;
+      std::map<int, scoped_refptr<base::RefCountedMemory>>;
 
   static bool IsInvalidIndex(int index) {
     return (index != printing::COMPLETE_PREVIEW_DOCUMENT_INDEX &&
@@ -94,7 +96,7 @@
 void PrintPreviewDataService::GetDataEntry(
     int32_t preview_ui_id,
     int index,
-    scoped_refptr<base::RefCountedBytes>* data_bytes) const {
+    scoped_refptr<base::RefCountedMemory>* data_bytes) const {
   *data_bytes = nullptr;
   PreviewDataStoreMap::const_iterator it = data_store_map_.find(preview_ui_id);
   if (it != data_store_map_.end())
@@ -104,7 +106,7 @@
 void PrintPreviewDataService::SetDataEntry(
     int32_t preview_ui_id,
     int index,
-    scoped_refptr<base::RefCountedBytes> data_bytes) {
+    scoped_refptr<base::RefCountedMemory> data_bytes) {
   if (!base::ContainsKey(data_store_map_, preview_ui_id))
     data_store_map_[preview_ui_id] = std::make_unique<PrintPreviewDataStore>();
   data_store_map_[preview_ui_id]->SetPreviewDataForIndex(index,
diff --git a/chrome/browser/printing/print_preview_data_service.h b/chrome/browser/printing/print_preview_data_service.h
index 5fa52e3..d133927 100644
--- a/chrome/browser/printing/print_preview_data_service.h
+++ b/chrome/browser/printing/print_preview_data_service.h
@@ -19,7 +19,7 @@
 namespace base {
 template <typename T>
 struct DefaultSingletonTraits;
-class RefCountedBytes;
+class RefCountedMemory;
 }
 
 // PrintPreviewDataService manages data stores for chrome://print requests.
@@ -34,7 +34,7 @@
   // to NULL if the requested page is not yet available.
   void GetDataEntry(int32_t preview_ui_id,
                     int index,
-                    scoped_refptr<base::RefCountedBytes>* data) const;
+                    scoped_refptr<base::RefCountedMemory>* data) const;
 
   // Set/Update the data entry in PrintPreviewDataStore. |index| is zero-based
   // or |printing::COMPLETE_PREVIEW_DOCUMENT_INDEX| to represent complete
@@ -43,7 +43,7 @@
   // calling this function. It will be refcounted in PrintPreviewDataStore.
   void SetDataEntry(int32_t preview_ui_id,
                     int index,
-                    scoped_refptr<base::RefCountedBytes> data);
+                    scoped_refptr<base::RefCountedMemory> data);
 
   // Remove the corresponding PrintPreviewUI entry from the map.
   void RemoveEntry(int32_t preview_ui_id);
diff --git a/chrome/browser/printing/print_preview_message_handler.cc b/chrome/browser/printing/print_preview_message_handler.cc
index d088fc0..b1c5b4b 100644
--- a/chrome/browser/printing/print_preview_message_handler.cc
+++ b/chrome/browser/printing/print_preview_message_handler.cc
@@ -58,11 +58,10 @@
   }
 }
 
-scoped_refptr<base::RefCountedBytes> GetDataFromHandle(
+scoped_refptr<base::RefCountedMemory> GetDataFromHandle(
     base::SharedMemoryHandle handle,
     uint32_t data_size) {
-  std::unique_ptr<base::SharedMemory> shared_buf(
-      new base::SharedMemory(handle, true));
+  auto shared_buf = std::make_unique<base::SharedMemory>(handle, true);
   if (!shared_buf->Map(data_size)) {
     NOTREACHED();
     return nullptr;
@@ -240,7 +239,7 @@
 void PrintPreviewMessageHandler::NotifyUIPreviewPageReady(
     int page_number,
     int request_id,
-    scoped_refptr<base::RefCountedBytes> data_bytes) {
+    scoped_refptr<base::RefCountedMemory> data_bytes) {
   DCHECK(data_bytes);
 
   PrintPreviewUI* print_preview_ui = GetPrintPreviewUI();
@@ -254,7 +253,7 @@
 void PrintPreviewMessageHandler::NotifyUIPreviewDocumentReady(
     int page_count,
     int request_id,
-    scoped_refptr<base::RefCountedBytes> data_bytes) {
+    scoped_refptr<base::RefCountedMemory> data_bytes) {
   if (!data_bytes || !data_bytes->size())
     return;
 
diff --git a/chrome/browser/printing/print_preview_message_handler.h b/chrome/browser/printing/print_preview_message_handler.h
index 1c30f2c1..695cb7f 100644
--- a/chrome/browser/printing/print_preview_message_handler.h
+++ b/chrome/browser/printing/print_preview_message_handler.h
@@ -78,11 +78,11 @@
   void NotifyUIPreviewPageReady(
       int page_number,
       int request_id,
-      scoped_refptr<base::RefCountedBytes> data_bytes);
+      scoped_refptr<base::RefCountedMemory> data_bytes);
   void NotifyUIPreviewDocumentReady(
       int page_count,
       int request_id,
-      scoped_refptr<base::RefCountedBytes> data_bytes);
+      scoped_refptr<base::RefCountedMemory> data_bytes);
 
   // Callbacks for pdf compositor client.
   void OnCompositePdfPageDone(int page_number,
diff --git a/chrome/browser/printing/print_preview_pdf_generated_browsertest.cc b/chrome/browser/printing/print_preview_pdf_generated_browsertest.cc
index afd2234..d72a186 100644
--- a/chrome/browser/printing/print_preview_pdf_generated_browsertest.cc
+++ b/chrome/browser/printing/print_preview_pdf_generated_browsertest.cc
@@ -253,13 +253,13 @@
     void RegisterMessages() override {
       web_ui()->RegisterMessageCallback(
           "UILoadedForTest",
-          base::Bind(&UIDoneLoadingMessageHandler::HandleDone,
-                     base::Unretained(this)));
+          base::BindRepeating(&UIDoneLoadingMessageHandler::HandleDone,
+                              base::Unretained(this)));
 
       web_ui()->RegisterMessageCallback(
           "UIFailedLoadingForTest",
-          base::Bind(&UIDoneLoadingMessageHandler::HandleFailure,
-                     base::Unretained(this)));
+          base::BindRepeating(&UIDoneLoadingMessageHandler::HandleFailure,
+                              base::Unretained(this)));
     }
 
    private:
diff --git a/chrome/browser/printing/print_view_manager_base.cc b/chrome/browser/printing/print_view_manager_base.cc
index 64628bc..0f1d2a67 100644
--- a/chrome/browser/printing/print_view_manager_base.cc
+++ b/chrome/browser/printing/print_view_manager_base.cc
@@ -11,6 +11,7 @@
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/memory/ptr_util.h"
+#include "base/memory/ref_counted_memory.h"
 #include "base/memory/shared_memory.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
@@ -143,7 +144,7 @@
 #if BUILDFLAG(ENABLE_PRINT_PREVIEW)
 void PrintViewManagerBase::PrintForPrintPreview(
     std::unique_ptr<base::DictionaryValue> job_settings,
-    const scoped_refptr<base::RefCountedBytes>& print_data,
+    const scoped_refptr<base::RefCountedMemory>& print_data,
     content::RenderFrameHost* rfh,
     PrinterHandler::PrintCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -164,7 +165,7 @@
 
 void PrintViewManagerBase::PrintDocument(
     PrintedDocument* document,
-    const scoped_refptr<base::RefCountedBytes>& print_data,
+    const scoped_refptr<base::RefCountedMemory>& print_data,
     const gfx::Size& page_size,
     const gfx::Rect& content_area,
     const gfx::Point& offsets) {
@@ -210,7 +211,7 @@
 
 #if BUILDFLAG(ENABLE_PRINT_PREVIEW)
 void PrintViewManagerBase::OnPrintSettingsDone(
-    const scoped_refptr<base::RefCountedBytes>& print_data,
+    const scoped_refptr<base::RefCountedMemory>& print_data,
     int page_count,
     PrinterHandler::PrintCallback callback,
     scoped_refptr<printing::PrinterQuery> printer_query) {
@@ -249,7 +250,7 @@
 }
 
 void PrintViewManagerBase::StartLocalPrintJob(
-    const scoped_refptr<base::RefCountedBytes>& print_data,
+    const scoped_refptr<base::RefCountedMemory>& print_data,
     int page_count,
     scoped_refptr<printing::PrinterQuery> printer_query,
     PrinterHandler::PrintCallback callback) {
@@ -263,6 +264,10 @@
     return;
   }
 
+#if defined(OS_WIN)
+  print_job_->ResetPageMapping();
+#endif
+
   const printing::PrintSettings& settings = printer_query->settings();
   gfx::Size page_size = settings.page_setup_device_units().physical_size();
   gfx::Rect content_area =
@@ -578,14 +583,12 @@
     return false;
   }
 
-  // Ask the renderer to generate the print preview, create the print preview
-  // view and switch to it, initialize the printer and show the print dialog.
   DCHECK(!print_job_.get());
   DCHECK(job);
   if (!job)
     return false;
 
-  print_job_ = new PrintJob();
+  print_job_ = base::MakeRefCounted<PrintJob>();
   print_job_->Initialize(job, RenderSourceName(), number_pages_);
   registrar_.Add(this, chrome::NOTIFICATION_PRINT_JOB_EVENT,
                  content::Source<PrintJob>(print_job_.get()));
diff --git a/chrome/browser/printing/print_view_manager_base.h b/chrome/browser/printing/print_view_manager_base.h
index 6daa186..67c6fea 100644
--- a/chrome/browser/printing/print_view_manager_base.h
+++ b/chrome/browser/printing/print_view_manager_base.h
@@ -8,7 +8,7 @@
 #include <memory>
 
 #include "base/macros.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/strings/string16.h"
 #include "build/build_config.h"
@@ -24,7 +24,7 @@
 struct PrintHostMsg_DidPrintDocument_Params;
 
 namespace base {
-class RefCountedBytes;
+class RefCountedMemory;
 }
 
 namespace content {
@@ -60,7 +60,7 @@
   // frame host for the preview initiator contents respectively.
   void PrintForPrintPreview(
       std::unique_ptr<base::DictionaryValue> job_settings,
-      const scoped_refptr<base::RefCountedBytes>& print_data,
+      const scoped_refptr<base::RefCountedMemory>& print_data,
       content::RenderFrameHost* rfh,
       PrinterHandler::PrintCallback callback);
 #endif
@@ -117,13 +117,13 @@
 // Helpers for PrintForPrintPreview();
 #if BUILDFLAG(ENABLE_PRINT_PREVIEW)
   void OnPrintSettingsDone(
-      const scoped_refptr<base::RefCountedBytes>& print_data,
+      const scoped_refptr<base::RefCountedMemory>& print_data,
       int page_count,
       PrinterHandler::PrintCallback callback,
       scoped_refptr<printing::PrinterQuery> printer_query);
 
   void StartLocalPrintJob(
-      const scoped_refptr<base::RefCountedBytes>& print_data,
+      const scoped_refptr<base::RefCountedMemory>& print_data,
       int page_count,
       scoped_refptr<printing::PrinterQuery> printer_query,
       PrinterHandler::PrintCallback callback);
@@ -144,7 +144,7 @@
   // Starts printing |document| with the given |print_data|. This method assumes
   // |print_data| contains valid data.
   void PrintDocument(PrintedDocument* document,
-                     const scoped_refptr<base::RefCountedBytes>& print_data,
+                     const scoped_refptr<base::RefCountedMemory>& print_data,
                      const gfx::Size& page_size,
                      const gfx::Rect& content_area,
                      const gfx::Point& offsets);
diff --git a/chrome/browser/printing/pwg_raster_converter.cc b/chrome/browser/printing/pwg_raster_converter.cc
index c9517f12..4094d78 100644
--- a/chrome/browser/printing/pwg_raster_converter.cc
+++ b/chrome/browser/printing/pwg_raster_converter.cc
@@ -194,6 +194,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (callback_)
     std::move(callback_).Run(success, files_->GetPwgPath());
+  pdf_to_pwg_raster_converter_ptr_.reset();
 }
 
 class PwgRasterConverterImpl : public PwgRasterConverter {
diff --git a/chrome/browser/profiles/off_the_record_profile_io_data.cc b/chrome/browser/profiles/off_the_record_profile_io_data.cc
index 4da0785..09071de 100644
--- a/chrome/browser/profiles/off_the_record_profile_io_data.cc
+++ b/chrome/browser/profiles/off_the_record_profile_io_data.cc
@@ -34,7 +34,7 @@
 #include "net/http/http_cache.h"
 #include "net/http/http_network_session.h"
 #include "net/http/http_server_properties_impl.h"
-#include "net/net_features.h"
+#include "net/net_buildflags.h"
 #include "net/ssl/channel_id_service.h"
 #include "net/ssl/default_channel_id_store.h"
 #include "net/url_request/url_request_context.h"
diff --git a/chrome/browser/profiles/profile_browsertest.cc b/chrome/browser/profiles/profile_browsertest.cc
index e173683..925db12 100644
--- a/chrome/browser/profiles/profile_browsertest.cc
+++ b/chrome/browser/profiles/profile_browsertest.cc
@@ -50,7 +50,7 @@
 #include "extensions/common/value_builder.h"
 #include "net/base/net_errors.h"
 #include "net/dns/mock_host_resolver.h"
-#include "net/net_features.h"
+#include "net/net_buildflags.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/test/embedded_test_server/http_request.h"
 #include "net/test/embedded_test_server/http_response.h"
diff --git a/chrome/browser/profiles/profile_impl_io_data.cc b/chrome/browser/profiles/profile_impl_io_data.cc
index a4af657a..7d8769a 100644
--- a/chrome/browser/profiles/profile_impl_io_data.cc
+++ b/chrome/browser/profiles/profile_impl_io_data.cc
@@ -68,7 +68,7 @@
 #include "net/http/http_network_session.h"
 #include "net/http/http_server_properties.h"
 #include "net/http/http_server_properties_manager.h"
-#include "net/net_features.h"
+#include "net/net_buildflags.h"
 #include "net/ssl/channel_id_service.h"
 #include "net/url_request/url_request_context_builder.h"
 #include "net/url_request/url_request_intercepting_job_factory.h"
@@ -435,9 +435,6 @@
   IOThread* const io_thread = profile_params->io_thread;
   IOThread::Globals* const io_thread_globals = io_thread->globals();
 
-  builder->set_network_quality_estimator(
-      io_thread_globals->network_quality_estimator.get());
-
   // This check is needed because with the network service the cookies are used
   // in a different process. See the bottom of
   // ProfileNetworkContextService::SetUpProfileIODataMainContext.
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc
index 0cd5bb8..e9977f2e 100644
--- a/chrome/browser/profiles/profile_io_data.cc
+++ b/chrome/browser/profiles/profile_io_data.cc
@@ -91,7 +91,7 @@
 #include "net/http/http_transaction_factory.h"
 #include "net/http/http_util.h"
 #include "net/http/transport_security_persister.h"
-#include "net/net_features.h"
+#include "net/net_buildflags.h"
 #include "net/nqe/network_quality_estimator.h"
 #include "net/ssl/channel_id_service.h"
 #include "net/ssl/client_cert_store.h"
@@ -1205,7 +1205,8 @@
   if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
     main_request_context_owner_ = std::move(builder)->Create(
         std::move(profile_params_->main_network_context_params).get(),
-        io_thread_globals->quic_disabled, io_thread->net_log());
+        io_thread_globals->quic_disabled, io_thread->net_log(),
+        io_thread_globals->deprecated_network_quality_estimator.get());
     main_request_context_ =
         main_request_context_owner_.url_request_context_getter
             ->GetURLRequestContext();
diff --git a/chrome/browser/profiles/profile_io_data.h b/chrome/browser/profiles/profile_io_data.h
index 176ae1f93..3ed2295d 100644
--- a/chrome/browser/profiles/profile_io_data.h
+++ b/chrome/browser/profiles/profile_io_data.h
@@ -32,7 +32,7 @@
 #include "net/cookies/cookie_store.h"
 #include "net/http/http_cache.h"
 #include "net/http/http_network_session.h"
-#include "net/net_features.h"
+#include "net/net_buildflags.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_interceptor.h"
 #include "net/url_request/url_request_job_factory.h"
diff --git a/chrome/browser/profiling_host/background_profiling_triggers_unittest.cc b/chrome/browser/profiling_host/background_profiling_triggers_unittest.cc
index 44a04a8..fea457f 100644
--- a/chrome/browser/profiling_host/background_profiling_triggers_unittest.cc
+++ b/chrome/browser/profiling_host/background_profiling_triggers_unittest.cc
@@ -56,7 +56,6 @@
       memory_instrumentation::mojom::ProcessMemoryDump::New());
   pmd->pid = pid;
   pmd->process_type = process_type;
-  pmd->chrome_dump = memory_instrumentation::mojom::ChromeMemDump::New();
   pmd->os_dump =
       GetFakeOSMemDump(resident_set_kb, private_memory_kb, shared_footprint_kb);
   (*global_dump)->process_dumps.push_back(std::move(pmd));
diff --git a/chrome/browser/renderer_host/pepper/pepper_platform_verification_message_filter.cc b/chrome/browser/renderer_host/pepper/pepper_platform_verification_message_filter.cc
index a4c7cd9d..4ddae96 100644
--- a/chrome/browser/renderer_host/pepper/pepper_platform_verification_message_filter.cc
+++ b/chrome/browser/renderer_host/pepper/pepper_platform_verification_message_filter.cc
@@ -10,7 +10,7 @@
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "ppapi/c/pp_errors.h"
 #include "ppapi/host/dispatch_host_message.h"
 #include "ppapi/host/host_message_context.h"
diff --git a/chrome/browser/renderer_preferences_util.cc b/chrome/browser/renderer_preferences_util.cc
index ef8350d..c5311e6 100644
--- a/chrome/browser/renderer_preferences_util.cc
+++ b/chrome/browser/renderer_preferences_util.cc
@@ -16,7 +16,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/renderer_preferences.h"
 #include "content/public/common/webrtc_ip_handling_policy.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "third_party/WebKit/public/public_features.h"
 #include "third_party/skia/include/core/SkColor.h"
 
diff --git a/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.cc b/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.cc
index 21fa186..5ee78b6 100644
--- a/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.cc
+++ b/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.cc
@@ -335,9 +335,9 @@
     base::ProcessHandle pid) {
   std::unique_ptr<base::ProcessMetrics> process_metrics(
       base::ProcessMetrics::CreateProcessMetrics(pid));
-  base::WorkingSetKBytes mem_usage;
-  process_metrics->GetWorkingSetKBytes(&mem_usage);
-  return mem_usage.priv;
+  base::ProcessMetrics::TotalsSummary summary =
+      process_metrics->GetTotalsSummary();
+  return summary.private_clean_kb + summary.private_dirty_kb + summary.swap_kb;
 }
 
 TabManagerDelegate::TabManagerDelegate(
diff --git a/chrome/browser/resources/chromeos/BUILD.gn b/chrome/browser/resources/chromeos/BUILD.gn
new file mode 100644
index 0000000..91287aa
--- /dev/null
+++ b/chrome/browser/resources/chromeos/BUILD.gn
@@ -0,0 +1,21 @@
+# Copyright 2018 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("//chrome/common/features.gni")
+import("//tools/grit/grit_rule.gni")
+
+assert(is_chromeos, "Only Chrome OS resources in //c/b/resources//chromeos.")
+
+grit("multidevice_setup_resources") {
+  source = "multidevice_setup/multidevice_setup_resources.grd"
+
+  defines = chrome_grit_defines
+  outputs = [
+    "grit/multidevice_setup_resources.h",
+    "grit/multidevice_setup_resources_map.cc",
+    "grit/multidevice_setup_resources_map.h",
+    "multidevice_setup_resources.pak",
+  ]
+  output_dir = "$root_gen_dir/chrome"
+}
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs
index a8ed1ad0..e65dacbe 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs
@@ -1416,7 +1416,8 @@
   });
 });
 
-TEST_F('BackgroundTest', 'ActiveDescendantUpdates', function() {
+// Flaky, see http://crbug.com/825429.
+TEST_F('BackgroundTest', 'DISABLED_ActiveDescendantUpdates', function() {
   var mockFeedback = this.createMockFeedback();
   this.runWithLoadedTree(function(root) {/*!
     <div aria-label="container" tabindex=0 role="group" id="active"
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js
index 67d0f44c..f29e628d 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js
@@ -61,6 +61,8 @@
   this.addListener_(
       EventType.CHECKED_STATE_CHANGED, this.onCheckedStateChanged);
   this.addListener_(EventType.CHILDREN_CHANGED, this.onChildrenChanged);
+  this.addListener_(
+      EventType.DOCUMENT_SELECTION_CHANGED, this.onDocumentSelectionChanged);
   this.addListener_(EventType.EXPANDED_CHANGED, this.onEventIfInRange);
   this.addListener_(EventType.FOCUS, this.onFocus);
   this.addListener_(EventType.HOVER, this.onHover);
@@ -297,6 +299,26 @@
   },
 
   /**
+   * @param {!AutomationEvent} evt
+   */
+  onDocumentSelectionChanged: function(evt) {
+    var anchor = evt.target.anchorObject;
+
+    // No selection.
+    if (!anchor)
+      return;
+
+    // Editable selection.
+    if (anchor.state[StateType.EDITABLE]) {
+      anchor = AutomationUtil.getEditableRoot(anchor) || anchor;
+      this.onEditableChanged_(
+          new CustomAutomationEvent(evt.type, anchor, evt.eventFrom));
+    }
+
+    // Non-editable selections are handled in |Background|.
+  },
+
+  /**
    * Provides all feedback once a focus event fires.
    * @param {!AutomationEvent} evt
    */
@@ -390,6 +412,12 @@
    * @private
    */
   onEditableChanged_: function(evt) {
+    // Document selections only apply to rich editables, text selections to
+    // non-rich editables.
+    if (evt.type != EventType.DOCUMENT_SELECTION_CHANGED &&
+        evt.target.state[StateType.RICHLY_EDITABLE])
+      return;
+
     if (!this.createTextEditHandlerIfNeeded_(evt.target))
       return;
 
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js
index 3d91da8..192bc23f 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js
@@ -80,6 +80,7 @@
   onEvent: function(evt) {
     if (evt.type !== EventType.TEXT_CHANGED &&
         evt.type !== EventType.TEXT_SELECTION_CHANGED &&
+        evt.type !== EventType.DOCUMENT_SELECTION_CHANGED &&
         evt.type !== EventType.VALUE_CHANGED && evt.type !== EventType.FOCUS)
       return;
     if (!evt.target.state.focused || !evt.target.state.editable ||
diff --git a/chrome/browser/resources/chromeos/multidevice_setup/.eslintrc.js b/chrome/browser/resources/chromeos/multidevice_setup/.eslintrc.js
new file mode 100644
index 0000000..25e21f9
--- /dev/null
+++ b/chrome/browser/resources/chromeos/multidevice_setup/.eslintrc.js
@@ -0,0 +1,13 @@
+// Copyright 2018 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.exports = {
+  'env': {
+    'browser': true,
+    'es6': true,
+  },
+  'rules': {
+    'no-var': 'error',
+  },
+};
diff --git a/chrome/browser/resources/chromeos/multidevice_setup/OWNERS b/chrome/browser/resources/chromeos/multidevice_setup/OWNERS
new file mode 100644
index 0000000..aef4ecb
--- /dev/null
+++ b/chrome/browser/resources/chromeos/multidevice_setup/OWNERS
@@ -0,0 +1 @@
+file://chromeos/services/multidevice_setup/OWNERS
diff --git a/chrome/browser/resources/chromeos/multidevice_setup/compiled_resources2.gyp b/chrome/browser/resources/chromeos/multidevice_setup/compiled_resources2.gyp
new file mode 100644
index 0000000..5c69afb8
--- /dev/null
+++ b/chrome/browser/resources/chromeos/multidevice_setup/compiled_resources2.gyp
@@ -0,0 +1,14 @@
+# Copyright 2018 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.
+{
+  'targets': [
+    {
+      'target_name': 'multidevice_setup',
+      'dependencies': [
+        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+      ],
+      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+    },
+  ],
+}
diff --git a/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup.html b/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup.html
new file mode 100644
index 0000000..2e4d457
--- /dev/null
+++ b/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup.html
@@ -0,0 +1,10 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/html/cr.html">
+
+<dom-module id="multidevice-setup">
+  <template>
+    Placeholder for MultiDevice Setup.
+  </template>
+  <script src="multidevice_setup.js"></script>
+</dom-module>
diff --git a/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup.js b/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup.js
new file mode 100644
index 0000000..93cf26e2
--- /dev/null
+++ b/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup.js
@@ -0,0 +1,12 @@
+// Copyright 2018 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.
+
+Polymer({
+  is: 'multidevice-setup',
+
+  /** @override */
+  attached: function() {
+    // TODO(jordynass): Implement.
+  },
+});
diff --git a/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup_dialog.html b/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup_dialog.html
new file mode 100644
index 0000000..70a1f2f
--- /dev/null
+++ b/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup_dialog.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<html dir="$i18n{textdirection}" lang="$i18n{language}">
+<head>
+  <meta charset="utf8">
+  <title>$i18n{title}</title>
+  <base href="chrome://multidevice-setup">
+  <style>
+    html,
+    body {
+      height: 100%;
+      margin: 0;
+      overflow: hidden;
+      width: 100%;
+    }
+  </style>
+</head>
+<body>
+  <multidevice-setup></multidevice-setup>
+  <link rel="stylesheet" href="chrome://resources/css/md_colors.css">
+  <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
+  <link rel="import" href="multidevice_setup.html">
+</body>
+</html>
diff --git a/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup_resources.grd b/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup_resources.grd
new file mode 100644
index 0000000..e700208
--- /dev/null
+++ b/chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup_resources.grd
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
+  <outputs>
+    <output filename="grit/multidevice_setup_resources.h" type="rc_header">
+      <emit emit_type='prepend'></emit>
+    </output>
+    <output filename="grit/multidevice_setup_resources_map.cc"
+            type="resource_file_map_source" />
+    <output filename="grit/multidevice_setup_resources_map.h"
+            type="resource_map_header" />
+    <output filename="multidevice_setup_resources.pak" type="data_package" />
+  </outputs>
+  <release seq="1">
+    <structures>
+      <structure name="IDR_MULTIDEVICE_SETUP_MULTIDEVICE_SETUP_HTML"
+                 file="multidevice_setup.html"
+                 type="chrome_html" />
+      <structure name="IDR_MULTIDEVICE_SETUP_MULTIDEVICE_SETUP_JS"
+                 file="multidevice_setup.js"
+                 type="chrome_html" />
+      <structure name="IDR_MULTIDEVICE_SETUP_MULTIDEVICE_SETUP_DIALOG_HTML"
+                 file="multidevice_setup_dialog.html"
+                 flattenhtml="true"
+                 allowexternalscript="true"
+                 type="chrome_html" />
+    </structures>
+  </release>
+</grit>
diff --git a/chrome/browser/resources/md_extensions/drop_overlay.js b/chrome/browser/resources/md_extensions/drop_overlay.js
index a1071ef..ededf3b 100644
--- a/chrome/browser/resources/md_extensions/drop_overlay.js
+++ b/chrome/browser/resources/md_extensions/drop_overlay.js
@@ -8,12 +8,23 @@
 Polymer({
   is: 'extensions-drop-overlay',
 
+  properties: {
+    /** @private {boolean} */
+    dragEnabled: {
+      type: Boolean,
+      observer: 'dragEnabledChanged_',
+    }
+  },
+
   /** @override */
   created: function() {
     this.hidden = true;
     const dragTarget = document.documentElement;
     this.dragWrapperHandler_ =
         new extensions.DragAndDropHandler(true, true, dragTarget);
+    // TODO(devlin): All these dragTarget listeners leak (they aren't removed
+    // when the element is). This only matters in tests at the moment, but would
+    // be good to fix.
     dragTarget.addEventListener('extension-drag-started', () => {
       this.hidden = false;
     });
@@ -26,5 +37,13 @@
     this.dragWrapper_ =
         new cr.ui.DragWrapper(dragTarget, this.dragWrapperHandler_);
   },
+
+  /**
+   * @param {boolean} dragEnabled
+   * @private
+   */
+  dragEnabledChanged_: function(dragEnabled) {
+    this.dragWrapperHandler_.dragEnabled = dragEnabled;
+  },
 });
 })();
diff --git a/chrome/browser/resources/md_extensions/item_list.html b/chrome/browser/resources/md_extensions/item_list.html
index 1f9aaf8..3431fec 100644
--- a/chrome/browser/resources/md_extensions/item_list.html
+++ b/chrome/browser/resources/md_extensions/item_list.html
@@ -10,12 +10,6 @@
 <dom-module id="extensions-item-list">
   <template>
     <style include="cr-shared-style">
-      :host {
-        /* Address corner-case where #container's padding is larger than max
-           available width. */
-        overflow: auto;
-      }
-
       .items-container,
       extensions-item {
         --extensions-card-width: 400px;
@@ -25,6 +19,9 @@
         box-sizing: border-box;
         height: 100%;
         overflow: overlay;
+      }
+
+      #content-wrapper {
         padding: 24px 60px 64px;
       }
 
@@ -61,47 +58,51 @@
       }
     </style>
     <div id="container">
-      <div class="empty-list-message" hidden="[[!isGuest]]">
-        $i18n{guestModeMessage}
-      </div>
-      <div id="no-items" class="empty-list-message"
-          hidden$="[[!shouldShowEmptyItemsMessage_(
-              apps.length, extensions.length)]]">
-        <span on-click="onNoExtensionsTap_">$i18nRaw{noExtensionsOrApps}</span>
-      </div>
-      <div id="no-search-results" class="empty-list-message"
-          hidden$="[[!shouldShowEmptySearchMessage_(
-              shownAppsCount_, shownExtensionsCount_, apps, extensions)]]">
-        <span>$i18n{noSearchResults}</span>
-      </div>
-      <div class="items-container" hidden="[[!shownExtensionsCount_]]">
-        <!-- Render only a few items first, to improve initial render time, then
-          render the remaining items on a different frame. Value of 3 was chosen
-          by experimentation, and it is a good trade-off between initial render
-          time and total render time. -->
-        <template is="dom-repeat" items="[[extensions]]" initial-count="3"
-            filter="[[computedFilter_]]"
-            rendered-item-count="{{shownExtensionsCount_::dom-change}}"
-            notify-dom-change>
-          <extensions-item id="[[item.id]]" data="[[item]]"
-              delegate="[[delegate]]" in-dev-mode="[[inDevMode]]">
-          </extensions-item>
-        </template>
-      </div>
-      <div hidden="[[!shownAppsCount_]]">
-        <!-- app-title needs to left-align with the grid content below, and
-             the easiest way to achieve this is to make it a grid as well. -->
-        <h2 id="app-title" class="items-container">$i18n{appsTitle}</h2>
-        <div class="items-container">
-          <template is="dom-repeat" items="[[apps]]" initial-count="3"
+      <div id="content-wrapper">
+        <div class="empty-list-message" hidden="[[!isGuest]]">
+          $i18n{guestModeMessage}
+        </div>
+        <div id="no-items" class="empty-list-message"
+            hidden$="[[!shouldShowEmptyItemsMessage_(
+                apps.length, extensions.length)]]">
+          <span on-click="onNoExtensionsTap_">
+            $i18nRaw{noExtensionsOrApps}
+          </span>
+        </div>
+        <div id="no-search-results" class="empty-list-message"
+            hidden$="[[!shouldShowEmptySearchMessage_(
+                shownAppsCount_, shownExtensionsCount_, apps, extensions)]]">
+          <span>$i18n{noSearchResults}</span>
+        </div>
+        <div class="items-container" hidden="[[!shownExtensionsCount_]]">
+          <!-- Render only a few items first, to improve initial render time,
+            then render the remaining items on a different frame. Value of 3
+            was chosen by experimentation, and it is a good trade-off between
+            initial render time and total render time. -->
+          <template is="dom-repeat" items="[[extensions]]" initial-count="3"
               filter="[[computedFilter_]]"
-              rendered-item-count="{{shownAppsCount_::dom-change}}"
+              rendered-item-count="{{shownExtensionsCount_::dom-change}}"
               notify-dom-change>
             <extensions-item id="[[item.id]]" data="[[item]]"
                 delegate="[[delegate]]" in-dev-mode="[[inDevMode]]">
             </extensions-item>
           </template>
         </div>
+        <div hidden="[[!shownAppsCount_]]">
+          <!-- app-title needs to left-align with the grid content below, and
+               the easiest way to achieve this is to make it a grid as well. -->
+          <h2 id="app-title" class="items-container">$i18n{appsTitle}</h2>
+          <div class="items-container">
+            <template is="dom-repeat" items="[[apps]]" initial-count="3"
+                filter="[[computedFilter_]]"
+                rendered-item-count="{{shownAppsCount_::dom-change}}"
+                notify-dom-change>
+              <extensions-item id="[[item.id]]" data="[[item]]"
+                  delegate="[[delegate]]" in-dev-mode="[[inDevMode]]">
+              </extensions-item>
+            </template>
+          </div>
+        </div>
       </div>
     </div>
   </template>
diff --git a/chrome/browser/resources/md_extensions/manager.html b/chrome/browser/resources/md_extensions/manager.html
index 235a6f1..54590401 100644
--- a/chrome/browser/resources/md_extensions/manager.html
+++ b/chrome/browser/resources/md_extensions/manager.html
@@ -54,7 +54,8 @@
         background-color: var(--md-toolbar-color);
       }
     </style>
-    <extensions-drop-overlay></extensions-drop-overlay>
+    <extensions-drop-overlay drag-enabled="[[inDevMode]]">
+    </extensions-drop-overlay>
     <extensions-toolbar is-guest="[[isGuest_]]"
         in-dev-mode="[[inDevMode]]"
         can-load-unpacked="[[canLoadUnpacked]]"
diff --git a/chrome/browser/resources/md_extensions/shortcut_input.html b/chrome/browser/resources/md_extensions/shortcut_input.html
index 8a4be68..d2ac3b3 100644
--- a/chrome/browser/resources/md_extensions/shortcut_input.html
+++ b/chrome/browser/resources/md_extensions/shortcut_input.html
@@ -29,7 +29,7 @@
         };
       }
 
-      #clear {
+      #clearContainer {
         bottom: -4px;
         position: absolute;
         right: -8px;
@@ -45,7 +45,7 @@
           value="[[computeText_(capturing_, shortcut, pendingShortcut_)]]"
           no-label-float>
       </paper-input>
-      <paper-icon-button-light class="icon-clear no-overlap"
+      <paper-icon-button-light class="icon-clear no-overlap" id="clearContainer"
           hidden$="[[computeClearHidden_(capturing_, shortcut)]]">
         <button id="clear" on-click="onClearTap_"></button>
       </paper-icon-button-light>
diff --git a/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html b/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html
index 50c147c..8c44d74 100644
--- a/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html
+++ b/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html
@@ -180,10 +180,6 @@
       </settings-dropdown-menu>
     </div>
     <settings-toggle-button class="continuation"
-        pref="{{prefs.settings.touchpad.enable_tap_dragging}}"
-        label="$i18n{tapDraggingLabel}">
-    </settings-toggle-button>
-    <settings-toggle-button class="continuation"
         pref="{{prefs.settings.a11y.large_cursor_enabled}}"
         label="$i18n{largeMouseCursorLabel}">
     </settings-toggle-button>
diff --git a/chrome/browser/resources/settings/passwords_and_forms_page/password_list_item.html b/chrome/browser/resources/settings/passwords_and_forms_page/password_list_item.html
index 04a26f15..d9a7b19 100644
--- a/chrome/browser/resources/settings/passwords_and_forms_page/password_list_item.html
+++ b/chrome/browser/resources/settings/passwords_and_forms_page/password_list_item.html
@@ -27,6 +27,7 @@
          */
         font-family: inherit;
         font-size: inherit;
+        text-overflow: ellipsis;
       }
     </style>
     <div class="list-item" focus-row-container>
@@ -42,8 +43,8 @@
           </span>
         </a>
       </div>
-      <div class="username-column text-elide"
-           id="username">[[item.entry.loginPair.username]]</div>
+      <input id="username" class="username-column text-elide password-field"
+          readonly value="[[item.entry.loginPair.username]]">
       <div class="password-column">
         <template is="dom-if" if="[[!item.entry.federationText]]">
           <input id="password" aria-label=$i18n{editPasswordPasswordLabel}
diff --git a/chrome/browser/resources/settings/people_page/people_page.html b/chrome/browser/resources/settings/people_page/people_page.html
index beeb359..f298949 100644
--- a/chrome/browser/resources/settings/people_page/people_page.html
+++ b/chrome/browser/resources/settings/people_page/people_page.html
@@ -119,6 +119,7 @@
         <template is="dom-if" if="[[shouldShowSyncAccountControl_(diceEnabled_,
             syncStatus.syncSystemEnabled, syncStatus.signinAllowed)]]">
           <settings-sync-account-control
+              sync-status="[[syncStatus]]"
               promo-label="$i18n{peopleSignInPrompt}"
               promo-secondary-label="$i18n{peopleSignInPromptSecondary}">
           </settings-sync-account-control>
@@ -209,8 +210,8 @@
         </template>
 </if>
 
-        <template is="dom-if"
-            if="[[isAdvancedSyncSettingsVisible_(syncStatus)]]">
+        <template is="dom-if" if="[[isAdvancedSyncSettingsVisible_(
+            syncStatus, unifiedConsentEnabled_)]]">
           <div class="settings-box two-line" on-click="onSyncTap_"
               id="sync-status" actionable$="[[isSyncStatusActionable_(
               syncStatus)]]">
@@ -232,6 +233,16 @@
           </div>
         </template>
 
+        <template is="dom-if" if="[[unifiedConsentEnabled_]]">
+          <div class="settings-box" id="sync-setup" on-click="onSyncTap_"
+              actionable>
+            <div class="start">$i18n{syncAndPersonalization}</div>
+            <paper-icon-button-light class="subpage-arrow">
+              <button aria-label="$i18n{sync}"></button>
+            </paper-icon-button-light>
+          </div>
+        </template>
+
 <if expr="not chromeos">
         <template is="dom-if" if="[[diceEnabled_]]">
           <div class="settings-box" id="edit-profile" on-click="onProfileTap_"
@@ -282,11 +293,13 @@
 
       </neon-animatable>
       <template is="dom-if" route-path="/syncSetup"
-          no-search$="[[!isAdvancedSyncSettingsVisible_(syncStatus)]]">
+          no-search$="[[!isAdvancedSyncSettingsVisible_(syncStatus,
+              unifiedConsentEnabled_)]]">
         <settings-subpage
             associated-control="[[$$('#sync-status')]]"
             page-title="$i18n{syncPageTitle}"
-            no-search$="[[!isAdvancedSyncSettingsVisible_(syncStatus)]]">
+            no-search$="[[!isAdvancedSyncSettingsVisible_(syncStatus,
+                unifiedConsentEnabled_)]]">
           <settings-sync-page
 <if expr="not chromeos">
               setup-in-progress="[[syncStatus.setupInProgress]]"
diff --git a/chrome/browser/resources/settings/people_page/people_page.js b/chrome/browser/resources/settings/people_page/people_page.js
index 88cf9b2..3fa0504 100644
--- a/chrome/browser/resources/settings/people_page/people_page.js
+++ b/chrome/browser/resources/settings/people_page/people_page.js
@@ -42,6 +42,20 @@
     // </if>
 
     /**
+     * This flag is used to conditionally show a set of sync UIs to the
+     * profiles that have been migrated to have a unified consent flow.
+     * TODO(scottchen): In the future when all profiles are completely migrated,
+     * this should be removed, and UIs hidden behind it should become default.
+     * @private
+     */
+    unifiedConsentEnabled_: {
+      type: Boolean,
+      value: function() {
+        return loadTimeData.getBoolean('unifiedConsentEnabled');
+      },
+    },
+
+    /**
      * The current sync status, supplied by SyncBrowserProxy.
      * @type {?settings.SyncStatus}
      */
@@ -318,6 +332,15 @@
 
   /** @private */
   onSyncTap_: function() {
+    // When unified-consent is enabled, users can go to sync subpage regardless
+    // of sync status.
+    // TODO(scottchen): figure out how to deal with sync error states in the
+    //    subpage (https://crbug.com/824546).
+    if (this.unifiedConsentEnabled_) {
+      settings.navigateTo(settings.routes.SYNC);
+      return;
+    }
+
     assert(this.syncStatus.signedIn);
     assert(this.syncStatus.syncSystemEnabled);
 
@@ -433,7 +456,7 @@
    */
   isAdvancedSyncSettingsVisible_: function(syncStatus) {
     return !!syncStatus && !!syncStatus.signedIn &&
-        !!syncStatus.syncSystemEnabled;
+        !!syncStatus.syncSystemEnabled && !this.unifiedConsentEnabled_;
   },
 
   /**
diff --git a/chrome/browser/resources/settings/people_page/sync_account_control.js b/chrome/browser/resources/settings/people_page/sync_account_control.js
index 3ea73fbd..fd6e8b7d 100644
--- a/chrome/browser/resources/settings/people_page/sync_account_control.js
+++ b/chrome/browser/resources/settings/people_page/sync_account_control.js
@@ -16,7 +16,7 @@
   behaviors: [WebUIListenerBehavior],
   properties: {
     /**
-     * The current sync status, supplied by SyncBrowserProxy.
+     * The current sync status, supplied by parent element.
      * @type {!settings.SyncStatus}
      */
     syncStatus: Object,
@@ -65,16 +65,15 @@
   /** @private {?settings.SyncBrowserProxy} */
   syncBrowserProxy_: null,
 
+  created: function() {
+    this.syncBrowserProxy_ = settings.SyncBrowserProxyImpl.getInstance();
+  },
+
   /** @override */
   attached: function() {
-    this.syncBrowserProxy_ = settings.SyncBrowserProxyImpl.getInstance();
-    this.syncBrowserProxy_.getSyncStatus().then(
-        this.handleSyncStatus_.bind(this));
     this.syncBrowserProxy_.getStoredAccounts().then(
         this.handleStoredAccounts_.bind(this));
     this.addWebUIListener(
-        'sync-status-changed', this.handleSyncStatus_.bind(this));
-    this.addWebUIListener(
         'stored-accounts-updated', this.handleStoredAccounts_.bind(this));
   },
 
@@ -151,15 +150,6 @@
   },
 
   /**
-   * Handler for when the sync state is pushed from the browser.
-   * @param {!settings.SyncStatus} syncStatus
-   * @private
-   */
-  handleSyncStatus_: function(syncStatus) {
-    this.syncStatus = syncStatus;
-  },
-
-  /**
    * @return {boolean}
    * @private
    */
diff --git a/chrome/browser/resources/settings/reset_page/reset_page.html b/chrome/browser/resources/settings/reset_page/reset_page.html
index 6baf8650..b36d776 100644
--- a/chrome/browser/resources/settings/reset_page/reset_page.html
+++ b/chrome/browser/resources/settings/reset_page/reset_page.html
@@ -82,10 +82,11 @@
             <div class="start">
               $i18n{incompatibleApplicationsResetCardTitle}
             </div>
-            <button is="paper-icon-button-light"
-                class="subpage-arrow"
-                aria-label="$i18n{incompatibleApplicationsResetCardTitle}"
-                aria-describedby="incompatibleApplicationsSecondary"></button>
+            <paper-icon-button-light class="subpage-arrow">
+              <button
+                  aria-label="$i18n{incompatibleApplicationsResetCardTitle}"
+                  aria-describedby="incompatibleApplicationsSecondary"></button>
+            </paper-icon-button-light>
           </div>
         </template>
 </if>
diff --git a/chrome/browser/safe_browsing/browser_feature_extractor.cc b/chrome/browser/safe_browsing/browser_feature_extractor.cc
index ccdbfdbb..ed6cb26 100644
--- a/chrome/browser/safe_browsing/browser_feature_extractor.cc
+++ b/chrome/browser/safe_browsing/browser_feature_extractor.cc
@@ -189,7 +189,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(request);
   DCHECK(info);
-  DCHECK_EQ(0U, request->url().find("http:"));
+  DCHECK(GURL(request->url()).SchemeIsHTTPOrHTTPS());
   DCHECK(!callback.is_null());
   // Extract features pertaining to this navigation.
   const NavigationController& controller = tab_->GetController();
@@ -378,13 +378,13 @@
     callback.Run(false, std::move(request));
     return;
   }
-  GURL request_url(request->url());
+  GURL::Replacements rep;
+  rep.SetSchemeStr(url::kHttpScheme);
+  GURL http_url = GURL(request->url()).ReplaceComponents(rep);
   history->GetVisibleVisitCountToHost(
-      request_url,
+      http_url,
       base::Bind(&BrowserFeatureExtractor::QueryHttpHostVisitsDone,
-                 base::Unretained(this),
-                 base::Passed(&request),
-                 callback),
+                 base::Unretained(this), base::Passed(&request), callback),
       &cancelable_task_tracker_);
 }
 
@@ -409,13 +409,13 @@
     callback.Run(false, std::move(request));
     return;
   }
-  std::string https_url = request->url();
+  GURL::Replacements rep;
+  rep.SetSchemeStr(url::kHttpsScheme);
+  GURL https_url = GURL(request->url()).ReplaceComponents(rep);
   history->GetVisibleVisitCountToHost(
-      GURL(https_url.replace(0, 5, "https:")),
+      https_url,
       base::Bind(&BrowserFeatureExtractor::QueryHttpsHostVisitsDone,
-                 base::Unretained(this),
-                 base::Passed(&request),
-                 callback),
+                 base::Unretained(this), base::Passed(&request), callback),
       &cancelable_task_tracker_);
 }
 
diff --git a/chrome/browser/safe_browsing/browser_feature_extractor_unittest.cc b/chrome/browser/safe_browsing/browser_feature_extractor_unittest.cc
index 3579cf9..533427d1 100644
--- a/chrome/browser/safe_browsing/browser_feature_extractor_unittest.cc
+++ b/chrome/browser/safe_browsing/browser_feature_extractor_unittest.cc
@@ -296,6 +296,24 @@
   EXPECT_DOUBLE_EQ(1.0, features[features::kFirstHttpsHostVisitMoreThan24hAgo]);
 
   request.Clear();
+  request.set_url("https://www.foo.com/gaa.html");
+  request.set_client_score(0.5);
+  EXPECT_TRUE(ExtractFeatures(&request));
+  features.clear();
+  GetFeatureMap(request, &features);
+
+  EXPECT_EQ(8U, features.size());
+  EXPECT_DOUBLE_EQ(1.0, features[features::kUrlHistoryVisitCount]);
+  EXPECT_DOUBLE_EQ(0.0,
+                   features[features::kUrlHistoryVisitCountMoreThan24hAgo]);
+  EXPECT_DOUBLE_EQ(0.0, features[features::kUrlHistoryTypedCount]);
+  EXPECT_DOUBLE_EQ(1.0, features[features::kUrlHistoryLinkCount]);
+  EXPECT_DOUBLE_EQ(4.0, features[features::kHttpHostVisitCount]);
+  EXPECT_DOUBLE_EQ(2.0, features[features::kHttpsHostVisitCount]);
+  EXPECT_DOUBLE_EQ(1.0, features[features::kFirstHttpHostVisitMoreThan24hAgo]);
+  EXPECT_DOUBLE_EQ(1.0, features[features::kFirstHttpsHostVisitMoreThan24hAgo]);
+
+  request.Clear();
   request.set_url("http://bar.foo.com/gaa.html");
   request.set_client_score(0.5);
   EXPECT_TRUE(ExtractFeatures(&request));
diff --git a/chrome/browser/safe_browsing/certificate_reporting_service_factory.h b/chrome/browser/safe_browsing/certificate_reporting_service_factory.h
index 2984d67..b898bbe1 100644
--- a/chrome/browser/safe_browsing/certificate_reporting_service_factory.h
+++ b/chrome/browser/safe_browsing/certificate_reporting_service_factory.h
@@ -8,6 +8,10 @@
 #include "base/memory/singleton.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 
+namespace base {
+class Clock;
+}
+
 namespace content {
 class BrowserContext;
 }
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.cc
index ecdd14d..223b559a 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.cc
+++ b/chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.cc
@@ -39,7 +39,7 @@
     "RebootPromptDialog", base::FEATURE_DISABLED_BY_DEFAULT};
 
 const base::Feature kUserInitiatedChromeCleanupsFeature{
-    "UserInitiatedChromeCleanups", base::FEATURE_ENABLED_BY_DEFAULT};
+    "UserInitiatedChromeCleanups", base::FEATURE_DISABLED_BY_DEFAULT};
 
 const base::Feature kChromeCleanupDistributionFeature{
     "ChromeCleanupDistribution", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service.cc b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
index eb9466b..e3c4764 100644
--- a/chrome/browser/safe_browsing/chrome_password_protection_service.cc
+++ b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
@@ -222,12 +222,21 @@
       navigation_observer_manager_->IdentifyReferrerChainByEventURL(
           event_url, event_tab_id, kPasswordEventAttributionUserGestureLimit,
           frame->mutable_referrer_chain());
+  size_t referrer_chain_length = frame->referrer_chain().size();
   UMA_HISTOGRAM_COUNTS_100(
       "SafeBrowsing.ReferrerURLChainSize.PasswordEventAttribution",
-      frame->referrer_chain().size());
+      referrer_chain_length);
   UMA_HISTOGRAM_ENUMERATION(
       "SafeBrowsing.ReferrerAttributionResult.PasswordEventAttribution", result,
       SafeBrowsingNavigationObserverManager::ATTRIBUTION_FAILURE_TYPE_MAX);
+
+  // Determines how many recent navigation events to append to referrer chain.
+  size_t recent_navigations_to_collect =
+      profile_ ? SafeBrowsingNavigationObserverManager::
+                     CountOfRecentNavigationsToAppend(*profile_, result)
+               : 0u;
+  navigation_observer_manager_->AppendRecentNavigations(
+      recent_navigations_to_collect, frame->mutable_referrer_chain());
 }
 
 void ChromePasswordProtectionService::ShowModalWarning(
diff --git a/chrome/browser/safe_browsing/client_side_detection_host.cc b/chrome/browser/safe_browsing/client_side_detection_host.cc
index f016d14..9e992c7 100644
--- a/chrome/browser/safe_browsing/client_side_detection_host.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_host.cc
@@ -445,7 +445,7 @@
   classification_request_->Start();
 }
 
-void ClientSideDetectionHost::SubresourceResponseStarted(
+void ClientSideDetectionHost::SubresourceLoadComplete(
     const content::mojom::SubresourceLoadInfo& subresource_load_info) {
   if (browse_info_.get() && should_extract_malware_features_ &&
       subresource_load_info.url.is_valid() &&
diff --git a/chrome/browser/safe_browsing/client_side_detection_host.h b/chrome/browser/safe_browsing/client_side_detection_host.h
index 43b6d5a..2623aa4 100644
--- a/chrome/browser/safe_browsing/client_side_detection_host.h
+++ b/chrome/browser/safe_browsing/client_side_detection_host.h
@@ -45,8 +45,8 @@
   // we should classify the new URL.
   void DidFinishNavigation(
       content::NavigationHandle* navigation_handle) override;
-  void SubresourceResponseStarted(const content::mojom::SubresourceLoadInfo&
-                                      subresource_load_info) override;
+  void SubresourceLoadComplete(const content::mojom::SubresourceLoadInfo&
+                                   subresource_load_info) override;
 
   // Called when the SafeBrowsingService found a hit with one of the
   // SafeBrowsing lists.  This method is called on the UI thread.
diff --git a/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc b/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
index 8795774..e23e89da 100644
--- a/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
@@ -1242,8 +1242,7 @@
   subresource_load_info->referrer = GURL("http://host2.com");
   subresource_load_info->method = "GET";
   subresource_load_info->resource_type = content::RESOURCE_TYPE_SUB_FRAME;
-  subresource_load_info->cert_status = 0;
-  csd_host_->SubresourceResponseStarted(*subresource_load_info);
+  csd_host_->SubresourceLoadComplete(*subresource_load_info);
 
   EXPECT_EQ(0u, GetBrowseInfo()->ips.size());
 }
diff --git a/chrome/browser/search/search.cc b/chrome/browser/search/search.cc
index cea27c1..05ca70f 100644
--- a/chrome/browser/search/search.cc
+++ b/chrome/browser/search/search.cc
@@ -379,7 +379,8 @@
 
   // Do nothing in incognito.
   Profile* profile = Profile::FromBrowserContext(browser_context);
-  if (profile && profile->IsOffTheRecord())
+  DCHECK(profile);
+  if (profile->IsOffTheRecord())
     return false;
 
   if (IsInstantNTPURL(*url, profile)) {
diff --git a/chrome/browser/sessions/tab_restore_browsertest.cc b/chrome/browser/sessions/tab_restore_browsertest.cc
index 9bdc4f0..69665a4 100644
--- a/chrome/browser/sessions/tab_restore_browsertest.cc
+++ b/chrome/browser/sessions/tab_restore_browsertest.cc
@@ -715,9 +715,18 @@
   EXPECT_EQ(url1_, restored_tab->GetURL());
 }
 
+// https://crbug.com/835305: Timeout flakiness on Win7 Tests (dbg)(1) bot and
+// PASS/FAIL flakiness on Linux Chromium OS ASan LSan Tests (1) bot.
+#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
+    (defined(OS_WIN) && !defined(NDEBUG))
+#define MAYBE_RestoreTabWithSpecialURL DISABLED_RestoreTabWithSpecialURL
+#else
+#define MAYBE_RestoreTabWithSpecialURL RestoreTabWithSpecialURL
+#endif
+
 // Restore tab with special URL chrome://credits/ and make sure the page loads
 // properly after restore. See http://crbug.com/31905.
-IN_PROC_BROWSER_TEST_F(TabRestoreTest, RestoreTabWithSpecialURL) {
+IN_PROC_BROWSER_TEST_F(TabRestoreTest, MAYBE_RestoreTabWithSpecialURL) {
   // Navigate new tab to a special URL.
   ui_test_utils::NavigateToURLWithDisposition(
       browser(), GURL(chrome::kChromeUICreditsURL),
@@ -740,7 +749,9 @@
 }
 
 // https://crbug.com/667932: Flakiness on linux_chromium_asan_rel_ng bot.
-#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER)
+// https://crbug.com/835305: Timeout flakiness on Win7 Tests (dbg)(1) bot.
+#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
+    (defined(OS_WIN) && !defined(NDEBUG))
 #define MAYBE_RestoreTabWithSpecialURLOnBack DISABLED_RestoreTabWithSpecialURLOnBack
 #else
 #define MAYBE_RestoreTabWithSpecialURLOnBack RestoreTabWithSpecialURLOnBack
diff --git a/chrome/browser/ssl/ssl_browsertest.cc b/chrome/browser/ssl/ssl_browsertest.cc
index a674fbc..290b903b 100644
--- a/chrome/browser/ssl/ssl_browsertest.cc
+++ b/chrome/browser/ssl/ssl_browsertest.cc
@@ -5582,18 +5582,27 @@
   CheckAuthenticatedState(tab, AuthState::NONE);
 }
 
-// Checks that if a redirect occurs while the page is loading, the SSL state
-// reflects the final URL.
+// Checks that if a client redirect occurs while the page is loading, the SSL
+// state reflects the final URL.
 IN_PROC_BROWSER_TEST_P(SSLUITest, ClientRedirectSSLState) {
   ASSERT_TRUE(embedded_test_server()->Start());
   ASSERT_TRUE(https_server_.Start());
 
   GURL https_url = https_server_.GetURL("/ssl/redirect.html?");
   GURL http_url = embedded_test_server()->GetURL("/ssl/google.html");
-
   GURL url(https_url.spec() + http_url.spec());
-  ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(browser(), url, 2);
+
   WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
+  content::TestNavigationManager navigation_observer_https(tab, url);
+  content::TestNavigationManager navigation_observer_http(tab, http_url);
+
+  tab->GetController().LoadURL(url, content::Referrer(),
+                               ui::PAGE_TRANSITION_LINK, std::string());
+
+  navigation_observer_https.WaitForNavigationFinished();
+  navigation_observer_http.WaitForNavigationFinished();
+  content::WaitForLoadStop(tab);
+
   CheckUnauthenticatedState(tab, AuthState::NONE);
 }
 
@@ -5618,12 +5627,23 @@
   ASSERT_TRUE(embedded_test_server()->Start());
   ASSERT_TRUE(https_server_.Start());
 
-  GURL url = GURL(
-      https_server_.GetURL("/ssl/redirect.html").spec() + "?" +
-      https_server_.GetURL("/ssl/page_displays_insecure_content.html").spec());
+  GURL redirect(https_server_.GetURL("/ssl/redirect.html"));
+  GURL final_url(
+      https_server_.GetURL("/ssl/page_displays_insecure_content.html"));
+  GURL url = GURL(redirect.spec() + "?" + final_url.spec());
 
-  ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(browser(), url, 2);
   WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
+
+  content::TestNavigationManager navigation_manager_redirect(tab, url);
+  content::TestNavigationManager navigation_manager_final_url(tab, final_url);
+
+  tab->GetController().LoadURL(url, content::Referrer(),
+                               ui::PAGE_TRANSITION_LINK, std::string());
+
+  navigation_manager_redirect.WaitForNavigationFinished();
+  navigation_manager_final_url.WaitForNavigationFinished();
+  content::WaitForLoadStop(tab);
+
   CheckSecurityState(tab, CertError::NONE, security_state::NONE,
                      AuthState::DISPLAYED_INSECURE_CONTENT);
 }
diff --git a/chrome/browser/subresource_filter/subresource_filter_browser_test_harness.cc b/chrome/browser/subresource_filter/subresource_filter_browser_test_harness.cc
index 9557f511..c069144 100644
--- a/chrome/browser/subresource_filter/subresource_filter_browser_test_harness.cc
+++ b/chrome/browser/subresource_filter/subresource_filter_browser_test_harness.cc
@@ -77,7 +77,6 @@
   embedded_test_server()->ServeFilesFromDirectory(test_data_dir);
 
   ASSERT_TRUE(embedded_test_server()->Start());
-  ResetConfigurationToEnableOnPhishingSites();
 
   auto* factory = SubresourceFilterProfileContextFactory::GetForProfile(
       browser()->profile());
diff --git a/chrome/browser/subresource_filter/subresource_filter_browsertest.cc b/chrome/browser/subresource_filter/subresource_filter_browsertest.cc
index 45969d7..dba6f178 100644
--- a/chrome/browser/subresource_filter/subresource_filter_browsertest.cc
+++ b/chrome/browser/subresource_filter/subresource_filter_browsertest.cc
@@ -943,8 +943,14 @@
 
 IN_PROC_BROWSER_TEST_F(SubresourceFilterBrowserTest,
                        ExpectHistogramsNotRecordedWhenFilteringNotActivated) {
+  // This test only makes sense when AdTagging is disabled.
+  base::test::ScopedFeatureList scoped_tagging;
+  scoped_tagging.InitAndDisableFeature(kAdTagging);
   ASSERT_NO_FATAL_FAILURE(SetRulesetToDisallowURLsWithPathSuffix(
       "suffix-that-does-not-match-anything"));
+  ResetConfigurationToEnableOnPhishingSites(
+      true /* measure_performance */, false /* whitelist_site_on_reload */);
+
   const GURL url = GetTestUrl(kTestFrameSetPath);
   // Note: The |url| is not configured to be fishing.
 
diff --git a/chrome/browser/subresource_filter/subresource_filter_devtools_browsertest.cc b/chrome/browser/subresource_filter/subresource_filter_devtools_browsertest.cc
index 481ab2e..6104c43a 100644
--- a/chrome/browser/subresource_filter/subresource_filter_devtools_browsertest.cc
+++ b/chrome/browser/subresource_filter/subresource_filter_devtools_browsertest.cc
@@ -9,12 +9,12 @@
 #include "base/memory/ref_counted.h"
 #include "base/values.h"
 #include "chrome/browser/subresource_filter/subresource_filter_browser_test_harness.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/subresource_filter/core/browser/subresource_filter_constants.h"
 #include "content/public/browser/devtools_agent_host.h"
 #include "content/public/browser/devtools_agent_host_client.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/common/content_features.h"
 #include "content/public/test/browser_test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
diff --git a/chrome/browser/sync/chrome_sync_client.cc b/chrome/browser/sync/chrome_sync_client.cc
index 2055826..3ffbaaa 100644
--- a/chrome/browser/sync/chrome_sync_client.cc
+++ b/chrome/browser/sync/chrome_sync_client.cc
@@ -23,7 +23,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
-#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/sync/glue/sync_start_util.h"
 #include "chrome/browser/sync/glue/theme_data_type_controller.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
@@ -56,7 +55,6 @@
 #include "components/password_manager/core/browser/password_store.h"
 #include "components/password_manager/sync/browser/password_model_worker.h"
 #include "components/search_engines/search_engine_data_type_controller.h"
-#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "components/spellcheck/spellcheck_buildflags.h"
 #include "components/sync/base/pref_names.h"
 #include "components/sync/base/report_unrecoverable_error.h"
@@ -220,22 +218,14 @@
 
   // Component factory may already be set in tests.
   if (!GetSyncApiComponentFactory()) {
-    const GURL sync_service_url = syncer::GetSyncServiceURL(
-        *base::CommandLine::ForCurrentProcess(), chrome::GetChannel());
-    ProfileOAuth2TokenService* token_service =
-        ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
-    net::URLRequestContextGetter* url_request_context_getter =
-        profile_->GetRequestContext();
-
     component_factory_ = std::make_unique<ProfileSyncComponentsFactoryImpl>(
         this, chrome::GetChannel(), chrome::GetVersionString(),
         ui::GetDeviceFormFactor() == ui::DEVICE_FORM_FACTOR_TABLET,
         *base::CommandLine::ForCurrentProcess(),
-        prefs::kSavingBrowserHistoryDisabled, sync_service_url,
+        prefs::kSavingBrowserHistoryDisabled,
         content::BrowserThread::GetTaskRunnerForThread(
             content::BrowserThread::UI),
-        db_thread_, token_service, url_request_context_getter,
-        web_data_service_, password_store_);
+        db_thread_, web_data_service_, password_store_);
   }
 }
 
diff --git a/chrome/browser/sync/glue/synced_tab_delegate_android.cc b/chrome/browser/sync/glue/synced_tab_delegate_android.cc
index 84ddfb6..bd16757 100644
--- a/chrome/browser/sync/glue/synced_tab_delegate_android.cc
+++ b/chrome/browser/sync/glue/synced_tab_delegate_android.cc
@@ -8,6 +8,7 @@
 #include "chrome/browser/android/tab_android.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sync/glue/synced_window_delegates_getter_android.h"
+#include "chrome/browser/sync/sessions/sync_sessions_router_tab_helper.h"
 #include "chrome/browser/ui/sync/tab_contents_synced_tab_delegate.h"
 #include "components/sync_sessions/synced_window_delegate.h"
 #include "content/public/browser/navigation_entry.h"
@@ -79,12 +80,18 @@
 }
 
 void SyncedTabDelegateAndroid::SetWebContents(
-    content::WebContents* web_contents) {
+    content::WebContents* web_contents,
+    content::WebContents* source_web_contents) {
   web_contents_ = web_contents;
   TabContentsSyncedTabDelegate::CreateForWebContents(web_contents_);
   // Store the TabContentsSyncedTabDelegate object that was created.
   tab_contents_delegate_ =
       TabContentsSyncedTabDelegate::FromWebContents(web_contents_);
+  if (source_web_contents) {
+    sync_sessions::SyncSessionsRouterTabHelper::FromWebContents(
+        source_web_contents)
+        ->SetSourceTabIdForChild(web_contents_);
+  }
 }
 
 void SyncedTabDelegateAndroid::ResetWebContents() {
diff --git a/chrome/browser/sync/glue/synced_tab_delegate_android.h b/chrome/browser/sync/glue/synced_tab_delegate_android.h
index 836e5f3..c6c1f9f 100644
--- a/chrome/browser/sync/glue/synced_tab_delegate_android.h
+++ b/chrome/browser/sync/glue/synced_tab_delegate_android.h
@@ -55,8 +55,10 @@
   GetBlockedNavigations() const override;
 
   // Set the web contents for this tab. Also creates
-  // TabContentsSyncedTabDelegate for this tab.
-  virtual void SetWebContents(content::WebContents* web_contents);
+  // TabContentsSyncedTabDelegate for this tab and handles source tab id
+  // initialization.
+  virtual void SetWebContents(content::WebContents* web_contents,
+                              content::WebContents* source_web_contents);
   // Set web contents to null.
   virtual void ResetWebContents();
 
diff --git a/chrome/browser/sync/sessions/sync_sessions_router_tab_helper.cc b/chrome/browser/sync/sessions/sync_sessions_router_tab_helper.cc
index 43c6213..474b964 100644
--- a/chrome/browser/sync/sessions/sync_sessions_router_tab_helper.cc
+++ b/chrome/browser/sync/sessions/sync_sessions_router_tab_helper.cc
@@ -69,11 +69,16 @@
     ui::PageTransition transition,
     bool started_from_context_menu,
     bool renderer_initiated) {
+  SetSourceTabIdForChild(new_contents);
+}
+
+void SyncSessionsRouterTabHelper::SetSourceTabIdForChild(
+    content::WebContents* child_contents) {
   SessionID::id_type source_tab_id = SessionTabHelper::IdForTab(web_contents());
-  if (new_contents &&
-      SyncSessionsRouterTabHelper::FromWebContents(new_contents) &&
-      new_contents != web_contents() && source_tab_id != kInvalidTabID) {
-    SyncSessionsRouterTabHelper::FromWebContents(new_contents)
+  if (child_contents &&
+      SyncSessionsRouterTabHelper::FromWebContents(child_contents) &&
+      child_contents != web_contents() && source_tab_id != kInvalidTabID) {
+    SyncSessionsRouterTabHelper::FromWebContents(child_contents)
         ->set_source_tab_id(source_tab_id);
   }
   NotifyRouter();
diff --git a/chrome/browser/sync/sessions/sync_sessions_router_tab_helper.h b/chrome/browser/sync/sessions/sync_sessions_router_tab_helper.h
index b345cd9b..aeb8aa7 100644
--- a/chrome/browser/sync/sessions/sync_sessions_router_tab_helper.h
+++ b/chrome/browser/sync/sessions/sync_sessions_router_tab_helper.h
@@ -46,6 +46,10 @@
                            bool started_from_context_menu,
                            bool renderer_initiated) override;
 
+  // Sets the source tab id for the given child WebContents to the id of the
+  // WebContents that owns this helper.
+  void SetSourceTabIdForChild(content::WebContents* child_contents);
+
   // Get the tab id of the tab responsible for creating the tab this helper
   // corresponds to. Returns -1 if there is no such tab.
   SessionID::id_type source_tab_id() const { return source_tab_id_; }
diff --git a/chrome/browser/task_manager/sampling/task_group_sampler.cc b/chrome/browser/task_manager/sampling/task_group_sampler.cc
index d8b72bd..c838e91 100644
--- a/chrome/browser/task_manager/sampling/task_group_sampler.cc
+++ b/chrome/browser/task_manager/sampling/task_group_sampler.cc
@@ -130,10 +130,9 @@
   DCHECK(worker_pool_sequenced_checker_.CalledOnValidSequence());
 
 #if defined(OS_CHROMEOS)
-  base::WorkingSetKBytes ws_usage;
-  if (process_metrics_->GetWorkingSetKBytes(&ws_usage)) {
-    return ws_usage.swapped * 1024;
-  }
+  base::ProcessMetrics::TotalsSummary summary =
+      process_metrics_->GetTotalsSummary();
+  return summary.swap_kb * 1024;
 #endif  // defined(OS_CHROMEOS)
 
   return 0;
diff --git a/chrome/browser/themes/theme_properties.cc b/chrome/browser/themes/theme_properties.cc
index 29c1a3ce..7462b3ea 100644
--- a/chrome/browser/themes/theme_properties.cc
+++ b/chrome/browser/themes/theme_properties.cc
@@ -161,16 +161,11 @@
 constexpr char kTilingRepeatY[] = "repeat-y";
 constexpr char kTilingRepeat[] = "repeat";
 
-// Returns a |nullopt| if the touch-optimized UI is not enabled, or it's enabled
-// but for the given |id|, there's no touch-optimized specific colors, and we
-// should fall back to the default colors.
-// TODO(malaykeshav): Put this behind a flag separate from Touch Optimized Ui.
-// We want to be able to use it for other modes as well.
-// https://crbug/810165
-base::Optional<SkColor> MaybeGetDefaultColorForTouchOptimizedUi(
-    int id,
-    bool incognito) {
-  if (!ui::MaterialDesignController::IsTouchOptimizedUiEnabled())
+// Returns a |nullopt| if the newer material UI is not enabled (MD refresh or
+// touch-optimized UI).
+base::Optional<SkColor> MaybeGetDefaultColorForNewerMaterialUi(int id,
+                                                               bool incognito) {
+  if (!ui::MaterialDesignController::IsNewerMaterialUi())
     return base::nullopt;
 
   switch (id) {
@@ -300,7 +295,7 @@
 // static
 SkColor ThemeProperties::GetDefaultColor(int id, bool incognito) {
   const base::Optional<SkColor> color =
-      MaybeGetDefaultColorForTouchOptimizedUi(id, incognito);
+      MaybeGetDefaultColorForNewerMaterialUi(id, incognito);
   if (color)
     return color.value();
 
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index b5b537f..3b7b34ca 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -2055,6 +2055,8 @@
       "webui/chromeos/mobile_setup_dialog.h",
       "webui/chromeos/mobile_setup_ui.cc",
       "webui/chromeos/mobile_setup_ui.h",
+      "webui/chromeos/multidevice_setup/multidevice_setup_dialog.cc",
+      "webui/chromeos/multidevice_setup/multidevice_setup_dialog.h",
       "webui/chromeos/network_element_localized_strings_provider.cc",
       "webui/chromeos/network_element_localized_strings_provider.h",
       "webui/chromeos/network_ui.cc",
diff --git a/chrome/browser/ui/android/toolbar/toolbar_model_android.cc b/chrome/browser/ui/android/toolbar/toolbar_model_android.cc
index d03f8e1..06cdf6e 100644
--- a/chrome/browser/ui/android/toolbar/toolbar_model_android.cc
+++ b/chrome/browser/ui/android/toolbar/toolbar_model_android.cc
@@ -27,13 +27,20 @@
   delete this;
 }
 
-ScopedJavaLocalRef<jstring> ToolbarModelAndroid::GetText(
+ScopedJavaLocalRef<jstring> ToolbarModelAndroid::GetFormattedFullURL(
     JNIEnv* env,
     const JavaParamRef<jobject>& obj) {
   return base::android::ConvertUTF16ToJavaString(
       env, toolbar_model_->GetFormattedFullURL());
 }
 
+ScopedJavaLocalRef<jstring> ToolbarModelAndroid::GetURLForDisplay(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj) {
+  return base::android::ConvertUTF16ToJavaString(
+      env, toolbar_model_->GetURLForDisplay());
+}
+
 content::WebContents* ToolbarModelAndroid::GetActiveWebContents() const {
   JNIEnv* env = base::android::AttachCurrentThread();
   ScopedJavaLocalRef<jobject> jdelegate = weak_java_delegate_.get(env);
diff --git a/chrome/browser/ui/android/toolbar/toolbar_model_android.h b/chrome/browser/ui/android/toolbar/toolbar_model_android.h
index 761ad55..d5eaaf8 100644
--- a/chrome/browser/ui/android/toolbar/toolbar_model_android.h
+++ b/chrome/browser/ui/android/toolbar/toolbar_model_android.h
@@ -25,7 +25,10 @@
   ~ToolbarModelAndroid() override;
 
   void Destroy(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
-  base::android::ScopedJavaLocalRef<jstring> GetText(
+  base::android::ScopedJavaLocalRef<jstring> GetFormattedFullURL(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
+  base::android::ScopedJavaLocalRef<jstring> GetURLForDisplay(
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& obj);
 
diff --git a/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc b/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc
index 0a0b3f99..d22bd25 100644
--- a/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc
+++ b/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc
@@ -439,7 +439,8 @@
 
   VLOG(2) << this << " UpdateAppItemFromSyncItem: " << sync_item->ToString();
   if (sync_item->item_ordinal.IsValid() &&
-      !chrome_item->position().Equals(sync_item->item_ordinal)) {
+      (!chrome_item->position().IsValid() ||
+       !chrome_item->position().Equals(sync_item->item_ordinal))) {
     // This updates the position in both chrome and ash:
     chrome_item->SetPosition(sync_item->item_ordinal);
   }
diff --git a/chrome/browser/ui/app_list/search/omnibox_result.cc b/chrome/browser/ui/app_list/search/omnibox_result.cc
index 2090230..4bfd596e 100644
--- a/chrome/browser/ui/app_list/search/omnibox_result.cc
+++ b/chrome/browser/ui/app_list/search/omnibox_result.cc
@@ -144,18 +144,6 @@
 
   UpdateIcon();
   UpdateTitleAndDetails();
-
-  // The raw "what you typed" search results should be promoted and
-  // automatically selected by voice queries. If a "history" result exactly
-  // matches what you typed, then the omnibox will not produce a "what you
-  // typed" result; therefore, we must also flag "history" results as voice
-  // results if they exactly match the query.
-  if (match_.type == AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED ||
-      (match_.type == AutocompleteMatchType::SEARCH_HISTORY &&
-       match_.search_terms_args &&
-       match_.contents == match_.search_terms_args->original_query)) {
-    set_voice_result(true);
-  }
 }
 
 OmniboxResult::~OmniboxResult() = default;
diff --git a/chrome/browser/ui/app_list/search/tests/mixer_unittest.cc b/chrome/browser/ui/app_list/search/tests/mixer_unittest.cc
index 4e94edf97..aa155b97 100644
--- a/chrome/browser/ui/app_list/search/tests/mixer_unittest.cc
+++ b/chrome/browser/ui/app_list/search/tests/mixer_unittest.cc
@@ -7,7 +7,6 @@
 #include <stddef.h>
 
 #include <memory>
-#include <set>
 #include <string>
 #include <vector>
 
@@ -43,8 +42,6 @@
   }
   ~TestSearchResult() override {}
 
-  using SearchResult::set_voice_result;
-
   // SearchResult overrides:
   void Open(int event_flags) override {}
   void InvokeAction(int action_index, int event_flags) override {}
@@ -90,8 +87,6 @@
         relevance = 10.0 - i * 10;
       TestSearchResult* result = new TestSearchResult(id, relevance);
       result->set_display_type(display_type_);
-      if (voice_result_indices.find(i) != voice_result_indices.end())
-        result->set_voice_result(true);
       Add(std::unique_ptr<SearchResult>(result));
     }
   }
@@ -101,7 +96,6 @@
     display_type_ = display_type;
   }
   void set_count(size_t count) { count_ = count; }
-  void set_as_voice_result(size_t index) { voice_result_indices.insert(index); }
   void set_bad_relevance_range() { bad_relevance_range_ = true; }
 
  private:
@@ -109,8 +103,6 @@
   size_t count_;
   bool bad_relevance_range_;
   SearchResult::DisplayType display_type_;
-  // Indices of results that will have the |voice_result| flag set.
-  std::set<size_t> voice_result_indices;
 
   DISALLOW_COPY_AND_ASSIGN(TestSearchProvider);
 };
diff --git a/chrome/browser/ui/app_list/search/tests/omnibox_result_unittest.cc b/chrome/browser/ui/app_list/search/tests/omnibox_result_unittest.cc
index 5c31175..d1e79b5 100644
--- a/chrome/browser/ui/app_list/search/tests/omnibox_result_unittest.cc
+++ b/chrome/browser/ui/app_list/search/tests/omnibox_result_unittest.cc
@@ -22,7 +22,6 @@
 namespace {
 
 const char kFullQuery[] = "Hello World";
-const char kPartialQuery[] = "Hello Wo";
 const char kExampleDescription[] = "A website";
 const char kExampleUrl[] = "http://example.com/hello";
 const int kRelevance = 750;
@@ -87,54 +86,10 @@
   EXPECT_EQ(base::ASCIIToUTF16(kExampleDescription), result->title());
   EXPECT_EQ(base::ASCIIToUTF16(kFullQuery), result->details());
   EXPECT_EQ(kAppListRelevance, result->relevance());
-  EXPECT_FALSE(result->voice_result());
 
   result->Open(0);
   EXPECT_EQ(kExampleUrl, GetLastOpenedUrl().spec());
 }
 
-TEST_F(OmniboxResultTest, VoiceResult) {
-  // Searching for part of a word, and getting a HISTORY_URL result with that
-  // exact string in the title. Should not be automatically launchable as a
-  // voice result (because it is not a web search type result).
-  {
-    std::unique_ptr<OmniboxResult> result = CreateOmniboxResult(
-        kPartialQuery, kRelevance, kExampleUrl, kPartialQuery,
-        kExampleDescription, AutocompleteMatchType::HISTORY_URL,
-        kExampleKeyword);
-    EXPECT_FALSE(result->voice_result());
-  }
-
-  // Searching for part of a word, and getting a SEARCH_WHAT_YOU_TYPED result.
-  // Such a result should be promoted as a voice result.
-  {
-    std::unique_ptr<OmniboxResult> result = CreateOmniboxResult(
-        kPartialQuery, kRelevance, kExampleUrl, kPartialQuery,
-        kExampleDescription, AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
-        kExampleKeyword);
-    EXPECT_TRUE(result->voice_result());
-  }
-
-  // Searching for part of a word, and getting a SEARCH_HISTORY result for that
-  // exact string. Such a result should be promoted as a voice result.
-  {
-    std::unique_ptr<OmniboxResult> result = CreateOmniboxResult(
-        kPartialQuery, kRelevance, kExampleUrl, kPartialQuery,
-        kExampleDescription, AutocompleteMatchType::SEARCH_HISTORY,
-        kExampleKeyword);
-    EXPECT_TRUE(result->voice_result());
-  }
-
-  // Searching for part of a word, and getting a SEARCH_HISTORY result for a
-  // different string. Should not be automatically launchable as a voice result
-  // (because it does not exactly match what you typed).
-  {
-    std::unique_ptr<OmniboxResult> result = CreateOmniboxResult(
-        kPartialQuery, kRelevance, kExampleUrl, kFullQuery, kExampleDescription,
-        AutocompleteMatchType::SEARCH_HISTORY, kExampleKeyword);
-    EXPECT_FALSE(result->voice_result());
-  }
-}
-
 }  // namespace test
 }  // namespace app_list
diff --git a/chrome/browser/ui/app_list/test/fake_app_list_model_updater.cc b/chrome/browser/ui/app_list/test/fake_app_list_model_updater.cc
index bc52dad..c5fb8df7 100644
--- a/chrome/browser/ui/app_list/test/fake_app_list_model_updater.cc
+++ b/chrome/browser/ui/app_list/test/fake_app_list_model_updater.cc
@@ -192,7 +192,8 @@
 
   VLOG(2) << this << " UpdateAppItemFromSyncItem: " << sync_item->ToString();
   if (sync_item->item_ordinal.IsValid() &&
-      !chrome_item->position().Equals(sync_item->item_ordinal)) {
+      (!chrome_item->position().IsValid() ||
+       !chrome_item->position().Equals(sync_item->item_ordinal))) {
     // This updates the position in both chrome and ash:
     chrome_item->SetPosition(sync_item->item_ordinal);
   }
diff --git a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc
index 0be6ca9..81d7a12 100644
--- a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc
+++ b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.h"
 
+#include <utility>
+
 #include "ash/public/cpp/ash_features.h"
 #include "ash/public/cpp/ash_switches.h"
 #include "ash/public/cpp/mus_property_mirror_ash.h"
@@ -313,6 +315,10 @@
   cast_config_client_media_router_.reset();
   accessibility_controller_client_.reset();
 
+  // AppListClientImpl indirectly holds WebContents for answer card and
+  // needs to be released before destroying the profile.
+  app_list_client_.reset();
+
   ash_shell_init_.reset();
 
   chromeos::NetworkConnect::Shutdown();
diff --git a/chrome/browser/ui/ash/login_screen_client.cc b/chrome/browser/ui/ash/login_screen_client.cc
index 7142062..199d03f 100644
--- a/chrome/browser/ui/ash/login_screen_client.cc
+++ b/chrome/browser/ui/ash/login_screen_client.cc
@@ -129,6 +129,13 @@
                                                nullptr /*delegate*/);
 }
 
+void LoginScreenClient::LaunchPublicSession(const AccountId& account_id,
+                                            const std::string& locale,
+                                            const std::string& input_method) {
+  if (delegate_)
+    delegate_->HandleLaunchPublicSession(account_id, locale, input_method);
+}
+
 void LoginScreenClient::LoadWallpaper(const AccountId& account_id) {
   WallpaperControllerClient::Get()->ShowUserWallpaper(account_id);
 }
diff --git a/chrome/browser/ui/ash/login_screen_client.h b/chrome/browser/ui/ash/login_screen_client.h
index 2a186f60..a5f49c3 100644
--- a/chrome/browser/ui/ash/login_screen_client.h
+++ b/chrome/browser/ui/ash/login_screen_client.h
@@ -39,6 +39,9 @@
     // fail if a hander for lock screen apps focus has not been set.
     virtual bool HandleFocusLockScreenApps(bool reverse) = 0;
     virtual void HandleLoginAsGuest() = 0;
+    virtual void HandleLaunchPublicSession(const AccountId& account_id,
+                                           const std::string& locale,
+                                           const std::string& input_method) = 0;
 
    private:
     DISALLOW_COPY_AND_ASSIGN(Delegate);
@@ -76,6 +79,9 @@
   void ShowGaiaSignin() override;
   void OnRemoveUserWarningShown() override;
   void RemoveUser(const AccountId& account_id) override;
+  void LaunchPublicSession(const AccountId& account_id,
+                           const std::string& locale,
+                           const std::string& input_method) override;
 
  private:
   // Lock screen mojo service in ash.
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_test.cc b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_test.cc
deleted file mode 100644
index b468d41..0000000
--- a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_test.cc
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_test.h"
-
-#include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
-#include "chrome/browser/ui/browser_window.h"
-#include "components/signin/core/account_id/account_id.h"
-#include "ui/aura/window.h"
-
-TestMultiUserWindowManager::TestMultiUserWindowManager(
-    Browser* visiting_browser,
-    const AccountId& desktop_owner)
-    : browser_window_(visiting_browser->window()->GetNativeWindow()),
-      browser_owner_(multi_user_util::GetAccountIdFromProfile(
-          visiting_browser->profile())),
-      desktop_owner_(desktop_owner),
-      created_window_(NULL),
-      created_window_shown_for_(browser_owner_),
-      current_account_id_(desktop_owner) {
-  // Register this object with the system (which will take ownership). It will
-  // be deleted by ChromeLauncherController::~ChromeLauncherController().
-  MultiUserWindowManager::SetInstanceForTest(this);
-}
-
-TestMultiUserWindowManager::~TestMultiUserWindowManager() {
-  // This object is owned by the MultiUserWindowManager since the
-  // SetInstanceForTest call. As such no uninstall is required.
-}
-
-void TestMultiUserWindowManager::SetWindowOwner(aura::Window* window,
-                                                const AccountId& account_id) {
-  NOTREACHED();
-}
-
-const AccountId& TestMultiUserWindowManager::GetWindowOwner(
-    aura::Window* window) const {
-  // No matter which window will get queried - all browsers belong to the
-  // original browser's user.
-  return browser_owner_;
-}
-
-void TestMultiUserWindowManager::ShowWindowForUser(
-    aura::Window* window,
-    const AccountId& account_id) {
-  // This class is only able to handle one additional window <-> user
-  // association beside the creation parameters.
-  // If no association has yet been requested remember it now.
-  DCHECK(!created_window_);
-  created_window_ = window;
-  created_window_shown_for_ = account_id;
-
-  if (browser_window_ == window)
-    desktop_owner_ = account_id;
-
-  if (account_id == current_account_id_)
-    return;
-
-  // Change the visibility of the window to update the view recursively.
-  window->Hide();
-  window->Show();
-  current_account_id_ = account_id;
-}
-
-bool TestMultiUserWindowManager::AreWindowsSharedAmongUsers() const {
-  return browser_owner_ != desktop_owner_;
-}
-
-void TestMultiUserWindowManager::GetOwnersOfVisibleWindows(
-    std::set<AccountId>* account_ids) const {}
-
-bool TestMultiUserWindowManager::IsWindowOnDesktopOfUser(
-    aura::Window* window,
-    const AccountId& account_id) const {
-  return GetUserPresentingWindow(window) == account_id;
-}
-
-const AccountId& TestMultiUserWindowManager::GetUserPresentingWindow(
-    aura::Window* window) const {
-  if (window == browser_window_)
-    return desktop_owner_;
-  if (created_window_ && window == created_window_)
-    return created_window_shown_for_;
-  // We can come here before the window gets registered.
-  return browser_owner_;
-}
-
-void TestMultiUserWindowManager::AddUser(content::BrowserContext* profile) {}
-
-void TestMultiUserWindowManager::AddObserver(Observer* observer) {}
-
-void TestMultiUserWindowManager::RemoveObserver(Observer* observer) {}
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_test.h b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_test.h
deleted file mode 100644
index 22ff877..0000000
--- a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_test.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_ASH_MULTI_USER_MULTI_USER_WINDOW_MANAGER_TEST_H_
-#define CHROME_BROWSER_UI_ASH_MULTI_USER_MULTI_USER_WINDOW_MANAGER_TEST_H_
-
-#include "base/macros.h"
-#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
-#include "components/signin/core/account_id/account_id.h"
-
-class Browser;
-
-// This is a test implementation of a MultiUserWindowManager which allows to
-// test a visiting window on another desktop. It will install and remove itself
-// from the system upon creation / destruction.
-// The creation function gets a |browser| which is shown on |desktop_owner|'s
-// desktop.
-class TestMultiUserWindowManager : public MultiUserWindowManager {
- public:
-  TestMultiUserWindowManager(Browser* visiting_browser,
-                             const AccountId& desktop_owner);
-  ~TestMultiUserWindowManager() override;
-
-  aura::Window* created_window() { return created_window_; }
-
-  // MultiUserWindowManager overrides:
-  void SetWindowOwner(aura::Window* window,
-                      const AccountId& account_id) override;
-  const AccountId& GetWindowOwner(aura::Window* window) const override;
-  void ShowWindowForUser(aura::Window* window,
-                         const AccountId& account_id) override;
-  bool AreWindowsSharedAmongUsers() const override;
-  void GetOwnersOfVisibleWindows(
-      std::set<AccountId>* account_ids) const override;
-  bool IsWindowOnDesktopOfUser(aura::Window* window,
-                               const AccountId& account_id) const override;
-  const AccountId& GetUserPresentingWindow(aura::Window* window) const override;
-  void AddUser(content::BrowserContext* profile) override;
-  void AddObserver(Observer* observer) override;
-  void RemoveObserver(Observer* observer) override;
-
- private:
-  // The window of the visiting browser.
-  aura::Window* browser_window_;
-  // The owner of the visiting browser.
-  AccountId browser_owner_;
-  // The owner of the currently shown desktop.
-  AccountId desktop_owner_;
-  // The created window.
-  aura::Window* created_window_;
-  // The location of the window.
-  AccountId created_window_shown_for_;
-  // The current selected active user.
-  AccountId current_account_id_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestMultiUserWindowManager);
-};
-
-#endif  // CHROME_BROWSER_UI_ASH_MULTI_USER_MULTI_USER_WINDOW_MANAGER_TEST_H_
diff --git a/chrome/browser/ui/ash/multi_user/test_multi_user_window_manager.cc b/chrome/browser/ui/ash/multi_user/test_multi_user_window_manager.cc
new file mode 100644
index 0000000..9586b5d
--- /dev/null
+++ b/chrome/browser/ui/ash/multi_user/test_multi_user_window_manager.cc
@@ -0,0 +1,94 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/ash/multi_user/test_multi_user_window_manager.h"
+
+#include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "components/signin/core/account_id/account_id.h"
+#include "ui/aura/window.h"
+
+TestMultiUserWindowManager::TestMultiUserWindowManager(
+    Browser* visiting_browser,
+    const AccountId& desktop_owner)
+    : browser_window_(visiting_browser->window()->GetNativeWindow()),
+      browser_owner_(multi_user_util::GetAccountIdFromProfile(
+          visiting_browser->profile())),
+      desktop_owner_(desktop_owner),
+      created_window_(NULL),
+      created_window_shown_for_(browser_owner_),
+      current_account_id_(desktop_owner) {
+  // Register this object with the system (which will take ownership). It will
+  // be deleted by ChromeLauncherController::~ChromeLauncherController().
+  MultiUserWindowManager::SetInstanceForTest(this);
+}
+
+TestMultiUserWindowManager::~TestMultiUserWindowManager() {
+  // This object is owned by the MultiUserWindowManager since the
+  // SetInstanceForTest call. As such no uninstall is required.
+}
+
+void TestMultiUserWindowManager::SetWindowOwner(aura::Window* window,
+                                                const AccountId& account_id) {
+  NOTREACHED();
+}
+
+const AccountId& TestMultiUserWindowManager::GetWindowOwner(
+    aura::Window* window) const {
+  // No matter which window will get queried - all browsers belong to the
+  // original browser's user.
+  return browser_owner_;
+}
+
+void TestMultiUserWindowManager::ShowWindowForUser(
+    aura::Window* window,
+    const AccountId& account_id) {
+  // This class is only able to handle one additional window <-> user
+  // association beside the creation parameters.
+  // If no association has yet been requested remember it now.
+  if (browser_owner_ != account_id)
+    DCHECK(!created_window_);
+  created_window_ = window;
+  created_window_shown_for_ = account_id;
+
+  if (browser_window_ == window)
+    desktop_owner_ = account_id;
+
+  if (account_id == current_account_id_)
+    return;
+
+  // Change the visibility of the window to update the view recursively.
+  window->Hide();
+  window->Show();
+  current_account_id_ = account_id;
+}
+
+bool TestMultiUserWindowManager::AreWindowsSharedAmongUsers() const {
+  return browser_owner_ != desktop_owner_;
+}
+
+void TestMultiUserWindowManager::GetOwnersOfVisibleWindows(
+    std::set<AccountId>* account_ids) const {}
+
+bool TestMultiUserWindowManager::IsWindowOnDesktopOfUser(
+    aura::Window* window,
+    const AccountId& account_id) const {
+  return GetUserPresentingWindow(window) == account_id;
+}
+
+const AccountId& TestMultiUserWindowManager::GetUserPresentingWindow(
+    aura::Window* window) const {
+  if (window == browser_window_)
+    return desktop_owner_;
+  if (created_window_ && window == created_window_)
+    return created_window_shown_for_;
+  // We can come here before the window gets registered.
+  return browser_owner_;
+}
+
+void TestMultiUserWindowManager::AddUser(content::BrowserContext* profile) {}
+
+void TestMultiUserWindowManager::AddObserver(Observer* observer) {}
+
+void TestMultiUserWindowManager::RemoveObserver(Observer* observer) {}
diff --git a/chrome/browser/ui/ash/multi_user/test_multi_user_window_manager.h b/chrome/browser/ui/ash/multi_user/test_multi_user_window_manager.h
new file mode 100644
index 0000000..a1b4b50
--- /dev/null
+++ b/chrome/browser/ui/ash/multi_user/test_multi_user_window_manager.h
@@ -0,0 +1,60 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_ASH_MULTI_USER_TEST_MULTI_USER_WINDOW_MANAGER_H_
+#define CHROME_BROWSER_UI_ASH_MULTI_USER_TEST_MULTI_USER_WINDOW_MANAGER_H_
+
+#include "base/macros.h"
+#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
+#include "components/signin/core/account_id/account_id.h"
+
+class Browser;
+
+// This is a test implementation of a MultiUserWindowManager which allows to
+// test a visiting window on another desktop. It will install and remove itself
+// from the system upon creation / destruction.
+// The creation function gets a |browser| which is shown on |desktop_owner|'s
+// desktop.
+class TestMultiUserWindowManager : public MultiUserWindowManager {
+ public:
+  TestMultiUserWindowManager(Browser* visiting_browser,
+                             const AccountId& desktop_owner);
+  ~TestMultiUserWindowManager() override;
+
+  aura::Window* created_window() { return created_window_; }
+
+  // MultiUserWindowManager overrides:
+  void SetWindowOwner(aura::Window* window,
+                      const AccountId& account_id) override;
+  const AccountId& GetWindowOwner(aura::Window* window) const override;
+  void ShowWindowForUser(aura::Window* window,
+                         const AccountId& account_id) override;
+  bool AreWindowsSharedAmongUsers() const override;
+  void GetOwnersOfVisibleWindows(
+      std::set<AccountId>* account_ids) const override;
+  bool IsWindowOnDesktopOfUser(aura::Window* window,
+                               const AccountId& account_id) const override;
+  const AccountId& GetUserPresentingWindow(aura::Window* window) const override;
+  void AddUser(content::BrowserContext* profile) override;
+  void AddObserver(Observer* observer) override;
+  void RemoveObserver(Observer* observer) override;
+
+ private:
+  // The window of the visiting browser.
+  aura::Window* browser_window_;
+  // The owner of the visiting browser.
+  AccountId browser_owner_;
+  // The owner of the currently shown desktop.
+  AccountId desktop_owner_;
+  // The created window.
+  aura::Window* created_window_;
+  // The location of the window.
+  AccountId created_window_shown_for_;
+  // The current selected active user.
+  AccountId current_account_id_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestMultiUserWindowManager);
+};
+
+#endif  // CHROME_BROWSER_UI_ASH_MULTI_USER_TEST_MULTI_USER_WINDOW_MANAGER_H_
diff --git a/chrome/browser/ui/ash/system_tray_client.cc b/chrome/browser/ui/ash/system_tray_client.cc
index e28d1c53..868000a 100644
--- a/chrome/browser/ui/ash/system_tray_client.cc
+++ b/chrome/browser/ui/ash/system_tray_client.cc
@@ -32,6 +32,7 @@
 #include "chrome/browser/ui/webui/chromeos/bluetooth_pairing_dialog.h"
 #include "chrome/browser/ui/webui/chromeos/internet_config_dialog.h"
 #include "chrome/browser/ui/webui/chromeos/internet_detail_dialog.h"
+#include "chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_dialog.h"
 #include "chrome/browser/upgrade_detector.h"
 #include "chrome/common/url_constants.h"
 #include "chromeos/chromeos_switches.h"
@@ -427,6 +428,10 @@
   ShowSettingsSubPageForActiveUser(page);
 }
 
+void SystemTrayClient::ShowMultiDeviceSetup() {
+  chromeos::multidevice_setup::MultiDeviceSetupDialog::Show();
+}
+
 void SystemTrayClient::RequestRestartForUpdate() {
   // Flash updates on Chrome OS require device reboot.
   const browser_shutdown::RebootPolicy reboot_policy =
diff --git a/chrome/browser/ui/ash/system_tray_client.h b/chrome/browser/ui/ash/system_tray_client.h
index 0521b73..6be0cd3a 100644
--- a/chrome/browser/ui/ash/system_tray_client.h
+++ b/chrome/browser/ui/ash/system_tray_client.h
@@ -79,6 +79,7 @@
   void ShowThirdPartyVpnCreate(const std::string& extension_id) override;
   void ShowArcVpnCreate(const std::string& app_id) override;
   void ShowNetworkSettings(const std::string& network_id) override;
+  void ShowMultiDeviceSetup() override;
   void RequestRestartForUpdate() override;
 
  private:
diff --git a/chrome/browser/ui/ash/test_wallpaper_controller.cc b/chrome/browser/ui/ash/test_wallpaper_controller.cc
index bb0204c..5984b8c 100644
--- a/chrome/browser/ui/ash/test_wallpaper_controller.cc
+++ b/chrome/browser/ui/ash/test_wallpaper_controller.cc
@@ -41,7 +41,7 @@
     ash::mojom::WallpaperUserInfoPtr user_info,
     const std::string& wallpaper_files_id,
     const std::string& file_name,
-    wallpaper::WallpaperLayout layout,
+    ash::WallpaperLayout layout,
     const gfx::ImageSkia& image,
     bool preview_mode) {
   set_custom_wallpaper_count_++;
@@ -51,7 +51,7 @@
     ash::mojom::WallpaperUserInfoPtr user_info,
     const gfx::ImageSkia& image,
     const std::string& url,
-    wallpaper::WallpaperLayout layout,
+    ash::WallpaperLayout layout,
     bool preview_mode) {
   NOTIMPLEMENTED();
 }
@@ -84,7 +84,7 @@
     ash::mojom::WallpaperUserInfoPtr user_info,
     const std::string& wallpaper_files_id,
     const std::string& file_name,
-    wallpaper::WallpaperLayout layout,
+    ash::WallpaperLayout layout,
     const gfx::ImageSkia& image,
     ash::mojom::WallpaperController::SetThirdPartyWallpaperCallback callback) {
   std::move(callback).Run(true /*allowed=*/, dummy_image_id);
@@ -101,7 +101,7 @@
 
 void TestWallpaperController::UpdateCustomWallpaperLayout(
     ash::mojom::WallpaperUserInfoPtr user_info,
-    wallpaper::WallpaperLayout layout) {
+    ash::WallpaperLayout layout) {
   NOTIMPLEMENTED();
 }
 
diff --git a/chrome/browser/ui/ash/test_wallpaper_controller.h b/chrome/browser/ui/ash/test_wallpaper_controller.h
index 19404d2..73404334 100644
--- a/chrome/browser/ui/ash/test_wallpaper_controller.h
+++ b/chrome/browser/ui/ash/test_wallpaper_controller.h
@@ -45,13 +45,13 @@
   void SetCustomWallpaper(ash::mojom::WallpaperUserInfoPtr user_info,
                           const std::string& wallpaper_files_id,
                           const std::string& file_name,
-                          wallpaper::WallpaperLayout layout,
+                          ash::WallpaperLayout layout,
                           const gfx::ImageSkia& image,
                           bool preview_mode) override;
   void SetOnlineWallpaper(ash::mojom::WallpaperUserInfoPtr user_info,
                           const gfx::ImageSkia& image,
                           const std::string& url,
-                          wallpaper::WallpaperLayout layout,
+                          ash::WallpaperLayout layout,
                           bool preview_mode) override;
   void SetDefaultWallpaper(ash::mojom::WallpaperUserInfoPtr user_info,
                            const std::string& wallpaper_files_id,
@@ -67,14 +67,14 @@
       ash::mojom::WallpaperUserInfoPtr user_info,
       const std::string& wallpaper_files_id,
       const std::string& file_name,
-      wallpaper::WallpaperLayout layout,
+      ash::WallpaperLayout layout,
       const gfx::ImageSkia& image,
       ash::mojom::WallpaperController::SetThirdPartyWallpaperCallback callback)
       override;
   void ConfirmPreviewWallpaper() override;
   void CancelPreviewWallpaper() override;
   void UpdateCustomWallpaperLayout(ash::mojom::WallpaperUserInfoPtr user_info,
-                                   wallpaper::WallpaperLayout layout) override;
+                                   ash::WallpaperLayout layout) override;
   void ShowUserWallpaper(ash::mojom::WallpaperUserInfoPtr user_info) override;
   void ShowSigninWallpaper() override;
   void RemoveUserWallpaper(ash::mojom::WallpaperUserInfoPtr user_info,
diff --git a/chrome/browser/ui/ash/wallpaper_controller_client.cc b/chrome/browser/ui/ash/wallpaper_controller_client.cc
index 586ba44..32d505e 100644
--- a/chrome/browser/ui/ash/wallpaper_controller_client.cc
+++ b/chrome/browser/ui/ash/wallpaper_controller_client.cc
@@ -24,7 +24,6 @@
 #include "chromeos/cryptohome/system_salt_getter.h"
 #include "components/user_manager/known_user.h"
 #include "components/user_manager/user_manager.h"
-#include "components/wallpaper/wallpaper_files_id.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/common/service_manager_connection.h"
 #include "extensions/browser/extension_system.h"
@@ -75,8 +74,7 @@
 //    and we may lose user => wallpaper files mapping at that point.
 // So this function gives WallpaperManager independent hashing method to break
 // this dependency.
-wallpaper::WallpaperFilesId HashWallpaperFilesIdStr(
-    const std::string& files_id_unhashed) {
+std::string HashWallpaperFilesIdStr(const std::string& files_id_unhashed) {
   chromeos::SystemSaltGetter* salt_getter = chromeos::SystemSaltGetter::Get();
   DCHECK(salt_getter);
 
@@ -95,7 +93,7 @@
   base::SHA1HashBytes(data.data(), data.size(), binmd);
   std::string result = base::HexEncode(binmd, sizeof(binmd));
   std::transform(result.begin(), result.end(), result.begin(), ::tolower);
-  return wallpaper::WallpaperFilesId::FromString(result);
+  return result;
 }
 
 // Returns true if wallpaper files id can be returned successfully.
@@ -163,27 +161,27 @@
   return g_wallpaper_controller_client_instance;
 }
 
-wallpaper::WallpaperFilesId WallpaperControllerClient::GetFilesId(
+std::string WallpaperControllerClient::GetFilesId(
     const AccountId& account_id) const {
   DCHECK(CanGetFilesId());
   std::string stored_value;
   if (user_manager::known_user::GetStringPref(account_id, kWallpaperFilesId,
                                               &stored_value)) {
-    return wallpaper::WallpaperFilesId::FromString(stored_value);
+    return stored_value;
   }
 
-  const wallpaper::WallpaperFilesId wallpaper_files_id =
+  const std::string wallpaper_files_id =
       HashWallpaperFilesIdStr(account_id.GetUserEmail());
   user_manager::known_user::SetStringPref(account_id, kWallpaperFilesId,
-                                          wallpaper_files_id.id());
+                                          wallpaper_files_id);
   return wallpaper_files_id;
 }
 
 void WallpaperControllerClient::SetCustomWallpaper(
     const AccountId& account_id,
-    const wallpaper::WallpaperFilesId& wallpaper_files_id,
+    const std::string& wallpaper_files_id,
     const std::string& file_name,
-    wallpaper::WallpaperLayout layout,
+    ash::WallpaperLayout layout,
     const gfx::ImageSkia& image,
     bool preview_mode) {
   ash::mojom::WallpaperUserInfoPtr user_info =
@@ -191,16 +189,15 @@
   if (!user_info)
     return;
   wallpaper_controller_->SetCustomWallpaper(std::move(user_info),
-                                            wallpaper_files_id.id(), file_name,
+                                            wallpaper_files_id, file_name,
                                             layout, image, preview_mode);
 }
 
-void WallpaperControllerClient::SetOnlineWallpaper(
-    const AccountId& account_id,
-    const gfx::ImageSkia& image,
-    const std::string& url,
-    wallpaper::WallpaperLayout layout,
-    bool preview_mode) {
+void WallpaperControllerClient::SetOnlineWallpaper(const AccountId& account_id,
+                                                   const gfx::ImageSkia& image,
+                                                   const std::string& url,
+                                                   ash::WallpaperLayout layout,
+                                                   bool preview_mode) {
   ash::mojom::WallpaperUserInfoPtr user_info =
       AccountIdToWallpaperUserInfo(account_id);
   if (!user_info)
@@ -228,7 +225,7 @@
   }
 
   wallpaper_controller_->SetDefaultWallpaper(
-      std::move(user_info), GetFilesId(account_id).id(), show_wallpaper);
+      std::move(user_info), GetFilesId(account_id), show_wallpaper);
 }
 
 void WallpaperControllerClient::SetCustomizedDefaultWallpaperPaths(
@@ -259,14 +256,14 @@
   }
 
   wallpaper_controller_->SetPolicyWallpaper(std::move(user_info),
-                                            GetFilesId(account_id).id(), *data);
+                                            GetFilesId(account_id), *data);
 }
 
 void WallpaperControllerClient::SetThirdPartyWallpaper(
     const AccountId& account_id,
-    const wallpaper::WallpaperFilesId& wallpaper_files_id,
+    const std::string& wallpaper_files_id,
     const std::string& file_name,
-    wallpaper::WallpaperLayout layout,
+    ash::WallpaperLayout layout,
     const gfx::ImageSkia& image,
     ash::mojom::WallpaperController::SetThirdPartyWallpaperCallback callback) {
   ash::mojom::WallpaperUserInfoPtr user_info =
@@ -274,7 +271,7 @@
   if (!user_info)
     return;
   wallpaper_controller_->SetThirdPartyWallpaper(
-      std::move(user_info), wallpaper_files_id.id(), file_name, layout, image,
+      std::move(user_info), wallpaper_files_id, file_name, layout, image,
       std::move(callback));
 }
 
@@ -288,7 +285,7 @@
 
 void WallpaperControllerClient::UpdateCustomWallpaperLayout(
     const AccountId& account_id,
-    wallpaper::WallpaperLayout layout) {
+    ash::WallpaperLayout layout) {
   ash::mojom::WallpaperUserInfoPtr user_info =
       AccountIdToWallpaperUserInfo(account_id);
   if (!user_info)
@@ -328,7 +325,7 @@
   }
 
   wallpaper_controller_->RemoveUserWallpaper(std::move(user_info),
-                                             GetFilesId(account_id).id());
+                                             GetFilesId(account_id));
 }
 
 void WallpaperControllerClient::RemovePolicyWallpaper(
@@ -350,7 +347,7 @@
   }
 
   wallpaper_controller_->RemovePolicyWallpaper(std::move(user_info),
-                                               GetFilesId(account_id).id());
+                                               GetFilesId(account_id));
 }
 
 void WallpaperControllerClient::SetAnimationDuration(
diff --git a/chrome/browser/ui/ash/wallpaper_controller_client.h b/chrome/browser/ui/ash/wallpaper_controller_client.h
index 71b96fd..cb70751 100644
--- a/chrome/browser/ui/ash/wallpaper_controller_client.h
+++ b/chrome/browser/ui/ash/wallpaper_controller_client.h
@@ -5,17 +5,12 @@
 #ifndef CHROME_BROWSER_UI_ASH_WALLPAPER_CONTROLLER_CLIENT_H_
 #define CHROME_BROWSER_UI_ASH_WALLPAPER_CONTROLLER_CLIENT_H_
 
+#include "ash/public/cpp/wallpaper_types.h"
 #include "ash/public/interfaces/wallpaper.mojom.h"
 #include "base/macros.h"
 #include "chrome/browser/ui/ash/wallpaper_policy_handler.h"
 #include "mojo/public/cpp/bindings/binding.h"
 
-namespace wallpaper {
-class WallpaperFilesId;
-enum WallpaperLayout;
-enum WallpaperType;
-}  // namespace wallpaper
-
 // Handles method calls sent from ash to chrome. Also sends messages from chrome
 // to ash.
 class WallpaperControllerClient : public ash::mojom::WallpaperControllerClient,
@@ -33,19 +28,19 @@
   static WallpaperControllerClient* Get();
 
   // Returns files identifier for the |account_id|.
-  wallpaper::WallpaperFilesId GetFilesId(const AccountId& account_id) const;
+  std::string GetFilesId(const AccountId& account_id) const;
 
   // Wrappers around the ash::mojom::WallpaperController interface.
   void SetCustomWallpaper(const AccountId& account_id,
-                          const wallpaper::WallpaperFilesId& wallpaper_files_id,
+                          const std::string& wallpaper_files_id,
                           const std::string& file_name,
-                          wallpaper::WallpaperLayout layout,
+                          ash::WallpaperLayout layout,
                           const gfx::ImageSkia& image,
                           bool preview_mode);
   void SetOnlineWallpaper(const AccountId& account_id,
                           const gfx::ImageSkia& image,
                           const std::string& url,
-                          wallpaper::WallpaperLayout layout,
+                          ash::WallpaperLayout layout,
                           bool preview_mode);
   void SetDefaultWallpaper(const AccountId& account_id, bool show_wallpaper);
   void SetCustomizedDefaultWallpaperPaths(
@@ -55,15 +50,15 @@
                           std::unique_ptr<std::string> data);
   void SetThirdPartyWallpaper(
       const AccountId& account_id,
-      const wallpaper::WallpaperFilesId& wallpaper_files_id,
+      const std::string& wallpaper_files_id,
       const std::string& file_name,
-      wallpaper::WallpaperLayout layout,
+      ash::WallpaperLayout layout,
       const gfx::ImageSkia& image,
       ash::mojom::WallpaperController::SetThirdPartyWallpaperCallback callback);
   void ConfirmPreviewWallpaper();
   void CancelPreviewWallpaper();
   void UpdateCustomWallpaperLayout(const AccountId& account_id,
-                                   wallpaper::WallpaperLayout layout);
+                                   ash::WallpaperLayout layout);
   void ShowUserWallpaper(const AccountId& account_id);
   void ShowSigninWallpaper();
   void RemoveUserWallpaper(const AccountId& account_id);
diff --git a/chrome/browser/ui/aura/accessibility/automation_manager_aura.cc b/chrome/browser/ui/aura/accessibility/automation_manager_aura.cc
index b1a3a2c5..8c98a70f4 100644
--- a/chrome/browser/ui/aura/accessibility/automation_manager_aura.cc
+++ b/chrome/browser/ui/aura/accessibility/automation_manager_aura.cc
@@ -193,7 +193,9 @@
   }
   processing_events_ = true;
 
-  ExtensionMsg_AccessibilityEventParams params;
+  std::vector<ExtensionMsg_AccessibilityEventParams> events;
+  events.emplace_back(ExtensionMsg_AccessibilityEventParams());
+  ExtensionMsg_AccessibilityEventParams& params = events.back();
   if (!current_tree_serializer_->SerializeChanges(aura_obj, &params.update)) {
     LOG(ERROR) << "Unable to serialize one accessibility event.";
     return;
@@ -209,8 +211,9 @@
   params.id = aura_obj->GetUniqueId().Get();
   params.event_type = event_type;
   params.mouse_location = aura::Env::GetInstance()->last_mouse_location();
+
   AutomationEventRouter* router = AutomationEventRouter::GetInstance();
-  router->DispatchAccessibilityEvent(params);
+  router->DispatchAccessibilityEvents(events);
 
   processing_events_ = false;
   auto pending_events_copy = pending_events_;
diff --git a/chrome/browser/ui/browser_commands.cc b/chrome/browser/ui/browser_commands.cc
index ea76ede..b9034c7d 100644
--- a/chrome/browser/ui/browser_commands.cc
+++ b/chrome/browser/ui/browser_commands.cc
@@ -873,7 +873,8 @@
 void SavePage(Browser* browser) {
   base::RecordAction(UserMetricsAction("SavePage"));
   WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
-  if (current_tab && current_tab->GetContentsMimeType() == "application/pdf")
+  DCHECK(current_tab);
+  if (current_tab->GetContentsMimeType() == "application/pdf")
     base::RecordAction(UserMetricsAction("PDF.SavePage"));
   current_tab->OnSavePage();
 }
diff --git a/chrome/browser/ui/browser_navigator_browsertest_chromeos.cc b/chrome/browser/ui/browser_navigator_browsertest_chromeos.cc
index 2f1e2926..f427289 100644
--- a/chrome/browser/ui/browser_navigator_browsertest_chromeos.cc
+++ b/chrome/browser/ui/browser_navigator_browsertest_chromeos.cc
@@ -7,7 +7,7 @@
 #include "base/command_line.h"
 #include "chrome/browser/chromeos/login/chrome_restart_request.h"
 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
-#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_test.h"
+#include "chrome/browser/ui/ash/multi_user/test_multi_user_window_manager.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_navigator.h"
diff --git a/chrome/browser/ui/browser_ui_prefs.cc b/chrome/browser/ui/browser_ui_prefs.cc
index 88a0bcf..ca2068d 100644
--- a/chrome/browser/ui/browser_ui_prefs.cc
+++ b/chrome/browser/ui/browser_ui_prefs.cc
@@ -16,7 +16,7 @@
 #include "components/prefs/scoped_user_pref_update.h"
 #include "components/translate/core/browser/translate_pref_names.h"
 #include "content/public/common/webrtc_ip_handling_policy.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 #if defined(OS_WIN)
 #include "base/win/windows_version.h"
diff --git a/chrome/browser/ui/cocoa/download/md_download_item_view.mm b/chrome/browser/ui/cocoa/download/md_download_item_view.mm
index 9167ebe..cfadcf3 100644
--- a/chrome/browser/ui/cocoa/download/md_download_item_view.mm
+++ b/chrome/browser/ui/cocoa/download/md_download_item_view.mm
@@ -8,6 +8,7 @@
 #include "base/strings/sys_string_conversions.h"
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/download/download_item_model.h"
+#import "chrome/browser/download/download_shelf_context_menu.h"
 #include "chrome/browser/download/download_stats.h"
 #import "chrome/browser/themes/theme_properties.h"
 #import "chrome/browser/ui/cocoa/download/download_item_controller.h"
@@ -36,6 +37,7 @@
 
 // Size of a download item in a non-dangerous state.
 constexpr CGSize kNormalSize = {245, 44};
+constexpr CGFloat kTrailingPadding = 12;
 
 constexpr CGFloat kDangerousDownloadIconX = 16;
 constexpr CGFloat kDangerousDownloadIconSize = 16;
@@ -59,7 +61,6 @@
 constexpr CGFloat kStatusTextY = 8;
 constexpr CGFloat kMenuButtonSpacing = 8;
 
-constexpr CGFloat kMenuButtonTrailingMargin = 12;
 constexpr CGFloat kMenuButtonSize = 24;
 constexpr const gfx::VectorIcon* kMenuButtonIcon = &kHorizontalMenuIcon;
 
@@ -142,14 +143,16 @@
 @end
 
 @interface MDDownloadItemDangerView : NSView
-@property(nonatomic, assign) NSButton* button;
+@property(nonatomic, assign) NSButton* discardButton;
+@property(nonatomic, assign) NSButton* saveButton;
 @end
 
 @implementation MDDownloadItemDangerView {
   NSImageView* iconView_;
   NSTextField* label_;
 }
-@synthesize button = button_;
+@synthesize discardButton = discardButton_;
+@synthesize saveButton = saveButton_;
 
 - (instancetype)initWithFrame:(NSRect)frameRect {
   if ((self = [super initWithFrame:frameRect])) {
@@ -174,18 +177,23 @@
         [NSView cr_localizedAutoresizingMask:NSViewMaxXMargin];
     [self addSubview:label_];
 
-    base::scoped_nsobject<HarmonyButton> button(
+    base::scoped_nsobject<HarmonyButton> discardButton(
         [[HarmonyButton alloc] initWithFrame:NSZeroRect]);
-    button_ = button;
-    button_.title = l10n_util::GetNSString(IDS_DISCARD_DOWNLOAD);
-    [button_ sizeToFit];
-    NSRect buttonRect = button_.frame;
-    buttonRect.origin.x = NSWidth(self.bounds) - NSWidth(buttonRect);
-    buttonRect.origin.y = NSMidY(self.bounds) - NSMidY(button_.bounds);
-    button_.frame = [self cr_localizedRect:buttonRect];
-    button_.autoresizingMask =
+    discardButton_ = discardButton;
+    discardButton_.title = l10n_util::GetNSString(IDS_DISCARD_DOWNLOAD);
+    [discardButton_ sizeToFit];
+    discardButton_.autoresizingMask =
         [NSView cr_localizedAutoresizingMask:NSViewMinXMargin];
-    [self addSubview:button_];
+    [self addSubview:discardButton_];
+
+    base::scoped_nsobject<HarmonyButton> saveButton(
+        [[HarmonyButton alloc] initWithFrame:NSZeroRect]);
+    saveButton_ = saveButton;
+    [saveButton_ sizeToFit];
+    saveButton_.autoresizingMask =
+        [NSView cr_localizedAutoresizingMask:NSViewMinXMargin];
+    saveButton_.hidden = YES;
+    [self addSubview:saveButton_];
   }
   return self;
 }
@@ -193,7 +201,10 @@
 - (CGFloat)preferredWidth {
   CGFloat preferredWidth = kDangerousDownloadLabelX + NSWidth(label_.frame) +
                            kDangerousDownloadLabelButtonSpacing +
-                           NSWidth(button_.frame);
+                           NSWidth(discardButton_.frame);
+  if (!saveButton_.hidden)
+    preferredWidth +=
+        kDangerousDownloadLabelButtonSpacing + NSWidth(saveButton_.frame);
   return NSWidth([self backingAlignedRect:NSMakeRect(0, 0, preferredWidth, 0)
                                   options:NSAlignAllEdgesOutward]);
 }
@@ -208,6 +219,28 @@
   labelRect.origin.x = kDangerousDownloadLabelX;
   labelRect.origin.y = NSMidY(self.bounds) - NSMidY(label_.bounds);
   label_.frame = [self cr_localizedRect:labelRect];
+
+  CGFloat maxX = NSMaxX(self.bounds);
+
+  if (downloadModel->MightBeMalicious()) {
+    saveButton_.hidden = YES;
+  } else {
+    saveButton_.hidden = NO;
+    saveButton_.title =
+        base::SysUTF16ToNSString(downloadModel->GetWarningConfirmButtonText());
+    [saveButton_ sizeToFit];
+    NSRect saveButtonRect = saveButton_.frame;
+    saveButtonRect.origin.x = maxX - NSWidth(saveButtonRect);
+    saveButtonRect.origin.y = NSMidY(self.bounds) - NSMidY(saveButton_.bounds);
+    saveButton_.frame = [self cr_localizedRect:saveButtonRect];
+    maxX = NSMinX(saveButtonRect) - kDangerousDownloadLabelButtonSpacing;
+  }
+
+  NSRect discardButtonRect = discardButton_.frame;
+  discardButtonRect.origin.x = maxX - NSWidth(discardButtonRect);
+  discardButtonRect.origin.y =
+      NSMidY(self.bounds) - NSMidY(discardButton_.bounds);
+  discardButton_.frame = [self cr_localizedRect:discardButtonRect];
 }
 
 // NSView overrides
@@ -281,7 +314,7 @@
     [self addSubview:progressIndicator_];
 
     NSRect menuButtonRect = NSMakeRect(
-        NSMaxX(bounds) - kMenuButtonSize - kMenuButtonTrailingMargin,
+        NSMaxX(bounds) - kMenuButtonSize - kTrailingPadding,
         NSMidY(bounds) - kMenuButtonSize / 2, kMenuButtonSize, kMenuButtonSize);
     base::scoped_nsobject<MDDownloadItemMenuButton> menuButton(
         [[MDDownloadItemMenuButton alloc]
@@ -356,8 +389,9 @@
 
 - (CGFloat)preferredWidth {
   if (dangerView_) {
-    return NSWidth(dangerView_.frame) + kMenuButtonSpacing + kMenuButtonSize +
-           kMenuButtonTrailingMargin;
+    return NSWidth(dangerView_.frame) +
+           (menuButton_.hidden ? 0 : kMenuButtonSpacing + kMenuButtonSize) +
+           kTrailingPadding;
   } else {
     return kNormalSize.width;
   }
@@ -465,6 +499,10 @@
 - (void)setStateFromDownload:(DownloadItemModel*)downloadModel {
   const download::DownloadItem& download = *downloadModel->download();
   const download::DownloadItem::DownloadState state = download.GetState();
+
+  menuButton_.hidden =
+      !DownloadShelfContextMenu::WantsContextMenu(*downloadModel);
+
   if (download.IsDangerous()) {
     if (!dangerView_) {
       for (NSView* view in [self normalViews]) {
@@ -476,8 +514,10 @@
       dangerView_ = dangerView;
       dangerView_.autoresizingMask =
           [NSView cr_localizedAutoresizingMask:NSViewMaxXMargin];
-      dangerView_.button.target = controller_;
-      dangerView_.button.action = @selector(discardDownload:);
+      dangerView_.discardButton.target = controller_;
+      dangerView_.discardButton.action = @selector(discardDownload:);
+      dangerView_.saveButton.target = controller_;
+      dangerView_.saveButton.action = @selector(saveDownload:);
       [self addSubview:dangerView_];
     }
     [dangerView_ setStateFromDownload:downloadModel];
diff --git a/chrome/browser/ui/cocoa/harmony_button.mm b/chrome/browser/ui/cocoa/harmony_button.mm
index 1cb15a5..338adb5 100644
--- a/chrome/browser/ui/cocoa/harmony_button.mm
+++ b/chrome/browser/ui/cocoa/harmony_button.mm
@@ -222,7 +222,9 @@
   CALayer* layer = self.layer;
   layer.shadowPath =
       base::ScopedCFTypeRef<CGPathRef>(CGPathCreateWithRoundedRect(
-          layer.bounds, layer.cornerRadius, layer.cornerRadius, nullptr));
+          layer.bounds,
+          MIN(layer.cornerRadius, CGRectGetWidth(layer.bounds) / 2),
+          MIN(layer.cornerRadius, CGRectGetHeight(layer.bounds) / 2), nullptr));
   [self updateHoverButtonAppearanceAnimated:NO];
   self.title = self.title;  // Match the theme.
   [super layout];
diff --git a/chrome/browser/ui/cocoa/harmony_button_unittest.mm b/chrome/browser/ui/cocoa/harmony_button_unittest.mm
index 82539e8..f79ecc5 100644
--- a/chrome/browser/ui/cocoa/harmony_button_unittest.mm
+++ b/chrome/browser/ui/cocoa/harmony_button_unittest.mm
@@ -24,6 +24,17 @@
 
 TEST_VIEW(HarmonyButtonTest, button_)
 
+// Verify that displaying a button that's smaller than double the corner radius
+// doesn't crash. (CGPathCreateWithRoundedRect throws an exception if you pass
+// it a radius that's too big).
+TEST_F(HarmonyButtonTest, TooSmall) {
+  CGFloat cornerRadius = button_.layer.cornerRadius;
+  EXPECT_LT(0, cornerRadius);
+  [button_ setFrameSize:NSMakeSize(cornerRadius, cornerRadius)];
+  [button_ layoutSubtreeIfNeeded];
+  [button_ displayIfNeeded];
+}
+
 TEST(HarmonyButtonTestMore, NSViewRespondsToClipsToBounds) {
   // HarmonyButton implements an undocumented method to avoid having its shadow
   // clipped, so verify that it hasn't disappeared.
diff --git a/chrome/browser/ui/extensions/application_launch.cc b/chrome/browser/ui/extensions/application_launch.cc
index b2bcb90..1eb9650f 100644
--- a/chrome/browser/ui/extensions/application_launch.cc
+++ b/chrome/browser/ui/extensions/application_launch.cc
@@ -219,7 +219,7 @@
 
   WebContents* web_contents = nav_params.target_contents;
   extensions::HostedAppBrowserController::SetAppPrefsForWebContents(
-      web_contents);
+      browser->hosted_app_controller(), web_contents);
 
   browser->window()->Show();
 
diff --git a/chrome/browser/ui/extensions/hosted_app_browser_controller.cc b/chrome/browser/ui/extensions/hosted_app_browser_controller.cc
index 4d6184d3..4737964 100644
--- a/chrome/browser/ui/extensions/hosted_app_browser_controller.cc
+++ b/chrome/browser/ui/extensions/hosted_app_browser_controller.cc
@@ -25,6 +25,7 @@
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/renderer_preferences.h"
+#include "content/public/common/web_preferences.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/common/extension.h"
 #include "ui/gfx/favicon_size.h"
@@ -87,11 +88,22 @@
 
 // static
 void HostedAppBrowserController::SetAppPrefsForWebContents(
+    HostedAppBrowserController* controller,
     content::WebContents* web_contents) {
   auto* rvh = web_contents->GetRenderViewHost();
 
   web_contents->GetMutableRendererPrefs()->can_accept_load_drops = false;
   rvh->SyncRendererPrefs();
+
+  // This function could be called for non Hosted Apps.
+  if (!controller)
+    return;
+
+  if (controller->created_for_installed_pwa()) {
+    content::WebPreferences prefs = rvh->GetWebkitPreferences();
+    prefs.strict_mixed_content_checking = true;
+    rvh->UpdateWebkitPreferences(prefs);
+  }
 }
 
 base::string16 HostedAppBrowserController::FormatUrlOrigin(const GURL& url) {
@@ -109,7 +121,13 @@
     : SiteEngagementObserver(SiteEngagementService::Get(browser->profile())),
       browser_(browser),
       extension_id_(
-          web_app::GetExtensionIdFromApplicationName(browser->app_name())) {
+          web_app::GetExtensionIdFromApplicationName(browser->app_name())),
+      // If a bookmark app has a URL handler, then it is a PWA.
+      // TODO(https://crbug.com/774918): Replace once there is a more explicit
+      // indicator of a Bookmark App for an installable website.
+      created_for_installed_pwa_(
+          base::FeatureList::IsEnabled(features::kDesktopPWAWindowing) &&
+          UrlHandlers::GetUrlHandlers(GetExtension())) {
   browser_->tab_strip_model()->AddObserver(this);
 }
 
@@ -117,25 +135,6 @@
   browser_->tab_strip_model()->RemoveObserver(this);
 }
 
-bool HostedAppBrowserController::IsForInstalledPwa(
-    content::WebContents* web_contents) const {
-  if (!web_contents ||
-      web_contents != browser_->tab_strip_model()->GetActiveWebContents()) {
-    return false;
-  }
-
-  if (!browser_->is_app())
-    return false;
-
-  // If a bookmark app has a URL handler, then it is a PWA.
-  // TODO(https://crbug.com/774918): Replace once there is a more explicit
-  // indicator of a Bookmark App for an installable website.
-  if (extensions::UrlHandlers::GetUrlHandlers(GetExtension()) == nullptr)
-    return false;
-
-  return true;
-}
-
 bool HostedAppBrowserController::ShouldShowLocationBar() const {
   const Extension* extension = GetExtension();
 
@@ -238,9 +237,15 @@
     const GURL& /*url*/,
     double /*score*/,
     SiteEngagementService::EngagementType type) {
-  if (!IsForInstalledPwa(web_contents))
+  if (!created_for_installed_pwa_)
     return;
 
+  // Check the event belongs to the controller's associated browser window.
+  if (!web_contents ||
+      web_contents != browser_->tab_strip_model()->GetActiveWebContents()) {
+    return;
+  }
+
   UMA_HISTOGRAM_ENUMERATION(kPwaWindowEngagementTypeHistogram, type,
                             SiteEngagementService::ENGAGEMENT_LAST);
 }
@@ -249,7 +254,7 @@
                                                content::WebContents* contents,
                                                int index,
                                                bool foreground) {
-  HostedAppBrowserController::SetAppPrefsForWebContents(contents);
+  HostedAppBrowserController::SetAppPrefsForWebContents(this, contents);
 }
 
 void HostedAppBrowserController::TabDetachedAt(content::WebContents* contents,
@@ -258,6 +263,12 @@
 
   contents->GetMutableRendererPrefs()->can_accept_load_drops = true;
   rvh->SyncRendererPrefs();
+
+  if (created_for_installed_pwa_) {
+    content::WebPreferences prefs = rvh->GetWebkitPreferences();
+    prefs.strict_mixed_content_checking = false;
+    rvh->UpdateWebkitPreferences(prefs);
+  }
 }
 
 }  // namespace extensions
diff --git a/chrome/browser/ui/extensions/hosted_app_browser_controller.h b/chrome/browser/ui/extensions/hosted_app_browser_controller.h
index 7a1cf1f9..31bacc1b 100644
--- a/chrome/browser/ui/extensions/hosted_app_browser_controller.h
+++ b/chrome/browser/ui/extensions/hosted_app_browser_controller.h
@@ -37,7 +37,8 @@
   static bool IsForExperimentalHostedAppBrowser(const Browser* browser);
 
   // Functions to set preferences that are unique to app windows.
-  static void SetAppPrefsForWebContents(content::WebContents* web_contents);
+  static void SetAppPrefsForWebContents(HostedAppBrowserController* controller,
+                                        content::WebContents* web_contents);
 
   // Renders |url|'s origin as Unicode.
   static base::string16 FormatUrlOrigin(const GURL& url);
@@ -45,8 +46,8 @@
   explicit HostedAppBrowserController(Browser* browser);
   ~HostedAppBrowserController() override;
 
-  // Returns whether the associated browser is for an installed PWA window.
-  bool IsForInstalledPwa(content::WebContents* web_contents) const;
+  // Returns true if the associated Hosted App is for a PWA.
+  bool created_for_installed_pwa() const { return created_for_installed_pwa_; }
 
   // Whether the browser being controlled should be currently showing the
   // location bar.
@@ -95,6 +96,7 @@
  private:
   Browser* const browser_;
   const std::string extension_id_;
+  const bool created_for_installed_pwa_;
 
   DISALLOW_COPY_AND_ASSIGN(HostedAppBrowserController);
 };
diff --git a/chrome/browser/ui/extensions/hosted_app_browsertest.cc b/chrome/browser/ui/extensions/hosted_app_browsertest.cc
index d62d6cf7..e3eefc21 100644
--- a/chrome/browser/ui/extensions/hosted_app_browsertest.cc
+++ b/chrome/browser/ui/extensions/hosted_app_browsertest.cc
@@ -17,7 +17,10 @@
 #include "chrome/browser/extensions/extension_browsertest.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_util.h"
+#include "chrome/browser/profiles/profile_io_data.h"
 #include "chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h"
+#include "chrome/browser/ssl/cert_verifier_browser_test.h"
+#include "chrome/browser/ssl/ssl_browsertest_util.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_list.h"
@@ -45,6 +48,7 @@
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_set.h"
 #include "extensions/test/test_extension_dir.h"
+#include "net/cert/mock_cert_verifier.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "ui/base/clipboard/clipboard.h"
@@ -72,6 +76,9 @@
   }
 } )";
 
+const base::FilePath::CharType kDocRoot[] =
+    FILE_PATH_LITERAL("chrome/test/data");
+
 enum class AppType {
   HOSTED_APP,
   BOOKMARK_APP,
@@ -110,6 +117,20 @@
   EXPECT_TRUE(prefs->can_accept_load_drops);
 }
 
+void CheckMixedContentLoaded(Browser* browser) {
+  ssl_test_util::CheckSecurityState(
+      browser->tab_strip_model()->GetActiveWebContents(),
+      ssl_test_util::CertError::NONE, security_state::NONE,
+      ssl_test_util::AuthState::DISPLAYED_INSECURE_CONTENT);
+}
+
+void CheckMixedContentFailedToLoad(Browser* browser) {
+  ssl_test_util::CheckSecurityState(
+      browser->tab_strip_model()->GetActiveWebContents(),
+      ssl_test_util::CertError::NONE, security_state::SECURE,
+      ssl_test_util::AuthState::NONE);
+}
+
 }  // namespace
 
 // Parameters are {app_type, desktop_pwa_flag}. |app_type| controls whether it
@@ -119,10 +140,17 @@
     : public ExtensionBrowserTest,
       public ::testing::WithParamInterface<std::tuple<AppType, bool>> {
  public:
-  HostedAppTest() : app_browser_(nullptr), app_(nullptr) {}
+  HostedAppTest()
+      : app_browser_(nullptr),
+        app_(nullptr),
+        https_server_(net::EmbeddedTestServer::TYPE_HTTPS),
+        mock_cert_verifier_(),
+        cert_verifier_(&mock_cert_verifier_) {}
   ~HostedAppTest() override {}
 
   void SetUp() override {
+    https_server_.AddDefaultHandlers(base::FilePath(kDocRoot));
+
     bool desktop_pwa_flag;
     std::tie(app_type_, desktop_pwa_flag) = GetParam();
     if (desktop_pwa_flag) {
@@ -155,9 +183,47 @@
     ASSERT_TRUE(app_browser_ != browser());
   }
 
+  GURL GetMixedContentAppURL() {
+    return https_server()->GetURL("app.com",
+                                  "/ssl/page_displays_insecure_content.html");
+  }
+
+  void InstallMixedContentPWA() {
+    GURL app_url = GetMixedContentAppURL();
+    WebApplicationInfo web_app_info;
+    web_app_info.app_url = app_url;
+    web_app_info.scope = app_url.GetWithoutFilename();
+    app_ = InstallBookmarkApp(web_app_info);
+
+    ui_test_utils::UrlLoadObserver url_observer(
+        app_url, content::NotificationService::AllSources());
+    app_browser_ = LaunchAppBrowser(app_);
+    url_observer.Wait();
+
+    CHECK(app_browser_);
+    CHECK(app_browser_ != browser());
+  }
+
+  void SetUpInProcessBrowserTestFixture() override {
+    ExtensionBrowserTest::SetUpInProcessBrowserTestFixture();
+    ProfileIOData::SetCertVerifierForTesting(&mock_cert_verifier_);
+  }
+
+  void TearDownInProcessBrowserTestFixture() override {
+    ExtensionBrowserTest::TearDownInProcessBrowserTestFixture();
+    ProfileIOData::SetCertVerifierForTesting(nullptr);
+  }
+
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    ExtensionBrowserTest::SetUpCommandLine(command_line);
+    command_line->AppendSwitch(switches::kUseMockCertVerifierForTesting);
+  }
+
   void SetUpOnMainThread() override {
     ExtensionBrowserTest::SetUpOnMainThread();
     host_resolver()->AddRule("*", "127.0.0.1");
+    // By default, all SSL cert checks are valid. Can be overriden in tests.
+    cert_verifier_.set_default_result(net::OK);
   }
 
   // Tests that performing |action| results in a new foreground tab
@@ -188,10 +254,19 @@
 
   AppType app_type() const { return app_type_; }
 
+  net::EmbeddedTestServer* https_server() { return &https_server_; }
+
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
   AppType app_type_;
 
+  net::EmbeddedTestServer https_server_;
+  net::MockCertVerifier mock_cert_verifier_;
+  // Similar to net::MockCertVerifier, but also updates the CertVerifier
+  // used by the NetworkService. This is needed for when tests run with
+  // the NetworkService enabled.
+  CertVerifierBrowserTest::CertVerifier cert_verifier_;
+
   DISALLOW_COPY_AND_ASSIGN(HostedAppTest);
 };
 
@@ -478,8 +553,156 @@
             app_browser->GetWindowTitleForCurrentTab(false));
 }
 
+// Tests that regular Hosted Apps and Bookmark Apps can still load mixed
+// content.
+IN_PROC_BROWSER_TEST_P(HostedAppTest, MixedContentInBookmarkApp) {
+  ASSERT_TRUE(https_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->Start());
+
+  const GURL app_url = GetMixedContentAppURL();
+
+  ui_test_utils::UrlLoadObserver url_observer(
+      app_url, content::NotificationService::AllSources());
+  extensions::TestExtensionDir test_app_dir;
+  test_app_dir.WriteManifest(
+      base::StringPrintf(kAppDotComManifest, app_url.spec().c_str()));
+  SetupApp(test_app_dir.UnpackedPath());
+  url_observer.Wait();
+
+  CheckMixedContentLoaded(app_browser_);
+}
+
 using HostedAppPWAOnlyTest = HostedAppTest;
 
+// Tests that mixed content is not loaded inside PWA windows.
+IN_PROC_BROWSER_TEST_P(HostedAppPWAOnlyTest, MixedContentInPWA) {
+  ASSERT_TRUE(https_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->Start());
+
+  InstallMixedContentPWA();
+  CheckMixedContentFailedToLoad(app_browser_);
+}
+
+// Tests that when calling OpenInChrome, mixed content can be loaded in the new
+// tab.
+IN_PROC_BROWSER_TEST_P(HostedAppPWAOnlyTest, MixedContentOpenInChrome) {
+  ASSERT_TRUE(https_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->Start());
+
+  InstallMixedContentPWA();
+
+  // Mixed content is not allowed in PWAs.
+  CheckMixedContentFailedToLoad(app_browser_);
+
+  chrome::OpenInChrome(app_browser_);
+  ASSERT_EQ(browser(), chrome::FindLastActive());
+  ASSERT_EQ(GetMixedContentAppURL(), browser()
+                                         ->tab_strip_model()
+                                         ->GetActiveWebContents()
+                                         ->GetLastCommittedURL());
+
+  // The WebContents is just reparented, so mixed content is still not loaded.
+  CheckMixedContentFailedToLoad(browser());
+
+  ui_test_utils::UrlLoadObserver url_observer(
+      GetMixedContentAppURL(), content::NotificationService::AllSources());
+  chrome::Reload(browser(), WindowOpenDisposition::CURRENT_TAB);
+  url_observer.Wait();
+
+  // After reloading, mixed content should successfully load because the
+  // WebContents is no longer in a PWA window.
+  CheckMixedContentLoaded(browser());
+}
+
+// Tests that when calling ReparentWebContentsIntoAppBrowser, mixed content
+// cannot be loaded in the new app window.
+IN_PROC_BROWSER_TEST_P(HostedAppPWAOnlyTest,
+                       MixedContentReparentWebContentsIntoAppBrowser) {
+  ASSERT_TRUE(https_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->Start());
+
+  InstallMixedContentPWA();
+
+  NavigateToURLAndWait(browser(), GetMixedContentAppURL());
+  content::WebContents* tab_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  ASSERT_EQ(tab_contents->GetLastCommittedURL(), GetMixedContentAppURL());
+
+  // A regular tab should be able to load mixed content.
+  CheckMixedContentLoaded(browser());
+
+  ReparentWebContentsIntoAppBrowser(tab_contents, app_);
+
+  Browser* app_browser = chrome::FindLastActive();
+  ASSERT_NE(app_browser, browser());
+  ASSERT_EQ(GetMixedContentAppURL(), app_browser->tab_strip_model()
+                                         ->GetActiveWebContents()
+                                         ->GetLastCommittedURL());
+
+  // After reparenting, the WebContents should still have its mixed content
+  // loaded. Note that in practice, this should never happen for PWAs. Users
+  // won't be able to reparent WebContents if there is mixed content loaded
+  // in them.
+  CheckMixedContentLoaded(app_browser);
+
+  ui_test_utils::UrlLoadObserver url_observer(
+      GetMixedContentAppURL(), content::NotificationService::AllSources());
+  chrome::Reload(app_browser, WindowOpenDisposition::CURRENT_TAB);
+  url_observer.Wait();
+
+  // After reloading, mixed content should fail to load, because the WebContents
+  // is now in a PWA window.
+  CheckMixedContentFailedToLoad(app_browser);
+}
+
+// Check that uninstalling a PWA with a window opened doesn't crash.
+IN_PROC_BROWSER_TEST_P(HostedAppPWAOnlyTest, UninstallPwaWithWindowOpened) {
+  ASSERT_TRUE(https_server()->Start());
+  ASSERT_TRUE(embedded_test_server()->Start());
+  InstallMixedContentPWA();
+  UninstallExtension(app_->id());
+}
+
+IN_PROC_BROWSER_TEST_P(HostedAppTest,
+                       DesktopPWAsFlagDisabledCreatedForInstalledPwa) {
+  const extensions::Extension* app;
+  {
+    base::test::ScopedFeatureList feature_list;
+    feature_list.InitAndEnableFeature(features::kDesktopPWAWindowing);
+
+    WebApplicationInfo web_app_info;
+    web_app_info.app_url = GURL(kExampleURL);
+    web_app_info.scope = GURL(kExampleURL);
+    app = InstallBookmarkApp(web_app_info);
+  }
+
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndDisableFeature(features::kDesktopPWAWindowing);
+
+  Browser* app_browser = LaunchAppBrowser(app);
+  EXPECT_FALSE(
+      app_browser->hosted_app_controller()->created_for_installed_pwa());
+}
+
+IN_PROC_BROWSER_TEST_P(HostedAppTest, CreatedForInstalledPwaForNonPwas) {
+  SetupApp("https_app");
+
+  EXPECT_FALSE(
+      app_browser_->hosted_app_controller()->created_for_installed_pwa());
+}
+
+IN_PROC_BROWSER_TEST_P(HostedAppPWAOnlyTest, CreatedForInstalledPwaForPwa) {
+  WebApplicationInfo web_app_info;
+  web_app_info.app_url = GURL(kExampleURL);
+  web_app_info.scope = GURL(kExampleURL);
+
+  const extensions::Extension* app = InstallBookmarkApp(web_app_info);
+  Browser* app_browser = LaunchAppBrowser(app);
+
+  EXPECT_TRUE(
+      app_browser->hosted_app_controller()->created_for_installed_pwa());
+}
+
 // Check the 'Copy URL' menu button for Hosted App windows.
 IN_PROC_BROWSER_TEST_P(HostedAppPWAOnlyTest, CopyURL) {
   WebApplicationInfo web_app_info;
@@ -693,6 +916,7 @@
   ~HostedAppProcessModelTest() override {}
 
   void SetUpCommandLine(base::CommandLine* command_line) override {
+    HostedAppTest::SetUpCommandLine(command_line);
     ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
     std::string origin_list =
         embedded_test_server()->GetURL("isolated.site.com", "/").spec();
@@ -1176,6 +1400,7 @@
   ~HostedAppIsolatedOriginTest() override {}
 
   void SetUpCommandLine(base::CommandLine* command_line) override {
+    HostedAppTest::SetUpCommandLine(command_line);
     ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
     GURL isolated_url = embedded_test_server()->GetURL("isolated.com", "/");
     GURL very_isolated_url =
diff --git a/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc b/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc
index ddc9e3e..377592c 100644
--- a/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc
+++ b/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc
@@ -423,8 +423,15 @@
                                  kFwd, kIgnoreCase, NULL));
 }
 
+// https://crbug.com/825341: Flaky timeout on Win7 Tests (dbg)(1)
+#if defined(OS_WIN) && !defined(NDEBUG)
+#define MAYBE_FindLongString DISABLED_FindLongString
+#else
+#define MAYBE_FindLongString FindLongString
+#endif
+
 // Find a very long string in a large page.
-IN_PROC_BROWSER_TEST_F(FindInPageControllerTest, FindLongString) {
+IN_PROC_BROWSER_TEST_F(FindInPageControllerTest, MAYBE_FindLongString) {
   WebContents* web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
   ui_test_utils::NavigateToURL(browser(), GetURL("largepage.html"));
diff --git a/chrome/browser/ui/input_method/input_method_engine.cc b/chrome/browser/ui/input_method/input_method_engine.cc
index 6965dbd..d355322 100644
--- a/chrome/browser/ui/input_method/input_method_engine.cc
+++ b/chrome/browser/ui/input_method/input_method_engine.cc
@@ -137,11 +137,11 @@
     bool is_visible) {
   composition_ = composition_text;
 
-  // Use a black thin underline by default.
+  // Use a thin underline with text color by default.
   if (composition_.ime_text_spans.empty()) {
     composition_.ime_text_spans.push_back(ui::ImeTextSpan(
         ui::ImeTextSpan::Type::kComposition, 0, composition_.text.length(),
-        SK_ColorBLACK, ui::ImeTextSpan::Thickness::kThin, SK_ColorTRANSPARENT));
+        ui::ImeTextSpan::Thickness::kThin, SK_ColorTRANSPARENT));
   }
 
   ui::IMEInputContextHandlerInterface* input_context =
diff --git a/chrome/browser/ui/input_method/input_method_engine_base.cc b/chrome/browser/ui/input_method/input_method_engine_base.cc
index 944caad..43b53f99 100644
--- a/chrome/browser/ui/input_method/input_method_engine_base.cc
+++ b/chrome/browser/ui/input_method/input_method_engine_base.cc
@@ -208,13 +208,12 @@
        segment != segments.end(); ++segment) {
     ui::ImeTextSpan ime_text_span;
 
+    ime_text_span.underline_color = SK_ColorTRANSPARENT;
     switch (segment->style) {
       case SEGMENT_STYLE_UNDERLINE:
-        ime_text_span.underline_color = SK_ColorBLACK;
         ime_text_span.thickness = ui::ImeTextSpan::Thickness::kThin;
         break;
       case SEGMENT_STYLE_DOUBLE_UNDERLINE:
-        ime_text_span.underline_color = SK_ColorBLACK;
         ime_text_span.thickness = ui::ImeTextSpan::Thickness::kThick;
         break;
       case SEGMENT_STYLE_NO_UNDERLINE:
diff --git a/chrome/browser/ui/layout_constants.cc b/chrome/browser/ui/layout_constants.cc
index 41dd712..9ab1e4c 100644
--- a/chrome/browser/ui/layout_constants.cc
+++ b/chrome/browser/ui/layout_constants.cc
@@ -12,6 +12,7 @@
   const bool hybrid = mode == ui::MaterialDesignController::MATERIAL_HYBRID;
   const bool touch_optimized_material =
       mode == ui::MaterialDesignController::MATERIAL_TOUCH_OPTIMIZED;
+  const bool newer_material = ui::MaterialDesignController::IsNewerMaterialUi();
   switch (constant) {
     case BOOKMARK_BAR_HEIGHT:
       return touch_optimized_material ? 40 : 28;
@@ -36,7 +37,7 @@
       // TODO(tapted): This should match BubbleBorder::GetBorderRadius() once
       // MD is default for secondary UI everywhere. That is, the constant should
       // move to views/layout_provider.h so that all bubbles are consistent.
-      return touch_optimized_material ? 8 : 2;
+      return newer_material ? 8 : 2;
     case LOCATION_BAR_BUBBLE_ANCHOR_VERTICAL_INSET:
       if (ui::MaterialDesignController::IsSecondaryUiMaterial())
         return 1;
@@ -46,7 +47,7 @@
     case LOCATION_BAR_PADDING:
       return hybrid ? 3 : 1;
     case LOCATION_BAR_HEIGHT: {
-      constexpr int kHeights[] = {28, 32, 36};
+      constexpr int kHeights[] = {28, 32, 36, 28};
       return kHeights[mode];
     }
     case LOCATION_BAR_ICON_SIZE:
@@ -60,7 +61,7 @@
       // further away from the tab. The distance is 8 DIP from the point at
       // which the last tab's endcap intersects with the tabstrip separator,
       // which is actually 6 DIP from the last tab's right point.
-      constexpr int kSpacing[] = {-5, -6, 6};
+      constexpr int kSpacing[] = {-5, -6, 6, -5};
       return kSpacing[mode];
     }
     case TAB_AFTER_TITLE_PADDING:
@@ -70,7 +71,7 @@
     case TAB_ALERT_INDICATOR_ICON_WIDTH:
       return touch_optimized_material ? 12 : 16;
     case TAB_HEIGHT: {
-      constexpr int kTabHeight[] = {29, 33, 41};
+      constexpr int kTabHeight[] = {29, 33, 41, 29};
       return kTabHeight[mode];
     }
     case TAB_PRE_TITLE_PADDING:
@@ -84,7 +85,7 @@
     case TOOLBAR_ELEMENT_PADDING:
       return hybrid ? 8 : 0;
     case TOOLBAR_STANDARD_SPACING: {
-      constexpr int kSpacings[] = {4, 8, 12};
+      constexpr int kSpacings[] = {4, 8, 12, 4};
       return kSpacings[mode];
     }
   }
@@ -96,7 +97,7 @@
   const int mode = ui::MaterialDesignController::GetMode();
   switch (inset) {
     case TAB: {
-      constexpr int kTabHorizontalInset[] = {16, 18, 24};
+      constexpr int kTabHorizontalInset[] = {16, 18, 24, 16};
       return gfx::Insets(1, kTabHorizontalInset[mode]);
     }
     case TOOLBAR_BUTTON:
@@ -106,7 +107,7 @@
     case TOOLBAR_ACTION_VIEW: {
       // TODO(afakhry): Unify all toolbar button sizes on all platforms.
       // https://crbug.com/822967.
-      constexpr int kToolbarActionsInsets[] = {2, 4, 10};
+      constexpr int kToolbarActionsInsets[] = {2, 4, 10, 2};
       return gfx::Insets(kToolbarActionsInsets[mode]);
     }
   }
@@ -119,7 +120,7 @@
   switch (size) {
     case NEW_TAB_BUTTON: {
       const gfx::Size sizes[] = {
-          {36, 18}, {39, 21}, {(is_incognito ? 42 : 24), 24}};
+          {36, 18}, {39, 21}, {(is_incognito ? 42 : 24), 24}, {36, 18}};
       return sizes[mode];
     }
   }
diff --git a/chrome/browser/ui/libgtkui/gtk_key_bindings_handler.cc b/chrome/browser/ui/libgtkui/gtk_key_bindings_handler.cc
index 111a418..14c181f 100644
--- a/chrome/browser/ui/libgtkui/gtk_key_bindings_handler.cc
+++ b/chrome/browser/ui/libgtkui/gtk_key_bindings_handler.cc
@@ -102,7 +102,7 @@
 }
 
 void Gtk2KeyBindingsHandler::BuildGdkEventKeyFromXEvent(
-    const base::NativeEvent& xevent,
+    const ui::PlatformEvent& xevent,
     GdkEventKey* gdk_event) {
   GdkKeymap* keymap = gdk_keymap_get_for_display(gdk_display_get_default());
   GdkModifierType consumed, state;
diff --git a/chrome/browser/ui/libgtkui/gtk_key_bindings_handler.h b/chrome/browser/ui/libgtkui/gtk_key_bindings_handler.h
index 6794cc22d..62f547c 100644
--- a/chrome/browser/ui/libgtkui/gtk_key_bindings_handler.h
+++ b/chrome/browser/ui/libgtkui/gtk_key_bindings_handler.h
@@ -10,8 +10,8 @@
 #include <string>
 #include <vector>
 
-#include "base/event_types.h"
 #include "ui/base/ime/linux/text_edit_command_auralinux.h"
+#include "ui/events/platform_event.h"
 
 namespace ui {
 class Event;
@@ -70,7 +70,7 @@
                           const std::string& value);
 
   // Builds a fake GdkEventKey from an XEvent.
-  void BuildGdkEventKeyFromXEvent(const base::NativeEvent& xevent,
+  void BuildGdkEventKeyFromXEvent(const ui::PlatformEvent& xevent,
                                   GdkEventKey* gdk_event);
 
   // Initializes Handler structure.
diff --git a/chrome/browser/ui/libgtkui/settings_provider_gsettings.cc b/chrome/browser/ui/libgtkui/settings_provider_gsettings.cc
index fee7763..0809f7a 100644
--- a/chrome/browser/ui/libgtkui/settings_provider_gsettings.cc
+++ b/chrome/browser/ui/libgtkui/settings_provider_gsettings.cc
@@ -40,11 +40,10 @@
   // gtk3 API). The default in 14.04 is Unity, but Cinnamon has enough
   // usage to justify also checking its value.
   std::unique_ptr<base::Environment> env(base::Environment::Create());
-  const gchar* settings_schema =
-      base::nix::GetDesktopEnvironment(env.get()) ==
-              base::nix::DESKTOP_ENVIRONMENT_CINNAMON
-          ? settings_schema = kCinnamonPreferencesSchema
-          : settings_schema = kGnomePreferencesSchema;
+  const gchar* settings_schema = base::nix::GetDesktopEnvironment(env.get()) ==
+                                         base::nix::DESKTOP_ENVIRONMENT_CINNAMON
+                                     ? kCinnamonPreferencesSchema
+                                     : kGnomePreferencesSchema;
 
   if (!g_settings_schema_source_lookup(g_settings_schema_source_get_default(),
                                        settings_schema, FALSE) ||
diff --git a/chrome/browser/ui/libgtkui/x11_input_method_context_impl_gtk.cc b/chrome/browser/ui/libgtkui/x11_input_method_context_impl_gtk.cc
index 2ad80ca..386e961 100644
--- a/chrome/browser/ui/libgtkui/x11_input_method_context_impl_gtk.cc
+++ b/chrome/browser/ui/libgtkui/x11_input_method_context_impl_gtk.cc
@@ -166,7 +166,7 @@
 }
 
 GdkEvent* X11InputMethodContextImplGtk2::GdkEventFromNativeEvent(
-    const base::NativeEvent& native_event) {
+    const ui::PlatformEvent& native_event) {
   XEvent xkeyevent;
   if (native_event->type == GenericEvent) {
     // If this is an XI2 key event, build a matching core X event, to avoid
diff --git a/chrome/browser/ui/libgtkui/x11_input_method_context_impl_gtk.h b/chrome/browser/ui/libgtkui/x11_input_method_context_impl_gtk.h
index d3733a8..3ff624d 100644
--- a/chrome/browser/ui/libgtkui/x11_input_method_context_impl_gtk.h
+++ b/chrome/browser/ui/libgtkui/x11_input_method_context_impl_gtk.h
@@ -8,12 +8,12 @@
 #include <vector>
 
 #include "base/containers/hash_tables.h"
-#include "base/event_types.h"
 #include "base/macros.h"
 #include "base/strings/string16.h"
 #include "ui/base/glib/glib_integers.h"
 #include "ui/base/glib/glib_signal.h"
 #include "ui/base/ime/linux/linux_input_method_context.h"
+#include "ui/events/platform_event.h"
 #include "ui/gfx/geometry/rect.h"
 
 typedef union _GdkEvent GdkEvent;
@@ -44,7 +44,7 @@
 
   // Constructs a GdkEventKey from a XKeyEvent and returns it.  Otherwise,
   // returns nullptr.  The returned GdkEvent must be freed by gdk_event_free.
-  GdkEvent* GdkEventFromNativeEvent(const base::NativeEvent& native_event);
+  GdkEvent* GdkEventFromNativeEvent(const ui::PlatformEvent& native_event);
 
   // Returns true if the hardware |keycode| is assigned to a modifier key.
   bool IsKeycodeModifierKey(unsigned int keycode) const;
diff --git a/chrome/browser/ui/omnibox/omnibox_theme.cc b/chrome/browser/ui/omnibox/omnibox_theme.cc
index fef75ec..1b085a9 100644
--- a/chrome/browser/ui/omnibox/omnibox_theme.cc
+++ b/chrome/browser/ui/omnibox/omnibox_theme.cc
@@ -192,12 +192,30 @@
                                      : native_theme->GetSystemColor(color_id);
 }
 
+SkColor GetSecurityChipColor(OmniboxTint tint, OmniboxPartState state) {
+  if (tint == OmniboxTint::DARK)
+    return gfx::kGoogleGrey100;
+
+  switch (state) {
+    case OmniboxPartState::CHIP_DEFAULT:
+      return gfx::kGoogleGrey800;
+    case OmniboxPartState::CHIP_SECURE:
+      return gfx::kGoogleGreen600;
+    case OmniboxPartState::CHIP_DANGEROUS:
+      return gfx::kGoogleRed600;
+    default:
+      NOTREACHED();
+  }
+
+  return gfx::kPlaceholderColor;
+}
+
 }  // namespace
 
 SkColor GetOmniboxColor(OmniboxPart part,
                         OmniboxTint tint,
                         OmniboxPartState state) {
-  if (!ui::MaterialDesignController::IsTouchOptimizedUiEnabled())
+  if (!ui::MaterialDesignController::IsNewerMaterialUi())
     return GetLegacyColor(part, tint, state);
 
   // Note this will use LIGHT for OmniboxTint::NATIVE.
@@ -205,34 +223,46 @@
   const bool dark = tint == OmniboxTint::DARK;
 
   switch (part) {
+    case OmniboxPart::LOCATION_BAR_BACKGROUND:
+      return dark ? SkColorSetRGB(0x28, 0x2C, 0x2F)
+                  : SkColorSetRGB(0xED, 0xEF, 0xF2);
+    case OmniboxPart::LOCATION_BAR_SECURITY_CHIP:
+      return GetSecurityChipColor(tint, state);
+    case OmniboxPart::LOCATION_BAR_SELECTED_KEYWORD:
+      return dark ? gfx::kGoogleGrey100 : gfx::kGoogleBlue600;
     case OmniboxPart::RESULTS_BACKGROUND:
       // The spec calls for transparent black (or white) overlays for hover (6%)
       // and select (8%), which can overlap (for 14%). Pre-blend these with the
       // background for the best text AA result.
       return color_utils::BlendTowardOppositeLuma(
           dark ? gfx::kGoogleGrey800 : SK_ColorWHITE,
-          NormalHoveredSelectedOrBoth<SkAlpha>(state, 0x00, 0x0f, 0x14, 0x24));
+          NormalHoveredSelectedOrBoth<SkAlpha>(state, 0x00, 0x0F, 0x14, 0x24));
     case OmniboxPart::RESULTS_SEPARATOR:
-      // The dark base color doesn't appear in the MD2 spec, just Chrome's.
-      return dark ? SkColorSetARGB(0x6e, 0x16, 0x17, 0x1a)   // 43% alpha.
+      // The dark base color doesn't appear in the Material spec, just Chrome's.
+      return dark ? SkColorSetARGB(0x6E, 0x16, 0x17, 0x1A)   // 43% alpha.
                   : SkColorSetA(gfx::kGoogleGrey900, 0x24);  // 14% alpha.
 
+    case OmniboxPart::LOCATION_BAR_TEXT_DEFAULT:
+    case OmniboxPart::RESULTS_TEXT_DEFAULT:
+      return dark ? gfx::kGoogleGrey100 : gfx::kGoogleGrey800;
+
+    case OmniboxPart::LOCATION_BAR_TEXT_DIMMED:
+    case OmniboxPart::RESULTS_ICON:
+    case OmniboxPart::RESULTS_TEXT_DIMMED:
+      // This is a pre-lightened (or darkened) variant of the base text color.
+      return dark ? gfx::kGoogleGrey400 : gfx::kGoogleGrey700;
+
+    case OmniboxPart::RESULTS_TEXT_URL:
+      // The darker blue doesn't appear in the Material spec.
+      return dark ? SkColorSetRGB(0x25, 0x81, 0xDF) : gfx::kGoogleBlue600;
+
     // TODO(tapted): Add these.
-    case OmniboxPart::LOCATION_BAR_BACKGROUND:
     case OmniboxPart::LOCATION_BAR_CLEAR_ALL:
     case OmniboxPart::LOCATION_BAR_IME_AUTOCOMPLETE_BACKGROUND:
     case OmniboxPart::LOCATION_BAR_IME_AUTOCOMPLETE_TEXT:
-    case OmniboxPart::LOCATION_BAR_SECURITY_CHIP:
-    case OmniboxPart::LOCATION_BAR_SELECTED_KEYWORD:
-    case OmniboxPart::LOCATION_BAR_TEXT_DEFAULT:
-    case OmniboxPart::LOCATION_BAR_TEXT_DIMMED:
-    case OmniboxPart::RESULTS_ICON:
-    case OmniboxPart::RESULTS_TEXT_DEFAULT:
-    case OmniboxPart::RESULTS_TEXT_DIMMED:
     case OmniboxPart::RESULTS_TEXT_INVISIBLE:
     case OmniboxPart::RESULTS_TEXT_NEGATIVE:
     case OmniboxPart::RESULTS_TEXT_POSITIVE:
-    case OmniboxPart::RESULTS_TEXT_URL:
       return GetLegacyColor(part, tint, state);
   }
   return gfx::kPlaceholderColor;
diff --git a/chrome/browser/ui/prefs/prefs_tab_helper.cc b/chrome/browser/ui/prefs/prefs_tab_helper.cc
index 381b7c8..6dd64d8 100644
--- a/chrome/browser/ui/prefs/prefs_tab_helper.cc
+++ b/chrome/browser/ui/prefs/prefs_tab_helper.cc
@@ -45,7 +45,7 @@
 #include "content/public/common/renderer_preferences.h"
 #include "content/public/common/web_preferences.h"
 #include "extensions/buildflags/buildflags.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "third_party/icu/source/common/unicode/uchar.h"
 #include "third_party/icu/source/common/unicode/uscript.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/ui/search_engines/template_url_table_model.cc b/chrome/browser/ui/search_engines/template_url_table_model.cc
index 601536a8..cdcc8009 100644
--- a/chrome/browser/ui/search_engines/template_url_table_model.cc
+++ b/chrome/browser/ui/search_engines/template_url_table_model.cc
@@ -9,6 +9,7 @@
 #include "base/bind.h"
 #include "base/i18n/rtl.h"
 #include "base/macros.h"
+#include "base/stl_util.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/search_engines/template_url.h"
 #include "components/search_engines/template_url_service.h"
@@ -138,9 +139,14 @@
 }
 
 TemplateURL* TemplateURLTableModel::GetTemplateURL(int index) {
-  // Sanity check for https://crbug.com/781703.
+  // Sanity checks for https://crbug.com/781703.
   CHECK_GE(index, 0);
   CHECK_LT(static_cast<size_t>(index), entries_.size());
+  CHECK(base::ContainsValue(template_url_service_->GetTemplateURLs(),
+                            entries_[index]))
+      << "TemplateURLTableModel is returning a pointer to a TemplateURL "
+         "that has already been freed by TemplateURLService.";
+
   return entries_[index];
 }
 
diff --git a/chrome/browser/ui/startup/bad_flags_prompt.cc b/chrome/browser/ui/startup/bad_flags_prompt.cc
index 778e77f..a18b767 100644
--- a/chrome/browser/ui/startup/bad_flags_prompt.cc
+++ b/chrome/browser/ui/startup/bad_flags_prompt.cc
@@ -33,7 +33,7 @@
 #include "extensions/common/switches.h"
 #include "google_apis/gaia/gaia_switches.h"
 #include "media/base/media_switches.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "services/network/public/cpp/network_switches.h"
 #include "services/service_manager/sandbox/switches.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -119,14 +119,6 @@
 }  // namespace
 
 void ShowBadFlagsPrompt(content::WebContents* web_contents) {
-  // Do not show a warning of "stability and security will suffer" when the
-  // browser is being controlled by automated tests, so that it doesn't
-  // interfere with tests that assume no info bars.
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableAutomation)) {
-    return;
-  }
-
   // Flags only available in specific builds, for which to display a warning
   // "the flag is not implemented in this build", if necessary.
   struct {
diff --git a/chrome/browser/ui/views/accelerator_table_unittest_mac.mm b/chrome/browser/ui/views/accelerator_table_unittest_mac.mm
index d629a13..dad1087 100644
--- a/chrome/browser/ui/views/accelerator_table_unittest_mac.mm
+++ b/chrome/browser/ui/views/accelerator_table_unittest_mac.mm
@@ -11,6 +11,7 @@
 #include "chrome/app/chrome_command_ids.h"
 #import "chrome/browser/global_keyboard_shortcuts_mac.h"
 #include "chrome/browser/ui/views/accelerator_table.h"
+#include "chrome/test/views/scoped_macviews_browser_mode.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/events/event_constants.h"
 #import "ui/events/keycodes/keyboard_code_conversion_mac.h"
@@ -105,6 +106,7 @@
 // Verifies that we're not processing any duplicate accelerators in
 // global_keyboard_shortcuts_mac.mm functions.
 TEST(AcceleratorTableTest, CheckNoDuplicatesGlobalKeyboardShortcutsMac) {
+  test::ScopedMacViewsBrowserMode views_mode_{true};
   VerifyTableDoesntHaveDuplicates(GetWindowKeyboardShortcutTable(),
                                   "WindowKeyboardShortcutTable");
   VerifyTableDoesntHaveDuplicates(GetDelayedWindowKeyboardShortcutTable(),
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc
index 3757a006..e2d572e 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc
@@ -114,6 +114,10 @@
   return true;
 }
 
+bool BookmarkEditorView::ShouldShowCloseButton() const {
+  return false;
+}
+
 base::string16 BookmarkEditorView::GetWindowTitle() const {
   return l10n_util::GetStringUTF16(details_.GetWindowTitleId());
 }
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_editor_view.h b/chrome/browser/ui/views/bookmarks/bookmark_editor_view.h
index e716a4d..0a271ea 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_editor_view.h
+++ b/chrome/browser/ui/views/bookmarks/bookmark_editor_view.h
@@ -85,6 +85,7 @@
   views::View* CreateExtraView() override;
   ui::ModalType GetModalType() const override;
   bool CanResize() const override;
+  bool ShouldShowCloseButton() const override;
   base::string16 GetWindowTitle() const override;
   bool Accept() override;
 
diff --git a/chrome/browser/ui/views/content_setting_bubble_contents.cc b/chrome/browser/ui/views/content_setting_bubble_contents.cc
index 72a91231..809b514 100644
--- a/chrome/browser/ui/views/content_setting_bubble_contents.cc
+++ b/chrome/browser/ui/views/content_setting_bubble_contents.cc
@@ -96,42 +96,64 @@
   DISALLOW_COPY_AND_ASSIGN(MediaComboboxModel);
 };
 
-// A view representing a label and combobox pair that allows the user to select
-// which device is being used for the media type (either microphone or camera).
-class MediaMenuRow : public views::View {
+// A view representing one or more rows, each containing a label and combobox
+// pair, that allow the user to select a device for each media type (microphone
+// and/or camera).
+class MediaMenuBlock : public views::View {
  public:
-  MediaMenuRow(views::ComboboxListener* listener,
-               content::MediaStreamType stream_type,
-               const ContentSettingBubbleModel::MediaMenu& menu) {
+  MediaMenuBlock(views::ComboboxListener* listener,
+                 ContentSettingBubbleModel::MediaMenuMap media) {
     const ChromeLayoutProvider* provider = ChromeLayoutProvider::Get();
-    SetLayoutManager(std::make_unique<views::BoxLayout>(
-        views::BoxLayout::kHorizontal, gfx::Insets(),
-        provider->GetDistanceMetric(
-            views::DISTANCE_RELATED_CONTROL_HORIZONTAL)));
 
-    views::Label* label = new views::Label(menu.label);
-    label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-    AddChildView(label);
+    views::GridLayout* layout =
+        SetLayoutManager(std::make_unique<views::GridLayout>(this));
+    constexpr int kColumnSetId = 0;
+    views::ColumnSet* column_set = layout->AddColumnSet(kColumnSetId);
+    column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER,
+                          0, views::GridLayout::USE_PREF, 0, 0);
+    column_set->AddPaddingColumn(
+        0, provider->GetDistanceMetric(
+               views::DISTANCE_RELATED_CONTROL_HORIZONTAL));
+    column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
+                          views::GridLayout::FIXED, 0, 0);
 
-    auto combobox_model = std::make_unique<MediaComboboxModel>(stream_type);
-    // Disable the device selection when the website is managing the devices
-    // itself or if there are no devices present.
-    const bool combobox_enabled =
-        !menu.disabled && !combobox_model->GetDevices().empty();
-    const int combobox_selected_index =
-        combobox_model->GetDevices().empty()
-            ? 0
-            : combobox_model->GetDeviceIndex(menu.selected_device);
-    // The combobox takes ownership of the model.
-    views::Combobox* combobox = new views::Combobox(std::move(combobox_model));
-    combobox->SetEnabled(combobox_enabled);
-    combobox->set_listener(listener);
-    combobox->SetSelectedIndex(combobox_selected_index);
-    AddChildView(combobox);
+    bool first_row = true;
+    for (auto i = media.cbegin(); i != media.cend(); ++i) {
+      if (!first_row) {
+        layout->AddPaddingRow(0, provider->GetDistanceMetric(
+                                     views::DISTANCE_RELATED_CONTROL_VERTICAL));
+      }
+      first_row = false;
+
+      layout->StartRow(0, kColumnSetId);
+      content::MediaStreamType stream_type = i->first;
+      const ContentSettingBubbleModel::MediaMenu& menu = i->second;
+
+      views::Label* label = new views::Label(menu.label);
+      label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+      layout->AddView(label);
+
+      auto combobox_model = std::make_unique<MediaComboboxModel>(stream_type);
+      // Disable the device selection when the website is managing the devices
+      // itself or if there are no devices present.
+      const bool combobox_enabled =
+          !menu.disabled && !combobox_model->GetDevices().empty();
+      const int combobox_selected_index =
+          combobox_model->GetDevices().empty()
+              ? 0
+              : combobox_model->GetDeviceIndex(menu.selected_device);
+      // The combobox takes ownership of the model.
+      views::Combobox* combobox =
+          new views::Combobox(std::move(combobox_model));
+      combobox->SetEnabled(combobox_enabled);
+      combobox->set_listener(listener);
+      combobox->SetSelectedIndex(combobox_selected_index);
+      layout->AddView(combobox);
+    }
   }
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(MediaMenuRow);
+  DISALLOW_COPY_AND_ASSIGN(MediaMenuBlock);
 };
 
 }  // namespace
@@ -482,12 +504,9 @@
 
   // Layout code for the media device menus.
   if (content_setting_bubble_model_->AsMediaStreamBubbleModel()) {
-    for (ContentSettingBubbleModel::MediaMenuMap::const_iterator i(
-         bubble_content.media_menus.begin());
-         i != bubble_content.media_menus.end(); ++i) {
-      rows.push_back({std::make_unique<MediaMenuRow>(this, i->first, i->second),
-                      LayoutRowType::INDENTED});
-    }
+    rows.push_back(
+        {std::make_unique<MediaMenuBlock>(this, bubble_content.media_menus),
+         LayoutRowType::INDENTED});
   }
 
   for (std::vector<ContentSettingBubbleModel::DomainList>::const_iterator i(
diff --git a/chrome/browser/ui/views/frame/browser_frame_header_ash.cc b/chrome/browser/ui/views/frame/browser_frame_header_ash.cc
index f3f3cc58..6d28e9d9 100644
--- a/chrome/browser/ui/views/frame/browser_frame_header_ash.cc
+++ b/chrome/browser/ui/views/frame/browser_frame_header_ash.cc
@@ -11,6 +11,7 @@
 #include "ash/public/cpp/vector_icons/vector_icons.h"
 #include "base/logging.h"
 #include "chrome/browser/themes/theme_properties.h"
+#include "chrome/browser/ui/ash/tablet_mode_client.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/views/frame/browser_frame.h"
 #include "chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h"
@@ -280,6 +281,10 @@
 }
 
 void BrowserFrameHeaderAsh::UpdateCaptionButtons() {
+  // When |frame_| minimized, avoid tablet mode toggling to update caption
+  // buttons as it would cause mismatch beteen window state and size button.
+  if (frame_->IsMinimized())
+    return;
   caption_button_container_->SetButtonImage(ash::CAPTION_BUTTON_ICON_MINIMIZE,
                                             ash::kWindowControlMinimizeIcon);
   caption_button_container_->SetButtonImage(ash::CAPTION_BUTTON_ICON_CLOSE,
@@ -291,17 +296,21 @@
       ash::CAPTION_BUTTON_ICON_RIGHT_SNAPPED,
       ash::kWindowControlRightSnappedIcon);
 
-  const gfx::VectorIcon* size_icon = &ash::kWindowControlMaximizeIcon;
-  gfx::Size button_size(
-      GetAshLayoutSize(AshLayoutSize::BROWSER_RESTORED_CAPTION_BUTTON));
-  if (frame_->IsMaximized() || frame_->IsFullscreen()) {
-    size_icon = &ash::kWindowControlRestoreIcon;
-    button_size =
-        GetAshLayoutSize(AshLayoutSize::BROWSER_MAXIMIZED_CAPTION_BUTTON);
-  }
+  const bool is_in_tablet_mode =
+      TabletModeClient::Get() && TabletModeClient::Get()->tablet_mode_enabled();
+  const bool is_maximized_or_fullscreen =
+      frame_->IsMaximized() || frame_->IsFullscreen();
+  const AshLayoutSize button_size_type =
+      is_maximized_or_fullscreen || is_in_tablet_mode
+          ? AshLayoutSize::kBrowserCaptionMaximized
+          : AshLayoutSize::kBrowserCaptionRestored;
+  const gfx::VectorIcon* const size_icon =
+      is_maximized_or_fullscreen ? &ash::kWindowControlRestoreIcon
+                                 : &ash::kWindowControlMaximizeIcon;
+
   caption_button_container_->SetButtonImage(
       ash::CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE, *size_icon);
-  caption_button_container_->SetButtonSize(button_size);
+  caption_button_container_->SetButtonSize(GetAshLayoutSize(button_size_type));
 }
 
 gfx::Rect BrowserFrameHeaderAsh::GetPaintedBounds() const {
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
index d623f98..f9300fe 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
@@ -177,28 +177,14 @@
     return;
   }
 
-  Browser* browser = browser_view()->browser();
-  Profile* profile = browser->profile();
-  const bool is_incognito =
-      profile->GetProfileType() == Profile::INCOGNITO_PROFILE;
-
-  // In the touch-optimized UI, we don't show the incognito icon in the browser
-  // frame. It's instead shown in the new tab button. However, we still show an
-  // avatar icon for the teleported browser windows between multi-user sessions
-  // (Chrome OS only). Note that you can't teleport an incognito window.
-  if (is_incognito && ui::MaterialDesignController::IsTouchOptimizedUiEnabled())
-    return;
-
-#if defined(OS_CHROMEOS)
-  // Ash and MUS specific.
-  if (!browser->is_type_tabbed() && !browser->is_app())
-    return;
-
-  if (!is_incognito && !MultiUserWindowManager::ShouldShowAvatar(
-                           browser_view()->GetNativeWindow())) {
+  if (!ShouldShowProfileIndicatorIcon()) {
+    if (profile_indicator_icon_) {
+      delete profile_indicator_icon_;
+      profile_indicator_icon_ = nullptr;
+      frame_->GetRootView()->Layout();
+    }
     return;
   }
-#endif  // defined(OS_CHROMEOS)
 
   if (!profile_indicator_icon_) {
     profile_indicator_icon_ = new ProfileIndicatorIcon();
@@ -210,6 +196,9 @@
   }
 
   gfx::Image icon;
+  Profile* profile = browser_view()->browser()->profile();
+  const bool is_incognito =
+      profile->GetProfileType() == Profile::INCOGNITO_PROFILE;
   if (is_incognito) {
     icon = gfx::Image(GetIncognitoAvatarIcon());
     profile_indicator_icon_->set_stroke_color(SK_ColorTRANSPARENT);
@@ -424,3 +413,28 @@
   chrome::DrawTaskbarDecoration(frame_->GetNativeWindow(), &decoration);
 #endif
 }
+
+bool BrowserNonClientFrameView::ShouldShowProfileIndicatorIcon() const {
+  Browser* browser = browser_view()->browser();
+  Profile* profile = browser->profile();
+  const bool is_incognito =
+      profile->GetProfileType() == Profile::INCOGNITO_PROFILE;
+
+  // In the touch-optimized UI, we don't show the incognito icon in the browser
+  // frame. It's instead shown in the new tab button. However, we still show an
+  // avatar icon for the teleported browser windows between multi-user sessions
+  // (Chrome OS only). Note that you can't teleport an incognito window.
+  if (is_incognito && ui::MaterialDesignController::IsTouchOptimizedUiEnabled())
+    return false;
+
+#if defined(OS_CHROMEOS)
+  if (!browser->is_type_tabbed() && !browser->is_app())
+    return false;
+
+  if (!is_incognito && !MultiUserWindowManager::ShouldShowAvatar(
+                           browser_view()->GetNativeWindow())) {
+    return false;
+  }
+#endif  // defined(OS_CHROMEOS)
+  return true;
+}
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
index a43a838..59cf09c 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
@@ -142,6 +142,9 @@
   // Draws a taskbar icon if avatars are enabled, erases it otherwise.
   void UpdateTaskbarDecoration();
 
+  // Returns true if |profile_indicator_icon_| should be shown.
+  bool ShouldShowProfileIndicatorIcon() const;
+
   // The frame that hosts this view.
   BrowserFrame* frame_;
 
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
index 45791f9..1c4a262 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
@@ -241,8 +241,7 @@
 
   const int header_height =
       restored
-          ? GetAshLayoutSize(AshLayoutSize::BROWSER_RESTORED_CAPTION_BUTTON)
-                .height()
+          ? GetAshLayoutSize(AshLayoutSize::kBrowserCaptionRestored).height()
           : frame_header_->GetHeaderHeight();
   return header_height - browser_view()->GetTabStripHeight();
 }
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
index 682ad124..592f4d5c 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
@@ -101,9 +101,13 @@
                            AvatarDisplayOnTeleportedWindow);
   FRIEND_TEST_ALL_PREFIXES(BrowserNonClientFrameViewAshTest,
                            HeaderVisibilityInOverviewAndSplitview);
+  FRIEND_TEST_ALL_PREFIXES(BrowserNonClientFrameViewAshTest,
+                           HeaderHeightForSnappedBrowserInSplitView);
   FRIEND_TEST_ALL_PREFIXES(HostedAppNonClientFrameViewAshTest, HostedAppFrame);
   FRIEND_TEST_ALL_PREFIXES(BrowserNonClientFrameViewAshBackButtonTest,
                            V1BackButton);
+  FRIEND_TEST_ALL_PREFIXES(BrowserNonClientFrameViewAshTest,
+                           ToggleTabletModeOnMinimizedWindow);
   FRIEND_TEST_ALL_PREFIXES(ImmersiveModeControllerAshHostedAppBrowserTest,
                            FrameLayout);
 
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
index fa38d0a..67f14a4 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
@@ -13,6 +13,7 @@
 #include "ash/frame/frame_header.h"
 #include "ash/public/cpp/ash_switches.h"
 #include "ash/public/cpp/immersive/immersive_fullscreen_controller_test_api.h"
+#include "ash/public/cpp/vector_icons/vector_icons.h"
 #include "ash/shell.h"
 #include "ash/wm/overview/window_selector_controller.h"
 #include "ash/wm/splitview/split_view_controller.h"
@@ -27,7 +28,8 @@
 #include "chrome/browser/command_updater.h"
 #include "chrome/browser/profiles/profile_avatar_icon_util.h"
 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
-#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_test.h"
+#include "chrome/browser/ui/ash/multi_user/test_multi_user_window_manager.h"
+#include "chrome/browser/ui/ash/tablet_mode_client.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_command_controller.h"
 #include "chrome/browser/ui/browser_commands.h"
@@ -63,6 +65,7 @@
 #include "ui/events/event.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/views/widget/widget.h"
+#include "ui/wm/core/window_util.h"
 
 namespace {
 
@@ -293,10 +296,10 @@
   EXPECT_FALSE(MultiUserWindowManager::ShouldShowAvatar(window));
   EXPECT_FALSE(frame_view->profile_indicator_icon());
 
-  const AccountId current_account_id =
+  const AccountId account_id1 =
       multi_user_util::GetAccountIdFromProfile(browser()->profile());
   TestMultiUserWindowManager* manager =
-      new TestMultiUserWindowManager(browser(), current_account_id);
+      new TestMultiUserWindowManager(browser(), account_id1);
 
   // Teleport the window to another desktop.
   const AccountId account_id2(AccountId::FromUserEmail("user2"));
@@ -306,6 +309,11 @@
   // An icon should show on the top left corner of the teleported browser
   // window.
   EXPECT_TRUE(frame_view->profile_indicator_icon());
+
+  // Teleport the window back to owner desktop.
+  manager->ShowWindowForUser(window, account_id1);
+  EXPECT_FALSE(MultiUserWindowManager::ShouldShowAvatar(window));
+  EXPECT_FALSE(frame_view->profile_indicator_icon());
 }
 
 // Hit Test for Avatar Menu Button on ChromeOS.
@@ -418,6 +426,40 @@
   EXPECT_EQ(*min_window_size, frame_view->GetMinimumSize());
 }
 
+// Tests that when browser frame is minimized, toggling tablet mode doesn't
+// trigger caption button update (https://crbug.com/822890).
+IN_PROC_BROWSER_TEST_P(BrowserNonClientFrameViewAshTest,
+                       ToggleTabletModeOnMinimizedWindow) {
+  BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser());
+  Widget* widget = browser_view->GetWidget();
+  // We know we're using Ash, so static cast.
+  BrowserNonClientFrameViewAsh* frame_view =
+      static_cast<BrowserNonClientFrameViewAsh*>(
+          widget->non_client_view()->frame_view());
+  ash::FrameCaptionButtonContainerView::TestApi test(
+      frame_view->caption_button_container_);
+  widget->Maximize();
+  // Restore icon for size button in maximized window state.
+  EXPECT_EQ(&ash::kWindowControlRestoreIcon,
+            test.size_button()->icon_definition_for_test());
+  widget->Minimize();
+  // When entering tablet mode in minimized window state, size button should not
+  // get updated.
+  TabletModeClient::Get()->OnTabletModeToggled(true);
+  EXPECT_EQ(&ash::kWindowControlRestoreIcon,
+            test.size_button()->icon_definition_for_test());
+  // When leaving tablet mode in minimized window state, size button should not
+  // get updated.
+  TabletModeClient::Get()->OnTabletModeToggled(false);
+  EXPECT_EQ(&ash::kWindowControlRestoreIcon,
+            test.size_button()->icon_definition_for_test());
+  // When unminimizing in non-tablet mode, size button should match with
+  // maximized window state, which is restore icon.
+  ::wm::Unminimize(widget->GetNativeWindow());
+  EXPECT_EQ(&ash::kWindowControlRestoreIcon,
+            test.size_button()->icon_definition_for_test());
+}
+
 namespace {
 
 class ImmersiveModeBrowserViewTest
@@ -801,6 +843,43 @@
   EXPECT_FALSE(frame_view2->caption_button_container_->visible());
 }
 
+// Tests that the header of a snapped browser window in splitview mode uses
+// the same header height of a maximized window.
+IN_PROC_BROWSER_TEST_P(BrowserNonClientFrameViewAshTest,
+                       HeaderHeightForSnappedBrowserInSplitView) {
+  BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser());
+  Widget* widget = browser_view->GetWidget();
+  BrowserNonClientFrameViewAsh* frame_view =
+      static_cast<BrowserNonClientFrameViewAsh*>(
+          widget->non_client_view()->frame_view());
+  widget->GetNativeWindow()->SetProperty(
+      aura::client::kResizeBehaviorKey,
+      ui::mojom::kResizeBehaviorCanMaximize |
+          ui::mojom::kResizeBehaviorCanResize);
+
+  // Maximize the widget and store its frame header height.
+  widget->Maximize();
+  const int expected_height = frame_view->frame_header_->GetHeaderHeight();
+  widget->Restore();
+
+  ash::Shell* shell = ash::Shell::Get();
+  ash::SplitViewController* split_view_controller =
+      shell->split_view_controller();
+  split_view_controller->BindRequest(
+      mojo::MakeRequest(&frame_view->split_view_controller_));
+  split_view_controller->AddObserver(
+      frame_view->CreateInterfacePtrForTesting());
+  frame_view->split_view_controller_.FlushForTesting();
+
+  shell->tablet_mode_controller()->EnableTabletModeWindowManager(true);
+  shell->window_selector_controller()->ToggleOverview();
+  split_view_controller->SnapWindow(widget->GetNativeWindow(),
+                                    ash::SplitViewController::LEFT);
+  frame_view->split_view_controller_.FlushForTesting();
+  EXPECT_TRUE(frame_view->caption_button_container_->visible());
+  EXPECT_EQ(expected_height, frame_view->frame_header_->GetHeaderHeight());
+}
+
 // Test the V1 apps' kTopViewInset.
 IN_PROC_BROWSER_TEST_P(HostedAppNonClientFrameViewAshTest, V1AppTopViewInset) {
   browser()->window()->Close();
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mus.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mus.cc
index 6812476..7587342 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mus.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mus.cc
@@ -443,9 +443,8 @@
 #if defined(OS_CHROMEOS)
   // TODO: move ash_layout_constants to ash/public/cpp.
   const bool restored = !frame()->IsMaximized() && !frame()->IsFullscreen();
-  return GetAshLayoutSize(restored
-                              ? AshLayoutSize::BROWSER_RESTORED_CAPTION_BUTTON
-                              : AshLayoutSize::BROWSER_MAXIMIZED_CAPTION_BUTTON)
+  return GetAshLayoutSize(restored ? AshLayoutSize::kBrowserCaptionRestored
+                                   : AshLayoutSize::kBrowserCaptionMaximized)
       .height();
 #else
   return views::WindowManagerFrameValues::instance().normal_insets.top();
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
index 607c39f..e34d404 100644
--- a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
+++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
@@ -634,9 +634,16 @@
   // power consumption needed for DWM to blend the window contents.
   //
   // So the accent border also has to be opaque, but native inactive borders
-  // are #565656 with 80% alpha. We copy Edge (which also custom-draws its top
-  // border) and use #A2A2A2 instead.
-  constexpr SkColor inactive_border_color = 0xFFA2A2A2;
+  // are #494949 with 47% alpha. Against white (the most visible case) this is
+  // #AAAAAA, so we color with that normally. However, when the titlebar is dark
+  // that color sometimes stands out badly. In that case we lighten the titlebar
+  // color slightly, which creates a subtle highlight effect. This isn't exactly
+  // native but it looks good given our constraints.
+  const SkColor titlebar_color = GetTitlebarColor();
+  const SkColor inactive_border_color =
+      color_utils::IsDark(titlebar_color)
+          ? color_utils::BlendTowardOppositeLuma(titlebar_color, 0x0F)
+          : SkColorSetRGB(0xAA, 0xAA, 0xAA);
   flags.setColor(
       ShouldPaintAsActive()
           ? GetThemeProvider()->GetColor(ThemeProperties::COLOR_ACCENT_BORDER)
@@ -647,7 +654,7 @@
       gfx::RectF(0, y, width() * scale, tabstrip_bounds.bottom() * scale - y));
   // Paint the titlebar first so we have a background if an area isn't covered
   // by the theme image.
-  flags.setColor(GetTitlebarColor());
+  flags.setColor(titlebar_color);
   canvas->DrawRect(titlebar_rect, flags);
   const gfx::ImageSkia frame_image = GetFrameImage();
   if (!frame_image.isNull()) {
diff --git a/chrome/browser/ui/views/fullscreen_control/fullscreen_control_view.cc b/chrome/browser/ui/views/fullscreen_control/fullscreen_control_view.cc
index ba4f5ed0..7488420e 100644
--- a/chrome/browser/ui/views/fullscreen_control/fullscreen_control_view.cc
+++ b/chrome/browser/ui/views/fullscreen_control/fullscreen_control_view.cc
@@ -21,6 +21,7 @@
 #include "ui/views/controls/button/button.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/layout/fill_layout.h"
+#include "ui/views/vector_icons.h"
 
 namespace {
 
@@ -37,7 +38,7 @@
     std::unique_ptr<views::ImageView> close_image_view =
         std::make_unique<views::ImageView>();
     close_image_view->SetImage(gfx::CreateVectorIcon(
-        vector_icons::kCloseIcon, kCloseIconSize, SK_ColorWHITE));
+        views::kIcCloseIcon, kCloseIconSize, SK_ColorWHITE));
     SetAccessibleName(l10n_util::GetStringUTF16(IDS_EXIT_FULLSCREEN_MODE));
     AddChildView(close_image_view.release());
     SetLayoutManager(std::make_unique<views::FillLayout>());
diff --git a/chrome/browser/ui/views/harmony/chrome_layout_provider.cc b/chrome/browser/ui/views/harmony/chrome_layout_provider.cc
index 050611e..acbf8b2 100644
--- a/chrome/browser/ui/views/harmony/chrome_layout_provider.cc
+++ b/chrome/browser/ui/views/harmony/chrome_layout_provider.cc
@@ -114,3 +114,16 @@
 bool ChromeLayoutProvider::IsHarmonyMode() const {
   return false;
 }
+
+int ChromeLayoutProvider::GetCornerRadiusMetric(
+    ChromeEmphasisMetric emphasis_metric,
+    const gfx::Rect& bounds) const {
+  // Outside of MD (refresh) mode, just stick to the current fixed value.
+  return emphasis_metric == EMPHASIS_HIGH ? 0 : 4;
+}
+
+int ChromeLayoutProvider::GetShadowElevationMetric(
+    ChromeEmphasisMetric emphasis_metric) const {
+  // Just return a value for now.
+  return 2;
+}
diff --git a/chrome/browser/ui/views/harmony/chrome_layout_provider.h b/chrome/browser/ui/views/harmony/chrome_layout_provider.h
index 325bad5..02887e30 100644
--- a/chrome/browser/ui/views/harmony/chrome_layout_provider.h
+++ b/chrome/browser/ui/views/harmony/chrome_layout_provider.h
@@ -9,6 +9,7 @@
 
 #include "base/macros.h"
 #include "ui/gfx/geometry/insets.h"
+#include "ui/gfx/geometry/rect.h"
 #include "ui/views/layout/grid_layout.h"
 #include "ui/views/layout/layout_provider.h"
 
@@ -59,6 +60,18 @@
   DISTANCE_BUBBLE_PREFERRED_WIDTH,
 };
 
+enum ChromeEmphasisMetric {
+  // No emphasis needed for shadows, corner radius, etc.
+  EMPHASIS_NONE,
+  // Use this to indicate low-emphasis interactive elements such as buttons and
+  // text fields
+  EMPHASIS_LOW,
+  // Use this for components with medium emphasis, such as tabs or dialogs.
+  EMPHASIS_MEDIUM,
+  // High-emphasis components like the omnibox or rich suggestions.
+  EMPHASIS_HIGH,
+};
+
 class ChromeLayoutProvider : public views::LayoutProvider {
  public:
   ChromeLayoutProvider();
@@ -96,6 +109,20 @@
   // TODO(pkasting): Fix callers and remove this.
   virtual bool IsHarmonyMode() const;
 
+  // TODO (https://crbug.com/822000): Possibly combine the following two
+  // functions into a single function returning a struct. Keeping them separate
+  // for now in case different emphasis is needed for different elements in the
+  // same context. Delete this TODO in Q4 2018.
+
+  // Returns the corner radius specific to the given emphasis metric.
+  virtual int GetCornerRadiusMetric(
+      ChromeEmphasisMetric emphasis_metric,
+      const gfx::Rect& bounds = gfx::Rect()) const;
+
+  // Returns the shadow elevation metric for the given emphasis.
+  virtual int GetShadowElevationMetric(
+      ChromeEmphasisMetric emphasis_metric) const;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(ChromeLayoutProvider);
 };
diff --git a/chrome/browser/ui/views/harmony/chrome_typography.cc b/chrome/browser/ui/views/harmony/chrome_typography.cc
index 058e626..cbd0ea1d 100644
--- a/chrome/browser/ui/views/harmony/chrome_typography.cc
+++ b/chrome/browser/ui/views/harmony/chrome_typography.cc
@@ -5,20 +5,89 @@
 #include "chrome/browser/ui/views/harmony/chrome_typography.h"
 
 #include "build/build_config.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "ui/base/default_style.h"
+#include "ui/base/material_design/material_design_controller.h"
 #include "ui/base/resource/resource_bundle.h"
+#include "ui/base/ui_features.h"
 #include "ui/gfx/platform_font.h"
 
+namespace {
+
+// Mac doesn't use LocationBarView (yet).
+#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
+
+// Takes a desired font size and returns the size delta to request from
+// ui::ResourceBundle that will result either in that font size, or the biggest
+// font size that is smaller than the desired font size but will fit inside
+// |available_height|.
+int GetFontSizeDeltaBoundedByAvailableHeight(int available_height,
+                                             int desired_font_size) {
+  int size_delta = desired_font_size - gfx::PlatformFont::kDefaultBaseFontSize;
+  ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
+  gfx::FontList base_font = bundle.GetFontListWithDelta(size_delta);
+
+  // The ResourceBundle's default font may not actually be kDefaultBaseFontSize
+  // if, for example, the user has changed their system font sizes or the
+  // current locale has been overridden to use a different default font size.
+  // Adjust for the difference in default font sizes.
+  if (base_font.GetFontSize() != desired_font_size) {
+    size_delta += desired_font_size - base_font.GetFontSize();
+    base_font = bundle.GetFontListWithDelta(size_delta);
+  }
+  DCHECK_EQ(desired_font_size, base_font.GetFontSize());
+
+  // Shrink large fonts to ensure they fit. Default fonts should fit already.
+  // TODO(tapted): Move DeriveWithHeightUpperBound() to ui::ResourceBundle to
+  // take advantage of the font cache.
+  base_font = base_font.DeriveWithHeightUpperBound(available_height);
+  return base_font.GetFontSize() - gfx::PlatformFont::kDefaultBaseFontSize;
+}
+
+#endif  // OS_MACOSX || MAC_VIEWS_BROWSER
+
+}  // namespace
+
 void ApplyCommonFontStyles(int context,
                            int style,
                            int* size_delta,
                            gfx::Font::Weight* weight) {
+  switch (context) {
+#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
+    case CONTEXT_OMNIBOX_PRIMARY: {
+      constexpr int kDesiredFontSizeRegular = 14;
+      constexpr int kDesiredFontSizeTouchable = 15;
+      static const int omnibox_primary_delta =
+          GetFontSizeDeltaBoundedByAvailableHeight(
+              LocationBarView::GetAvailableTextHeight(),
+              ui::MaterialDesignController::IsTouchOptimizedUiEnabled()
+                  ? kDesiredFontSizeTouchable
+                  : kDesiredFontSizeRegular);
+      *size_delta = omnibox_primary_delta;
+      break;
+    }
+    case CONTEXT_OMNIBOX_DECORATION: {
+      // Use 11 for both touchable and non-touchable. The touchable spec
+      // specifies 11 explicitly. Historically, non-touchable would take the
+      // primary omnibox font and incrementally reduce its size until it fit.
+      // In default configurations, it would obtain 11. Deriving fonts is slow,
+      // so don't bother starting at 14.
+      constexpr int kDesiredFontSizeDecoration = 11;
+      static const int omnibox_decoration_delta =
+          GetFontSizeDeltaBoundedByAvailableHeight(
+              LocationBarView::GetAvailableDecorationTextHeight(),
+              kDesiredFontSizeDecoration);
+      *size_delta = omnibox_decoration_delta;
+      break;
+    }
+#endif  // !OS_MACOSX || MAC_VIEWS_BROWSER
 #if defined(OS_WIN)
-  if (context == CONTEXT_WINDOWS10_NATIVE) {
-    // Adjusts default font size up to match Win10 modern UI.
-    *size_delta = 15 - gfx::PlatformFont::kDefaultBaseFontSize;
-  }
+    case CONTEXT_WINDOWS10_NATIVE:
+      // Adjusts default font size up to match Win10 modern UI.
+      *size_delta = 15 - gfx::PlatformFont::kDefaultBaseFontSize;
+      break;
 #endif
+  }
 }
 
 const gfx::FontList& LegacyTypographyProvider::GetFont(int context,
@@ -54,6 +123,7 @@
 
   switch (style) {
     case STYLE_EMPHASIZED:
+    case STYLE_EMPHASIZED_SECONDARY:
       font_weight = gfx::Font::Weight::BOLD;
       break;
   }
@@ -66,8 +136,10 @@
                                            int context,
                                            int style) const {
   // Use "disabled grey" for HINT and SECONDARY when Harmony is disabled.
-  if (style == STYLE_HINT || style == STYLE_SECONDARY)
+  if (style == STYLE_HINT || style == STYLE_SECONDARY ||
+      style == STYLE_EMPHASIZED_SECONDARY) {
     style = views::style::STYLE_DISABLED;
+  }
 
   return DefaultTypographyProvider::GetColor(view, context, style);
 }
diff --git a/chrome/browser/ui/views/harmony/chrome_typography.h b/chrome/browser/ui/views/harmony/chrome_typography.h
index 984df09..3773a6d1 100644
--- a/chrome/browser/ui/views/harmony/chrome_typography.h
+++ b/chrome/browser/ui/views/harmony/chrome_typography.h
@@ -31,6 +31,12 @@
   // "Body 2". Usually 12pt.
   CONTEXT_BODY_TEXT_SMALL,
 
+  // Text in the location bar entry, and primary text in the omnibox dropdown.
+  CONTEXT_OMNIBOX_PRIMARY,
+
+  // Text that goes inside location bar decorations such as the keyword hint.
+  CONTEXT_OMNIBOX_DECORATION,
+
   // Text for titles, body text and buttons that appear in dialogs attempting to
   // mimic the native Windows 10 look and feel.
   CONTEXT_WINDOWS10_NATIVE,
@@ -59,6 +65,10 @@
   // Used to draw attention to a section of body text such as an extension name
   // or hostname.
   STYLE_EMPHASIZED,
+
+  // Emphasized secondary style. Like STYLE_EMPHASIZED but styled to match
+  // surrounding STYLE_SECONDARY text.
+  STYLE_EMPHASIZED_SECONDARY,
 };
 
 // Sets the |size_delta| and |font_weight| for text that should not be affected
diff --git a/chrome/browser/ui/views/harmony/harmony_typography_provider.cc b/chrome/browser/ui/views/harmony/harmony_typography_provider.cc
index 32c04305..3baa9d5 100644
--- a/chrome/browser/ui/views/harmony/harmony_typography_provider.cc
+++ b/chrome/browser/ui/views/harmony/harmony_typography_provider.cc
@@ -142,7 +142,7 @@
 
   // Use a bold style for emphasized text in body contexts, and ignore |style|
   // otherwise.
-  if (style == STYLE_EMPHASIZED) {
+  if (style == STYLE_EMPHASIZED || style == STYLE_EMPHASIZED_SECONDARY) {
     switch (context) {
       case CONTEXT_BODY_TEXT_SMALL:
       case CONTEXT_BODY_TEXT_LARGE:
@@ -194,6 +194,7 @@
     case views::style::STYLE_LINK:
       return gfx::kGoogleBlue700;
     case STYLE_SECONDARY:
+    case STYLE_EMPHASIZED_SECONDARY:
     case STYLE_HINT:
       return SkColorSetRGB(0x75, 0x75, 0x75);
     case STYLE_RED:
diff --git a/chrome/browser/ui/views/ime/input_ime_apitest_nonchromeos.cc b/chrome/browser/ui/views/ime/input_ime_apitest_nonchromeos.cc
index dbeaeb7..f84fd33 100644
--- a/chrome/browser/ui/views/ime/input_ime_apitest_nonchromeos.cc
+++ b/chrome/browser/ui/views/ime/input_ime_apitest_nonchromeos.cc
@@ -93,7 +93,7 @@
   composition.text = base::UTF8ToUTF16("test_set_composition");
   composition.ime_text_spans.push_back(ui::ImeTextSpan(
       ui::ImeTextSpan::Type::kComposition, 0, composition.text.length(),
-      SK_ColorBLACK, ui::ImeTextSpan::Thickness::kThin, SK_ColorTRANSPARENT));
+      ui::ImeTextSpan::Thickness::kThin, SK_ColorTRANSPARENT));
   composition.selection = gfx::Range(2, 2);
   const std::vector<ui::CompositionText>& composition_history =
       client->composition_history();
diff --git a/chrome/browser/ui/views/intent_picker_bubble_view.cc b/chrome/browser/ui/views/intent_picker_bubble_view.cc
index 00df606..2d34bcce 100644
--- a/chrome/browser/ui/views/intent_picker_bubble_view.cc
+++ b/chrome/browser/ui/views/intent_picker_bubble_view.cc
@@ -148,6 +148,8 @@
   }
   views::Widget* widget =
       views::BubbleDialogDelegateView::CreateBubble(intent_picker_bubble_);
+  intent_picker_bubble_->SetArrowPaintType(
+      views::BubbleBorder::PAINT_TRANSPARENT);
   intent_picker_bubble_->GetDialogClientView()->Layout();
   intent_picker_bubble_->SetFocusBehavior(View::FocusBehavior::ALWAYS);
   intent_picker_bubble_->GetIntentPickerLabelButtonAt(0)->MarkAsSelected(
diff --git a/chrome/browser/ui/views/location_bar/background_with_1_px_border.cc b/chrome/browser/ui/views/location_bar/background_with_1_px_border.cc
index db321d1..f59027b 100644
--- a/chrome/browser/ui/views/location_bar/background_with_1_px_border.cc
+++ b/chrome/browser/ui/views/location_bar/background_with_1_px_border.cc
@@ -21,8 +21,7 @@
 
 // static
 bool BackgroundWith1PxBorder::IsRounded() {
-  return ui::MaterialDesignController::GetMode() ==
-         ui::MaterialDesignController::MATERIAL_TOUCH_OPTIMIZED;
+  return ui::MaterialDesignController::IsNewerMaterialUi();
 }
 
 void BackgroundWith1PxBorder::PaintFocusRing(gfx::Canvas* canvas,
diff --git a/chrome/browser/ui/views/location_bar/content_setting_bubble_dialog_browsertest.cc b/chrome/browser/ui/views/location_bar/content_setting_bubble_dialog_browsertest.cc
index a0997fa..fc78e57 100644
--- a/chrome/browser/ui/views/location_bar/content_setting_bubble_dialog_browsertest.cc
+++ b/chrome/browser/ui/views/location_bar/content_setting_bubble_dialog_browsertest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/memory/ptr_util.h"
+#include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/histogram_tester.h"
 #include "base/time/time.h"
@@ -36,8 +37,10 @@
  public:
   ContentSettingBubbleDialogTest() {}
 
-  void ShowDialogBubble(ContentSettingsType content_type,
-                        ContentSettingImageModel::ImageType image_type);
+  void ApplyMediastreamSettings(bool mic_accessed, bool camera_accessed);
+  void ApplyContentSettingsForType(ContentSettingsType content_type);
+
+  void ShowDialogBubble(ContentSettingImageModel::ImageType image_type);
 
   void ShowUi(const std::string& name) override;
 
@@ -45,23 +48,28 @@
   DISALLOW_COPY_AND_ASSIGN(ContentSettingBubbleDialogTest);
 };
 
-void ContentSettingBubbleDialogTest::ShowDialogBubble(
-    ContentSettingsType content_type,
-    ContentSettingImageModel::ImageType image_type) {
+void ContentSettingBubbleDialogTest::ApplyMediastreamSettings(
+    bool mic_accessed,
+    bool camera_accessed) {
+  const int mic_setting =
+      mic_accessed ? TabSpecificContentSettings::MICROPHONE_ACCESSED : 0;
+  const int camera_setting =
+      camera_accessed ? TabSpecificContentSettings::CAMERA_ACCESSED : 0;
+  TabSpecificContentSettings* content_settings =
+      TabSpecificContentSettings::FromWebContents(
+          browser()->tab_strip_model()->GetActiveWebContents());
+  content_settings->OnMediaStreamPermissionSet(
+      GURL::EmptyGURL(), mic_setting | camera_setting, std::string(),
+      std::string(), std::string(), std::string());
+}
+
+void ContentSettingBubbleDialogTest::ApplyContentSettingsForType(
+    ContentSettingsType content_type) {
   content::WebContents* web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
   TabSpecificContentSettings* content_settings =
       TabSpecificContentSettings::FromWebContents(web_contents);
   switch (content_type) {
-    case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
-    case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
-      content_settings->OnMediaStreamPermissionSet(
-          GURL::EmptyGURL(),
-          content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
-              ? TabSpecificContentSettings::MICROPHONE_ACCESSED
-              : TabSpecificContentSettings::CAMERA_ACCESSED,
-          std::string(), std::string(), std::string(), std::string());
-      break;
     case CONTENT_SETTINGS_TYPE_GEOLOCATION:
       content_settings->OnGeolocationPermissionSet(GURL::EmptyGURL(), false);
       break;
@@ -97,6 +105,10 @@
       break;
   }
   browser()->window()->UpdateToolbar(web_contents);
+}
+
+void ContentSettingBubbleDialogTest::ShowDialogBubble(
+    ContentSettingImageModel::ImageType image_type) {
   LocationBarTesting* location_bar_testing =
       browser()->window()->GetLocationBar()->GetLocationBarForTesting();
 
@@ -111,6 +123,14 @@
 }
 
 void ContentSettingBubbleDialogTest::ShowUi(const std::string& name) {
+  if (base::StartsWith(name, "mediastream", base::CompareCase::SENSITIVE)) {
+    ApplyMediastreamSettings(
+        name == "mediastream_mic" || name == "mediastream_mic_and_camera",
+        name == "mediastream_camera" || name == "mediastream_mic_and_camera");
+    ShowDialogBubble(ImageType::MEDIASTREAM);
+    return;
+  }
+
   constexpr struct {
     const char* name;
     ContentSettingsType content_type;
@@ -127,10 +147,6 @@
        ImageType::PPAPI_BROKER},
       {"mixed_script", CONTENT_SETTINGS_TYPE_MIXEDSCRIPT,
        ImageType::MIXEDSCRIPT},
-      {"mediastream_mic", CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
-       ImageType::MEDIASTREAM},
-      {"mediastream_camera", CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
-       ImageType::MEDIASTREAM},
       {"protocol_handlers", CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS,
        ImageType::PROTOCOL_HANDLERS},
       {"automatic_downloads", CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS,
@@ -140,8 +156,8 @@
   };
   for (auto content_settings : content_settings_values) {
     if (name == content_settings.name) {
-      ShowDialogBubble(content_settings.content_type,
-                       content_settings.image_type);
+      ApplyContentSettingsForType(content_settings.content_type);
+      ShowDialogBubble(content_settings.image_type);
       return;
     }
   }
@@ -192,6 +208,11 @@
 }
 
 IN_PROC_BROWSER_TEST_F(ContentSettingBubbleDialogTest,
+                       InvokeUi_mediastream_mic_and_camera) {
+  ShowAndVerifyUi();
+}
+
+IN_PROC_BROWSER_TEST_F(ContentSettingBubbleDialogTest,
                        InvokeUi_protocol_handlers) {
   ShowAndVerifyUi();
 }
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc
index 5734f1c8..8ff51521 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -41,6 +41,7 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/views/autofill/save_card_icon_view.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/harmony/chrome_typography.h"
 #include "chrome/browser/ui/views/location_bar/background_with_1_px_border.h"
 #include "chrome/browser/ui/views/location_bar/bubble_icon_view.h"
 #include "chrome/browser/ui/views/location_bar/content_setting_image_view.h"
@@ -184,27 +185,8 @@
   layer()->SetFillsBoundsOpaquely(false);
   layer()->SetMasksToBounds(true);
 
-  // Determine the main font.
-  gfx::FontList font_list = ui::ResourceBundle::GetSharedInstance().GetFontList(
-      ui::ResourceBundle::BaseFont);
-  const int current_font_size = font_list.GetFontSize();
-  constexpr int kDesiredFontSize = 14;
-  if (current_font_size != kDesiredFontSize) {
-    font_list =
-        font_list.DeriveWithSizeDelta(kDesiredFontSize - current_font_size);
-  }
-  // Shrink large fonts to make them fit.
-  // TODO(pkasting): Stretch the location bar instead in this case.
-  const int vertical_padding = GetTotalVerticalPadding();
-  const int location_height =
-      std::max(GetPreferredSize().height() - (vertical_padding * 2), 0);
-  font_list = font_list.DeriveWithHeightUpperBound(location_height);
-
-  // Determine the font for use inside the bubbles.
-  const int bubble_padding =
-      GetLayoutConstant(LOCATION_BAR_BUBBLE_VERTICAL_PADDING) +
-      GetLayoutConstant(LOCATION_BAR_BUBBLE_FONT_VERTICAL_PADDING);
-  const int bubble_height = location_height - (bubble_padding * 2);
+  const gfx::FontList& font_list = views::style::GetFont(
+      CONTEXT_OMNIBOX_PRIMARY, views::style::STYLE_PRIMARY);
 
   const SkColor background_color =
       GetColor(OmniboxPart::LOCATION_BAR_BACKGROUND);
@@ -235,8 +217,8 @@
   selected_keyword_view_ = new SelectedKeywordView(this, font_list, profile());
   AddChildView(selected_keyword_view_);
 
-  gfx::FontList bubble_font_list =
-      font_list.DeriveWithHeightUpperBound(bubble_height);
+  const gfx::FontList& bubble_font_list = views::style::GetFont(
+      CONTEXT_OMNIBOX_DECORATION, views::style::STYLE_PRIMARY);
   keyword_hint_view_ = new KeywordHintView(
       this, profile(), font_list, bubble_font_list,
       GetColor(OmniboxPart::LOCATION_BAR_TEXT_DIMMED), background_color);
@@ -714,6 +696,35 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
+// LocationBarView, public static methods:
+
+// static
+bool LocationBarView::IsVirtualKeyboardVisible() {
+#if defined(OS_WIN)
+  return ui::OnScreenKeyboardDisplayManager::GetInstance()->IsKeyboardVisible();
+#elif defined(USE_AURA)
+  return keyboard::IsKeyboardVisible();
+#else
+  return false;
+#endif
+}
+
+// static
+int LocationBarView::GetAvailableTextHeight() {
+  return std::max(0, GetLayoutConstant(LOCATION_BAR_HEIGHT) -
+                         2 * GetTotalVerticalPadding());
+}
+
+// static
+int LocationBarView::GetAvailableDecorationTextHeight() {
+  const int bubble_padding =
+      GetLayoutConstant(LOCATION_BAR_BUBBLE_VERTICAL_PADDING) +
+      GetLayoutConstant(LOCATION_BAR_BUBBLE_FONT_VERTICAL_PADDING);
+  return std::max(
+      0, LocationBarView::GetAvailableTextHeight() - (bubble_padding * 2));
+}
+
+////////////////////////////////////////////////////////////////////////////////
 // LocationBarView, private:
 
 int LocationBarView::IncrementalMinimumWidth(views::View* view) const {
@@ -733,11 +744,6 @@
              : BackgroundWith1PxBorder::kLocationBarBorderThicknessDip;
 }
 
-int LocationBarView::GetTotalVerticalPadding() const {
-  return BackgroundWith1PxBorder::kLocationBarBorderThicknessDip +
-         GetLayoutConstant(LOCATION_BAR_PADDING);
-}
-
 void LocationBarView::RefreshLocationIcon() {
   // |omnibox_view_| may not be ready yet if Init() has not been called. The
   // icon will be set soon by OnChanged().
@@ -812,16 +818,6 @@
   }
 }
 
-bool LocationBarView::IsVirtualKeyboardVisible() {
-#if defined(OS_WIN)
-  return ui::OnScreenKeyboardDisplayManager::GetInstance()->IsKeyboardVisible();
-#elif defined(USE_AURA)
-  return keyboard::IsKeyboardVisible();
-#else
-  return false;
-#endif
-}
-
 bool LocationBarView::RefreshFindBarIcon() {
   // |browser_| may be nullptr since some unit tests pass it in for the
   // Browser*. |browser_->window()| may return nullptr because Update() is
@@ -1117,3 +1113,12 @@
 void LocationBarView::SetFocusAndSelection(bool select_all) {
   FocusLocation(select_all);
 }
+
+////////////////////////////////////////////////////////////////////////////////
+// LocationBarView, private static methods:
+
+// static
+int LocationBarView::GetTotalVerticalPadding() {
+  return BackgroundWith1PxBorder::kLocationBarBorderThicknessDip +
+         GetLayoutConstant(LOCATION_BAR_PADDING);
+}
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.h b/chrome/browser/ui/views/location_bar/location_bar_view.h
index c8726fa4..0ea3a232 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.h
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.h
@@ -246,6 +246,12 @@
 
   static bool IsVirtualKeyboardVisible();
 
+  // Returns the height available for user-entered text in the location bar.
+  static int GetAvailableTextHeight();
+
+  // Returns the height available for text within location bar decorations.
+  static int GetAvailableDecorationTextHeight();
+
  private:
   FRIEND_TEST_ALL_PREFIXES(SecurityIndicatorTest, CheckIndicatorText);
   using ContentSettingViews = std::vector<ContentSettingImageView*>;
@@ -260,10 +266,6 @@
   // Returns the thickness of any visible edge, in pixels.
   int GetHorizontalEdgeThickness() const;
 
-  // Returns the total amount of space reserved above or below the content,
-  // which is the vertical edge thickness plus the padding next to it.
-  int GetTotalVerticalPadding() const;
-
   // Updates |location_icon_view_| based on the current state and theme.
   void RefreshLocationIcon();
 
@@ -354,6 +356,10 @@
   // DropdownBarHostDelegate:
   void SetFocusAndSelection(bool select_all) override;
 
+  // Returns the total amount of space reserved above or below the content,
+  // which is the vertical edge thickness plus the padding next to it.
+  static int GetTotalVerticalPadding();
+
   // The Browser this LocationBarView is in.  Note that at least
   // chromeos::SimpleWebViewDialog uses a LocationBarView outside any browser
   // window, so this may be NULL.
diff --git a/chrome/browser/ui/views/location_bar/selected_keyword_view.cc b/chrome/browser/ui/views/location_bar/selected_keyword_view.cc
index 218c860..e42cf4b 100644
--- a/chrome/browser/ui/views/location_bar/selected_keyword_view.cc
+++ b/chrome/browser/ui/views/location_bar/selected_keyword_view.cc
@@ -11,9 +11,11 @@
 #include "chrome/browser/ui/omnibox/omnibox_theme.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/grit/generated_resources.h"
+#include "components/omnibox/browser/vector_icons.h"
 #include "components/search_engines/template_url_service.h"
 #include "components/vector_icons/vector_icons.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/material_design/material_design_controller.h"
 #include "ui/base/theme_provider.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/color_utils.h"
@@ -36,9 +38,11 @@
 }
 
 void SelectedKeywordView::ResetImage() {
-  SetImage(gfx::CreateVectorIcon(vector_icons::kSearchIcon,
-                                 GetLayoutConstant(LOCATION_BAR_ICON_SIZE),
-                                 GetTextColor()));
+  SetImage(gfx::CreateVectorIcon(
+      ui::MaterialDesignController::IsTouchOptimizedUiEnabled()
+          ? omnibox::kTouchableSearchIcon
+          : vector_icons::kSearchIcon,
+      GetLayoutConstant(LOCATION_BAR_ICON_SIZE), GetTextColor()));
 }
 
 SkColor SelectedKeywordView::GetTextColor() const {
diff --git a/chrome/browser/ui/views/message_center/popups_only_ui_delegate.cc b/chrome/browser/ui/views/message_center/popups_only_ui_delegate.cc
index b4ce267..de7da93ce 100644
--- a/chrome/browser/ui/views/message_center/popups_only_ui_delegate.cc
+++ b/chrome/browser/ui/views/message_center/popups_only_ui_delegate.cc
@@ -33,7 +33,7 @@
 
 bool PopupsOnlyUiDelegate::ShowPopups() {
   alignment_delegate_->StartObserving(display::Screen::GetScreen());
-  popup_collection_->DoUpdateIfPossible();
+  popup_collection_->DoUpdate();
   return true;
 }
 
diff --git a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
index 4ccf59c..2e4acd29 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/search/search.h"
 #include "chrome/browser/themes/theme_properties.h"
 #include "chrome/browser/ui/omnibox/omnibox_theme.h"
+#include "chrome/browser/ui/views/location_bar/background_with_1_px_border.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/browser/ui/views/omnibox/omnibox_result_view.h"
 #include "chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.h"
@@ -52,12 +53,8 @@
 
 constexpr int kPopupVerticalPadding = 4;
 
-bool IsRounded() {
-  return ui::MaterialDesignController::IsTouchOptimizedUiEnabled();
-}
-
 bool IsNarrow() {
-  return IsRounded() ||
+  return BackgroundWith1PxBorder::IsRounded() ||
          base::FeatureList::IsEnabled(omnibox::kUIExperimentNarrowDropdown);
 }
 
@@ -166,7 +163,7 @@
     params.bounds = bounds;
     params.context = parent_widget->GetNativeWindow();
 
-    if (IsRounded())
+    if (BackgroundWith1PxBorder::IsRounded())
       RoundedOmniboxResultsFrame::OnBeforeWidgetInit(&params);
     else
       animator_ = std::make_unique<WidgetShrinkAnimation>(this, bounds);
@@ -175,7 +172,7 @@
   }
 
   void SetPopupContentsView(OmniboxPopupContentsView* contents) {
-    if (IsRounded()) {
+    if (BackgroundWith1PxBorder::IsRounded()) {
       SetContentsView(new RoundedOmniboxResultsFrame(
           contents, contents->location_bar_view_));
     } else {
@@ -317,7 +314,7 @@
     child_at(i)->SetVisible(false);
 
   gfx::Rect new_target_bounds = UpdateMarginsAndGetTargetBounds();
-  if (IsNarrow() && !IsRounded()) {
+  if (IsNarrow() && !BackgroundWith1PxBorder::IsRounded()) {
     SkColor background_color =
         GetOmniboxColor(OmniboxPart::RESULTS_BACKGROUND, GetTint());
     auto border = std::make_unique<views::BubbleBorder>(
@@ -441,7 +438,7 @@
 // OmniboxPopupContentsView, private:
 
 gfx::Rect OmniboxPopupContentsView::UpdateMarginsAndGetTargetBounds() {
-  if (IsRounded()) {
+  if (BackgroundWith1PxBorder::IsRounded()) {
     // The rounded popup is always offset the same amount from the omnibox.
     gfx::Rect content_rect = location_bar_view_->GetBoundsInScreen();
     content_rect.Inset(
@@ -492,7 +489,7 @@
   // amount of space between the text and the popup border as there is in the
   // interior between each row of text.
   int height = popup_height;
-  if (IsRounded()) {
+  if (BackgroundWith1PxBorder::IsRounded()) {
     height += RoundedOmniboxResultsFrame::GetAlignmentInsets(location_bar_view_)
                   .height();
   } else {
@@ -504,7 +501,7 @@
 
 void OmniboxPopupContentsView::LayoutChildren() {
   gfx::Rect contents_rect = GetContentsBounds();
-  if (!IsRounded()) {
+  if (!BackgroundWith1PxBorder::IsRounded()) {
     contents_rect.Inset(gfx::Insets(kPopupVerticalPadding, 0));
     contents_rect.Inset(start_margin_, g_top_shadow.Get().height(), end_margin_,
                         0);
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
index 3bd163a..be5d7bd 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
@@ -67,13 +67,12 @@
 
 // Whether to use the two-line layout.
 bool IsTwoLineLayout() {
-  return base::FeatureList::IsEnabled(omnibox::kUIExperimentVerticalLayout) ||
-         ui::MaterialDesignController::IsTouchOptimizedUiEnabled();
+  return base::FeatureList::IsEnabled(omnibox::kUIExperimentVerticalLayout);
 }
 
 // Creates a views::Background for the current result style.
 std::unique_ptr<views::Background> CreateBackgroundWithColor(SkColor bg_color) {
-  return ui::MaterialDesignController::IsTouchOptimizedUiEnabled()
+  return ui::MaterialDesignController::IsNewerMaterialUi()
              ? views::CreateSolidBackground(bg_color)
              : std::make_unique<BackgroundWith1PxBorder>(bg_color, bg_color);
 }
@@ -134,7 +133,8 @@
   keyword_icon_view_->SizeToPreferredSize();
 
   if (OmniboxFieldTrial::InTabSwitchSuggestionWithButtonTrial()) {
-    tab_switch_button_.reset(new OmniboxTabSwitchButton(this));
+    tab_switch_button_ =
+        std::make_unique<OmniboxTabSwitchButton>(this, GetTextHeight());
     tab_switch_button_->set_owned_by_client();
   }
 }
@@ -373,11 +373,6 @@
   return model_->GetMatchIcon(match_, GetColor(OmniboxPart::RESULTS_ICON));
 }
 
-bool OmniboxResultView::ShowOnlyKeywordMatch() const {
-  return match_.associated_keyword &&
-         (keyword_icon_view_->x() <= (icon_view_->x() + icon_view_->width()));
-}
-
 int OmniboxResultView::GetAnswerHeight() const {
   const int horizontal_padding =
       GetLayoutConstant(LOCATION_BAR_PADDING) +
@@ -405,9 +400,16 @@
       omnibox::kUIExperimentVerticalMargin,
       OmniboxFieldTrial::kUIVerticalMarginParam,
       Md::GetMode() == Md::MATERIAL_HYBRID ? 8 : 4);
-  const int min_height =
+  int min_height =
       GetLayoutConstant(LOCATION_BAR_ICON_SIZE) + (kIconVerticalPad * 2);
 
+  if (Md::IsTouchOptimizedUiEnabled()) {
+    // The touchable spec specifies a height of 44 DIP. Ensure that's satisfied.
+    // Answer rows can still exceed this size.
+    constexpr int kTouchOptimizedResultHeight = 44;
+    min_height = std::max(min_height, kTouchOptimizedResultHeight);
+  }
+
   return std::max(kVerticalMargin, (min_height - GetTextHeight()) / 2);
 }
 
@@ -432,18 +434,12 @@
       GetLayoutConstant(LOCATION_BAR_PADDING) +
       GetLayoutConstant(LOCATION_BAR_ICON_INTERIOR_PADDING);
   const int start_x = GetIconAlignmentOffset() + horizontal_padding;
-  int end_x = width() - start_x;
+  int end_x = width();
 
   int text_height = GetTextHeight();
   int row_height = text_height;
   if (IsTwoLineLayout())
     row_height += match_.answer ? GetAnswerHeight() : GetTextHeight();
-
-  const gfx::Image icon = GetIcon();
-  const int icon_y = GetVerticalMargin() + (row_height - icon.Height()) / 2;
-  icon_view_->SetBounds(start_x, icon_y, icon.Width(), icon.Height());
-
-  icon_view_->SetVisible(!ShowOnlyKeywordMatch());
   separator_view_->SetVisible(false);
 
   // TODO(dschuyler): Refactor these if/else's into separate pieces of code to
@@ -452,112 +448,108 @@
   AutocompleteMatch* keyword_match = match_.associated_keyword.get();
   if (keyword_match) {
     // NOTE: While animating the keyword match, both matches may be visible.
-    const int max_kw_x = end_x - keyword_icon_view_->width();
-    int kw_x = animation_->CurrentValueBetween(max_kw_x, start_x);
+    const int icon_width = keyword_icon_view_->width() +
+                           GetIconAlignmentOffset() + horizontal_padding * 2;
+    const int max_kw_x = width() - icon_width;
+    int kw_x = animation_->CurrentValueBetween(max_kw_x, 0);
     end_x = kw_x;
-    int y = GetVerticalMargin();
-    kw_x += BackgroundWith1PxBorder::kLocationBarBorderThicknessDip;
+    kw_x += start_x + BackgroundWith1PxBorder::kLocationBarBorderThicknessDip;
     keyword_icon_view_->SetPosition(
         gfx::Point(kw_x, (height() - keyword_icon_view_->height()) / 2));
     kw_x += keyword_icon_view_->width() + horizontal_padding;
 
-    keyword_content_view_->SizeToPreferredSize();
-    int first_width = keyword_content_view_->GetContentsBounds().width();
-    keyword_description_view_->SizeToPreferredSize();
-    int second_width =
-        keyword_description_view_
-            ? keyword_description_view_->GetContentsBounds().width()
-            : 0;
+    int content_width = keyword_content_view_->CalculatePreferredSize().width();
+    int description_width =
+        keyword_description_view_->CalculatePreferredSize().width();
     OmniboxPopupModel::ComputeMatchMaxWidths(
-        first_width, separator_view_->width(), second_width, width(),
+        content_width, separator_view_->width(), description_width, width(),
         /*description_on_separate_line=*/false,
-        !AutocompleteMatch::IsSearchType(match_.type), &first_width,
-        &second_width);
-    keyword_content_view_->SetBounds(kw_x, y, first_width, text_height);
-    if (second_width != 0) {
+        !AutocompleteMatch::IsSearchType(match_.type), &content_width,
+        &description_width);
+    int y = GetVerticalMargin();
+    keyword_content_view_->SetBounds(kw_x, y, content_width, text_height);
+    if (description_width != 0) {
       kw_x += keyword_content_view_->width();
       separator_view_->SetVisible(true);
       separator_view_->SetBounds(kw_x, y, separator_view_->width(),
                                  text_height);
       kw_x += separator_view_->width();
-      keyword_description_view_->SetBounds(kw_x, y, second_width, text_height);
+      keyword_description_view_->SetBounds(kw_x, y, description_width,
+                                           text_height);
     } else if (IsTwoLineLayout()) {
-      keyword_content_view_->SetSize(gfx::Size(first_width, text_height * 2));
+      keyword_content_view_->SetSize(gfx::Size(content_width, text_height * 2));
     }
   }
 
-  if (tab_switch_button_ && match_.type == AutocompleteMatchType::TAB_SEARCH) {
-    const int ts_button_width = tab_switch_button_->GetPreferredSize().width();
-    const int ts_button_height = height();
-    tab_switch_button_->SetSize(gfx::Size(ts_button_width, ts_button_height));
+  const gfx::Image icon = GetIcon();
+  const int icon_y = GetVerticalMargin() + (row_height - icon.Height()) / 2;
+  icon_view_->SetBounds(start_x, icon_y, std::min(end_x, icon.Width()),
+                        icon.Height());
 
-    const int ts_x = end_x - ts_button_width + horizontal_padding;
-    end_x = ts_x - start_x - horizontal_padding;
-    tab_switch_button_->SetPosition(gfx::Point(ts_x, 0));
+  if (tab_switch_button_ && match_.type == AutocompleteMatchType::TAB_SEARCH) {
+    const gfx::Size ts_button_size = tab_switch_button_->GetPreferredSize();
+    tab_switch_button_->SetSize(ts_button_size);
+
+    // It looks nice to have the same margin on top, bottom and right side.
+    const int margin = (height() - ts_button_size.height()) / 2;
+    end_x -= ts_button_size.width() + margin;
+    tab_switch_button_->SetPosition(gfx::Point(end_x, margin));
   }
 
   // NOTE: While animating the keyword match, both matches may be visible.
-  if (!ShowOnlyKeywordMatch()) {
-    description_view_->SizeToPreferredSize();
-    int x = start_x;
-    x += icon.Width() + horizontal_padding;
-    int y = GetVerticalMargin();
-    if (match_.answer) {
-      content_view_->SetBounds(x, y, end_x - x, text_height);
-      y += text_height;
-      if (image_view_->visible()) {
-        // The description may be multi-line. Using the view height results in
-        // an image that's too large, so we use the line height here instead.
-        int image_edge_length = description_view_->GetLineHeight();
-        image_view_->SetBounds(
-            start_x + icon_view_->width() + horizontal_padding,
-            y + (kVerticalPadding / 2), image_edge_length, image_edge_length);
-        image_view_->SetImageSize(
-            gfx::Size(image_edge_length, image_edge_length));
-        x += image_view_->width() + kAnswerIconToTextPadding;
-      }
+  int x = start_x;
+  x += icon.Width() + horizontal_padding;
+  int y = GetVerticalMargin();
+  if (match_.answer) {
+    content_view_->SetBounds(x, y, end_x - x, text_height);
+    y += text_height;
+    if (image_view_->visible()) {
+      // The description may be multi-line. Using the view height results in
+      // an image that's too large, so we use the line height here instead.
+      int image_edge_length = description_view_->GetLineHeight();
+      image_view_->SetBounds(start_x + icon_view_->width() + horizontal_padding,
+                             y + (kVerticalPadding / 2), image_edge_length,
+                             image_edge_length);
+      image_view_->SetImageSize(
+          gfx::Size(image_edge_length, image_edge_length));
+      x += image_view_->width() + kAnswerIconToTextPadding;
+    }
+    int description_width = end_x - x;
+    description_view_->SetBounds(
+        x, y, description_width,
+        description_view_->GetHeightForWidth(description_width) +
+            kVerticalPadding);
+  } else if (IsTwoLineLayout()) {
+    if (!!description_view_->GetContentsBounds().width()) {
+      // A description is present.
+      content_view_->SetBounds(x, y, end_x - x, GetTextHeight());
+      y += GetTextHeight();
       int description_width = end_x - x;
       description_view_->SetBounds(
           x, y, description_width,
           description_view_->GetHeightForWidth(description_width) +
               kVerticalPadding);
-    } else if (IsTwoLineLayout()) {
-      if (!!description_view_->GetContentsBounds().width()) {
-        // A description is present.
-        content_view_->SetBounds(x, y, end_x - x, GetTextHeight());
-        y += GetTextHeight();
-        int description_width = end_x - x;
-        description_view_->SetBounds(
-            x, y, description_width,
-            description_view_->GetHeightForWidth(description_width) +
-                kVerticalPadding);
-      } else {
-        // For no description, shift down halfway to draw contents in middle.
-        y += GetTextHeight() / 2;
-        content_view_->SetBounds(x, y, end_x - x, GetTextHeight());
-      }
     } else {
-      content_view_->SizeToPreferredSize();
-      int first_width = content_view_->GetContentsBounds().width();
-      int second_width = description_view_
-                             ? description_view_->GetContentsBounds().width()
-                             : 0;
-      OmniboxPopupModel::ComputeMatchMaxWidths(
-          first_width, separator_view_->width(), second_width, end_x - x,
-          /*description_on_separate_line=*/false,
-          !AutocompleteMatch::IsSearchType(match_.type), &first_width,
-          &second_width);
-      OmniboxTextView* first_view = content_view_;
-      OmniboxTextView* second_view = description_view_;
-      first_view->SetBounds(x, y, first_width, text_height);
-      x += first_width;
-      if (second_width) {
-        separator_view_->SetVisible(true);
-        separator_view_->SetBounds(x, y, separator_view_->width(), text_height);
-        x += separator_view_->width();
-      }
-      second_view->SetBounds(x, y, second_width, text_height);
+      // For no description, shift down halfway to draw contents in middle.
+      y += GetTextHeight() / 2;
+      content_view_->SetBounds(x, y, end_x - x, GetTextHeight());
     }
+  } else {
+    int content_width = content_view_->CalculatePreferredSize().width();
+    int description_width = description_view_->CalculatePreferredSize().width();
+    OmniboxPopupModel::ComputeMatchMaxWidths(
+        content_width, separator_view_->width(), description_width, end_x - x,
+        /*description_on_separate_line=*/false,
+        !AutocompleteMatch::IsSearchType(match_.type), &content_width,
+        &description_width);
+    content_view_->SetBounds(x, y, content_width, text_height);
+    x += content_width;
+    if (description_width) {
+      separator_view_->SetVisible(true);
+      separator_view_->SetBounds(x, y, separator_view_->width(), text_height);
+      x += separator_view_->width();
+    }
+    description_view_->SetBounds(x, y, description_width, text_height);
   }
 }
 
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view.h b/chrome/browser/ui/views/omnibox/omnibox_result_view.h
index e0116d63..06134d2 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_result_view.h
+++ b/chrome/browser/ui/views/omnibox/omnibox_result_view.h
@@ -89,11 +89,6 @@
 
   gfx::Image GetIcon() const;
 
-  // Whether to render only the keyword match.  Returns true if |match_| has an
-  // associated keyword match that has been animated so close to the start that
-  // the keyword match will hide even the icon of the regular match.
-  bool ShowOnlyKeywordMatch() const;
-
   // Returns the height of the the description section of answer suggestions.
   int GetAnswerHeight() const;
 
diff --git a/chrome/browser/ui/views/omnibox/omnibox_tab_switch_button.cc b/chrome/browser/ui/views/omnibox/omnibox_tab_switch_button.cc
index 07349c5..d3dbeee 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_tab_switch_button.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_tab_switch_button.cc
@@ -13,21 +13,23 @@
 #include "ui/gfx/color_utils.h"
 #include "ui/gfx/paint_vector_icon.h"
 
-OmniboxTabSwitchButton::OmniboxTabSwitchButton(OmniboxResultView* result_view)
+OmniboxTabSwitchButton::OmniboxTabSwitchButton(OmniboxResultView* result_view,
+                                               int text_height)
     : MdTextButton(this, views::style::CONTEXT_BUTTON_MD),
+      text_height_(text_height),
       result_view_(result_view) {
   // TODO: SetTooltipText(text);
   //       SetImageAlignment(ALIGN_CENTER, ALIGN_MIDDLE);
-  SetBackground(std::make_unique<BackgroundWith1PxBorder>(GetBackgroundColor(),
-                                                          SK_ColorBLACK));
   SetBgColorOverride(GetBackgroundColor());
   SetImage(STATE_NORMAL,
            gfx::CreateVectorIcon(omnibox::kSwitchIcon, 16, SK_ColorBLACK));
   SetText(base::ASCIIToUTF16("Switch to open tab"));
+  set_corner_radius(CalculatePreferredSize().height() / 2.f);
 }
 
 gfx::Size OmniboxTabSwitchButton::CalculatePreferredSize() const {
   gfx::Size size = MdTextButton::CalculatePreferredSize();
+  size.set_height(text_height_ + kVerticalPadding);
   const int horizontal_padding =
       GetLayoutConstant(LOCATION_BAR_PADDING) +
       GetLayoutConstant(LOCATION_BAR_ICON_INTERIOR_PADDING);
diff --git a/chrome/browser/ui/views/omnibox/omnibox_tab_switch_button.h b/chrome/browser/ui/views/omnibox/omnibox_tab_switch_button.h
index b008e1d..2116ee0 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_tab_switch_button.h
+++ b/chrome/browser/ui/views/omnibox/omnibox_tab_switch_button.h
@@ -12,7 +12,7 @@
 class OmniboxTabSwitchButton : public views::MdTextButton,
                                public views::ButtonListener {
  public:
-  explicit OmniboxTabSwitchButton(OmniboxResultView* result_view);
+  OmniboxTabSwitchButton(OmniboxResultView* result_view, int text_height);
 
   // views::View
   gfx::Size CalculatePreferredSize() const override;
@@ -24,12 +24,18 @@
   void StateChanged(ButtonState old_state) override;
 
  private:
+  // Encapsulates the color look-up, which uses the button state (hovered,
+  // etc.) and consults the parent result view.
   SkColor GetBackgroundColor() const;
 
-  OmniboxResultView* result_view_;
-
+  // Encapsulates changing the color of the button to display being
+  // pressed.
   void SetPressed();
 
+  static constexpr int kVerticalPadding = 2;
+  const int text_height_;
+  OmniboxResultView* result_view_;
+
   DISALLOW_COPY_AND_ASSIGN(OmniboxTabSwitchButton);
 };
 
diff --git a/chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.cc b/chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.cc
index 5526e5b..a4845ad1 100644
--- a/chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.cc
+++ b/chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.cc
@@ -10,6 +10,7 @@
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/location_bar/background_with_1_px_border.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
+#include "ui/base/material_design/material_design_controller.h"
 #include "ui/compositor/layer.h"
 #include "ui/views/painter.h"
 
@@ -41,19 +42,6 @@
   }
 };
 
-class SeparatorView : public views::View {
- public:
-  explicit SeparatorView(SkColor color) : color_(color) {}
-
-  // Views:View:
-  void OnPaint(gfx::Canvas* canvas) override {
-    BrowserView::Paint1pxHorizontalLine(canvas, color_, GetLocalBounds(), true);
-  }
-
- private:
-  const SkColor color_;
-};
-
 // Insets used to position |contents_| within |contents_host_|.
 gfx::Insets GetContentInsets(views::View* location_bar) {
   return gfx::Insets(
@@ -71,7 +59,6 @@
     LocationBarView* location_bar)
     : content_insets_(GetContentInsets(location_bar)),
       location_bar_height_(location_bar->height()),
-      separator_inset_(location_bar->GetTextInsetForNormalInputStart()),
       contents_(contents) {
   // Host the contents in its own View to simplify layout and clipping.
   contents_host_ = new views::View();
@@ -95,10 +82,7 @@
   contents_host_->layer()->SetMaskLayer(contents_mask_->layer());
 
   top_background_ = new TopBackgroundView(background_color);
-  separator_ = new SeparatorView(
-      GetOmniboxColor(OmniboxPart::RESULTS_SEPARATOR, location_bar->tint()));
   contents_host_->AddChildView(top_background_);
-  contents_host_->AddChildView(separator_);
   contents_host_->AddChildView(contents_);
 
   AddChildView(contents_host_);
@@ -143,11 +127,6 @@
   top_bounds.set_height(location_bar_height_);
   top_background_->SetBoundsRect(top_bounds);
 
-  top_bounds.set_y(top_bounds.bottom());  // Shift down.
-  top_bounds.Inset(separator_inset_, 0);  // Inset the width further.
-  top_bounds.set_height(kSeparatorViewHeightDIP);
-  separator_->SetBoundsRect(top_bounds);
-
   gfx::Rect results_bounds = gfx::Rect(bounds.size());
   results_bounds.Inset(content_insets_);
   contents_->SetBoundsRect(results_bounds);
diff --git a/chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.h b/chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.h
index fd3f5df..42b92fc 100644
--- a/chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.h
+++ b/chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.h
@@ -40,12 +40,10 @@
   // Fixed layout constants.
   const gfx::Insets content_insets_;
   const int location_bar_height_;
-  const int separator_inset_;
 
   std::unique_ptr<ui::LayerOwner> contents_mask_;
 
   views::View* top_background_ = nullptr;
-  views::View* separator_ = nullptr;
   views::View* contents_ = nullptr;
   views::View* contents_host_ = nullptr;
 
diff --git a/chrome/browser/ui/views/settings_reset_prompt_dialog.cc b/chrome/browser/ui/views/settings_reset_prompt_dialog.cc
index e2a4b94..fd93370c 100644
--- a/chrome/browser/ui/views/settings_reset_prompt_dialog.cc
+++ b/chrome/browser/ui/views/settings_reset_prompt_dialog.cc
@@ -44,8 +44,9 @@
   views::StyledLabel* dialog_label =
       new views::StyledLabel(controller_->GetMainText(), /*listener=*/nullptr);
   dialog_label->SetTextContext(CONTEXT_BODY_TEXT_LARGE);
+  dialog_label->SetDefaultTextStyle(STYLE_SECONDARY);
   views::StyledLabel::RangeStyleInfo url_style;
-  url_style.text_style = STYLE_EMPHASIZED;
+  url_style.text_style = STYLE_EMPHASIZED_SECONDARY;
   dialog_label->AddStyleRange(controller_->GetMainTextUrlRange(), url_style);
   AddChildView(dialog_label);
 }
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc
index 58099be3..dbfa074 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -93,7 +93,7 @@
   // button starts from the beginning of the view, and the app menu button ends
   // at the end of the view.
   using Md = ui::MaterialDesignController;
-  constexpr int kPaddings[] = {4, 8, 0};
+  constexpr int kPaddings[] = {4, 8, 0, 4};
   return kPaddings[Md::GetMode()];
 }
 
diff --git a/chrome/browser/ui/webui/app_launcher_login_handler.cc b/chrome/browser/ui/webui/app_launcher_login_handler.cc
index b7ea9d7..30364d9 100644
--- a/chrome/browser/ui/webui/app_launcher_login_handler.cc
+++ b/chrome/browser/ui/webui/app_launcher_login_handler.cc
@@ -94,18 +94,22 @@
       base::Bind(&AppLauncherLoginHandler::UpdateLogin,
                  base::Unretained(this))));
 
-  web_ui()->RegisterMessageCallback("initializeSyncLogin",
-      base::Bind(&AppLauncherLoginHandler::HandleInitializeSyncLogin,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("showSyncLoginUI",
-      base::Bind(&AppLauncherLoginHandler::HandleShowSyncLoginUI,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("loginMessageSeen",
-      base::Bind(&AppLauncherLoginHandler::HandleLoginMessageSeen,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("showAdvancedLoginUI",
-      base::Bind(&AppLauncherLoginHandler::HandleShowAdvancedLoginUI,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "initializeSyncLogin",
+      base::BindRepeating(&AppLauncherLoginHandler::HandleInitializeSyncLogin,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "showSyncLoginUI",
+      base::BindRepeating(&AppLauncherLoginHandler::HandleShowSyncLoginUI,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "loginMessageSeen",
+      base::BindRepeating(&AppLauncherLoginHandler::HandleLoginMessageSeen,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "showAdvancedLoginUI",
+      base::BindRepeating(&AppLauncherLoginHandler::HandleShowAdvancedLoginUI,
+                          base::Unretained(this)));
 }
 
 void AppLauncherLoginHandler::HandleInitializeSyncLogin(
diff --git a/chrome/browser/ui/webui/browsing_history_handler.cc b/chrome/browser/ui/webui/browsing_history_handler.cc
index 2e4edbc..4b54248 100644
--- a/chrome/browser/ui/webui/browsing_history_handler.cc
+++ b/chrome/browser/ui/webui/browsing_history_handler.cc
@@ -247,22 +247,27 @@
   // Create our favicon data source.
   content::URLDataSource::Add(profile, new FaviconSource(profile));
 
-  web_ui()->RegisterMessageCallback("queryHistory",
-      base::Bind(&BrowsingHistoryHandler::HandleQueryHistory,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "queryHistory",
+      base::BindRepeating(&BrowsingHistoryHandler::HandleQueryHistory,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "queryHistoryContinuation",
-      base::Bind(&BrowsingHistoryHandler::HandleQueryHistoryContinuation,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("removeVisits",
-      base::Bind(&BrowsingHistoryHandler::HandleRemoveVisits,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("clearBrowsingData",
-      base::Bind(&BrowsingHistoryHandler::HandleClearBrowsingData,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("removeBookmark",
-      base::Bind(&BrowsingHistoryHandler::HandleRemoveBookmark,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &BrowsingHistoryHandler::HandleQueryHistoryContinuation,
+          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "removeVisits",
+      base::BindRepeating(&BrowsingHistoryHandler::HandleRemoveVisits,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "clearBrowsingData",
+      base::BindRepeating(&BrowsingHistoryHandler::HandleClearBrowsingData,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "removeBookmark",
+      base::BindRepeating(&BrowsingHistoryHandler::HandleRemoveBookmark,
+                          base::Unretained(this)));
 }
 
 void BrowsingHistoryHandler::HandleQueryHistory(const base::ListValue* args) {
diff --git a/chrome/browser/ui/webui/certificate_viewer_webui.cc b/chrome/browser/ui/webui/certificate_viewer_webui.cc
index 969c9bd..156ffb8 100644
--- a/chrome/browser/ui/webui/certificate_viewer_webui.cc
+++ b/chrome/browser/ui/webui/certificate_viewer_webui.cc
@@ -345,12 +345,15 @@
 }
 
 void CertificateViewerDialogHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback("exportCertificate",
-      base::Bind(&CertificateViewerDialogHandler::ExportCertificate,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("requestCertificateFields",
-      base::Bind(&CertificateViewerDialogHandler::RequestCertificateFields,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "exportCertificate",
+      base::BindRepeating(&CertificateViewerDialogHandler::ExportCertificate,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "requestCertificateFields",
+      base::BindRepeating(
+          &CertificateViewerDialogHandler::RequestCertificateFields,
+          base::Unretained(this)));
 }
 
 void CertificateViewerDialogHandler::ExportCertificate(
diff --git a/chrome/browser/ui/webui/certificates_handler.cc b/chrome/browser/ui/webui/certificates_handler.cc
index 854bbb0..53fafce 100644
--- a/chrome/browser/ui/webui/certificates_handler.cc
+++ b/chrome/browser/ui/webui/certificates_handler.cc
@@ -345,68 +345,72 @@
 
 void CertificatesHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
-      "viewCertificate", base::Bind(&CertificatesHandler::HandleViewCertificate,
-                                    base::Unretained(this)));
+      "viewCertificate",
+      base::BindRepeating(&CertificatesHandler::HandleViewCertificate,
+                          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       "getCaCertificateTrust",
-      base::Bind(&CertificatesHandler::HandleGetCATrust,
-                 base::Unretained(this)));
+      base::BindRepeating(&CertificatesHandler::HandleGetCATrust,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "editCaCertificateTrust",
-      base::Bind(&CertificatesHandler::HandleEditCATrust,
-                 base::Unretained(this)));
+      base::BindRepeating(&CertificatesHandler::HandleEditCATrust,
+                          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       "cancelImportExportCertificate",
-      base::Bind(&CertificatesHandler::HandleCancelImportExportProcess,
-                 base::Unretained(this)));
+      base::BindRepeating(&CertificatesHandler::HandleCancelImportExportProcess,
+                          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       "exportPersonalCertificate",
-      base::Bind(&CertificatesHandler::HandleExportPersonal,
-                 base::Unretained(this)));
+      base::BindRepeating(&CertificatesHandler::HandleExportPersonal,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "exportPersonalCertificatePasswordSelected",
-      base::Bind(&CertificatesHandler::HandleExportPersonalPasswordSelected,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &CertificatesHandler::HandleExportPersonalPasswordSelected,
+          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       "importPersonalCertificate",
-      base::Bind(&CertificatesHandler::HandleImportPersonal,
-                 base::Unretained(this)));
+      base::BindRepeating(&CertificatesHandler::HandleImportPersonal,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "importPersonalCertificatePasswordSelected",
-      base::Bind(&CertificatesHandler::HandleImportPersonalPasswordSelected,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &CertificatesHandler::HandleImportPersonalPasswordSelected,
+          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       "importCaCertificate",
-      base::Bind(&CertificatesHandler::HandleImportCA, base::Unretained(this)));
+      base::BindRepeating(&CertificatesHandler::HandleImportCA,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "importCaCertificateTrustSelected",
-      base::Bind(&CertificatesHandler::HandleImportCATrustSelected,
-                 base::Unretained(this)));
+      base::BindRepeating(&CertificatesHandler::HandleImportCATrustSelected,
+                          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       "importServerCertificate",
-      base::Bind(&CertificatesHandler::HandleImportServer,
-                 base::Unretained(this)));
+      base::BindRepeating(&CertificatesHandler::HandleImportServer,
+                          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       "exportCertificate",
-      base::Bind(&CertificatesHandler::HandleExportCertificate,
-                 base::Unretained(this)));
+      base::BindRepeating(&CertificatesHandler::HandleExportCertificate,
+                          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       "deleteCertificate",
-      base::Bind(&CertificatesHandler::HandleDeleteCertificate,
-                 base::Unretained(this)));
+      base::BindRepeating(&CertificatesHandler::HandleDeleteCertificate,
+                          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       "refreshCertificates",
-      base::Bind(&CertificatesHandler::HandleRefreshCertificates,
-                 base::Unretained(this)));
+      base::BindRepeating(&CertificatesHandler::HandleRefreshCertificates,
+                          base::Unretained(this)));
 }
 
 void CertificatesHandler::CertificatesRefreshed() {
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
index aa94ebd..85f85590 100644
--- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
+++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -89,7 +89,7 @@
 #include "content/public/common/content_client.h"
 #include "content/public/common/url_utils.h"
 #include "extensions/buildflags/buildflags.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "ppapi/features/features.h"
 #include "printing/features/features.h"
 #include "ui/gfx/favicon_size.h"
@@ -147,6 +147,7 @@
 #include "chrome/browser/ui/webui/chromeos/keyboard_overlay_ui.h"
 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
 #include "chrome/browser/ui/webui/chromeos/mobile_setup_ui.h"
+#include "chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_dialog.h"
 #include "chrome/browser/ui/webui/chromeos/network_ui.h"
 #include "chrome/browser/ui/webui/chromeos/power_ui.h"
 #include "chrome/browser/ui/webui/chromeos/set_time_ui.h"
@@ -448,6 +449,8 @@
     return &NewWebUI<KeyboardOverlayUI>;
   if (url.host_piece() == chrome::kChromeUIMobileSetupHost)
     return &NewWebUI<MobileSetupUI>;
+  if (url.host_piece() == chrome::kChromeUIMultiDeviceSetupHost)
+    return &NewWebUI<chromeos::multidevice_setup::MultiDeviceSetupDialogUI>;
   if (url.host_piece() == chrome::kChromeUINetworkHost)
     return &NewWebUI<chromeos::NetworkUI>;
   if (url.host_piece() == chrome::kChromeUIOobeHost)
diff --git a/chrome/browser/ui/webui/chromeos/cryptohome_web_ui_handler.cc b/chrome/browser/ui/webui/chromeos/cryptohome_web_ui_handler.cc
index 007928a7..40d8a1a 100644
--- a/chrome/browser/ui/webui/chromeos/cryptohome_web_ui_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/cryptohome_web_ui_handler.cc
@@ -22,9 +22,8 @@
 
 void CryptohomeWebUIHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
-      "pageLoaded",
-      base::Bind(&CryptohomeWebUIHandler::OnPageLoaded,
-                 weak_ptr_factory_.GetWeakPtr()));
+      "pageLoaded", base::BindRepeating(&CryptohomeWebUIHandler::OnPageLoaded,
+                                        weak_ptr_factory_.GetWeakPtr()));
 }
 
 void CryptohomeWebUIHandler::OnPageLoaded(const base::ListValue* args) {
diff --git a/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc b/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc
index 5ee6b3b..2000125 100644
--- a/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc
@@ -375,28 +375,28 @@
 void DriveInternalsWebUIHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "pageLoaded",
-      base::Bind(&DriveInternalsWebUIHandler::OnPageLoaded,
-                 weak_ptr_factory_.GetWeakPtr()));
+      base::BindRepeating(&DriveInternalsWebUIHandler::OnPageLoaded,
+                          weak_ptr_factory_.GetWeakPtr()));
   web_ui()->RegisterMessageCallback(
       "periodicUpdate",
-      base::Bind(&DriveInternalsWebUIHandler::OnPeriodicUpdate,
-                 weak_ptr_factory_.GetWeakPtr()));
+      base::BindRepeating(&DriveInternalsWebUIHandler::OnPeriodicUpdate,
+                          weak_ptr_factory_.GetWeakPtr()));
   web_ui()->RegisterMessageCallback(
       "clearAccessToken",
-      base::Bind(&DriveInternalsWebUIHandler::ClearAccessToken,
-                 weak_ptr_factory_.GetWeakPtr()));
+      base::BindRepeating(&DriveInternalsWebUIHandler::ClearAccessToken,
+                          weak_ptr_factory_.GetWeakPtr()));
   web_ui()->RegisterMessageCallback(
       "clearRefreshToken",
-      base::Bind(&DriveInternalsWebUIHandler::ClearRefreshToken,
-                 weak_ptr_factory_.GetWeakPtr()));
+      base::BindRepeating(&DriveInternalsWebUIHandler::ClearRefreshToken,
+                          weak_ptr_factory_.GetWeakPtr()));
   web_ui()->RegisterMessageCallback(
       "resetDriveFileSystem",
-      base::Bind(&DriveInternalsWebUIHandler::ResetDriveFileSystem,
-                 weak_ptr_factory_.GetWeakPtr()));
+      base::BindRepeating(&DriveInternalsWebUIHandler::ResetDriveFileSystem,
+                          weak_ptr_factory_.GetWeakPtr()));
   web_ui()->RegisterMessageCallback(
       "listFileEntries",
-      base::Bind(&DriveInternalsWebUIHandler::ListFileEntries,
-                 weak_ptr_factory_.GetWeakPtr()));
+      base::BindRepeating(&DriveInternalsWebUIHandler::ListFileEntries,
+                          weak_ptr_factory_.GetWeakPtr()));
 }
 
 drive::DriveIntegrationService*
diff --git a/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.cc b/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.cc
index cc3b48bb..7255016 100644
--- a/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.cc
@@ -476,72 +476,77 @@
 
 void DeviceEmulatorMessageHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
-      kInitialize,
-      base::Bind(&DeviceEmulatorMessageHandler::Init, base::Unretained(this)));
+      kInitialize, base::BindRepeating(&DeviceEmulatorMessageHandler::Init,
+                                       base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kRequestPowerInfo,
-      base::Bind(&DeviceEmulatorMessageHandler::RequestPowerInfo,
-                 base::Unretained(this)));
+      base::BindRepeating(&DeviceEmulatorMessageHandler::RequestPowerInfo,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kUpdateBatteryPercent,
-      base::Bind(&DeviceEmulatorMessageHandler::UpdateBatteryPercent,
-                 base::Unretained(this)));
+      base::BindRepeating(&DeviceEmulatorMessageHandler::UpdateBatteryPercent,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kUpdateBatteryState,
-      base::Bind(&DeviceEmulatorMessageHandler::UpdateBatteryState,
-                 base::Unretained(this)));
+      base::BindRepeating(&DeviceEmulatorMessageHandler::UpdateBatteryState,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kUpdateTimeToEmpty,
-      base::Bind(&DeviceEmulatorMessageHandler::UpdateTimeToEmpty,
-                 base::Unretained(this)));
+      base::BindRepeating(&DeviceEmulatorMessageHandler::UpdateTimeToEmpty,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kUpdateTimeToFull,
-      base::Bind(&DeviceEmulatorMessageHandler::UpdateTimeToFull,
-                 base::Unretained(this)));
+      base::BindRepeating(&DeviceEmulatorMessageHandler::UpdateTimeToFull,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kUpdatePowerSources,
-      base::Bind(&DeviceEmulatorMessageHandler::UpdatePowerSources,
-                 base::Unretained(this)));
+      base::BindRepeating(&DeviceEmulatorMessageHandler::UpdatePowerSources,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kUpdatePowerSourceId,
-      base::Bind(&DeviceEmulatorMessageHandler::UpdatePowerSourceId,
-                 base::Unretained(this)));
+      base::BindRepeating(&DeviceEmulatorMessageHandler::UpdatePowerSourceId,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kRequestAudioNodes,
-      base::Bind(&DeviceEmulatorMessageHandler::HandleRequestAudioNodes,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &DeviceEmulatorMessageHandler::HandleRequestAudioNodes,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kInsertAudioNode,
-      base::Bind(&DeviceEmulatorMessageHandler::HandleInsertAudioNode,
-                 base::Unretained(this)));
+      base::BindRepeating(&DeviceEmulatorMessageHandler::HandleInsertAudioNode,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kRemoveAudioNode,
-      base::Bind(&DeviceEmulatorMessageHandler::HandleRemoveAudioNode,
-                 base::Unretained(this)));
+      base::BindRepeating(&DeviceEmulatorMessageHandler::HandleRemoveAudioNode,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kBluetoothDiscoverFunction,
-      base::Bind(&DeviceEmulatorMessageHandler::HandleRequestBluetoothDiscover,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &DeviceEmulatorMessageHandler::HandleRequestBluetoothDiscover,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kBluetoothPairFunction,
-      base::Bind(&DeviceEmulatorMessageHandler::HandleRequestBluetoothPair,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &DeviceEmulatorMessageHandler::HandleRequestBluetoothPair,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kRequestBluetoothInfo,
-      base::Bind(&DeviceEmulatorMessageHandler::HandleRequestBluetoothInfo,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &DeviceEmulatorMessageHandler::HandleRequestBluetoothInfo,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kRemoveBluetoothDevice,
-      base::Bind(&DeviceEmulatorMessageHandler::HandleRemoveBluetoothDevice,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &DeviceEmulatorMessageHandler::HandleRemoveBluetoothDevice,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kSetHasTouchpad,
-      base::Bind(&DeviceEmulatorMessageHandler::HandleSetHasTouchpad,
-                 base::Unretained(this)));
+      base::BindRepeating(&DeviceEmulatorMessageHandler::HandleSetHasTouchpad,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kSetHasMouse,
-      base::Bind(&DeviceEmulatorMessageHandler::HandleSetHasMouse,
-                 base::Unretained(this)));
+      base::BindRepeating(&DeviceEmulatorMessageHandler::HandleSetHasMouse,
+                          base::Unretained(this)));
 }
 
 void DeviceEmulatorMessageHandler::OnJavascriptAllowed() {
diff --git a/chrome/browser/ui/webui/chromeos/first_run/first_run_handler.cc b/chrome/browser/ui/webui/chromeos/first_run/first_run_handler.cc
index 312a705..ca8d66242 100644
--- a/chrome/browser/ui/webui/chromeos/first_run/first_run_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/first_run/first_run_handler.cc
@@ -88,23 +88,26 @@
 }
 
 void FirstRunHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback("initialized",
-      base::Bind(&FirstRunHandler::HandleInitialized, base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("nextButtonClicked",
-      base::Bind(&FirstRunHandler::HandleNextButtonClicked,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("helpButtonClicked",
-      base::Bind(&FirstRunHandler::HandleHelpButtonClicked,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("stepShown",
-      base::Bind(&FirstRunHandler::HandleStepShown,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("stepHidden",
-      base::Bind(&FirstRunHandler::HandleStepHidden,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("finalized",
-      base::Bind(&FirstRunHandler::HandleFinalized,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "initialized", base::BindRepeating(&FirstRunHandler::HandleInitialized,
+                                         base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "nextButtonClicked",
+      base::BindRepeating(&FirstRunHandler::HandleNextButtonClicked,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "helpButtonClicked",
+      base::BindRepeating(&FirstRunHandler::HandleHelpButtonClicked,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "stepShown", base::BindRepeating(&FirstRunHandler::HandleStepShown,
+                                       base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "stepHidden", base::BindRepeating(&FirstRunHandler::HandleStepHidden,
+                                        base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "finalized", base::BindRepeating(&FirstRunHandler::HandleFinalized,
+                                       base::Unretained(this)));
 }
 
 void FirstRunHandler::HandleInitialized(const base::ListValue* args) {
diff --git a/chrome/browser/ui/webui/chromeos/keyboard_overlay_ui.cc b/chrome/browser/ui/webui/chromeos/keyboard_overlay_ui.cc
index d9eb887..c197c33 100644
--- a/chrome/browser/ui/webui/chromeos/keyboard_overlay_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/keyboard_overlay_ui.cc
@@ -393,15 +393,17 @@
 }
 
 void KeyboardOverlayHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback("getInputMethodId",
-      base::Bind(&KeyboardOverlayHandler::GetInputMethodId,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("getLabelMap",
-      base::Bind(&KeyboardOverlayHandler::GetLabelMap,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("openLearnMorePage",
-      base::Bind(&KeyboardOverlayHandler::OpenLearnMorePage,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "getInputMethodId",
+      base::BindRepeating(&KeyboardOverlayHandler::GetInputMethodId,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "getLabelMap", base::BindRepeating(&KeyboardOverlayHandler::GetLabelMap,
+                                         base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "openLearnMorePage",
+      base::BindRepeating(&KeyboardOverlayHandler::OpenLearnMorePage,
+                          base::Unretained(this)));
 }
 
 void KeyboardOverlayHandler::GetInputMethodId(const base::ListValue* args) {
diff --git a/chrome/browser/ui/webui/chromeos/keyboard_overlay_ui_browsertest.cc b/chrome/browser/ui/webui/chromeos/keyboard_overlay_ui_browsertest.cc
index 1e0bc93e..2deea081 100644
--- a/chrome/browser/ui/webui/chromeos/keyboard_overlay_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/chromeos/keyboard_overlay_ui_browsertest.cc
@@ -23,8 +23,9 @@
   // content::WebUIMessageHandler:
   void RegisterMessages() override {
     web_ui()->RegisterMessageCallback(
-        "didPaint", base::Bind(&TestWebUIMessageHandler::HandleDidPaint,
-                               base::Unretained(this)));
+        "didPaint",
+        base::BindRepeating(&TestWebUIMessageHandler::HandleDidPaint,
+                            base::Unretained(this)));
   }
 
  private:
diff --git a/chrome/browser/ui/webui/chromeos/login/base_webui_handler.h b/chrome/browser/ui/webui/chromeos/login/base_webui_handler.h
index 3d959a7510..37835bc 100644
--- a/chrome/browser/ui/webui/chromeos/login/base_webui_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/base_webui_handler.h
@@ -185,15 +185,17 @@
   void AddRawCallback(const std::string& name,
                       void (T::*method)(const base::ListValue* args)) {
     web_ui()->RegisterMessageCallback(
-        name, base::Bind(method, base::Unretained(static_cast<T*>(this))));
+        name,
+        base::BindRepeating(method, base::Unretained(static_cast<T*>(this))));
   }
 
   template <typename T, typename... Args>
   void AddCallback(const std::string& name, void (T::*method)(Args...)) {
-    base::Callback<void(Args...)> callback =
+    base::RepeatingCallback<void(Args...)> callback =
         base::Bind(method, base::Unretained(static_cast<T*>(this)));
     web_ui()->RegisterMessageCallback(
-        name, base::Bind(&::login::CallbackWrapper<Args...>, callback));
+        name,
+        base::BindRepeating(&::login::CallbackWrapper<Args...>, callback));
   }
 
   template <typename Method>
diff --git a/chrome/browser/ui/webui/chromeos/login/kiosk_app_menu_handler.cc b/chrome/browser/ui/webui/chromeos/login/kiosk_app_menu_handler.cc
index 1ea6854..c490f95 100644
--- a/chrome/browser/ui/webui/chromeos/login/kiosk_app_menu_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/kiosk_app_menu_handler.cc
@@ -77,15 +77,18 @@
 }
 
 void KioskAppMenuHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback("initializeKioskApps",
-      base::Bind(&KioskAppMenuHandler::HandleInitializeKioskApps,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("kioskAppsLoaded",
-      base::Bind(&KioskAppMenuHandler::HandleKioskAppsLoaded,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("checkKioskAppLaunchError",
-      base::Bind(&KioskAppMenuHandler::HandleCheckKioskAppLaunchError,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "initializeKioskApps",
+      base::BindRepeating(&KioskAppMenuHandler::HandleInitializeKioskApps,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "kioskAppsLoaded",
+      base::BindRepeating(&KioskAppMenuHandler::HandleKioskAppsLoaded,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "checkKioskAppLaunchError",
+      base::BindRepeating(&KioskAppMenuHandler::HandleCheckKioskAppLaunchError,
+                          base::Unretained(this)));
 }
 
 // static
diff --git a/chrome/browser/ui/webui/chromeos/mobile_setup_ui.cc b/chrome/browser/ui/webui/chromeos/mobile_setup_ui.cc
index 69d43646..8c0b5f0 100644
--- a/chrome/browser/ui/webui/chromeos/mobile_setup_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/mobile_setup_ui.cc
@@ -426,18 +426,22 @@
 }
 
 void MobileSetupHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback(kJsApiStartActivation,
-      base::Bind(&MobileSetupHandler::HandleStartActivation,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback(kJsApiSetTransactionStatus,
-      base::Bind(&MobileSetupHandler::HandleSetTransactionStatus,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback(kJsApiPaymentPortalLoad,
-      base::Bind(&MobileSetupHandler::HandlePaymentPortalLoad,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback(kJsGetDeviceInfo,
-      base::Bind(&MobileSetupHandler::HandleGetDeviceInfo,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      kJsApiStartActivation,
+      base::BindRepeating(&MobileSetupHandler::HandleStartActivation,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      kJsApiSetTransactionStatus,
+      base::BindRepeating(&MobileSetupHandler::HandleSetTransactionStatus,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      kJsApiPaymentPortalLoad,
+      base::BindRepeating(&MobileSetupHandler::HandlePaymentPortalLoad,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      kJsGetDeviceInfo,
+      base::BindRepeating(&MobileSetupHandler::HandleGetDeviceInfo,
+                          base::Unretained(this)));
 }
 
 void MobileSetupHandler::HandleStartActivation(const base::ListValue* args) {
diff --git a/chrome/browser/ui/webui/chromeos/multidevice_setup/OWNERS b/chrome/browser/ui/webui/chromeos/multidevice_setup/OWNERS
new file mode 100644
index 0000000..aef4ecb
--- /dev/null
+++ b/chrome/browser/ui/webui/chromeos/multidevice_setup/OWNERS
@@ -0,0 +1 @@
+file://chromeos/services/multidevice_setup/OWNERS
diff --git a/chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_dialog.cc b/chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_dialog.cc
new file mode 100644
index 0000000..bf9bf597
--- /dev/null
+++ b/chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_dialog.cc
@@ -0,0 +1,101 @@
+// Copyright 2018 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/webui/chromeos/multidevice_setup/multidevice_setup_dialog.h"
+
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/webui_url_constants.h"
+#include "chrome/grit/generated_resources.h"
+#include "chrome/grit/multidevice_setup_resources.h"
+#include "chrome/grit/multidevice_setup_resources_map.h"
+#include "components/strings/grit/components_strings.h"
+#include "content/public/browser/web_ui.h"
+#include "content/public/browser/web_ui_data_source.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace chromeos {
+
+namespace multidevice_setup {
+
+namespace {
+
+constexpr int kDialogHeightPx = 640;
+constexpr int kDialogWidthPx = 768;
+
+void AddMultiDeviceSetupStrings(content::WebUIDataSource* html_source) {
+  // TODO(jordynass): Add translations for other strings appearing in the
+  // dialog by adding new name/translation pairs to |kLocalizedStrings| below.
+  // String definitions belong in //chrome/app/chromeos_strings.grdp.
+  static constexpr struct {
+    const char* name;
+    int id;
+  } kLocalizedStrings[] = {
+      {"title", IDS_MULTIDEVICE_SETUP_DIALOG_TITLE}, {"cancel", IDS_CANCEL},
+  };
+
+  for (const auto& entry : kLocalizedStrings)
+    html_source->AddLocalizedString(entry.name, entry.id);
+}
+
+}  // namespace
+
+// static
+MultiDeviceSetupDialog* MultiDeviceSetupDialog::current_instance_ = nullptr;
+
+// static
+void MultiDeviceSetupDialog::Show() {
+  // The dialog is already showing, so there is nothing to do.
+  if (current_instance_)
+    return;
+
+  current_instance_ = new MultiDeviceSetupDialog();
+  current_instance_->ShowSystemDialog();
+}
+
+MultiDeviceSetupDialog::MultiDeviceSetupDialog()
+    : SystemWebDialogDelegate(
+          GURL(chrome::kChromeUIMultiDeviceSetupUrl),
+          l10n_util::GetStringUTF16(IDS_MULTIDEVICE_SETUP_DIALOG_TITLE)) {}
+
+MultiDeviceSetupDialog::~MultiDeviceSetupDialog() = default;
+
+void MultiDeviceSetupDialog::GetDialogSize(gfx::Size* size) const {
+  size->SetSize(kDialogWidthPx, kDialogHeightPx);
+}
+
+void MultiDeviceSetupDialog::OnDialogClosed(const std::string& json_retval) {
+  DCHECK(this == current_instance_);
+  current_instance_ = nullptr;
+
+  // Note: The call below deletes |this|, so there is no further need to keep
+  // track of the pointer.
+  SystemWebDialogDelegate::OnDialogClosed(json_retval);
+}
+
+MultiDeviceSetupDialogUI::MultiDeviceSetupDialogUI(content::WebUI* web_ui)
+    : ui::WebDialogUI(web_ui) {
+  content::WebUIDataSource* source =
+      content::WebUIDataSource::Create(chrome::kChromeUIMultiDeviceSetupHost);
+
+  AddMultiDeviceSetupStrings(source);
+  source->SetJsonPath("strings.js");
+  source->SetDefaultResource(
+      IDR_MULTIDEVICE_SETUP_MULTIDEVICE_SETUP_DIALOG_HTML);
+
+  // Note: The |kMultiDeviceSetupResourcesSize| and |kMultideviceSetupResources|
+  // fields are defined in the generated file
+  // chrome/grit/multidevice_setup_resources_map.h.
+  for (size_t i = 0; i < kMultideviceSetupResourcesSize; ++i) {
+    source->AddResourcePath(kMultideviceSetupResources[i].name,
+                            kMultideviceSetupResources[i].value);
+  }
+
+  content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), source);
+}
+
+MultiDeviceSetupDialogUI::~MultiDeviceSetupDialogUI() = default;
+
+}  // namespace multidevice_setup
+
+}  // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_dialog.h b/chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_dialog.h
new file mode 100644
index 0000000..66433f0
--- /dev/null
+++ b/chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_dialog.h
@@ -0,0 +1,54 @@
+// Copyright 2018 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_UI_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_MULTIDEVICE_SETUP_DIALOG_H_
+#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_MULTIDEVICE_SETUP_DIALOG_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.h"
+#include "ui/web_dialogs/web_dialog_ui.h"
+
+namespace chromeos {
+
+namespace multidevice_setup {
+
+// Dialog which displays the multi-device setup flow which allows users to
+// enable features involving communication between multiple devices (e.g., a
+// Chromebook and a phone).
+class MultiDeviceSetupDialog : public SystemWebDialogDelegate {
+ public:
+  // Shows the dialog; if the dialog is already displayed, this function is a
+  // no-op.
+  static void Show();
+
+ protected:
+  MultiDeviceSetupDialog();
+  ~MultiDeviceSetupDialog() override;
+
+  // ui::WebDialogDelegate
+  void GetDialogSize(gfx::Size* size) const override;
+  void OnDialogClosed(const std::string& json_retval) override;
+
+ private:
+  static MultiDeviceSetupDialog* current_instance_;
+
+  DISALLOW_COPY_AND_ASSIGN(MultiDeviceSetupDialog);
+};
+
+class MultiDeviceSetupDialogUI : public ui::WebDialogUI {
+ public:
+  explicit MultiDeviceSetupDialogUI(content::WebUI* web_ui);
+  ~MultiDeviceSetupDialogUI() override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MultiDeviceSetupDialogUI);
+};
+
+}  // namespace multidevice_setup
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_UI_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_MULTIDEVICE_SETUP_DIALOG_H_
diff --git a/chrome/browser/ui/webui/chromeos/network_ui.cc b/chrome/browser/ui/webui/chromeos/network_ui.cc
index c41a3dbb..26d8445 100644
--- a/chrome/browser/ui/webui/chromeos/network_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/network_ui.cc
@@ -84,15 +84,18 @@
   void RegisterMessages() override {
     web_ui()->RegisterMessageCallback(
         kGetNetworkProperties,
-        base::Bind(&NetworkConfigMessageHandler::GetShillNetworkProperties,
-                   base::Unretained(this)));
+        base::BindRepeating(
+            &NetworkConfigMessageHandler::GetShillNetworkProperties,
+            base::Unretained(this)));
     web_ui()->RegisterMessageCallback(
         kGetDeviceProperties,
-        base::Bind(&NetworkConfigMessageHandler::GetShillDeviceProperties,
-                   base::Unretained(this)));
+        base::BindRepeating(
+            &NetworkConfigMessageHandler::GetShillDeviceProperties,
+            base::Unretained(this)));
     web_ui()->RegisterMessageCallback(
-        "addNetwork", base::Bind(&NetworkConfigMessageHandler::AddNetwork,
-                                 base::Unretained(this)));
+        "addNetwork",
+        base::BindRepeating(&NetworkConfigMessageHandler::AddNetwork,
+                            base::Unretained(this)));
   }
 
  private:
diff --git a/chrome/browser/ui/webui/chromeos/power_ui.cc b/chrome/browser/ui/webui/chromeos/power_ui.cc
index 6300c28..21d6578 100644
--- a/chrome/browser/ui/webui/chromeos/power_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/power_ui.cc
@@ -71,16 +71,16 @@
 void PowerMessageHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       kRequestBatteryChargeDataCallback,
-      base::Bind(&PowerMessageHandler::OnGetBatteryChargeData,
-                 base::Unretained(this)));
+      base::BindRepeating(&PowerMessageHandler::OnGetBatteryChargeData,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kRequestCpuIdleDataCallback,
-      base::Bind(&PowerMessageHandler::OnGetCpuIdleData,
-                 base::Unretained(this)));
+      base::BindRepeating(&PowerMessageHandler::OnGetCpuIdleData,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kRequestCpuFreqDataCallback,
-      base::Bind(&PowerMessageHandler::OnGetCpuFreqData,
-                 base::Unretained(this)));
+      base::BindRepeating(&PowerMessageHandler::OnGetCpuFreqData,
+                          base::Unretained(this)));
 }
 
 void PowerMessageHandler::OnGetBatteryChargeData(const base::ListValue* value) {
diff --git a/chrome/browser/ui/webui/chromeos/set_time_ui.cc b/chrome/browser/ui/webui/chromeos/set_time_ui.cc
index d231988..95008b5 100644
--- a/chrome/browser/ui/webui/chromeos/set_time_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/set_time_ui.cc
@@ -52,11 +52,12 @@
   void RegisterMessages() override {
     web_ui()->RegisterMessageCallback(
         "setTimeInSeconds",
-        base::Bind(&SetTimeMessageHandler::OnSetTime, base::Unretained(this)));
+        base::BindRepeating(&SetTimeMessageHandler::OnSetTime,
+                            base::Unretained(this)));
     web_ui()->RegisterMessageCallback(
         "setTimezone",
-        base::Bind(&SetTimeMessageHandler::OnSetTimezone,
-                   base::Unretained(this)));
+        base::BindRepeating(&SetTimeMessageHandler::OnSetTimezone,
+                            base::Unretained(this)));
   }
 
  private:
diff --git a/chrome/browser/ui/webui/chromeos/slow_ui.cc b/chrome/browser/ui/webui/chromeos/slow_ui.cc
index f8696f9..2e5b4c35 100644
--- a/chrome/browser/ui/webui/chromeos/slow_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/slow_ui.cc
@@ -87,12 +87,15 @@
 }
 
 void SlowHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback(kJsApiDisableTracing,
-      base::Bind(&SlowHandler::HandleDisable, base::Unretained(this)));
-  web_ui()->RegisterMessageCallback(kJsApiEnableTracing,
-      base::Bind(&SlowHandler::HandleEnable, base::Unretained(this)));
-  web_ui()->RegisterMessageCallback(kJsApiLoadComplete,
-      base::Bind(&SlowHandler::LoadComplete, base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      kJsApiDisableTracing,
+      base::BindRepeating(&SlowHandler::HandleDisable, base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      kJsApiEnableTracing,
+      base::BindRepeating(&SlowHandler::HandleEnable, base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      kJsApiLoadComplete,
+      base::BindRepeating(&SlowHandler::LoadComplete, base::Unretained(this)));
 
   user_pref_registrar_.reset(new PrefChangeRegistrar);
   user_pref_registrar_->Init(profile_->GetPrefs());
diff --git a/chrome/browser/ui/webui/chromeos/sys_internals/sys_internals_message_handler.cc b/chrome/browser/ui/webui/chromeos/sys_internals/sys_internals_message_handler.cc
index ad01a66d..eef91e1 100644
--- a/chrome/browser/ui/webui/chromeos/sys_internals/sys_internals_message_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/sys_internals/sys_internals_message_handler.cc
@@ -205,8 +205,9 @@
 
 void SysInternalsMessageHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
-      "getSysInfo", base::Bind(&SysInternalsMessageHandler::HandleGetSysInfo,
-                               base::Unretained(this)));
+      "getSysInfo",
+      base::BindRepeating(&SysInternalsMessageHandler::HandleGetSysInfo,
+                          base::Unretained(this)));
 }
 
 void SysInternalsMessageHandler::HandleGetSysInfo(const base::ListValue* args) {
diff --git a/chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.cc b/chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.cc
index c61dedb5..e2ed0c2 100644
--- a/chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.cc
+++ b/chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.cc
@@ -42,6 +42,10 @@
   size->SetSize(kDialogWidth, kDialogHeight);
 }
 
+std::string SystemWebDialogDelegate::GetDialogArgs() const {
+  return std::string();
+}
+
 void SystemWebDialogDelegate::OnDialogShown(
     content::WebUI* webui,
     content::RenderViewHost* render_view_host) {
diff --git a/chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.h b/chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.h
index c91592c4..5d7de216 100644
--- a/chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.h
+++ b/chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.h
@@ -31,6 +31,7 @@
   void GetWebUIMessageHandlers(
       std::vector<content::WebUIMessageHandler*>* handlers) const override;
   void GetDialogSize(gfx::Size* size) const override;
+  std::string GetDialogArgs() const override;
   void OnDialogShown(content::WebUI* webui,
                      content::RenderViewHost* render_view_host) override;
   // Note: deletes |this|.
diff --git a/chrome/browser/ui/webui/components_ui.cc b/chrome/browser/ui/webui/components_ui.cc
index f58e250..8a5db7e 100644
--- a/chrome/browser/ui/webui/components_ui.cc
+++ b/chrome/browser/ui/webui/components_ui.cc
@@ -99,13 +99,13 @@
 void ComponentsDOMHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "requestComponentsData",
-      base::Bind(&ComponentsDOMHandler::HandleRequestComponentsData,
-                 base::Unretained(this)));
+      base::BindRepeating(&ComponentsDOMHandler::HandleRequestComponentsData,
+                          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       "checkUpdate",
-      base::Bind(&ComponentsDOMHandler::HandleCheckUpdate,
-                 base::Unretained(this)));
+      base::BindRepeating(&ComponentsDOMHandler::HandleCheckUpdate,
+                          base::Unretained(this)));
 }
 
 void ComponentsDOMHandler::HandleRequestComponentsData(
diff --git a/chrome/browser/ui/webui/conflicts_handler.cc b/chrome/browser/ui/webui/conflicts_handler.cc
index abfae651..ee1e739d 100644
--- a/chrome/browser/ui/webui/conflicts_handler.cc
+++ b/chrome/browser/ui/webui/conflicts_handler.cc
@@ -22,8 +22,8 @@
 void ConflictsHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "requestModuleList",
-      base::Bind(&ConflictsHandler::HandleRequestModuleList,
-                 base::Unretained(this)));
+      base::BindRepeating(&ConflictsHandler::HandleRequestModuleList,
+                          base::Unretained(this)));
 }
 
 void ConflictsHandler::OnScanCompleted() {
diff --git a/chrome/browser/ui/webui/constrained_web_dialog_ui.cc b/chrome/browser/ui/webui/constrained_web_dialog_ui.cc
index 7f6c2bc..12f77178 100644
--- a/chrome/browser/ui/webui/constrained_web_dialog_ui.cc
+++ b/chrome/browser/ui/webui/constrained_web_dialog_ui.cc
@@ -67,9 +67,10 @@
 void ConstrainedWebDialogUI::RenderFrameCreated(
     RenderFrameHost* render_frame_host) {
   // Add a "dialogClose" callback which matches WebDialogUI behavior.
-  web_ui()->RegisterMessageCallback("dialogClose",
-      base::Bind(&ConstrainedWebDialogUI::OnDialogCloseMessage,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "dialogClose",
+      base::BindRepeating(&ConstrainedWebDialogUI::OnDialogCloseMessage,
+                          base::Unretained(this)));
 
   ConstrainedWebDialogDelegate* delegate = GetConstrainedDelegate();
   if (!delegate)
diff --git a/chrome/browser/ui/webui/crashes_ui.cc b/chrome/browser/ui/webui/crashes_ui.cc
index d8444cb..296a09f 100644
--- a/chrome/browser/ui/webui/crashes_ui.cc
+++ b/chrome/browser/ui/webui/crashes_ui.cc
@@ -114,20 +114,20 @@
                                     base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       crash::kCrashesUIRequestCrashList,
-      base::Bind(&CrashesDOMHandler::HandleRequestCrashes,
-                 base::Unretained(this)));
+      base::BindRepeating(&CrashesDOMHandler::HandleRequestCrashes,
+                          base::Unretained(this)));
 
 #if defined(OS_CHROMEOS)
   web_ui()->RegisterMessageCallback(
       crash::kCrashesUIRequestCrashUpload,
-      base::Bind(&CrashesDOMHandler::HandleRequestUploads,
-                 base::Unretained(this)));
+      base::BindRepeating(&CrashesDOMHandler::HandleRequestUploads,
+                          base::Unretained(this)));
 #endif
 
   web_ui()->RegisterMessageCallback(
       crash::kCrashesUIRequestSingleCrashUpload,
-      base::Bind(&CrashesDOMHandler::HandleRequestSingleCrashUpload,
-                 base::Unretained(this)));
+      base::BindRepeating(&CrashesDOMHandler::HandleRequestSingleCrashUpload,
+                          base::Unretained(this)));
 }
 
 void CrashesDOMHandler::HandleRequestCrashes(const base::ListValue* args) {
diff --git a/chrome/browser/ui/webui/device_log_ui.cc b/chrome/browser/ui/webui/device_log_ui.cc
index 6f55ce92..22d484d 100644
--- a/chrome/browser/ui/webui/device_log_ui.cc
+++ b/chrome/browser/ui/webui/device_log_ui.cc
@@ -33,7 +33,8 @@
   void RegisterMessages() override {
     web_ui()->RegisterMessageCallback(
         "DeviceLog.getLog",
-        base::Bind(&DeviceLogMessageHandler::GetLog, base::Unretained(this)));
+        base::BindRepeating(&DeviceLogMessageHandler::GetLog,
+                            base::Unretained(this)));
   }
 
  private:
diff --git a/chrome/browser/ui/webui/domain_reliability_internals_ui.cc b/chrome/browser/ui/webui/domain_reliability_internals_ui.cc
index ba3525b..2afd8eb0 100644
--- a/chrome/browser/ui/webui/domain_reliability_internals_ui.cc
+++ b/chrome/browser/ui/webui/domain_reliability_internals_ui.cc
@@ -29,9 +29,10 @@
   html_source->SetDefaultResource(IDR_DOMAIN_RELIABILITY_INTERNALS_HTML);
   html_source->UseGzip();
 
-  web_ui->RegisterMessageCallback("updateData",
-      base::Bind(&DomainReliabilityInternalsUI::UpdateData,
-                 base::Unretained(this)));
+  web_ui->RegisterMessageCallback(
+      "updateData",
+      base::BindRepeating(&DomainReliabilityInternalsUI::UpdateData,
+                          base::Unretained(this)));
 
   Profile* profile = Profile::FromWebUI(web_ui);
   content::WebUIDataSource::Add(profile, html_source);
diff --git a/chrome/browser/ui/webui/extensions/chromeos/kiosk_apps_handler.cc b/chrome/browser/ui/webui/extensions/chromeos/kiosk_apps_handler.cc
index f6fed88..56b411c5 100644
--- a/chrome/browser/ui/webui/extensions/chromeos/kiosk_apps_handler.cc
+++ b/chrome/browser/ui/webui/extensions/chromeos/kiosk_apps_handler.cc
@@ -129,27 +129,33 @@
 }
 
 void KioskAppsHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback("initializeKioskAppSettings",
-      base::Bind(&KioskAppsHandler::HandleInitializeKioskAppSettings,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("getKioskAppSettings",
-      base::Bind(&KioskAppsHandler::HandleGetKioskAppSettings,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("addKioskApp",
-      base::Bind(&KioskAppsHandler::HandleAddKioskApp,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("removeKioskApp",
-      base::Bind(&KioskAppsHandler::HandleRemoveKioskApp,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("enableKioskAutoLaunch",
-      base::Bind(&KioskAppsHandler::HandleEnableKioskAutoLaunch,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("disableKioskAutoLaunch",
-      base::Bind(&KioskAppsHandler::HandleDisableKioskAutoLaunch,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("setDisableBailoutShortcut",
-      base::Bind(&KioskAppsHandler::HandleSetDisableBailoutShortcut,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "initializeKioskAppSettings",
+      base::BindRepeating(&KioskAppsHandler::HandleInitializeKioskAppSettings,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "getKioskAppSettings",
+      base::BindRepeating(&KioskAppsHandler::HandleGetKioskAppSettings,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "addKioskApp", base::BindRepeating(&KioskAppsHandler::HandleAddKioskApp,
+                                         base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "removeKioskApp",
+      base::BindRepeating(&KioskAppsHandler::HandleRemoveKioskApp,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "enableKioskAutoLaunch",
+      base::BindRepeating(&KioskAppsHandler::HandleEnableKioskAutoLaunch,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "disableKioskAutoLaunch",
+      base::BindRepeating(&KioskAppsHandler::HandleDisableKioskAutoLaunch,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "setDisableBailoutShortcut",
+      base::BindRepeating(&KioskAppsHandler::HandleSetDisableBailoutShortcut,
+                          base::Unretained(this)));
 }
 
 void KioskAppsHandler::GetLocalizedValues(content::WebUIDataSource* source) {
diff --git a/chrome/browser/ui/webui/extensions/extension_loader_handler.cc b/chrome/browser/ui/webui/extensions/extension_loader_handler.cc
index 03e8062..59ae285 100644
--- a/chrome/browser/ui/webui/extensions/extension_loader_handler.cc
+++ b/chrome/browser/ui/webui/extensions/extension_loader_handler.cc
@@ -93,16 +93,16 @@
 
   web_ui()->RegisterMessageCallback(
       "extensionLoaderRetry",
-      base::Bind(&ExtensionLoaderHandler::HandleRetry,
-                 weak_ptr_factory_.GetWeakPtr()));
+      base::BindRepeating(&ExtensionLoaderHandler::HandleRetry,
+                          weak_ptr_factory_.GetWeakPtr()));
   web_ui()->RegisterMessageCallback(
       "extensionLoaderIgnoreFailure",
-      base::Bind(&ExtensionLoaderHandler::HandleIgnoreFailure,
-                 weak_ptr_factory_.GetWeakPtr()));
+      base::BindRepeating(&ExtensionLoaderHandler::HandleIgnoreFailure,
+                          weak_ptr_factory_.GetWeakPtr()));
   web_ui()->RegisterMessageCallback(
       "extensionLoaderDisplayFailures",
-      base::Bind(&ExtensionLoaderHandler::HandleDisplayFailures,
-                 weak_ptr_factory_.GetWeakPtr()));
+      base::BindRepeating(&ExtensionLoaderHandler::HandleDisplayFailures,
+                          weak_ptr_factory_.GetWeakPtr()));
 }
 
 // static
diff --git a/chrome/browser/ui/webui/extensions/install_extension_handler.cc b/chrome/browser/ui/webui/extensions/install_extension_handler.cc
index cafe0181..1782d196 100644
--- a/chrome/browser/ui/webui/extensions/install_extension_handler.cc
+++ b/chrome/browser/ui/webui/extensions/install_extension_handler.cc
@@ -44,20 +44,21 @@
 void InstallExtensionHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "startDrag",
-      base::Bind(&InstallExtensionHandler::HandleStartDragMessage,
-                 base::Unretained(this)));
+      base::BindRepeating(&InstallExtensionHandler::HandleStartDragMessage,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "stopDrag",
-      base::Bind(&InstallExtensionHandler::HandleStopDragMessage,
-                 base::Unretained(this)));
+      base::BindRepeating(&InstallExtensionHandler::HandleStopDragMessage,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "installDroppedFile",
-      base::Bind(&InstallExtensionHandler::HandleInstallMessage,
-                 base::Unretained(this)));
+      base::BindRepeating(&InstallExtensionHandler::HandleInstallMessage,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "installDroppedDirectory",
-      base::Bind(&InstallExtensionHandler::HandleInstallDirectoryMessage,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &InstallExtensionHandler::HandleInstallDirectoryMessage,
+          base::Unretained(this)));
 }
 
 void InstallExtensionHandler::HandleStartDragMessage(
diff --git a/chrome/browser/ui/webui/flags_ui.cc b/chrome/browser/ui/webui/flags_ui.cc
index ff91793..f65befb 100644
--- a/chrome/browser/ui/webui/flags_ui.cc
+++ b/chrome/browser/ui/webui/flags_ui.cc
@@ -132,20 +132,21 @@
 void FlagsDOMHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       flags_ui::kRequestExperimentalFeatures,
-      base::Bind(&FlagsDOMHandler::HandleRequestExperimentalFeatures,
-                 base::Unretained(this)));
+      base::BindRepeating(&FlagsDOMHandler::HandleRequestExperimentalFeatures,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       flags_ui::kEnableExperimentalFeature,
-      base::Bind(&FlagsDOMHandler::HandleEnableExperimentalFeatureMessage,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &FlagsDOMHandler::HandleEnableExperimentalFeatureMessage,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       flags_ui::kRestartBrowser,
-      base::Bind(&FlagsDOMHandler::HandleRestartBrowser,
-                 base::Unretained(this)));
+      base::BindRepeating(&FlagsDOMHandler::HandleRestartBrowser,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       flags_ui::kResetAllFlags,
-      base::Bind(&FlagsDOMHandler::HandleResetAllFlags,
-                 base::Unretained(this)));
+      base::BindRepeating(&FlagsDOMHandler::HandleResetAllFlags,
+                          base::Unretained(this)));
 }
 
 void FlagsDOMHandler::Init(flags_ui::FlagsStorage* flags_storage,
diff --git a/chrome/browser/ui/webui/flash_ui.cc b/chrome/browser/ui/webui/flash_ui.cc
index 1f92cb6..625921b 100644
--- a/chrome/browser/ui/webui/flash_ui.cc
+++ b/chrome/browser/ui/webui/flash_ui.cc
@@ -176,9 +176,10 @@
 }
 
 void FlashDOMHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback("requestFlashInfo",
-      base::Bind(&FlashDOMHandler::HandleRequestFlashInfo,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "requestFlashInfo",
+      base::BindRepeating(&FlashDOMHandler::HandleRequestFlashInfo,
+                          base::Unretained(this)));
 }
 
 void FlashDOMHandler::OnUploadListAvailable() {
diff --git a/chrome/browser/ui/webui/foreign_session_handler.cc b/chrome/browser/ui/webui/foreign_session_handler.cc
index cbae4e8..94585185d 100644
--- a/chrome/browser/ui/webui/foreign_session_handler.cc
+++ b/chrome/browser/ui/webui/foreign_session_handler.cc
@@ -240,18 +240,23 @@
   if (service)
     scoped_observer_.Add(service);
 
-  web_ui()->RegisterMessageCallback("deleteForeignSession",
-      base::Bind(&ForeignSessionHandler::HandleDeleteForeignSession,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("getForeignSessions",
-      base::Bind(&ForeignSessionHandler::HandleGetForeignSessions,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("openForeignSession",
-      base::Bind(&ForeignSessionHandler::HandleOpenForeignSession,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("setForeignSessionCollapsed",
-      base::Bind(&ForeignSessionHandler::HandleSetForeignSessionCollapsed,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "deleteForeignSession",
+      base::BindRepeating(&ForeignSessionHandler::HandleDeleteForeignSession,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "getForeignSessions",
+      base::BindRepeating(&ForeignSessionHandler::HandleGetForeignSessions,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "openForeignSession",
+      base::BindRepeating(&ForeignSessionHandler::HandleOpenForeignSession,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "setForeignSessionCollapsed",
+      base::BindRepeating(
+          &ForeignSessionHandler::HandleSetForeignSessionCollapsed,
+          base::Unretained(this)));
 }
 
 void ForeignSessionHandler::OnSyncConfigurationCompleted(
diff --git a/chrome/browser/ui/webui/gcm_internals_ui.cc b/chrome/browser/ui/webui/gcm_internals_ui.cc
index 80a41087..cf281da 100644
--- a/chrome/browser/ui/webui/gcm_internals_ui.cc
+++ b/chrome/browser/ui/webui/gcm_internals_ui.cc
@@ -145,12 +145,12 @@
 void GcmInternalsUIMessageHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       gcm_driver::kGetGcmInternalsInfo,
-      base::Bind(&GcmInternalsUIMessageHandler::RequestAllInfo,
-                 weak_ptr_factory_.GetWeakPtr()));
+      base::BindRepeating(&GcmInternalsUIMessageHandler::RequestAllInfo,
+                          weak_ptr_factory_.GetWeakPtr()));
   web_ui()->RegisterMessageCallback(
       gcm_driver::kSetGcmInternalsRecording,
-      base::Bind(&GcmInternalsUIMessageHandler::SetRecording,
-                 weak_ptr_factory_.GetWeakPtr()));
+      base::BindRepeating(&GcmInternalsUIMessageHandler::SetRecording,
+                          weak_ptr_factory_.GetWeakPtr()));
 }
 
 }  // namespace
diff --git a/chrome/browser/ui/webui/history_login_handler.cc b/chrome/browser/ui/webui/history_login_handler.cc
index 33d1b52..5fe265f 100644
--- a/chrome/browser/ui/webui/history_login_handler.cc
+++ b/chrome/browser/ui/webui/history_login_handler.cc
@@ -28,13 +28,15 @@
       base::Bind(&HistoryLoginHandler::ProfileInfoChanged,
                  base::Unretained(this))));
 
-  web_ui()->RegisterMessageCallback("otherDevicesInitialized",
-      base::Bind(&HistoryLoginHandler::HandleOtherDevicesInitialized,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "otherDevicesInitialized",
+      base::BindRepeating(&HistoryLoginHandler::HandleOtherDevicesInitialized,
+                          base::Unretained(this)));
 
-  web_ui()->RegisterMessageCallback("startSignInFlow",
-      base::Bind(&HistoryLoginHandler::HandleStartSignInFlow,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "startSignInFlow",
+      base::BindRepeating(&HistoryLoginHandler::HandleStartSignInFlow,
+                          base::Unretained(this)));
 }
 
 void HistoryLoginHandler::HandleOtherDevicesInitialized(
diff --git a/chrome/browser/ui/webui/identity_internals_ui.cc b/chrome/browser/ui/webui/identity_internals_ui.cc
index cabffb7a..6a524d4 100644
--- a/chrome/browser/ui/webui/identity_internals_ui.cc
+++ b/chrome/browser/ui/webui/identity_internals_ui.cc
@@ -249,12 +249,15 @@
 }
 
 void IdentityInternalsUIMessageHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback("identityInternalsGetTokens",
-      base::Bind(&IdentityInternalsUIMessageHandler::GetInfoForAllTokens,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("identityInternalsRevokeToken",
-      base::Bind(&IdentityInternalsUIMessageHandler::RevokeToken,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "identityInternalsGetTokens",
+      base::BindRepeating(
+          &IdentityInternalsUIMessageHandler::GetInfoForAllTokens,
+          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "identityInternalsRevokeToken",
+      base::BindRepeating(&IdentityInternalsUIMessageHandler::RevokeToken,
+                          base::Unretained(this)));
 }
 
 void IdentityInternalsUIMessageHandler::RevokeToken(
diff --git a/chrome/browser/ui/webui/inspect_ui.cc b/chrome/browser/ui/webui/inspect_ui.cc
index 65d8f55..acad9c57e 100644
--- a/chrome/browser/ui/webui/inspect_ui.cc
+++ b/chrome/browser/ui/webui/inspect_ui.cc
@@ -110,56 +110,72 @@
 };
 
 void InspectMessageHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback(kInitUICommand,
-      base::Bind(&InspectMessageHandler::HandleInitUICommand,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback(kInspectCommand,
-      base::Bind(&InspectMessageHandler::HandleInspectCommand,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      kInitUICommand,
+      base::BindRepeating(&InspectMessageHandler::HandleInitUICommand,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      kInspectCommand,
+      base::BindRepeating(&InspectMessageHandler::HandleInspectCommand,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kInspectFallbackCommand,
       base::BindRepeating(&InspectMessageHandler::HandleInspectFallbackCommand,
                           base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kInspectAdditionalCommand,
-      base::Bind(&InspectMessageHandler::HandleInspectAdditionalCommand,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback(kActivateCommand,
-      base::Bind(&InspectMessageHandler::HandleActivateCommand,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback(kCloseCommand,
-      base::Bind(&InspectMessageHandler::HandleCloseCommand,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback(kDiscoverUsbDevicesEnabledCommand,
-      base::Bind(&InspectMessageHandler::HandleBooleanPrefChanged,
-                  base::Unretained(this),
-                  &prefs::kDevToolsDiscoverUsbDevicesEnabled[0]));
-  web_ui()->RegisterMessageCallback(kPortForwardingEnabledCommand,
-      base::Bind(&InspectMessageHandler::HandleBooleanPrefChanged,
-                 base::Unretained(this),
-                 &prefs::kDevToolsPortForwardingEnabled[0]));
-  web_ui()->RegisterMessageCallback(kPortForwardingConfigCommand,
-      base::Bind(&InspectMessageHandler::HandlePortForwardingConfigCommand,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback(kDiscoverTCPTargetsEnabledCommand,
-      base::Bind(&InspectMessageHandler::HandleBooleanPrefChanged,
-                 base::Unretained(this),
-                 &prefs::kDevToolsDiscoverTCPTargetsEnabled[0]));
-  web_ui()->RegisterMessageCallback(kTCPDiscoveryConfigCommand,
-      base::Bind(&InspectMessageHandler::HandleTCPDiscoveryConfigCommand,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback(kOpenNodeFrontendCommand,
-      base::Bind(&InspectMessageHandler::HandleOpenNodeFrontendCommand,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback(kReloadCommand,
-      base::Bind(&InspectMessageHandler::HandleReloadCommand,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback(kOpenCommand,
-      base::Bind(&InspectMessageHandler::HandleOpenCommand,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback(kInspectBrowser,
-      base::Bind(&InspectMessageHandler::HandleInspectBrowserCommand,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &InspectMessageHandler::HandleInspectAdditionalCommand,
+          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      kActivateCommand,
+      base::BindRepeating(&InspectMessageHandler::HandleActivateCommand,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      kCloseCommand,
+      base::BindRepeating(&InspectMessageHandler::HandleCloseCommand,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      kDiscoverUsbDevicesEnabledCommand,
+      base::BindRepeating(&InspectMessageHandler::HandleBooleanPrefChanged,
+                          base::Unretained(this),
+                          &prefs::kDevToolsDiscoverUsbDevicesEnabled[0]));
+  web_ui()->RegisterMessageCallback(
+      kPortForwardingEnabledCommand,
+      base::BindRepeating(&InspectMessageHandler::HandleBooleanPrefChanged,
+                          base::Unretained(this),
+                          &prefs::kDevToolsPortForwardingEnabled[0]));
+  web_ui()->RegisterMessageCallback(
+      kPortForwardingConfigCommand,
+      base::BindRepeating(
+          &InspectMessageHandler::HandlePortForwardingConfigCommand,
+          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      kDiscoverTCPTargetsEnabledCommand,
+      base::BindRepeating(&InspectMessageHandler::HandleBooleanPrefChanged,
+                          base::Unretained(this),
+                          &prefs::kDevToolsDiscoverTCPTargetsEnabled[0]));
+  web_ui()->RegisterMessageCallback(
+      kTCPDiscoveryConfigCommand,
+      base::BindRepeating(
+          &InspectMessageHandler::HandleTCPDiscoveryConfigCommand,
+          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      kOpenNodeFrontendCommand,
+      base::BindRepeating(&InspectMessageHandler::HandleOpenNodeFrontendCommand,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      kReloadCommand,
+      base::BindRepeating(&InspectMessageHandler::HandleReloadCommand,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      kOpenCommand,
+      base::BindRepeating(&InspectMessageHandler::HandleOpenCommand,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      kInspectBrowser,
+      base::BindRepeating(&InspectMessageHandler::HandleInspectBrowserCommand,
+                          base::Unretained(this)));
 }
 
 void InspectMessageHandler::HandleInitUICommand(const base::ListValue*) {
diff --git a/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.cc b/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.cc
index 0a4eb3c..7acc8d0 100644
--- a/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.cc
+++ b/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.cc
@@ -18,6 +18,7 @@
 #include "components/previews/core/previews_experiments.h"
 #include "components/previews/core/previews_switches.h"
 #include "net/nqe/network_quality_estimator_params.h"
+#include "services/network/public/cpp/network_switches.h"
 
 namespace {
 
@@ -235,7 +236,7 @@
   ect_status->link = kEctFlagLink;
   std::string ect_value =
       base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
-          switches::kForceEffectiveConnectionType);
+          network::switches::kForceEffectiveConnectionType);
   ect_status->value = ect_value.empty() ? GetNonFlagEctValue() : ect_value;
   ect_status->htmlId = kEctFlagHtmlId;
   flags.push_back(std::move(ect_status));
diff --git a/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler_unittest.cc b/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler_unittest.cc
index d9572b7..da4c18dd 100644
--- a/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler_unittest.cc
+++ b/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler_unittest.cc
@@ -39,6 +39,7 @@
 #include "mojo/public/cpp/bindings/binding.h"
 #include "net/nqe/effective_connection_type.h"
 #include "net/nqe/network_quality_estimator_params.h"
+#include "services/network/public/cpp/network_switches.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
@@ -451,8 +452,8 @@
   base::test::ScopedCommandLine scoped_command_line;
   base::CommandLine* command_line = scoped_command_line.GetProcessCommandLine();
   for (auto expected_ect : expected_ects) {
-    command_line->AppendSwitchASCII(switches::kForceEffectiveConnectionType,
-                                    expected_ect);
+    command_line->AppendSwitchASCII(
+        network::switches::kForceEffectiveConnectionType, expected_ect);
     page_handler_->GetPreviewsFlagsDetails(
         base::BindOnce(&MockGetPreviewsFlagsCallback));
     auto ect_flag = passed_in_flags.find(kEctFlagHtmlId);
diff --git a/chrome/browser/ui/webui/invalidations_message_handler.cc b/chrome/browser/ui/webui/invalidations_message_handler.cc
index 7415064..388d20b 100644
--- a/chrome/browser/ui/webui/invalidations_message_handler.cc
+++ b/chrome/browser/ui/webui/invalidations_message_handler.cc
@@ -33,13 +33,13 @@
 
 void InvalidationsMessageHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
-      "doneLoading",
-      base::Bind(&InvalidationsMessageHandler::UIReady,
-                 base::Unretained(this)));
+      "doneLoading", base::BindRepeating(&InvalidationsMessageHandler::UIReady,
+                                         base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "requestDetailedStatus",
-      base::Bind(&InvalidationsMessageHandler::HandleRequestDetailedStatus,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &InvalidationsMessageHandler::HandleRequestDetailedStatus,
+          base::Unretained(this)));
 }
 
 void InvalidationsMessageHandler::UIReady(const base::ListValue* args) {
diff --git a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.cc b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.cc
index 78324376..57556f7 100644
--- a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.cc
+++ b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.cc
@@ -119,39 +119,45 @@
 }
 
 void LocalDiscoveryUIHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback("start", base::Bind(
-      &LocalDiscoveryUIHandler::HandleStart,
-      base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("isVisible", base::Bind(
-      &LocalDiscoveryUIHandler::HandleIsVisible,
-      base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("registerDevice", base::Bind(
-      &LocalDiscoveryUIHandler::HandleRegisterDevice,
-      base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("cancelRegistration", base::Bind(
-      &LocalDiscoveryUIHandler::HandleCancelRegistration,
-      base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "start", base::BindRepeating(&LocalDiscoveryUIHandler::HandleStart,
+                                   base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "isVisible",
+      base::BindRepeating(&LocalDiscoveryUIHandler::HandleIsVisible,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "registerDevice",
+      base::BindRepeating(&LocalDiscoveryUIHandler::HandleRegisterDevice,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "cancelRegistration",
+      base::BindRepeating(&LocalDiscoveryUIHandler::HandleCancelRegistration,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "requestDeviceList",
-      base::Bind(&LocalDiscoveryUIHandler::HandleRequestDeviceList,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("openCloudPrintURL", base::Bind(
-      &LocalDiscoveryUIHandler::HandleOpenCloudPrintURL,
-      base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("showSyncUI", base::Bind(
-      &LocalDiscoveryUIHandler::HandleShowSyncUI,
-      base::Unretained(this)));
+      base::BindRepeating(&LocalDiscoveryUIHandler::HandleRequestDeviceList,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "openCloudPrintURL",
+      base::BindRepeating(&LocalDiscoveryUIHandler::HandleOpenCloudPrintURL,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "showSyncUI",
+      base::BindRepeating(&LocalDiscoveryUIHandler::HandleShowSyncUI,
+                          base::Unretained(this)));
 
   // Cloud print connector related messages
 #if defined(CLOUD_PRINT_CONNECTOR_UI_AVAILABLE)
   web_ui()->RegisterMessageCallback(
       "showCloudPrintSetupDialog",
-      base::Bind(&LocalDiscoveryUIHandler::ShowCloudPrintSetupDialog,
-                 base::Unretained(this)));
+      base::BindRepeating(&LocalDiscoveryUIHandler::ShowCloudPrintSetupDialog,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "disableCloudPrintConnector",
-      base::Bind(&LocalDiscoveryUIHandler::HandleDisableCloudPrintConnector,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &LocalDiscoveryUIHandler::HandleDisableCloudPrintConnector,
+          base::Unretained(this)));
 #endif  // defined(CLOUD_PRINT_CONNECTOR_UI_AVAILABLE)
 }
 
diff --git a/chrome/browser/ui/webui/local_state/local_state_ui.cc b/chrome/browser/ui/webui/local_state/local_state_ui.cc
index df96c79..818dc70e 100644
--- a/chrome/browser/ui/webui/local_state/local_state_ui.cc
+++ b/chrome/browser/ui/webui/local_state/local_state_ui.cc
@@ -57,8 +57,9 @@
 
 void LocalStateUIHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
-      "requestJson", base::Bind(&LocalStateUIHandler::HandleRequestJson,
-                                base::Unretained(this)));
+      "requestJson",
+      base::BindRepeating(&LocalStateUIHandler::HandleRequestJson,
+                          base::Unretained(this)));
 }
 
 void LocalStateUIHandler::HandleRequestJson(const base::ListValue* args) {
diff --git a/chrome/browser/ui/webui/md_bookmarks/bookmarks_message_handler.cc b/chrome/browser/ui/webui/md_bookmarks/bookmarks_message_handler.cc
index 249049a..0b19140 100644
--- a/chrome/browser/ui/webui/md_bookmarks/bookmarks_message_handler.cc
+++ b/chrome/browser/ui/webui/md_bookmarks/bookmarks_message_handler.cc
@@ -19,12 +19,13 @@
 void BookmarksMessageHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "getIncognitoAvailability",
-      base::Bind(&BookmarksMessageHandler::HandleGetIncognitoAvailability,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &BookmarksMessageHandler::HandleGetIncognitoAvailability,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "getCanEditBookmarks",
-      base::Bind(&BookmarksMessageHandler::HandleGetCanEditBookmarks,
-                 base::Unretained(this)));
+      base::BindRepeating(&BookmarksMessageHandler::HandleGetCanEditBookmarks,
+                          base::Unretained(this)));
 }
 
 void BookmarksMessageHandler::OnJavascriptAllowed() {
diff --git a/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_browsertest.cc b/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_browsertest.cc
index 7dea1b0..2a1a13f0 100644
--- a/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_browsertest.cc
+++ b/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_browsertest.cc
@@ -18,12 +18,13 @@
 void MdBookmarksBrowserTest::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "testSetIncognito",
-      base::Bind(&MdBookmarksBrowserTest::HandleSetIncognitoAvailability,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &MdBookmarksBrowserTest::HandleSetIncognitoAvailability,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "testSetCanEdit",
-      base::Bind(&MdBookmarksBrowserTest::HandleSetCanEditBookmarks,
-                 base::Unretained(this)));
+      base::BindRepeating(&MdBookmarksBrowserTest::HandleSetCanEditBookmarks,
+                          base::Unretained(this)));
 }
 
 void MdBookmarksBrowserTest::SetIncognitoAvailability(int availability) {
diff --git a/chrome/browser/ui/webui/md_downloads/md_downloads_dom_handler.cc b/chrome/browser/ui/webui/md_downloads/md_downloads_dom_handler.cc
index 4138366..e15089f 100644
--- a/chrome/browser/ui/webui/md_downloads/md_downloads_dom_handler.cc
+++ b/chrome/browser/ui/webui/md_downloads/md_downloads_dom_handler.cc
@@ -89,48 +89,50 @@
 // MdDownloadsDOMHandler, public: ---------------------------------------------
 
 void MdDownloadsDOMHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback("getDownloads",
-      base::Bind(&MdDownloadsDOMHandler::HandleGetDownloads,
-                 weak_ptr_factory_.GetWeakPtr()));
+  web_ui()->RegisterMessageCallback(
+      "getDownloads",
+      base::BindRepeating(&MdDownloadsDOMHandler::HandleGetDownloads,
+                          weak_ptr_factory_.GetWeakPtr()));
   web_ui()->RegisterMessageCallback(
       "openFileRequiringGesture",
-      base::Bind(&MdDownloadsDOMHandler::HandleOpenFile,
-                 weak_ptr_factory_.GetWeakPtr()));
-  web_ui()->RegisterMessageCallback("drag",
-      base::Bind(&MdDownloadsDOMHandler::HandleDrag,
-                 weak_ptr_factory_.GetWeakPtr()));
+      base::BindRepeating(&MdDownloadsDOMHandler::HandleOpenFile,
+                          weak_ptr_factory_.GetWeakPtr()));
+  web_ui()->RegisterMessageCallback(
+      "drag", base::BindRepeating(&MdDownloadsDOMHandler::HandleDrag,
+                                  weak_ptr_factory_.GetWeakPtr()));
   web_ui()->RegisterMessageCallback(
       "saveDangerousRequiringGesture",
-      base::Bind(&MdDownloadsDOMHandler::HandleSaveDangerous,
-                 weak_ptr_factory_.GetWeakPtr()));
-  web_ui()->RegisterMessageCallback("discardDangerous",
-      base::Bind(&MdDownloadsDOMHandler::HandleDiscardDangerous,
-                 weak_ptr_factory_.GetWeakPtr()));
-  web_ui()->RegisterMessageCallback("show",
-      base::Bind(&MdDownloadsDOMHandler::HandleShow,
-                 weak_ptr_factory_.GetWeakPtr()));
-  web_ui()->RegisterMessageCallback("pause",
-      base::Bind(&MdDownloadsDOMHandler::HandlePause,
-                 weak_ptr_factory_.GetWeakPtr()));
-  web_ui()->RegisterMessageCallback("resume",
-      base::Bind(&MdDownloadsDOMHandler::HandleResume,
-                 weak_ptr_factory_.GetWeakPtr()));
-  web_ui()->RegisterMessageCallback("remove",
-      base::Bind(&MdDownloadsDOMHandler::HandleRemove,
-                 weak_ptr_factory_.GetWeakPtr()));
-  web_ui()->RegisterMessageCallback("undo",
-      base::Bind(&MdDownloadsDOMHandler::HandleUndo,
-                 weak_ptr_factory_.GetWeakPtr()));
-  web_ui()->RegisterMessageCallback("cancel",
-      base::Bind(&MdDownloadsDOMHandler::HandleCancel,
-                 weak_ptr_factory_.GetWeakPtr()));
-  web_ui()->RegisterMessageCallback("clearAll",
-      base::Bind(&MdDownloadsDOMHandler::HandleClearAll,
-                 weak_ptr_factory_.GetWeakPtr()));
+      base::BindRepeating(&MdDownloadsDOMHandler::HandleSaveDangerous,
+                          weak_ptr_factory_.GetWeakPtr()));
+  web_ui()->RegisterMessageCallback(
+      "discardDangerous",
+      base::BindRepeating(&MdDownloadsDOMHandler::HandleDiscardDangerous,
+                          weak_ptr_factory_.GetWeakPtr()));
+  web_ui()->RegisterMessageCallback(
+      "show", base::BindRepeating(&MdDownloadsDOMHandler::HandleShow,
+                                  weak_ptr_factory_.GetWeakPtr()));
+  web_ui()->RegisterMessageCallback(
+      "pause", base::BindRepeating(&MdDownloadsDOMHandler::HandlePause,
+                                   weak_ptr_factory_.GetWeakPtr()));
+  web_ui()->RegisterMessageCallback(
+      "resume", base::BindRepeating(&MdDownloadsDOMHandler::HandleResume,
+                                    weak_ptr_factory_.GetWeakPtr()));
+  web_ui()->RegisterMessageCallback(
+      "remove", base::BindRepeating(&MdDownloadsDOMHandler::HandleRemove,
+                                    weak_ptr_factory_.GetWeakPtr()));
+  web_ui()->RegisterMessageCallback(
+      "undo", base::BindRepeating(&MdDownloadsDOMHandler::HandleUndo,
+                                  weak_ptr_factory_.GetWeakPtr()));
+  web_ui()->RegisterMessageCallback(
+      "cancel", base::BindRepeating(&MdDownloadsDOMHandler::HandleCancel,
+                                    weak_ptr_factory_.GetWeakPtr()));
+  web_ui()->RegisterMessageCallback(
+      "clearAll", base::BindRepeating(&MdDownloadsDOMHandler::HandleClearAll,
+                                      weak_ptr_factory_.GetWeakPtr()));
   web_ui()->RegisterMessageCallback(
       "openDownloadsFolderRequiringGesture",
-      base::Bind(&MdDownloadsDOMHandler::HandleOpenDownloadsFolder,
-                 weak_ptr_factory_.GetWeakPtr()));
+      base::BindRepeating(&MdDownloadsDOMHandler::HandleOpenDownloadsFolder,
+                          weak_ptr_factory_.GetWeakPtr()));
 
   Observe(GetWebUIWebContents());
 }
diff --git a/chrome/browser/ui/webui/md_history_ui.cc b/chrome/browser/ui/webui/md_history_ui.cc
index e59e7fa2..d24d3ba8 100644
--- a/chrome/browser/ui/webui/md_history_ui.cc
+++ b/chrome/browser/ui/webui/md_history_ui.cc
@@ -208,8 +208,9 @@
   web_ui->AddMessageHandler(std::make_unique<HistoryLoginHandler>(
       base::Bind(&MdHistoryUI::UpdateDataSource, base::Unretained(this))));
 
-  web_ui->RegisterMessageCallback("menuPromoShown",
-      base::Bind(&MdHistoryUI::HandleMenuPromoShown, base::Unretained(this)));
+  web_ui->RegisterMessageCallback(
+      "menuPromoShown", base::BindRepeating(&MdHistoryUI::HandleMenuPromoShown,
+                                            base::Unretained(this)));
 }
 
 MdHistoryUI::~MdHistoryUI() {}
diff --git a/chrome/browser/ui/webui/media/webrtc_logs_ui.cc b/chrome/browser/ui/webui/media/webrtc_logs_ui.cc
index 782ea7d..43e045c5 100644
--- a/chrome/browser/ui/webui/media/webrtc_logs_ui.cc
+++ b/chrome/browser/ui/webui/media/webrtc_logs_ui.cc
@@ -126,9 +126,10 @@
   upload_list_->Load(base::BindOnce(
       &WebRtcLogsDOMHandler::OnUploadListAvailable, base::Unretained(this)));
 
-  web_ui()->RegisterMessageCallback("requestWebRtcLogsList",
-      base::Bind(&WebRtcLogsDOMHandler::HandleRequestWebRtcLogs,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "requestWebRtcLogsList",
+      base::BindRepeating(&WebRtcLogsDOMHandler::HandleRequestWebRtcLogs,
+                          base::Unretained(this)));
 }
 
 void WebRtcLogsDOMHandler::HandleRequestWebRtcLogs(
diff --git a/chrome/browser/ui/webui/media_router/media_router_webui_message_handler.cc b/chrome/browser/ui/webui/media_router/media_router_webui_message_handler.cc
index 51ae200..c04434f 100644
--- a/chrome/browser/ui/webui/media_router/media_router_webui_message_handler.cc
+++ b/chrome/browser/ui/webui/media_router/media_router_webui_message_handler.cc
@@ -374,127 +374,151 @@
 void MediaRouterWebUIMessageHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       kRequestInitialData,
-      base::Bind(&MediaRouterWebUIMessageHandler::OnRequestInitialData,
-                 base::Unretained(this)));
+      base::BindRepeating(&MediaRouterWebUIMessageHandler::OnRequestInitialData,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      kCreateRoute, base::Bind(&MediaRouterWebUIMessageHandler::OnCreateRoute,
-                               base::Unretained(this)));
+      kCreateRoute,
+      base::BindRepeating(&MediaRouterWebUIMessageHandler::OnCreateRoute,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kAcknowledgeFirstRunFlow,
-      base::Bind(&MediaRouterWebUIMessageHandler::OnAcknowledgeFirstRunFlow,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &MediaRouterWebUIMessageHandler::OnAcknowledgeFirstRunFlow,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      kActOnIssue, base::Bind(&MediaRouterWebUIMessageHandler::OnActOnIssue,
-                              base::Unretained(this)));
+      kActOnIssue,
+      base::BindRepeating(&MediaRouterWebUIMessageHandler::OnActOnIssue,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      kCloseRoute, base::Bind(&MediaRouterWebUIMessageHandler::OnCloseRoute,
-                              base::Unretained(this)));
+      kCloseRoute,
+      base::BindRepeating(&MediaRouterWebUIMessageHandler::OnCloseRoute,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      kJoinRoute, base::Bind(&MediaRouterWebUIMessageHandler::OnJoinRoute,
-                             base::Unretained(this)));
+      kJoinRoute,
+      base::BindRepeating(&MediaRouterWebUIMessageHandler::OnJoinRoute,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      kCloseDialog, base::Bind(&MediaRouterWebUIMessageHandler::OnCloseDialog,
-                               base::Unretained(this)));
+      kCloseDialog,
+      base::BindRepeating(&MediaRouterWebUIMessageHandler::OnCloseDialog,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      kReportBlur, base::Bind(&MediaRouterWebUIMessageHandler::OnReportBlur,
-                              base::Unretained(this)));
+      kReportBlur,
+      base::BindRepeating(&MediaRouterWebUIMessageHandler::OnReportBlur,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kReportClickedSinkIndex,
-      base::Bind(&MediaRouterWebUIMessageHandler::OnReportClickedSinkIndex,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &MediaRouterWebUIMessageHandler::OnReportClickedSinkIndex,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      kReportFilter, base::Bind(&MediaRouterWebUIMessageHandler::OnReportFilter,
-                                base::Unretained(this)));
+      kReportFilter,
+      base::BindRepeating(&MediaRouterWebUIMessageHandler::OnReportFilter,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kReportInitialState,
-      base::Bind(&MediaRouterWebUIMessageHandler::OnReportInitialState,
-                 base::Unretained(this)));
+      base::BindRepeating(&MediaRouterWebUIMessageHandler::OnReportInitialState,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kReportInitialAction,
-      base::Bind(&MediaRouterWebUIMessageHandler::OnReportInitialAction,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &MediaRouterWebUIMessageHandler::OnReportInitialAction,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kReportRouteCreation,
-      base::Bind(&MediaRouterWebUIMessageHandler::OnReportRouteCreation,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &MediaRouterWebUIMessageHandler::OnReportRouteCreation,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kReportRouteCreationOutcome,
-      base::Bind(&MediaRouterWebUIMessageHandler::OnReportRouteCreationOutcome,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &MediaRouterWebUIMessageHandler::OnReportRouteCreationOutcome,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kReportSelectedCastMode,
-      base::Bind(&MediaRouterWebUIMessageHandler::OnReportSelectedCastMode,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &MediaRouterWebUIMessageHandler::OnReportSelectedCastMode,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kReportNavigateToView,
-      base::Bind(&MediaRouterWebUIMessageHandler::OnReportNavigateToView,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &MediaRouterWebUIMessageHandler::OnReportNavigateToView,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kReportSinkCount,
-      base::Bind(&MediaRouterWebUIMessageHandler::OnReportSinkCount,
-                 base::Unretained(this)));
+      base::BindRepeating(&MediaRouterWebUIMessageHandler::OnReportSinkCount,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kReportTimeToClickSink,
-      base::Bind(&MediaRouterWebUIMessageHandler::OnReportTimeToClickSink,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &MediaRouterWebUIMessageHandler::OnReportTimeToClickSink,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kReportTimeToInitialActionClose,
-      base::Bind(
+      base::BindRepeating(
           &MediaRouterWebUIMessageHandler::OnReportTimeToInitialActionClose,
           base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kReportWebUIRouteControllerLoaded,
-      base::Bind(
+      base::BindRepeating(
           &MediaRouterWebUIMessageHandler::OnReportWebUIRouteControllerLoaded,
           base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kSearchSinksAndCreateRoute,
-      base::Bind(&MediaRouterWebUIMessageHandler::OnSearchSinksAndCreateRoute,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &MediaRouterWebUIMessageHandler::OnSearchSinksAndCreateRoute,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kOnInitialDataReceived,
-      base::Bind(&MediaRouterWebUIMessageHandler::OnInitialDataReceived,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &MediaRouterWebUIMessageHandler::OnInitialDataReceived,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kOnMediaControllerAvailable,
-      base::Bind(&MediaRouterWebUIMessageHandler::OnMediaControllerAvailable,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &MediaRouterWebUIMessageHandler::OnMediaControllerAvailable,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kOnMediaControllerClosed,
-      base::Bind(&MediaRouterWebUIMessageHandler::OnMediaControllerClosed,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &MediaRouterWebUIMessageHandler::OnMediaControllerClosed,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kPauseCurrentMedia,
-      base::Bind(&MediaRouterWebUIMessageHandler::OnPauseCurrentMedia,
-                 base::Unretained(this)));
+      base::BindRepeating(&MediaRouterWebUIMessageHandler::OnPauseCurrentMedia,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kPlayCurrentMedia,
-      base::Bind(&MediaRouterWebUIMessageHandler::OnPlayCurrentMedia,
-                 base::Unretained(this)));
+      base::BindRepeating(&MediaRouterWebUIMessageHandler::OnPlayCurrentMedia,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kSeekCurrentMedia,
-      base::Bind(&MediaRouterWebUIMessageHandler::OnSeekCurrentMedia,
-                 base::Unretained(this)));
+      base::BindRepeating(&MediaRouterWebUIMessageHandler::OnSeekCurrentMedia,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kSelectLocalMediaFile,
-      base::Bind(&MediaRouterWebUIMessageHandler::OnSelectLocalMediaFile,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &MediaRouterWebUIMessageHandler::OnSelectLocalMediaFile,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kSetCurrentMediaMute,
-      base::Bind(&MediaRouterWebUIMessageHandler::OnSetCurrentMediaMute,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &MediaRouterWebUIMessageHandler::OnSetCurrentMediaMute,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kSetCurrentMediaVolume,
-      base::Bind(&MediaRouterWebUIMessageHandler::OnSetCurrentMediaVolume,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &MediaRouterWebUIMessageHandler::OnSetCurrentMediaVolume,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kSetMediaRemotingEnabled,
-      base::Bind(&MediaRouterWebUIMessageHandler::OnSetMediaRemotingEnabled,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &MediaRouterWebUIMessageHandler::OnSetMediaRemotingEnabled,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kHangoutsSetLocalPresent,
-      base::Bind(&MediaRouterWebUIMessageHandler::OnSetHangoutsLocalPresent,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &MediaRouterWebUIMessageHandler::OnSetHangoutsLocalPresent,
+          base::Unretained(this)));
 }
 
 void MediaRouterWebUIMessageHandler::OnRequestInitialData(
diff --git a/chrome/browser/ui/webui/memory_internals_ui.cc b/chrome/browser/ui/webui/memory_internals_ui.cc
index c38eda3..fb970e4 100644
--- a/chrome/browser/ui/webui/memory_internals_ui.cc
+++ b/chrome/browser/ui/webui/memory_internals_ui.cc
@@ -171,8 +171,8 @@
   // the WebUI.
   web_ui()->RegisterMessageCallback(
       "requestProcessList",
-      base::Bind(&MemoryInternalsDOMHandler::HandleRequestProcessList,
-                 base::Unretained(this)));
+      base::BindRepeating(&MemoryInternalsDOMHandler::HandleRequestProcessList,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "saveDump",
       base::BindRepeating(&MemoryInternalsDOMHandler::HandleSaveDump,
diff --git a/chrome/browser/ui/webui/metrics_handler.cc b/chrome/browser/ui/webui/metrics_handler.cc
index 21fcb2cb..6911732 100644
--- a/chrome/browser/ui/webui/metrics_handler.cc
+++ b/chrome/browser/ui/webui/metrics_handler.cc
@@ -26,21 +26,24 @@
 void MetricsHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "metricsHandler:recordAction",
-      base::Bind(&MetricsHandler::HandleRecordAction, base::Unretained(this)));
+      base::BindRepeating(&MetricsHandler::HandleRecordAction,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "metricsHandler:recordInHistogram",
-      base::Bind(&MetricsHandler::HandleRecordInHistogram,
-                 base::Unretained(this)));
+      base::BindRepeating(&MetricsHandler::HandleRecordInHistogram,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "metricsHandler:recordBooleanHistogram",
-      base::Bind(&MetricsHandler::HandleRecordBooleanHistogram,
-                 base::Unretained(this)));
+      base::BindRepeating(&MetricsHandler::HandleRecordBooleanHistogram,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "metricsHandler:recordTime",
-      base::Bind(&MetricsHandler::HandleRecordTime, base::Unretained(this)));
+      base::BindRepeating(&MetricsHandler::HandleRecordTime,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "metricsHandler:logEventTime",
-      base::Bind(&MetricsHandler::HandleLogEventTime, base::Unretained(this)));
+      base::BindRepeating(&MetricsHandler::HandleLogEventTime,
+                          base::Unretained(this)));
 }
 
 void MetricsHandler::HandleRecordAction(const base::ListValue* args) {
diff --git a/chrome/browser/ui/webui/nacl_ui.cc b/chrome/browser/ui/webui/nacl_ui.cc
index d2acc6d..153107f0 100644
--- a/chrome/browser/ui/webui/nacl_ui.cc
+++ b/chrome/browser/ui/webui/nacl_ui.cc
@@ -151,8 +151,8 @@
 void NaClDomHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "requestNaClInfo",
-      base::Bind(&NaClDomHandler::HandleRequestNaClInfo,
-                 base::Unretained(this)));
+      base::BindRepeating(&NaClDomHandler::HandleRequestNaClInfo,
+                          base::Unretained(this)));
 }
 
 // Helper functions for collecting a list of key-value pairs that will
diff --git a/chrome/browser/ui/webui/net_export_ui.cc b/chrome/browser/ui/webui/net_export_ui.cc
index 896cdb11..24a70cf 100644
--- a/chrome/browser/ui/webui/net_export_ui.cc
+++ b/chrome/browser/ui/webui/net_export_ui.cc
@@ -185,23 +185,24 @@
 
   web_ui()->RegisterMessageCallback(
       net_log::kEnableNotifyUIWithStateHandler,
-      base::Bind(&NetExportMessageHandler::OnEnableNotifyUIWithState,
-                 base::Unretained(this)));
+      base::BindRepeating(&NetExportMessageHandler::OnEnableNotifyUIWithState,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       net_log::kStartNetLogHandler,
-      base::Bind(&NetExportMessageHandler::OnStartNetLog,
-                 base::Unretained(this)));
+      base::BindRepeating(&NetExportMessageHandler::OnStartNetLog,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       net_log::kStopNetLogHandler,
-      base::Bind(&NetExportMessageHandler::OnStopNetLog,
-                 base::Unretained(this)));
+      base::BindRepeating(&NetExportMessageHandler::OnStopNetLog,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       net_log::kSendNetLogHandler,
-      base::Bind(&NetExportMessageHandler::OnSendNetLog,
-                 base::Unretained(this)));
+      base::BindRepeating(&NetExportMessageHandler::OnSendNetLog,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       net_log::kShowFile,
-      base::Bind(&NetExportMessageHandler::OnShowFile, base::Unretained(this)));
+      base::BindRepeating(&NetExportMessageHandler::OnShowFile,
+                          base::Unretained(this)));
 }
 
 // The net-export UI is not notified of state changes until this function runs.
diff --git a/chrome/browser/ui/webui/net_internals/net_internals_ui.cc b/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
index 3c8c7e3..9a9192ba 100644
--- a/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
+++ b/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
@@ -424,101 +424,102 @@
 
   web_ui()->RegisterMessageCallback(
       "notifyReady",
-      base::Bind(&NetInternalsMessageHandler::OnRendererReady,
-                 base::Unretained(this)));
+      base::BindRepeating(&NetInternalsMessageHandler::OnRendererReady,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "getNetInfo",
-      base::Bind(&IOThreadImpl::CallbackHelper,
-                 &IOThreadImpl::OnGetNetInfo, proxy_));
+      "getNetInfo", base::BindRepeating(&IOThreadImpl::CallbackHelper,
+                                        &IOThreadImpl::OnGetNetInfo, proxy_));
   web_ui()->RegisterMessageCallback(
       "reloadProxySettings",
-      base::Bind(&IOThreadImpl::CallbackHelper,
-                 &IOThreadImpl::OnReloadProxySettings, proxy_));
+      base::BindRepeating(&IOThreadImpl::CallbackHelper,
+                          &IOThreadImpl::OnReloadProxySettings, proxy_));
   web_ui()->RegisterMessageCallback(
       "clearBadProxies",
-      base::Bind(&IOThreadImpl::CallbackHelper,
-                 &IOThreadImpl::OnClearBadProxies, proxy_));
+      base::BindRepeating(&IOThreadImpl::CallbackHelper,
+                          &IOThreadImpl::OnClearBadProxies, proxy_));
   web_ui()->RegisterMessageCallback(
       "clearHostResolverCache",
-      base::Bind(&IOThreadImpl::CallbackHelper,
-                 &IOThreadImpl::OnClearHostResolverCache, proxy_));
+      base::BindRepeating(&IOThreadImpl::CallbackHelper,
+                          &IOThreadImpl::OnClearHostResolverCache, proxy_));
   web_ui()->RegisterMessageCallback(
       "domainSecurityPolicyDelete",
-      base::Bind(&IOThreadImpl::CallbackHelper,
-                 &IOThreadImpl::OnDomainSecurityPolicyDelete, proxy_));
+      base::BindRepeating(&IOThreadImpl::CallbackHelper,
+                          &IOThreadImpl::OnDomainSecurityPolicyDelete, proxy_));
   web_ui()->RegisterMessageCallback(
-      "hstsQuery",
-      base::Bind(&IOThreadImpl::CallbackHelper,
-                 &IOThreadImpl::OnHSTSQuery, proxy_));
+      "hstsQuery", base::BindRepeating(&IOThreadImpl::CallbackHelper,
+                                       &IOThreadImpl::OnHSTSQuery, proxy_));
   web_ui()->RegisterMessageCallback(
-      "hstsAdd",
-      base::Bind(&IOThreadImpl::CallbackHelper,
-                 &IOThreadImpl::OnHSTSAdd, proxy_));
+      "hstsAdd", base::BindRepeating(&IOThreadImpl::CallbackHelper,
+                                     &IOThreadImpl::OnHSTSAdd, proxy_));
   web_ui()->RegisterMessageCallback(
-      "expectCTQuery", base::Bind(&IOThreadImpl::CallbackHelper,
-                                  &IOThreadImpl::OnExpectCTQuery, proxy_));
+      "expectCTQuery",
+      base::BindRepeating(&IOThreadImpl::CallbackHelper,
+                          &IOThreadImpl::OnExpectCTQuery, proxy_));
   web_ui()->RegisterMessageCallback(
-      "expectCTAdd", base::Bind(&IOThreadImpl::CallbackHelper,
-                                &IOThreadImpl::OnExpectCTAdd, proxy_));
+      "expectCTAdd", base::BindRepeating(&IOThreadImpl::CallbackHelper,
+                                         &IOThreadImpl::OnExpectCTAdd, proxy_));
   web_ui()->RegisterMessageCallback(
       "expectCTTestReport",
-      base::Bind(&IOThreadImpl::CallbackHelper,
-                 &IOThreadImpl::OnExpectCTTestReport, proxy_));
+      base::BindRepeating(&IOThreadImpl::CallbackHelper,
+                          &IOThreadImpl::OnExpectCTTestReport, proxy_));
   web_ui()->RegisterMessageCallback(
       "closeIdleSockets",
-      base::Bind(&IOThreadImpl::CallbackHelper,
-                 &IOThreadImpl::OnCloseIdleSockets, proxy_));
+      base::BindRepeating(&IOThreadImpl::CallbackHelper,
+                          &IOThreadImpl::OnCloseIdleSockets, proxy_));
   web_ui()->RegisterMessageCallback(
       "flushSocketPools",
-      base::Bind(&IOThreadImpl::CallbackHelper,
-                 &IOThreadImpl::OnFlushSocketPools, proxy_));
+      base::BindRepeating(&IOThreadImpl::CallbackHelper,
+                          &IOThreadImpl::OnFlushSocketPools, proxy_));
 #if defined(OS_WIN)
   web_ui()->RegisterMessageCallback(
       "getServiceProviders",
-      base::Bind(&IOThreadImpl::CallbackHelper,
-                 &IOThreadImpl::OnGetServiceProviders, proxy_));
+      base::BindRepeating(&IOThreadImpl::CallbackHelper,
+                          &IOThreadImpl::OnGetServiceProviders, proxy_));
 #endif
 
   web_ui()->RegisterMessageCallback(
-      "setCaptureMode", base::Bind(&IOThreadImpl::CallbackHelper,
-                                   &IOThreadImpl::OnSetCaptureMode, proxy_));
+      "setCaptureMode",
+      base::BindRepeating(&IOThreadImpl::CallbackHelper,
+                          &IOThreadImpl::OnSetCaptureMode, proxy_));
   web_ui()->RegisterMessageCallback(
       "clearBrowserCache",
-      base::Bind(&NetInternalsMessageHandler::OnClearBrowserCache,
-                 base::Unretained(this)));
+      base::BindRepeating(&NetInternalsMessageHandler::OnClearBrowserCache,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "getPrerenderInfo",
-      base::Bind(&NetInternalsMessageHandler::OnGetPrerenderInfo,
-                 base::Unretained(this)));
+      base::BindRepeating(&NetInternalsMessageHandler::OnGetPrerenderInfo,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "getHistoricNetworkStats",
-      base::Bind(&NetInternalsMessageHandler::OnGetHistoricNetworkStats,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &NetInternalsMessageHandler::OnGetHistoricNetworkStats,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "getSessionNetworkStats",
-      base::Bind(&NetInternalsMessageHandler::OnGetSessionNetworkStats,
-                 base::Unretained(this)));
+      base::BindRepeating(&NetInternalsMessageHandler::OnGetSessionNetworkStats,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "getExtensionInfo",
-      base::Bind(&NetInternalsMessageHandler::OnGetExtensionInfo,
-                 base::Unretained(this)));
+      base::BindRepeating(&NetInternalsMessageHandler::OnGetExtensionInfo,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "getDataReductionProxyInfo",
-      base::Bind(&NetInternalsMessageHandler::OnGetDataReductionProxyInfo,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &NetInternalsMessageHandler::OnGetDataReductionProxyInfo,
+          base::Unretained(this)));
 #if defined(OS_CHROMEOS)
   web_ui()->RegisterMessageCallback(
       "importONCFile",
-      base::Bind(&NetInternalsMessageHandler::OnImportONCFile,
-                 base::Unretained(this)));
+      base::BindRepeating(&NetInternalsMessageHandler::OnImportONCFile,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "storeDebugLogs",
-      base::Bind(&NetInternalsMessageHandler::OnStoreDebugLogs,
-                 base::Unretained(this)));
+      base::BindRepeating(&NetInternalsMessageHandler::OnStoreDebugLogs,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "setNetworkDebugMode",
-      base::Bind(&NetInternalsMessageHandler::OnSetNetworkDebugMode,
-                 base::Unretained(this)));
+      base::BindRepeating(&NetInternalsMessageHandler::OnSetNetworkDebugMode,
+                          base::Unretained(this)));
 #endif
 }
 
diff --git a/chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.cc b/chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.cc
index 4082f857..ac58f8b1 100644
--- a/chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.cc
@@ -188,41 +188,53 @@
 }
 
 void NetInternalsTest::MessageHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback("getTestServerURL",
-      base::Bind(&NetInternalsTest::MessageHandler::GetTestServerURL,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("addCacheEntry",
-      base::Bind(&NetInternalsTest::MessageHandler::AddCacheEntry,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "getTestServerURL",
+      base::BindRepeating(&NetInternalsTest::MessageHandler::GetTestServerURL,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "addCacheEntry",
+      base::BindRepeating(&NetInternalsTest::MessageHandler::AddCacheEntry,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "changeNetwork",
-      base::Bind(&NetInternalsTest::MessageHandler::ChangeNetwork,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("loadPage",
-      base::Bind(&NetInternalsTest::MessageHandler::LoadPage,
-                  base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("prerenderPage",
-      base::Bind(&NetInternalsTest::MessageHandler::PrerenderPage,
-                  base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("navigateToPrerender",
-      base::Bind(&NetInternalsTest::MessageHandler::NavigateToPrerender,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("createIncognitoBrowser",
-      base::Bind(&NetInternalsTest::MessageHandler::CreateIncognitoBrowser,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("closeIncognitoBrowser",
-      base::Bind(&NetInternalsTest::MessageHandler::CloseIncognitoBrowser,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("getNetLogFileContents",
-      base::Bind(
+      base::BindRepeating(&NetInternalsTest::MessageHandler::ChangeNetwork,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "loadPage",
+      base::BindRepeating(&NetInternalsTest::MessageHandler::LoadPage,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "prerenderPage",
+      base::BindRepeating(&NetInternalsTest::MessageHandler::PrerenderPage,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "navigateToPrerender",
+      base::BindRepeating(
+          &NetInternalsTest::MessageHandler::NavigateToPrerender,
+          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "createIncognitoBrowser",
+      base::BindRepeating(
+          &NetInternalsTest::MessageHandler::CreateIncognitoBrowser,
+          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "closeIncognitoBrowser",
+      base::BindRepeating(
+          &NetInternalsTest::MessageHandler::CloseIncognitoBrowser,
+          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "getNetLogFileContents",
+      base::BindRepeating(
           &NetInternalsTest::MessageHandler::GetNetLogFileContents,
           base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "setUpTestReportURI",
-      base::Bind(&NetInternalsTest::MessageHandler::SetUpTestReportURI,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("enableDataReductionProxy",
-      base::Bind(
+      base::BindRepeating(&NetInternalsTest::MessageHandler::SetUpTestReportURI,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "enableDataReductionProxy",
+      base::BindRepeating(
           &NetInternalsTest::MessageHandler::EnableDataReductionProxy,
           base::Unretained(this)));
 }
diff --git a/chrome/browser/ui/webui/ntp/app_icon_webui_handler.cc b/chrome/browser/ui/webui/ntp/app_icon_webui_handler.cc
index beaad4ec..fe8bd9c 100644
--- a/chrome/browser/ui/webui/ntp/app_icon_webui_handler.cc
+++ b/chrome/browser/ui/webui/ntp/app_icon_webui_handler.cc
@@ -39,8 +39,8 @@
 void AppIconWebUIHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "getAppIconDominantColor",
-      base::Bind(&AppIconWebUIHandler::HandleGetAppIconDominantColor,
-                 base::Unretained(this)));
+      base::BindRepeating(&AppIconWebUIHandler::HandleGetAppIconDominantColor,
+                          base::Unretained(this)));
 }
 
 void AppIconWebUIHandler::HandleGetAppIconDominantColor(
diff --git a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
index 604df9e..a073ddf6 100644
--- a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
+++ b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
@@ -223,39 +223,46 @@
   registrar_.Add(this, chrome::NOTIFICATION_APP_INSTALLED_TO_NTP,
       content::Source<WebContents>(web_ui()->GetWebContents()));
 
-  web_ui()->RegisterMessageCallback("getApps",
-      base::Bind(&AppLauncherHandler::HandleGetApps,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("launchApp",
-      base::Bind(&AppLauncherHandler::HandleLaunchApp,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("setLaunchType",
-      base::Bind(&AppLauncherHandler::HandleSetLaunchType,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("uninstallApp",
-      base::Bind(&AppLauncherHandler::HandleUninstallApp,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("createAppShortcut",
-      base::Bind(&AppLauncherHandler::HandleCreateAppShortcut,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("showAppInfo",
-      base::Bind(&AppLauncherHandler::HandleShowAppInfo,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("reorderApps",
-      base::Bind(&AppLauncherHandler::HandleReorderApps,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("setPageIndex",
-      base::Bind(&AppLauncherHandler::HandleSetPageIndex,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("saveAppPageName",
-      base::Bind(&AppLauncherHandler::HandleSaveAppPageName,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("generateAppForLink",
-      base::Bind(&AppLauncherHandler::HandleGenerateAppForLink,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("pageSelected",
-      base::Bind(&AppLauncherHandler::HandlePageSelected,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "getApps", base::BindRepeating(&AppLauncherHandler::HandleGetApps,
+                                     base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "launchApp", base::BindRepeating(&AppLauncherHandler::HandleLaunchApp,
+                                       base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "setLaunchType",
+      base::BindRepeating(&AppLauncherHandler::HandleSetLaunchType,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "uninstallApp",
+      base::BindRepeating(&AppLauncherHandler::HandleUninstallApp,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "createAppShortcut",
+      base::BindRepeating(&AppLauncherHandler::HandleCreateAppShortcut,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "showAppInfo", base::BindRepeating(&AppLauncherHandler::HandleShowAppInfo,
+                                         base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "reorderApps", base::BindRepeating(&AppLauncherHandler::HandleReorderApps,
+                                         base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "setPageIndex",
+      base::BindRepeating(&AppLauncherHandler::HandleSetPageIndex,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "saveAppPageName",
+      base::BindRepeating(&AppLauncherHandler::HandleSaveAppPageName,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "generateAppForLink",
+      base::BindRepeating(&AppLauncherHandler::HandleGenerateAppForLink,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "pageSelected",
+      base::BindRepeating(&AppLauncherHandler::HandlePageSelected,
+                          base::Unretained(this)));
 }
 
 void AppLauncherHandler::Observe(int type,
diff --git a/chrome/browser/ui/webui/ntp/core_app_launcher_handler.cc b/chrome/browser/ui/webui/ntp/core_app_launcher_handler.cc
index 4257360..da34298 100644
--- a/chrome/browser/ui/webui/ntp/core_app_launcher_handler.cc
+++ b/chrome/browser/ui/webui/ntp/core_app_launcher_handler.cc
@@ -64,7 +64,8 @@
 }
 
 void CoreAppLauncherHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback("recordAppLaunchByURL",
-      base::Bind(&CoreAppLauncherHandler::HandleRecordAppLaunchByUrl,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "recordAppLaunchByURL",
+      base::BindRepeating(&CoreAppLauncherHandler::HandleRecordAppLaunchByUrl,
+                          base::Unretained(this)));
 }
diff --git a/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc b/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc
index 5513e2c..7915180 100644
--- a/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc
+++ b/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc
@@ -50,7 +50,8 @@
   PrefService* GetPrefs() override;
   void RegisterMessageCallback(
       const std::string& message,
-      const base::Callback<void(const base::ListValue*)>& callback) override;
+      const base::RepeatingCallback<void(const base::ListValue*)>& callback)
+      override;
   void CallJavascriptFunctionVector(
       const std::string& name,
       const std::vector<const base::Value*>& values) override;
@@ -101,7 +102,7 @@
 
 void ChromeNTPTilesInternalsMessageHandlerClient::RegisterMessageCallback(
     const std::string& message,
-    const base::Callback<void(const base::ListValue*)>& callback) {
+    const base::RepeatingCallback<void(const base::ListValue*)>& callback) {
   web_ui()->RegisterMessageCallback(message, callback);
 }
 
diff --git a/chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.cc b/chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.cc
index 8053b7a..9ca918dd 100644
--- a/chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.cc
+++ b/chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.cc
@@ -492,75 +492,86 @@
 void OfflineInternalsUIMessageHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "deleteSelectedPages",
-      base::Bind(&OfflineInternalsUIMessageHandler::HandleDeleteSelectedPages,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &OfflineInternalsUIMessageHandler::HandleDeleteSelectedPages,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "deleteSelectedRequests",
-      base::Bind(
+      base::BindRepeating(
           &OfflineInternalsUIMessageHandler::HandleDeleteSelectedRequests,
           base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "getRequestQueue",
-      base::Bind(&OfflineInternalsUIMessageHandler::HandleGetRequestQueue,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &OfflineInternalsUIMessageHandler::HandleGetRequestQueue,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "getStoredPages",
-      base::Bind(&OfflineInternalsUIMessageHandler::HandleGetStoredPages,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &OfflineInternalsUIMessageHandler::HandleGetStoredPages,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "getEventLogs",
-      base::Bind(&OfflineInternalsUIMessageHandler::HandleGetEventLogs,
-                 base::Unretained(this)));
+      base::BindRepeating(&OfflineInternalsUIMessageHandler::HandleGetEventLogs,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "setRecordRequestQueue",
-      base::Bind(&OfflineInternalsUIMessageHandler::HandleSetRecordRequestQueue,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &OfflineInternalsUIMessageHandler::HandleSetRecordRequestQueue,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "setRecordPageModel",
-      base::Bind(&OfflineInternalsUIMessageHandler::HandleSetRecordPageModel,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &OfflineInternalsUIMessageHandler::HandleSetRecordPageModel,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "setRecordPrefetchService",
-      base::Bind(
+      base::BindRepeating(
           &OfflineInternalsUIMessageHandler::HandleSetRecordPrefetchService,
           base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "getLoggingState",
-      base::Bind(&OfflineInternalsUIMessageHandler::HandleGetLoggingState,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &OfflineInternalsUIMessageHandler::HandleGetLoggingState,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "addToRequestQueue",
-      base::Bind(&OfflineInternalsUIMessageHandler::HandleAddToRequestQueue,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &OfflineInternalsUIMessageHandler::HandleAddToRequestQueue,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "getNetworkStatus",
-      base::Bind(&OfflineInternalsUIMessageHandler::HandleGetNetworkStatus,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &OfflineInternalsUIMessageHandler::HandleGetNetworkStatus,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "scheduleNwake",
-      base::Bind(&OfflineInternalsUIMessageHandler::HandleScheduleNwake,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &OfflineInternalsUIMessageHandler::HandleScheduleNwake,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "cancelNwake",
-      base::Bind(&OfflineInternalsUIMessageHandler::HandleCancelNwake,
-                 base::Unretained(this)));
+      base::BindRepeating(&OfflineInternalsUIMessageHandler::HandleCancelNwake,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "showPrefetchNotification",
-      base::Bind(
+      base::BindRepeating(
           &OfflineInternalsUIMessageHandler::HandleShowPrefetchNotification,
           base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "generatePageBundle",
-      base::Bind(&OfflineInternalsUIMessageHandler::HandleGeneratePageBundle,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &OfflineInternalsUIMessageHandler::HandleGeneratePageBundle,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "getOperation",
-      base::Bind(&OfflineInternalsUIMessageHandler::HandleGetOperation,
-                 base::Unretained(this)));
+      base::BindRepeating(&OfflineInternalsUIMessageHandler::HandleGetOperation,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "downloadArchive",
-      base::Bind(&OfflineInternalsUIMessageHandler::HandleDownloadArchive,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &OfflineInternalsUIMessageHandler::HandleDownloadArchive,
+          base::Unretained(this)));
 
   // Get the offline page model associated with this web ui.
   Profile* profile = Profile::FromWebUI(web_ui());
diff --git a/chrome/browser/ui/webui/plural_string_handler.cc b/chrome/browser/ui/webui/plural_string_handler.cc
index 4693d19..69cd5e22 100644
--- a/chrome/browser/ui/webui/plural_string_handler.cc
+++ b/chrome/browser/ui/webui/plural_string_handler.cc
@@ -16,8 +16,9 @@
 
 void PluralStringHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
-      "getPluralString", base::Bind(&PluralStringHandler::HandleGetPluralString,
-                                    base::Unretained(this)));
+      "getPluralString",
+      base::BindRepeating(&PluralStringHandler::HandleGetPluralString,
+                          base::Unretained(this)));
 }
 
 void PluralStringHandler::AddLocalizedString(const std::string& name, int id) {
diff --git a/chrome/browser/ui/webui/policy_ui_handler.cc b/chrome/browser/ui/webui/policy_ui_handler.cc
index 8ca7434..c39da0a 100644
--- a/chrome/browser/ui/webui/policy_ui_handler.cc
+++ b/chrome/browser/ui/webui/policy_ui_handler.cc
@@ -633,16 +633,16 @@
   registry->AddObserver(this);
 
   web_ui()->RegisterMessageCallback(
-      "initialized",
-      base::Bind(&PolicyUIHandler::HandleInitialized, base::Unretained(this)));
+      "initialized", base::BindRepeating(&PolicyUIHandler::HandleInitialized,
+                                         base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "reloadPolicies",
-      base::Bind(&PolicyUIHandler::HandleReloadPolicies,
-                 base::Unretained(this)));
+      base::BindRepeating(&PolicyUIHandler::HandleReloadPolicies,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "exportPoliciesJSON",
-      base::Bind(&PolicyUIHandler::HandleExportPoliciesJSON,
-                 base::Unretained(this)));
+      base::BindRepeating(&PolicyUIHandler::HandleExportPoliciesJSON,
+                          base::Unretained(this)));
 }
 
 #if BUILDFLAG(ENABLE_EXTENSIONS)
diff --git a/chrome/browser/ui/webui/predictors/predictors_handler.cc b/chrome/browser/ui/webui/predictors/predictors_handler.cc
index 7a33859..50387cd 100644
--- a/chrome/browser/ui/webui/predictors/predictors_handler.cc
+++ b/chrome/browser/ui/webui/predictors/predictors_handler.cc
@@ -33,12 +33,16 @@
 PredictorsHandler::~PredictorsHandler() { }
 
 void PredictorsHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback("requestAutocompleteActionPredictorDb",
-      base::Bind(&PredictorsHandler::RequestAutocompleteActionPredictorDb,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("requestResourcePrefetchPredictorDb",
-      base::Bind(&PredictorsHandler::RequestResourcePrefetchPredictorDb,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "requestAutocompleteActionPredictorDb",
+      base::BindRepeating(
+          &PredictorsHandler::RequestAutocompleteActionPredictorDb,
+          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "requestResourcePrefetchPredictorDb",
+      base::BindRepeating(
+          &PredictorsHandler::RequestResourcePrefetchPredictorDb,
+          base::Unretained(this)));
 }
 
 void PredictorsHandler::RequestAutocompleteActionPredictorDb(
diff --git a/chrome/browser/ui/webui/print_preview/extension_printer_handler.cc b/chrome/browser/ui/webui/print_preview/extension_printer_handler.cc
index 5bdf402..a6bd6ed 100644
--- a/chrome/browser/ui/webui/print_preview/extension_printer_handler.cc
+++ b/chrome/browser/ui/webui/print_preview/extension_printer_handler.cc
@@ -185,7 +185,7 @@
     const base::string16& job_title,
     const std::string& ticket_json,
     const gfx::Size& page_size,
-    const scoped_refptr<base::RefCountedBytes>& print_data,
+    const scoped_refptr<base::RefCountedMemory>& print_data,
     PrintCallback callback) {
   auto print_job = std::make_unique<extensions::PrinterProviderPrintJob>();
   print_job->printer_id = destination_id;
diff --git a/chrome/browser/ui/webui/print_preview/extension_printer_handler.h b/chrome/browser/ui/webui/print_preview/extension_printer_handler.h
index 005ad93..ce7ab8f 100644
--- a/chrome/browser/ui/webui/print_preview/extension_printer_handler.h
+++ b/chrome/browser/ui/webui/print_preview/extension_printer_handler.h
@@ -18,7 +18,6 @@
 namespace base {
 class DictionaryValue;
 class ListValue;
-class RefCountedBytes;
 class RefCountedMemory;
 }
 
@@ -63,7 +62,7 @@
                   const base::string16& job_title,
                   const std::string& ticket_json,
                   const gfx::Size& page_size,
-                  const scoped_refptr<base::RefCountedBytes>& print_data,
+                  const scoped_refptr<base::RefCountedMemory>& print_data,
                   PrintCallback callback) override;
   void StartGrantPrinterAccess(const std::string& printer_id,
                                GetPrinterInfoCallback callback) override;
diff --git a/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc b/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc
index 09c7646d..70180e76 100644
--- a/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc
+++ b/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc
@@ -202,7 +202,7 @@
     const base::string16& job_title,
     const std::string& ticket_json,
     const gfx::Size& page_size,
-    const scoped_refptr<base::RefCountedBytes>& print_data,
+    const scoped_refptr<base::RefCountedMemory>& print_data,
     PrintCallback callback) {
   printing::StartLocalPrint(ticket_json, print_data, preview_web_contents_,
                             std::move(callback));
diff --git a/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.h b/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.h
index b22c9bc58..a96aa70 100644
--- a/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.h
+++ b/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.h
@@ -41,7 +41,7 @@
                   const base::string16& job_title,
                   const std::string& ticket_json,
                   const gfx::Size& page_size,
-                  const scoped_refptr<base::RefCountedBytes>& print_data,
+                  const scoped_refptr<base::RefCountedMemory>& print_data,
                   PrintCallback callback) override;
 
  private:
diff --git a/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc b/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc
index c756a0ba..6c7b700a 100644
--- a/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc
+++ b/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc
@@ -108,7 +108,7 @@
     const base::string16& job_title,
     const std::string& ticket_json,
     const gfx::Size& page_size,
-    const scoped_refptr<base::RefCountedBytes>& print_data,
+    const scoped_refptr<base::RefCountedMemory>& print_data,
     PrintCallback callback) {
   printing::StartLocalPrint(ticket_json, print_data, preview_web_contents_,
                             std::move(callback));
diff --git a/chrome/browser/ui/webui/print_preview/local_printer_handler_default.h b/chrome/browser/ui/webui/print_preview/local_printer_handler_default.h
index ab07dea..a9da375 100644
--- a/chrome/browser/ui/webui/print_preview/local_printer_handler_default.h
+++ b/chrome/browser/ui/webui/print_preview/local_printer_handler_default.h
@@ -36,7 +36,7 @@
                   const base::string16& job_title,
                   const std::string& ticket_json,
                   const gfx::Size& page_size,
-                  const scoped_refptr<base::RefCountedBytes>& print_data,
+                  const scoped_refptr<base::RefCountedMemory>& print_data,
                   PrintCallback callback) override;
 
  private:
diff --git a/chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc b/chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc
index 52fbb52..a09caf94 100644
--- a/chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc
+++ b/chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc
@@ -111,7 +111,7 @@
 }
 
 // Callback that stores a PDF file on disk.
-void PrintToPdfCallback(const scoped_refptr<base::RefCountedBytes>& data,
+void PrintToPdfCallback(const scoped_refptr<base::RefCountedMemory>& data,
                         const base::FilePath& path,
                         const base::Closure& pdf_file_saved_closure) {
   base::File file(path,
@@ -184,7 +184,7 @@
     const base::string16& job_title,
     const std::string& ticket_json,
     const gfx::Size& page_size,
-    const scoped_refptr<base::RefCountedBytes>& print_data,
+    const scoped_refptr<base::RefCountedMemory>& print_data,
     PrintCallback callback) {
   print_data_ = print_data;
   if (!print_to_pdf_path_.empty()) {
diff --git a/chrome/browser/ui/webui/print_preview/pdf_printer_handler.h b/chrome/browser/ui/webui/print_preview/pdf_printer_handler.h
index 641fb89..ffa4bb4e 100644
--- a/chrome/browser/ui/webui/print_preview/pdf_printer_handler.h
+++ b/chrome/browser/ui/webui/print_preview/pdf_printer_handler.h
@@ -17,7 +17,7 @@
 #include "ui/shell_dialogs/select_file_dialog.h"
 
 namespace base {
-class RefCountedBytes;
+class RefCountedMemory;
 }
 
 namespace content {
@@ -56,7 +56,7 @@
                   const base::string16& job_title,
                   const std::string& ticket_json,
                   const gfx::Size& page_size,
-                  const scoped_refptr<base::RefCountedBytes>& print_data,
+                  const scoped_refptr<base::RefCountedMemory>& print_data,
                   PrintCallback callback) override;
 
   // SelectFileDialog::Listener implementation.
@@ -108,7 +108,7 @@
   base::Closure pdf_file_saved_closure_;
 
   // The data to print
-  scoped_refptr<base::RefCountedBytes> print_data_;
+  scoped_refptr<base::RefCountedMemory> print_data_;
 
   // The callback to call when complete.
   PrintCallback print_callback_;
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
index 9bce25e..200bb88e 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
@@ -410,58 +410,70 @@
 }
 
 void PrintPreviewHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback("getPrinters",
-      base::Bind(&PrintPreviewHandler::HandleGetPrinters,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("getPreview",
-      base::Bind(&PrintPreviewHandler::HandleGetPreview,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("print",
-      base::Bind(&PrintPreviewHandler::HandlePrint,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "getPrinters",
+      base::BindRepeating(&PrintPreviewHandler::HandleGetPrinters,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "getPreview", base::BindRepeating(&PrintPreviewHandler::HandleGetPreview,
+                                        base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "print", base::BindRepeating(&PrintPreviewHandler::HandlePrint,
+                                   base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "getPrinterCapabilities",
-      base::Bind(&PrintPreviewHandler::HandleGetPrinterCapabilities,
-                 base::Unretained(this)));
+      base::BindRepeating(&PrintPreviewHandler::HandleGetPrinterCapabilities,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "setupPrinter", base::Bind(&PrintPreviewHandler::HandlePrinterSetup,
-                                 base::Unretained(this)));
+      "setupPrinter",
+      base::BindRepeating(&PrintPreviewHandler::HandlePrinterSetup,
+                          base::Unretained(this)));
 #if BUILDFLAG(ENABLE_BASIC_PRINT_DIALOG)
-  web_ui()->RegisterMessageCallback("showSystemDialog",
-      base::Bind(&PrintPreviewHandler::HandleShowSystemDialog,
-                 base::Unretained(this)));
-#endif
-  web_ui()->RegisterMessageCallback("signIn",
-      base::Bind(&PrintPreviewHandler::HandleSignin,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("getAccessToken",
-      base::Bind(&PrintPreviewHandler::HandleGetAccessToken,
-                 base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "managePrinters", base::Bind(&PrintPreviewHandler::HandleManagePrinters,
-                                   base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("closePrintPreviewDialog",
-      base::Bind(&PrintPreviewHandler::HandleClosePreviewDialog,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("hidePreview",
-      base::Bind(&PrintPreviewHandler::HandleHidePreview,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("cancelPendingPrintRequest",
-      base::Bind(&PrintPreviewHandler::HandleCancelPendingPrintRequest,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("saveAppState",
-      base::Bind(&PrintPreviewHandler::HandleSaveAppState,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("getInitialSettings",
-      base::Bind(&PrintPreviewHandler::HandleGetInitialSettings,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("forceOpenNewTab",
-      base::Bind(&PrintPreviewHandler::HandleForceOpenNewTab,
-                 base::Unretained(this)));
+      "showSystemDialog",
+      base::BindRepeating(&PrintPreviewHandler::HandleShowSystemDialog,
+                          base::Unretained(this)));
+#endif
+  web_ui()->RegisterMessageCallback(
+      "signIn", base::BindRepeating(&PrintPreviewHandler::HandleSignin,
+                                    base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "getAccessToken",
+      base::BindRepeating(&PrintPreviewHandler::HandleGetAccessToken,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "managePrinters",
+      base::BindRepeating(&PrintPreviewHandler::HandleManagePrinters,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "closePrintPreviewDialog",
+      base::BindRepeating(&PrintPreviewHandler::HandleClosePreviewDialog,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "hidePreview",
+      base::BindRepeating(&PrintPreviewHandler::HandleHidePreview,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "cancelPendingPrintRequest",
+      base::BindRepeating(&PrintPreviewHandler::HandleCancelPendingPrintRequest,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "saveAppState",
+      base::BindRepeating(&PrintPreviewHandler::HandleSaveAppState,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "getInitialSettings",
+      base::BindRepeating(&PrintPreviewHandler::HandleGetInitialSettings,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "forceOpenNewTab",
+      base::BindRepeating(&PrintPreviewHandler::HandleForceOpenNewTab,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "grantExtensionPrinterAccess",
-      base::Bind(&PrintPreviewHandler::HandleGrantExtensionPrinterAccess,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &PrintPreviewHandler::HandleGrantExtensionPrinterAccess,
+          base::Unretained(this)));
 }
 
 void PrintPreviewHandler::OnJavascriptAllowed() {
@@ -708,7 +720,7 @@
     ReportUserActionHistogram(PRINT_WITH_CLOUD_PRINT);
   }
 
-  scoped_refptr<base::RefCountedBytes> data;
+  scoped_refptr<base::RefCountedMemory> data;
   print_preview_ui()->GetPrintPreviewDataForIndex(
       printing::COMPLETE_PREVIEW_DOCUMENT_INDEX, &data);
   if (!data) {
@@ -1032,11 +1044,11 @@
   }
 }
 
-void PrintPreviewHandler::SendCloudPrintJob(const std::string& callback_id,
-                                            const base::RefCountedBytes* data) {
+void PrintPreviewHandler::SendCloudPrintJob(
+    const std::string& callback_id,
+    const base::RefCountedMemory* data) {
   // BASE64 encode the job data.
-  const base::StringPiece raw_data(reinterpret_cast<const char*>(data->front()),
-                                   data->size());
+  const base::StringPiece raw_data(data->front_as<char>(), data->size());
   std::string base64_data;
   base::Base64Encode(raw_data, &base64_data);
 
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.h b/chrome/browser/ui/webui/print_preview/print_preview_handler.h
index 8efb847..e7e3b87 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_handler.h
+++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.h
@@ -27,7 +27,7 @@
 
 namespace base {
 class DictionaryValue;
-class RefCountedBytes;
+class RefCountedMemory;
 }
 
 namespace content {
@@ -246,7 +246,7 @@
 
   // Send the PDF data to the cloud to print.
   void SendCloudPrintJob(const std::string& callback_id,
-                         const base::RefCountedBytes* data);
+                         const base::RefCountedMemory* data);
 
   // Closes the preview dialog.
   void ClosePreviewDialog();
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc
index 91dfd885..287224f 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc
@@ -4,6 +4,10 @@
 
 #include "chrome/browser/ui/webui/print_preview/print_preview_handler.h"
 
+#include <map>
+#include <utility>
+#include <vector>
+
 #include "base/base64.h"
 #include "base/containers/flat_set.h"
 #include "base/json/json_writer.h"
@@ -203,7 +207,7 @@
                   const base::string16& job_title,
                   const std::string& ticket_json,
                   const gfx::Size& page_size,
-                  const scoped_refptr<base::RefCountedBytes>& print_data,
+                  const scoped_refptr<base::RefCountedMemory>& print_data,
                   PrintCallback callback) override {
     std::move(callback).Run(base::Value());
   }
@@ -239,8 +243,8 @@
 
   void GetPrintPreviewDataForIndex(
       int index,
-      scoped_refptr<base::RefCountedBytes>* data) const override {
-    *data = base::MakeRefCounted<base::RefCountedBytes>(
+      scoped_refptr<base::RefCountedMemory>* data) const override {
+    *data = base::MakeRefCounted<base::RefCountedStaticMemory>(
         reinterpret_cast<const unsigned char*>(kTestData),
         sizeof(kTestData) - 1);
   }
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
index aab42a4..f36e0bf 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/ui/webui/print_preview/print_preview_ui.h"
 
 #include <map>
-#include <memory>
+#include <string>
 #include <utility>
 #include <vector>
 
@@ -150,7 +150,7 @@
     return false;
 
   // Print Preview data.
-  scoped_refptr<base::RefCountedBytes> data;
+  scoped_refptr<base::RefCountedMemory> data;
   std::vector<std::string> url_substr = base::SplitString(
       path, "/", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
   int preview_ui_id = -1;
@@ -599,13 +599,13 @@
 
 void PrintPreviewUI::GetPrintPreviewDataForIndex(
     int index,
-    scoped_refptr<base::RefCountedBytes>* data) const {
+    scoped_refptr<base::RefCountedMemory>* data) const {
   PrintPreviewDataService::GetInstance()->GetDataEntry(id_, index, data);
 }
 
 void PrintPreviewUI::SetPrintPreviewDataForIndex(
     int index,
-    scoped_refptr<base::RefCountedBytes> data) {
+    scoped_refptr<base::RefCountedMemory> data) {
   PrintPreviewDataService::GetInstance()->SetDataEntry(id_, index,
                                                        std::move(data));
 }
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_ui.h b/chrome/browser/ui/webui/print_preview/print_preview_ui.h
index d3a3d0d2..06c39ec 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_ui.h
+++ b/chrome/browser/ui/webui/print_preview/print_preview_ui.h
@@ -7,7 +7,7 @@
 
 #include <stdint.h>
 
-#include <string>
+#include <memory>
 
 #include "base/callback_forward.h"
 #include "base/gtest_prod_util.h"
@@ -25,7 +25,7 @@
 namespace base {
 class DictionaryValue;
 class FilePath;
-class RefCountedBytes;
+class RefCountedMemory;
 }
 
 namespace gfx {
@@ -47,13 +47,13 @@
   // document.
   virtual void GetPrintPreviewDataForIndex(
       int index,
-      scoped_refptr<base::RefCountedBytes>* data) const;
+      scoped_refptr<base::RefCountedMemory>* data) const;
 
   // Sets the print preview |data|. |index| is zero-based, and can be
   // |printing::COMPLETE_PREVIEW_DOCUMENT_INDEX| to set the entire preview
   // document.
   void SetPrintPreviewDataForIndex(int index,
-                                   scoped_refptr<base::RefCountedBytes> data);
+                                   scoped_refptr<base::RefCountedMemory> data);
 
   // Clear the existing print preview data.
   void ClearAllPreviewData();
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_ui_unittest.cc b/chrome/browser/ui/webui/print_preview/print_preview_ui_unittest.cc
index b374eda8..02e979f 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_ui_unittest.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_ui_unittest.cc
@@ -85,13 +85,13 @@
 
   PrintPreviewUI* preview_ui = static_cast<PrintPreviewUI*>(
       preview_dialog->GetWebUI()->GetController());
-  ASSERT_TRUE(preview_ui != NULL);
+  ASSERT_TRUE(preview_ui);
 
-  scoped_refptr<base::RefCountedBytes> data;
+  scoped_refptr<base::RefCountedMemory> data;
   preview_ui->GetPrintPreviewDataForIndex(
       printing::COMPLETE_PREVIEW_DOCUMENT_INDEX,
       &data);
-  EXPECT_EQ(NULL, data.get());
+  EXPECT_FALSE(data);
 
   scoped_refptr<base::RefCountedBytes> dummy_data = CreateTestData();
 
@@ -115,7 +115,7 @@
   preview_ui->GetPrintPreviewDataForIndex(
       printing::COMPLETE_PREVIEW_DOCUMENT_INDEX,
       &data);
-  EXPECT_EQ(NULL, data.get());
+  EXPECT_FALSE(data);
 }
 
 // Set and get the individual draft pages.
@@ -138,11 +138,11 @@
 
   PrintPreviewUI* preview_ui = static_cast<PrintPreviewUI*>(
       preview_dialog->GetWebUI()->GetController());
-  ASSERT_TRUE(preview_ui != NULL);
+  ASSERT_TRUE(preview_ui);
 
-  scoped_refptr<base::RefCountedBytes> data;
+  scoped_refptr<base::RefCountedMemory> data;
   preview_ui->GetPrintPreviewDataForIndex(printing::FIRST_PAGE_INDEX, &data);
-  EXPECT_EQ(NULL, data.get());
+  EXPECT_FALSE(data);
 
   scoped_refptr<base::RefCountedBytes> dummy_data = CreateTestData();
 
@@ -163,7 +163,7 @@
   // Get the second page data.
   preview_ui->GetPrintPreviewDataForIndex(printing::FIRST_PAGE_INDEX + 1,
                                           &data);
-  EXPECT_EQ(NULL, data.get());
+  EXPECT_FALSE(data);
 
   preview_ui->SetPrintPreviewDataForIndex(printing::FIRST_PAGE_INDEX + 1,
                                           dummy_data.get());
@@ -175,7 +175,7 @@
   // Clear the preview data.
   preview_ui->ClearAllPreviewData();
   preview_ui->GetPrintPreviewDataForIndex(printing::FIRST_PAGE_INDEX, &data);
-  EXPECT_EQ(NULL, data.get());
+  EXPECT_FALSE(data);
 }
 
 // Test the browser-side print preview cancellation functionality.
@@ -198,7 +198,7 @@
 
   PrintPreviewUI* preview_ui = static_cast<PrintPreviewUI*>(
       preview_dialog->GetWebUI()->GetController());
-  ASSERT_TRUE(preview_ui != NULL);
+  ASSERT_TRUE(preview_ui);
 
   // Test with invalid |preview_ui_addr|.
   bool cancel = false;
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_utils.cc b/chrome/browser/ui/webui/print_preview/print_preview_utils.cc
index d316673..6d8dc9b 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_utils.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_utils.cc
@@ -181,7 +181,7 @@
 }
 
 void StartLocalPrint(const std::string& ticket_json,
-                     const scoped_refptr<base::RefCountedBytes>& print_data,
+                     const scoped_refptr<base::RefCountedMemory>& print_data,
                      content::WebContents* preview_web_contents,
                      PrinterHandler::PrintCallback callback) {
   std::unique_ptr<base::DictionaryValue> job_settings =
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_utils.h b/chrome/browser/ui/webui/print_preview/print_preview_utils.h
index 87db929e..f13e2c1 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_utils.h
+++ b/chrome/browser/ui/webui/print_preview/print_preview_utils.h
@@ -43,7 +43,7 @@
 // Starts a local print of |print_data| with print settings dictionary
 // |ticket_json|. Runs |callback| on failure or success.
 void StartLocalPrint(const std::string& ticket_json,
-                     const scoped_refptr<base::RefCountedBytes>& print_data,
+                     const scoped_refptr<base::RefCountedMemory>& print_data,
                      content::WebContents* preview_web_contents,
                      PrinterHandler::PrintCallback callback);
 
diff --git a/chrome/browser/ui/webui/print_preview/printer_handler.h b/chrome/browser/ui/webui/print_preview/printer_handler.h
index 29fc319..ec72a59 100644
--- a/chrome/browser/ui/webui/print_preview/printer_handler.h
+++ b/chrome/browser/ui/webui/print_preview/printer_handler.h
@@ -16,7 +16,7 @@
 namespace base {
 class DictionaryValue;
 class ListValue;
-class RefCountedBytes;
+class RefCountedMemory;
 class Value;
 }
 
@@ -127,7 +127,7 @@
       const base::string16& job_title,
       const std::string& ticket_json,
       const gfx::Size& page_size,
-      const scoped_refptr<base::RefCountedBytes>& print_data,
+      const scoped_refptr<base::RefCountedMemory>& print_data,
       PrintCallback callback) = 0;
 };
 
diff --git a/chrome/browser/ui/webui/print_preview/privet_printer_handler.cc b/chrome/browser/ui/webui/print_preview/privet_printer_handler.cc
index 5e3966d..be5aedb2 100644
--- a/chrome/browser/ui/webui/print_preview/privet_printer_handler.cc
+++ b/chrome/browser/ui/webui/print_preview/privet_printer_handler.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 #include <string>
+#include <utility>
 
 #include "base/bind.h"
 #include "base/callback.h"
@@ -85,7 +86,7 @@
     const base::string16& job_title,
     const std::string& ticket_json,
     const gfx::Size& page_size,
-    const scoped_refptr<base::RefCountedBytes>& print_data,
+    const scoped_refptr<base::RefCountedMemory>& print_data,
     PrintCallback callback) {
   DCHECK(!print_callback_);
   print_callback_ = std::move(callback);
@@ -205,7 +206,7 @@
 
 void PrivetPrinterHandler::PrintUpdateClient(
     const base::string16& job_title,
-    const scoped_refptr<base::RefCountedBytes>& print_data,
+    const scoped_refptr<base::RefCountedMemory>& print_data,
     const std::string& print_ticket,
     const std::string& capabilities,
     const gfx::Size& page_size,
@@ -237,7 +238,7 @@
 
 void PrivetPrinterHandler::StartPrint(
     const base::string16& job_title,
-    const scoped_refptr<base::RefCountedBytes>& print_data,
+    const scoped_refptr<base::RefCountedMemory>& print_data,
     const std::string& print_ticket,
     const std::string& capabilities,
     const gfx::Size& page_size) {
diff --git a/chrome/browser/ui/webui/print_preview/privet_printer_handler.h b/chrome/browser/ui/webui/print_preview/privet_printer_handler.h
index 87a3d3a..4a14f2a 100644
--- a/chrome/browser/ui/webui/print_preview/privet_printer_handler.h
+++ b/chrome/browser/ui/webui/print_preview/privet_printer_handler.h
@@ -19,7 +19,7 @@
 namespace base {
 class DictionaryValue;
 class OneShotTimer;
-class RefCountedBytes;
+class RefCountedMemory;
 }  // namespace base
 
 namespace gfx {
@@ -48,7 +48,7 @@
                   const base::string16& job_title,
                   const std::string& ticket_json,
                   const gfx::Size& page_size,
-                  const scoped_refptr<base::RefCountedBytes>& print_data,
+                  const scoped_refptr<base::RefCountedMemory>& print_data,
                   PrintCallback callback) override;
 
   // PrivetLocalPrinterLister::Delegate implementation.
@@ -76,14 +76,14 @@
   void OnGotCapabilities(const base::DictionaryValue* capabilities);
   void PrintUpdateClient(
       const base::string16& job_title,
-      const scoped_refptr<base::RefCountedBytes>& print_data,
+      const scoped_refptr<base::RefCountedMemory>& print_data,
       const std::string& print_ticket,
       const std::string& capabilities,
       const gfx::Size& page_size,
       std::unique_ptr<cloud_print::PrivetHTTPClient> http_client);
   bool UpdateClient(std::unique_ptr<cloud_print::PrivetHTTPClient> http_client);
   void StartPrint(const base::string16& job_title,
-                  const scoped_refptr<base::RefCountedBytes>& print_data,
+                  const scoped_refptr<base::RefCountedMemory>& print_data,
                   const std::string& print_ticket,
                   const std::string& capabilities,
                   const gfx::Size& page_size);
diff --git a/chrome/browser/ui/webui/quota_internals/quota_internals_handler.cc b/chrome/browser/ui/webui/quota_internals/quota_internals_handler.cc
index 1c632127..8c70d1b 100644
--- a/chrome/browser/ui/webui/quota_internals/quota_internals_handler.cc
+++ b/chrome/browser/ui/webui/quota_internals/quota_internals_handler.cc
@@ -27,9 +27,9 @@
 }
 
 void QuotaInternalsHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback("requestInfo",
-      base::Bind(&QuotaInternalsHandler::OnRequestInfo,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "requestInfo", base::BindRepeating(&QuotaInternalsHandler::OnRequestInfo,
+                                         base::Unretained(this)));
 }
 
 void QuotaInternalsHandler::ReportAvailableSpace(int64_t available_space) {
diff --git a/chrome/browser/ui/webui/set_as_default_browser_ui_win.cc b/chrome/browser/ui/webui/set_as_default_browser_ui_win.cc
index 56f8eded..c0977b81 100644
--- a/chrome/browser/ui/webui/set_as_default_browser_ui_win.cc
+++ b/chrome/browser/ui/webui/set_as_default_browser_ui_win.cc
@@ -140,8 +140,9 @@
 void SetAsDefaultBrowserHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "SetAsDefaultBrowser:LaunchSetDefaultBrowserFlow",
-      base::Bind(&SetAsDefaultBrowserHandler::HandleLaunchSetDefaultBrowserFlow,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &SetAsDefaultBrowserHandler::HandleLaunchSetDefaultBrowserFlow,
+          base::Unretained(this)));
 }
 
 void SetAsDefaultBrowserHandler::HandleLaunchSetDefaultBrowserFlow(
diff --git a/chrome/browser/ui/webui/settings/about_handler.cc b/chrome/browser/ui/webui/settings/about_handler.cc
index 4f86dbe..787f802 100644
--- a/chrome/browser/ui/webui/settings/about_handler.cc
+++ b/chrome/browser/ui/webui/settings/about_handler.cc
@@ -346,42 +346,44 @@
 
 void AboutHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
-      "aboutPageReady",
-      base::Bind(&AboutHandler::HandlePageReady, base::Unretained(this)));
+      "aboutPageReady", base::BindRepeating(&AboutHandler::HandlePageReady,
+                                            base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "refreshUpdateStatus",
-      base::Bind(&AboutHandler::HandleRefreshUpdateStatus,
-                 base::Unretained(this)));
+      base::BindRepeating(&AboutHandler::HandleRefreshUpdateStatus,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "openFeedbackDialog", base::Bind(&AboutHandler::HandleOpenFeedbackDialog,
-                                       base::Unretained(this)));
+      "openFeedbackDialog",
+      base::BindRepeating(&AboutHandler::HandleOpenFeedbackDialog,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "openHelpPage",
-      base::Bind(&AboutHandler::HandleOpenHelpPage, base::Unretained(this)));
+      "openHelpPage", base::BindRepeating(&AboutHandler::HandleOpenHelpPage,
+                                          base::Unretained(this)));
 #if defined(OS_CHROMEOS)
   web_ui()->RegisterMessageCallback(
-      "setChannel",
-      base::Bind(&AboutHandler::HandleSetChannel, base::Unretained(this)));
+      "setChannel", base::BindRepeating(&AboutHandler::HandleSetChannel,
+                                        base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "requestUpdate",
-      base::Bind(&AboutHandler::HandleRequestUpdate, base::Unretained(this)));
+      "requestUpdate", base::BindRepeating(&AboutHandler::HandleRequestUpdate,
+                                           base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "requestUpdateOverCellular",
-      base::Bind(&AboutHandler::HandleRequestUpdateOverCellular,
-                 base::Unretained(this)));
+      base::BindRepeating(&AboutHandler::HandleRequestUpdateOverCellular,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "getVersionInfo",
-      base::Bind(&AboutHandler::HandleGetVersionInfo, base::Unretained(this)));
+      "getVersionInfo", base::BindRepeating(&AboutHandler::HandleGetVersionInfo,
+                                            base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "getRegulatoryInfo", base::Bind(&AboutHandler::HandleGetRegulatoryInfo,
-                                      base::Unretained(this)));
+      "getRegulatoryInfo",
+      base::BindRepeating(&AboutHandler::HandleGetRegulatoryInfo,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "getChannelInfo", base::Bind(&AboutHandler::HandleGetChannelInfo,
-                                   base::Unretained(this)));
+      "getChannelInfo", base::BindRepeating(&AboutHandler::HandleGetChannelInfo,
+                                            base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "refreshTPMFirmwareUpdateStatus",
-      base::Bind(&AboutHandler::HandleRefreshTPMFirmwareUpdateStatus,
-                 base::Unretained(this)));
+      base::BindRepeating(&AboutHandler::HandleRefreshTPMFirmwareUpdateStatus,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "getHasEndOfLife",
       base::BindRepeating(&AboutHandler::HandleGetHasEndOfLife,
@@ -389,8 +391,8 @@
 #endif
 #if defined(OS_MACOSX)
   web_ui()->RegisterMessageCallback(
-      "promoteUpdater",
-      base::Bind(&AboutHandler::PromoteUpdater, base::Unretained(this)));
+      "promoteUpdater", base::BindRepeating(&AboutHandler::PromoteUpdater,
+                                            base::Unretained(this)));
 #endif
 
 #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/ui/webui/settings/appearance_handler.cc b/chrome/browser/ui/webui/settings/appearance_handler.cc
index 3e9bb1a..ae92d56 100644
--- a/chrome/browser/ui/webui/settings/appearance_handler.cc
+++ b/chrome/browser/ui/webui/settings/appearance_handler.cc
@@ -29,29 +29,29 @@
 void AppearanceHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "useDefaultTheme",
-      base::Bind(&AppearanceHandler::HandleUseDefaultTheme,
-                 base::Unretained(this)));
+      base::BindRepeating(&AppearanceHandler::HandleUseDefaultTheme,
+                          base::Unretained(this)));
 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
   web_ui()->RegisterMessageCallback(
       "useSystemTheme",
-      base::Bind(&AppearanceHandler::HandleUseSystemTheme,
-                 base::Unretained(this)));
+      base::BindRepeating(&AppearanceHandler::HandleUseSystemTheme,
+                          base::Unretained(this)));
 #endif
 #if defined(OS_CHROMEOS)
   web_ui()->RegisterMessageCallback(
       "openWallpaperManager",
-      base::Bind(&AppearanceHandler::HandleOpenWallpaperManager,
-                 base::Unretained(this)));
+      base::BindRepeating(&AppearanceHandler::HandleOpenWallpaperManager,
+                          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       "isWallpaperSettingVisible",
-      base::Bind(&AppearanceHandler::IsWallpaperSettingVisible,
-                 base::Unretained(this)));
+      base::BindRepeating(&AppearanceHandler::IsWallpaperSettingVisible,
+                          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       "isWallpaperPolicyControlled",
-      base::Bind(&AppearanceHandler::IsWallpaperPolicyControlled,
-                 base::Unretained(this)));
+      base::BindRepeating(&AppearanceHandler::IsWallpaperPolicyControlled,
+                          base::Unretained(this)));
 #endif
 }
 
diff --git a/chrome/browser/ui/webui/settings/browser_lifetime_handler.cc b/chrome/browser/ui/webui/settings/browser_lifetime_handler.cc
index 551123b..c4eb728 100644
--- a/chrome/browser/ui/webui/settings/browser_lifetime_handler.cc
+++ b/chrome/browser/ui/webui/settings/browser_lifetime_handler.cc
@@ -25,19 +25,21 @@
 BrowserLifetimeHandler::~BrowserLifetimeHandler() {}
 
 void BrowserLifetimeHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback("restart",
-      base::Bind(&BrowserLifetimeHandler::HandleRestart,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("relaunch",
-      base::Bind(&BrowserLifetimeHandler::HandleRelaunch,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "restart", base::BindRepeating(&BrowserLifetimeHandler::HandleRestart,
+                                     base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "relaunch", base::BindRepeating(&BrowserLifetimeHandler::HandleRelaunch,
+                                      base::Unretained(this)));
 #if defined(OS_CHROMEOS)
-  web_ui()->RegisterMessageCallback("signOutAndRestart",
-      base::Bind(&BrowserLifetimeHandler::HandleSignOutAndRestart,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("factoryReset",
-      base::Bind(&BrowserLifetimeHandler::HandleFactoryReset,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "signOutAndRestart",
+      base::BindRepeating(&BrowserLifetimeHandler::HandleSignOutAndRestart,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "factoryReset",
+      base::BindRepeating(&BrowserLifetimeHandler::HandleFactoryReset,
+                          base::Unretained(this)));
 #endif  // defined(OS_CHROMEOS)
 }
 
diff --git a/chrome/browser/ui/webui/settings/change_password_handler.cc b/chrome/browser/ui/webui/settings/change_password_handler.cc
index a077bd75..6d64f7bb 100644
--- a/chrome/browser/ui/webui/settings/change_password_handler.cc
+++ b/chrome/browser/ui/webui/settings/change_password_handler.cc
@@ -26,11 +26,12 @@
 void ChangePasswordHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "initializeChangePasswordHandler",
-      base::Bind(&ChangePasswordHandler::HandleInitialize,
-                 base::Unretained(this)));
+      base::BindRepeating(&ChangePasswordHandler::HandleInitialize,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "changePassword", base::Bind(&ChangePasswordHandler::HandleChangePassword,
-                                   base::Unretained(this)));
+      "changePassword",
+      base::BindRepeating(&ChangePasswordHandler::HandleChangePassword,
+                          base::Unretained(this)));
 }
 
 void ChangePasswordHandler::OnJavascriptAllowed() {
diff --git a/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc b/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc
index a74053c..43375c8 100644
--- a/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc
@@ -25,16 +25,17 @@
 void AccessibilityHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "showChromeVoxSettings",
-      base::Bind(&AccessibilityHandler::HandleShowChromeVoxSettings,
-                 base::Unretained(this)));
+      base::BindRepeating(&AccessibilityHandler::HandleShowChromeVoxSettings,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "showSelectToSpeakSettings",
-      base::Bind(&AccessibilityHandler::HandleShowSelectToSpeakSettings,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &AccessibilityHandler::HandleShowSelectToSpeakSettings,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "showSwitchAccessSettings",
-      base::Bind(&AccessibilityHandler::HandleShowSwitchAccessSettings,
-                 base::Unretained(this)));
+      base::BindRepeating(&AccessibilityHandler::HandleShowSwitchAccessSettings,
+                          base::Unretained(this)));
 }
 
 void AccessibilityHandler::HandleShowChromeVoxSettings(
diff --git a/chrome/browser/ui/webui/settings/chromeos/android_apps_handler.cc b/chrome/browser/ui/webui/settings/chromeos/android_apps_handler.cc
index 01baa40..1a3824c 100644
--- a/chrome/browser/ui/webui/settings/chromeos/android_apps_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/android_apps_handler.cc
@@ -28,16 +28,16 @@
   // Note: requestAndroidAppsInfo must be called before observers will be added.
   web_ui()->RegisterMessageCallback(
       "requestAndroidAppsInfo",
-      base::Bind(&AndroidAppsHandler::HandleRequestAndroidAppsInfo,
-                 weak_ptr_factory_.GetWeakPtr()));
+      base::BindRepeating(&AndroidAppsHandler::HandleRequestAndroidAppsInfo,
+                          weak_ptr_factory_.GetWeakPtr()));
   web_ui()->RegisterMessageCallback(
       "showAndroidAppsSettings",
-      base::Bind(&AndroidAppsHandler::ShowAndroidAppsSettings,
-                 weak_ptr_factory_.GetWeakPtr()));
+      base::BindRepeating(&AndroidAppsHandler::ShowAndroidAppsSettings,
+                          weak_ptr_factory_.GetWeakPtr()));
   web_ui()->RegisterMessageCallback(
       "showAndroidManageAppLinks",
-      base::Bind(&AndroidAppsHandler::ShowAndroidManageAppLinks,
-                 weak_ptr_factory_.GetWeakPtr()));
+      base::BindRepeating(&AndroidAppsHandler::ShowAndroidManageAppLinks,
+                          weak_ptr_factory_.GetWeakPtr()));
 }
 
 void AndroidAppsHandler::OnJavascriptAllowed() {
diff --git a/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc b/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc
index 6a345261..578bbdb 100644
--- a/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc
@@ -100,25 +100,27 @@
 
 void ChangePictureHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
-      "chooseFile", base::Bind(&ChangePictureHandler::HandleChooseFile,
-                               base::Unretained(this)));
+      "chooseFile", base::BindRepeating(&ChangePictureHandler::HandleChooseFile,
+                                        base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "photoTaken", base::Bind(&ChangePictureHandler::HandlePhotoTaken,
-                               base::Unretained(this)));
+      "photoTaken", base::BindRepeating(&ChangePictureHandler::HandlePhotoTaken,
+                                        base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "discardPhoto", base::Bind(&ChangePictureHandler::HandleDiscardPhoto,
-                                 base::Unretained(this)));
+      "discardPhoto",
+      base::BindRepeating(&ChangePictureHandler::HandleDiscardPhoto,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "onChangePicturePageInitialized",
-      base::Bind(&ChangePictureHandler::HandlePageInitialized,
-                 base::Unretained(this)));
+      base::BindRepeating(&ChangePictureHandler::HandlePageInitialized,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "selectImage", base::Bind(&ChangePictureHandler::HandleSelectImage,
-                                base::Unretained(this)));
+      "selectImage",
+      base::BindRepeating(&ChangePictureHandler::HandleSelectImage,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "requestSelectedImage",
-      base::Bind(&ChangePictureHandler::HandleRequestSelectedImage,
-                 base::Unretained(this)));
+      base::BindRepeating(&ChangePictureHandler::HandleRequestSelectedImage,
+                          base::Unretained(this)));
 }
 
 void ChangePictureHandler::OnJavascriptAllowed() {
diff --git a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
index a535d49..019c796 100644
--- a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
@@ -265,52 +265,58 @@
 void CupsPrintersHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "getCupsPrintersList",
-      base::Bind(&CupsPrintersHandler::HandleGetCupsPrintersList,
-                 base::Unretained(this)));
+      base::BindRepeating(&CupsPrintersHandler::HandleGetCupsPrintersList,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "updateCupsPrinter",
-      base::Bind(&CupsPrintersHandler::HandleUpdateCupsPrinter,
-                 base::Unretained(this)));
+      base::BindRepeating(&CupsPrintersHandler::HandleUpdateCupsPrinter,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "removeCupsPrinter",
-      base::Bind(&CupsPrintersHandler::HandleRemoveCupsPrinter,
-                 base::Unretained(this)));
+      base::BindRepeating(&CupsPrintersHandler::HandleRemoveCupsPrinter,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "addCupsPrinter", base::Bind(&CupsPrintersHandler::HandleAddCupsPrinter,
-                                   base::Unretained(this)));
+      "addCupsPrinter",
+      base::BindRepeating(&CupsPrintersHandler::HandleAddCupsPrinter,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "getPrinterInfo", base::Bind(&CupsPrintersHandler::HandleGetPrinterInfo,
-                                   base::Unretained(this)));
+      "getPrinterInfo",
+      base::BindRepeating(&CupsPrintersHandler::HandleGetPrinterInfo,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "getCupsPrinterManufacturersList",
-      base::Bind(&CupsPrintersHandler::HandleGetCupsPrinterManufacturers,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &CupsPrintersHandler::HandleGetCupsPrinterManufacturers,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "getCupsPrinterModelsList",
-      base::Bind(&CupsPrintersHandler::HandleGetCupsPrinterModels,
-                 base::Unretained(this)));
+      base::BindRepeating(&CupsPrintersHandler::HandleGetCupsPrinterModels,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "selectPPDFile", base::Bind(&CupsPrintersHandler::HandleSelectPPDFile,
-                                  base::Unretained(this)));
+      "selectPPDFile",
+      base::BindRepeating(&CupsPrintersHandler::HandleSelectPPDFile,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "startDiscoveringPrinters",
-      base::Bind(&CupsPrintersHandler::HandleStartDiscovery,
-                 base::Unretained(this)));
+      base::BindRepeating(&CupsPrintersHandler::HandleStartDiscovery,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "stopDiscoveringPrinters",
-      base::Bind(&CupsPrintersHandler::HandleStopDiscovery,
-                 base::Unretained(this)));
+      base::BindRepeating(&CupsPrintersHandler::HandleStopDiscovery,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "getPrinterPpdManufacturerAndModel",
-      base::Bind(&CupsPrintersHandler::HandleGetPrinterPpdManufacturerAndModel,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &CupsPrintersHandler::HandleGetPrinterPpdManufacturerAndModel,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "addDiscoveredPrinter",
-      base::Bind(&CupsPrintersHandler::HandleAddDiscoveredPrinter,
-                 base::Unretained(this)));
+      base::BindRepeating(&CupsPrintersHandler::HandleAddDiscoveredPrinter,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "cancelPrinterSetUp", base::Bind(&CupsPrintersHandler::HandleSetUpCancel,
-                                       base::Unretained(this)));
+      "cancelPrinterSetUp",
+      base::BindRepeating(&CupsPrintersHandler::HandleSetUpCancel,
+                          base::Unretained(this)));
 }
 
 void CupsPrintersHandler::OnJavascriptAllowed() {
diff --git a/chrome/browser/ui/webui/settings/chromeos/date_time_handler.cc b/chrome/browser/ui/webui/settings/chromeos/date_time_handler.cc
index ffe094e..901d00620 100644
--- a/chrome/browser/ui/webui/settings/chromeos/date_time_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/date_time_handler.cc
@@ -88,14 +88,16 @@
 
 void DateTimeHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
-      "dateTimePageReady", base::Bind(&DateTimeHandler::HandleDateTimePageReady,
-                                      base::Unretained(this)));
+      "dateTimePageReady",
+      base::BindRepeating(&DateTimeHandler::HandleDateTimePageReady,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "getTimeZones",
-      base::Bind(&DateTimeHandler::HandleGetTimeZones, base::Unretained(this)));
+      "getTimeZones", base::BindRepeating(&DateTimeHandler::HandleGetTimeZones,
+                                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "showSetDateTimeUI", base::Bind(&DateTimeHandler::HandleShowSetDateTimeUI,
-                                      base::Unretained(this)));
+      "showSetDateTimeUI",
+      base::BindRepeating(&DateTimeHandler::HandleShowSetDateTimeUI,
+                          base::Unretained(this)));
 }
 
 void DateTimeHandler::OnJavascriptAllowed() {
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.cc b/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.cc
index 53bf085..59a3f7f0 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.cc
@@ -46,12 +46,12 @@
 void KeyboardHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "initializeKeyboardSettings",
-      base::Bind(&KeyboardHandler::HandleInitialize,
-                 base::Unretained(this)));
+      base::BindRepeating(&KeyboardHandler::HandleInitialize,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "showKeyboardShortcutsOverlay",
-      base::Bind(&KeyboardHandler::HandleShowKeyboardShortcutsOverlay,
-                 base::Unretained(this)));
+      base::BindRepeating(&KeyboardHandler::HandleShowKeyboardShortcutsOverlay,
+                          base::Unretained(this)));
 }
 
 void KeyboardHandler::OnJavascriptAllowed() {
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_pointer_handler.cc b/chrome/browser/ui/webui/settings/chromeos/device_pointer_handler.cc
index 061dad6..0f5933cc 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_pointer_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/device_pointer_handler.cc
@@ -18,7 +18,8 @@
 void PointerHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "initializePointerSettings",
-      base::Bind(&PointerHandler::HandleInitialize, base::Unretained(this)));
+      base::BindRepeating(&PointerHandler::HandleInitialize,
+                          base::Unretained(this)));
 }
 
 void PointerHandler::OnJavascriptAllowed() {
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc b/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc
index c07cfbf..da797d5 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc
@@ -89,22 +89,24 @@
 
 void PowerHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
-      "updatePowerStatus", base::Bind(&PowerHandler::HandleUpdatePowerStatus,
-                                      base::Unretained(this)));
+      "updatePowerStatus",
+      base::BindRepeating(&PowerHandler::HandleUpdatePowerStatus,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "setPowerSource",
-      base::Bind(&PowerHandler::HandleSetPowerSource, base::Unretained(this)));
+      "setPowerSource", base::BindRepeating(&PowerHandler::HandleSetPowerSource,
+                                            base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "requestPowerManagementSettings",
-      base::Bind(&PowerHandler::HandleRequestPowerManagementSettings,
-                 base::Unretained(this)));
+      base::BindRepeating(&PowerHandler::HandleRequestPowerManagementSettings,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "setLidClosedBehavior",
-      base::Bind(&PowerHandler::HandleSetLidClosedBehavior,
-                 base::Unretained(this)));
+      base::BindRepeating(&PowerHandler::HandleSetLidClosedBehavior,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "setIdleBehavior",
-      base::Bind(&PowerHandler::HandleSetIdleBehavior, base::Unretained(this)));
+      base::BindRepeating(&PowerHandler::HandleSetIdleBehavior,
+                          base::Unretained(this)));
 }
 
 void PowerHandler::OnJavascriptAllowed() {
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc b/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc
index 4ff2b1c..04fe8449 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc
@@ -84,20 +84,19 @@
 
   web_ui()->RegisterMessageCallback(
       "updateStorageInfo",
-      base::Bind(&StorageHandler::HandleUpdateStorageInfo,
-                 base::Unretained(this)));
+      base::BindRepeating(&StorageHandler::HandleUpdateStorageInfo,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "openDownloads",
-      base::Bind(&StorageHandler::HandleOpenDownloads,
-                 base::Unretained(this)));
+      "openDownloads", base::BindRepeating(&StorageHandler::HandleOpenDownloads,
+                                           base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "openArcStorage",
-      base::Bind(&StorageHandler::HandleOpenArcStorage,
-                 base::Unretained(this)));
+      base::BindRepeating(&StorageHandler::HandleOpenArcStorage,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "clearDriveCache",
-      base::Bind(&StorageHandler::HandleClearDriveCache,
-                 base::Unretained(this)));
+      base::BindRepeating(&StorageHandler::HandleClearDriveCache,
+                          base::Unretained(this)));
 }
 
 void StorageHandler::HandleUpdateStorageInfo(const base::ListValue* args) {
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_stylus_handler.cc b/chrome/browser/ui/webui/settings/chromeos/device_stylus_handler.cc
index 612839194..e289167 100644
--- a/chrome/browser/ui/webui/settings/chromeos/device_stylus_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/device_stylus_handler.cc
@@ -40,22 +40,25 @@
   // added.
   web_ui()->RegisterMessageCallback(
       "initializeStylusSettings",
-      base::Bind(&StylusHandler::HandleInitialize, base::Unretained(this)));
+      base::BindRepeating(&StylusHandler::HandleInitialize,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "requestNoteTakingApps",
-      base::Bind(&StylusHandler::HandleRequestApps, base::Unretained(this)));
+      base::BindRepeating(&StylusHandler::HandleRequestApps,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "setPreferredNoteTakingApp",
-      base::Bind(&StylusHandler::HandleSetPreferredNoteTakingApp,
-                 base::Unretained(this)));
+      base::BindRepeating(&StylusHandler::HandleSetPreferredNoteTakingApp,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "setPreferredNoteTakingAppEnabledOnLockScreen",
-      base::Bind(
+      base::BindRepeating(
           &StylusHandler::HandleSetPreferredNoteTakingAppEnabledOnLockScreen,
           base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "showPlayStoreApps", base::Bind(&StylusHandler::HandleShowPlayStoreApps,
-                                      base::Unretained(this)));
+      "showPlayStoreApps",
+      base::BindRepeating(&StylusHandler::HandleShowPlayStoreApps,
+                          base::Unretained(this)));
 }
 
 void StylusHandler::OnJavascriptAllowed() {
diff --git a/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler.cc b/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler.cc
index dc6133e..8535dc1 100644
--- a/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/easy_unlock_settings_handler.cc
@@ -50,24 +50,25 @@
 void EasyUnlockSettingsHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "easyUnlockGetEnabledStatus",
-      base::Bind(&EasyUnlockSettingsHandler::HandleGetEnabledStatus,
-                 base::Unretained(this)));
+      base::BindRepeating(&EasyUnlockSettingsHandler::HandleGetEnabledStatus,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "easyUnlockStartTurnOnFlow",
-      base::Bind(&EasyUnlockSettingsHandler::HandleStartTurnOnFlow,
-                 base::Unretained(this)));
+      base::BindRepeating(&EasyUnlockSettingsHandler::HandleStartTurnOnFlow,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "easyUnlockGetTurnOffFlowStatus",
-      base::Bind(&EasyUnlockSettingsHandler::HandleGetTurnOffFlowStatus,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &EasyUnlockSettingsHandler::HandleGetTurnOffFlowStatus,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "easyUnlockStartTurnOffFlow",
-      base::Bind(&EasyUnlockSettingsHandler::HandleStartTurnOffFlow,
-                 base::Unretained(this)));
+      base::BindRepeating(&EasyUnlockSettingsHandler::HandleStartTurnOffFlow,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "easyUnlockCancelTurnOffFlow",
-      base::Bind(&EasyUnlockSettingsHandler::HandleCancelTurnOffFlow,
-                 base::Unretained(this)));
+      base::BindRepeating(&EasyUnlockSettingsHandler::HandleCancelTurnOffFlow,
+                          base::Unretained(this)));
 }
 
 void EasyUnlockSettingsHandler::OnJavascriptAllowed() {
diff --git a/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc b/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc
index a97d004..bd4ef59c 100644
--- a/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc
@@ -72,40 +72,39 @@
   // Note: getFingerprintsList must be called before observers will be added.
   web_ui()->RegisterMessageCallback(
       "getFingerprintsList",
-      base::Bind(&FingerprintHandler::HandleGetFingerprintsList,
-                 base::Unretained(this)));
+      base::BindRepeating(&FingerprintHandler::HandleGetFingerprintsList,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "getNumFingerprints",
-      base::Bind(&FingerprintHandler::HandleGetNumFingerprints,
-                 base::Unretained(this)));
+      base::BindRepeating(&FingerprintHandler::HandleGetNumFingerprints,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "startEnroll",
-      base::Bind(&FingerprintHandler::HandleStartEnroll,
-                 base::Unretained(this)));
+      "startEnroll", base::BindRepeating(&FingerprintHandler::HandleStartEnroll,
+                                         base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "cancelCurrentEnroll",
-      base::Bind(&FingerprintHandler::HandleCancelCurrentEnroll,
-                 base::Unretained(this)));
+      base::BindRepeating(&FingerprintHandler::HandleCancelCurrentEnroll,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "getEnrollmentLabel",
-      base::Bind(&FingerprintHandler::HandleGetEnrollmentLabel,
-                 base::Unretained(this)));
+      base::BindRepeating(&FingerprintHandler::HandleGetEnrollmentLabel,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "removeEnrollment",
-      base::Bind(&FingerprintHandler::HandleRemoveEnrollment,
-                 base::Unretained(this)));
+      base::BindRepeating(&FingerprintHandler::HandleRemoveEnrollment,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "changeEnrollmentLabel",
-      base::Bind(&FingerprintHandler::HandleChangeEnrollmentLabel,
-                 base::Unretained(this)));
+      base::BindRepeating(&FingerprintHandler::HandleChangeEnrollmentLabel,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "startAuthentication",
-      base::Bind(&FingerprintHandler::HandleStartAuthentication,
-                 base::Unretained(this)));
+      base::BindRepeating(&FingerprintHandler::HandleStartAuthentication,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "endCurrentAuthentication",
-      base::Bind(&FingerprintHandler::HandleEndCurrentAuthentication,
-                 base::Unretained(this)));
+      base::BindRepeating(&FingerprintHandler::HandleEndCurrentAuthentication,
+                          base::Unretained(this)));
 }
 
 void FingerprintHandler::OnJavascriptAllowed() {
diff --git a/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.cc b/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.cc
index a6ddb49d..f926306 100644
--- a/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.cc
@@ -27,21 +27,23 @@
 void GoogleAssistantHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "setGoogleAssistantEnabled",
-      base::Bind(&GoogleAssistantHandler::HandleSetGoogleAssistantEnabled,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &GoogleAssistantHandler::HandleSetGoogleAssistantEnabled,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "setGoogleAssistantContextEnabled",
-      base::Bind(
+      base::BindRepeating(
           &GoogleAssistantHandler::HandleSetGoogleAssistantContextEnabled,
           base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "showGoogleAssistantSettings",
-      base::Bind(&GoogleAssistantHandler::HandleShowGoogleAssistantSettings,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &GoogleAssistantHandler::HandleShowGoogleAssistantSettings,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "turnOnGoogleAssistant",
-      base::Bind(&GoogleAssistantHandler::HandleTurnOnGoogleAssistant,
-                 base::Unretained(this)));
+      base::BindRepeating(&GoogleAssistantHandler::HandleTurnOnGoogleAssistant,
+                          base::Unretained(this)));
 }
 
 void GoogleAssistantHandler::HandleSetGoogleAssistantEnabled(
diff --git a/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc b/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc
index 38e54c5..8367559 100644
--- a/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc
@@ -96,18 +96,19 @@
   // TODO(stevenjb): Eliminate once network configuration UI is integrated
   // into settings.
   web_ui()->RegisterMessageCallback(
-      kAddNetworkMessage,
-      base::Bind(&InternetHandler::AddNetwork, base::Unretained(this)));
+      kAddNetworkMessage, base::BindRepeating(&InternetHandler::AddNetwork,
+                                              base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kConfigureNetworkMessage,
-      base::Bind(&InternetHandler::ConfigureNetwork, base::Unretained(this)));
+      base::BindRepeating(&InternetHandler::ConfigureNetwork,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kRequestArcVpnProviders,
-      base::Bind(&InternetHandler::RequestArcVpnProviders,
-                 base::Unretained(this)));
+      base::BindRepeating(&InternetHandler::RequestArcVpnProviders,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kRequestGmsCoreNotificationsDisabledDeviceNames,
-      base::Bind(
+      base::BindRepeating(
           &InternetHandler::RequestGmsCoreNotificationsDisabledDeviceNames,
           base::Unretained(this)));
 }
diff --git a/chrome/browser/ui/webui/settings/downloads_handler.cc b/chrome/browser/ui/webui/settings/downloads_handler.cc
index b5ab983..4e45994 100644
--- a/chrome/browser/ui/webui/settings/downloads_handler.cc
+++ b/chrome/browser/ui/webui/settings/downloads_handler.cc
@@ -34,15 +34,16 @@
 void DownloadsHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "initializeDownloads",
-      base::Bind(&DownloadsHandler::HandleInitialize, base::Unretained(this)));
+      base::BindRepeating(&DownloadsHandler::HandleInitialize,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "resetAutoOpenFileTypes",
-      base::Bind(&DownloadsHandler::HandleResetAutoOpenFileTypes,
-                 base::Unretained(this)));
+      base::BindRepeating(&DownloadsHandler::HandleResetAutoOpenFileTypes,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "selectDownloadLocation",
-      base::Bind(&DownloadsHandler::HandleSelectDownloadLocation,
-                 base::Unretained(this)));
+      base::BindRepeating(&DownloadsHandler::HandleSelectDownloadLocation,
+                          base::Unretained(this)));
 }
 
 void DownloadsHandler::OnJavascriptAllowed() {
diff --git a/chrome/browser/ui/webui/settings/extension_control_handler.cc b/chrome/browser/ui/webui/settings/extension_control_handler.cc
index a7c9d726..7f5a1b2 100644
--- a/chrome/browser/ui/webui/settings/extension_control_handler.cc
+++ b/chrome/browser/ui/webui/settings/extension_control_handler.cc
@@ -19,9 +19,10 @@
 ExtensionControlHandler::~ExtensionControlHandler() {}
 
 void ExtensionControlHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback("disableExtension",
-      base::Bind(&ExtensionControlHandler::HandleDisableExtension,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "disableExtension",
+      base::BindRepeating(&ExtensionControlHandler::HandleDisableExtension,
+                          base::Unretained(this)));
 }
 
 void ExtensionControlHandler::HandleDisableExtension(
diff --git a/chrome/browser/ui/webui/settings/font_handler.cc b/chrome/browser/ui/webui/settings/font_handler.cc
index abd118e..037d0a5b 100644
--- a/chrome/browser/ui/webui/settings/font_handler.cc
+++ b/chrome/browser/ui/webui/settings/font_handler.cc
@@ -51,16 +51,17 @@
 
 void FontHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
-      "fetchFontsData", base::Bind(&FontHandler::HandleFetchFontsData,
-                                   base::Unretained(this)));
+      "fetchFontsData", base::BindRepeating(&FontHandler::HandleFetchFontsData,
+                                            base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "observeAdvancedFontExtensionAvailable",
-      base::Bind(&FontHandler::HandleObserveAdvancedFontExtensionAvailable,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &FontHandler::HandleObserveAdvancedFontExtensionAvailable,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "openAdvancedFontSettings",
-      base::Bind(&FontHandler::HandleOpenAdvancedFontSettings,
-                 base::Unretained(this)));
+      base::BindRepeating(&FontHandler::HandleOpenAdvancedFontSettings,
+                          base::Unretained(this)));
 }
 
 void FontHandler::OnJavascriptAllowed() {
diff --git a/chrome/browser/ui/webui/settings/languages_handler.cc b/chrome/browser/ui/webui/settings/languages_handler.cc
index 2f98827..b36e744 100644
--- a/chrome/browser/ui/webui/settings/languages_handler.cc
+++ b/chrome/browser/ui/webui/settings/languages_handler.cc
@@ -31,12 +31,12 @@
 void LanguagesHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "getProspectiveUILanguage",
-      base::Bind(&LanguagesHandler::HandleGetProspectiveUILanguage,
-                 base::Unretained(this)));
+      base::BindRepeating(&LanguagesHandler::HandleGetProspectiveUILanguage,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "setProspectiveUILanguage",
-      base::Bind(&LanguagesHandler::HandleSetProspectiveUILanguage,
-                 base::Unretained(this)));
+      base::BindRepeating(&LanguagesHandler::HandleSetProspectiveUILanguage,
+                          base::Unretained(this)));
 }
 
 void LanguagesHandler::HandleGetProspectiveUILanguage(
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
index 4425a0d..6ff1d3b 100644
--- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -1536,6 +1536,7 @@
     {"syncDisconnectExplanation", IDS_SETTINGS_SYNC_DISCONNECT_EXPLANATION},
     {"syncDisconnectConfirm", IDS_SETTINGS_SYNC_DISCONNECT_CONFIRM},
     {"sync", IDS_SETTINGS_SYNC},
+    {"syncAndPersonalization", IDS_SETTINGS_SYNC_SYNC_AND_PERSONALIZATION},
     {"syncPageTitle", IDS_SETTINGS_SYNC_PAGE_TITLE},
     {"syncLoading", IDS_SETTINGS_SYNC_LOADING},
     {"syncTimeout", IDS_SETTINGS_SYNC_TIMEOUT},
diff --git a/chrome/browser/ui/webui/settings/md_settings_ui.cc b/chrome/browser/ui/webui/settings/md_settings_ui.cc
index c3d1a1d2..158af7fd 100644
--- a/chrome/browser/ui/webui/settings/md_settings_ui.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_ui.cc
@@ -14,6 +14,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/signin/unified_consent_helper.h"
 #include "chrome/browser/ui/webui/metrics_handler.h"
 #include "chrome/browser/ui/webui/settings/about_handler.h"
 #include "chrome/browser/ui/webui/settings/appearance_handler.h"
@@ -302,6 +303,9 @@
                           signin::IsDiceEnabledForProfile(profile->GetPrefs()));
 #endif  // defined(OS_CHROMEOS)
 
+  html_source->AddBoolean("unifiedConsentEnabled",
+                          IsUnifiedConsentEnabled(profile));
+
   html_source->AddBoolean("showExportPasswords",
                           base::FeatureList::IsEnabled(
                               password_manager::features::kPasswordExport));
diff --git a/chrome/browser/ui/webui/settings/metrics_reporting_handler.cc b/chrome/browser/ui/webui/settings/metrics_reporting_handler.cc
index def21ea7..7d8fb692 100644
--- a/chrome/browser/ui/webui/settings/metrics_reporting_handler.cc
+++ b/chrome/browser/ui/webui/settings/metrics_reporting_handler.cc
@@ -23,12 +23,15 @@
 MetricsReportingHandler::~MetricsReportingHandler() {}
 
 void MetricsReportingHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback("getMetricsReporting",
-      base::Bind(&MetricsReportingHandler::HandleGetMetricsReporting,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("setMetricsReportingEnabled",
-      base::Bind(&MetricsReportingHandler::HandleSetMetricsReportingEnabled,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "getMetricsReporting",
+      base::BindRepeating(&MetricsReportingHandler::HandleGetMetricsReporting,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "setMetricsReportingEnabled",
+      base::BindRepeating(
+          &MetricsReportingHandler::HandleSetMetricsReportingEnabled,
+          base::Unretained(this)));
 }
 
 void MetricsReportingHandler::OnJavascriptAllowed() {
diff --git a/chrome/browser/ui/webui/settings/native_certificates_handler.cc b/chrome/browser/ui/webui/settings/native_certificates_handler.cc
index 4661e32..63776d6 100644
--- a/chrome/browser/ui/webui/settings/native_certificates_handler.cc
+++ b/chrome/browser/ui/webui/settings/native_certificates_handler.cc
@@ -19,8 +19,9 @@
 void NativeCertificatesHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "showManageSSLCertificates",
-      base::Bind(&NativeCertificatesHandler::HandleShowManageSSLCertificates,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &NativeCertificatesHandler::HandleShowManageSSLCertificates,
+          base::Unretained(this)));
 }
 
 void NativeCertificatesHandler::HandleShowManageSSLCertificates(
diff --git a/chrome/browser/ui/webui/settings/on_startup_handler.cc b/chrome/browser/ui/webui/settings/on_startup_handler.cc
index fe50a55..48ae46235 100644
--- a/chrome/browser/ui/webui/settings/on_startup_handler.cc
+++ b/chrome/browser/ui/webui/settings/on_startup_handler.cc
@@ -41,12 +41,13 @@
 
 void OnStartupHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
-      "getNtpExtension", base::Bind(&OnStartupHandler::HandleGetNtpExtension,
-                                    base::Unretained(this)));
+      "getNtpExtension",
+      base::BindRepeating(&OnStartupHandler::HandleGetNtpExtension,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "validateStartupPage",
-      base::Bind(&OnStartupHandler::HandleValidateStartupPage,
-                 base::Unretained(this)));
+      base::BindRepeating(&OnStartupHandler::HandleValidateStartupPage,
+                          base::Unretained(this)));
 }
 
 void OnStartupHandler::OnExtensionUnloaded(
diff --git a/chrome/browser/ui/webui/settings/people_handler.cc b/chrome/browser/ui/webui/settings/people_handler.cc
index bcafbc0..6211aaa 100644
--- a/chrome/browser/ui/webui/settings/people_handler.cc
+++ b/chrome/browser/ui/webui/settings/people_handler.cc
@@ -25,6 +25,7 @@
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/signin/signin_promo.h"
 #include "chrome/browser/signin/signin_ui_util.h"
+#include "chrome/browser/signin/unified_consent_helper.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/sync/sync_ui_util.h"
 #include "chrome/browser/ui/browser_finder.h"
@@ -216,39 +217,46 @@
   InitializeSyncBlocker();
   web_ui()->RegisterMessageCallback(
       "SyncSetupDidClosePage",
-      base::Bind(&PeopleHandler::OnDidClosePage, base::Unretained(this)));
+      base::BindRepeating(&PeopleHandler::OnDidClosePage,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "SyncSetupSetDatatypes",
-      base::Bind(&PeopleHandler::HandleSetDatatypes, base::Unretained(this)));
+      base::BindRepeating(&PeopleHandler::HandleSetDatatypes,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "SyncSetupSetSyncEverything",
-      base::Bind(&PeopleHandler::HandleSetSyncEverything,
-                 base::Unretained(this)));
+      base::BindRepeating(&PeopleHandler::HandleSetSyncEverything,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "SyncSetupSetEncryption",
-      base::Bind(&PeopleHandler::HandleSetEncryption, base::Unretained(this)));
+      base::BindRepeating(&PeopleHandler::HandleSetEncryption,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "SyncSetupShowSetupUI",
-      base::Bind(&PeopleHandler::HandleShowSetupUI, base::Unretained(this)));
+      base::BindRepeating(&PeopleHandler::HandleShowSetupUI,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "SyncSetupGetSyncStatus",
-      base::Bind(&PeopleHandler::HandleGetSyncStatus, base::Unretained(this)));
+      base::BindRepeating(&PeopleHandler::HandleGetSyncStatus,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "SyncSetupManageOtherPeople",
-      base::Bind(&PeopleHandler::HandleManageOtherPeople,
-                 base::Unretained(this)));
+      base::BindRepeating(&PeopleHandler::HandleManageOtherPeople,
+                          base::Unretained(this)));
 #if defined(OS_CHROMEOS)
   web_ui()->RegisterMessageCallback(
       "AttemptUserExit",
-      base::Bind(&PeopleHandler::HandleAttemptUserExit,
-                 base::Unretained(this)));
+      base::BindRepeating(&PeopleHandler::HandleAttemptUserExit,
+                          base::Unretained(this)));
 #else
   web_ui()->RegisterMessageCallback(
       "SyncSetupStopSyncing",
-      base::Bind(&PeopleHandler::HandleStopSyncing, base::Unretained(this)));
+      base::BindRepeating(&PeopleHandler::HandleStopSyncing,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "SyncSetupStartSignIn",
-      base::Bind(&PeopleHandler::HandleStartSignin, base::Unretained(this)));
+      base::BindRepeating(&PeopleHandler::HandleStartSignin,
+                          base::Unretained(this)));
 #endif
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
   web_ui()->RegisterMessageCallback(
@@ -617,6 +625,14 @@
 void PeopleHandler::HandleShowSetupUI(const base::ListValue* args) {
   AllowJavascript();
 
+  // Just let the page open for now, even when the user's not signed in.
+  // TODO(scottchen): finish the UI for signed-out users
+  //    (https://crbug.com/800972).
+  if (IsUnifiedConsentEnabled(profile_) && IsProfileAuthNeededOrHasErrors()) {
+    FireWebUIListener("sync-prefs-changed", base::DictionaryValue());
+    return;
+  }
+
   ProfileSyncService* service = GetSyncService();
   if (!service) {
     CloseUI();
diff --git a/chrome/browser/ui/webui/settings/printing_handler.cc b/chrome/browser/ui/webui/settings/printing_handler.cc
index 4564403..8647b2d 100644
--- a/chrome/browser/ui/webui/settings/printing_handler.cc
+++ b/chrome/browser/ui/webui/settings/printing_handler.cc
@@ -18,8 +18,8 @@
 void PrintingHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "openSystemPrintDialog",
-      base::Bind(&PrintingHandler::HandleOpenSystemPrintDialog,
-                 base::Unretained(this)));
+      base::BindRepeating(&PrintingHandler::HandleOpenSystemPrintDialog,
+                          base::Unretained(this)));
 }
 
 void PrintingHandler::OnJavascriptAllowed() {}
diff --git a/chrome/browser/ui/webui/settings/profile_info_handler.cc b/chrome/browser/ui/webui/settings/profile_info_handler.cc
index 299d6fe..e7c647f 100644
--- a/chrome/browser/ui/webui/settings/profile_info_handler.cc
+++ b/chrome/browser/ui/webui/settings/profile_info_handler.cc
@@ -52,13 +52,14 @@
 
 void ProfileInfoHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
-      "getProfileInfo", base::Bind(&ProfileInfoHandler::HandleGetProfileInfo,
-                                   base::Unretained(this)));
+      "getProfileInfo",
+      base::BindRepeating(&ProfileInfoHandler::HandleGetProfileInfo,
+                          base::Unretained(this)));
 #if !defined(OS_CHROMEOS)
   web_ui()->RegisterMessageCallback(
       "getProfileStatsCount",
-      base::Bind(&ProfileInfoHandler::HandleGetProfileStats,
-                 base::Unretained(this)));
+      base::BindRepeating(&ProfileInfoHandler::HandleGetProfileStats,
+                          base::Unretained(this)));
 #endif
 }
 
diff --git a/chrome/browser/ui/webui/settings/protocol_handlers_handler.cc b/chrome/browser/ui/webui/settings/protocol_handlers_handler.cc
index 3b1453e6..57d7ceca 100644
--- a/chrome/browser/ui/webui/settings/protocol_handlers_handler.cc
+++ b/chrome/browser/ui/webui/settings/protocol_handlers_handler.cc
@@ -40,22 +40,28 @@
 }
 
 void ProtocolHandlersHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback("observeProtocolHandlers",
-      base::Bind(&ProtocolHandlersHandler::HandleObserveProtocolHandlers,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("observeProtocolHandlersEnabledState",
-      base::Bind(
+  web_ui()->RegisterMessageCallback(
+      "observeProtocolHandlers",
+      base::BindRepeating(
+          &ProtocolHandlersHandler::HandleObserveProtocolHandlers,
+          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "observeProtocolHandlersEnabledState",
+      base::BindRepeating(
           &ProtocolHandlersHandler::HandleObserveProtocolHandlersEnabledState,
           base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("removeHandler",
-      base::Bind(&ProtocolHandlersHandler::HandleRemoveHandler,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("setHandlersEnabled",
-      base::Bind(&ProtocolHandlersHandler::HandleSetHandlersEnabled,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("setDefault",
-      base::Bind(&ProtocolHandlersHandler::HandleSetDefault,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "removeHandler",
+      base::BindRepeating(&ProtocolHandlersHandler::HandleRemoveHandler,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "setHandlersEnabled",
+      base::BindRepeating(&ProtocolHandlersHandler::HandleSetHandlersEnabled,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "setDefault",
+      base::BindRepeating(&ProtocolHandlersHandler::HandleSetDefault,
+                          base::Unretained(this)));
 }
 
 ProtocolHandlerRegistry* ProtocolHandlersHandler::GetProtocolHandlerRegistry() {
diff --git a/chrome/browser/ui/webui/settings/reset_settings_handler.cc b/chrome/browser/ui/webui/settings/reset_settings_handler.cc
index 6ecd5cc..4cc1ff9e 100644
--- a/chrome/browser/ui/webui/settings/reset_settings_handler.cc
+++ b/chrome/browser/ui/webui/settings/reset_settings_handler.cc
@@ -105,30 +105,36 @@
 }
 
 void ResetSettingsHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback("performResetProfileSettings",
-      base::Bind(&ResetSettingsHandler::HandleResetProfileSettings,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("onShowResetProfileDialog",
-      base::Bind(&ResetSettingsHandler::OnShowResetProfileDialog,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("getReportedSettings",
-      base::Bind(&ResetSettingsHandler::HandleGetReportedSettings,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("onHideResetProfileDialog",
-      base::Bind(&ResetSettingsHandler::OnHideResetProfileDialog,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("onHideResetProfileBanner",
-      base::Bind(&ResetSettingsHandler::OnHideResetProfileBanner,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "performResetProfileSettings",
+      base::BindRepeating(&ResetSettingsHandler::HandleResetProfileSettings,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "onShowResetProfileDialog",
+      base::BindRepeating(&ResetSettingsHandler::OnShowResetProfileDialog,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "getReportedSettings",
+      base::BindRepeating(&ResetSettingsHandler::HandleGetReportedSettings,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "onHideResetProfileDialog",
+      base::BindRepeating(&ResetSettingsHandler::OnHideResetProfileDialog,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "onHideResetProfileBanner",
+      base::BindRepeating(&ResetSettingsHandler::OnHideResetProfileBanner,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "getTriggeredResetToolName",
-      base::Bind(&ResetSettingsHandler::HandleGetTriggeredResetToolName,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &ResetSettingsHandler::HandleGetTriggeredResetToolName,
+          base::Unretained(this)));
 #if defined(OS_CHROMEOS)
   web_ui()->RegisterMessageCallback(
-       "onPowerwashDialogShow",
-       base::Bind(&ResetSettingsHandler::OnShowPowerwashDialog,
-                  base::Unretained(this)));
+      "onPowerwashDialogShow",
+      base::BindRepeating(&ResetSettingsHandler::OnShowPowerwashDialog,
+                          base::Unretained(this)));
 #endif  // defined(OS_CHROMEOS)
 }
 
diff --git a/chrome/browser/ui/webui/settings/safe_browsing_handler.cc b/chrome/browser/ui/webui/settings/safe_browsing_handler.cc
index f017287a..2601cbc 100644
--- a/chrome/browser/ui/webui/settings/safe_browsing_handler.cc
+++ b/chrome/browser/ui/webui/settings/safe_browsing_handler.cc
@@ -19,11 +19,12 @@
 void SafeBrowsingHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "getSafeBrowsingExtendedReporting",
-      base::Bind(&SafeBrowsingHandler::HandleGetSafeBrowsingExtendedReporting,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &SafeBrowsingHandler::HandleGetSafeBrowsingExtendedReporting,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "setSafeBrowsingExtendedReportingEnabled",
-      base::Bind(
+      base::BindRepeating(
           &SafeBrowsingHandler::HandleSetSafeBrowsingExtendedReportingEnabled,
           base::Unretained(this)));
 }
diff --git a/chrome/browser/ui/webui/settings/search_engines_handler.cc b/chrome/browser/ui/webui/settings/search_engines_handler.cc
index f051d091..bf98d178 100644
--- a/chrome/browser/ui/webui/settings/search_engines_handler.cc
+++ b/chrome/browser/ui/webui/settings/search_engines_handler.cc
@@ -61,32 +61,35 @@
 void SearchEnginesHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "getSearchEnginesList",
-      base::Bind(&SearchEnginesHandler::HandleGetSearchEnginesList,
-                 base::Unretained(this)));
+      base::BindRepeating(&SearchEnginesHandler::HandleGetSearchEnginesList,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "setDefaultSearchEngine",
-      base::Bind(&SearchEnginesHandler::HandleSetDefaultSearchEngine,
-                 base::Unretained(this)));
+      base::BindRepeating(&SearchEnginesHandler::HandleSetDefaultSearchEngine,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "removeSearchEngine",
-      base::Bind(&SearchEnginesHandler::HandleRemoveSearchEngine,
-                 base::Unretained(this)));
+      base::BindRepeating(&SearchEnginesHandler::HandleRemoveSearchEngine,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "validateSearchEngineInput",
-      base::Bind(&SearchEnginesHandler::HandleValidateSearchEngineInput,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &SearchEnginesHandler::HandleValidateSearchEngineInput,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "searchEngineEditStarted",
-      base::Bind(&SearchEnginesHandler::HandleSearchEngineEditStarted,
-                 base::Unretained(this)));
+      base::BindRepeating(&SearchEnginesHandler::HandleSearchEngineEditStarted,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "searchEngineEditCancelled",
-      base::Bind(&SearchEnginesHandler::HandleSearchEngineEditCancelled,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &SearchEnginesHandler::HandleSearchEngineEditCancelled,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "searchEngineEditCompleted",
-      base::Bind(&SearchEnginesHandler::HandleSearchEngineEditCompleted,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &SearchEnginesHandler::HandleSearchEngineEditCompleted,
+          base::Unretained(this)));
 }
 
 void SearchEnginesHandler::OnJavascriptAllowed() {
diff --git a/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.cc b/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.cc
index b4c04a9..f6e53a16 100644
--- a/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.cc
+++ b/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.cc
@@ -93,18 +93,18 @@
 void ClearBrowsingDataHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "clearBrowsingData",
-      base::Bind(&ClearBrowsingDataHandler::HandleClearBrowsingData,
-                 base::Unretained(this)));
+      base::BindRepeating(&ClearBrowsingDataHandler::HandleClearBrowsingData,
+                          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       "getImportantSites",
-      base::Bind(&ClearBrowsingDataHandler::HandleGetImportantSites,
-                 base::Unretained(this)));
+      base::BindRepeating(&ClearBrowsingDataHandler::HandleGetImportantSites,
+                          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       "initializeClearBrowsingData",
-      base::Bind(&ClearBrowsingDataHandler::HandleInitialize,
-                 base::Unretained(this)));
+      base::BindRepeating(&ClearBrowsingDataHandler::HandleInitialize,
+                          base::Unretained(this)));
 }
 
 void ClearBrowsingDataHandler::OnJavascriptAllowed() {
diff --git a/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc b/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc
index 9b31e54..2017d6c 100644
--- a/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc
+++ b/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc
@@ -160,28 +160,32 @@
 
   web_ui()->RegisterMessageCallback(
       "localData.getDisplayList",
-      base::Bind(&CookiesViewHandler::HandleGetDisplayList,
-                 base::Unretained(this)));
+      base::BindRepeating(&CookiesViewHandler::HandleGetDisplayList,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "localData.removeAll",
-      base::Bind(&CookiesViewHandler::HandleRemoveAll, base::Unretained(this)));
+      base::BindRepeating(&CookiesViewHandler::HandleRemoveAll,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "localData.removeShownItems",
-      base::Bind(&CookiesViewHandler::HandleRemoveShownItems,
-                 base::Unretained(this)));
+      base::BindRepeating(&CookiesViewHandler::HandleRemoveShownItems,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "localData.removeItem", base::Bind(&CookiesViewHandler::HandleRemoveItem,
-                                         base::Unretained(this)));
+      "localData.removeItem",
+      base::BindRepeating(&CookiesViewHandler::HandleRemoveItem,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "localData.getCookieDetails",
-      base::Bind(&CookiesViewHandler::HandleGetCookieDetails,
-                 base::Unretained(this)));
+      base::BindRepeating(&CookiesViewHandler::HandleGetCookieDetails,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "localData.removeCookie",
-      base::Bind(&CookiesViewHandler::HandleRemove, base::Unretained(this)));
+      base::BindRepeating(&CookiesViewHandler::HandleRemove,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "localData.reload", base::Bind(&CookiesViewHandler::HandleReloadCookies,
-                                     base::Unretained(this)));
+      "localData.reload",
+      base::BindRepeating(&CookiesViewHandler::HandleReloadCookies,
+                          base::Unretained(this)));
 }
 
 void CookiesViewHandler::TreeNodesAdded(ui::TreeModel* model,
diff --git a/chrome/browser/ui/webui/settings/settings_default_browser_handler.cc b/chrome/browser/ui/webui/settings/settings_default_browser_handler.cc
index 66932e5..bc66616f 100644
--- a/chrome/browser/ui/webui/settings/settings_default_browser_handler.cc
+++ b/chrome/browser/ui/webui/settings/settings_default_browser_handler.cc
@@ -39,12 +39,12 @@
 void DefaultBrowserHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "SettingsDefaultBrowser.requestDefaultBrowserState",
-      base::Bind(&DefaultBrowserHandler::RequestDefaultBrowserState,
-                 base::Unretained(this)));
+      base::BindRepeating(&DefaultBrowserHandler::RequestDefaultBrowserState,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "SettingsDefaultBrowser.setAsDefaultBrowser",
-      base::Bind(&DefaultBrowserHandler::SetAsDefaultBrowser,
-                 base::Unretained(this)));
+      base::BindRepeating(&DefaultBrowserHandler::SetAsDefaultBrowser,
+                          base::Unretained(this)));
 }
 
 void DefaultBrowserHandler::OnJavascriptAllowed() {
diff --git a/chrome/browser/ui/webui/settings/settings_import_data_handler.cc b/chrome/browser/ui/webui/settings/settings_import_data_handler.cc
index 4a01949..32deebd 100644
--- a/chrome/browser/ui/webui/settings/settings_import_data_handler.cc
+++ b/chrome/browser/ui/webui/settings/settings_import_data_handler.cc
@@ -60,14 +60,15 @@
 
   web_ui()->RegisterMessageCallback(
       "initializeImportDialog",
-      base::Bind(&ImportDataHandler::InitializeDialog, base::Unretained(this)));
+      base::BindRepeating(&ImportDataHandler::InitializeDialog,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "importData",
-      base::Bind(&ImportDataHandler::ImportData, base::Unretained(this)));
+      "importData", base::BindRepeating(&ImportDataHandler::ImportData,
+                                        base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "importFromBookmarksFile",
-      base::Bind(&ImportDataHandler::HandleChooseBookmarksFile,
-                 base::Unretained(this)));
+      base::BindRepeating(&ImportDataHandler::HandleChooseBookmarksFile,
+                          base::Unretained(this)));
 }
 
 void ImportDataHandler::OnJavascriptDisallowed() {
diff --git a/chrome/browser/ui/webui/settings/settings_manage_profile_handler.cc b/chrome/browser/ui/webui/settings/settings_manage_profile_handler.cc
index 6a6ab39c..5a68d24 100644
--- a/chrome/browser/ui/webui/settings/settings_manage_profile_handler.cc
+++ b/chrome/browser/ui/webui/settings/settings_manage_profile_handler.cc
@@ -58,31 +58,35 @@
 void ManageProfileHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "getAvailableIcons",
-      base::Bind(&ManageProfileHandler::HandleGetAvailableIcons,
-                 base::Unretained(this)));
+      base::BindRepeating(&ManageProfileHandler::HandleGetAvailableIcons,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "setProfileIconToGaiaAvatar",
-      base::Bind(&ManageProfileHandler::HandleSetProfileIconToGaiaAvatar,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &ManageProfileHandler::HandleSetProfileIconToGaiaAvatar,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "setProfileIconToDefaultAvatar",
-      base::Bind(&ManageProfileHandler::HandleSetProfileIconToDefaultAvatar,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &ManageProfileHandler::HandleSetProfileIconToDefaultAvatar,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "setProfileName", base::Bind(&ManageProfileHandler::HandleSetProfileName,
-                                   base::Unretained(this)));
+      "setProfileName",
+      base::BindRepeating(&ManageProfileHandler::HandleSetProfileName,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "requestProfileShortcutStatus",
-      base::Bind(&ManageProfileHandler::HandleRequestProfileShortcutStatus,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &ManageProfileHandler::HandleRequestProfileShortcutStatus,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "addProfileShortcut",
-      base::Bind(&ManageProfileHandler::HandleAddProfileShortcut,
-                 base::Unretained(this)));
+      base::BindRepeating(&ManageProfileHandler::HandleAddProfileShortcut,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "removeProfileShortcut",
-      base::Bind(&ManageProfileHandler::HandleRemoveProfileShortcut,
-                 base::Unretained(this)));
+      base::BindRepeating(&ManageProfileHandler::HandleRemoveProfileShortcut,
+                          base::Unretained(this)));
 }
 
 void ManageProfileHandler::OnJavascriptAllowed() {
diff --git a/chrome/browser/ui/webui/settings/settings_media_devices_selection_handler.cc b/chrome/browser/ui/webui/settings/settings_media_devices_selection_handler.cc
index 17987af..9c91e087 100644
--- a/chrome/browser/ui/webui/settings/settings_media_devices_selection_handler.cc
+++ b/chrome/browser/ui/webui/settings/settings_media_devices_selection_handler.cc
@@ -46,12 +46,16 @@
 }
 
 void MediaDevicesSelectionHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback("getDefaultCaptureDevices",
-      base::Bind(&MediaDevicesSelectionHandler::GetDefaultCaptureDevices,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("setDefaultCaptureDevice",
-      base::Bind(&MediaDevicesSelectionHandler::SetDefaultCaptureDevice,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "getDefaultCaptureDevices",
+      base::BindRepeating(
+          &MediaDevicesSelectionHandler::GetDefaultCaptureDevices,
+          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "setDefaultCaptureDevice",
+      base::BindRepeating(
+          &MediaDevicesSelectionHandler::SetDefaultCaptureDevice,
+          base::Unretained(this)));
 }
 
 void MediaDevicesSelectionHandler::OnUpdateAudioDevices(
diff --git a/chrome/browser/ui/webui/settings/settings_startup_pages_handler.cc b/chrome/browser/ui/webui/settings/settings_startup_pages_handler.cc
index 4b128752..36037ef 100644
--- a/chrome/browser/ui/webui/settings/settings_startup_pages_handler.cc
+++ b/chrome/browser/ui/webui/settings/settings_startup_pages_handler.cc
@@ -29,21 +29,27 @@
   if (Profile::FromWebUI(web_ui())->IsOffTheRecord())
     return;
 
-  web_ui()->RegisterMessageCallback("addStartupPage",
-      base::Bind(&StartupPagesHandler::HandleAddStartupPage,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("editStartupPage",
-      base::Bind(&StartupPagesHandler::HandleEditStartupPage,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("onStartupPrefsPageLoad",
-      base::Bind(&StartupPagesHandler::HandleOnStartupPrefsPageLoad,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("removeStartupPage",
-      base::Bind(&StartupPagesHandler::HandleRemoveStartupPage,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("setStartupPagesToCurrentPages",
-      base::Bind(&StartupPagesHandler::HandleSetStartupPagesToCurrentPages,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "addStartupPage",
+      base::BindRepeating(&StartupPagesHandler::HandleAddStartupPage,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "editStartupPage",
+      base::BindRepeating(&StartupPagesHandler::HandleEditStartupPage,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "onStartupPrefsPageLoad",
+      base::BindRepeating(&StartupPagesHandler::HandleOnStartupPrefsPageLoad,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "removeStartupPage",
+      base::BindRepeating(&StartupPagesHandler::HandleRemoveStartupPage,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "setStartupPagesToCurrentPages",
+      base::BindRepeating(
+          &StartupPagesHandler::HandleSetStartupPagesToCurrentPages,
+          base::Unretained(this)));
 }
 
 void StartupPagesHandler::OnJavascriptAllowed() {
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler.cc b/chrome/browser/ui/webui/settings/site_settings_handler.cc
index 8a37d2655..a8a66e29 100644
--- a/chrome/browser/ui/webui/settings/site_settings_handler.cc
+++ b/chrome/browser/ui/webui/settings/site_settings_handler.cc
@@ -125,70 +125,75 @@
 void SiteSettingsHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "fetchUsageTotal",
-      base::Bind(&SiteSettingsHandler::HandleFetchUsageTotal,
-                 base::Unretained(this)));
+      base::BindRepeating(&SiteSettingsHandler::HandleFetchUsageTotal,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "clearUsage",
-      base::Bind(&SiteSettingsHandler::HandleClearUsage,
-                 base::Unretained(this)));
+      "clearUsage", base::BindRepeating(&SiteSettingsHandler::HandleClearUsage,
+                                        base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "fetchUsbDevices",
-      base::Bind(&SiteSettingsHandler::HandleFetchUsbDevices,
-                 base::Unretained(this)));
+      base::BindRepeating(&SiteSettingsHandler::HandleFetchUsbDevices,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "removeUsbDevice",
-      base::Bind(&SiteSettingsHandler::HandleRemoveUsbDevice,
-                 base::Unretained(this)));
+      base::BindRepeating(&SiteSettingsHandler::HandleRemoveUsbDevice,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "setDefaultValueForContentType",
-      base::Bind(&SiteSettingsHandler::HandleSetDefaultValueForContentType,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &SiteSettingsHandler::HandleSetDefaultValueForContentType,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "getDefaultValueForContentType",
-      base::Bind(&SiteSettingsHandler::HandleGetDefaultValueForContentType,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &SiteSettingsHandler::HandleGetDefaultValueForContentType,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "getExceptionList",
-      base::Bind(&SiteSettingsHandler::HandleGetExceptionList,
-                 base::Unretained(this)));
+      base::BindRepeating(&SiteSettingsHandler::HandleGetExceptionList,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "getOriginPermissions",
-      base::Bind(&SiteSettingsHandler::HandleGetOriginPermissions,
-                 base::Unretained(this)));
+      base::BindRepeating(&SiteSettingsHandler::HandleGetOriginPermissions,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "setOriginPermissions",
-      base::Bind(&SiteSettingsHandler::HandleSetOriginPermissions,
-                 base::Unretained(this)));
+      base::BindRepeating(&SiteSettingsHandler::HandleSetOriginPermissions,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "clearFlashPref", base::Bind(&SiteSettingsHandler::HandleClearFlashPref,
-                                   base::Unretained(this)));
+      "clearFlashPref",
+      base::BindRepeating(&SiteSettingsHandler::HandleClearFlashPref,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "resetCategoryPermissionForPattern",
-      base::Bind(&SiteSettingsHandler::HandleResetCategoryPermissionForPattern,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &SiteSettingsHandler::HandleResetCategoryPermissionForPattern,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "setCategoryPermissionForPattern",
-      base::Bind(&SiteSettingsHandler::HandleSetCategoryPermissionForPattern,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &SiteSettingsHandler::HandleSetCategoryPermissionForPattern,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "isOriginValid", base::Bind(&SiteSettingsHandler::HandleIsOriginValid,
-                                  base::Unretained(this)));
+      "isOriginValid",
+      base::BindRepeating(&SiteSettingsHandler::HandleIsOriginValid,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "isPatternValid",
-      base::Bind(&SiteSettingsHandler::HandleIsPatternValid,
-                 base::Unretained(this)));
+      base::BindRepeating(&SiteSettingsHandler::HandleIsPatternValid,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "updateIncognitoStatus",
-      base::Bind(&SiteSettingsHandler::HandleUpdateIncognitoStatus,
-                 base::Unretained(this)));
+      base::BindRepeating(&SiteSettingsHandler::HandleUpdateIncognitoStatus,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "fetchZoomLevels",
-      base::Bind(&SiteSettingsHandler::HandleFetchZoomLevels,
-                 base::Unretained(this)));
+      base::BindRepeating(&SiteSettingsHandler::HandleFetchZoomLevels,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "removeZoomLevel",
-      base::Bind(&SiteSettingsHandler::HandleRemoveZoomLevel,
-                 base::Unretained(this)));
+      base::BindRepeating(&SiteSettingsHandler::HandleRemoveZoomLevel,
+                          base::Unretained(this)));
 }
 
 void SiteSettingsHandler::OnJavascriptAllowed() {
diff --git a/chrome/browser/ui/webui/settings/system_handler.cc b/chrome/browser/ui/webui/settings/system_handler.cc
index c87ab9f..7c70827 100644
--- a/chrome/browser/ui/webui/settings/system_handler.cc
+++ b/chrome/browser/ui/webui/settings/system_handler.cc
@@ -28,8 +28,9 @@
 
 void SystemHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
-      "showProxySettings", base::Bind(&SystemHandler::HandleShowProxySettings,
-                                      base::Unretained(this)));
+      "showProxySettings",
+      base::BindRepeating(&SystemHandler::HandleShowProxySettings,
+                          base::Unretained(this)));
 }
 
 void SystemHandler::HandleShowProxySettings(const base::ListValue* /*args*/) {
diff --git a/chrome/browser/ui/webui/signin/inline_login_handler.cc b/chrome/browser/ui/webui/signin/inline_login_handler.cc
index 89c7c432..8f581b17 100644
--- a/chrome/browser/ui/webui/signin/inline_login_handler.cc
+++ b/chrome/browser/ui/webui/signin/inline_login_handler.cc
@@ -37,22 +37,25 @@
 InlineLoginHandler::~InlineLoginHandler() {}
 
 void InlineLoginHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback("initialize",
-      base::Bind(&InlineLoginHandler::HandleInitializeMessage,
-                  base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("completeLogin",
-      base::Bind(&InlineLoginHandler::HandleCompleteLoginMessage,
-                  base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "initialize",
+      base::BindRepeating(&InlineLoginHandler::HandleInitializeMessage,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "completeLogin",
+      base::BindRepeating(&InlineLoginHandler::HandleCompleteLoginMessage,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "switchToFullTab",
-      base::Bind(&InlineLoginHandler::HandleSwitchToFullTabMessage,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("navigationButtonClicked",
-      base::Bind(&InlineLoginHandler::HandleNavigationButtonClicked,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("dialogClose",
-      base::Bind(&InlineLoginHandler::HandleDialogClose,
-                 base::Unretained(this)));
+      base::BindRepeating(&InlineLoginHandler::HandleSwitchToFullTabMessage,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "navigationButtonClicked",
+      base::BindRepeating(&InlineLoginHandler::HandleNavigationButtonClicked,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "dialogClose", base::BindRepeating(&InlineLoginHandler::HandleDialogClose,
+                                         base::Unretained(this)));
 }
 
 void InlineLoginHandler::HandleInitializeMessage(const base::ListValue* args) {
diff --git a/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc b/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc
index b98fde0..93fe4d5a4 100644
--- a/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc
+++ b/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc
@@ -202,10 +202,8 @@
     Profile::CreateStatus status) {
   if (is_force_sign_in_with_usermanager_)
     UnlockProfileAndHideLoginUI(profile_->GetPath(), handler_.get());
-  content::WebContents* contents = NULL;
   Browser* browser = NULL;
   if (handler_) {
-    contents = handler_->web_ui()->GetWebContents();
     browser = handler_->GetDesktopBrowser();
   }
 
diff --git a/chrome/browser/ui/webui/signin/signin_create_profile_handler.cc b/chrome/browser/ui/webui/signin/signin_create_profile_handler.cc
index ea5488a..3f06185b 100644
--- a/chrome/browser/ui/webui/signin/signin_create_profile_handler.cc
+++ b/chrome/browser/ui/webui/signin/signin_create_profile_handler.cc
@@ -159,27 +159,30 @@
   // Cancellation is only supported for supervised users.
   web_ui()->RegisterMessageCallback(
       "cancelCreateProfile",
-      base::Bind(&SigninCreateProfileHandler::HandleCancelProfileCreation,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &SigninCreateProfileHandler::HandleCancelProfileCreation,
+          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       "switchToProfile",
-      base::Bind(&SigninCreateProfileHandler::SwitchToProfile,
-                 base::Unretained(this)));
+      base::BindRepeating(&SigninCreateProfileHandler::SwitchToProfile,
+                          base::Unretained(this)));
 #endif
   web_ui()->RegisterMessageCallback(
-      "createProfile", base::Bind(&SigninCreateProfileHandler::CreateProfile,
-                                  base::Unretained(this)));
+      "createProfile",
+      base::BindRepeating(&SigninCreateProfileHandler::CreateProfile,
+                          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       "requestDefaultProfileIcons",
-      base::Bind(&SigninCreateProfileHandler::RequestDefaultProfileIcons,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &SigninCreateProfileHandler::RequestDefaultProfileIcons,
+          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       "requestSignedInProfiles",
-      base::Bind(&SigninCreateProfileHandler::RequestSignedInProfiles,
-                 base::Unretained(this)));
+      base::BindRepeating(&SigninCreateProfileHandler::RequestSignedInProfiles,
+                          base::Unretained(this)));
 }
 
 void SigninCreateProfileHandler::RequestDefaultProfileIcons(
diff --git a/chrome/browser/ui/webui/signin/signin_error_handler.cc b/chrome/browser/ui/webui/signin/signin_error_handler.cc
index 6824d82..8bda6fa 100644
--- a/chrome/browser/ui/webui/signin/signin_error_handler.cc
+++ b/chrome/browser/ui/webui/signin/signin_error_handler.cc
@@ -34,21 +34,21 @@
 
 void SigninErrorHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
-      "confirm",
-      base::Bind(&SigninErrorHandler::HandleConfirm, base::Unretained(this)));
+      "confirm", base::BindRepeating(&SigninErrorHandler::HandleConfirm,
+                                     base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "switchToExistingProfile",
-      base::Bind(&SigninErrorHandler::HandleSwitchToExistingProfile,
-                 base::Unretained(this)));
+      base::BindRepeating(&SigninErrorHandler::HandleSwitchToExistingProfile,
+                          base::Unretained(this)));
   if (!is_system_profile_) {
     web_ui()->RegisterMessageCallback(
-        "learnMore", base::Bind(&SigninErrorHandler::HandleLearnMore,
-                                base::Unretained(this)));
+        "learnMore", base::BindRepeating(&SigninErrorHandler::HandleLearnMore,
+                                         base::Unretained(this)));
   }
   web_ui()->RegisterMessageCallback(
       "initializedWithSize",
-      base::Bind(&SigninErrorHandler::HandleInitializedWithSize,
-                 base::Unretained(this)));
+      base::BindRepeating(&SigninErrorHandler::HandleInitializedWithSize,
+                          base::Unretained(this)));
 }
 
 void SigninErrorHandler::HandleSwitchToExistingProfile(
diff --git a/chrome/browser/ui/webui/signin/signin_supervised_user_import_handler.cc b/chrome/browser/ui/webui/signin/signin_supervised_user_import_handler.cc
index f7e115ff..1de21e772 100644
--- a/chrome/browser/ui/webui/signin/signin_supervised_user_import_handler.cc
+++ b/chrome/browser/ui/webui/signin/signin_supervised_user_import_handler.cc
@@ -70,20 +70,24 @@
 }
 
 void SigninSupervisedUserImportHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback("getExistingSupervisedUsers",
-      base::Bind(&SigninSupervisedUserImportHandler::GetExistingSupervisedUsers,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("openUrlInLastActiveProfileBrowser",
-      base::Bind(
+  web_ui()->RegisterMessageCallback(
+      "getExistingSupervisedUsers",
+      base::BindRepeating(
+          &SigninSupervisedUserImportHandler::GetExistingSupervisedUsers,
+          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "openUrlInLastActiveProfileBrowser",
+      base::BindRepeating(
           &SigninSupervisedUserImportHandler::OpenUrlInLastActiveProfileBrowser,
           base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "authenticateCustodian",
-      base::Bind(&SigninSupervisedUserImportHandler::AuthenticateCustodian,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &SigninSupervisedUserImportHandler::AuthenticateCustodian,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "cancelLoadingSupervisedUsers",
-      base::Bind(
+      base::BindRepeating(
           &SigninSupervisedUserImportHandler::HandleCancelLoadSupervisedUsers,
           base::Unretained(this)));
 }
diff --git a/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc b/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc
index e2ed758..f1e5aa3 100644
--- a/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc
+++ b/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc
@@ -59,17 +59,20 @@
 }
 
 void SyncConfirmationHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback("confirm",
-      base::Bind(&SyncConfirmationHandler::HandleConfirm,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("undo",
-      base::Bind(&SyncConfirmationHandler::HandleUndo, base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "goToSettings", base::Bind(&SyncConfirmationHandler::HandleGoToSettings,
-                                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("initializedWithSize",
-      base::Bind(&SyncConfirmationHandler::HandleInitializedWithSize,
-                 base::Unretained(this)));
+      "confirm", base::BindRepeating(&SyncConfirmationHandler::HandleConfirm,
+                                     base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "undo", base::BindRepeating(&SyncConfirmationHandler::HandleUndo,
+                                  base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "goToSettings",
+      base::BindRepeating(&SyncConfirmationHandler::HandleGoToSettings,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "initializedWithSize",
+      base::BindRepeating(&SyncConfirmationHandler::HandleInitializedWithSize,
+                          base::Unretained(this)));
 }
 
 void SyncConfirmationHandler::HandleConfirm(const base::ListValue* args) {
diff --git a/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc b/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
index d41a28db..a449210 100644
--- a/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
+++ b/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
@@ -588,30 +588,39 @@
 }
 
 void UserManagerScreenHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback(kJsApiUserManagerInitialize,
-      base::Bind(&UserManagerScreenHandler::HandleInitialize,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback(kJsApiUserManagerAuthLaunchUser,
-      base::Bind(&UserManagerScreenHandler::HandleAuthenticatedLaunchUser,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback(kJsApiUserManagerLaunchGuest,
-      base::Bind(&UserManagerScreenHandler::HandleLaunchGuest,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback(kJsApiUserManagerLaunchUser,
-      base::Bind(&UserManagerScreenHandler::HandleLaunchUser,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback(kJsApiUserManagerRemoveUser,
-      base::Bind(&UserManagerScreenHandler::HandleRemoveUser,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback(kJsApiUserManagerLogRemoveUserWarningShown,
-      base::Bind(&HandleLogRemoveUserWarningShown));
-  web_ui()->RegisterMessageCallback(kJsApiUserManagerRemoveUserWarningLoadStats,
-      base::Bind(&UserManagerScreenHandler::HandleRemoveUserWarningLoadStats,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      kJsApiUserManagerInitialize,
+      base::BindRepeating(&UserManagerScreenHandler::HandleInitialize,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      kJsApiUserManagerAuthLaunchUser,
+      base::BindRepeating(
+          &UserManagerScreenHandler::HandleAuthenticatedLaunchUser,
+          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      kJsApiUserManagerLaunchGuest,
+      base::BindRepeating(&UserManagerScreenHandler::HandleLaunchGuest,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      kJsApiUserManagerLaunchUser,
+      base::BindRepeating(&UserManagerScreenHandler::HandleLaunchUser,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      kJsApiUserManagerRemoveUser,
+      base::BindRepeating(&UserManagerScreenHandler::HandleRemoveUser,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      kJsApiUserManagerLogRemoveUserWarningShown,
+      base::BindRepeating(&HandleLogRemoveUserWarningShown));
+  web_ui()->RegisterMessageCallback(
+      kJsApiUserManagerRemoveUserWarningLoadStats,
+      base::BindRepeating(
+          &UserManagerScreenHandler::HandleRemoveUserWarningLoadStats,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       kJsApiUserManagerAreAllProfilesLocked,
-      base::Bind(&UserManagerScreenHandler::HandleAreAllProfilesLocked,
-                 base::Unretained(this)));
+      base::BindRepeating(&UserManagerScreenHandler::HandleAreAllProfilesLocked,
+                          base::Unretained(this)));
 
   // Unused callbacks from screen_account_picker.js
   web_ui()->RegisterMessageCallback("accountPickerReady", base::DoNothing());
diff --git a/chrome/browser/ui/webui/snippets_internals_message_handler.cc b/chrome/browser/ui/webui/snippets_internals_message_handler.cc
index 52527a8d..ad838c64 100644
--- a/chrome/browser/ui/webui/snippets_internals_message_handler.cc
+++ b/chrome/browser/ui/webui/snippets_internals_message_handler.cc
@@ -195,62 +195,67 @@
 void SnippetsInternalsMessageHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "clearCachedSuggestions",
-      base::Bind(&SnippetsInternalsMessageHandler::HandleClearCachedSuggestions,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &SnippetsInternalsMessageHandler::HandleClearCachedSuggestions,
+          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       "clearClassification",
-      base::Bind(&SnippetsInternalsMessageHandler::HandleClearClassification,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &SnippetsInternalsMessageHandler::HandleClearClassification,
+          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       "clearDismissedSuggestions",
-      base::Bind(
+      base::BindRepeating(
           &SnippetsInternalsMessageHandler::HandleClearDismissedSuggestions,
           base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
-      "download", base::Bind(&SnippetsInternalsMessageHandler::HandleDownload,
-                             base::Unretained(this)));
+      "download",
+      base::BindRepeating(&SnippetsInternalsMessageHandler::HandleDownload,
+                          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       "fetchRemoteSuggestionsInTheBackgroundIn2Seconds",
-      base::Bind(&SnippetsInternalsMessageHandler::
-                     HandleFetchRemoteSuggestionsInTheBackgroundIn2Seconds,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &SnippetsInternalsMessageHandler::
+              HandleFetchRemoteSuggestionsInTheBackgroundIn2Seconds,
+          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       "fetchContextualSuggestions",
-      base::Bind(
+      base::BindRepeating(
           &SnippetsInternalsMessageHandler::HandleFetchContextualSuggestions,
           base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       "resetNotificationsState",
-      base::Bind(
+      base::BindRepeating(
           &SnippetsInternalsMessageHandler::HandleResetNotificationsState,
           base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       "pushDummySuggestionIn10Seconds",
-      base::Bind(&SnippetsInternalsMessageHandler::
-                     HandlePushDummySuggestionIn10Seconds,
-                 base::Unretained(this)));
+      base::BindRepeating(&SnippetsInternalsMessageHandler::
+                              HandlePushDummySuggestionIn10Seconds,
+                          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       "refreshContent",
-      base::Bind(&SnippetsInternalsMessageHandler::HandleRefreshContent,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &SnippetsInternalsMessageHandler::HandleRefreshContent,
+          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       "toggleDismissedSuggestions",
-      base::Bind(
+      base::BindRepeating(
           &SnippetsInternalsMessageHandler::HandleToggleDismissedSuggestions,
           base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       "initializationCompleted",
-      base::Bind(
+      base::BindRepeating(
           &SnippetsInternalsMessageHandler::HandleInitializationCompleted,
           base::Unretained(this)));
 
diff --git a/chrome/browser/ui/webui/supervised_user_internals_message_handler.cc b/chrome/browser/ui/webui/supervised_user_internals_message_handler.cc
index a8a2f5e..8241044 100644
--- a/chrome/browser/ui/webui/supervised_user_internals_message_handler.cc
+++ b/chrome/browser/ui/webui/supervised_user_internals_message_handler.cc
@@ -126,18 +126,22 @@
 void SupervisedUserInternalsMessageHandler::RegisterMessages() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-  web_ui()->RegisterMessageCallback("registerForEvents",
-      base::Bind(&SupervisedUserInternalsMessageHandler::
-                     HandleRegisterForEvents,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "registerForEvents",
+      base::BindRepeating(
+          &SupervisedUserInternalsMessageHandler::HandleRegisterForEvents,
+          base::Unretained(this)));
 
-  web_ui()->RegisterMessageCallback("getBasicInfo",
-      base::Bind(&SupervisedUserInternalsMessageHandler::HandleGetBasicInfo,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "getBasicInfo",
+      base::BindRepeating(
+          &SupervisedUserInternalsMessageHandler::HandleGetBasicInfo,
+          base::Unretained(this)));
 
-  web_ui()->RegisterMessageCallback("tryURL",
-      base::Bind(&SupervisedUserInternalsMessageHandler::HandleTryURL,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "tryURL",
+      base::BindRepeating(&SupervisedUserInternalsMessageHandler::HandleTryURL,
+                          base::Unretained(this)));
 }
 
 void SupervisedUserInternalsMessageHandler::OnURLFilterChanged() {
diff --git a/chrome/browser/ui/webui/sync_file_system_internals/dump_database_handler.cc b/chrome/browser/ui/webui/sync_file_system_internals/dump_database_handler.cc
index 5d2d2db..5b6ab2d0 100644
--- a/chrome/browser/ui/webui/sync_file_system_internals/dump_database_handler.cc
+++ b/chrome/browser/ui/webui/sync_file_system_internals/dump_database_handler.cc
@@ -21,8 +21,8 @@
 void DumpDatabaseHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "getDatabaseDump",
-      base::Bind(&DumpDatabaseHandler::GetDatabaseDump,
-                 base::Unretained(this)));
+      base::BindRepeating(&DumpDatabaseHandler::GetDatabaseDump,
+                          base::Unretained(this)));
 }
 
 void DumpDatabaseHandler::GetDatabaseDump(const base::ListValue*) {
diff --git a/chrome/browser/ui/webui/sync_file_system_internals/extension_statuses_handler.cc b/chrome/browser/ui/webui/sync_file_system_internals/extension_statuses_handler.cc
index a9e8ec0..d6aa8fc 100644
--- a/chrome/browser/ui/webui/sync_file_system_internals/extension_statuses_handler.cc
+++ b/chrome/browser/ui/webui/sync_file_system_internals/extension_statuses_handler.cc
@@ -70,8 +70,8 @@
 void ExtensionStatusesHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "getExtensionStatuses",
-      base::Bind(&ExtensionStatusesHandler::GetExtensionStatuses,
-                 base::Unretained(this)));
+      base::BindRepeating(&ExtensionStatusesHandler::GetExtensionStatuses,
+                          base::Unretained(this)));
 }
 
 // static
diff --git a/chrome/browser/ui/webui/sync_file_system_internals/file_metadata_handler.cc b/chrome/browser/ui/webui/sync_file_system_internals/file_metadata_handler.cc
index 19108f4f..4779edd 100644
--- a/chrome/browser/ui/webui/sync_file_system_internals/file_metadata_handler.cc
+++ b/chrome/browser/ui/webui/sync_file_system_internals/file_metadata_handler.cc
@@ -32,13 +32,12 @@
 
 void FileMetadataHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
-      "getExtensions",
-      base::Bind(&FileMetadataHandler::GetExtensions,
-                 base::Unretained(this)));
+      "getExtensions", base::BindRepeating(&FileMetadataHandler::GetExtensions,
+                                           base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "getFileMetadata",
-      base::Bind(&FileMetadataHandler::GetFileMetadata,
-                 base::Unretained(this)));
+      base::BindRepeating(&FileMetadataHandler::GetFileMetadata,
+                          base::Unretained(this)));
 }
 
 void FileMetadataHandler::GetFileMetadata(
diff --git a/chrome/browser/ui/webui/sync_file_system_internals/sync_file_system_internals_handler.cc b/chrome/browser/ui/webui/sync_file_system_internals/sync_file_system_internals_handler.cc
index a17ed60d..bdbe8a70 100644
--- a/chrome/browser/ui/webui/sync_file_system_internals/sync_file_system_internals_handler.cc
+++ b/chrome/browser/ui/webui/sync_file_system_internals/sync_file_system_internals_handler.cc
@@ -54,24 +54,24 @@
 void SyncFileSystemInternalsHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "getServiceStatus",
-      base::Bind(&SyncFileSystemInternalsHandler::GetServiceStatus,
-                 base::Unretained(this)));
+      base::BindRepeating(&SyncFileSystemInternalsHandler::GetServiceStatus,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "getLog",
-      base::Bind(&SyncFileSystemInternalsHandler::GetLog,
-                 base::Unretained(this)));
+      "getLog", base::BindRepeating(&SyncFileSystemInternalsHandler::GetLog,
+                                    base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "clearLogs",
-      base::Bind(&SyncFileSystemInternalsHandler::ClearLogs,
-                 base::Unretained(this)));
+      base::BindRepeating(&SyncFileSystemInternalsHandler::ClearLogs,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "getNotificationSource",
-      base::Bind(&SyncFileSystemInternalsHandler::GetNotificationSource,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &SyncFileSystemInternalsHandler::GetNotificationSource,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "observeTaskLog",
-      base::Bind(&SyncFileSystemInternalsHandler::ObserveTaskLog,
-                 base::Unretained(this)));
+      base::BindRepeating(&SyncFileSystemInternalsHandler::ObserveTaskLog,
+                          base::Unretained(this)));
 }
 
 void SyncFileSystemInternalsHandler::OnSyncStateUpdated(
diff --git a/chrome/browser/ui/webui/sync_internals_message_handler.cc b/chrome/browser/ui/webui/sync_internals_message_handler.cc
index 2ed7f22a..4563fa61c 100644
--- a/chrome/browser/ui/webui/sync_internals_message_handler.cc
+++ b/chrome/browser/ui/webui/sync_internals_message_handler.cc
@@ -91,44 +91,48 @@
 
   web_ui()->RegisterMessageCallback(
       syncer::sync_ui_util::kRegisterForEvents,
-      base::Bind(&SyncInternalsMessageHandler::HandleRegisterForEvents,
-                 base::Unretained(this)));
+      base::BindRepeating(&SyncInternalsMessageHandler::HandleRegisterForEvents,
+                          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       syncer::sync_ui_util::kRegisterForPerTypeCounters,
-      base::Bind(&SyncInternalsMessageHandler::HandleRegisterForPerTypeCounters,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &SyncInternalsMessageHandler::HandleRegisterForPerTypeCounters,
+          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       syncer::sync_ui_util::kRequestUpdatedAboutInfo,
-      base::Bind(&SyncInternalsMessageHandler::HandleRequestUpdatedAboutInfo,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &SyncInternalsMessageHandler::HandleRequestUpdatedAboutInfo,
+          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       syncer::sync_ui_util::kRequestListOfTypes,
-      base::Bind(&SyncInternalsMessageHandler::HandleRequestListOfTypes,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &SyncInternalsMessageHandler::HandleRequestListOfTypes,
+          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       syncer::sync_ui_util::kRequestUserEventsVisibility,
-      base::Bind(
+      base::BindRepeating(
           &SyncInternalsMessageHandler::HandleRequestUserEventsVisibility,
           base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       syncer::sync_ui_util::kSetIncludeSpecifics,
-      base::Bind(&SyncInternalsMessageHandler::HandleSetIncludeSpecifics,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &SyncInternalsMessageHandler::HandleSetIncludeSpecifics,
+          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       syncer::sync_ui_util::kWriteUserEvent,
-      base::Bind(&SyncInternalsMessageHandler::HandleWriteUserEvent,
-                 base::Unretained(this)));
+      base::BindRepeating(&SyncInternalsMessageHandler::HandleWriteUserEvent,
+                          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       syncer::sync_ui_util::kGetAllNodes,
-      base::Bind(&SyncInternalsMessageHandler::HandleGetAllNodes,
-                 base::Unretained(this)));
+      base::BindRepeating(&SyncInternalsMessageHandler::HandleGetAllNodes,
+                          base::Unretained(this)));
 }
 
 void SyncInternalsMessageHandler::HandleRegisterForEvents(
diff --git a/chrome/browser/ui/webui/task_scheduler_internals/task_scheduler_internals_ui.cc b/chrome/browser/ui/webui/task_scheduler_internals/task_scheduler_internals_ui.cc
index 4c62ad6..641156f4 100644
--- a/chrome/browser/ui/webui/task_scheduler_internals/task_scheduler_internals_ui.cc
+++ b/chrome/browser/ui/webui/task_scheduler_internals/task_scheduler_internals_ui.cc
@@ -58,8 +58,8 @@
   void RegisterMessages() override {
     web_ui()->RegisterMessageCallback(
         "getTaskSchedulerData",
-        base::Bind(&TaskSchedulerDataHandler::GetTaskSchedulerData,
-                   base::Unretained(this)));
+        base::BindRepeating(&TaskSchedulerDataHandler::GetTaskSchedulerData,
+                            base::Unretained(this)));
   }
 
  private:
diff --git a/chrome/browser/ui/webui/translate_internals/translate_internals_handler.cc b/chrome/browser/ui/webui/translate_internals/translate_internals_handler.cc
index 1077d81..366846e 100644
--- a/chrome/browser/ui/webui/translate_internals/translate_internals_handler.cc
+++ b/chrome/browser/ui/webui/translate_internals/translate_internals_handler.cc
@@ -60,15 +60,17 @@
 
 void TranslateInternalsHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
-      "removePrefItem", base::Bind(&TranslateInternalsHandler::OnRemovePrefItem,
-                                   base::Unretained(this)));
+      "removePrefItem",
+      base::BindRepeating(&TranslateInternalsHandler::OnRemovePrefItem,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "requestInfo", base::Bind(&TranslateInternalsHandler::OnRequestInfo,
-                                base::Unretained(this)));
+      "requestInfo",
+      base::BindRepeating(&TranslateInternalsHandler::OnRequestInfo,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "overrideCountry",
-      base::Bind(&TranslateInternalsHandler::OnOverrideCountry,
-                 base::Unretained(this)));
+      base::BindRepeating(&TranslateInternalsHandler::OnOverrideCountry,
+                          base::Unretained(this)));
 }
 
 void TranslateInternalsHandler::Observe(
diff --git a/chrome/browser/ui/webui/version_handler.cc b/chrome/browser/ui/webui/version_handler.cc
index 9bd498d..27c69bbd 100644
--- a/chrome/browser/ui/webui/version_handler.cc
+++ b/chrome/browser/ui/webui/version_handler.cc
@@ -62,8 +62,8 @@
 void VersionHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       version_ui::kRequestVersionInfo,
-      base::Bind(&VersionHandler::HandleRequestVersionInfo,
-                 base::Unretained(this)));
+      base::BindRepeating(&VersionHandler::HandleRequestVersionInfo,
+                          base::Unretained(this)));
 }
 
 void VersionHandler::HandleRequestVersionInfo(const base::ListValue* args) {
diff --git a/chrome/browser/ui/webui/web_ui_test_handler.cc b/chrome/browser/ui/webui/web_ui_test_handler.cc
index be8e805..4b22c25 100644
--- a/chrome/browser/ui/webui/web_ui_test_handler.cc
+++ b/chrome/browser/ui/webui/web_ui_test_handler.cc
@@ -60,8 +60,9 @@
 }
 
 void WebUITestHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback("testResult",
-      base::Bind(&WebUITestHandler::HandleTestResult, base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "testResult", base::BindRepeating(&WebUITestHandler::HandleTestResult,
+                                        base::Unretained(this)));
 }
 
 void WebUITestHandler::HandleTestResult(const base::ListValue* test_result) {
diff --git a/chrome/browser/ui/webui/webapks_handler.cc b/chrome/browser/ui/webui/webapks_handler.cc
index 2510fbe..8a4f9487 100644
--- a/chrome/browser/ui/webui/webapks_handler.cc
+++ b/chrome/browser/ui/webui/webapks_handler.cc
@@ -31,8 +31,8 @@
 void WebApksHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "requestWebApksInfo",
-      base::Bind(&WebApksHandler::HandleRequestWebApksInfo,
-                 base::Unretained(this)));
+      base::BindRepeating(&WebApksHandler::HandleRequestWebApksInfo,
+                          base::Unretained(this)));
 }
 
 void WebApksHandler::HandleRequestWebApksInfo(const base::ListValue* args) {
diff --git a/chrome/browser/ui/webui/webui_webview_browsertest.cc b/chrome/browser/ui/webui/webui_webview_browsertest.cc
index 0e8346f..1c31268e 100644
--- a/chrome/browser/ui/webui/webui_webview_browsertest.cc
+++ b/chrome/browser/ui/webui/webui_webview_browsertest.cc
@@ -39,8 +39,8 @@
   WebUIMessageListener(content::WebUI* web_ui, const std::string& message)
       : message_loop_(new content::MessageLoopRunner) {
     web_ui->RegisterMessageCallback(
-        message, base::Bind(&WebUIMessageListener::HandleMessage,
-                            AsWeakPtr()));
+        message,
+        base::BindRepeating(&WebUIMessageListener::HandleMessage, AsWeakPtr()));
   }
   bool Wait() {
     message_loop_->Run();
diff --git a/chrome/browser/ui/webui/welcome_handler.cc b/chrome/browser/ui/webui/welcome_handler.cc
index d989be5..c9f907e 100644
--- a/chrome/browser/ui/webui/welcome_handler.cc
+++ b/chrome/browser/ui/webui/welcome_handler.cc
@@ -80,11 +80,13 @@
 // Override from WebUIMessageHandler.
 void WelcomeHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
-      "handleActivateSignIn", base::Bind(&WelcomeHandler::HandleActivateSignIn,
-                                         base::Unretained(this)));
+      "handleActivateSignIn",
+      base::BindRepeating(&WelcomeHandler::HandleActivateSignIn,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "handleUserDecline",
-      base::Bind(&WelcomeHandler::HandleUserDecline, base::Unretained(this)));
+      base::BindRepeating(&WelcomeHandler::HandleUserDecline,
+                          base::Unretained(this)));
 }
 
 void WelcomeHandler::GoToNewTabPage() {
diff --git a/chrome/browser/ui/webui/welcome_win10_handler.cc b/chrome/browser/ui/webui/welcome_win10_handler.cc
index 9f345f4a..fcc39583b 100644
--- a/chrome/browser/ui/webui/welcome_win10_handler.cc
+++ b/chrome/browser/ui/webui/welcome_win10_handler.cc
@@ -87,15 +87,16 @@
 void WelcomeWin10Handler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "handleSetDefaultBrowser",
-      base::Bind(&WelcomeWin10Handler::HandleSetDefaultBrowser,
-                 base::Unretained(this)));
+      base::BindRepeating(&WelcomeWin10Handler::HandleSetDefaultBrowser,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "handleContinue",
-      base::Bind(&WelcomeWin10Handler::HandleContinue, base::Unretained(this)));
+      base::BindRepeating(&WelcomeWin10Handler::HandleContinue,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "getPinnedToTaskbarState",
-      base::Bind(&WelcomeWin10Handler::HandleGetPinnedToTaskbarState,
-                 base::Unretained(this)));
+      base::BindRepeating(&WelcomeWin10Handler::HandleGetPinnedToTaskbarState,
+                          base::Unretained(this)));
 }
 
 void WelcomeWin10Handler::HandleGetPinnedToTaskbarState(
diff --git a/chrome/browser/vr/BUILD.gn b/chrome/browser/vr/BUILD.gn
index fac872d..fa09bfb 100644
--- a/chrome/browser/vr/BUILD.gn
+++ b/chrome/browser/vr/BUILD.gn
@@ -61,6 +61,8 @@
     "elements/exit_prompt_texture.h",
     "elements/full_screen_rect.cc",
     "elements/full_screen_rect.h",
+    "elements/indicator_spec.cc",
+    "elements/indicator_spec.h",
     "elements/invisible_hit_target.cc",
     "elements/invisible_hit_target.h",
     "elements/keyboard.cc",
@@ -73,6 +75,8 @@
     "elements/omnibox_formatting.h",
     "elements/omnibox_text_field.cc",
     "elements/omnibox_text_field.h",
+    "elements/oval.cc",
+    "elements/oval.h",
     "elements/prompt.cc",
     "elements/prompt.h",
     "elements/prompt_texture.cc",
@@ -120,6 +124,8 @@
     "elements/url_bar_texture.h",
     "elements/vector_icon.cc",
     "elements/vector_icon.h",
+    "elements/vector_icon_button.cc",
+    "elements/vector_icon_button.h",
     "elements/viewport_aware_root.cc",
     "elements/viewport_aware_root.h",
     "elements/webvr_url_toast.cc",
@@ -144,6 +150,7 @@
     "model/assets.cc",
     "model/assets.h",
     "model/camera_model.h",
+    "model/capturing_state_model.cc",
     "model/capturing_state_model.h",
     "model/color_scheme.cc",
     "model/color_scheme.h",
@@ -266,6 +273,7 @@
     "elements/linear_layout_unittest.cc",
     "elements/omnibox_formatting_unittest.cc",
     "elements/omnibox_text_field_unittest.cc",
+    "elements/oval_unittest.cc",
     "elements/rect_unittest.cc",
     "elements/repositioner_unittest.cc",
     "elements/resizer_unittest.cc",
@@ -279,6 +287,7 @@
     "elements/ui_element_iterator_unittest.cc",
     "elements/ui_element_unittest.cc",
     "elements/url_bar_texture_unittest.cc",
+    "elements/vector_icon_button_unittest.cc",
     "elements/vector_icon_unittest.cc",
     "elements/viewport_aware_root_unittest.cc",
     "fps_meter_unittest.cc",
diff --git a/chrome/browser/vr/browser_ui_interface.h b/chrome/browser/vr/browser_ui_interface.h
index 19edb8b8..c742d238 100644
--- a/chrome/browser/vr/browser_ui_interface.h
+++ b/chrome/browser/vr/browser_ui_interface.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_VR_BROWSER_UI_INTERFACE_H_
 
 #include "chrome/browser/vr/assets_load_status.h"
+#include "chrome/browser/vr/model/capturing_state_model.h"
 #include "chrome/browser/vr/ui_unsupported_mode.h"
 #include "components/security_state/core/security_state.h"
 
@@ -33,11 +34,7 @@
   virtual void SetIsExiting() = 0;
   virtual void SetHistoryButtonsEnabled(bool can_go_back,
                                         bool can_go_forward) = 0;
-  virtual void SetVideoCaptureEnabled(bool enabled) = 0;
-  virtual void SetScreenCaptureEnabled(bool enabled) = 0;
-  virtual void SetAudioCaptureEnabled(bool enabled) = 0;
-  virtual void SetBluetoothConnected(bool enabled) = 0;
-  virtual void SetLocationAccessEnabled(bool enabled) = 0;
+  virtual void SetCapturingState(const CapturingStateModel& state) = 0;
   virtual void ShowExitVrPrompt(UiUnsupportedMode reason) = 0;
   virtual void SetSpeechRecognitionEnabled(bool enabled) = 0;
   virtual void SetRecognitionResult(const base::string16& result) = 0;
diff --git a/chrome/browser/vr/elements/button.cc b/chrome/browser/vr/elements/button.cc
index 8f429f1a..4cd7c9b 100644
--- a/chrome/browser/vr/elements/button.cc
+++ b/chrome/browser/vr/elements/button.cc
@@ -23,7 +23,8 @@
 
 }  // namespace
 
-Button::Button(base::RepeatingCallback<void()> click_handler)
+Button::Button(base::RepeatingCallback<void()> click_handler,
+               AudioDelegate* audio_delegate)
     : click_handler_(click_handler), hover_offset_(kDefaultHoverOffsetDMM) {
   auto background = std::make_unique<Rect>();
   background->SetType(kTypeButtonBackground);
@@ -39,7 +40,7 @@
   hit_plane->set_bubble_events(true);
   hit_plane->set_contributes_to_parent_bounds(false);
   hit_plane_ = hit_plane.get();
-  AddChild(std::move(hit_plane));
+  background_->AddChild(std::move(hit_plane));
 
   EventHandlers event_handlers;
   event_handlers.hover_enter =
@@ -53,6 +54,14 @@
   event_handlers.button_up =
       base::BindRepeating(&Button::HandleButtonUp, base::Unretained(this));
   set_event_handlers(event_handlers);
+
+  Sounds sounds;
+  sounds.hover_enter = kSoundButtonHover;
+  sounds.button_down = kSoundButtonClick;
+  SetSounds(sounds, audio_delegate);
+
+  disabled_sounds_.hover_enter = kSoundNone;
+  disabled_sounds_.button_down = kSoundInactiveButtonClick;
 }
 
 Button::~Button() = default;
@@ -137,11 +146,20 @@
 void Button::NotifyClientSizeAnimated(const gfx::SizeF& size,
                                       int target_property_id,
                                       cc::KeyframeModel* animation) {
+  // We could have OnSetSize called in UiElement's Notify handler instead, but
+  // this may have expensive implications (such as regenerating textures on
+  // every frame of an animation).  For now, keep this elements-specific.
   if (target_property_id == BOUNDS) {
-    background_->SetSize(size.width(), size.height());
-    hit_plane_->SetSize(size.width(), size.height());
+    OnSetSize(size);
   }
   UiElement::NotifyClientSizeAnimated(size, target_property_id, animation);
 }
 
+const Sounds& Button::GetSounds() const {
+  if (!enabled()) {
+    return disabled_sounds_;
+  }
+  return UiElement::GetSounds();
+}
+
 }  // namespace vr
diff --git a/chrome/browser/vr/elements/button.h b/chrome/browser/vr/elements/button.h
index 00323faa..02a4da14 100644
--- a/chrome/browser/vr/elements/button.h
+++ b/chrome/browser/vr/elements/button.h
@@ -21,12 +21,15 @@
 
 class Rect;
 
-// Button has a circle as the background and a vector icon as the foreground.
-// When hovered, background and foreground both move forward on Z axis.
-// This matches the Daydream disk-style button.
+// Button has a rounded rectangle as the background and a hit plane as the
+// foreground.  When hovered, background and foreground both move forward on Z
+// axis.  This matches the Daydream disk-style button. Subclasses may add
+// arbitrary non-hit-testable elements as children of the background, if
+// desired.
 class Button : public UiElement {
  public:
-  explicit Button(base::RepeatingCallback<void()> click_handler);
+  explicit Button(base::RepeatingCallback<void()> click_handler,
+                  AudioDelegate* audio_delegate);
   ~Button() override;
 
   void Render(UiElementRenderer* renderer,
@@ -46,6 +49,8 @@
   // method and the associated field can be removed.
   void set_hover_offset(float hover_offset) { hover_offset_ = hover_offset; }
 
+  void set_disabled_sounds(const Sounds& sounds) { disabled_sounds_ = sounds; }
+
   bool hovered() const { return hovered_; }
   bool down() const { return down_; }
   bool pressed() const { return pressed_; }
@@ -71,6 +76,8 @@
   void HandleButtonDown();
   void HandleButtonUp();
 
+  const Sounds& GetSounds() const override;
+
   bool down_ = false;
   bool hovered_ = false;
   bool pressed_ = false;
@@ -78,9 +85,9 @@
   base::RepeatingCallback<void()> click_handler_;
   ButtonColors colors_;
   float hover_offset_;
-
   Rect* background_;
   UiElement* hit_plane_;
+  Sounds disabled_sounds_;
 
   DISALLOW_COPY_AND_ASSIGN(Button);
 };
diff --git a/chrome/browser/vr/elements/button_unittest.cc b/chrome/browser/vr/elements/button_unittest.cc
index b68ce02..6f508a4e 100644
--- a/chrome/browser/vr/elements/button_unittest.cc
+++ b/chrome/browser/vr/elements/button_unittest.cc
@@ -10,7 +10,7 @@
 
 TEST(Button, Hover) {
   base::RepeatingCallback<void()> callback;
-  Button button(callback);
+  Button button(callback, nullptr);
   button.set_hover_offset(0.0f);
   button.SetSize(1.0f, 1.0f);
 
diff --git a/chrome/browser/vr/elements/disc_button.cc b/chrome/browser/vr/elements/disc_button.cc
index 1e301dc4..e1ae6b4 100644
--- a/chrome/browser/vr/elements/disc_button.cc
+++ b/chrome/browser/vr/elements/disc_button.cc
@@ -14,29 +14,11 @@
 
 namespace vr {
 
-namespace {
-
-constexpr float kDefaultIconScaleFactor = 0.5f;
-
-}  // namespace
-
 DiscButton::DiscButton(base::RepeatingCallback<void()> click_handler,
                        const gfx::VectorIcon& icon,
                        AudioDelegate* audio_delegate)
-    : Button(click_handler), icon_scale_factor_(kDefaultIconScaleFactor) {
-  auto vector_icon = std::make_unique<VectorIcon>(512);
-  vector_icon->SetType(kTypeButtonForeground);
-  vector_icon->SetIcon(icon);
-  vector_icon->set_bubble_events(true);
-  vector_icon->SetTransitionedProperties({TRANSFORM});
-  foreground_ = vector_icon.get();
-
-  // We now need to reparent the hit target so that it is a child of the
-  // newly-created foreground.
-  auto target = RemoveChild(hit_plane());
-  vector_icon->AddChild(std::move(target));
-  AddChild(std::move(vector_icon));
-
+    : VectorIconButton(click_handler, icon, audio_delegate) {
+  // By default, DiscButton is a mode exit button, and gets the 'back' sound.
   Sounds sounds;
   sounds.hover_enter = kSoundButtonHover;
   sounds.button_down = kSoundBackButtonClick;
@@ -45,42 +27,19 @@
 
 DiscButton::~DiscButton() = default;
 
-void DiscButton::OnStateUpdated() {
-  Button::OnStateUpdated();
-
-  if (hovered()) {
-    foreground_->SetTranslate(0.0, 0.0, hover_offset());
-  } else {
-    foreground_->SetTranslate(0.0, 0.0, 0.0);
-  }
-
-  foreground_->SetColor(colors().GetForegroundColor(!enabled()));
-}
-
-void DiscButton::OnSetDrawPhase() {
-  Button::OnSetDrawPhase();
-  foreground_->SetDrawPhase(draw_phase());
-}
-
-void DiscButton::OnSetName() {
-  Button::OnSetName();
-  foreground_->set_owner_name_for_test(name());
-}
-
 void DiscButton::OnSetCornerRadii(const CornerRadii& radii) {
-  Button::OnSetCornerRadii(radii);
-  foreground_->SetCornerRadii(radii);
+  NOTREACHED();
 }
 
 void DiscButton::NotifyClientSizeAnimated(const gfx::SizeF& size,
                                           int target_property_id,
-                                          cc::KeyframeModel* animation) {
-  Button::NotifyClientSizeAnimated(size, target_property_id, animation);
+                                          cc::KeyframeModel* keyframe_model) {
+  Button::NotifyClientSizeAnimated(size, target_property_id, keyframe_model);
   if (target_property_id == BOUNDS) {
     background()->SetSize(size.width(), size.height());
     background()->set_corner_radius(size.width() * 0.5f);  // Creates a circle.
-    foreground()->SetSize(size.width() * icon_scale_factor_,
-                          size.height() * icon_scale_factor_);
+    foreground()->SetSize(size.width() * icon_scale_factor(),
+                          size.height() * icon_scale_factor());
     hit_plane()->SetSize(size.width(), size.height());
     hit_plane()->set_corner_radius(size.width() * 0.5f);  // Creates a circle.
   }
diff --git a/chrome/browser/vr/elements/disc_button.h b/chrome/browser/vr/elements/disc_button.h
index 81890d66..00a6bb1 100644
--- a/chrome/browser/vr/elements/disc_button.h
+++ b/chrome/browser/vr/elements/disc_button.h
@@ -9,7 +9,7 @@
 
 #include "base/callback.h"
 #include "base/macros.h"
-#include "chrome/browser/vr/elements/button.h"
+#include "chrome/browser/vr/elements/vector_icon_button.h"
 #include "ui/gfx/vector_icon_types.h"
 
 namespace vr {
@@ -17,33 +17,21 @@
 class VectorIcon;
 
 // A disc button has a circle as the background and a vector icon as the
-// foreground.  When hovered, background and foreground both move forward on Z
-// axis.  This matches the Daydream disk-style button.
-class DiscButton : public Button {
+// foreground. When hovered, background and foreground both move forward on Z
+// axis. This matches the Daydream disc-style button.
+class DiscButton : public VectorIconButton {
  public:
   DiscButton(base::RepeatingCallback<void()> click_handler,
              const gfx::VectorIcon& icon,
              AudioDelegate* audio_delegate);
   ~DiscButton() override;
 
-  VectorIcon* foreground() const { return foreground_; }
-
-  void set_icon_scale_factor(float factor) { icon_scale_factor_ = factor; }
-
  private:
-  void OnStateUpdated() override;
-  void OnSetDrawPhase() override;
-  void OnSetName() override;
   void OnSetCornerRadii(const CornerRadii& radii) override;
   void NotifyClientSizeAnimated(const gfx::SizeF& size,
                                 int target_property_id,
                                 cc::KeyframeModel* keyframe_model) override;
 
-  // This button will automatically scale down the given icon to fit the button.
-  // This value is used to determine the amount of scaling and can be set
-  // externally to create a smaller or larger icon.
-  float icon_scale_factor_;
-  VectorIcon* foreground_;
   DISALLOW_COPY_AND_ASSIGN(DiscButton);
 };
 
diff --git a/chrome/browser/vr/elements/disc_button_unittest.cc b/chrome/browser/vr/elements/disc_button_unittest.cc
index b6975c74..1952db3 100644
--- a/chrome/browser/vr/elements/disc_button_unittest.cc
+++ b/chrome/browser/vr/elements/disc_button_unittest.cc
@@ -38,8 +38,6 @@
   cc::TransformOperation hit_plane_op_hover =
       button.hit_plane()->GetTargetTransform().at(UiElement::kScaleIndex);
 
-  EXPECT_TRUE(foreground_op_hover.translate.z - foreground_op.translate.z >
-              0.f);
   EXPECT_TRUE(background_op_hover.translate.z - background_op.translate.z >
               0.f);
   EXPECT_TRUE(hit_plane_op_hover.scale.x - hit_plane_op.scale.x > 0.f);
diff --git a/chrome/browser/vr/elements/indicator_spec.cc b/chrome/browser/vr/elements/indicator_spec.cc
new file mode 100644
index 0000000..05b15e19a
--- /dev/null
+++ b/chrome/browser/vr/elements/indicator_spec.cc
@@ -0,0 +1,55 @@
+// Copyright 2018 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/vr/elements/indicator_spec.h"
+#include "chrome/browser/vr/vector_icons/vector_icons.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/vector_icons/vector_icons.h"
+
+namespace vr {
+
+// clang-format off
+std::vector<IndicatorSpec> GetIndicatorSpecs() {
+
+  std::vector<IndicatorSpec> specs = {
+      {kLocationAccessIndicator, kWebVrLocationAccessIndicator,
+       kMyLocationIcon,
+       IDS_VR_SHELL_SITE_IS_TRACKING_LOCATION,
+       IDS_VR_SHELL_SITE_CAN_TRACK_LOCATION,
+       &CapturingStateModel::location_access_enabled,
+       &CapturingStateModel::location_access_potentially_enabled},
+
+      {kAudioCaptureIndicator, kWebVrAudioCaptureIndicator,
+       vector_icons::kMicIcon,
+       IDS_VR_SHELL_SITE_IS_USING_MICROPHONE,
+       IDS_VR_SHELL_SITE_CAN_USE_MICROPHONE,
+       &CapturingStateModel::audio_capture_enabled,
+       &CapturingStateModel::audio_capture_potentially_enabled},
+
+      {kVideoCaptureIndicator, kWebVrVideoCaptureIndicator,
+       vector_icons::kVideocamIcon,
+       IDS_VR_SHELL_SITE_IS_USING_CAMERA,
+       IDS_VR_SHELL_SITE_CAN_USE_CAMERA,
+       &CapturingStateModel::video_capture_enabled,
+       &CapturingStateModel::video_capture_potentially_enabled},
+
+      {kBluetoothConnectedIndicator, kWebVrBluetoothConnectedIndicator,
+       vector_icons::kBluetoothConnectedIcon,
+       IDS_VR_SHELL_SITE_IS_USING_BLUETOOTH,
+       IDS_VR_SHELL_SITE_CAN_USE_BLUETOOTH,
+       &CapturingStateModel::bluetooth_connected,
+       &CapturingStateModel::bluetooth_potentially_connected},
+
+      {kScreenCaptureIndicator, kWebVrScreenCaptureIndicator,
+       vector_icons::kScreenShareIcon,
+       IDS_VR_SHELL_SITE_IS_SHARING_SCREEN,
+       IDS_VR_SHELL_SITE_CAN_SHARE_SCREEN,
+       &CapturingStateModel::screen_capture_enabled,
+       &CapturingStateModel::screen_capture_potentially_enabled}};
+
+  return specs;
+}
+// clang-format on
+
+}  // namespace vr
diff --git a/chrome/browser/vr/elements/indicator_spec.h b/chrome/browser/vr/elements/indicator_spec.h
new file mode 100644
index 0000000..0d7d4367
--- /dev/null
+++ b/chrome/browser/vr/elements/indicator_spec.h
@@ -0,0 +1,30 @@
+// Copyright 2018 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_VR_ELEMENTS_INDICATOR_SPEC_H_
+#define CHROME_BROWSER_VR_ELEMENTS_INDICATOR_SPEC_H_
+
+#include <vector>
+
+#include "chrome/browser/vr/elements/ui_element_name.h"
+#include "chrome/browser/vr/model/capturing_state_model.h"
+#include "ui/gfx/vector_icon_types.h"
+
+namespace vr {
+
+struct IndicatorSpec {
+  UiElementName name;
+  UiElementName webvr_name;
+  const gfx::VectorIcon& icon;
+  int resource_string;
+  int potential_resource_string;
+  bool CapturingStateModel::*signal;
+  bool CapturingStateModel::*potential_signal;
+};
+
+std::vector<IndicatorSpec> GetIndicatorSpecs();
+
+}  // namespace vr
+
+#endif  // CHROME_BROWSER_VR_ELEMENTS_INDICATOR_SPEC_H_
diff --git a/chrome/browser/vr/elements/invisible_hit_target.cc b/chrome/browser/vr/elements/invisible_hit_target.cc
index 02b7296..f052ef42 100644
--- a/chrome/browser/vr/elements/invisible_hit_target.cc
+++ b/chrome/browser/vr/elements/invisible_hit_target.cc
@@ -12,8 +12,6 @@
 InvisibleHitTarget::~InvisibleHitTarget() = default;
 
 void InvisibleHitTarget::Render(UiElementRenderer* renderer,
-                                const CameraModel& model) const {
-  DCHECK(hit_testable());
-}
+                                const CameraModel& model) const {}
 
 }  // namespace vr
diff --git a/chrome/browser/vr/elements/oval.cc b/chrome/browser/vr/elements/oval.cc
new file mode 100644
index 0000000..57d56307
--- /dev/null
+++ b/chrome/browser/vr/elements/oval.cc
@@ -0,0 +1,24 @@
+// Copyright 2018 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/vr/elements/oval.h"
+
+#include "chrome/browser/vr/target_property.h"
+#include "chrome/browser/vr/ui_element_renderer.h"
+#include "ui/gfx/geometry/rect_f.h"
+
+namespace vr {
+
+Oval::Oval() = default;
+Oval::~Oval() = default;
+
+void Oval::NotifyClientSizeAnimated(const gfx::SizeF& size,
+                                    int target_property_id,
+                                    cc::KeyframeModel* keyframe_model) {
+  Rect::NotifyClientSizeAnimated(size, target_property_id, keyframe_model);
+  if (target_property_id == BOUNDS)
+    set_corner_radius(0.5f * std::min(size.height(), size.width()));
+}
+
+}  // namespace vr
diff --git a/chrome/browser/vr/elements/oval.h b/chrome/browser/vr/elements/oval.h
new file mode 100644
index 0000000..39359df
--- /dev/null
+++ b/chrome/browser/vr/elements/oval.h
@@ -0,0 +1,29 @@
+// Copyright 2018 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_VR_ELEMENTS_OVAL_H_
+#define CHROME_BROWSER_VR_ELEMENTS_OVAL_H_
+
+#include "chrome/browser/vr/elements/rect.h"
+
+namespace vr {
+
+// An oval behaves like a rect save for the fact that it manages its own corner
+// radii to ensure circular right and left end caps.
+class Oval : public Rect {
+ public:
+  Oval();
+  ~Oval() override;
+
+ private:
+  void NotifyClientSizeAnimated(const gfx::SizeF& size,
+                                int target_property_id,
+                                cc::KeyframeModel* keyframe_model) override;
+
+  DISALLOW_COPY_AND_ASSIGN(Oval);
+};
+
+}  // namespace vr
+
+#endif  // CHROME_BROWSER_VR_ELEMENTS_OVAL_H_
diff --git a/chrome/browser/vr/elements/oval_unittest.cc b/chrome/browser/vr/elements/oval_unittest.cc
new file mode 100644
index 0000000..0d228207
--- /dev/null
+++ b/chrome/browser/vr/elements/oval_unittest.cc
@@ -0,0 +1,17 @@
+// Copyright 2018 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/vr/elements/oval.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace vr {
+
+TEST(Oval, CornerRadii) {
+  Oval oval;
+  oval.SetSize(10.0f, 1.0f);
+  EXPECT_FLOAT_EQ(0.5f, oval.corner_radius());
+}
+
+}  // namespace vr
diff --git a/chrome/browser/vr/elements/rect.cc b/chrome/browser/vr/elements/rect.cc
index 2f941e75..a637b64d 100644
--- a/chrome/browser/vr/elements/rect.cc
+++ b/chrome/browser/vr/elements/rect.cc
@@ -10,8 +10,8 @@
 
 namespace vr {
 
-Rect::Rect() {}
-Rect::~Rect() {}
+Rect::Rect() = default;
+Rect::~Rect() = default;
 
 void Rect::SetColor(SkColor color) {
   SetCenterColor(color);
diff --git a/chrome/browser/vr/elements/toast.cc b/chrome/browser/vr/elements/toast.cc
index d7f4ba18..70ee424a 100644
--- a/chrome/browser/vr/elements/toast.cc
+++ b/chrome/browser/vr/elements/toast.cc
@@ -67,7 +67,7 @@
 }
 
 void Toast::SetMargin(float margin) {
-  container_->set_margin(kIndicatorMargin);
+  container_->set_margin(margin);
 }
 
 void Toast::OnSetDrawPhase() {
diff --git a/chrome/browser/vr/elements/ui_element.cc b/chrome/browser/vr/elements/ui_element.cc
index e112782..67787b7 100644
--- a/chrome/browser/vr/elements/ui_element.cc
+++ b/chrome/browser/vr/elements/ui_element.cc
@@ -140,9 +140,10 @@
 void UiElement::Initialize(SkiaSurfaceProvider* provider) {}
 
 void UiElement::OnHoverEnter(const gfx::PointF& position) {
-  if (sounds_.hover_enter != kSoundNone && audio_delegate_) {
-    audio_delegate_->PlaySound(sounds_.hover_enter);
+  if (GetSounds().hover_enter != kSoundNone && audio_delegate_) {
+    audio_delegate_->PlaySound(GetSounds().hover_enter);
   }
+
   if (event_handlers_.hover_enter) {
     event_handlers_.hover_enter.Run();
   } else if (parent() && bubble_events()) {
@@ -151,8 +152,8 @@
 }
 
 void UiElement::OnHoverLeave() {
-  if (sounds_.hover_leave != kSoundNone && audio_delegate_) {
-    audio_delegate_->PlaySound(sounds_.hover_leave);
+  if (GetSounds().hover_leave != kSoundNone && audio_delegate_) {
+    audio_delegate_->PlaySound(GetSounds().hover_leave);
   }
   if (event_handlers_.hover_leave) {
     event_handlers_.hover_leave.Run();
@@ -162,8 +163,8 @@
 }
 
 void UiElement::OnMove(const gfx::PointF& position) {
-  if (sounds_.move != kSoundNone && audio_delegate_) {
-    audio_delegate_->PlaySound(sounds_.move);
+  if (GetSounds().move != kSoundNone && audio_delegate_) {
+    audio_delegate_->PlaySound(GetSounds().move);
   }
   if (event_handlers_.hover_move) {
     event_handlers_.hover_move.Run(position);
@@ -173,8 +174,8 @@
 }
 
 void UiElement::OnButtonDown(const gfx::PointF& position) {
-  if (sounds_.button_down != kSoundNone && audio_delegate_) {
-    audio_delegate_->PlaySound(sounds_.button_down);
+  if (GetSounds().button_down != kSoundNone && audio_delegate_) {
+    audio_delegate_->PlaySound(GetSounds().button_down);
   }
   if (event_handlers_.button_down) {
     event_handlers_.button_down.Run();
@@ -184,8 +185,8 @@
 }
 
 void UiElement::OnButtonUp(const gfx::PointF& position) {
-  if (sounds_.button_up != kSoundNone && audio_delegate_) {
-    audio_delegate_->PlaySound(sounds_.button_up);
+  if (GetSounds().button_up != kSoundNone && audio_delegate_) {
+    audio_delegate_->PlaySound(GetSounds().button_up);
   }
   if (event_handlers_.button_up) {
     event_handlers_.button_up.Run();
@@ -672,6 +673,10 @@
   animation_.RemoveKeyframeModel(keyframe_model_id);
 }
 
+void UiElement::RemoveKeyframeModels(int target_property) {
+  animation_.RemoveKeyframeModels(target_property);
+}
+
 bool UiElement::IsAnimatingProperty(TargetProperty property) const {
   return animation_.IsAnimatingProperty(static_cast<int>(property));
 }
@@ -764,6 +769,20 @@
   }
 }
 
+UiElement* UiElement::FirstLaidOutChild() const {
+  auto i = std::find_if(
+      children_.begin(), children_.end(),
+      [](const std::unique_ptr<UiElement>& e) { return e->requires_layout(); });
+  return i == children_.end() ? nullptr : i->get();
+}
+
+UiElement* UiElement::LastLaidOutChild() const {
+  auto i = std::find_if(
+      children_.rbegin(), children_.rend(),
+      [](const std::unique_ptr<UiElement>& e) { return e->requires_layout(); });
+  return i == children_.rend() ? nullptr : i->get();
+}
+
 void UiElement::UpdateComputedOpacity() {
   bool was_visible = computed_opacity_ > 0.0f;
   set_computed_opacity(opacity_);
@@ -809,4 +828,8 @@
   return layout_offset_.Apply() * GetTargetTransform().Apply();
 }
 
+const Sounds& UiElement::GetSounds() const {
+  return sounds_;
+}
+
 }  // namespace vr
diff --git a/chrome/browser/vr/elements/ui_element.h b/chrome/browser/vr/elements/ui_element.h
index 9e1026f..46639e0 100644
--- a/chrome/browser/vr/elements/ui_element.h
+++ b/chrome/browser/vr/elements/ui_element.h
@@ -390,6 +390,7 @@
 
   void AddKeyframeModel(std::unique_ptr<cc::KeyframeModel> keyframe_model);
   void RemoveKeyframeModel(int keyframe_model_id);
+  void RemoveKeyframeModels(int target_property);
   bool IsAnimatingProperty(TargetProperty property) const;
 
   // Recursive method that sizes and lays out element subtrees. This method may
@@ -404,6 +405,9 @@
   // applies anchoring.
   virtual void LayOutChildren();
 
+  UiElement* FirstLaidOutChild() const;
+  UiElement* LastLaidOutChild() const;
+
   virtual gfx::Transform LocalTransform() const;
   virtual gfx::Transform GetTargetLocalTransform() const;
 
@@ -485,6 +489,8 @@
 
   base::TimeTicks last_frame_time() const { return last_frame_time_; }
 
+  virtual const Sounds& GetSounds() const;
+
   EventHandlers event_handlers_;
 
  private:
diff --git a/chrome/browser/vr/elements/ui_element_name.cc b/chrome/browser/vr/elements/ui_element_name.cc
index d089e60..7d894248 100644
--- a/chrome/browser/vr/elements/ui_element_name.cc
+++ b/chrome/browser/vr/elements/ui_element_name.cc
@@ -44,19 +44,19 @@
     "kFloor",
     "kStars",
     "kUpdateKeyboardPrompt",
-    "kUrlBarBackplane",
     "kUrlBarPositioner",
     "kUrlBarDmmRoot",
     "kUrlBar",
     "kUrlBarLayout",
     "kUrlBarBackButton",
-    "kUrlBarBackButtonIcon",
     "kUrlBarSeparator",
+    "kUrlBarSecurityButtonRegion",
+    "kUrlBarSecurityButton",
+    "kUrlBarOriginLayout",
     "kUrlBarOriginRegion",
-    "kUrlBarOriginContent",
+    "kUrlBarUrlText",
     "kUrlBarHintText",
     "kUrlBarOverflowButton",
-    "kUrlBarOverflowButtonIcon",
     "kOverflowMenuBackplane",
     "kOverflowMenu",
     "kOverflowMenuLayout",
@@ -84,12 +84,18 @@
     "k2dBrowsingOpacityControlForAudioPermissionPrompt",
     "k2dBrowsingOpacityControlForNativeDialogPrompt",
     "k2dBrowsingOpacityControlForUpdateKeyboardPrompt",
+    "kIndicatorBackplane",
     "kIndicatorLayout",
     "kAudioCaptureIndicator",
     "kVideoCaptureIndicator",
     "kScreenCaptureIndicator",
     "kLocationAccessIndicator",
     "kBluetoothConnectedIndicator",
+    "kWebVrAudioCaptureIndicator",
+    "kWebVrVideoCaptureIndicator",
+    "kWebVrScreenCaptureIndicator",
+    "kWebVrLocationAccessIndicator",
+    "kWebVrBluetoothConnectedIndicator",
     "kLoadingIndicator",
     "kLoadingIndicatorForeground",
     "kCloseButton",
@@ -108,7 +114,6 @@
     "kWebVrUrlToast",
     "kExclusiveScreenToastTransientParent",
     "kExclusiveScreenToast",
-    "kExclusiveScreenToastViewportAwareTransientParent",
     "kExclusiveScreenToastViewportAware",
     "kSplashScreenRoot",
     "kSplashScreenTransientParent",
diff --git a/chrome/browser/vr/elements/ui_element_name.h b/chrome/browser/vr/elements/ui_element_name.h
index 7921f93..b1a7653 100644
--- a/chrome/browser/vr/elements/ui_element_name.h
+++ b/chrome/browser/vr/elements/ui_element_name.h
@@ -43,19 +43,19 @@
   kFloor,
   kStars,
   kUpdateKeyboardPrompt,
-  kUrlBarBackplane,
   kUrlBarPositioner,
   kUrlBarDmmRoot,
   kUrlBar,
   kUrlBarLayout,
   kUrlBarBackButton,
-  kUrlBarBackButtonIcon,
   kUrlBarSeparator,
+  kUrlBarSecurityButtonRegion,
+  kUrlBarSecurityButton,
+  kUrlBarOriginLayout,
   kUrlBarOriginRegion,
-  kUrlBarOriginContent,
+  kUrlBarUrlText,
   kUrlBarHintText,
   kUrlBarOverflowButton,
-  kUrlBarOverflowButtonIcon,
   kOverflowMenuBackplane,
   kOverflowMenu,
   kOverflowMenuLayout,
@@ -83,12 +83,18 @@
   k2dBrowsingOpacityControlForAudioPermissionPrompt,
   k2dBrowsingOpacityControlForNativeDialogPrompt,
   k2dBrowsingOpacityControlForUpdateKeyboardPrompt,
+  kIndicatorBackplane,
   kIndicatorLayout,
   kAudioCaptureIndicator,
   kVideoCaptureIndicator,
   kScreenCaptureIndicator,
   kLocationAccessIndicator,
   kBluetoothConnectedIndicator,
+  kWebVrAudioCaptureIndicator,
+  kWebVrVideoCaptureIndicator,
+  kWebVrScreenCaptureIndicator,
+  kWebVrLocationAccessIndicator,
+  kWebVrBluetoothConnectedIndicator,
   kLoadingIndicator,
   kLoadingIndicatorForeground,
   kCloseButton,
@@ -107,7 +113,6 @@
   kWebVrUrlToast,
   kExclusiveScreenToastTransientParent,
   kExclusiveScreenToast,
-  kExclusiveScreenToastViewportAwareTransientParent,
   kExclusiveScreenToastViewportAware,
   kSplashScreenRoot,
   kSplashScreenTransientParent,
diff --git a/chrome/browser/vr/elements/ui_element_type.cc b/chrome/browser/vr/elements/ui_element_type.cc
index 353f4775..4468ab1 100644
--- a/chrome/browser/vr/elements/ui_element_type.cc
+++ b/chrome/browser/vr/elements/ui_element_type.cc
@@ -40,6 +40,8 @@
     "kTypeCursorForeground",
     "kTypeOverflowMenuButton",
     "kTypeOverflowMenuItem",
+    "kTypeTooltip",
+    "kTypeLabel",
 };
 
 static_assert(
diff --git a/chrome/browser/vr/elements/ui_element_type.h b/chrome/browser/vr/elements/ui_element_type.h
index 12aa336..c8fa152 100644
--- a/chrome/browser/vr/elements/ui_element_type.h
+++ b/chrome/browser/vr/elements/ui_element_type.h
@@ -40,6 +40,8 @@
   kTypeCursorForeground,
   kTypeOverflowMenuButton,
   kTypeOverflowMenuItem,
+  kTypeTooltip,
+  kTypeLabel,
 
   // This must be last.
   kNumUiElementTypes,
diff --git a/chrome/browser/vr/elements/url_bar.cc b/chrome/browser/vr/elements/url_bar.cc
index 418c617c..4c54977b 100644
--- a/chrome/browser/vr/elements/url_bar.cc
+++ b/chrome/browser/vr/elements/url_bar.cc
@@ -10,11 +10,9 @@
 
 UrlBar::UrlBar(
     int preferred_width,
-    const base::RepeatingCallback<void()>& url_click_callback,
     const base::RepeatingCallback<void(UiUnsupportedMode)>& failure_callback)
     : TexturedElement(preferred_width),
       texture_(std::make_unique<UrlBarTexture>(failure_callback)),
-      url_click_callback_(url_click_callback),
       failure_callback_(failure_callback) {}
 
 UrlBar::~UrlBar() = default;
@@ -23,22 +21,6 @@
   return texture_.get();
 }
 
-void UrlBar::OnButtonDown(const gfx::PointF& position) {
-  if (texture_->HitsSecurityRegion(position))
-    security_region_down_ = true;
-  else
-    url_down_ = true;
-}
-
-void UrlBar::OnButtonUp(const gfx::PointF& position) {
-  if (security_region_down_ && texture_->HitsSecurityRegion(position))
-    failure_callback_.Run(UiUnsupportedMode::kUnhandledPageInfo);
-  else
-    url_click_callback_.Run();
-  security_region_down_ = false;
-  url_down_ = false;
-}
-
 void UrlBar::SetToolbarState(const ToolbarState& state) {
   texture_->SetToolbarState(state);
 }
diff --git a/chrome/browser/vr/elements/url_bar.h b/chrome/browser/vr/elements/url_bar.h
index aa471db..a69ff48 100644
--- a/chrome/browser/vr/elements/url_bar.h
+++ b/chrome/browser/vr/elements/url_bar.h
@@ -25,13 +25,9 @@
  public:
   UrlBar(
       int preferred_width,
-      const base::RepeatingCallback<void()>& url_click_callback,
       const base::RepeatingCallback<void(UiUnsupportedMode)>& failure_callback);
   ~UrlBar() override;
 
-  void OnButtonDown(const gfx::PointF& position) override;
-  void OnButtonUp(const gfx::PointF& position) override;
-
   void SetToolbarState(const ToolbarState& state);
   void SetColors(const UrlBarColors& colors);
 
@@ -39,12 +35,8 @@
   UiTexture* GetTexture() const override;
 
   std::unique_ptr<UrlBarTexture> texture_;
-  base::RepeatingCallback<void()> url_click_callback_;
   base::RepeatingCallback<void(UiUnsupportedMode)> failure_callback_;
 
-  bool security_region_down_ = false;
-  bool url_down_ = false;
-
   DISALLOW_COPY_AND_ASSIGN(UrlBar);
 };
 
diff --git a/chrome/browser/vr/elements/url_bar_texture.cc b/chrome/browser/vr/elements/url_bar_texture.cc
index 7ca9e1b..1da6cac9 100644
--- a/chrome/browser/vr/elements/url_bar_texture.cc
+++ b/chrome/browser/vr/elements/url_bar_texture.cc
@@ -9,19 +9,15 @@
 #include "base/strings/utf_string_conversions.h"
 #include "cc/paint/skia_paint_canvas.h"
 #include "chrome/browser/vr/elements/render_text_wrapper.h"
-#include "chrome/browser/vr/elements/vector_icon.h"
 #include "chrome/browser/vr/model/color_scheme.h"
 #include "chrome/browser/vr/ui_scene_constants.h"
 #include "components/url_formatter/elide_url.h"
 #include "components/url_formatter/url_formatter.h"
-#include "components/vector_icons/vector_icons.h"
 #include "third_party/skia/include/effects/SkGradientShader.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/font.h"
 #include "ui/gfx/font_list.h"
-#include "ui/gfx/geometry/point_f.h"
 #include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/paint_vector_icon.h"
 #include "ui/gfx/render_text.h"
 
 namespace vr {
@@ -33,27 +29,9 @@
 // Most of this could be decomposed into sub-elements in a linear layout, if
 // linear layout gains the ability to constrain its total size by limiting one
 // (or more) of it's children.
-constexpr float kWidth = kUrlBarOriginContentWidthDMM;
+constexpr float kWidth = kUrlBarUrlWidthDMM;
 constexpr float kHeight = kUrlBarHeightDMM;
 
-using security_state::SecurityLevel;
-
-SkColor GetIconColor(SecurityLevel level, const UrlBarColors& colors) {
-  switch (level) {
-    case SecurityLevel::NONE:
-    case SecurityLevel::HTTP_SHOW_WARNING:
-    case SecurityLevel::EV_SECURE:
-    case SecurityLevel::SECURE:
-      return colors.default_icon;
-    case SecurityLevel::DANGEROUS:
-      return colors.dangerous_icon;
-    case SecurityLevel::SECURE_WITH_POLICY_INSTALLED_CERT:  // ChromeOS only.
-    default:
-      NOTREACHED();
-      return colors.dangerous_icon;
-  }
-}
-
 void SetEmphasis(RenderTextWrapper* render_text,
                  bool emphasis,
                  const gfx::Range& range,
@@ -66,10 +44,6 @@
   }
 }
 
-gfx::PointF PercentToMeters(const gfx::PointF& percent) {
-  return gfx::PointF(percent.x() * kWidth, percent.y() * kHeight);
-}
-
 void ApplyUrlFading(SkCanvas* canvas,
                     const gfx::Rect& text_bounds,
                     float fade_width,
@@ -125,10 +99,6 @@
   return pixels * kWidth / size_.width();
 }
 
-bool UrlBarTexture::HitsSecurityRegion(const gfx::PointF& position) const {
-  return security_hit_region_.Contains(PercentToMeters(position));
-}
-
 void UrlBarTexture::SetColors(const UrlBarColors& colors) {
   SetAndDirty(&colors_, colors);
 }
@@ -137,91 +107,13 @@
   size_.set_height(texture_size.height());
   size_.set_width(texture_size.width());
 
-  rendered_url_text_ = base::string16();
-  rendered_url_text_rect_ = gfx::Rect();
-  rendered_security_text_ = base::string16();
-  rendered_security_text_rect_ = gfx::Rect();
-  security_hit_region_ = gfx::RectF();
-
-  // Make a gfx canvas to support utility drawing methods.
-  cc::SkiaPaintCanvas paint_canvas(canvas);
-  gfx::Canvas gfx_canvas(&paint_canvas, 1.0f);
-
-  if (!state_.should_display_url)
-    return;
-
-  // Keep track of horizontal position as elements are added left to right.
-  float left_edge = 0;
-
-  // Site security state icon.
-  if (state_.vector_icon != nullptr) {
-    gfx::RectF icon_region(left_edge,
-                           kHeight / 2 - kUrlBarButtonIconSizeDMM / 2,
-                           kUrlBarButtonIconSizeDMM, kUrlBarButtonIconSizeDMM);
-    VectorIcon::DrawVectorIcon(
-        &gfx_canvas, *state_.vector_icon, ToPixels(kUrlBarButtonIconSizeDMM),
-        {ToPixels(icon_region.x()), ToPixels(icon_region.y())},
-        GetIconColor(state_.security_level, colors_));
-    security_hit_region_ = icon_region;
-    left_edge += kUrlBarButtonIconSizeDMM;
-  }
-
   std::unique_ptr<gfx::RenderText> render_text;
   gfx::FontList font_list;
   int pixel_font_height =
       texture_size.height() * kUrlBarFontHeightDMM / kHeight;
 
-  // Possibly draw security text (eg. "Offline") next to the icon.  This text
-  // consumes a significant percentage of URL bar text space, so for now, only
-  // Offline mode shows text (see crbug.com/735770).
-  if (state_.offline_page) {
-    left_edge += kUrlBarOfflineIconTextSpacingDMM;
-    float chip_max_width = kWidth - left_edge;
-    gfx::Rect text_bounds(ToPixels(left_edge), 0, ToPixels(chip_max_width),
-                          ToPixels(kHeight));
+  gfx::Rect url_text_bounds(0, 0, texture_size.width(), texture_size.height());
 
-    const base::string16& chip_text = state_.secure_verbose_text;
-    DCHECK(!chip_text.empty());
-
-    if (!GetDefaultFontList(pixel_font_height, chip_text, &font_list))
-      failure_callback_.Run(UiUnsupportedMode::kUnhandledCodePoint);
-
-    render_text = CreateRenderText();
-    render_text->SetFontList(font_list);
-    render_text->SetColor(colors_.offline_page_warning);
-    render_text->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-    render_text->SetText(chip_text);
-    render_text->SetDisplayRect(text_bounds);
-    render_text->Draw(&gfx_canvas);
-    rendered_security_text_ = render_text->text();
-    rendered_security_text_rect_ = render_text->display_rect();
-
-    // Capture the rendered text region for future hit testing.
-    gfx::Size string_size = render_text->GetStringSize();
-    gfx::RectF hit_bounds(
-        left_edge, kHeight / 2 - ToMeters(string_size.height()) / 2,
-        ToMeters(string_size.width()), ToMeters(string_size.height()));
-    security_hit_region_.Union(hit_bounds);
-    left_edge += ToMeters(string_size.width());
-
-    // Separator line between security text and URL.
-    left_edge += kUrlBarFieldSpacingDMM;
-    SkPaint paint;
-    paint.setColor(colors_.deemphasized);
-    canvas->drawRect(
-        SkRect::MakeXYWH(
-            ToPixels(left_edge), ToPixels(kUrlBarSecuritySeparatorHeightDMM),
-            ToPixels(kUrlBarSeparatorWidthDMM),
-            ToPixels(kHeight - 2 * kUrlBarSecuritySeparatorHeightDMM)),
-        paint);
-    left_edge += kUrlBarSeparatorWidthDMM;
-  }
-
-  left_edge += kUrlBarFieldSpacingDMM;
-
-  float url_width = kWidth - left_edge;
-  gfx::Rect url_text_bounds(ToPixels(left_edge), 0, ToPixels(url_width),
-                            ToPixels(kHeight));
   url::Parsed parsed;
   const base::string16 text = url_formatter::FormatUrl(
       state_.gurl, GetVrFormatUrlTypes(), net::UnescapeRule::NORMAL, &parsed,
@@ -238,21 +130,20 @@
   render_text->SetDisplayRect(url_text_bounds);
 
   RenderTextWrapper vr_render_text(render_text.get());
-  ApplyUrlStyling(text, parsed, state_.security_level, &vr_render_text,
-                  colors_);
+  ApplyUrlStyling(text, parsed, &vr_render_text, colors_);
 
   ElisionParameters elision_parameters =
       GetElisionParameters(state_.gurl, parsed, render_text.get(),
                            ToPixels(kUrlBarOriginMinimumPathWidth));
   render_text->SetDisplayOffset(elision_parameters.offset);
 
+  cc::SkiaPaintCanvas paint_canvas(canvas);
+  gfx::Canvas gfx_canvas(&paint_canvas, 1.0f);
   render_text->Draw(&gfx_canvas);
+
   float fade_width = ToPixels(kUrlBarOriginFadeWidth);
   ApplyUrlFading(canvas, render_text->display_rect(), fade_width,
                  elision_parameters.fade_left, elision_parameters.fade_right);
-
-  rendered_url_text_ = render_text->text();
-  rendered_url_text_rect_ = render_text->display_rect();
 }
 
 // static
@@ -260,7 +151,6 @@
 void UrlBarTexture::ApplyUrlStyling(
     const base::string16& formatted_url,
     const url::Parsed& parsed,
-    const security_state::SecurityLevel security_level,
     RenderTextWrapper* render_text,
     const UrlBarColors& colors) {
   const url::Component& scheme = parsed.scheme;
diff --git a/chrome/browser/vr/elements/url_bar_texture.h b/chrome/browser/vr/elements/url_bar_texture.h
index e504a14..a301171 100644
--- a/chrome/browser/vr/elements/url_bar_texture.h
+++ b/chrome/browser/vr/elements/url_bar_texture.h
@@ -19,21 +19,12 @@
 #include "ui/gfx/geometry/rect_f.h"
 #include "url/gurl.h"
 
-namespace gfx {
-class PointF;
-}  // namespace gfx
-
 namespace vr {
 
 class RenderTextWrapper;
 
 class UrlBarTexture : public UiTexture {
  public:
-  enum DrawFlags {
-    FLAG_BACK_HOVER = 1 << 0,
-    FLAG_BACK_DOWN = 1 << 1,
-  };
-
   UrlBarTexture(
       const base::Callback<void(UiUnsupportedMode)>& failure_callback);
   ~UrlBarTexture() override;
@@ -43,34 +34,22 @@
   void SetColors(const UrlBarColors& colors);
   void SetToolbarState(const ToolbarState& state);
 
-  bool HitsSecurityRegion(const gfx::PointF& position) const;
-
  protected:
   static void ApplyUrlStyling(const base::string16& formatted_url,
                               const url::Parsed& parsed,
-                              security_state::SecurityLevel security_level,
                               RenderTextWrapper* render_text,
                               const UrlBarColors& colors);
 
-  // Rendered state for test purposes. The text rectangles represent regions
-  // available to text, not the smaller area of the actual rendered text.
-  base::string16 rendered_url_text_;
-  gfx::Rect rendered_url_text_rect_;
-  base::string16 rendered_security_text_;
-  gfx::Rect rendered_security_text_rect_;
-
  private:
   void Draw(SkCanvas* canvas, const gfx::Size& texture_size) override;
   float ToPixels(float meters) const;
   float ToMeters(float pixels) const;
-  bool HitsTransparentRegion(const gfx::PointF& meters, bool left) const;
 
   gfx::SizeF size_;
   ToolbarState state_;
   UrlBarColors colors_;
 
   base::Callback<void(UiUnsupportedMode)> failure_callback_;
-  gfx::RectF security_hit_region_;
 
   DISALLOW_COPY_AND_ASSIGN(UrlBarTexture);
 };
diff --git a/chrome/browser/vr/elements/url_bar_texture_unittest.cc b/chrome/browser/vr/elements/url_bar_texture_unittest.cc
index 9507035..6350e90 100644
--- a/chrome/browser/vr/elements/url_bar_texture_unittest.cc
+++ b/chrome/browser/vr/elements/url_bar_texture_unittest.cc
@@ -64,7 +64,7 @@
                              security_state::SecurityLevel security_level,
                              vr::RenderTextWrapper* render_text,
                              const UrlBarColors& colors) {
-    ApplyUrlStyling(formatted_url, parsed, security_level, render_text, colors);
+    ApplyUrlStyling(formatted_url, parsed, render_text, colors);
   }
 
   void SetForceFontFallbackFailure(bool force) {
@@ -89,11 +89,6 @@
   // no unsupported mode was encountered.
   UiUnsupportedMode unsupported_mode() const { return unsupported_mode_; }
 
-  const base::string16& url_text() { return rendered_url_text_; }
-  const base::string16& security_text() { return rendered_security_text_; }
-  const gfx::Rect url_rect() { return rendered_url_text_rect_; }
-  const gfx::Rect security_rect() { return rendered_security_text_rect_; }
-
  private:
   void OnUnsupportedFeature(UiUnsupportedMode mode) {
     unsupported_mode_ = mode;
@@ -204,42 +199,4 @@
   EXPECT_EQ(UiUnsupportedMode::kCount, texture.unsupported_mode());
 }
 
-TEST(UrlBarTexture, OfflinePage) {
-  TestUrlBarTexture texture;
-  ToolbarState state(GURL("https://host.com/page"), SecurityLevel::NONE,
-                     &toolbar::kHttpsInvalidIcon, base::UTF8ToUTF16("Offline"),
-                     true, false);
-
-  // Render online page.
-  state.offline_page = false;
-  texture.DrawURLState(state);
-  EXPECT_EQ(texture.security_rect().width(), 0);
-  EXPECT_EQ(texture.security_rect().height(), 0);
-  EXPECT_GT(texture.url_rect().width(), 0);
-  EXPECT_GT(texture.url_rect().height(), 0);
-  EXPECT_TRUE(texture.security_text().empty());
-  EXPECT_EQ(texture.url_text(), base::UTF8ToUTF16("host.com/page"));
-  gfx::Rect online_url_rect = texture.url_rect();
-
-  // Go offline. Security text should be visible and displace the URL.
-  state.offline_page = true;
-  texture.DrawURLState(state);
-  EXPECT_GT(texture.security_rect().width(), 0);
-  EXPECT_GT(texture.security_rect().height(), 0);
-  EXPECT_GT(texture.url_rect().width(), 0);
-  EXPECT_GT(texture.url_rect().height(), 0);
-  EXPECT_GT(texture.url_rect().x(), online_url_rect.x());
-  EXPECT_EQ(texture.security_text(), base::UTF8ToUTF16("Offline"));
-  EXPECT_EQ(texture.url_text(), base::UTF8ToUTF16("host.com/page"));
-
-  // Go back online.
-  state.offline_page = false;
-  texture.DrawURLState(state);
-  EXPECT_EQ(texture.security_rect().width(), 0);
-  EXPECT_EQ(texture.security_rect().height(), 0);
-  EXPECT_EQ(texture.url_rect(), online_url_rect);
-  EXPECT_TRUE(texture.security_text().empty());
-  EXPECT_EQ(texture.url_text(), base::UTF8ToUTF16("host.com/page"));
-}
-
 }  // namespace vr
diff --git a/chrome/browser/vr/elements/vector_icon_button.cc b/chrome/browser/vr/elements/vector_icon_button.cc
new file mode 100644
index 0000000..5fed7d2
--- /dev/null
+++ b/chrome/browser/vr/elements/vector_icon_button.cc
@@ -0,0 +1,75 @@
+// Copyright 2018 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/vr/elements/vector_icon_button.h"
+
+#include "chrome/browser/vr/elements/rect.h"
+#include "chrome/browser/vr/elements/ui_element.h"
+#include "chrome/browser/vr/elements/ui_element_name.h"
+#include "chrome/browser/vr/elements/vector_icon.h"
+#include "chrome/browser/vr/ui_scene_constants.h"
+
+#include "ui/gfx/geometry/point_f.h"
+
+namespace vr {
+
+namespace {
+
+constexpr float kDefaultIconScaleFactor = 0.5f;
+
+}  // namespace
+
+VectorIconButton::VectorIconButton(
+    base::RepeatingCallback<void()> click_handler,
+    const gfx::VectorIcon& icon,
+    AudioDelegate* audio_delegate)
+    : Button(click_handler, audio_delegate),
+      icon_scale_factor_(kDefaultIconScaleFactor) {
+  auto vector_icon = std::make_unique<VectorIcon>(512);
+  vector_icon->SetType(kTypeButtonForeground);
+  vector_icon->SetIcon(icon);
+  vector_icon->set_hit_testable(false);
+  foreground_ = vector_icon.get();
+
+  background()->AddChild(std::move(vector_icon));
+}
+
+VectorIconButton::~VectorIconButton() = default;
+
+void VectorIconButton::SetIcon(const gfx::VectorIcon& icon) {
+  foreground_->SetIcon(icon);
+}
+
+void VectorIconButton::SetIconScaleFactor(float factor) {
+  icon_scale_factor_ = factor;
+  OnSetSize(size());
+}
+
+void VectorIconButton::SetIconTranslation(float x, float y) {
+  foreground_->SetTranslate(x, y, 0);
+}
+
+void VectorIconButton::OnStateUpdated() {
+  Button::OnStateUpdated();
+  foreground_->SetColor(colors().GetForegroundColor(!enabled()));
+}
+
+void VectorIconButton::OnSetDrawPhase() {
+  Button::OnSetDrawPhase();
+  foreground_->SetDrawPhase(draw_phase());
+}
+
+void VectorIconButton::OnSetName() {
+  Button::OnSetName();
+  foreground_->set_owner_name_for_test(name());
+}
+
+void VectorIconButton::OnSetSize(const gfx::SizeF& size) {
+  Button::OnSetSize(size);
+  // Maintain aspect ratio of the icon, even if the button isn't square.
+  float new_size = std::min(size.width(), size.height()) * icon_scale_factor_;
+  foreground()->SetSize(new_size, new_size);
+}
+
+}  // namespace vr
diff --git a/chrome/browser/vr/elements/vector_icon_button.h b/chrome/browser/vr/elements/vector_icon_button.h
new file mode 100644
index 0000000..89f98612
--- /dev/null
+++ b/chrome/browser/vr/elements/vector_icon_button.h
@@ -0,0 +1,52 @@
+// Copyright 2018 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_VR_ELEMENTS_VECTOR_ICON_BUTTON_H_
+#define CHROME_BROWSER_VR_ELEMENTS_VECTOR_ICON_BUTTON_H_
+
+#include <memory>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "chrome/browser/vr/elements/button.h"
+#include "ui/gfx/vector_icon_types.h"
+
+namespace vr {
+
+class VectorIcon;
+
+// A vector button has rect as a background and a vector icon as the
+// foreground. When hovered, background and foreground both move forward on Z
+// axis.
+class VectorIconButton : public Button {
+ public:
+  VectorIconButton(base::RepeatingCallback<void()> click_handler,
+                   const gfx::VectorIcon& icon,
+                   AudioDelegate* audio_delegate);
+  ~VectorIconButton() override;
+
+  VectorIcon* foreground() const { return foreground_; }
+
+  void SetIcon(const gfx::VectorIcon& icon);
+  void SetIconTranslation(float x, float y);
+  void SetIconScaleFactor(float factor);
+  float icon_scale_factor() const { return icon_scale_factor_; }
+
+ private:
+  void OnStateUpdated() override;
+  void OnSetDrawPhase() override;
+  void OnSetName() override;
+  void OnSetSize(const gfx::SizeF& size) override;
+
+  // This button will automatically scale down the given icon to fit the button.
+  // This value is used to determine the amount of scaling and can be set
+  // externally to create a smaller or larger icon.
+  float icon_scale_factor_;
+  VectorIcon* foreground_;
+  DISALLOW_COPY_AND_ASSIGN(VectorIconButton);
+};
+
+}  // namespace vr
+
+#endif  // CHROME_BROWSER_VR_ELEMENTS_VECTOR_ICON_BUTTON_H_
diff --git a/chrome/browser/vr/elements/vector_icon_button_unittest.cc b/chrome/browser/vr/elements/vector_icon_button_unittest.cc
new file mode 100644
index 0000000..243f8412
--- /dev/null
+++ b/chrome/browser/vr/elements/vector_icon_button_unittest.cc
@@ -0,0 +1,35 @@
+// Copyright 2018 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/vr/elements/vector_icon_button.h"
+
+#include "chrome/browser/vr/elements/rect.h"
+#include "chrome/browser/vr/elements/vector_icon.h"
+#include "components/vector_icons/vector_icons.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace vr {
+
+TEST(VectorIconButton, CornerRadiiOnResize) {
+  VectorIconButton button(base::RepeatingCallback<void()>(),
+                          vector_icons::kMicIcon, nullptr);
+  button.SetSize(1.0f, 1.0f);
+  button.set_corner_radius(0.25f);
+
+  EXPECT_FLOAT_EQ(0.25f, button.corner_radius());
+  // The foreground of vector icons is not not automatically affected by corner
+  // radius.
+  EXPECT_FLOAT_EQ(0.0f, button.foreground()->corner_radius());
+  EXPECT_FLOAT_EQ(0.25f, button.background()->corner_radius());
+  EXPECT_FLOAT_EQ(0.25f, button.hit_plane()->corner_radius());
+
+  button.SetSize(2.0f, 2.0f);
+
+  EXPECT_FLOAT_EQ(0.25f, button.corner_radius());
+  EXPECT_FLOAT_EQ(0.0f, button.foreground()->corner_radius());
+  EXPECT_FLOAT_EQ(0.25f, button.background()->corner_radius());
+  EXPECT_FLOAT_EQ(0.25f, button.hit_plane()->corner_radius());
+}
+
+}  // namespace vr
diff --git a/chrome/browser/vr/model/capturing_state_model.cc b/chrome/browser/vr/model/capturing_state_model.cc
new file mode 100644
index 0000000..381f346
--- /dev/null
+++ b/chrome/browser/vr/model/capturing_state_model.cc
@@ -0,0 +1,14 @@
+// Copyright 2018 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/vr/model/capturing_state_model.h"
+
+namespace vr {
+
+CapturingStateModel::CapturingStateModel() = default;
+CapturingStateModel::CapturingStateModel(const CapturingStateModel& other) =
+    default;
+CapturingStateModel::~CapturingStateModel() = default;
+
+}  // namespace vr
diff --git a/chrome/browser/vr/model/capturing_state_model.h b/chrome/browser/vr/model/capturing_state_model.h
index 374fd351..823ba086 100644
--- a/chrome/browser/vr/model/capturing_state_model.h
+++ b/chrome/browser/vr/model/capturing_state_model.h
@@ -8,11 +8,21 @@
 namespace vr {
 
 struct CapturingStateModel {
+  CapturingStateModel();
+  CapturingStateModel(const CapturingStateModel& other);
+  ~CapturingStateModel();
+
   bool audio_capture_enabled = false;
   bool video_capture_enabled = false;
   bool screen_capture_enabled = false;
   bool location_access_enabled = false;
   bool bluetooth_connected = false;
+
+  bool audio_capture_potentially_enabled = false;
+  bool video_capture_potentially_enabled = false;
+  bool screen_capture_potentially_enabled = false;
+  bool location_access_potentially_enabled = false;
+  bool bluetooth_potentially_connected = false;
 };
 
 }  // namespace vr
diff --git a/chrome/browser/vr/model/color_scheme.cc b/chrome/browser/vr/model/color_scheme.cc
index 341d42c9..b298ad0 100644
--- a/chrome/browser/vr/model/color_scheme.cc
+++ b/chrome/browser/vr/model/color_scheme.cc
@@ -50,9 +50,8 @@
   normal_scheme.web_vr_transient_toast_background = SK_ColorBLACK;
   normal_scheme.exclusive_screen_toast_foreground = 0xCCFFFFFF;
   normal_scheme.exclusive_screen_toast_background = 0xCC2F2F2F;
-
-  normal_scheme.system_indicator_foreground = normal_scheme.element_foreground;
-  normal_scheme.system_indicator_background = normal_scheme.element_background;
+  normal_scheme.system_indicator_foreground = SK_ColorWHITE;
+  normal_scheme.system_indicator_background = 0x99212121;
   normal_scheme.modal_prompt_icon_foreground = 0xFF4285F4;
   normal_scheme.modal_prompt_background = 0xFFF5F5F5;
   normal_scheme.modal_prompt_foreground = 0xFF333333;
@@ -73,22 +72,19 @@
   normal_scheme.modal_prompt_primary_button_colors.background_hover =
       0xFF3E7DE6;
   normal_scheme.modal_prompt_primary_button_colors.background_down = 0xFF3E7DE6;
-  normal_scheme.back_button.background = normal_scheme.element_background;
-  normal_scheme.back_button.background_down =
+  normal_scheme.url_bar_button.background = SK_ColorTRANSPARENT;
+  normal_scheme.url_bar_button.background_down =
       normal_scheme.element_background_down;
-  normal_scheme.back_button.background_hover =
+  normal_scheme.url_bar_button.background_hover =
       normal_scheme.element_background_hover;
-  normal_scheme.back_button.foreground = normal_scheme.element_foreground;
-  normal_scheme.back_button.foreground_disabled = 0x33333333;
+  normal_scheme.url_bar_button.foreground = normal_scheme.element_foreground;
+  normal_scheme.url_bar_button.foreground_disabled = 0x33333333;
   normal_scheme.url_bar_separator = 0xFF9E9E9E;
-  normal_scheme.url_bar_hint = 0xFF5A5A5A;
+  normal_scheme.url_bar_hint_text = 0xFF5A5A5A;
+  normal_scheme.url_bar_default_icon = 0xFF535353;
+  normal_scheme.url_bar_dangerous_icon = gfx::kGoogleRed700;
   normal_scheme.url_bar.deemphasized = 0xFF5A5A5A;
   normal_scheme.url_bar.emphasized = SK_ColorBLACK;
-  normal_scheme.url_bar.default_icon = 0xFF535353;
-  normal_scheme.url_bar.dangerous_icon = gfx::kGoogleRed700;
-  normal_scheme.url_bar.offline_page_warning =
-      normal_scheme.url_bar.default_icon;
-  normal_scheme.url_bar.separator = normal_scheme.url_bar_separator;
   normal_scheme.prompt_foreground = 0xCC000000;
   normal_scheme.prompt_primary_button_colors.foreground = 0xA6000000;
   normal_scheme.prompt_primary_button_colors.foreground_disabled = 0xA6000000;
@@ -158,6 +154,15 @@
   normal_scheme.cursor_background_edge = SK_ColorTRANSPARENT;
   normal_scheme.cursor_foreground = SK_ColorWHITE;
 
+  normal_scheme.webvr_permission_background = 0xD9212121;
+  normal_scheme.webvr_permission_foreground = SK_ColorWHITE;
+
+  normal_scheme.indicator.background = 0x73212121;
+  normal_scheme.indicator.background_hover = 0xDE212121;
+  normal_scheme.indicator.background_down = 0xDE212121;
+  normal_scheme.indicator.foreground = SK_ColorWHITE;
+  normal_scheme.indicator.foreground_disabled = SK_ColorWHITE;
+
   g_fullscreen_scheme.Get() = normal_scheme;
   ColorScheme& fullscreen_scheme = g_fullscreen_scheme.Get();
   fullscreen_scheme.world_background = 0xFF000714;
@@ -214,21 +219,22 @@
       incognito_scheme.element_foreground;
   incognito_scheme.system_indicator_background =
       incognito_scheme.element_background;
-  incognito_scheme.back_button.background = incognito_scheme.element_background;
-  incognito_scheme.back_button.background_down =
+  incognito_scheme.url_bar_button.background =
+      incognito_scheme.element_background;
+  incognito_scheme.url_bar_button.background_down =
       incognito_scheme.element_background_down;
-  incognito_scheme.back_button.background_hover =
+  incognito_scheme.url_bar_button.background_hover =
       incognito_scheme.element_background_hover;
-  incognito_scheme.back_button.foreground = incognito_scheme.element_foreground;
-  incognito_scheme.back_button.foreground_disabled = 0x33E6E6E6;
+  incognito_scheme.url_bar_button.foreground =
+      incognito_scheme.element_foreground;
+  incognito_scheme.url_bar_button.foreground_disabled = 0x33E6E6E6;
   incognito_scheme.url_bar_separator = 0x1FFFFFFF;
-  incognito_scheme.url_bar_hint = 0xCCFFFFFF;
+  incognito_scheme.url_bar_hint_text = 0xCCFFFFFF;
+  incognito_scheme.url_bar_default_icon = SK_ColorWHITE;
+  incognito_scheme.url_bar_dangerous_icon = SK_ColorWHITE;
+  incognito_scheme.url_bar_separator = incognito_scheme.url_bar_separator;
   incognito_scheme.url_bar.deemphasized = 0xCCFFFFFF;
   incognito_scheme.url_bar.emphasized = SK_ColorWHITE;
-  incognito_scheme.url_bar.default_icon = SK_ColorWHITE;
-  incognito_scheme.url_bar.dangerous_icon = SK_ColorWHITE;
-  incognito_scheme.url_bar.offline_page_warning = SK_ColorWHITE;
-  incognito_scheme.url_bar.separator = incognito_scheme.url_bar_separator;
   incognito_scheme.prompt_foreground = 0xCCFFFFFF;
   incognito_scheme.prompt_primary_button_colors.foreground = 0xD9000000;
   incognito_scheme.prompt_primary_button_colors.foreground_disabled =
@@ -268,7 +274,7 @@
 }
 
 static constexpr size_t kButtonColorsSize = 20;
-static constexpr size_t kUrlBarColorsSize = 24;
+static constexpr size_t kUrlBarColorsSize = 8;
 
 }  // namespace
 
@@ -310,11 +316,7 @@
               "bump this size and update operator== below");
 
 bool UrlBarColors::operator==(const UrlBarColors& other) const {
-  return deemphasized == other.deemphasized && emphasized == other.emphasized &&
-         default_icon == other.default_icon &&
-         dangerous_icon == other.dangerous_icon &&
-         offline_page_warning == other.offline_page_warning &&
-         separator == other.separator;
+  return deemphasized == other.deemphasized && emphasized == other.emphasized;
 }
 
 bool UrlBarColors::operator!=(const UrlBarColors& other) const {
@@ -348,18 +350,15 @@
     normal_scheme.button_colors.background = 0xCCEEEEEE;
     normal_scheme.button_colors.foreground_disabled = 0x33000000;
     normal_scheme.url_bar_separator = 0xFFD0D0D0;
-    normal_scheme.url_bar_hint = 0x61333333;
+    normal_scheme.url_bar_hint_text = 0x61333333;
+    normal_scheme.url_bar_button.background_down =
+        normal_scheme.element_background_down;
+    normal_scheme.url_bar_button.background_hover =
+        normal_scheme.element_background_hover;
+    normal_scheme.url_bar_button.foreground = normal_scheme.element_foreground;
+    normal_scheme.url_bar_button.foreground_disabled = 0x33333333;
     normal_scheme.url_bar.deemphasized = 0x61333333;
     normal_scheme.url_bar.emphasized = 0xFF333333;
-
-    normal_scheme.back_button.background = normal_scheme.element_background;
-    normal_scheme.back_button.background_down =
-        normal_scheme.element_background_down;
-    normal_scheme.back_button.background_hover =
-        normal_scheme.element_background_hover;
-    normal_scheme.back_button.foreground = normal_scheme.element_foreground;
-    normal_scheme.back_button.foreground_disabled = 0x33333333;
-
     normal_scheme.button_colors.background = normal_scheme.element_background;
     normal_scheme.button_colors.background_hover =
         normal_scheme.element_background_hover;
@@ -381,13 +380,12 @@
     incognito_scheme.element_background_hover = 0xCC404A50;
     incognito_scheme.element_background_down = 0xCC212B31;
     incognito_scheme.url_bar_separator = 0xFF445056;
-    incognito_scheme.url_bar_hint = 0x80FFFFFF;
+    incognito_scheme.url_bar_hint_text = 0x80FFFFFF;
+    incognito_scheme.url_bar_default_icon = 0xA7FFFFFF;
+    incognito_scheme.url_bar_dangerous_icon = 0xA7FFFFFF;
     incognito_scheme.url_bar.deemphasized = 0x80FFFFFF;
     incognito_scheme.url_bar.emphasized = 0xCCFFFFFF;
-    incognito_scheme.url_bar.separator = 0xFF445056;
-    incognito_scheme.url_bar.default_icon = 0xA7FFFFFF;
-    incognito_scheme.url_bar.dangerous_icon = 0xA7FFFFFF;
-    incognito_scheme.url_bar.offline_page_warning = 0xA7FFFFFF;
+
     incognito_scheme.omnibox_background = incognito_scheme.element_background;
     incognito_scheme.omnibox_icon = 0xA7FFFFFF;
 
@@ -402,12 +400,10 @@
         incognito_scheme.element_foreground;
     incognito_scheme.system_indicator_background =
         incognito_scheme.element_background;
-    incognito_scheme.back_button.background =
-        incognito_scheme.element_background;
-    incognito_scheme.back_button.background_down =
+    incognito_scheme.url_bar_button.background_down =
         incognito_scheme.element_background_down;
-    incognito_scheme.back_button.background_hover = 0xFF445056;
-    incognito_scheme.back_button.foreground =
+    incognito_scheme.url_bar_button.background_hover = 0xFF445056;
+    incognito_scheme.url_bar_button.foreground =
         incognito_scheme.element_foreground;
     incognito_scheme.suggestion_button_colors.foreground =
         incognito_scheme.suggestion_text;
diff --git a/chrome/browser/vr/model/color_scheme.h b/chrome/browser/vr/model/color_scheme.h
index 816ea62..b66fcc7 100644
--- a/chrome/browser/vr/model/color_scheme.h
+++ b/chrome/browser/vr/model/color_scheme.h
@@ -29,10 +29,6 @@
   bool operator!=(const UrlBarColors& other) const;
   SkColor deemphasized = SK_ColorBLACK;
   SkColor emphasized = SK_ColorBLACK;
-  SkColor default_icon = SK_ColorBLACK;
-  SkColor dangerous_icon = SK_ColorBLACK;
-  SkColor offline_page_warning = SK_ColorBLACK;
-  SkColor separator = SK_ColorBLACK;
 };
 
 struct TextSelectionColors {
@@ -96,13 +92,15 @@
   ButtonColors prompt_secondary_button_colors;
   ButtonColors prompt_primary_button_colors;
 
-  ButtonColors back_button;
+  ButtonColors url_bar_button;
   SkColor url_bar_separator;
-  SkColor url_bar_hint;
-
-  // These colors feed the URL origin texture.
+  SkColor url_bar_hint_text;
+  SkColor url_bar_default_icon;
+  SkColor url_bar_dangerous_icon;
   UrlBarColors url_bar;
 
+  ButtonColors indicator;
+
   SkColor dimmer_outer;
   SkColor dimmer_inner;
 
@@ -143,6 +141,9 @@
   SkColor cursor_background_edge;
   SkColor cursor_foreground;
 
+  SkColor webvr_permission_background;
+  SkColor webvr_permission_foreground;
+
   // These are used for blending between colors that are available only in
   // shaders. They are, as you might expect, one for a given mode, but zero
   // otherwise.
diff --git a/chrome/browser/vr/model/model.cc b/chrome/browser/vr/model/model.cc
index 9db411f4eb..b699211e 100644
--- a/chrome/browser/vr/model/model.cc
+++ b/chrome/browser/vr/model/model.cc
@@ -120,4 +120,10 @@
   return ui_modes.back() == kModeRepositionWindow;
 }
 
+bool Model::reposition_window_permitted() const {
+  return !editing_input && !editing_web_input &&
+         active_modal_prompt_type == kModalPromptTypeNone &&
+         !native_ui.hosted_ui_enabled;
+}
+
 }  // namespace vr
diff --git a/chrome/browser/vr/model/model.h b/chrome/browser/vr/model/model.h
index adc71a33..3ef8961 100644
--- a/chrome/browser/vr/model/model.h
+++ b/chrome/browser/vr/model/model.h
@@ -72,6 +72,7 @@
   bool web_vr_enabled() const;
   bool web_vr_autopresentation_enabled() const;
   bool reposition_window_enabled() const;
+  bool reposition_window_permitted() const;
 
   // Focused text state.
   bool editing_input = false;
diff --git a/chrome/browser/vr/model/web_vr_model.h b/chrome/browser/vr/model/web_vr_model.h
index e98fbc9..db735ba 100644
--- a/chrome/browser/vr/model/web_vr_model.h
+++ b/chrome/browser/vr/model/web_vr_model.h
@@ -35,6 +35,7 @@
   // TODO(ymalik): We should be able to remove this by keeping a history of UI
   // modes.
   bool show_exit_toast = false;
+  bool has_received_permissions = false;
   bool has_produced_frames() const { return state == kWebVrPresenting; }
   bool awaiting_min_splash_screen_duration() const {
     return state == kWebVrAwaitingMinSplashScreenDuration;
diff --git a/chrome/browser/vr/test/mock_browser_ui_interface.h b/chrome/browser/vr/test/mock_browser_ui_interface.h
index 4cd950f..a43b7176 100644
--- a/chrome/browser/vr/test/mock_browser_ui_interface.h
+++ b/chrome/browser/vr/test/mock_browser_ui_interface.h
@@ -28,11 +28,7 @@
   MOCK_METHOD0(SetIsExiting, void());
   MOCK_METHOD2(SetHistoryButtonsEnabled,
                void(bool can_go_back, bool can_go_forward));
-  MOCK_METHOD1(SetVideoCaptureEnabled, void(bool enabled));
-  MOCK_METHOD1(SetScreenCaptureEnabled, void(bool enabled));
-  MOCK_METHOD1(SetAudioCaptureEnabled, void(bool enabled));
-  MOCK_METHOD1(SetBluetoothConnected, void(bool enabled));
-  MOCK_METHOD1(SetLocationAccessEnabled, void(bool enabled));
+  MOCK_METHOD1(SetCapturingState, void(const CapturingStateModel& state));
   MOCK_METHOD1(ShowExitVrPrompt, void(UiUnsupportedMode reason));
   MOCK_METHOD1(SetSpeechRecognitionEnabled, void(bool enabled));
   MOCK_METHOD1(SetRecognitionResult, void(const base::string16& result));
diff --git a/chrome/browser/vr/testapp/vr_test_context.cc b/chrome/browser/vr/testapp/vr_test_context.cc
index 74b7e26..8e0fc9d 100644
--- a/chrome/browser/vr/testapp/vr_test_context.cc
+++ b/chrome/browser/vr/testapp/vr_test_context.cc
@@ -113,10 +113,12 @@
   ui_->SetHistoryButtonsEnabled(true, true);
   ui_->SetLoading(true);
   ui_->SetLoadProgress(0.4);
-  ui_->SetVideoCaptureEnabled(true);
-  ui_->SetScreenCaptureEnabled(true);
-  ui_->SetBluetoothConnected(true);
-  ui_->SetLocationAccessEnabled(true);
+  CapturingStateModel capturing_state;
+  capturing_state.video_capture_enabled = true;
+  capturing_state.screen_capture_enabled = true;
+  capturing_state.bluetooth_connected = true;
+  capturing_state.location_access_enabled = true;
+  ui_->SetCapturingState(capturing_state);
   ui_->input_manager()->set_hit_test_strategy(
       UiInputManager::PROJECT_TO_LASER_ORIGIN_FOR_TEST);
 }
@@ -174,6 +176,9 @@
         incognito_ = !incognito_;
         ui_->SetIncognito(incognito_);
         break;
+      case ui::DomCode::US_C:
+        CycleIndicators();
+        break;
       case ui::DomCode::US_D:
         ui_->Dump(false);
         break;
@@ -457,7 +462,10 @@
 }
 
 void VrTestContext::ExitPresent() {}
-void VrTestContext::ExitFullscreen() {}
+void VrTestContext::ExitFullscreen() {
+  fullscreen_ = false;
+  ui_->SetFullscreen(fullscreen_);
+}
 
 void VrTestContext::Navigate(GURL gurl, NavigationMethod method) {
   ToolbarState state(gurl, security_state::SecurityLevel::HTTP_SHOW_WARNING,
@@ -568,6 +576,24 @@
   ui_->SetOmniboxSuggestions(std::make_unique<OmniboxSuggestions>());
 }
 
+typedef bool CapturingStateModel::*CapturingStateModelMemberPtr;
+
+void VrTestContext::CycleIndicators() {
+  static size_t state = 0;
+
+  const std::vector<CapturingStateModelMemberPtr> signals = {
+      &CapturingStateModel::location_access_enabled,
+      &CapturingStateModel::audio_capture_enabled,
+      &CapturingStateModel::video_capture_enabled,
+      &CapturingStateModel::bluetooth_connected,
+      &CapturingStateModel::screen_capture_enabled};
+
+  state = (state + 1) % (1 << signals.size());
+  for (size_t i = 0; i < signals.size(); ++i) {
+    model_->capturing_state.*signals[i] = state & (1 << i);
+  }
+}
+
 void VrTestContext::CycleOrigin() {
   const std::vector<ToolbarState> states = {
       {GURL("http://domain.com"),
diff --git a/chrome/browser/vr/testapp/vr_test_context.h b/chrome/browser/vr/testapp/vr_test_context.h
index 6d5e6eb..337994c 100644
--- a/chrome/browser/vr/testapp/vr_test_context.h
+++ b/chrome/browser/vr/testapp/vr_test_context.h
@@ -67,6 +67,7 @@
   void CycleWebVrModes();
   void ToggleSplashScreen();
   void CycleOrigin();
+  void CycleIndicators();
   RenderInfo GetRenderInfo() const;
   gfx::Transform ProjectionMatrix() const;
   gfx::Transform ViewProjectionMatrix() const;
diff --git a/chrome/browser/vr/ui.cc b/chrome/browser/vr/ui.cc
index 5b30ff7c..bebbd90 100644
--- a/chrome/browser/vr/ui.cc
+++ b/chrome/browser/vr/ui.cc
@@ -77,6 +77,7 @@
 void Ui::SetWebVrMode(bool enabled, bool show_toast) {
   model_->web_vr.show_exit_toast = show_toast;
   if (enabled) {
+    model_->web_vr.has_received_permissions = false;
     if (!model_->web_vr_autopresentation_enabled()) {
       // When auto-presenting, we transition into this state when the minimum
       // splash-screen duration has passed.
@@ -127,24 +128,9 @@
   model_->can_navigate_forward = can_go_forward;
 }
 
-void Ui::SetVideoCaptureEnabled(bool enabled) {
-  model_->capturing_state.video_capture_enabled = enabled;
-}
-
-void Ui::SetScreenCaptureEnabled(bool enabled) {
-  model_->capturing_state.screen_capture_enabled = enabled;
-}
-
-void Ui::SetAudioCaptureEnabled(bool enabled) {
-  model_->capturing_state.audio_capture_enabled = enabled;
-}
-
-void Ui::SetBluetoothConnected(bool enabled) {
-  model_->capturing_state.bluetooth_connected = enabled;
-}
-
-void Ui::SetLocationAccessEnabled(bool enabled) {
-  model_->capturing_state.location_access_enabled = enabled;
+void Ui::SetCapturingState(const CapturingStateModel& state) {
+  model_->capturing_state = state;
+  model_->web_vr.has_received_permissions = true;
 }
 
 void Ui::ShowExitVrPrompt(UiUnsupportedMode reason) {
@@ -452,6 +438,7 @@
   model_->push_mode(kModeBrowsing);
   if (ui_initial_state.in_web_vr) {
     auto mode = kModeWebVr;
+    model_->web_vr.has_received_permissions = false;
     if (ui_initial_state.web_vr_autopresentation_expected) {
       mode = kModeWebVrAutopresented;
       model_->web_vr.state = kWebVrAwaitingMinSplashScreenDuration;
diff --git a/chrome/browser/vr/ui.h b/chrome/browser/vr/ui.h
index 0b0e71d..1a56d37 100644
--- a/chrome/browser/vr/ui.h
+++ b/chrome/browser/vr/ui.h
@@ -85,11 +85,7 @@
   void SetLoadProgress(float progress) override;
   void SetIsExiting() override;
   void SetHistoryButtonsEnabled(bool can_go_back, bool can_go_forward) override;
-  void SetVideoCaptureEnabled(bool enabled) override;
-  void SetScreenCaptureEnabled(bool enabled) override;
-  void SetAudioCaptureEnabled(bool enabled) override;
-  void SetBluetoothConnected(bool enabled) override;
-  void SetLocationAccessEnabled(bool enabled) override;
+  void SetCapturingState(const CapturingStateModel& state) override;
   void ShowExitVrPrompt(UiUnsupportedMode reason) override;
   void SetSpeechRecognitionEnabled(bool enabled) override;
   void SetRecognitionResult(const base::string16& result) override;
diff --git a/chrome/browser/vr/ui_scene_constants.h b/chrome/browser/vr/ui_scene_constants.h
index bdfab10..a43c9c7 100644
--- a/chrome/browser/vr/ui_scene_constants.h
+++ b/chrome/browser/vr/ui_scene_constants.h
@@ -9,14 +9,6 @@
 
 namespace vr {
 
-static constexpr int kWarningTimeoutSeconds = 30;
-static constexpr float kWarningDistance = 1.0f;
-static constexpr float kWarningAngleRadians = gfx::DegToRad(16.3f);
-static constexpr float kPermanentWarningHeightDMM = 0.049f;
-static constexpr float kPermanentWarningWidthDMM = 0.1568f;
-static constexpr float kTransientWarningHeightDMM = 0.160f;
-static constexpr float kTransientWarningWidthDMM = 0.512f;
-
 static constexpr float kExitWarningDistance = 0.6f;
 static constexpr float kExitWarningTextWidthDMM = 0.44288f;
 static constexpr float kExitWarningFontHeightDMM = 0.024576f;
@@ -54,7 +46,6 @@
 static constexpr float kExitPromptVerticalOffset = -0.09f * kContentDistance;
 
 static constexpr float kUrlBarDistance = 2.4f;
-static constexpr float kUrlBarWidthDMM = 0.672f;
 static constexpr float kUrlBarHeightDMM = 0.088f;
 // This is the non-DMM relative offset of the URL bar. It is used to position
 // the DMM root of the URL bar.
@@ -69,35 +60,27 @@
 static constexpr float kUrlBarEndButtonWidthDMM = 0.088f;
 static constexpr float kUrlBarSeparatorWidthDMM = 0.002f;
 static constexpr float kUrlBarOriginRegionWidthDMM = 0.492f;
-static constexpr float kUrlBarOriginContentWidthDMM = 0.452f;
+static constexpr float kUrlBarOriginRightMarginDMM = 0.020f;
 static constexpr float kUrlBarOriginContentOffsetDMM = 0.020f;
-static constexpr float kUrlBarFieldSpacingDMM = 0.014f;
-static constexpr float kUrlBarOfflineIconTextSpacingDMM = 0.004f;
-static constexpr float kUrlBarSecuritySeparatorHeightDMM = 0.026f;
 static constexpr float kUrlBarOriginFadeWidth = 0.044f;
 static constexpr float kUrlBarOriginMinimumPathWidth = 0.044f;
-static constexpr float kUrlBarBackplaneTopPadding = 0.065f;
-static constexpr float kUrlBarBackplanePadding = 0.005f;
 static constexpr float kUrlBarItemCornerRadiusDMM = 0.006f;
+static constexpr float kUrlBarUrlWidthDMM = kUrlBarOriginRegionWidthDMM -
+                                            kUrlBarEndButtonWidthDMM -
+                                            kUrlBarOriginRightMarginDMM;
 static constexpr float kUrlBarButtonIconScaleFactor =
     kUrlBarButtonIconSizeDMM / kUrlBarButtonSizeDMM;
 
-static constexpr float kOverlayPlaneDistance = 2.3f;
-
-static constexpr float kAudioPermissionPromptWidth = 0.63f * kUrlBarDistance;
-static constexpr float kAudioPermissionPromptHeight = 0.218f * kUrlBarDistance;
-static constexpr float kAudionPermisionPromptDepth = 0.11f;
-
-static constexpr float kIndicatorHeight = 0.08f;
-static constexpr float kIndicatorXPadding = kIndicatorHeight * 0.1f;
-static constexpr float kIndicatorYPadding = kIndicatorHeight * 0.15f;
-static constexpr float kIndicatorIconSize = kIndicatorHeight * 0.7f;
-static constexpr float kIndicatorCornerRadius = kIndicatorHeight * 0.1f;
-static constexpr float kIndicatorMargin = kIndicatorHeight * 0.2f;
-static constexpr float kIndicatorFontHeightDmm = 0.032f;
-static constexpr float kIndicatorGap = 0.05f;
+static constexpr float kIndicatorHeightDMM = 0.064f;
+static constexpr float kIndicatorIconScaleFactor = 0.55f;
+static constexpr float kIndicatorXPaddingDMM = 0.024f;
+static constexpr float kIndicatorYPaddingDMM = 0.018f;
+static constexpr float kIndicatorCornerRadiusDMM = 0.006f;
+static constexpr float kIndicatorOffsetDMM = -0.008f;
+static constexpr float kIndicatorMarginDMM = 0.001f;
 static constexpr float kIndicatorVerticalOffset = 0.1f;
 static constexpr float kIndicatorDistanceOffset = 0.1f;
+static constexpr float kIndicatorDepth = 2.4f;
 
 static constexpr float kWebVrUrlToastWidthDMM = 0.472f;
 static constexpr float kWebVrUrlToastHeightDMM = 0.064f;
@@ -111,9 +94,6 @@
 static constexpr float kWebVrUrlToastRotationRad = gfx::DegToRad(14.0f);
 
 static constexpr float kWebVrToastDistance = 1.0f;
-static constexpr float kToastWidthDMM = 0.512f;
-static constexpr float kToastHeightDMM = 0.064f;
-static constexpr float kToastOffsetDMM = 0.004f;
 static constexpr float kFullScreenToastOffsetDMM = 0.1f;
 static constexpr float kExclusiveScreenToastXPaddingDMM = 0.017f;
 static constexpr float kExclusiveScreenToastYPaddingDMM = 0.02f;
@@ -151,8 +131,6 @@
     (-kUrlBarVerticalOffsetDMM + kContentVerticalOffsetDMM -
      kContentHeightDMM / 2 - kUrlBarHeightDMM / 2) /
     2;
-static constexpr float kLoadingIndicatorDepthOffset =
-    (kUrlBarDistance - kContentDistance) / 2;
 
 static constexpr float kSceneSize = 25.0f;
 static constexpr float kSceneHeight = 4.0f;
@@ -186,9 +164,6 @@
 static constexpr float kTimeoutMessageTextHeightDMM = 0.056f;
 static constexpr float kTimeoutMessageTextWidthDMM = 0.4f;
 
-static constexpr float kTimeoutButtonVerticalOffset =
-    kUrlBarVerticalOffsetDMM * kUrlBarDistance;
-static constexpr float kTimeoutButtonDistance = kUrlBarDistance;
 static constexpr float kTimeoutButtonDepthOffset = -0.1f;
 static constexpr float kTimeoutButtonRotationRad = kUrlBarRotationRad;
 static constexpr float kWebVrTimeoutMessageButtonDiameterDMM = 0.096f;
@@ -223,7 +198,6 @@
 static constexpr float kOmniboxShadowIntensity = 0.4f;
 static constexpr int kOmniboxTransitionMs = 300;
 
-static constexpr float kOmniboxTextFieldIconSizeDMM = 0.05f;
 static constexpr float kOmniboxTextFieldIconButtonSizeDMM = 0.064f;
 static constexpr float kOmniboxTextFieldIconButtonHoverOffsetDMM = 0.012f;
 static constexpr float kOmniboxTextFieldRightMargin =
@@ -252,7 +226,6 @@
 
 static constexpr float kKeyboardDistance = 2.2f;
 static constexpr float kKeyboardVerticalOffsetDMM = -0.45f;
-static constexpr float kKeyboardRotationRadians = -0.14f;
 
 static constexpr float kSnackbarDistance = 1.5f;
 static constexpr float kSnackbarAngle = -gfx::DegToRad(34.0f);
@@ -289,6 +262,23 @@
 
 static constexpr float kRepositionContentOpacity = 0.2f;
 
+static constexpr float kWebVrPermissionCornerRadius = 0.006f;
+static constexpr float kWebVrPermissionLeftPadding = 0.024f;
+static constexpr float kWebVrPermissionRightPadding = 0.032f;
+static constexpr float kWebVrPermissionTopPadding = 0.026f;
+static constexpr float kWebVrPermissionBottomPadding = 0.026f;
+static constexpr float kWebVrPermissionMargin = 0.016f;
+static constexpr float kWebVrPermissionIconSize = 0.034f;
+static constexpr float kWebVrPermissionFontHeight = 0.024f;
+static constexpr float kWebVrPermissionTextWidth = 0.380f;
+static constexpr float kWebVrPermissionOuterMargin = 0.008f;
+static constexpr float kWebVrPermissionDepth = 0.015f;
+static constexpr float kWebVrPermissionOffsetStart = 0.3f;
+static constexpr float kWebVrPermissionOffsetOvershoot = -0.01f;
+static constexpr float kWebVrPermissionOffsetFinal = 0.0f;
+static constexpr int kWebVrPermissionOffsetMs = 250;
+static constexpr int kWebVrPermissionAnimationDurationMs = 750;
+
 static constexpr float kPromptWidthDMM = 0.63f;
 static constexpr float kPromptHeightDMM = 0.218f;
 static constexpr float kPromptVerticalOffsetDMM = -0.1f;
@@ -301,10 +291,8 @@
 static constexpr float kMinResizerScale = 0.5f;
 static constexpr float kMaxResizerScale = 1.5f;
 
-static constexpr float kRepositionFrameTolerance = 0.3f;
 static constexpr float kRepositionFrameTopPadding = 0.25f;
 static constexpr float kRepositionFrameEdgePadding = 0.04f;
-static constexpr float kRepositionFrameMaxOpacity = 0.6f;
 static constexpr float kRepositionFrameHitPlaneTopPadding = 0.5f;
 static constexpr float kRepositionFrameTransitionDurationMs = 300;
 
diff --git a/chrome/browser/vr/ui_scene_creator.cc b/chrome/browser/vr/ui_scene_creator.cc
index 8fc02c4..f946f88 100644
--- a/chrome/browser/vr/ui_scene_creator.cc
+++ b/chrome/browser/vr/ui_scene_creator.cc
@@ -12,6 +12,10 @@
 #include "base/i18n/case_conversion.h"
 #include "base/numerics/math_constants.h"
 #include "base/strings/utf_string_conversions.h"
+#include "cc/animation/animation_curve.h"
+#include "cc/animation/animation_target.h"
+#include "cc/animation/keyframe_effect.h"
+#include "cc/animation/keyframed_animation_curve.h"
 #include "chrome/browser/vr/databinding/binding.h"
 #include "chrome/browser/vr/databinding/vector_binding.h"
 #include "chrome/browser/vr/elements/button.h"
@@ -24,12 +28,14 @@
 #include "chrome/browser/vr/elements/environment/stars.h"
 #include "chrome/browser/vr/elements/exit_prompt.h"
 #include "chrome/browser/vr/elements/full_screen_rect.h"
+#include "chrome/browser/vr/elements/indicator_spec.h"
 #include "chrome/browser/vr/elements/invisible_hit_target.h"
 #include "chrome/browser/vr/elements/keyboard.h"
 #include "chrome/browser/vr/elements/laser.h"
 #include "chrome/browser/vr/elements/linear_layout.h"
 #include "chrome/browser/vr/elements/omnibox_formatting.h"
 #include "chrome/browser/vr/elements/omnibox_text_field.h"
+#include "chrome/browser/vr/elements/oval.h"
 #include "chrome/browser/vr/elements/prompt.h"
 #include "chrome/browser/vr/elements/rect.h"
 #include "chrome/browser/vr/elements/repositioner.h"
@@ -60,6 +66,7 @@
 #include "chrome/browser/vr/vector_icons/vector_icons.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/grit/generated_resources.h"
+#include "components/toolbar/vector_icons.h"
 #include "components/vector_icons/vector_icons.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/transform_util.h"
@@ -126,13 +133,6 @@
   return element;
 }
 
-Sounds CreateButtonSounds() {
-  Sounds sounds;
-  sounds.hover_enter = kSoundButtonHover;
-  sounds.button_down = kSoundButtonClick;
-  return sounds;
-}
-
 typedef VectorBinding<OmniboxSuggestion, Button> SuggestionSetBinding;
 typedef typename SuggestionSetBinding::ElementBinding SuggestionBinding;
 
@@ -200,14 +200,14 @@
             ui->OnUiRequestedNavigation();
           },
           base::Unretained(browser), base::Unretained(ui),
-          base::Unretained(model), base::Unretained(element_binding)));
+          base::Unretained(model), base::Unretained(element_binding)),
+      audio_delegate);
 
   background->SetType(kTypeOmniboxSuggestionBackground);
   background->set_hit_testable(true);
   background->set_bubble_events(true);
   background->set_bounds_contain_children(true);
   background->set_hover_offset(0.0);
-  background->SetSounds(CreateButtonSounds(), audio_delegate);
   VR_BIND_BUTTON_COLORS(model, background.get(),
                         &ColorScheme::suggestion_button_colors,
                         &Button::SetButtonColors);
@@ -333,7 +333,8 @@
     const gfx::VectorIcon& vector_icon,
     const base::string16& label,
     const base::string16& button_label,
-    base::RepeatingCallback<void()> callback) {
+    base::RepeatingCallback<void()> callback,
+    AudioDelegate* audio_delegate) {
   auto scaler = std::make_unique<ScaledDepthAdjuster>(kSnackbarDistance);
 
   auto snackbar_layout =
@@ -371,7 +372,8 @@
   VR_BIND_COLOR(model, text.get(), &ColorScheme::snackbar_foreground,
                 &Text::SetColor);
 
-  auto button = Create<Button>(kNone, kPhaseForeground, callback);
+  auto button =
+      Create<Button>(kNone, kPhaseForeground, callback, audio_delegate);
   button->SetType(kTypeSnackbarButton);
   VR_BIND_BUTTON_COLORS(model, button.get(),
                         &ColorScheme::snackbar_button_colors,
@@ -612,6 +614,68 @@
   return handlers;
 }
 
+std::unique_ptr<UiElement> CreateWebVrIndicator(Model* model,
+                                                IndicatorSpec spec) {
+  auto container = Create<Rect>(spec.webvr_name, kPhaseOverlayForeground);
+  VR_BIND_COLOR(model, container.get(),
+                &ColorScheme::webvr_permission_background, &Rect::SetColor);
+  container->set_corner_radius(kWebVrPermissionCornerRadius);
+  container->set_bounds_contain_children(true);
+  container->SetVisible(false);
+  container->set_padding(
+      kWebVrPermissionLeftPadding, kWebVrPermissionTopPadding,
+      kWebVrPermissionRightPadding, kWebVrPermissionBottomPadding);
+
+  auto layout = Create<LinearLayout>(kNone, kPhaseNone, LinearLayout::kRight);
+  layout->set_margin(kWebVrPermissionMargin);
+
+  auto icon_element = Create<VectorIcon>(kNone, kPhaseOverlayForeground, 128);
+  VR_BIND_COLOR(model, icon_element.get(),
+                &ColorScheme::webvr_permission_foreground,
+                &VectorIcon::SetColor);
+  icon_element->SetIcon(spec.icon);
+  icon_element->set_y_anchoring(TOP);
+  icon_element->SetSize(kWebVrPermissionIconSize, kWebVrPermissionIconSize);
+
+  auto text_element =
+      Create<Text>(kNone, kPhaseOverlayForeground, kWebVrPermissionFontHeight);
+  text_element->SetLayoutMode(kMultiLineFixedWidth);
+  text_element->SetAlignment(UiTexture::kTextAlignmentLeft);
+  text_element->SetColor(SK_ColorWHITE);
+  text_element->SetSize(kWebVrPermissionTextWidth, 0.0f);
+  if (spec.signal) {
+    text_element->AddBinding(std::make_unique<Binding<bool>>(
+        VR_BIND_LAMBDA(
+            [](Model* model, bool CapturingStateModel::*signal) {
+              return model->capturing_state.*signal;
+            },
+            base::Unretained(model), spec.signal),
+        VR_BIND_LAMBDA(
+            [](Text* view, int resource, int potential_resource,
+               const bool& value) {
+              view->SetText(l10n_util::GetStringUTF16(
+                  value ? resource : potential_resource));
+            },
+            base::Unretained(text_element.get()), spec.resource_string,
+            spec.potential_resource_string)));
+  } else {
+    text_element->SetText(l10n_util::GetStringUTF16(spec.resource_string));
+  }
+  VR_BIND_COLOR(model, text_element.get(),
+                &ColorScheme::webvr_permission_foreground, &Text::SetColor);
+
+  layout->AddChild(std::move(icon_element));
+  layout->AddChild(std::move(text_element));
+  container->AddChild(std::move(layout));
+
+  return container;
+}
+
+void SetVisibleInLayout(UiElement* e, bool v) {
+  e->SetVisible(v);
+  e->set_requires_layout(v);
+}
+
 }  // namespace
 
 UiSceneCreator::UiSceneCreator(UiBrowserInterface* browser,
@@ -665,6 +729,7 @@
   backplane->SetName(kHostedUiBackplane);
   backplane->SetSize(kSceneSize, kSceneSize);
   backplane->SetTranslate(0.0, kContentVerticalOffset, -kContentDistance);
+  backplane->set_contributes_to_parent_bounds(false);
   EventHandlers event_handlers;
   event_handlers.button_up = base::BindRepeating(
       [](Model* model, UiBrowserInterface* browser) {
@@ -716,7 +781,8 @@
           },
           base::Unretained(hosted_ui.get()))));
   backplane->AddChild(std::move(hosted_ui));
-  scene_->AddUiElement(k2dBrowsingRoot, std::move(backplane));
+  scene_->AddUiElement(k2dBrowsingOpacityControlForUpdateKeyboardPrompt,
+                       std::move(backplane));
 }
 
 void UiSceneCreator::Create2dBrowsingSubtreeRoots() {
@@ -768,7 +834,6 @@
   element->set_bounds_contain_children(true);
   VR_BIND_VISIBILITY(element, model->active_modal_prompt_type !=
                                   kModalPromptTypeExitVRForSiteInfo);
-
   scene_->AddUiElement(k2dBrowsingVisibilityControlForPrompt,
                        std::move(element));
 
@@ -784,16 +849,6 @@
   scene_->AddUiElement(k2dBrowsingVisibiltyControlForSiteInfoPrompt,
                        std::move(element));
 
-  element = Create<UiElement>(k2dBrowsingOpacityControlForNativeDialogPrompt,
-                              kPhaseNone);
-  element->set_bounds_contain_children(true);
-  element->SetTransitionedProperties({OPACITY});
-  element->AddBinding(VR_BIND(
-      bool, Model, model_, !model->native_ui.hosted_ui_enabled, UiElement,
-      element.get(), view->SetOpacity(value ? 1.0 : kModalPromptFadeOpacity)));
-  scene_->AddUiElement(k2dBrowsingOpacityControlForAudioPermissionPrompt,
-                       std::move(element));
-
   element = Create<UiElement>(k2dBrowsingOpacityControlForUpdateKeyboardPrompt,
                               kPhaseNone);
   element->set_bounds_contain_children(true);
@@ -803,7 +858,17 @@
               model->active_modal_prompt_type != kModalPromptTypeUpdateKeyboard,
               UiElement, element.get(),
               view->SetOpacity(value ? 1.0 : kModalPromptFadeOpacity)));
-  scene_->AddUiElement(k2dBrowsingOpacityControlForNativeDialogPrompt,
+  scene_->AddUiElement(k2dBrowsingOpacityControlForAudioPermissionPrompt,
+                       std::move(element));
+
+  element = Create<UiElement>(k2dBrowsingOpacityControlForNativeDialogPrompt,
+                              kPhaseNone);
+  element->set_bounds_contain_children(true);
+  element->SetTransitionedProperties({OPACITY});
+  element->AddBinding(VR_BIND(
+      bool, Model, model_, !model->native_ui.hosted_ui_enabled, UiElement,
+      element.get(), view->SetOpacity(value ? 1.0 : kModalPromptFadeOpacity)));
+  scene_->AddUiElement(k2dBrowsingOpacityControlForUpdateKeyboardPrompt,
                        std::move(element));
 
   element = Create<UiElement>(k2dBrowsingForeground, kPhaseNone);
@@ -813,7 +878,7 @@
       kSpeechRecognitionOpacityAnimationDurationMs));
   VR_BIND_VISIBILITY(element, model->default_browsing_enabled() ||
                                   model->fullscreen_enabled());
-  scene_->AddUiElement(k2dBrowsingOpacityControlForUpdateKeyboardPrompt,
+  scene_->AddUiElement(k2dBrowsingOpacityControlForNativeDialogPrompt,
                        std::move(element));
 
   element = Create<UiElement>(k2dBrowsingContentGroup, kPhaseNone);
@@ -875,75 +940,111 @@
 }
 
 void UiSceneCreator::CreateSystemIndicators() {
-  struct Indicator {
-    UiElementName name;
-    const gfx::VectorIcon& icon;
-    int resource_string;
-    bool CapturingStateModel::*signal;
-  };
-  const std::vector<Indicator> indicators = {
-      {kAudioCaptureIndicator, vector_icons::kMicIcon,
-       IDS_AUDIO_CALL_NOTIFICATION_TEXT_2,
-       &CapturingStateModel::audio_capture_enabled},
-      {kVideoCaptureIndicator, vector_icons::kVideocamIcon,
-       IDS_VIDEO_CALL_NOTIFICATION_TEXT_2,
-       &CapturingStateModel::video_capture_enabled},
-      {kScreenCaptureIndicator, vector_icons::kScreenShareIcon,
-       IDS_SCREEN_CAPTURE_NOTIFICATION_TEXT_2,
-       &CapturingStateModel::screen_capture_enabled},
-      {kBluetoothConnectedIndicator, vector_icons::kBluetoothConnectedIcon, 0,
-       &CapturingStateModel::bluetooth_connected},
-      {kLocationAccessIndicator, vector_icons::kLocationOnIcon, 0,
-       &CapturingStateModel::location_access_enabled},
-  };
+  auto backplane =
+      Create<InvisibleHitTarget>(kIndicatorBackplane, kPhaseForeground);
+  backplane->set_bounds_contain_children(true);
+  backplane->set_contributes_to_parent_bounds(false);
+  backplane->set_y_anchoring(TOP);
+  backplane->set_corner_radius(kIndicatorCornerRadiusDMM);
+  backplane->SetTranslate(0, kIndicatorVerticalOffset,
+                          kIndicatorDistanceOffset);
+  backplane->SetScale(kIndicatorDepth, kIndicatorDepth, 1.0f);
+  VR_BIND_VISIBILITY(backplane, !model->fullscreen_enabled());
 
-  std::unique_ptr<LinearLayout> indicator_layout =
-      std::make_unique<LinearLayout>(LinearLayout::kRight);
-  indicator_layout->SetName(kIndicatorLayout);
-  indicator_layout->set_y_anchoring(TOP);
-  indicator_layout->SetTranslate(0, kIndicatorVerticalOffset,
-                                 kIndicatorDistanceOffset);
-  indicator_layout->set_margin(kIndicatorGap);
-  indicator_layout->set_contributes_to_parent_bounds(false);
-  VR_BIND_VISIBILITY(indicator_layout, !model->fullscreen_enabled());
+  auto indicator_layout =
+      Create<LinearLayout>(kIndicatorLayout, kPhaseNone, LinearLayout::kRight);
+  indicator_layout->set_margin(kIndicatorMarginDMM);
 
-  for (const auto& indicator : indicators) {
-    auto element = std::make_unique<Toast>();
-    element->SetName(indicator.name);
+  auto specs = GetIndicatorSpecs();
+  for (const auto& spec : specs) {
+    auto element = std::make_unique<VectorIconButton>(
+        base::RepeatingCallback<void()>(), spec.icon, audio_delegate_);
+    element->SetName(spec.name);
     element->SetDrawPhase(kPhaseForeground);
-    element->set_padding(kIndicatorXPadding, kIndicatorYPadding);
-    element->set_corner_radius(kIndicatorCornerRadius);
-    element->set_hit_testable(true);
-    element->SetMargin(kIndicatorMargin);
-    element->AddIcon(indicator.icon, 64, kIndicatorIconSize);
-    if (indicator.resource_string != 0) {
-      element->AddText(l10n_util::GetStringUTF16(indicator.resource_string),
-                       kIndicatorFontHeightDmm,
-                       TextLayoutMode::kSingleLineFixedHeight);
-    }
-
-    VR_BIND_COLOR(model_, element.get(),
-                  &ColorScheme::system_indicator_background,
-                  &Toast::SetBackgroundColor);
-    VR_BIND_COLOR(model_, element.get(),
-                  &ColorScheme::system_indicator_foreground,
-                  &Toast::SetForegroundColor);
+    element->SetSize(kIndicatorHeightDMM, kIndicatorHeightDMM);
+    element->SetIconScaleFactor(kIndicatorIconScaleFactor);
+    element->set_hover_offset(0.0f);
     element->AddBinding(std::make_unique<Binding<bool>>(
         VR_BIND_LAMBDA(
-            [](Model* m, bool CapturingStateModel::*permission) {
-              return m->capturing_state.*permission;
+            [](Model* model, bool CapturingStateModel::*signal) {
+              return model->capturing_state.*signal;
             },
-            base::Unretained(model_), indicator.signal),
+            base::Unretained(model_), spec.signal),
         VR_BIND_LAMBDA(
-            [](UiElement* e, const bool& v) {
-              e->SetVisible(v);
-              e->set_requires_layout(v);
+            [](UiElement* view, const bool& value) {
+              view->SetVisible(value);
+              view->set_requires_layout(value);
             },
             base::Unretained(element.get()))));
+    element->AddBinding(std::make_unique<Binding<std::pair<bool, bool>>>(
+        VR_BIND_LAMBDA(
+            [](UiElement* parent, UiElement* child) {
+              return std::make_pair(parent->FirstLaidOutChild() == child,
+                                    parent->LastLaidOutChild() == child);
+            },
+            base::Unretained(indicator_layout.get()),
+            base::Unretained(element.get())),
+        VR_BIND_LAMBDA(
+            [](UiElement* view, const std::pair<bool, bool>& value) {
+              CornerRadii radii;
+              radii.upper_left = value.first ? kIndicatorCornerRadiusDMM : 0.0f;
+              radii.lower_left = radii.upper_left;
+              radii.upper_right =
+                  value.second ? kIndicatorCornerRadiusDMM : 0.0f;
+              radii.lower_right = radii.upper_right;
+              view->SetCornerRadii(radii);
+            },
+            base::Unretained(element.get()))));
+    VR_BIND_BUTTON_COLORS(model_, element.get(), &ColorScheme::indicator,
+                          &Button::SetButtonColors);
 
+    auto tooltip = Create<Oval>(kNone, kPhaseForeground);
+    VR_BIND_COLOR(model_, tooltip.get(),
+                  &ColorScheme::webvr_permission_background, &Rect::SetColor);
+    tooltip->set_bounds_contain_children(true);
+    tooltip->set_padding(kIndicatorXPaddingDMM, kIndicatorYPaddingDMM,
+                         kIndicatorXPaddingDMM, kIndicatorYPaddingDMM);
+    tooltip->set_y_anchoring(BOTTOM);
+    tooltip->set_y_centering(TOP);
+    tooltip->SetVisible(false);
+    tooltip->SetTranslate(0, kIndicatorOffsetDMM, 0);
+    tooltip->set_owner_name_for_test(element->name());
+    tooltip->SetTransitionedProperties({OPACITY});
+    tooltip->SetType(kTypeTooltip);
+    tooltip->AddBinding(VR_BIND_FUNC(bool, Button, element.get(),
+                                     model->hovered(), UiElement, tooltip.get(),
+                                     SetVisible));
+
+    auto text_element =
+        Create<Text>(kNone, kPhaseForeground, kWebVrPermissionFontHeight);
+    text_element->SetLayoutMode(kSingleLineFixedHeight);
+    text_element->SetColor(SK_ColorWHITE);
+    text_element->set_owner_name_for_test(element->name());
+    text_element->SetSize(0.0f, kWebVrPermissionFontHeight);
+    text_element->SetType(kTypeLabel);
+    text_element->AddBinding(std::make_unique<Binding<bool>>(
+        VR_BIND_LAMBDA(
+            [](Model* model, bool CapturingStateModel::*signal) {
+              return model->capturing_state.*signal;
+            },
+            base::Unretained(model_), spec.signal),
+        VR_BIND_LAMBDA(
+            [](Text* view, int resource, int potential_resource,
+               const bool& value) {
+              view->SetText(l10n_util::GetStringUTF16(
+                  value ? resource : potential_resource));
+            },
+            base::Unretained(text_element.get()), spec.resource_string,
+            spec.potential_resource_string)));
+    VR_BIND_COLOR(model_, text_element.get(),
+                  &ColorScheme::webvr_permission_foreground, &Text::SetColor);
+
+    tooltip->AddChild(std::move(text_element));
+    element->AddChild(std::move(tooltip));
     indicator_layout->AddChild(std::move(element));
   }
-  scene_->AddUiElement(k2dBrowsingContentGroup, std::move(indicator_layout));
+  backplane->AddChild(std::move(indicator_layout));
+  scene_->AddUiElement(k2dBrowsingContentGroup, std::move(backplane));
 }
 
 void UiSceneCreator::CreateContentQuad() {
@@ -1064,7 +1165,7 @@
           },
           base::Unretained(model_), base::Unretained(frame.get())),
       VR_BIND_LAMBDA(
-          [](Rect* e, const gfx::PointF& value) {
+          [](Model* model, Rect* e, const gfx::PointF& value) {
             gfx::RectF inner(e->stale_size());
             inner.Inset(kRepositionFrameEdgePadding, kRepositionFrameTopPadding,
                         kRepositionFrameEdgePadding,
@@ -1074,11 +1175,12 @@
                 kRepositionFrameEdgePadding,
                 kRepositionFrameTopPadding - kRepositionFrameHitPlaneTopPadding,
                 kRepositionFrameEdgePadding, kRepositionFrameEdgePadding);
-            const bool is_on_frame =
-                outer.Contains(value) && !inner.Contains(value);
+            const bool is_on_frame = outer.Contains(value) &&
+                                     !inner.Contains(value) &&
+                                     model->reposition_window_permitted();
             e->SetLocalOpacity(is_on_frame ? 1.0f : 0.0f);
           },
-          base::Unretained(frame.get()))));
+          base::Unretained(model_), base::Unretained(frame.get()))));
 
   auto plane =
       Create<InvisibleHitTarget>(kContentFrameHitPlane, kPhaseForeground);
@@ -1091,6 +1193,9 @@
   plane->SetSounds(sounds, audio_delegate_);
   plane->set_padding(0, kRepositionFrameHitPlaneTopPadding, 0, 0);
   plane->set_event_handlers(CreateRepositioningHandlers(model_, scene_));
+  plane->AddBinding(VR_BIND_FUNC(bool, Model, model_,
+                                 model->reposition_window_permitted(),
+                                 UiElement, plane.get(), set_hit_testable));
 
   shadow->AddChild(std::move(main_content));
   resizer->AddChild(std::move(shadow));
@@ -1258,7 +1363,7 @@
       Create<Text>(kWebVrTimeoutMessageButtonText, kPhaseForeground,
                    kTimeoutMessageTextFontHeightDMM);
 
-  // Disk-style button text is not uppercase. See crbug.com/787654.
+  // Disc-style button text is not uppercase. See https://crbug.com/787654.
   timeout_button_text->SetText(
       l10n_util::GetStringUTF16(IDS_VR_WEB_VR_EXIT_BUTTON_LABEL));
   timeout_button_text->SetColor(model_->color_scheme().web_vr_timeout_spinner);
@@ -1757,10 +1862,13 @@
   scaler->set_contributes_to_parent_bounds(false);
   scene_->AddUiElement(kUrlBarPositioner, std::move(scaler));
 
-  auto url_bar = Create<UiElement>(kUrlBar, kPhaseNone);
+  auto url_bar = Create<Rect>(kUrlBar, kPhaseForeground);
   url_bar->SetRotate(1, 0, 0, kUrlBarRotationRad);
   url_bar->set_bounds_contain_children(true);
+  url_bar->set_corner_radius(kUrlBarHeightDMM / 2);
   VR_BIND_VISIBILITY(url_bar, !model->fullscreen_enabled());
+  VR_BIND_COLOR(model_, url_bar.get(), &ColorScheme::element_background,
+                &Rect::SetColor);
   scene_->AddUiElement(kUrlBarDmmRoot, std::move(url_bar));
 
   auto indicator_bg = std::make_unique<Rect>();
@@ -1799,40 +1907,30 @@
           base::Unretained(indicator_fg.get()))));
 
   scene_->AddUiElement(kLoadingIndicator, std::move(indicator_fg));
+
   auto layout =
       Create<LinearLayout>(kUrlBarLayout, kPhaseNone, LinearLayout::kRight);
   layout->set_bounds_contain_children(true);
   scene_->AddUiElement(kUrlBar, std::move(layout));
 
-  auto back_button =
-      Create<Button>(kUrlBarBackButton, kPhaseForeground,
-                     base::BindRepeating(&UiBrowserInterface::NavigateBack,
-                                         base::Unretained(browser_)));
+  auto back_button = Create<VectorIconButton>(
+      kUrlBarBackButton, kPhaseForeground,
+      base::BindRepeating(&UiBrowserInterface::NavigateBack,
+                          base::Unretained(browser_)),
+      vector_icons::kBackArrowIcon, audio_delegate_);
   back_button->SetSize(kUrlBarEndButtonWidthDMM, kUrlBarHeightDMM);
   back_button->SetCornerRadii(
       {kUrlBarHeightDMM / 2, 0, kUrlBarHeightDMM / 2, 0});
-  back_button->set_hover_offset(0.0f);
-  back_button->SetSounds(CreateButtonSounds(), audio_delegate_);
+  back_button->set_hover_offset(0);
+  back_button->SetIconScaleFactor(kUrlBarButtonIconSizeDMM / kUrlBarHeightDMM);
+  back_button->SetIconTranslation(kUrlBarEndButtonIconOffsetDMM, 0);
   back_button->AddBinding(VR_BIND_FUNC(bool, Model, model_,
                                        model->can_navigate_back, Button,
                                        back_button.get(), SetEnabled));
-  VR_BIND_BUTTON_COLORS(model_, back_button.get(), &ColorScheme::back_button,
+  VR_BIND_BUTTON_COLORS(model_, back_button.get(), &ColorScheme::url_bar_button,
                         &Button::SetButtonColors);
   scene_->AddUiElement(kUrlBarLayout, std::move(back_button));
 
-  auto back_icon =
-      Create<VectorIcon>(kUrlBarBackButtonIcon, kPhaseForeground, 128);
-  back_icon->SetIcon(vector_icons::kBackArrowIcon);
-  back_icon->SetSize(kUrlBarButtonIconSizeDMM, kUrlBarButtonIconSizeDMM);
-  back_icon->SetTranslate(kUrlBarEndButtonIconOffsetDMM, 0, 0);
-  back_icon->AddBinding(VR_BIND_FUNC(
-      SkColor, Model, model_,
-      model->can_navigate_back
-          ? model->color_scheme().button_colors.foreground
-          : model->color_scheme().button_colors.foreground_disabled,
-      VectorIcon, back_icon.get(), SetColor));
-  scene_->AddUiElement(kUrlBarBackButton, std::move(back_icon));
-
   auto separator = Create<Rect>(kUrlBarSeparator, kPhaseForeground);
   separator->set_hit_testable(true);
   separator->SetSize(kUrlBarSeparatorWidthDMM, kUrlBarHeightDMM);
@@ -1840,13 +1938,6 @@
                 &Rect::SetColor);
   scene_->AddUiElement(kUrlBarLayout, std::move(separator));
 
-  auto origin_region = Create<Rect>(kUrlBarOriginRegion, kPhaseForeground);
-  origin_region->set_hit_testable(true);
-  origin_region->SetSize(kUrlBarOriginRegionWidthDMM, kUrlBarHeightDMM);
-  VR_BIND_COLOR(model_, origin_region.get(), &ColorScheme::element_background,
-                &Rect::SetColor);
-  scene_->AddUiElement(kUrlBarLayout, std::move(origin_region));
-
   base::RepeatingCallback<void()> url_click_callback;
   if (base::FeatureList::IsEnabled(features::kVrBrowserKeyboard)) {
     url_click_callback = base::BindRepeating(
@@ -1862,42 +1953,102 @@
     url_click_callback = base::BindRepeating([] {});
   }
 
-  auto origin_content = Create<UrlBar>(
-      kUrlBarOriginContent, kPhaseForeground, 512, url_click_callback,
+  auto origin_region = Create<Button>(kUrlBarOriginRegion, kPhaseForeground,
+                                      url_click_callback, audio_delegate_);
+  origin_region->set_hit_testable(true);
+  origin_region->set_bounds_contain_children(true);
+  origin_region->set_hover_offset(0);
+  VR_BIND_BUTTON_COLORS(model_, origin_region.get(),
+                        &ColorScheme::url_bar_button, &Button::SetButtonColors);
+  scene_->AddUiElement(kUrlBarLayout, std::move(origin_region));
+
+  auto origin_layout = Create<LinearLayout>(kUrlBarOriginLayout, kPhaseNone,
+                                            LinearLayout::kRight);
+  scene_->AddUiElement(kUrlBarOriginRegion, std::move(origin_layout));
+
+  auto security_button_region =
+      Create<Rect>(kUrlBarSecurityButtonRegion, kPhaseNone);
+  security_button_region->SetType(kTypeSpacer);
+  security_button_region->SetSize(kUrlBarEndButtonWidthDMM, kUrlBarHeightDMM);
+  scene_->AddUiElement(kUrlBarOriginLayout, std::move(security_button_region));
+
+  auto security_button = Create<VectorIconButton>(
+      kUrlBarSecurityButton, kPhaseForeground,
       base::BindRepeating(&UiBrowserInterface::OnUnsupportedMode,
-                          base::Unretained(browser_)));
-  origin_content->set_hit_testable(true);
-  origin_content->SetSize(kUrlBarOriginContentWidthDMM, kUrlBarHeightDMM);
-  origin_content->SetTranslate(kUrlBarOriginContentOffsetDMM, 0, 0);
-  origin_content->set_x_anchoring(LEFT);
-  origin_content->set_x_centering(LEFT);
-  VR_BIND_VISIBILITY(origin_content, model->toolbar_state.should_display_url);
-  origin_content->AddBinding(
-      VR_BIND_FUNC(ToolbarState, Model, model_, model->toolbar_state, UrlBar,
-                   origin_content.get(), SetToolbarState));
-  origin_content->AddBinding(VR_BIND_FUNC(UrlBarColors, Model, model_,
-                                          model->color_scheme().url_bar, UrlBar,
-                                          origin_content.get(), SetColors));
-  VR_BIND_COLOR(model_, origin_content.get(), &ColorScheme::element_background,
+                          base::Unretained(browser_),
+                          UiUnsupportedMode::kUnhandledPageInfo),
+      toolbar::kHttpsInvalidIcon, audio_delegate_);
+  security_button->SetIconScaleFactor(kUrlBarButtonIconScaleFactor);
+  security_button->SetSize(kUrlBarButtonSizeDMM, kUrlBarButtonSizeDMM);
+  security_button->set_corner_radius(kUrlBarItemCornerRadiusDMM);
+  security_button->set_hover_offset(kOmniboxTextFieldIconButtonHoverOffsetDMM);
+  VR_BIND_VISIBILITY(security_button, model->toolbar_state.should_display_url);
+  VR_BIND_BUTTON_COLORS(model_, security_button.get(),
+                        &ColorScheme::url_bar_button, &Button::SetButtonColors);
+  security_button->AddBinding(std::make_unique<Binding<const gfx::VectorIcon*>>(
+      VR_BIND_LAMBDA([](Model* m) { return m->toolbar_state.vector_icon; },
+                     base::Unretained(model_)),
+      VR_BIND_LAMBDA(
+          [](VectorIconButton* e, const gfx::VectorIcon* const& icon) {
+            if (icon != nullptr) {
+              e->SetIcon(*icon);
+            }
+          },
+          security_button.get())));
+  security_button->AddBinding(std::make_unique<Binding<ButtonColors>>(
+      VR_BIND_LAMBDA(
+          [](Model* m) {
+            ButtonColors colors = m->color_scheme().url_bar_button;
+            if (m->toolbar_state.security_level ==
+                security_state::SecurityLevel::DANGEROUS) {
+              colors.foreground = m->color_scheme().url_bar_dangerous_icon;
+            } else {
+              colors.foreground = m->color_scheme().url_bar_default_icon;
+            }
+            return colors;
+          },
+          base::Unretained(model_)),
+      VR_BIND_LAMBDA(
+          [](VectorIconButton* e, const ButtonColors& colors) {
+            e->SetButtonColors(colors);
+          },
+          base::Unretained(security_button.get()))));
+  scene_->AddUiElement(kUrlBarSecurityButtonRegion, std::move(security_button));
+
+  auto url_text =
+      Create<UrlBar>(kUrlBarUrlText, kPhaseForeground, 512,
+                     base::BindRepeating(&UiBrowserInterface::OnUnsupportedMode,
+                                         base::Unretained(browser_)));
+  url_text->SetSize(kUrlBarUrlWidthDMM, kUrlBarHeightDMM);
+  VR_BIND_VISIBILITY(url_text, model->toolbar_state.should_display_url);
+  url_text->AddBinding(VR_BIND_FUNC(ToolbarState, Model, model_,
+                                    model->toolbar_state, UrlBar,
+                                    url_text.get(), SetToolbarState));
+  url_text->AddBinding(VR_BIND_FUNC(UrlBarColors, Model, model_,
+                                    model->color_scheme().url_bar, UrlBar,
+                                    url_text.get(), SetColors));
+  VR_BIND_COLOR(model_, url_text.get(), &ColorScheme::element_background,
                 &TexturedElement::SetBackgroundColor);
-  scene_->AddUiElement(kUrlBarOriginRegion, std::move(origin_content));
+  scene_->AddUiElement(kUrlBarOriginLayout, std::move(url_text));
+
+  auto right_margin = Create<Rect>(kNone, kPhaseNone);
+  right_margin->SetType(kTypeSpacer);
+  right_margin->SetSize(kUrlBarOriginRightMarginDMM, 0);
+  scene_->AddUiElement(kUrlBarOriginLayout, std::move(right_margin));
 
   auto hint_text =
       Create<Text>(kUrlBarHintText, kPhaseForeground, kUrlBarFontHeightDMM);
-  hint_text->set_hit_testable(true);
+  hint_text->set_contributes_to_parent_bounds(false);
   hint_text->set_x_anchoring(LEFT);
   hint_text->set_x_centering(LEFT);
-  hint_text->SetSize(kUrlBarOriginContentWidthDMM, kUrlBarHeightDMM);
+  hint_text->SetSize(kUrlBarUrlWidthDMM, kUrlBarHeightDMM);
   hint_text->SetTranslate(kUrlBarOriginContentOffsetDMM, 0, 0);
   hint_text->SetLayoutMode(TextLayoutMode::kSingleLineFixedWidth);
   hint_text->SetAlignment(UiTexture::kTextAlignmentLeft);
   hint_text->SetText(l10n_util::GetStringUTF16(IDS_SEARCH_OR_TYPE_WEB_ADDRESS));
   VR_BIND_VISIBILITY(hint_text, !model->toolbar_state.should_display_url);
-  VR_BIND_COLOR(model_, hint_text.get(), &ColorScheme::url_bar_hint,
+  VR_BIND_COLOR(model_, hint_text.get(), &ColorScheme::url_bar_hint_text,
                 &Text::SetColor);
-  EventHandlers event_handlers;
-  event_handlers.button_up = url_click_callback;
-  hint_text->set_event_handlers(event_handlers);
   scene_->AddUiElement(kUrlBarOriginRegion, std::move(hint_text));
 
   separator = Create<Rect>(kUrlBarSeparator, kPhaseForeground);
@@ -1907,29 +2058,22 @@
                 &Rect::SetColor);
   scene_->AddUiElement(kUrlBarLayout, std::move(separator));
 
-  auto overflow_button = Create<Button>(
+  auto overflow_button = Create<VectorIconButton>(
       kUrlBarOverflowButton, kPhaseForeground,
       base::BindRepeating(
           [](Model* model) { model->overflow_menu_enabled = true; },
-          base::Unretained(model_)));
+          base::Unretained(model_)),
+      kMoreVertIcon, audio_delegate_);
   overflow_button->SetSize(kUrlBarEndButtonWidthDMM, kUrlBarHeightDMM);
   overflow_button->SetCornerRadii(
       {0, kUrlBarHeightDMM / 2, 0, kUrlBarHeightDMM / 2});
-  overflow_button->set_hover_offset(0.0f);
-  overflow_button->SetSounds(CreateButtonSounds(), audio_delegate_);
+  overflow_button->set_hover_offset(0);
+  overflow_button->SetIconScaleFactor(kUrlBarButtonIconSizeDMM /
+                                      kUrlBarHeightDMM);
+  overflow_button->SetIconTranslation(-kUrlBarEndButtonIconOffsetDMM, 0);
   VR_BIND_BUTTON_COLORS(model_, overflow_button.get(),
-                        &ColorScheme::back_button, &Button::SetButtonColors);
+                        &ColorScheme::url_bar_button, &Button::SetButtonColors);
   scene_->AddUiElement(kUrlBarLayout, std::move(overflow_button));
-
-  auto overflow_icon =
-      Create<VectorIcon>(kUrlBarOverflowButtonIcon, kPhaseForeground, 128);
-  overflow_icon->SetIcon(kMoreVertIcon);
-  overflow_icon->SetSize(kUrlBarButtonIconSizeDMM, kUrlBarButtonIconSizeDMM);
-  overflow_icon->SetTranslate(-kUrlBarEndButtonIconOffsetDMM, 0, 0);
-  overflow_icon->AddBinding(VR_BIND_FUNC(
-      SkColor, Model, model_, model->color_scheme().element_foreground,
-      VectorIcon, overflow_icon.get(), SetColor));
-  scene_->AddUiElement(kUrlBarOverflowButton, std::move(overflow_icon));
 }
 
 void UiSceneCreator::CreateOverflowMenu() {
@@ -1969,13 +2113,13 @@
           {kOverflowMenuReloadButton, RIGHT, vector_icons::kReloadIcon},
       };
   for (auto& item : menu_buttons) {
-    auto button = Create<DiscButton>(std::get<0>(item), kPhaseForeground,
-                                     base::DoNothing(), std::get<2>(item),
-                                     audio_delegate_);
+    auto button = Create<VectorIconButton>(std::get<0>(item), kPhaseForeground,
+                                           base::DoNothing(), std::get<2>(item),
+                                           audio_delegate_);
     button->SetType(kTypeOverflowMenuButton);
     button->SetDrawPhase(kPhaseForeground);
     button->SetSize(kUrlBarButtonSizeDMM, kUrlBarButtonSizeDMM);
-    button->set_icon_scale_factor(kUrlBarButtonIconScaleFactor);
+    button->SetIconScaleFactor(kUrlBarButtonIconScaleFactor);
     button->set_hover_offset(kOmniboxTextFieldIconButtonHoverOffsetDMM);
     button->set_corner_radius(kUrlBarItemCornerRadiusDMM);
     button->set_requires_layout(false);
@@ -1987,7 +2131,7 @@
     button->SetTranslate(
         kOverflowButtonXOffset * (std::get<1>(item) == RIGHT ? -1 : 1),
         kOverflowMenuYPadding, 0);
-    VR_BIND_BUTTON_COLORS(model_, button.get(), &ColorScheme::back_button,
+    VR_BIND_BUTTON_COLORS(model_, button.get(), &ColorScheme::url_bar_button,
                           &Button::SetButtonColors);
 
     switch (std::get<0>(item)) {
@@ -2053,8 +2197,8 @@
     spacer->set_resizable_by_layout(true);
     layout->AddChild(std::move(spacer));
 
-    auto background =
-        Create<Button>(std::get<0>(item), kPhaseForeground, base::DoNothing());
+    auto background = Create<Button>(std::get<0>(item), kPhaseForeground,
+                                     base::DoNothing(), audio_delegate_);
     background->set_hit_testable(true);
     background->set_bounds_contain_children(true);
     background->set_hover_offset(0);
@@ -2103,7 +2247,7 @@
       kDownloadedSnackbar, model_, kFileDownloadDoneIcon,
       l10n_util::GetStringUTF16(IDS_VR_COMPONENT_UPDATE_READY),
       base::i18n::ToUpper(l10n_util::GetStringUTF16(IDS_VR_COMPONENT_APPLY)),
-      base::DoNothing());
+      base::DoNothing(), audio_delegate_);
   snackbar->SetVisible(false);
   snackbar->SetRotate(1, 0, 0, kSnackbarMoveInAngle);
   snackbar->SetTransitionedProperties({OPACITY, TRANSFORM});
@@ -2317,18 +2461,17 @@
           },
           base::Unretained(omnibox_text_field.get()))));
 
-  auto mic_button = Create<DiscButton>(
+  auto mic_button = Create<VectorIconButton>(
       kOmniboxVoiceSearchButton, kPhaseForeground,
       base::BindRepeating(
           [](UiBrowserInterface* b, Ui* ui) { b->SetVoiceSearchActive(true); },
           base::Unretained(browser_), base::Unretained(ui_)),
       vector_icons::kMicIcon, audio_delegate_);
-  mic_button->set_icon_scale_factor(kVoiceSearchIconScaleFactor);
+  mic_button->SetIconScaleFactor(kVoiceSearchIconScaleFactor);
   mic_button->SetSize(kOmniboxTextFieldIconButtonSizeDMM,
                       kOmniboxTextFieldIconButtonSizeDMM);
   mic_button->set_hover_offset(kOmniboxTextFieldIconButtonHoverOffsetDMM);
   mic_button->set_corner_radius(kUrlBarItemCornerRadiusDMM);
-  mic_button->SetSounds(CreateButtonSounds(), audio_delegate_);
 
   VR_BIND_VISIBILITY(mic_button,
                      model->speech.has_or_can_request_audio_permission &&
@@ -2614,42 +2757,95 @@
                                      url_toast.get(), SetToolbarState));
   scene_->AddUiElement(kWebVrUrlToastTransientParent, std::move(url_toast));
 
-  // Create "Press app button to exit" toast.
-  parent =
-      CreateTransientParent(kExclusiveScreenToastViewportAwareTransientParent,
-                            kToastTimeoutSeconds, false);
-  // When we first get a web vr frame, we switch states to
-  // kWebVrNoTimeoutPending, when that happens, we want to SetVisible(true) to
-  // kick the visibility of this element.
-  VR_BIND_VISIBILITY(parent, model->web_vr.has_produced_frames() &&
-                                 model->web_vr.show_exit_toast);
-  scene_->AddUiElement(kWebVrViewportAwareRoot, std::move(parent));
+  // Create transient WebVR elements.
+  auto indicators =
+      Create<LinearLayout>(kNone, kPhaseNone, LinearLayout::kDown);
+  indicators->SetTranslate(0, 0, kWebVrPermissionDepth);
+  indicators->set_margin(kWebVrPermissionOuterMargin);
+
+  IndicatorSpec app_button_spec = {kNone,
+                                   kExclusiveScreenToastViewportAware,
+                                   kRemoveCircleOutlineIcon,
+                                   IDS_PRESS_APP_TO_EXIT,
+                                   0,
+                                   nullptr,
+                                   nullptr};
+  auto app_button_to_exit = CreateWebVrIndicator(model_, app_button_spec);
+  VR_BIND_VISIBILITY(app_button_to_exit, model->web_vr.show_exit_toast);
+  indicators->AddChild(std::move(app_button_to_exit));
+
+  // TODO(crbug.com/824472): add an indicator for the transient URL toast.
+
+  auto specs = GetIndicatorSpecs();
+  for (const auto& spec : specs) {
+    indicators->AddChild(CreateWebVrIndicator(model_, spec));
+  }
+
+  parent = CreateTransientParent(kNone, kToastTimeoutSeconds, true);
+  parent->AddBinding(std::make_unique<Binding<bool>>(
+      VR_BIND_LAMBDA(
+          [](Model* model, UiElement* splash_screen) {
+            return model->web_vr.has_produced_frames() &&
+                   model->web_vr.has_received_permissions &&
+                   splash_screen->GetTargetOpacity() == 0.f;
+          },
+          base::Unretained(model_),
+          base::Unretained(
+              scene_->GetUiElementByName(kSplashScreenTransientParent))),
+      VR_BIND_LAMBDA(
+          [](UiElement* e, Model* model, UiScene* scene, const bool& value) {
+            SetVisibleInLayout(e, value);
+            auto specs = GetIndicatorSpecs();
+            for (const auto& spec : specs) {
+              SetVisibleInLayout(
+                  scene->GetUiElementByName(spec.webvr_name),
+                  model->capturing_state.*spec.signal ||
+                      model->capturing_state.*spec.potential_signal);
+            }
+
+            e->RemoveKeyframeModels(TRANSFORM);
+            e->SetTranslate(0, kWebVrPermissionOffsetStart, 0);
+
+            // Build up a keyframe model for the initial transition.
+            std::unique_ptr<cc::KeyframedTransformAnimationCurve> curve(
+                cc::KeyframedTransformAnimationCurve::Create());
+
+            cc::TransformOperations value_1;
+            value_1.AppendTranslate(0, kWebVrPermissionOffsetStart, 0);
+            curve->AddKeyframe(cc::TransformKeyframe::Create(
+                base::TimeDelta(), value_1,
+                cc::CubicBezierTimingFunction::CreatePreset(
+                    cc::CubicBezierTimingFunction::EaseType::EASE)));
+
+            cc::TransformOperations value_2;
+            value_2.AppendTranslate(0, kWebVrPermissionOffsetOvershoot, 0);
+            curve->AddKeyframe(cc::TransformKeyframe::Create(
+                base::TimeDelta::FromMilliseconds(kWebVrPermissionOffsetMs),
+                value_2,
+                cc::CubicBezierTimingFunction::CreatePreset(
+                    cc::CubicBezierTimingFunction::EaseType::EASE)));
+
+            cc::TransformOperations value_3;
+            value_3.AppendTranslate(0, kWebVrPermissionOffsetFinal, 0);
+            curve->AddKeyframe(cc::TransformKeyframe::Create(
+                base::TimeDelta::FromMilliseconds(
+                    kWebVrPermissionAnimationDurationMs),
+                value_3,
+                cc::CubicBezierTimingFunction::CreatePreset(
+                    cc::CubicBezierTimingFunction::EaseType::EASE)));
+
+            e->AddKeyframeModel(cc::KeyframeModel::Create(
+                std::move(curve), Animation::GetNextKeyframeModelId(),
+                Animation::GetNextGroupId(), TRANSFORM));
+          },
+          base::Unretained(parent.get()), base::Unretained(model_),
+          base::Unretained(scene_))));
 
   auto scaler = std::make_unique<ScaledDepthAdjuster>(kWebVrToastDistance);
+  scaler->AddChild(std::move(indicators));
+  parent->AddChild(std::move(scaler));
 
-  auto exit_toast = std::make_unique<Toast>();
-  exit_toast->SetName(kExclusiveScreenToastViewportAware);
-  exit_toast->SetDrawPhase(kPhaseOverlayForeground);
-  exit_toast->SetTranslate(0, sin(kWebVrAngleRadians),
-                           1.0 - cos(kWebVrAngleRadians));
-  exit_toast->SetRotate(1, 0, 0, kWebVrAngleRadians);
-  exit_toast->set_padding(kExclusiveScreenToastXPaddingDMM,
-                          kExclusiveScreenToastYPaddingDMM);
-  exit_toast->set_corner_radius(kExclusiveScreenToastCornerRadiusDMM);
-  exit_toast->AddText(l10n_util::GetStringUTF16(IDS_PRESS_APP_TO_EXIT),
-                      kExclusiveScreenToastTextFontHeightDMM,
-                      TextLayoutMode::kSingleLineFixedHeight);
-
-  VR_BIND_COLOR(model_, exit_toast.get(),
-                &ColorScheme::exclusive_screen_toast_background,
-                &Toast::SetBackgroundColor);
-  VR_BIND_COLOR(model_, exit_toast.get(),
-                &ColorScheme::exclusive_screen_toast_foreground,
-                &Toast::SetForegroundColor);
-
-  scaler->AddChild(std::move(exit_toast));
-  scene_->AddUiElement(kExclusiveScreenToastViewportAwareTransientParent,
-                       std::move(scaler));
+  scene_->AddUiElement(kWebVrViewportAwareRoot, std::move(parent));
 }
 
 void UiSceneCreator::CreateFullscreenToast() {
@@ -2657,19 +2853,18 @@
                                       kToastTimeoutSeconds, false);
   parent->set_contributes_to_parent_bounds(false);
   parent->set_y_anchoring(TOP);
+  parent->SetScale(kContentDistance, kContentDistance, 1.0f);
+  parent->SetTranslate(0, kIndicatorVerticalOffset, kIndicatorDistanceOffset);
   VR_BIND_VISIBILITY(parent, model->fullscreen_enabled());
-  scene_->AddUiElement(k2dBrowsingForeground, std::move(parent));
-
-  auto scaler = std::make_unique<ScaledDepthAdjuster>(kFullscreenDistance);
+  scene_->AddUiElement(k2dBrowsingContentGroup, std::move(parent));
 
   auto element = std::make_unique<Toast>();
   element->SetName(kExclusiveScreenToast);
   element->SetDrawPhase(kPhaseForeground);
-  element->SetTranslate(0, kFullScreenToastOffsetDMM, 0);
   element->set_padding(kExclusiveScreenToastXPaddingDMM,
                        kExclusiveScreenToastYPaddingDMM);
   element->set_corner_radius(kExclusiveScreenToastCornerRadiusDMM);
-  element->AddText(l10n_util::GetStringUTF16(IDS_PRESS_APP_TO_EXIT),
+  element->AddText(l10n_util::GetStringUTF16(IDS_PRESS_APP_TO_EXIT_FULLSCREEN),
                    kExclusiveScreenToastTextFontHeightDMM,
                    TextLayoutMode::kSingleLineFixedHeight);
 
@@ -2680,8 +2875,8 @@
                 &ColorScheme::exclusive_screen_toast_foreground,
                 &Toast::SetForegroundColor);
 
-  scaler->AddChild(std::move(element));
-  scene_->AddUiElement(kExclusiveScreenToastTransientParent, std::move(scaler));
+  scene_->AddUiElement(kExclusiveScreenToastTransientParent,
+                       std::move(element));
 }
 
 }  // namespace vr
diff --git a/chrome/browser/vr/ui_unittest.cc b/chrome/browser/vr/ui_unittest.cc
index 6ab4fa3..24e0811 100644
--- a/chrome/browser/vr/ui_unittest.cc
+++ b/chrome/browser/vr/ui_unittest.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/vr/elements/content_element.h"
 #include "chrome/browser/vr/elements/disc_button.h"
 #include "chrome/browser/vr/elements/exit_prompt.h"
+#include "chrome/browser/vr/elements/indicator_spec.h"
 #include "chrome/browser/vr/elements/rect.h"
 #include "chrome/browser/vr/elements/repositioner.h"
 #include "chrome/browser/vr/elements/ui_element.h"
@@ -54,20 +55,20 @@
     kContentQuad,
     kContentQuadShadow,
     kBackplane,
-    kUrlBarBackplane,
+    kUrlBar,
     kUrlBarBackButton,
-    kUrlBarBackButtonIcon,
     kUrlBarSeparator,
     kUrlBarOriginRegion,
-    kUrlBarOriginContent,
+    kUrlBarSecurityButton,
+    kUrlBarUrlText,
     kUrlBarOverflowButton,
-    kUrlBarOverflowButtonIcon,
     kController,
     kReticle,
     kLaser,
     kControllerTouchpadButton,
     kControllerAppButton,
     kControllerHomeButton,
+    kIndicatorBackplane,
 };
 const std::set<UiElementName> kElementsVisibleWithExitPrompt = {
     kBackgroundFront,
@@ -134,6 +135,7 @@
 
   ui_->SetWebVrMode(true, true);
   ui_->OnWebVrFrameAvailable();
+  ui_->SetCapturingState(CapturingStateModel());
   EXPECT_FALSE(IsVisible(kExclusiveScreenToast));
   EXPECT_TRUE(IsVisible(kExclusiveScreenToastViewportAware));
 
@@ -168,6 +170,7 @@
 
   ui_->SetWebVrMode(true, true);
   ui_->OnWebVrFrameAvailable();
+  ui_->SetCapturingState(CapturingStateModel());
   EXPECT_TRUE(IsVisible(kExclusiveScreenToastViewportAware));
   EXPECT_TRUE(RunFor(base::TimeDelta::FromSecondsD(kToastTimeoutSeconds +
                                                    kSmallDelaySeconds)));
@@ -177,6 +180,33 @@
   EXPECT_FALSE(IsVisible(kExclusiveScreenToastViewportAware));
 }
 
+TEST_F(UiTest, CaptureToasts) {
+  CreateScene(kNotInCct, kNotInWebVr);
+  EXPECT_FALSE(IsVisible(kExclusiveScreenToast));
+
+  for (auto& spec : GetIndicatorSpecs()) {
+    for (int i = 0; i < 2; ++i) {
+      ui_->SetWebVrMode(true, true);
+      ui_->OnWebVrFrameAvailable();
+
+      CapturingStateModel state;
+      state.*spec.signal = i == 0;
+      state.*spec.potential_signal = true;
+
+      ui_->SetCapturingState(state);
+      EXPECT_TRUE(IsVisible(kExclusiveScreenToastViewportAware));
+      EXPECT_TRUE(IsVisible(spec.webvr_name));
+      EXPECT_TRUE(RunFor(base::TimeDelta::FromSecondsD(kToastTimeoutSeconds +
+                                                       kSmallDelaySeconds)));
+      EXPECT_FALSE(IsVisible(kExclusiveScreenToastViewportAware));
+
+      ui_->SetWebVrMode(false, false);
+      EXPECT_FALSE(IsVisible(kExclusiveScreenToastViewportAware));
+      EXPECT_FALSE(IsVisible(spec.webvr_name));
+    }
+  }
+}
+
 TEST_F(UiTest, CloseButtonVisibleInCctFullscreen) {
   // Button should be visible in cct.
   CreateScene(kInCct, kNotInWebVr);
@@ -535,10 +565,11 @@
   VerifyOnlyElementsVisible("Initial", kElementsVisibleInBrowsing);
 
   // Clicking the omnibox should show the update prompt.
-  auto* omnibox = scene_->GetUiElementByName(kUrlBarOriginContent);
+  auto* omnibox = scene_->GetUiElementByName(kUrlBarOriginRegion);
   EXPECT_CALL(*browser_,
               OnUnsupportedMode(UiUnsupportedMode::kNeedsKeyboardUpdate));
-  omnibox->OnButtonUp({0, 10});
+  omnibox->OnHoverEnter({0.5, 0.5});
+  omnibox->OnButtonUp({0.5, 0.5});
   ui_->ShowExitVrPrompt(UiUnsupportedMode::kNeedsKeyboardUpdate);
   OnBeginFrame();
   EXPECT_EQ(model_->active_modal_prompt_type,
@@ -1248,4 +1279,61 @@
   }
 }
 
+TEST_F(UiTest, DisableResizeWhenEditing) {
+  CreateScene(kNotInCct, kNotInWebVr);
+  UiElement* hit_plane = scene_->GetUiElementByName(kContentFrameHitPlane);
+  EXPECT_TRUE(hit_plane->hit_testable());
+  model_->editing_web_input = true;
+  OnBeginFrame();
+  EXPECT_FALSE(hit_plane->hit_testable());
+  model_->editing_web_input = false;
+  OnBeginFrame();
+  EXPECT_TRUE(hit_plane->hit_testable());
+
+  model_->editing_input = true;
+  OnBeginFrame();
+  EXPECT_FALSE(hit_plane->hit_testable());
+  model_->editing_input = false;
+  OnBeginFrame();
+  EXPECT_TRUE(hit_plane->hit_testable());
+
+  model_->native_ui.hosted_ui_enabled = true;
+  OnBeginFrame();
+  EXPECT_FALSE(hit_plane->hit_testable());
+  model_->native_ui.hosted_ui_enabled = false;
+  OnBeginFrame();
+  EXPECT_TRUE(hit_plane->hit_testable());
+
+  model_->active_modal_prompt_type =
+      kModalPromptTypeExitVRForVoiceSearchRecordAudioOsPermission;
+  OnBeginFrame();
+  EXPECT_FALSE(hit_plane->hit_testable());
+  model_->active_modal_prompt_type = kModalPromptTypeNone;
+  OnBeginFrame();
+  EXPECT_TRUE(hit_plane->hit_testable());
+}
+
+TEST_F(UiTest, RepositionHostedUi) {
+  CreateScene(kNotInCct, kNotInWebVr);
+
+  Repositioner* repositioner = static_cast<Repositioner*>(
+      scene_->GetUiElementByName(k2dBrowsingRepositioner));
+  UiElement* hosted_ui = scene_->GetUiElementByName(kHostedUi);
+
+  OnBeginFrame();
+  gfx::Transform original = hosted_ui->world_space_transform();
+
+  repositioner->set_laser_direction(kForwardVector);
+  repositioner->SetEnabled(true);
+  repositioner->set_laser_direction({0, 1, 0});
+  OnBeginFrame();
+
+  EXPECT_NE(original, hosted_ui->world_space_transform());
+  repositioner->SetEnabled(false);
+  model_->controller.recentered = true;
+
+  OnBeginFrame();
+  EXPECT_EQ(original, hosted_ui->world_space_transform());
+}
+
 }  // namespace vr
diff --git a/chrome/browser/vr/vector_icons/BUILD.gn b/chrome/browser/vr/vector_icons/BUILD.gn
index f4983820..7383f85 100644
--- a/chrome/browser/vr/vector_icons/BUILD.gn
+++ b/chrome/browser/vr/vector_icons/BUILD.gn
@@ -12,6 +12,8 @@
     "daydream_controller_app_button.icon",
     "file_download_done.icon",
     "more_vert.icon",
+    "my_location.icon",
+    "remove_circle_outline.icon",
     "reposition.icon",
     "sad_tab.icon",
   ]
diff --git a/chrome/browser/vr/vector_icons/my_location.icon b/chrome/browser/vr/vector_icons/my_location.icon
new file mode 100644
index 0000000..f508f5b
--- /dev/null
+++ b/chrome/browser/vr/vector_icons/my_location.icon
@@ -0,0 +1,34 @@
+// Copyright 2018 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.
+
+MOVE_TO, 24, 16,
+R_CUBIC_TO, -4.42f, 0, -8, 3.58f, -8, 8,
+R_CUBIC_TO, 0, 4.42f, 3.58f, 8, 8, 8,
+R_CUBIC_TO, 4.42f, 0, 8, -3.58f, 8, -8,
+R_CUBIC_TO, 0, -4.42f, -3.58f, -8, -8, -8,
+CLOSE,
+R_MOVE_TO, 17.88f, 6,
+CUBIC_TO, 40.96f, 13.66f, 34.34f, 7.04f, 26, 6.12f,
+V_LINE_TO, 2,
+R_H_LINE_TO, -4,
+R_V_LINE_TO, 4.12f,
+CUBIC_TO, 13.66f, 7.04f, 7.04f, 13.66f, 6.12f, 22,
+H_LINE_TO, 2,
+R_V_LINE_TO, 4,
+R_H_LINE_TO, 4.12f,
+R_CUBIC_TO, 0.92f, 8.34f, 7.54f, 14.96f, 15.88f, 15.88f,
+V_LINE_TO, 46,
+R_H_LINE_TO, 4,
+R_V_LINE_TO, -4.12f,
+R_CUBIC_TO, 8.34f, -0.92f, 14.96f, -7.54f, 15.88f, -15.88f,
+H_LINE_TO, 46,
+R_V_LINE_TO, -4,
+R_H_LINE_TO, -4.12f,
+CLOSE,
+MOVE_TO, 24, 38,
+R_CUBIC_TO, -7.73f, 0, -14, -6.27f, -14, -14,
+R_CUBIC_TO, 0, -7.73f, 6.27f, -14, 14, -14,
+R_CUBIC_TO, 7.73f, 0, 14, 6.27f, 14, 14,
+R_CUBIC_TO, 0, 7.73f, -6.27f, 14, -14, 14,
+CLOSE
diff --git a/chrome/browser/vr/vector_icons/remove_circle_outline.icon b/chrome/browser/vr/vector_icons/remove_circle_outline.icon
new file mode 100644
index 0000000..a25aae05
--- /dev/null
+++ b/chrome/browser/vr/vector_icons/remove_circle_outline.icon
@@ -0,0 +1,23 @@
+// Copyright 2018 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.
+
+CANVAS_DIMENSIONS, 24,
+MOVE_TO, 7, 11,
+R_V_LINE_TO, 2,
+R_H_LINE_TO, 10,
+R_V_LINE_TO, -2,
+H_LINE_TO, 7,
+CLOSE,
+R_MOVE_TO, 5, -9,
+CUBIC_TO, 6.48f, 2, 2, 6.48f, 2, 12,
+R_CUBIC_TO, 0, 5.52f, 4.48f, 10, 10, 10,
+R_CUBIC_TO, 5.52f, 0, 10, -4.48f, 10, -10,
+CUBIC_TO_SHORTHAND, 17.52f, 2, 12, 2,
+CLOSE,
+R_MOVE_TO, 0, 18,
+R_CUBIC_TO, -4.41f, 0, -8, -3.59f, -8, -8,
+R_CUBIC_TO, 0, -4.41f, 3.59f, -8, 8, -8,
+R_CUBIC_TO, 4.41f, 0, 8, 3.59f, 8, 8,
+R_CUBIC_TO, 0, 4.41f, -3.59f, 8, -8, 8,
+CLOSE
diff --git a/chrome/browser/win/settings_app_monitor.cc b/chrome/browser/win/settings_app_monitor.cc
index 8eef3ec..b474d94 100644
--- a/chrome/browser/win/settings_app_monitor.cc
+++ b/chrome/browser/win/settings_app_monitor.cc
@@ -14,6 +14,7 @@
 #include "base/sequenced_task_runner.h"
 #include "base/strings/pattern.h"
 #include "base/strings/string16.h"
+#include "base/synchronization/lock.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/win/scoped_variant.h"
 #include "chrome/browser/win/automation_controller.h"
@@ -128,8 +129,10 @@
   // Only used to post callbacks to |monitor_runner_|;
   const base::WeakPtr<SettingsAppMonitor> monitor_;
 
+  // Protect against concurrent accesses to |last_focused_element_|.
+  mutable base::Lock last_focused_element_lock_;
+
   // State to suppress duplicate "focus changed" events.
-  // Only accessed by OnFocusChangedEvent().
   mutable ElementType last_focused_element_;
 
   DISALLOW_COPY_AND_ASSIGN(AutomationControllerDelegate);
@@ -195,11 +198,14 @@
 void SettingsAppMonitor::AutomationControllerDelegate::OnFocusChangedEvent(
     IUIAutomation* automation,
     IUIAutomationElement* sender) const {
-  // Duplicate focus changed events are suppressed.
   ElementType element_type = DetectElementType(automation, sender);
-  if (last_focused_element_ == element_type)
-    return;
-  last_focused_element_ = element_type;
+  {
+    // Duplicate focus changed events are suppressed.
+    base::AutoLock auto_lock(last_focused_element_lock_);
+    if (last_focused_element_ == element_type)
+      return;
+    last_focused_element_ = element_type;
+  }
 
   if (element_type == ElementType::DEFAULT_BROWSER) {
     monitor_runner_->PostTask(
diff --git a/chrome/chrome_paks.gni b/chrome/chrome_paks.gni
index f8defd39..b3ca9a3c 100644
--- a/chrome/chrome_paks.gni
+++ b/chrome/chrome_paks.gni
@@ -151,11 +151,13 @@
     }
     if (is_chromeos) {
       sources += [
+        "$root_gen_dir/chrome/multidevice_setup_resources.pak",
         "$root_gen_dir/chromeos/chromeos_resources.pak",
         "$root_gen_dir/components/chrome_apps/chrome_apps_resources.pak",
         "$root_gen_dir/ui/file_manager/file_manager_resources.pak",
       ]
       deps += [
+        "//chrome/browser/resources/chromeos:multidevice_setup_resources",
         "//chromeos/resources",
         "//components/chrome_apps:resources",
         "//ui/file_manager:resources",
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn
index dc302a1..3476fa7c 100644
--- a/chrome/common/BUILD.gn
+++ b/chrome/common/BUILD.gn
@@ -264,7 +264,7 @@
     "//media",
     "//mojo/edk",
     "//mojo/public/cpp/bindings",
-    "//pdf:features",
+    "//pdf:buildflags",
     "//ppapi/features",
     "//printing/features",
     "//services/service_manager/sandbox",
@@ -572,7 +572,7 @@
     "//components/nacl/common:switches",
     "//components/offline_pages/buildflags",
     "//device/vr/buildflags",
-    "//media:media_features",
+    "//media:media_buildflags",
     "//media/cdm:cdm_paths",  # Needed by chrome_paths.cc.
     "//ppapi/features",
     "//third_party/widevine/cdm:headers",
diff --git a/chrome/common/chrome_content_client.cc b/chrome/common/chrome_content_client.cc
index 6f7b8a3..7270cb9 100644
--- a/chrome/common/chrome_content_client.cc
+++ b/chrome/common/chrome_content_client.cc
@@ -50,9 +50,9 @@
 #include "gpu/config/gpu_util.h"
 #include "media/base/media_switches.h"
 #include "media/base/video_codecs.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "net/http/http_util.h"
-#include "pdf/features.h"
+#include "pdf/buildflags.h"
 #include "ppapi/features/features.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/layout.h"
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index 2faf3c1..444fefae 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -244,18 +244,6 @@
 const base::Feature kExperimentalKeyboardLockUI{
     "ExperimentalKeyboardLockUI", base::FEATURE_DISABLED_BY_DEFAULT};
 
-#if BUILDFLAG(ENABLE_VR) || defined(OS_ANDROID)
-// Controls whether browsing in VR headsets is enabled.
-const base::Feature kVrBrowsing {
-  "VrBrowsing",
-#if defined(OS_ANDROID)
-      base::FEATURE_ENABLED_BY_DEFAULT
-#else
-      base::FEATURE_DISABLED_BY_DEFAULT
-#endif
-};
-#endif  // BUILDFLAG(ENABLE_VR) || defined(OS_ANDROID)
-
 #if BUILDFLAG(ENABLE_VR)
 // Enables the virtual keyboard for Chrome VR.
 const base::Feature kVrBrowserKeyboard{"VrBrowserKeyboard",
@@ -531,6 +519,13 @@
                                               base::FEATURE_ENABLED_BY_DEFAULT};
 #endif  // defined(OS_ANDROID)
 
+// Alternative to switches::kSitePerProcess, for turning on full site isolation.
+// Launch bug: https://crbug.com/739418.  This is a //chrome-layer feature to
+// avoid turning on site-per-process by default for *all* //content embedders
+// (e.g. this approach lets ChromeCast avoid site-per-process mode).
+const base::Feature kSitePerProcess{"site-per-process",
+                                    base::FEATURE_DISABLED_BY_DEFAULT};
+
 // A new user experience for transitioning into fullscreen and mouse pointer
 // lock states.
 const base::Feature kSimplifiedFullscreenUI{"ViewsSimplifiedFullscreenUI",
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h
index 561702fb..52725f64 100644
--- a/chrome/common/chrome_features.h
+++ b/chrome/common/chrome_features.h
@@ -284,6 +284,8 @@
 extern const base::Feature kSiteNotificationChannels;
 #endif
 
+extern const base::Feature kSitePerProcess;
+
 #if defined(OS_CHROMEOS)
 extern const base::Feature kNativeSmb;
 #endif
diff --git a/chrome/common/chrome_paths.cc b/chrome/common/chrome_paths.cc
index e5c64bd..1ca39d0 100644
--- a/chrome/common/chrome_paths.cc
+++ b/chrome/common/chrome_paths.cc
@@ -18,7 +18,7 @@
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths_internal.h"
 #include "media/cdm/cdm_paths.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 #if defined(OS_ANDROID)
 #include "base/android/path_utils.h"
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 400cd6fe..d3d3dd9d 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -392,10 +392,6 @@
 // is triggered.
 const char kForceDesktopIOSPromotion[] = "force-desktop-ios-promotion";
 
-// Forces Network Quality Estimator (NQE) to return a specific effective
-// connection type.
-const char kForceEffectiveConnectionType[] = "force-effective-connection-type";
-
 // Forces metrics reporting to be enabled.
 const char kForceEnableMetricsReporting[] = "force-enable-metrics-reporting";
 
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 0d2b79be..1b92d681 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -123,7 +123,6 @@
 extern const char kForceAndroidAppMode[];
 extern const char kForceAppMode[];
 extern const char kForceDesktopIOSPromotion[];
-extern const char kForceEffectiveConnectionType[];
 extern const char kForceEnableMetricsReporting[];
 extern const char kForceFirstRun[];
 extern const char kForceFirstRunDialog[];
diff --git a/chrome/common/common_message_generator.h b/chrome/common/common_message_generator.h
index 1f6ca74..19e4f70 100644
--- a/chrome/common/common_message_generator.h
+++ b/chrome/common/common_message_generator.h
@@ -29,7 +29,7 @@
 #include "content/public/common/common_param_traits.h"
 #include "content/public/common/common_param_traits_macros.h"
 #include "extensions/buildflags/buildflags.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "printing/features/features.h"
 
 #if BUILDFLAG(ENABLE_EXTENSIONS)
diff --git a/chrome/common/extensions/api/windows.json b/chrome/common/extensions/api/windows.json
index 7e1bf88..89603fc 100644
--- a/chrome/common/extensions/api/windows.json
+++ b/chrome/common/extensions/api/windows.json
@@ -57,6 +57,7 @@
           "description": "<i>Deprecated since Chrome M59.</i> Docked windows are no longer supported. This state will be converted to \"normal\"."
         }, {
           "name": "locked-fullscreen",
+          "nodoc": true,
           "description": "Locked fullscreen window state. This fullscreen state cannot be exited by user action. It is available only to whitelisted extensions on Chrome OS."
         }]
       },
diff --git a/chrome/common/extensions/chrome_extension_messages.h b/chrome/common/extensions/chrome_extension_messages.h
index 9ac7c6b9..e2e0fb8 100644
--- a/chrome/common/extensions/chrome_extension_messages.h
+++ b/chrome/common/extensions/chrome_extension_messages.h
@@ -111,9 +111,10 @@
 
 // Forward an accessibility message to an extension process where an
 // extension is using the automation API to listen for accessibility events.
-IPC_MESSAGE_CONTROL2(ExtensionMsg_AccessibilityEvent,
-                     ExtensionMsg_AccessibilityEventParams,
-                     bool /* is_active_profile */)
+IPC_MESSAGE_CONTROL2(
+    ExtensionMsg_AccessibilityEvents,
+    std::vector<ExtensionMsg_AccessibilityEventParams> /* events */,
+    bool /* is_active_profile */)
 
 // Forward an accessibility location change message to an extension process
 // where an extension is using the automation API to listen for
diff --git a/chrome/common/extensions/docs/static/images/packaging/packaging_devmode.png b/chrome/common/extensions/docs/static/images/packaging/packaging_devmode.png
index 85c53a3..f19c541 100644
--- a/chrome/common/extensions/docs/static/images/packaging/packaging_devmode.png
+++ b/chrome/common/extensions/docs/static/images/packaging/packaging_devmode.png
Binary files differ
diff --git a/chrome/common/extensions/docs/static/images/packaging/packaging_files.png b/chrome/common/extensions/docs/static/images/packaging/packaging_files.png
index a13f3cd..0e5b741 100644
--- a/chrome/common/extensions/docs/static/images/packaging/packaging_files.png
+++ b/chrome/common/extensions/docs/static/images/packaging/packaging_files.png
Binary files differ
diff --git a/chrome/common/extensions/docs/static/images/packaging/packaging_root.png b/chrome/common/extensions/docs/static/images/packaging/packaging_root.png
index 837b565e..f9efa14 100644
--- a/chrome/common/extensions/docs/static/images/packaging/packaging_root.png
+++ b/chrome/common/extensions/docs/static/images/packaging/packaging_root.png
Binary files differ
diff --git a/chrome/common/extensions/docs/static/images/packaging/packaging_updated.png b/chrome/common/extensions/docs/static/images/packaging/packaging_updated.png
index 6e04153..0e84cfb 100644
--- a/chrome/common/extensions/docs/static/images/packaging/packaging_updated.png
+++ b/chrome/common/extensions/docs/static/images/packaging/packaging_updated.png
Binary files differ
diff --git a/chrome/common/extensions/docs/static/images/packaging/packaging_updating.png b/chrome/common/extensions/docs/static/images/packaging/packaging_updating.png
index 96b00723..ae2a4931e 100644
--- a/chrome/common/extensions/docs/static/images/packaging/packaging_updating.png
+++ b/chrome/common/extensions/docs/static/images/packaging/packaging_updating.png
Binary files differ
diff --git a/chrome/common/extensions/docs/templates/articles/linux_hosting.html b/chrome/common/extensions/docs/templates/articles/linux_hosting.html
index 96302e9..9569e48 100644
--- a/chrome/common/extensions/docs/templates/articles/linux_hosting.html
+++ b/chrome/common/extensions/docs/templates/articles/linux_hosting.html
@@ -48,24 +48,24 @@
   hover over "More Tools" then select "Extensions"</span>.
 </p>
 <p>
-  On the Extensions Management Page, enable "Developer mode"
-  by checking the box in the top right-hand corner and
-  select the <strong>Pack extension...</strong> button.
+  On the Extensions Management Page,
+  enable Developer Mode by clicking the toggle switch
+  next to <strong>Developer mode</strong>.
+  Then select the <strong>PACK EXTENSION</strong> button.
 </p>
 
 <img src="{{static}}/images/packaging/packaging_devmode.png"
- height="100"
  alt="Developer Mode is Checked then Click Pack Extension">
 
 <p>
   Specify the path to the extension’s folder
   in the Extension root directory field then click the
-  <strong>Pack Extension</strong> button.
+  <strong>PACK EXTENSION</strong> button.
   Ignore the <strong>Private key</strong> field for a first-time package.
 </p>
 
 <img src="{{static}}/images/packaging/packaging_root.png"
- height="200"
+ height="300"
  alt="Specify Extension Path then Click Pack Extension">
 
 <p>
@@ -74,7 +74,7 @@
   which contains the extension’s private key.
 </p>
 <img src="{{static}}/images/packaging/packaging_files.png"
- height="200"
+ height="300"
  alt="Packaged Extension Files">
 
  <p>
@@ -106,18 +106,18 @@
 <p>
   Return to the
   <a href="/packaging#extension_management">Extensions Management Page</a>
-  and click the <b>Pack extension...</b> button.
+  and click the <b>PACK EXTENSION</b> button.
   Specify the path to the extensions directory and the location of private key.
 </p>
 
 <img src="{{static}}/images/packaging/packaging_updating.png"
- height="200"
+ height="300"
  alt="Updating Extension Files">
 <p>
   The page will provide the path for the updated packaged extension.
 </p>
  <img src="{{static}}/images/packaging/packaging_updated.png"
-  height="150"
+  height="200"
   alt="Updating Extension Files">
 
 <h3 id="packaging">Package through Command Line</h3>
diff --git a/chrome/common/logging_chrome.cc b/chrome/common/logging_chrome.cc
index 27e9b5c..66c69169 100644
--- a/chrome/common/logging_chrome.cc
+++ b/chrome/common/logging_chrome.cc
@@ -8,7 +8,7 @@
 // IPC_MESSAGE_LOG_ENABLED. We need to use it to define
 // IPC_MESSAGE_MACROS_LOG_ENABLED so render_messages.h will generate the
 // ViewMsgLog et al. functions.
-#include "ipc/ipc_features.h"
+#include "ipc/ipc_buildflags.h"
 
 // On Windows, the about:ipc dialog shows IPCs; on POSIX, we hook up a
 // logger in this file.  (We implement about:ipc on Mac but implement
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 0eca654..d028bc9 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -9,7 +9,7 @@
 #include "chrome/common/buildflags.h"
 #include "chrome/common/pref_font_webkit_names.h"
 #include "extensions/buildflags/buildflags.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "ppapi/features/features.h"
 
 namespace prefs {
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index b4a7eb0..bcea972 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -13,7 +13,7 @@
 #include "chrome/common/buildflags.h"
 #include "components/offline_pages/buildflags/buildflags.h"
 #include "extensions/buildflags/buildflags.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "ppapi/features/features.h"
 #include "rlz/features/features.h"
 
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h
index a40263b..9f98f54 100644
--- a/chrome/common/render_messages.h
+++ b/chrome/common/render_messages.h
@@ -24,7 +24,7 @@
 #include "ipc/ipc_channel_handle.h"
 #include "ipc/ipc_message_macros.h"
 #include "ipc/ipc_platform_file.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "ppapi/features/features.h"
 #include "url/gurl.h"
 #include "url/ipc/url_param_traits.h"
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc
index cb71167..d3bdd81 100644
--- a/chrome/common/webui_url_constants.cc
+++ b/chrome/common/webui_url_constants.cc
@@ -198,6 +198,8 @@
 const char kChromeUIKeyboardOverlayURL[] = "chrome://keyboardoverlay/";
 const char kChromeUIMobileSetupHost[] = "mobilesetup";
 const char kChromeUIMobileSetupURL[] = "chrome://mobilesetup/";
+const char kChromeUIMultiDeviceSetupHost[] = "multidevice-setup";
+const char kChromeUIMultiDeviceSetupUrl[] = "chrome://multidevice-setup";
 const char kChromeUINetworkHost[] = "network";
 const char kChromeUIOSCreditsHost[] = "os-credits";
 const char kChromeUIOSCreditsURL[] = "chrome://os-credits/";
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h
index 0c22d762..16c439e 100644
--- a/chrome/common/webui_url_constants.h
+++ b/chrome/common/webui_url_constants.h
@@ -13,7 +13,7 @@
 #include "build/build_config.h"
 #include "chrome/common/buildflags.h"
 #include "content/public/common/url_constants.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "printing/features/features.h"
 
 namespace chrome {
@@ -194,6 +194,8 @@
 extern const char kChromeUIKeyboardOverlayURL[];
 extern const char kChromeUIMobileSetupHost[];
 extern const char kChromeUIMobileSetupURL[];
+extern const char kChromeUIMultiDeviceSetupHost[];
+extern const char kChromeUIMultiDeviceSetupUrl[];
 extern const char kChromeUINetworkHost[];
 extern const char kChromeUIOSCreditsHost[];
 extern const char kChromeUIOSCreditsURL[];
diff --git a/chrome/gpu/chrome_content_gpu_client.cc b/chrome/gpu/chrome_content_gpu_client.cc
index d30f94b..5386f1a 100644
--- a/chrome/gpu/chrome_content_gpu_client.cc
+++ b/chrome/gpu/chrome_content_gpu_client.cc
@@ -38,7 +38,7 @@
     : main_thread_profiler_(ThreadProfiler::CreateAndStartOnMainThread(
           metrics::CallStackProfileParams::GPU_MAIN_THREAD)) {
 #if defined(OS_CHROMEOS)
-  protected_buffer_manager_ = std::make_unique<arc::ProtectedBufferManager>();
+  protected_buffer_manager_ = new arc::ProtectedBufferManager();
 #endif
 }
 
@@ -112,10 +112,9 @@
 #if defined(OS_CHROMEOS)
 void ChromeContentGpuClient::CreateArcVideoDecodeAccelerator(
     ::arc::mojom::VideoDecodeAcceleratorRequest request) {
-  mojo::MakeStrongBinding(
-      std::make_unique<arc::GpuArcVideoDecodeAccelerator>(
-          gpu_preferences_, protected_buffer_manager_.get()),
-      std::move(request));
+  mojo::MakeStrongBinding(std::make_unique<arc::GpuArcVideoDecodeAccelerator>(
+                              gpu_preferences_, protected_buffer_manager_),
+                          std::move(request));
 }
 
 void ChromeContentGpuClient::CreateArcVideoEncodeAccelerator(
@@ -129,7 +128,7 @@
     ::arc::mojom::ProtectedBufferManagerRequest request) {
   mojo::MakeStrongBinding(
       std::make_unique<arc::GpuArcProtectedBufferManagerProxy>(
-          protected_buffer_manager_.get()),
+          protected_buffer_manager_),
       std::move(request));
 }
 #endif
diff --git a/chrome/gpu/chrome_content_gpu_client.h b/chrome/gpu/chrome_content_gpu_client.h
index b6a38dc..31c5dae 100644
--- a/chrome/gpu/chrome_content_gpu_client.h
+++ b/chrome/gpu/chrome_content_gpu_client.h
@@ -9,6 +9,7 @@
 #include <string>
 
 #include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/single_thread_task_runner.h"
 #include "chrome/common/thread_profiler.h"
 #include "content/public/gpu/content_gpu_client.h"
@@ -60,7 +61,7 @@
 
 #if defined(OS_CHROMEOS)
   gpu::GpuPreferences gpu_preferences_;
-  std::unique_ptr<arc::ProtectedBufferManager> protected_buffer_manager_;
+  scoped_refptr<arc::ProtectedBufferManager> protected_buffer_manager_;
 #endif
 
   DISALLOW_COPY_AND_ASSIGN(ChromeContentGpuClient);
diff --git a/chrome/installer/setup/setup_util_unittest.cc b/chrome/installer/setup/setup_util_unittest.cc
index c2ea3ad..346766d 100644
--- a/chrome/installer/setup/setup_util_unittest.cc
+++ b/chrome/installer/setup/setup_util_unittest.cc
@@ -476,7 +476,12 @@
   registry_util::RegistryOverrideManager registry_override_manager;
   registry_override_manager.OverrideRegistry(HKEY_LOCAL_MACHINE);
 
-  std::string token("tokens are \0 binary data");
+  // Use the 2 argument std::string constructor so that the length of the string
+  // is not calculated by assuming the input char array is null terminated.
+  static constexpr char kTokenData[] = "tokens are \0 binary data";
+  static constexpr DWORD kExpectedSize = sizeof(kTokenData) - 1;
+  std::string token(&kTokenData[0], kExpectedSize);
+  ASSERT_EQ(kExpectedSize, token.length());
   EXPECT_TRUE(installer::StoreDMToken(token));
 
   std::wstring path;
@@ -486,14 +491,14 @@
   ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, path.c_str(),
                                     KEY_QUERY_VALUE | KEY_WOW64_64KEY));
 
-  DWORD size = 64;
+  DWORD size = kExpectedSize;
   std::vector<char> raw_value(size);
   DWORD dtype;
   ASSERT_EQ(ERROR_SUCCESS,
             key.ReadValue(name.c_str(), raw_value.data(), &size, &dtype));
   EXPECT_EQ(REG_BINARY, dtype);
-  ASSERT_EQ(token.length(), size);
-  EXPECT_EQ(0, memcmp(token.data(), raw_value.data(), size));
+  ASSERT_EQ(kExpectedSize, size);
+  EXPECT_EQ(0, memcmp(token.data(), raw_value.data(), kExpectedSize));
 }
 
 namespace installer {
diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn
index f519705..86014333 100644
--- a/chrome/renderer/BUILD.gn
+++ b/chrome/renderer/BUILD.gn
@@ -142,7 +142,7 @@
     "//content/public/renderer",
     "//extensions/buildflags",
     "//media",
-    "//media:media_features",
+    "//media:media_buildflags",
     "//media/capture",
     "//mojo/public/cpp/bindings",
     "//net",
@@ -203,7 +203,7 @@
     deps += [
       "//components/pdf/renderer",
       "//components/strings",
-      "//media:media_features",
+      "//media:media_buildflags",
       "//ppapi/host",
       "//ppapi/proxy",
       "//ppapi/proxy:ipc",
@@ -313,7 +313,6 @@
       "resources/extensions/declarative_content_custom_bindings.js",
       "resources/extensions/easy_unlock_proximity_required.js",
       "resources/extensions/enterprise_platform_keys_custom_bindings.js",
-      "resources/extensions/feedback_private_custom_bindings.js",
       "resources/extensions/gcm_custom_bindings.js",
       "resources/extensions/identity_custom_bindings.js",
       "resources/extensions/image_writer_private_custom_bindings.js",
diff --git a/chrome/renderer/autofill/password_generation_agent_browsertest.cc b/chrome/renderer/autofill/password_generation_agent_browsertest.cc
index 4c61d2d..7d8fb08 100644
--- a/chrome/renderer/autofill/password_generation_agent_browsertest.cc
+++ b/chrome/renderer/autofill/password_generation_agent_browsertest.cc
@@ -19,6 +19,7 @@
 #include "components/autofill/content/renderer/autofill_agent.h"
 #include "components/autofill/content/renderer/form_autofill_util.h"
 #include "components/autofill/content/renderer/test_password_generation_agent.h"
+#include "components/autofill/core/common/autofill_switches.h"
 #include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/password_generation_util.h"
 #include "components/password_manager/core/common/password_manager_features.h"
@@ -150,6 +151,21 @@
   DISALLOW_COPY_AND_ASSIGN(PasswordGenerationAgentTest);
 };
 
+class PasswordGenerationAgentTestForHtmlAnnotation
+    : public PasswordGenerationAgentTest {
+ public:
+  PasswordGenerationAgentTestForHtmlAnnotation() {}
+
+  void SetUp() override {
+    base::CommandLine::ForCurrentProcess()->AppendSwitch(
+        switches::kShowAutofillSignatures);
+    PasswordGenerationAgentTest::SetUp();
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(PasswordGenerationAgentTestForHtmlAnnotation);
+};
+
 const char kSigninFormHTML[] =
     "<FORM name = 'blah' action = 'http://www.random.com/'> "
     "  <INPUT type = 'text' id = 'username'/> "
@@ -159,7 +175,7 @@
     "</FORM>";
 
 const char kAccountCreationFormHTML[] =
-    "<FORM name = 'blah' action = 'http://www.random.com/pa/th?q=1&p=3#first'> "
+    "<FORM id = 'blah' action = 'http://www.random.com/pa/th?q=1&p=3#first'> "
     "  <INPUT type = 'text' id = 'username'/> "
     "  <INPUT type = 'password' id = 'first_password' size = 5/>"
     "  <INPUT type = 'password' id = 'second_password' size = 5/> "
@@ -890,4 +906,45 @@
   EXPECT_FALSE(fake_driver_.called_password_no_longer_generated());
 }
 
+TEST_F(PasswordGenerationAgentTestForHtmlAnnotation, AnnotateForm) {
+  LoadHTMLWithUserGesture(kAccountCreationFormHTML);
+  SetNotBlacklistedMessage(password_generation_, kAccountCreationFormHTML);
+  SetAccountCreationFormsDetectedMessage(password_generation_,
+                                         GetMainFrame()->GetDocument(), 0, 1);
+  ExpectGenerationAvailable("first_password", true);
+  WebDocument document = GetMainFrame()->GetDocument();
+
+  // Check the form signature is set.
+  blink::WebElement form_element =
+      document.GetElementById(blink::WebString::FromUTF8("blah"));
+  ASSERT_FALSE(form_element.IsNull());
+  blink::WebString form_signature =
+      form_element.GetAttribute(blink::WebString::FromUTF8("form_signature"));
+  ASSERT_FALSE(form_signature.IsNull());
+  EXPECT_EQ("3524919054660658462", form_signature.Ascii());
+
+  // Check field signatures are set.
+  blink::WebElement username_element =
+      document.GetElementById(blink::WebString::FromUTF8("username"));
+  ASSERT_FALSE(username_element.IsNull());
+  blink::WebString username_signature = username_element.GetAttribute(
+      blink::WebString::FromUTF8("field_signature"));
+  ASSERT_FALSE(username_signature.IsNull());
+  EXPECT_EQ("239111655", username_signature.Ascii());
+
+  blink::WebElement password_element =
+      document.GetElementById(blink::WebString::FromUTF8("first_password"));
+  ASSERT_FALSE(password_element.IsNull());
+  blink::WebString password_signature = password_element.GetAttribute(
+      blink::WebString::FromUTF8("field_signature"));
+  ASSERT_FALSE(password_signature.IsNull());
+  EXPECT_EQ("3933215845", password_signature.Ascii());
+
+  // Check the generation element is marked.
+  blink::WebString generation_mark = password_element.GetAttribute(
+      blink::WebString::FromUTF8("password_creation_field"));
+  ASSERT_FALSE(generation_mark.IsNull());
+  EXPECT_EQ("1", generation_mark.Utf8());
+}
+
 }  // namespace autofill
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index e8c0ec3..9301f60 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -103,7 +103,7 @@
 #include "extensions/common/constants.h"
 #include "ipc/ipc_sync_channel.h"
 #include "media/base/media_switches.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "net/base/net_errors.h"
 #include "ppapi/c/private/ppb_pdf.h"
 #include "ppapi/features/features.h"
@@ -1295,22 +1295,25 @@
   return false;
 }
 
-bool ChromeContentRendererClient::WillSendRequest(
+void ChromeContentRendererClient::WillSendRequest(
     WebLocalFrame* frame,
     ui::PageTransition transition_type,
     const blink::WebURL& url,
-    GURL* new_url) {
+    const url::Origin* initiator_origin,
+    GURL* new_url,
+    bool* attach_same_site_cookies) {
 // Check whether the request should be allowed. If not allowed, we reset the
 // URL to something invalid to prevent the request and cause an error.
 #if BUILDFLAG(ENABLE_EXTENSIONS)
-  if (ChromeExtensionsRendererClient::GetInstance()->WillSendRequest(
-          frame, transition_type, url, new_url)) {
-    return true;
-  }
+  ChromeExtensionsRendererClient::GetInstance()->WillSendRequest(
+      frame, transition_type, url, initiator_origin, new_url,
+      attach_same_site_cookies);
+  if (!new_url->is_empty())
+    return;
 #endif
 
   if (!url.ProtocolIs(chrome::kChromeSearchScheme))
-    return false;
+    return;
 
 #if !defined(OS_ANDROID)
   SearchBox* search_box =
@@ -1325,11 +1328,9 @@
       type = SearchBox::THUMB;
 
     if (type != SearchBox::NONE)
-      return search_box->GenerateImageURLFromTransientURL(url, type, new_url);
+      search_box->GenerateImageURLFromTransientURL(url, type, new_url);
   }
 #endif  // !defined(OS_ANDROID)
-
-  return false;
 }
 
 bool ChromeContentRendererClient::IsPrefetchOnly(
diff --git a/chrome/renderer/chrome_content_renderer_client.h b/chrome/renderer/chrome_content_renderer_client.h
index c6ec0e87..95bd1ea 100644
--- a/chrome/renderer/chrome_content_renderer_client.h
+++ b/chrome/renderer/chrome_content_renderer_client.h
@@ -26,7 +26,7 @@
 #include "content/public/renderer/render_thread.h"
 #include "extensions/buildflags/buildflags.h"
 #include "ipc/ipc_channel_proxy.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "ppapi/features/features.h"
 #include "printing/features/features.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
@@ -154,11 +154,12 @@
                   bool is_initial_navigation,
                   bool is_server_redirect,
                   bool* send_referrer) override;
-  bool WillSendRequest(
-      blink::WebLocalFrame* frame,
-      ui::PageTransition transition_type,
-      const blink::WebURL& url,
-      GURL* new_url) override;
+  void WillSendRequest(blink::WebLocalFrame* frame,
+                       ui::PageTransition transition_type,
+                       const blink::WebURL& url,
+                       const url::Origin* initiator_origin,
+                       GURL* new_url,
+                       bool* attach_same_site_cookies) override;
   bool IsPrefetchOnly(content::RenderFrame* render_frame,
                       const blink::WebURLRequest& request) override;
   unsigned long long VisitedLinkHash(const char* canonical_url,
diff --git a/chrome/renderer/chrome_content_renderer_client_browsertest.cc b/chrome/renderer/chrome_content_renderer_client_browsertest.cc
index 31833d1..47f5723 100644
--- a/chrome/renderer/chrome_content_renderer_client_browsertest.cc
+++ b/chrome/renderer/chrome_content_renderer_client_browsertest.cc
@@ -99,9 +99,12 @@
       render_frame->GetRenderView()->GetRoutingID()));
 
   GURL result;
+  bool attach_same_site_cookies;
   // Make sure the SearchBox rewrites a thumbnail request from the main frame.
-  EXPECT_TRUE(client.WillSendRequest(GetMainFrame(), ui::PAGE_TRANSITION_LINK,
-                                     blink::WebURL(thumbnail_url), &result));
+  client.WillSendRequest(GetMainFrame(), ui::PAGE_TRANSITION_LINK,
+                         blink::WebURL(thumbnail_url), nullptr, &result,
+                         &attach_same_site_cookies);
+  EXPECT_NE(result, thumbnail_url);
 
   // Make sure the SearchBox rewrites a thumbnail request from the iframe.
   blink::WebFrame* child_frame = GetMainFrame()->FirstChild();
@@ -109,8 +112,10 @@
   ASSERT_TRUE(child_frame->IsWebLocalFrame());
   blink::WebLocalFrame* local_child =
       static_cast<blink::WebLocalFrame*>(child_frame);
-  EXPECT_TRUE(client.WillSendRequest(local_child, ui::PAGE_TRANSITION_LINK,
-                                     blink::WebURL(thumbnail_url), &result));
+  client.WillSendRequest(local_child, ui::PAGE_TRANSITION_LINK,
+                         blink::WebURL(thumbnail_url), nullptr, &result,
+                         &attach_same_site_cookies);
+  EXPECT_NE(result, thumbnail_url);
 }
 
 // The tests below examine Youtube requests that use the Flash API and ensure
diff --git a/chrome/renderer/extensions/automation_ax_tree_wrapper.cc b/chrome/renderer/extensions/automation_ax_tree_wrapper.cc
index 2137e4ad..4373161 100644
--- a/chrome/renderer/extensions/automation_ax_tree_wrapper.cc
+++ b/chrome/renderer/extensions/automation_ax_tree_wrapper.cc
@@ -193,40 +193,46 @@
   tree_.SetDelegate(nullptr);
 }
 
-bool AutomationAXTreeWrapper::OnAccessibilityEvent(
-    const ExtensionMsg_AccessibilityEventParams& params,
+bool AutomationAXTreeWrapper::OnAccessibilityEvents(
+    const std::vector<ExtensionMsg_AccessibilityEventParams>& events,
     bool is_active_profile) {
-  deleted_node_ids_.clear();
+  for (const auto& params : events) {
+    deleted_node_ids_.clear();
 
-  if (!tree_.Unserialize(params.update))
-    return false;
+    if (!tree_.Unserialize(params.update))
+      return false;
 
-  // Don't send any events if it's not the active profile.
+    if (is_active_profile)
+      owner_->SendNodesRemovedEvent(&tree_, deleted_node_ids_);
+  }
+
+  // Exit early if this isn't the active profile.
   if (!is_active_profile)
     return true;
 
-  owner_->SendNodesRemovedEvent(&tree_, deleted_node_ids_);
-  deleted_node_ids_.clear();
-
-  api::automation::EventType automation_event_type =
-      ToAutomationEvent(params.event_type);
-
-  // Send some events directly from the event message, if they're not
-  // handled by AXEventGenerator yet.
-  if (!IsEventTypeHandledByAXEventGenerator(automation_event_type))
-    owner_->SendAutomationEvent(params, params.id, automation_event_type);
-
   // Send auto-generated AXEventGenerator events.
   for (auto targeted_event : *this) {
     api::automation::EventType event_type =
         ToAutomationEvent(targeted_event.event);
     if (IsEventTypeHandledByAXEventGenerator(event_type)) {
-      owner_->SendAutomationEvent(params, targeted_event.node->id(),
+      ExtensionMsg_AccessibilityEventParams generated_params;
+      generated_params.tree_id = tree_id_;
+      owner_->SendAutomationEvent(generated_params, targeted_event.node->id(),
                                   event_type);
     }
   }
   ClearEvents();
 
+  for (auto params : events) {
+    api::automation::EventType automation_event_type =
+        ToAutomationEvent(params.event_type);
+
+    // Send some events directly from the event message, if they're not
+    // handled by AXEventGenerator yet.
+    if (!IsEventTypeHandledByAXEventGenerator(automation_event_type))
+      owner_->SendAutomationEvent(params, params.id, automation_event_type);
+  }
+
   return true;
 }
 
@@ -290,6 +296,7 @@
     case api::automation::EVENT_TYPE_ACTIVEDESCENDANTCHANGED:
     case api::automation::EVENT_TYPE_ARIAATTRIBUTECHANGED:
     case api::automation::EVENT_TYPE_CHECKEDSTATECHANGED:
+    case api::automation::EVENT_TYPE_DOCUMENTSELECTIONCHANGED:
     case api::automation::EVENT_TYPE_EXPANDEDCHANGED:
     case api::automation::EVENT_TYPE_INVALIDSTATUSCHANGED:
     case api::automation::EVENT_TYPE_LIVEREGIONCHANGED:
@@ -335,7 +342,6 @@
     case api::automation::EVENT_TYPE_ALERT:
     case api::automation::EVENT_TYPE_BLUR:
     case api::automation::EVENT_TYPE_CHILDRENCHANGED:
-    case api::automation::EVENT_TYPE_DOCUMENTSELECTIONCHANGED:
     case api::automation::EVENT_TYPE_FOCUS:
     case api::automation::EVENT_TYPE_IMAGEFRAMEUPDATED:
     case api::automation::EVENT_TYPE_LOCATIONCHANGED:
diff --git a/chrome/renderer/extensions/automation_ax_tree_wrapper.h b/chrome/renderer/extensions/automation_ax_tree_wrapper.h
index e25f548..4a02585 100644
--- a/chrome/renderer/extensions/automation_ax_tree_wrapper.h
+++ b/chrome/renderer/extensions/automation_ax_tree_wrapper.h
@@ -31,12 +31,13 @@
   int32_t host_node_id() const { return host_node_id_; }
   void set_host_node_id(int32_t id) { host_node_id_ = id; }
 
-  // Called by AutomationInternalCustomBindings::OnAccessibilityEvent on
+  // Called by AutomationInternalCustomBindings::OnAccessibilityEvents on
   // the AutomationAXTreeWrapper instance for the correct tree corresponding
   // to this event. Unserializes the tree update and calls back to
   // AutomationInternalCustomBindings to fire any automation events needed.
-  bool OnAccessibilityEvent(const ExtensionMsg_AccessibilityEventParams& params,
-                            bool is_active_profile);
+  bool OnAccessibilityEvents(
+      const std::vector<ExtensionMsg_AccessibilityEventParams>& events,
+      bool is_active_profile);
 
  private:
   // AXEventGenerator overrides.
diff --git a/chrome/renderer/extensions/automation_internal_custom_bindings.cc b/chrome/renderer/extensions/automation_internal_custom_bindings.cc
index 3bd89498..e003158 100644
--- a/chrome/renderer/extensions/automation_internal_custom_bindings.cc
+++ b/chrome/renderer/extensions/automation_internal_custom_bindings.cc
@@ -896,8 +896,8 @@
 void AutomationInternalCustomBindings::OnMessageReceived(
     const IPC::Message& message){
   IPC_BEGIN_MESSAGE_MAP(AutomationInternalCustomBindings, message)
-    IPC_MESSAGE_HANDLER(ExtensionMsg_AccessibilityEvent,
-                        OnAccessibilityEvent)
+    IPC_MESSAGE_HANDLER(ExtensionMsg_AccessibilityEvents,
+                        OnAccessibilityEvents)
     IPC_MESSAGE_HANDLER(ExtensionMsg_AccessibilityLocationChange,
                         OnAccessibilityLocationChange)
   IPC_END_MESSAGE_MAP()
@@ -1286,15 +1286,15 @@
 // Handle accessibility events from the browser process.
 //
 
-void AutomationInternalCustomBindings::OnAccessibilityEvent(
-    const ExtensionMsg_AccessibilityEventParams& params,
+void AutomationInternalCustomBindings::OnAccessibilityEvents(
+    const std::vector<ExtensionMsg_AccessibilityEventParams>& events,
     bool is_active_profile) {
   is_active_profile_ = is_active_profile;
-  int tree_id = params.tree_id;
+  int tree_id = events[0].tree_id;
   AutomationAXTreeWrapper* tree_wrapper;
   auto iter = tree_id_to_tree_wrapper_map_.find(tree_id);
   if (iter == tree_id_to_tree_wrapper_map_.end()) {
-    tree_wrapper = new AutomationAXTreeWrapper(params.tree_id, this);
+    tree_wrapper = new AutomationAXTreeWrapper(events[0].tree_id, this);
     tree_id_to_tree_wrapper_map_.insert(
         std::make_pair(tree_id, base::WrapUnique(tree_wrapper)));
     axtree_to_tree_wrapper_map_.insert(
@@ -1303,7 +1303,7 @@
     tree_wrapper = iter->second.get();
   }
 
-  if (!tree_wrapper->OnAccessibilityEvent(params, is_active_profile)) {
+  if (!tree_wrapper->OnAccessibilityEvents(events, is_active_profile)) {
     LOG(ERROR) << tree_wrapper->tree()->error();
     base::ListValue args;
     args.AppendInteger(tree_id);
diff --git a/chrome/renderer/extensions/automation_internal_custom_bindings.h b/chrome/renderer/extensions/automation_internal_custom_bindings.h
index 551f9168..d94d6ec 100644
--- a/chrome/renderer/extensions/automation_internal_custom_bindings.h
+++ b/chrome/renderer/extensions/automation_internal_custom_bindings.h
@@ -155,8 +155,9 @@
   //
 
   // Handle accessibility events from the browser process.
-  void OnAccessibilityEvent(const ExtensionMsg_AccessibilityEventParams& params,
-                            bool is_active_profile);
+  void OnAccessibilityEvents(
+      const std::vector<ExtensionMsg_AccessibilityEventParams>& events,
+      bool is_active_profile);
   void OnAccessibilityLocationChange(
       const ExtensionMsg_AccessibilityLocationChangeParams& params);
 
diff --git a/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc b/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc
index 6dc4a350..9bcd2fdc 100644
--- a/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc
+++ b/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc
@@ -46,7 +46,7 @@
 #include "extensions/renderer/native_handler.h"
 #include "extensions/renderer/resource_bundle_source_map.h"
 #include "extensions/renderer/script_context.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "third_party/WebKit/public/platform/WebString.h"
 #include "third_party/WebKit/public/platform/WebURL.h"
 #include "third_party/WebKit/public/web/WebSecurityPolicy.h"
@@ -181,8 +181,6 @@
   source_map->RegisterSource("developerPrivate",
                              IDR_DEVELOPER_PRIVATE_CUSTOM_BINDINGS_JS);
   source_map->RegisterSource("downloads", IDR_DOWNLOADS_CUSTOM_BINDINGS_JS);
-  source_map->RegisterSource("feedbackPrivate",
-                             IDR_FEEDBACK_PRIVATE_CUSTOM_BINDINGS_JS);
   source_map->RegisterSource("gcm", IDR_GCM_CUSTOM_BINDINGS_JS);
   source_map->RegisterSource("identity", IDR_IDENTITY_CUSTOM_BINDINGS_JS);
   source_map->RegisterSource("imageWriterPrivate",
diff --git a/chrome/renderer/extensions/chrome_extensions_renderer_client.cc b/chrome/renderer/extensions/chrome_extensions_renderer_client.cc
index de3ba48..0c9b507 100644
--- a/chrome/renderer/extensions/chrome_extensions_renderer_client.cc
+++ b/chrome/renderer/extensions/chrome_extensions_renderer_client.cc
@@ -27,6 +27,7 @@
 #include "extensions/common/constants.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_set.h"
+#include "extensions/common/permissions/permissions_data.h"
 #include "extensions/common/switches.h"
 #include "extensions/renderer/dispatcher.h"
 #include "extensions/renderer/extension_frame_helper.h"
@@ -39,6 +40,7 @@
 #include "third_party/WebKit/public/web/WebDocument.h"
 #include "third_party/WebKit/public/web/WebLocalFrame.h"
 #include "third_party/WebKit/public/web/WebPluginParams.h"
+#include "url/origin.h"
 
 using extensions::Extension;
 
@@ -215,19 +217,40 @@
   }
 }
 
-bool ChromeExtensionsRendererClient::WillSendRequest(
+void ChromeExtensionsRendererClient::WillSendRequest(
     blink::WebLocalFrame* frame,
     ui::PageTransition transition_type,
     const blink::WebURL& url,
-    GURL* new_url) {
+    const url::Origin* initiator_origin,
+    GURL* new_url,
+    bool* attach_same_site_cookies) {
+  if (initiator_origin &&
+      initiator_origin->scheme() == extensions::kExtensionScheme) {
+    const extensions::RendererExtensionRegistry* extension_registry =
+        extensions::RendererExtensionRegistry::Get();
+    const Extension* extension =
+        extension_registry->GetByID(initiator_origin->host());
+    if (extension) {
+      int tab_id = extensions::ExtensionFrameHelper::Get(
+                       content::RenderFrame::FromWebFrame(frame))
+                       ->tab_id();
+      GURL request_url(url);
+      if (extension->permissions_data()->GetPageAccess(extension, request_url,
+                                                       tab_id, nullptr) ==
+              extensions::PermissionsData::ACCESS_ALLOWED ||
+          extension->permissions_data()->GetContentScriptAccess(
+              extension, request_url, tab_id, nullptr) ==
+              extensions::PermissionsData::ACCESS_ALLOWED) {
+        *attach_same_site_cookies = true;
+      }
+    }
+  }
+
   if (url.ProtocolIs(extensions::kExtensionScheme) &&
       !resource_request_policy_->CanRequestResource(GURL(url), frame,
                                                     transition_type)) {
     *new_url = GURL(chrome::kExtensionInvalidRequestURL);
-    return true;
   }
-
-  return false;
 }
 
 void ChromeExtensionsRendererClient::SetExtensionDispatcherForTest(
diff --git a/chrome/renderer/extensions/chrome_extensions_renderer_client.h b/chrome/renderer/extensions/chrome_extensions_renderer_client.h
index 66ce674..019b6e2 100644
--- a/chrome/renderer/extensions/chrome_extensions_renderer_client.h
+++ b/chrome/renderer/extensions/chrome_extensions_renderer_client.h
@@ -35,6 +35,10 @@
 class ResourceRequestPolicy;
 }
 
+namespace url {
+class Origin;
+}
+
 class ChromeExtensionsRendererClient
     : public extensions::ExtensionsRendererClient {
  public:
@@ -59,10 +63,12 @@
   bool OverrideCreatePlugin(content::RenderFrame* render_frame,
                             const blink::WebPluginParams& params);
   bool AllowPopup();
-  bool WillSendRequest(blink::WebLocalFrame* frame,
+  void WillSendRequest(blink::WebLocalFrame* frame,
                        ui::PageTransition transition_type,
                        const blink::WebURL& url,
-                       GURL* new_url);
+                       const url::Origin* initiator_origin,
+                       GURL* new_url,
+                       bool* attach_same_site_cookies);
   void SetExtensionDispatcherForTest(
       std::unique_ptr<extensions::Dispatcher> extension_dispatcher);
   extensions::Dispatcher* GetExtensionDispatcherForTest();
diff --git a/chrome/renderer/media/chrome_key_systems.cc b/chrome/renderer/media/chrome_key_systems.cc
index d3fa1f7..bd610f63 100644
--- a/chrome/renderer/media/chrome_key_systems.cc
+++ b/chrome/renderer/media/chrome_key_systems.cc
@@ -20,7 +20,7 @@
 #include "content/public/renderer/render_thread.h"
 #include "media/base/eme_constants.h"
 #include "media/base/key_system_properties.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 #if defined(OS_ANDROID)
 #include "components/cdm/renderer/android_key_systems.h"
diff --git a/chrome/renderer/pepper/pepper_uma_host.cc b/chrome/renderer/pepper/pepper_uma_host.cc
index 94477d3..58df7276 100644
--- a/chrome/renderer/pepper/pepper_uma_host.cc
+++ b/chrome/renderer/pepper/pepper_uma_host.cc
@@ -19,7 +19,7 @@
 #include "content/public/renderer/render_thread.h"
 #include "content/public/renderer/renderer_ppapi_host.h"
 #include "extensions/buildflags/buildflags.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "ppapi/c/pp_errors.h"
 #include "ppapi/features/features.h"
 #include "ppapi/host/dispatch_host_message.h"
diff --git a/chrome/renderer/plugins/plugin_uma_unittest.cc b/chrome/renderer/plugins/plugin_uma_unittest.cc
index f1769f2b..35410ca2 100644
--- a/chrome/renderer/plugins/plugin_uma_unittest.cc
+++ b/chrome/renderer/plugins/plugin_uma_unittest.cc
@@ -5,7 +5,7 @@
 #include <gtest/gtest.h>
 
 #include "chrome/renderer/plugins/plugin_uma.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "ppapi/features/features.h"
 
 class PluginUMATest : public testing::Test {
diff --git a/chrome/renderer/resources/renderer_resources.grd b/chrome/renderer/resources/renderer_resources.grd
index cedfb4dc6..9e287f1 100644
--- a/chrome/renderer/resources/renderer_resources.grd
+++ b/chrome/renderer/resources/renderer_resources.grd
@@ -41,7 +41,6 @@
         <include name="IDR_DEVELOPER_PRIVATE_CUSTOM_BINDINGS_JS" file="extensions\developer_private_custom_bindings.js" type="BINDATA" />
         <include name="IDR_DOWNLOADS_CUSTOM_BINDINGS_JS" file="extensions\downloads_custom_bindings.js" type="BINDATA" />
         <include name="IDR_EASY_UNLOCK_PROXIMITY_REQUIRED_JS" file="extensions\easy_unlock_proximity_required.js" type="BINDATA" />
-        <include name="IDR_FEEDBACK_PRIVATE_CUSTOM_BINDINGS_JS" file="extensions\feedback_private_custom_bindings.js" type="BINDATA" />
         <include name="IDR_GCM_CUSTOM_BINDINGS_JS" file="extensions\gcm_custom_bindings.js" type="BINDATA" />
         <include name="IDR_IDENTITY_CUSTOM_BINDINGS_JS" file="extensions\identity_custom_bindings.js" type="BINDATA" />
         <include name="IDR_IMAGE_WRITER_PRIVATE_CUSTOM_BINDINGS_JS" file="extensions\image_writer_private_custom_bindings.js" type="BINDATA" />
diff --git a/chrome/renderer/url_loader_throttle_provider_impl.cc b/chrome/renderer/url_loader_throttle_provider_impl.cc
index 4263abda..e151989 100644
--- a/chrome/renderer/url_loader_throttle_provider_impl.cc
+++ b/chrome/renderer/url_loader_throttle_provider_impl.cc
@@ -46,22 +46,6 @@
   return canceler->get();
 }
 
-void PrerenderThrottleDestructed(
-    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
-    prerender::PrerenderDispatcher* prerender_dispatcher) {
-  // http://crbug.com/823306: nostateprefetch shouldn't be executing XHR since
-  // it's not supposed to be running scripts.
-  if (!task_runner->BelongsToCurrentThread()) {
-    task_runner->PostTask(
-        FROM_HERE,
-        base::BindOnce(&prerender::PrerenderDispatcher::DecrementPrefetchCount,
-                       base::Unretained(prerender_dispatcher)));
-    return;
-  }
-
-  prerender_dispatcher->DecrementPrefetchCount();
-}
-
 }  // namespace
 
 URLLoaderThrottleProviderImpl::URLLoaderThrottleProviderImpl(
@@ -132,8 +116,8 @@
             chrome_content_renderer_client_->prerender_dispatcher();
         prerender_dispatcher->IncrementPrefetchCount();
         throttle->set_destruction_closure(base::BindOnce(
-            PrerenderThrottleDestructed,
-            base::MessageLoop::current()->task_runner(), prerender_dispatcher));
+            &prerender::PrerenderDispatcher::DecrementPrefetchCount,
+            base::Unretained(prerender_dispatcher)));
       }
       throttles.push_back(std::move(throttle));
     }
diff --git a/chrome/services/media_gallery_util/media_metadata_parser.cc b/chrome/services/media_gallery_util/media_metadata_parser.cc
index 450f5f6..1d0583d 100644
--- a/chrome/services/media_gallery_util/media_metadata_parser.cc
+++ b/chrome/services/media_gallery_util/media_metadata_parser.cc
@@ -13,7 +13,7 @@
 #include "base/threading/thread.h"
 #include "media/base/data_source.h"
 #include "media/filters/audio_video_metadata_extractor.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "net/base/mime_sniffer.h"
 
 namespace MediaGalleries = extensions::api::media_galleries;
diff --git a/chrome/services/media_gallery_util/media_parser.cc b/chrome/services/media_gallery_util/media_parser.cc
index 439676c..5958ce4b 100644
--- a/chrome/services/media_gallery_util/media_parser.cc
+++ b/chrome/services/media_gallery_util/media_parser.cc
@@ -6,7 +6,7 @@
 
 #include "chrome/services/media_gallery_util/ipc_data_source.h"
 #include "chrome/services/media_gallery_util/media_metadata_parser.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 #if BUILDFLAG(ENABLE_FFMPEG)
 #include "media/filters/media_file_checker.h"
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 186dc4c..10bf8df3 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -156,7 +156,7 @@
     "//google_apis:test_support",
     "//gpu/ipc/service",
     "//ipc:test_support",
-    "//media:media_features",
+    "//media:media_buildflags",
     "//net",
     "//net:test_support",
     "//pdf",
@@ -362,7 +362,7 @@
     "//components/spellcheck:buildflags",
     "//components/sync:test_support_model",
     "//extensions/buildflags",
-    "//media:media_features",
+    "//media:media_buildflags",
     "//net:test_support",
     "//ppapi/features",
     "//printing/features",
@@ -582,6 +582,7 @@
       "../browser/media/webrtc/webrtc_desktop_capture_browsertest.cc",
       "../browser/media/webrtc/webrtc_disable_encryption_flag_browsertest.cc",
       "../browser/media/webrtc/webrtc_getmediadevices_browsertest.cc",
+      "../browser/media/webrtc/webrtc_internals_integration_browsertest.cc",
       "../browser/media/webrtc/webrtc_internals_perf_browsertest.cc",
       "../browser/media/webrtc/webrtc_rtp_browsertest.cc",
       "../browser/media/webrtc/webrtc_simulcast_browsertest.cc",
@@ -1607,7 +1608,7 @@
         "../browser/chromeos/login/users/avatar/user_image_manager_browsertest.cc",
         "../browser/chromeos/login/users/avatar/user_image_manager_test_util.cc",
         "../browser/chromeos/login/users/avatar/user_image_manager_test_util.h",
-        "../browser/chromeos/login/users/wallpaper/wallpaper_manager_policy_browsertest.cc",
+        "../browser/chromeos/login/users/wallpaper_policy_browsertest.cc",
         "../browser/chromeos/login/webview_login_browsertest.cc",
         "../browser/chromeos/login/wizard_controller_browsertest.cc",
         "../browser/chromeos/net/network_portal_detector_impl_browsertest.cc",
@@ -1665,8 +1666,8 @@
         "../browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc",
         "../browser/ui/ash/launcher/chrome_launcher_controller_test_util.cc",
         "../browser/ui/ash/launcher/chrome_launcher_controller_test_util.h",
-        "../browser/ui/ash/multi_user/multi_user_window_manager_test.cc",
-        "../browser/ui/ash/multi_user/multi_user_window_manager_test.h",
+        "../browser/ui/ash/multi_user/test_multi_user_window_manager.cc",
+        "../browser/ui/ash/multi_user/test_multi_user_window_manager.h",
         "../browser/ui/ash/network/networking_config_delegate_chromeos_browsertest.cc",
         "../browser/ui/ash/shelf_browsertest.cc",
         "../browser/ui/ash/system_tray_client_browsertest.cc",
@@ -1783,6 +1784,7 @@
         "../browser/media/webrtc/webrtc_browsertest.cc",
         "../browser/media/webrtc/webrtc_disable_encryption_flag_browsertest.cc",
         "../browser/media/webrtc/webrtc_getmediadevices_browsertest.cc",
+        "../browser/media/webrtc/webrtc_internals_integration_browsertest.cc",
         "../browser/media/webrtc/webrtc_internals_perf_browsertest.cc",
         "../browser/media/webrtc/webrtc_rtp_browsertest.cc",
         "../browser/media/webrtc/webrtc_simulcast_browsertest.cc",
@@ -1945,7 +1947,6 @@
         # Tests for non mobile and non CrOS (includes Linux, Win, Mac).
         "../browser/extensions/api/image_writer_private/image_writer_utility_client_browsertest.cc",
         "../browser/metrics/desktop_session_duration/audible_contents_tracker_browsertest.cc",
-        "../browser/metrics/desktop_session_duration/chrome_visibility_observer_browsertest.cc",
         "../browser/profiles/profile_statistics_browsertest.cc",
       ]
     }
@@ -2457,6 +2458,7 @@
     "../browser/permissions/permission_request_manager_unittest.cc",
     "../browser/permissions/permission_util_unittest.cc",
     "../browser/plugins/pdf_iframe_navigation_throttle_unittest.cc",
+    "../browser/policy/browser_dm_token_storage_win_unittest.cc",
     "../browser/policy/cloud/cloud_policy_invalidator_unittest.cc",
     "../browser/policy/cloud/cloud_policy_test_utils.cc",
     "../browser/policy/cloud/cloud_policy_test_utils.h",
@@ -2753,6 +2755,7 @@
     "//net:test_support",
     "//ppapi/features",
     "//services/data_decoder/public/cpp:test_support",
+    "//services/network/public/cpp",
     "//skia",
     "//testing/gmock",
     "//testing/gtest",
@@ -4972,6 +4975,13 @@
         "../browser/notifications/platform_notification_service_interactive_uitest.cc",
       ]
     }
+
+    if (is_mac || is_win || (is_linux && !is_chromeos)) {
+      sources += [
+        # Tests for non mobile and non CrOS (includes Linux, Win, Mac).
+        "../browser/metrics/desktop_session_duration/chrome_visibility_observer_interactive_uitest.cc",
+      ]
+    }
   }
 
   # TODO(609855): Make this compile on Android and run on the bots.
@@ -5441,7 +5451,7 @@
     # differently if possible).
     deps = [
       "//base/test:test_support_perf",
-      "//media:media_features",
+      "//media:media_buildflags",
       "//testing/gtest",
       "//testing/perf",
       "//third_party/widevine/cdm:headers",
diff --git a/chrome/test/base/testing_browser_process.cc b/chrome/test/base/testing_browser_process.cc
index 2a64a817..e3ee15a8 100644
--- a/chrome/test/base/testing_browser_process.cc
+++ b/chrome/test/base/testing_browser_process.cc
@@ -30,7 +30,7 @@
 #include "content/public/browser/notification_service.h"
 #include "content/public/common/network_connection_tracker.h"
 #include "extensions/buildflags/buildflags.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "printing/features/features.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/test/base/testing_browser_process.h b/chrome/test/base/testing_browser_process.h
index ea6b4325..ac4a658 100644
--- a/chrome/test/base/testing_browser_process.h
+++ b/chrome/test/base/testing_browser_process.h
@@ -21,7 +21,7 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_process_platform_part.h"
 #include "extensions/buildflags/buildflags.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "printing/features/features.h"
 
 class BackgroundModeManager;
diff --git a/chrome/test/base/testing_profile.cc b/chrome/test/base/testing_profile.cc
index 1650d5f..fc37d2e 100644
--- a/chrome/test/base/testing_profile.cc
+++ b/chrome/test/base/testing_profile.cc
@@ -8,6 +8,7 @@
 
 #include "base/base_paths.h"
 #include "base/command_line.h"
+#include "base/feature_list.h"
 #include "base/files/file_util.h"
 #include "base/location.h"
 #include "base/macros.h"
@@ -93,10 +94,12 @@
 #include "content/public/test/test_utils.h"
 #include "extensions/buildflags/buildflags.h"
 #include "extensions/common/constants.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
 #include "net/cookies/cookie_store.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "net/url_request/url_request_test_util.h"
+#include "services/network/public/cpp/features.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 #if BUILDFLAG(ENABLE_EXTENSIONS)
@@ -985,6 +988,11 @@
 }
 
 network::mojom::NetworkContextPtr TestingProfile::CreateMainNetworkContext() {
+  if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+    network::mojom::NetworkContextPtr network_context;
+    mojo::MakeRequest(&network_context);
+    return network_context;
+  }
   return nullptr;
 }
 
diff --git a/chrome/test/base/web_ui_browser_test_browsertest.cc b/chrome/test/base/web_ui_browser_test_browsertest.cc
index a1b3728..f424d7c 100644
--- a/chrome/test/base/web_ui_browser_test_browsertest.cc
+++ b/chrome/test/base/web_ui_browser_test_browsertest.cc
@@ -112,18 +112,22 @@
 
    private:
     void RegisterMessages() override {
-      web_ui()->RegisterMessageCallback("startAsyncTest",
-          base::Bind(&AsyncWebUIMessageHandler::HandleStartAsyncTest,
-                     base::Unretained(this)));
-      web_ui()->RegisterMessageCallback("testContinues",
-          base::Bind(&AsyncWebUIMessageHandler::HandleTestContinues,
-                     base::Unretained(this)));
-      web_ui()->RegisterMessageCallback("testFails",
-          base::Bind(&AsyncWebUIMessageHandler::HandleTestFails,
-                     base::Unretained(this)));
-      web_ui()->RegisterMessageCallback("testPasses",
-          base::Bind(&AsyncWebUIMessageHandler::HandleTestPasses,
-                     base::Unretained(this)));
+      web_ui()->RegisterMessageCallback(
+          "startAsyncTest",
+          base::BindRepeating(&AsyncWebUIMessageHandler::HandleStartAsyncTest,
+                              base::Unretained(this)));
+      web_ui()->RegisterMessageCallback(
+          "testContinues",
+          base::BindRepeating(&AsyncWebUIMessageHandler::HandleTestContinues,
+                              base::Unretained(this)));
+      web_ui()->RegisterMessageCallback(
+          "testFails",
+          base::BindRepeating(&AsyncWebUIMessageHandler::HandleTestFails,
+                              base::Unretained(this)));
+      web_ui()->RegisterMessageCallback(
+          "testPasses",
+          base::BindRepeating(&AsyncWebUIMessageHandler::HandleTestPasses,
+                              base::Unretained(this)));
     }
 
     // Starts the test in |list_value|[0] with the runAsync wrapper.
diff --git a/chrome/test/data/extensions/api_test/automation/sites/index.html b/chrome/test/data/extensions/api_test/automation/sites/index.html
index 337dee51..2d78ff3 100644
--- a/chrome/test/data/extensions/api_test/automation/sites/index.html
+++ b/chrome/test/data/extensions/api_test/automation/sites/index.html
@@ -5,7 +5,13 @@
 -->
 <html>
 <head>
-<title>Automation Tests</title>
+  <title>Automation Tests</title>
+  <style>
+    button {
+      max-width: 30;
+      max-height: 30;
+    }
+    </style>
 </head>
 <body>
 <button><span id="span-in-button">Ok</span></button>
diff --git a/chrome/test/data/extensions/api_test/automation/tests/tabs/document_selection.js b/chrome/test/data/extensions/api_test/automation/tests/tabs/document_selection.js
index 9bbb477..0bdc502 100644
--- a/chrome/test/data/extensions/api_test/automation/tests/tabs/document_selection.js
+++ b/chrome/test/data/extensions/api_test/automation/tests/tabs/document_selection.js
@@ -33,12 +33,10 @@
   },
 
   function selectInTextField() {
-    var textField = rootNode.find({role: RoleType.TEXT_FIELD});
-    assertTrue(!!textField);
-    textField.focus();
-    listenOnce(textField, EventType.TEXT_SELECTION_CHANGED, function(evt) {
-      listenOnce(rootNode, EventType.DOCUMENT_SELECTION_CHANGED, function(evt) {
-        assertTrue(evt.target === rootNode);
+    listenOnce(rootNode, EventType.DOCUMENT_SELECTION_CHANGED, function(evt1) {
+      listenOnce(textField, EventType.TEXT_SELECTION_CHANGED, function(evt2) {
+        assertTrue(evt1.target === rootNode);
+        assertTrue(evt2.target == textField);
         assertEq(textField, rootNode.anchorObject);
         assertEq(0, rootNode.anchorOffset);
         assertEq(textField, rootNode.focusObject);
@@ -57,6 +55,10 @@
         });
       });
     });
+
+    var textField = rootNode.find({role: RoleType.TEXT_FIELD});
+    assertTrue(!!textField);
+    textField.focus();
   },
 ];
 
diff --git a/chrome/test/data/extensions/api_test/automation/tests/tabs/location.js b/chrome/test/data/extensions/api_test/automation/tests/tabs/location.js
index 94982c7..81df1d5 100644
--- a/chrome/test/data/extensions/api_test/automation/tests/tabs/location.js
+++ b/chrome/test/data/extensions/api_test/automation/tests/tabs/location.js
@@ -11,9 +11,9 @@
 
       // We can't assert the left and top positions because they're
       // returned in global screen coordinates. Just check the width and
-      // height.
-      assertEq(300, okButton.location.width);
-      assertEq(350, okButton.location.height);
+      // height which may be clipped.
+      assertTrue(okButton.location.width <= 30);
+      assertTrue(okButton.location.height <= 30);
       chrome.test.succeed();
     };
 
diff --git a/chrome/test/data/extensions/api_test/content_scripts/request_cookies/background.js b/chrome/test/data/extensions/api_test/content_scripts/request_cookies/background.js
new file mode 100644
index 0000000..c7867cb
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/content_scripts/request_cookies/background.js
@@ -0,0 +1,5 @@
+// Copyright 2018 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.
+
+// <This space intentionally left empty.>
diff --git a/chrome/test/data/extensions/api_test/content_scripts/request_cookies/cookies.js b/chrome/test/data/extensions/api_test/content_scripts/request_cookies/cookies.js
new file mode 100644
index 0000000..2b7701e
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/content_scripts/request_cookies/cookies.js
@@ -0,0 +1,45 @@
+// Copyright 2018 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.
+
+let requests = [
+  {method: 'GET', url: '/set-cookie?laxcookie=1;samesite=lax'},
+  {method: 'GET', url: '/set-cookie?strictcookie=1;samesite=strict'},
+  {
+    method: 'GET',
+    url: '/expect-and-set-cookie?expect=laxcookie%3d1&set=laxFoundGet%3d1'
+  },
+  {
+    method: 'GET',
+    url:
+        '/expect-and-set-cookie?expect=strictcookie%3d1&set=strictFoundGet%3d1'
+  },
+  {
+    method: 'POST',
+    url:
+        '/expect-and-set-cookie?expect=laxcookie%3d1&set=laxFoundPost%3d1'
+  },
+  {
+    method: 'POST',
+    url:
+        '/expect-and-set-cookie?expect=strictcookie%3d1&set=strictFoundPost%3d1'
+  }
+];
+
+(async function makeRequests() {
+  // Make all the requests to the server in a sequential order.
+  for (const req of requests)
+    await fetch(req.url, {method: req.method, credentials: 'same-origin'});
+
+  // Verify that the expected cookies were seen on the server side and the
+  // expected cookies in response are present.
+  let s = document.cookie.split('; ');
+  if (s.includes('laxFoundGet=1') &&
+      s.includes('strictFoundGet=1') &&
+      s.includes('laxFoundPost=1') &&
+      s.includes('strictFoundPost=1')) {
+    chrome.test.notifyPass();
+  }
+
+  chrome.test.notifyFail(document.cookie);
+})();
diff --git a/chrome/test/data/extensions/api_test/content_scripts/request_cookies/manifest.json b/chrome/test/data/extensions/api_test/content_scripts/request_cookies/manifest.json
new file mode 100644
index 0000000..50c4ed7b
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/content_scripts/request_cookies/manifest.json
@@ -0,0 +1,15 @@
+{
+  "name": "Content Script API Tests",
+  "version": "1",
+  "manifest_version": 2,
+  "background": {
+    "scripts": ["background.js"]
+  },
+  "permissions": [ "*://a.com:*/*", "*://b.com:*/*" ],
+  "content_scripts": [
+    {
+      "matches": ["*://a.com:*/*"],
+      "js": ["cookies.js"]
+    }
+  ]
+}
diff --git a/chrome/test/data/extensions/api_test/incognito/apis/background.js b/chrome/test/data/extensions/api_test/incognito/apis/background.js
index 762f49c..324986a 100644
--- a/chrome/test/data/extensions/api_test/incognito/apis/background.js
+++ b/chrome/test/data/extensions/api_test/incognito/apis/background.js
@@ -86,7 +86,8 @@
       var testUrl = "http://localhost:PORT/extensions/test_file.html"
           .replace(/PORT/, config.testServer.port);
 
-      // Test that chrome.extension.inIncognitoTab is true for incognito tabs.
+      // Test that chrome.extension.inIncognitoContext is true for incognito
+      // tabs.
       chrome.tabs.create({windowId: incognitoWindow.id, url: testUrl},
         pass(function(tab) {
           chrome.tabs.executeScript(tab.id,
diff --git a/chrome/test/data/vr/e2e_test_files/html/test_web_input_editing.html b/chrome/test/data/vr/e2e_test_files/html/test_web_input_editing.html
new file mode 100644
index 0000000..e99a995
--- /dev/null
+++ b/chrome/test/data/vr/e2e_test_files/html/test_web_input_editing.html
@@ -0,0 +1,34 @@
+<!DOCTYPE hmtl>
+<!--
+This page toggles focus on an input field on click events and is used to test
+that focus gain spawns the keyboard and focus loss hides it.
+-->
+<html>
+  <head>
+    <style>
+      html, body {
+        height: 100%;
+        margin: 0;
+      }
+      #divtoclick {
+        min-height: 100%;
+      }
+    </style>
+  </head>
+  <script>
+    var focused = false;
+    function toggleFocusOnClick() {
+      if (focused) {
+        document.getElementById("input").blur();
+      } else {
+        document.getElementById("input").focus();
+      }
+      focused = !focused;
+    }
+  </script>
+  <body>
+    <div id="divtoclick" onclick="toggleFocusOnClick()">
+      <input id="input"></input>
+    </div>
+  </body>
+</html>
diff --git a/chrome/test/data/vr/e2e_test_files/html/test_window_raf_stops_firing_while_presenting.html b/chrome/test/data/vr/e2e_test_files/html/test_window_raf_stops_firing_while_presenting.html
index e41d694..83d37705 100644
--- a/chrome/test/data/vr/e2e_test_files/html/test_window_raf_stops_firing_while_presenting.html
+++ b/chrome/test/data/vr/e2e_test_files/html/test_window_raf_stops_firing_while_presenting.html
@@ -14,6 +14,7 @@
     <script src="../resources/webvr_boilerplate.js"></script>
     <script>
       var t = async_test("window.rAF stops while presenting");
+      var numWindowRafs = 0;
 
       function stepVerifyBeforePresent() {
         window.requestAnimationFrame( () => {
@@ -23,14 +24,18 @@
 
       function stepVerifyDuringPresent() {
         let handle = window.requestAnimationFrame( () => {
+          numWindowRafs++;
           t.step( () => {
-            assert_unreached("window.rAF fired during presentation");
+            // Even though we wait for setVSyncPaused to be called Java-side,
+            // 1-2 frames might still get window rAFs due to the call to the
+            // renderer being asynchronous.
+            assert_less_than(numWindowRafs, 3);
           });
         });
         window.setTimeout( () => {
           window.cancelAnimationFrame(handle);
           finishJavaScriptStep();
-        }, 100);
+        }, 500);
       }
 
       function stepVerifyAfterPresent() {
diff --git a/chrome/test/data/vr/e2e_test_files/html/webxr_test_window_raf_stops_firing_during_exclusive_session.html b/chrome/test/data/vr/e2e_test_files/html/webxr_test_window_raf_stops_firing_during_exclusive_session.html
index ca26ccd..7eb574a7 100644
--- a/chrome/test/data/vr/e2e_test_files/html/webxr_test_window_raf_stops_firing_during_exclusive_session.html
+++ b/chrome/test/data/vr/e2e_test_files/html/webxr_test_window_raf_stops_firing_during_exclusive_session.html
@@ -23,14 +23,18 @@
 
       function stepVerifyDuringPresent() {
         let handle = window.requestAnimationFrame( () => {
+          numWindowRafs++;
           t.step( () => {
-            assert_unreached("window.rAF fired during presentation");
+            // Even though we wait for setVSyncPaused to be called Java-side,
+            // 1-2 frames might still get window rAFs due to the call to the
+            // renderer being asynchronous.
+            assert_less_than(numWindowRafs, 3);
           });
         });
         window.setTimeout( () => {
           window.cancelAnimationFrame(handle);
           finishJavaScriptStep();
-        }, 100);
+        }, 500);
       }
 
       function stepVerifyAfterPresent() {
diff --git a/chrome/test/data/webui/async_gen.cc b/chrome/test/data/webui/async_gen.cc
index b1f7398..4bf85ee 100644
--- a/chrome/test/data/webui/async_gen.cc
+++ b/chrome/test/data/webui/async_gen.cc
@@ -28,9 +28,9 @@
 
 void WebUIBrowserAsyncGenTest::AsyncWebUIMessageHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
-      "callJS", base::Bind(&AsyncWebUIMessageHandler::HandleCallJS,
-                           base::Unretained(this)));
+      "callJS", base::BindRepeating(&AsyncWebUIMessageHandler::HandleCallJS,
+                                    base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "tearDown", base::Bind(&AsyncWebUIMessageHandler::HandleTearDown,
-                             base::Unretained(this)));
+      "tearDown", base::BindRepeating(&AsyncWebUIMessageHandler::HandleTearDown,
+                                      base::Unretained(this)));
 }
diff --git a/chrome/test/data/webui/chrome_send_browsertest.cc b/chrome/test/data/webui/chrome_send_browsertest.cc
index c3bb91a2..be772ce3 100644
--- a/chrome/test/data/webui/chrome_send_browsertest.cc
+++ b/chrome/test/data/webui/chrome_send_browsertest.cc
@@ -25,8 +25,8 @@
 void ChromeSendWebUITest::ChromeSendWebUIMessageHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "checkSend",
-      base::Bind(&ChromeSendWebUIMessageHandler::HandleCheckSend,
-                 base::Unretained(this)));
+      base::BindRepeating(&ChromeSendWebUIMessageHandler::HandleCheckSend,
+                          base::Unretained(this)));
 }
 
 WebUIMessageHandler* ChromeSendWebUITest::GetMockMessageHandler() {
diff --git a/chrome/test/data/webui/net_internals/events_view.js b/chrome/test/data/webui/net_internals/events_view.js
index 79778b5..d62d9e3 100644
--- a/chrome/test/data/webui/net_internals/events_view.js
+++ b/chrome/test/data/webui/net_internals/events_view.js
@@ -99,7 +99,16 @@
 /**
  * Tests the filters, both in terms of filtering correctly and UI.
  */
-TEST_F('NetInternalsTest', 'netInternalsEventsViewFilter', function() {
+// Disabling on debug Windows due to flaky timeout on some build bots.
+// http://crbug.com/825282
+GEN('#if defined(OS_WIN) && !defined(NDEBUG)');
+GEN('#define MAYBE_netInternalsEventsViewFilter \\');
+GEN('    DISABLED_netInternalsEventsViewFilter');
+GEN('#else');
+GEN('#define MAYBE_netInternalsEventsViewFilter netInternalsEventsViewFilter');
+GEN('#endif');
+
+TEST_F('NetInternalsTest', 'MAYBE_netInternalsEventsViewFilter', function() {
   // Sets the filter and checks the results.
   // @param {string} filter Filter to use.
   // @param {Array<boolean>} matches Ordered list of whether or not each source
diff --git a/chrome/test/data/webui/settings/about_page_tests.js b/chrome/test/data/webui/settings/about_page_tests.js
index d90ca932..004f87e 100644
--- a/chrome/test/data/webui/settings/about_page_tests.js
+++ b/chrome/test/data/webui/settings/about_page_tests.js
@@ -775,7 +775,8 @@
 
           arrow = page.$$('#promoteUpdater button');
           assertTrue(!!arrow);
-          assertFalse(arrow.hidden);
+          assertEquals('PAPER-ICON-BUTTON-LIGHT', arrow.parentElement.tagName);
+          assertFalse(arrow.parentElement.hidden);
           assertFalse(arrow.hasAttribute('disabled'));
 
           firePromoteUpdaterStatusChanged(PromoStatusScenarios.IN_BETWEEN);
@@ -787,7 +788,8 @@
 
           arrow = page.$$('#promoteUpdater button');
           assertTrue(!!arrow);
-          assertFalse(arrow.hidden);
+          assertEquals('PAPER-ICON-BUTTON-LIGHT', arrow.parentElement.tagName);
+          assertFalse(arrow.parentElement.hidden);
           assertTrue(arrow.hasAttribute('disabled'));
 
           firePromoteUpdaterStatusChanged(PromoStatusScenarios.PROMOTED);
@@ -799,7 +801,8 @@
 
           arrow = page.$$('#promoteUpdater button');
           assertTrue(!!arrow);
-          assertTrue(arrow.hidden);
+          assertEquals('PAPER-ICON-BUTTON-LIGHT', arrow.parentElement.tagName);
+          assertTrue(arrow.parentElement.hidden);
           assertTrue(arrow.hasAttribute('disabled'));
         });
 
diff --git a/chrome/test/data/webui/settings/cr_settings_browsertest.js b/chrome/test/data/webui/settings/cr_settings_browsertest.js
index e21ec4d..91a2deb 100644
--- a/chrome/test/data/webui/settings/cr_settings_browsertest.js
+++ b/chrome/test/data/webui/settings/cr_settings_browsertest.js
@@ -955,7 +955,15 @@
   ]),
 };
 
-TEST_F('CrSettingsSiteDetailsTest', 'All', function() {
+// Disabling on Windows debug due to flaky timeout on Win7 Tests (dbg)(1) bot.
+// https://crbug.com/825304
+GEN('#if defined(OS_WIN) && !defined(NDEBUG)');
+GEN('#define MAYBE_All DISABLED_All');
+GEN('#else');
+GEN('#define MAYBE_All All');
+GEN('#endif');
+
+TEST_F('CrSettingsSiteDetailsTest', 'MAYBE_All', function() {
   mocha.run();
 });
 
diff --git a/chrome/test/data/webui/settings/people_page_test.js b/chrome/test/data/webui/settings/people_page_test.js
index 86b8f53..08f8417 100644
--- a/chrome/test/data/webui/settings/people_page_test.js
+++ b/chrome/test/data/webui/settings/people_page_test.js
@@ -25,33 +25,47 @@
       PolymerTest.clearBody();
       peoplePage = document.createElement('settings-people-page');
       document.body.appendChild(peoplePage);
+
+      return Promise
+          .all([
+            browserProxy.whenCalled('getProfileInfo'),
+            syncBrowserProxy.whenCalled('getSyncStatus')
+          ])
+          .then(function() {
+            Polymer.dom.flush();
+          });
     });
 
     teardown(function() { peoplePage.remove(); });
 
     test('GetProfileInfo', function() {
-      return Promise.all([browserProxy.whenCalled('getProfileInfo'),
-                          syncBrowserProxy.whenCalled('getSyncStatus')])
-          .then(function() {
-        Polymer.dom.flush();
-        assertEquals(browserProxy.fakeProfileInfo.name,
-                     peoplePage.$$('#profile-name').textContent.trim());
-        const bg = peoplePage.$$('#profile-icon').style.backgroundImage;
-        assertTrue(bg.includes(browserProxy.fakeProfileInfo.iconUrl));
+      assertEquals(
+          browserProxy.fakeProfileInfo.name,
+          peoplePage.$$('#profile-name').textContent.trim());
+      const bg = peoplePage.$$('#profile-icon').style.backgroundImage;
+      assertTrue(bg.includes(browserProxy.fakeProfileInfo.iconUrl));
 
-        const iconDataUrl =
-            'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEA' +
-            'LAAAAAABAAEAAAICTAEAOw==';
-        cr.webUIListenerCallback(
-          'profile-info-changed',
-          {name: 'pushedName', iconUrl: iconDataUrl});
+      const iconDataUrl = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEA' +
+          'LAAAAAABAAEAAAICTAEAOw==';
+      cr.webUIListenerCallback(
+          'profile-info-changed', {name: 'pushedName', iconUrl: iconDataUrl});
 
-        Polymer.dom.flush();
-        assertEquals('pushedName',
-                     peoplePage.$$('#profile-name').textContent.trim());
-        const newBg = peoplePage.$$('#profile-icon').style.backgroundImage;
-        assertTrue(newBg.includes(iconDataUrl));
+      Polymer.dom.flush();
+      assertEquals(
+          'pushedName', peoplePage.$$('#profile-name').textContent.trim());
+      const newBg = peoplePage.$$('#profile-icon').style.backgroundImage;
+      assertTrue(newBg.includes(iconDataUrl));
+    });
+
+    // This test ensures when unifiedConsentEnabled and diceEnabled is false,
+    // the #sync-status row is shown instead of the #sync-setup row.
+    test('ShowCorrectSyncRow', function() {
+      sync_test_util.simulateSyncStatus({
+        signedIn: true,
+        syncSystemEnabled: true,
       });
+      assertFalse(!!peoplePage.$$('#sync-setup'));
+      assertTrue(!!peoplePage.$$('#sync-status'));
     });
   });
 
@@ -393,6 +407,66 @@
               window.getComputedStyle(accountControl)['display'], 'none');
         });
       });
+
+      // This test ensures when diceEnabled is true, but unifiedConsentEnabled
+      // is false, the #sync-status row is shown instead of the #sync-setup row.
+      test('ShowCorrectSyncRowWithDice', function() {
+        sync_test_util.simulateSyncStatus({
+          signedIn: true,
+          syncSystemEnabled: true,
+        });
+        assertFalse(!!peoplePage.$$('#sync-setup'));
+        assertTrue(!!peoplePage.$$('#sync-status'));
+      });
     });
   }
+
+  suite('UnifiedConsentUITest', function() {
+    let peoplePage = null;
+    let browserProxy = null;
+    let profileInfoBrowserProxy = null;
+
+    suiteSetup(function() {
+      // Force UIs to think DICE is enabled for this profile.
+      loadTimeData.overrideValues({
+        diceEnabled: true,
+        unifiedConsentEnabled: true,
+      });
+    });
+
+    setup(function() {
+      browserProxy = new TestSyncBrowserProxy();
+      settings.SyncBrowserProxyImpl.instance_ = browserProxy;
+
+      profileInfoBrowserProxy = new TestProfileInfoBrowserProxy();
+      settings.ProfileInfoBrowserProxyImpl.instance_ = profileInfoBrowserProxy;
+
+      PolymerTest.clearBody();
+      peoplePage = document.createElement('settings-people-page');
+      document.body.appendChild(peoplePage);
+
+      Polymer.dom.flush();
+      return browserProxy.whenCalled('getSyncStatus');
+    });
+
+    teardown(function() {
+      peoplePage.remove();
+    });
+
+    test('ShowCorrectSyncRowWithUnifiedConsent', function() {
+      assertTrue(!!peoplePage.$$('#sync-setup'));
+      assertFalse(!!peoplePage.$$('#sync-status'));
+
+      // Make sures the subpage opens even when logged out or has errors.
+      sync_test_util.simulateSyncStatus({
+        signedIn: false,
+        statusAction: settings.StatusAction.REAUTHENTICATE,
+      });
+
+      MockInteractions.tap(peoplePage.$$('#sync-setup'));
+      Polymer.dom.flush();
+
+      assertEquals(settings.getCurrentRoute(), settings.routes.SYNC);
+    });
+  });
 });
diff --git a/chrome/test/data/webui/settings/settings_passwords_section_browsertest.js b/chrome/test/data/webui/settings/settings_passwords_section_browsertest.js
index 6aab20f..3845d83d 100644
--- a/chrome/test/data/webui/settings/settings_passwords_section_browsertest.js
+++ b/chrome/test/data/webui/settings/settings_passwords_section_browsertest.js
@@ -69,7 +69,7 @@
           node.$$('#originUrl').href);
       assertEquals(
           passwordInfo.loginPair.username,
-          node.$$('#username').textContent.trim());
+          node.$$('#username').value);
       assertEquals(passwordInfo.numCharactersInPassword,
           node.$$('#password').value.length);
     }
diff --git a/chrome/test/data/webui/settings/sync_account_control_test.js b/chrome/test/data/webui/settings/sync_account_control_test.js
index 7aa8779..bb1399c 100644
--- a/chrome/test/data/webui/settings/sync_account_control_test.js
+++ b/chrome/test/data/webui/settings/sync_account_control_test.js
@@ -24,12 +24,8 @@
     function forcePromoResetWithCount(count, signedIn) {
       browserProxy.setImpressionCount(count);
       // Flipping syncStatus.signedIn will force promo state to be reset.
-      sync_test_util.simulateSyncStatus({
-        signedIn: !signedIn,
-      });
-      sync_test_util.simulateSyncStatus({
-        signedIn: signedIn,
-      });
+      testElement.syncStatus = {signedIn: !signedIn};
+      testElement.syncStatus = {signedIn: signedIn};
     }
 
     suiteSetup(function() {
@@ -45,14 +41,15 @@
 
       PolymerTest.clearBody();
       testElement = document.createElement('settings-sync-account-control');
+      testElement.syncStatus = {
+        signedIn: true,
+        signedInUsername: 'fakeUsername'
+      };
       document.body.appendChild(testElement);
 
-      Polymer.dom.flush();
-
-      return Promise.all([
-        browserProxy.whenCalled('getSyncStatus'),
-        browserProxy.whenCalled('getStoredAccounts'),
-      ]);
+      return browserProxy.whenCalled('getStoredAccounts').then(() => {
+        Polymer.dom.flush();
+      });
     });
 
     teardown(function() {
@@ -91,8 +88,7 @@
     });
 
     test('not signed in and no stored accounts', function() {
-      sync_test_util.simulateSyncStatus(
-          {signedIn: false, signedInUsername: ''});
+      testElement.syncStatus = {signedIn: false, signedInUsername: ''};
       sync_test_util.simulateStoredAccounts([]);
 
       assertVisible(testElement.$$('#promo-headers'), true);
@@ -105,8 +101,7 @@
     });
 
     test('not signed in but has stored accounts', function() {
-      sync_test_util.simulateSyncStatus(
-          {signedIn: false, signedInUsername: ''});
+      testElement.syncStatus = {signedIn: false, signedInUsername: ''};
       sync_test_util.simulateStoredAccounts([
         {
           fullName: 'fooName',
@@ -189,8 +184,10 @@
     });
 
     test('signed in', function() {
-      sync_test_util.simulateSyncStatus(
-          {signedIn: true, signedInUsername: 'bar@bar.com'});
+      testElement.syncStatus = {
+        signedIn: true,
+        signedInUsername: 'bar@bar.com'
+      };
       sync_test_util.simulateStoredAccounts([
         {
           fullName: 'fooName',
@@ -226,8 +223,11 @@
 
       assertEquals(settings.getCurrentRoute(), settings.routes.SIGN_OUT);
 
-      sync_test_util.simulateSyncStatus(
-          {signedIn: true, signedInUsername: 'bar@bar.com', hasError: true});
+      testElement.syncStatus = {
+        signedIn: true,
+        signedInUsername: 'bar@bar.com',
+        hasError: true
+      };
       assertTrue(
           testElement.$$('#sync-icon-container').hasAttribute('has-error'));
       assertFalse(userInfo.textContent.includes('barName'));
diff --git a/chrome/test/media_router/BUILD.gn b/chrome/test/media_router/BUILD.gn
index dd89abc..493fea6 100644
--- a/chrome/test/media_router/BUILD.gn
+++ b/chrome/test/media_router/BUILD.gn
@@ -72,6 +72,7 @@
   ]
   data = [
     "$root_out_dir/mr_extension/",
+    "internal/",
   ]
 }
 
diff --git a/chrome/test/media_router/media_router_one_ua_integration_browsertest.cc b/chrome/test/media_router/media_router_one_ua_integration_browsertest.cc
index c4486625..760ab45 100644
--- a/chrome/test/media_router/media_router_one_ua_integration_browsertest.cc
+++ b/chrome/test/media_router/media_router_one_ua_integration_browsertest.cc
@@ -61,8 +61,9 @@
   ExecuteJavaScriptAPI(web_contents, kInitiateCloseFromReceiverPageScript);
 }
 
+// TODO(crbug.com/824889): Flaky in Chromium waterfall.
 IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationOneUABrowserTest,
-                       Fail_SendMessage) {
+                       MANUAL_Fail_SendMessage) {
   RunFailToSendMessageTest();
 }
 
diff --git a/chrome/test/mini_installer/test_chrome_with_chromedriver.py b/chrome/test/mini_installer/test_chrome_with_chromedriver.py
index 5b1f5e5a..1094a2e8 100644
--- a/chrome/test/mini_installer/test_chrome_with_chromedriver.py
+++ b/chrome/test/mini_installer/test_chrome_with_chromedriver.py
@@ -19,6 +19,7 @@
 import shutil
 import sys
 import tempfile
+import time
 
 THIS_DIR = os.path.dirname(os.path.abspath(__file__))
 SRC_DIR = os.path.join(THIS_DIR, '..', '..', '..')
@@ -43,6 +44,19 @@
 @contextlib.contextmanager
 def CreateChromedriver(args):
   """Create a webdriver object ad close it after."""
+
+  def DeleteWithRetry(path, func):
+    # There seems to be a race condition on the bots that causes the paths
+    # to not delete because they are being used. This allows up to 2 seconds
+    # to delete
+    for _ in xrange(4):
+      try:
+        return func(path)
+      except WindowsError:
+        time.sleep(0.5)
+    raise
+
+  driver = None
   user_data_dir = tempfile.mkdtemp()
   fd, log_file = tempfile.mkstemp()
   os.close(fd)
@@ -62,9 +76,10 @@
       logging.error(fh.read())
     raise
   finally:
-    driver.quit()
-    os.remove(log_file)
-    shutil.rmtree(user_data_dir)
+    if driver:
+      driver.quit()
+    DeleteWithRetry(log_file, os.remove)
+    DeleteWithRetry(user_data_dir, shutil.rmtree)
 
 
 def main():
diff --git a/chromecast/base/chromecast_switches.cc b/chromecast/base/chromecast_switches.cc
index 9782ab7..19ee727 100644
--- a/chromecast/base/chromecast_switches.cc
+++ b/chromecast/base/chromecast_switches.cc
@@ -136,6 +136,14 @@
 // Background color used when Chromium hasn't rendered anything yet.
 const char kCastAppBackgroundColor[] = "cast-app-background-color";
 
+// The number of pixels from the very left or right of the screen to consider as
+// a valid origin for the left or right swipe gesture.
+const char kSystemGestureStartWidth[] = "system-gesture-start-width";
+
+// The number of pixels from the very top or bottom of the screen to consider as
+// a valid origin for the top or bottom swipe gesture.
+const char kSystemGestureStartHeight[] = "system-gesture-start-height";
+
 }  // namespace switches
 
 namespace chromecast {
diff --git a/chromecast/base/chromecast_switches.h b/chromecast/base/chromecast_switches.h
index 0195ac8..42e9786 100644
--- a/chromecast/base/chromecast_switches.h
+++ b/chromecast/base/chromecast_switches.h
@@ -73,6 +73,8 @@
 
 // UI switches
 extern const char kEnableInput[];
+extern const char kSystemGestureStartWidth[];
+extern const char kSystemGestureStartHeight[];
 
 // Background color used when Chromium hasn't rendered anything yet.
 extern const char kCastAppBackgroundColor[];
diff --git a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastContentWindowAndroid.java b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastContentWindowAndroid.java
index 2fe54c23..88ccf9b 100644
--- a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastContentWindowAndroid.java
+++ b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastContentWindowAndroid.java
@@ -124,7 +124,7 @@
 
     @Override
     public boolean consumeGesture(int gestureType) {
-        if (DEBUG) Log.d(TAG, "onVisibilityChange type=" + gestureType);
+        if (DEBUG) Log.d(TAG, "consumeGesture type=" + gestureType);
         if (mNativeCastContentWindowAndroid != 0) {
             return nativeConsumeGesture(mNativeCastContentWindowAndroid, gestureType);
         }
diff --git a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsComponent.java b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsComponent.java
index 95c19b66..2b7a3eb 100644
--- a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsComponent.java
+++ b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsComponent.java
@@ -210,8 +210,9 @@
         } else if (CastWebContentsIntentUtils.isIntentOfVisibilityChange(intent)) {
             int visibilityType = CastWebContentsIntentUtils.getVisibilityType(intent);
             if (DEBUG) {
-                Log.d(TAG, "onReceive ACTION_ON_VISIBILITY_CHANGE instance=" + mInstanceId
-                        + "; visibility=" + visibilityType);
+                Log.d(TAG,
+                        "onReceive ACTION_ON_VISIBILITY_CHANGE instance=" + mInstanceId
+                                + "; visibilityType=" + visibilityType);
             }
             if (mSurfaceEventHandler != null) {
                 mSurfaceEventHandler.onVisibilityChange(visibilityType);
@@ -219,8 +220,9 @@
         } else if (CastWebContentsIntentUtils.isIntentOfGesturing(intent)) {
             int gestureType = CastWebContentsIntentUtils.getGestureType(intent);
             if (DEBUG) {
-                Log.d(TAG, "onReceive ACTION_ON_VISIBILITY_CHANGE instance=" + mInstanceId
-                        + "; gesture=" + gestureType);
+                Log.d(TAG,
+                        "onReceive ACTION_ON_GESTURE_CHANGE instance=" + mInstanceId
+                                + "; gesture=" + gestureType);
             }
             if (mSurfaceEventHandler != null) {
                 if (mSurfaceEventHandler.consumeGesture(gestureType)) {
diff --git a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsFragment.java b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsFragment.java
index 4dc9505..2050c82 100644
--- a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsFragment.java
+++ b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsFragment.java
@@ -6,6 +6,7 @@
 
 import android.app.Fragment;
 import android.content.Context;
+import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
 import android.view.LayoutInflater;
@@ -80,6 +81,10 @@
     public void onStart() {
         Log.d(TAG, "onStart");
         super.onStart();
+
+        sendIntentSync(CastWebContentsIntentUtils.onVisibilityChange(mSurfaceHelper.getInstanceId(),
+                CastWebContentsIntentUtils.VISIBITY_TYPE_FULL_SCREEN));
+
         if (mSurfaceHelper != null) {
             return;
         }
@@ -129,6 +134,8 @@
     @Override
     public void onStop() {
         Log.d(TAG, "onStop");
+        sendIntentSync(CastWebContentsIntentUtils.onVisibilityChange(
+                mSurfaceHelper.getInstanceId(), CastWebContentsIntentUtils.VISIBITY_TYPE_HIDDEN));
         super.onStop();
     }
 
@@ -140,4 +147,8 @@
         }
         super.onDestroy();
     }
+
+    private void sendIntentSync(Intent in) {
+        CastWebContentsIntentUtils.getLocalBroadcastManager().sendBroadcastSync(in);
+    }
 }
diff --git a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsIntentUtils.java b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsIntentUtils.java
index 1879db7..bd0c6d97 100644
--- a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsIntentUtils.java
+++ b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsIntentUtils.java
@@ -126,6 +126,12 @@
     private static final String INTENT_EXTRA_GESTURE_CONSUMED =
             "com.google.android.apps.castshell.intent.extra.GESTURE_CONSUMED";
 
+    // Matches to chromecast::shell::VisibilityPriority
+    static final int VISIBITY_TYPE_UNKNOWN = 0;
+    static final int VISIBITY_TYPE_FULL_SCREEN = 1;
+    static final int VISIBITY_TYPE_PARTIAL_OUT = 2;
+    static final int VISIBITY_TYPE_HIDDEN = 3;
+
     // CastWebContentsSurfaceHelper -> CastWebContentsComponent.Receiver
     // -> CastContentWindowAndroid
     public static Intent onActivityStopped(String instanceId) {
diff --git a/chromecast/browser/cast_browser_context.cc b/chromecast/browser/cast_browser_context.cc
index f1ac8ea..0aa8205 100644
--- a/chromecast/browser/cast_browser_context.cc
+++ b/chromecast/browser/cast_browser_context.cc
@@ -62,6 +62,7 @@
 }
 
 CastBrowserContext::~CastBrowserContext() {
+  BrowserContext::NotifyWillBeDestroyed(this);
   ShutdownStoragePartitions();
   content::BrowserThread::DeleteSoon(
       content::BrowserThread::IO,
diff --git a/chromecast/browser/cast_browser_context.h b/chromecast/browser/cast_browser_context.h
index 1623b0c..fbd3537 100644
--- a/chromecast/browser/cast_browser_context.h
+++ b/chromecast/browser/cast_browser_context.h
@@ -18,7 +18,7 @@
 // Chromecast does not currently support multiple profiles.  So there is a
 // single BrowserContext for all chromecast renderers.
 // There is no support for PartitionStorage.
-class CastBrowserContext : public content::BrowserContext {
+class CastBrowserContext final : public content::BrowserContext {
  public:
   explicit CastBrowserContext(
       URLRequestContextFactory* url_request_context_factory);
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc
index 7095629..3efe61a4 100644
--- a/chromecast/browser/cast_content_browser_client.cc
+++ b/chromecast/browser/cast_content_browser_client.cc
@@ -59,7 +59,7 @@
 #include "content/public/common/url_constants.h"
 #include "content/public/common/web_preferences.h"
 #include "media/audio/audio_thread_impl.h"
-#include "media/mojo/features.h"
+#include "media/mojo/buildflags.h"
 #include "net/ssl/ssl_cert_request_info.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "ui/base/resource/resource_bundle.h"
diff --git a/chromecast/browser/cast_content_window_aura.cc b/chromecast/browser/cast_content_window_aura.cc
index e2829ac6..0e6ff7f 100644
--- a/chromecast/browser/cast_content_window_aura.cc
+++ b/chromecast/browser/cast_content_window_aura.cc
@@ -16,27 +16,51 @@
 
 class TouchBlocker : public ui::EventHandler, public aura::WindowObserver {
  public:
-  explicit TouchBlocker(aura::Window* window) : window_(window) {
+  TouchBlocker(aura::Window* window, bool activated)
+      : window_(window), activated_(activated) {
     DCHECK(window_);
     window_->AddObserver(this);
-    window_->AddPreTargetHandler(this);
+    if (activated_) {
+      window_->AddPreTargetHandler(this);
+    }
   }
 
   ~TouchBlocker() override {
     if (window_) {
       window_->RemoveObserver(this);
+      if (activated_) {
+        window_->RemovePreTargetHandler(this);
+      }
+    }
+  }
+
+  void Activate(bool activate) {
+    if (!window_ || activate == activated_) {
+      return;
+    }
+
+    if (activate) {
+      window_->AddPreTargetHandler(this);
+    } else {
       window_->RemovePreTargetHandler(this);
     }
+
+    activated_ = activate;
   }
 
  private:
   // Overriden from ui::EventHandler.
-  void OnTouchEvent(ui::TouchEvent* touch) override { touch->SetHandled(); }
+  void OnTouchEvent(ui::TouchEvent* touch) override {
+    if (activated_) {
+      touch->SetHandled();
+    }
+  }
 
   // Overriden from aura::WindowObserver.
   void OnWindowDestroyed(aura::Window* window) override { window_ = nullptr; }
 
   aura::Window* window_;
+  bool activated_;
 
   DISALLOW_COPY_AND_ASSIGN(TouchBlocker);
 };
@@ -65,9 +89,7 @@
   window_manager->SetWindowId(window, CastWindowManager::APP);
   window_manager->AddWindow(window);
 
-  if (!is_touch_enabled_) {
-    touch_blocker_ = std::make_unique<TouchBlocker>(window);
-  }
+  touch_blocker_ = std::make_unique<TouchBlocker>(window, !is_touch_enabled_);
 
   if (is_visible) {
     window->Show();
@@ -77,7 +99,9 @@
 }
 
 void CastContentWindowAura::EnableTouchInput(bool enabled) {
-  // TODO(halliwell): implement this
+  if (touch_blocker_) {
+    touch_blocker_->Activate(!enabled);
+  }
 }
 
 void CastContentWindowAura::RequestVisibility(
diff --git a/chromecast/browser/cast_web_view.h b/chromecast/browser/cast_web_view.h
index 4753967..dfc7d35 100644
--- a/chromecast/browser/cast_web_view.h
+++ b/chromecast/browser/cast_web_view.h
@@ -19,6 +19,8 @@
 
 class CastWindowManager;
 
+using shell::VisibilityPriority;
+
 // A simplified interface for loading and displaying WebContents in cast_shell.
 class CastWebView {
  public:
@@ -102,7 +104,8 @@
   // Adds the page to the window manager and makes it visible to the user if
   // |is_visible| is true.
   virtual void CreateWindow(CastWindowManager* window_manager,
-                            bool is_visible) = 0;
+                            bool is_visible,
+                            VisibilityPriority initial_priority) = 0;
 
   // Observer interface:
   void AddObserver(Observer* observer);
diff --git a/chromecast/browser/cast_web_view_default.cc b/chromecast/browser/cast_web_view_default.cc
index 12f7ab8..c59020ec 100644
--- a/chromecast/browser/cast_web_view_default.cc
+++ b/chromecast/browser/cast_web_view_default.cc
@@ -18,6 +18,7 @@
 #include "chromecast/chromecast_buildflags.h"
 #include "chromecast/public/cast_media_shlib.h"
 #include "content/public/browser/media_capture_devices.h"
+#include "content/public/browser/media_session.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_view_host.h"
@@ -86,6 +87,23 @@
   content::WebContentsObserver::Observe(web_contents_.get());
   web_contents_->SetDelegate(this);
 
+#if BUILDFLAG(IS_ANDROID_THINGS)
+// Configure the ducking multiplier for AThings speakers. When CMA backend is
+// used we don't want the Chromium MediaSession to duck since we are doing
+// our own ducking. When no CMA backend is used we rely on the MediaSession
+// for ducking. In that case set it to a proper value to match the ducking
+// done in CMA backend.
+#if BUILDFLAG(IS_CAST_USING_CMA_BACKEND)
+  // passthrough, i.e., disable ducking
+  constexpr double kDuckingMultiplier = 1.0;
+#else
+  // duck by -30dB
+  constexpr double kDuckingMultiplier = 0.03;
+#endif
+  content::MediaSession::Get(web_contents_.get())
+      ->SetDuckingVolumeMultiplier(kDuckingMultiplier);
+#endif
+
   // If this CastWebView is enabled for development, start the remote debugger.
   if (enabled_for_dev_) {
     LOG(INFO) << "Enabling dev console for " << web_contents_->GetVisibleURL();
@@ -128,15 +146,15 @@
 }
 
 void CastWebViewDefault::CreateWindow(CastWindowManager* window_manager,
-                                      bool is_visible) {
+                                      bool is_visible,
+                                      VisibilityPriority initial_priority) {
   if (media::CastMediaShlib::ClearVideoPlaneImage) {
     media::CastMediaShlib::ClearVideoPlaneImage();
   }
 
   DCHECK(window_manager);
-  window_->CreateWindowForWebContents(
-      web_contents_.get(), window_manager, is_visible,
-      chromecast::shell::VisibilityPriority::STICKY_ACTIVITY);
+  window_->CreateWindowForWebContents(web_contents_.get(), window_manager,
+                                      is_visible, initial_priority);
   web_contents_->Focus();
 }
 
diff --git a/chromecast/browser/cast_web_view_default.h b/chromecast/browser/cast_web_view_default.h
index 3370bb58..886a84be 100644
--- a/chromecast/browser/cast_web_view_default.h
+++ b/chromecast/browser/cast_web_view_default.h
@@ -50,7 +50,8 @@
   void LoadUrl(GURL url) override;
   void ClosePage(const base::TimeDelta& shutdown_delay) override;
   void CreateWindow(CastWindowManager* window_manager,
-                    bool is_visible) override;
+                    bool is_visible,
+                    VisibilityPriority initial_priority) override;
 
  private:
   // WebContentsObserver implementation:
diff --git a/chromecast/browser/cast_web_view_extension.cc b/chromecast/browser/cast_web_view_extension.cc
index 95c9d69..34418875 100644
--- a/chromecast/browser/cast_web_view_extension.cc
+++ b/chromecast/browser/cast_web_view_extension.cc
@@ -61,10 +61,10 @@
 void CastWebViewExtension::ClosePage(const base::TimeDelta& shutdown_delay) {}
 
 void CastWebViewExtension::CreateWindow(CastWindowManager* window_manager,
-                                        bool is_visible) {
-  window_->CreateWindowForWebContents(
-      web_contents(), window_manager, is_visible,
-      chromecast::shell::VisibilityPriority::DEFAULT);
+                                        bool is_visible,
+                                        VisibilityPriority initial_priority) {
+  window_->CreateWindowForWebContents(web_contents(), window_manager,
+                                      is_visible, initial_priority);
   web_contents()->Focus();
 }
 
diff --git a/chromecast/browser/cast_web_view_extension.h b/chromecast/browser/cast_web_view_extension.h
index 8a82956..b07225b 100644
--- a/chromecast/browser/cast_web_view_extension.h
+++ b/chromecast/browser/cast_web_view_extension.h
@@ -50,7 +50,8 @@
   void LoadUrl(GURL url) override;
   void ClosePage(const base::TimeDelta& shutdown_delay) override;
   void CreateWindow(CastWindowManager* window_manager,
-                    bool is_visible) override;
+                    bool is_visible,
+                    VisibilityPriority initial_priority) override;
 
  private:
   // WebContentsObserver implementation:
diff --git a/chromecast/browser/service/cast_service_simple.cc b/chromecast/browser/service/cast_service_simple.cc
index db81923..c8260c7 100644
--- a/chromecast/browser/service/cast_service_simple.cc
+++ b/chromecast/browser/service/cast_service_simple.cc
@@ -73,7 +73,9 @@
                                            nullptr,         /* extension */
                                            GURL() /* initial_url */);
   cast_web_view_->LoadUrl(startup_url_);
-  cast_web_view_->CreateWindow(window_manager_, true /* is_visible */);
+  cast_web_view_->CreateWindow(
+      window_manager_, true /* is_visible */,
+      chromecast::shell::VisibilityPriority::STICKY_ACTIVITY);
 }
 
 void CastServiceSimple::StopInternal() {
diff --git a/chromecast/device/bluetooth/le/BUILD.gn b/chromecast/device/bluetooth/le/BUILD.gn
new file mode 100644
index 0000000..3d19af80
--- /dev/null
+++ b/chromecast/device/bluetooth/le/BUILD.gn
@@ -0,0 +1,50 @@
+# Copyright 2018 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("//chromecast/chromecast.gni")
+
+cast_source_set("le") {
+  sources = [
+    "gatt_client_manager.cc",
+    "gatt_client_manager.h",
+    "le_scan_manager.cc",
+    "le_scan_manager.h",
+    "remote_characteristic.cc",
+    "remote_characteristic.h",
+    "remote_descriptor.cc",
+    "remote_descriptor.h",
+    "remote_device.cc",
+    "remote_device.h",
+    "remote_service.cc",
+    "remote_service.h",
+  ]
+  deps = [
+    "//base",
+    "//chromecast/base",
+    "//chromecast/device/bluetooth/shlib",
+    "//chromecast/internal/base",
+    "//chromecast/internal/public",
+    "//chromecast/public",
+  ]
+}
+
+cast_source_set("unittests") {
+  testonly = true
+
+  sources = [
+    "gatt_client_manager_test.cc",
+    "le_scan_manager_test.cc",
+  ]
+  deps = [
+    ":le",
+    "//base",
+    "//base/test:test_support",
+    "//chromecast/device/bluetooth/shlib:mock_shlib",
+    "//chromecast/internal/device/bluetooth:bluetooth_util",
+    "//chromecast/internal/device/bluetooth:test_support",
+    "//chromecast/public",
+    "//testing/gmock",
+    "//testing/gtest",
+  ]
+}
diff --git a/chromecast/device/bluetooth/le/DEPS b/chromecast/device/bluetooth/le/DEPS
new file mode 100644
index 0000000..c5c07222
--- /dev/null
+++ b/chromecast/device/bluetooth/le/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+  "+chromecast/internal/device/bluetooth",
+  "+chromecast/internal/public",
+]
diff --git a/chromecast/device/bluetooth/le/gatt_client_manager.cc b/chromecast/device/bluetooth/le/gatt_client_manager.cc
new file mode 100644
index 0000000..a1a06ba
--- /dev/null
+++ b/chromecast/device/bluetooth/le/gatt_client_manager.cc
@@ -0,0 +1,270 @@
+// 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 "chromecast/device/bluetooth/le/gatt_client_manager.h"
+
+#include <vector>
+
+#include "base/bind.h"
+#include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
+#include "chromecast/base/bind_to_task_runner.h"
+#include "chromecast/device/bluetooth/le/remote_characteristic.h"
+#include "chromecast/device/bluetooth/le/remote_descriptor.h"
+#include "chromecast/device/bluetooth/le/remote_device.h"
+#include "chromecast/device/bluetooth/le/remote_service.h"
+
+namespace chromecast {
+namespace bluetooth {
+
+namespace {
+
+#define RUN_ON_IO_THREAD(method, ...) \
+  io_task_runner_->PostTask(          \
+      FROM_HERE,                      \
+      base::BindOnce(&GattClientManager::method, weak_this_, ##__VA_ARGS__));
+
+#define MAKE_SURE_IO_THREAD(method, ...)            \
+  DCHECK(io_task_runner_);                          \
+  if (!io_task_runner_->BelongsToCurrentThread()) { \
+    RUN_ON_IO_THREAD(method, ##__VA_ARGS__)         \
+    return;                                         \
+  }
+
+#define CHECK_DEVICE_EXISTS_IT(it)                  \
+  do {                                              \
+    if (it == addr_to_device_.end()) {              \
+      LOG(ERROR) << __func__ << ": No such device"; \
+      return;                                       \
+    }                                               \
+  } while (0)
+
+}  // namespace
+
+GattClientManager::GattClientManager(
+    bluetooth_v2_shlib::GattClient* gatt_client)
+    : gatt_client_(gatt_client),
+      observers_(new base::ObserverListThreadSafe<Observer>()),
+      weak_factory_(
+          std::make_unique<base::WeakPtrFactory<GattClientManager>>(this)) {
+  weak_this_ = weak_factory_->GetWeakPtr();
+}
+
+GattClientManager::~GattClientManager() {}
+
+void GattClientManager::Initialize(
+    scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) {
+  io_task_runner_ = std::move(io_task_runner);
+}
+
+void GattClientManager::Finalize() {
+  io_task_runner_->PostTask(
+      FROM_HERE, base::BindOnce(&GattClientManager::FinalizeOnIoThread,
+                                std::move(weak_factory_)));
+}
+
+void GattClientManager::AddObserver(Observer* o) {
+  observers_->AddObserver(o);
+}
+
+void GattClientManager::RemoveObserver(Observer* o) {
+  observers_->RemoveObserver(o);
+}
+
+void GattClientManager::GetDevice(
+    const bluetooth_v2_shlib::Addr& addr,
+    base::OnceCallback<void(scoped_refptr<RemoteDevice>)> cb) {
+  MAKE_SURE_IO_THREAD(GetDevice, addr, BindToCurrentThread(std::move(cb)));
+  DCHECK(cb);
+  std::move(cb).Run(GetDeviceSync(addr));
+}
+
+scoped_refptr<RemoteDevice> GattClientManager::GetDeviceSync(
+    const bluetooth_v2_shlib::Addr& addr) {
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+  auto it = addr_to_device_.find(addr);
+  if (it != addr_to_device_.end()) {
+    return it->second.get();
+  }
+
+  scoped_refptr<RemoteDevice> new_device(
+      new RemoteDevice(addr, weak_this_, io_task_runner_));
+  addr_to_device_[addr] = new_device;
+  return new_device;
+}
+
+size_t GattClientManager::GetNumConnected() const {
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+  return connected_devices_.size();
+}
+
+void GattClientManager::NotifyConnect(const bluetooth_v2_shlib::Addr& addr) {
+  observers_->Notify(FROM_HERE, &Observer::OnConnectInitated, addr);
+}
+
+void GattClientManager::OnConnectChanged(const bluetooth_v2_shlib::Addr& addr,
+                                         bool status,
+                                         bool connected) {
+  MAKE_SURE_IO_THREAD(OnConnectChanged, addr, status, connected);
+  auto it = addr_to_device_.find(addr);
+  CHECK_DEVICE_EXISTS_IT(it);
+
+  it->second->SetConnected(connected);
+  if (connected) {
+    connected_devices_.insert(addr);
+  } else {
+    connected_devices_.erase(addr);
+  }
+
+  observers_->Notify(FROM_HERE, &Observer::OnConnectChanged, it->second,
+                     connected);
+}
+
+void GattClientManager::OnNotification(const bluetooth_v2_shlib::Addr& addr,
+                                       uint16_t handle,
+                                       const std::vector<uint8_t>& value) {
+  MAKE_SURE_IO_THREAD(OnNotification, addr, handle, value);
+  auto it = addr_to_device_.find(addr);
+  CHECK_DEVICE_EXISTS_IT(it);
+  auto characteristic = it->second->CharacteristicFromHandle(handle);
+  if (!characteristic) {
+    LOG(ERROR) << "No such characteristic";
+    return;
+  }
+
+  observers_->Notify(FROM_HERE, &Observer::OnCharacteristicNotification,
+                     it->second, characteristic, value);
+}
+
+void GattClientManager::OnCharacteristicReadResponse(
+    const bluetooth_v2_shlib::Addr& addr,
+    bool status,
+    uint16_t handle,
+    const std::vector<uint8_t>& value) {
+  MAKE_SURE_IO_THREAD(OnCharacteristicReadResponse, addr, status, handle,
+                      value);
+  auto it = addr_to_device_.find(addr);
+  CHECK_DEVICE_EXISTS_IT(it);
+  auto characteristic = it->second->CharacteristicFromHandle(handle);
+  if (!characteristic) {
+    LOG(ERROR) << "No such characteristic";
+    return;
+  }
+
+  characteristic->OnReadComplete(status, value);
+}
+
+void GattClientManager::OnCharacteristicWriteResponse(
+    const bluetooth_v2_shlib::Addr& addr,
+    bool status,
+    uint16_t handle) {
+  MAKE_SURE_IO_THREAD(OnCharacteristicWriteResponse, addr, status, handle);
+  auto it = addr_to_device_.find(addr);
+  CHECK_DEVICE_EXISTS_IT(it);
+  auto characteristic = it->second->CharacteristicFromHandle(handle);
+  if (!characteristic) {
+    LOG(ERROR) << "No such characteristic";
+    return;
+  }
+
+  characteristic->OnWriteComplete(status);
+}
+
+void GattClientManager::OnDescriptorReadResponse(
+    const bluetooth_v2_shlib::Addr& addr,
+    bool status,
+    uint16_t handle,
+    const std::vector<uint8_t>& value) {
+  MAKE_SURE_IO_THREAD(OnDescriptorReadResponse, addr, status, handle, value);
+  auto it = addr_to_device_.find(addr);
+  CHECK_DEVICE_EXISTS_IT(it);
+  auto descriptor = it->second->DescriptorFromHandle(handle);
+  if (!descriptor) {
+    LOG(ERROR) << "No such descriptor";
+    return;
+  }
+
+  descriptor->OnReadComplete(status, value);
+}
+
+void GattClientManager::OnDescriptorWriteResponse(
+    const bluetooth_v2_shlib::Addr& addr,
+    bool status,
+    uint16_t handle) {
+  MAKE_SURE_IO_THREAD(OnDescriptorWriteResponse, addr, status, handle);
+  auto it = addr_to_device_.find(addr);
+  CHECK_DEVICE_EXISTS_IT(it);
+  auto descriptor = it->second->DescriptorFromHandle(handle);
+  if (!descriptor) {
+    LOG(ERROR) << "No such descriptor";
+    return;
+  }
+
+  descriptor->OnWriteComplete(status);
+}
+
+void GattClientManager::OnReadRemoteRssi(const bluetooth_v2_shlib::Addr& addr,
+                                         bool status,
+                                         int rssi) {
+  MAKE_SURE_IO_THREAD(OnReadRemoteRssi, addr, status, rssi);
+  auto it = addr_to_device_.find(addr);
+  CHECK_DEVICE_EXISTS_IT(it);
+  it->second->OnReadRemoteRssiComplete(status, rssi);
+}
+
+void GattClientManager::OnMtuChanged(const bluetooth_v2_shlib::Addr& addr,
+                                     bool status,
+                                     int mtu) {
+  MAKE_SURE_IO_THREAD(OnMtuChanged, addr, status, mtu);
+  auto it = addr_to_device_.find(addr);
+  CHECK_DEVICE_EXISTS_IT(it);
+  it->second->SetMtu(mtu);
+
+  observers_->Notify(FROM_HERE, &Observer::OnMtuChanged, it->second, mtu);
+}
+
+void GattClientManager::OnGetServices(
+    const bluetooth_v2_shlib::Addr& addr,
+    const std::vector<bluetooth_v2_shlib::Gatt::Service>& services) {
+  MAKE_SURE_IO_THREAD(OnGetServices, addr, services);
+  auto it = addr_to_device_.find(addr);
+  CHECK_DEVICE_EXISTS_IT(it);
+  it->second->OnGetServices(services);
+
+  observers_->Notify(FROM_HERE, &Observer::OnServicesUpdated, it->second,
+                     it->second->GetServicesSync());
+}
+
+void GattClientManager::OnServicesRemoved(const bluetooth_v2_shlib::Addr& addr,
+                                          uint16_t start_handle,
+                                          uint16_t end_handle) {
+  MAKE_SURE_IO_THREAD(OnServicesRemoved, addr, start_handle, end_handle);
+  auto it = addr_to_device_.find(addr);
+  CHECK_DEVICE_EXISTS_IT(it);
+  it->second->OnServicesRemoved(start_handle, end_handle);
+
+  observers_->Notify(FROM_HERE, &Observer::OnServicesUpdated, it->second,
+                     it->second->GetServicesSync());
+}
+
+void GattClientManager::OnServicesAdded(
+    const bluetooth_v2_shlib::Addr& addr,
+    const std::vector<bluetooth_v2_shlib::Gatt::Service>& services) {
+  MAKE_SURE_IO_THREAD(OnServicesAdded, addr, services);
+  auto it = addr_to_device_.find(addr);
+  CHECK_DEVICE_EXISTS_IT(it);
+
+  it->second->OnServicesAdded(services);
+  observers_->Notify(FROM_HERE, &Observer::OnServicesUpdated, it->second,
+                     it->second->GetServicesSync());
+}
+
+// static
+void GattClientManager::FinalizeOnIoThread(
+    std::unique_ptr<base::WeakPtrFactory<GattClientManager>> weak_factory) {
+  weak_factory->InvalidateWeakPtrs();
+}
+
+}  // namespace bluetooth
+}  // namespace chromecast
diff --git a/chromecast/device/bluetooth/le/gatt_client_manager.h b/chromecast/device/bluetooth/le/gatt_client_manager.h
new file mode 100644
index 0000000..8c7e733
--- /dev/null
+++ b/chromecast/device/bluetooth/le/gatt_client_manager.h
@@ -0,0 +1,156 @@
+// 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 CHROMECAST_DEVICE_BLUETOOTH_LE_GATT_CLIENT_MANAGER_H_
+#define CHROMECAST_DEVICE_BLUETOOTH_LE_GATT_CLIENT_MANAGER_H_
+
+#include <map>
+#include <set>
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "base/observer_list_threadsafe.h"
+#include "base/single_thread_task_runner.h"
+#include "base/synchronization/waitable_event.h"
+#include "chromecast/device/bluetooth/shlib/gatt_client.h"
+
+namespace chromecast {
+namespace bluetooth {
+
+class RemoteCharacteristic;
+class RemoteDevice;
+class RemoteService;
+
+class GattClientManager : public bluetooth_v2_shlib::Gatt::Client::Delegate {
+ public:
+  class Observer {
+   public:
+    // Called when the connection state changes for |device|.
+    virtual void OnConnectChanged(scoped_refptr<RemoteDevice> device,
+                                  bool connected) {}
+
+    // Called when the connection MTU changes for |device|.
+    virtual void OnMtuChanged(scoped_refptr<RemoteDevice> device, int mtu) {}
+
+    // Called when the device |device|'s service list changed. |services| is the
+    // new list of services, and any old ones should be considered invalidated.
+    virtual void OnServicesUpdated(
+        scoped_refptr<RemoteDevice> device,
+        std::vector<scoped_refptr<RemoteService>> services) {}
+
+    // Called when |device| has a notification on |characteristic| with |value|.
+    virtual void OnCharacteristicNotification(
+        scoped_refptr<RemoteDevice> device,
+        scoped_refptr<RemoteCharacteristic> characteristic,
+        std::vector<uint8_t> value) {}
+
+    // Called when a connection is requested.
+    virtual void OnConnectInitated(const bluetooth_v2_shlib::Addr& addr) {}
+
+    virtual ~Observer() = default;
+  };
+
+  explicit GattClientManager(bluetooth_v2_shlib::GattClient* gatt_client);
+  ~GattClientManager() override;
+
+  void Initialize(scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
+  void Finalize();
+
+  void AddObserver(Observer* o);
+  void RemoveObserver(Observer* o);
+
+  // TODO(bcf/slan): Add new method:
+  // void GetDevices(Callback<void(vector<scoped_refptr<RemoteDevice>>)> cb);
+
+  // Get a RemoteDevice object corresponding to |addr| for performing GATT
+  // operations. |cb| will be run on the callers thread. Callbacks passed into
+  // methods on RemoteDevice and its subobjects (RemoteService,
+  // RemoteCharacteristic, RemoteDescriptor) will also be run on the thread
+  // which called the specific method.
+  void GetDevice(const bluetooth_v2_shlib::Addr& addr,
+                 base::OnceCallback<void(scoped_refptr<RemoteDevice>)> cb);
+
+  // TODO(bcf): Deprecated. Replace usage with async version.
+  scoped_refptr<RemoteDevice> GetDeviceSync(
+      const bluetooth_v2_shlib::Addr& addr);
+
+  // TODO(bcf): Make async.
+  // Returns the number of devices which are currently connected.
+  size_t GetNumConnected() const;
+
+  void NotifyConnect(const bluetooth_v2_shlib::Addr& addr);
+
+  // TODO(bcf): Deprecated. Should be removed now that this class may be used
+  // from any thread.
+  scoped_refptr<base::SingleThreadTaskRunner> task_runner() {
+    return io_task_runner_;
+  }
+
+  // TODO(bcf): Should be private and passed into objects which need it (e.g.
+  // RemoteDevice, RemoteCharacteristic).
+  bluetooth_v2_shlib::GattClient* gatt_client() const { return gatt_client_; }
+
+ private:
+  // bluetooth_v2_shlib::Gatt::Client::Delegate implementation:
+  void OnConnectChanged(const bluetooth_v2_shlib::Addr& addr,
+                        bool status,
+                        bool connected) override;
+  void OnNotification(const bluetooth_v2_shlib::Addr& addr,
+                      uint16_t handle,
+                      const std::vector<uint8_t>& value) override;
+  void OnCharacteristicReadResponse(const bluetooth_v2_shlib::Addr& addr,
+                                    bool status,
+                                    uint16_t handle,
+                                    const std::vector<uint8_t>& value) override;
+  void OnCharacteristicWriteResponse(const bluetooth_v2_shlib::Addr& addr,
+                                     bool status,
+                                     uint16_t handle) override;
+  void OnDescriptorReadResponse(const bluetooth_v2_shlib::Addr& addr,
+                                bool status,
+                                uint16_t handle,
+                                const std::vector<uint8_t>& value) override;
+  void OnDescriptorWriteResponse(const bluetooth_v2_shlib::Addr& addr,
+                                 bool status,
+                                 uint16_t handle) override;
+  void OnReadRemoteRssi(const bluetooth_v2_shlib::Addr& addr,
+                        bool status,
+                        int rssi) override;
+  void OnMtuChanged(const bluetooth_v2_shlib::Addr& addr,
+                    bool status,
+                    int mtu) override;
+  void OnGetServices(
+      const bluetooth_v2_shlib::Addr& addr,
+      const std::vector<bluetooth_v2_shlib::Gatt::Service>& services) override;
+  void OnServicesRemoved(const bluetooth_v2_shlib::Addr& addr,
+                         uint16_t start_handle,
+                         uint16_t end_handle) override;
+  void OnServicesAdded(
+      const bluetooth_v2_shlib::Addr& addr,
+      const std::vector<bluetooth_v2_shlib::Gatt::Service>& services) override;
+
+  static void FinalizeOnIoThread(
+      std::unique_ptr<base::WeakPtrFactory<GattClientManager>> weak_factory);
+
+  bluetooth_v2_shlib::GattClient* const gatt_client_;
+
+  scoped_refptr<base::ObserverListThreadSafe<Observer>> observers_;
+
+  // All bluetooth_v2_shlib calls are run on this task_runner. Following members
+  // must only be accessed on this task runner.
+  scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
+
+  // TODO(bcf): Need to delete on disconnect.
+  std::map<bluetooth_v2_shlib::Addr, scoped_refptr<RemoteDevice>>
+      addr_to_device_;
+  std::set<bluetooth_v2_shlib::Addr> connected_devices_;
+
+  base::WeakPtr<GattClientManager> weak_this_;
+  std::unique_ptr<base::WeakPtrFactory<GattClientManager>> weak_factory_;
+  DISALLOW_COPY_AND_ASSIGN(GattClientManager);
+};
+
+}  // namespace bluetooth
+}  // namespace chromecast
+
+#endif  // CHROMECAST_DEVICE_BLUETOOTH_LE_GATT_CLIENT_MANAGER_H_
diff --git a/chromecast/device/bluetooth/le/gatt_client_manager_test.cc b/chromecast/device/bluetooth/le/gatt_client_manager_test.cc
new file mode 100644
index 0000000..dac990c78
--- /dev/null
+++ b/chromecast/device/bluetooth/le/gatt_client_manager_test.cc
@@ -0,0 +1,563 @@
+// 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 "chromecast/device/bluetooth/le/gatt_client_manager.h"
+
+#include "base/bind.h"
+#include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "chromecast/device/bluetooth/le/remote_characteristic.h"
+#include "chromecast/device/bluetooth/le/remote_descriptor.h"
+#include "chromecast/device/bluetooth/le/remote_device.h"
+#include "chromecast/device/bluetooth/le/remote_service.h"
+#include "chromecast/device/bluetooth/shlib/mock_gatt_client.h"
+#include "chromecast/internal/device/bluetooth/bluetooth_util.h"
+#include "chromecast/internal/device/bluetooth/test_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+using ::testing::Return;
+
+namespace chromecast {
+namespace bluetooth {
+
+namespace {
+
+const bluetooth_v2_shlib::Addr kTestAddr1 = {
+    {0x00, 0x01, 0x02, 0x03, 0x04, 0x05}};
+
+class MockGattClientManagerObserver : public GattClientManager::Observer {
+ public:
+  MOCK_METHOD2(OnConnectChanged,
+               void(scoped_refptr<RemoteDevice> device, bool connected));
+  MOCK_METHOD2(OnMtuChanged, void(scoped_refptr<RemoteDevice> device, int mtu));
+  MOCK_METHOD2(OnServicesUpdated,
+               void(scoped_refptr<RemoteDevice> device,
+                    std::vector<scoped_refptr<RemoteService>> services));
+  MOCK_METHOD3(OnCharacteristicNotification,
+               void(scoped_refptr<RemoteDevice> device,
+                    scoped_refptr<RemoteCharacteristic> characteristic,
+                    std::vector<uint8_t> value));
+};
+
+std::vector<bluetooth_v2_shlib::Gatt::Service> GenerateServices() {
+  std::vector<bluetooth_v2_shlib::Gatt::Service> ret;
+
+  bluetooth_v2_shlib::Gatt::Service service;
+  bluetooth_v2_shlib::Gatt::Characteristic characteristic;
+  bluetooth_v2_shlib::Gatt::Descriptor descriptor;
+
+  service.uuid = {{0x1}};
+  service.handle = 0x1;
+  service.primary = true;
+
+  characteristic.uuid = {{0x1, 0x1}};
+  characteristic.handle = 0x2;
+  characteristic.permissions =
+      static_cast<bluetooth_v2_shlib::Gatt::Permissions>(
+          bluetooth_v2_shlib::Gatt::PERMISSION_READ |
+          bluetooth_v2_shlib::Gatt::PERMISSION_WRITE);
+  characteristic.properties = bluetooth_v2_shlib::Gatt::PROPERTY_NOTIFY;
+
+  descriptor.uuid = {{0x1, 0x1, 0x1}};
+  descriptor.handle = 0x3;
+  descriptor.permissions = static_cast<bluetooth_v2_shlib::Gatt::Permissions>(
+      bluetooth_v2_shlib::Gatt::PERMISSION_READ |
+      bluetooth_v2_shlib::Gatt::PERMISSION_WRITE);
+  characteristic.descriptors.push_back(descriptor);
+
+  descriptor.uuid = RemoteDescriptor::kCccdUuid;
+  descriptor.handle = 0x4;
+  descriptor.permissions = static_cast<bluetooth_v2_shlib::Gatt::Permissions>(
+      bluetooth_v2_shlib::Gatt::PERMISSION_READ |
+      bluetooth_v2_shlib::Gatt::PERMISSION_WRITE);
+  characteristic.descriptors.push_back(descriptor);
+  service.characteristics.push_back(characteristic);
+
+  characteristic.uuid = {{0x1, 0x2}};
+  characteristic.handle = 0x5;
+  characteristic.permissions =
+      static_cast<bluetooth_v2_shlib::Gatt::Permissions>(
+          bluetooth_v2_shlib::Gatt::PERMISSION_READ |
+          bluetooth_v2_shlib::Gatt::PERMISSION_WRITE);
+  characteristic.properties =
+      static_cast<bluetooth_v2_shlib::Gatt::Properties>(0);
+  characteristic.descriptors.clear();
+
+  ret.push_back(service);
+
+  service.uuid = {{0x2}};
+  service.handle = 0x6;
+  service.primary = true;
+  service.characteristics.clear();
+  ret.push_back(service);
+
+  return ret;
+}
+
+class GattClientManagerTest : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    message_loop_ =
+        std::make_unique<base::MessageLoop>(base::MessageLoop::TYPE_DEFAULT);
+    gatt_client_ = std::make_unique<bluetooth_v2_shlib::MockGattClient>();
+    gatt_client_manager_ =
+        std::make_unique<GattClientManager>(gatt_client_.get());
+    observer_ = std::make_unique<MockGattClientManagerObserver>();
+
+    // Normally bluetooth_manager does this.
+    gatt_client_->SetDelegate(gatt_client_manager_.get());
+    gatt_client_manager_->Initialize(base::ThreadTaskRunnerHandle::Get());
+    gatt_client_manager_->AddObserver(observer_.get());
+  }
+
+  void TearDown() override {
+    gatt_client_->SetDelegate(nullptr);
+    gatt_client_manager_->RemoveObserver(observer_.get());
+    gatt_client_manager_->Finalize();
+  }
+
+  scoped_refptr<RemoteDevice> GetDevice(const bluetooth_v2_shlib::Addr& addr) {
+    scoped_refptr<RemoteDevice> ret;
+    gatt_client_manager_->GetDevice(
+        addr, base::BindOnce(
+                  [](scoped_refptr<RemoteDevice>* ret_ptr,
+                     scoped_refptr<RemoteDevice> result) { *ret_ptr = result; },
+                  &ret));
+
+    return ret;
+  }
+
+  std::vector<scoped_refptr<RemoteService>> GetServices(RemoteDevice* device) {
+    std::vector<scoped_refptr<RemoteService>> ret;
+    device->GetServices(base::BindOnce(
+        [](std::vector<scoped_refptr<RemoteService>>* ret_ptr,
+           std::vector<scoped_refptr<RemoteService>> result) {
+          *ret_ptr = result;
+        },
+        &ret));
+
+    return ret;
+  }
+
+  scoped_refptr<RemoteService> GetServiceByUuid(
+      RemoteDevice* device,
+      const bluetooth_v2_shlib::Uuid& uuid) {
+    scoped_refptr<RemoteService> ret;
+    device->GetServiceByUuid(uuid, base::BindOnce(
+                                       [](scoped_refptr<RemoteService>* ret_ptr,
+                                          scoped_refptr<RemoteService> result) {
+                                         *ret_ptr = result;
+                                       },
+                                       &ret));
+    return ret;
+  }
+
+  void Connect(const bluetooth_v2_shlib::Addr& addr) {
+    EXPECT_CALL(*gatt_client_, Connect(addr)).WillOnce(Return(true));
+    scoped_refptr<RemoteDevice> device = GetDevice(addr);
+    cb_checker_.Reset();
+    device->Connect(cb_checker_.CreateCallback());
+    bluetooth_v2_shlib::Gatt::Client::Delegate* delegate =
+        gatt_client_->delegate();
+    delegate->OnConnectChanged(addr, true /* status */, true /* connected */);
+    ASSERT_TRUE(cb_checker_.called());
+    ASSERT_TRUE(cb_checker_.status());
+    ASSERT_TRUE(device->IsConnected());
+  }
+
+  StatusCallbackChecker cb_checker_;
+  std::unique_ptr<base::MessageLoop> message_loop_;
+  std::unique_ptr<GattClientManager> gatt_client_manager_;
+  std::unique_ptr<bluetooth_v2_shlib::MockGattClient> gatt_client_;
+  std::unique_ptr<MockGattClientManagerObserver> observer_;
+};
+
+}  // namespace
+
+TEST_F(GattClientManagerTest, RemoteDeviceConnect) {
+  bluetooth_v2_shlib::Gatt::Client::Delegate* delegate =
+      gatt_client_->delegate();
+
+  scoped_refptr<RemoteDevice> device = GetDevice(kTestAddr1);
+  EXPECT_FALSE(device->IsConnected());
+  EXPECT_EQ(kTestAddr1, device->addr());
+
+  // These should fail if we're not connected.
+  cb_checker_.Reset();
+  device->Disconnect(cb_checker_.CreateCallback());
+  EXPECT_TRUE(cb_checker_.called());
+  EXPECT_FALSE(cb_checker_.status());
+
+  {
+    bool called = false;
+    bool status = false;
+    device->ReadRemoteRssi(base::BindOnce(
+        [](bool* pcalled, bool* pstatus, bool status, int rssi) {
+          *pcalled = true;
+          *pstatus = status;
+        },
+        &called, &status));
+    EXPECT_TRUE(called);
+    EXPECT_FALSE(status);
+  }
+
+  cb_checker_.Reset();
+  device->RequestMtu(512, cb_checker_.CreateCallback());
+  EXPECT_TRUE(cb_checker_.called());
+  EXPECT_FALSE(cb_checker_.status());
+
+  cb_checker_.Reset();
+  device->ConnectionParameterUpdate(10, 10, 50, 100,
+                                    cb_checker_.CreateCallback());
+  EXPECT_TRUE(cb_checker_.called());
+  EXPECT_FALSE(cb_checker_.status());
+
+  {
+    bool called = false;
+    bool status = false;
+    device->DiscoverServices(base::BindOnce(
+        [](bool* pstatus, bool* pcalled, bool status,
+           std::vector<scoped_refptr<RemoteService>> services) {
+          *pcalled = true;
+          *pstatus = status;
+        },
+        &status, &called));
+    EXPECT_TRUE(called);
+    EXPECT_FALSE(status);
+  }
+
+  EXPECT_CALL(*gatt_client_, Connect(kTestAddr1)).WillOnce(Return(true));
+
+  cb_checker_.Reset();
+  device->Connect(cb_checker_.CreateCallback());
+  EXPECT_FALSE(device->IsConnected());
+  EXPECT_CALL(*observer_, OnConnectChanged(device, true));
+  delegate->OnConnectChanged(kTestAddr1, true /* status */,
+                             true /* connected */);
+  EXPECT_TRUE(cb_checker_.called());
+  EXPECT_TRUE(cb_checker_.status());
+
+  EXPECT_TRUE(device->IsConnected());
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_CALL(*gatt_client_, Disconnect(kTestAddr1)).WillOnce(Return(true));
+  device->Disconnect({});
+  EXPECT_TRUE(device->IsConnected());
+
+  EXPECT_CALL(*observer_, OnConnectChanged(device, false));
+  delegate->OnConnectChanged(kTestAddr1, true /* status */,
+                             false /* connected */);
+  EXPECT_FALSE(device->IsConnected());
+  base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(GattClientManagerTest, RemoteDeviceReadRssi) {
+  static const int kRssi = -34;
+
+  bluetooth_v2_shlib::Gatt::Client::Delegate* delegate =
+      gatt_client_->delegate();
+  scoped_refptr<RemoteDevice> device = GetDevice(kTestAddr1);
+
+  Connect(kTestAddr1);
+
+  bool rssi_cb_called = false;
+  auto rssi_cb = [](bool* cb_called, bool status, int rssi) {
+    *cb_called = true;
+    EXPECT_TRUE(status);
+    EXPECT_EQ(kRssi, rssi);
+  };
+
+  EXPECT_CALL(*gatt_client_, ReadRemoteRssi(kTestAddr1)).WillOnce(Return(true));
+  device->ReadRemoteRssi(base::BindOnce(rssi_cb, &rssi_cb_called));
+
+  delegate->OnReadRemoteRssi(kTestAddr1, true /* status */, kRssi);
+  EXPECT_TRUE(rssi_cb_called);
+}
+
+TEST_F(GattClientManagerTest, RemoteDeviceRequestMtu) {
+  static const int kMtu = 512;
+  bluetooth_v2_shlib::Gatt::Client::Delegate* delegate =
+      gatt_client_->delegate();
+  scoped_refptr<RemoteDevice> device = GetDevice(kTestAddr1);
+  Connect(kTestAddr1);
+
+  EXPECT_EQ(RemoteDevice::kDefaultMtu, device->GetMtu());
+  EXPECT_CALL(*gatt_client_, RequestMtu(kTestAddr1, kMtu))
+      .WillOnce(Return(true));
+  cb_checker_.Reset();
+  device->RequestMtu(kMtu, cb_checker_.CreateCallback());
+  EXPECT_CALL(*observer_, OnMtuChanged(device, kMtu));
+  delegate->OnMtuChanged(kTestAddr1, true, kMtu);
+  EXPECT_TRUE(cb_checker_.called());
+  EXPECT_TRUE(cb_checker_.status());
+  EXPECT_EQ(kMtu, device->GetMtu());
+  base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(GattClientManagerTest, RemoteDeviceConnectionParameterUpdate) {
+  const int kMinInterval = 10;
+  const int kMaxInterval = 10;
+  const int kLatency = 50;
+  const int kTimeout = 100;
+
+  Connect(kTestAddr1);
+
+  scoped_refptr<RemoteDevice> device = GetDevice(kTestAddr1);
+  EXPECT_CALL(*gatt_client_,
+              ConnectionParameterUpdate(kTestAddr1, kMinInterval, kMaxInterval,
+                                        kLatency, kTimeout))
+      .WillOnce(Return(true));
+  cb_checker_.Reset();
+  device->ConnectionParameterUpdate(kMinInterval, kMaxInterval, kLatency,
+                                    kTimeout, cb_checker_.CreateCallback());
+  EXPECT_TRUE(cb_checker_.called());
+  EXPECT_TRUE(cb_checker_.status());
+}
+
+TEST_F(GattClientManagerTest, RemoteDeviceServices) {
+  const auto kServices = GenerateServices();
+  Connect(kTestAddr1);
+  scoped_refptr<RemoteDevice> device = GetDevice(kTestAddr1);
+  EXPECT_EQ(0ul, GetServices(device.get()).size());
+
+  EXPECT_CALL(*gatt_client_, GetServices(kTestAddr1)).WillOnce(Return(true));
+
+  bool status = false;
+  std::vector<scoped_refptr<RemoteService>> services;
+  device->DiscoverServices(base::BindOnce(
+      [](bool* pstatus, std::vector<scoped_refptr<RemoteService>>* pservices,
+         bool status, std::vector<scoped_refptr<RemoteService>> services) {
+        *pstatus = status;
+        *pservices = services;
+      },
+      &status, &services));
+  EXPECT_CALL(*observer_, OnServicesUpdated(device, _));
+  bluetooth_v2_shlib::Gatt::Client::Delegate* delegate =
+      gatt_client_->delegate();
+  delegate->OnServicesAdded(kTestAddr1, kServices);
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(status);
+
+  EXPECT_EQ(kServices.size(), GetServices(device.get()).size());
+  for (const auto& service : kServices) {
+    scoped_refptr<RemoteService> remote_service =
+        GetServiceByUuid(device.get(), service.uuid);
+    ASSERT_TRUE(remote_service);
+    EXPECT_EQ(service.uuid, remote_service->uuid());
+    EXPECT_EQ(service.handle, remote_service->handle());
+    EXPECT_EQ(service.primary, remote_service->primary());
+    EXPECT_EQ(service.characteristics.size(),
+              remote_service->GetCharacteristics().size());
+
+    for (const auto& characteristic : service.characteristics) {
+      scoped_refptr<RemoteCharacteristic> remote_char =
+          remote_service->GetCharacteristicByUuid(characteristic.uuid);
+      ASSERT_TRUE(remote_char);
+      EXPECT_EQ(characteristic.uuid, remote_char->uuid());
+      EXPECT_EQ(characteristic.handle, remote_char->handle());
+      EXPECT_EQ(characteristic.permissions, remote_char->permissions());
+      EXPECT_EQ(characteristic.properties, remote_char->properties());
+      EXPECT_EQ(characteristic.descriptors.size(),
+                remote_char->GetDescriptors().size());
+
+      for (const auto& descriptor : characteristic.descriptors) {
+        scoped_refptr<RemoteDescriptor> remote_desc =
+            remote_char->GetDescriptorByUuid(descriptor.uuid);
+        ASSERT_TRUE(remote_desc);
+        EXPECT_EQ(descriptor.uuid, remote_desc->uuid());
+        EXPECT_EQ(descriptor.handle, remote_desc->handle());
+        EXPECT_EQ(descriptor.permissions, remote_desc->permissions());
+      }
+    }
+  }
+}
+
+TEST_F(GattClientManagerTest, RemoteDeviceCharacteristic) {
+  const std::vector<uint8_t> kTestData1 = {0x1, 0x2, 0x3};
+  const std::vector<uint8_t> kTestData2 = {0x4, 0x5, 0x6};
+  const std::vector<uint8_t> kTestData3 = {0x7, 0x8, 0x9};
+  const auto kServices = GenerateServices();
+  const bluetooth_v2_shlib::Gatt::Client::AuthReq kAuthReq =
+      bluetooth_v2_shlib::Gatt::Client::AUTH_REQ_MITM;
+  const bluetooth_v2_shlib::Gatt::WriteType kWriteType =
+      bluetooth_v2_shlib::Gatt::WRITE_TYPE_DEFAULT;
+
+  Connect(kTestAddr1);
+  scoped_refptr<RemoteDevice> device = GetDevice(kTestAddr1);
+  bluetooth_v2_shlib::Gatt::Client::Delegate* delegate =
+      gatt_client_->delegate();
+  delegate->OnServicesAdded(kTestAddr1, kServices);
+  std::vector<scoped_refptr<RemoteService>> services =
+      GetServices(device.get());
+  ASSERT_EQ(kServices.size(), services.size());
+
+  auto service = services[0];
+  std::vector<scoped_refptr<RemoteCharacteristic>> characteristics =
+      service->GetCharacteristics();
+  ASSERT_GE(characteristics.size(), 1ul);
+  auto characteristic = characteristics[0];
+
+  EXPECT_CALL(*gatt_client_,
+              WriteCharacteristic(kTestAddr1, characteristic->characteristic(),
+                                  kAuthReq, kWriteType, kTestData1))
+      .WillOnce(Return(true));
+
+  bool write_cb_called = false;
+  auto write_cb = base::BindOnce(
+      [](bool* cb_called, bool status) {
+        *cb_called = true;
+        DCHECK(status);
+      },
+      &write_cb_called);
+
+  characteristic->WriteAuth(kAuthReq, kWriteType, kTestData1,
+                            std::move(write_cb));
+  delegate->OnCharacteristicWriteResponse(kTestAddr1, true,
+                                          characteristic->handle());
+  EXPECT_TRUE(write_cb_called);
+
+  EXPECT_CALL(*gatt_client_,
+              ReadCharacteristic(kTestAddr1, characteristic->characteristic(),
+                                 kAuthReq))
+      .WillOnce(Return(true));
+
+  bool cb_called = false;
+  auto read_cb = [](bool* cb_called, const std::vector<uint8_t>& expected,
+                    bool success, const std::vector<uint8_t>& value) {
+    *cb_called = true;
+    EXPECT_TRUE(success);
+    EXPECT_EQ(expected, value);
+  };
+  characteristic->ReadAuth(kAuthReq,
+                           base::BindOnce(read_cb, &cb_called, kTestData2));
+  delegate->OnCharacteristicReadResponse(kTestAddr1, true,
+                                         characteristic->handle(), kTestData2);
+  EXPECT_TRUE(cb_called);
+
+  EXPECT_CALL(*gatt_client_,
+              SetCharacteristicNotification(
+                  kTestAddr1, characteristic->characteristic(), true))
+      .WillOnce(Return(true));
+
+  cb_checker_.Reset();
+  characteristic->SetNotification(true, cb_checker_.CreateCallback());
+  EXPECT_TRUE(cb_checker_.called());
+  EXPECT_TRUE(cb_checker_.status());
+
+  EXPECT_CALL(*observer_,
+              OnCharacteristicNotification(device, characteristic, kTestData3));
+  delegate->OnNotification(kTestAddr1, characteristic->handle(), kTestData3);
+  base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(GattClientManagerTest,
+       RemoteDeviceCharacteristicSetRegisterNotification) {
+  const std::vector<uint8_t> kTestData1 = {0x1, 0x2, 0x3};
+  const auto kServices = GenerateServices();
+  Connect(kTestAddr1);
+  scoped_refptr<RemoteDevice> device = GetDevice(kTestAddr1);
+  bluetooth_v2_shlib::Gatt::Client::Delegate* delegate =
+      gatt_client_->delegate();
+  delegate->OnServicesAdded(kTestAddr1, kServices);
+  std::vector<scoped_refptr<RemoteService>> services =
+      GetServices(device.get());
+  ASSERT_EQ(kServices.size(), services.size());
+
+  scoped_refptr<RemoteService> service = services[0];
+  std::vector<scoped_refptr<RemoteCharacteristic>> characteristics =
+      service->GetCharacteristics();
+  ASSERT_GE(characteristics.size(), 1ul);
+  scoped_refptr<RemoteCharacteristic> characteristic = characteristics[0];
+
+  scoped_refptr<RemoteDescriptor> cccd =
+      characteristic->GetDescriptorByUuid(RemoteDescriptor::kCccdUuid);
+  ASSERT_TRUE(cccd);
+
+  EXPECT_CALL(*gatt_client_,
+              SetCharacteristicNotification(
+                  kTestAddr1, characteristic->characteristic(), true))
+      .WillOnce(Return(true));
+  std::vector<uint8_t> cccd_enable_notification = {
+      std::begin(bluetooth::RemoteDescriptor::kEnableNotificationValue),
+      std::end(bluetooth::RemoteDescriptor::kEnableNotificationValue)};
+  EXPECT_CALL(*gatt_client_, WriteDescriptor(kTestAddr1, cccd->descriptor(), _,
+                                             cccd_enable_notification))
+      .WillOnce(Return(true));
+
+  StatusCallbackChecker cb_checker;
+  characteristic->SetRegisterNotification(true, cb_checker.CreateCallback());
+  delegate->OnDescriptorWriteResponse(kTestAddr1, true, cccd->handle());
+  EXPECT_TRUE(cb_checker.called());
+  EXPECT_TRUE(cb_checker.status());
+
+  EXPECT_CALL(*observer_,
+              OnCharacteristicNotification(device, characteristic, kTestData1));
+  delegate->OnNotification(kTestAddr1, characteristic->handle(), kTestData1);
+  base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(GattClientManagerTest, RemoteDeviceDescriptor) {
+  const std::vector<uint8_t> kTestData1 = {0x1, 0x2, 0x3};
+  const std::vector<uint8_t> kTestData2 = {0x4, 0x5, 0x6};
+  const bluetooth_v2_shlib::Gatt::Client::AuthReq kAuthReq =
+      bluetooth_v2_shlib::Gatt::Client::AUTH_REQ_MITM;
+  const auto kServices = GenerateServices();
+  Connect(kTestAddr1);
+  scoped_refptr<RemoteDevice> device = GetDevice(kTestAddr1);
+  bluetooth_v2_shlib::Gatt::Client::Delegate* delegate =
+      gatt_client_->delegate();
+  delegate->OnServicesAdded(kTestAddr1, kServices);
+  std::vector<scoped_refptr<RemoteService>> services =
+      GetServices(device.get());
+  ASSERT_EQ(kServices.size(), services.size());
+
+  auto service = services[0];
+  std::vector<scoped_refptr<RemoteCharacteristic>> characteristics =
+      service->GetCharacteristics();
+  ASSERT_GE(characteristics.size(), 1ul);
+  auto characteristic = characteristics[0];
+
+  std::vector<scoped_refptr<RemoteDescriptor>> descriptors =
+      characteristic->GetDescriptors();
+  ASSERT_GE(descriptors.size(), 1ul);
+  auto descriptor = descriptors[0];
+
+  EXPECT_CALL(*gatt_client_,
+              WriteDescriptor(kTestAddr1, descriptor->descriptor(), kAuthReq,
+                              kTestData1))
+      .WillOnce(Return(true));
+  bool write_cb_called = false;
+  auto write_cb = base::BindOnce(
+      [](bool* cb_called, bool status) {
+        *cb_called = true;
+        DCHECK(status);
+      },
+      &write_cb_called);
+  descriptor->WriteAuth(kAuthReq, kTestData1, std::move(write_cb));
+  delegate->OnDescriptorWriteResponse(kTestAddr1, true, descriptor->handle());
+  EXPECT_TRUE(write_cb_called);
+
+  EXPECT_CALL(*gatt_client_,
+              ReadDescriptor(kTestAddr1, descriptor->descriptor(), kAuthReq))
+      .WillOnce(Return(true));
+
+  bool cb_called = false;
+  auto read_cb = [](bool* cb_called, const std::vector<uint8_t>& expected,
+                    bool success, const std::vector<uint8_t>& value) {
+    *cb_called = true;
+    EXPECT_TRUE(success);
+    EXPECT_EQ(expected, value);
+  };
+  descriptor->ReadAuth(kAuthReq,
+                       base::BindOnce(read_cb, &cb_called, kTestData2));
+  delegate->OnDescriptorReadResponse(kTestAddr1, true, descriptor->handle(),
+                                     kTestData2);
+  EXPECT_TRUE(cb_called);
+}
+
+}  // namespace bluetooth
+}  // namespace chromecast
diff --git a/chromecast/device/bluetooth/le/le_scan_manager.cc b/chromecast/device/bluetooth/le/le_scan_manager.cc
new file mode 100644
index 0000000..92e1457
--- /dev/null
+++ b/chromecast/device/bluetooth/le/le_scan_manager.cc
@@ -0,0 +1,227 @@
+// 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 "chromecast/device/bluetooth/le/le_scan_manager.h"
+
+#include <algorithm>
+
+#include "chromecast/base/bind_to_task_runner.h"
+#include "chromecast/public/cast_media_shlib.h"
+
+#define RUN_ON_IO_THREAD(method, ...)                   \
+  io_task_runner_->PostTask(                            \
+      FROM_HERE, base::BindOnce(&LeScanManager::method, \
+                                weak_factory_.GetWeakPtr(), ##__VA_ARGS__));
+
+#define MAKE_SURE_IO_THREAD(method, ...)            \
+  DCHECK(io_task_runner_);                          \
+  if (!io_task_runner_->BelongsToCurrentThread()) { \
+    RUN_ON_IO_THREAD(method, ##__VA_ARGS__)         \
+    return;                                         \
+  }
+
+#define EXEC_CB_AND_RET(cb, ret, ...)        \
+  do {                                       \
+    if (cb) {                                \
+      std::move(cb).Run(ret, ##__VA_ARGS__); \
+    }                                        \
+    return;                                  \
+  } while (0)
+
+namespace chromecast {
+namespace bluetooth {
+
+namespace {
+
+// http://www.argenox.com/bluetooth-low-energy-ble-v4-0-development/library/a-ble-advertising-primer/
+const uint8_t kGapFlags = 0x01;
+const uint8_t kGapIncomplete16BitServiceUuids = 0x02;
+const uint8_t kGapComplete16BitServiceUuids = 0x03;
+const uint8_t kGapShortName = 0x08;
+const uint8_t kGapCompleteName = 0x09;
+
+const int kMaxMessagesInQueue = 5;
+
+bool DataContainsUuid(const std::vector<uint8_t>& data, uint16_t uuid) {
+  if (data.size() % 2 != 0) {
+    LOG(ERROR) << "Malformed service UUID data";
+    return false;
+  }
+  for (size_t i = 0; i < data.size(); i += 2) {
+    // Uuids are transmitted in little endian byte order (i.e. 0x1827 is
+    // transmitted as 0x27, 0x18), so we have to reverse the order on
+    // reconstruction. See Bluetooth Core Specification v4.0 Vol 3 Part C
+    // Section 11.1 for reference.
+    uint16_t uuid_from_data = ((uint16_t)data[i + 1] << 8) | data[i];
+    if (uuid_from_data == uuid) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool ScanResultHasServiceUuid(const LeScanManager::ScanResult& scan_result,
+                              uint16_t service_uuid) {
+  auto it = scan_result.type_to_data.find(kGapIncomplete16BitServiceUuids);
+  if (it != scan_result.type_to_data.end() &&
+      DataContainsUuid(it->second, service_uuid)) {
+    return true;
+  }
+
+  it = scan_result.type_to_data.find(kGapComplete16BitServiceUuids);
+  if (it != scan_result.type_to_data.end() &&
+      DataContainsUuid(it->second, service_uuid)) {
+    return true;
+  }
+
+  return false;
+}
+
+}  // namespace
+
+LeScanManager::ScanResult::ScanResult() = default;
+LeScanManager::ScanResult::ScanResult(const LeScanManager::ScanResult& other) =
+    default;
+LeScanManager::ScanResult::~ScanResult() = default;
+
+LeScanManager::LeScanManager(bluetooth_v2_shlib::LeScannerImpl* le_scanner)
+    : le_scanner_(le_scanner),
+      observers_(new base::ObserverListThreadSafe<Observer>()),
+      weak_factory_(this) {}
+
+LeScanManager::~LeScanManager() = default;
+
+void LeScanManager::Initialize(
+    scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) {
+  io_task_runner_ = std::move(io_task_runner);
+}
+
+void LeScanManager::Finalize() {}
+
+void LeScanManager::AddObserver(Observer* observer) {
+  observers_->AddObserver(observer);
+}
+
+void LeScanManager::RemoveObserver(Observer* observer) {
+  observers_->RemoveObserver(observer);
+}
+
+void LeScanManager::SetScanEnable(bool enable, SetScanEnableCallback cb) {
+  MAKE_SURE_IO_THREAD(SetScanEnable, enable,
+                      BindToCurrentThread(std::move(cb)));
+  bool success;
+  if (enable) {
+    success = le_scanner_->StartScan();
+  } else {
+    success = le_scanner_->StopScan();
+  }
+
+  if (!success) {
+    LOG(ERROR) << "Failed to " << (enable ? "enable" : "disable")
+               << " ble scanning";
+    EXEC_CB_AND_RET(cb, false);
+  }
+
+  observers_->Notify(FROM_HERE, &Observer::OnScanEnableChanged, enable);
+  EXEC_CB_AND_RET(cb, true);
+}
+
+void LeScanManager::GetScanResults(GetScanResultsCallback cb,
+                                   base::Optional<uint16_t> service_uuid) {
+  MAKE_SURE_IO_THREAD(GetScanResults, BindToCurrentThread(std::move(cb)),
+                      service_uuid);
+  std::move(cb).Run(GetScanResultsInternal(service_uuid));
+}
+
+// Returns a list of all scan results. The results are sorted by RSSI.
+std::vector<LeScanManager::ScanResult> LeScanManager::GetScanResultsInternal(
+    base::Optional<uint16_t> service_uuid) {
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+  std::vector<ScanResult> results;
+  for (const auto& pair : addr_to_scan_results_) {
+    for (const auto& scan_result : pair.second) {
+      if (!service_uuid ||
+          ScanResultHasServiceUuid(scan_result, *service_uuid)) {
+        results.push_back(scan_result);
+      }
+    }
+  }
+
+  std::sort(results.begin(), results.end(),
+            [](const ScanResult& d1, const ScanResult& d2) {
+              return d1.rssi > d2.rssi;
+            });
+
+  return results;
+}
+
+void LeScanManager::ClearScanResults() {
+  MAKE_SURE_IO_THREAD(ClearScanResults);
+  addr_to_scan_results_.clear();
+}
+
+void LeScanManager::OnScanResult(
+    const bluetooth_v2_shlib::LeScanner::ScanResult& scan_result_shlib) {
+  ScanResult scan_result;
+  scan_result.addr = scan_result_shlib.addr;
+  scan_result.adv_data = scan_result_shlib.adv_data;
+  scan_result.rssi = scan_result_shlib.rssi;
+
+  const char* as_char =
+      reinterpret_cast<const char*>(scan_result.adv_data.data());
+
+  size_t i = 0;
+  while (i < scan_result.adv_data.size()) {
+    if (i + 1 == scan_result.adv_data.size()) {
+      LOG(ERROR) << "Malformed BLE packet";
+      return;
+    }
+
+    // http://www.argenox.com/bluetooth-low-energy-ble-v4-0-development/library/a-ble-advertising-primer/
+    // Format:
+    // [size][type][payload     ]
+    // [i   ][i+1 ][i+2:i+1+size]
+    //
+    // Note: size does not include its own byte
+    uint8_t size = scan_result.adv_data[i];
+    uint8_t type = scan_result.adv_data[i + 1];
+
+    // Avoid infinite loop if invalid data
+    if (size == 0 || i + 1 + size > scan_result.adv_data.size()) {
+      LOG(ERROR) << "Invalid size";
+      return;
+    }
+
+    if (type == kGapCompleteName ||
+        (type == kGapShortName && scan_result.name.empty())) {
+      scan_result.name.assign(as_char + i + 2, size - 1);
+    } else if (type == kGapFlags) {
+      scan_result.flags = scan_result.adv_data[i + 2];
+    }
+
+    std::vector<uint8_t> data(scan_result.adv_data.begin() + i + 2,
+                              scan_result.adv_data.begin() + i + 1 + size);
+    scan_result.type_to_data[type] = std::move(data);
+
+    i += (size + 1);
+  }
+
+  // Remove results with the same data as the current result to avoid duplicate
+  // messages in the queue
+  auto& previous_scan_results = addr_to_scan_results_[scan_result.addr];
+  previous_scan_results.remove_if([&scan_result](const auto& previous_result) {
+    return previous_result.adv_data == scan_result.adv_data;
+  });
+
+  previous_scan_results.push_front(scan_result);
+  if (previous_scan_results.size() > kMaxMessagesInQueue) {
+    previous_scan_results.pop_back();
+  }
+
+  // Update observers.
+  observers_->Notify(FROM_HERE, &Observer::OnNewScanResult, scan_result);
+}
+
+}  // namespace bluetooth
+}  // namespace chromecast
diff --git a/chromecast/device/bluetooth/le/le_scan_manager.h b/chromecast/device/bluetooth/le/le_scan_manager.h
new file mode 100644
index 0000000..49dec84
--- /dev/null
+++ b/chromecast/device/bluetooth/le/le_scan_manager.h
@@ -0,0 +1,99 @@
+// 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 CHROMECAST_DEVICE_BLUETOOTH_LE_LE_SCAN_MANAGER_H_
+#define CHROMECAST_DEVICE_BLUETOOTH_LE_LE_SCAN_MANAGER_H_
+
+#include <list>
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/observer_list_threadsafe.h"
+#include "chromecast/device/bluetooth/shlib/le_scanner.h"
+
+namespace chromecast {
+namespace bluetooth {
+
+class LeScanManager : public bluetooth_v2_shlib::LeScanner::Delegate {
+ public:
+  struct ScanResult {
+    ScanResult();
+    ScanResult(const ScanResult& other);
+    ~ScanResult();
+
+    bluetooth_v2_shlib::Addr addr;
+    std::vector<uint8_t> adv_data;
+    int rssi = -255;
+
+    std::string name;
+    uint8_t flags = 0;
+    std::map<uint8_t, std::vector<uint8_t>> type_to_data;
+  };
+
+  class Observer {
+   public:
+    // Called when the scan has been enabled or disabled.
+    virtual void OnScanEnableChanged(bool enabled) {}
+
+    // Called when a new scan result is ready.
+    virtual void OnNewScanResult(ScanResult result) {}
+
+    virtual ~Observer() = default;
+  };
+
+  explicit LeScanManager(bluetooth_v2_shlib::LeScannerImpl* le_scanner);
+  ~LeScanManager() override;
+
+  void Initialize(scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
+  void Finalize();
+
+  void AddObserver(Observer* o);
+  void RemoveObserver(Observer* o);
+
+  // Enable or disable BLE scnaning. Can be called on any thread. |cb| is
+  // called on the thread that calls this method. |success| is false iff the
+  // operation failed.
+  using SetScanEnableCallback = base::OnceCallback<void(bool success)>;
+  void SetScanEnable(bool enable, SetScanEnableCallback cb);
+
+  // Asynchronously get the most recent scan results. Can be called on any
+  // thread. |cb| is called on the calling thread with the results. If
+  // |service_uuid| is passed, only scan results advertising the given
+  // |service_uuid| will be returned.
+  using GetScanResultsCallback =
+      base::OnceCallback<void(std::vector<ScanResult>)>;
+  void GetScanResults(GetScanResultsCallback cb,
+                      base::Optional<uint16_t> service_uuid = base::nullopt);
+
+  void ClearScanResults();
+
+ private:
+  // Returns a list of all BLE scan results. The results are sorted by RSSI.
+  // Must be called on |io_task_runner|.
+  std::vector<ScanResult> GetScanResultsInternal(
+      base::Optional<uint16_t> service_uuid);
+
+  // bluetooth_v2_shlib::LeScanner::Delegate implementation:
+  void OnScanResult(const bluetooth_v2_shlib::LeScanner::ScanResult&
+                        scan_result_shlib) override;
+
+  bluetooth_v2_shlib::LeScannerImpl* const le_scanner_;
+  scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
+
+  scoped_refptr<base::ObserverListThreadSafe<Observer>> observers_;
+  std::map<bluetooth_v2_shlib::Addr, std::list<ScanResult>>
+      addr_to_scan_results_;
+
+  base::WeakPtrFactory<LeScanManager> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(LeScanManager);
+};
+
+}  // namespace bluetooth
+}  // namespace chromecast
+
+#endif  // CHROMECAST_DEVICE_BLUETOOTH_LE_LE_SCAN_MANAGER_H_
diff --git a/chromecast/device/bluetooth/le/le_scan_manager_test.cc b/chromecast/device/bluetooth/le/le_scan_manager_test.cc
new file mode 100644
index 0000000..285b852
--- /dev/null
+++ b/chromecast/device/bluetooth/le/le_scan_manager_test.cc
@@ -0,0 +1,279 @@
+// 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 "chromecast/device/bluetooth/le/le_scan_manager.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/memory/ptr_util.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "chromecast/device/bluetooth/le/remote_characteristic.h"
+#include "chromecast/device/bluetooth/le/remote_descriptor.h"
+#include "chromecast/device/bluetooth/le/remote_device.h"
+#include "chromecast/device/bluetooth/le/remote_service.h"
+#include "chromecast/device/bluetooth/shlib/mock_gatt_client.h"
+#include "chromecast/internal/device/bluetooth/bluetooth_util.h"
+#include "chromecast/internal/device/bluetooth/test_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+using ::testing::Invoke;
+using ::testing::Return;
+
+namespace chromecast {
+namespace bluetooth {
+
+namespace {
+
+const bluetooth_v2_shlib::Addr kTestAddr1 = {
+    {0x00, 0x01, 0x02, 0x03, 0x04, 0x05}};
+const bluetooth_v2_shlib::Addr kTestAddr2 = {
+    {0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B}};
+
+// This hack is needed because base::BindOnce does not support capture lambdas.
+template <typename T>
+void CopyResult(T* out, T in) {
+  *out = in;
+}
+
+class FakeLeScannerImpl : public bluetooth_v2_shlib::LeScannerImpl {
+ public:
+  FakeLeScannerImpl() {}
+  ~FakeLeScannerImpl() override = default;
+
+  // bluetooth_v2_shlib::LeScannerImpl implementation:
+  bool IsSupported() override { return true; }
+  void SetDelegate(bluetooth_v2_shlib::LeScanner::Delegate* delegate) override {
+  }
+  bool StartScan() override { return true; }
+  bool StopScan() override { return true; }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(FakeLeScannerImpl);
+};
+
+class MockLeScanManagerObserver : public LeScanManager::Observer {
+ public:
+  MOCK_METHOD1(OnScanEnableChanged, void(bool enabled));
+  MOCK_METHOD1(OnNewScanResult, void(LeScanManager::ScanResult result));
+};
+
+class LeScanManagerTest : public ::testing::Test {
+ protected:
+  LeScanManagerTest()
+      : io_task_runner_(base::CreateSingleThreadTaskRunnerWithTraits(
+            {base::TaskPriority::BACKGROUND, base::MayBlock()})),
+        le_scan_manager_(&fake_le_scan_manager_impl_) {}
+  ~LeScanManagerTest() override {}
+
+  // testing::Test implementation:
+  void SetUp() override {
+    le_scan_manager_.Initialize(io_task_runner_);
+    le_scan_manager_.AddObserver(&mock_observer_);
+    scoped_task_environment_.RunUntilIdle();
+  }
+
+  void TearDown() override {
+    le_scan_manager_.RemoveObserver(&mock_observer_);
+    le_scan_manager_.Finalize();
+  }
+
+  bluetooth_v2_shlib::LeScanner::Delegate* delegate() {
+    return &le_scan_manager_;
+  }
+
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
+  scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
+  FakeLeScannerImpl fake_le_scan_manager_impl_;
+  LeScanManager le_scan_manager_;
+  MockLeScanManagerObserver mock_observer_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(LeScanManagerTest);
+};
+
+}  // namespace
+
+TEST_F(LeScanManagerTest, TestSetScanEnable) {
+  bool enabled = false;
+  EXPECT_CALL(mock_observer_, OnScanEnableChanged(true));
+
+  // Enable the LE scan. We expect the observer to be updated and the callback
+  // to be called with success=true.
+  le_scan_manager_.SetScanEnable(true, /* enable */
+                                 base::BindOnce(&CopyResult<bool>, &enabled));
+
+  scoped_task_environment_.RunUntilIdle();
+  ASSERT_TRUE(enabled);
+}
+
+TEST_F(LeScanManagerTest, TestGetScanResultsEmpty) {
+  std::vector<LeScanManager::ScanResult> results;
+
+  // Get asynchronous scan results. The result should be empty.
+  le_scan_manager_.GetScanResults(base::BindOnce(
+      &CopyResult<std::vector<LeScanManager::ScanResult>>, &results));
+
+  scoped_task_environment_.RunUntilIdle();
+  ASSERT_EQ(0u, results.size());
+}
+
+TEST_F(LeScanManagerTest, TestGetScanResults) {
+  // Simulate some scan results.
+  bluetooth_v2_shlib::LeScanner::ScanResult raw_scan_result;
+  raw_scan_result.addr = kTestAddr1;
+  raw_scan_result.rssi = 1234;
+
+  EXPECT_CALL(mock_observer_, OnNewScanResult(_));
+  delegate()->OnScanResult(raw_scan_result);
+  scoped_task_environment_.RunUntilIdle();
+
+  std::vector<LeScanManager::ScanResult> results;
+  // Get asynchronous scan results.
+  le_scan_manager_.GetScanResults(base::BindOnce(
+      &CopyResult<std::vector<LeScanManager::ScanResult>>, &results));
+
+  scoped_task_environment_.RunUntilIdle();
+
+  ASSERT_EQ(1u, results.size());
+  ASSERT_EQ(kTestAddr1, results[0].addr);
+  ASSERT_EQ(1234, results[0].rssi);
+}
+
+TEST_F(LeScanManagerTest, TestGetScanResultsWithService) {
+  EXPECT_CALL(mock_observer_, OnNewScanResult(_)).Times(2);
+
+  // Add a scan result with service 0x4444.
+  bluetooth_v2_shlib::LeScanner::ScanResult raw_scan_result;
+  raw_scan_result.addr = kTestAddr1;
+  raw_scan_result.adv_data = {0x03, 0x02, 0x44, 0x44};
+  raw_scan_result.rssi = 1234;
+  delegate()->OnScanResult(raw_scan_result);
+
+  // Add a scan result with service 0x5555.
+  raw_scan_result.addr = kTestAddr2;
+  raw_scan_result.adv_data = {0x03, 0x02, 0x55, 0x55};
+  raw_scan_result.rssi = 1234;
+  delegate()->OnScanResult(raw_scan_result);
+
+  scoped_task_environment_.RunUntilIdle();
+
+  // Get asynchronous scan results for results with service 0x4444.
+  std::vector<LeScanManager::ScanResult> results;
+  le_scan_manager_.GetScanResults(
+      base::BindOnce(&CopyResult<std::vector<LeScanManager::ScanResult>>,
+                     &results),
+      0x4444);
+  scoped_task_environment_.RunUntilIdle();
+
+  ASSERT_EQ(1u, results.size());
+  ASSERT_EQ(kTestAddr1, results[0].addr);
+  ASSERT_EQ(std::vector<uint8_t>({0x44, 0x44}), results[0].type_to_data[0x02]);
+  ASSERT_EQ(1234, results[0].rssi);
+
+  // Get asynchronous scan results for results with service 0x5555.
+  le_scan_manager_.GetScanResults(
+      base::BindOnce(&CopyResult<std::vector<LeScanManager::ScanResult>>,
+                     &results),
+      0x5555);
+  scoped_task_environment_.RunUntilIdle();
+
+  ASSERT_EQ(1u, results.size());
+  ASSERT_EQ(kTestAddr2, results[0].addr);
+  ASSERT_EQ(std::vector<uint8_t>({0x55, 0x55}), results[0].type_to_data[0x02]);
+  ASSERT_EQ(1234, results[0].rssi);
+
+  // Get asynchronous scan results for results with service 0x6666.
+  le_scan_manager_.GetScanResults(
+      base::BindOnce(&CopyResult<std::vector<LeScanManager::ScanResult>>,
+                     &results),
+      0x6666);
+  scoped_task_environment_.RunUntilIdle();
+
+  ASSERT_EQ(0u, results.size());
+}
+
+TEST_F(LeScanManagerTest, TestGetScanResultsSortedByRssi) {
+  EXPECT_CALL(mock_observer_, OnNewScanResult(_)).Times(3);
+
+  // Add a scan result with service 0x4444.
+  bluetooth_v2_shlib::LeScanner::ScanResult raw_scan_result;
+  raw_scan_result.addr = kTestAddr1;
+  raw_scan_result.adv_data = {0x03, 0x02, 0x44, 0x44};
+  raw_scan_result.rssi = 1;
+  delegate()->OnScanResult(raw_scan_result);
+
+  // Add a scan result with service 0x5555.
+  raw_scan_result.addr = kTestAddr2;
+  raw_scan_result.adv_data = {0x03, 0x02, 0x55, 0x55};
+  raw_scan_result.rssi = 3;
+  delegate()->OnScanResult(raw_scan_result);
+
+  // Add a scan result with service 0x5555.
+  raw_scan_result.addr = kTestAddr1;
+  raw_scan_result.adv_data = {0x03, 0x02, 0x55, 0x55};
+  raw_scan_result.rssi = 2;
+  delegate()->OnScanResult(raw_scan_result);
+
+  scoped_task_environment_.RunUntilIdle();
+
+  std::vector<LeScanManager::ScanResult> results;
+  // Get asynchronous scan results.
+  le_scan_manager_.GetScanResults(base::BindOnce(
+      &CopyResult<std::vector<LeScanManager::ScanResult>>, &results));
+
+  scoped_task_environment_.RunUntilIdle();
+
+  ASSERT_EQ(3u, results.size());
+  EXPECT_EQ(kTestAddr2, results[0].addr);
+  EXPECT_EQ(3, results[0].rssi);
+  EXPECT_EQ(kTestAddr1, results[1].addr);
+  EXPECT_EQ(2, results[1].rssi);
+  EXPECT_EQ(kTestAddr1, results[2].addr);
+  EXPECT_EQ(1, results[2].rssi);
+}
+
+TEST_F(LeScanManagerTest, TestOnNewScanResult) {
+  LeScanManager::ScanResult result;
+  ON_CALL(mock_observer_, OnNewScanResult(_))
+      .WillByDefault(Invoke([&result](LeScanManager::ScanResult result_in) {
+        result = result_in;
+      }));
+
+  // Add a scan result with service 0x4444.
+  bluetooth_v2_shlib::LeScanner::ScanResult raw_scan_result;
+  raw_scan_result.addr = kTestAddr1;
+  raw_scan_result.adv_data = {0x03, 0x02, 0x44, 0x44};
+  raw_scan_result.rssi = 1;
+  delegate()->OnScanResult(raw_scan_result);
+  scoped_task_environment_.RunUntilIdle();
+
+  // Ensure that the observer was notified.
+  ASSERT_EQ(kTestAddr1, result.addr);
+  ASSERT_EQ(std::vector<uint8_t>({0x44, 0x44}), result.type_to_data[0x02]);
+  ASSERT_EQ(1, result.rssi);
+}
+
+TEST_F(LeScanManagerTest, TestOnScanEnableChanged) {
+  bool enabled = false;
+  ON_CALL(mock_observer_, OnScanEnableChanged(_))
+      .WillByDefault(
+          Invoke([&enabled](bool enabled_in) { enabled = enabled_in; }));
+
+  // Enable scanning.
+  le_scan_manager_.SetScanEnable(true /* enable */, base::DoNothing());
+  scoped_task_environment_.RunUntilIdle();
+  ASSERT_TRUE(enabled);
+
+  // Disable scanning.
+  le_scan_manager_.SetScanEnable(false /* enable */, base::DoNothing());
+  scoped_task_environment_.RunUntilIdle();
+  ASSERT_FALSE(enabled);
+}
+
+}  // namespace bluetooth
+}  // namespace chromecast
diff --git a/chromecast/device/bluetooth/le/remote_characteristic.cc b/chromecast/device/bluetooth/le/remote_characteristic.cc
new file mode 100644
index 0000000..f416def
--- /dev/null
+++ b/chromecast/device/bluetooth/le/remote_characteristic.cc
@@ -0,0 +1,247 @@
+// 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 "chromecast/device/bluetooth/le/remote_characteristic.h"
+
+#include "chromecast/base/bind_to_task_runner.h"
+#include "chromecast/device/bluetooth/le/gatt_client_manager.h"
+#include "chromecast/device/bluetooth/le/remote_descriptor.h"
+#include "chromecast/device/bluetooth/le/remote_device.h"
+
+#define EXEC_CB_AND_RET(cb, ret, ...)        \
+  do {                                       \
+    if (cb) {                                \
+      std::move(cb).Run(ret, ##__VA_ARGS__); \
+    }                                        \
+    return;                                  \
+  } while (0)
+
+#define RUN_ON_IO_THREAD(method, ...) \
+  io_task_runner_->PostTask(          \
+      FROM_HERE,                      \
+      base::BindOnce(&RemoteCharacteristic::method, this, ##__VA_ARGS__));
+
+#define MAKE_SURE_IO_THREAD(method, ...)            \
+  DCHECK(io_task_runner_);                          \
+  if (!io_task_runner_->BelongsToCurrentThread()) { \
+    RUN_ON_IO_THREAD(method, ##__VA_ARGS__)         \
+    return;                                         \
+  }
+
+namespace chromecast {
+namespace bluetooth {
+
+namespace {
+std::vector<uint8_t> GetDescriptorNotificationValue(bool enable) {
+  if (enable) {
+    return std::vector<uint8_t>(
+        std::begin(bluetooth::RemoteDescriptor::kEnableNotificationValue),
+        std::end(bluetooth::RemoteDescriptor::kEnableNotificationValue));
+  }
+  return std::vector<uint8_t>(
+      std::begin(bluetooth::RemoteDescriptor::kDisableNotificationValue),
+      std::end(bluetooth::RemoteDescriptor::kDisableNotificationValue));
+}
+}  // namespace
+
+// static
+std::map<bluetooth_v2_shlib::Uuid, scoped_refptr<RemoteDescriptor>>
+RemoteCharacteristic::CreateDescriptorMap(
+    RemoteDevice* device,
+    base::WeakPtr<GattClientManager> gatt_client_manager,
+    const bluetooth_v2_shlib::Gatt::Characteristic* characteristic,
+    scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) {
+  std::map<bluetooth_v2_shlib::Uuid, scoped_refptr<RemoteDescriptor>> ret;
+  for (const auto& descriptor : characteristic->descriptors) {
+    ret[descriptor.uuid] = new RemoteDescriptor(device, gatt_client_manager,
+                                                &descriptor, io_task_runner);
+  }
+
+  return ret;
+}
+
+RemoteCharacteristic::RemoteCharacteristic(
+    RemoteDevice* device,
+    base::WeakPtr<GattClientManager> gatt_client_manager,
+    const bluetooth_v2_shlib::Gatt::Characteristic* characteristic,
+    scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
+    : device_(device),
+      gatt_client_manager_(gatt_client_manager),
+      characteristic_(characteristic),
+      io_task_runner_(io_task_runner),
+      uuid_to_descriptor_(CreateDescriptorMap(device,
+                                              gatt_client_manager,
+                                              characteristic_,
+                                              io_task_runner)) {
+  DCHECK(gatt_client_manager);
+  DCHECK(characteristic);
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+}
+
+RemoteCharacteristic::~RemoteCharacteristic() = default;
+
+std::vector<scoped_refptr<RemoteDescriptor>>
+RemoteCharacteristic::GetDescriptors() {
+  std::vector<scoped_refptr<RemoteDescriptor>> ret;
+  ret.reserve(uuid_to_descriptor_.size());
+  for (const auto& pair : uuid_to_descriptor_) {
+    ret.push_back(pair.second);
+  }
+
+  return ret;
+}
+
+scoped_refptr<RemoteDescriptor> RemoteCharacteristic::GetDescriptorByUuid(
+    const bluetooth_v2_shlib::Uuid& uuid) {
+  auto it = uuid_to_descriptor_.find(uuid);
+  if (it == uuid_to_descriptor_.end()) {
+    return nullptr;
+  }
+
+  return it->second;
+}
+
+void RemoteCharacteristic::SetRegisterNotification(bool enable,
+                                                   StatusCallback cb) {
+  MAKE_SURE_IO_THREAD(SetRegisterNotification, enable,
+                      BindToCurrentThread(std::move(cb)));
+  if (!gatt_client_manager_) {
+    LOG(ERROR) << __func__ << " failed: Destroyed";
+    EXEC_CB_AND_RET(cb, false);
+  }
+
+  if (!gatt_client_manager_->gatt_client()->SetCharacteristicNotification(
+          device_->addr(), *characteristic_, enable)) {
+    LOG(ERROR) << "Set characteristic notification failed";
+    EXEC_CB_AND_RET(cb, false);
+  }
+
+  auto it = uuid_to_descriptor_.find(RemoteDescriptor::kCccdUuid);
+  if (it == uuid_to_descriptor_.end()) {
+    LOG(ERROR) << "No CCCD found";
+    EXEC_CB_AND_RET(cb, false);
+  }
+
+  it->second->WriteAuth(bluetooth_v2_shlib::Gatt::Client::AUTH_REQ_NONE,
+                        GetDescriptorNotificationValue(enable), std::move(cb));
+}
+
+void RemoteCharacteristic::SetNotification(bool enable, StatusCallback cb) {
+  MAKE_SURE_IO_THREAD(SetNotification, enable,
+                      BindToCurrentThread(std::move(cb)));
+  if (!gatt_client_manager_) {
+    LOG(ERROR) << __func__ << " failed: Destroyed";
+    EXEC_CB_AND_RET(cb, false);
+  }
+  if (!gatt_client_manager_->gatt_client()->SetCharacteristicNotification(
+          device_->addr(), *characteristic_, enable)) {
+    LOG(ERROR) << "Set characteristic notification failed";
+    EXEC_CB_AND_RET(cb, false);
+  }
+
+  notification_enabled_ = enable;
+  EXEC_CB_AND_RET(cb, true);
+}
+
+void RemoteCharacteristic::ReadAuth(
+    bluetooth_v2_shlib::Gatt::Client::AuthReq auth_req,
+    ReadCallback callback) {
+  MAKE_SURE_IO_THREAD(ReadAuth, auth_req,
+                      BindToCurrentThread(std::move(callback)));
+  if (!gatt_client_manager_) {
+    LOG(ERROR) << __func__ << " failed: Destroyed";
+    EXEC_CB_AND_RET(callback, false, {});
+  }
+  if (pending_read_) {
+    LOG(ERROR) << "Read already pending";
+    EXEC_CB_AND_RET(callback, false, {});
+  }
+
+  if (!gatt_client_manager_->gatt_client()->ReadCharacteristic(
+          device_->addr(), *characteristic_, auth_req)) {
+    EXEC_CB_AND_RET(callback, false, {});
+  }
+  pending_read_ = true;
+  read_callback_ = std::move(callback);
+}
+
+void RemoteCharacteristic::Read(ReadCallback callback) {
+  ReadAuth(bluetooth_v2_shlib::Gatt::Client::AUTH_REQ_INVALID,
+           std::move(callback));
+}
+
+void RemoteCharacteristic::WriteAuth(
+    bluetooth_v2_shlib::Gatt::Client::AuthReq auth_req,
+    bluetooth_v2_shlib::Gatt::WriteType write_type,
+    const std::vector<uint8_t>& value,
+    StatusCallback callback) {
+  MAKE_SURE_IO_THREAD(WriteAuth, auth_req, write_type, value,
+                      BindToCurrentThread(std::move(callback)));
+  if (!gatt_client_manager_) {
+    LOG(ERROR) << __func__ << " failed: Destroyed";
+    EXEC_CB_AND_RET(callback, false);
+  }
+  if (pending_write_) {
+    LOG(ERROR) << "Write already pending";
+    EXEC_CB_AND_RET(callback, false);
+  }
+
+  if (!gatt_client_manager_->gatt_client()->WriteCharacteristic(
+          device_->addr(), *characteristic_, auth_req, write_type, value)) {
+    EXEC_CB_AND_RET(callback, false);
+  }
+
+  pending_write_ = true;
+  write_callback_ = std::move(callback);
+}
+
+void RemoteCharacteristic::Write(bluetooth_v2_shlib::Gatt::WriteType write_type,
+                                 const std::vector<uint8_t>& value,
+                                 StatusCallback callback) {
+  return WriteAuth(bluetooth_v2_shlib::Gatt::Client::AUTH_REQ_NONE, write_type,
+                   value, std::move(callback));
+}
+
+bool RemoteCharacteristic::NotificationEnabled() {
+  return notification_enabled_;
+}
+
+void RemoteCharacteristic::OnConnectChanged(bool connected) {
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+  if (connected) {
+    return;
+  }
+
+  pending_read_ = false;
+  pending_write_ = false;
+
+  if (read_callback_) {
+    LOG(ERROR) << "Read failed: Device disconnected";
+    std::move(read_callback_).Run(false, std::vector<uint8_t>());
+  }
+
+  if (write_callback_) {
+    LOG(ERROR) << "Write failed: Device disconnected";
+    std::move(write_callback_).Run(false);
+  }
+}
+
+void RemoteCharacteristic::OnReadComplete(bool status,
+                                          const std::vector<uint8_t>& value) {
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+  pending_read_ = false;
+  if (read_callback_) {
+    std::move(read_callback_).Run(status, value);
+  }
+}
+
+void RemoteCharacteristic::OnWriteComplete(bool status) {
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+  pending_write_ = false;
+  if (write_callback_)
+    std::move(write_callback_).Run(status);
+}
+
+}  // namespace bluetooth
+}  // namespace chromecast
diff --git a/chromecast/device/bluetooth/le/remote_characteristic.h b/chromecast/device/bluetooth/le/remote_characteristic.h
new file mode 100644
index 0000000..f540a1b
--- /dev/null
+++ b/chromecast/device/bluetooth/le/remote_characteristic.h
@@ -0,0 +1,139 @@
+// 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 CHROMECAST_DEVICE_BLUETOOTH_LE_REMOTE_CHARACTERISTIC_H_
+#define CHROMECAST_DEVICE_BLUETOOTH_LE_REMOTE_CHARACTERISTIC_H_
+
+#include <atomic>
+#include <map>
+#include <memory>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/single_thread_task_runner.h"
+#include "chromecast/internal/public/bluetooth_v2_shlib/gatt.h"
+
+namespace chromecast {
+namespace bluetooth {
+
+class GattClientManager;
+class RemoteDescriptor;
+class RemoteDevice;
+
+// A proxy for a remote characteristic on a RemoteDevice. Unless otherwise
+// specified, all callbacks are run on the caller's thread.
+class RemoteCharacteristic
+    : public base::RefCountedThreadSafe<RemoteCharacteristic> {
+ public:
+  using ReadCallback =
+      base::OnceCallback<void(bool, const std::vector<uint8_t>&)>;
+  using StatusCallback = base::OnceCallback<void(bool)>;
+
+  // Return a list of all descriptors.
+  std::vector<scoped_refptr<RemoteDescriptor>> GetDescriptors();
+
+  // Retrieves the descriptor with |uuid|, or nullptr if it doesn't exist.
+  scoped_refptr<RemoteDescriptor> GetDescriptorByUuid(
+      const bluetooth_v2_shlib::Uuid& uuid);
+
+  // Register or deregister from a notification. Calls |SetNotification| and
+  // writes the cccd.
+  void SetRegisterNotification(bool enable, StatusCallback cb);
+
+  // Enable notifications for this characteristic. Client must still write to
+  // the CCCD seperately (or use |SetRegisterNotification| instead).
+  void SetNotification(bool enable, StatusCallback cb);
+
+  // Read the characteristic with |auth_req|. When completed, |callback| will be
+  // called.
+  void ReadAuth(bluetooth_v2_shlib::Gatt::Client::AuthReq auth_req,
+                ReadCallback callback);
+
+  // Read the characteristic. Will retry if auth_req isn't met. When completed,
+  // |callback| will be called.
+  void Read(ReadCallback callback);
+
+  // Write |value| to the characteristic with |auth_req| and |write_type|. When
+  // completed, |callback| will be called.
+  void WriteAuth(bluetooth_v2_shlib::Gatt::Client::AuthReq auth_req,
+                 bluetooth_v2_shlib::Gatt::WriteType write_type,
+                 const std::vector<uint8_t>& value,
+                 StatusCallback callback);
+
+  // Write |value| to the characteristic with |write_type|. Will retry if
+  // auth_req isn't met. When completed, |callback| will be called.
+  void Write(bluetooth_v2_shlib::Gatt::WriteType write_type,
+             const std::vector<uint8_t>& value,
+             StatusCallback callback);
+
+  // Returns true if notifications are enabled.
+  bool NotificationEnabled();
+
+  const bluetooth_v2_shlib::Gatt::Characteristic& characteristic() const {
+    return *characteristic_;
+  }
+  const bluetooth_v2_shlib::Uuid& uuid() const { return characteristic_->uuid; }
+  uint16_t handle() const { return characteristic_->handle; }
+  bluetooth_v2_shlib::Gatt::Permissions permissions() const {
+    return characteristic_->permissions;
+  }
+
+  bluetooth_v2_shlib::Gatt::Properties properties() const {
+    return characteristic_->properties;
+  }
+
+ private:
+  friend class GattClientManager;
+  friend class RemoteDevice;
+  friend class RemoteService;
+  friend class base::RefCountedThreadSafe<RemoteCharacteristic>;
+
+  static std::map<bluetooth_v2_shlib::Uuid, scoped_refptr<RemoteDescriptor>>
+  CreateDescriptorMap(
+      RemoteDevice* device,
+      base::WeakPtr<GattClientManager> gatt_client_manager,
+      const bluetooth_v2_shlib::Gatt::Characteristic* characteristic,
+      scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
+
+  RemoteCharacteristic(
+      RemoteDevice* device,
+      base::WeakPtr<GattClientManager> gatt_client_manager,
+      const bluetooth_v2_shlib::Gatt::Characteristic* characteristic,
+      scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
+  ~RemoteCharacteristic();
+
+  void OnConnectChanged(bool connected);
+  void OnReadComplete(bool status, const std::vector<uint8_t>& value);
+  void OnWriteComplete(bool status);
+
+  // Weak reference to avoid refcount loop.
+  RemoteDevice* const device_;
+  const base::WeakPtr<GattClientManager> gatt_client_manager_;
+  const bluetooth_v2_shlib::Gatt::Characteristic* const characteristic_;
+
+  // All bluetooth_v2_shlib calls are run on this task_runner. All members must
+  // be accessed on this task_runner.
+  const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
+
+  const std::map<bluetooth_v2_shlib::Uuid, scoped_refptr<RemoteDescriptor>>
+      uuid_to_descriptor_;
+
+  ReadCallback read_callback_;
+  StatusCallback write_callback_;
+
+  std::atomic<bool> notification_enabled_{false};
+
+  bool pending_read_ = false;
+  bool pending_write_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(RemoteCharacteristic);
+};
+
+}  // namespace bluetooth
+}  // namespace chromecast
+
+#endif  // CHROMECAST_DEVICE_BLUETOOTH_LE_REMOTE_CHARACTERISTIC_H_
diff --git a/chromecast/device/bluetooth/le/remote_descriptor.cc b/chromecast/device/bluetooth/le/remote_descriptor.cc
new file mode 100644
index 0000000..0f9da2b
--- /dev/null
+++ b/chromecast/device/bluetooth/le/remote_descriptor.cc
@@ -0,0 +1,153 @@
+// 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 "chromecast/device/bluetooth/le/remote_descriptor.h"
+
+#include "chromecast/base/bind_to_task_runner.h"
+#include "chromecast/device/bluetooth/le/remote_characteristic.h"
+#include "chromecast/device/bluetooth/le/remote_device.h"
+
+#define EXEC_CB_AND_RET(cb, ret, ...)        \
+  do {                                       \
+    if (cb) {                                \
+      std::move(cb).Run(ret, ##__VA_ARGS__); \
+    }                                        \
+    return;                                  \
+  } while (0)
+
+#define RUN_ON_IO_THREAD(method, ...) \
+  io_task_runner_->PostTask(          \
+      FROM_HERE,                      \
+      base::BindOnce(&RemoteDescriptor::method, this, ##__VA_ARGS__));
+
+#define MAKE_SURE_IO_THREAD(method, ...)            \
+  DCHECK(io_task_runner_);                          \
+  if (!io_task_runner_->BelongsToCurrentThread()) { \
+    RUN_ON_IO_THREAD(method, ##__VA_ARGS__)         \
+    return;                                         \
+  }
+
+namespace chromecast {
+namespace bluetooth {
+
+// static
+constexpr uint8_t RemoteDescriptor::kEnableNotificationValue[];
+// static
+constexpr uint8_t RemoteDescriptor::kDisableNotificationValue[];
+// static
+const bluetooth_v2_shlib::Uuid RemoteDescriptor::kCccdUuid = {
+    {0x00, 0x00, 0x29, 0x02, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80,
+     0x5f, 0x9b, 0x34, 0xfb}};
+
+RemoteDescriptor::RemoteDescriptor(
+    RemoteDevice* device,
+    base::WeakPtr<GattClientManager> gatt_client_manager,
+    const bluetooth_v2_shlib::Gatt::Descriptor* descriptor,
+    scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
+    : device_(device),
+      gatt_client_manager_(std::move(gatt_client_manager)),
+      descriptor_(descriptor),
+      io_task_runner_(io_task_runner) {
+  DCHECK(device);
+  DCHECK(gatt_client_manager_);
+  DCHECK(descriptor);
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+}
+
+RemoteDescriptor::~RemoteDescriptor() = default;
+
+void RemoteDescriptor::ReadAuth(
+    bluetooth_v2_shlib::Gatt::Client::AuthReq auth_req,
+    ReadCallback callback) {
+  MAKE_SURE_IO_THREAD(ReadAuth, auth_req,
+                      BindToCurrentThread(std::move(callback)));
+  if (!gatt_client_manager_) {
+    LOG(ERROR) << __func__ << " failed: Destroyed";
+    EXEC_CB_AND_RET(callback, false, {});
+  }
+
+  if (pending_read_) {
+    LOG(ERROR) << "Read already pending";
+    EXEC_CB_AND_RET(callback, false, {});
+  }
+
+  if (!gatt_client_manager_->gatt_client()->ReadDescriptor(
+          device_->addr(), *descriptor_, auth_req)) {
+    EXEC_CB_AND_RET(callback, false, {});
+  }
+  pending_read_ = true;
+  read_callback_ = std::move(callback);
+}
+
+void RemoteDescriptor::Read(ReadCallback callback) {
+  ReadAuth(bluetooth_v2_shlib::Gatt::Client::AUTH_REQ_INVALID,
+           std::move(callback));
+}
+
+void RemoteDescriptor::WriteAuth(
+    bluetooth_v2_shlib::Gatt::Client::AuthReq auth_req,
+    const std::vector<uint8_t>& value,
+    StatusCallback callback) {
+  MAKE_SURE_IO_THREAD(WriteAuth, auth_req, value,
+                      BindToCurrentThread(std::move(callback)));
+  if (!gatt_client_manager_) {
+    LOG(ERROR) << __func__ << " failed: Destroyed";
+    EXEC_CB_AND_RET(callback, false);
+  }
+  if (pending_write_) {
+    LOG(ERROR) << "Write already pending";
+    EXEC_CB_AND_RET(callback, false);
+  }
+
+  if (!gatt_client_manager_->gatt_client()->WriteDescriptor(
+          device_->addr(), *descriptor_, auth_req, value)) {
+    EXEC_CB_AND_RET(callback, false);
+  }
+  pending_write_ = true;
+  write_callback_ = std::move(callback);
+}
+
+void RemoteDescriptor::Write(const std::vector<uint8_t>& value,
+                             StatusCallback callback) {
+  WriteAuth(bluetooth_v2_shlib::Gatt::Client::AUTH_REQ_INVALID, value,
+            std::move(callback));
+}
+
+void RemoteDescriptor::OnConnectChanged(bool connected) {
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+  if (connected) {
+    return;
+  }
+
+  pending_read_ = false;
+  pending_write_ = false;
+
+  if (read_callback_) {
+    LOG(ERROR) << "Read failed: Device disconnected";
+    std::move(read_callback_).Run(false, std::vector<uint8_t>());
+  }
+
+  if (write_callback_) {
+    LOG(ERROR) << "Write failed: Device disconnected";
+    std::move(write_callback_).Run(false);
+  }
+}
+
+void RemoteDescriptor::OnReadComplete(bool status,
+                                      const std::vector<uint8_t>& value) {
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+  pending_read_ = false;
+  if (read_callback_)
+    std::move(read_callback_).Run(status, value);
+}
+
+void RemoteDescriptor::OnWriteComplete(bool status) {
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+  pending_write_ = false;
+  if (write_callback_)
+    std::move(write_callback_).Run(status);
+}
+
+}  // namespace bluetooth
+}  // namespace chromecast
diff --git a/chromecast/device/bluetooth/le/remote_descriptor.h b/chromecast/device/bluetooth/le/remote_descriptor.h
new file mode 100644
index 0000000..8e7f0321
--- /dev/null
+++ b/chromecast/device/bluetooth/le/remote_descriptor.h
@@ -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.
+
+#ifndef CHROMECAST_DEVICE_BLUETOOTH_LE_REMOTE_DESCRIPTOR_H_
+#define CHROMECAST_DEVICE_BLUETOOTH_LE_REMOTE_DESCRIPTOR_H_
+
+#include <map>
+#include <memory>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/single_thread_task_runner.h"
+#include "chromecast/device/bluetooth/le/gatt_client_manager.h"
+#include "chromecast/internal/public/bluetooth_v2_shlib/gatt.h"
+
+namespace chromecast {
+namespace bluetooth {
+
+class RemoteDevice;
+class RemoteDescriptor;
+
+// A proxy for a remote descriptor on a RemoteDevice. Unless otherwise
+// specified, all callbacks are run on the caller's thread.
+class RemoteDescriptor : public base::RefCountedThreadSafe<RemoteDescriptor> {
+ public:
+  static constexpr uint8_t kEnableNotificationValue[] = {0x01, 0x00};
+  static constexpr uint8_t kDisableNotificationValue[] = {0x00, 0x00};
+  static const bluetooth_v2_shlib::Uuid kCccdUuid;
+
+  using ReadCallback =
+      base::OnceCallback<void(bool, const std::vector<uint8_t>&)>;
+  using StatusCallback = base::OnceCallback<void(bool)>;
+
+  // Read the descriptor with |auth_req|. When completed, |callback| will be
+  // called.
+  void ReadAuth(bluetooth_v2_shlib::Gatt::Client::AuthReq auth_req,
+                ReadCallback callback);
+
+  // Read the descriptor. When completed, |callback| will be called.
+  void Read(ReadCallback callback);
+
+  // Write |value| to the descriptor with |auth_req|. When completed, |callback|
+  // will be called.
+  void WriteAuth(bluetooth_v2_shlib::Gatt::Client::AuthReq auth_req,
+                 const std::vector<uint8_t>& value,
+                 StatusCallback callback);
+
+  // Write |value| to the descriptor. Will retry if auth_req isn't met. When
+  // completed, |callback| will be called.
+  void Write(const std::vector<uint8_t>& value, StatusCallback callback);
+
+  const bluetooth_v2_shlib::Gatt::Descriptor& descriptor() const {
+    return *descriptor_;
+  }
+  const bluetooth_v2_shlib::Uuid uuid() const { return descriptor_->uuid; }
+  uint16_t handle() const { return descriptor_->handle; }
+  bluetooth_v2_shlib::Gatt::Permissions permissions() const {
+    return descriptor_->permissions;
+  }
+
+ private:
+  friend class GattClientManager;
+  friend class RemoteCharacteristic;
+  friend class RemoteDevice;
+  friend class base::RefCountedThreadSafe<RemoteDescriptor>;
+
+  RemoteDescriptor(RemoteDevice* device,
+                   base::WeakPtr<GattClientManager> gatt_client_manager,
+                   const bluetooth_v2_shlib::Gatt::Descriptor* characteristic,
+                   scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
+  ~RemoteDescriptor();
+
+  void OnConnectChanged(bool connected);
+  void OnReadComplete(bool status, const std::vector<uint8_t>& value);
+  void OnWriteComplete(bool status);
+
+  RemoteDevice* const device_;
+  const base::WeakPtr<GattClientManager> gatt_client_manager_;
+  const bluetooth_v2_shlib::Gatt::Descriptor* const descriptor_;
+
+  // All bluetooth_v2_shlib calls are run on this task_runner. All members must
+  // be accessed on this task_runner.
+  const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
+
+  ReadCallback read_callback_;
+  StatusCallback write_callback_;
+
+  bool pending_read_ = false;
+  bool pending_write_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(RemoteDescriptor);
+};
+
+}  // namespace bluetooth
+}  // namespace chromecast
+
+#endif  // CHROMECAST_DEVICE_BLUETOOTH_LE_REMOTE_DESCRIPTOR_H_
diff --git a/chromecast/device/bluetooth/le/remote_device.cc b/chromecast/device/bluetooth/le/remote_device.cc
new file mode 100644
index 0000000..8f8684d
--- /dev/null
+++ b/chromecast/device/bluetooth/le/remote_device.cc
@@ -0,0 +1,408 @@
+// 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 "chromecast/device/bluetooth/le/remote_device.h"
+
+#include "base/bind.h"
+#include "chromecast/base/bind_to_task_runner.h"
+#include "chromecast/device/bluetooth/le/gatt_client_manager.h"
+#include "chromecast/device/bluetooth/le/remote_characteristic.h"
+#include "chromecast/device/bluetooth/le/remote_descriptor.h"
+#include "chromecast/device/bluetooth/le/remote_service.h"
+
+namespace chromecast {
+namespace bluetooth {
+
+#define RUN_ON_IO_THREAD(method, ...) \
+  io_task_runner_->PostTask(          \
+      FROM_HERE, base::BindOnce(&RemoteDevice::method, this, ##__VA_ARGS__));
+
+#define MAKE_SURE_IO_THREAD(method, ...)            \
+  DCHECK(io_task_runner_);                          \
+  if (!io_task_runner_->BelongsToCurrentThread()) { \
+    RUN_ON_IO_THREAD(method, ##__VA_ARGS__)         \
+    return;                                         \
+  }
+
+#define EXEC_CB_AND_RET(cb, ret, ...)        \
+  do {                                       \
+    if (cb) {                                \
+      std::move(cb).Run(ret, ##__VA_ARGS__); \
+    }                                        \
+    return;                                  \
+  } while (0)
+
+#define CHECK_CONNECTED(cb)                              \
+  do {                                                   \
+    if (!connected_) {                                   \
+      LOG(ERROR) << __func__ << "failed: Not connected"; \
+      EXEC_CB_AND_RET(cb, false);                        \
+    }                                                    \
+  } while (0)
+
+#define LOG_EXEC_CB_AND_RET(cb, ret)      \
+  do {                                    \
+    if (!ret) {                           \
+      LOG(ERROR) << __func__ << "failed"; \
+    }                                     \
+    EXEC_CB_AND_RET(cb, ret);             \
+  } while (0)
+
+// static
+constexpr int RemoteDevice::kDefaultMtu;
+
+RemoteDevice::RemoteDevice(
+    const bluetooth_v2_shlib::Addr& addr,
+    base::WeakPtr<GattClientManager> gatt_client_manager,
+    scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
+    : gatt_client_manager_(gatt_client_manager),
+      addr_(addr),
+      io_task_runner_(io_task_runner) {
+  DCHECK(gatt_client_manager);
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+}
+
+RemoteDevice::~RemoteDevice() = default;
+
+void RemoteDevice::Connect(StatusCallback cb) {
+  MAKE_SURE_IO_THREAD(Connect, BindToCurrentThread(std::move(cb)));
+  if (!ConnectSync()) {
+    // Error logged.
+    EXEC_CB_AND_RET(cb, false);
+  }
+
+  connect_cb_ = std::move(cb);
+}
+
+bool RemoteDevice::ConnectSync() {
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+  if (!gatt_client_manager_) {
+    LOG(ERROR) << __func__ << " failed: Destroyed";
+    return false;
+  }
+  if (connect_pending_) {
+    LOG(ERROR) << __func__ << " failed: Connection pending";
+    return false;
+  }
+
+  gatt_client_manager_->NotifyConnect(addr_);
+  if (!gatt_client_manager_->gatt_client()->Connect(addr_)) {
+    LOG(ERROR) << __func__ << " failed";
+    return false;
+  }
+  connect_pending_ = true;
+  return true;
+}
+
+void RemoteDevice::Disconnect(StatusCallback cb) {
+  MAKE_SURE_IO_THREAD(Disconnect, BindToCurrentThread(std::move(cb)));
+  if (!DisconnectSync()) {
+    // Error logged.
+    EXEC_CB_AND_RET(cb, false);
+  }
+
+  disconnect_cb_ = std::move(cb);
+}
+
+bool RemoteDevice::DisconnectSync() {
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+  if (!gatt_client_manager_) {
+    LOG(ERROR) << __func__ << " failed: Destroyed";
+    return false;
+  }
+
+  if (!connected_) {
+    LOG(ERROR) << "Not connected";
+    return false;
+  }
+
+  if (!gatt_client_manager_->gatt_client()->Disconnect(addr_)) {
+    LOG(ERROR) << __func__ << " failed";
+    return false;
+  }
+  disconnect_pending_ = true;
+
+  return true;
+}
+
+void RemoteDevice::ReadRemoteRssi(RssiCallback cb) {
+  MAKE_SURE_IO_THREAD(ReadRemoteRssi, BindToCurrentThread(std::move(cb)));
+  if (!gatt_client_manager_) {
+    LOG(ERROR) << __func__ << " failed: Destroyed";
+    EXEC_CB_AND_RET(cb, false, 0);
+  }
+
+  if (rssi_pending_) {
+    LOG(ERROR) << "Read remote RSSI already pending";
+    EXEC_CB_AND_RET(cb, false, 0);
+  }
+  if (!gatt_client_manager_->gatt_client()->ReadRemoteRssi(addr_)) {
+    LOG(ERROR) << __func__ << " failed";
+    EXEC_CB_AND_RET(cb, false, 0);
+  }
+  rssi_pending_ = true;
+  rssi_cb_ = std::move(cb);
+}
+
+void RemoteDevice::RequestMtu(int mtu, StatusCallback cb) {
+  MAKE_SURE_IO_THREAD(RequestMtu, mtu, BindToCurrentThread(std::move(cb)));
+  if (!gatt_client_manager_) {
+    LOG(ERROR) << __func__ << " failed: Destroyed";
+    EXEC_CB_AND_RET(cb, false);
+  }
+  CHECK_CONNECTED(cb);
+  if (mtu_pending_) {
+    LOG(ERROR) << "MTU change already pending";
+    EXEC_CB_AND_RET(cb, false);
+  }
+
+  if (!gatt_client_manager_->gatt_client()->RequestMtu(addr_, mtu)) {
+    LOG(ERROR) << __func__ << " failed";
+    EXEC_CB_AND_RET(cb, false);
+  }
+
+  mtu_pending_ = true;
+  mtu_cb_ = std::move(cb);
+}
+
+void RemoteDevice::ConnectionParameterUpdate(int min_interval,
+                                             int max_interval,
+                                             int latency,
+                                             int timeout,
+                                             StatusCallback cb) {
+  MAKE_SURE_IO_THREAD(ConnectionParameterUpdate, min_interval, max_interval,
+                      latency, timeout, BindToCurrentThread(std::move(cb)));
+  if (!gatt_client_manager_) {
+    LOG(ERROR) << __func__ << " failed: Destroyed";
+    EXEC_CB_AND_RET(cb, false);
+  }
+  CHECK_CONNECTED(cb);
+  bool ret = gatt_client_manager_->gatt_client()->ConnectionParameterUpdate(
+      addr_, min_interval, max_interval, latency, timeout);
+  LOG_EXEC_CB_AND_RET(cb, ret);
+}
+
+void RemoteDevice::DiscoverServices(DiscoverServicesCb cb) {
+  MAKE_SURE_IO_THREAD(DiscoverServices, BindToCurrentThread(std::move(cb)));
+  if (!gatt_client_manager_) {
+    LOG(ERROR) << __func__ << " failed: Destroyed";
+    EXEC_CB_AND_RET(cb, false, {});
+  }
+
+  if (!connected_) {
+    LOG(ERROR) << __func__ << " failed: Not connected";
+    EXEC_CB_AND_RET(cb, false, {});
+  }
+
+  if (discover_services_pending_) {
+    LOG(ERROR) << __func__ << " failed: Already discovering services";
+    EXEC_CB_AND_RET(cb, false, {});
+  }
+
+  if (!gatt_client_manager_->gatt_client()->GetServices(addr_)) {
+    LOG(ERROR) << __func__ << " failed";
+    EXEC_CB_AND_RET(cb, false, {});
+  }
+
+  discover_services_pending_ = true;
+  discover_services_cb_ = std::move(cb);
+}
+
+bool RemoteDevice::IsConnected() {
+  return connected_;
+}
+
+int RemoteDevice::GetMtu() {
+  return mtu_;
+}
+
+void RemoteDevice::GetServices(
+    base::OnceCallback<void(std::vector<scoped_refptr<RemoteService>>)> cb) {
+  MAKE_SURE_IO_THREAD(GetServices, BindToCurrentThread(std::move(cb)));
+  auto ret = GetServicesSync();
+  EXEC_CB_AND_RET(cb, std::move(ret));
+}
+
+std::vector<scoped_refptr<RemoteService>> RemoteDevice::GetServicesSync() {
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+  std::vector<scoped_refptr<RemoteService>> services;
+  services.reserve(uuid_to_service_.size());
+  for (const auto& pair : uuid_to_service_)
+    services.push_back(pair.second);
+
+  return services;
+}
+
+void RemoteDevice::GetServiceByUuid(
+    const bluetooth_v2_shlib::Uuid& uuid,
+    base::OnceCallback<void(scoped_refptr<RemoteService>)> cb) {
+  MAKE_SURE_IO_THREAD(GetServiceByUuid, uuid,
+                      BindToCurrentThread(std::move(cb)));
+  auto ret = GetServiceByUuidSync(uuid);
+  EXEC_CB_AND_RET(cb, std::move(ret));
+}
+
+scoped_refptr<RemoteService> RemoteDevice::GetServiceByUuidSync(
+    const bluetooth_v2_shlib::Uuid& uuid) {
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+  auto it = uuid_to_service_.find(uuid);
+  if (it == uuid_to_service_.end())
+    return nullptr;
+
+  return it->second;
+}
+
+void RemoteDevice::SetConnected(bool connected) {
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+  if (connect_pending_) {
+    connect_pending_ = false;
+    if (connect_cb_) {
+      std::move(connect_cb_).Run(connected);
+    }
+  }
+
+  if (disconnect_pending_) {
+    disconnect_pending_ = false;
+    if (disconnect_cb_) {
+      std::move(disconnect_cb_).Run(!connected);
+    }
+  }
+
+  connected_ = connected;
+  if (!connected && rssi_pending_) {
+    LOG(ERROR) << "Read remote RSSI failed: disconnected";
+    if (rssi_cb_) {
+      std::move(rssi_cb_).Run(false, 0);
+    }
+    rssi_pending_ = false;
+  }
+
+  if (!connected && mtu_pending_) {
+    LOG(ERROR) << "Set MTU failed: disconnected";
+    if (mtu_cb_) {
+      std::move(mtu_cb_).Run(false);
+    }
+
+    mtu_pending_ = false;
+  }
+
+  if (!connected && discover_services_pending_) {
+    LOG(ERROR) << "Discover services failed: disconnected";
+    if (discover_services_cb_) {
+      std::move(discover_services_cb_).Run(false, {});
+    }
+    discover_services_pending_ = false;
+  }
+
+  for (const auto& characteristic : handle_to_characteristic_) {
+    characteristic.second->OnConnectChanged(connected);
+  }
+
+  for (const auto& descriptor : handle_to_descriptor_) {
+    descriptor.second->OnConnectChanged(connected);
+  }
+}
+
+void RemoteDevice::SetMtu(int mtu) {
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+  mtu_pending_ = false;
+  mtu_ = mtu;
+
+  if (mtu_cb_) {
+    std::move(mtu_cb_).Run(true);
+  }
+}
+
+scoped_refptr<RemoteCharacteristic> RemoteDevice::CharacteristicFromHandle(
+    uint16_t handle) {
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+  auto it = handle_to_characteristic_.find(handle);
+  if (it == handle_to_characteristic_.end())
+    return nullptr;
+
+  return it->second;
+}
+
+scoped_refptr<RemoteDescriptor> RemoteDevice::DescriptorFromHandle(
+    uint16_t handle) {
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+  auto it = handle_to_descriptor_.find(handle);
+  if (it == handle_to_descriptor_.end())
+    return nullptr;
+
+  return it->second;
+}
+
+void RemoteDevice::OnGetServices(
+    const std::vector<bluetooth_v2_shlib::Gatt::Service>& services) {
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+  uuid_to_service_.clear();
+  handle_to_characteristic_.clear();
+  handle_to_descriptor_.clear();
+  OnServicesAdded(services);
+
+  discover_services_pending_ = false;
+  if (discover_services_cb_) {
+    std::move(discover_services_cb_).Run(true, GetServicesSync());
+  }
+}
+
+void RemoteDevice::OnServicesRemoved(uint16_t start_handle,
+                                     uint16_t end_handle) {
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+  for (auto it = uuid_to_service_.begin(); it != uuid_to_service_.end();) {
+    if (it->second->handle() >= start_handle &&
+        it->second->handle() <= end_handle) {
+      for (auto& characteristic : it->second->GetCharacteristics()) {
+        for (auto& descriptor : characteristic->GetDescriptors())
+          handle_to_descriptor_.erase(descriptor->handle());
+
+        handle_to_characteristic_.erase(characteristic->handle());
+      }
+      it = uuid_to_service_.erase(it);
+    } else {
+      ++it;
+    }
+  }
+
+  discover_services_pending_ = false;
+  if (discover_services_cb_) {
+    std::move(discover_services_cb_).Run(true, GetServicesSync());
+  }
+}
+
+void RemoteDevice::OnServicesAdded(
+    const std::vector<bluetooth_v2_shlib::Gatt::Service>& services) {
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+  for (const auto& service : services) {
+    uuid_to_service_[service.uuid] =
+        new RemoteService(this, gatt_client_manager_, service, io_task_runner_);
+  }
+
+  for (const auto& pair : uuid_to_service_) {
+    for (auto& characteristic : pair.second->GetCharacteristics()) {
+      handle_to_characteristic_.emplace(characteristic->handle(),
+                                        characteristic);
+      for (auto& descriptor : characteristic->GetDescriptors()) {
+        handle_to_descriptor_.emplace(descriptor->handle(), descriptor);
+      }
+    }
+  }
+
+  discover_services_pending_ = false;
+  if (discover_services_cb_) {
+    std::move(discover_services_cb_).Run(true, GetServicesSync());
+  }
+}
+
+void RemoteDevice::OnReadRemoteRssiComplete(bool status, int rssi) {
+  DCHECK(io_task_runner_->BelongsToCurrentThread());
+  rssi_pending_ = false;
+  if (rssi_cb_) {
+    std::move(rssi_cb_).Run(true, rssi);
+  }
+}
+
+}  // namespace bluetooth
+}  // namespace chromecast
diff --git a/chromecast/device/bluetooth/le/remote_device.h b/chromecast/device/bluetooth/le/remote_device.h
new file mode 100644
index 0000000..bfdefb0
--- /dev/null
+++ b/chromecast/device/bluetooth/le/remote_device.h
@@ -0,0 +1,156 @@
+// 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 CHROMECAST_DEVICE_BLUETOOTH_LE_REMOTE_DEVICE_H_
+#define CHROMECAST_DEVICE_BLUETOOTH_LE_REMOTE_DEVICE_H_
+
+#include <atomic>
+#include <map>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/single_thread_task_runner.h"
+#include "base/threading/thread_checker.h"
+#include "chromecast/internal/public/bluetooth_v2_shlib/gatt.h"
+
+namespace chromecast {
+namespace bluetooth {
+
+class GattClientManager;
+class RemoteCharacteristic;
+class RemoteDescriptor;
+class RemoteService;
+
+// A proxy to for a remote GATT server device.
+class RemoteDevice : public base::RefCountedThreadSafe<RemoteDevice> {
+ public:
+  static constexpr int kDefaultMtu = 20;
+  using StatusCallback = base::OnceCallback<void(bool)>;
+
+  // Initiate a connection to this device. Callback will return |true| if
+  // connected successfully, otherwise false. Only one pending call is allowed
+  // at a time.
+  void Connect(StatusCallback cb);
+
+  // TODO(bcf): Deprecated. Replace usage with async version.
+  bool ConnectSync();
+
+  // Disconnect from this device. Callback will return |true| if disconnected
+  // successfully, otherwise false. Only one pending call is allowed at a time.
+  void Disconnect(StatusCallback cb);
+
+  // TODO(bcf): Deprecated. Replace usage with async version.
+  bool DisconnectSync();
+
+  // Read this device's RSSI. The result will be sent in |callback|. Only one
+  // pending call is allowed at a time.
+  using RssiCallback = base::OnceCallback<void(bool success, int rssi)>;
+  void ReadRemoteRssi(RssiCallback cb);
+
+  // Request an MTU update to |mtu|. Callback will return |true| if MTU is
+  // updated successfully, otherwise false. Only one pending call is allowed at
+  // a time.
+  void RequestMtu(int mtu, StatusCallback cb);
+
+  // Request an update to connection parameters.
+  void ConnectionParameterUpdate(int min_interval,
+                                 int max_interval,
+                                 int latency,
+                                 int timeout,
+                                 StatusCallback cb);
+
+  // Initiate service discovery on this device. If it fails, the result will be
+  // empty.
+  using DiscoverServicesCb = base::OnceCallback<
+      void(bool success, std::vector<scoped_refptr<RemoteService>> services)>;
+  void DiscoverServices(DiscoverServicesCb cb);
+
+  // Returns true if this device is connected.
+  bool IsConnected();
+
+  // Returns the current MTU of the connection with this device.
+  int GetMtu();
+
+  // Returns a list of all discovered services on this device. After
+  // GattClientManager::Observer::OnServicesUpdated is called, these may point
+  // to old services, so services need to be reobtained.
+  void GetServices(
+      base::OnceCallback<void(std::vector<scoped_refptr<RemoteService>>)> cb);
+
+  // TODO(bcf): Deprecated. Replace usage with async version.
+  std::vector<scoped_refptr<RemoteService>> GetServicesSync();
+
+  // Returns the service corresponding to |uuid|, or nullptr if none exist.
+  void GetServiceByUuid(
+      const bluetooth_v2_shlib::Uuid& uuid,
+      base::OnceCallback<void(scoped_refptr<RemoteService>)> cb);
+
+  // TODO(bcf): Deprecated. Replace usage with async version.
+  scoped_refptr<RemoteService> GetServiceByUuidSync(
+      const bluetooth_v2_shlib::Uuid& uuid);
+
+  const bluetooth_v2_shlib::Addr& addr() const { return addr_; }
+
+ private:
+  friend class GattClientManager;
+  friend base::RefCountedThreadSafe<RemoteDevice>;
+
+  RemoteDevice(const bluetooth_v2_shlib::Addr& addr,
+               base::WeakPtr<GattClientManager> gatt_client_manager,
+               scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
+  ~RemoteDevice();
+
+  // Friend methods for GattClientManager
+  void SetConnected(bool connected);
+  void SetMtu(int mtu);
+
+  scoped_refptr<RemoteCharacteristic> CharacteristicFromHandle(uint16_t handle);
+  scoped_refptr<RemoteDescriptor> DescriptorFromHandle(uint16_t handle);
+
+  void OnGetServices(
+      const std::vector<bluetooth_v2_shlib::Gatt::Service>& services);
+  void OnServicesRemoved(uint16_t start_handle, uint16_t end_handle);
+  void OnServicesAdded(
+      const std::vector<bluetooth_v2_shlib::Gatt::Service>& services);
+  void OnReadRemoteRssiComplete(bool status, int rssi);
+  // end Friend methods for GattClientManager
+
+  const base::WeakPtr<GattClientManager> gatt_client_manager_;
+  const bluetooth_v2_shlib::Addr addr_;
+
+  // All bluetooth_v2_shlib calls are run on this task_runner. Below members
+  // should only be accessed on this task_runner.
+  const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
+
+  bool connect_pending_ = false;
+  StatusCallback connect_cb_;
+
+  bool disconnect_pending_ = false;
+  StatusCallback disconnect_cb_;
+
+  bool rssi_pending_ = false;
+  RssiCallback rssi_cb_;
+
+  bool mtu_pending_ = false;
+  StatusCallback mtu_cb_;
+
+  bool discover_services_pending_ = false;
+  DiscoverServicesCb discover_services_cb_;
+
+  std::atomic<bool> connected_{false};
+  std::atomic<int> mtu_{kDefaultMtu};
+  std::map<bluetooth_v2_shlib::Uuid, scoped_refptr<RemoteService>>
+      uuid_to_service_;
+  std::map<uint16_t, scoped_refptr<RemoteCharacteristic>>
+      handle_to_characteristic_;
+  std::map<uint16_t, scoped_refptr<RemoteDescriptor>> handle_to_descriptor_;
+  DISALLOW_COPY_AND_ASSIGN(RemoteDevice);
+};
+
+}  // namespace bluetooth
+}  // namespace chromecast
+
+#endif  // CHROMECAST_DEVICE_BLUETOOTH_LE_REMOTE_DEVICE_H_
diff --git a/chromecast/device/bluetooth/le/remote_service.cc b/chromecast/device/bluetooth/le/remote_service.cc
new file mode 100644
index 0000000..b539241e
--- /dev/null
+++ b/chromecast/device/bluetooth/le/remote_service.cc
@@ -0,0 +1,65 @@
+// 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 "chromecast/device/bluetooth/le/remote_service.h"
+
+#include "chromecast/base/bind_to_task_runner.h"
+#include "chromecast/device/bluetooth/le/remote_characteristic.h"
+
+namespace chromecast {
+namespace bluetooth {
+
+// static
+std::map<bluetooth_v2_shlib::Uuid, scoped_refptr<RemoteCharacteristic>>
+RemoteService::CreateCharMap(
+    RemoteDevice* remote_device,
+    base::WeakPtr<GattClientManager> gatt_client_manager,
+    const bluetooth_v2_shlib::Gatt::Service& service,
+    scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) {
+  std::map<bluetooth_v2_shlib::Uuid, scoped_refptr<RemoteCharacteristic>> ret;
+  for (const auto& characteristic : service.characteristics) {
+    ret[characteristic.uuid] = new RemoteCharacteristic(
+        remote_device, gatt_client_manager, &characteristic, io_task_runner);
+  }
+  return ret;
+}
+
+RemoteService::RemoteService(
+    RemoteDevice* remote_device,
+    base::WeakPtr<GattClientManager> gatt_client_manager,
+    const bluetooth_v2_shlib::Gatt::Service& service,
+    scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
+    : service_(service),
+      uuid_to_characteristic_(CreateCharMap(remote_device,
+                                            gatt_client_manager,
+                                            service_,
+                                            io_task_runner)) {
+  DCHECK(gatt_client_manager);
+  DCHECK(io_task_runner);
+  DCHECK(io_task_runner->BelongsToCurrentThread());
+}
+
+RemoteService::~RemoteService() = default;
+
+std::vector<scoped_refptr<RemoteCharacteristic>>
+RemoteService::GetCharacteristics() {
+  std::vector<scoped_refptr<RemoteCharacteristic>> ret;
+  ret.reserve(uuid_to_characteristic_.size());
+  for (const auto& pair : uuid_to_characteristic_) {
+    ret.push_back(pair.second);
+  }
+
+  return ret;
+}
+
+scoped_refptr<RemoteCharacteristic> RemoteService::GetCharacteristicByUuid(
+    const bluetooth_v2_shlib::Uuid& uuid) {
+  auto it = uuid_to_characteristic_.find(uuid);
+  if (it == uuid_to_characteristic_.end())
+    return nullptr;
+  return it->second;
+}
+
+}  // namespace bluetooth
+}  // namespace chromecast
diff --git a/chromecast/device/bluetooth/le/remote_service.h b/chromecast/device/bluetooth/le/remote_service.h
new file mode 100644
index 0000000..d3ba45c
--- /dev/null
+++ b/chromecast/device/bluetooth/le/remote_service.h
@@ -0,0 +1,72 @@
+// 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 CHROMECAST_DEVICE_BLUETOOTH_LE_REMOTE_SERVICE_H_
+#define CHROMECAST_DEVICE_BLUETOOTH_LE_REMOTE_SERVICE_H_
+
+#include <map>
+#include <memory>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/single_thread_task_runner.h"
+#include "chromecast/internal/public/bluetooth_v2_shlib/gatt.h"
+
+namespace chromecast {
+namespace bluetooth {
+
+class GattClientManager;
+class RemoteCharacteristic;
+class RemoteDevice;
+
+// A proxy for a remote service on a RemoteDevice. Unless otherwise
+// specified, all callbacks are run on the caller's thread.
+class RemoteService : public base::RefCountedThreadSafe<RemoteService> {
+ public:
+  // Returns a list of characteristics in this service.
+  void GetCharacteristics(
+      base::OnceCallback<void(std::vector<scoped_refptr<RemoteCharacteristic>>)>
+          cb);
+
+  std::vector<scoped_refptr<RemoteCharacteristic>> GetCharacteristics();
+
+  scoped_refptr<RemoteCharacteristic> GetCharacteristicByUuid(
+      const bluetooth_v2_shlib::Uuid& uuid);
+
+  const bluetooth_v2_shlib::Uuid& uuid() const { return service_.uuid; }
+  uint16_t handle() const { return service_.handle; }
+  bool primary() const { return service_.primary; }
+
+ private:
+  friend class RemoteDevice;
+  friend class base::RefCountedThreadSafe<RemoteService>;
+
+  static std::map<bluetooth_v2_shlib::Uuid, scoped_refptr<RemoteCharacteristic>>
+  CreateCharMap(RemoteDevice* remote_device,
+                base::WeakPtr<GattClientManager> gatt_client_manager,
+                const bluetooth_v2_shlib::Gatt::Service& service,
+                scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
+
+  // May only be constructed by RemoteDevice.
+  explicit RemoteService(
+      RemoteDevice* remote_device,
+      base::WeakPtr<GattClientManager> gatt_client_manager,
+      const bluetooth_v2_shlib::Gatt::Service& service,
+      scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
+  ~RemoteService();
+
+  const bluetooth_v2_shlib::Gatt::Service service_;
+
+  const std::map<bluetooth_v2_shlib::Uuid, scoped_refptr<RemoteCharacteristic>>
+      uuid_to_characteristic_;
+
+  DISALLOW_COPY_AND_ASSIGN(RemoteService);
+};
+
+}  // namespace bluetooth
+}  // namespace chromecast
+
+#endif  // CHROMECAST_DEVICE_BLUETOOTH_LE_REMOTE_SERVICE_H_
diff --git a/chromecast/device/bluetooth/shlib/BUILD.gn b/chromecast/device/bluetooth/shlib/BUILD.gn
new file mode 100644
index 0000000..8c4d086
--- /dev/null
+++ b/chromecast/device/bluetooth/shlib/BUILD.gn
@@ -0,0 +1,30 @@
+# 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.
+
+import("//chromecast/chromecast.gni")
+
+cast_source_set("shlib") {
+  sources = [
+    "gatt_client.h",
+    "le_scanner.h",
+  ]
+
+  deps = [
+    "//chromecast/internal/public",
+  ]
+}
+
+cast_source_set("mock_shlib") {
+  testonly = true
+  sources = [
+    "mock_gatt_client.h",
+    "mock_le_scanner.h",
+  ]
+
+  deps = [
+    ":shlib",
+    "//chromecast/internal/public",
+    "//testing/gmock:gmock",
+  ]
+}
diff --git a/chromecast/device/bluetooth/shlib/DEPS b/chromecast/device/bluetooth/shlib/DEPS
new file mode 100644
index 0000000..32bae81d
--- /dev/null
+++ b/chromecast/device/bluetooth/shlib/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+chromecast/internal/public",
+]
diff --git a/chromecast/device/bluetooth/shlib/gatt_client.h b/chromecast/device/bluetooth/shlib/gatt_client.h
new file mode 100644
index 0000000..9fef2d7e6
--- /dev/null
+++ b/chromecast/device/bluetooth/shlib/gatt_client.h
@@ -0,0 +1,54 @@
+// 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 CHROMECAST_DEVICE_BLUETOOTH_SHLIB_GATT_CLIENT_H_
+#define CHROMECAST_DEVICE_BLUETOOTH_SHLIB_GATT_CLIENT_H_
+
+#include <vector>
+
+#include "chromecast/internal/public/bluetooth_v2_shlib/gatt.h"
+
+namespace chromecast {
+namespace bluetooth_v2_shlib {
+
+class GattClient {
+ public:
+  virtual ~GattClient() = default;
+  virtual bool IsSupported() = 0;
+  virtual void SetDelegate(Gatt::Client::Delegate* delegate) = 0;
+  virtual bool Connect(const Addr& addr) = 0;
+  virtual bool Disconnect(const Addr& addr) = 0;
+  virtual bool ReadCharacteristic(const Addr& addr,
+                                  const Gatt::Characteristic& characteristic,
+                                  Gatt::Client::AuthReq auth_req) = 0;
+  virtual bool WriteCharacteristic(const Addr& addr,
+                                   const Gatt::Characteristic& characteristic,
+                                   Gatt::Client::AuthReq auth_req,
+                                   Gatt::WriteType write_type,
+                                   const std::vector<uint8_t>& value) = 0;
+  virtual bool ReadDescriptor(const Addr& addr,
+                              const Gatt::Descriptor& descriptor,
+                              Gatt::Client::AuthReq auth_req) = 0;
+  virtual bool WriteDescriptor(const Addr& addr,
+                               const Gatt::Descriptor& descriptor,
+                               Gatt::Client::AuthReq auth_req,
+                               const std::vector<uint8_t>& value) = 0;
+  virtual bool SetCharacteristicNotification(
+      const Addr& addr,
+      const Gatt::Characteristic& characteristic,
+      bool enable) = 0;
+  virtual bool ReadRemoteRssi(const Addr& addr) = 0;
+  virtual bool RequestMtu(const Addr& addr, int mtu) = 0;
+  virtual bool ConnectionParameterUpdate(const Addr& addr,
+                                         int min_interval,
+                                         int max_interval,
+                                         int latency,
+                                         int timeout) = 0;
+  virtual bool GetServices(const Addr& addr) = 0;
+};
+
+}  // namespace bluetooth_v2_shlib
+}  // namespace chromecast
+
+#endif  // CHROMECAST_DEVICE_BLUETOOTH_SHLIB_GATT_CLIENT_H_
diff --git a/chromecast/device/bluetooth/shlib/le_scanner.h b/chromecast/device/bluetooth/shlib/le_scanner.h
new file mode 100644
index 0000000..1940bc0
--- /dev/null
+++ b/chromecast/device/bluetooth/shlib/le_scanner.h
@@ -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.
+
+#ifndef CHROMECAST_DEVICE_BLUETOOTH_SHLIB_LE_SCANNER_H_
+#define CHROMECAST_DEVICE_BLUETOOTH_SHLIB_LE_SCANNER_H_
+
+#include "chromecast/internal/public/bluetooth_v2_shlib/le_scanner.h"
+
+namespace chromecast {
+namespace bluetooth_v2_shlib {
+
+class LeScannerImpl {
+ public:
+  virtual ~LeScannerImpl() = default;
+  virtual bool IsSupported() = 0;
+  virtual void SetDelegate(LeScanner::Delegate* delegate) = 0;
+  virtual bool StartScan() = 0;
+  virtual bool StopScan() = 0;
+};
+
+}  // namespace bluetooth_v2_shlib
+}  // namespace chromecast
+
+#endif  // CHROMECAST_DEVICE_BLUETOOTH_SHLIB_LE_SCANNER_H_
diff --git a/chromecast/device/bluetooth/shlib/mock_gatt_client.h b/chromecast/device/bluetooth/shlib/mock_gatt_client.h
new file mode 100644
index 0000000..aeb70c0
--- /dev/null
+++ b/chromecast/device/bluetooth/shlib/mock_gatt_client.h
@@ -0,0 +1,67 @@
+// 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 CHROMECAST_DEVICE_BLUETOOTH_SHLIB_MOCK_GATT_CLIENT_H_
+#define CHROMECAST_DEVICE_BLUETOOTH_SHLIB_MOCK_GATT_CLIENT_H_
+
+#include <vector>
+
+#include "chromecast/device/bluetooth/shlib/gatt_client.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace chromecast {
+namespace bluetooth_v2_shlib {
+
+class MockGattClient : public GattClient {
+ public:
+  MockGattClient();
+  ~MockGattClient() override;
+  MOCK_METHOD0(IsSupported, bool());
+  MOCK_METHOD1(Connect, bool(const Addr&));
+  void SetDelegate(Gatt::Client::Delegate* delegate) override {
+    delegate_ = delegate;
+  }
+  MOCK_METHOD0(Enable, bool());
+  MOCK_METHOD0(Disable, bool());
+  MOCK_METHOD1(Disconnect, bool(const Addr&));
+  MOCK_METHOD3(ReadCharacteristic,
+               bool(const Addr&,
+                    const Gatt::Characteristic&,
+                    Gatt::Client::AuthReq));
+  MOCK_METHOD5(WriteCharacteristic,
+               bool(const Addr&,
+                    const Gatt::Characteristic&,
+                    Gatt::Client::AuthReq,
+                    Gatt::WriteType,
+                    const std::vector<uint8_t>&));
+  MOCK_METHOD3(ReadDescriptor,
+               bool(const Addr&,
+                    const Gatt::Descriptor&,
+                    Gatt::Client::AuthReq));
+  MOCK_METHOD4(WriteDescriptor,
+               bool(const Addr&,
+                    const Gatt::Descriptor&,
+                    Gatt::Client::AuthReq,
+                    const std::vector<uint8_t>&));
+  MOCK_METHOD3(SetCharacteristicNotification,
+               bool(const Addr&, const Gatt::Characteristic&, bool));
+  MOCK_METHOD1(ReadRemoteRssi, bool(const Addr&));
+  MOCK_METHOD2(RequestMtu, bool(const Addr&, int mtu));
+  MOCK_METHOD5(ConnectionParameterUpdate,
+               bool(const Addr&, int, int, int, int));
+  MOCK_METHOD1(GetServices, bool(const Addr&));
+
+  Gatt::Client::Delegate* delegate() const { return delegate_; }
+
+ private:
+  Gatt::Client::Delegate* delegate_ = nullptr;
+};
+
+inline MockGattClient::MockGattClient() = default;
+inline MockGattClient::~MockGattClient() = default;
+
+}  // namespace bluetooth_v2_shlib
+}  // namespace chromecast
+
+#endif  // CHROMECAST_DEVICE_BLUETOOTH_SHLIB_MOCK_GATT_CLIENT_H_
diff --git a/chromecast/device/bluetooth/shlib/mock_le_scanner.h b/chromecast/device/bluetooth/shlib/mock_le_scanner.h
new file mode 100644
index 0000000..11674b5
--- /dev/null
+++ b/chromecast/device/bluetooth/shlib/mock_le_scanner.h
@@ -0,0 +1,30 @@
+// 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 CHROMECAST_DEVICE_BLUETOOTH_SHLIB_MOCK_LE_SCANNER_H_
+#define CHROMECAST_DEVICE_BLUETOOTH_SHLIB_MOCK_LE_SCANNER_H_
+
+#include "chromecast/device/bluetooth/shlib/le_scanner.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace chromecast {
+namespace bluetooth_v2_shlib {
+
+class MockLeScanner : public LeScannerImpl {
+ public:
+  MockLeScanner();
+  ~MockLeScanner() override;
+  MOCK_METHOD0(IsSupported, bool());
+  MOCK_METHOD1(SetDelegate, void(LeScanner::Delegate* delegate));
+  MOCK_METHOD0(StartScan, bool());
+  MOCK_METHOD0(StopScan, bool());
+};
+
+inline MockLeScanner::MockLeScanner() = default;
+inline MockLeScanner::~MockLeScanner() = default;
+
+}  // namespace bluetooth_v2_shlib
+}  // namespace chromecast
+
+#endif  // CHROMECAST_DEVICE_BLUETOOTH_SHLIB_MOCK_LE_SCANNER_H_
diff --git a/chromecast/graphics/cast_system_gesture_event_handler.cc b/chromecast/graphics/cast_system_gesture_event_handler.cc
index 42bc44c..ba3821e 100644
--- a/chromecast/graphics/cast_system_gesture_event_handler.cc
+++ b/chromecast/graphics/cast_system_gesture_event_handler.cc
@@ -4,6 +4,7 @@
 
 #include "chromecast/graphics/cast_system_gesture_event_handler.h"
 
+#include "chromecast/base/chromecast_switches.h"
 #include "ui/aura/window.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
@@ -18,17 +19,22 @@
 
 // The number of pixels from the very left or right of the screen to consider as
 // a valid origin for the left or right swipe gesture.
-constexpr int kSideGestureStartWidth = 10;
+constexpr int kDefaultSideGestureStartWidth = 10;
 
 // The number of pixels from the very top or bottom of the screen to consider as
 // a valid origin for the top or bottom swipe gesture.
-constexpr int kSideGestureStartHeight = 10;
+constexpr int kDefaultSideGestureStartHeight = 10;
 
 }  // namespace
 
 CastSystemGestureEventHandler::CastSystemGestureEventHandler(
     aura::Window* root_window)
     : EventHandler(),
+      gesture_start_width_(GetSwitchValueInt(switches::kSystemGestureStartWidth,
+                                             kDefaultSideGestureStartWidth)),
+      gesture_start_height_(
+          GetSwitchValueInt(switches::kSystemGestureStartHeight,
+                            kDefaultSideGestureStartHeight)),
       root_window_(root_window),
       current_swipe_(CastSideSwipeOrigin::NONE) {
   DCHECK(root_window);
@@ -43,18 +49,18 @@
 CastSideSwipeOrigin CastSystemGestureEventHandler::GetDragPosition(
     const gfx::Point& point,
     const gfx::Rect& screen_bounds) const {
-  if (point.y() < (screen_bounds.y() + kSideGestureStartHeight)) {
+  if (point.y() < (screen_bounds.y() + gesture_start_height_)) {
     return CastSideSwipeOrigin::TOP;
   }
-  if (point.x() < (screen_bounds.x() + kSideGestureStartWidth)) {
+  if (point.x() < (screen_bounds.x() + gesture_start_width_)) {
     return CastSideSwipeOrigin::LEFT;
   }
   if (point.x() >
-      (screen_bounds.x() + screen_bounds.width() - kSideGestureStartWidth)) {
+      (screen_bounds.x() + screen_bounds.width() - gesture_start_width_)) {
     return CastSideSwipeOrigin::RIGHT;
   }
   if (point.y() >
-      (screen_bounds.y() + screen_bounds.height() - kSideGestureStartHeight)) {
+      (screen_bounds.y() + screen_bounds.height() - gesture_start_height_)) {
     return CastSideSwipeOrigin::BOTTOM;
   }
   return CastSideSwipeOrigin::NONE;
diff --git a/chromecast/graphics/cast_system_gesture_event_handler.h b/chromecast/graphics/cast_system_gesture_event_handler.h
index 07746e541..998c502 100644
--- a/chromecast/graphics/cast_system_gesture_event_handler.h
+++ b/chromecast/graphics/cast_system_gesture_event_handler.h
@@ -43,6 +43,9 @@
   void OnGestureEvent(ui::GestureEvent* event) override;
 
  private:
+  const int gesture_start_width_;
+  const int gesture_start_height_;
+
   aura::Window* root_window_;
   CastSideSwipeOrigin current_swipe_;
 
diff --git a/chromecast/media/base/decrypt_context_impl.cc b/chromecast/media/base/decrypt_context_impl.cc
index b45fb67..2451446 100644
--- a/chromecast/media/base/decrypt_context_impl.cc
+++ b/chromecast/media/base/decrypt_context_impl.cc
@@ -50,8 +50,8 @@
   std::move(decrypt_cb).Run(false);
 }
 
-bool DecryptContextImpl::CanDecryptToBuffer() const {
-  return false;
+DecryptContextImpl::OutputType DecryptContextImpl::GetOutputType() const {
+  return OutputType::kSecure;
 }
 
 }  // namespace media
diff --git a/chromecast/media/base/decrypt_context_impl.h b/chromecast/media/base/decrypt_context_impl.h
index 5b74261..c1ffa3a 100644
--- a/chromecast/media/base/decrypt_context_impl.h
+++ b/chromecast/media/base/decrypt_context_impl.h
@@ -25,6 +25,14 @@
  public:
   using DecryptCB = base::OnceCallback<void(bool)>;
 
+  // Type for the output buffer:
+  // |kSecure| means the decrypted data will be put in a secured buffer, where
+  // normal CPU can't access.
+  // |kClearAllowed| means the license allows the decrypted data to be accessed
+  // by normal CPU. Caller can decide where is the decrypted data.
+  // |kClearRequired| means the CDM or platform doesn't support secure buffer.
+  enum class OutputType { kSecure, kClearAllowed, kClearRequired };
+
   explicit DecryptContextImpl(CastKeySystem key_system);
   ~DecryptContextImpl() override;
 
@@ -41,12 +49,8 @@
                             size_t data_offset,
                             DecryptCB decrypt_cb);
 
-  // Returns whether the data can be decrypted into user memory.
-  // If the key system doesn't support secure output or the app explicitly
-  // requires non secure output, it should return true;
-  // If the key system doesn't allow clear content to be decrypted into user
-  // memory, it should return false.
-  virtual bool CanDecryptToBuffer() const;
+  // Returns the type of output buffer.
+  virtual OutputType GetOutputType() const;
 
  private:
   CastKeySystem key_system_;
diff --git a/chromecast/media/base/decrypt_context_impl_clearkey.cc b/chromecast/media/base/decrypt_context_impl_clearkey.cc
index 29c9b24..241743c 100644
--- a/chromecast/media/base/decrypt_context_impl_clearkey.cc
+++ b/chromecast/media/base/decrypt_context_impl_clearkey.cc
@@ -84,8 +84,9 @@
   return true;
 }
 
-bool DecryptContextImplClearKey::CanDecryptToBuffer() const {
-  return true;
+DecryptContextImpl::OutputType DecryptContextImplClearKey::GetOutputType()
+    const {
+  return OutputType::kClearRequired;
 }
 
 }  // namespace media
diff --git a/chromecast/media/base/decrypt_context_impl_clearkey.h b/chromecast/media/base/decrypt_context_impl_clearkey.h
index 428bad8..b2e1c7c 100644
--- a/chromecast/media/base/decrypt_context_impl_clearkey.h
+++ b/chromecast/media/base/decrypt_context_impl_clearkey.h
@@ -31,7 +31,7 @@
                     size_t data_offset,
                     DecryptCB decrypt_cb) override;
 
-  bool CanDecryptToBuffer() const override;
+  OutputType GetOutputType() const override;
 
  private:
   bool DoDecrypt(CastDecoderBuffer* buffer,
diff --git a/chromecast/media/cma/backend/alsa/mixer_output_stream_alsa.cc b/chromecast/media/cma/backend/alsa/mixer_output_stream_alsa.cc
index 76b3495..2c128b0 100644
--- a/chromecast/media/cma/backend/alsa/mixer_output_stream_alsa.cc
+++ b/chromecast/media/cma/backend/alsa/mixer_output_stream_alsa.cc
@@ -77,7 +77,7 @@
 constexpr char kOutputDeviceDefaultName[] = "default";
 
 constexpr bool kPcmRecoverIsSilent = false;
-constexpr int kDefaultOutputBufferSizeFrames = 512;
+constexpr int kDefaultOutputBufferSizeFrames = 1024;
 
 // A list of supported sample rates.
 // TODO(jyw): move this up into chromecast/public for 1) documentation and
diff --git a/chromecast/media/cma/backend/buffering_mixer_source.cc b/chromecast/media/cma/backend/buffering_mixer_source.cc
index 5a32c3d..8340480d 100644
--- a/chromecast/media/cma/backend/buffering_mixer_source.cc
+++ b/chromecast/media/cma/backend/buffering_mixer_source.cc
@@ -17,13 +17,15 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "chromecast/media/cma/backend/stream_mixer.h"
 #include "chromecast/media/cma/base/decoder_buffer_base.h"
+#include "media/audio/audio_device_description.h"
 #include "media/base/audio_bus.h"
 #include "media/base/audio_timestamp_helper.h"
 
-#define POST_TASK_TO_CALLER_THREAD(task, ...) \
-  caller_task_runner_->PostTask(              \
-      FROM_HERE,                              \
-      base::BindOnce(&BufferingMixerSource::task, weak_this_, ##__VA_ARGS__));
+#define POST_TASK_TO_CALLER_THREAD(task, ...)                               \
+  shim_task_runner_->PostTask(                                              \
+      FROM_HERE, base::BindOnce(&PostTaskShim, caller_task_runner_,         \
+                                base::BindOnce(&BufferingMixerSource::task, \
+                                               weak_this_, ##__VA_ARGS__)));
 
 namespace chromecast {
 namespace media {
@@ -34,6 +36,16 @@
 const int64_t kInputQueueMs = 90;
 const int kFadeTimeMs = 5;
 
+// Special queue size and start threshold for "communications" streams to avoid
+// issues with voice calling.
+const int64_t kCommsInputQueueMs = 200;
+const int64_t kCommsStartThresholdMs = 150;
+
+void PostTaskShim(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+                  base::OnceClosure task) {
+  task_runner->PostTask(FROM_HERE, std::move(task));
+}
+
 std::string AudioContentTypeToString(media::AudioContentType type) {
   switch (type) {
     case media::AudioContentType::kAlarm:
@@ -55,6 +67,20 @@
       .InMicroseconds();
 }
 
+int MaxQueuedFrames(const std::string& device_id, int sample_rate) {
+  if (device_id == ::media::AudioDeviceDescription::kCommunicationsDeviceId) {
+    return MsToSamples(kCommsInputQueueMs, sample_rate);
+  }
+  return MsToSamples(kInputQueueMs, sample_rate);
+}
+
+int StartThreshold(const std::string& device_id, int sample_rate) {
+  if (device_id == ::media::AudioDeviceDescription::kCommunicationsDeviceId) {
+    return MsToSamples(kCommsStartThresholdMs, sample_rate);
+  }
+  return 0;
+}
+
 }  // namespace
 
 BufferingMixerSource::LockedMembers::Members::Members(
@@ -70,7 +96,8 @@
       fader_(source,
              num_channels,
              MsToSamples(kFadeTimeMs, input_samples_per_second)),
-      zero_fader_frames_(false) {}
+      zero_fader_frames_(false),
+      started_(false) {}
 
 BufferingMixerSource::LockedMembers::Members::~Members() = default;
 
@@ -124,13 +151,17 @@
       playout_channel_(playout_channel),
       mixer_(StreamMixer::Get()),
       caller_task_runner_(base::ThreadTaskRunnerHandle::Get()),
-      max_queued_frames_(MsToSamples(kInputQueueMs, input_samples_per_second)),
+      shim_task_runner_(mixer_->shim_task_runner()),
+      max_queued_frames_(MaxQueuedFrames(device_id, input_samples_per_second)),
+      start_threshold_frames_(
+          StartThreshold(device_id, input_samples_per_second)),
       locked_members_(this, input_samples_per_second, num_channels_),
       weak_factory_(this) {
   LOG(INFO) << "Create " << device_id_ << " (" << this
             << "), content type = " << AudioContentTypeToString(content_type_);
   DCHECK(delegate_);
   DCHECK(mixer_);
+  DCHECK_LE(start_threshold_frames_, max_queued_frames_);
   weak_this_ = weak_factory_.GetWeakPtr();
 
   mixer_->AddInput(this);
@@ -254,10 +285,22 @@
     // In normal playback, don't pass data to the fader if we can't satisfy the
     // full request. This will allow us to buffer up more data so we can fully
     // fade in.
-    locked->zero_fader_frames_ =
-        (locked->state_ == State::kNormalPlayback &&
-         locked->queued_frames_ <
-             locked->fader_.FramesNeededFromSource(num_frames));
+    if (locked->state_ == State::kNormalPlayback &&
+        (locked->queued_frames_ <
+             locked->fader_.FramesNeededFromSource(num_frames) ||
+         (!locked->started_ &&
+          locked->queued_frames_ < start_threshold_frames_))) {
+      if (locked->started_) {
+        LOG(INFO) << "Stream underrun for " << device_id_ << " (" << this
+                  << ")";
+      }
+      locked->zero_fader_frames_ = true;
+      locked->started_ = false;
+    } else {
+      locked->zero_fader_frames_ = false;
+      locked->started_ = true;
+    }
+
     filled = locked->fader_.FillFrames(num_frames, buffer);
 
     locked->mixer_rendering_delay_ = rendering_delay;
@@ -291,6 +334,7 @@
   if (signal_eos) {
     POST_TASK_TO_CALLER_THREAD(PostEos);
   }
+
   if (remove_self) {
     mixer_->RemoveInput(this);
   }
diff --git a/chromecast/media/cma/backend/buffering_mixer_source.h b/chromecast/media/cma/backend/buffering_mixer_source.h
index 8c9fba8..d192f21 100644
--- a/chromecast/media/cma/backend/buffering_mixer_source.h
+++ b/chromecast/media/cma/backend/buffering_mixer_source.h
@@ -120,6 +120,7 @@
       int current_buffer_offset_;
       AudioFader fader_;
       bool zero_fader_frames_;
+      bool started_;
 
      private:
       DISALLOW_COPY_AND_ASSIGN(Members);
@@ -200,7 +201,10 @@
   const int playout_channel_;
   StreamMixer* const mixer_;
   const scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_;
+  const scoped_refptr<base::SingleThreadTaskRunner> shim_task_runner_;
   const int max_queued_frames_;
+  // Minimum number of frames buffered before starting to fill data.
+  const int start_threshold_frames_;
 
   LockedMembers locked_members_;
 
diff --git a/chromecast/media/cma/backend/stream_mixer.cc b/chromecast/media/cma/backend/stream_mixer.cc
index f82277db..808eb4e 100644
--- a/chromecast/media/cma/backend/stream_mixer.cc
+++ b/chromecast/media/cma/backend/stream_mixer.cc
@@ -4,6 +4,8 @@
 
 #include "chromecast/media/cma/backend/stream_mixer.h"
 
+#include <pthread.h>
+
 #include <algorithm>
 #include <cmath>
 #include <limits>
@@ -15,6 +17,7 @@
 #include "base/lazy_instance.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "build/build_config.h"
 #include "chromecast/base/chromecast_switches.h"
 #include "chromecast/media/base/audio_device_ids.h"
 #include "chromecast/media/cma/backend/cast_audio_json.h"
@@ -25,15 +28,16 @@
 #include "chromecast/public/media/audio_post_processor_shlib.h"
 #include "media/audio/audio_device_description.h"
 
-#define RUN_ON_MIXER_THREAD(callback, ...)              \
-  if (!mixer_task_runner_->BelongsToCurrentThread()) {  \
-    POST_TASK_TO_MIXER_THREAD(callback, ##__VA_ARGS__); \
-    return;                                             \
-  }
+#define POST_THROUGH_SHIM_THREAD(method, ...)                                  \
+  shim_task_runner_->PostTask(                                                 \
+      FROM_HERE, base::BindOnce(&PostTaskShim, mixer_task_runner_,             \
+                                base::BindOnce(method, base::Unretained(this), \
+                                               ##__VA_ARGS__)));
 
-#define POST_TASK_TO_MIXER_THREAD(task, ...) \
-  mixer_task_runner_->PostTask(              \
-      FROM_HERE, base::BindOnce(task, base::Unretained(this), ##__VA_ARGS__));
+#define POST_TASK_TO_SHIM_THREAD(method, ...) \
+  shim_task_runner_->PostTask(                \
+      FROM_HERE,                              \
+      base::BindOnce(method, base::Unretained(this), ##__VA_ARGS__));
 
 namespace chromecast {
 namespace media {
@@ -57,6 +61,11 @@
 const int kMediaUnduckFadeMs = 700;
 const int kDefaultFilterFrameAlignment = 64;
 
+void PostTaskShim(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+                  base::OnceClosure task) {
+  task_runner->PostTask(FROM_HERE, std::move(task));
+}
+
 bool IsOutputDeviceId(const std::string& device) {
   return device == ::media::AudioDeviceDescription::kDefaultDeviceId ||
          device == ::media::AudioDeviceDescription::kCommunicationsDeviceId ||
@@ -108,6 +117,13 @@
   return base::TimeDelta::FromMilliseconds(close_timeout_ms);
 }
 
+void UseHighPriority() {
+#if (!defined(OS_FUCHSIA) && !defined(OS_ANDROID))
+  const struct sched_param kAudioPrio = {10};
+  pthread_setschedparam(pthread_self(), SCHED_RR, &kAudioPrio);
+#endif
+}
+
 base::LazyInstance<StreamMixer>::DestructorAtExit g_mixer_instance =
     LAZY_INSTANCE_INITIALIZER;
 
@@ -124,7 +140,7 @@
 
 StreamMixer::StreamMixer()
     : StreamMixer(nullptr,
-                  std::make_unique<base::Thread>("CMA mixer thread"),
+                  std::make_unique<base::Thread>("CMA mixer"),
                   nullptr) {}
 
 StreamMixer::StreamMixer(
@@ -155,6 +171,16 @@
     options.priority = base::ThreadPriority::REALTIME_AUDIO;
     mixer_thread_->StartWithOptions(options);
     mixer_task_runner_ = mixer_thread_->task_runner();
+    mixer_task_runner_->PostTask(FROM_HERE, base::BindOnce(&UseHighPriority));
+
+    shim_thread_ = std::make_unique<base::Thread>("CMA mixer PI shim");
+    base::Thread::Options shim_options;
+    shim_options.priority = base::ThreadPriority::REALTIME_AUDIO;
+    shim_thread_->StartWithOptions(shim_options);
+    shim_task_runner_ = shim_thread_->task_runner();
+    shim_task_runner_->PostTask(FROM_HERE, base::BindOnce(&UseHighPriority));
+  } else {
+    shim_task_runner_ = mixer_task_runner_;
   }
 
   if (fixed_sample_rate_ != MixerOutputStream::kInvalidSampleRate) {
@@ -269,7 +295,13 @@
 
 StreamMixer::~StreamMixer() {
   VLOG(1) << __func__;
-  POST_TASK_TO_MIXER_THREAD(&StreamMixer::FinalizeOnMixerThread);
+  if (shim_thread_) {
+    shim_thread_->Stop();
+  }
+
+  mixer_task_runner_->PostTask(
+      FROM_HERE, base::BindOnce(&StreamMixer::FinalizeOnMixerThread,
+                                base::Unretained(this)));
   if (mixer_thread_) {
     mixer_thread_->Stop();
   }
@@ -341,9 +373,7 @@
 
   weak_factory_.InvalidateWeakPtrs();
 
-  for (auto* observer : loopback_observers_) {
-    observer->OnLoopbackInterrupted();
-  }
+  POST_TASK_TO_SHIM_THREAD(&StreamMixer::LoopbackInterrupted);
 
   if (output_) {
     output_->Stop();
@@ -389,7 +419,11 @@
 }
 
 void StreamMixer::AddInput(MixerInput::Source* input_source) {
-  RUN_ON_MIXER_THREAD(&StreamMixer::AddInput, input_source);
+  POST_THROUGH_SHIM_THREAD(&StreamMixer::AddInputOnThread, input_source);
+}
+
+void StreamMixer::AddInputOnThread(MixerInput::Source* input_source) {
+  DCHECK(mixer_task_runner_->BelongsToCurrentThread());
   DCHECK(input_source);
 
   LOG(INFO) << "Add input " << input_source;
@@ -449,7 +483,7 @@
 }
 
 void StreamMixer::RemoveInput(MixerInput::Source* input_source) {
-  POST_TASK_TO_MIXER_THREAD(&StreamMixer::RemoveInputOnThread, input_source);
+  POST_THROUGH_SHIM_THREAD(&StreamMixer::RemoveInputOnThread, input_source);
 }
 
 void StreamMixer::RemoveInputOnThread(MixerInput::Source* input_source) {
@@ -578,12 +612,14 @@
     mixed_data[i] = std::min(1.0f, std::max(-1.0f, mixed_data[i]));
   }
 
-  for (CastMediaShlib::LoopbackAudioObserver* observer : loopback_observers_) {
-    observer->OnLoopbackAudio(
-        expected_playback_time, kSampleFormatF32, output_samples_per_second_,
-        loopback_channel_count, reinterpret_cast<uint8_t*>(mixed_data),
-        static_cast<size_t>(frames) * loopback_channel_count * sizeof(float));
-  }
+  auto loopback_data =
+      std::make_unique<float[]>(frames * loopback_channel_count);
+  std::copy(mixed_data, mixed_data + frames * loopback_channel_count,
+            loopback_data.get());
+  POST_TASK_TO_SHIM_THREAD(&StreamMixer::SendLoopbackData,
+                           expected_playback_time, output_samples_per_second_,
+                           frames, loopback_channel_count,
+                           std::move(loopback_data));
 
   // Drop extra channels from linearize filter if necessary.
   float* linearized_data = linearize_filter_->GetOutputBuffer();
@@ -604,28 +640,63 @@
                  &playback_interrupted);
 
   if (playback_interrupted) {
-    for (auto* observer : loopback_observers_) {
-      observer->OnLoopbackInterrupted();
-    }
+    POST_TASK_TO_SHIM_THREAD(&StreamMixer::LoopbackInterrupted);
   }
 }
 
 void StreamMixer::AddLoopbackAudioObserver(
     CastMediaShlib::LoopbackAudioObserver* observer) {
-  RUN_ON_MIXER_THREAD(&StreamMixer::AddLoopbackAudioObserver, observer);
+  POST_TASK_TO_SHIM_THREAD(&StreamMixer::AddLoopbackAudioObserverOnShimThread,
+                           observer);
+}
+
+void StreamMixer::AddLoopbackAudioObserverOnShimThread(
+    CastMediaShlib::LoopbackAudioObserver* observer) {
+  DCHECK(shim_task_runner_->BelongsToCurrentThread());
   DCHECK(observer);
   loopback_observers_.insert(observer);
 }
 
 void StreamMixer::RemoveLoopbackAudioObserver(
     CastMediaShlib::LoopbackAudioObserver* observer) {
-  RUN_ON_MIXER_THREAD(&StreamMixer::RemoveLoopbackAudioObserver, observer);
+  POST_TASK_TO_SHIM_THREAD(
+      &StreamMixer::RemoveLoopbackAudioObserverOnShimThread, observer);
+}
+
+void StreamMixer::RemoveLoopbackAudioObserverOnShimThread(
+    CastMediaShlib::LoopbackAudioObserver* observer) {
+  DCHECK(shim_task_runner_->BelongsToCurrentThread());
   loopback_observers_.erase(observer);
   observer->OnRemoved();
 }
 
+void StreamMixer::SendLoopbackData(int64_t expected_playback_time,
+                                   int sample_rate,
+                                   int frames,
+                                   int channels,
+                                   std::unique_ptr<float[]> data) {
+  DCHECK(shim_task_runner_->BelongsToCurrentThread());
+  for (CastMediaShlib::LoopbackAudioObserver* observer : loopback_observers_) {
+    observer->OnLoopbackAudio(
+        expected_playback_time, kSampleFormatF32, sample_rate, channels,
+        reinterpret_cast<uint8_t*>(data.get()),
+        static_cast<size_t>(frames) * channels * sizeof(float));
+  }
+}
+
+void StreamMixer::LoopbackInterrupted() {
+  DCHECK(shim_task_runner_->BelongsToCurrentThread());
+  for (auto* observer : loopback_observers_) {
+    observer->OnLoopbackInterrupted();
+  }
+}
+
 void StreamMixer::SetVolume(AudioContentType type, float level) {
-  RUN_ON_MIXER_THREAD(&StreamMixer::SetVolume, type, level);
+  POST_THROUGH_SHIM_THREAD(&StreamMixer::SetVolumeOnThread, type, level);
+}
+
+void StreamMixer::SetVolumeOnThread(AudioContentType type, float level) {
+  DCHECK(mixer_task_runner_->BelongsToCurrentThread());
   volume_info_[type].volume = level;
   float effective_volume = volume_info_[type].GetEffectiveVolume();
   for (const auto& input : inputs_) {
@@ -641,7 +712,11 @@
 }
 
 void StreamMixer::SetMuted(AudioContentType type, bool muted) {
-  RUN_ON_MIXER_THREAD(&StreamMixer::SetMuted, type, muted);
+  POST_THROUGH_SHIM_THREAD(&StreamMixer::SetMutedOnThread, type, muted);
+}
+
+void StreamMixer::SetMutedOnThread(AudioContentType type, bool muted) {
+  DCHECK(mixer_task_runner_->BelongsToCurrentThread());
   volume_info_[type].muted = muted;
   for (const auto& input : inputs_) {
     if (input.second->content_type() == type) {
@@ -651,7 +726,11 @@
 }
 
 void StreamMixer::SetOutputLimit(AudioContentType type, float limit) {
-  RUN_ON_MIXER_THREAD(&StreamMixer::SetOutputLimit, type, limit);
+  POST_THROUGH_SHIM_THREAD(&StreamMixer::SetOutputLimitOnThread, type, limit);
+}
+
+void StreamMixer::SetOutputLimitOnThread(AudioContentType type, float limit) {
+  DCHECK(mixer_task_runner_->BelongsToCurrentThread());
   LOG(INFO) << "Set volume limit for " << static_cast<int>(type) << " to "
             << limit;
   volume_info_[type].limit = limit;
@@ -674,7 +753,13 @@
 
 void StreamMixer::SetVolumeMultiplier(MixerInput::Source* source,
                                       float multiplier) {
-  RUN_ON_MIXER_THREAD(&StreamMixer::SetVolumeMultiplier, source, multiplier);
+  POST_THROUGH_SHIM_THREAD(&StreamMixer::SetVolumeMultiplierOnThread, source,
+                           multiplier);
+}
+
+void StreamMixer::SetVolumeMultiplierOnThread(MixerInput::Source* source,
+                                              float multiplier) {
+  DCHECK(mixer_task_runner_->BelongsToCurrentThread());
   auto it = inputs_.find(source);
   if (it != inputs_.end()) {
     it->second->SetVolumeMultiplier(multiplier);
@@ -683,7 +768,13 @@
 
 void StreamMixer::SetPostProcessorConfig(const std::string& name,
                                          const std::string& config) {
-  RUN_ON_MIXER_THREAD(&StreamMixer::SetPostProcessorConfig, name, config);
+  POST_THROUGH_SHIM_THREAD(&StreamMixer::SetPostProcessorConfigOnThread, name,
+                           config);
+}
+
+void StreamMixer::SetPostProcessorConfigOnThread(const std::string& name,
+                                                 const std::string& config) {
+  DCHECK(mixer_task_runner_->BelongsToCurrentThread());
   for (auto&& filter_group : filter_groups_) {
     filter_group->SetPostProcessorConfig(name, config);
   }
diff --git a/chromecast/media/cma/backend/stream_mixer.h b/chromecast/media/cma/backend/stream_mixer.h
index 0145d2e..c67983b 100644
--- a/chromecast/media/cma/backend/stream_mixer.h
+++ b/chromecast/media/cma/backend/stream_mixer.h
@@ -53,6 +53,20 @@
 //    input sources, then the output sample rate is updated to match the input
 //    sample rate of the new source.
 //  * Otherwise, the output sample rate remains unchanged.
+//
+// We use a "shim thread" to avoid priority inversion due to PostTask to
+// low-priority threads. Suppose we want to PostTask to some low-priority
+// thread, and the internal PostTask mutex is locked by that thread (and the
+// low-priority thread isn't running right now). If the mixer thread does the
+// PostTask, then it will block until the low-priority thread gets to run again
+// and unlocks the mutex. Instead, we can PostTask to the shim thread (which is
+// high-priority, and won't be holding the mutex for significant periods) and so
+// avoid blocking waiting for the low-priority thread. The shim thread will
+// maybe block when it does the PostTask to the low-priority thread, but we
+// don't really care about that.
+// All loopback audio handling is done on the shim thread, and any tasks posted
+// from/to potentially low-priority threads should be done through the shim
+// thread.
 class StreamMixer {
  public:
   // Returns the mixer instance for this process. Caller must not delete the
@@ -105,6 +119,10 @@
   void ValidatePostProcessorsForTest();
   int num_output_channels() const { return num_output_channels_; }
 
+  scoped_refptr<base::SingleThreadTaskRunner> shim_task_runner() const {
+    return shim_task_runner_;
+  }
+
  private:
   enum State {
     kStateStopped,
@@ -127,6 +145,7 @@
   void Stop();
   void CheckChangeOutputRate(int input_samples_per_second);
   void SignalError(MixerInput::Source::MixerError error);
+  void AddInputOnThread(MixerInput::Source* input_source);
   void RemoveInputOnThread(MixerInput::Source* input_source);
   void SetCloseTimeout();
   void UpdatePlayoutChannel();
@@ -137,12 +156,35 @@
   void WriteOneBuffer();
   void WriteMixedPcm(int frames, int64_t expected_playback_time);
 
+  void SetVolumeOnThread(AudioContentType type, float level);
+  void SetMutedOnThread(AudioContentType type, bool muted);
+  void SetOutputLimitOnThread(AudioContentType type, float limit);
+  void SetVolumeMultiplierOnThread(MixerInput::Source* source,
+                                   float multiplier);
+  void SetPostProcessorConfigOnThread(const std::string& name,
+                                      const std::string& config);
+
+  void AddLoopbackAudioObserverOnShimThread(
+      CastMediaShlib::LoopbackAudioObserver* observer);
+  void RemoveLoopbackAudioObserverOnShimThread(
+      CastMediaShlib::LoopbackAudioObserver* observer);
+  void SendLoopbackData(int64_t expected_playback_time,
+                        int sample_rate,
+                        int frames,
+                        int channels,
+                        std::unique_ptr<float[]> data);
+  void LoopbackInterrupted();
+
   std::unique_ptr<MixerOutputStream> output_;
   std::unique_ptr<PostProcessingPipelineFactory>
       post_processing_pipeline_factory_;
   std::unique_ptr<base::Thread> mixer_thread_;
   scoped_refptr<base::SingleThreadTaskRunner> mixer_task_runner_;
 
+  // Special thread to avoid underruns due to priority inversion.
+  std::unique_ptr<base::Thread> shim_thread_;
+  scoped_refptr<base::SingleThreadTaskRunner> shim_task_runner_;
+
   int num_output_channels_;
   const int low_sample_rate_cutoff_;
   const int fixed_sample_rate_;
diff --git a/chromecast/media/cma/backend/stream_mixer_unittest.cc b/chromecast/media/cma/backend/stream_mixer_unittest.cc
index 517335c..7a9c83c9 100644
--- a/chromecast/media/cma/backend/stream_mixer_unittest.cc
+++ b/chromecast/media/cma/backend/stream_mixer_unittest.cc
@@ -455,6 +455,15 @@
              static_cast<size_t>(kNumPostProcessors));
   }
 
+  void WaitForMixer() {
+    base::RunLoop run_loop1;
+    message_loop_->task_runner()->PostTask(FROM_HERE, run_loop1.QuitClosure());
+    run_loop1.Run();
+    base::RunLoop run_loop2;
+    message_loop_->task_runner()->PostTask(FROM_HERE, run_loop2.QuitClosure());
+    run_loop2.Run();
+  }
+
   void PlaybackOnce() {
     // Run one playback iteration.
     EXPECT_CALL(*mock_output_, Write(_,
@@ -465,13 +474,7 @@
     base::RunLoop run_loop;
     message_loop_->task_runner()->PostTask(FROM_HERE, run_loop.QuitClosure());
     run_loop.Run();
-  }
-
-  void WaitForRemoval() {
-    // Need to wait for the removal task (it is always posted).
-    base::RunLoop run_loop;
-    message_loop_->task_runner()->PostTask(FROM_HERE, run_loop.QuitClosure());
-    run_loop.Run();
+    testing::Mock::VerifyAndClearExpectations(mock_output_);
   }
 
  protected:
@@ -490,6 +493,7 @@
   EXPECT_CALL(*mock_output_, Start(kTestSamplesPerSecond, _)).Times(1);
   EXPECT_CALL(*mock_output_, Stop()).Times(0);
   mixer_->AddInput(&input);
+  WaitForMixer();
 
   mixer_.reset();
 }
@@ -504,6 +508,7 @@
   EXPECT_CALL(*mock_output_, Stop()).Times(0);
   mixer_->AddInput(&input1);
   mixer_->AddInput(&input2);
+  WaitForMixer();
 
   mixer_.reset();
 }
@@ -524,12 +529,14 @@
     mixer_->AddInput(inputs[i].get());
   }
 
+  WaitForMixer();
+
   for (size_t i = 0; i < inputs.size(); ++i) {
     EXPECT_CALL(*inputs[i], FinalizeAudioPlayback()).Times(1);
     mixer_->RemoveInput(inputs[i].get());
   }
 
-  WaitForRemoval();
+  WaitForMixer();
 }
 
 TEST_F(StreamMixerTest, WriteFrames) {
@@ -547,6 +554,8 @@
     mixer_->AddInput(inputs[i].get());
   }
 
+  WaitForMixer();
+
   for (size_t i = 0; i < inputs.size(); ++i) {
     EXPECT_CALL(*inputs[i], FillAudioPlaybackFrames(_, _, _)).Times(1);
   }
@@ -563,6 +572,7 @@
   EXPECT_CALL(*mock_output_, Start(kTestSamplesPerSecond, _)).Times(1);
   EXPECT_CALL(*mock_output_, Stop()).Times(0);
   mixer_->AddInput(&input);
+  WaitForMixer();
   mock_output_->ClearData();
 
   // Populate the stream with data.
@@ -589,17 +599,17 @@
   EXPECT_CALL(input, InitializeAudioPlayback(_, _)).Times(1);
   EXPECT_CALL(*mock_output_, Start(kTestSamplesPerSecond, _)).Times(1);
   EXPECT_CALL(*mock_output_, Stop()).Times(0);
+  input.set_multiplier(0.75f);
   mixer_->AddInput(&input);
-  mock_output_->ClearData();
+  mixer_->SetVolumeMultiplier(&input, input.multiplier());
+  WaitForMixer();
 
   // Populate the stream with data.
   const int kNumFrames = 32;
   ASSERT_EQ(sizeof(kTestData[0]), kNumChannels * kNumFrames * kBytesPerSample);
   input.SetData(GetTestData(0));
 
-  // Set the volume multiplier.
-  input.set_multiplier(0.75f);
-  mixer_->SetVolumeMultiplier(&input, input.multiplier());
+  mock_output_->ClearData();
 
   EXPECT_CALL(input, FillAudioPlaybackFrames(_, _, _)).Times(1);
   PlaybackOnce();
@@ -630,6 +640,7 @@
     EXPECT_CALL(*inputs[i], InitializeAudioPlayback(_, _)).Times(1);
     mixer_->AddInput(inputs[i].get());
   }
+  WaitForMixer();
   mock_output_->ClearData();
 
   // Populate the streams with data.
@@ -669,6 +680,7 @@
     EXPECT_CALL(*inputs[i], InitializeAudioPlayback(_, _)).Times(1);
     mixer_->AddInput(inputs[i].get());
   }
+  WaitForMixer();
   mock_output_->ClearData();
 
   // Populate the streams with data.
@@ -706,6 +718,7 @@
     EXPECT_CALL(*inputs[i], InitializeAudioPlayback(_, _)).Times(1);
     mixer_->AddInput(inputs[i].get());
   }
+  WaitForMixer();
   mock_output_->ClearData();
 
   // Create edge case data for the inputs. By mixing these two short streams,
@@ -792,6 +805,7 @@
     EXPECT_CALL(*inputs[i], InitializeAudioPlayback(_, _)).Times(1);
     mixer_->AddInput(inputs[i].get());
   }
+  WaitForMixer();
 
   auto* post_processors = &pp_factory_->instances;
   EXPECT_POSTPROCESSOR_CALL_PROCESSFRAMES(post_processors, "default", 1, _,
@@ -832,6 +846,7 @@
   EXPECT_POSTPROCESSOR_CALL_PROCESSFRAMES(post_processors, "assistant-tts", 1,
                                           _, _);
   mixer_->AddInput(&input);
+  WaitForMixer();
 
   // Delay should be based on default processor.
   int64_t delay = FramesToDelayUs(
@@ -880,6 +895,7 @@
   MockPostProcessorFactory* factory_ptr = factory.get();
   mixer_->ResetPostProcessorsForTest(std::move(factory), test_pipeline_json);
   mixer_->AddInput(&input);
+  WaitForMixer();
 
   // "mix" + "linearize" should be automatic
   CHECK_EQ(factory_ptr->instances.size(), 4u);
@@ -976,11 +992,13 @@
   // Requests: all = 0 ch0 = 0 ch1 = 1.
   EXPECT_CALL_ALL_POSTPROCESSORS(factory_ptr, UpdatePlayoutChannel(1));
   mixer_->AddInput(&input3);
+  WaitForMixer();
   VerifyAndClearPostProcessors(factory_ptr);
 
   // Requests: all = 0 ch0 = 0 ch1 = 2.
   EXPECT_CALL_ALL_POSTPROCESSORS(factory_ptr, UpdatePlayoutChannel(1));
   mixer_->AddInput(&input4);
+  WaitForMixer();
   VerifyAndClearPostProcessors(factory_ptr);
 
   // Requests: all = 1 ch0 = 0 ch1 = 2.
@@ -988,42 +1006,45 @@
   EXPECT_CALL_ALL_POSTPROCESSORS(factory_ptr,
                                  UpdatePlayoutChannel(kChannelAll));
   mixer_->AddInput(&input1);
+  WaitForMixer();
   VerifyAndClearPostProcessors(factory_ptr);
 
   // Requests: all = 1 ch0 = 0 ch1 = 1.
   EXPECT_CALL_ALL_POSTPROCESSORS(factory_ptr,
                                  UpdatePlayoutChannel(kChannelAll));
   mixer_->RemoveInput(&input3);
-  WaitForRemoval();
+  WaitForMixer();
   VerifyAndClearPostProcessors(factory_ptr);
 
   // Requests: all = 0 ch0 = 0 ch1 = 1.
   EXPECT_CALL_ALL_POSTPROCESSORS(factory_ptr, UpdatePlayoutChannel(1));
   mixer_->RemoveInput(&input1);
-  WaitForRemoval();
+  WaitForMixer();
   VerifyAndClearPostProcessors(factory_ptr);
 
   // Requests: all = 0 ch0 = 0 ch1 = 0.
   EXPECT_CALL_ALL_POSTPROCESSORS(factory_ptr,
                                  UpdatePlayoutChannel(kChannelAll));
   mixer_->RemoveInput(&input4);
-  WaitForRemoval();
+  WaitForMixer();
   VerifyAndClearPostProcessors(factory_ptr);
 
   // Requests: all = 0 ch0 = 1 ch1 = 0
   EXPECT_CALL_ALL_POSTPROCESSORS(factory_ptr, UpdatePlayoutChannel(0));
   mixer_->AddInput(&input2);
+  WaitForMixer();
   VerifyAndClearPostProcessors(factory_ptr);
 
   // Requests: all = 1 ch0 = 1 ch1 = 0
   EXPECT_CALL_ALL_POSTPROCESSORS(factory_ptr,
                                  UpdatePlayoutChannel(kChannelAll));
   mixer_->AddInput(&input1);
+  WaitForMixer();
   VerifyAndClearPostProcessors(factory_ptr);
 
   mixer_->RemoveInput(&input1);
   mixer_->RemoveInput(&input2);
-  WaitForRemoval();
+  WaitForMixer();
 }
 
 TEST_F(StreamMixerTest, SetPostProcessorConfig) {
@@ -1035,6 +1056,7 @@
   }
 
   mixer_->SetPostProcessorConfig(name, config);
+  WaitForMixer();
 }
 
 TEST_F(StreamMixerTest, ObserverGets2ChannelsByDefault) {
@@ -1042,15 +1064,18 @@
   testing::StrictMock<MockLoopbackAudioObserver> observer;
   mixer_->AddInput(&input);
   mixer_->AddLoopbackAudioObserver(&observer);
+  WaitForMixer();
 
   EXPECT_CALL(observer,
               OnLoopbackAudio(_, kSampleFormatF32, kTestSamplesPerSecond,
-                              kNumChannels, _, _));
+                              kNumChannels, _, _))
+      .Times(testing::AtLeast(1));
 
   PlaybackOnce();
 
   EXPECT_CALL(observer, OnRemoved());
   mixer_->RemoveLoopbackAudioObserver(&observer);
+  WaitForMixer();
 
   mixer_.reset();
 }
@@ -1063,15 +1088,18 @@
   testing::StrictMock<MockLoopbackAudioObserver> observer;
   mixer_->AddInput(&input);
   mixer_->AddLoopbackAudioObserver(&observer);
+  WaitForMixer();
 
   EXPECT_CALL(observer,
               OnLoopbackAudio(_, kSampleFormatF32, kTestSamplesPerSecond,
-                              kNumOutputChannels, _, _));
+                              kNumOutputChannels, _, _))
+      .Times(testing::AtLeast(1));
 
   PlaybackOnce();
 
   EXPECT_CALL(observer, OnRemoved());
   mixer_->RemoveLoopbackAudioObserver(&observer);
+  WaitForMixer();
 
   mixer_.reset();
 }
diff --git a/chromecast/media/cma/backend/video/av_sync_video.cc b/chromecast/media/cma/backend/video/av_sync_video.cc
index a759bc2..7cb56486b 100644
--- a/chromecast/media/cma/backend/video/av_sync_video.cc
+++ b/chromecast/media/cma/backend/video/av_sync_video.cc
@@ -38,9 +38,11 @@
 constexpr base::TimeDelta kAvSyncUpkeepInterval =
     base::TimeDelta::FromMilliseconds(10);
 
+#if DCHECK_IS_ON()
 // Time interval between checking playbacks statistics.
 constexpr base::TimeDelta kPlaybackStatisticsCheckInterval =
     base::TimeDelta::FromSeconds(1);
+#endif
 
 // When we're in sync (i.e. the apts and vpts difference is
 // < kSoftCorrectionThresholdUs), if the apts and vpts slopes are different by
@@ -195,6 +197,11 @@
 }
 
 void AvSyncVideo::GatherPlaybackStatistics() {
+  DCHECK(backend_);
+  if (!backend_->video_decoder()) {
+    return;
+  }
+
   int64_t frame_rate_difference =
       (backend_->video_decoder()->GetCurrentContentRefreshRate() -
        backend_->video_decoder()->GetOutputRefreshRate()) /
diff --git a/chromecast/media/cma/pipeline/audio_pipeline_impl.cc b/chromecast/media/cma/pipeline/audio_pipeline_impl.cc
index 49f5f98..9d3859d5 100644
--- a/chromecast/media/cma/pipeline/audio_pipeline_impl.cc
+++ b/chromecast/media/cma/pipeline/audio_pipeline_impl.cc
@@ -80,14 +80,14 @@
 }
 
 std::unique_ptr<StreamDecryptor> AudioPipelineImpl::CreateDecryptor() {
+  bool clear_buffer_needed = audio_decoder_->RequiresDecryption();
   if (audio_config_.encryption_scheme.is_encrypted() &&
-      MediaPipelineBackend::CreateAudioDecryptor &&
-      audio_decoder_->RequiresDecryption()) {
+      MediaPipelineBackend::CreateAudioDecryptor && clear_buffer_needed) {
     CMALOG(kLogControl) << __func__ << " Create backend decryptor for audio.";
     return std::make_unique<BackendDecryptor>(audio_config_.encryption_scheme);
   }
 
-  return std::make_unique<CdmDecryptor>();
+  return std::make_unique<CdmDecryptor>(clear_buffer_needed);
 }
 
 void AudioPipelineImpl::UpdateStatistics() {
diff --git a/chromecast/media/cma/pipeline/cdm_decryptor.cc b/chromecast/media/cma/pipeline/cdm_decryptor.cc
index 1a26323..993358ec 100644
--- a/chromecast/media/cma/pipeline/cdm_decryptor.cc
+++ b/chromecast/media/cma/pipeline/cdm_decryptor.cc
@@ -12,7 +12,8 @@
 namespace chromecast {
 namespace media {
 
-CdmDecryptor::CdmDecryptor() : weak_factory_(this) {
+CdmDecryptor::CdmDecryptor(bool clear_buffer_needed)
+    : clear_buffer_needed_(clear_buffer_needed), weak_factory_(this) {
   weak_this_ = weak_factory_.GetWeakPtr();
 }
 
@@ -33,7 +34,10 @@
       static_cast<DecryptContextImpl*>(buffer->decrypt_context());
   DCHECK(decrypt_context);
 
-  if (decrypt_context->CanDecryptToBuffer()) {
+  DecryptContextImpl::OutputType output_type = decrypt_context->GetOutputType();
+  if (output_type == DecryptContextImpl::OutputType::kClearRequired ||
+      (clear_buffer_needed_ &&
+       output_type == DecryptContextImpl::OutputType::kClearAllowed)) {
     DecryptDecoderBuffer(std::move(buffer), decrypt_context,
                          base::BindOnce(&CdmDecryptor::OnResult, weak_this_));
     return;
diff --git a/chromecast/media/cma/pipeline/cdm_decryptor.h b/chromecast/media/cma/pipeline/cdm_decryptor.h
index 0de4c3d7..f822000 100644
--- a/chromecast/media/cma/pipeline/cdm_decryptor.h
+++ b/chromecast/media/cma/pipeline/cdm_decryptor.h
@@ -14,7 +14,7 @@
 // StreamDecryptor implemented with CDM decrypt APIs.
 class CdmDecryptor : public StreamDecryptor {
  public:
-  CdmDecryptor();
+  explicit CdmDecryptor(bool clear_buffer_needed);
   ~CdmDecryptor() override;
 
   // StreamDecryptor implementation:
@@ -26,6 +26,8 @@
 
   DecryptCB decrypt_cb_;
 
+  const bool clear_buffer_needed_;
+
   base::WeakPtr<CdmDecryptor> weak_this_;
   base::WeakPtrFactory<CdmDecryptor> weak_factory_;
   DISALLOW_COPY_AND_ASSIGN(CdmDecryptor);
diff --git a/chromecast/media/cma/pipeline/video_pipeline_impl.cc b/chromecast/media/cma/pipeline/video_pipeline_impl.cc
index 8a9e5f1..efec585f 100644
--- a/chromecast/media/cma/pipeline/video_pipeline_impl.cc
+++ b/chromecast/media/cma/pipeline/video_pipeline_impl.cc
@@ -127,7 +127,7 @@
 }
 
 std::unique_ptr<StreamDecryptor> VideoPipelineImpl::CreateDecryptor() {
-  return std::make_unique<CdmDecryptor>();
+  return std::make_unique<CdmDecryptor>(false /* clear_buffer_needed */);
 }
 
 void VideoPipelineImpl::UpdateStatistics() {
diff --git a/chromecast/public/reboot_shlib.h b/chromecast/public/reboot_shlib.h
index de9efa42..c12ef1f 100644
--- a/chromecast/public/reboot_shlib.h
+++ b/chromecast/public/reboot_shlib.h
@@ -15,6 +15,7 @@
 // All methods in the RebootShlib interface can be called from any thread.
 class CHROMECAST_EXPORT RebootShlib {
  public:
+  // GENERATED_JAVA_ENUM_PACKAGE: com.google.android.apps.cast
   enum RebootSource {
     // A default value to use if the source of a reboot is not known.
     UNKNOWN = 0,
diff --git a/chromecast/renderer/DEPS b/chromecast/renderer/DEPS
index 4858adc..fc623b2f 100644
--- a/chromecast/renderer/DEPS
+++ b/chromecast/renderer/DEPS
@@ -9,7 +9,7 @@
   "+extensions/common",
   "+extensions/renderer",
   "+media/base",
-  "+media/media_features.h",
+  "+media/media_buildflags.h",
   "+media/renderers",
   "+mojo/public",
   "+services/service_manager/public",
diff --git a/chromecast/renderer/media/key_systems_cast.cc b/chromecast/renderer/media/key_systems_cast.cc
index a67a65d..aee10818 100644
--- a/chromecast/renderer/media/key_systems_cast.cc
+++ b/chromecast/renderer/media/key_systems_cast.cc
@@ -15,7 +15,7 @@
 #include "components/cdm/renderer/widevine_key_system_properties.h"
 #include "media/base/eme_constants.h"
 #include "media/base/key_system_properties.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 #include "widevine_cdm_version.h"  // In SHARED_INTERMEDIATE_DIR.
 
diff --git a/chromecast/system/reboot/BUILD.gn b/chromecast/system/reboot/BUILD.gn
index 25331b92..b3cb233 100644
--- a/chromecast/system/reboot/BUILD.gn
+++ b/chromecast/system/reboot/BUILD.gn
@@ -12,7 +12,6 @@
   ]
 
   deps = [
-    ":libcast_reboot_1.0",
     "//base",
   ]
 
@@ -21,6 +20,18 @@
   } else {
     sources += [ "reboot_util_dummy.cc" ]
   }
+
+  if (is_android_things && chromecast_branding != "public") {
+    deps += [
+      "//chromecast/internal/system/reboot/android:reboot_android_things",
+      "//chromecast/public",
+    ]
+  } else if (is_android) {
+    sources += [ "reboot_dummy.cc" ]
+    deps += [ "//chromecast/public" ]
+  } else {
+    deps += [ ":libcast_reboot_1.0" ]
+  }
 }
 
 test("cast_reboot_unittests") {
diff --git a/chromeos/components/tether/asynchronous_shutdown_object_container_impl.cc b/chromeos/components/tether/asynchronous_shutdown_object_container_impl.cc
index 38bd02e..31a821c 100644
--- a/chromeos/components/tether/asynchronous_shutdown_object_container_impl.cc
+++ b/chromeos/components/tether/asynchronous_shutdown_object_container_impl.cc
@@ -97,6 +97,7 @@
       ble_scanner_(BleScannerImpl::Factory::NewInstance(
           adapter,
           local_device_data_provider_.get(),
+          remote_beacon_seed_fetcher_.get(),
           ble_synchronizer_.get(),
           tether_host_fetcher_)),
       ad_hoc_ble_advertiser_(std::make_unique<AdHocBleAdvertiserImpl>(
diff --git a/chromeos/components/tether/ble_scanner_impl.cc b/chromeos/components/tether/ble_scanner_impl.cc
index de303b0..278788a 100644
--- a/chromeos/components/tether/ble_scanner_impl.cc
+++ b/chromeos/components/tether/ble_scanner_impl.cc
@@ -13,7 +13,9 @@
 #include "chromeos/components/tether/ble_constants.h"
 #include "chromeos/components/tether/ble_synchronizer.h"
 #include "chromeos/components/tether/tether_host_fetcher.h"
+#include "components/cryptauth/local_device_data_provider.h"
 #include "components/cryptauth/proto/cryptauth_api.pb.h"
+#include "components/cryptauth/remote_beacon_seed_fetcher.h"
 #include "components/cryptauth/remote_device.h"
 #include "components/proximity_auth/logging/logging.h"
 #include "device/bluetooth/bluetooth_device.h"
@@ -26,10 +28,15 @@
 
 namespace {
 
-// Valid service data must include at least 4 bytes: 2 bytes associated with the
-// scanning device (used as a scan filter) and 2 bytes which identify the
-// advertising device to the scanning device.
-const size_t kMinNumBytesInServiceData = 4;
+// Valid advertisement service data must be at least 2 bytes.
+// As of March 2018, valid background advertisement service data is exactly 2
+// bytes, which identify the advertising device to the scanning device.
+// Valid foreground advertisement service data must include at least 4 bytes:
+// 2 bytes associated with the scanning device (used as a scan filter) and 2
+// bytes which identify the advertising device to the scanning device.
+const size_t kMinNumBytesInServiceData = 2;
+const size_t kMaxNumBytesInBackgroundServiceData = 3;
+const size_t kMinNumBytesInForegroundServiceData = 4;
 
 }  // namespace
 
@@ -40,14 +47,15 @@
 std::unique_ptr<BleScanner> BleScannerImpl::Factory::NewInstance(
     scoped_refptr<device::BluetoothAdapter> adapter,
     cryptauth::LocalDeviceDataProvider* local_device_data_provider,
+    cryptauth::RemoteBeaconSeedFetcher* remote_beacon_seed_fetcher,
     BleSynchronizerBase* ble_synchronizer,
     TetherHostFetcher* tether_host_fetcher) {
   if (!factory_instance_)
     factory_instance_ = new Factory();
 
-  return factory_instance_->BuildInstance(adapter, local_device_data_provider,
-                                          ble_synchronizer,
-                                          tether_host_fetcher);
+  return factory_instance_->BuildInstance(
+      adapter, local_device_data_provider, remote_beacon_seed_fetcher,
+      ble_synchronizer, tether_host_fetcher);
 }
 
 // static
@@ -58,11 +66,12 @@
 std::unique_ptr<BleScanner> BleScannerImpl::Factory::BuildInstance(
     scoped_refptr<device::BluetoothAdapter> adapter,
     cryptauth::LocalDeviceDataProvider* local_device_data_provider,
+    cryptauth::RemoteBeaconSeedFetcher* remote_beacon_seed_fetcher,
     BleSynchronizerBase* ble_synchronizer,
     TetherHostFetcher* tether_host_fetcher) {
-  return base::WrapUnique(
-      new BleScannerImpl(adapter, local_device_data_provider, ble_synchronizer,
-                         tether_host_fetcher));
+  return base::WrapUnique(new BleScannerImpl(
+      adapter, local_device_data_provider, remote_beacon_seed_fetcher,
+      ble_synchronizer, tether_host_fetcher));
 }
 
 BleScannerImpl::ServiceDataProviderImpl::ServiceDataProviderImpl() = default;
@@ -79,14 +88,19 @@
 BleScannerImpl::BleScannerImpl(
     scoped_refptr<device::BluetoothAdapter> adapter,
     cryptauth::LocalDeviceDataProvider* local_device_data_provider,
+    cryptauth::RemoteBeaconSeedFetcher* remote_beacon_seed_fetcher,
     BleSynchronizerBase* ble_synchronizer,
     TetherHostFetcher* tether_host_fetcher)
     : adapter_(adapter),
       local_device_data_provider_(local_device_data_provider),
+      remote_beacon_seed_fetcher_(remote_beacon_seed_fetcher),
       ble_synchronizer_(ble_synchronizer),
       tether_host_fetcher_(tether_host_fetcher),
       service_data_provider_(std::make_unique<ServiceDataProviderImpl>()),
-      eid_generator_(std::make_unique<cryptauth::ForegroundEidGenerator>()),
+      background_eid_generator_(
+          std::make_unique<cryptauth::BackgroundEidGenerator>()),
+      foreground_eid_generator_(
+          std::make_unique<cryptauth::ForegroundEidGenerator>()),
       task_runner_(base::ThreadTaskRunnerHandle::Get()),
       weak_ptr_factory_(this) {
   adapter_->AddObserver(this);
@@ -116,7 +130,8 @@
   }
 
   std::unique_ptr<cryptauth::ForegroundEidGenerator::EidData> scan_filters =
-      eid_generator_->GenerateBackgroundScanFilter(local_device_beacon_seeds);
+      foreground_eid_generator_->GenerateBackgroundScanFilter(
+          local_device_beacon_seeds);
   if (!scan_filters) {
     PA_LOG(WARNING) << "Error generating background scan filters. Cannot scan";
     return false;
@@ -160,10 +175,12 @@
 
 void BleScannerImpl::SetTestDoubles(
     std::unique_ptr<ServiceDataProvider> service_data_provider,
-    std::unique_ptr<cryptauth::ForegroundEidGenerator> eid_generator,
+    std::unique_ptr<cryptauth::BackgroundEidGenerator> background_eid_generator,
+    std::unique_ptr<cryptauth::ForegroundEidGenerator> foreground_eid_generator,
     scoped_refptr<base::TaskRunner> test_task_runner) {
   service_data_provider_ = std::move(service_data_provider);
-  eid_generator_ = std::move(eid_generator);
+  background_eid_generator_ = std::move(background_eid_generator);
+  foreground_eid_generator_ = std::move(foreground_eid_generator);
   task_runner_ = test_task_runner;
 }
 
@@ -306,16 +323,27 @@
 void BleScannerImpl::CheckForMatchingScanFilters(
     device::BluetoothDevice* bluetooth_device,
     const std::string& service_data) {
-  std::vector<cryptauth::BeaconSeed> beacon_seeds;
-  if (!local_device_data_provider_->GetLocalDeviceData(nullptr,
-                                                       &beacon_seeds)) {
-    // If no beacon seeds are available, the scan cannot be checked for a match.
-    return;
+  std::string device_id;
+
+  // First try, identifying |service_data| as a foreground advertisement.
+  if (service_data.size() >= kMinNumBytesInForegroundServiceData) {
+    std::vector<cryptauth::BeaconSeed> beacon_seeds;
+    if (local_device_data_provider_->GetLocalDeviceData(nullptr,
+                                                        &beacon_seeds)) {
+      device_id =
+          foreground_eid_generator_->IdentifyRemoteDeviceByAdvertisement(
+              service_data, registered_remote_device_ids_, beacon_seeds);
+    }
   }
 
-  const std::string device_id =
-      eid_generator_->IdentifyRemoteDeviceByAdvertisement(
-          service_data, registered_remote_device_ids_, beacon_seeds);
+  // If the device has not yet been identified, try identifying |service_data|
+  // as a background advertisement.
+  if (device_id.empty() && service_data.size() >= kMinNumBytesInServiceData &&
+      service_data.size() <= kMaxNumBytesInBackgroundServiceData) {
+    device_id = background_eid_generator_->IdentifyRemoteDeviceByAdvertisement(
+        remote_beacon_seed_fetcher_, service_data,
+        registered_remote_device_ids_);
+  }
 
   // If the service data does not correspond to an advertisement from a device
   // on this account, ignore it.
diff --git a/chromeos/components/tether/ble_scanner_impl.h b/chromeos/components/tether/ble_scanner_impl.h
index b53bc61..2b4e91e 100644
--- a/chromeos/components/tether/ble_scanner_impl.h
+++ b/chromeos/components/tether/ble_scanner_impl.h
@@ -11,8 +11,8 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "chromeos/components/tether/ble_scanner.h"
+#include "components/cryptauth/background_eid_generator.h"
 #include "components/cryptauth/foreground_eid_generator.h"
-#include "components/cryptauth/local_device_data_provider.h"
 #include "components/cryptauth/remote_device.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 
@@ -20,6 +20,11 @@
 class TaskRunner;
 }  // namespace base
 
+namespace cryptauth {
+class LocalDeviceDataProvider;
+class RemoteBeaconSeedFetcher;
+}  // namespace cryptauth
+
 namespace device {
 class BluetoothDevice;
 class BluetoothDiscoverySession;
@@ -41,6 +46,7 @@
     static std::unique_ptr<BleScanner> NewInstance(
         scoped_refptr<device::BluetoothAdapter> adapter,
         cryptauth::LocalDeviceDataProvider* local_device_data_provider,
+        cryptauth::RemoteBeaconSeedFetcher* remote_beacon_seed_fetcher,
         BleSynchronizerBase* ble_synchronizer,
         TetherHostFetcher* tether_host_fetcher);
 
@@ -50,6 +56,7 @@
     virtual std::unique_ptr<BleScanner> BuildInstance(
         scoped_refptr<device::BluetoothAdapter> adapter,
         cryptauth::LocalDeviceDataProvider* local_device_data_provider,
+        cryptauth::RemoteBeaconSeedFetcher* remote_beacon_seed_fetcher,
         BleSynchronizerBase* ble_synchronizer,
         TetherHostFetcher* tether_host_fetcher);
 
@@ -67,6 +74,7 @@
  protected:
   BleScannerImpl(scoped_refptr<device::BluetoothAdapter> adapter,
                  cryptauth::LocalDeviceDataProvider* local_device_data_provider,
+                 cryptauth::RemoteBeaconSeedFetcher* remote_beacon_seed_fetcher,
                  BleSynchronizerBase* ble_synchronizer,
                  TetherHostFetcher* tether_host_fetcher);
 
@@ -96,7 +104,10 @@
 
   void SetTestDoubles(
       std::unique_ptr<ServiceDataProvider> service_data_provider,
-      std::unique_ptr<cryptauth::ForegroundEidGenerator> eid_generator,
+      std::unique_ptr<cryptauth::BackgroundEidGenerator>
+          background_eid_generator,
+      std::unique_ptr<cryptauth::ForegroundEidGenerator>
+          foreground_eid_generator,
       scoped_refptr<base::TaskRunner> test_task_runner);
 
   bool IsDeviceRegistered(const std::string& device_id);
@@ -130,11 +141,13 @@
 
   scoped_refptr<device::BluetoothAdapter> adapter_;
   cryptauth::LocalDeviceDataProvider* local_device_data_provider_;
+  cryptauth::RemoteBeaconSeedFetcher* remote_beacon_seed_fetcher_;
   BleSynchronizerBase* ble_synchronizer_;
   TetherHostFetcher* tether_host_fetcher_;
 
   std::unique_ptr<ServiceDataProvider> service_data_provider_;
-  std::unique_ptr<cryptauth::ForegroundEidGenerator> eid_generator_;
+  std::unique_ptr<cryptauth::BackgroundEidGenerator> background_eid_generator_;
+  std::unique_ptr<cryptauth::ForegroundEidGenerator> foreground_eid_generator_;
 
   std::vector<std::string> registered_remote_device_ids_;
 
diff --git a/chromeos/components/tether/ble_scanner_impl_unittest.cc b/chromeos/components/tether/ble_scanner_impl_unittest.cc
index 847c6ec..dd9fcab6 100644
--- a/chromeos/components/tether/ble_scanner_impl_unittest.cc
+++ b/chromeos/components/tether/ble_scanner_impl_unittest.cc
@@ -13,8 +13,10 @@
 #include "chromeos/components/tether/ble_constants.h"
 #include "chromeos/components/tether/fake_ble_synchronizer.h"
 #include "chromeos/components/tether/fake_tether_host_fetcher.h"
+#include "components/cryptauth/fake_background_eid_generator.h"
 #include "components/cryptauth/mock_foreground_eid_generator.h"
 #include "components/cryptauth/mock_local_device_data_provider.h"
+#include "components/cryptauth/mock_remote_beacon_seed_fetcher.h"
 #include "components/cryptauth/proto/cryptauth_api.pb.h"
 #include "components/cryptauth/remote_device_test_util.h"
 #include "device/bluetooth/test/mock_bluetooth_adapter.h"
@@ -114,7 +116,8 @@
   std::vector<uint8_t> service_data_;
 };
 
-const size_t kMinNumBytesInServiceData = 4;
+const size_t kNumBytesInBackgroundAdvertisementServiceData = 2;
+const size_t kMinNumBytesInForegroundAdvertisementServiceData = 4;
 
 const char kDefaultBluetoothAddress[] = "11:22:33:44:55:66";
 
@@ -200,6 +203,9 @@
         std::make_unique<std::vector<cryptauth::BeaconSeed>>(
             test_beacon_seeds_));
 
+    mock_seed_fetcher_ =
+        std::make_unique<cryptauth::MockRemoteBeaconSeedFetcher>();
+
     fake_ble_synchronizer_ = std::make_unique<FakeBleSynchronizer>();
     fake_tether_host_fetcher_ =
         std::make_unique<FakeTetherHostFetcher>(test_devices_);
@@ -212,16 +218,22 @@
 
     ble_scanner_ = base::WrapUnique(new BleScannerImpl(
         mock_adapter_, mock_local_device_data_provider_.get(),
-        fake_ble_synchronizer_.get(), fake_tether_host_fetcher_.get()));
+        mock_seed_fetcher_.get(), fake_ble_synchronizer_.get(),
+        fake_tether_host_fetcher_.get()));
 
-    mock_eid_generator_ = new cryptauth::MockForegroundEidGenerator();
-    mock_eid_generator_->set_background_scan_filter(
+    mock_foreground_eid_generator_ =
+        new cryptauth::MockForegroundEidGenerator();
+    mock_foreground_eid_generator_->set_background_scan_filter(
         CreateFakeBackgroundScanFilter());
+    fake_background_eid_generator_ =
+        new cryptauth::FakeBackgroundEidGenerator();
     test_service_data_provider_ = new TestServiceDataProvider();
     test_task_runner_ = base::MakeRefCounted<base::TestSimpleTaskRunner>();
-    ble_scanner_->SetTestDoubles(base::WrapUnique(test_service_data_provider_),
-                                 base::WrapUnique(mock_eid_generator_),
-                                 test_task_runner_);
+
+    ble_scanner_->SetTestDoubles(
+        base::WrapUnique(test_service_data_provider_),
+        base::WrapUnique(fake_background_eid_generator_),
+        base::WrapUnique(mock_foreground_eid_generator_), test_task_runner_);
 
     test_observer_ = std::make_unique<TestBleScannerObserver>();
     ble_scanner_->AddObserver(test_observer_.get());
@@ -282,6 +294,7 @@
 
   std::unique_ptr<cryptauth::MockLocalDeviceDataProvider>
       mock_local_device_data_provider_;
+  std::unique_ptr<cryptauth::MockRemoteBeaconSeedFetcher> mock_seed_fetcher_;
   std::unique_ptr<FakeBleSynchronizer> fake_ble_synchronizer_;
   std::unique_ptr<FakeTetherHostFetcher> fake_tether_host_fetcher_;
 
@@ -289,7 +302,8 @@
   device::MockBluetoothDiscoverySession* mock_discovery_session_;
 
   TestServiceDataProvider* test_service_data_provider_;
-  cryptauth::MockForegroundEidGenerator* mock_eid_generator_;
+  cryptauth::MockForegroundEidGenerator* mock_foreground_eid_generator_;
+  cryptauth::FakeBackgroundEidGenerator* fake_background_eid_generator_;
   scoped_refptr<base::TestSimpleTaskRunner> test_task_runner_;
 
   std::unique_ptr<TestBleScannerObserver> test_observer_;
@@ -313,7 +327,7 @@
 }
 
 TEST_F(BleScannerImplTest, TestNoBackgroundScanFilter) {
-  mock_eid_generator_->set_background_scan_filter(nullptr);
+  mock_foreground_eid_generator_->set_background_scan_filter(nullptr);
   EXPECT_FALSE(ble_scanner_->RegisterScanFilterForDevice(
       test_devices_[0].GetDeviceId()));
   EXPECT_FALSE(IsDeviceRegistered(test_devices_[0].GetDeviceId()));
@@ -364,13 +378,14 @@
   MockBluetoothDeviceWithServiceData device(
       mock_adapter_.get(), kDefaultBluetoothAddress, empty_service_data);
   DeviceAdded(&device);
-  EXPECT_FALSE(mock_eid_generator_->num_identify_calls());
+  EXPECT_FALSE(mock_foreground_eid_generator_->num_identify_calls());
   EXPECT_EQ(0u, test_observer_->device_addresses().size());
 }
 
 TEST_F(BleScannerImplTest, TestDiscovery_ServiceDataTooShort) {
   std::string short_service_data = "abc";
-  ASSERT_TRUE(short_service_data.size() < kMinNumBytesInServiceData);
+  ASSERT_TRUE(short_service_data.size() <
+              kMinNumBytesInForegroundAdvertisementServiceData);
 
   EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(
       test_devices_[0].GetDeviceId()));
@@ -383,14 +398,14 @@
   MockBluetoothDeviceWithServiceData device(
       mock_adapter_.get(), kDefaultBluetoothAddress, short_service_data);
   DeviceAdded(&device);
-  EXPECT_FALSE(mock_eid_generator_->num_identify_calls());
+  EXPECT_FALSE(mock_foreground_eid_generator_->num_identify_calls());
   EXPECT_EQ(0u, test_observer_->device_addresses().size());
 }
 
 TEST_F(BleScannerImplTest, TestDiscovery_LocalDeviceDataCannotBeFetched) {
   std::string valid_service_data_for_other_device = "abcd";
   ASSERT_TRUE(valid_service_data_for_other_device.size() >=
-              kMinNumBytesInServiceData);
+              kMinNumBytesInForegroundAdvertisementServiceData);
 
   EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(
       test_devices_[0].GetDeviceId()));
@@ -406,14 +421,14 @@
       mock_adapter_.get(), kDefaultBluetoothAddress,
       valid_service_data_for_other_device);
   DeviceAdded(&device);
-  EXPECT_FALSE(mock_eid_generator_->num_identify_calls());
+  EXPECT_FALSE(mock_foreground_eid_generator_->num_identify_calls());
   EXPECT_EQ(0u, test_observer_->device_addresses().size());
 }
 
 TEST_F(BleScannerImplTest, TestDiscovery_ScanSuccessfulButNoRegisteredDevice) {
   std::string valid_service_data_for_other_device = "abcd";
   ASSERT_TRUE(valid_service_data_for_other_device.size() >=
-              kMinNumBytesInServiceData);
+              kMinNumBytesInForegroundAdvertisementServiceData);
 
   EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(
       test_devices_[0].GetDeviceId()));
@@ -431,14 +446,14 @@
       mock_adapter_.get(), kDefaultBluetoothAddress,
       valid_service_data_for_other_device);
   DeviceAdded(&device);
-  EXPECT_EQ(1, mock_eid_generator_->num_identify_calls());
+  EXPECT_EQ(1, mock_foreground_eid_generator_->num_identify_calls());
   EXPECT_EQ(0u, test_observer_->device_addresses().size());
 }
 
 TEST_F(BleScannerImplTest, TestDiscovery_Success) {
   std::string valid_service_data_for_registered_device = "abcde";
   ASSERT_TRUE(valid_service_data_for_registered_device.size() >=
-              kMinNumBytesInServiceData);
+              kMinNumBytesInForegroundAdvertisementServiceData);
 
   EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(
       test_devices_[0].GetDeviceId()));
@@ -450,9 +465,10 @@
   MockBluetoothDeviceWithServiceData device(
       mock_adapter_.get(), kDefaultBluetoothAddress,
       valid_service_data_for_registered_device);
-  mock_eid_generator_->set_identified_device_id(test_devices_[0].GetDeviceId());
+  mock_foreground_eid_generator_->set_identified_device_id(
+      test_devices_[0].GetDeviceId());
   DeviceAdded(&device);
-  EXPECT_EQ(1, mock_eid_generator_->num_identify_calls());
+  EXPECT_EQ(1, mock_foreground_eid_generator_->num_identify_calls());
   EXPECT_EQ(1u, test_observer_->device_addresses().size());
   EXPECT_EQ(device.GetAddress(), test_observer_->device_addresses()[0]);
   EXPECT_EQ(1u, test_observer_->devices().size());
@@ -461,7 +477,7 @@
   EXPECT_TRUE(IsDeviceRegistered(test_devices_[0].GetDeviceId()));
   EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(
       test_devices_[0].GetDeviceId()));
-  EXPECT_EQ(1, mock_eid_generator_->num_identify_calls());
+  EXPECT_EQ(1, mock_foreground_eid_generator_->num_identify_calls());
   EXPECT_EQ(1u, test_observer_->device_addresses().size());
   InvokeStopDiscoveryCallback(true /* success */, 1u /* command_index */);
 }
@@ -478,7 +494,8 @@
 
   MockBluetoothDeviceWithServiceData mock_bluetooth_device(
       mock_adapter_.get(), kDefaultBluetoothAddress, "fakeServiceData");
-  mock_eid_generator_->set_identified_device_id(test_devices_[0].GetDeviceId());
+  mock_foreground_eid_generator_->set_identified_device_id(
+      test_devices_[0].GetDeviceId());
   DeviceAdded(&mock_bluetooth_device);
 
   EXPECT_EQ(1u, test_observer_->device_addresses().size());
@@ -757,6 +774,41 @@
   test_task_runner_->RunUntilIdle();
 }
 
+TEST_F(BleScannerImplTest, TestDiscovery_HostIsBackgroundAdvertising) {
+  std::string valid_service_data_for_registered_device = "ab";
+  ASSERT_TRUE(valid_service_data_for_registered_device.size() ==
+              kNumBytesInBackgroundAdvertisementServiceData);
+
+  EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(
+      test_devices_[0].GetDeviceId()));
+  EXPECT_TRUE(IsDeviceRegistered(test_devices_[0].GetDeviceId()));
+
+  InvokeDiscoveryStartedCallback(true /* success */, 0u /* command_index */);
+
+  // Registered device connects.
+  MockBluetoothDeviceWithServiceData device(
+      mock_adapter_.get(), kDefaultBluetoothAddress,
+      valid_service_data_for_registered_device);
+  fake_background_eid_generator_->set_identified_device_id(
+      test_devices_[0].GetDeviceId());
+
+  DeviceAdded(&device);
+  EXPECT_EQ(0, mock_foreground_eid_generator_->num_identify_calls());
+  EXPECT_EQ(1, fake_background_eid_generator_->num_identify_calls());
+  EXPECT_EQ(1u, test_observer_->device_addresses().size());
+  EXPECT_EQ(device.GetAddress(), test_observer_->device_addresses()[0]);
+  EXPECT_EQ(1u, test_observer_->devices().size());
+  EXPECT_EQ(test_devices_[0], test_observer_->devices()[0]);
+
+  EXPECT_TRUE(IsDeviceRegistered(test_devices_[0].GetDeviceId()));
+  EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(
+      test_devices_[0].GetDeviceId()));
+  EXPECT_EQ(0, mock_foreground_eid_generator_->num_identify_calls());
+  EXPECT_EQ(1, fake_background_eid_generator_->num_identify_calls());
+  EXPECT_EQ(1u, test_observer_->device_addresses().size());
+  InvokeStopDiscoveryCallback(true /* success */, 1u /* command_index */);
+}
+
 }  // namespace tether
 
 }  // namespace chromeos
diff --git a/chromeos/services/assistant/BUILD.gn b/chromeos/services/assistant/BUILD.gn
index 71e455b..93c0005 100644
--- a/chromeos/services/assistant/BUILD.gn
+++ b/chromeos/services/assistant/BUILD.gn
@@ -41,6 +41,8 @@
       "platform/audio_input_provider_impl.h",
       "platform/file_provider_impl.cc",
       "platform/file_provider_impl.h",
+      "platform/network_provider_impl.cc",
+      "platform/network_provider_impl.h",
       "platform/system_provider_impl.cc",
       "platform/system_provider_impl.h",
       "platform_api_impl.cc",
diff --git a/chromeos/services/assistant/assistant_manager_service_impl.cc b/chromeos/services/assistant/assistant_manager_service_impl.cc
index 4f07e27..2259ac4 100644
--- a/chromeos/services/assistant/assistant_manager_service_impl.cc
+++ b/chromeos/services/assistant/assistant_manager_service_impl.cc
@@ -29,7 +29,8 @@
           assistant_client::AssistantManager::Create(&platform_api_,
                                                      kDefaultConfigStr)),
       assistant_manager_internal_(
-          UnwrapAssistantManagerInternal(assistant_manager_.get())) {}
+          UnwrapAssistantManagerInternal(assistant_manager_.get())),
+      display_connection_(std::make_unique<CrosDisplayConnection>(this)) {}
 
 AssistantManagerServiceImpl::~AssistantManagerServiceImpl() {}
 
@@ -55,6 +56,7 @@
     DVLOG(2) << "set options: " << success;
   });
 
+  assistant_manager_internal_->SetDisplayConnection(display_connection_.get());
   assistant_manager_internal_->RegisterActionModule(action_module_.get());
 
   SetAccessToken(access_token);
@@ -121,5 +123,8 @@
       [&url](auto* ptr) { ptr->OnOpenUrlResponse(GURL(url)); });
 }
 
+void AssistantManagerServiceImpl::OnSpeechLevelUpdated(
+    const float speech_level) {}
+
 }  // namespace assistant
 }  // namespace chromeos
diff --git a/chromeos/services/assistant/assistant_manager_service_impl.h b/chromeos/services/assistant/assistant_manager_service_impl.h
index 97bce47..e6c0ae1 100644
--- a/chromeos/services/assistant/assistant_manager_service_impl.h
+++ b/chromeos/services/assistant/assistant_manager_service_impl.h
@@ -11,6 +11,7 @@
 // TODO(xiaohuic): replace with "base/macros.h" once we remove
 // libassistant/contrib dependency.
 #include "chromeos/assistant/internal/action/cros_action_module.h"
+#include "chromeos/assistant/internal/cros_display_connection.h"
 #include "chromeos/services/assistant/assistant_manager_service.h"
 #include "chromeos/services/assistant/platform_api_impl.h"
 #include "chromeos/services/assistant/public/mojom/assistant.mojom.h"
@@ -28,7 +29,8 @@
 // Implementation of AssistantManagerService based on libassistant.
 class AssistantManagerServiceImpl
     : public AssistantManagerService,
-      public ::chromeos::assistant::action::AssistantActionObserver {
+      public ::chromeos::assistant::action::AssistantActionObserver,
+      public AssistantEventObserver {
  public:
   explicit AssistantManagerServiceImpl(mojom::AudioInputPtr audio_input);
   ~AssistantManagerServiceImpl() override;
@@ -49,12 +51,16 @@
   void OnShowText(const std::string& text) override;
   void OnOpenUrl(const std::string& url) override;
 
+  // AssistantEventObserver overrides:
+  void OnSpeechLevelUpdated(float speech_level) override;
+
  private:
   bool running_ = false;
   PlatformApiImpl platform_api_;
   std::unique_ptr<action::CrosActionModule> action_module_;
   std::unique_ptr<assistant_client::AssistantManager> assistant_manager_;
   assistant_client::AssistantManagerInternal* const assistant_manager_internal_;
+  std::unique_ptr<CrosDisplayConnection> display_connection_;
   mojo::InterfacePtrSet<mojom::AssistantEventSubscriber> subscribers_;
 
   void StartAssistantInternal(const std::string& access_token,
diff --git a/chromeos/services/assistant/platform/file_provider_impl.cc b/chromeos/services/assistant/platform/file_provider_impl.cc
index bf02dea..d7360a4 100644
--- a/chromeos/services/assistant/platform/file_provider_impl.cc
+++ b/chromeos/services/assistant/platform/file_provider_impl.cc
@@ -42,12 +42,29 @@
 bool FileProviderImpl::WriteFile(const std::string& path,
                                  const std::string& data) {
   base::FilePath full_path = root_path_.Append(path);
-  if (!base::PathExists(full_path) && !base::CreateDirectory(full_path))
+  if (!base::PathExists(full_path.DirName()) &&
+      !base::CreateDirectory(full_path.DirName()))
     return false;
 
+  // Create a temp file.
+  base::FilePath temp_file;
+  if (!base::CreateTemporaryFileInDir(full_path.DirName(), &temp_file)) {
+    return false;
+  }
+
+  // Write to the tmp file.
   const int size = data.size();
-  int written_size = base::WriteFile(full_path, data.data(), size);
-  return written_size == size;
+  int written_size = base::WriteFile(temp_file, data.data(), size);
+  if (written_size != size) {
+    return false;
+  }
+
+  // Replace the current file with the temp file.
+  if (!base::ReplaceFile(temp_file, full_path, nullptr)) {
+    return false;
+  }
+
+  return true;
 }
 
 std::string FileProviderImpl::ReadSecureFile(const std::string& path) {
diff --git a/chromeos/services/assistant/platform/network_provider_impl.cc b/chromeos/services/assistant/platform/network_provider_impl.cc
new file mode 100644
index 0000000..58a14cac
--- /dev/null
+++ b/chromeos/services/assistant/platform/network_provider_impl.cc
@@ -0,0 +1,49 @@
+// Copyright 2018 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 "chromeos/services/assistant/platform/network_provider_impl.h"
+
+using assistant_client::NetworkProvider;
+using ConnectionStatus = assistant_client::NetworkProvider::ConnectionStatus;
+
+namespace chromeos {
+namespace assistant {
+
+NetworkProviderImpl::NetworkProviderImpl()
+    : connection_type_(net::NetworkChangeNotifier::GetConnectionType()) {
+  net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
+}
+
+NetworkProviderImpl::~NetworkProviderImpl() = default;
+
+void NetworkProviderImpl::OnNetworkChanged(
+    net::NetworkChangeNotifier::ConnectionType type) {
+  connection_type_ = type;
+}
+
+ConnectionStatus NetworkProviderImpl::GetConnectionStatus() {
+  // TODO(updowndota): Check actual internect connectivity in addition to the
+  // physical connectivity.
+  switch (connection_type_) {
+    case net::NetworkChangeNotifier::CONNECTION_UNKNOWN:
+      return ConnectionStatus::UNKNOWN;
+    case net::NetworkChangeNotifier::CONNECTION_ETHERNET:
+    case net::NetworkChangeNotifier::CONNECTION_WIFI:
+    case net::NetworkChangeNotifier::CONNECTION_2G:
+    case net::NetworkChangeNotifier::CONNECTION_3G:
+    case net::NetworkChangeNotifier::CONNECTION_4G:
+    case net::NetworkChangeNotifier::CONNECTION_BLUETOOTH:
+      return ConnectionStatus::CONNECTED;
+    case net::NetworkChangeNotifier::CONNECTION_NONE:
+      return ConnectionStatus::DISCONNECTED_FROM_INTERNET;
+  }
+}
+
+// Mdns responder is not supported in ChromeOS.
+assistant_client::MdnsResponder* NetworkProviderImpl::GetMdnsResponder() {
+  return nullptr;
+}
+
+}  // namespace assistant
+}  // namespace chromeos
diff --git a/chromeos/services/assistant/platform/network_provider_impl.h b/chromeos/services/assistant/platform/network_provider_impl.h
new file mode 100644
index 0000000..ca5bcde
--- /dev/null
+++ b/chromeos/services/assistant/platform/network_provider_impl.h
@@ -0,0 +1,39 @@
+// Copyright 2018 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 CHROMEOS_SERVICES_ASSISTANT_PLATFORM_NETWORK_PROVIDER_IMPL_H_
+#define CHROMEOS_SERVICES_ASSISTANT_PLATFORM_NETWORK_PROVIDER_IMPL_H_
+
+#include "base/macros.h"
+#include "libassistant/shared/public/platform_net.h"
+#include "net/base/network_change_notifier.h"
+
+namespace chromeos {
+namespace assistant {
+
+class NetworkProviderImpl
+    : public assistant_client::NetworkProvider,
+      public net::NetworkChangeNotifier::NetworkChangeObserver {
+ public:
+  NetworkProviderImpl();
+  ~NetworkProviderImpl() override;
+
+  // net::NetworkChangeNotifier overrides:
+  void OnNetworkChanged(
+      net::NetworkChangeNotifier::ConnectionType type) override;
+
+  // assistant_client::NetworkProvider::NetworkChangeObserver overrides:
+  ConnectionStatus GetConnectionStatus() override;
+  assistant_client::MdnsResponder* GetMdnsResponder() override;
+
+ private:
+  net::NetworkChangeNotifier::ConnectionType connection_type_;
+
+  DISALLOW_COPY_AND_ASSIGN(NetworkProviderImpl);
+};
+
+}  // namespace assistant
+}  // namespace chromeos
+
+#endif  // CHROMEOS_SERVICES_ASSISTANT_PLATFORM_NETWORK_PROVIDER_IMPL_H_
diff --git a/chromeos/services/assistant/platform_api_impl.cc b/chromeos/services/assistant/platform_api_impl.cc
index a608cf916..247517f 100644
--- a/chromeos/services/assistant/platform_api_impl.cc
+++ b/chromeos/services/assistant/platform_api_impl.cc
@@ -76,7 +76,6 @@
                                  mojom::AudioInputPtr audio_input)
     : audio_input_provider_(std::move(audio_input)),
       audio_output_provider_(config, this),
-      network_provider_(config),
       resource_provider_(config),
       system_provider_() {}
 
diff --git a/chromeos/services/assistant/platform_api_impl.h b/chromeos/services/assistant/platform_api_impl.h
index 359b559..1cdc330 100644
--- a/chromeos/services/assistant/platform_api_impl.h
+++ b/chromeos/services/assistant/platform_api_impl.h
@@ -12,6 +12,7 @@
 
 #include "chromeos/services/assistant/platform/audio_input_provider_impl.h"
 #include "chromeos/services/assistant/platform/file_provider_impl.h"
+#include "chromeos/services/assistant/platform/network_provider_impl.h"
 #include "chromeos/services/assistant/platform/system_provider_impl.h"
 #include "chromeos/services/assistant/public/mojom/assistant.mojom.h"
 // TODO(xiaohuic): replace with "base/macros.h" once we remove
@@ -19,7 +20,6 @@
 #include "libassistant/contrib/core/macros.h"
 #include "libassistant/contrib/platform/audio/output/audio_output_provider_impl.h"
 #include "libassistant/contrib/platform/auth/auth_provider_impl.h"
-#include "libassistant/contrib/platform/net/network_provider_impl.h"
 #include "libassistant/contrib/platform/resources/resource_provider.h"
 #include "libassistant/shared/public/platform_api.h"
 
@@ -78,7 +78,7 @@
   assistant_contrib::AudioOutputProviderImpl audio_output_provider_;
   DummyAuthProvider auth_provider_;
   FileProviderImpl file_provider_;
-  assistant_contrib::NetworkProviderImpl network_provider_;
+  NetworkProviderImpl network_provider_;
   assistant_contrib::ResourceProviderImpl resource_provider_;
   SystemProviderImpl system_provider_;
 
diff --git a/chromeos/system/statistics_provider.cc b/chromeos/system/statistics_provider.cc
index 203baaf8..f4abf61 100644
--- a/chromeos/system/statistics_provider.cc
+++ b/chromeos/system/statistics_provider.cc
@@ -174,6 +174,10 @@
 // Key values for GetMachineStatistic()/GetMachineFlag() calls.
 const char kActivateDateKey[] = "ActivateDate";
 const char kCheckEnrollmentKey[] = "check_enrollment";
+const char kShouldSendRlzPingKey[] = "should_send_rlz_ping";
+const char kShouldSendRlzPingValueFalse[] = "0";
+const char kShouldSendRlzPingValueTrue[] = "1";
+const char kRlzEmbargoEndDateKey[] = "rlz_embargo_end_date";
 const char kCustomizationIdKey[] = "customization_id";
 const char kDevSwitchBootKey[] = "devsw_boot";
 const char kDevSwitchBootValueDev[] = "1";
diff --git a/chromeos/system/statistics_provider.h b/chromeos/system/statistics_provider.h
index 85a939d..339fa166 100644
--- a/chromeos/system/statistics_provider.h
+++ b/chromeos/system/statistics_provider.h
@@ -19,6 +19,15 @@
 // The key that will be present in VPD if the device ever was enrolled.
 CHROMEOS_EXPORT extern const char kCheckEnrollmentKey[];
 
+// The key and values present in VPD to indicate if RLZ ping should be sent.
+CHROMEOS_EXPORT extern const char kShouldSendRlzPingKey[];
+CHROMEOS_EXPORT extern const char kShouldSendRlzPingValueFalse[];
+CHROMEOS_EXPORT extern const char kShouldSendRlzPingValueTrue[];
+
+// The key present in VPD that indicates the date after which the RLZ ping is
+// allowed to be sent. It is in the format of "yyyy-mm-dd".
+CHROMEOS_EXPORT extern const char kRlzEmbargoEndDateKey[];
+
 // Customization ID key.
 CHROMEOS_EXPORT extern const char kCustomizationIdKey[];
 
diff --git a/components/BUILD.gn b/components/BUILD.gn
index 1be4632..43cf4d0 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -233,7 +233,6 @@
       "//components/translate/content/renderer:unit_tests",
       "//components/ukm/content:unit_tests",
       "//components/visitedlink/test:unit_tests",
-      "//components/wallpaper:unit_tests",
       "//components/web_cache/browser:unit_tests",
       "//components/webcrypto:unit_tests",
     ]
@@ -572,6 +571,12 @@
       "$root_out_dir/components_tests_resources.pak",
       "$root_out_dir/ui_test.pak",
       "//components/subresource_filter/core/common/perftests/data",
+
+      # Needed for isolate script to execute.
+      "//testing/scripts/common.py",
+      "//testing/xvfb.py",
+      "//testing/scripts/run_gtest_perf_test.py",
+      "//tools/perf/generate_legacy_perf_dashboard_json.py",
     ]
 
     if (is_android) {
diff --git a/components/OWNERS b/components/OWNERS
index 7a8738d..2c20e78c 100644
--- a/components/OWNERS
+++ b/components/OWNERS
@@ -24,6 +24,7 @@
 per-file physical_web_ui_strings.grdp=file://components/physical_web/OWNERS
 per-file policy_strings.grdp=file://components/policy/OWNERS
 per-file printing_strings.grdp=file://components/printing/OWNERS
+per-file reset_password_strings.grdp=file://components/safe_browsing/OWNERS
 per-file security_interstitials_strings.grdp=file://components/security_interstitials/OWNERS
 per-file security_state_strings.grdp=file://components/security_state/OWNERS
 per-file ssl_errors_strings.grdp=file://components/ssl_errors/OWNERS
diff --git a/components/arc/timer/arc_timer_bridge_unittest.cc b/components/arc/timer/arc_timer_bridge_unittest.cc
index 56b51b7..54b38517 100644
--- a/components/arc/timer/arc_timer_bridge_unittest.cc
+++ b/components/arc/timer/arc_timer_bridge_unittest.cc
@@ -14,7 +14,6 @@
 #include "base/optional.h"
 #include "base/posix/unix_domain_socket.h"
 #include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
 #include "base/time/time.h"
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_service_manager.h"
@@ -27,6 +26,7 @@
 #include "components/arc/timer/arc_timer_traits.h"
 #include "components/arc/timer/create_timer_request.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace arc {
@@ -36,8 +36,7 @@
 class ArcTimerTest : public testing::Test {
  public:
   ArcTimerTest()
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::IO),
+      : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
         timer_bridge_(
             ArcTimerBridge::GetForBrowserContextForTesting(&context_)) {
     // This results in ArcTimerBridge::OnInstanceReady being called.
@@ -59,7 +58,7 @@
   FakeTimerInstance* GetFakeTimerInstance() { return &timer_instance_; }
 
  private:
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
+  content::TestBrowserThreadBundle thread_bundle_;
   ArcServiceManager arc_service_manager_;
   TestBrowserContext context_;
   FakeTimerInstance timer_instance_;
diff --git a/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.cc b/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.cc
index 3319035..9484d2f 100644
--- a/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.cc
+++ b/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.cc
@@ -7,6 +7,7 @@
 #include "base/callback_helpers.h"
 #include "base/metrics/histogram_macros.h"
 #include "build/build_config.h"
+#include "components/arc/video_accelerator/protected_buffer_allocator.h"
 #include "components/arc/video_accelerator/protected_buffer_manager.h"
 #include "media/base/video_frame.h"
 #include "media/base/video_types.h"
@@ -55,6 +56,7 @@
 // It is disallowed to allocate more than number of protected input buffers.
 constexpr size_t kMaxProtectedInputBuffers = 8;
 
+// TODO(hiroh): Refactor UnwrapFdFromMojoHandle not to declare multiple times.
 base::ScopedFD UnwrapFdFromMojoHandle(mojo::ScopedHandle handle) {
   if (!handle.is_valid()) {
     VLOGF(1) << "Handle is invalid.";
@@ -167,9 +169,9 @@
 
 GpuArcVideoDecodeAccelerator::GpuArcVideoDecodeAccelerator(
     const gpu::GpuPreferences& gpu_preferences,
-    ProtectedBufferManager* protected_buffer_manager)
+    scoped_refptr<ProtectedBufferManager> protected_buffer_manager)
     : gpu_preferences_(gpu_preferences),
-      protected_buffer_manager_(protected_buffer_manager) {}
+      protected_buffer_manager_(std::move(protected_buffer_manager)) {}
 
 GpuArcVideoDecodeAccelerator::~GpuArcVideoDecodeAccelerator() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
@@ -417,8 +419,19 @@
   pending_requests_ = {};
   pending_flush_callbacks_ = {};
   pending_reset_callback_.Reset();
-  protected_input_handles_.clear();
-  protected_output_handles_.clear();
+  protected_input_buffer_allocator_.reset();
+  protected_output_buffer_allocator_.reset();
+  protected_input_buffer_count_ = 0;
+  allocated_protected_output_buffer_fds_.clear();
+  if (secure_mode_) {
+    protected_input_buffer_allocator_ =
+        ProtectedBufferManager::CreateProtectedBufferAllocator(
+            protected_buffer_manager_);
+    if (!protected_input_buffer_allocator_) {
+      VLOGF(1) << "Failed to initialize protected_input_buffer_allocator_";
+      return mojom::VideoDecodeAccelerator::Result::PLATFORM_FAILURE;
+    }
+  }
   VLOGF(2) << "Number of concurrent clients: " << client_count_;
   return mojom::VideoDecodeAccelerator::Result::SUCCESS;
 }
@@ -434,7 +447,7 @@
     std::move(callback).Run(false);
     return;
   }
-  if (protected_input_handles_.size() >= kMaxProtectedInputBuffers) {
+  if (protected_input_buffer_count_ >= kMaxProtectedInputBuffers) {
     VLOGF(1) << "Too many protected input buffers"
              << ", kMaxProtectedInputBuffers=" << kMaxProtectedInputBuffers;
     std::move(callback).Run(false);
@@ -448,15 +461,13 @@
   }
   VLOGF(2) << " fd=" << fd.get() << " size=" << size;
 
-  auto protected_shmem =
-      protected_buffer_manager_->AllocateProtectedSharedMemory(std::move(fd),
-                                                               size);
-  if (!protected_shmem) {
+  if (!protected_input_buffer_allocator_->AllocateProtectedSharedMemory(
+          std::move(fd), size)) {
     VLOGF(1) << "Failed allocating protected shared memory.";
     std::move(callback).Run(false);
     return;
   }
-  protected_input_handles_.emplace_back(std::move(protected_shmem));
+  protected_input_buffer_count_++;
   std::move(callback).Run(true);
 }
 
@@ -531,8 +542,19 @@
         media::PictureBuffer(static_cast<int32_t>(id), coded_size_));
   }
   if (secure_mode_) {
-    protected_output_handles_.clear();
-    protected_output_handles_.resize(static_cast<size_t>(count));
+    allocated_protected_output_buffer_fds_ =
+        std::vector<base::ScopedFD>(static_cast<size_t>(count));
+    // Drops all the references of previously-allocated protected output
+    // buffers. That will eventually result in freeing those protected buffers.
+    protected_output_buffer_allocator_ =
+        ProtectedBufferManager::CreateProtectedBufferAllocator(
+            protected_buffer_manager_);
+    if (!protected_output_buffer_allocator_) {
+      VLOGF(1) << "Failed to initialize protected_output_buffer_allocator_";
+      client_->NotifyError(
+          mojom::VideoDecodeAccelerator::Result::PLATFORM_FAILURE);
+      return;
+    }
   }
   output_buffer_count_ = static_cast<size_t>(count);
   vda_->AssignPictureBuffers(buffers);
@@ -582,23 +604,49 @@
   gfx::GpuMemoryBufferHandle gmb_handle;
   gmb_handle.type = gfx::NATIVE_PIXMAP;
   if (secure_mode_) {
-    DCHECK_EQ(protected_output_handles_.size(), output_buffer_count_);
+    DCHECK_EQ(allocated_protected_output_buffer_fds_.size(),
+              output_buffer_count_);
+    DCHECK(protected_output_buffer_allocator_);
     VLOGF(2) << "Allocate output protected buffer"
              << ", picture_buffer_id=" << picture_buffer_id;
-    auto protected_pixmap =
-        protected_buffer_manager_->AllocateProtectedNativePixmap(
-            std::move(handle_fd),
+    // Allocate protected output buffer associated with |handle_fd|.
+    // Duplicating handle here is needed as ownership of passed fd is
+    // transferred to AllocateProtectedNativePixmap().
+    if (!protected_output_buffer_allocator_->AllocateProtectedNativePixmap(
+            base::ScopedFD(HANDLE_EINTR(dup(handle_fd.get()))),
             media::VideoPixelFormatToGfxBufferFormat(pixel_format),
-            coded_size_);
-    if (!protected_pixmap) {
+            coded_size_)) {
       VLOGF(1) << "Failed allocating protected pixmap.";
       client_->NotifyError(
           mojom::VideoDecodeAccelerator::Result::PLATFORM_FAILURE);
       return;
     }
-    gmb_handle.native_pixmap_handle =
-        gfx::CloneHandleForIPC(protected_pixmap->native_pixmap_handle());
-    protected_output_handles_[picture_buffer_id] = std::move(protected_pixmap);
+
+    // Get protected output buffer associated with |handle_fd|.
+    // Duplicating handle here is needed as ownership of passed fd is
+    // transferred to AllocateProtectedNativePixmap().
+    auto protected_native_pixmap =
+        protected_buffer_manager_->GetProtectedNativePixmapHandleFor(
+            base::ScopedFD(HANDLE_EINTR(dup(handle_fd.get()))));
+    if (protected_native_pixmap.fds.size() == 0) {
+      VLOGF(1) << "No protected native pixmap found for handle";
+      client_->NotifyError(
+          mojom::VideoDecodeAccelerator::Result::PLATFORM_FAILURE);
+      return;
+    }
+    gmb_handle.native_pixmap_handle = std::move(protected_native_pixmap);
+
+    // Try to get the dummy fd of the previously-allocated protected buffer for
+    // the same picture buffer id.
+    auto& fd = allocated_protected_output_buffer_fds_[picture_buffer_id];
+    if (fd.is_valid()) {
+      // In the case that there is previously-allocated protected buffer,
+      // release it.
+      protected_output_buffer_allocator_->ReleaseProtectedBuffer(std::move(fd));
+    }
+    // Save |handle_fd| to deallocate |handle_fd| when reimporting new fd for
+    // the same picture buffer id.
+    fd = std::move(handle_fd);
   } else {
     if (!VerifyDmabuf(pixel_format, coded_size_, handle_fd.get(), planes)) {
       VLOGF(1) << "Failed verifying dmabuf";
diff --git a/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.h b/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.h
index e9b2321b..09b36d8 100644
--- a/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.h
+++ b/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.h
@@ -11,6 +11,7 @@
 #include <vector>
 
 #include "base/callback_forward.h"
+#include "base/files/scoped_file.h"
 #include "base/threading/thread_checker.h"
 #include "components/arc/common/video_decode_accelerator.mojom.h"
 #include "gpu/command_buffer/service/gpu_preferences.h"
@@ -19,7 +20,7 @@
 namespace arc {
 
 class ProtectedBufferManager;
-class ProtectedBufferHandle;
+class ProtectedBufferAllocator;
 
 // GpuArcVideoDecodeAccelerator is executed in the GPU process.
 // It takes decoding requests from ARC via IPC channels and translates and
@@ -37,7 +38,7 @@
  public:
   GpuArcVideoDecodeAccelerator(
       const gpu::GpuPreferences& gpu_preferences,
-      ProtectedBufferManager* protected_buffer_manager);
+      scoped_refptr<ProtectedBufferManager> protected_buffer_manager);
   ~GpuArcVideoDecodeAccelerator() override;
 
   // Implementation of media::VideoDecodeAccelerator::Client interface.
@@ -145,25 +146,21 @@
   gfx::Size coded_size_;
   gfx::Size pending_coded_size_;
 
-  // Owned by caller.
-  ProtectedBufferManager* const protected_buffer_manager_;
+  scoped_refptr<ProtectedBufferManager> protected_buffer_manager_;
+
+  std::unique_ptr<ProtectedBufferAllocator> protected_input_buffer_allocator_;
+  std::unique_ptr<ProtectedBufferAllocator> protected_output_buffer_allocator_;
+  size_t protected_input_buffer_count_ = 0;
+  // Used only if secure_mode_ = true. Stores fds for all buffers successfully
+  // imported via ImportBufferForPicture() for which protected buffers were
+  // allocated, at indices equal to their picture_buffer_id.
+  // Used to release these buffers when the client requests a different buffer
+  // to be imported under the same picture_buffer_id later on.
+  std::vector<base::ScopedFD> allocated_protected_output_buffer_fds_;
 
   bool secure_mode_ = false;
   size_t output_buffer_count_ = 0;
 
-  // Although the stored data are not used for anything in GAVDA,
-  // storing them in GAVDA is needed to keep the protected buffers and
-  // their mappings valid on behalf of the GAVDA client.
-  // For both of them, it is prohibited to allocate more than the predetermined
-  // number of protected buffers.
-  // The predetermined number is a constant value (kMaxProtectedInputBuffers)
-  // for protected input buffers, and it is |output_buffer_count_| set in
-  // AssignPictureBuffers() for protected output buffers.
-  // |protected_output_handles_| is indexed by |picture_buffer_id| in
-  // ImportBufferForPicture().
-  std::vector<std::unique_ptr<ProtectedBufferHandle>> protected_input_handles_;
-  std::vector<std::unique_ptr<ProtectedBufferHandle>> protected_output_handles_;
-
   THREAD_CHECKER(thread_checker_);
   DISALLOW_COPY_AND_ASSIGN(GpuArcVideoDecodeAccelerator);
 };
diff --git a/components/arc/video_accelerator/protected_buffer_allocator.h b/components/arc/video_accelerator/protected_buffer_allocator.h
new file mode 100644
index 0000000..7834a3a
--- /dev/null
+++ b/components/arc/video_accelerator/protected_buffer_allocator.h
@@ -0,0 +1,44 @@
+// Copyright 2018 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_ARC_VIDEO_ACCELERATOR_PROTECTED_BUFFER_ALLOCATOR_H_
+#define COMPONENTS_ARC_VIDEO_ACCELERATOR_PROTECTED_BUFFER_ALLOCATOR_H_
+
+#include "base/files/scoped_file.h"
+#include "ui/gfx/buffer_types.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace arc {
+
+// ProtectedBufferAllocator allocates/deallocates protected buffers.
+// This class guarantees that the underlying protected buffers are not destroyed
+// and guarantees that referring to the protected buffers via the dummy handles
+// will always work and return the same buffers for the same dummy_fd for the
+// lifetime of this class. Once the class is destroyed, referring via dummy
+// handles becomes impossible, and the underlying buffers will be freed as soon
+// as all other users release own references to them (if any).
+class ProtectedBufferAllocator {
+ public:
+  virtual ~ProtectedBufferAllocator() = default;
+
+  // Allocates a protected SharedMemory whose size is |size| bytes, to be
+  // referred to via |dummy_fd| as the dummy handle.
+  // Returns whether the allocation is successful.
+  virtual bool AllocateProtectedSharedMemory(base::ScopedFD dummy_fd,
+                                             size_t size) = 0;
+
+  // Allocates a protected native pixmap with |format| and |size|, to be
+  // referred to via |dummy_fd| as the dummy handle.
+  // Returns whether the allocation is successful.
+  virtual bool AllocateProtectedNativePixmap(base::ScopedFD dummy_fd,
+                                             gfx::BufferFormat format,
+                                             const gfx::Size& size) = 0;
+
+  // Releases reference to ProtectedSharedMemory or ProtectedNativePixmap
+  // referred by |dummy_fd|.
+  virtual void ReleaseProtectedBuffer(base::ScopedFD dummy_fd) = 0;
+};
+
+}  // namespace arc
+#endif  // COMPONENTS_ARC_VIDEO_ACCELERATOR_PROTECTED_BUFFER_ALLOCATOR_H_
diff --git a/components/arc/video_accelerator/protected_buffer_manager.cc b/components/arc/video_accelerator/protected_buffer_manager.cc
index 60bb2be..993342af 100644
--- a/components/arc/video_accelerator/protected_buffer_manager.cc
+++ b/components/arc/video_accelerator/protected_buffer_manager.cc
@@ -4,10 +4,13 @@
 
 #include "components/arc/video_accelerator/protected_buffer_manager.h"
 
+#include <utility>
+
 #include "base/bits.h"
 #include "base/logging.h"
 #include "base/memory/shared_memory.h"
 #include "base/sys_info.h"
+#include "components/arc/video_accelerator/protected_buffer_allocator.h"
 #include "mojo/public/cpp/system/buffer.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 #include "ui/gfx/geometry/size.h"
@@ -21,49 +24,13 @@
 namespace {
 // Size of the pixmap to be used as the dummy handle for protected buffers.
 constexpr gfx::Size kDummyBufferSize(32, 32);
+
+// Maximum number of concurrent ProtectedBufferAllocatorImpl instances.
+// Currently we have no way to know the resources of ProtectedBufferAllocator.
+// Arbitrarily chosen a reasonable constant as the limit.
+constexpr size_t kMaxConcurrentProtectedBufferAllocators = 32;
 }  // namespace
 
-ProtectedBufferHandle::ProtectedBufferHandle(
-    base::OnceClosure destruction_cb,
-    const base::SharedMemoryHandle& shm_handle)
-    : shm_handle_(shm_handle), destruction_cb_(std::move(destruction_cb)) {
-  DCHECK(shm_handle_.IsValid());
-  DCHECK(shm_handle.OwnershipPassesToIPC());
-}
-
-ProtectedBufferHandle::ProtectedBufferHandle(
-    base::OnceClosure destruction_cb,
-    const gfx::NativePixmapHandle& native_pixmap_handle)
-    : native_pixmap_handle_(native_pixmap_handle),
-      destruction_cb_(std::move(destruction_cb)) {
-  DCHECK(!native_pixmap_handle_.fds.empty());
-  for (const auto& fd : native_pixmap_handle_.fds)
-    DCHECK(fd.auto_close);
-}
-
-ProtectedBufferHandle::~ProtectedBufferHandle() {
-  if (shm_handle_.OwnershipPassesToIPC())
-    shm_handle_.Close();
-
-  for (const auto& fd : native_pixmap_handle_.fds) {
-    // Close the fd by wrapping it in a ScopedFD and letting
-    // it fall out of scope.
-    base::ScopedFD scoped_fd(fd.fd);
-  }
-
-  std::move(destruction_cb_).Run();
-}
-
-base::SharedMemoryHandle ProtectedBufferHandle::shm_handle() const {
-  base::SharedMemoryHandle handle = shm_handle_;
-  handle.SetOwnershipPassesToIPC(false);
-  return handle;
-}
-
-gfx::NativePixmapHandle ProtectedBufferHandle::native_pixmap_handle() const {
-  return native_pixmap_handle_;
-}
-
 class ProtectedBufferManager::ProtectedBuffer {
  public:
   virtual ~ProtectedBuffer() {}
@@ -205,31 +172,129 @@
   return protected_pixmap;
 }
 
-ProtectedBufferManager::ProtectedBufferManager() : weak_factory_(this) {
+// The ProtectedBufferAllocator implementation using ProtectedBufferManager.
+// The functions just delegate the corresponding functions of
+// ProtectedBufferManager.
+// This destructor executes the callback to release the references of all non
+// released protected buffers.
+class ProtectedBufferManager::ProtectedBufferAllocatorImpl
+    : public ProtectedBufferAllocator {
+ public:
+  ProtectedBufferAllocatorImpl(
+      uint64_t allocator_id,
+      scoped_refptr<ProtectedBufferManager> protected_buffer_manager,
+      base::OnceClosure release_all_protected_buffers_cb);
+  ~ProtectedBufferAllocatorImpl() override;
+  bool AllocateProtectedSharedMemory(base::ScopedFD dummy_fd,
+                                     size_t size) override;
+  bool AllocateProtectedNativePixmap(base::ScopedFD dummy_fd,
+                                     gfx::BufferFormat format,
+                                     const gfx::Size& size) override;
+  void ReleaseProtectedBuffer(base::ScopedFD dummy_fd) override;
+
+ private:
+  const uint64_t allocator_id_;
+  const scoped_refptr<ProtectedBufferManager> protected_buffer_manager_;
+  base::OnceClosure release_all_protected_buffers_cb_;
+
+  THREAD_CHECKER(thread_checker_);
+  DISALLOW_COPY_AND_ASSIGN(ProtectedBufferAllocatorImpl);
+};
+
+ProtectedBufferManager::ProtectedBufferAllocatorImpl::
+    ProtectedBufferAllocatorImpl(
+        uint64_t allocator_id,
+        scoped_refptr<ProtectedBufferManager> protected_buffer_manager,
+        base::OnceClosure release_all_protected_buffers_cb)
+    : allocator_id_(allocator_id),
+      protected_buffer_manager_(std::move(protected_buffer_manager)),
+      release_all_protected_buffers_cb_(
+          std::move(release_all_protected_buffers_cb)) {}
+
+ProtectedBufferManager::ProtectedBufferAllocatorImpl::
+    ~ProtectedBufferAllocatorImpl() {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  DCHECK(release_all_protected_buffers_cb_);
+  std::move(release_all_protected_buffers_cb_).Run();
+}
+
+bool ProtectedBufferManager::ProtectedBufferAllocatorImpl::
+    AllocateProtectedSharedMemory(base::ScopedFD dummy_fd, size_t size) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  return protected_buffer_manager_->AllocateProtectedSharedMemory(
+      allocator_id_, std::move(dummy_fd), size);
+}
+
+bool ProtectedBufferManager::ProtectedBufferAllocatorImpl::
+    AllocateProtectedNativePixmap(base::ScopedFD dummy_fd,
+                                  gfx::BufferFormat format,
+                                  const gfx::Size& size) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  return protected_buffer_manager_->AllocateProtectedNativePixmap(
+      allocator_id_, std::move(dummy_fd), format, size);
+}
+
+void ProtectedBufferManager::ProtectedBufferAllocatorImpl::
+    ReleaseProtectedBuffer(base::ScopedFD dummy_fd) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  protected_buffer_manager_->ReleaseProtectedBuffer(allocator_id_,
+                                                    std::move(dummy_fd));
+}
+
+ProtectedBufferManager::ProtectedBufferManager() {
   VLOGF(2);
-  weak_this_ = weak_factory_.GetWeakPtr();
 }
 
 ProtectedBufferManager::~ProtectedBufferManager() {
   VLOGF(2);
 }
 
-std::unique_ptr<ProtectedBufferHandle>
-ProtectedBufferManager::AllocateProtectedSharedMemory(base::ScopedFD dummy_fd,
-                                                      size_t size) {
-  VLOGF(2) << "dummy_fd: " << dummy_fd.get() << ", size: " << size;
+bool ProtectedBufferManager::GetAllocatorId(uint64_t* const allocator_id) {
+  base::AutoLock lock(buffer_map_lock_);
+  if (allocator_to_buffers_map_.size() ==
+      kMaxConcurrentProtectedBufferAllocators) {
+    VLOGF(1) << "Failed Creating PBA due to many ProtectedBufferAllocators: "
+             << kMaxConcurrentProtectedBufferAllocators;
+    return false;
+  }
+  *allocator_id = next_protected_buffer_allocator_id_;
+  allocator_to_buffers_map_.insert({*allocator_id, {}});
+  next_protected_buffer_allocator_id_++;
+  return true;
+}
+
+// static
+std::unique_ptr<ProtectedBufferAllocator>
+ProtectedBufferManager::CreateProtectedBufferAllocator(
+    scoped_refptr<ProtectedBufferManager> protected_buffer_manager) {
+  uint64_t allocator_id = 0;
+  if (!protected_buffer_manager->GetAllocatorId(&allocator_id))
+    return nullptr;
+
+  return std::make_unique<ProtectedBufferAllocatorImpl>(
+      allocator_id, protected_buffer_manager,
+      base::BindOnce(&ProtectedBufferManager::ReleaseAllProtectedBuffers,
+                     protected_buffer_manager, allocator_id));
+}
+
+bool ProtectedBufferManager::AllocateProtectedSharedMemory(
+    uint64_t allocator_id,
+    base::ScopedFD dummy_fd,
+    size_t size) {
+  VLOGF(2) << "allocator_id:" << allocator_id
+           << ", dummy_fd: " << dummy_fd.get() << ", size: " << size;
 
   // Import the |dummy_fd| to produce a unique id for it.
   uint32_t id;
   auto pixmap = ImportDummyFd(std::move(dummy_fd), &id);
   if (!pixmap)
-    return nullptr;
+    return false;
 
   base::AutoLock lock(buffer_map_lock_);
 
   if (buffer_map_.find(id) != buffer_map_.end()) {
     VLOGF(1) << "A protected buffer for this handle already exists";
-    return nullptr;
+    return false;
   }
 
   // Allocate a protected buffer and associate it with the dummy pixmap.
@@ -238,47 +303,44 @@
   auto protected_shmem = ProtectedSharedMemory::Create(pixmap, size);
   if (!protected_shmem) {
     VLOGF(1) << "Failed allocating a protected shared memory buffer";
-    return nullptr;
+    return false;
   }
 
-  auto shm_handle = protected_shmem->DuplicateSharedMemoryHandle();
-  if (!shm_handle.IsValid()) {
-    VLOGF(1) << "Failed duplicating SharedMemoryHandle";
-    return nullptr;
-  }
-
-  // Store the buffer in the buffer_map_, and return a handle to it to the
-  // client. The buffer will be permanently removed from the map when the
-  // handle is destroyed.
   VLOGF(2) << "New protected shared memory buffer, handle id: " << id;
-  auto protected_buffer_handle = std::make_unique<ProtectedBufferHandle>(
-      base::BindOnce(&ProtectedBufferManager::RemoveEntry, weak_this_, id),
-      shm_handle);
 
   // This will always succeed as we find() first above.
   buffer_map_.emplace(id, std::move(protected_shmem));
 
-  return protected_buffer_handle;
+  DCHECK_EQ(allocator_to_buffers_map_.count(allocator_id), 1u);
+  if (!allocator_to_buffers_map_[allocator_id].insert(id).second) {
+    VLOGF(1) << "Failed inserting id: " << id
+             << " to allocator_to_buffers_map_, allocator_id: " << allocator_id;
+    return false;
+  }
+  return true;
 }
 
-std::unique_ptr<ProtectedBufferHandle>
-ProtectedBufferManager::AllocateProtectedNativePixmap(base::ScopedFD dummy_fd,
-                                                      gfx::BufferFormat format,
-                                                      const gfx::Size& size) {
-  VLOGF(2) << "dummy_fd: " << dummy_fd.get() << ", format: " << (int)format
+bool ProtectedBufferManager::AllocateProtectedNativePixmap(
+    uint64_t allocator_id,
+    base::ScopedFD dummy_fd,
+    gfx::BufferFormat format,
+    const gfx::Size& size) {
+  VLOGF(2) << "allocator_id: " << allocator_id
+           << ", dummy_fd: " << dummy_fd.get()
+           << ", format: " << static_cast<int>(format)
            << ", size: " << size.ToString();
 
   // Import the |dummy_fd| to produce a unique id for it.
   uint32_t id = 0;
   auto pixmap = ImportDummyFd(std::move(dummy_fd), &id);
   if (!pixmap)
-    return nullptr;
+    return false;
 
   base::AutoLock lock(buffer_map_lock_);
 
   if (buffer_map_.find(id) != buffer_map_.end()) {
     VLOGF(1) << "A protected buffer for this handle already exists";
-    return nullptr;
+    return false;
   }
 
   // Allocate a protected buffer and associate it with the dummy pixmap.
@@ -287,27 +349,57 @@
   auto protected_pixmap = ProtectedNativePixmap::Create(pixmap, format, size);
   if (!protected_pixmap) {
     VLOGF(1) << "Failed allocating a protected native pixmap";
-    return nullptr;
+    return false;
   }
 
-  auto native_pixmap_handle = protected_pixmap->DuplicateNativePixmapHandle();
-  if (native_pixmap_handle.planes.empty()) {
-    VLOGF(1) << "Failed duplicating NativePixmapHandle";
-    return nullptr;
-  }
-
-  // Store the buffer in the buffer_map_, and return a handle to it to the
-  // client. The buffer will be permanently removed from the map when the
-  // handle is destroyed.
   VLOGF(2) << "New protected native pixmap, handle id: " << id;
-  auto protected_buffer_handle = std::make_unique<ProtectedBufferHandle>(
-      base::BindOnce(&ProtectedBufferManager::RemoveEntry, weak_this_, id),
-      native_pixmap_handle);
-
   // This will always succeed as we find() first above.
   buffer_map_.emplace(id, std::move(protected_pixmap));
 
-  return protected_buffer_handle;
+  DCHECK_EQ(allocator_to_buffers_map_.count(allocator_id), 1u);
+  if (!allocator_to_buffers_map_[allocator_id].insert(id).second) {
+    VLOGF(1) << "Failed inserting id: " << id
+             << " to allocator_to_buffers_map_, allocator_id: " << allocator_id;
+    return false;
+  }
+  return true;
+}
+
+void ProtectedBufferManager::ReleaseProtectedBuffer(uint64_t allocator_id,
+                                                    base::ScopedFD dummy_fd) {
+  VLOGF(2) << "allocator_id: " << allocator_id
+           << ", dummy_fd: " << dummy_fd.get();
+
+  // Import the |dummy_fd| to produce a unique id for it.
+  uint32_t id = 0;
+  auto pixmap = ImportDummyFd(std::move(dummy_fd), &id);
+  if (!pixmap)
+    return;
+
+  base::AutoLock lock(buffer_map_lock_);
+  RemoveEntry(id);
+
+  auto it = allocator_to_buffers_map_.find(allocator_id);
+  if (it == allocator_to_buffers_map_.end()) {
+    VLOGF(1) << "No allocated buffer by allocator id " << allocator_id;
+    return;
+  }
+  if (it->second.erase(id) != 1) {
+    VLOGF(1) << "No buffer id " << id << " to destroy";
+    return;
+  }
+}
+
+void ProtectedBufferManager::ReleaseAllProtectedBuffers(uint64_t allocator_id) {
+  base::AutoLock lock(buffer_map_lock_);
+  auto it = allocator_to_buffers_map_.find(allocator_id);
+  if (it == allocator_to_buffers_map_.end())
+    return;
+
+  for (const uint32_t id : it->second) {
+    RemoveEntry(id);
+  }
+  allocator_to_buffers_map_.erase(allocator_id);
 }
 
 base::SharedMemoryHandle
@@ -397,12 +489,10 @@
 }
 
 void ProtectedBufferManager::RemoveEntry(uint32_t id) {
+  buffer_map_lock_.AssertAcquired();
   VLOGF(2) << "id: " << id;
-
-  base::AutoLock lock(buffer_map_lock_);
   auto num_erased = buffer_map_.erase(id);
   if (num_erased != 1)
     VLOGF(1) << "No buffer id " << id << " to destroy";
 }
-
 }  // namespace arc
diff --git a/components/arc/video_accelerator/protected_buffer_manager.h b/components/arc/video_accelerator/protected_buffer_manager.h
index ea6b1e23..95feeba8 100644
--- a/components/arc/video_accelerator/protected_buffer_manager.h
+++ b/components/arc/video_accelerator/protected_buffer_manager.h
@@ -6,84 +6,33 @@
 #define COMPONENTS_ARC_VIDEO_ACCELERATOR_PROTECTED_BUFFER_MANAGER_H_
 
 #include <map>
+#include <memory>
+#include <set>
 
+#include "base/files/scoped_file.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/shared_memory.h"
 #include "base/memory/weak_ptr.h"
 #include "base/synchronization/lock.h"
+#include "mojo/public/cpp/system/platform_handle.h"
+#include "ui/gfx/geometry/size.h"
 #include "ui/gfx/gpu_memory_buffer.h"
 #include "ui/gfx/native_pixmap.h"
 
 namespace arc {
+class ProtectedBufferAllocator;
 
-// A ProtectedBufferHandle is returned to the owning client that requested
-// the underlying ProtectedBuffer to be allocated.
-//
-// A ProtectedBuffer is a buffer that can be referred to via a handle (a dummy
-// handle), which does not provide access to the actual contents of the buffer.
-//
-// The client should release this handle once the buffer is no longer needed.
-// Releasing triggers destruction of the ProtectedBuffer instance stored in
-// the ProtectedBufferManager, via the destruction callback passed to the
-// ProtectedBufferHandle's constructor.
-class ProtectedBufferHandle {
- public:
-  // ProtectedBufferHandle takes ownership of the passed |shm_handle|.
-  ProtectedBufferHandle(base::OnceClosure destruction_cb,
-                        const base::SharedMemoryHandle& shm_handle);
-
-  // ProtectedBufferHandle takes ownership of the passed |native_pixmap_handle|.
-  ProtectedBufferHandle(base::OnceClosure destruction_cb,
-                        const gfx::NativePixmapHandle& native_pixmap_handle);
-
-  // Closes the underlying handle.
-  ~ProtectedBufferHandle();
-
-  // Return a non-owned SharedMemoryHandle or NativePixmapHandle for this
-  // ProtectedBufferHandle, or an invalid/null handle if not applicable for the
-  // underlying type.
-  base::SharedMemoryHandle shm_handle() const;
-  gfx::NativePixmapHandle native_pixmap_handle() const;
-
- private:
-  // The underlying, owning handles to the protected buffer.
-  // Only one of the handles is valid for each instance of this class.
-  // Closed on destruction of this ProtectedBufferHandle.
-  base::SharedMemoryHandle shm_handle_;
-  gfx::NativePixmapHandle native_pixmap_handle_;
-
-  base::OnceClosure destruction_cb_;
-};
-
-class ProtectedBufferManager {
+class ProtectedBufferManager
+    : public base::RefCountedThreadSafe<ProtectedBufferManager> {
  public:
   ProtectedBufferManager();
-  ~ProtectedBufferManager();
 
-  // Allocate a ProtectedSharedMemory buffer of |size| bytes, to be referred to
-  // via |dummy_fd| as the dummy handle, returning a ProtectedBufferHandle to
-  // it.
-  // Destroying the ProtectedBufferHandle will result in permanently
-  // disassociating the |dummy_fd| with the underlying ProtectedBuffer, but may
-  // not free the underlying protected memory, which will remain valid as long
-  // as any SharedMemoryHandles to it are still in use.
-  // Return nullptr on failure.
-  std::unique_ptr<ProtectedBufferHandle> AllocateProtectedSharedMemory(
-      base::ScopedFD dummy_fd,
-      size_t size);
-
-  // Allocate a ProtectedNativePixmap of |format| and |size|, to be referred to
-  // via |dummy_fd| as the dummy handle, returning a ProtectedBufferHandle to
-  // it.
-  // Destroying the ProtectedBufferHandle will result in permanently
-  // disassociating the |dummy_fd| with the underlying ProtectedBuffer, but may
-  // not free the underlying protected memory, which will remain valid as long
-  // as any NativePixmapHandles to it are still in use.
-  // Return nullptr on failure.
-  std::unique_ptr<ProtectedBufferHandle> AllocateProtectedNativePixmap(
-      base::ScopedFD dummy_fd,
-      gfx::BufferFormat format,
-      const gfx::Size& size);
+  // Creates ProtectedBufferAllocatorImpl and return it as
+  // unique_ptr<ProtectedBufferAllocator>.
+  // The created PBA would call the function |protected_buffer_manager|.
+  static std::unique_ptr<ProtectedBufferAllocator>
+  CreateProtectedBufferAllocator(
+      scoped_refptr<ProtectedBufferManager> protected_buffer_manager);
 
   // Return a duplicated SharedMemoryHandle associated with the |dummy_fd|,
   // if one exists, or an invalid handle otherwise.
@@ -108,6 +57,45 @@
   class ProtectedBuffer;
   class ProtectedSharedMemory;
   class ProtectedNativePixmap;
+  class ProtectedBufferAllocatorImpl;
+
+  // Be friend with ProtectedBufferAllocatorImpl so that private functions can
+  // be called in ProtectedBufferAllocatorImpl.
+  friend class ProtectedBufferAllocatorImpl;
+
+  friend class base::RefCountedThreadSafe<ProtectedBufferManager>;
+  // Destructor must be private for base::RefCounted class.
+  ~ProtectedBufferManager();
+
+  // Returns whether the number of active protected buffer allocators is less
+  // than the predetermined threshold (kMaxConcurrentProtectedBufferAllocators).
+  // This also returns current available allocator id through |allocator_id|.
+  bool GetAllocatorId(uint64_t* const allocator_id);
+
+  // Allocates a ProtectedSharedMemory buffer of |size| bytes, to be referred to
+  // via |dummy_fd| as the dummy handle.
+  // |allocator_id| is the allocator id of the caller.
+  // Returns whether allocation is successful.
+  bool AllocateProtectedSharedMemory(uint64_t allocator_id,
+                                     base::ScopedFD dummy_fd,
+                                     size_t size);
+
+  // Allocates a ProtectedNativePixmap of |format| and |size|, to be referred to
+  // via |dummy_fd| as the dummy handle.
+  // |allocator_id| is the allocator id of the caller.
+  // Returns whether allocation is successful.
+  bool AllocateProtectedNativePixmap(uint64_t allocator_id,
+                                     base::ScopedFD dummy_fd,
+                                     gfx::BufferFormat format,
+                                     const gfx::Size& size);
+
+  // Releases reference to ProtectedSharedMemory or ProtectedNativePixmap
+  // referred via |dummy_fd|. |allocator_id| is the allocator id of the caller.
+  void ReleaseProtectedBuffer(uint64_t allocator_id, base::ScopedFD dummy_fd);
+
+  // Releases all the references of protected buffers which is allocated by PBA
+  // whose allocator id is |allocator_id|.
+  void ReleaseAllProtectedBuffers(uint64_t allocator_id);
 
   // Imports the |dummy_fd| as a NativePixmap. This returns a unique |id|,
   // which is guaranteed to be the same for all future imports of any fd
@@ -122,22 +110,24 @@
   scoped_refptr<gfx::NativePixmap> ImportDummyFd(base::ScopedFD dummy_fd,
                                                  uint32_t* id) const;
 
-  // Removes an entry for given |id| from buffer_map_, to be called when the
-  // last reference to the buffer is dropped.
+  // Removes an entry for given |id| from buffer_map_.
   void RemoveEntry(uint32_t id);
 
   // A map of unique ids to the ProtectedBuffers associated with them.
   using ProtectedBufferMap =
       std::map<uint32_t, std::unique_ptr<ProtectedBuffer>>;
   ProtectedBufferMap buffer_map_;
+  // A map of allocator ids to the unique ids of ProtectedBuffers allocated by
+  // the allocator with the allocator id. The size is equal to the number of
+  // active protected buffer allocators.
+  std::map<uint64_t, std::set<uint32_t>> allocator_to_buffers_map_;
+  uint64_t next_protected_buffer_allocator_id_ = 0;
+  // The lock for buffer_map_ and alocator_to_buffers_map_ and
+  // next_protected_buffer_allocator_id_.
   base::Lock buffer_map_lock_;
 
-  base::WeakPtr<ProtectedBufferManager> weak_this_;
-  base::WeakPtrFactory<ProtectedBufferManager> weak_factory_;
-
   DISALLOW_COPY_AND_ASSIGN(ProtectedBufferManager);
 };
-
 }  // namespace arc
 
 #endif  // COMPONENTS_ARC_VIDEO_ACCELERATOR_PROTECTED_BUFFER_MANAGER_H_
diff --git a/components/arc/video_accelerator/protected_buffer_manager_proxy.cc b/components/arc/video_accelerator/protected_buffer_manager_proxy.cc
index 878eefa3..4eeefd30 100644
--- a/components/arc/video_accelerator/protected_buffer_manager_proxy.cc
+++ b/components/arc/video_accelerator/protected_buffer_manager_proxy.cc
@@ -12,11 +12,13 @@
 namespace arc {
 
 GpuArcProtectedBufferManagerProxy::GpuArcProtectedBufferManagerProxy(
-    arc::ProtectedBufferManager* protected_buffer_manager)
-    : protected_buffer_manager_(protected_buffer_manager) {
+    scoped_refptr<arc::ProtectedBufferManager> protected_buffer_manager)
+    : protected_buffer_manager_(std::move(protected_buffer_manager)) {
   DCHECK(protected_buffer_manager_);
 }
 
+GpuArcProtectedBufferManagerProxy::~GpuArcProtectedBufferManagerProxy() {}
+
 base::ScopedFD GpuArcProtectedBufferManagerProxy::UnwrapFdFromMojoHandle(
     mojo::ScopedHandle handle) {
   base::PlatformFile platform_file;
diff --git a/components/arc/video_accelerator/protected_buffer_manager_proxy.h b/components/arc/video_accelerator/protected_buffer_manager_proxy.h
index 15f7786..d8045e5 100644
--- a/components/arc/video_accelerator/protected_buffer_manager_proxy.h
+++ b/components/arc/video_accelerator/protected_buffer_manager_proxy.h
@@ -16,7 +16,9 @@
     : public ::arc::mojom::ProtectedBufferManager {
  public:
   explicit GpuArcProtectedBufferManagerProxy(
-      arc::ProtectedBufferManager* protected_buffer_manager);
+      scoped_refptr<arc::ProtectedBufferManager> protected_buffer_manager);
+
+  ~GpuArcProtectedBufferManagerProxy() override;
 
   // arc::mojom::ProtectedBufferManager implementation.
   void GetProtectedSharedMemoryFromHandle(
@@ -27,7 +29,7 @@
   base::ScopedFD UnwrapFdFromMojoHandle(mojo::ScopedHandle handle);
   mojo::ScopedHandle WrapFdInMojoHandle(base::ScopedFD fd);
 
-  arc::ProtectedBufferManager* protected_buffer_manager_;
+  scoped_refptr<arc::ProtectedBufferManager> protected_buffer_manager_;
 
   DISALLOW_COPY_AND_ASSIGN(GpuArcProtectedBufferManagerProxy);
 };
diff --git a/components/assist_ranker/predictor_config_definitions.cc b/components/assist_ranker/predictor_config_definitions.cc
index 771593c..879306d 100644
--- a/components/assist_ranker/predictor_config_definitions.cc
+++ b/components/assist_ranker/predictor_config_definitions.cc
@@ -36,6 +36,7 @@
   static auto* kContextualSearchFeatureWhitelist =
       new base::flat_set<std::string>({"DidOptIn",
                                        "DurationAfterScrollMs",
+                                       "FontSize",
                                        "IsEntity",
                                        "IsEntityEligible",
                                        "IsHttp",
@@ -50,6 +51,7 @@
                                        "OutcomeWasPanelOpened",
                                        "OutcomeWasQuickActionClicked",
                                        "OutcomeWasQuickAnswerSeen",
+                                       "PortionOfElement",
                                        "Previous28DayCtrPercent",
                                        "Previous28DayImpressionsCount",
                                        "PreviousWeekCtrPercent",
diff --git a/components/autofill/android/autofill_provider_android.cc b/components/autofill/android/autofill_provider_android.cc
index 7bd9104..70ca9340 100644
--- a/components/autofill/android/autofill_provider_android.cc
+++ b/components/autofill/android/autofill_provider_android.cc
@@ -316,38 +316,4 @@
   check_submission_ = false;
 }
 
-void AutofillProviderAndroid::FireSelectControlDidChangeForTesting(
-    JNIEnv* env,
-    jobject jcaller,
-    jint index,
-    jstring id,
-    jobjectArray options,
-    jint selected_option) {
-  FormData form_data;
-  FormFieldData form_field_data;
-  AutofillHandlerProxy* handler = nullptr;
-  if (form_.get() == nullptr) {
-    // Build a fake form
-    for (int i = 0; i < index; i++)
-      form_data.fields.push_back(FormFieldData());
-
-    base::android::AppendJavaStringArrayToStringVector(
-        env, options, &(form_field_data.option_values));
-    form_field_data.option_contents = form_field_data.option_values;
-    form_field_data.id = base::android::ConvertJavaStringToUTF16(env, id);
-    form_data.fields.push_back(form_field_data);
-    handler = handler_for_testing_.get();
-  } else {
-    form_data = form_->form_for_testing();
-    form_field_data = form_data.fields[index];
-    handler = handler_.get();
-  }
-  DCHECK(form_field_data.option_values.size() != 0);
-  DCHECK(!handler);
-  form_field_data.value = base::android::ConvertJavaStringToUTF16(
-      env, static_cast<jstring>(
-               env->GetObjectArrayElement(options, selected_option)));
-  OnSelectControlDidChange(handler, form_data, form_field_data, gfx::RectF());
-}
-
 }  // namespace autofill
diff --git a/components/autofill/android/autofill_provider_android.h b/components/autofill/android/autofill_provider_android.h
index d46d603..6c30caa 100644
--- a/components/autofill/android/autofill_provider_android.h
+++ b/components/autofill/android/autofill_provider_android.h
@@ -65,12 +65,6 @@
 
   // Methods called by Java.
   void OnAutofillAvailable(JNIEnv* env, jobject jcaller, jobject form_data);
-  void FireSelectControlDidChangeForTesting(JNIEnv* env,
-                                            jobject jcaller,
-                                            jint index,
-                                            jstring id,
-                                            jobjectArray options,
-                                            jint selected_option);
 
  private:
   void FireSuccessfulSubmission(SubmissionSource source);
diff --git a/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProvider.java b/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProvider.java
index f21a1f1..0937a50 100644
--- a/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProvider.java
+++ b/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProvider.java
@@ -9,7 +9,6 @@
 import android.view.ViewStructure;
 import android.view.autofill.AutofillValue;
 
-import org.chromium.base.VisibleForTesting;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.content_public.browser.WebContents;
@@ -150,9 +149,4 @@
 
     private native void nativeOnAutofillAvailable(
             long nativeAutofillProviderAndroid, FormData formData);
-
-    @VisibleForTesting
-    protected native void nativeFireSelectControlDidChangeForTesting(
-            long nativeAutofillProviderAndroid, int index, String selectControlId, String[] options,
-            int seletedOption);
 }
diff --git a/components/autofill/content/renderer/password_generation_agent.cc b/components/autofill/content/renderer/password_generation_agent.cc
index cb68dd8..0d06dfc 100644
--- a/components/autofill/content/renderer/password_generation_agent.cc
+++ b/components/autofill/content/renderer/password_generation_agent.cc
@@ -164,6 +164,9 @@
       editing_popup_shown_(false),
       enabled_(password_generation::IsPasswordGenerationEnabled()),
       form_classifier_enabled_(false),
+      mark_generation_element_(
+          base::CommandLine::ForCurrentProcess()->HasSwitch(
+              switches::kShowAutofillSignatures)),
       password_agent_(password_agent),
       binding_(this) {
   LogBoolean(Logger::STRING_GENERATION_RENDERER_ENABLED, enabled_);
@@ -464,6 +467,8 @@
     generation_form_data_.reset(new AccountCreationFormData(
         possible_form_data.form, std::move(password_elements)));
     generation_element_ = generation_form_data_->password_elements[0];
+    if (mark_generation_element_)
+      generation_element_.SetAttribute("password_creation_field", "1");
     generation_element_.SetAttribute("aria-autocomplete", "list");
     password_generation::LogPasswordGenerationEvent(
         password_generation::GENERATION_AVAILABLE);
diff --git a/components/autofill/content/renderer/password_generation_agent.h b/components/autofill/content/renderer/password_generation_agent.h
index ea45d6b..f23cf5ac 100644
--- a/components/autofill/content/renderer/password_generation_agent.h
+++ b/components/autofill/content/renderer/password_generation_agent.h
@@ -199,6 +199,10 @@
   // If the form classifier should run.
   bool form_classifier_enabled_;
 
+  // True iff the generation element should be marked with special HTML
+  // attribute (only for experimental purposes).
+  bool mark_generation_element_;
+
   // Unowned pointer. Used to notify PassowrdAutofillAgent when values
   // in password fields are updated.
   PasswordAutofillAgent* password_agent_;
diff --git a/components/autofill/core/browser/autofill_experiments.cc b/components/autofill/core/browser/autofill_experiments.cc
index eaf33e9..ebd67929 100644
--- a/components/autofill/core/browser/autofill_experiments.cc
+++ b/components/autofill/core/browser/autofill_experiments.cc
@@ -34,6 +34,8 @@
     "AutofillCreditCardAssist", base::FEATURE_DISABLED_BY_DEFAULT};
 const base::Feature kAutofillScanCardholderName{
     "AutofillScanCardholderName", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kAutofillCreditCardBankNameDisplay{
+    "AutofillCreditCardBankNameDisplay", base::FEATURE_DISABLED_BY_DEFAULT};
 const base::Feature kAutofillCreditCardAblationExperiment{
     "AutofillCreditCardAblationExperiment", base::FEATURE_DISABLED_BY_DEFAULT};
 const base::Feature kAutofillCreditCardPopupLayout{
@@ -129,6 +131,10 @@
   return base::FeatureList::IsEnabled(kAutofillCreditCardLastUsedDateDisplay);
 }
 
+bool IsAutofillCreditCardBankNameDisplayExperimentEnabled() {
+  return base::FeatureList::IsEnabled(kAutofillCreditCardBankNameDisplay);
+}
+
 // |GetCreditCardPopupParameterUintValue| returns 0 if experiment parameter is
 // not specified. 0 == |SK_ColorTRANSPARENT|.
 SkColor GetCreditCardPopupBackgroundColor() {
diff --git a/components/autofill/core/browser/autofill_experiments.h b/components/autofill/core/browser/autofill_experiments.h
index 987f9c1..b0f8c98 100644
--- a/components/autofill/core/browser/autofill_experiments.h
+++ b/components/autofill/core/browser/autofill_experiments.h
@@ -31,6 +31,7 @@
 extern const base::Feature kAutofillCreditCardAssist;
 extern const base::Feature kAutofillScanCardholderName;
 extern const base::Feature kAutofillCreditCardAblationExperiment;
+extern const base::Feature kAutofillCreditCardBankNameDisplay;
 extern const base::Feature kAutofillCreditCardPopupLayout;
 extern const base::Feature kAutofillCreditCardLastUsedDateDisplay;
 extern const base::Feature kAutofillDeleteDisusedAddresses;
@@ -93,6 +94,9 @@
 // Returns whether Autofill credit card last used date shows expiration date.
 bool ShowExpirationDateInAutofillCreditCardLastUsedDate();
 
+// Returns whether Autofill credit card bank name display experiment is enabled.
+bool IsAutofillCreditCardBankNameDisplayExperimentEnabled();
+
 // Returns the background color for credit card autofill popup, or
 // |SK_ColorTRANSPARENT| if the new credit card autofill popup layout experiment
 // is not enabled.
diff --git a/components/autofill/core/browser/credit_card.cc b/components/autofill/core/browser/credit_card.cc
index a11c463..4788afc 100644
--- a/components/autofill/core/browser/credit_card.cc
+++ b/components/autofill/core/browser/credit_card.cc
@@ -756,8 +756,11 @@
 }
 
 base::string16 CreditCard::NetworkOrBankNameAndLastFourDigits() const {
-  return bank_name_.empty() ? NetworkAndLastFourDigits()
-                            : BankNameAndLastFourDigits();
+  if (IsAutofillCreditCardBankNameDisplayExperimentEnabled() &&
+      !bank_name_.empty()) {
+    return BankNameAndLastFourDigits();
+  }
+  return NetworkAndLastFourDigits();
 }
 
 base::string16 CreditCard::AbbreviatedExpirationDateForDisplay() const {
diff --git a/components/autofill/core/browser/credit_card_unittest.cc b/components/autofill/core/browser/credit_card_unittest.cc
index 560b9d4..99b28bf0 100644
--- a/components/autofill/core/browser/credit_card_unittest.cc
+++ b/components/autofill/core/browser/credit_card_unittest.cc
@@ -8,6 +8,7 @@
 #include "base/macros.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "components/autofill/core/browser/autofill_experiments.h"
@@ -188,7 +189,24 @@
 
 // Tests function NetworkOrBankNameAndLastFourDigits.
 TEST(CreditCardTest, NetworkOrBankNameAndLastFourDigitsStrings) {
-  // Case 1: Bank name is empty -> show network name.
+  // Case 1: Experiment off -> show network name.
+  CreditCard credit_card1(base::GenerateGUID(), "https://www.example.com/");
+  test::SetCreditCardInfo(&credit_card1, "John Dillinger",
+                          "5105 1051 0510 5100" /* Mastercard */, "01", "2010",
+                          "1");
+  credit_card1.set_bank_name("Chase");
+  base::string16 obfuscated1 =
+      credit_card1.NetworkOrBankNameAndLastFourDigits();
+  EXPECT_FALSE(credit_card1.bank_name().empty());
+  EXPECT_EQ(
+      UTF8ToUTF16(std::string("Mastercard") + kUTF8MidlineEllipsis + "5100"),
+      obfuscated1);
+
+  // Turn on feature flag.
+  base::test::ScopedFeatureList scoped_feature_list_;
+  scoped_feature_list_.InitAndEnableFeature(kAutofillCreditCardBankNameDisplay);
+
+  // Case 2: Bank name is empty -> show network name.
   CreditCard credit_card2(base::GenerateGUID(), "https://www.example.com/");
   test::SetCreditCardInfo(&credit_card2, "John Dillinger",
                           "5105 1051 0510 5100" /* Mastercard */, "01", "2010",
@@ -200,7 +218,7 @@
       UTF8ToUTF16(std::string("Mastercard") + kUTF8MidlineEllipsis + "5100"),
       obfuscated2);
 
-  // Case 2: Bank name is not empty -> show bank name.
+  // Case 3: Experiment on && bank name not empty -> show bank name.
   CreditCard credit_card3(base::GenerateGUID(), "https://www.example.com/");
   test::SetCreditCardInfo(&credit_card3, "John Dillinger",
                           "5105 1051 0510 5100" /* Mastercard */, "01", "2010",
diff --git a/components/autofill/core/browser/personal_data_manager_unittest.cc b/components/autofill/core/browser/personal_data_manager_unittest.cc
index b831ac8..36ec3b3 100644
--- a/components/autofill/core/browser/personal_data_manager_unittest.cc
+++ b/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -2509,9 +2509,14 @@
   ASSERT_EQ(3U, suggestions.size());
 }
 
-// Tests that server cards will show bank name when bank name is available.
+// Tests that server cards will show bank name when bank name is available and
+// feature flag on.
 TEST_F(PersonalDataManagerTest,
        GetCreditCardSuggestions_ShowBankNameOfServerCards) {
+  // Turn on feature flag.
+  base::test::ScopedFeatureList scoped_feature_list_;
+  scoped_feature_list_.InitAndEnableFeature(kAutofillCreditCardBankNameDisplay);
+
   EnableWalletCardImport();
 
   // Add a local card.
diff --git a/components/browser_sync/profile_sync_components_factory_impl.cc b/components/browser_sync/profile_sync_components_factory_impl.cc
index ac89e31..8eb5fb2 100644
--- a/components/browser_sync/profile_sync_components_factory_impl.cc
+++ b/components/browser_sync/profile_sync_components_factory_impl.cc
@@ -16,8 +16,6 @@
 #include "components/autofill/core/browser/webdata/autofill_profile_data_type_controller.h"
 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
 #include "components/autofill/core/browser/webdata/web_data_model_type_controller.h"
-#include "components/autofill/core/common/autofill_pref_names.h"
-#include "components/autofill/core/common/autofill_switches.h"
 #include "components/browser_sync/browser_sync_switches.h"
 #include "components/browser_sync/profile_sync_service.h"
 #include "components/dom_distiller/core/dom_distiller_features.h"
@@ -42,9 +40,6 @@
 #include "components/sync_bookmarks/bookmark_model_associator.h"
 #include "components/sync_bookmarks/bookmark_model_type_controller.h"
 #include "components/sync_sessions/session_data_type_controller.h"
-#include "google_apis/gaia/oauth2_token_service.h"
-#include "google_apis/gaia/oauth2_token_service_request.h"
-#include "net/url_request/url_request_context_getter.h"
 
 using base::FeatureList;
 using bookmarks::BookmarkModel;
@@ -74,11 +69,6 @@
   return disabled_types;
 }
 
-syncer::ModelTypeSet GetEnabledTypesFromCommandLine(
-    const base::CommandLine& command_line) {
-  return syncer::ModelTypeSet();
-}
-
 }  // namespace
 
 ProfileSyncComponentsFactoryImpl::ProfileSyncComponentsFactoryImpl(
@@ -88,11 +78,8 @@
     bool is_tablet,
     const base::CommandLine& command_line,
     const char* history_disabled_pref,
-    const GURL& sync_service_url,
     const scoped_refptr<base::SingleThreadTaskRunner>& ui_thread,
     const scoped_refptr<base::SingleThreadTaskRunner>& db_thread,
-    OAuth2TokenService* token_service,
-    net::URLRequestContextGetter* url_request_context_getter,
     const scoped_refptr<autofill::AutofillWebDataService>& web_data_service,
     const scoped_refptr<password_manager::PasswordStore>& password_store)
     : sync_client_(sync_client),
@@ -101,17 +88,10 @@
       is_tablet_(is_tablet),
       command_line_(command_line),
       history_disabled_pref_(history_disabled_pref),
-      sync_service_url_(sync_service_url),
       ui_thread_(ui_thread),
       db_thread_(db_thread),
-      token_service_(token_service),
-      url_request_context_getter_(url_request_context_getter),
       web_data_service_(web_data_service),
-      password_store_(password_store),
-      weak_factory_(this) {
-  DCHECK(token_service_);
-  DCHECK(url_request_context_getter_);
-}
+      password_store_(password_store) {}
 
 ProfileSyncComponentsFactoryImpl::~ProfileSyncComponentsFactoryImpl() {}
 
@@ -120,18 +100,17 @@
     const RegisterDataTypesMethod& register_platform_types_method) {
   syncer::ModelTypeSet disabled_types =
       GetDisabledTypesFromCommandLine(command_line_);
-  syncer::ModelTypeSet enabled_types =
-      GetEnabledTypesFromCommandLine(command_line_);
-  RegisterCommonDataTypes(sync_service, disabled_types, enabled_types);
-  if (!register_platform_types_method.is_null())
+  RegisterCommonDataTypes(sync_service, disabled_types);
+  if (!register_platform_types_method.is_null()) {
+    syncer::ModelTypeSet enabled_types;
     register_platform_types_method.Run(sync_service, disabled_types,
                                        enabled_types);
+  }
 }
 
 void ProfileSyncComponentsFactoryImpl::RegisterCommonDataTypes(
     syncer::SyncService* sync_service,
-    syncer::ModelTypeSet disabled_types,
-    syncer::ModelTypeSet enabled_types) {
+    syncer::ModelTypeSet disabled_types) {
   base::Closure error_callback =
       base::Bind(&syncer::ReportUnrecoverableError, channel_);
 
@@ -331,41 +310,6 @@
       channel_, version_, is_tablet_);
 }
 
-class TokenServiceProvider
-    : public OAuth2TokenServiceRequest::TokenServiceProvider {
- public:
-  TokenServiceProvider(
-      const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
-      OAuth2TokenService* token_service);
-
-  // OAuth2TokenServiceRequest::TokenServiceProvider implementation.
-  scoped_refptr<base::SingleThreadTaskRunner> GetTokenServiceTaskRunner()
-      override;
-  OAuth2TokenService* GetTokenService() override;
-
- private:
-  ~TokenServiceProvider() override;
-
-  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-  OAuth2TokenService* token_service_;
-};
-
-TokenServiceProvider::TokenServiceProvider(
-    const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
-    OAuth2TokenService* token_service)
-    : task_runner_(task_runner), token_service_(token_service) {}
-
-TokenServiceProvider::~TokenServiceProvider() {}
-
-scoped_refptr<base::SingleThreadTaskRunner>
-TokenServiceProvider::GetTokenServiceTaskRunner() {
-  return task_runner_;
-}
-
-OAuth2TokenService* TokenServiceProvider::GetTokenService() {
-  return token_service_;
-}
-
 syncer::SyncApiComponentFactory::SyncComponents
 ProfileSyncComponentsFactoryImpl::CreateBookmarkSyncComponents(
     syncer::SyncService* sync_service,
diff --git a/components/browser_sync/profile_sync_components_factory_impl.h b/components/browser_sync/profile_sync_components_factory_impl.h
index fa0259a..d72ed962 100644
--- a/components/browser_sync/profile_sync_components_factory_impl.h
+++ b/components/browser_sync/profile_sync_components_factory_impl.h
@@ -15,9 +15,6 @@
 #include "components/sync/base/model_type.h"
 #include "components/sync/driver/sync_api_component_factory.h"
 #include "components/version_info/version_info.h"
-#include "url/gurl.h"
-
-class OAuth2TokenService;
 
 namespace autofill {
 class AutofillWebDataService;
@@ -27,23 +24,11 @@
 class PasswordStore;
 }
 
-namespace net {
-class URLRequestContextGetter;
-}
-
 namespace browser_sync {
 
 class ProfileSyncComponentsFactoryImpl
     : public syncer::SyncApiComponentFactory {
  public:
-  // Constructs a ProfileSyncComponentsFactoryImpl.
-  //
-  // |sync_service_url| is the base URL of the sync server.
-  //
-  // |token_service| must outlive the ProfileSyncComponentsFactoryImpl.
-  //
-  // |url_request_context_getter| must outlive the
-  // ProfileSyncComponentsFactoryImpl.
   ProfileSyncComponentsFactoryImpl(
       syncer::SyncClient* sync_client,
       version_info::Channel channel,
@@ -51,11 +36,8 @@
       bool is_tablet,
       const base::CommandLine& command_line,
       const char* history_disabled_pref,
-      const GURL& sync_service_url,
       const scoped_refptr<base::SingleThreadTaskRunner>& ui_thread,
       const scoped_refptr<base::SingleThreadTaskRunner>& db_thread,
-      OAuth2TokenService* token_service,
-      net::URLRequestContextGetter* url_request_context_getter,
       const scoped_refptr<autofill::AutofillWebDataService>& web_data_service,
       const scoped_refptr<password_manager::PasswordStore>& password_store);
   ~ProfileSyncComponentsFactoryImpl() override;
@@ -89,15 +71,10 @@
 
  private:
   // Register data types which are enabled on both desktop and mobile.
-  // |disabled_types| and |enabled_types| correspond only to those types
-  // being explicitly enabled/disabled by the command line.
+  // |disabled_types| corresponds only to those types being explicitly disabled
+  // by the command line.
   void RegisterCommonDataTypes(syncer::SyncService* sync_service,
-                               syncer::ModelTypeSet disabled_types,
-                               syncer::ModelTypeSet enabled_types);
-
-  void DisableBrokenType(syncer::ModelType type,
-                         const base::Location& from_here,
-                         const std::string& message);
+                               syncer::ModelTypeSet disabled_types);
 
   // Client/platform specific members.
   syncer::SyncClient* const sync_client_;
@@ -106,16 +83,11 @@
   const bool is_tablet_;
   const base::CommandLine command_line_;
   const char* history_disabled_pref_;
-  const GURL sync_service_url_;
   const scoped_refptr<base::SingleThreadTaskRunner> ui_thread_;
   const scoped_refptr<base::SingleThreadTaskRunner> db_thread_;
-  OAuth2TokenService* const token_service_;
-  net::URLRequestContextGetter* const url_request_context_getter_;
   const scoped_refptr<autofill::AutofillWebDataService> web_data_service_;
   const scoped_refptr<password_manager::PasswordStore> password_store_;
 
-  base::WeakPtrFactory<ProfileSyncComponentsFactoryImpl> weak_factory_;
-
   // Whether to override PREFERENCES to use USS.
   static bool override_prefs_controller_to_uss_for_test_;
 
diff --git a/components/browser_sync/profile_sync_service.cc b/components/browser_sync/profile_sync_service.cc
index f085b8b2..db105fc 100644
--- a/components/browser_sync/profile_sync_service.cc
+++ b/components/browser_sync/profile_sync_service.cc
@@ -4,10 +4,7 @@
 
 #include "components/browser_sync/profile_sync_service.h"
 
-#include <stddef.h>
-
 #include <cstddef>
-#include <map>
 #include <utility>
 
 #include "base/bind.h"
@@ -15,30 +12,23 @@
 #include "base/callback.h"
 #include "base/command_line.h"
 #include "base/feature_list.h"
-#include "base/files/file_util.h"
+#include "base/files/file_path.h"
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
-#include "base/metrics/histogram.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/stringprintf.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "components/autofill/core/common/autofill_pref_names.h"
 #include "components/browser_sync/browser_sync_switches.h"
 #include "components/invalidation/impl/invalidation_prefs.h"
 #include "components/invalidation/public/invalidation_service.h"
 #include "components/pref_registry/pref_registry_syncable.h"
-#include "components/prefs/json_pref_store.h"
 #include "components/reading_list/features/reading_list_buildflags.h"
-#include "components/signin/core/browser/about_signin_internals.h"
 #include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "components/signin/core/browser/signin_manager.h"
 #include "components/signin/core/browser/signin_metrics.h"
 #include "components/sync/base/bind_to_task_runner.h"
 #include "components/sync/base/cryptographer.h"
 #include "components/sync/base/passphrase_type.h"
-#include "components/sync/base/pref_names.h"
 #include "components/sync/base/report_unrecoverable_error.h"
 #include "components/sync/base/stop_source.h"
 #include "components/sync/base/system_encryptor.h"
diff --git a/components/browser_sync/profile_sync_service.h b/components/browser_sync/profile_sync_service.h
index b39ae3d3..391a6c7 100644
--- a/components/browser_sync/profile_sync_service.h
+++ b/components/browser_sync/profile_sync_service.h
@@ -19,7 +19,6 @@
 #include "base/memory/weak_ptr.h"
 #include "base/message_loop/message_loop.h"
 #include "base/observer_list.h"
-#include "base/strings/string16.h"
 #include "base/threading/thread.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
diff --git a/components/cdm/DEPS b/components/cdm/DEPS
index 158aad01..7af36474 100644
--- a/components/cdm/DEPS
+++ b/components/cdm/DEPS
@@ -2,6 +2,6 @@
   "+ipc",
   "+media/base",
   "+media/cdm",
-  "+media/media_features.h",
+  "+media/media_buildflags.h",
   "+ppapi/features",
 ]
diff --git a/components/cdm/browser/DEPS b/components/cdm/browser/DEPS
index 3a2cd64..9bab7f84 100644
--- a/components/cdm/browser/DEPS
+++ b/components/cdm/browser/DEPS
@@ -2,7 +2,7 @@
   "+components/prefs",
   "+content/public/browser",
   "+media/cdm",
-  "+media/media_features.h",
+  "+media/media_buildflags.h",
   "+media/mojo",
   "+mojo/public/cpp/bindings",
 
diff --git a/components/cdm/browser/cdm_message_filter_android.cc b/components/cdm/browser/cdm_message_filter_android.cc
index e025a22e..fc66fab20 100644
--- a/components/cdm/browser/cdm_message_filter_android.cc
+++ b/components/cdm/browser/cdm_message_filter_android.cc
@@ -20,7 +20,7 @@
 #include "media/base/audio_codecs.h"
 #include "media/base/media_switches.h"
 #include "media/base/video_codecs.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 using media::MediaDrmBridge;
 using media::SupportedCodecs;
diff --git a/components/cdm/common/widevine_drm_delegate_android.cc b/components/cdm/common/widevine_drm_delegate_android.cc
index 8c96a125..7d5af43 100644
--- a/components/cdm/common/widevine_drm_delegate_android.cc
+++ b/components/cdm/common/widevine_drm_delegate_android.cc
@@ -6,7 +6,7 @@
 
 #include "base/macros.h"
 #include "media/cdm/cenc_utils.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 namespace cdm {
 
diff --git a/components/cdm/renderer/BUILD.gn b/components/cdm/renderer/BUILD.gn
index c14dd74..5f93f7e 100644
--- a/components/cdm/renderer/BUILD.gn
+++ b/components/cdm/renderer/BUILD.gn
@@ -22,7 +22,7 @@
     "//components/cdm/common",
     "//content/public/renderer",
     "//media",
-    "//media:media_features",
+    "//media:media_buildflags",
     "//third_party/widevine/cdm:headers",
   ]
 }
diff --git a/components/cdm/renderer/android_key_systems.cc b/components/cdm/renderer/android_key_systems.cc
index a9dc30f..ec177e9 100644
--- a/components/cdm/renderer/android_key_systems.cc
+++ b/components/cdm/renderer/android_key_systems.cc
@@ -13,7 +13,7 @@
 #include "content/public/renderer/render_thread.h"
 #include "media/base/eme_constants.h"
 #include "media/base/media_switches.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 #include "widevine_cdm_version.h"  // In SHARED_INTERMEDIATE_DIR.
 
diff --git a/components/cdm/renderer/external_clear_key_key_system_properties.cc b/components/cdm/renderer/external_clear_key_key_system_properties.cc
index 7cad7fa..9ff56dc6 100644
--- a/components/cdm/renderer/external_clear_key_key_system_properties.cc
+++ b/components/cdm/renderer/external_clear_key_key_system_properties.cc
@@ -6,7 +6,7 @@
 
 #include "base/logging.h"
 #include "media/base/eme_constants.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 namespace cdm {
 
diff --git a/components/cdm/renderer/external_clear_key_key_system_properties.h b/components/cdm/renderer/external_clear_key_key_system_properties.h
index 64260d0..f08967a 100644
--- a/components/cdm/renderer/external_clear_key_key_system_properties.h
+++ b/components/cdm/renderer/external_clear_key_key_system_properties.h
@@ -9,7 +9,7 @@
 
 #include "build/build_config.h"
 #include "media/base/key_system_properties.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 namespace cdm {
 
diff --git a/components/cdm/renderer/widevine_key_system_properties.cc b/components/cdm/renderer/widevine_key_system_properties.cc
index a428bfe..3683fb8b5 100644
--- a/components/cdm/renderer/widevine_key_system_properties.cc
+++ b/components/cdm/renderer/widevine_key_system_properties.cc
@@ -4,7 +4,7 @@
 
 #include "components/cdm/renderer/widevine_key_system_properties.h"
 
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "widevine_cdm_version.h"  // In SHARED_INTERMEDIATE_DIR.
 
 #if defined(WIDEVINE_CDM_AVAILABLE)
diff --git a/components/cdm/renderer/widevine_key_system_properties.h b/components/cdm/renderer/widevine_key_system_properties.h
index 043814b3..c758b84c 100644
--- a/components/cdm/renderer/widevine_key_system_properties.h
+++ b/components/cdm/renderer/widevine_key_system_properties.h
@@ -7,7 +7,7 @@
 
 #include "build/build_config.h"
 #include "media/base/key_system_properties.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 namespace cdm {
 
diff --git a/components/components_strings.grd b/components/components_strings.grd
index de57007..9134fb8 100644
--- a/components/components_strings.grd
+++ b/components/components_strings.grd
@@ -206,6 +206,7 @@
       <part file="physical_web_ui_strings.grdp" />
       <part file="policy_strings.grdp" />
       <part file="printing_strings.grdp" />
+      <part file="reset_password_strings.grdp" />
       <part file="safe_browsing_strings.grdp" />
       <part file="security_interstitials_strings.grdp" />
       <part file="security_state_strings.grdp" />
diff --git a/components/cronet/OWNERS b/components/cronet/OWNERS
index c9838da..03269570 100644
--- a/components/cronet/OWNERS
+++ b/components/cronet/OWNERS
@@ -1,7 +1,6 @@
 kapishnikov@chromium.org
 mef@chromium.org
-mgersh@chromium.org
 pauljensen@chromium.org
 xunjieli@chromium.org
 
-# COMPONENT: Internals>Network>Library
\ No newline at end of file
+# COMPONENT: Internals>Network>Library
diff --git a/components/cronet/android/java/src/org/chromium/net/impl/UrlResponseInfoImpl.java b/components/cronet/android/java/src/org/chromium/net/impl/UrlResponseInfoImpl.java
index 57eb9ca..ab00062 100644
--- a/components/cronet/android/java/src/org/chromium/net/impl/UrlResponseInfoImpl.java
+++ b/components/cronet/android/java/src/org/chromium/net/impl/UrlResponseInfoImpl.java
@@ -95,6 +95,17 @@
         mReceivedByteCount = new AtomicLong(receivedByteCount);
     }
 
+    /**
+     * Constructor for backwards compatibility.  See main constructor above for more info.
+     */
+    @Deprecated
+    public UrlResponseInfoImpl(List<String> urlChain, int httpStatusCode, String httpStatusText,
+            List<Map.Entry<String, String>> allHeadersList, boolean wasCached,
+            String negotiatedProtocol, String proxyServer) {
+        this(urlChain, httpStatusCode, httpStatusText, allHeadersList, wasCached,
+                negotiatedProtocol, proxyServer, 0);
+    }
+
     @Override
     public String getUrl() {
         return mResponseInfoUrlChain.get(mResponseInfoUrlChain.size() - 1);
diff --git a/components/cryptauth/BUILD.gn b/components/cryptauth/BUILD.gn
index 3691029..7e2c290 100644
--- a/components/cryptauth/BUILD.gn
+++ b/components/cryptauth/BUILD.gn
@@ -118,6 +118,8 @@
     "device_to_device_responder_operations.h",
     "fake_authenticator.cc",
     "fake_authenticator.h",
+    "fake_background_eid_generator.cc",
+    "fake_background_eid_generator.h",
     "fake_connection.cc",
     "fake_connection.h",
     "fake_cryptauth_device_manager.cc",
diff --git a/components/cryptauth/background_eid_generator.cc b/components/cryptauth/background_eid_generator.cc
index d7f8e03..f18c465a 100644
--- a/components/cryptauth/background_eid_generator.cc
+++ b/components/cryptauth/background_eid_generator.cc
@@ -13,6 +13,8 @@
 #include "components/cryptauth/proto/cryptauth_api.pb.h"
 #include "components/cryptauth/raw_eid_generator.h"
 #include "components/cryptauth/raw_eid_generator_impl.h"
+#include "components/cryptauth/remote_beacon_seed_fetcher.h"
+#include "components/cryptauth/remote_device.h"
 #include "components/proximity_auth/logging/logging.h"
 
 namespace cryptauth {
@@ -66,7 +68,6 @@
       eids.push_back(*eid);
   }
 
-  PA_LOG(INFO) << "Generated EIDs: " << DataWithTimestamp::ToDebugString(eids);
   return eids;
 }
 
@@ -76,7 +77,7 @@
   const BeaconSeed* beacon_seed =
       GetBeaconSeedForTimestamp(timestamp_ms, beacon_seeds);
   if (!beacon_seed) {
-    PA_LOG(INFO) << "  " << timestamp_ms << ": outside of BeaconSeed range.";
+    PA_LOG(WARNING) << "  " << timestamp_ms << ": outside of BeaconSeed range.";
     return nullptr;
   }
 
@@ -92,4 +93,40 @@
                                              start_of_period_ms + kEidPeriodMs);
 }
 
+std::string BackgroundEidGenerator::IdentifyRemoteDeviceByAdvertisement(
+    cryptauth::RemoteBeaconSeedFetcher* remote_beacon_seed_fetcher,
+    const std::string& advertisement_service_data,
+    const std::vector<std::string>& device_ids) const {
+  // Resize the service data to analyze only the first |kNumBytesInEidValue|
+  // bytes. If there are any bytes after those first |kNumBytesInEidValue|
+  // bytes, they are flags, so they are not needed to identify the device which
+  // sent a message.
+  std::string service_data_without_flags = advertisement_service_data;
+  service_data_without_flags.resize(RawEidGenerator::kNumBytesInEidValue);
+
+  const auto device_id_it = std::find_if(
+      device_ids.begin(), device_ids.end(),
+      [this, remote_beacon_seed_fetcher,
+       &service_data_without_flags](auto device_id) {
+        std::vector<BeaconSeed> beacon_seeds;
+        if (!remote_beacon_seed_fetcher->FetchSeedsForDeviceId(device_id,
+                                                               &beacon_seeds)) {
+          PA_LOG(WARNING) << "Error fetching beacon seeds for device with ID "
+                          << RemoteDevice::TruncateDeviceIdForLogs(device_id);
+          return false;
+        }
+
+        std::vector<DataWithTimestamp> eids = GenerateNearestEids(beacon_seeds);
+        const auto eid_it = std::find_if(
+            eids.begin(), eids.end(), [&service_data_without_flags](auto eid) {
+              return eid.data == service_data_without_flags;
+            });
+
+        return eid_it != eids.end();
+      });
+
+  // Return empty string if no matching device is found.
+  return device_id_it != device_ids.end() ? *device_id_it : std::string();
+}
+
 }  // cryptauth
diff --git a/components/cryptauth/background_eid_generator.h b/components/cryptauth/background_eid_generator.h
index ebe1f06..4788723 100644
--- a/components/cryptauth/background_eid_generator.h
+++ b/components/cryptauth/background_eid_generator.h
@@ -17,16 +17,22 @@
 
 class BeaconSeed;
 class RawEidGenerator;
+class RemoteBeaconSeedFetcher;
 
 // Generates ephemeral ID (EID) values that are broadcast for background BLE
 // advertisements in the ProximityAuth protocol.
 //
+// Background BLE advertisements, because they're generally being advertised for
+// extended periods of time, use a frequently rotating EID rotation scheme, for
+// privacy reasons (EIDs should rotate more frequently to prevent others from
+// tracking this device or user).
+//
 // When advertising in background mode, we offload advertising to the hardware
 // in order to conserve battery. We assume, however, that the scanning side is
 // not bound by battery constraints.
 //
-// For the inverse of this model, in which advertising is battery-sensitive, see
-// ForegroundEidGenerator.
+// For the inverse of this model, in which advertising is neither privacy- nor
+// battery-sensitive, see ForegroundEidGenerator.
 class BackgroundEidGenerator {
  public:
   BackgroundEidGenerator();
@@ -37,6 +43,15 @@
   virtual std::vector<DataWithTimestamp> GenerateNearestEids(
       const std::vector<BeaconSeed>& beacon_seed) const;
 
+  // Given an incoming background advertisement with |service_data|, identifies
+  // which device (if any) sent the advertisement. Returns a device ID which
+  // identifies the device. If no device can be identified, returns an empty
+  // string.
+  virtual std::string IdentifyRemoteDeviceByAdvertisement(
+      cryptauth::RemoteBeaconSeedFetcher* remote_beacon_seed_fetcher,
+      const std::string& advertisement_service_data,
+      const std::vector<std::string>& device_ids) const;
+
  private:
   friend class CryptAuthBackgroundEidGeneratorTest;
   BackgroundEidGenerator(std::unique_ptr<RawEidGenerator> raw_eid_generator,
diff --git a/components/cryptauth/background_eid_generator_unittest.cc b/components/cryptauth/background_eid_generator_unittest.cc
index dbbae6b..2b02a1a 100644
--- a/components/cryptauth/background_eid_generator_unittest.cc
+++ b/components/cryptauth/background_eid_generator_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/strings/string_util.h"
 #include "base/test/simple_test_clock.h"
 #include "base/time/time.h"
+#include "components/cryptauth/mock_remote_beacon_seed_fetcher.h"
 #include "components/cryptauth/proto/cryptauth_api.pb.h"
 #include "components/cryptauth/raw_eid_generator_impl.h"
 #include "components/cryptauth/remote_device.h"
@@ -37,6 +38,9 @@
 const std::string kThirdSeed = "thirdSeed";
 const std::string kFourthSeed = "fourthSeed";
 
+const std::string kDeviceId1 = "deviceId1";
+const std::string kDeviceId2 = "deviceId2";
+
 BeaconSeed CreateBeaconSeed(const std::string& data,
                             const int64_t start_timestamp_ms,
                             const int64_t end_timestamp_ms) {
@@ -47,15 +51,18 @@
   return seed;
 }
 
-DataWithTimestamp CreateEid(const std::string& eid_seed,
-                            int64_t start_of_period_timestamp_ms) {
-  std::string data =
-      eid_seed + "|" + std::to_string(start_of_period_timestamp_ms);
+DataWithTimestamp CreateDataWithTimestamp(
+    const std::string& eid_seed,
+    int64_t start_of_period_timestamp_ms) {
+  std::unique_ptr<RawEidGenerator> raw_eid_generator =
+      std::make_unique<RawEidGeneratorImpl>();
+  std::string data = raw_eid_generator->GenerateEid(
+      eid_seed, start_of_period_timestamp_ms, nullptr /* extra_entropy */);
   return DataWithTimestamp(data, start_of_period_timestamp_ms,
                            start_of_period_timestamp_ms + kEidPeriodMs);
 }
 
-class TestRawEidGenerator : public RawEidGenerator {
+class TestRawEidGenerator : public RawEidGeneratorImpl {
  public:
   TestRawEidGenerator() {}
   ~TestRawEidGenerator() override {}
@@ -65,7 +72,8 @@
                           int64_t start_of_period_timestamp_ms,
                           std::string const* extra_entropy) override {
     EXPECT_FALSE(extra_entropy);
-    return CreateEid(eid_seed, start_of_period_timestamp_ms).data;
+    return RawEidGeneratorImpl::GenerateEid(
+        eid_seed, start_of_period_timestamp_ms, extra_entropy);
   }
 
  private:
@@ -92,6 +100,9 @@
   void SetUp() override {
     SetTestTime(kCurrentTimeMs);
 
+    mock_seed_fetcher_ =
+        std::make_unique<cryptauth::MockRemoteBeaconSeedFetcher>();
+
     eid_generator_.reset(new BackgroundEidGenerator(
         std::make_unique<TestRawEidGenerator>(), &test_clock_));
   }
@@ -103,11 +114,13 @@
   }
 
   std::unique_ptr<BackgroundEidGenerator> eid_generator_;
+  std::unique_ptr<MockRemoteBeaconSeedFetcher> mock_seed_fetcher_;
   base::SimpleTestClock test_clock_;
   std::vector<BeaconSeed> beacon_seeds_;
 };
 
-TEST_F(CryptAuthBackgroundEidGeneratorTest, BeaconSeedsExpired) {
+TEST_F(CryptAuthBackgroundEidGeneratorTest,
+       GenerateNearestEids_BeaconSeedsExpired) {
   SetTestTime(beacon_seeds_[beacon_seeds_.size() - 1].end_time_millis() +
               kEidCount * kEidPeriodMs);
   std::vector<DataWithTimestamp> eids =
@@ -115,14 +128,16 @@
   EXPECT_EQ(0u, eids.size());
 }
 
-TEST_F(CryptAuthBackgroundEidGeneratorTest, BeaconSeedsValidInFuture) {
+TEST_F(CryptAuthBackgroundEidGeneratorTest,
+       GenerateNearestEids_BeaconSeedsValidInFuture) {
   SetTestTime(beacon_seeds_[0].start_time_millis() - kEidCount * kEidPeriodMs);
   std::vector<DataWithTimestamp> eids =
       eid_generator_->GenerateNearestEids(beacon_seeds_);
   EXPECT_EQ(0u, eids.size());
 }
 
-TEST_F(CryptAuthBackgroundEidGeneratorTest, EidsUseSameBeaconSeed) {
+TEST_F(CryptAuthBackgroundEidGeneratorTest,
+       GenerateNearestEids_EidsUseSameBeaconSeed) {
   int64_t start_period_ms =
       beacon_seeds_[0].start_time_millis() + kEidCount * kEidPeriodMs;
   SetTestTime(start_period_ms + kEidPeriodMs / 2);
@@ -132,14 +147,20 @@
 
   std::string seed = beacon_seeds_[0].data();
   EXPECT_EQ(kEidCount, eids.size());
-  EXPECT_EQ(CreateEid(seed, start_period_ms - 2 * kEidPeriodMs), eids[0]);
-  EXPECT_EQ(CreateEid(seed, start_period_ms - 1 * kEidPeriodMs), eids[1]);
-  EXPECT_EQ(CreateEid(seed, start_period_ms + 0 * kEidPeriodMs), eids[2]);
-  EXPECT_EQ(CreateEid(seed, start_period_ms + 1 * kEidPeriodMs), eids[3]);
-  EXPECT_EQ(CreateEid(seed, start_period_ms + 2 * kEidPeriodMs), eids[4]);
+  EXPECT_EQ(CreateDataWithTimestamp(seed, start_period_ms - 2 * kEidPeriodMs),
+            eids[0]);
+  EXPECT_EQ(CreateDataWithTimestamp(seed, start_period_ms - 1 * kEidPeriodMs),
+            eids[1]);
+  EXPECT_EQ(CreateDataWithTimestamp(seed, start_period_ms + 0 * kEidPeriodMs),
+            eids[2]);
+  EXPECT_EQ(CreateDataWithTimestamp(seed, start_period_ms + 1 * kEidPeriodMs),
+            eids[3]);
+  EXPECT_EQ(CreateDataWithTimestamp(seed, start_period_ms + 2 * kEidPeriodMs),
+            eids[4]);
 }
 
-TEST_F(CryptAuthBackgroundEidGeneratorTest, EidsAcrossBeaconSeeds) {
+TEST_F(CryptAuthBackgroundEidGeneratorTest,
+       GenerateNearestEids_EidsAcrossBeaconSeeds) {
   int64_t end_period_ms = beacon_seeds_[0].end_time_millis();
   int64_t start_period_ms = beacon_seeds_[1].start_time_millis();
   SetTestTime(start_period_ms + kEidPeriodMs / 2);
@@ -150,14 +171,20 @@
   std::string seed0 = beacon_seeds_[0].data();
   std::string seed1 = beacon_seeds_[1].data();
   EXPECT_EQ(kEidCount, eids.size());
-  EXPECT_EQ(CreateEid(seed0, end_period_ms - 2 * kEidPeriodMs), eids[0]);
-  EXPECT_EQ(CreateEid(seed0, end_period_ms - 1 * kEidPeriodMs), eids[1]);
-  EXPECT_EQ(CreateEid(seed1, start_period_ms + 0 * kEidPeriodMs), eids[2]);
-  EXPECT_EQ(CreateEid(seed1, start_period_ms + 1 * kEidPeriodMs), eids[3]);
-  EXPECT_EQ(CreateEid(seed1, start_period_ms + 2 * kEidPeriodMs), eids[4]);
+  EXPECT_EQ(CreateDataWithTimestamp(seed0, end_period_ms - 2 * kEidPeriodMs),
+            eids[0]);
+  EXPECT_EQ(CreateDataWithTimestamp(seed0, end_period_ms - 1 * kEidPeriodMs),
+            eids[1]);
+  EXPECT_EQ(CreateDataWithTimestamp(seed1, start_period_ms + 0 * kEidPeriodMs),
+            eids[2]);
+  EXPECT_EQ(CreateDataWithTimestamp(seed1, start_period_ms + 1 * kEidPeriodMs),
+            eids[3]);
+  EXPECT_EQ(CreateDataWithTimestamp(seed1, start_period_ms + 2 * kEidPeriodMs),
+            eids[4]);
 }
 
-TEST_F(CryptAuthBackgroundEidGeneratorTest, CurrentTimeAtStartOfRange) {
+TEST_F(CryptAuthBackgroundEidGeneratorTest,
+       GenerateNearestEids_CurrentTimeAtStartOfRange) {
   int64_t start_period_ms = beacon_seeds_[0].start_time_millis();
   SetTestTime(start_period_ms + kEidPeriodMs / 2);
 
@@ -166,12 +193,16 @@
 
   std::string seed = beacon_seeds_[0].data();
   EXPECT_EQ(3u, eids.size());
-  EXPECT_EQ(CreateEid(seed, start_period_ms + 0 * kEidPeriodMs), eids[0]);
-  EXPECT_EQ(CreateEid(seed, start_period_ms + 1 * kEidPeriodMs), eids[1]);
-  EXPECT_EQ(CreateEid(seed, start_period_ms + 2 * kEidPeriodMs), eids[2]);
+  EXPECT_EQ(CreateDataWithTimestamp(seed, start_period_ms + 0 * kEidPeriodMs),
+            eids[0]);
+  EXPECT_EQ(CreateDataWithTimestamp(seed, start_period_ms + 1 * kEidPeriodMs),
+            eids[1]);
+  EXPECT_EQ(CreateDataWithTimestamp(seed, start_period_ms + 2 * kEidPeriodMs),
+            eids[2]);
 }
 
-TEST_F(CryptAuthBackgroundEidGeneratorTest, CurrentTimeAtEndOfRange) {
+TEST_F(CryptAuthBackgroundEidGeneratorTest,
+       GenerateNearestEids_CurrentTimeAtEndOfRange) {
   int64_t start_period_ms = beacon_seeds_[3].end_time_millis() - kEidPeriodMs;
   SetTestTime(start_period_ms + kEidPeriodMs / 2);
 
@@ -180,9 +211,40 @@
 
   std::string seed = beacon_seeds_[3].data();
   EXPECT_EQ(3u, eids.size());
-  EXPECT_EQ(CreateEid(seed, start_period_ms - 2 * kEidPeriodMs), eids[0]);
-  EXPECT_EQ(CreateEid(seed, start_period_ms - 1 * kEidPeriodMs), eids[1]);
-  EXPECT_EQ(CreateEid(seed, start_period_ms - 0 * kEidPeriodMs), eids[2]);
+  EXPECT_EQ(CreateDataWithTimestamp(seed, start_period_ms - 2 * kEidPeriodMs),
+            eids[0]);
+  EXPECT_EQ(CreateDataWithTimestamp(seed, start_period_ms - 1 * kEidPeriodMs),
+            eids[1]);
+  EXPECT_EQ(CreateDataWithTimestamp(seed, start_period_ms - 0 * kEidPeriodMs),
+            eids[2]);
+}
+
+// Test the case where the account has other devices, but their beacon seeds
+// don't match the incoming advertisement. |beacon_seeds_[0]| corresponds to
+// |kDeviceId1|. Since |kDeviceId1| is not present in the device ids passed to
+// IdentifyRemoteDeviceByAdvertisement(), no match is expected to be found.
+TEST_F(CryptAuthBackgroundEidGeneratorTest,
+       IdentifyRemoteDeviceByAdvertisement_NoMatchingRemoteDevices) {
+  SetTestTime(kStartPeriodMs + kEidPeriodMs / 2);
+  DataWithTimestamp advertisement_eid = CreateDataWithTimestamp(
+      beacon_seeds_[0].data(), kStartPeriodMs - kEidPeriodMs);
+  mock_seed_fetcher_->SetSeedsForDeviceId(kDeviceId1, &beacon_seeds_);
+
+  EXPECT_EQ(std::string(), eid_generator_->IdentifyRemoteDeviceByAdvertisement(
+                               mock_seed_fetcher_.get(), advertisement_eid.data,
+                               {kDeviceId2}));
+}
+
+TEST_F(CryptAuthBackgroundEidGeneratorTest,
+       IdentifyRemoteDeviceByAdvertisement_Success) {
+  SetTestTime(kStartPeriodMs + kEidPeriodMs / 2);
+  DataWithTimestamp advertisement_eid = CreateDataWithTimestamp(
+      beacon_seeds_[0].data(), kStartPeriodMs - kEidPeriodMs);
+  mock_seed_fetcher_->SetSeedsForDeviceId(kDeviceId1, &beacon_seeds_);
+
+  EXPECT_EQ(kDeviceId1, eid_generator_->IdentifyRemoteDeviceByAdvertisement(
+                            mock_seed_fetcher_.get(), advertisement_eid.data,
+                            {kDeviceId1, kDeviceId2}));
 }
 
 }  // namespace cryptauth
diff --git a/components/cryptauth/fake_background_eid_generator.cc b/components/cryptauth/fake_background_eid_generator.cc
new file mode 100644
index 0000000..5af0e76
--- /dev/null
+++ b/components/cryptauth/fake_background_eid_generator.cc
@@ -0,0 +1,31 @@
+// Copyright 2018 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/cryptauth/fake_background_eid_generator.h"
+
+#include <memory>
+
+namespace cryptauth {
+
+FakeBackgroundEidGenerator::FakeBackgroundEidGenerator() = default;
+FakeBackgroundEidGenerator::~FakeBackgroundEidGenerator() = default;
+
+std::vector<DataWithTimestamp> FakeBackgroundEidGenerator::GenerateNearestEids(
+    const std::vector<BeaconSeed>& beacon_seed) const {
+  return *nearest_eids_;
+}
+
+std::string FakeBackgroundEidGenerator::IdentifyRemoteDeviceByAdvertisement(
+    cryptauth::RemoteBeaconSeedFetcher* remote_beacon_seed_fetcher,
+    const std::string& advertisement_service_data,
+    const std::vector<std::string>& device_ids) const {
+  // Increment num_identify_calls_. Since this overrides a const method, some
+  // hacking is needed to modify the num_identify_calls_ instance variable.
+  int* num_identify_calls_ptr = const_cast<int*>(&num_identify_calls_);
+  *num_identify_calls_ptr = *num_identify_calls_ptr + 1;
+
+  return identified_device_id_;
+}
+
+}  // namespace cryptauth
\ No newline at end of file
diff --git a/components/cryptauth/fake_background_eid_generator.h b/components/cryptauth/fake_background_eid_generator.h
new file mode 100644
index 0000000..31fe19f
--- /dev/null
+++ b/components/cryptauth/fake_background_eid_generator.h
@@ -0,0 +1,52 @@
+// Copyright 2018 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_CRYPTAUTH_FAKE_BACKGROUND_EID_GENERATOR_H_
+#define COMPONENTS_CRYPTAUTH_FAKE_BACKGROUND_EID_GENERATOR_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "components/cryptauth/background_eid_generator.h"
+
+namespace cryptauth {
+
+class BeaconSeed;
+
+// Test double class for BackgroundEidGenerator.
+class FakeBackgroundEidGenerator : public BackgroundEidGenerator {
+ public:
+  FakeBackgroundEidGenerator();
+  ~FakeBackgroundEidGenerator() override;
+
+  // BackgroundEidGenerator:
+  std::vector<DataWithTimestamp> GenerateNearestEids(
+      const std::vector<BeaconSeed>& beacon_seed) const override;
+  std::string IdentifyRemoteDeviceByAdvertisement(
+      cryptauth::RemoteBeaconSeedFetcher* remote_beacon_seed_fetcher,
+      const std::string& advertisement_service_data,
+      const std::vector<std::string>& device_ids) const override;
+
+  void set_nearest_eids_(
+      std::unique_ptr<std::vector<DataWithTimestamp>> nearest_eids) {
+    nearest_eids_ = std::move(nearest_eids);
+  }
+
+  void set_identified_device_id(const std::string& identified_device_id) {
+    identified_device_id_ = identified_device_id;
+  }
+
+  int num_identify_calls() { return num_identify_calls_; }
+
+ private:
+  std::unique_ptr<std::vector<DataWithTimestamp>> nearest_eids_;
+  std::string identified_device_id_;
+
+  int num_identify_calls_ = 0;
+};
+
+}  // namespace cryptauth
+
+#endif  // COMPONENTS_CRYPTAUTH_FAKE_BACKGROUND_EID_GENERATOR_H_
diff --git a/components/dom_distiller/webui/dom_distiller_handler.cc b/components/dom_distiller/webui/dom_distiller_handler.cc
index c2b1488..eebfca30 100644
--- a/components/dom_distiller/webui/dom_distiller_handler.cc
+++ b/components/dom_distiller/webui/dom_distiller_handler.cc
@@ -44,19 +44,18 @@
 void DomDistillerHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "requestEntries",
-      base::Bind(&DomDistillerHandler::HandleRequestEntries,
-                 base::Unretained(this)));
+      base::BindRepeating(&DomDistillerHandler::HandleRequestEntries,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "addArticle",
-      base::Bind(&DomDistillerHandler::HandleAddArticle,
-                 base::Unretained(this)));
+      "addArticle", base::BindRepeating(&DomDistillerHandler::HandleAddArticle,
+                                        base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "selectArticle",
-      base::Bind(&DomDistillerHandler::HandleSelectArticle,
-                 base::Unretained(this)));
+      base::BindRepeating(&DomDistillerHandler::HandleSelectArticle,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "viewUrl",
-      base::Bind(&DomDistillerHandler::HandleViewUrl, base::Unretained(this)));
+      "viewUrl", base::BindRepeating(&DomDistillerHandler::HandleViewUrl,
+                                     base::Unretained(this)));
 }
 
 void DomDistillerHandler::HandleAddArticle(const base::ListValue* args) {
diff --git a/components/domain_reliability/service_unittest.cc b/components/domain_reliability/service_unittest.cc
index 5dfbc1a..754e01f 100644
--- a/components/domain_reliability/service_unittest.cc
+++ b/components/domain_reliability/service_unittest.cc
@@ -11,9 +11,12 @@
 #include "base/time/time.h"
 #include "components/domain_reliability/monitor.h"
 #include "components/domain_reliability/test_util.h"
+#include "content/public/browser/browser_thread.h"
 #include "content/public/browser/permission_manager.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_utils.h"
 #include "net/base/host_port_pair.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "net/url_request/url_request_test_util.h"
@@ -134,16 +137,20 @@
 
   DomainReliabilityServiceTest()
       : upload_reporter_string_("test"),
-        permission_manager_(new TestPermissionManager()),
-        ui_task_runner_(new base::TestSimpleTaskRunner()),
-        network_task_runner_(new base::TestSimpleTaskRunner()),
-        url_request_context_getter_(
-            new net::TestURLRequestContextGetter(network_task_runner_)) {
+        permission_manager_(new TestPermissionManager()) {
+    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner =
+        content::BrowserThread::GetTaskRunnerForThread(
+            content::BrowserThread::UI);
+    scoped_refptr<base::SingleThreadTaskRunner> network_task_runner =
+        content::BrowserThread::GetTaskRunnerForThread(
+            content::BrowserThread::IO);
+    url_request_context_getter_ =
+        new net::TestURLRequestContextGetter(network_task_runner);
     browser_context_.SetPermissionManager(
         base::WrapUnique(permission_manager_));
     service_ = base::WrapUnique(DomainReliabilityService::Create(
         upload_reporter_string_, &browser_context_));
-    monitor_ = service_->CreateMonitor(ui_task_runner_, network_task_runner_);
+    monitor_ = service_->CreateMonitor(ui_task_runner, network_task_runner);
     monitor_->MoveToNetworkThread();
     monitor_->InitURLRequestContext(url_request_context_getter_);
     monitor_->SetDiscardUploads(true);
@@ -162,7 +169,7 @@
     return monitor_->uploader_->GetDiscardedUploadCount();
   }
 
-  base::MessageLoopForIO message_loop_;
+  content::TestBrowserThreadBundle thread_bundle_;
 
   std::string upload_reporter_string_;
 
@@ -173,9 +180,6 @@
 
   std::unique_ptr<DomainReliabilityService> service_;
 
-  scoped_refptr<base::TestSimpleTaskRunner> ui_task_runner_;
-  scoped_refptr<base::TestSimpleTaskRunner> network_task_runner_;
-
   scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
 
   std::unique_ptr<DomainReliabilityMonitor> monitor_;
@@ -212,10 +216,10 @@
 
   monitor_->ForceUploadsForTesting();
 
-  ui_task_runner_->RunPendingTasks();
+  content::RunAllPendingInMessageLoop(content::BrowserThread::UI);
   EXPECT_EQ(1, permission_manager_->get_permission_status_count());
 
-  network_task_runner_->RunPendingTasks();
+  content::RunAllPendingInMessageLoop(content::BrowserThread::IO);
   EXPECT_EQ(1, GetDiscardedUploadCount());
 }
 
@@ -243,10 +247,10 @@
 
   monitor_->ForceUploadsForTesting();
 
-  ui_task_runner_->RunPendingTasks();
+  content::RunAllPendingInMessageLoop(content::BrowserThread::UI);
   EXPECT_EQ(1, permission_manager_->get_permission_status_count());
 
-  network_task_runner_->RunPendingTasks();
+  content::RunAllPendingInMessageLoop(content::BrowserThread::IO);
   EXPECT_EQ(0, GetDiscardedUploadCount());
 }
 
@@ -277,10 +281,10 @@
   monitor_->Shutdown();
   monitor_.reset();
 
-  ui_task_runner_->RunPendingTasks();
+  content::RunAllPendingInMessageLoop(content::BrowserThread::UI);
   EXPECT_EQ(1, permission_manager_->get_permission_status_count());
 
-  network_task_runner_->RunPendingTasks();
+  content::RunAllPendingInMessageLoop(content::BrowserThread::IO);
   // Makes no sense to check upload count, since monitor was destroyed.
 }
 
@@ -308,13 +312,13 @@
 
   monitor_->ForceUploadsForTesting();
 
-  ui_task_runner_->RunPendingTasks();
+  content::RunAllPendingInMessageLoop(content::BrowserThread::UI);
   EXPECT_EQ(1, permission_manager_->get_permission_status_count());
 
   monitor_->Shutdown();
   monitor_.reset();
 
-  network_task_runner_->RunPendingTasks();
+  content::RunAllPendingInMessageLoop(content::BrowserThread::IO);
   // Makes no sense to check upload count, since monitor was destroyed.
 }
 
diff --git a/components/download/internal/common/BUILD.gn b/components/download/internal/common/BUILD.gn
index 8894045..a199d64 100644
--- a/components/download/internal/common/BUILD.gn
+++ b/components/download/internal/common/BUILD.gn
@@ -25,10 +25,12 @@
     "download_task_runner.cc",
     "download_ukm_helper.cc",
     "download_utils.cc",
+    "download_worker.cc",
     "parallel_download_utils.cc",
     "rate_estimator.cc",
     "resource_downloader.cc",
     "stream_handle_input_stream.cc",
+    "url_download_handler_factory.cc",
   ]
 
   public_deps = [
diff --git a/components/download/internal/common/DEPS b/components/download/internal/common/DEPS
index e2115897..cea69eb 100644
--- a/components/download/internal/common/DEPS
+++ b/components/download/internal/common/DEPS
@@ -6,9 +6,11 @@
   "+crypto",
   "+mojo/public/c/system",
   "+net/base/filename_util.h",
+  "+net/base/load_flags.h",
   "+net/base/io_buffer.h",
   "+net/base/net_errors.h",
   "+net/http/http_content_disposition.h",
+  "+net/http/http_request_headers.h",
   "+net/http/http_response_headers.h",
   "+net/http/http_status_code.h",
   "+net/http/http_util.h",
diff --git a/components/download/internal/common/download_utils.cc b/components/download/internal/common/download_utils.cc
index 1ff7f26..2248949 100644
--- a/components/download/internal/common/download_utils.cc
+++ b/components/download/internal/common/download_utils.cc
@@ -11,10 +11,24 @@
 #include "components/download/public/common/download_item.h"
 #include "components/download/public/common/download_save_info.h"
 #include "components/download/public/common/download_stats.h"
+#include "components/download/public/common/download_url_parameters.h"
+#include "net/base/load_flags.h"
+#include "net/http/http_request_headers.h"
 #include "net/http/http_status_code.h"
+#include "services/network/public/cpp/resource_request.h"
 
 namespace download {
 
+namespace {
+
+void AppendExtraHeaders(net::HttpRequestHeaders* headers,
+                        DownloadUrlParameters* params) {
+  for (const auto& header : params->request_headers())
+    headers->SetHeaderIfMissing(header.first, header.second);
+}
+
+}  // namespace
+
 const uint32_t DownloadItem::kInvalidId = 0;
 
 DownloadInterruptReason HandleRequestCompletionStatus(
@@ -208,4 +222,129 @@
        headers->response_code() == net::HTTP_PARTIAL_CONTENT);
 }
 
+std::unique_ptr<network::ResourceRequest> CreateResourceRequest(
+    DownloadUrlParameters* params) {
+  DCHECK(params->offset() >= 0);
+
+  std::unique_ptr<network::ResourceRequest> request(
+      new network::ResourceRequest);
+  request->method = params->method();
+  request->url = params->url();
+  request->request_initiator = params->initiator();
+  request->do_not_prompt_for_login = params->do_not_prompt_for_login();
+  request->site_for_cookies = params->url();
+  request->referrer = params->referrer();
+  request->referrer_policy = params->referrer_policy();
+  request->allow_download = true;
+  request->is_main_frame = true;
+
+  if (params->render_process_host_id() >= 0)
+    request->render_frame_id = params->render_frame_host_routing_id();
+
+  bool has_upload_data = false;
+  if (params->post_body()) {
+    request->request_body = params->post_body();
+    has_upload_data = true;
+  }
+
+  if (params->post_id() >= 0) {
+    // The POST in this case does not have an actual body, and only works
+    // when retrieving data from cache. This is done because we don't want
+    // to do a re-POST without user consent, and currently don't have a good
+    // plan on how to display the UI for that.
+    DCHECK(params->prefer_cache());
+    DCHECK_EQ("POST", params->method());
+    request->request_body = new network::ResourceRequestBody();
+    request->request_body->set_identifier(params->post_id());
+    has_upload_data = true;
+  }
+
+  request->load_flags = GetLoadFlags(params, has_upload_data);
+
+  // Add additional request headers.
+  std::unique_ptr<net::HttpRequestHeaders> headers =
+      GetAdditionalRequestHeaders(params);
+  request->headers.Swap(headers.get());
+
+  return request;
+}
+
+int GetLoadFlags(DownloadUrlParameters* params, bool has_upload_data) {
+  int load_flags = 0;
+  if (params->prefer_cache()) {
+    // If there is upload data attached, only retrieve from cache because there
+    // is no current mechanism to prompt the user for their consent for a
+    // re-post. For GETs, try to retrieve data from the cache and skip
+    // validating the entry if present.
+    if (has_upload_data)
+      load_flags |= net::LOAD_ONLY_FROM_CACHE | net::LOAD_SKIP_CACHE_VALIDATION;
+    else
+      load_flags |= net::LOAD_SKIP_CACHE_VALIDATION;
+  } else {
+    load_flags |= net::LOAD_DISABLE_CACHE;
+  }
+  return load_flags;
+}
+
+std::unique_ptr<net::HttpRequestHeaders> GetAdditionalRequestHeaders(
+    DownloadUrlParameters* params) {
+  auto headers = std::make_unique<net::HttpRequestHeaders>();
+  if (params->offset() == 0 &&
+      params->length() == DownloadSaveInfo::kLengthFullContent) {
+    AppendExtraHeaders(headers.get(), params);
+    return headers;
+  }
+
+  bool has_last_modified = !params->last_modified().empty();
+  bool has_etag = !params->etag().empty();
+
+  // Strong validator(i.e. etag or last modified) is required in range requests
+  // for download resumption and parallel download.
+  DCHECK(has_etag || has_last_modified);
+  if (!has_etag && !has_last_modified) {
+    DVLOG(1) << "Creating partial request without strong validators.";
+    AppendExtraHeaders(headers.get(), params);
+    return headers;
+  }
+
+  // Add "Range" header.
+  std::string range_header =
+      (params->length() == DownloadSaveInfo::kLengthFullContent)
+          ? base::StringPrintf("bytes=%" PRId64 "-", params->offset())
+          : base::StringPrintf("bytes=%" PRId64 "-%" PRId64, params->offset(),
+                               params->offset() + params->length() - 1);
+  headers->SetHeader(net::HttpRequestHeaders::kRange, range_header);
+
+  // Add "If-Range" headers.
+  if (params->use_if_range()) {
+    // In accordance with RFC 7233 Section 3.2, use If-Range to specify that
+    // the server return the entire entity if the validator doesn't match.
+    // Last-Modified can be used in the absence of ETag as a validator if the
+    // response headers satisfied the HttpUtil::HasStrongValidators()
+    // predicate.
+    //
+    // This function assumes that HasStrongValidators() was true and that the
+    // ETag and Last-Modified header values supplied are valid.
+    headers->SetHeader(net::HttpRequestHeaders::kIfRange,
+                       has_etag ? params->etag() : params->last_modified());
+    AppendExtraHeaders(headers.get(), params);
+    return headers;
+  }
+
+  // Add "If-Match"/"If-Unmodified-Since" headers.
+  if (has_etag)
+    headers->SetHeader(net::HttpRequestHeaders::kIfMatch, params->etag());
+
+  // According to RFC 7232 section 3.4, "If-Unmodified-Since" is mainly for
+  // old servers that didn't implement "If-Match" and must be ignored when
+  // "If-Match" presents.
+  if (has_last_modified) {
+    headers->SetHeader(net::HttpRequestHeaders::kIfUnmodifiedSince,
+                       params->last_modified());
+  }
+
+  AppendExtraHeaders(headers.get(), params);
+  return headers;
+}
+
 }  // namespace download
diff --git a/components/download/internal/common/download_worker.cc b/components/download/internal/common/download_worker.cc
new file mode 100644
index 0000000..b49ce93
--- /dev/null
+++ b/components/download/internal/common/download_worker.cc
@@ -0,0 +1,151 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/download/public/common/download_worker.h"
+
+#include "base/message_loop/message_loop.h"
+#include "components/download/public/common/download_create_info.h"
+#include "components/download/public/common/download_interrupt_reasons.h"
+#include "components/download/public/common/download_task_runner.h"
+#include "components/download/public/common/download_utils.h"
+#include "components/download/public/common/input_stream.h"
+#include "components/download/public/common/resource_downloader.h"
+#include "components/download/public/common/url_download_handler_factory.h"
+#include "services/network/public/cpp/features.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+
+namespace download {
+namespace {
+
+const int kWorkerVerboseLevel = 1;
+
+class CompletedInputStream : public InputStream {
+ public:
+  CompletedInputStream(DownloadInterruptReason status) : status_(status){};
+  ~CompletedInputStream() override = default;
+
+  // InputStream
+  bool IsEmpty() override { return false; }
+  InputStream::StreamState Read(scoped_refptr<net::IOBuffer>* data,
+                                size_t* length) override {
+    *length = 0;
+    return InputStream::StreamState::COMPLETE;
+  }
+
+  DownloadInterruptReason GetCompletionStatus() override { return status_; }
+
+ private:
+  DownloadInterruptReason status_;
+  DISALLOW_COPY_AND_ASSIGN(CompletedInputStream);
+};
+
+void CreateUrlDownloadHandler(
+    std::unique_ptr<DownloadUrlParameters> params,
+    base::WeakPtr<UrlDownloadHandler::Delegate> delegate,
+    scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
+    const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
+  auto downloader = UrlDownloadHandlerFactory::Create(
+      std::move(params), delegate, std::move(shared_url_loader_factory),
+      task_runner);
+  task_runner->PostTask(
+      FROM_HERE,
+      base::BindOnce(&UrlDownloadHandler::Delegate::OnUrlDownloadHandlerCreated,
+                     delegate, std::move(downloader)));
+}
+
+}  // namespace
+
+DownloadWorker::DownloadWorker(DownloadWorker::Delegate* delegate,
+                               int64_t offset,
+                               int64_t length)
+    : delegate_(delegate),
+      offset_(offset),
+      length_(length),
+      is_paused_(false),
+      is_canceled_(false),
+      is_user_cancel_(false),
+      url_download_handler_(nullptr, base::OnTaskRunnerDeleter(nullptr)),
+      weak_factory_(this) {
+  DCHECK(delegate_);
+}
+
+DownloadWorker::~DownloadWorker() = default;
+
+void DownloadWorker::SendRequest(
+    std::unique_ptr<DownloadUrlParameters> params,
+    scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory) {
+  GetIOTaskRunner()->PostTask(
+      FROM_HERE, base::BindOnce(&CreateUrlDownloadHandler, std::move(params),
+                                weak_factory_.GetWeakPtr(),
+                                std::move(shared_url_loader_factory),
+                                base::ThreadTaskRunnerHandle::Get()));
+}
+
+void DownloadWorker::Pause() {
+  is_paused_ = true;
+  if (request_handle_)
+    request_handle_->PauseRequest();
+}
+
+void DownloadWorker::Resume() {
+  is_paused_ = false;
+  if (request_handle_)
+    request_handle_->ResumeRequest();
+}
+
+void DownloadWorker::Cancel(bool user_cancel) {
+  is_canceled_ = true;
+  is_user_cancel_ = user_cancel;
+  if (request_handle_)
+    request_handle_->CancelRequest(user_cancel);
+}
+
+void DownloadWorker::OnUrlDownloadStarted(
+    std::unique_ptr<DownloadCreateInfo> create_info,
+    std::unique_ptr<InputStream> input_stream,
+    scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
+    const DownloadUrlParameters::OnStartedCallback& callback) {
+  // |callback| is not used in subsequent requests.
+  DCHECK(callback.is_null());
+
+  // Destroy the request if user canceled.
+  if (is_canceled_) {
+    VLOG(kWorkerVerboseLevel)
+        << "Byte stream arrived after user cancel the request.";
+    create_info->request_handle->CancelRequest(is_user_cancel_);
+    return;
+  }
+
+  // TODO(xingliu): Add metric for error handling.
+  if (create_info->result != DOWNLOAD_INTERRUPT_REASON_NONE) {
+    VLOG(kWorkerVerboseLevel)
+        << "Parallel download sub-request failed. reason = "
+        << create_info->result;
+    input_stream.reset(new CompletedInputStream(create_info->result));
+  }
+
+  request_handle_ = std::move(create_info->request_handle);
+
+  // Pause the stream if user paused, still push the stream reader to the sink.
+  if (is_paused_) {
+    VLOG(kWorkerVerboseLevel)
+        << "Byte stream arrived after user pause the request.";
+    Pause();
+  }
+
+  delegate_->OnInputStreamReady(this, std::move(input_stream));
+}
+
+void DownloadWorker::OnUrlDownloadStopped(UrlDownloadHandler* downloader) {
+  // Release the |url_download_handler_|, the object will be deleted on IO
+  // thread.
+  url_download_handler_.reset();
+}
+
+void DownloadWorker::OnUrlDownloadHandlerCreated(
+    UrlDownloadHandler::UniqueUrlDownloadHandlerPtr downloader) {
+  url_download_handler_ = std::move(downloader);
+}
+
+}  // namespace download
diff --git a/components/download/internal/common/resource_downloader.cc b/components/download/internal/common/resource_downloader.cc
index 98e6fea1..e6cd589 100644
--- a/components/download/internal/common/resource_downloader.cc
+++ b/components/download/internal/common/resource_downloader.cc
@@ -71,10 +71,10 @@
   auto downloader = std::make_unique<ResourceDownloader>(
       delegate, std::move(request), params->render_process_host_id(),
       params->render_frame_host_routing_id(), site_url, tab_url,
-      tab_referrer_url, download_id, task_runner);
+      tab_referrer_url, download_id, task_runner,
+      std::move(shared_url_loader_factory));
 
-  downloader->Start(std::move(shared_url_loader_factory), std::move(params),
-                    is_parallel_request);
+  downloader->Start(std::move(params), is_parallel_request);
   return downloader;
 }
 
@@ -93,11 +93,12 @@
     const scoped_refptr<network::ResourceResponse>& response,
     net::CertStatus cert_status,
     network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
+    scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
   auto downloader = std::make_unique<ResourceDownloader>(
       delegate, std::move(resource_request), render_process_id, render_frame_id,
       site_url, tab_url, tab_referrer_url, download::DownloadItem::kInvalidId,
-      task_runner);
+      task_runner, std::move(shared_url_loader_factory));
   downloader->InterceptResponse(std::move(response), std::move(url_chain),
                                 suggested_filename, cert_status,
                                 std::move(url_loader_client_endpoints));
@@ -113,7 +114,8 @@
     const GURL& tab_url,
     const GURL& tab_referrer_url,
     uint32_t download_id,
-    const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
+    const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
+    scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory)
     : delegate_(delegate),
       resource_request_(std::move(resource_request)),
       download_id_(download_id),
@@ -123,12 +125,12 @@
       tab_url_(tab_url),
       tab_referrer_url_(tab_referrer_url),
       delegate_task_runner_(task_runner),
+      shared_url_loader_factory_(std::move(shared_url_loader_factory)),
       weak_ptr_factory_(this) {}
 
 ResourceDownloader::~ResourceDownloader() = default;
 
 void ResourceDownloader::Start(
-    scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
     std::unique_ptr<DownloadUrlParameters> download_url_parameters,
     bool is_parallel_request) {
   callback_ = download_url_parameters->callback();
@@ -153,7 +155,7 @@
   // Set up the URLLoader
   network::mojom::URLLoaderRequest url_loader_request =
       mojo::MakeRequest(&url_loader_);
-  shared_url_loader_factory->CreateLoaderAndStart(
+  shared_url_loader_factory_->CreateLoaderAndStart(
       std::move(url_loader_request),
       0,  // routing_id
       0,  // request_id
@@ -217,7 +219,7 @@
           &UrlDownloadHandler::Delegate::OnUrlDownloadStarted, delegate_,
           std::move(download_create_info),
           std::make_unique<StreamHandleInputStream>(std::move(stream_handle)),
-          callback_));
+          std::move(shared_url_loader_factory_), callback_));
 }
 
 void ResourceDownloader::OnReceiveRedirect() {
diff --git a/components/download/internal/common/url_download_handler_factory.cc b/components/download/internal/common/url_download_handler_factory.cc
new file mode 100644
index 0000000..fec5bf4
--- /dev/null
+++ b/components/download/internal/common/url_download_handler_factory.cc
@@ -0,0 +1,83 @@
+// Copyright 2018 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/download/public/common/url_download_handler_factory.h"
+
+#include "base/no_destructor.h"
+#include "base/synchronization/lock.h"
+#include "components/download/public/common/download_item.h"
+#include "components/download/public/common/download_utils.h"
+#include "components/download/public/common/resource_downloader.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+
+namespace download {
+
+namespace {
+
+// Factory for creating URLDownloadHandler used by network service.
+class DefaultUrlDownloadHandlerFactory : public UrlDownloadHandlerFactory {
+ public:
+  DefaultUrlDownloadHandlerFactory() = default;
+  ~DefaultUrlDownloadHandlerFactory() override = default;
+
+ protected:
+  UrlDownloadHandler::UniqueUrlDownloadHandlerPtr CreateUrlDownloadHandler(
+      std::unique_ptr<download::DownloadUrlParameters> params,
+      base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate,
+      scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
+      const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) override {
+    std::unique_ptr<network::ResourceRequest> request =
+        CreateResourceRequest(params.get());
+    return UrlDownloadHandler::UniqueUrlDownloadHandlerPtr(
+        download::ResourceDownloader::BeginDownload(
+            delegate, std::move(params), std::move(request),
+            std::move(shared_url_loader_factory), GURL(), GURL(), GURL(),
+            download::DownloadItem::kInvalidId, true, task_runner)
+            .release(),
+        base::OnTaskRunnerDeleter(base::ThreadTaskRunnerHandle::Get()));
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DefaultUrlDownloadHandlerFactory);
+};
+
+UrlDownloadHandlerFactory* g_url_download_handler_factory;
+
+// Lock to protect |g_url_download_handler_factory|
+base::Lock& GetURLDownloadHandlerFactoryLock() {
+  static base::NoDestructor<base::Lock> instance;
+  return *instance;
+}
+
+}  // namespace
+
+// static
+UrlDownloadHandler::UniqueUrlDownloadHandlerPtr
+UrlDownloadHandlerFactory::Create(
+    std::unique_ptr<download::DownloadUrlParameters> params,
+    base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate,
+    scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
+    const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
+  base::AutoLock auto_lock(GetURLDownloadHandlerFactoryLock());
+  if (!g_url_download_handler_factory)
+    g_url_download_handler_factory = new DefaultUrlDownloadHandlerFactory();
+  return g_url_download_handler_factory->CreateUrlDownloadHandler(
+      std::move(params), delegate, std::move(shared_url_loader_factory),
+      task_runner);
+}
+
+// static
+void UrlDownloadHandlerFactory::Install(UrlDownloadHandlerFactory* factory) {
+  base::AutoLock auto_lock(GetURLDownloadHandlerFactoryLock());
+  if (factory == g_url_download_handler_factory)
+    return;
+  delete g_url_download_handler_factory;
+  g_url_download_handler_factory = factory;
+}
+
+UrlDownloadHandlerFactory::UrlDownloadHandlerFactory() = default;
+
+UrlDownloadHandlerFactory::~UrlDownloadHandlerFactory() = default;
+
+}  // namespace download
diff --git a/components/download/public/common/BUILD.gn b/components/download/public/common/BUILD.gn
index fb9f727..2b6d6c15 100644
--- a/components/download/public/common/BUILD.gn
+++ b/components/download/public/common/BUILD.gn
@@ -43,6 +43,7 @@
     "download_url_parameters.cc",
     "download_url_parameters.h",
     "download_utils.h",
+    "download_worker.h",
     "input_stream.cc",
     "input_stream.h",
     "parallel_download_utils.h",
@@ -50,6 +51,7 @@
     "resource_downloader.h",
     "resume_mode.h",
     "stream_handle_input_stream.h",
+    "url_download_handler_factory.h",
   ]
 
   configs += [ ":components_download_implementation" ]
diff --git a/components/download/public/common/download_utils.h b/components/download/public/common/download_utils.h
index e5c7eec..9fc9c5a 100644
--- a/components/download/public/common/download_utils.h
+++ b/components/download/public/common/download_utils.h
@@ -11,9 +11,18 @@
 #include "net/cert/cert_status_flags.h"
 #include "net/http/http_response_headers.h"
 
+namespace net {
+class HttpRequestHeaders;
+}
+
+namespace network {
+struct ResourceRequest;
+}
+
 namespace download {
 struct DownloadCreateInfo;
 struct DownloadSaveInfo;
+class DownloadUrlParameters;
 
 // Handle the url request completion status and return the interrupt reasons.
 // |cert_status| is ignored if error_code is not net::ERR_ABORTED.
@@ -36,6 +45,18 @@
     const net::HttpResponseHeaders* headers,
     DownloadCreateInfo* create_info);
 
+// Create a ResourceRequest from |params|.
+COMPONENTS_DOWNLOAD_EXPORT std::unique_ptr<network::ResourceRequest>
+CreateResourceRequest(DownloadUrlParameters* params);
+
+// Gets LoadFlags from |params|.
+COMPONENTS_DOWNLOAD_EXPORT int GetLoadFlags(DownloadUrlParameters* params,
+                                            bool has_upload_data);
+
+// Gets addtional request headers from |params|.
+COMPONENTS_DOWNLOAD_EXPORT std::unique_ptr<net::HttpRequestHeaders>
+GetAdditionalRequestHeaders(DownloadUrlParameters* params);
+
 }  // namespace download
 
 #endif  // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_UTILS_H_
diff --git a/components/download/public/common/download_worker.h b/components/download/public/common/download_worker.h
new file mode 100644
index 0000000..8865f28
--- /dev/null
+++ b/components/download/public/common/download_worker.h
@@ -0,0 +1,95 @@
+// 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_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_WORKER_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_WORKER_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "components/download/public/common/download_export.h"
+#include "components/download/public/common/download_request_handle_interface.h"
+#include "components/download/public/common/download_url_parameters.h"
+#include "components/download/public/common/url_download_handler.h"
+
+namespace network {
+class SharedURLLoaderFactory;
+}
+
+namespace download {
+
+// Helper class used to send subsequent range requests to fetch slices of the
+// file after handling response of the original non-range request.
+// TODO(xingliu): we should consider to reuse this class for single connection
+// download.
+class COMPONENTS_DOWNLOAD_EXPORT DownloadWorker
+    : public UrlDownloadHandler::Delegate {
+ public:
+  class Delegate {
+   public:
+    // Called when the the input stream is established after server response is
+    // handled. The stream contains data starts from |offset| of the
+    // destination file.
+    virtual void OnInputStreamReady(
+        DownloadWorker* worker,
+        std::unique_ptr<InputStream> input_stream) = 0;
+  };
+
+  DownloadWorker(DownloadWorker::Delegate* delegate,
+                 int64_t offset,
+                 int64_t length);
+  virtual ~DownloadWorker();
+
+  int64_t offset() const { return offset_; }
+  int64_t length() const { return length_; }
+
+  // Send network request to ask for a download.
+  void SendRequest(
+      std::unique_ptr<DownloadUrlParameters> params,
+      scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory);
+
+  // Download operations.
+  void Pause();
+  void Resume();
+  void Cancel(bool user_cancel);
+
+ private:
+  // UrlDownloader::Delegate implementation.
+  void OnUrlDownloadStarted(
+      std::unique_ptr<DownloadCreateInfo> create_info,
+      std::unique_ptr<InputStream> input_stream,
+      scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
+      const DownloadUrlParameters::OnStartedCallback& callback) override;
+  void OnUrlDownloadStopped(UrlDownloadHandler* downloader) override;
+  void OnUrlDownloadHandlerCreated(
+      UrlDownloadHandler::UniqueUrlDownloadHandlerPtr downloader) override;
+
+  DownloadWorker::Delegate* const delegate_;
+
+  // The starting position of the content for this worker to download.
+  int64_t offset_;
+
+  // The length of the request. May be 0 to fetch to the end of the file.
+  int64_t length_;
+
+  // States of the worker.
+  bool is_paused_;
+  bool is_canceled_;
+  bool is_user_cancel_;
+
+  // Used to control the network request. Live on UI thread.
+  std::unique_ptr<DownloadRequestHandleInterface> request_handle_;
+
+  // Used to handle the url request. Live and die on IO thread.
+  UrlDownloadHandler::UniqueUrlDownloadHandlerPtr url_download_handler_;
+
+  base::WeakPtrFactory<DownloadWorker> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(DownloadWorker);
+};
+
+}  // namespace download
+
+#endif  // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_WORKER_H_
diff --git a/components/download/public/common/resource_downloader.h b/components/download/public/common/resource_downloader.h
index 3a587b8..9106f98 100644
--- a/components/download/public/common/resource_downloader.h
+++ b/components/download/public/common/resource_downloader.h
@@ -53,6 +53,7 @@
       const scoped_refptr<network::ResourceResponse>& response,
       net::CertStatus cert_status,
       network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
+      scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
       const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
 
   ResourceDownloader(
@@ -64,7 +65,8 @@
       const GURL& tab_url,
       const GURL& tab_referrer_url,
       uint32_t download_id,
-      const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
+      const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
+      scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory);
   ~ResourceDownloader() override;
 
   // download::DownloadResponseHandler::Delegate
@@ -76,7 +78,6 @@
  private:
   // Helper method to start the network request.
   void Start(
-      scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
       std::unique_ptr<download::DownloadUrlParameters> download_url_parameters,
       bool is_parallel_request);
 
@@ -132,6 +133,9 @@
   // TaskRunner to post callbacks to the |delegate_|
   scoped_refptr<base::SingleThreadTaskRunner> delegate_task_runner_;
 
+  // URLLoaderFactory for issueing network requests.
+  scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
+
   base::WeakPtrFactory<ResourceDownloader> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ResourceDownloader);
diff --git a/components/download/public/common/url_download_handler.h b/components/download/public/common/url_download_handler.h
index 7ab5198..5779dd13 100644
--- a/components/download/public/common/url_download_handler.h
+++ b/components/download/public/common/url_download_handler.h
@@ -7,6 +7,7 @@
 
 #include "components/download/public/common/download_export.h"
 #include "components/download/public/common/download_url_parameters.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 namespace download {
 struct DownloadCreateInfo;
@@ -23,6 +24,8 @@
     virtual void OnUrlDownloadStarted(
         std::unique_ptr<DownloadCreateInfo> download_create_info,
         std::unique_ptr<InputStream> input_stream,
+        scoped_refptr<network::SharedURLLoaderFactory>
+            shared_url_loader_factory,
         const DownloadUrlParameters::OnStartedCallback& callback) = 0;
 
     // Called after the connection is cancelled or finished.
diff --git a/components/download/public/common/url_download_handler_factory.h b/components/download/public/common/url_download_handler_factory.h
new file mode 100644
index 0000000..c437194
--- /dev/null
+++ b/components/download/public/common/url_download_handler_factory.h
@@ -0,0 +1,51 @@
+// Copyright 2018 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_DOWNLOAD_PUBLIC_COMMON_URL_DOWNLOAD_HANDLER_FACTORY_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_URL_DOWNLOAD_HANDLER_FACTORY_H_
+
+#include "components/download/public/common/url_download_handler.h"
+
+namespace network {
+class SharedURLLoaderFactory;
+}
+
+namespace download {
+class DownloadUrlParameters;
+
+// Class for handling the creation of a URLDownloadHandler. This is used to
+// allow injection of different URLDownloadHandler implementations.
+// TODO(qinmin): remove this factory once network service is fully enabled.
+class COMPONENTS_DOWNLOAD_EXPORT UrlDownloadHandlerFactory {
+ public:
+  // Installs a new factory for creating the URLDownloadHandler. Can be called
+  // on any thread.
+  static void Install(UrlDownloadHandlerFactory* factory);
+
+  // Creates a URLDownloadHandler. By default the handler is used for network
+  // service. Must be called on the IO thread.
+  static UrlDownloadHandler::UniqueUrlDownloadHandlerPtr Create(
+      std::unique_ptr<download::DownloadUrlParameters> params,
+      base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate,
+      scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
+      const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
+
+  virtual ~UrlDownloadHandlerFactory();
+
+ protected:
+  UrlDownloadHandlerFactory();
+
+  // To be implemented by child classes to provide their own URLDownloadHandler
+  // instances.
+  virtual UrlDownloadHandler::UniqueUrlDownloadHandlerPtr
+  CreateUrlDownloadHandler(
+      std::unique_ptr<download::DownloadUrlParameters> params,
+      base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate,
+      scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
+      const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) = 0;
+};
+
+}  // namespace download
+
+#endif  // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_URL_DOWNLOAD_HANDLER_FACTORY_H_
diff --git a/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/FeatureConstants.java b/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/FeatureConstants.java
index bba3eca..43945151 100644
--- a/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/FeatureConstants.java
+++ b/components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement/FeatureConstants.java
@@ -13,7 +13,6 @@
     public static final String DOWNLOAD_PAGE_SCREENSHOT_FEATURE = "IPH_DownloadPageScreenshot";
     public static final String DOWNLOAD_HOME_FEATURE = "IPH_DownloadHome";
     public static final String CHROME_HOME_EXPAND_FEATURE = "IPH_ChromeHomeExpand";
-    public static final String CHROME_HOME_MENU_HEADER_FEATURE = "IPH_ChromeHomeMenuHeader";
     public static final String CHROME_HOME_PULL_TO_REFRESH_FEATURE = "IPH_ChromeHomePullToRefresh";
     public static final String DATA_SAVER_PREVIEW_FEATURE = "IPH_DataSaverPreview";
     public static final String DATA_SAVER_DETAIL_FEATURE = "IPH_DataSaverDetail";
diff --git a/components/feature_engagement/public/feature_constants.cc b/components/feature_engagement/public/feature_constants.cc
index 3c44da0..ca3b4ce0 100644
--- a/components/feature_engagement/public/feature_constants.cc
+++ b/components/feature_engagement/public/feature_constants.cc
@@ -27,8 +27,6 @@
     "IPH_DownloadPageScreenshot", base::FEATURE_DISABLED_BY_DEFAULT};
 const base::Feature kIPHChromeHomeExpandFeature{
     "IPH_ChromeHomeExpand", base::FEATURE_DISABLED_BY_DEFAULT};
-const base::Feature kIPHChromeHomeMenuHeaderFeature{
-    "IPH_ChromeHomeMenuHeader", base::FEATURE_DISABLED_BY_DEFAULT};
 const base::Feature kIPHChromeHomePullToRefreshFeature{
     "IPH_ChromeHomePullToRefresh", base::FEATURE_DISABLED_BY_DEFAULT};
 const base::Feature kIPHMediaDownloadFeature{"IPH_MediaDownload",
diff --git a/components/feature_engagement/public/feature_constants.h b/components/feature_engagement/public/feature_constants.h
index bf2857d..d7d39f14 100644
--- a/components/feature_engagement/public/feature_constants.h
+++ b/components/feature_engagement/public/feature_constants.h
@@ -27,7 +27,6 @@
 extern const base::Feature kIPHDownloadPageFeature;
 extern const base::Feature kIPHDownloadPageScreenshotFeature;
 extern const base::Feature kIPHChromeHomeExpandFeature;
-extern const base::Feature kIPHChromeHomeMenuHeaderFeature;
 extern const base::Feature kIPHChromeHomePullToRefreshFeature;
 extern const base::Feature kIPHMediaDownloadFeature;
 extern const base::Feature kIPHContextualSearchWebSearchFeature;
diff --git a/components/feature_engagement/public/feature_list.cc b/components/feature_engagement/public/feature_list.cc
index 9b7a306..c4989dbe 100644
--- a/components/feature_engagement/public/feature_list.cc
+++ b/components/feature_engagement/public/feature_list.cc
@@ -22,7 +22,6 @@
     &kIPHDownloadPageFeature,
     &kIPHDownloadPageScreenshotFeature,
     &kIPHChromeHomeExpandFeature,
-    &kIPHChromeHomeMenuHeaderFeature,
     &kIPHChromeHomePullToRefreshFeature,
     &kIPHMediaDownloadFeature,
     &kIPHContextualSearchWebSearchFeature,
diff --git a/components/feature_engagement/public/feature_list.h b/components/feature_engagement/public/feature_list.h
index 2b189656..5b71eba6a 100644
--- a/components/feature_engagement/public/feature_list.h
+++ b/components/feature_engagement/public/feature_list.h
@@ -53,8 +53,6 @@
 DEFINE_VARIATION_PARAM(kIPHDownloadPageScreenshotFeature,
                        "IPH_DownloadPageScreenshot");
 DEFINE_VARIATION_PARAM(kIPHChromeHomeExpandFeature, "IPH_ChromeHomeExpand");
-DEFINE_VARIATION_PARAM(kIPHChromeHomeMenuHeaderFeature,
-                       "IPH_ChromeHomeMenuHeader");
 DEFINE_VARIATION_PARAM(kIPHChromeHomePullToRefreshFeature,
                        "IPH_ChromeHomePullToRefresh");
 DEFINE_VARIATION_PARAM(kIPHMediaDownloadFeature, "IPH_MediaDownload");
@@ -92,7 +90,6 @@
         VARIATION_ENTRY(kIPHDownloadPageFeature),
         VARIATION_ENTRY(kIPHDownloadPageScreenshotFeature),
         VARIATION_ENTRY(kIPHChromeHomeExpandFeature),
-        VARIATION_ENTRY(kIPHChromeHomeMenuHeaderFeature),
         VARIATION_ENTRY(kIPHChromeHomePullToRefreshFeature),
         VARIATION_ENTRY(kIPHMediaDownloadFeature),
         VARIATION_ENTRY(kIPHContextualSearchWebSearchFeature),
diff --git a/components/nacl/common/BUILD.gn b/components/nacl/common/BUILD.gn
index 84e81bf3..df8a120c 100644
--- a/components/nacl/common/BUILD.gn
+++ b/components/nacl/common/BUILD.gn
@@ -57,7 +57,7 @@
 
     # Deps required by the above headers.
     deps = [
-      "//media:media_features",
+      "//media:media_buildflags",
     ]
   }
 
diff --git a/components/nacl/loader/BUILD.gn b/components/nacl/loader/BUILD.gn
index d6715af..b125e1a 100644
--- a/components/nacl/loader/BUILD.gn
+++ b/components/nacl/loader/BUILD.gn
@@ -59,7 +59,7 @@
 
   # Deps required by the above headers.
   deps = [
-    "//media:media_features",
+    "//media:media_buildflags",
   ]
 }
 
diff --git a/components/ntp_snippets/contextual/contextual_content_suggestions_service.h b/components/ntp_snippets/contextual/contextual_content_suggestions_service.h
index e24fa661..4b050ba 100644
--- a/components/ntp_snippets/contextual/contextual_content_suggestions_service.h
+++ b/components/ntp_snippets/contextual/contextual_content_suggestions_service.h
@@ -15,6 +15,7 @@
 #include "components/image_fetcher/core/image_fetcher.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/ntp_snippets/callbacks.h"
+#include "components/ntp_snippets/content_suggestion.h"
 #include "components/ntp_snippets/contextual/contextual_suggestions_fetcher.h"
 
 namespace ntp_snippets {
@@ -26,6 +27,29 @@
 // for contextual suggestion, using caching.
 class ContextualContentSuggestionsService : public KeyedService {
  public:
+  // A structure representing a suggestion cluster.
+  struct Cluster {
+    Cluster();
+    ~Cluster();
+
+    std::string title;
+    std::vector<ContentSuggestion> suggestions;
+
+    DISALLOW_COPY_AND_ASSIGN(Cluster);
+  };
+
+  // Delegate for UI to hook into contextual suggestions service.
+  class Delegate {
+   public:
+    virtual ~Delegate() = default;
+
+    // Sends the new suggestions to the delegate, when they are available.
+    virtual void OnSuggestionsAvailable(std::vector<Cluster> clusters) = 0;
+    // Informs the delegate that user has switched to another tab or clobbered
+    // the current tab, therefore the UI state should be cleared.
+    virtual void OnStateCleared() = 0;
+  };
+
   ContextualContentSuggestionsService(
       std::unique_ptr<ContextualSuggestionsFetcher>
           contextual_suggestions_fetcher,
diff --git a/components/ntp_tiles/webui/ntp_tiles_internals_message_handler.cc b/components/ntp_tiles/webui/ntp_tiles_internals_message_handler.cc
index d006069..43ef930 100644
--- a/components/ntp_tiles/webui/ntp_tiles_internals_message_handler.cc
+++ b/components/ntp_tiles/webui/ntp_tiles_internals_message_handler.cc
@@ -69,22 +69,26 @@
 
   client_->RegisterMessageCallback(
       "registerForEvents",
-      base::Bind(&NTPTilesInternalsMessageHandler::HandleRegisterForEvents,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &NTPTilesInternalsMessageHandler::HandleRegisterForEvents,
+          base::Unretained(this)));
 
   client_->RegisterMessageCallback(
-      "update", base::Bind(&NTPTilesInternalsMessageHandler::HandleUpdate,
-                           base::Unretained(this)));
+      "update",
+      base::BindRepeating(&NTPTilesInternalsMessageHandler::HandleUpdate,
+                          base::Unretained(this)));
 
   client_->RegisterMessageCallback(
       "fetchSuggestions",
-      base::Bind(&NTPTilesInternalsMessageHandler::HandleFetchSuggestions,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &NTPTilesInternalsMessageHandler::HandleFetchSuggestions,
+          base::Unretained(this)));
 
   client_->RegisterMessageCallback(
       "viewPopularSitesJson",
-      base::Bind(&NTPTilesInternalsMessageHandler::HandleViewPopularSitesJson,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &NTPTilesInternalsMessageHandler::HandleViewPopularSitesJson,
+          base::Unretained(this)));
 }
 
 void NTPTilesInternalsMessageHandler::HandleRegisterForEvents(
diff --git a/components/ntp_tiles/webui/ntp_tiles_internals_message_handler_client.h b/components/ntp_tiles/webui/ntp_tiles_internals_message_handler_client.h
index 456f52e..08cb018 100644
--- a/components/ntp_tiles/webui/ntp_tiles_internals_message_handler_client.h
+++ b/components/ntp_tiles/webui/ntp_tiles_internals_message_handler_client.h
@@ -44,7 +44,8 @@
   // Registers a callback in Javascript. See content::WebUI and web::WebUIIOS.
   virtual void RegisterMessageCallback(
       const std::string& message,
-      const base::Callback<void(const base::ListValue*)>& callback) = 0;
+      const base::RepeatingCallback<void(const base::ListValue*)>&
+          callback) = 0;
 
   // Invokes a function in Javascript. See content::WebUI and web::WebUIIOS.
   virtual void CallJavascriptFunctionVector(
diff --git a/components/offline_pages/core/offline_page_feature.cc b/components/offline_pages/core/offline_page_feature.cc
index 59aaf91..7bff4c6 100644
--- a/components/offline_pages/core/offline_page_feature.cc
+++ b/components/offline_pages/core/offline_page_feature.cc
@@ -63,6 +63,9 @@
 const base::Feature kOfflinePagesDescriptivePendingStatusFeature{
     "OfflinePagesDescriptivePendingStatus", base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kOfflinePagesInDownloadHomeOpenInCctFeature{
+    "OfflinePagesInDownloadHomeOpenInCct", base::FEATURE_DISABLED_BY_DEFAULT};
+
 const char kPrefetchingOfflinePagesExperimentsOption[] = "exp";
 
 bool IsOfflineBookmarksEnabled() {
@@ -131,6 +134,11 @@
       kOfflinePagesDescriptivePendingStatusFeature);
 }
 
+bool ShouldOfflinePagesInDownloadHomeOpenInCct() {
+  return base::FeatureList::IsEnabled(
+      kOfflinePagesInDownloadHomeOpenInCctFeature);
+}
+
 std::string GetPrefetchingOfflinePagesExperimentTag() {
   return base::GetFieldTrialParamValueByFeature(
       kPrefetchingOfflinePagesFeature,
diff --git a/components/offline_pages/core/offline_page_feature.h b/components/offline_pages/core/offline_page_feature.h
index 79fa8e5..8c981e71 100644
--- a/components/offline_pages/core/offline_page_feature.h
+++ b/components/offline_pages/core/offline_page_feature.h
@@ -24,6 +24,7 @@
 extern const base::Feature kOfflinePagesPrefetchingUIFeature;
 extern const base::Feature kOfflinePagesLimitlessPrefetchingFeature;
 extern const base::Feature kOfflinePagesDescriptivePendingStatusFeature;
+extern const base::Feature kOfflinePagesInDownloadHomeOpenInCctFeature;
 
 // The parameter name used to find the experiment tag for prefetching offline
 // pages.
@@ -81,6 +82,10 @@
 // notifications and Downloads Home.
 bool IsOfflinePagesDescriptivePendingStatusEnabled();
 
+// Controls whether offline pages opened from the Downloads Home should be
+// opened in CCTs instead of new tabs.
+bool ShouldOfflinePagesInDownloadHomeOpenInCct();
+
 // Returns an experiment tag provided by the field trial. This experiment tag
 // will be included in a custom header in all requests sent to Offline Prefetch
 // Server. The server will use this this optional tag to decide how to process
diff --git a/components/offline_pages/core/offline_page_feature_unittest.cc b/components/offline_pages/core/offline_page_feature_unittest.cc
index f3673276..7ac2e7bc 100644
--- a/components/offline_pages/core/offline_page_feature_unittest.cc
+++ b/components/offline_pages/core/offline_page_feature_unittest.cc
@@ -113,4 +113,26 @@
   }
 }
 
+TEST(OfflinePageFeatureTest, OfflinePagesInDownloadHomeOpenInCct) {
+  // Disabled by default.
+  EXPECT_FALSE(offline_pages::ShouldOfflinePagesInDownloadHomeOpenInCct());
+
+  // Check if helper method works correctly when the features is enabled.
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(
+      kOfflinePagesInDownloadHomeOpenInCctFeature);
+  EXPECT_TRUE(offline_pages::ShouldOfflinePagesInDownloadHomeOpenInCct());
+}
+
+TEST(OfflinePageFeatureTest, OfflinePagesDescriptivePendingStatus) {
+  // Disabled by default.
+  EXPECT_FALSE(offline_pages::IsOfflinePagesDescriptivePendingStatusEnabled());
+
+  // Check if helper method works correctly when the features is enabled.
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(
+      kOfflinePagesDescriptivePendingStatusFeature);
+  EXPECT_TRUE(offline_pages::IsOfflinePagesDescriptivePendingStatusEnabled());
+}
+
 }  // namespace offline_pages
diff --git a/components/omnibox/browser/BUILD.gn b/components/omnibox/browser/BUILD.gn
index f232f87..7dec54fc 100644
--- a/components/omnibox/browser/BUILD.gn
+++ b/components/omnibox/browser/BUILD.gn
@@ -20,15 +20,11 @@
   icon_directory = "vector_icons"
 
   icons = [
-    "blank.1x.icon",
     "blank.icon",
-    "calculator.1x.icon",
     "calculator.icon",
-    "extension_app.1x.icon",
     "extension_app.icon",
     "http.icon",
     "keyword_search.icon",
-    "star.1x.icon",
     "star.icon",
     "switch.icon",
     "tab.icon",
diff --git a/components/omnibox/browser/omnibox_field_trial.cc b/components/omnibox/browser/omnibox_field_trial.cc
index 955baf0..b575e02 100644
--- a/components/omnibox/browser/omnibox_field_trial.cc
+++ b/components/omnibox/browser/omnibox_field_trial.cc
@@ -655,9 +655,9 @@
     return EMPHASIZE_WHEN_NONEMPTY;
   }
 
-  // Touch devices also always swap title and URL.
+  // Touch-optimized UI and MD Refresh also always swap title and URL.
   if (ui::MaterialDesignController::is_mode_initialized() &&
-      ui::MaterialDesignController::IsTouchOptimizedUiEnabled()) {
+      ui::MaterialDesignController::IsNewerMaterialUi()) {
     return EMPHASIZE_WHEN_NONEMPTY;
   }
 
diff --git a/components/omnibox/browser/vector_icons/blank.1x.icon b/components/omnibox/browser/vector_icons/blank.1x.icon
deleted file mode 100644
index 27913f6c..0000000
--- a/components/omnibox/browser/vector_icons/blank.1x.icon
+++ /dev/null
@@ -1,5 +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.
-
-CANVAS_DIMENSIONS, 16
diff --git a/components/omnibox/browser/vector_icons/blank.icon b/components/omnibox/browser/vector_icons/blank.icon
index 521d94a..6f97ad4 100644
--- a/components/omnibox/browser/vector_icons/blank.icon
+++ b/components/omnibox/browser/vector_icons/blank.icon
@@ -3,3 +3,5 @@
 // found in the LICENSE file.
 
 CANVAS_DIMENSIONS, 32
+
+CANVAS_DIMENSIONS, 16
diff --git a/components/omnibox/browser/vector_icons/calculator.1x.icon b/components/omnibox/browser/vector_icons/calculator.1x.icon
deleted file mode 100644
index 4ddd046..0000000
--- a/components/omnibox/browser/vector_icons/calculator.1x.icon
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 4, 5,
-LINE_TO, 12, 5,
-LINE_TO, 12, 7,
-LINE_TO, 4, 7,
-LINE_TO, 4, 5,
-LINE_TO, 4, 5,
-CLOSE,
-MOVE_TO, 4, 9,
-LINE_TO, 12, 9,
-LINE_TO, 12, 11,
-LINE_TO, 4, 11,
-LINE_TO, 4, 9,
-LINE_TO, 4, 9,
-CLOSE
diff --git a/components/omnibox/browser/vector_icons/calculator.icon b/components/omnibox/browser/vector_icons/calculator.icon
index da2e2f4..76a09fc 100644
--- a/components/omnibox/browser/vector_icons/calculator.icon
+++ b/components/omnibox/browser/vector_icons/calculator.icon
@@ -17,3 +17,19 @@
 LINE_TO, 8, 18,
 LINE_TO, 8, 18,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 4, 5,
+LINE_TO, 12, 5,
+LINE_TO, 12, 7,
+LINE_TO, 4, 7,
+LINE_TO, 4, 5,
+LINE_TO, 4, 5,
+CLOSE,
+MOVE_TO, 4, 9,
+LINE_TO, 12, 9,
+LINE_TO, 12, 11,
+LINE_TO, 4, 11,
+LINE_TO, 4, 9,
+LINE_TO, 4, 9,
+CLOSE
diff --git a/components/omnibox/browser/vector_icons/extension_app.1x.icon b/components/omnibox/browser/vector_icons/extension_app.1x.icon
deleted file mode 100644
index d2079f6..0000000
--- a/components/omnibox/browser/vector_icons/extension_app.1x.icon
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 12.71f, 6.71f,
-LINE_TO, 12.71f, 4.43f,
-CUBIC_TO, 12.71f, 3.8f, 12.2f, 3.29f, 11.57f, 3.29f,
-LINE_TO, 9.29f, 3.29f,
-LINE_TO, 9.29f, 2.43f,
-CUBIC_TO, 9.29f, 1.64f, 8.65f, 1, 7.86f, 1,
-CUBIC_TO, 7.07f, 1, 6.43f, 1.64f, 6.43f, 2.43f,
-LINE_TO, 6.43f, 3.29f,
-LINE_TO, 4.14f, 3.29f,
-CUBIC_TO, 3.51f, 3.29f, 3.01f, 3.8f, 3.01f, 4.43f,
-LINE_TO, 3.01f, 6.6f,
-LINE_TO, 3.86f, 6.6f,
-CUBIC_TO, 4.71f, 6.6f, 5.4f, 7.29f, 5.4f, 8.14f,
-CUBIC_TO, 5.4f, 8.99f, 4.71f, 9.69f, 3.86f, 9.69f,
-LINE_TO, 3, 9.69f,
-LINE_TO, 3, 11.86f,
-CUBIC_TO, 3, 12.49f, 3.51f, 13, 4.14f, 13,
-LINE_TO, 6.31f, 13,
-LINE_TO, 6.31f, 12.14f,
-CUBIC_TO, 6.31f, 11.29f, 7.01f, 10.6f, 7.86f, 10.6f,
-CUBIC_TO, 8.71f, 10.6f, 9.4f, 11.29f, 9.4f, 12.14f,
-LINE_TO, 9.4f, 13,
-LINE_TO, 11.57f, 13,
-CUBIC_TO, 12.2f, 13, 12.71f, 12.49f, 12.71f, 11.86f,
-LINE_TO, 12.71f, 9.57f,
-LINE_TO, 13.57f, 9.57f,
-CUBIC_TO, 14.36f, 9.57f, 15, 8.93f, 15, 8.14f,
-CUBIC_TO, 15, 7.35f, 14.36f, 6.71f, 13.57f, 6.71f,
-LINE_TO, 12.71f, 6.71f,
-CLOSE
diff --git a/components/omnibox/browser/vector_icons/extension_app.icon b/components/omnibox/browser/vector_icons/extension_app.icon
index f3270e8e..56cdc49a 100644
--- a/components/omnibox/browser/vector_icons/extension_app.icon
+++ b/components/omnibox/browser/vector_icons/extension_app.icon
@@ -33,3 +33,35 @@
 CUBIC_TO, 29, 15.5f, 27.72f, 14.43f, 26, 14,
 LINE_TO, 24, 14,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 12.71f, 6.71f,
+LINE_TO, 12.71f, 4.43f,
+CUBIC_TO, 12.71f, 3.8f, 12.2f, 3.29f, 11.57f, 3.29f,
+LINE_TO, 9.29f, 3.29f,
+LINE_TO, 9.29f, 2.43f,
+CUBIC_TO, 9.29f, 1.64f, 8.65f, 1, 7.86f, 1,
+CUBIC_TO, 7.07f, 1, 6.43f, 1.64f, 6.43f, 2.43f,
+LINE_TO, 6.43f, 3.29f,
+LINE_TO, 4.14f, 3.29f,
+CUBIC_TO, 3.51f, 3.29f, 3.01f, 3.8f, 3.01f, 4.43f,
+LINE_TO, 3.01f, 6.6f,
+LINE_TO, 3.86f, 6.6f,
+CUBIC_TO, 4.71f, 6.6f, 5.4f, 7.29f, 5.4f, 8.14f,
+CUBIC_TO, 5.4f, 8.99f, 4.71f, 9.69f, 3.86f, 9.69f,
+LINE_TO, 3, 9.69f,
+LINE_TO, 3, 11.86f,
+CUBIC_TO, 3, 12.49f, 3.51f, 13, 4.14f, 13,
+LINE_TO, 6.31f, 13,
+LINE_TO, 6.31f, 12.14f,
+CUBIC_TO, 6.31f, 11.29f, 7.01f, 10.6f, 7.86f, 10.6f,
+CUBIC_TO, 8.71f, 10.6f, 9.4f, 11.29f, 9.4f, 12.14f,
+LINE_TO, 9.4f, 13,
+LINE_TO, 11.57f, 13,
+CUBIC_TO, 12.2f, 13, 12.71f, 12.49f, 12.71f, 11.86f,
+LINE_TO, 12.71f, 9.57f,
+LINE_TO, 13.57f, 9.57f,
+CUBIC_TO, 14.36f, 9.57f, 15, 8.93f, 15, 8.14f,
+CUBIC_TO, 15, 7.35f, 14.36f, 6.71f, 13.57f, 6.71f,
+LINE_TO, 12.71f, 6.71f,
+CLOSE
diff --git a/components/omnibox/browser/vector_icons/star.1x.icon b/components/omnibox/browser/vector_icons/star.1x.icon
deleted file mode 100644
index a3dab5a..0000000
--- a/components/omnibox/browser/vector_icons/star.1x.icon
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 6.31f, 6.19f,
-LINE_TO, 2, 6.58f,
-LINE_TO, 5.27f, 9.56f,
-LINE_TO, 4.29f, 14,
-LINE_TO, 8, 11.65f,
-LINE_TO, 11.71f, 14,
-LINE_TO, 10.73f, 9.56f,
-LINE_TO, 14, 6.58f,
-LINE_TO, 9.69f, 6.19f,
-LINE_TO, 8, 2,
-LINE_TO, 6.31f, 6.19f,
-CLOSE
diff --git a/components/omnibox/browser/vector_icons/star.icon b/components/omnibox/browser/vector_icons/star.icon
index f1d4ff5..c5f7224e 100644
--- a/components/omnibox/browser/vector_icons/star.icon
+++ b/components/omnibox/browser/vector_icons/star.icon
@@ -15,3 +15,17 @@
 LINE_TO, 16.5f, 5,
 LINE_TO, 13.27f, 12.67f,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 6.31f, 6.19f,
+LINE_TO, 2, 6.58f,
+LINE_TO, 5.27f, 9.56f,
+LINE_TO, 4.29f, 14,
+LINE_TO, 8, 11.65f,
+LINE_TO, 11.71f, 14,
+LINE_TO, 10.73f, 9.56f,
+LINE_TO, 14, 6.58f,
+LINE_TO, 9.69f, 6.19f,
+LINE_TO, 8, 2,
+LINE_TO, 6.31f, 6.19f,
+CLOSE
diff --git a/components/omnibox/browser/vector_icons/switch.icon b/components/omnibox/browser/vector_icons/switch.icon
index e4c82d1..ace88749 100644
--- a/components/omnibox/browser/vector_icons/switch.icon
+++ b/components/omnibox/browser/vector_icons/switch.icon
@@ -3,16 +3,16 @@
 // found in the LICENSE file.
 
 CANVAS_DIMENSIONS, 32,
-MOVE_TO, 4, 6,
-LINE_TO, 26, 6,
-LINE_TO, 26, 24,
-LINE_TO, 4, 24,
-LINE_TO, 4, 8,
-LINE_TO, 5, 8,
-LINE_TO, 5, 23,
-LINE_TO, 25, 23,
-LINE_TO, 25, 13,
-LINE_TO, 16, 13,
-LINE_TO, 16, 7,
-LINE_TO, 4, 7,
+MOVE_TO, 4, 8,
+LINE_TO, 26, 8,
+LINE_TO, 26, 26,
+LINE_TO, 4, 26,
+LINE_TO, 4, 10,
+LINE_TO, 5, 10,
+LINE_TO, 5, 25,
+LINE_TO, 25, 25,
+LINE_TO, 25, 15,
+LINE_TO, 16, 15,
+LINE_TO, 16, 9,
+LINE_TO, 4, 9,
 CLOSE
diff --git a/components/page_info_strings.grdp b/components/page_info_strings.grdp
index e7f28d6..b3b34f1 100644
--- a/components/page_info_strings.grdp
+++ b/components/page_info_strings.grdp
@@ -368,11 +368,17 @@
         <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS" desc="A short paragraph explaining to the user that they has reuse their google password on current website.">
           You could lose access to your Google Account or experience identity theft. Chrome recommends changing your password now.
         </message>
+        <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_ENTERPRISE" desc="A short paragraph explaining to the user that they have reused their password on the current website.">
+          You could lose access to your <ph name="ORG_NAME">$1<ex>Google</ex></ph> account or experience identity theft. Chrome recommends changing your password now.
+        </message>
       </if>
       <if expr="not _google_chrome">
         <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS" desc="A short paragraph explaining to the user that they has reuse their google password on current website.">
           You could lose access to your Google Account or experience identity theft. Chromium recommends changing your password now.
         </message>
+        <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_ENTERPRISE" desc="A short paragraph explaining to the user that they have reused their password on the current website.">
+          You could lose access to your <ph name="ORG_NAME">$1<ex>Google</ex></ph> account or experience identity theft. Chromium recommends changing your password now.
+        </message>
       </if>
 
       <if expr="use_titlecase">
diff --git a/components/payments/content/service_worker_payment_instrument_unittest.cc b/components/payments/content/service_worker_payment_instrument_unittest.cc
index 8139d58e..ac0c15f 100644
--- a/components/payments/content/service_worker_payment_instrument_unittest.cc
+++ b/components/payments/content/service_worker_payment_instrument_unittest.cc
@@ -11,6 +11,7 @@
 #include "components/payments/core/payment_request_delegate.h"
 #include "content/public/browser/stored_payment_app.h"
 #include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/WebKit/public/platform/modules/payments/payment_request.mojom.h"
@@ -157,6 +158,7 @@
 
  private:
   MockPaymentRequestDelegate delegate_;
+  content::TestBrowserThreadBundle thread_bundle_;
   content::TestBrowserContext browser_context_;
 
   std::unique_ptr<PaymentRequestSpec> spec_;
diff --git a/components/payments/content/utility/payment_method_manifest_parser_fuzzer.cc b/components/payments/content/utility/payment_method_manifest_parser_fuzzer.cc
index c3b6d35b..4bc4053a 100644
--- a/components/payments/content/utility/payment_method_manifest_parser_fuzzer.cc
+++ b/components/payments/content/utility/payment_method_manifest_parser_fuzzer.cc
@@ -31,7 +31,7 @@
   std::vector<url::Origin> supported_origins;
   bool all_origins_supported;
 
-  std::string json_data(reinterpret_cast<const char*>(data), size);
+  base::StringPiece json_data(reinterpret_cast<const char*>(data), size);
   std::unique_ptr<base::Value> value = base::JSONReader::Read(json_data);
 
   payments::PaymentManifestParser::ParsePaymentMethodManifestIntoVectors(
diff --git a/components/pdf/DEPS b/components/pdf/DEPS
index 4cc7efa..ffe2e8c 100644
--- a/components/pdf/DEPS
+++ b/components/pdf/DEPS
@@ -1,5 +1,6 @@
 include_rules = [
   "+content/public/common",
+  "+content/public/test",
   "+ipc",
   "+ui/gfx",
 ]
diff --git a/components/pdf/renderer/DEPS b/components/pdf/renderer/DEPS
index fc10b69..127a486f 100644
--- a/components/pdf/renderer/DEPS
+++ b/components/pdf/renderer/DEPS
@@ -1,5 +1,6 @@
 include_rules = [
   "+content/public/renderer",
+  "+content/public/test",
   "+components/strings/grit/components_strings.h",
   "+mojo/public/cpp/bindings",
   "+ppapi",
diff --git a/components/physical_web/webui/physical_web_base_message_handler.h b/components/physical_web/webui/physical_web_base_message_handler.h
index 21b07cd..0aa2d81 100644
--- a/components/physical_web/webui/physical_web_base_message_handler.h
+++ b/components/physical_web/webui/physical_web_base_message_handler.h
@@ -22,7 +22,7 @@
 namespace physical_web_ui {
 
 // This is the equivalent of content::WebUI::MessageCallback.
-typedef base::Callback<void(const base::ListValue*)> MessageCallback;
+using MessageCallback = base::RepeatingCallback<void(const base::ListValue*)>;
 
 // The base handler for Javascript messages for the chrome://physical-web page.
 // This does not implement WebUIMessageHandler or register its methods.
diff --git a/components/printing/browser/BUILD.gn b/components/printing/browser/BUILD.gn
index 6371ce7..d7e30dd 100644
--- a/components/printing/browser/BUILD.gn
+++ b/components/printing/browser/BUILD.gn
@@ -4,6 +4,8 @@
 
 static_library("browser") {
   sources = [
+    "features.cc",
+    "features.h",
     "print_composite_client.cc",
     "print_composite_client.h",
     "print_manager.cc",
diff --git a/components/printing/browser/features.cc b/components/printing/browser/features.cc
new file mode 100644
index 0000000..cca95f2
--- /dev/null
+++ b/components/printing/browser/features.cc
@@ -0,0 +1,14 @@
+// Copyright 2018 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/printing/browser/features.h"
+
+namespace printing {
+namespace features {
+
+const base::Feature kUsePdfCompositorServiceForPrint{
+    "UsePdfCompositorServiceForPrint", base::FEATURE_DISABLED_BY_DEFAULT};
+
+}  // namespace features
+}  // namespace printing
diff --git a/components/printing/browser/features.h b/components/printing/browser/features.h
new file mode 100644
index 0000000..1d18c2f
--- /dev/null
+++ b/components/printing/browser/features.h
@@ -0,0 +1,19 @@
+// Copyright 2018 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_PRINTING_BROWSER_FEATURES_H_
+#define COMPONENTS_PRINTING_BROWSER_FEATURES_H_
+
+#include "base/feature_list.h"
+
+namespace printing {
+namespace features {
+
+// Use pdf compositor service to generate PDF files for printing.
+extern const base::Feature kUsePdfCompositorServiceForPrint;
+
+}  // namespace features
+}  // namespace printing
+
+#endif  // COMPONENTS_PRINTING_BROWSER_FEATURES_H_
diff --git a/components/printing/browser/print_manager_utils.cc b/components/printing/browser/print_manager_utils.cc
index 6f2e7ab2..1257c7a 100644
--- a/components/printing/browser/print_manager_utils.cc
+++ b/components/printing/browser/print_manager_utils.cc
@@ -5,8 +5,10 @@
 #include "components/printing/browser/print_manager_utils.h"
 
 #include "base/command_line.h"
+#include "components/printing/browser/features.h"
 #include "components/printing/browser/print_composite_client.h"
 #include "components/printing/common/print_messages.h"
+#include "content/public/browser/content_browser_client.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
 #include "printing/print_settings.h"
@@ -32,15 +34,27 @@
   // where OOPIF is used such as isolate-extensions, but should be good for
   // feature testing purpose. Eventually, we will remove this check and use pdf
   // compositor service by default for printing.
+
+  bool is_auxiliary_site_isolation_enabled;
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kSitePerProcess) ||
-      base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kIsolateOrigins) ||
-      ((base::FeatureList::IsEnabled(features::kSitePerProcess) ||
-        base::FeatureList::IsEnabled(features::kIsolateOrigins)) &&
-       !base::CommandLine::ForCurrentProcess()->HasSwitch(
-           switches::kDisableSiteIsolationTrials)) ||
-      base::FeatureList::IsEnabled(features::kTopDocumentIsolation)) {
+          switches::kIsolateOrigins)) {
+    is_auxiliary_site_isolation_enabled = true;
+  } else if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+                 switches::kDisableSiteIsolationTrials)) {
+    is_auxiliary_site_isolation_enabled = false;
+  } else {
+    // The features need to be checked last, because checking a feature
+    // activates the field trial and assigns the client either to a control or
+    // an experiment group.
+    is_auxiliary_site_isolation_enabled =
+        base::FeatureList::IsEnabled(::features::kIsolateOrigins) ||
+        base::FeatureList::IsEnabled(::features::kTopDocumentIsolation);
+  }
+
+  if (is_auxiliary_site_isolation_enabled ||
+      content::ContentBrowserClient::IsStrictSiteIsolationEnabled() ||
+      base::FeatureList::IsEnabled(
+          printing::features::kUsePdfCompositorServiceForPrint)) {
     PrintCompositeClient::CreateForWebContents(web_contents);
     SetOopifEnabled();
   }
diff --git a/components/printing/service/public/cpp/pdf_service_mojo_utils.cc b/components/printing/service/public/cpp/pdf_service_mojo_utils.cc
index 8e129e1a..b2224c80 100644
--- a/components/printing/service/public/cpp/pdf_service_mojo_utils.cc
+++ b/components/printing/service/public/cpp/pdf_service_mojo_utils.cc
@@ -4,6 +4,8 @@
 
 #include "components/printing/service/public/cpp/pdf_service_mojo_utils.h"
 
+#include <utility>
+
 #include "base/memory/ref_counted_memory.h"
 #include "base/memory/shared_memory.h"
 #include "mojo/public/cpp/system/platform_handle.h"
@@ -20,8 +22,8 @@
       std::move(handle), &memory_handle, &memory_size, &protection);
   if (result != MOJO_RESULT_OK)
     return nullptr;
-  DCHECK_GT(memory_size, 0u);
 
+  DCHECK_GT(memory_size, 0u);
   const bool read_only =
       protection == mojo::UnwrappedSharedMemoryHandleProtection::kReadOnly;
   std::unique_ptr<base::SharedMemory> shm =
@@ -33,7 +35,7 @@
   return shm;
 }
 
-scoped_refptr<base::RefCountedBytes> GetDataFromMojoHandle(
+scoped_refptr<base::RefCountedMemory> GetDataFromMojoHandle(
     mojo::ScopedSharedBufferHandle handle) {
   std::unique_ptr<base::SharedMemory> shm =
       GetShmFromMojoHandle(std::move(handle));
diff --git a/components/printing/service/public/cpp/pdf_service_mojo_utils.h b/components/printing/service/public/cpp/pdf_service_mojo_utils.h
index 11a2ebe..d7b5547 100644
--- a/components/printing/service/public/cpp/pdf_service_mojo_utils.h
+++ b/components/printing/service/public/cpp/pdf_service_mojo_utils.h
@@ -11,7 +11,7 @@
 #include "mojo/public/cpp/system/buffer.h"
 
 namespace base {
-class RefCountedBytes;
+class RefCountedMemory;
 class SharedMemory;
 }  // namespace base
 
@@ -20,7 +20,7 @@
 std::unique_ptr<base::SharedMemory> GetShmFromMojoHandle(
     mojo::ScopedSharedBufferHandle handle);
 
-scoped_refptr<base::RefCountedBytes> GetDataFromMojoHandle(
+scoped_refptr<base::RefCountedMemory> GetDataFromMojoHandle(
     mojo::ScopedSharedBufferHandle handle);
 
 }  // namespace printing
diff --git a/components/proximity_auth/webui/proximity_auth_webui_handler.cc b/components/proximity_auth/webui/proximity_auth_webui_handler.cc
index 6581fb66..50b8d427 100644
--- a/components/proximity_auth/webui/proximity_auth_webui_handler.cc
+++ b/components/proximity_auth/webui/proximity_auth_webui_handler.cc
@@ -125,47 +125,53 @@
 void ProximityAuthWebUIHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "onWebContentsInitialized",
-      base::Bind(&ProximityAuthWebUIHandler::OnWebContentsInitialized,
-                 base::Unretained(this)));
+      base::BindRepeating(&ProximityAuthWebUIHandler::OnWebContentsInitialized,
+                          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
-      "clearLogBuffer", base::Bind(&ProximityAuthWebUIHandler::ClearLogBuffer,
-                                   base::Unretained(this)));
+      "clearLogBuffer",
+      base::BindRepeating(&ProximityAuthWebUIHandler::ClearLogBuffer,
+                          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
-      "getLogMessages", base::Bind(&ProximityAuthWebUIHandler::GetLogMessages,
-                                   base::Unretained(this)));
+      "getLogMessages",
+      base::BindRepeating(&ProximityAuthWebUIHandler::GetLogMessages,
+                          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
-      "toggleUnlockKey", base::Bind(&ProximityAuthWebUIHandler::ToggleUnlockKey,
-                                    base::Unretained(this)));
+      "toggleUnlockKey",
+      base::BindRepeating(&ProximityAuthWebUIHandler::ToggleUnlockKey,
+                          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       "findEligibleUnlockDevices",
-      base::Bind(&ProximityAuthWebUIHandler::FindEligibleUnlockDevices,
-                 base::Unretained(this)));
+      base::BindRepeating(&ProximityAuthWebUIHandler::FindEligibleUnlockDevices,
+                          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       "findReachableDevices",
-      base::Bind(&ProximityAuthWebUIHandler::FindReachableDevices,
-                 base::Unretained(this)));
+      base::BindRepeating(&ProximityAuthWebUIHandler::FindReachableDevices,
+                          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
-      "getLocalState", base::Bind(&ProximityAuthWebUIHandler::GetLocalState,
-                                  base::Unretained(this)));
+      "getLocalState",
+      base::BindRepeating(&ProximityAuthWebUIHandler::GetLocalState,
+                          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
-      "forceEnrollment", base::Bind(&ProximityAuthWebUIHandler::ForceEnrollment,
-                                    base::Unretained(this)));
+      "forceEnrollment",
+      base::BindRepeating(&ProximityAuthWebUIHandler::ForceEnrollment,
+                          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
-      "forceDeviceSync", base::Bind(&ProximityAuthWebUIHandler::ForceDeviceSync,
-                                    base::Unretained(this)));
+      "forceDeviceSync",
+      base::BindRepeating(&ProximityAuthWebUIHandler::ForceDeviceSync,
+                          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       "toggleConnection",
-      base::Bind(&ProximityAuthWebUIHandler::ToggleConnection,
-                 base::Unretained(this)));
+      base::BindRepeating(&ProximityAuthWebUIHandler::ToggleConnection,
+                          base::Unretained(this)));
 }
 
 void ProximityAuthWebUIHandler::OnLogMessageAdded(
diff --git a/components/reset_password_strings.grdp b/components/reset_password_strings.grdp
new file mode 100644
index 0000000..bd8b3bc
--- /dev/null
+++ b/components/reset_password_strings.grdp
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<grit-part>
+  <message name="IDS_RESET_PASSWORD_WARNING_HEADING" desc="Title of the reset password page.">
+    Reset your password now
+  </message>
+  <message name="IDS_RESET_PASSWORD_HEADING" desc="Title of the reset password page when the user manually navigates to this page.">
+    Reset password?
+  </message>
+  <message name="IDS_RESET_PASSWORD_WARNING_EXPLANATION_PARAGRAPH" desc="The primary explanatory paragraph for the reset password page.">
+    You entered your password on a site that’s not managed by <ph name="ORG_NAME">$1<ex>Google</ex></ph>. To protect your account, don’t reuse your password on other apps and sites.
+  </message>
+  <message name="IDS_RESET_PASSWORD_BUTTON" desc="The text for the button that takes the user to reset their password.">
+    Reset password
+  </message>
+  <if expr="_google_chrome">
+    <message name="IDS_RESET_PASSWORD_EXPLANATION_PARAGRAPH" desc="The primary explanatory paragraph for the reset password page when the user manually navigates to this page.">
+      Chrome recommends resetting your <ph name="ORG_NAME">$1<ex>Google</ex></ph> password if you reused it on other sites.
+    </message>
+  </if>
+  <if expr="not _google_chrome">
+    <message name="IDS_RESET_PASSWORD_EXPLANATION_PARAGRAPH" desc="The primary explanatory paragraph for the reset password page when the user manually navigates to this page.">
+      Chromium recommends resetting your <ph name="ORG_NAME">$1<ex>Google</ex></ph> password if you reused it on other sites.
+    </message>
+  </if>
+</grit-part>
diff --git a/components/rlz/BUILD.gn b/components/rlz/BUILD.gn
index 9514a46..f8434c42 100644
--- a/components/rlz/BUILD.gn
+++ b/components/rlz/BUILD.gn
@@ -37,4 +37,8 @@
     "//rlz:test_support",
     "//ui/base",
   ]
+
+  if (is_chromeos) {
+    deps += [ "//chromeos" ]
+  }
 }
diff --git a/components/rlz/DEPS b/components/rlz/DEPS
index 099cc88..15cc8cc7 100644
--- a/components/rlz/DEPS
+++ b/components/rlz/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
+  "+chromeos/system",
   "+components/google",
   "+net",
   "+rlz",
diff --git a/components/rlz/rlz_tracker_unittest.cc b/components/rlz/rlz_tracker_unittest.cc
index d1fefe7c..0ed70ac 100644
--- a/components/rlz/rlz_tracker_unittest.cc
+++ b/components/rlz/rlz_tracker_unittest.cc
@@ -24,6 +24,10 @@
 #include "ui/base/device_form_factor.h"
 #endif
 
+#if defined(OS_CHROMEOS)
+#include "chromeos/system/fake_statistics_provider.h"
+#endif
+
 using testing::AssertionResult;
 using testing::AssertionSuccess;
 using testing::AssertionFailure;
@@ -255,6 +259,11 @@
   TestRLZTrackerDelegate* delegate_;
   std::unique_ptr<TestRLZTracker> tracker_;
   RlzLibTestNoMachineStateHelper m_rlz_test_helper_;
+
+#if defined(OS_CHROMEOS)
+  std::unique_ptr<chromeos::system::FakeStatisticsProvider>
+      statistics_provider_;
+#endif
 };
 
 void RlzLibTest::SetUp() {
@@ -269,6 +278,13 @@
   // is pretty much a no-op.
   SetMainBrand("TEST");
   SetReactivationBrand("");
+
+#if defined(OS_CHROMEOS)
+  statistics_provider_ =
+      std::make_unique<chromeos::system::FakeStatisticsProvider>();
+  chromeos::system::StatisticsProvider::SetTestProvider(
+      statistics_provider_.get());
+#endif  // defined(OS_CHROMEOS)
 }
 
 void RlzLibTest::TearDown() {
@@ -276,6 +292,10 @@
   tracker_.reset();
   testing::Test::TearDown();
   m_rlz_test_helper_.TearDown();
+
+#if defined(OS_CHROMEOS)
+  chromeos::system::StatisticsProvider::SetTestProvider(nullptr);
+#endif  // defined(OS_CHROMEOS)
 }
 
 void RlzLibTest::SetMainBrand(const char* brand) {
diff --git a/components/safe_browsing/web_ui/safe_browsing_ui.cc b/components/safe_browsing/web_ui/safe_browsing_ui.cc
index 11a4bd4..6dfff9f 100644
--- a/components/safe_browsing/web_ui/safe_browsing_ui.cc
+++ b/components/safe_browsing/web_ui/safe_browsing_ui.cc
@@ -384,19 +384,20 @@
 
 void SafeBrowsingUIHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
-      "getExperiments", base::Bind(&SafeBrowsingUIHandler::GetExperiments,
-                                   base::Unretained(this)));
+      "getExperiments",
+      base::BindRepeating(&SafeBrowsingUIHandler::GetExperiments,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "getPrefs",
-      base::Bind(&SafeBrowsingUIHandler::GetPrefs, base::Unretained(this)));
+      "getPrefs", base::BindRepeating(&SafeBrowsingUIHandler::GetPrefs,
+                                      base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "getDatabaseManagerInfo",
-      base::Bind(&SafeBrowsingUIHandler::GetDatabaseManagerInfo,
-                 base::Unretained(this)));
+      base::BindRepeating(&SafeBrowsingUIHandler::GetDatabaseManagerInfo,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "getSentThreatDetails",
-      base::Bind(&SafeBrowsingUIHandler::GetSentThreatDetails,
-                 base::Unretained(this)));
+      base::BindRepeating(&SafeBrowsingUIHandler::GetSentThreatDetails,
+                          base::Unretained(this)));
 }
 
 }  // namespace safe_browsing
diff --git a/components/security_interstitials/content/resources/connection_help.css b/components/security_interstitials/content/resources/connection_help.css
index f963ca4..832e2f8 100644
--- a/components/security_interstitials/content/resources/connection_help.css
+++ b/components/security_interstitials/content/resources/connection_help.css
@@ -23,3 +23,7 @@
     text-decoration: underline;
     text-transform: uppercase;
 }
+
+ul.expandable button:hover {
+  box-shadow: none;
+}
diff --git a/components/security_interstitials_strings.grdp b/components/security_interstitials_strings.grdp
index 4f4752dc..bcfe4f3 100644
--- a/components/security_interstitials_strings.grdp
+++ b/components/security_interstitials_strings.grdp
@@ -279,7 +279,7 @@
   <message name="IDS_PHISHING_V4_HEADING" desc="The large heading at the top of the phishing interstitial.">
     Deceptive site ahead
   </message>
-  <message name="IDS_PHISHING_V4_PRIMARY_PARAGRAPH" desc="The primary explanatory paragraph for the malware interstitial.">
+  <message name="IDS_PHISHING_V4_PRIMARY_PARAGRAPH" desc="The primary explanatory paragraph for the phishing interstitial.">
     Attackers on <ph name="BEGIN_BOLD">&lt;strong&gt;</ph><ph name="SITE">$1<ex>example.com</ex></ph><ph name="END_BOLD">&lt;/strong&gt;</ph> may trick you into doing something dangerous like installing software or revealing your personal information (for example, passwords, phone numbers, or credit cards). <ph name="BEGIN_LEARN_MORE_LINK">&lt;a href="#" id="learn-more-link"&gt;</ph>Learn more<ph name="END_LEARN_MORE_LINK">&lt;/a&gt;</ph>
   </message>
   <message name="IDS_PHISHING_V4_EXPLANATION_PARAGRAPH" desc="The explanation of why Safe Browsing has blocked the page.">
diff --git a/components/services/leveldb/public/interfaces/BUILD.gn b/components/services/leveldb/public/interfaces/BUILD.gn
index 4e519e6..f7212314 100644
--- a/components/services/leveldb/public/interfaces/BUILD.gn
+++ b/components/services/leveldb/public/interfaces/BUILD.gn
@@ -17,5 +17,6 @@
 
   public_deps = [
     "//mojo/common:common_custom_types",
+    "//mojo/public/mojom/base",
   ]
 }
diff --git a/components/services/leveldb/public/interfaces/leveldb.mojom b/components/services/leveldb/public/interfaces/leveldb.mojom
index a4144f600..8e636af 100644
--- a/components/services/leveldb/public/interfaces/leveldb.mojom
+++ b/components/services/leveldb/public/interfaces/leveldb.mojom
@@ -5,8 +5,8 @@
 module leveldb.mojom;
 
 import "components/services/filesystem/public/interfaces/directory.mojom";
-import "mojo/common/unguessable_token.mojom";
 import "mojo/common/memory_allocator_dump_cross_process_uid.mojom";
+import "mojo/public/mojom/base/unguessable_token.mojom";
 
 enum DatabaseError {
   OK,
@@ -136,48 +136,48 @@
   // Snapshots -------------------------------------------------------------
 
   // Returns a handle to the current database state.
-  GetSnapshot() => (mojo.common.mojom.UnguessableToken snapshot);
+  GetSnapshot() => (mojo_base.mojom.UnguessableToken snapshot);
 
   // Releases a previously acquired snapshot.
-  ReleaseSnapshot(mojo.common.mojom.UnguessableToken snapshot);
+  ReleaseSnapshot(mojo_base.mojom.UnguessableToken snapshot);
 
   // If |key| exists at the time |snapshot_id| was taken, return OK and the
   // value. Otherwise return NOT_FOUND.
-  GetFromSnapshot(mojo.common.mojom.UnguessableToken snapshot,
+  GetFromSnapshot(mojo_base.mojom.UnguessableToken snapshot,
                   array<uint8> key)
       => (DatabaseError status, array<uint8> value);
 
   // Iteartors -------------------------------------------------------------
 
   // Creates an iterator, either from the current view or from a snapshot.
-  NewIterator() => (mojo.common.mojom.UnguessableToken iterator);
-  NewIteratorFromSnapshot(mojo.common.mojom.UnguessableToken snapshot)
-      => (mojo.common.mojom.UnguessableToken? iterator);
+  NewIterator() => (mojo_base.mojom.UnguessableToken iterator);
+  NewIteratorFromSnapshot(mojo_base.mojom.UnguessableToken snapshot)
+      => (mojo_base.mojom.UnguessableToken? iterator);
 
-  ReleaseIterator(mojo.common.mojom.UnguessableToken iterator);
+  ReleaseIterator(mojo_base.mojom.UnguessableToken iterator);
 
   // Positions the iterator at the first key, last key, or the first key after
   // |target|.
   [Sync]
-  IteratorSeekToFirst(mojo.common.mojom.UnguessableToken iterator)
+  IteratorSeekToFirst(mojo_base.mojom.UnguessableToken iterator)
       => (bool valid, DatabaseError status, array<uint8>? key,
           array<uint8>? value);
   [Sync]
-  IteratorSeekToLast(mojo.common.mojom.UnguessableToken iterator)
+  IteratorSeekToLast(mojo_base.mojom.UnguessableToken iterator)
       => (bool valid, DatabaseError status, array<uint8>? key,
           array<uint8>? value);
   [Sync]
-  IteratorSeek(mojo.common.mojom.UnguessableToken iterator, array<uint8> target)
+  IteratorSeek(mojo_base.mojom.UnguessableToken iterator, array<uint8> target)
       => (bool valid, DatabaseError status, array<uint8>? key,
           array<uint8>? value);
 
   // Moves forward or backwards in iterator space.
   [Sync]
-  IteratorNext(mojo.common.mojom.UnguessableToken iterator)
+  IteratorNext(mojo_base.mojom.UnguessableToken iterator)
       => (bool valid, DatabaseError status, array<uint8>? key,
           array<uint8>? value);
   [Sync]
-  IteratorPrev(mojo.common.mojom.UnguessableToken iterator)
+  IteratorPrev(mojo_base.mojom.UnguessableToken iterator)
       => (bool valid, DatabaseError status, array<uint8>? key,
           array<uint8>? value);
 };
diff --git a/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.cc b/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.cc
index a31197e..a2719da 100644
--- a/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.cc
+++ b/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.cc
@@ -62,8 +62,6 @@
         VerifiedRuleset::Handle* ruleset_handle,
         const ActivationState& page_activation_state) {
   DCHECK(navigation_handle()->IsInMainFrame());
-  DCHECK(!parent_activation_state_);
-  DCHECK(!ruleset_handle_);
   DCHECK_NE(ActivationLevel::DISABLED, page_activation_state.activation_level);
   parent_activation_state_ = page_activation_state;
   ruleset_handle_ = ruleset_handle;
@@ -71,14 +69,14 @@
 
 content::NavigationThrottle::ThrottleCheckResult
 ActivationStateComputingNavigationThrottle::WillStartRequest() {
-  if (!navigation_handle()->IsInMainFrame())
+  if (parent_activation_state_)
     CheckActivationState();
   return content::NavigationThrottle::PROCEED;
 }
 
 content::NavigationThrottle::ThrottleCheckResult
 ActivationStateComputingNavigationThrottle::WillRedirectRequest() {
-  if (!navigation_handle()->IsInMainFrame())
+  if (parent_activation_state_)
     CheckActivationState();
   return content::NavigationThrottle::PROCEED;
 }
@@ -100,6 +98,8 @@
   // check.
   if (async_filter_ && async_filter_->has_activation_state()) {
     LogDelayMetrics(base::TimeDelta::FromMilliseconds(0));
+    if (navigation_handle()->IsInMainFrame())
+      UpdateWithMoreAccurateState();
     return content::NavigationThrottle::PROCEED;
   }
   DCHECK(!defer_timer_);
@@ -142,10 +142,22 @@
     ActivationState state) {
   if (defer_timer_) {
     LogDelayMetrics(defer_timer_->Elapsed());
+    if (navigation_handle()->IsInMainFrame())
+      UpdateWithMoreAccurateState();
     Resume();
   }
 }
 
+void ActivationStateComputingNavigationThrottle::UpdateWithMoreAccurateState() {
+  // This method is only needed for main frame navigations that are notified of
+  // page activation more than once. Even for those that are updated once, it
+  // should be a no-op.
+  DCHECK(navigation_handle()->IsInMainFrame());
+  DCHECK(parent_activation_state_);
+  DCHECK(async_filter_);
+  async_filter_->UpdateWithMoreAccurateState(*parent_activation_state_);
+}
+
 void ActivationStateComputingNavigationThrottle::LogDelayMetrics(
     base::TimeDelta delay) const {
   UMA_HISTOGRAM_CUSTOM_MICRO_TIMES(
diff --git a/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.h b/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.h
index 20e01345..98a08e1 100644
--- a/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.h
+++ b/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.h
@@ -30,8 +30,9 @@
 //
 // Note: for performance, activation computation for subframes is done
 // speculatively at navigation start and at every redirect. This is to reduce
-// the wait time (most likely to 0) by WillProcessResponse time.
-// TODO(crbug.com/809504): Implement speculation for main frames as well.
+// the wait time (most likely to 0) by WillProcessResponse time. For main
+// frames, speculation will be done at the next navigation stage after
+// NotifyPageActivationWithRuleset is called.
 class ActivationStateComputingNavigationThrottle
     : public content::NavigationThrottle {
  public:
@@ -58,6 +59,10 @@
   // navigation for main frames.
   //
   // Should never be called with DISABLED activation.
+  //
+  // Note: can be called multiple times, at any point in the navigation to
+  // update the page state. |page_activation_state| will be merged into any
+  // previously computed activation state.
   void NotifyPageActivationWithRuleset(
       VerifiedRuleset::Handle* ruleset_handle,
       const ActivationState& page_activation_state);
@@ -89,6 +94,13 @@
   void CheckActivationState();
   void OnActivationStateComputed(ActivationState state);
 
+  // In the case when main frame navigations get notified of ActivationState
+  // multiple times, a method is needed for overriding previously computed
+  // results with a more accurate ActivationState.
+  //
+  // This must be called at the end of the WillProcessResponse stage.
+  void UpdateWithMoreAccurateState();
+
   void LogDelayMetrics(base::TimeDelta delay) const;
 
   ActivationStateComputingNavigationThrottle(
diff --git a/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle_unittest.cc b/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle_unittest.cc
index 36ced49..fa7bf80 100644
--- a/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle_unittest.cc
+++ b/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle_unittest.cc
@@ -34,13 +34,17 @@
 
 namespace proto = url_pattern_index::proto;
 
+// The tests are parameterized by a bool which enables speculative main frame
+// activation computation in DRYRUN mode. In practice, this will correspond to
+// the kAdTagging feature.
 class ActivationStateComputingNavigationThrottleTest
     : public content::RenderViewHostTestHarness,
-      public content::WebContentsObserver {
+      public content::WebContentsObserver,
+      public ::testing::WithParamInterface<bool> {
  public:
   ActivationStateComputingNavigationThrottleTest()
-      : simple_task_runner_(
-            base::MakeRefCounted<base::TestSimpleTaskRunner>()) {}
+      : simple_task_runner_(base::MakeRefCounted<base::TestSimpleTaskRunner>()),
+        dryrun_speculation_(GetParam()) {}
   ~ActivationStateComputingNavigationThrottleTest() override {}
 
   void SetUp() override {
@@ -177,6 +181,10 @@
             : ActivationStateComputingNavigationThrottle::CreateForSubframe(
                   navigation_handle, ruleset_handle_.get(),
                   parent_activation_state_.value());
+    if (navigation_handle->IsInMainFrame() && dryrun_speculation_) {
+      throttle->NotifyPageActivationWithRuleset(
+          ruleset_handle_.get(), ActivationState(ActivationLevel::DRYRUN));
+    }
     test_throttle_ = throttle.get();
     navigation_handle->RegisterThrottleForTesting(std::move(throttle));
   }
@@ -206,6 +214,8 @@
     test_throttle_ = nullptr;
   }
 
+  bool dryrun_speculation() const { return dryrun_speculation_; }
+
  private:
   testing::TestRulesetCreator test_ruleset_creator_;
   testing::TestRulesetPair test_ruleset_pair_;
@@ -225,6 +235,8 @@
   // Needed for potential cross process navigations which swap hosts.
   content::RenderFrameHost* last_committed_frame_host_ = nullptr;
 
+  bool dryrun_speculation_;
+
   DISALLOW_COPY_AND_ASSIGN(ActivationStateComputingNavigationThrottleTest);
 };
 
@@ -233,7 +245,7 @@
 typedef ActivationStateComputingNavigationThrottleTest
     ActivationStateComputingThrottleSubFrameTest;
 
-TEST_F(ActivationStateComputingThrottleMainFrameTest, Activate) {
+TEST_P(ActivationStateComputingThrottleMainFrameTest, Activate) {
   NavigateAndCommitMainFrameWithPageActivationState(
       GURL("http://example.test/"), ActivationState(ActivationLevel::ENABLED));
   ActivationState state = last_activation_state();
@@ -241,7 +253,7 @@
   EXPECT_FALSE(state.filtering_disabled_for_document);
 }
 
-TEST_F(ActivationStateComputingThrottleMainFrameTest,
+TEST_P(ActivationStateComputingThrottleMainFrameTest,
        NoPageActivationNotification_NoActivation) {
   CreateTestNavigationForMainFrame(GURL("http://example.test/"));
   SimulateStartAndExpectToProceed();
@@ -254,7 +266,7 @@
   EXPECT_EQ(ActivationLevel::DISABLED, state.activation_level);
 }
 
-TEST_F(ActivationStateComputingThrottleMainFrameTest,
+TEST_P(ActivationStateComputingThrottleMainFrameTest,
        WhitelistDoesNotApply_CausesActivation) {
   NavigateAndCommitMainFrameWithPageActivationState(
       GURL("http://allow-child-to-be-whitelisted.com/"),
@@ -270,7 +282,7 @@
   EXPECT_EQ(ActivationLevel::ENABLED, state.activation_level);
 }
 
-TEST_F(ActivationStateComputingThrottleMainFrameTest,
+TEST_P(ActivationStateComputingThrottleMainFrameTest,
        Whitelisted_DisablesFiltering) {
   NavigateAndCommitMainFrameWithPageActivationState(
       GURL("http://whitelisted-always.com/"),
@@ -282,7 +294,7 @@
   EXPECT_EQ(ActivationLevel::ENABLED, state.activation_level);
 }
 
-TEST_F(ActivationStateComputingThrottleSubFrameTest, Activate) {
+TEST_P(ActivationStateComputingThrottleSubFrameTest, Activate) {
   NavigateAndCommitMainFrameWithPageActivationState(
       GURL("http://example.test/"), ActivationState(ActivationLevel::ENABLED));
 
@@ -299,7 +311,7 @@
   EXPECT_FALSE(state.generic_blocking_rules_disabled);
 }
 
-TEST_F(ActivationStateComputingThrottleSubFrameTest,
+TEST_P(ActivationStateComputingThrottleSubFrameTest,
        WhitelistDoesNotApply_CausesActivation) {
   NavigateAndCommitMainFrameWithPageActivationState(
       GURL("http://disallows-child-to-be-whitelisted.com/"),
@@ -317,7 +329,7 @@
   EXPECT_FALSE(state.generic_blocking_rules_disabled);
 }
 
-TEST_F(ActivationStateComputingThrottleSubFrameTest,
+TEST_P(ActivationStateComputingThrottleSubFrameTest,
        Whitelisted_DisableDocumentFiltering) {
   NavigateAndCommitMainFrameWithPageActivationState(
       GURL("http://allow-child-to-be-whitelisted.com/"),
@@ -335,7 +347,7 @@
   EXPECT_EQ(ActivationLevel::ENABLED, state.activation_level);
 }
 
-TEST_F(ActivationStateComputingThrottleSubFrameTest,
+TEST_P(ActivationStateComputingThrottleSubFrameTest,
        Whitelisted_DisablesGenericRules) {
   NavigateAndCommitMainFrameWithPageActivationState(
       GURL("http://allow-child-to-be-whitelisted.com/"),
@@ -353,7 +365,7 @@
   EXPECT_EQ(ActivationLevel::ENABLED, state.activation_level);
 }
 
-TEST_F(ActivationStateComputingThrottleSubFrameTest, DryRunIsPropagated) {
+TEST_P(ActivationStateComputingThrottleSubFrameTest, DryRunIsPropagated) {
   NavigateAndCommitMainFrameWithPageActivationState(
       GURL("http://example.test/"), ActivationState(ActivationLevel::DRYRUN));
   EXPECT_EQ(ActivationLevel::DRYRUN, last_activation_state().activation_level);
@@ -371,7 +383,7 @@
   EXPECT_FALSE(state.generic_blocking_rules_disabled);
 }
 
-TEST_F(ActivationStateComputingThrottleSubFrameTest,
+TEST_P(ActivationStateComputingThrottleSubFrameTest,
        DryRunWithLoggingIsPropagated) {
   ActivationState page_state(ActivationLevel::DRYRUN);
   page_state.enable_logging = true;
@@ -393,7 +405,7 @@
   EXPECT_FALSE(state.generic_blocking_rules_disabled);
 }
 
-TEST_F(ActivationStateComputingThrottleSubFrameTest, DisabledStatePropagated) {
+TEST_P(ActivationStateComputingThrottleSubFrameTest, DisabledStatePropagated) {
   NavigateAndCommitMainFrameWithPageActivationState(
       GURL("http://allow-child-to-be-whitelisted.com/"),
       ActivationState(ActivationLevel::ENABLED));
@@ -416,7 +428,7 @@
   EXPECT_FALSE(state.generic_blocking_rules_disabled);
 }
 
-TEST_F(ActivationStateComputingThrottleSubFrameTest, DisabledStatePropagated2) {
+TEST_P(ActivationStateComputingThrottleSubFrameTest, DisabledStatePropagated2) {
   NavigateAndCommitMainFrameWithPageActivationState(
       GURL("http://allow-child-to-be-whitelisted.com/"),
       ActivationState(ActivationLevel::ENABLED));
@@ -443,7 +455,7 @@
   EXPECT_TRUE(state.generic_blocking_rules_disabled);
 }
 
-TEST_F(ActivationStateComputingThrottleSubFrameTest, DelayMetrics) {
+TEST_P(ActivationStateComputingThrottleSubFrameTest, DelayMetrics) {
   base::HistogramTester histogram_tester;
   NavigateAndCommitMainFrameWithPageActivationState(
       GURL("http://example.test/"), ActivationState(ActivationLevel::ENABLED));
@@ -473,49 +485,56 @@
   SimulateCommitAndExpectToProceed();
 
   state = last_activation_state();
-  EXPECT_EQ(ActivationLevel::DISABLED, state.activation_level);
-  histogram_tester.ExpectTotalCount(kActivationDelay, 2);
-  histogram_tester.ExpectTotalCount(kActivationDelayMainFrame, 1);
+  EXPECT_EQ(dryrun_speculation() ? ActivationLevel::DRYRUN
+                                 : ActivationLevel::DISABLED,
+            state.activation_level);
+  int extra_activation = dryrun_speculation() ? 1 : 0;
+  histogram_tester.ExpectTotalCount(kActivationDelay, 2 + extra_activation);
+  histogram_tester.ExpectTotalCount(kActivationDelayMainFrame,
+                                    1 + extra_activation);
 }
 
-TEST_F(ActivationStateComputingThrottleSubFrameTest, SpeculativeSubframes) {
+TEST_P(ActivationStateComputingThrottleSubFrameTest, Speculation) {
   // Use the activation performance metric as a proxy for how many times
   // activation computation occurred.
-  base::HistogramTester histogram_tester;
   const char kActivationCPU[] =
       "SubresourceFilter.DocumentLoad.Activation.CPUDuration";
 
   // Main frames don't do speculative lookups, a navigation commit should only
   // trigger a single ruleset lookup.
+  base::HistogramTester main_histogram_tester;
   CreateTestNavigationForMainFrame(GURL("http://example.test/"));
   SimulateStartAndExpectToProceed();
-  histogram_tester.ExpectTotalCount(kActivationCPU, 0);
+  int main_frame_checks = dryrun_speculation() ? 1 : 0;
+  main_histogram_tester.ExpectTotalCount(kActivationCPU, main_frame_checks);
 
   SimulateRedirectAndExpectToProceed(GURL("http://example.test2/"));
-  histogram_tester.ExpectTotalCount(kActivationCPU, 0);
+  main_frame_checks += dryrun_speculation() ? 1 : 0;
+  main_histogram_tester.ExpectTotalCount(kActivationCPU, main_frame_checks);
 
   NotifyPageActivation(ActivationState(ActivationLevel::ENABLED));
   SimulateCommitAndExpectToProceed();
-  histogram_tester.ExpectTotalCount(kActivationCPU, 1);
+  main_frame_checks += dryrun_speculation() ? 0 : 1;
+  main_histogram_tester.ExpectTotalCount(kActivationCPU, main_frame_checks);
 
+  base::HistogramTester sub_histogram_tester;
   CreateSubframeAndInitTestNavigation(GURL("http://example.test/"),
                                       last_committed_frame_host(),
                                       last_activation_state());
   // For subframes, do a ruleset lookup at the start and every redirect.
   SimulateStartAndExpectToProceed();
-  histogram_tester.ExpectTotalCount(kActivationCPU, 2);
+  sub_histogram_tester.ExpectTotalCount(kActivationCPU, 1);
 
   SimulateRedirectAndExpectToProceed(GURL("http://example.test2/"));
-  histogram_tester.ExpectTotalCount(kActivationCPU, 3);
+  sub_histogram_tester.ExpectTotalCount(kActivationCPU, 2);
 
   // No ruleset lookup required at commit because we've already checked the
   // latest URL.
   SimulateCommitAndExpectToProceed();
-  histogram_tester.ExpectTotalCount(kActivationCPU, 3);
+  sub_histogram_tester.ExpectTotalCount(kActivationCPU, 2);
 }
 
-TEST_F(ActivationStateComputingThrottleSubFrameTest,
-       SpeculativeSubframesWithDelay) {
+TEST_P(ActivationStateComputingThrottleSubFrameTest, SpeculationWithDelay) {
   InitializeRulesetHandles(simple_task_runner());
 
   // TODO(csharrison): Once crbug.com/822275 is resolved, implement this via a
@@ -532,24 +551,27 @@
 
   // Use the activation performance metric as a proxy for how many times
   // activation computation occurred.
-  base::HistogramTester histogram_tester;
+  base::HistogramTester main_histogram_tester;
   const char kActivationCPU[] =
       "SubresourceFilter.DocumentLoad.Activation.CPUDuration";
 
-  // Main frames don't do speculative lookups, a navigation commit should only
-  // trigger a single ruleset lookup.
+  // Main frames will do speculative lookup only in some cases.
   CreateTestNavigationForMainFrame(GURL("http://example.test/"));
   SimulateStartAndExpectToProceed();
-  histogram_tester.ExpectTotalCount(kActivationCPU, 0);
+  main_histogram_tester.ExpectTotalCount(kActivationCPU, 0);
 
   SimulateRedirectAndExpectToProceed(GURL("http://example.test2/"));
-  histogram_tester.ExpectTotalCount(kActivationCPU, 0);
+  main_histogram_tester.ExpectTotalCount(kActivationCPU, 0);
 
   NotifyPageActivation(ActivationState(ActivationLevel::ENABLED));
   post_advance();
   SimulateCommitAndExpectToProceed();
-  histogram_tester.ExpectTotalCount(kActivationCPU, 1);
+  // If speculation was enabled for this test, will do a lookup at start and
+  // redirect.
+  main_histogram_tester.ExpectTotalCount(kActivationCPU,
+                                         dryrun_speculation() ? 2 : 1);
 
+  base::HistogramTester sub_histogram_tester;
   CreateSubframeAndInitTestNavigation(GURL("http://example.test/"),
                                       last_committed_frame_host(),
                                       last_activation_state());
@@ -557,19 +579,26 @@
   // Simulate slow ruleset checks for the subframe, these should not delay the
   // navigation until commit time.
   SimulateStartAndExpectToProceed();
-  histogram_tester.ExpectTotalCount(kActivationCPU, 1);
+  sub_histogram_tester.ExpectTotalCount(kActivationCPU, 0);
 
   // Calling redirect should ensure that the throttle does not receive the
   // results of the check, but the task to actually perform the check will still
   // happen.
   SimulateRedirectAndExpectToProceed(GURL("http://example.test2/"));
-  histogram_tester.ExpectTotalCount(kActivationCPU, 1);
+  sub_histogram_tester.ExpectTotalCount(kActivationCPU, 0);
 
   // Finish the checks dispatched in the start and redirect phase when the
   // navigation is ready to commit.
   post_advance();
   SimulateCommitAndExpectToProceed();
-  histogram_tester.ExpectTotalCount(kActivationCPU, 3);
+  sub_histogram_tester.ExpectTotalCount(kActivationCPU, 2);
 }
 
+INSTANTIATE_TEST_CASE_P(,
+                        ActivationStateComputingNavigationThrottleTest,
+                        ::testing::Values(true, false));
+INSTANTIATE_TEST_CASE_P(,
+                        ActivationStateComputingThrottleSubFrameTest,
+                        ::testing::Values(true, false));
+
 }  // namespace subresource_filter
diff --git a/components/subresource_filter/content/browser/async_document_subresource_filter.cc b/components/subresource_filter/content/browser/async_document_subresource_filter.cc
index 9dd0c275..9601c62 100644
--- a/components/subresource_filter/content/browser/async_document_subresource_filter.cc
+++ b/components/subresource_filter/content/browser/async_document_subresource_filter.cc
@@ -58,6 +58,9 @@
                  url_pattern_index::proto::ACTIVATION_TYPE_GENERICBLOCK)) {
     activation_state.generic_blocking_rules_disabled = true;
   }
+
+  // Careful note: any new state computed for ActivationState in this method
+  // must also update UpdateWithMoreAccurateState..
   return activation_state;
 }
 
@@ -158,6 +161,29 @@
     std::move(first_disallowed_load_callback_).Run();
 }
 
+void AsyncDocumentSubresourceFilter::UpdateWithMoreAccurateState(
+    const ActivationState& updated_page_state) {
+  // DISABLED activation level implies that the ruleset is somehow invalid. Make
+  // sure that we don't update the state in that case.
+  DCHECK(has_activation_state());
+  if (activation_state_->activation_level == ActivationLevel::DISABLED)
+    return;
+
+  // TODO(csharrison): Split ActivationState into multiple structs, with one
+  // that includes members that are inherited from the parent without change,
+  // and one that includes members that need to be computed.
+  bool filtering_disabled = activation_state_->filtering_disabled_for_document;
+  bool generic_disabled = activation_state_->generic_blocking_rules_disabled;
+
+  activation_state_ = updated_page_state;
+  activation_state_->filtering_disabled_for_document = filtering_disabled;
+  activation_state_->generic_blocking_rules_disabled = generic_disabled;
+  task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(&AsyncDocumentSubresourceFilter::Core::SetActivationState,
+                     base::Unretained(core_.get()), *activation_state_));
+}
+
 const ActivationState& AsyncDocumentSubresourceFilter::activation_state()
     const {
   CHECK(activation_state_);
@@ -174,6 +200,12 @@
   DCHECK(sequence_checker_.CalledOnValidSequence());
 }
 
+void AsyncDocumentSubresourceFilter::Core::SetActivationState(
+    const ActivationState& state) {
+  DCHECK(filter_);
+  filter_->set_activation_state(state);
+}
+
 ActivationState AsyncDocumentSubresourceFilter::Core::Initialize(
     InitializationParams params,
     VerifiedRuleset* verified_ruleset) {
diff --git a/components/subresource_filter/content/browser/async_document_subresource_filter.h b/components/subresource_filter/content/browser/async_document_subresource_filter.h
index 749415f..d973c9aa 100644
--- a/components/subresource_filter/content/browser/async_document_subresource_filter.h
+++ b/components/subresource_filter/content/browser/async_document_subresource_filter.h
@@ -116,6 +116,16 @@
   // |task_runner|.
   void ReportDisallowedLoad();
 
+  // Should only be called for main frames. Updates |activation_state_| with the
+  // more accurate |updated_page_state|, but retains ruleset specific properties
+  // like document whitelisting. Must be called after initial activation state
+  // is computed.
+  //
+  // Posts a task to update the state in |core_|, so any calls to
+  // GetLoadPolicyForSubdocument that are called before this will get the old
+  // state.
+  void UpdateWithMoreAccurateState(const ActivationState& updated_page_state);
+
   // Must be called after activation state computation is finished.
   const ActivationState& activation_state() const;
 
@@ -163,6 +173,9 @@
  private:
   friend class AsyncDocumentSubresourceFilter;
 
+  // Updates the ActivationState in |filter_|.
+  void SetActivationState(const ActivationState& state);
+
   // Computes ActivationState from |params| and initializes a DSF using it.
   // Returns the computed activation state.
   ActivationState Initialize(InitializationParams params,
diff --git a/components/subresource_filter/content/browser/async_document_subresource_filter_unittest.cc b/components/subresource_filter/content/browser/async_document_subresource_filter_unittest.cc
index 7d4cb88..58642b7 100644
--- a/components/subresource_filter/content/browser/async_document_subresource_filter_unittest.cc
+++ b/components/subresource_filter/content/browser/async_document_subresource_filter_unittest.cc
@@ -262,6 +262,40 @@
   RunUntilIdle();
 }
 
+TEST_F(AsyncDocumentSubresourceFilterTest, UpdateActivationState) {
+  // Properly initilize the ruleset and handle to use for computations.
+  dealer_handle()->TryOpenAndSetRulesetFile(ruleset().path, base::DoNothing());
+  auto ruleset_handle = CreateRulesetHandle();
+
+  // Initialize |filter| with a starting ActivationLevel of DRYRUN. This value
+  // will be updated later on.
+  AsyncDocumentSubresourceFilter::InitializationParams params(
+      GURL("http://example.com"), ActivationLevel::DRYRUN, false);
+  testing::TestActivationStateCallbackReceiver activation_state;
+  auto filter = std::make_unique<AsyncDocumentSubresourceFilter>(
+      ruleset_handle.get(), std::move(params), activation_state.GetCallback());
+
+  // Make sure the ADSF computes its initial activation before updating it.
+  RunUntilIdle();
+  activation_state.ExpectReceivedOnce(ActivationState(ActivationLevel::DRYRUN));
+
+  // Update the ActivationState before calling GetLoadPolicyForSubdocument.
+  filter->UpdateWithMoreAccurateState(
+      ActivationState(ActivationLevel::ENABLED));
+
+  LoadPolicyCallbackReceiver load_policy_1;
+  filter->GetLoadPolicyForSubdocument(GURL("http://example.com/allowed.html"),
+                                      load_policy_1.GetCallback());
+  RunUntilIdle();
+  load_policy_1.ExpectReceivedOnce(LoadPolicy::ALLOW);
+
+  LoadPolicyCallbackReceiver load_policy_2;
+  filter->GetLoadPolicyForSubdocument(
+      GURL("http://example.com/disallowed.html"), load_policy_2.GetCallback());
+  RunUntilIdle();
+  load_policy_2.ExpectReceivedOnce(LoadPolicy::DISALLOW);
+}
+
 // Tests for ComputeActivationState:
 
 class SubresourceFilterComputeActivationStateTest : public ::testing::Test {
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc
index 1f5ad609..e4de7d3 100644
--- a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc
+++ b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/feature_list.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/stl_util.h"
@@ -20,6 +21,7 @@
 #include "components/subresource_filter/content/common/subresource_filter_messages.h"
 #include "components/subresource_filter/content/common/subresource_filter_utils.h"
 #include "components/subresource_filter/core/browser/subresource_filter_constants.h"
+#include "components/subresource_filter/core/browser/subresource_filter_features.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/navigation_throttle.h"
 #include "content/public/browser/render_frame_host.h"
@@ -285,8 +287,14 @@
         content::NavigationHandle* navigation_handle) {
   // Main frames: create unconditionally.
   if (navigation_handle->IsInMainFrame()) {
-    return ActivationStateComputingNavigationThrottle::CreateForMainFrame(
-        navigation_handle);
+    auto throttle =
+        ActivationStateComputingNavigationThrottle::CreateForMainFrame(
+            navigation_handle);
+    if (base::FeatureList::IsEnabled(kAdTagging)) {
+      throttle->NotifyPageActivationWithRuleset(
+          EnsureRulesetHandle(), ActivationState(ActivationLevel::DRYRUN));
+    }
+    return throttle;
   }
 
   // Subframes: create only for frames with activated parents.
diff --git a/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.cc b/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.cc
index 4ecca054..99f4d74 100644
--- a/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.cc
+++ b/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.cc
@@ -50,12 +50,12 @@
 
 content::NavigationThrottle::ThrottleCheckResult
 SubframeNavigationFilteringThrottle::WillStartRequest() {
-  return DeferToCalculateLoadPolicy(ThrottlingStage::WillStartRequest);
+  return DeferToCalculateLoadPolicy();
 }
 
 content::NavigationThrottle::ThrottleCheckResult
 SubframeNavigationFilteringThrottle::WillRedirectRequest() {
-  return DeferToCalculateLoadPolicy(ThrottlingStage::WillRedirectRequest);
+  return DeferToCalculateLoadPolicy();
 }
 
 content::NavigationThrottle::ThrottleCheckResult
@@ -70,21 +70,19 @@
 }
 
 content::NavigationThrottle::ThrottleCheckResult
-SubframeNavigationFilteringThrottle::DeferToCalculateLoadPolicy(
-    ThrottlingStage stage) {
+SubframeNavigationFilteringThrottle::DeferToCalculateLoadPolicy() {
   DCHECK_NE(load_policy_, LoadPolicy::DISALLOW);
   if (load_policy_ == LoadPolicy::WOULD_DISALLOW)
     return PROCEED;
   parent_frame_filter_->GetLoadPolicyForSubdocument(
       navigation_handle()->GetURL(),
       base::Bind(&SubframeNavigationFilteringThrottle::OnCalculatedLoadPolicy,
-                 weak_ptr_factory_.GetWeakPtr(), stage));
+                 weak_ptr_factory_.GetWeakPtr()));
   last_defer_timestamp_ = base::TimeTicks::Now();
   return DEFER;
 }
 
 void SubframeNavigationFilteringThrottle::OnCalculatedLoadPolicy(
-    ThrottlingStage stage,
     LoadPolicy policy) {
   DCHECK(!last_defer_timestamp_.is_null());
   load_policy_ = policy;
diff --git a/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.h b/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.h
index 74d8921..c79c1daf6 100644
--- a/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.h
+++ b/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.h
@@ -44,11 +44,8 @@
   const char* GetNameForLogging() override;
 
  private:
-  enum class ThrottlingStage { WillStartRequest, WillRedirectRequest };
-
-  content::NavigationThrottle::ThrottleCheckResult DeferToCalculateLoadPolicy(
-      ThrottlingStage stage);
-  void OnCalculatedLoadPolicy(ThrottlingStage stage, LoadPolicy policy);
+  content::NavigationThrottle::ThrottleCheckResult DeferToCalculateLoadPolicy();
+  void OnCalculatedLoadPolicy(LoadPolicy policy);
 
   void NotifyLoadPolicy() const;
 
diff --git a/components/subresource_filter/core/common/document_subresource_filter.h b/components/subresource_filter/core/common/document_subresource_filter.h
index 11305de..9f83fcdc 100644
--- a/components/subresource_filter/core/common/document_subresource_filter.h
+++ b/components/subresource_filter/core/common/document_subresource_filter.h
@@ -62,8 +62,14 @@
       const GURL& subresource_url,
       url_pattern_index::proto::ElementType subresource_type);
 
+  // Called if the DocumentSubresourceFilter needs to change how it filters
+  // subresources.
+  void set_activation_state(const ActivationState& state) {
+    activation_state_ = state;
+  }
+
  private:
-  const ActivationState activation_state_;
+  ActivationState activation_state_;
   const scoped_refptr<const MemoryMappedRuleset> ruleset_;
   const IndexedRulesetMatcher ruleset_matcher_;
 
diff --git a/components/suggestions/suggestions_service_impl.cc b/components/suggestions/suggestions_service_impl.cc
index 81dab47..19465528 100644
--- a/components/suggestions/suggestions_service_impl.cc
+++ b/components/suggestions/suggestions_service_impl.cc
@@ -137,9 +137,8 @@
       blacklist_upload_timer_(tick_clock_),
       weak_ptr_factory_(this) {
   // |sync_service_| is null if switches::kDisableSync is set (tests use that).
-  if (sync_service_) {
+  if (sync_service_)
     sync_service_observer_.Add(sync_service_);
-  }
   // Immediately get the current sync state, so we'll flush the cache if
   // necessary.
   OnStateChanged(sync_service_);
@@ -147,14 +146,13 @@
   blacklist_upload_backoff_.InformOfRequest(/*succeeded=*/true);
 }
 
-SuggestionsServiceImpl::~SuggestionsServiceImpl() {}
+SuggestionsServiceImpl::~SuggestionsServiceImpl() = default;
 
 bool SuggestionsServiceImpl::FetchSuggestionsData() {
   DCHECK(thread_checker_.CalledOnValidThread());
   // If sync state allows, issue a network request to refresh the suggestions.
-  if (history_sync_state_ != syncer::UploadState::ACTIVE) {
+  if (history_sync_state_ != syncer::UploadState::ACTIVE)
     return false;
-  }
   IssueRequestIfNoneOngoing(BuildSuggestionsURL());
   return true;
 }
@@ -163,12 +161,11 @@
 SuggestionsServiceImpl::GetSuggestionsDataFromCache() const {
   SuggestionsProfile suggestions;
   // In case of empty cache or error, return empty.
-  if (!suggestions_store_->LoadSuggestions(&suggestions)) {
-    return base::Optional<SuggestionsProfile>();
-  }
+  if (!suggestions_store_->LoadSuggestions(&suggestions))
+    return base::nullopt;
   thumbnail_manager_->Initialize(suggestions);
   blacklist_store_->FilterSuggestions(&suggestions);
-  return base::Optional<SuggestionsProfile>(suggestions);
+  return suggestions;
 }
 
 std::unique_ptr<SuggestionsServiceImpl::ResponseCallbackList::Subscription>
@@ -360,13 +357,11 @@
 void SuggestionsServiceImpl::SetDefaultExpiryTimestamp(
     SuggestionsProfile* suggestions,
     int64_t default_timestamp_usec) {
-  for (int i = 0; i < suggestions->suggestions_size(); ++i) {
-    ChromeSuggestion* suggestion = suggestions->mutable_suggestions(i);
+  for (ChromeSuggestion& suggestion : *suggestions->mutable_suggestions()) {
     // Do not set expiry if the server has already provided a more specific
     // expiry time for this suggestion.
-    if (!suggestion->has_expiry_ts()) {
-      suggestion->set_expiry_ts(default_timestamp_usec);
-    }
+    if (!suggestion.has_expiry_ts())
+      suggestion.set_expiry_ts(default_timestamp_usec);
   }
 }
 
@@ -376,13 +371,11 @@
   // request happens to be ongoing.
   // TODO(treib): Queue such requests and send them after the current one
   // completes.
-  if (pending_request_.get()) {
+  if (pending_request_.get())
     return;
-  }
   // If there is an ongoing token request, also wait for that.
-  if (token_fetcher_) {
+  if (token_fetcher_)
     return;
-  }
 
   OAuth2TokenService::ScopeSet scopes{GaiaConstants::kChromeSyncOAuth2Scope};
   token_fetcher_ = identity_manager_->CreateAccessTokenFetcherForPrimaryAccount(
@@ -517,9 +510,8 @@
 
   // Handle a successful blacklisting.
   GURL blacklisted_url;
-  if (GetBlacklistedUrl(*source, &blacklisted_url)) {
+  if (GetBlacklistedUrl(*source, &blacklisted_url))
     blacklist_store_->RemoveUrl(blacklisted_url);
-  }
 
   std::string suggestions_data;
   bool success = request->GetResponseAsString(&suggestions_data);
@@ -552,10 +544,10 @@
 
 void SuggestionsServiceImpl::PopulateExtraData(
     SuggestionsProfile* suggestions) {
-  for (int i = 0; i < suggestions->suggestions_size(); ++i) {
-    suggestions::ChromeSuggestion* s = suggestions->mutable_suggestions(i);
-    if (!s->has_favicon_url() || s->favicon_url().empty()) {
-      s->set_favicon_url(base::StringPrintf(kFaviconURL, s->url().c_str()));
+  for (ChromeSuggestion& suggestion : *suggestions->mutable_suggestions()) {
+    if (!suggestion.has_favicon_url() || suggestion.favicon_url().empty()) {
+      suggestion.set_favicon_url(
+          base::StringPrintf(kFaviconURL, suggestion.url().c_str()));
     }
   }
 }
diff --git a/components/sync/driver/glue/sync_backend_host_impl.cc b/components/sync/driver/glue/sync_backend_host_impl.cc
index 39a1603..d231751 100644
--- a/components/sync/driver/glue/sync_backend_host_impl.cc
+++ b/components/sync/driver/glue/sync_backend_host_impl.cc
@@ -14,7 +14,6 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "components/invalidation/public/invalidation_service.h"
 #include "components/invalidation/public/object_id_invalidation_map.h"
-#include "components/signin/core/browser/signin_client.h"
 #include "components/sync/base/experiments.h"
 #include "components/sync/base/invalidation_helper.h"
 #include "components/sync/base/sync_prefs.h"
diff --git a/components/toolbar/BUILD.gn b/components/toolbar/BUILD.gn
index d2859e4..97fcbb13 100644
--- a/components/toolbar/BUILD.gn
+++ b/components/toolbar/BUILD.gn
@@ -17,17 +17,12 @@
 
   icons = [
     "find_in_page.icon",
-    "http.1x.icon",
     "http.icon",
-    "https_invalid.1x.icon",
     "https_invalid.icon",
-    "https_valid.1x.icon",
     "https_valid.icon",
-    "https_valid_in_chip.1x.icon",
     "https_valid_in_chip.icon",
     "offline_pin.icon",
     "open_in_new.icon",
-    "product.1x.icon",
     "product.icon",
     "star_active.icon",
     "star.icon",
diff --git a/components/toolbar/vector_icons/http.1x.icon b/components/toolbar/vector_icons/http.1x.icon
deleted file mode 100644
index de63149..0000000
--- a/components/toolbar/vector_icons/http.1x.icon
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 8, 1,
-CUBIC_TO, 4.14f, 1, 1, 4.14f, 1, 8,
-CUBIC_TO, 1, 11.86f, 4.14f, 15, 8, 15,
-CUBIC_TO, 11.86f, 15, 15, 11.86f, 15, 8,
-CUBIC_TO, 15, 4.14f, 11.86f, 1, 8, 1,
-MOVE_TO, 2.5f, 8,
-CUBIC_TO, 2.5f, 4.97f, 4.97f, 2.5f, 8, 2.5f,
-CUBIC_TO, 11.03f, 2.5f, 13.5f, 4.97f, 13.5f, 8,
-CUBIC_TO, 13.5f, 11.03f, 11.03f, 13.5f, 8, 13.5f,
-CUBIC_TO, 4.97f, 13.5f, 2.5f, 11.03f, 2.5f, 8,
-MOVE_TO, 9, 12,
-LINE_TO, 9, 7,
-LINE_TO, 7, 7,
-LINE_TO, 7, 12,
-LINE_TO, 9, 12,
-MOVE_TO, 7, 6,
-LINE_TO, 9, 6,
-LINE_TO, 9, 4,
-LINE_TO, 7, 4,
-LINE_TO, 7, 6,
-CLOSE
diff --git a/components/toolbar/vector_icons/http.icon b/components/toolbar/vector_icons/http.icon
index 2ab6355..387a8745 100644
--- a/components/toolbar/vector_icons/http.icon
+++ b/components/toolbar/vector_icons/http.icon
@@ -24,3 +24,26 @@
 LINE_TO, 15, 10,
 LINE_TO, 15, 13,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 8, 1,
+CUBIC_TO, 4.14f, 1, 1, 4.14f, 1, 8,
+CUBIC_TO, 1, 11.86f, 4.14f, 15, 8, 15,
+CUBIC_TO, 11.86f, 15, 15, 11.86f, 15, 8,
+CUBIC_TO, 15, 4.14f, 11.86f, 1, 8, 1,
+MOVE_TO, 2.5f, 8,
+CUBIC_TO, 2.5f, 4.97f, 4.97f, 2.5f, 8, 2.5f,
+CUBIC_TO, 11.03f, 2.5f, 13.5f, 4.97f, 13.5f, 8,
+CUBIC_TO, 13.5f, 11.03f, 11.03f, 13.5f, 8, 13.5f,
+CUBIC_TO, 4.97f, 13.5f, 2.5f, 11.03f, 2.5f, 8,
+MOVE_TO, 9, 12,
+LINE_TO, 9, 7,
+LINE_TO, 7, 7,
+LINE_TO, 7, 12,
+LINE_TO, 9, 12,
+MOVE_TO, 7, 6,
+LINE_TO, 9, 6,
+LINE_TO, 9, 4,
+LINE_TO, 7, 4,
+LINE_TO, 7, 6,
+CLOSE
diff --git a/components/toolbar/vector_icons/https_invalid.1x.icon b/components/toolbar/vector_icons/https_invalid.1x.icon
deleted file mode 100644
index dabd65b8..0000000
--- a/components/toolbar/vector_icons/https_invalid.1x.icon
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 0.5f, 14,
-R_H_LINE_TO, 15,
-LINE_TO, 8, 1,
-LINE_TO, 0.5f, 14,
-CLOSE,
-MOVE_TO, 9, 12,
-H_LINE_TO, 7,
-R_V_LINE_TO, -2,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, 2,
-CLOSE,
-R_MOVE_TO, 0, -3,
-H_LINE_TO, 7,
-V_LINE_TO, 6,
-R_H_LINE_TO, 2,
-R_V_LINE_TO, 3,
-CLOSE
diff --git a/components/toolbar/vector_icons/https_invalid.icon b/components/toolbar/vector_icons/https_invalid.icon
index 9d17d46..87478cc 100644
--- a/components/toolbar/vector_icons/https_invalid.icon
+++ b/components/toolbar/vector_icons/https_invalid.icon
@@ -20,3 +20,22 @@
 R_H_LINE_TO, 3,
 R_V_LINE_TO, 6,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 0.5f, 14,
+R_H_LINE_TO, 15,
+LINE_TO, 8, 1,
+LINE_TO, 0.5f, 14,
+CLOSE,
+MOVE_TO, 9, 12,
+H_LINE_TO, 7,
+R_V_LINE_TO, -2,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 2,
+CLOSE,
+R_MOVE_TO, 0, -3,
+H_LINE_TO, 7,
+V_LINE_TO, 6,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 3,
+CLOSE
diff --git a/components/toolbar/vector_icons/https_valid.1x.icon b/components/toolbar/vector_icons/https_valid.1x.icon
deleted file mode 100644
index c6ba83a..0000000
--- a/components/toolbar/vector_icons/https_valid.1x.icon
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 11, 5,
-R_CUBIC_TO, 0, -1.67f, -1.34f, -3, -3, -2.99f,
-R_CUBIC_TO, -1.67f, 0, -3, 1.32f, -3, 2.99f,
-R_V_LINE_TO, 1,
-R_CUBIC_TO, -0.55f, 0, -1, 0.45f, -1, 1,
-V_LINE_TO, 12,
-R_CUBIC_TO, 0, 0.55f, 0.45f, 1, 1, 1,
-R_H_LINE_TO, 6,
-R_CUBIC_TO, 0.55f, 0, 1, -0.45f, 1, -1,
-V_LINE_TO, 7,
-R_CUBIC_TO, 0, -0.53f, -0.48f, -0.97f, -1, -1,
-R_CUBIC_TO, -0.02f, 0, 0, -1, 0, -1,
-CLOSE,
-MOVE_TO, 6, 6.01f,
-V_LINE_TO, 5.01f,
-R_CUBIC_TO, 0, -1.1f, 0.9f, -1.99f, 2, -1.99f,
-R_CUBIC_TO, 1.1f, 0, 2, 0.89f, 2, 2,
-V_LINE_TO, 6.01f,
-H_LINE_TO, 6,
-CLOSE
diff --git a/components/toolbar/vector_icons/https_valid.icon b/components/toolbar/vector_icons/https_valid.icon
index 2c4612d..ae3a54b4 100644
--- a/components/toolbar/vector_icons/https_valid.icon
+++ b/components/toolbar/vector_icons/https_valid.icon
@@ -25,3 +25,25 @@
 R_V_LINE_TO, 2.02f,
 R_H_LINE_TO, -6,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 11, 5,
+R_CUBIC_TO, 0, -1.67f, -1.34f, -3, -3, -2.99f,
+R_CUBIC_TO, -1.67f, 0, -3, 1.32f, -3, 2.99f,
+R_V_LINE_TO, 1,
+R_CUBIC_TO, -0.55f, 0, -1, 0.45f, -1, 1,
+V_LINE_TO, 12,
+R_CUBIC_TO, 0, 0.55f, 0.45f, 1, 1, 1,
+R_H_LINE_TO, 6,
+R_CUBIC_TO, 0.55f, 0, 1, -0.45f, 1, -1,
+V_LINE_TO, 7,
+R_CUBIC_TO, 0, -0.53f, -0.48f, -0.97f, -1, -1,
+R_CUBIC_TO, -0.02f, 0, 0, -1, 0, -1,
+CLOSE,
+MOVE_TO, 6, 6.01f,
+V_LINE_TO, 5.01f,
+R_CUBIC_TO, 0, -1.1f, 0.9f, -1.99f, 2, -1.99f,
+R_CUBIC_TO, 1.1f, 0, 2, 0.89f, 2, 2,
+V_LINE_TO, 6.01f,
+H_LINE_TO, 6,
+CLOSE
diff --git a/components/toolbar/vector_icons/https_valid_in_chip.1x.icon b/components/toolbar/vector_icons/https_valid_in_chip.1x.icon
deleted file mode 100644
index 3c7a0e31..0000000
--- a/components/toolbar/vector_icons/https_valid_in_chip.1x.icon
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 10, 6,
-CUBIC_TO, 10, 6, 10, 6.88f, 10, 5.5f,
-CUBIC_TO, 10, 4.12f, 8.88f, 3, 7.5f, 3,
-CUBIC_TO, 6.12f, 3, 5, 4.12f, 5, 5.5f,
-CUBIC_TO, 5, 6.88f, 5, 6, 5, 6,
-CUBIC_TO, 5, 6, 5.17f, 6, 4.75f, 6,
-CUBIC_TO, 4.33f, 6, 4, 6.34f, 4, 6.75f,
-CUBIC_TO, 4, 7.16f, 4, 10.84f, 4, 11.25f,
-CUBIC_TO, 4, 11.66f, 4.33f, 12, 4.75f, 12,
-LINE_TO, 10.25f, 12,
-CUBIC_TO, 10.67f, 12, 11, 11.66f, 11, 11.25f,
-CUBIC_TO, 11, 10.84f, 11, 7.16f, 11, 6.75f,
-CUBIC_TO, 11, 6.34f, 10.67f, 6, 10.25f, 6,
-CUBIC_TO, 9.83f, 6, 10, 6, 10, 6,
-MOVE_TO, 6, 6,
-CUBIC_TO, 6, 6, 6, 6.33f, 6, 5.5f,
-CUBIC_TO, 6, 4.67f, 6.67f, 4, 7.5f, 4,
-CUBIC_TO, 8.33f, 4, 9, 4.67f, 9, 5.5f,
-LINE_TO, 9, 6,
-LINE_TO, 6, 6,
-CLOSE
diff --git a/components/toolbar/vector_icons/https_valid_in_chip.icon b/components/toolbar/vector_icons/https_valid_in_chip.icon
index 0ecae4ec..e041cb4 100644
--- a/components/toolbar/vector_icons/https_valid_in_chip.icon
+++ b/components/toolbar/vector_icons/https_valid_in_chip.icon
@@ -25,3 +25,26 @@
 R_V_LINE_TO, 2.02f,
 R_H_LINE_TO, -6,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 10, 6,
+CUBIC_TO, 10, 6, 10, 6.88f, 10, 5.5f,
+CUBIC_TO, 10, 4.12f, 8.88f, 3, 7.5f, 3,
+CUBIC_TO, 6.12f, 3, 5, 4.12f, 5, 5.5f,
+CUBIC_TO, 5, 6.88f, 5, 6, 5, 6,
+CUBIC_TO, 5, 6, 5.17f, 6, 4.75f, 6,
+CUBIC_TO, 4.33f, 6, 4, 6.34f, 4, 6.75f,
+CUBIC_TO, 4, 7.16f, 4, 10.84f, 4, 11.25f,
+CUBIC_TO, 4, 11.66f, 4.33f, 12, 4.75f, 12,
+LINE_TO, 10.25f, 12,
+CUBIC_TO, 10.67f, 12, 11, 11.66f, 11, 11.25f,
+CUBIC_TO, 11, 10.84f, 11, 7.16f, 11, 6.75f,
+CUBIC_TO, 11, 6.34f, 10.67f, 6, 10.25f, 6,
+CUBIC_TO, 9.83f, 6, 10, 6, 10, 6,
+MOVE_TO, 6, 6,
+CUBIC_TO, 6, 6, 6, 6.33f, 6, 5.5f,
+CUBIC_TO, 6, 4.67f, 6.67f, 4, 7.5f, 4,
+CUBIC_TO, 8.33f, 4, 9, 4.67f, 9, 5.5f,
+LINE_TO, 9, 6,
+LINE_TO, 6, 6,
+CLOSE
diff --git a/components/toolbar/vector_icons/product.1x.icon b/components/toolbar/vector_icons/product.1x.icon
deleted file mode 100644
index 1565657..0000000
--- a/components/toolbar/vector_icons/product.1x.icon
+++ /dev/null
@@ -1,37 +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.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 8, 5.3f,
-LINE_TO, 13.34f, 5.3f,
-CUBIC_TO, 12.38f, 3.32f, 10.34f, 2, 8, 2,
-CUBIC_TO, 6.14f, 2, 4.46f, 2.84f, 3.38f, 4.16f,
-LINE_TO, 5.36f, 7.58f,
-CUBIC_TO, 5.54f, 6.32f, 6.68f, 5.3f, 8, 5.3f,
-LINE_TO, 8, 5.3f,
-CLOSE,
-MOVE_TO, 8, 10.7f,
-CUBIC_TO, 6.98f, 10.7f, 6.14f, 10.16f, 5.66f, 9.32f,
-LINE_TO, 2.96f, 4.7f,
-CUBIC_TO, 2.36f, 5.66f, 2, 6.8f, 2, 8,
-CUBIC_TO, 2, 11, 4.16f, 13.46f, 7.04f, 13.94f,
-LINE_TO, 9.02f, 10.52f,
-CUBIC_TO, 8.66f, 10.64f, 8.36f, 10.7f, 8, 10.7f,
-LINE_TO, 8, 10.7f,
-CLOSE,
-MOVE_TO, 10.7f, 8,
-CUBIC_TO, 10.7f, 8.48f, 10.58f, 8.96f, 10.34f, 9.32f,
-LINE_TO, 7.64f, 14,
-LINE_TO, 8, 14,
-CUBIC_TO, 11.3f, 14, 14, 11.3f, 14, 8,
-CUBIC_TO, 14, 7.28f, 13.88f, 6.56f, 13.64f, 5.9f,
-LINE_TO, 9.68f, 5.9f,
-CUBIC_TO, 10.28f, 6.38f, 10.7f, 7.16f, 10.7f, 8,
-CLOSE,
-MOVE_TO, 8, 10.1f,
-CUBIC_TO, 9.16f, 10.1f, 10.1f, 9.16f, 10.1f, 8,
-CUBIC_TO, 10.1f, 6.84f, 9.16f, 5.9f, 8, 5.9f,
-CUBIC_TO, 6.84f, 5.9f, 5.9f, 6.84f, 5.9f, 8,
-CUBIC_TO, 5.9f, 9.16f, 6.84f, 10.1f, 8, 10.1f,
-CLOSE
diff --git a/components/toolbar/vector_icons/product.icon b/components/toolbar/vector_icons/product.icon
index 9b741cac..bb6a3254 100644
--- a/components/toolbar/vector_icons/product.icon
+++ b/components/toolbar/vector_icons/product.icon
@@ -35,3 +35,37 @@
 CUBIC_TO, 13.68f, 11.8f, 11.8f, 13.68f, 11.8f, 16,
 CUBIC_TO, 11.8f, 18.32f, 13.68f, 20.2f, 16, 20.2f,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 8, 5.3f,
+LINE_TO, 13.34f, 5.3f,
+CUBIC_TO, 12.38f, 3.32f, 10.34f, 2, 8, 2,
+CUBIC_TO, 6.14f, 2, 4.46f, 2.84f, 3.38f, 4.16f,
+LINE_TO, 5.36f, 7.58f,
+CUBIC_TO, 5.54f, 6.32f, 6.68f, 5.3f, 8, 5.3f,
+LINE_TO, 8, 5.3f,
+CLOSE,
+MOVE_TO, 8, 10.7f,
+CUBIC_TO, 6.98f, 10.7f, 6.14f, 10.16f, 5.66f, 9.32f,
+LINE_TO, 2.96f, 4.7f,
+CUBIC_TO, 2.36f, 5.66f, 2, 6.8f, 2, 8,
+CUBIC_TO, 2, 11, 4.16f, 13.46f, 7.04f, 13.94f,
+LINE_TO, 9.02f, 10.52f,
+CUBIC_TO, 8.66f, 10.64f, 8.36f, 10.7f, 8, 10.7f,
+LINE_TO, 8, 10.7f,
+CLOSE,
+MOVE_TO, 10.7f, 8,
+CUBIC_TO, 10.7f, 8.48f, 10.58f, 8.96f, 10.34f, 9.32f,
+LINE_TO, 7.64f, 14,
+LINE_TO, 8, 14,
+CUBIC_TO, 11.3f, 14, 14, 11.3f, 14, 8,
+CUBIC_TO, 14, 7.28f, 13.88f, 6.56f, 13.64f, 5.9f,
+LINE_TO, 9.68f, 5.9f,
+CUBIC_TO, 10.28f, 6.38f, 10.7f, 7.16f, 10.7f, 8,
+CLOSE,
+MOVE_TO, 8, 10.1f,
+CUBIC_TO, 9.16f, 10.1f, 10.1f, 9.16f, 10.1f, 8,
+CUBIC_TO, 10.1f, 6.84f, 9.16f, 5.9f, 8, 5.9f,
+CUBIC_TO, 6.84f, 5.9f, 5.9f, 6.84f, 5.9f, 8,
+CUBIC_TO, 5.9f, 9.16f, 6.84f, 10.1f, 8, 10.1f,
+CLOSE
diff --git a/components/ukm/test_ukm_recorder.cc b/components/ukm/test_ukm_recorder.cc
index 3e4c88a8..75b3e6be1 100644
--- a/components/ukm/test_ukm_recorder.cc
+++ b/components/ukm/test_ukm_recorder.cc
@@ -33,30 +33,6 @@
   }
 }
 
-// Provides a single merged ukm::mojom::UkmEntry proto that contains all metrics
-// from the given |entries|. |entries| must be non-empty, and all |entries| must
-// have the same |source_id| and |event_hash|.
-mojom::UkmEntryPtr GetMergedEntry(
-    const std::vector<const mojom::UkmEntry*>& entries) {
-  EXPECT_FALSE(entries.empty());
-  mojom::UkmEntryPtr merged_entry = mojom::UkmEntry::New();
-  for (const auto* entry : entries) {
-    MergeEntry(entry, merged_entry.get());
-  }
-  return merged_entry;
-}
-
-std::vector<int64_t> GetValuesForMetric(const mojom::UkmEntry* entry,
-                                        const char* metric_name) {
-  std::vector<int64_t> values;
-  const uint64_t metric_hash = base::HashMetricName(metric_name);
-  for (const auto& metric : entry->metrics) {
-    if (metric->metric_hash == metric_hash)
-      values.push_back(metric->value);
-  }
-  return values;
-}
-
 }  // namespace
 
 TestUkmRecorder::TestUkmRecorder() {
@@ -78,35 +54,6 @@
   return false;
 }
 
-std::set<ukm::SourceId> TestUkmRecorder::GetSourceIds() const {
-  std::set<ukm::SourceId> result;
-  for (const auto& kv : sources()) {
-    result.insert(kv.first);
-  }
-  for (const auto& it : entries()) {
-    result.insert(it->source_id);
-  }
-  return result;
-}
-
-const UkmSource* TestUkmRecorder::GetSourceForUrl(const char* url) const {
-  for (const auto& kv : sources()) {
-    if (kv.second->url() == url)
-      return kv.second.get();
-  }
-  return nullptr;
-}
-
-std::vector<const UkmSource*> TestUkmRecorder::GetSourcesForUrl(
-    const char* url) const {
-  std::vector<const UkmSource*> matching_sources;
-  for (const auto& kv : sources()) {
-    if (kv.second->url() == url)
-      matching_sources.push_back(kv.second.get());
-  }
-  return matching_sources;
-}
-
 const UkmSource* TestUkmRecorder::GetSourceForSourceId(
     SourceId source_id) const {
   const UkmSource* source = nullptr;
@@ -119,20 +66,6 @@
   return source;
 }
 
-const mojom::UkmEntry* TestUkmRecorder::GetEntry(size_t entry_num) const {
-  DCHECK_LT(entry_num, entries().size());
-  return entries()[entry_num].get();
-}
-
-const mojom::UkmEntry* TestUkmRecorder::GetEntryForEntryName(
-    const char* entry_name) const {
-  for (const auto& it : entries()) {
-    if (it->event_hash == base::HashMetricName(entry_name))
-      return it.get();
-  }
-  return nullptr;
-}
-
 std::vector<const mojom::UkmEntry*> TestUkmRecorder::GetEntriesByName(
     base::StringPiece entry_name) const {
   uint64_t hash = base::HashMetricName(entry_name);
@@ -159,12 +92,6 @@
   return result;
 }
 
-// static
-bool TestUkmRecorder::EntryHasMetric(const mojom::UkmEntry* entry,
-                                     base::StringPiece metric_name) {
-  return FindMetric(entry, metric_name) != nullptr;
-}
-
 void TestUkmRecorder::ExpectEntrySourceHasUrl(const mojom::UkmEntry* entry,
                                               const GURL& url) const {
   const UkmSource* src = GetSourceForSourceId(entry->source_id);
@@ -176,171 +103,32 @@
 }
 
 // static
+bool TestUkmRecorder::EntryHasMetric(const mojom::UkmEntry* entry,
+                                     base::StringPiece metric_name) {
+  return GetEntryMetric(entry, metric_name) != nullptr;
+}
+
+// static
 const int64_t* TestUkmRecorder::GetEntryMetric(const mojom::UkmEntry* entry,
                                                base::StringPiece metric_name) {
-  const mojom::UkmMetric* metric = FindMetric(entry, metric_name);
-  return metric ? &metric->value : nullptr;
+  uint64_t hash = base::HashMetricName(metric_name);
+  for (const auto& metric : entry->metrics) {
+    if (metric->metric_hash == hash)
+      return &metric->value;
+  }
+  return nullptr;
 }
 
 // static
 void TestUkmRecorder::ExpectEntryMetric(const mojom::UkmEntry* entry,
                                         base::StringPiece metric_name,
                                         int64_t expected_value) {
-  const mojom::UkmMetric* metric = FindMetric(entry, metric_name);
+  const int64_t* metric = GetEntryMetric(entry, metric_name);
   if (metric == nullptr) {
     FAIL() << "Failed to find metric for event: " << metric_name;
     return;
   }
-  EXPECT_EQ(metric->value, expected_value) << " for metric:" << metric_name;
-}
-
-// static
-const mojom::UkmMetric* TestUkmRecorder::FindMetric(
-    const mojom::UkmEntry* entry,
-    base::StringPiece metric_name) {
-  uint64_t hash = base::HashMetricName(metric_name);
-  for (const auto& metric : entry->metrics) {
-    if (metric->metric_hash == hash)
-      return metric.get();
-  }
-  return nullptr;
-}
-
-std::vector<const mojom::UkmEntry*> TestUkmRecorder::GetEntriesForSourceID(
-    SourceId source_id,
-    const char* event_name) const {
-  const uint64_t event_hash = base::HashMetricName(event_name);
-  std::vector<const mojom::UkmEntry*> entries;
-  for (size_t i = 0; i < entries_count(); ++i) {
-    const mojom::UkmEntry* entry = GetEntry(i);
-    if (entry->source_id == source_id && entry->event_hash == event_hash) {
-      entries.push_back(entry);
-    }
-  }
-  return entries;
-}
-
-mojom::UkmEntryPtr TestUkmRecorder::GetMergedEntryForSourceID(
-    SourceId source_id,
-    const char* event_name) const {
-  mojom::UkmEntryPtr entry =
-      GetMergedEntry(GetEntriesForSourceID(source_id, event_name));
-  EXPECT_EQ(source_id, entry->source_id);
-  EXPECT_EQ(base::HashMetricName(event_name), entry->event_hash);
-  return entry;
-}
-
-bool TestUkmRecorder::HasEntry(const UkmSource& source,
-                               const char* event_name) const {
-  return CountEntries(source, event_name) > 0;
-}
-
-int TestUkmRecorder::CountEntries(const UkmSource& source,
-                                  const char* event_name) const {
-  return GetEntriesForSourceID(source.id(), event_name).size();
-}
-
-void TestUkmRecorder::ExpectEntry(
-    const UkmSource& source,
-    const char* event_name,
-    const std::vector<std::pair<const char*, int64_t>>& expected_metrics)
-    const {
-  // Produce a sorted view of the expected metrics, since order is not
-  // significant.
-  std::vector<std::pair<uint64_t, int64_t>> sorted_expected_metrics;
-  std::transform(expected_metrics.begin(), expected_metrics.end(),
-                 std::back_inserter(sorted_expected_metrics),
-                 [](const std::pair<const char*, int64_t>& metric) {
-                   return std::make_pair(base::HashMetricName(metric.first),
-                                         metric.second);
-                 });
-  std::sort(sorted_expected_metrics.begin(), sorted_expected_metrics.end());
-
-  std::vector<const mojom::UkmEntry*> candidate_entries =
-      GetEntriesForSourceID(source.id(), event_name);
-
-  // Produce a view of each matching entry's metrics that can be compared with
-  // sorted_expected_metrics.
-  std::vector<std::vector<std::pair<uint64_t, int64_t>>> candidate_metrics;
-  std::transform(
-      candidate_entries.begin(), candidate_entries.end(),
-      std::back_inserter(candidate_metrics),
-      [](const mojom::UkmEntry* candidate_entry) {
-        std::vector<std::pair<uint64_t, int64_t>> metrics;
-        std::transform(
-            candidate_entry->metrics.begin(), candidate_entry->metrics.end(),
-            std::back_inserter(metrics), [](const mojom::UkmMetricPtr& metric) {
-              return std::make_pair(metric->metric_hash, metric->value);
-            });
-        std::sort(metrics.begin(), metrics.end());
-        return metrics;
-      });
-
-  if (std::find(candidate_metrics.begin(), candidate_metrics.end(),
-                sorted_expected_metrics) == candidate_metrics.end()) {
-    FAIL() << "Failed to find metrics for event: " << event_name;
-  }
-}
-
-int TestUkmRecorder::CountMetricsForEventName(const UkmSource& source,
-                                              const char* event_name) const {
-  mojom::UkmEntryPtr entry = GetMergedEntryForSourceID(source.id(), event_name);
-  return entry.get() ? entry->metrics.size() : 0;
-}
-
-bool TestUkmRecorder::HasMetric(const UkmSource& source,
-                                const char* event_name,
-                                const char* metric_name) const {
-  return CountMetrics(source, event_name, metric_name) > 0;
-}
-
-int TestUkmRecorder::CountMetrics(const UkmSource& source,
-                                  const char* event_name,
-                                  const char* metric_name) const {
-  mojom::UkmEntryPtr entry = GetMergedEntryForSourceID(source.id(), event_name);
-  return GetValuesForMetric(entry.get(), metric_name).size();
-}
-
-void TestUkmRecorder::ExpectMetric(const UkmSource& source,
-                                   const char* event_name,
-                                   const char* metric_name,
-                                   int64_t expected_value) const {
-  ExpectMetrics(source, event_name, metric_name, {expected_value});
-}
-
-void TestUkmRecorder::ExpectMetrics(
-    const UkmSource& source,
-    const char* event_name,
-    const char* metric_name,
-    const std::vector<int64_t>& expected_values) const {
-  mojom::UkmEntryPtr entry = GetMergedEntryForSourceID(source.id(), event_name);
-
-  // Make sure both vectors are sorted before comparing, since order is not
-  // significant.
-  std::vector<int64_t> sorted_expected_values(expected_values);
-  std::sort(sorted_expected_values.begin(), sorted_expected_values.end());
-
-  std::vector<int64_t> actual_values =
-      GetValuesForMetric(entry.get(), metric_name);
-  std::sort(actual_values.begin(), actual_values.end());
-
-  EXPECT_EQ(actual_values, sorted_expected_values)
-      << "Failed to find expected_values for metric: " << metric_name;
-}
-
-std::vector<int64_t> TestUkmRecorder::GetMetricValues(
-    ukm::SourceId source_id,
-    const char* event_name,
-    const char* metric_name) const {
-  mojom::UkmEntryPtr entry = GetMergedEntryForSourceID(source_id, event_name);
-  return GetValuesForMetric(entry.get(), metric_name);
-}
-
-std::vector<int64_t> TestUkmRecorder::GetMetrics(
-    const UkmSource& source,
-    const char* event_name,
-    const char* metric_name) const {
-  return GetMetricValues(source.id(), event_name, metric_name);
+  EXPECT_EQ(expected_value, *metric) << " for metric:" << metric_name;
 }
 
 TestAutoSetUkmRecorder::TestAutoSetUkmRecorder() : self_ptr_factory_(this) {
diff --git a/components/ukm/test_ukm_recorder.h b/components/ukm/test_ukm_recorder.h
index bbc6c74..7db123e2 100644
--- a/components/ukm/test_ukm_recorder.h
+++ b/components/ukm/test_ukm_recorder.h
@@ -73,109 +73,7 @@
   static const int64_t* GetEntryMetric(const mojom::UkmEntry* entry,
                                        base::StringPiece metric_name);
 
-  // All of the methods below are deprecated.
-  // Use GetEntriesByName based testing instead.
-  // TODO(crbug/761524): Migrate tests and remove these.
-
-  // Get all SourceIds with any data associated with them.
-  std::set<ukm::SourceId> GetSourceIds() const;
-
-  // Returns the UKM source for the given URL. If there are multiple sources for
-  // the given URL, this returns the first source that is created. If there is
-  // no source for the given URL, this returns nullptr.
-  const UkmSource* GetSourceForUrl(const char* url) const;
-  const UkmSource* GetSourceForUrl(const GURL& url) const {
-    return GetSourceForUrl(url.spec().c_str());
-  }
-  std::vector<const ukm::UkmSource*> GetSourcesForUrl(const char* url) const;
-
-  // Returns whether the given UKM |source| has an entry with the given
-  // |event_name|.
-  bool HasEntry(const ukm::UkmSource& source,
-                const char* event_name) const WARN_UNUSED_RESULT;
-
-  // Returns the number of metrics recorded for the given UKM |source| and
-  // |event_name|.
-  int CountMetricsForEventName(const ukm::UkmSource& source,
-                               const char* event_name) const;
-
-  // Returns whether a metric with the given |metric_name| was recorded for the
-  // given UKM |source| and |event_name|.
-  bool HasMetric(const ukm::UkmSource& source,
-                 const char* event_name,
-                 const char* metric_name) const WARN_UNUSED_RESULT;
-
-  // Returns the number of metrics recorded with the given |metric_name|, for
-  // the given UKM |source| and |event_name|.
-  int CountMetrics(const ukm::UkmSource& source,
-                   const char* event_name,
-                   const char* metric_name) const WARN_UNUSED_RESULT;
-
-  // Expects that a single metric was recorded with the given |expected_value|,
-  // for the given |source| and |event_name|. This is shorthand for calling
-  // ExpectMetrics with a single value in the expected values vector.
-  void ExpectMetric(const ukm::UkmSource& source,
-                    const char* event_name,
-                    const char* metric_name,
-                    int64_t expected_value) const;
-
-  // Expects that metrics were recorded with the given |expected_values|, for
-  // the given |source| and |event_name|. The order of |expected_values| is not
-  // significant.
-  void ExpectMetrics(const ukm::UkmSource& source,
-                     const char* event_name,
-                     const char* metric_name,
-                     const std::vector<int64_t>& expected_values) const;
-
-  // Returns all recorded values of a metric for the given |source|,
-  // |event_name| and |metric_name|. The order of values is not specified.
-  std::vector<int64_t> GetMetricValues(ukm::SourceId source_id,
-                                       const char* event_name,
-                                       const char* metric_name) const;
-
-  // Deprecated.
-  // Returns all collected metrics for the given |source|, |event_name| and
-  // |metric_name|. The order of values is not specified.
-  std::vector<int64_t> GetMetrics(const UkmSource& source,
-                                  const char* event_name,
-                                  const char* metric_name) const;
-
-  // UKM entries that may be recorded multiple times for a single source may
-  // need to verify that an expected number of UKM entries were logged. The
-  // utility methods below can be used to verify expected entries. UKM entries
-  // that aren't recorded multiple times per source should prefer using
-  // HasMetric/CountMetrics/ExpectMetric(s) above.
-
-  // Returns the number of entries recorded with the given |event_name|, for the
-  // given UKM |source|.
-  int CountEntries(const ukm::UkmSource& source, const char* event_name) const;
-
-  // Expects that an entry with the given |expected_metrics| was recorded, for
-  // the given |source| and |event_name|. The order of |expected_metrics| is not
-  // significant. |expected_metrics| contains (metric name,metric value) pairs.
-  void ExpectEntry(const ukm::UkmSource& source,
-                   const char* event_name,
-                   const std::vector<std::pair<const char*, int64_t>>&
-                       expected_metrics) const;
-
-  // Deprecated.
-  const mojom::UkmEntry* GetEntry(size_t entry_num) const;
-  // Deprecated.
-  const mojom::UkmEntry* GetEntryForEntryName(const char* entry_name) const;
-
-  // Deprecated.
-  static const mojom::UkmMetric* FindMetric(const mojom::UkmEntry* entry,
-                                            base::StringPiece metric_name);
-
  private:
-  ukm::mojom::UkmEntryPtr GetMergedEntryForSourceID(
-      ukm::SourceId source_id,
-      const char* event_name) const;
-
-  std::vector<const ukm::mojom::UkmEntry*> GetEntriesForSourceID(
-      ukm::SourceId source_id,
-      const char* event_name) const;
-
   DISALLOW_COPY_AND_ASSIGN(TestUkmRecorder);
 };
 
diff --git a/components/vector_icons/BUILD.gn b/components/vector_icons/BUILD.gn
index 96e5a42..030a9c5 100644
--- a/components/vector_icons/BUILD.gn
+++ b/components/vector_icons/BUILD.gn
@@ -9,22 +9,17 @@
 
   icons = [
     "accessibility.icon",
-    "back_arrow.1x.icon",
     "back_arrow.icon",
     "bluetooth_connected.icon",
     "business.icon",
     "check_circle.icon",
     "close.icon",
-    "close_16.1x.icon",
     "close_16.icon",
     "edit.icon",
-    "folder.1x.icon",
     "folder.icon",
-    "folder_managed.1x.icon",
     "folder_managed.icon",
     "folder_managed_touch.icon",
     "folder_touch.icon",
-    "forward_arrow.1x.icon",
     "forward_arrow.icon",
     "help_outline.icon",
     "info_outline.icon",
@@ -38,7 +33,6 @@
     "midi.icon",
     "notifications.icon",
     "protocol_handler.icon",
-    "reload.1x.icon",
     "reload.icon",
     "screen_share.icon",
     "search.icon",
diff --git a/components/vector_icons/aggregate_vector_icons.py b/components/vector_icons/aggregate_vector_icons.py
index f096a9e..112cf7bb 100644
--- a/components/vector_icons/aggregate_vector_icons.py
+++ b/components/vector_icons/aggregate_vector_icons.py
@@ -6,31 +6,85 @@
 import glob
 import optparse
 import os
+import re
 import shlex
 import sys
 import textwrap
 
+CANVAS_DIMENSIONS = "CANVAS_DIMENSIONS"
+CPP_COMMENT_DELIMITER = "//"
+REFERENCE_SIZE_DIP = 48
+TEMPLATE_PLACEHOLDER = "TEMPLATE_PLACEHOLDER"
+
+
 def Error(msg):
   print >> sys.stderr, msg
   sys.exit(1)
 
 
 def CamelCase(name, suffix):
-  words = name.split('_')
+  words = name.split("_")
   words = [w.capitalize() for w in words]
-  return 'k' + ''.join(words) + suffix
+  return "k" + "".join(words) + suffix
 
 
-def GetPathName(name, append_1x = False):
-  return CamelCase(name, "Path1x" if append_1x else "Path");
+def GetPathName(name, append_1x=False):
+  return CamelCase(name, "Path1x" if append_1x else "Path")
 
 
-def GetRepName(name, append_1x = False):
-  return CamelCase(name, "Rep1x" if append_1x else "Rep");
+def GetRepName(name, append_1x=False):
+  return CamelCase(name, "Rep1x" if append_1x else "Rep")
 
 
 def GetIconName(name):
-  return CamelCase(name, "Icon");
+  return CamelCase(name, "Icon")
+
+
+def ExtractIconReps(icon_file_name):
+  """Reads the contents of the given icon file and returns a list of vector
+     commands for different icon representations stored in that file.
+
+  Args:
+      icon_file_name: The file path of the icon file to read.
+  """
+  with open(icon_file_name, "r") as icon_file:
+    icon_file_contents = icon_file.readlines()
+
+  icon_sizes = []
+  current_icon_representation = []
+  icon_representation_list = []
+  for line in icon_file_contents:
+    # Strip comments and empty lines.
+    line = line.partition(CPP_COMMENT_DELIMITER)[0].strip()
+    if not line:
+      continue
+    # Retrieve sizes specified by CANVAS_DIMENSIONS to ensure icons are added in
+    # sorted order by size descending.
+    if line.startswith(CANVAS_DIMENSIONS):
+      sizes = re.findall(r"\d+", line)
+      if len(sizes) != 1:
+        Error("Malformed {} line found in {} - it should only specify one size."
+              .format(CANVAS_DIMENSIONS, icon_file_name))
+      icon_sizes.append(int(sizes[0]))
+
+      # All icons except the first / default icon must start with
+      # "CANVAS_DIMENSIONS", so rely on it here as a icon delimiter.
+      if current_icon_representation:
+        icon_representation_list.append("\n".join(current_icon_representation))
+        current_icon_representation = []
+    current_icon_representation.append(line)
+  if current_icon_representation:
+    icon_representation_list.append("\n".join(current_icon_representation))
+
+  if not icon_representation_list:
+    Error("Didn't find any icons in {}.".format(icon_file_name))
+
+  if len(icon_representation_list) != len(icon_sizes):
+    icon_sizes.insert(0, REFERENCE_SIZE_DIP)
+  if sorted(icon_sizes, reverse=True) != icon_sizes:
+    Error("The icons in {} should be sorted in descending order of size."
+          .format(icon_file_name))
+  return icon_representation_list
 
 
 def AggregateVectorIcons(working_directory, file_list, output_cc, output_h):
@@ -45,62 +99,50 @@
   """
 
   # For each file in |file_list|, place it in |path_map| if its extension is
-  # .icon or place it in |path_map_1x| if its extension is .1x.icon. The
-  # two dictionaries map the icon's name to its path, e.g.,
+  # .icon. This will map the icon's name to its path, e.g.,
   # path_map['cat'] = 'foo/bar/cat.icon'.
   icon_list = []
-  with open(file_list, 'r') as f:
+  with open(file_list, "r") as f:
     file_list_contents = f.read()
   icon_list = shlex.split(file_list_contents)
 
   path_map = {}
-  path_map_1x = {}
 
   for icon_path in icon_list:
     (icon_name, extension) = os.path.splitext(os.path.basename(icon_path))
-    (icon_name, scale_factor) = os.path.splitext(icon_name)
 
-    if (scale_factor and scale_factor != ".1x") or (extension != ".icon"):
-      Error("Only filenames " + icon_name + ".icon or " + icon_name +
-            ".1x.icon are allowed.")
+    if extension != ".icon":
+      Error("Only filenames " + icon_name + ".icon are allowed.")
 
-    if not scale_factor and icon_name not in path_map:
+    if icon_name not in path_map:
       path_map[icon_name] = icon_path
-    elif scale_factor and icon_name not in path_map_1x:
-      path_map_1x[icon_name] = icon_path
     else:
       Error("A vector icon with name '" + icon_name + "' already exists.")
 
-  for icon_1x in path_map_1x:
-    if icon_1x not in path_map:
-      Error("The file " + icon_1x + ".icon must be provided.")
-
   # Generate the file vector_icons.h which declares a variable for each
   # icon in |path_map|. The variable name is derived from the icon name by
   # converting to camel case, prepending 'k', and appending 'Icon'. For
   # example, the icon 'foo_bar' will have the variable name kFooBarIcon.
-  input_header_template = open(os.path.join(working_directory,
-                                            "vector_icons.h.template"))
-  header_template_contents = input_header_template.readlines()
-  input_header_template.close()
+  with open(os.path.join(working_directory, "vector_icons.h.template"),
+            "r") as input_header_template:
+    header_template_contents = input_header_template.readlines()
 
   output_header = open(output_h, "w")
   for line in header_template_contents:
-    if not "TEMPLATE_PLACEHOLDER" in line:
+    if not TEMPLATE_PLACEHOLDER in line:
       output_header.write(line)
       continue
 
     for icon in path_map:
       (icon_name, extension) = os.path.splitext(
                                os.path.basename(path_map[icon]))
-      (icon_name, scale_factor) = os.path.splitext(icon_name)
       output_header.write("VECTOR_ICON_TEMPLATE_H({})\n".format(
           GetIconName(icon_name)))
   output_header.close()
 
-  # Copy the vector icon drawing commands from the .icon and .1x.icon files
-  # and use them to generate vector_icons.cc, which defines the variables
-  # declared in vector_icons.h.
+  # Copy the vector icon drawing commands from the .icon files, splitting them
+  # into their individual icon representations, and use them to generate
+  # vector_icons.cc, which defines the variables declared in vector_icons.h.
   input_cc_template = open(
       os.path.join(working_directory, "vector_icons.cc.template"))
   cc_template_contents = input_cc_template.readlines()
@@ -108,43 +150,41 @@
 
   output_cc = open(output_cc, "w")
   for line in cc_template_contents:
-    if not "TEMPLATE_PLACEHOLDER" in line:
+    if not TEMPLATE_PLACEHOLDER in line:
       output_cc.write(line)
-      continue;
-
+      continue
     for icon in path_map:
       (icon_name, extension) = os.path.splitext(
                                os.path.basename(path_map[icon]))
-      (icon_name, scale_factor) = os.path.splitext(icon_name)
 
       # Store the vector-drawing commands for foo_bar.icon in the temporary
       # variable kFooBarPath.
-      icon_file = open(path_map[icon])
-      vector_commands = "".join(icon_file.readlines())
-      icon_file.close()
+      icon_representation_list = ExtractIconReps(path_map[icon])
+      (vector_commands, vector_commands_1x) = None, None
+      if len(icon_representation_list) >= 1:
+        vector_commands = icon_representation_list[0]
+      if len(icon_representation_list) >= 2:
+        vector_commands_1x = icon_representation_list[1]
+      if len(icon_representation_list) >= 3:
+        print "Warning: " + path_map[icon] + " has more than two icon", \
+              "representations. Support for this is still a WIP - see", \
+              "crbug.com/647286. For now, only the first two will be used."
       output_cc.write("VECTOR_ICON_REP_TEMPLATE({}, {}, {})\n".format(
           GetPathName(icon_name), GetRepName(icon_name), vector_commands))
 
-      # Store the vector-drawing commands for foo_bar.1x.icon in the temporary
-      # variable kFooBarPath1x, if the file exists.
-      vector_commands_1x = None
-      if (icon in path_map_1x):
-        icon_file = open(path_map_1x[icon])
-        vector_commands_1x = "".join(icon_file.readlines())
-        icon_file.close()
+      # Store the vector-drawing commands for foo_bar.icon's 1x version in the
+      # temporary variable kFooBarPath1x, if it exists.
+      if vector_commands_1x:
         output_cc.write("VECTOR_ICON_REP_TEMPLATE({}, {}, {})\n".format(
             GetPathName(icon_name, True), GetRepName(icon_name, True),
             vector_commands_1x))
-
-      # Define the value of kFooBarIcon.
-      if vector_commands_1x is None:
-        output_cc.write("VECTOR_ICON_TEMPLATE({}, {})\n".format(
-            GetIconName(icon_name), GetRepName(icon_name)))
-      else:
         output_cc.write("VECTOR_ICON_TEMPLATE2({}, {}, {})\n".format(
             GetIconName(icon_name), GetRepName(icon_name),
             GetRepName(icon_name, True)))
-
+      else:
+        # Define the value of kFooBarIcon.
+        output_cc.write("VECTOR_ICON_TEMPLATE({}, {})\n".format(
+            GetIconName(icon_name), GetRepName(icon_name)))
   output_cc.close()
 
 
diff --git a/components/vector_icons/back_arrow.1x.icon b/components/vector_icons/back_arrow.1x.icon
deleted file mode 100644
index 3b8ee7a..0000000
--- a/components/vector_icons/back_arrow.1x.icon
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 9, 13.51f,
-LINE_TO, 4.49f, 9,
-LINE_TO, 14, 9,
-CUBIC_TO, 14.55f, 9, 15, 8.55f, 15, 8,
-CUBIC_TO, 15, 7.45f, 14.55f, 7, 14, 7,
-LINE_TO, 4.49f, 7,
-LINE_TO, 9, 2.49f,
-CUBIC_TO, 8.97f, 2.28f, 9, 2.14f, 9, 2,
-CUBIC_TO, 9, 1.45f, 8.55f, 1, 8, 1,
-CUBIC_TO, 7.86f, 1, 7.72f, 1.03f, 7.59f, 1.09f,
-LINE_TO, 7.51f, 1,
-LINE_TO, 1, 7.51f,
-CUBIC_TO, 1.03f, 7.72f, 1, 7.85f, 1, 8,
-CUBIC_TO, 1, 8.15f, 1.03f, 8.28f, 1.09f, 8.41f,
-LINE_TO, 1, 8.49f,
-LINE_TO, 7.51f, 15,
-CUBIC_TO, 7.72f, 14.97f, 7.86f, 15, 8, 15,
-CUBIC_TO, 8.55f, 15, 9, 14.55f, 9, 14,
-CUBIC_TO, 9, 13.86f, 8.97f, 13.72f, 8.91f, 13.59f,
-CLOSE
diff --git a/components/vector_icons/back_arrow.icon b/components/vector_icons/back_arrow.icon
index 4bc93db1..40fcf7f 100644
--- a/components/vector_icons/back_arrow.icon
+++ b/components/vector_icons/back_arrow.icon
@@ -24,3 +24,25 @@
 LINE_TO, 14.36f, 3.47f,
 LINE_TO, 4, 13.81f,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 9, 13.51f,
+LINE_TO, 4.49f, 9,
+LINE_TO, 14, 9,
+CUBIC_TO, 14.55f, 9, 15, 8.55f, 15, 8,
+CUBIC_TO, 15, 7.45f, 14.55f, 7, 14, 7,
+LINE_TO, 4.49f, 7,
+LINE_TO, 9, 2.49f,
+CUBIC_TO, 8.97f, 2.28f, 9, 2.14f, 9, 2,
+CUBIC_TO, 9, 1.45f, 8.55f, 1, 8, 1,
+CUBIC_TO, 7.86f, 1, 7.72f, 1.03f, 7.59f, 1.09f,
+LINE_TO, 7.51f, 1,
+LINE_TO, 1, 7.51f,
+CUBIC_TO, 1.03f, 7.72f, 1, 7.85f, 1, 8,
+CUBIC_TO, 1, 8.15f, 1.03f, 8.28f, 1.09f, 8.41f,
+LINE_TO, 1, 8.49f,
+LINE_TO, 7.51f, 15,
+CUBIC_TO, 7.72f, 14.97f, 7.86f, 15, 8, 15,
+CUBIC_TO, 8.55f, 15, 9, 14.55f, 9, 14,
+CUBIC_TO, 9, 13.86f, 8.97f, 13.72f, 8.91f, 13.59f,
+CLOSE
diff --git a/components/vector_icons/close.1x.icon b/components/vector_icons/close.1x.icon
deleted file mode 100644
index 6033fcb..0000000
--- a/components/vector_icons/close.1x.icon
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// A variant of ic_close with rounded corners and optimized for 1x scale factor
-// devices.
-CANVAS_DIMENSIONS, 16,
-STROKE, 1.85f,
-MOVE_TO, 4, 4,
-R_LINE_TO, 8, 8,
-MOVE_TO, 4, 12,
-R_LINE_TO, 8, -8
diff --git a/components/vector_icons/close.icon b/components/vector_icons/close.icon
index 55c4b63..76f42a0 100644
--- a/components/vector_icons/close.icon
+++ b/components/vector_icons/close.icon
@@ -16,3 +16,12 @@
 LINE_TO, 19, 17.59f,
 LINE_TO, 13.41f, 12,
 CLOSE
+
+// A variant of ic_close with rounded corners and optimized for 1x scale factor
+// devices.
+CANVAS_DIMENSIONS, 16,
+STROKE, 1.85f,
+MOVE_TO, 4, 4,
+R_LINE_TO, 8, 8,
+MOVE_TO, 4, 12,
+R_LINE_TO, 8, -8
diff --git a/components/vector_icons/close_16.1x.icon b/components/vector_icons/close_16.1x.icon
deleted file mode 100644
index 6033fcb..0000000
--- a/components/vector_icons/close_16.1x.icon
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// A variant of ic_close with rounded corners and optimized for 1x scale factor
-// devices.
-CANVAS_DIMENSIONS, 16,
-STROKE, 1.85f,
-MOVE_TO, 4, 4,
-R_LINE_TO, 8, 8,
-MOVE_TO, 4, 12,
-R_LINE_TO, 8, -8
diff --git a/components/vector_icons/close_16.icon b/components/vector_icons/close_16.icon
index 425aa3b..e97aa9c 100644
--- a/components/vector_icons/close_16.icon
+++ b/components/vector_icons/close_16.icon
@@ -9,3 +9,12 @@
 R_LINE_TO, 14.5f, 14.5f,
 MOVE_TO, 8.75f, 23.25f,
 R_LINE_TO, 14.5f, -14.5f
+
+// A variant of ic_close with rounded corners and optimized for 1x scale factor
+// devices.
+CANVAS_DIMENSIONS, 16,
+STROKE, 1.85f,
+MOVE_TO, 4, 4,
+R_LINE_TO, 8, 8,
+MOVE_TO, 4, 12,
+R_LINE_TO, 8, -8
diff --git a/components/vector_icons/folder.1x.icon b/components/vector_icons/folder.1x.icon
deleted file mode 100644
index d8057ec4..0000000
--- a/components/vector_icons/folder.1x.icon
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 2.5f, 2,
-CUBIC_TO, 1.73f, 2, 1.01f, 3.15f, 1.01f, 3.94f,
-LINE_TO, 1, 12.56f,
-CUBIC_TO, 1, 13.35f, 1.63f, 14, 2.4f, 14,
-LINE_TO, 13.6f, 14,
-CUBIC_TO, 14.37f, 14, 15, 13.35f, 15, 12.56f,
-LINE_TO, 15, 5.38f,
-CUBIC_TO, 15, 4.58f, 14.27f, 4, 13.5f, 4,
-LINE_TO, 9, 4,
-LINE_TO, 7, 2,
-LINE_TO, 2.5f, 2,
-CLOSE
diff --git a/components/vector_icons/folder.icon b/components/vector_icons/folder.icon
index 3d375b15..bc13742 100644
--- a/components/vector_icons/folder.icon
+++ b/components/vector_icons/folder.icon
@@ -15,3 +15,17 @@
 LINE_TO, 13.2f, 5,
 LINE_TO, 4.8f, 5,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 2.5f, 2,
+CUBIC_TO, 1.73f, 2, 1.01f, 3.15f, 1.01f, 3.94f,
+LINE_TO, 1, 12.56f,
+CUBIC_TO, 1, 13.35f, 1.63f, 14, 2.4f, 14,
+LINE_TO, 13.6f, 14,
+CUBIC_TO, 14.37f, 14, 15, 13.35f, 15, 12.56f,
+LINE_TO, 15, 5.38f,
+CUBIC_TO, 15, 4.58f, 14.27f, 4, 13.5f, 4,
+LINE_TO, 9, 4,
+LINE_TO, 7, 2,
+LINE_TO, 2.5f, 2,
+CLOSE
diff --git a/components/vector_icons/folder_managed.1x.icon b/components/vector_icons/folder_managed.1x.icon
deleted file mode 100644
index 8786abf..0000000
--- a/components/vector_icons/folder_managed.1x.icon
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 2.5f, 2,
-CUBIC_TO, 1.73f, 2, 1.01f, 3.15f, 1.01f, 3.94f,
-LINE_TO, 1, 12.56f,
-CUBIC_TO, 1, 13.35f, 1.63f, 14, 2.4f, 14,
-LINE_TO, 13.6f, 14,
-CUBIC_TO, 14.37f, 14, 15, 13.35f, 15, 12.56f,
-LINE_TO, 15, 5.38f,
-CUBIC_TO, 15, 4.58f, 14.27f, 4, 13.5f, 4,
-LINE_TO, 9, 4,
-LINE_TO, 7, 2,
-LINE_TO, 2.5f, 2,
-CLOSE,
-MOVE_TO, 3, 5,
-LINE_TO, 3, 12,
-LINE_TO, 13, 12,
-LINE_TO, 13, 7,
-LINE_TO, 8, 7,
-LINE_TO, 8, 5,
-LINE_TO, 3, 5,
-CLOSE,
-MOVE_TO, 5, 11,
-LINE_TO, 4, 11,
-LINE_TO, 4, 10,
-LINE_TO, 5, 10,
-LINE_TO, 5, 11,
-CLOSE,
-MOVE_TO, 5, 9,
-LINE_TO, 4, 9,
-LINE_TO, 4, 8,
-LINE_TO, 5, 8,
-LINE_TO, 5, 9,
-CLOSE,
-MOVE_TO, 5, 7,
-LINE_TO, 4, 7,
-LINE_TO, 4, 6,
-LINE_TO, 5, 6,
-LINE_TO, 5, 7,
-CLOSE,
-MOVE_TO, 7, 11,
-LINE_TO, 6, 11,
-LINE_TO, 6, 10,
-LINE_TO, 7, 10,
-LINE_TO, 7, 11,
-CLOSE,
-MOVE_TO, 7, 9,
-LINE_TO, 6, 9,
-LINE_TO, 6, 8,
-LINE_TO, 7, 8,
-LINE_TO, 7, 9,
-CLOSE,
-MOVE_TO, 7, 7,
-LINE_TO, 6, 7,
-LINE_TO, 6, 6,
-LINE_TO, 7, 6,
-LINE_TO, 7, 7,
-CLOSE,
-MOVE_TO, 12, 11,
-LINE_TO, 8, 11,
-LINE_TO, 8, 10,
-LINE_TO, 9, 10,
-LINE_TO, 9, 9,
-LINE_TO, 8, 9,
-LINE_TO, 8, 8,
-LINE_TO, 12, 8,
-LINE_TO, 12, 11,
-CLOSE,
-MOVE_TO, 10, 9,
-LINE_TO, 10, 10,
-LINE_TO, 11, 10,
-LINE_TO, 11, 9,
-LINE_TO, 10, 9,
-CLOSE
diff --git a/components/vector_icons/folder_managed.icon b/components/vector_icons/folder_managed.icon
index 9ffb4653..a8631b7 100644
--- a/components/vector_icons/folder_managed.icon
+++ b/components/vector_icons/folder_managed.icon
@@ -78,3 +78,77 @@
 LINE_TO, 23, 19,
 LINE_TO, 21, 19,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 2.5f, 2,
+CUBIC_TO, 1.73f, 2, 1.01f, 3.15f, 1.01f, 3.94f,
+LINE_TO, 1, 12.56f,
+CUBIC_TO, 1, 13.35f, 1.63f, 14, 2.4f, 14,
+LINE_TO, 13.6f, 14,
+CUBIC_TO, 14.37f, 14, 15, 13.35f, 15, 12.56f,
+LINE_TO, 15, 5.38f,
+CUBIC_TO, 15, 4.58f, 14.27f, 4, 13.5f, 4,
+LINE_TO, 9, 4,
+LINE_TO, 7, 2,
+LINE_TO, 2.5f, 2,
+CLOSE,
+MOVE_TO, 3, 5,
+LINE_TO, 3, 12,
+LINE_TO, 13, 12,
+LINE_TO, 13, 7,
+LINE_TO, 8, 7,
+LINE_TO, 8, 5,
+LINE_TO, 3, 5,
+CLOSE,
+MOVE_TO, 5, 11,
+LINE_TO, 4, 11,
+LINE_TO, 4, 10,
+LINE_TO, 5, 10,
+LINE_TO, 5, 11,
+CLOSE,
+MOVE_TO, 5, 9,
+LINE_TO, 4, 9,
+LINE_TO, 4, 8,
+LINE_TO, 5, 8,
+LINE_TO, 5, 9,
+CLOSE,
+MOVE_TO, 5, 7,
+LINE_TO, 4, 7,
+LINE_TO, 4, 6,
+LINE_TO, 5, 6,
+LINE_TO, 5, 7,
+CLOSE,
+MOVE_TO, 7, 11,
+LINE_TO, 6, 11,
+LINE_TO, 6, 10,
+LINE_TO, 7, 10,
+LINE_TO, 7, 11,
+CLOSE,
+MOVE_TO, 7, 9,
+LINE_TO, 6, 9,
+LINE_TO, 6, 8,
+LINE_TO, 7, 8,
+LINE_TO, 7, 9,
+CLOSE,
+MOVE_TO, 7, 7,
+LINE_TO, 6, 7,
+LINE_TO, 6, 6,
+LINE_TO, 7, 6,
+LINE_TO, 7, 7,
+CLOSE,
+MOVE_TO, 12, 11,
+LINE_TO, 8, 11,
+LINE_TO, 8, 10,
+LINE_TO, 9, 10,
+LINE_TO, 9, 9,
+LINE_TO, 8, 9,
+LINE_TO, 8, 8,
+LINE_TO, 12, 8,
+LINE_TO, 12, 11,
+CLOSE,
+MOVE_TO, 10, 9,
+LINE_TO, 10, 10,
+LINE_TO, 11, 10,
+LINE_TO, 11, 9,
+LINE_TO, 10, 9,
+CLOSE
diff --git a/components/vector_icons/forward_arrow.1x.icon b/components/vector_icons/forward_arrow.1x.icon
deleted file mode 100644
index 1337e439..0000000
--- a/components/vector_icons/forward_arrow.1x.icon
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 7, 13.51f,
-LINE_TO, 11.51f, 9,
-LINE_TO, 2, 9,
-CUBIC_TO, 1.45f, 9, 1, 8.55f, 1, 8,
-CUBIC_TO, 1, 7.45f, 1.45f, 7, 2, 7,
-LINE_TO, 11.51f, 7,
-LINE_TO, 7, 2.49f,
-CUBIC_TO, 7.03f, 2.28f, 7, 2.14f, 7, 2,
-CUBIC_TO, 7, 1.45f, 7.45f, 1, 8, 1,
-CUBIC_TO, 8.14f, 1, 8.28f, 1.03f, 8.41f, 1.09f,
-LINE_TO, 8.49f, 1,
-LINE_TO, 15, 7.51f,
-LINE_TO, 14.91f, 7.59f,
-CUBIC_TO, 14.97f, 7.72f, 15, 7.85f, 15, 8,
-CUBIC_TO, 15, 8.15f, 14.97f, 8.28f, 14.91f, 8.41f,
-LINE_TO, 15, 8.49f,
-LINE_TO, 8.49f, 15,
-CUBIC_TO, 8.28f, 14.97f, 8.14f, 15, 8, 15,
-CUBIC_TO, 7.45f, 15, 7, 14.55f, 7, 14,
-CUBIC_TO, 7, 13.86f, 7.03f, 13.72f, 7.09f, 13.59f,
-CLOSE
diff --git a/components/vector_icons/forward_arrow.icon b/components/vector_icons/forward_arrow.icon
index aebc27f..d22a99b 100644
--- a/components/vector_icons/forward_arrow.icon
+++ b/components/vector_icons/forward_arrow.icon
@@ -24,3 +24,26 @@
 LINE_TO, 17.64f, 3.47f,
 LINE_TO, 28, 13.81f,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 7, 13.51f,
+LINE_TO, 11.51f, 9,
+LINE_TO, 2, 9,
+CUBIC_TO, 1.45f, 9, 1, 8.55f, 1, 8,
+CUBIC_TO, 1, 7.45f, 1.45f, 7, 2, 7,
+LINE_TO, 11.51f, 7,
+LINE_TO, 7, 2.49f,
+CUBIC_TO, 7.03f, 2.28f, 7, 2.14f, 7, 2,
+CUBIC_TO, 7, 1.45f, 7.45f, 1, 8, 1,
+CUBIC_TO, 8.14f, 1, 8.28f, 1.03f, 8.41f, 1.09f,
+LINE_TO, 8.49f, 1,
+LINE_TO, 15, 7.51f,
+LINE_TO, 14.91f, 7.59f,
+CUBIC_TO, 14.97f, 7.72f, 15, 7.85f, 15, 8,
+CUBIC_TO, 15, 8.15f, 14.97f, 8.28f, 14.91f, 8.41f,
+LINE_TO, 15, 8.49f,
+LINE_TO, 8.49f, 15,
+CUBIC_TO, 8.28f, 14.97f, 8.14f, 15, 8, 15,
+CUBIC_TO, 7.45f, 15, 7, 14.55f, 7, 14,
+CUBIC_TO, 7, 13.86f, 7.03f, 13.72f, 7.09f, 13.59f,
+CLOSE
diff --git a/components/vector_icons/reload.1x.icon b/components/vector_icons/reload.1x.icon
deleted file mode 100644
index b3017e7..0000000
--- a/components/vector_icons/reload.1x.icon
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 15, 1,
-LINE_TO, 15, 7,
-LINE_TO, 9, 7,
-LINE_TO, 11.62f, 4.37f,
-CUBIC_TO, 10.67f, 3.43f, 9.44f, 3, 8, 3,
-CUBIC_TO, 5.09f, 3, 3, 5.1f, 3, 8,
-CUBIC_TO, 3, 10.9f, 5.09f, 13, 8, 13,
-CUBIC_TO, 10.3f, 13, 12.08f, 11.81f, 12.75f, 9.83f,
-LINE_TO, 12.77f, 9.79f,
-CUBIC_TO, 12.93f, 9.44f, 13.47f, 9.18f, 13.76f, 9.18f,
-CUBIC_TO, 14.15f, 9.18f, 14.79f, 9.41f, 14.79f, 10.01f,
-CUBIC_TO, 14.79f, 10.14f, 14.71f, 10.46f, 14.66f, 10.57f,
-CUBIC_TO, 13.66f, 13.13f, 10.98f, 15, 8.03f, 15,
-CUBIC_TO, 4.15f, 15, 1, 11.87f, 1, 8,
-CUBIC_TO, 1, 4.13f, 4.15f, 1, 8.03f, 1,
-CUBIC_TO, 9.96f, 1, 11.7f, 1.77f, 12.97f, 3.03f,
-CLOSE
diff --git a/components/vector_icons/reload.icon b/components/vector_icons/reload.icon
index 3292497..fcd592ec 100644
--- a/components/vector_icons/reload.icon
+++ b/components/vector_icons/reload.icon
@@ -24,3 +24,22 @@
 CUBIC_TO, 28.03f, 19.78f, 27.36f, 19.11f, 26.53f, 19.11f,
 CUBIC_TO, 25.87f, 19.11f, 25.3f, 19.55f, 25.1f, 20.15f,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 15, 1,
+LINE_TO, 15, 7,
+LINE_TO, 9, 7,
+LINE_TO, 11.62f, 4.37f,
+CUBIC_TO, 10.67f, 3.43f, 9.44f, 3, 8, 3,
+CUBIC_TO, 5.09f, 3, 3, 5.1f, 3, 8,
+CUBIC_TO, 3, 10.9f, 5.09f, 13, 8, 13,
+CUBIC_TO, 10.3f, 13, 12.08f, 11.81f, 12.75f, 9.83f,
+LINE_TO, 12.77f, 9.79f,
+CUBIC_TO, 12.93f, 9.44f, 13.47f, 9.18f, 13.76f, 9.18f,
+CUBIC_TO, 14.15f, 9.18f, 14.79f, 9.41f, 14.79f, 10.01f,
+CUBIC_TO, 14.79f, 10.14f, 14.71f, 10.46f, 14.66f, 10.57f,
+CUBIC_TO, 13.66f, 13.13f, 10.98f, 15, 8.03f, 15,
+CUBIC_TO, 4.15f, 15, 1, 11.87f, 1, 8,
+CUBIC_TO, 1, 4.13f, 4.15f, 1, 8.03f, 1,
+CUBIC_TO, 9.96f, 1, 11.7f, 1.77f, 12.97f, 3.03f,
+CLOSE
diff --git a/components/viz/client/BUILD.gn b/components/viz/client/BUILD.gn
index 4137fa5..f1ff32e 100644
--- a/components/viz/client/BUILD.gn
+++ b/components/viz/client/BUILD.gn
@@ -17,6 +17,8 @@
     "hit_test_data_provider.h",
     "hit_test_data_provider_draw_quad.cc",
     "hit_test_data_provider_draw_quad.h",
+    "hit_test_data_provider_surface_layer.cc",
+    "hit_test_data_provider_surface_layer.h",
     "local_surface_id_provider.cc",
     "local_surface_id_provider.h",
   ]
@@ -37,6 +39,7 @@
   sources = [
     "client_layer_tree_frame_sink_unittest.cc",
     "hit_test_data_provider_draw_quad_unittest.cc",
+    "hit_test_data_provider_surface_layer_unittest.cc",
   ]
 
   deps = [
diff --git a/components/viz/client/client_layer_tree_frame_sink.cc b/components/viz/client/client_layer_tree_frame_sink.cc
index 6640d1d..58c487fce 100644
--- a/components/viz/client/client_layer_tree_frame_sink.cc
+++ b/components/viz/client/client_layer_tree_frame_sink.cc
@@ -10,6 +10,7 @@
 #include "base/trace_event/trace_event.h"
 #include "cc/trees/layer_tree_frame_sink_client.h"
 #include "components/viz/client/hit_test_data_provider.h"
+#include "components/viz/client/hit_test_data_provider_surface_layer.h"
 #include "components/viz/client/local_surface_id_provider.h"
 #include "components/viz/common/frame_sinks/begin_frame_args.h"
 #include "components/viz/common/quads/compositor_frame.h"
@@ -108,6 +109,12 @@
   cc::LayerTreeFrameSink::DetachFromClient();
 }
 
+void ClientLayerTreeFrameSink::UpdateHitTestData(
+    const cc::LayerTreeHostImpl* host_impl) {
+  if (hit_test_data_provider_)
+    hit_test_data_provider_->UpdateLayerTreeHostImpl(host_impl);
+}
+
 void ClientLayerTreeFrameSink::SetLocalSurfaceId(
     const LocalSurfaceId& local_surface_id) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
diff --git a/components/viz/client/client_layer_tree_frame_sink.h b/components/viz/client/client_layer_tree_frame_sink.h
index 701c349..06101ea8 100644
--- a/components/viz/client/client_layer_tree_frame_sink.h
+++ b/components/viz/client/client_layer_tree_frame_sink.h
@@ -77,6 +77,7 @@
   // cc::LayerTreeFrameSink implementation.
   bool BindToClient(cc::LayerTreeFrameSinkClient* client) override;
   void DetachFromClient() override;
+  void UpdateHitTestData(const cc::LayerTreeHostImpl* host_impl) override;
   void SetLocalSurfaceId(const LocalSurfaceId& local_surface_id) override;
   void SubmitCompositorFrame(CompositorFrame frame) override;
   void DidNotProduceFrame(const BeginFrameAck& ack) override;
diff --git a/components/viz/client/hit_test_data_provider.h b/components/viz/client/hit_test_data_provider.h
index 3c7e177..8afb7cc 100644
--- a/components/viz/client/hit_test_data_provider.h
+++ b/components/viz/client/hit_test_data_provider.h
@@ -13,6 +13,10 @@
 #include "components/viz/common/quads/compositor_frame.h"
 #include "services/viz/public/interfaces/hit_test/hit_test_region_list.mojom.h"
 
+namespace cc {
+class LayerTreeHostImpl;
+}
+
 namespace viz {
 
 class VIZ_CLIENT_EXPORT HitTestDataProvider {
@@ -25,6 +29,10 @@
   virtual mojom::HitTestRegionListPtr GetHitTestData(
       const CompositorFrame& compositor_frame) const = 0;
 
+  // Exclusively called by HitTestDataProviderSurfaceLayer.
+  virtual void UpdateLayerTreeHostImpl(const cc::LayerTreeHostImpl* host_impl) {
+  }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(HitTestDataProvider);
 };
diff --git a/components/viz/client/hit_test_data_provider_surface_layer.cc b/components/viz/client/hit_test_data_provider_surface_layer.cc
new file mode 100644
index 0000000..acea52c
--- /dev/null
+++ b/components/viz/client/hit_test_data_provider_surface_layer.cc
@@ -0,0 +1,116 @@
+// Copyright 2018 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 "hit_test_data_provider_surface_layer.h"
+
+#include "base/containers/adapters.h"
+#include "cc/layers/surface_layer_impl.h"
+#include "cc/trees/layer_tree_host_impl.h"
+#include "cc/trees/layer_tree_impl.h"
+
+namespace {
+
+uint32_t GetFlagsForSurfaceLayer(const cc::SurfaceLayerImpl* layer) {
+  uint32_t flags = viz::mojom::kHitTestMouse | viz::mojom::kHitTestTouch;
+  const auto& surface_id = layer->primary_surface_id();
+  if (layer->is_clipped()) {
+    flags |= viz::mojom::kHitTestAsk;
+  }
+  if (surface_id.local_surface_id().is_valid()) {
+    flags |= viz::mojom::kHitTestChildSurface;
+  } else {
+    flags |= viz::mojom::kHitTestMine;
+  }
+  return flags;
+}
+
+viz::mojom::HitTestRegionPtr CreateHitTestRegion(
+    const cc::LayerImpl* layer,
+    uint32_t flags,
+    const gfx::Rect& rect,
+    const viz::SurfaceId& surface_id,
+    float device_scale_factor) {
+  auto hit_test_region = viz::mojom::HitTestRegion::New();
+  hit_test_region->frame_sink_id = surface_id.frame_sink_id();
+  hit_test_region->flags = flags;
+
+  hit_test_region->rect = rect;
+  // The transform of hit test region maps a point from parent hit test region
+  // to the local space. This is the inverse of screen space transform. Because
+  // hit test query wants the point in target to be in Pixel space, we
+  // counterscale the transform here. Note that the rect is scaled by dsf, so
+  // the point and the rect are still in the same space.
+  gfx::Transform surface_to_root_transform = layer->ScreenSpaceTransform();
+  surface_to_root_transform.Scale(SK_MScalar1 / device_scale_factor,
+                                  SK_MScalar1 / device_scale_factor);
+  // TODO(sunxd): Avoid losing precision by not using inverse if possible.
+  if (!surface_to_root_transform.GetInverse(&(hit_test_region->transform)))
+    hit_test_region->transform = gfx::Transform();
+  return hit_test_region;
+}
+
+}  // namespace
+
+namespace viz {
+
+// TODO(sunxd): Remove the compositor_frame parameter in base class when surface
+// layer hit testing is enabled.
+mojom::HitTestRegionListPtr HitTestDataProviderSurfaceLayer::GetHitTestData(
+    const CompositorFrame& compositor_frame) const {
+  DCHECK(host_impl_);
+  float device_scale_factor = host_impl_->active_tree()->device_scale_factor();
+  auto hit_test_region_list = mojom::HitTestRegionList::New();
+  hit_test_region_list->flags =
+      mojom::kHitTestMine | mojom::kHitTestMouse | mojom::kHitTestTouch;
+  hit_test_region_list->bounds = host_impl_->DeviceViewport();
+  hit_test_region_list->transform = host_impl_->DrawTransform();
+
+  cc::Region overlapping_region;
+  for (const auto* layer : base::Reversed(*host_impl_->active_tree())) {
+    if (!layer->should_hit_test())
+      continue;
+
+    if (layer->is_surface_layer()) {
+      const auto* surface_layer =
+          static_cast<const cc::SurfaceLayerImpl*>(layer);
+
+      if (!surface_layer->hit_testable()) {
+        overlapping_region.Union(cc::MathUtil::MapEnclosingClippedRect(
+            layer->ScreenSpaceTransform(), gfx::Rect(surface_layer->bounds())));
+        continue;
+      }
+
+      gfx::Rect content_rect(
+          gfx::ScaleToEnclosingRect(gfx::Rect(surface_layer->bounds()),
+                                    device_scale_factor, device_scale_factor));
+
+      gfx::Rect layer_screen_space_rect = cc::MathUtil::MapEnclosingClippedRect(
+          surface_layer->ScreenSpaceTransform(),
+          gfx::Rect(surface_layer->bounds()));
+      if (overlapping_region.Contains(layer_screen_space_rect))
+        continue;
+
+      auto flag = GetFlagsForSurfaceLayer(surface_layer);
+      if (overlapping_region.Intersects(layer_screen_space_rect))
+        flag |= mojom::kHitTestAsk;
+      auto surface_id = surface_layer->primary_surface_id();
+      hit_test_region_list->regions.push_back(CreateHitTestRegion(
+          layer, flag, content_rect, surface_id, device_scale_factor));
+      continue;
+    }
+    // TODO(sunxd): Submit all overlapping layer bounds as hit test regions to
+    // viz.
+    overlapping_region.Union(cc::MathUtil::MapEnclosingClippedRect(
+        layer->ScreenSpaceTransform(), gfx::Rect(layer->bounds())));
+  }
+
+  return hit_test_region_list;
+}
+
+void HitTestDataProviderSurfaceLayer::UpdateLayerTreeHostImpl(
+    const cc::LayerTreeHostImpl* host_impl) {
+  host_impl_ = host_impl;
+}
+
+}  // namespace viz
diff --git a/components/viz/client/hit_test_data_provider_surface_layer.h b/components/viz/client/hit_test_data_provider_surface_layer.h
new file mode 100644
index 0000000..50480404
--- /dev/null
+++ b/components/viz/client/hit_test_data_provider_surface_layer.h
@@ -0,0 +1,39 @@
+// Copyright 2018 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_VIZ_CLIENT_HIT_TEST_DATA_PROVIDER_SURFACE_LAYER_H_
+#define COMPONENTS_VIZ_CLIENT_HIT_TEST_DATA_PROVIDER_SURFACE_LAYER_H_
+
+#include "base/macros.h"
+#include "components/viz/client/hit_test_data_provider.h"
+#include "components/viz/client/viz_client_export.h"
+
+namespace cc {
+
+class LayerTreeHostImpl;
+}
+
+namespace viz {
+
+// HitTestDataProviderSurfaceLayer is used to extract hit test data from
+// cc::LayerTreeHostImpl when submitting CompositorFrame.
+class VIZ_CLIENT_EXPORT HitTestDataProviderSurfaceLayer
+    : public HitTestDataProvider {
+ public:
+  HitTestDataProviderSurfaceLayer() = default;
+
+  mojom::HitTestRegionListPtr GetHitTestData(
+      const CompositorFrame& compositor_frame) const override;
+
+  void UpdateLayerTreeHostImpl(const cc::LayerTreeHostImpl* host_impl) override;
+
+ private:
+  const cc::LayerTreeHostImpl* host_impl_ = nullptr;
+
+  DISALLOW_COPY_AND_ASSIGN(HitTestDataProviderSurfaceLayer);
+};
+
+}  // namespace viz
+
+#endif  // COMPONENTS_VIZ_CLIENT_HIT_TEST_DATA_PROVIDER_SURFACE_LAYER_H_
diff --git a/components/viz/client/hit_test_data_provider_surface_layer_unittest.cc b/components/viz/client/hit_test_data_provider_surface_layer_unittest.cc
new file mode 100644
index 0000000..c92968d9
--- /dev/null
+++ b/components/viz/client/hit_test_data_provider_surface_layer_unittest.cc
@@ -0,0 +1,153 @@
+// Copyright 2018 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/viz/client/hit_test_data_provider_surface_layer.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/threading/thread.h"
+#include "cc/layers/surface_layer_impl.h"
+#include "cc/test/fake_impl_task_runner_provider.h"
+#include "cc/test/fake_layer_tree_frame_sink_client.h"
+#include "cc/test/fake_layer_tree_host_impl.h"
+#include "cc/test/test_task_graph_runner.h"
+#include "cc/trees/layer_tree_impl.h"
+#include "components/viz/client/local_surface_id_provider.h"
+#include "components/viz/common/quads/surface_draw_quad.h"
+#include "components/viz/test/compositor_frame_helpers.h"
+#include "components/viz/test/test_gpu_memory_buffer_manager.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace viz {
+
+// Test to ensure that hit test data is created correctly from CompositorFrame
+// and the underlying layer tree.
+TEST(HitTestDataProviderSurfaceLayerTest, HitTestDataRenderer) {
+  cc::FakeImplTaskRunnerProvider task_runner_provider;
+  cc::TestTaskGraphRunner task_graph_runner;
+  cc::FakeLayerTreeHostImpl host_impl(&task_runner_provider,
+                                      &task_graph_runner);
+
+#if DCHECK_IS_ON()
+  task_runner_provider.SetCurrentThreadIsImplThread(true);
+#endif
+
+  std::unique_ptr<HitTestDataProvider> hit_test_data_provider =
+      std::make_unique<HitTestDataProviderSurfaceLayer>();
+
+  // Setup surface layers in LayerTreeHostImpl.
+
+  host_impl.CreatePendingTree();
+  host_impl.ActivateSyncTree();
+
+  // The structure of the layer tree:
+  // +-Root (1024x768)
+  // +---intermediate_layer (200, 300), 200x200
+  // +-----surface_child1 (50, 50), 100x100, Rotate(45)
+  // +---surface_child2 (450, 300), 100x100
+  // +---overlapping_layer (500, 350), 200x200
+  std::unique_ptr<cc::LayerImpl> intermediate_layer =
+      cc::LayerImpl::Create(host_impl.active_tree(), 2);
+  std::unique_ptr<cc::SurfaceLayerImpl> surface_child1 =
+      cc::SurfaceLayerImpl::Create(host_impl.active_tree(), 3);
+  std::unique_ptr<cc::SurfaceLayerImpl> surface_child2 =
+      cc::SurfaceLayerImpl::Create(host_impl.active_tree(), 4);
+  std::unique_ptr<cc::LayerImpl> overlapping_layer =
+      cc::LayerImpl::Create(host_impl.active_tree(), 5);
+
+  host_impl.SetViewportSize(gfx::Size(1024, 768));
+
+  intermediate_layer->SetPosition(gfx::PointF(200, 300));
+  intermediate_layer->SetBounds(gfx::Size(200, 200));
+
+  surface_child1->SetPosition(gfx::PointF(50, 50));
+  surface_child1->SetBounds(gfx::Size(100, 100));
+  gfx::Transform rotate;
+  rotate.Rotate(45);
+  surface_child1->test_properties()->transform = rotate;
+  surface_child1->SetDrawsContent(true);
+  surface_child1->SetHitTestable(true);
+
+  surface_child2->SetPosition(gfx::PointF(450, 300));
+  surface_child2->SetBounds(gfx::Size(100, 100));
+  surface_child2->SetDrawsContent(true);
+  surface_child2->SetHitTestable(true);
+
+  overlapping_layer->SetPosition(gfx::PointF(500, 350));
+  overlapping_layer->SetBounds(gfx::Size(200, 200));
+  overlapping_layer->SetDrawsContent(true);
+
+  LocalSurfaceId child_local_surface_id(2, base::UnguessableToken::Create());
+  FrameSinkId frame_sink_id(2, 0);
+  SurfaceId child_surface_id(frame_sink_id, child_local_surface_id);
+  surface_child1->SetPrimarySurfaceId(child_surface_id, base::nullopt);
+  surface_child2->SetPrimarySurfaceId(child_surface_id, base::nullopt);
+
+  std::unique_ptr<cc::LayerImpl> root =
+      cc::LayerImpl::Create(host_impl.active_tree(), 1);
+  host_impl.active_tree()->SetRootLayerForTesting(std::move(root));
+  intermediate_layer->test_properties()->AddChild(std::move(surface_child1));
+  host_impl.active_tree()
+      ->root_layer_for_testing()
+      ->test_properties()
+      ->AddChild(std::move(intermediate_layer));
+  host_impl.active_tree()
+      ->root_layer_for_testing()
+      ->test_properties()
+      ->AddChild(std::move(surface_child2));
+  host_impl.active_tree()
+      ->root_layer_for_testing()
+      ->test_properties()
+      ->AddChild(std::move(overlapping_layer));
+
+  host_impl.active_tree()->BuildPropertyTreesForTesting();
+
+  hit_test_data_provider->UpdateLayerTreeHostImpl(&host_impl);
+  constexpr gfx::Rect kFrameRect(0, 0, 1024, 768);
+
+  CompositorFrame compositor_frame =
+      CompositorFrameBuilder().AddRenderPass(kFrameRect, kFrameRect).Build();
+  mojom::HitTestRegionListPtr hit_test_region_list =
+      hit_test_data_provider->GetHitTestData(compositor_frame);
+
+  // Since surface_child2 draws in front of surface_child1, it should also be in
+  // the front of the hit test region list.
+  EXPECT_EQ(mojom::kHitTestMouse | mojom::kHitTestTouch | mojom::kHitTestMine,
+            hit_test_region_list->flags);
+  EXPECT_EQ(kFrameRect, hit_test_region_list->bounds);
+  EXPECT_EQ(2u, hit_test_region_list->regions.size());
+
+  EXPECT_EQ(child_surface_id.frame_sink_id(),
+            hit_test_region_list->regions[1]->frame_sink_id);
+  EXPECT_EQ(
+      mojom::kHitTestMouse | mojom::kHitTestTouch | mojom::kHitTestChildSurface,
+      hit_test_region_list->regions[1]->flags);
+  gfx::Transform child1_transform;
+  child1_transform.Rotate(-45);
+  child1_transform.Translate(-250, -350);
+  EXPECT_TRUE(child1_transform.ApproximatelyEqual(
+      hit_test_region_list->regions[1]->transform));
+  EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
+            hit_test_region_list->regions[1]->rect.ToString());
+
+  EXPECT_EQ(child_surface_id.frame_sink_id(),
+            hit_test_region_list->regions[0]->frame_sink_id);
+  EXPECT_EQ(mojom::kHitTestMouse | mojom::kHitTestTouch |
+                mojom::kHitTestChildSurface | mojom::kHitTestAsk,
+            hit_test_region_list->regions[0]->flags);
+  gfx::Transform child2_transform;
+  child2_transform.Translate(-450, -300);
+  EXPECT_TRUE(child2_transform.ApproximatelyEqual(
+      hit_test_region_list->regions[0]->transform));
+  EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
+            hit_test_region_list->regions[0]->rect.ToString());
+}
+
+}  // namespace viz
diff --git a/components/viz/common/BUILD.gn b/components/viz/common/BUILD.gn
index 91512424..ea9eed0 100644
--- a/components/viz/common/BUILD.gn
+++ b/components/viz/common/BUILD.gn
@@ -116,6 +116,8 @@
     "resources/resource.h",
     "resources/resource_fence.h",
     "resources/resource_id.h",
+    "resources/resource_metadata.cc",
+    "resources/resource_metadata.h",
     "resources/resource_settings.cc",
     "resources/resource_settings.h",
     "resources/resource_sizes.h",
@@ -166,7 +168,7 @@
     "//gpu/command_buffer/service",
     "//gpu/ipc:gl_in_process_context",
     "//gpu/skia_bindings:skia_bindings",
-    "//gpu/vulkan:features",
+    "//gpu/vulkan:buildflags",
     "//mojo/public/cpp/bindings",
     "//skia",
     "//third_party/libyuv",
diff --git a/components/viz/common/features.cc b/components/viz/common/features.cc
index b2364574..0fced8e 100644
--- a/components/viz/common/features.cc
+++ b/components/viz/common/features.cc
@@ -37,6 +37,9 @@
 const base::Feature kEnableVizHitTestDrawQuad{
     "VizHitTestDrawQuad", base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kEnableVizHitTestSurfaceLayer{
+    "VizHitTestSurfaceLayer", base::FEATURE_DISABLED_BY_DEFAULT};
+
 bool IsSurfaceSynchronizationEnabled() {
   auto* command_line = base::CommandLine::ForCurrentProcess();
   return base::FeatureList::IsEnabled(kEnableSurfaceSynchronization) ||
@@ -64,7 +67,8 @@
   // TODO(riajiang): Check kVizDisplayCompositor feature when it works with
   // that config.
   return base::CommandLine::ForCurrentProcess()->HasSwitch(
-      switches::kUseVizHitTestSurfaceLayer);
+             switches::kUseVizHitTestSurfaceLayer) ||
+         base::FeatureList::IsEnabled(kEnableVizHitTestSurfaceLayer);
 }
 
 bool IsDrawOcclusionEnabled() {
diff --git a/components/viz/common/features.h b/components/viz/common/features.h
index f7bffcf..b7eaf7f3 100644
--- a/components/viz/common/features.h
+++ b/components/viz/common/features.h
@@ -15,6 +15,7 @@
 VIZ_COMMON_EXPORT extern const base::Feature kEnableSurfaceSynchronization;
 VIZ_COMMON_EXPORT extern const base::Feature kEnableInvariantsViolationLogging;
 VIZ_COMMON_EXPORT extern const base::Feature kEnableVizHitTestDrawQuad;
+VIZ_COMMON_EXPORT extern const base::Feature kEnableVizHitTestSurfaceLayer;
 VIZ_COMMON_EXPORT extern const base::Feature kVizDisplayCompositor;
 
 VIZ_COMMON_EXPORT bool IsDrawOcclusionEnabled();
diff --git a/components/viz/common/gpu/vulkan_in_process_context_provider.cc b/components/viz/common/gpu/vulkan_in_process_context_provider.cc
index d70d000..4e023d4e 100644
--- a/components/viz/common/gpu/vulkan_in_process_context_provider.cc
+++ b/components/viz/common/gpu/vulkan_in_process_context_provider.cc
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 #include "components/viz/common/gpu/vulkan_in_process_context_provider.h"
-#include "gpu/vulkan/features.h"
+#include "gpu/vulkan/buildflags.h"
 
 #if BUILDFLAG(ENABLE_VULKAN)
 #include "gpu/vulkan/vulkan_device_queue.h"
diff --git a/components/viz/common/gpu/vulkan_in_process_context_provider.h b/components/viz/common/gpu/vulkan_in_process_context_provider.h
index 0fdfad8..2015aa0 100644
--- a/components/viz/common/gpu/vulkan_in_process_context_provider.h
+++ b/components/viz/common/gpu/vulkan_in_process_context_provider.h
@@ -9,7 +9,7 @@
 
 #include "components/viz/common/gpu/vulkan_context_provider.h"
 #include "components/viz/common/viz_common_export.h"
-#include "gpu/vulkan/features.h"
+#include "gpu/vulkan/buildflags.h"
 #if BUILDFLAG(ENABLE_VULKAN)
 #include "third_party/skia/include/gpu/vk/GrVkBackendContext.h"
 #endif
diff --git a/components/viz/common/quads/shared_quad_state.h b/components/viz/common/quads/shared_quad_state.h
index 9390b24..aa1cc84b 100644
--- a/components/viz/common/quads/shared_quad_state.h
+++ b/components/viz/common/quads/shared_quad_state.h
@@ -45,6 +45,9 @@
   // Transforms quad rects into the target content space.
   gfx::Transform quad_to_target_transform;
   // The rect of the quads' originating layer in the space of the quad rects.
+  // Note that the |quad_layer_rect| represents the union of the |rect| of
+  // DrawQuads in this SharedQuadState. If it does not hold, then
+  // |are_contents_opaque| needs to be set to false.
   gfx::Rect quad_layer_rect;
   // The size of the visible area in the quads' originating layer, in the space
   // of the quad rects.
@@ -52,7 +55,7 @@
   // This rect lives in the target content space.
   gfx::Rect clip_rect;
   bool is_clipped;
-  // Indicates whether the quads share this sqs contains opaque content.
+  // Indicates whether the content in |quad_layer_rect| are fully opaque.
   bool are_contents_opaque;
   float opacity;
   SkBlendMode blend_mode;
diff --git a/components/viz/common/resources/bitmap_allocation.cc b/components/viz/common/resources/bitmap_allocation.cc
index 1e23ed5c61..4babe5f 100644
--- a/components/viz/common/resources/bitmap_allocation.cc
+++ b/components/viz/common/resources/bitmap_allocation.cc
@@ -84,6 +84,8 @@
     CollectMemoryUsageAndDie(size, format, memory->requested_size());
   }
 
+  memory->Close();
+
   return mojo::WrapSharedMemoryHandle(
       dupe_handle, memory->mapped_size(),
       mojo::UnwrappedSharedMemoryHandleProtection::kReadWrite);
diff --git a/components/viz/common/resources/resource_metadata.cc b/components/viz/common/resources/resource_metadata.cc
new file mode 100644
index 0000000..4b9649b4
--- /dev/null
+++ b/components/viz/common/resources/resource_metadata.cc
@@ -0,0 +1,18 @@
+// Copyright 2018 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/viz/common/resources/resource_metadata.h"
+
+namespace viz {
+
+ResourceMetadata::ResourceMetadata() = default;
+
+ResourceMetadata::ResourceMetadata(ResourceMetadata&& other) = default;
+
+ResourceMetadata::~ResourceMetadata() = default;
+
+ResourceMetadata& ResourceMetadata::operator=(ResourceMetadata&& other) =
+    default;
+
+}  // namespace viz
diff --git a/components/viz/common/resources/resource_metadata.h b/components/viz/common/resources/resource_metadata.h
new file mode 100644
index 0000000..86d91f1
--- /dev/null
+++ b/components/viz/common/resources/resource_metadata.h
@@ -0,0 +1,57 @@
+// Copyright 2018 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_VIZ_COMMON_RESOURCES_RESOURCE_METADATA_H_
+#define COMPONENTS_VIZ_COMMON_RESOURCES_RESOURCE_METADATA_H_
+
+#include "components/viz/common/viz_common_export.h"
+#include "gpu/command_buffer/common/mailbox.h"
+#include "gpu/command_buffer/common/sync_token.h"
+#include "third_party/skia/include/core/SkColorSpace.h"
+#include "third_party/skia/include/gpu/GrBackendSurface.h"
+#include "third_party/skia/include/gpu/GrTypes.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace viz {
+
+// Metadata for a Resoource. It is used by SkiaRenderer to get resource metedata
+// from DisplayResourceProvider, and make a promise SkImage from it.
+struct VIZ_COMMON_EXPORT ResourceMetadata {
+  ResourceMetadata();
+  ResourceMetadata(ResourceMetadata&& other);
+  ~ResourceMetadata();
+  ResourceMetadata& operator=(ResourceMetadata&& other);
+
+  // A mailbox for the resource texture.
+  gpu::Mailbox mailbox;
+
+  // The backend format for the resource texture. It includes sized texture
+  // format and texture target.
+  GrBackendFormat backend_format;
+
+  // The resource size.
+  gfx::Size size;
+
+  // the mipmap of the resource texture.
+  GrMipMapped mip_mapped = GrMipMapped::kNo;
+
+  // The origin type for the resource texture.
+  GrSurfaceOrigin origin = kTopLeft_GrSurfaceOrigin;
+
+  // The color type for creating SkImage from the resource texture.
+  SkColorType color_type = kUnknown_SkColorType;
+
+  // The alpha type for the resource texture.
+  SkAlphaType alpha_type = kUnknown_SkAlphaType;
+
+  // The color space for the resource texture. It could be null.
+  sk_sp<SkColorSpace> color_space;
+
+  // The sync token for the resource texture.
+  gpu::SyncToken sync_token;
+};
+
+}  // namespace viz
+
+#endif  // COMPONENTS_VIZ_COMMON_RESOURCES_RESOURCE_METADATA_H_
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn
index 52759f2..512a055 100644
--- a/components/viz/service/BUILD.gn
+++ b/components/viz/service/BUILD.gn
@@ -113,6 +113,7 @@
     "frame_sinks/direct_layer_tree_frame_sink.h",
     "frame_sinks/frame_sink_manager_impl.cc",
     "frame_sinks/frame_sink_manager_impl.h",
+    "frame_sinks/frame_sink_observer.h",
     "frame_sinks/primary_begin_frame_source.cc",
     "frame_sinks/primary_begin_frame_source.h",
     "frame_sinks/referenced_surface_tracker.cc",
@@ -172,7 +173,7 @@
     # dependency should not be in public_deps.
     "//gpu/ipc/client",
     "//gpu/ipc/service",
-    "//gpu/vulkan:features",
+    "//gpu/vulkan:buildflags",
     "//media",
     "//media/capture:capture_lib",
     "//media/gpu/ipc/service",
diff --git a/components/viz/service/display/display.cc b/components/viz/service/display/display.cc
index c343c05..ba53c3d 100644
--- a/components/viz/service/display/display.cc
+++ b/components/viz/service/display/display.cc
@@ -28,7 +28,7 @@
 #include "components/viz/service/surfaces/surface.h"
 #include "components/viz/service/surfaces/surface_manager.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
-#include "gpu/vulkan/features.h"
+#include "gpu/vulkan/buildflags.h"
 #include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
 #include "ui/gfx/buffer_types.h"
 #include "ui/gfx/geometry/rect_conversions.h"
diff --git a/components/viz/service/display/output_surface.h b/components/viz/service/display/output_surface.h
index 73b7b88..26d0e63 100644
--- a/components/viz/service/display/output_surface.h
+++ b/components/viz/service/display/output_surface.h
@@ -18,7 +18,7 @@
 #include "components/viz/service/display/software_output_device.h"
 #include "components/viz/service/viz_service_export.h"
 #include "gpu/command_buffer/common/texture_in_use_response.h"
-#include "gpu/vulkan/features.h"
+#include "gpu/vulkan/buildflags.h"
 #include "gpu/vulkan/vulkan_surface.h"
 #include "ui/gfx/color_space.h"
 #include "ui/latency/latency_info.h"
diff --git a/components/viz/service/display/overlay_strategy_single_on_top.cc b/components/viz/service/display/overlay_strategy_single_on_top.cc
index 836d98f0..8888d6b4 100644
--- a/components/viz/service/display/overlay_strategy_single_on_top.cc
+++ b/components/viz/service/display/overlay_strategy_single_on_top.cc
@@ -9,11 +9,6 @@
 #include "ui/gfx/geometry/rect_conversions.h"
 
 namespace viz {
-namespace {
-
-const gfx::BufferFormat kOverlayFormatsWithAlpha[] = {
-    gfx::BufferFormat::RGBA_8888, gfx::BufferFormat::BGRA_8888};
-}
 
 OverlayStrategySingleOnTop::OverlayStrategySingleOnTop(
     OverlayCandidateValidator* capability_checker)
@@ -38,17 +33,6 @@
     if (cc::OverlayCandidate::FromDrawQuad(
             resource_provider, output_color_matrix, *it, &candidate) &&
         !cc::OverlayCandidate::IsOccluded(candidate, quad_list->cbegin(), it)) {
-      // We currently reject quads with alpha that do not request alpha blending
-      // since the alpha channel might not be set to 1 and we're not disabling
-      // blending when scanning out.
-      // TODO(dcastagna): We should support alpha formats without blending using
-      // the opaque FB at scanout.
-      if (std::find(std::begin(kOverlayFormatsWithAlpha),
-                    std::end(kOverlayFormatsWithAlpha),
-                    candidate.format) != std::end(kOverlayFormatsWithAlpha) &&
-          it->shared_quad_state->blend_mode == SkBlendMode::kSrc)
-        continue;
-
       if (candidate.display_rect.size().GetArea() >
           best_candidate.display_rect.size().GetArea()) {
         best_candidate = candidate;
diff --git a/components/viz/service/display/renderer_pixeltest.cc b/components/viz/service/display/renderer_pixeltest.cc
index e7c3158..7453986 100644
--- a/components/viz/service/display/renderer_pixeltest.cc
+++ b/components/viz/service/display/renderer_pixeltest.cc
@@ -1100,13 +1100,17 @@
  public:
   void SetUp() override {
     IntersectingQuadPixelTest<TypeParam>::SetUp();
-    bool use_stream_video_draw_quad = false;
+    constexpr bool kUseStreamVideoDrawQuad = false;
+    constexpr bool kUseGpuMemoryBufferResources = false;
+
     video_resource_updater_ = std::make_unique<cc::VideoResourceUpdater>(
-        this->child_context_provider_.get(),
-        this->child_resource_provider_.get(), use_stream_video_draw_quad);
+        this->child_context_provider_.get(), nullptr,
+        this->child_resource_provider_.get(), kUseStreamVideoDrawQuad,
+        kUseGpuMemoryBufferResources);
     video_resource_updater2_ = std::make_unique<cc::VideoResourceUpdater>(
-        this->child_context_provider_.get(),
-        this->child_resource_provider_.get(), use_stream_video_draw_quad);
+        this->child_context_provider_.get(), nullptr,
+        this->child_resource_provider_.get(), kUseStreamVideoDrawQuad,
+        kUseGpuMemoryBufferResources);
   }
 
  protected:
@@ -1429,40 +1433,20 @@
 
   void SetUp() override {
     GLRendererPixelTest::SetUp();
-    bool use_stream_video_draw_quad = false;
+    constexpr bool kUseStreamVideoDrawQuad = false;
+    constexpr bool kUseGpuMemoryBufferResources = false;
     video_resource_updater_ = std::make_unique<cc::VideoResourceUpdater>(
-        child_context_provider_.get(), child_resource_provider_.get(),
-        use_stream_video_draw_quad);
+        child_context_provider_.get(), nullptr, child_resource_provider_.get(),
+        kUseStreamVideoDrawQuad, kUseGpuMemoryBufferResources);
   }
 
   std::unique_ptr<cc::VideoResourceUpdater> video_resource_updater_;
 };
 
-enum class HighbitTexture {
-  Y8,
-  R16_EXT,
-};
-
-class VideoGLRendererPixelHiLoTest
-    : public VideoGLRendererPixelTest,
-      public ::testing::WithParamInterface<
-          ::testing::tuple<bool, HighbitTexture>> {
+class VideoGLRendererPixelHiLoTest : public VideoGLRendererPixelTest,
+                                     public testing::WithParamInterface<bool> {
  public:
-  void SetSupportHighbitTexture(HighbitTexture texture) {
-    switch (texture) {
-      case HighbitTexture::Y8:
-        break;
-      case HighbitTexture::R16_EXT:
-        video_resource_updater_->SetUseR16ForTesting(true);
-        break;
-    }
-  }
-
- private:
-  cc::TestInProcessContextProvider* GetTestInProcessContextProvider() {
-    return static_cast<cc::TestInProcessContextProvider*>(
-        output_surface_->context_provider());
-  }
+  bool IsHighbit() const { return GetParam(); }
 };
 
 TEST_P(VideoGLRendererPixelHiLoTest, SimpleYUVRect) {
@@ -1477,13 +1461,9 @@
   SharedQuadState* shared_state =
       CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
 
-  const bool highbit = testing::get<0>(GetParam());
-  const HighbitTexture format = testing::get<1>(GetParam());
-  SetSupportHighbitTexture(format);
-
   CreateTestYUVVideoDrawQuad_Striped(
       shared_state, media::PIXEL_FORMAT_I420, media::COLOR_SPACE_SD_REC601,
-      false, highbit, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), pass.get(),
+      false, IsHighbit(), gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), pass.get(),
       video_resource_updater_.get(), rect, rect, resource_provider_.get(),
       child_resource_provider_.get());
 
@@ -1509,13 +1489,9 @@
   SharedQuadState* shared_state =
       CreateTestSharedQuadState(gfx::Transform(), viewport, pass.get());
 
-  const bool highbit = testing::get<0>(GetParam());
-  const HighbitTexture format = testing::get<1>(GetParam());
-  SetSupportHighbitTexture(format);
-
   CreateTestYUVVideoDrawQuad_Striped(
       shared_state, media::PIXEL_FORMAT_I420, media::COLOR_SPACE_SD_REC601,
-      false, highbit, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), pass.get(),
+      false, IsHighbit(), gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), pass.get(),
       video_resource_updater_.get(), draw_rect, viewport,
       resource_provider_.get(), child_resource_provider_.get());
   RenderPassList pass_list;
@@ -1583,12 +1559,7 @@
 }
 
 // First argument (test case prefix) is intentionally left empty.
-INSTANTIATE_TEST_CASE_P(
-    ,
-    VideoGLRendererPixelHiLoTest,
-    testing::Combine(testing::Bool(),
-                     testing::Values(HighbitTexture::Y8,
-                                     HighbitTexture::R16_EXT)));
+INSTANTIATE_TEST_CASE_P(, VideoGLRendererPixelHiLoTest, testing::Bool());
 
 TEST_F(VideoGLRendererPixelTest, SimpleYUVJRect) {
   gfx::Rect rect(this->device_viewport_size_);
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc
index 4efa8ea..c3f9425 100644
--- a/components/viz/service/display/skia_renderer.cc
+++ b/components/viz/service/display/skia_renderer.cc
@@ -214,8 +214,8 @@
   GrContext* gr_context =
       output_surface_->vulkan_context_provider()->GetGrContext();
   root_surface_ = SkSurface::MakeFromBackendRenderTarget(
-      gr_context, render_target, kTopLeft_GrSurfaceOrigin, nullptr,
-      &surface_props);
+      gr_context, render_target, kTopLeft_GrSurfaceOrigin,
+      kBGRA_8888_SkColorType, nullptr, &surface_props);
 #else
   // TODO(weiliangc): Set up correct can_use_lcd_text for SkSurfaceProps flags.
   // How to setup is in ResourceProvider. (http://crbug.com/644851)
@@ -228,14 +228,14 @@
     // surface.
     GrGLFramebufferInfo framebuffer_info;
     framebuffer_info.fFBOID = 0;
+    framebuffer_info.fFormat = GL_RGBA8_OES;
     GrBackendRenderTarget render_target(
         current_frame()->device_viewport_size.width(),
-        current_frame()->device_viewport_size.height(), 0, 8,
-        kRGBA_8888_GrPixelConfig, framebuffer_info);
+        current_frame()->device_viewport_size.height(), 0, 8, framebuffer_info);
 
     root_surface_ = SkSurface::MakeFromBackendRenderTarget(
-        gr_context, render_target, kBottomLeft_GrSurfaceOrigin, nullptr,
-        &surface_props);
+        gr_context, render_target, kBottomLeft_GrSurfaceOrigin,
+        kRGBA_8888_SkColorType, nullptr, &surface_props);
   }
 #endif
 
diff --git a/components/viz/service/display/skia_renderer.h b/components/viz/service/display/skia_renderer.h
index b330c57..bc6be5f 100644
--- a/components/viz/service/display/skia_renderer.h
+++ b/components/viz/service/display/skia_renderer.h
@@ -10,7 +10,7 @@
 #include "components/viz/service/display/direct_renderer.h"
 #include "components/viz/service/display/sync_query_collection.h"
 #include "components/viz/service/viz_service_export.h"
-#include "gpu/vulkan/features.h"
+#include "gpu/vulkan/buildflags.h"
 #include "ui/latency/latency_info.h"
 
 class SkNWayCanvas;
diff --git a/components/viz/service/display/surface_aggregator.cc b/components/viz/service/display/surface_aggregator.cc
index a262fad..78c6bca3 100644
--- a/components/viz/service/display/surface_aggregator.cc
+++ b/components/viz/service/display/surface_aggregator.cc
@@ -426,6 +426,12 @@
   } else {
     auto* shared_quad_state = CopyAndScaleSharedQuadState(
         source_sqs, scaled_quad_to_target_transform, target_transform,
+        gfx::ScaleToEnclosingRect(source_sqs->quad_layer_rect,
+                                  layer_to_content_scale_x,
+                                  layer_to_content_scale_y),
+        gfx::ScaleToEnclosingRect(source_sqs->visible_quad_layer_rect,
+                                  layer_to_content_scale_x,
+                                  layer_to_content_scale_y),
         clip_rect, dest_pass, layer_to_content_scale_x,
         layer_to_content_scale_y);
 
@@ -489,15 +495,17 @@
   if (has_transparent_background)
     return;
 
-  SharedQuadState* shared_quad_state = nullptr;
   if (fallback_rect.width() < primary_rect.width()) {
-    shared_quad_state = CopySharedQuadState(
-        primary_shared_quad_state, target_transform, clip_rect, dest_pass);
-
     // The right gutter also includes the bottom-right corner, if necessary.
     gfx::Rect right_gutter_rect(fallback_rect.right(), primary_rect.y(),
                                 primary_rect.width() - fallback_rect.width(),
                                 primary_rect.height());
+
+    SharedQuadState* shared_quad_state = CopyAndScaleSharedQuadState(
+        primary_shared_quad_state,
+        primary_shared_quad_state->quad_to_target_transform, target_transform,
+        right_gutter_rect, right_gutter_rect, clip_rect, dest_pass, 1.0f, 1.0f);
+
     auto* right_gutter =
         dest_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
     right_gutter->SetNew(shared_quad_state, right_gutter_rect,
@@ -505,14 +513,16 @@
   }
 
   if (fallback_rect.height() < primary_rect.height()) {
-    if (!shared_quad_state) {
-      shared_quad_state = CopySharedQuadState(
-          primary_shared_quad_state, target_transform, clip_rect, dest_pass);
-    }
-
     gfx::Rect bottom_gutter_rect(
         primary_rect.x(), fallback_rect.bottom(), fallback_rect.width(),
         primary_rect.height() - fallback_rect.height());
+
+    SharedQuadState* shared_quad_state = CopyAndScaleSharedQuadState(
+        primary_shared_quad_state,
+        primary_shared_quad_state->quad_to_target_transform, target_transform,
+        bottom_gutter_rect, bottom_gutter_rect, clip_rect, dest_pass, 1.0f,
+        1.0f);
+
     auto* bottom_gutter =
         dest_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
     bottom_gutter->SetNew(shared_quad_state, bottom_gutter_rect,
@@ -588,6 +598,7 @@
     RenderPass* dest_render_pass) {
   return CopyAndScaleSharedQuadState(
       source_sqs, source_sqs->quad_to_target_transform, target_transform,
+      source_sqs->quad_layer_rect, source_sqs->visible_quad_layer_rect,
       clip_rect, dest_render_pass, 1.0f, 1.0f);
 }
 
@@ -595,6 +606,8 @@
     const SharedQuadState* source_sqs,
     const gfx::Transform& scaled_quad_to_target_transform,
     const gfx::Transform& target_transform,
+    const gfx::Rect& quad_layer_rect,
+    const gfx::Rect& visible_quad_layer_rect,
     const ClipData& clip_rect,
     RenderPass* dest_render_pass,
     float x_scale,
@@ -613,14 +626,8 @@
   gfx::Transform new_transform = scaled_quad_to_target_transform;
   new_transform.ConcatTransform(target_transform);
 
-  gfx::Rect scaled_quad_layer_rect(
-      gfx::ScaleToEnclosingRect(source_sqs->quad_layer_rect, x_scale, y_scale));
-
-  gfx::Rect scaled_visible_quad_layer_rect(gfx::ScaleToEnclosingRect(
-      source_sqs->visible_quad_layer_rect, x_scale, y_scale));
-
   shared_quad_state->SetAll(
-      new_transform, scaled_quad_layer_rect, scaled_visible_quad_layer_rect,
+      new_transform, quad_layer_rect, visible_quad_layer_rect,
       new_clip_rect.rect, new_clip_rect.is_clipped,
       source_sqs->are_contents_opaque, source_sqs->opacity,
       source_sqs->blend_mode, source_sqs->sorting_context_id);
diff --git a/components/viz/service/display/surface_aggregator.h b/components/viz/service/display/surface_aggregator.h
index 9ff6edbe..fc2c379e 100644
--- a/components/viz/service/display/surface_aggregator.h
+++ b/components/viz/service/display/surface_aggregator.h
@@ -160,6 +160,8 @@
       const SharedQuadState* source_sqs,
       const gfx::Transform& scaled_quad_to_target_transform,
       const gfx::Transform& target_transform,
+      const gfx::Rect& quad_layer_rect,
+      const gfx::Rect& visible_quad_layer_rect,
       const ClipData& clip_rect,
       RenderPass* dest_render_pass,
       float x_scale,
diff --git a/components/viz/service/display/surface_aggregator_unittest.cc b/components/viz/service/display/surface_aggregator_unittest.cc
index 768aa885..a5f477a 100644
--- a/components/viz/service/display/surface_aggregator_unittest.cc
+++ b/components/viz/service/display/surface_aggregator_unittest.cc
@@ -19,6 +19,7 @@
 #include "cc/test/render_pass_test_utils.h"
 #include "components/viz/common/frame_sinks/begin_frame_args.h"
 #include "components/viz/common/quads/compositor_frame.h"
+#include "components/viz/common/quads/draw_quad.h"
 #include "components/viz/common/quads/render_pass.h"
 #include "components/viz/common/quads/render_pass_draw_quad.h"
 #include "components/viz/common/quads/solid_color_draw_quad.h"
@@ -386,6 +387,28 @@
     SurfaceAggregatorTest::TearDown();
   }
 
+  // Verifies that if the |SharedQuadState::quad_layer_rect| can be covered by
+  // |DrawQuad::Rect| in the SharedQuadState.
+  void VerifyQuadCoverSQS(CompositorFrame* aggregated_frame) {
+    const SharedQuadState* shared_quad_state = nullptr;
+    gfx::Rect draw_quad_coverage;
+    for (size_t i = 0; i < aggregated_frame->render_pass_list.size(); ++i) {
+      for (auto quad =
+               aggregated_frame->render_pass_list[i]->quad_list.cbegin();
+           quad != aggregated_frame->render_pass_list[i]->quad_list.cend();
+           ++quad) {
+        if (shared_quad_state != quad->shared_quad_state) {
+          if (shared_quad_state)
+            EXPECT_EQ(shared_quad_state->quad_layer_rect, draw_quad_coverage);
+
+          shared_quad_state = quad->shared_quad_state;
+          draw_quad_coverage = quad->rect;
+        }
+        draw_quad_coverage.Union(quad->rect);
+      }
+    }
+  }
+
   void AggregateAndVerify(Pass* expected_passes,
                           size_t expected_pass_count,
                           SurfaceId* surface_ids,
@@ -396,6 +419,7 @@
 
     TestPassesMatchExpectations(expected_passes, expected_pass_count,
                                 &aggregated_frame.render_pass_list);
+    VerifyQuadCoverSQS(&aggregated_frame);
 
     // Ensure no duplicate pass ids output.
     std::set<RenderPassId> used_passes;
diff --git a/components/viz/service/display_embedder/buffer_queue_unittest.cc b/components/viz/service/display_embedder/buffer_queue_unittest.cc
index ff4221f1..fd949f4 100644
--- a/components/viz/service/display_embedder/buffer_queue_unittest.cc
+++ b/components/viz/service/display_embedder/buffer_queue_unittest.cc
@@ -94,6 +94,9 @@
 const gpu::SurfaceHandle kFakeSurfaceHandle = 1;
 #endif
 
+const unsigned int kBufferQueueInternalformat = GL_RGBA;
+const gfx::BufferFormat kBufferQueueFormat = gfx::BufferFormat::RGBA_8888;
+
 class MockBufferQueue : public BufferQueue {
  public:
   MockBufferQueue(gpu::gles2::GLES2Interface* gl,
@@ -102,8 +105,8 @@
                   unsigned int internalformat)
       : BufferQueue(gl,
                     target,
-                    internalformat,
-                    display::DisplaySnapshot::PrimaryFormat(),
+                    kBufferQueueInternalformat,
+                    kBufferQueueFormat,
                     nullptr,
                     gpu_memory_buffer_manager,
                     kFakeSurfaceHandle) {}
@@ -123,7 +126,8 @@
     gpu_memory_buffer_manager_.reset(new StubGpuMemoryBufferManager);
     mock_output_surface_ = new MockBufferQueue(context_provider_->ContextGL(),
                                                gpu_memory_buffer_manager_.get(),
-                                               GL_TEXTURE_2D, GL_RGB);
+                                               GL_TEXTURE_2D,
+                                               kBufferQueueInternalformat);
     output_surface_.reset(mock_output_surface_);
     output_surface_->Initialize();
   }
@@ -263,7 +267,7 @@
     gpu::gles2::GLES2Interface* gl,
     gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager) {
   std::unique_ptr<BufferQueue> buffer_queue(new BufferQueue(
-      gl, target, GL_RGB, display::DisplaySnapshot::PrimaryFormat(), nullptr,
+      gl, target, kBufferQueueInternalformat, kBufferQueueFormat, nullptr,
       gpu_memory_buffer_manager, kFakeSurfaceHandle));
   buffer_queue->Initialize();
   return buffer_queue;
@@ -302,7 +306,8 @@
     EXPECT_CALL(*context, bindTexture(target, Ne(0U)));
     EXPECT_CALL(*context, destroyImageCHROMIUM(1));
     Expectation image =
-        EXPECT_CALL(*context, createImageCHROMIUM(_, 0, 0, GL_RGB))
+        EXPECT_CALL(*context,
+                    createImageCHROMIUM(_, 0, 0, kBufferQueueInternalformat))
             .WillOnce(Return(1));
     Expectation fb =
         EXPECT_CALL(*context, bindFramebuffer(GL_FRAMEBUFFER, Ne(0U)));
@@ -332,8 +337,9 @@
                                context_provider->ContextSupport()));
 
   output_surface.reset(new BufferQueue(
-      context_provider->ContextGL(), GL_TEXTURE_2D, GL_RGB,
-      display::DisplaySnapshot::PrimaryFormat(), gl_helper.get(),
+      context_provider->ContextGL(), GL_TEXTURE_2D,
+      kBufferQueueInternalformat, kBufferQueueFormat,
+      gl_helper.get(),
       gpu_memory_buffer_manager.get(), kFakeSurfaceHandle));
   output_surface->Initialize();
   output_surface->Reshape(screen_size, 1.0f, gfx::ColorSpace(), false);
@@ -622,7 +628,8 @@
   // Expect all 4 images to be destroyed, 3 of the existing textures to be
   // copied from and 3 new images to be created.
   EXPECT_CALL(*context_, createImageCHROMIUM(_, screen_size.width(),
-                                             screen_size.height(), GL_RGB))
+                                             screen_size.height(),
+                                             kBufferQueueInternalformat))
       .Times(3);
   Expectation copy1 = EXPECT_CALL(*mock_output_surface_,
                                   CopyBufferDamage(_, displayed->texture, _, _))
diff --git a/components/viz/service/frame_sinks/frame_sink_manager_impl.cc b/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
index a95bdf3c8..22309f7 100644
--- a/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
+++ b/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
@@ -87,11 +87,18 @@
   surface_manager_.RegisterFrameSinkId(frame_sink_id);
   if (video_detector_)
     video_detector_->OnFrameSinkIdRegistered(frame_sink_id);
+
+  for (auto& observer : observer_list_)
+    observer.OnRegisteredFrameSinkId(frame_sink_id);
 }
 
 void FrameSinkManagerImpl::InvalidateFrameSinkId(
     const FrameSinkId& frame_sink_id) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+  for (auto& observer : observer_list_)
+    observer.OnInvalidatedFrameSinkId(frame_sink_id);
+
   surface_manager_.InvalidateFrameSinkId(frame_sink_id);
   if (video_detector_)
     video_detector_->OnFrameSinkIdInvalidated(frame_sink_id);
@@ -159,6 +166,9 @@
               std::move(params->compositor_frame_sink_client)),
           std::move(params->display_private),
           mojom::DisplayClientPtr(std::move(params->display_client)));
+
+  for (auto& observer : observer_list_)
+    observer.OnCreatedRootCompositorFrameSink(params->frame_sink_id);
 }
 
 void FrameSinkManagerImpl::CreateCompositorFrameSink(
@@ -170,11 +180,17 @@
 
   sink_map_[frame_sink_id] = std::make_unique<CompositorFrameSinkImpl>(
       this, frame_sink_id, std::move(request), std::move(client));
+
+  for (auto& observer : observer_list_)
+    observer.OnCreatedCompositorFrameSink(frame_sink_id);
 }
 
 void FrameSinkManagerImpl::DestroyCompositorFrameSink(
     const FrameSinkId& frame_sink_id,
     DestroyCompositorFrameSinkCallback callback) {
+  for (auto& observer : observer_list_)
+    observer.OnDestroyedCompositorFrameSink(frame_sink_id);
+
   sink_map_.erase(frame_sink_id);
   std::move(callback).Run();
 }
@@ -199,6 +215,11 @@
 
   DCHECK_EQ(registered_sources_.count(parent_source), 1u);
   RecursivelyAttachBeginFrameSource(child_frame_sink_id, parent_source);
+
+  for (auto& observer : observer_list_) {
+    observer.OnRegisteredFrameSinkHierarchy(parent_frame_sink_id,
+                                            child_frame_sink_id);
+  }
 }
 
 void FrameSinkManagerImpl::UnregisterFrameSinkHierarchy(
@@ -209,6 +230,12 @@
   // in time. This makes it possible to invalidate parent and child FrameSinkIds
   // independently of each other and not have an ordering dependency of
   // unregistering the hierarchy first before either of them.
+
+  for (auto& observer : observer_list_) {
+    observer.OnUnregisteredFrameSinkHierarchy(parent_frame_sink_id,
+                                              child_frame_sink_id);
+  }
+
   auto iter = frame_sink_source_map_.find(parent_frame_sink_id);
   DCHECK(iter != frame_sink_source_map_.end());
 
@@ -371,12 +398,18 @@
   auto it = frame_sink_source_map_.find(frame_sink_id);
   if (it != frame_sink_source_map_.end() && it->second.source)
     support->SetBeginFrameSource(it->second.source);
+
+  for (auto& observer : observer_list_)
+    observer.OnRegisteredCompositorFrameSinkSupport(frame_sink_id, support);
 }
 
 void FrameSinkManagerImpl::UnregisterCompositorFrameSinkSupport(
     const FrameSinkId& frame_sink_id) {
   DCHECK(base::ContainsKey(support_map_, frame_sink_id));
 
+  for (auto& observer : observer_list_)
+    observer.OnUnregisteredCompositorFrameSinkSupport(frame_sink_id);
+
   for (auto& capturer : video_capturers_) {
     if (capturer->requested_target() == frame_sink_id)
       capturer->OnTargetWillGoAway();
@@ -528,4 +561,12 @@
   return video_detector_.get();
 }
 
+void FrameSinkManagerImpl::AddObserver(FrameSinkObserver* obs) {
+  observer_list_.AddObserver(obs);
+}
+
+void FrameSinkManagerImpl::RemoveObserver(FrameSinkObserver* obs) {
+  observer_list_.RemoveObserver(obs);
+}
+
 }  // namespace viz
diff --git a/components/viz/service/frame_sinks/frame_sink_manager_impl.h b/components/viz/service/frame_sinks/frame_sink_manager_impl.h
index 768a9b4a..f721bdc 100644
--- a/components/viz/service/frame_sinks/frame_sink_manager_impl.h
+++ b/components/viz/service/frame_sinks/frame_sink_manager_impl.h
@@ -19,6 +19,7 @@
 #include "base/threading/thread_checker.h"
 #include "components/viz/common/constants.h"
 #include "components/viz/common/surfaces/frame_sink_id.h"
+#include "components/viz/service/frame_sinks/frame_sink_observer.h"
 #include "components/viz/service/frame_sinks/primary_begin_frame_source.h"
 #include "components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_manager.h"
 #include "components/viz/service/frame_sinks/video_detector.h"
@@ -165,6 +166,9 @@
   void OnFrameTokenChanged(const FrameSinkId& frame_sink_id,
                            uint32_t frame_token);
 
+  void AddObserver(FrameSinkObserver* obs);
+  void RemoveObserver(FrameSinkObserver* obs);
+
  private:
   friend class FrameSinkManagerTest;
 
@@ -248,6 +252,8 @@
   mojom::FrameSinkManagerClientPtr client_ptr_;
   mojo::Binding<mojom::FrameSinkManager> binding_;
 
+  base::ObserverList<FrameSinkObserver> observer_list_;
+
   DISALLOW_COPY_AND_ASSIGN(FrameSinkManagerImpl);
 };
 
diff --git a/components/viz/service/frame_sinks/frame_sink_observer.h b/components/viz/service/frame_sinks/frame_sink_observer.h
new file mode 100644
index 0000000..8263ae5
--- /dev/null
+++ b/components/viz/service/frame_sinks/frame_sink_observer.h
@@ -0,0 +1,57 @@
+// Copyright 2018 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_VIZ_SERVICE_FRAME_SINKS_FRAME_SINK_OBSERVER_H_
+#define COMPONENTS_VIZ_SERVICE_FRAME_SINKS_FRAME_SINK_OBSERVER_H_
+
+namespace viz {
+
+class CompositorFrameSinkSupport;
+class FrameSinkId;
+
+class FrameSinkObserver {
+ public:
+  // Called when FrameSinkId is registered
+  virtual void OnRegisteredFrameSinkId(const FrameSinkId& frame_sink_id) = 0;
+
+  // Called when FrameSinkId is being invalidated
+  virtual void OnInvalidatedFrameSinkId(const FrameSinkId& frame_sink_id) = 0;
+
+  // Called when RootCompositorFrameSinkImpl is created
+  virtual void OnCreatedRootCompositorFrameSink(
+      const FrameSinkId& frame_sink_id) = 0;
+
+  // Called when CompositorFrameSinkImpl is created
+  virtual void OnCreatedCompositorFrameSink(
+      const FrameSinkId& frame_sink_id) = 0;
+
+  // Called when [Root]CompositorFrameSinkImpl is about to be destroyed
+  virtual void OnDestroyedCompositorFrameSink(
+      const FrameSinkId& frame_sink_id) = 0;
+
+  // Called when |parent_frame_sink_id| becomes a parent of
+  // |child_frame_sink_id|
+  virtual void OnRegisteredFrameSinkHierarchy(
+      const FrameSinkId& parent_frame_sink_id,
+      const FrameSinkId& child_frame_sink_id) = 0;
+
+  // Called when |parent_frame_sink_id| stops being a parent of
+  // |child_frame_sink_id|
+  virtual void OnUnregisteredFrameSinkHierarchy(
+      const FrameSinkId& parent_frame_sink_id,
+      const FrameSinkId& child_frame_sink_id) = 0;
+
+  // Called on creating of CompositorFrameSinkSupport
+  virtual void OnRegisteredCompositorFrameSinkSupport(
+      const FrameSinkId& frame_sink_id,
+      CompositorFrameSinkSupport* support) = 0;
+
+  // Called on destroying CompositorFrameSinkSupport
+  virtual void OnUnregisteredCompositorFrameSinkSupport(
+      const FrameSinkId& frame_sink_id) = 0;
+};
+
+}  // namespace viz
+
+#endif  // COMPONENTS_VIZ_SERVICE_FRAME_SINKS_FRAME_SINK_OBSERVER_H_
diff --git a/components/viz/service/gl/gpu_service_impl.cc b/components/viz/service/gl/gpu_service_impl.cc
index 06a030f..352a41d 100644
--- a/components/viz/service/gl/gpu_service_impl.cc
+++ b/components/viz/service/gl/gpu_service_impl.cc
@@ -43,9 +43,14 @@
 #include "media/mojo/services/mojo_jpeg_encode_accelerator_service.h"
 #include "media/mojo/services/mojo_video_encode_accelerator_provider.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
+#include "third_party/skia/include/gpu/GrContext.h"
+#include "third_party/skia/include/gpu/gl/GrGLAssembleInterface.h"
+#include "third_party/skia/include/gpu/gl/GrGLInterface.h"
+#include "ui/gl/gl_context.h"
 #include "ui/gl/gl_implementation.h"
 #include "ui/gl/gl_switches.h"
 #include "ui/gl/gpu_switching_manager.h"
+#include "ui/gl/init/create_gr_gl_interface.h"
 #include "ui/gl/init/gl_factory.h"
 #include "url/gurl.h"
 
@@ -122,7 +127,7 @@
       weak_ptr_factory_(this) {
   DCHECK(!io_runner_->BelongsToCurrentThread());
 #if defined(OS_CHROMEOS)
-  protected_buffer_manager_ = std::make_unique<arc::ProtectedBufferManager>();
+  protected_buffer_manager_ = new arc::ProtectedBufferManager();
 #endif  // defined(OS_CHROMEOS)
   weak_ptr_ = weak_ptr_factory_.GetWeakPtr();
 }
@@ -139,6 +144,15 @@
           FROM_HERE, base::Bind(&DestroyBinding, bindings_.get(), &wait))) {
     wait.Wait();
   }
+
+  // The sequence id and scheduler_ could be null for unit tests.
+  if (!skia_output_surface_sequence_id_.is_null()) {
+    DCHECK(scheduler_);
+    scheduler_->DestroySequence(skia_output_surface_sequence_id_);
+  }
+
+  gr_context_ = nullptr;
+  context_for_skia_ = nullptr;
   media_gpu_channel_manager_.reset();
   gpu_channel_manager_.reset();
   owned_sync_point_manager_.reset();
@@ -205,6 +219,9 @@
   scheduler_ = std::make_unique<gpu::Scheduler>(
       base::ThreadTaskRunnerHandle::Get(), sync_point_manager_);
 
+  skia_output_surface_sequence_id_ =
+      scheduler_->CreateSequence(gpu::SchedulingPriority::kHigh);
+
   // Defer creation of the render thread. This is to prevent it from handling
   // IPC messages before the sandbox has been enabled and all other necessary
   // initialization has succeeded.
@@ -230,6 +247,37 @@
   bindings_->AddBinding(this, std::move(request));
 }
 
+bool GpuServiceImpl::CreateGrContextIfNecessary(gl::GLSurface* surface) {
+  DCHECK(main_runner_->BelongsToCurrentThread());
+  DCHECK(surface);
+
+  if (!gr_context_) {
+    DCHECK(!context_for_skia_);
+    gl::GLContextAttribs attribs;
+    // TODO(penghuang) set attribs.
+    context_for_skia_ = gl::init::CreateGLContext(
+        gpu_channel_manager_->share_group(), surface, attribs);
+    DCHECK(context_for_skia_);
+    gpu_feature_info_.ApplyToGLContext(context_for_skia_.get());
+    if (!context_for_skia_->MakeCurrent(surface)) {
+      LOG(FATAL) << "Failed to make current.";
+      // TODO(penghuang): handle the failure.
+    }
+    auto native_interface =
+        GrGLMakeAssembledInterface(nullptr, [](void* ctx, const char name[]) {
+          return gl::GetGLProcAddress(name);
+        });
+    DCHECK(native_interface);
+
+    GrContextOptions options;
+    options.fExplicitlyAllocateGPUResources = GrContextOptions::Enable::kYes;
+    options.fUseGLBufferDataNullHint = GrContextOptions::Enable::kYes;
+    gr_context_ = GrContext::MakeGL(std::move(native_interface), options);
+    DCHECK(gr_context_);
+  }
+  return !!gr_context_;
+}
+
 gpu::ImageFactory* GpuServiceImpl::gpu_image_factory() {
   return gpu_memory_buffer_factory_
              ? gpu_memory_buffer_factory_->AsImageFactory()
@@ -291,10 +339,9 @@
 void GpuServiceImpl::CreateArcVideoDecodeAcceleratorOnMainThread(
     arc::mojom::VideoDecodeAcceleratorRequest vda_request) {
   DCHECK(main_runner_->BelongsToCurrentThread());
-  mojo::MakeStrongBinding(
-      std::make_unique<arc::GpuArcVideoDecodeAccelerator>(
-          gpu_preferences_, protected_buffer_manager_.get()),
-      std::move(vda_request));
+  mojo::MakeStrongBinding(std::make_unique<arc::GpuArcVideoDecodeAccelerator>(
+                              gpu_preferences_, protected_buffer_manager_),
+                          std::move(vda_request));
 }
 
 void GpuServiceImpl::CreateArcVideoEncodeAcceleratorOnMainThread(
@@ -310,7 +357,7 @@
   DCHECK(main_runner_->BelongsToCurrentThread());
   mojo::MakeStrongBinding(
       std::make_unique<arc::GpuArcProtectedBufferManagerProxy>(
-          protected_buffer_manager_.get()),
+          protected_buffer_manager_),
       std::move(pbm_request));
 }
 #endif  // defined(OS_CHROMEOS)
diff --git a/components/viz/service/gl/gpu_service_impl.h b/components/viz/service/gl/gpu_service_impl.h
index b14488a..fe3b098 100644
--- a/components/viz/service/gl/gpu_service_impl.h
+++ b/components/viz/service/gl/gpu_service_impl.h
@@ -7,6 +7,7 @@
 
 #include "base/callback.h"
 #include "base/compiler_specific.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/task/cancelable_task_tracker.h"
@@ -16,6 +17,7 @@
 #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
 #include "gpu/command_buffer/common/activity_flags.h"
 #include "gpu/command_buffer/service/gpu_preferences.h"
+#include "gpu/command_buffer/service/sequence_id.h"
 #include "gpu/config/gpu_info.h"
 #include "gpu/ipc/common/surface_handle.h"
 #include "gpu/ipc/service/gpu_channel.h"
@@ -26,8 +28,11 @@
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "services/viz/privileged/interfaces/gl/gpu_host.mojom.h"
 #include "services/viz/privileged/interfaces/gl/gpu_service.mojom.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
 #include "ui/gfx/native_widget_types.h"
 
+class GrContext;
+
 #if defined(OS_CHROMEOS)
 namespace arc {
 class ProtectedBufferManager;
@@ -69,6 +74,8 @@
                           base::WaitableEvent* shutdown_event = nullptr);
   void Bind(mojom::GpuServiceRequest request);
 
+  bool CreateGrContextIfNecessary(gl::GLSurface* surface);
+
   bool is_initialized() const { return !!gpu_host_; }
 
   media::MediaGpuChannelManager* media_gpu_channel_manager() {
@@ -93,6 +100,7 @@
   }
 
   gpu::SyncPointManager* sync_point_manager() { return sync_point_manager_; }
+  gpu::Scheduler* scheduler() { return scheduler_.get(); }
 
   gpu::GpuWatchdogThread* watchdog_thread() { return watchdog_thread_.get(); }
 
@@ -109,6 +117,12 @@
     return gpu_preferences_;
   }
 
+  gpu::SequenceId skia_output_surface_sequence_id() const {
+    return skia_output_surface_sequence_id_;
+  }
+  gl::GLContext* context_for_skia() { return context_for_skia_.get(); }
+  GrContext* gr_context() { return gr_context_.get(); }
+
  private:
   void RecordLogMessage(int severity,
                         size_t message_start,
@@ -215,6 +229,15 @@
 
   std::unique_ptr<gpu::Scheduler> scheduler_;
 
+  // sequence id for running tasks from SkiaOutputSurface;
+  gpu::SequenceId skia_output_surface_sequence_id_;
+
+  // A GLContext for |gr_context_|. It can only be accessed by Skia.
+  scoped_refptr<gl::GLContext> context_for_skia_;
+
+  // A GrContext for SkiaOutputSurface (maybe raster as well).
+  sk_sp<GrContext> gr_context_;
+
   // An event that will be signalled when we shutdown. On some platforms it
   // comes from external sources.
   std::unique_ptr<base::WaitableEvent> owned_shutdown_event_;
@@ -227,7 +250,7 @@
   std::unique_ptr<mojo::BindingSet<mojom::GpuService>> bindings_;
 
 #if defined(OS_CHROMEOS)
-  std::unique_ptr<arc::ProtectedBufferManager> protected_buffer_manager_;
+  scoped_refptr<arc::ProtectedBufferManager> protected_buffer_manager_;
 #endif  // defined(OS_CHROMEOS)
 
   base::WeakPtr<GpuServiceImpl> weak_ptr_;
diff --git a/components/viz/service/main/viz_main_impl.cc b/components/viz/service/main/viz_main_impl.cc
index 45ea1ea..82cb08d8 100644
--- a/components/viz/service/main/viz_main_impl.cc
+++ b/components/viz/service/main/viz_main_impl.cc
@@ -24,7 +24,7 @@
 #include "gpu/ipc/gpu_in_process_thread_service.h"
 #include "gpu/ipc/service/gpu_memory_buffer_factory.h"
 #include "gpu/ipc/service/gpu_watchdog_thread.h"
-#include "media/gpu/features.h"
+#include "media/gpu/buildflags.h"
 #include "services/metrics/public/cpp/delegating_ukm_recorder.h"
 #include "services/metrics/public/cpp/mojo_ukm_recorder.h"
 #include "services/metrics/public/mojom/constants.mojom.h"
diff --git a/components/wallpaper/BUILD.gn b/components/wallpaper/BUILD.gn
deleted file mode 100644
index b8e9d07e..0000000
--- a/components/wallpaper/BUILD.gn
+++ /dev/null
@@ -1,54 +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.
-
-component("wallpaper") {
-  sources = [
-    "wallpaper_color_calculator.cc",
-    "wallpaper_color_calculator.h",
-    "wallpaper_color_calculator_observer.h",
-    "wallpaper_color_extraction_result.h",
-    "wallpaper_color_profile.h",
-    "wallpaper_files_id.cc",
-    "wallpaper_files_id.h",
-    "wallpaper_info.h",
-    "wallpaper_resizer.cc",
-    "wallpaper_resizer.h",
-    "wallpaper_resizer_observer.h",
-  ]
-
-  defines = [ "WALLPAPER_IMPLEMENTATION" ]
-
-  public_deps = [
-    "//base",
-    "//skia",
-  ]
-  deps = [
-    "//components/prefs",
-    "//ui/gfx",
-    "//ui/gfx/geometry",
-    "//url",
-  ]
-  if (is_chromeos) {
-    deps += [
-      "//components/signin/core/account_id",
-      "//components/user_manager",
-    ]
-  }
-}
-
-source_set("unit_tests") {
-  testonly = true
-  sources = [
-    "wallpaper_color_calculator_unittest.cc",
-    "wallpaper_resizer_unittest.cc",
-  ]
-
-  deps = [
-    ":wallpaper",
-    "//base/test:test_support",
-    "//testing/gmock",
-    "//testing/gtest",
-    "//ui/gfx",
-  ]
-}
diff --git a/components/wallpaper/DEPS b/components/wallpaper/DEPS
deleted file mode 100644
index 8f911a0..0000000
--- a/components/wallpaper/DEPS
+++ /dev/null
@@ -1,12 +0,0 @@
-include_rules = [
-  "+components/prefs",
-  "+skia/ext",
-  "+third_party/skia/include",
-  "+ui/gfx",
-]
-
-specific_include_rules = {
-  "wallpaper_resizer_unittest\.cc": [
-    "+testing/gtest/include/gtest",
-  ],
-}
diff --git a/components/wallpaper/OWNERS b/components/wallpaper/OWNERS
deleted file mode 100644
index 663b89a..0000000
--- a/components/wallpaper/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-bshe@chromium.org
-wzang@chromium.org
-xdai@chromium.org
-
-# COMPONENT: UI>Shell>Wallpaper
diff --git a/components/wallpaper/wallpaper_color_calculator.cc b/components/wallpaper/wallpaper_color_calculator.cc
deleted file mode 100644
index 39f6f7a..0000000
--- a/components/wallpaper/wallpaper_color_calculator.cc
+++ /dev/null
@@ -1,166 +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 "components/wallpaper/wallpaper_color_calculator.h"
-
-#include <string>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/task_runner.h"
-#include "base/task_runner_util.h"
-#include "components/wallpaper/wallpaper_color_calculator_observer.h"
-#include "components/wallpaper/wallpaper_color_extraction_result.h"
-#include "ui/gfx/color_analysis.h"
-#include "ui/gfx/image/image_skia.h"
-
-using LumaRange = color_utils::LumaRange;
-using SaturationRange = color_utils::SaturationRange;
-
-namespace wallpaper {
-
-namespace {
-
-// The largest image size, in pixels, to synchronously calculate the prominent
-// color. This is a simple heuristic optimization because extraction on images
-// smaller than this should run very quickly, and offloading the task to another
-// thread would actually take longer.
-const int kMaxPixelsForSynchronousCalculation = 100;
-
-// Wrapper for color_utils::CalculateProminentColorsOfBitmap() that records
-// wallpaper specific metrics.
-//
-// NOTE: |image| is intentionally a copy to ensure it exists for the duration of
-// the calculation.
-std::vector<SkColor> CalculateWallpaperColor(
-    const gfx::ImageSkia image,
-    const std::vector<color_utils::ColorProfile> color_profiles) {
-  base::TimeTicks start_time = base::TimeTicks::Now();
-  const std::vector<SkColor> prominent_colors =
-      color_utils::CalculateProminentColorsOfBitmap(*image.bitmap(),
-                                                    color_profiles);
-
-  UMA_HISTOGRAM_TIMES("Ash.Wallpaper.ColorExtraction.Durations",
-                      base::TimeTicks::Now() - start_time);
-  WallpaperColorExtractionResult result = NUM_COLOR_EXTRACTION_RESULTS;
-  for (size_t i = 0; i < color_profiles.size(); ++i) {
-    bool is_result_transparent = prominent_colors[i] == SK_ColorTRANSPARENT;
-    if (color_profiles[i].saturation == SaturationRange::VIBRANT) {
-      switch (color_profiles[i].luma) {
-        case LumaRange::DARK:
-          result = is_result_transparent ? RESULT_DARK_VIBRANT_TRANSPARENT
-                                         : RESULT_DARK_VIBRANT_OPAQUE;
-          break;
-        case LumaRange::NORMAL:
-          result = is_result_transparent ? RESULT_NORMAL_VIBRANT_TRANSPARENT
-                                         : RESULT_NORMAL_VIBRANT_OPAQUE;
-          break;
-        case LumaRange::LIGHT:
-          result = is_result_transparent ? RESULT_LIGHT_VIBRANT_TRANSPARENT
-                                         : RESULT_LIGHT_VIBRANT_OPAQUE;
-          break;
-      }
-    } else {
-      switch (color_profiles[i].luma) {
-        case LumaRange::DARK:
-          result = is_result_transparent ? RESULT_DARK_MUTED_TRANSPARENT
-                                         : RESULT_DARK_MUTED_OPAQUE;
-          break;
-        case LumaRange::NORMAL:
-          result = is_result_transparent ? RESULT_NORMAL_MUTED_TRANSPARENT
-                                         : RESULT_NORMAL_MUTED_OPAQUE;
-          break;
-        case LumaRange::LIGHT:
-          result = is_result_transparent ? RESULT_LIGHT_MUTED_TRANSPARENT
-                                         : RESULT_LIGHT_MUTED_OPAQUE;
-          break;
-      }
-    }
-  }
-  DCHECK_NE(NUM_COLOR_EXTRACTION_RESULTS, result);
-  UMA_HISTOGRAM_ENUMERATION("Ash.Wallpaper.ColorExtractionResult2", result,
-                            NUM_COLOR_EXTRACTION_RESULTS);
-
-  return prominent_colors;
-}
-
-bool ShouldCalculateSync(const gfx::ImageSkia& image) {
-  return image.width() * image.height() <= kMaxPixelsForSynchronousCalculation;
-}
-
-}  // namespace
-
-WallpaperColorCalculator::WallpaperColorCalculator(
-    const gfx::ImageSkia& image,
-    const std::vector<color_utils::ColorProfile>& color_profiles,
-    scoped_refptr<base::TaskRunner> task_runner)
-    : image_(image),
-      color_profiles_(color_profiles),
-      task_runner_(std::move(task_runner)),
-      weak_ptr_factory_(this) {
-  prominent_colors_ =
-      std::vector<SkColor>(color_profiles_.size(), SK_ColorTRANSPARENT);
-}
-
-WallpaperColorCalculator::~WallpaperColorCalculator() = default;
-
-void WallpaperColorCalculator::AddObserver(
-    WallpaperColorCalculatorObserver* observer) {
-  observers_.AddObserver(observer);
-}
-
-void WallpaperColorCalculator::RemoveObserver(
-    WallpaperColorCalculatorObserver* observer) {
-  observers_.RemoveObserver(observer);
-}
-
-bool WallpaperColorCalculator::StartCalculation() {
-  if (ShouldCalculateSync(image_)) {
-    const std::vector<SkColor> prominent_colors =
-        CalculateWallpaperColor(image_, color_profiles_);
-    NotifyCalculationComplete(prominent_colors);
-    return true;
-  }
-
-  image_.MakeThreadSafe();
-  if (base::PostTaskAndReplyWithResult(
-          task_runner_.get(), FROM_HERE,
-          base::Bind(&CalculateWallpaperColor, image_, color_profiles_),
-          base::Bind(&WallpaperColorCalculator::OnAsyncCalculationComplete,
-                     weak_ptr_factory_.GetWeakPtr(), base::TimeTicks::Now()))) {
-    return true;
-  }
-
-  LOG(WARNING) << "PostSequencedWorkerTask failed. "
-               << "Wallpaper prominent colors may not be calculated.";
-
-  prominent_colors_ =
-      std::vector<SkColor>(color_profiles_.size(), SK_ColorTRANSPARENT);
-  return false;
-}
-
-void WallpaperColorCalculator::SetTaskRunnerForTest(
-    scoped_refptr<base::TaskRunner> task_runner) {
-  task_runner_ = task_runner;
-}
-
-void WallpaperColorCalculator::OnAsyncCalculationComplete(
-    base::TimeTicks async_start_time,
-    const std::vector<SkColor>& prominent_colors) {
-  UMA_HISTOGRAM_TIMES("Ash.Wallpaper.ColorExtraction.UserDelay",
-                      base::TimeTicks::Now() - async_start_time);
-  NotifyCalculationComplete(prominent_colors);
-}
-
-void WallpaperColorCalculator::NotifyCalculationComplete(
-    const std::vector<SkColor>& prominent_colors) {
-  prominent_colors_ = prominent_colors;
-  for (auto& observer : observers_)
-    observer.OnColorCalculationComplete();
-
-  // This could be deleted!
-}
-
-}  // namespace wallpaper
diff --git a/components/wallpaper/wallpaper_color_calculator.h b/components/wallpaper/wallpaper_color_calculator.h
deleted file mode 100644
index 6862dee..0000000
--- a/components/wallpaper/wallpaper_color_calculator.h
+++ /dev/null
@@ -1,89 +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 COMPONENTS_WALLPAPER_WALLPAPER_COLOR_CALCULATOR_H_
-#define COMPONENTS_WALLPAPER_WALLPAPER_COLOR_CALCULATOR_H_
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/observer_list.h"
-#include "base/time/time.h"
-#include "components/wallpaper/wallpaper_export.h"
-#include "third_party/skia/include/core/SkColor.h"
-#include "ui/gfx/image/image_skia.h"
-
-namespace base {
-class TaskRunner;
-}
-
-namespace color_utils {
-struct ColorProfile;
-}
-
-namespace wallpaper {
-class WallpaperColorCalculatorObserver;
-
-// Calculates colors based on a wallpaper image.
-class WALLPAPER_EXPORT WallpaperColorCalculator {
- public:
-  // |image|, |color_profiles| are the input parameters to the color calculation
-  // that is executed on the |task_runner|.
-  WallpaperColorCalculator(
-      const gfx::ImageSkia& image,
-      const std::vector<color_utils::ColorProfile>& color_profiles,
-      scoped_refptr<base::TaskRunner> task_runner);
-  ~WallpaperColorCalculator();
-
-  void AddObserver(WallpaperColorCalculatorObserver* observer);
-
-  void RemoveObserver(WallpaperColorCalculatorObserver* observer);
-
-  // Initiates the calculation and returns false if the calculation fails to be
-  // initiated. Observers may be notified synchronously or asynchronously.
-  // Callers should be aware that this will make |image_| read-only.
-  bool StartCalculation() WARN_UNUSED_RESULT;
-
-  std::vector<SkColor> prominent_colors() const { return prominent_colors_; }
-
-  void set_prominent_colors_for_test(
-      const std::vector<SkColor>& prominent_colors) {
-    prominent_colors_ = prominent_colors;
-  }
-
-  // Explicitly sets the |task_runner_| for testing.
-  void SetTaskRunnerForTest(scoped_refptr<base::TaskRunner> task_runner);
-
- private:
-  // Handles asynchronous calculation results. |async_start_time| is used to
-  // record duration metrics.
-  void OnAsyncCalculationComplete(base::TimeTicks async_start_time,
-                                  const std::vector<SkColor>& prominent_colors);
-
-  // Notifies observers that a color calulation has completed. Called on the
-  // same thread that constructed |this|.
-  void NotifyCalculationComplete(const std::vector<SkColor>& prominent_colors);
-
-  // The result of the color calculation.
-  std::vector<SkColor> prominent_colors_;
-
-  // The image to calculate colors from.
-  gfx::ImageSkia image_;
-
-  // The color profiles used to calculate colors.
-  std::vector<color_utils::ColorProfile> color_profiles_;
-
-  // The task runner to run the calculation on.
-  scoped_refptr<base::TaskRunner> task_runner_;
-
-  base::ObserverList<WallpaperColorCalculatorObserver> observers_;
-
-  base::WeakPtrFactory<WallpaperColorCalculator> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(WallpaperColorCalculator);
-};
-
-}  // namespace wallpaper
-
-#endif  // COMPONENTS_WALLPAPER_WALLPAPER_COLOR_CALCULATOR_H_
diff --git a/components/wallpaper/wallpaper_color_calculator_observer.h b/components/wallpaper/wallpaper_color_calculator_observer.h
deleted file mode 100644
index 45a701d..0000000
--- a/components/wallpaper/wallpaper_color_calculator_observer.h
+++ /dev/null
@@ -1,24 +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 COMPONENTS_WALLPAPER_WALLPAPER_COLOR_CALCULATOR_OBSERVER_H_
-#define COMPONENTS_WALLPAPER_WALLPAPER_COLOR_CALCULATOR_OBSERVER_H_
-
-#include "components/wallpaper/wallpaper_export.h"
-
-namespace wallpaper {
-
-// Observer for the WallpaperColorCalculator.
-class WALLPAPER_EXPORT WallpaperColorCalculatorObserver {
- public:
-  // Notified when a color calculation completes.
-  virtual void OnColorCalculationComplete() = 0;
-
- protected:
-  virtual ~WallpaperColorCalculatorObserver() {}
-};
-
-}  // namespace wallpaper
-
-#endif  // COMPONENTS_WALLPAPER_WALLPAPER_COLOR_CALCULATOR_OBSERVER_H_
diff --git a/components/wallpaper/wallpaper_color_calculator_unittest.cc b/components/wallpaper/wallpaper_color_calculator_unittest.cc
deleted file mode 100644
index 0245d09..0000000
--- a/components/wallpaper/wallpaper_color_calculator_unittest.cc
+++ /dev/null
@@ -1,251 +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 "components/wallpaper/wallpaper_color_calculator.h"
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/single_thread_task_runner.h"
-#include "base/test/histogram_tester.h"
-#include "base/test/null_task_runner.h"
-#include "base/test/test_mock_time_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "components/wallpaper/wallpaper_color_calculator_observer.h"
-#include "components/wallpaper/wallpaper_color_extraction_result.h"
-#include "skia/ext/platform_canvas.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/skia/include/core/SkColor.h"
-#include "ui/gfx/canvas.h"
-#include "ui/gfx/color_analysis.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/image/image_skia.h"
-
-using ::testing::ElementsAre;
-using ::testing::IsEmpty;
-
-namespace wallpaper {
-namespace {
-
-const SkColor kDefaultColor = SK_ColorTRANSPARENT;
-
-const SkColor kGray = SkColorSetRGB(10, 10, 10);
-
-const SkColor kVibrantGreen = SkColorSetRGB(25, 200, 25);
-
-// Image size that causes the WallpaperColorCalculator to synchronously extract
-// the prominent color.
-constexpr gfx::Size kSyncImageSize = gfx::Size(5, 5);
-
-// Image size that causes the WallpaperColorCalculator to asynchronously extract
-// the prominent color.
-constexpr gfx::Size kAsyncImageSize = gfx::Size(50, 50);
-
-class TestWallpaperColorCalculatorObserver
-    : public WallpaperColorCalculatorObserver {
- public:
-  TestWallpaperColorCalculatorObserver() {}
-
-  ~TestWallpaperColorCalculatorObserver() override {}
-
-  bool WasNotified() const { return notified_; }
-
-  // WallpaperColorCalculatorObserver:
-  void OnColorCalculationComplete() override { notified_ = true; }
-
- private:
-  bool notified_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(TestWallpaperColorCalculatorObserver);
-};
-
-// Returns an image that will yield a color using the LumaRange::NORMAL and
-// SaturationRange::VIBRANT values.
-gfx::ImageSkia CreateColorProducingImage(const gfx::Size& size) {
-  gfx::Canvas canvas(size, 1.0f, true);
-  canvas.DrawColor(kGray);
-  canvas.FillRect(gfx::Rect(0, 1, size.height(), 1), kVibrantGreen);
-  return gfx::ImageSkia::CreateFrom1xBitmap(canvas.GetBitmap());
-}
-
-// Returns an image that will not yield a color using the LumaRange::NORMAL and
-// SaturationRange::VIBRANT values.
-gfx::ImageSkia CreateNonColorProducingImage(const gfx::Size& size) {
-  gfx::Canvas canvas(size, 1.0f, true);
-  canvas.DrawColor(kGray);
-  return gfx::ImageSkia::CreateFrom1xBitmap(canvas.GetBitmap());
-}
-
-}  // namespace
-
-class WallPaperColorCalculatorTest : public testing::Test {
- public:
-  WallPaperColorCalculatorTest();
-  ~WallPaperColorCalculatorTest() override;
-
- protected:
-  // Installs the given |task_runner| globally and on the |calculator_| instance
-  // if it exists.
-  void InstallTaskRunner(
-      scoped_refptr<base::SingleThreadTaskRunner> task_runner);
-
-  // Creates a new |calculator_| for the given |image| and installs the current
-  // |task_runner_|.
-  void CreateCalculator(const gfx::ImageSkia& image);
-
-  std::unique_ptr<WallpaperColorCalculator> calculator_;
-
-  // Required for asynchronous calculations.
-  scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
-
-  TestWallpaperColorCalculatorObserver observer_;
-
-  base::HistogramTester histograms_;
-
- private:
-  // Required for asynchronous calculations, e.g. by PostTaskAndReplyImpl.
-  std::unique_ptr<base::ThreadTaskRunnerHandle> task_runner_handle_;
-
-  DISALLOW_COPY_AND_ASSIGN(WallPaperColorCalculatorTest);
-};
-
-WallPaperColorCalculatorTest::WallPaperColorCalculatorTest()
-    : task_runner_(new base::TestMockTimeTaskRunner()) {
-  CreateCalculator(CreateColorProducingImage(kAsyncImageSize));
-  InstallTaskRunner(task_runner_);
-}
-
-WallPaperColorCalculatorTest::~WallPaperColorCalculatorTest() {}
-
-void WallPaperColorCalculatorTest::InstallTaskRunner(
-    scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
-  task_runner_handle_.reset();
-  task_runner_handle_ =
-      std::make_unique<base::ThreadTaskRunnerHandle>(task_runner);
-  if (calculator_)
-    calculator_->SetTaskRunnerForTest(task_runner);
-}
-
-void WallPaperColorCalculatorTest::CreateCalculator(
-    const gfx::ImageSkia& image) {
-  std::vector<color_utils::ColorProfile> color_profiles;
-  color_profiles.emplace_back(color_utils::LumaRange::NORMAL,
-                              color_utils::SaturationRange::VIBRANT);
-  calculator_ = std::make_unique<WallpaperColorCalculator>(
-      image, color_profiles, task_runner_);
-  calculator_->AddObserver(&observer_);
-}
-
-// Used to group the asynchronous calculation tests.
-using WallPaperColorCalculatorAsyncTest = WallPaperColorCalculatorTest;
-
-TEST_F(WallPaperColorCalculatorAsyncTest, MetricsForSuccessfulExtraction) {
-  histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.Durations", 0);
-  histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.UserDelay", 0);
-  EXPECT_THAT(histograms_.GetAllSamples("Ash.Wallpaper.ColorExtractionResult2"),
-              IsEmpty());
-
-  EXPECT_TRUE(calculator_->StartCalculation());
-  task_runner_->RunUntilIdle();
-
-  histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.Durations", 1);
-  histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.UserDelay", 1);
-  EXPECT_THAT(histograms_.GetAllSamples("Ash.Wallpaper.ColorExtractionResult2"),
-              ElementsAre(base::Bucket(RESULT_NORMAL_VIBRANT_OPAQUE, 1)));
-}
-
-TEST_F(WallPaperColorCalculatorAsyncTest, MetricsWhenPostingTaskFails) {
-  scoped_refptr<base::NullTaskRunner> task_runner = new base::NullTaskRunner();
-  InstallTaskRunner(task_runner);
-
-  histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.Durations", 0);
-  histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.UserDelay", 0);
-  EXPECT_THAT(histograms_.GetAllSamples("Ash.Wallpaper.ColorExtractionResult2"),
-              IsEmpty());
-
-  EXPECT_FALSE(calculator_->StartCalculation());
-  task_runner_->RunUntilIdle();
-
-  histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.Durations", 0);
-  histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.UserDelay", 0);
-  EXPECT_THAT(histograms_.GetAllSamples("Ash.Wallpaper.ColorExtractionResult2"),
-              IsEmpty());
-
-  EXPECT_EQ(kDefaultColor, calculator_->prominent_colors()[0]);
-}
-
-TEST_F(WallPaperColorCalculatorAsyncTest,
-       ObserverNotifiedOnSuccessfulCalculation) {
-  EXPECT_FALSE(observer_.WasNotified());
-
-  EXPECT_TRUE(calculator_->StartCalculation());
-  EXPECT_FALSE(observer_.WasNotified());
-
-  task_runner_->RunUntilIdle();
-  EXPECT_TRUE(observer_.WasNotified());
-}
-
-TEST_F(WallPaperColorCalculatorAsyncTest, ColorUpdatedOnSuccessfulCalculation) {
-  std::vector<SkColor> colors = {kDefaultColor};
-  calculator_->set_prominent_colors_for_test(colors);
-
-  EXPECT_TRUE(calculator_->StartCalculation());
-  EXPECT_EQ(kDefaultColor, calculator_->prominent_colors()[0]);
-
-  task_runner_->RunUntilIdle();
-  EXPECT_NE(kDefaultColor, calculator_->prominent_colors()[0]);
-}
-
-TEST_F(WallPaperColorCalculatorAsyncTest,
-       NoCrashWhenCalculatorDestroyedBeforeTaskProcessing) {
-  EXPECT_TRUE(calculator_->StartCalculation());
-  calculator_.reset();
-
-  EXPECT_TRUE(task_runner_->HasPendingTask());
-
-  task_runner_->RunUntilIdle();
-  EXPECT_FALSE(observer_.WasNotified());
-  EXPECT_FALSE(task_runner_->HasPendingTask());
-}
-
-// Used to group the synchronous calculation tests.
-using WallPaperColorCalculatorSyncTest = WallPaperColorCalculatorTest;
-
-TEST_F(WallPaperColorCalculatorSyncTest, MetricsForSuccessfulExtraction) {
-  CreateCalculator(CreateColorProducingImage(kSyncImageSize));
-  calculator_->SetTaskRunnerForTest(nullptr);
-
-  histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.Durations", 0);
-  histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.UserDelay", 0);
-  EXPECT_THAT(histograms_.GetAllSamples("Ash.Wallpaper.ColorExtractionResult2"),
-              IsEmpty());
-
-  EXPECT_TRUE(calculator_->StartCalculation());
-
-  histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.Durations", 1);
-  histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.UserDelay", 0);
-  EXPECT_THAT(histograms_.GetAllSamples("Ash.Wallpaper.ColorExtractionResult2"),
-              ElementsAre(base::Bucket(RESULT_NORMAL_VIBRANT_OPAQUE, 1)));
-}
-
-TEST_F(WallPaperColorCalculatorSyncTest, MetricsForFailedExctraction) {
-  CreateCalculator(CreateNonColorProducingImage(kSyncImageSize));
-
-  histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.Durations", 0);
-  histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.UserDelay", 0);
-  EXPECT_THAT(histograms_.GetAllSamples("Ash.Wallpaper.ColorExtractionResult2"),
-              IsEmpty());
-
-  EXPECT_TRUE(calculator_->StartCalculation());
-
-  histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.Durations", 1);
-  histograms_.ExpectTotalCount("Ash.Wallpaper.ColorExtraction.UserDelay", 0);
-  EXPECT_THAT(histograms_.GetAllSamples("Ash.Wallpaper.ColorExtractionResult2"),
-              ElementsAre(base::Bucket(RESULT_NORMAL_VIBRANT_TRANSPARENT, 1)));
-}
-
-}  // namespace wallpaper
diff --git a/components/wallpaper/wallpaper_color_extraction_result.h b/components/wallpaper/wallpaper_color_extraction_result.h
deleted file mode 100644
index ebc7779..0000000
--- a/components/wallpaper/wallpaper_color_extraction_result.h
+++ /dev/null
@@ -1,45 +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 COMPONENTS_WALLPAPER_WALLPAPER_COLOR_EXTRACTION_RESULT_H_
-#define COMPONENTS_WALLPAPER_WALLPAPER_COLOR_EXTRACTION_RESULT_H_
-
-namespace wallpaper {
-
-// This enum is used to back a histogram, and should therefore be treated as
-// append-only.
-// For result, transparent indicates extraction failure and opaque indicates
-// extraction success.
-enum WallpaperColorExtractionResult {
-  // Transparent result on (dark, vibrant) color profile.
-  RESULT_DARK_VIBRANT_TRANSPARENT = 0,
-  // Opaque result on (dark, vibrant) color profile.
-  RESULT_DARK_VIBRANT_OPAQUE,
-  // Transparent result on (normal, vibrant) color profile.
-  RESULT_NORMAL_VIBRANT_TRANSPARENT,
-  // Opaque result on (normal, vibrant) color profile.
-  RESULT_NORMAL_VIBRANT_OPAQUE,
-  // Transparent result on (light, vibrant) color profile.
-  RESULT_LIGHT_VIBRANT_TRANSPARENT,
-  // Opaque result on (light, vibrant) color profile.
-  RESULT_LIGHT_VIBRANT_OPAQUE,
-  // Transparent result on (dark, muted) color profile.
-  RESULT_DARK_MUTED_TRANSPARENT,
-  // Opaque result on (dark, muted) color profile.
-  RESULT_DARK_MUTED_OPAQUE,
-  // Transparent result on (normal, muted) color profile.
-  RESULT_NORMAL_MUTED_TRANSPARENT,
-  // Opaque result on (normal, muted) color profile.
-  RESULT_NORMAL_MUTED_OPAQUE,
-  // Transparent result on (light, muted) color profile.
-  RESULT_LIGHT_MUTED_TRANSPARENT,
-  // Opaque result on (light, muted) color profile.
-  RESULT_LIGHT_MUTED_OPAQUE,
-
-  NUM_COLOR_EXTRACTION_RESULTS,
-};
-
-}  // namespace wallpaper
-
-#endif  // COMPONENTS_WALLPAPER_WALLPAPER_COLOR_EXTRACTION_RESULT_H_
diff --git a/components/wallpaper/wallpaper_color_profile.h b/components/wallpaper/wallpaper_color_profile.h
deleted file mode 100644
index 3112eec..0000000
--- a/components/wallpaper/wallpaper_color_profile.h
+++ /dev/null
@@ -1,25 +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 COMPONENTS_WALLPAPER_WALLPAPER_COLOR_PROFILE_H_
-#define COMPONENTS_WALLPAPER_WALLPAPER_COLOR_PROFILE_H_
-
-namespace wallpaper {
-
-// The color profile type, ordered as the color profiles applied in
-// ash::WallpaperController.
-enum class ColorProfileType {
-  DARK_VIBRANT = 0,
-  NORMAL_VIBRANT,
-  LIGHT_VIBRANT,
-  DARK_MUTED,
-  NORMAL_MUTED,
-  LIGHT_MUTED,
-
-  NUM_OF_COLOR_PROFILES,
-};
-
-}  // namespace wallpaper
-
-#endif  // COMPONENTS_WALLPAPER_WALLPAPER_COLOR_PROFILE_H_
diff --git a/components/wallpaper/wallpaper_export.h b/components/wallpaper/wallpaper_export.h
deleted file mode 100644
index 3fc352a..0000000
--- a/components/wallpaper/wallpaper_export.h
+++ /dev/null
@@ -1,32 +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.
-
-#ifndef COMPONENTS_WALLPAPER_EXPORT_H_
-#define COMPONENTS_WALLPAPER_EXPORT_H_
-
-// Defines WALLPAPER_EXPORT so that functionality implemented by the wallpaper
-// module can be exported to consumers.
-
-#if defined(COMPONENT_BUILD)
-#if defined(WIN32)
-
-#if defined(WALLPAPER_IMPLEMENTATION)
-#define WALLPAPER_EXPORT __declspec(dllexport)
-#else
-#define WALLPAPER_EXPORT __declspec(dllimport)
-#endif  // defined(WALLPAPER_IMPLEMENTATION)
-
-#else  // defined(WIN32)
-#if defined(WALLPAPER_IMPLEMENTATION)
-#define WALLPAPER_EXPORT __attribute__((visibility("default")))
-#else
-#define WALLPAPER_EXPORT
-#endif
-#endif
-
-#else  // defined(COMPONENT_BUILD)
-#define WALLPAPER_EXPORT
-#endif
-
-#endif  // COMPONENTS_WALLPAPER_EXPORT_H_
diff --git a/components/wallpaper/wallpaper_files_id.cc b/components/wallpaper/wallpaper_files_id.cc
deleted file mode 100644
index fce3c80d..0000000
--- a/components/wallpaper/wallpaper_files_id.cc
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/wallpaper/wallpaper_files_id.h"
-
-namespace wallpaper {
-
-WallpaperFilesId::WallpaperFilesId() {}
-
-WallpaperFilesId::WallpaperFilesId(const std::string& id) : id_(id) {}
-
-// static
-WallpaperFilesId WallpaperFilesId::FromString(const std::string& id) {
-  return WallpaperFilesId(id);
-}
-
-bool WallpaperFilesId::is_valid() const {
-  return !id_.empty();
-}
-
-}  // namespace wallpaper
diff --git a/components/wallpaper/wallpaper_files_id.h b/components/wallpaper/wallpaper_files_id.h
deleted file mode 100644
index 00fb1d0..0000000
--- a/components/wallpaper/wallpaper_files_id.h
+++ /dev/null
@@ -1,33 +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.
-
-#ifndef COMPONENTS_WALLPAPER_WALLPAPER_FILES_ID_H_
-#define COMPONENTS_WALLPAPER_WALLPAPER_FILES_ID_H_
-
-#include <string>
-
-#include "components/wallpaper/wallpaper_export.h"
-
-namespace wallpaper {
-
-class WALLPAPER_EXPORT WallpaperFilesId {
- public:
-  WallpaperFilesId();
-
-  // This should be used for deserialization only.
-  static WallpaperFilesId FromString(const std::string& data);
-
-  const std::string& id() const { return id_; }
-
-  // Returns true if id is not empty.
-  bool is_valid() const;
-
- private:
-  WallpaperFilesId(const std::string& id);
-  std::string id_;
-};
-
-}  // namespace wallpaper
-
-#endif  // COMPONENTS_WALLPAPER_WALLPAPER_FILES_ID_H_
diff --git a/components/wallpaper/wallpaper_info.h b/components/wallpaper/wallpaper_info.h
deleted file mode 100644
index 054faf7..0000000
--- a/components/wallpaper/wallpaper_info.h
+++ /dev/null
@@ -1,81 +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 COMPONENTS_WALLPAPER_WALLPAPER_INFO_H_
-#define COMPONENTS_WALLPAPER_WALLPAPER_INFO_H_
-
-#include "base/time/time.h"
-#include "components/wallpaper/wallpaper_export.h"
-
-namespace wallpaper {
-
-// This enum is used to define the buckets for an enumerated UMA histogram.
-// Hence,
-//   (a) existing enumerated constants should never be deleted or reordered,
-//   (b) new constants should only be appended at the end of the enumeration.
-enum WallpaperLayout {
-  // Center the wallpaper on the desktop without scaling it. The wallpaper
-  // may be cropped.
-  WALLPAPER_LAYOUT_CENTER,
-  // Scale the wallpaper (while preserving its aspect ratio) to cover the
-  // desktop; the wallpaper may be cropped.
-  WALLPAPER_LAYOUT_CENTER_CROPPED,
-  // Scale the wallpaper (without preserving its aspect ratio) to match the
-  // desktop's size.
-  WALLPAPER_LAYOUT_STRETCH,
-  // Tile the wallpaper over the background without scaling it.
-  WALLPAPER_LAYOUT_TILE,
-  // This must remain last.
-  NUM_WALLPAPER_LAYOUT,
-};
-
-// This enum is used to define the buckets for an enumerated UMA histogram.
-// Hence,
-//   (a) existing enumerated constants should never be deleted or reordered,
-//   (b) new constants should only be appended at the end of the enumeration.
-enum WallpaperType {
-  DAILY = 0,         // Surprise wallpaper. Changes once a day if enabled.
-  CUSTOMIZED = 1,    // Selected by user.
-  DEFAULT = 2,       // Default.
-  /* UNKNOWN = 3 */  // Removed.
-  ONLINE = 4,        // WallpaperInfo.location denotes an URL.
-  POLICY = 5,        // Controlled by policy, can't be changed by the user.
-  THIRDPARTY = 6,    // Current wallpaper is set by a third party app.
-  DEVICE = 7,        // Current wallpaper is the device policy controlled
-                     // wallpaper. It shows on the login screen if the device
-                     // is an enterprise managed device.
-  WALLPAPER_TYPE_COUNT = 8
-};
-
-struct WALLPAPER_EXPORT WallpaperInfo {
-  WallpaperInfo()
-      : layout(WALLPAPER_LAYOUT_CENTER), type(WALLPAPER_TYPE_COUNT) {}
-
-  WallpaperInfo(const std::string& in_location,
-                WallpaperLayout in_layout,
-                WallpaperType in_type,
-                const base::Time& in_date)
-      : location(in_location),
-        layout(in_layout),
-        type(in_type),
-        date(in_date) {}
-
-  ~WallpaperInfo() {}
-
-  bool operator==(const WallpaperInfo& other) const {
-    return (location == other.location) && (layout == other.layout) &&
-           (type == other.type);
-  }
-
-  // Either file name of migrated wallpaper including first directory level
-  // (corresponding to user wallpaper_files_id) or online wallpaper URL.
-  std::string location;
-  WallpaperLayout layout;
-  WallpaperType type;
-  base::Time date;
-};
-
-}  // namespace wallpaper
-
-#endif  // COMPONENTS_WALLPAPER_WALLPAPER_INFO_H_
diff --git a/components/wallpaper/wallpaper_resizer.cc b/components/wallpaper/wallpaper_resizer.cc
deleted file mode 100644
index 8dc729ad..0000000
--- a/components/wallpaper/wallpaper_resizer.cc
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/wallpaper/wallpaper_resizer.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/task_runner.h"
-#include "components/wallpaper/wallpaper_resizer_observer.h"
-#include "third_party/skia/include/core/SkImage.h"
-#include "ui/gfx/geometry/safe_integer_conversions.h"
-#include "ui/gfx/image/image_skia_rep.h"
-#include "ui/gfx/skia_util.h"
-
-namespace wallpaper {
-namespace {
-
-// Resizes |image| to |target_size| using |layout| and stores the
-// resulting bitmap at |resized_bitmap_out|.
-//
-// NOTE: |image| is intentionally a copy to ensure it exists for the duration of
-// the function.
-void Resize(const gfx::ImageSkia image,
-            const gfx::Size& target_size,
-            WallpaperLayout layout,
-            SkBitmap* resized_bitmap_out,
-            base::TaskRunner* task_runner) {
-  DCHECK(task_runner->RunsTasksInCurrentSequence());
-
-  SkBitmap orig_bitmap = *image.bitmap();
-  SkBitmap new_bitmap = orig_bitmap;
-
-  const int orig_width = orig_bitmap.width();
-  const int orig_height = orig_bitmap.height();
-  const int new_width = target_size.width();
-  const int new_height = target_size.height();
-
-  if (orig_width > new_width || orig_height > new_height) {
-    gfx::Rect wallpaper_rect(0, 0, orig_width, orig_height);
-    gfx::Size cropped_size = gfx::Size(std::min(new_width, orig_width),
-                                       std::min(new_height, orig_height));
-    switch (layout) {
-      case WALLPAPER_LAYOUT_CENTER:
-        wallpaper_rect.ClampToCenteredSize(cropped_size);
-        orig_bitmap.extractSubset(&new_bitmap,
-                                  gfx::RectToSkIRect(wallpaper_rect));
-        break;
-      case WALLPAPER_LAYOUT_TILE:
-        wallpaper_rect.set_size(cropped_size);
-        orig_bitmap.extractSubset(&new_bitmap,
-                                  gfx::RectToSkIRect(wallpaper_rect));
-        break;
-      case WALLPAPER_LAYOUT_STRETCH:
-        new_bitmap = skia::ImageOperations::Resize(
-            orig_bitmap, skia::ImageOperations::RESIZE_LANCZOS3, new_width,
-            new_height);
-        break;
-      case WALLPAPER_LAYOUT_CENTER_CROPPED:
-        if (orig_width > new_width && orig_height > new_height) {
-          // The dimension with the smallest ratio must be cropped, the other
-          // one is preserved. Both are set in gfx::Size cropped_size.
-          double horizontal_ratio =
-              static_cast<double>(new_width) / static_cast<double>(orig_width);
-          double vertical_ratio = static_cast<double>(new_height) /
-                                  static_cast<double>(orig_height);
-
-          if (vertical_ratio > horizontal_ratio) {
-            cropped_size = gfx::Size(
-                gfx::ToRoundedInt(new_width / vertical_ratio), orig_height);
-          } else {
-            cropped_size = gfx::Size(
-                orig_width, gfx::ToRoundedInt(new_height / horizontal_ratio));
-          }
-          wallpaper_rect.ClampToCenteredSize(cropped_size);
-          SkBitmap sub_image;
-          orig_bitmap.extractSubset(&sub_image,
-                                    gfx::RectToSkIRect(wallpaper_rect));
-          new_bitmap = skia::ImageOperations::Resize(
-              sub_image, skia::ImageOperations::RESIZE_LANCZOS3, new_width,
-              new_height);
-        }
-        break;
-      case NUM_WALLPAPER_LAYOUT:
-        NOTREACHED();
-        break;
-    }
-  }
-
-  *resized_bitmap_out = new_bitmap;
-  resized_bitmap_out->setImmutable();
-}
-
-}  // namespace
-
-// static
-uint32_t WallpaperResizer::GetImageId(const gfx::ImageSkia& image) {
-  const gfx::ImageSkiaRep& image_rep = image.GetRepresentation(1.0f);
-  return image_rep.is_null() ? 0 : image_rep.sk_bitmap().getGenerationID();
-}
-
-WallpaperResizer::WallpaperResizer(const gfx::ImageSkia& image,
-                                   const gfx::Size& target_size,
-                                   const WallpaperInfo& wallpaper_info,
-                                   scoped_refptr<base::TaskRunner> task_runner)
-    : image_(image),
-      original_image_id_(GetImageId(image_)),
-      target_size_(target_size),
-      wallpaper_info_(wallpaper_info),
-      task_runner_(std::move(task_runner)),
-      weak_ptr_factory_(this) {
-  image_.MakeThreadSafe();
-}
-
-WallpaperResizer::~WallpaperResizer() {
-}
-
-void WallpaperResizer::StartResize() {
-  start_calculation_time_ = base::TimeTicks::Now();
-
-  SkBitmap* resized_bitmap = new SkBitmap;
-  if (!task_runner_->PostTaskAndReply(
-          FROM_HERE,
-          base::Bind(&Resize, image_, target_size_, wallpaper_info_.layout,
-                     resized_bitmap, base::RetainedRef(task_runner_)),
-          base::Bind(&WallpaperResizer::OnResizeFinished,
-                     weak_ptr_factory_.GetWeakPtr(),
-                     base::Owned(resized_bitmap)))) {
-    LOG(WARNING) << "PostSequencedWorkerTask failed. "
-                 << "Wallpaper may not be resized.";
-  }
-}
-
-void WallpaperResizer::AddObserver(WallpaperResizerObserver* observer) {
-  observers_.AddObserver(observer);
-}
-
-void WallpaperResizer::RemoveObserver(WallpaperResizerObserver* observer) {
-  observers_.RemoveObserver(observer);
-}
-
-void WallpaperResizer::OnResizeFinished(SkBitmap* resized_bitmap) {
-  image_ = gfx::ImageSkia::CreateFrom1xBitmap(*resized_bitmap);
-  UMA_HISTOGRAM_TIMES("Ash.Wallpaper.TimeSpentResizing",
-                      base::TimeTicks::Now() - start_calculation_time_);
-
-  for (auto& observer : observers_)
-    observer.OnWallpaperResized();
-}
-
-}  // namespace wallpaper
diff --git a/components/wallpaper/wallpaper_resizer.h b/components/wallpaper/wallpaper_resizer.h
deleted file mode 100644
index 8a3db49..0000000
--- a/components/wallpaper/wallpaper_resizer.h
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_WALLPAPER_WALLPAPER_RESIZER_H_
-#define COMPONENTS_WALLPAPER_WALLPAPER_RESIZER_H_
-
-#include <stdint.h>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/observer_list.h"
-#include "base/time/time.h"
-#include "components/wallpaper/wallpaper_info.h"
-#include "components/wallpaper/wallpaper_resizer_observer.h"
-#include "skia/ext/image_operations.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/image/image_skia.h"
-
-namespace base {
-class TaskRunner;
-}
-
-namespace wallpaper {
-
-class WallpaperResizerObserver;
-
-// Stores the current wallpaper data and resize it to |target_size| if needed.
-class WALLPAPER_EXPORT WallpaperResizer {
- public:
-  // Returns a unique identifier corresponding to |image|, suitable for
-  // comparison against the value returned by original_image_id(). If the image
-  // is modified, its ID will change.
-  static uint32_t GetImageId(const gfx::ImageSkia& image);
-
-  WallpaperResizer(const gfx::ImageSkia& image,
-                   const gfx::Size& target_size,
-                   const WallpaperInfo& info,
-                   scoped_refptr<base::TaskRunner> task_runner);
-
-  ~WallpaperResizer();
-
-  const gfx::ImageSkia& image() const { return image_; }
-  uint32_t original_image_id() const { return original_image_id_; }
-  const WallpaperInfo& wallpaper_info() const { return wallpaper_info_; }
-
-  // Called on the UI thread to run Resize() on the task runner and post an
-  // OnResizeFinished() task back to the UI thread on completion.
-  void StartResize();
-
-  // Add/Remove observers.
-  void AddObserver(WallpaperResizerObserver* observer);
-  void RemoveObserver(WallpaperResizerObserver* observer);
-
- private:
-  // Copies |resized_bitmap| to |image_| and notifies observers after Resize()
-  // has finished running.
-  void OnResizeFinished(SkBitmap* resized_bitmap);
-
-  base::ObserverList<WallpaperResizerObserver> observers_;
-
-  // Image that should currently be used for wallpaper. It initially
-  // contains the original image and is updated to contain the resized
-  // image by OnResizeFinished().
-  gfx::ImageSkia image_;
-
-  // Unique identifier corresponding to the original (i.e. pre-resize) |image_|.
-  uint32_t original_image_id_;
-
-  gfx::Size target_size_;
-
-  const WallpaperInfo wallpaper_info_;
-
-  // The time that StartResize() was last called. Used for recording timing
-  // metrics.
-  base::TimeTicks start_calculation_time_;
-
-  scoped_refptr<base::TaskRunner> task_runner_;
-
-  base::WeakPtrFactory<WallpaperResizer> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(WallpaperResizer);
-};
-
-}  // namespace wallpaper
-
-#endif  // COMPONENTS_WALLPAPER_WALLPAPER_RESIZER_H_
diff --git a/components/wallpaper/wallpaper_resizer_observer.h b/components/wallpaper/wallpaper_resizer_observer.h
deleted file mode 100644
index 5e3d7ca..0000000
--- a/components/wallpaper/wallpaper_resizer_observer.h
+++ /dev/null
@@ -1,23 +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.
-
-#ifndef COMPONENTS_WALLPAPER_WALLPAPER_RESIZER_OBSERVER_H_
-#define COMPONENTS_WALLPAPER_WALLPAPER_RESIZER_OBSERVER_H_
-
-#include "components/wallpaper/wallpaper_export.h"
-
-namespace wallpaper {
-
-class WALLPAPER_EXPORT WallpaperResizerObserver {
- public:
-  // Invoked when the wallpaper is resized.
-  virtual void OnWallpaperResized() = 0;
-
- protected:
-  virtual ~WallpaperResizerObserver() {}
-};
-
-}  // namespace wallpaper
-
-#endif  // COMPONENTS_WALLPAPER_WALLPAPER_RESIZER_OBSERVER_H_
diff --git a/components/wallpaper/wallpaper_resizer_unittest.cc b/components/wallpaper/wallpaper_resizer_unittest.cc
deleted file mode 100644
index 295c656fc..0000000
--- a/components/wallpaper/wallpaper_resizer_unittest.cc
+++ /dev/null
@@ -1,172 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/wallpaper/wallpaper_resizer.h"
-
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/threading/thread.h"
-#include "components/wallpaper/wallpaper_resizer_observer.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/image/image_skia_rep.h"
-
-namespace {
-
-const int kTestImageWidth = 5;
-const int kTestImageHeight = 2;
-const int kTargetWidth = 1;
-const int kTargetHeight = 1;
-const uint32_t kExpectedCenter = 0x02020202u;
-const uint32_t kExpectedCenterCropped = 0x03030303u;
-const uint32_t kExpectedStretch = 0x04040404u;
-const uint32_t kExpectedTile = 0;
-
-gfx::ImageSkia CreateTestImage(const gfx::Size& size) {
-  SkBitmap src;
-  int w = size.width();
-  int h = size.height();
-  src.allocN32Pixels(w, h);
-
-  // Fill bitmap with data.
-  for (int y = 0; y < h; ++y) {
-    for (int x = 0; x < w; ++x) {
-      const uint8_t component = static_cast<uint8_t>(y * w + x);
-      const SkColor pixel =
-          SkColorSetARGB(component, component, component, component);
-      *(src.getAddr32(x, y)) = pixel;
-    }
-  }
-
-  gfx::ImageSkia image = gfx::ImageSkia::CreateFrom1xBitmap(src);
-  return image;
-}
-
-bool IsColor(const gfx::ImageSkia& image, const uint32_t expect) {
-  EXPECT_EQ(image.width(), kTargetWidth);
-  EXPECT_EQ(image.height(), kTargetHeight);
-  return *image.bitmap()->getAddr32(0, 0) == expect;
-}
-
-}  // namespace
-
-namespace wallpaper {
-
-class WallpaperResizerTest : public testing::Test,
-                             public WallpaperResizerObserver {
- public:
-  WallpaperResizerTest() : worker_thread_("WallpaperResizerTest") {}
-  ~WallpaperResizerTest() override {}
-
-  void SetUp() override {
-    ASSERT_TRUE(worker_thread_.Start());
-  }
-
-  gfx::ImageSkia Resize(const gfx::ImageSkia& image,
-                        const gfx::Size& target_size,
-                        WallpaperLayout layout) {
-    std::unique_ptr<WallpaperResizer> resizer;
-    resizer.reset(new WallpaperResizer(
-        image, target_size,
-        wallpaper::WallpaperInfo("", layout, DEFAULT,
-                                 base::Time::Now().LocalMidnight()),
-        task_runner()));
-    resizer->AddObserver(this);
-    resizer->StartResize();
-    WaitForResize();
-    resizer->RemoveObserver(this);
-    return resizer->image();
-  }
-
-  scoped_refptr<base::TaskRunner> task_runner() {
-    return worker_thread_.task_runner();
-  }
-
-  void WaitForResize() {
-    active_runloop_ = std::make_unique<base::RunLoop>();
-    active_runloop_->Run();
-  }
-
-  void OnWallpaperResized() override { active_runloop_->Quit(); }
-
- private:
-  base::MessageLoop message_loop_;
-  std::unique_ptr<base::RunLoop> active_runloop_;
-  base::Thread worker_thread_;
-
-  DISALLOW_COPY_AND_ASSIGN(WallpaperResizerTest);
-};
-
-TEST_F(WallpaperResizerTest, BasicResize) {
-  // Keeps in sync with WallpaperLayout enum.
-  WallpaperLayout layouts[4] = {
-      WALLPAPER_LAYOUT_CENTER,
-      WALLPAPER_LAYOUT_CENTER_CROPPED,
-      WALLPAPER_LAYOUT_STRETCH,
-      WALLPAPER_LAYOUT_TILE,
-  };
-  const int length = arraysize(layouts);
-
-  for (int i = 0; i < length; i++) {
-    WallpaperLayout layout = layouts[i];
-    gfx::ImageSkia small_image(gfx::ImageSkiaRep(gfx::Size(10, 20), 1.0f));
-
-    gfx::ImageSkia resized_small =
-        Resize(small_image, gfx::Size(800, 600), layout);
-    EXPECT_EQ(10, resized_small.width());
-    EXPECT_EQ(20, resized_small.height());
-
-    gfx::ImageSkia large_image(gfx::ImageSkiaRep(gfx::Size(1000, 1000), 1.0f));
-    gfx::ImageSkia resized_large =
-        Resize(large_image, gfx::Size(800, 600), layout);
-    EXPECT_EQ(800, resized_large.width());
-    EXPECT_EQ(600, resized_large.height());
-  }
-}
-
-// Test for crbug.com/244629. "CENTER_CROPPED generates the same image as
-// STRETCH layout"
-TEST_F(WallpaperResizerTest, AllLayoutDifferent) {
-  gfx::ImageSkia image =
-      CreateTestImage(gfx::Size(kTestImageWidth, kTestImageHeight));
-
-  gfx::Size target_size = gfx::Size(kTargetWidth, kTargetHeight);
-  gfx::ImageSkia center = Resize(image, target_size, WALLPAPER_LAYOUT_CENTER);
-
-  gfx::ImageSkia center_cropped =
-      Resize(image, target_size, WALLPAPER_LAYOUT_CENTER_CROPPED);
-
-  gfx::ImageSkia stretch = Resize(image, target_size, WALLPAPER_LAYOUT_STRETCH);
-
-  gfx::ImageSkia tile = Resize(image, target_size, WALLPAPER_LAYOUT_TILE);
-
-  EXPECT_TRUE(IsColor(center, kExpectedCenter));
-  EXPECT_TRUE(IsColor(center_cropped, kExpectedCenterCropped));
-  EXPECT_TRUE(IsColor(stretch, kExpectedStretch));
-  EXPECT_TRUE(IsColor(tile, kExpectedTile));
-}
-
-TEST_F(WallpaperResizerTest, ImageId) {
-  gfx::ImageSkia image =
-      CreateTestImage(gfx::Size(kTestImageWidth, kTestImageHeight));
-
-  // Create a WallpaperResizer and check that it reports an original image ID
-  // both pre- and post-resize that matches the ID returned by GetImageId().
-  WallpaperResizer resizer(image, gfx::Size(10, 20),
-                           WallpaperInfo("", WALLPAPER_LAYOUT_STRETCH, DEFAULT,
-                                         base::Time::Now().LocalMidnight()),
-                           task_runner());
-  EXPECT_EQ(WallpaperResizer::GetImageId(image), resizer.original_image_id());
-  resizer.AddObserver(this);
-  resizer.StartResize();
-  WaitForResize();
-  resizer.RemoveObserver(this);
-  EXPECT_EQ(WallpaperResizer::GetImageId(image), resizer.original_image_id());
-}
-
-}  // namespace ash
diff --git a/content/BUILD.gn b/content/BUILD.gn
index 2092909..62be6fcc 100644
--- a/content/BUILD.gn
+++ b/content/BUILD.gn
@@ -100,7 +100,7 @@
     set_sources_assignment_filter(sources_assignment_filter)
     deps = [
       "//base",
-      "//media:media_features",
+      "//media:media_buildflags",
       "//sandbox:sandbox_features",
       "//sandbox/linux:sandbox",
       "//services/service_manager/sandbox",
diff --git a/content/app/BUILD.gn b/content/app/BUILD.gn
index 19447fb..9a4425d 100644
--- a/content/app/BUILD.gn
+++ b/content/app/BUILD.gn
@@ -67,7 +67,7 @@
     ]
   }
 
-  if (is_linux && enable_plugins) {
+  if (!is_multi_dll_chrome && enable_plugins) {
     content_app_deps += [ "//content/ppapi_plugin:ppapi_plugin_sources" ]
   }
 
diff --git a/content/app/content_main_runner.cc b/content/app/content_main_runner.cc
index 49231a6..84e2469 100644
--- a/content/app/content_main_runner.cc
+++ b/content/app/content_main_runner.cc
@@ -55,7 +55,7 @@
 #include "content/public/common/zygote_buildflags.h"
 #include "gin/v8_initializer.h"
 #include "media/base/media.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "ppapi/features/features.h"
 #include "services/service_manager/embedder/switches.h"
 #include "services/service_manager/sandbox/sandbox_type.h"
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index af2a65f..35f189b 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -96,13 +96,13 @@
     "//gpu/command_buffer/client:raster_interface",
     "//gpu/ipc/common:gpu_preferences_util",
     "//gpu/ipc/host",
-    "//gpu/vulkan:features",
+    "//gpu/vulkan:buildflags",
     "//media",
-    "//media:media_features",
+    "//media:media_buildflags",
     "//media/capture",
     "//media/midi",
     "//media/midi:mojo",
-    "//media/mojo:features",
+    "//media/mojo:buildflags",
     "//media/mojo/clients:jpeg_decode_accelerator",
     "//media/mojo/interfaces",
     "//media/mojo/interfaces:constants",
@@ -711,8 +711,6 @@
     "download/download_resource_handler.h",
     "download/download_utils.cc",
     "download/download_utils.h",
-    "download/download_worker.cc",
-    "download/download_worker.h",
     "download/drag_download_file.cc",
     "download/drag_download_file.h",
     "download/drag_download_util.cc",
@@ -739,6 +737,8 @@
     "download/save_types.h",
     "download/url_downloader.cc",
     "download/url_downloader.h",
+    "download/url_downloader_factory.cc",
+    "download/url_downloader_factory.h",
     "field_trial_recorder.cc",
     "field_trial_recorder.h",
     "file_url_loader_factory.cc",
@@ -966,6 +966,8 @@
     "loader/mime_sniffing_resource_handler.h",
     "loader/mojo_async_resource_handler.cc",
     "loader/mojo_async_resource_handler.h",
+    "loader/navigation_loader_interceptor.cc",
+    "loader/navigation_loader_interceptor.h",
     "loader/navigation_metrics.cc",
     "loader/navigation_metrics.h",
     "loader/navigation_resource_handler.cc",
@@ -1021,8 +1023,6 @@
     "loader/upload_data_stream_builder.h",
     "loader/url_loader_factory_impl.cc",
     "loader/url_loader_factory_impl.h",
-    "loader/url_loader_request_handler.cc",
-    "loader/url_loader_request_handler.h",
     "loader/wake_lock_resource_throttle.cc",
     "loader/wake_lock_resource_throttle.h",
     "loader_delegate_impl.cc",
@@ -1685,8 +1685,6 @@
     "web_package/web_package_request_handler.h",
     "websockets/websocket_handshake_request_info_impl.cc",
     "websockets/websocket_handshake_request_info_impl.h",
-    "websockets/websocket_impl.cc",
-    "websockets/websocket_impl.h",
     "websockets/websocket_manager.cc",
     "websockets/websocket_manager.h",
     "webui/content_web_ui_controller_factory.cc",
diff --git a/content/browser/accessibility/accessibility_ui.cc b/content/browser/accessibility/accessibility_ui.cc
index 8beb189..945acc0 100644
--- a/content/browser/accessibility/accessibility_ui.cc
+++ b/content/browser/accessibility/accessibility_ui.cc
@@ -229,19 +229,21 @@
 
   web_ui()->RegisterMessageCallback(
       "toggleAccessibility",
-      base::Bind(&AccessibilityUIMessageHandler::ToggleAccessibility,
-                 base::Unretained(this)));
+      base::BindRepeating(&AccessibilityUIMessageHandler::ToggleAccessibility,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
-      "setGlobalFlag", base::Bind(&AccessibilityUIMessageHandler::SetGlobalFlag,
-                                  base::Unretained(this)));
+      "setGlobalFlag",
+      base::BindRepeating(&AccessibilityUIMessageHandler::SetGlobalFlag,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "requestWebContentsTree",
-      base::Bind(&AccessibilityUIMessageHandler::RequestWebContentsTree,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &AccessibilityUIMessageHandler::RequestWebContentsTree,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       "requestNativeUITree",
-      base::Bind(&AccessibilityUIMessageHandler::RequestNativeUITree,
-                 base::Unretained(this)));
+      base::BindRepeating(&AccessibilityUIMessageHandler::RequestNativeUITree,
+                          base::Unretained(this)));
 }
 
 void AccessibilityUIMessageHandler::ToggleAccessibility(
diff --git a/content/browser/accessibility/fullscreen_browsertest.cc b/content/browser/accessibility/fullscreen_browsertest.cc
index e22667f..dbc3358 100644
--- a/content/browser/accessibility/fullscreen_browsertest.cc
+++ b/content/browser/accessibility/fullscreen_browsertest.cc
@@ -106,7 +106,9 @@
   EXPECT_EQ(1, CountLinks(manager->GetRoot()));
 }
 
-IN_PROC_BROWSER_TEST_F(AccessibilityFullscreenBrowserTest, InsideIFrame) {
+// Fails flakily on all platforms: crbug.com/825735
+IN_PROC_BROWSER_TEST_F(AccessibilityFullscreenBrowserTest,
+                       DISABLED_InsideIFrame) {
   ASSERT_TRUE(embedded_test_server()->Start());
 
   FakeFullscreenDelegate delegate;
diff --git a/content/browser/android/content_view_core.cc b/content/browser/android/content_view_core.cc
index e6bcafb..7d3fcdd 100644
--- a/content/browser/android/content_view_core.cc
+++ b/content/browser/android/content_view_core.cc
@@ -93,14 +93,6 @@
     window->AddChild(view);
 }
 
-base::android::ScopedJavaLocalRef<jobject>
-ContentViewCore::GetJavaWindowAndroid(JNIEnv* env,
-                                      const JavaParamRef<jobject>& obj) {
-  if (!GetWindowAndroid())
-    return ScopedJavaLocalRef<jobject>();
-  return GetWindowAndroid()->GetJavaObject();
-}
-
 void ContentViewCore::OnJavaContentViewCoreDestroyed(
     JNIEnv* env,
     const JavaParamRef<jobject>& obj) {
@@ -256,15 +248,6 @@
     rwhv->SetMultiTouchZoomSupportEnabled(enabled);
 }
 
-void ContentViewCore::OnTouchDown(
-    const base::android::ScopedJavaLocalRef<jobject>& event) {
-  JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
-    return;
-  Java_ContentViewCoreImpl_onTouchDown(env, obj, event);
-}
-
 void ContentViewCore::SendOrientationChangeEventInternal() {
   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
   if (rwhv)
diff --git a/content/browser/android/content_view_core.h b/content/browser/android/content_view_core.h
index 85033fe..1eca6c6 100644
--- a/content/browser/android/content_view_core.h
+++ b/content/browser/android/content_view_core.h
@@ -38,10 +38,6 @@
   // Methods called from Java via JNI
   // --------------------------------------------------------------------------
 
-  base::android::ScopedJavaLocalRef<jobject> GetJavaWindowAndroid(
-      JNIEnv* env,
-      const base::android::JavaParamRef<jobject>& obj);
-
   void UpdateWindowAndroid(
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& obj,
@@ -80,18 +76,9 @@
                    const base::android::JavaParamRef<jobject>& obj,
                    jfloat dipScale);
 
-  // --------------------------------------------------------------------------
-  // Methods called from native code
-  // --------------------------------------------------------------------------
-
-  void OnTouchDown(const base::android::ScopedJavaLocalRef<jobject>& event);
-
   ui::ViewAndroid* GetViewAndroid() const;
 
  private:
-  class ContentViewUserData;
-
-  friend class ContentViewUserData;
 
   // WebContentsObserver implementation.
   void RenderViewReady() override;
diff --git a/content/browser/android/gesture_listener_manager.cc b/content/browser/android/gesture_listener_manager.cc
index abd3413..2de2a33 100644
--- a/content/browser/android/gesture_listener_manager.cc
+++ b/content/browser/android/gesture_listener_manager.cc
@@ -195,6 +195,15 @@
       viewport.width(), viewport.height(), top_shown_pix, top_changed);
 }
 
+void GestureListenerManager::UpdateOnTouchDown() {
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+  if (obj.is_null())
+    return;
+
+  Java_GestureListenerManagerImpl_updateOnTouchDown(env, obj);
+}
+
 void GestureListenerManager::UpdateRenderProcessConnection(
     RenderWidgetHostViewAndroid* old_rwhva,
     RenderWidgetHostViewAndroid* new_rwhva) {
diff --git a/content/browser/android/gesture_listener_manager.h b/content/browser/android/gesture_listener_manager.h
index 4923986..0302fb1 100644
--- a/content/browser/android/gesture_listener_manager.h
+++ b/content/browser/android/gesture_listener_manager.h
@@ -49,6 +49,7 @@
                         const float content_offset,
                         const float top_shown_pix,
                         bool top_changed);
+  void UpdateOnTouchDown();
 
   // RendetWidgetHostConnector implementation.
   void UpdateRenderProcessConnection(
diff --git a/content/browser/android/ime_adapter_android.cc b/content/browser/android/ime_adapter_android.cc
index a27bfd20..a6292112 100644
--- a/content/browser/android/ime_adapter_android.cc
+++ b/content/browser/android/ime_adapter_android.cc
@@ -85,12 +85,11 @@
   // Do not check |background_color|.
   std::vector<ui::ImeTextSpan>* ime_text_spans =
       reinterpret_cast<std::vector<ui::ImeTextSpan>*>(ime_text_spans_ptr);
-  ime_text_spans->push_back(
-      ui::ImeTextSpan(ui::ImeTextSpan::Type::kComposition,
-                      static_cast<unsigned>(start), static_cast<unsigned>(end),
-                      SK_ColorTRANSPARENT, ui::ImeTextSpan::Thickness::kNone,
-                      static_cast<unsigned>(background_color),
-                      SK_ColorTRANSPARENT, std::vector<std::string>()));
+  ime_text_spans->push_back(ui::ImeTextSpan(
+      ui::ImeTextSpan::Type::kComposition, static_cast<unsigned>(start),
+      static_cast<unsigned>(end), ui::ImeTextSpan::Thickness::kNone,
+      static_cast<unsigned>(background_color), SK_ColorTRANSPARENT,
+      std::vector<std::string>()));
 }
 
 // Callback from Java to convert SuggestionSpan data to a
@@ -116,11 +115,12 @@
       reinterpret_cast<std::vector<ui::ImeTextSpan>*>(ime_text_spans_ptr);
   std::vector<std::string> suggestions_vec;
   AppendJavaStringArrayToStringVector(env, suggestions, &suggestions_vec);
-  ime_text_spans->push_back(ui::ImeTextSpan(
+  ui::ImeTextSpan ime_text_span = ui::ImeTextSpan(
       type, static_cast<unsigned>(start), static_cast<unsigned>(end),
-      static_cast<unsigned>(underline_color),
       ui::ImeTextSpan::Thickness::kThick, SK_ColorTRANSPARENT,
-      static_cast<unsigned>(suggestion_highlight_color), suggestions_vec));
+      static_cast<unsigned>(suggestion_highlight_color), suggestions_vec);
+  ime_text_span.underline_color = static_cast<unsigned>(underline_color);
+  ime_text_spans->push_back(ime_text_span);
 }
 
 // Callback from Java to convert UnderlineSpan data to a
@@ -136,9 +136,8 @@
       reinterpret_cast<std::vector<ui::ImeTextSpan>*>(ime_text_spans_ptr);
   ime_text_spans->push_back(ui::ImeTextSpan(
       ui::ImeTextSpan::Type::kComposition, static_cast<unsigned>(start),
-      static_cast<unsigned>(end), SK_ColorBLACK,
-      ui::ImeTextSpan::Thickness::kThin, SK_ColorTRANSPARENT,
-      SK_ColorTRANSPARENT, std::vector<std::string>()));
+      static_cast<unsigned>(end), ui::ImeTextSpan::Thickness::kThin,
+      SK_ColorTRANSPARENT, SK_ColorTRANSPARENT, std::vector<std::string>()));
 }
 
 ImeAdapterAndroid::ImeAdapterAndroid(JNIEnv* env,
@@ -195,6 +194,14 @@
   Java_ImeAdapterImpl_updateAfterViewSizeChanged(env, obj);
 }
 
+void ImeAdapterAndroid::UpdateOnTouchDown() {
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jobject> obj = java_ime_adapter_.get(env);
+  if (obj.is_null())
+    return;
+  Java_ImeAdapterImpl_updateOnTouchDown(env, obj);
+}
+
 void ImeAdapterAndroid::UpdateFrameInfo(
     const gfx::SelectionBound& selection_start,
     float dip_scale,
@@ -258,10 +265,10 @@
 
   // Default to plain underline if we didn't find any span that we care about.
   if (ime_text_spans.empty()) {
-    ime_text_spans.push_back(ui::ImeTextSpan(
-        ui::ImeTextSpan::Type::kComposition, 0, text16.length(), SK_ColorBLACK,
-        ui::ImeTextSpan::Thickness::kThin, SK_ColorTRANSPARENT,
-        SK_ColorTRANSPARENT, std::vector<std::string>()));
+    ime_text_spans.push_back(
+        ui::ImeTextSpan(ui::ImeTextSpan::Type::kComposition, 0, text16.length(),
+                        ui::ImeTextSpan::Thickness::kThin, SK_ColorTRANSPARENT,
+                        SK_ColorTRANSPARENT, std::vector<std::string>()));
   }
 
   // relative_cursor_pos is as described in the Android API for
@@ -382,10 +389,10 @@
     return;
 
   std::vector<ui::ImeTextSpan> ime_text_spans;
-  ime_text_spans.push_back(ui::ImeTextSpan(
-      ui::ImeTextSpan::Type::kComposition, 0, end - start, SK_ColorBLACK,
-      ui::ImeTextSpan::Thickness::kThin, SK_ColorTRANSPARENT,
-      SK_ColorTRANSPARENT, std::vector<std::string>()));
+  ime_text_spans.push_back(
+      ui::ImeTextSpan(ui::ImeTextSpan::Type::kComposition, 0, end - start,
+                      ui::ImeTextSpan::Thickness::kThin, SK_ColorTRANSPARENT,
+                      SK_ColorTRANSPARENT, std::vector<std::string>()));
 
   rfh->GetFrameInputHandler()->SetCompositionFromExistingText(start, end,
                                                               ime_text_spans);
diff --git a/content/browser/android/ime_adapter_android.h b/content/browser/android/ime_adapter_android.h
index 58891af..2b16c70 100644
--- a/content/browser/android/ime_adapter_android.h
+++ b/content/browser/android/ime_adapter_android.h
@@ -106,6 +106,7 @@
 
   void UpdateState(const TextInputState& state);
   void UpdateAfterViewSizeChanged();
+  void UpdateOnTouchDown();
 
   void AdvanceFocusInForm(JNIEnv*,
                           const base::android::JavaParamRef<jobject>&,
diff --git a/content/browser/appcache/appcache_internals_ui.cc b/content/browser/appcache/appcache_internals_ui.cc
index b5f06aba..a2324fc 100644
--- a/content/browser/appcache/appcache_internals_ui.cc
+++ b/content/browser/appcache/appcache_internals_ui.cc
@@ -332,19 +332,20 @@
     : WebUIController(web_ui), weak_ptr_factory_(this) {
   web_ui->RegisterMessageCallback(
       kRequestGetAllAppCacheInfo,
-      base::Bind(&AppCacheInternalsUI::GetAllAppCache, AsWeakPtr()));
+      base::BindRepeating(&AppCacheInternalsUI::GetAllAppCache, AsWeakPtr()));
 
   web_ui->RegisterMessageCallback(
       kRequestDeleteAppCache,
-      base::Bind(&AppCacheInternalsUI::DeleteAppCache, AsWeakPtr()));
+      base::BindRepeating(&AppCacheInternalsUI::DeleteAppCache, AsWeakPtr()));
 
   web_ui->RegisterMessageCallback(
       kRequestGetAppCacheDetails,
-      base::Bind(&AppCacheInternalsUI::GetAppCacheDetails, AsWeakPtr()));
+      base::BindRepeating(&AppCacheInternalsUI::GetAppCacheDetails,
+                          AsWeakPtr()));
 
   web_ui->RegisterMessageCallback(
       kRequestGetFileDetails,
-      base::Bind(&AppCacheInternalsUI::GetFileDetails, AsWeakPtr()));
+      base::BindRepeating(&AppCacheInternalsUI::GetFileDetails, AsWeakPtr()));
 
   WebUIDataSource* source =
       WebUIDataSource::Create(kChromeUIAppCacheInternalsHost);
diff --git a/content/browser/appcache/appcache_request_handler.cc b/content/browser/appcache/appcache_request_handler.cc
index ff638ab..ac87c2f9 100644
--- a/content/browser/appcache/appcache_request_handler.cc
+++ b/content/browser/appcache/appcache_request_handler.cc
@@ -602,9 +602,9 @@
     network::mojom::URLLoaderClientRequest* client_request,
     ThrottlingURLLoader* url_loader) {
   // The sync interface of this method is inherited from the
-  // URLLoaderRequestHandler class. The LoaderCallback created here is invoked
-  // synchronously in fallback cases, and only when there really is a loader
-  // to start.
+  // NavigationLoaderInterceptor class. The LoaderCallback created here is
+  // invoked synchronously in fallback cases, and only when there really is
+  // a loader to start.
   bool was_called = false;
   loader_callback_ = base::BindOnce(
       [](network::mojom::URLLoaderPtr* loader,
diff --git a/content/browser/appcache/appcache_request_handler.h b/content/browser/appcache/appcache_request_handler.h
index 96ecfa5..9f79c30 100644
--- a/content/browser/appcache/appcache_request_handler.h
+++ b/content/browser/appcache/appcache_request_handler.h
@@ -17,7 +17,7 @@
 #include "content/browser/appcache/appcache_host.h"
 #include "content/browser/appcache/appcache_request_handler.h"
 #include "content/browser/appcache/appcache_service_impl.h"
-#include "content/browser/loader/url_loader_request_handler.h"
+#include "content/browser/loader/navigation_loader_interceptor.h"
 #include "content/browser/url_loader_factory_getter.h"
 #include "content/common/content_export.h"
 #include "content/public/common/resource_type.h"
@@ -50,7 +50,7 @@
       public AppCacheHost::Observer,
       public AppCacheServiceImpl::Observer,
       public AppCacheStorage::Delegate,
-      public URLLoaderRequestHandler {
+      public NavigationLoaderInterceptor {
  public:
   ~AppCacheRequestHandler() override;
 
@@ -80,7 +80,7 @@
 
   // NetworkService loading
 
-  // URLLoaderRequestHandler overrides - main resource loading.
+  // NavigationLoaderInterceptor overrides - main resource loading.
   // These methods are used by the NavigationURLLoaderNetworkService.
   // Internally they use same methods used by the network library based impl,
   // MaybeLoadResource and MaybeLoadFallbackForResponse.
diff --git a/content/browser/appcache/appcache_url_loader_job.cc b/content/browser/appcache/appcache_url_loader_job.cc
index a791fb1..c8df8fa 100644
--- a/content/browser/appcache/appcache_url_loader_job.cc
+++ b/content/browser/appcache/appcache_url_loader_job.cc
@@ -138,7 +138,7 @@
 AppCacheURLLoaderJob::AppCacheURLLoaderJob(
     AppCacheURLLoaderRequest* appcache_request,
     AppCacheStorage* storage,
-    URLLoaderRequestHandler::LoaderCallback loader_callback)
+    NavigationLoaderInterceptor::LoaderCallback loader_callback)
     : storage_(storage->GetWeakPtr()),
       start_time_tick_(base::TimeTicks::Now()),
       cache_id_(kAppCacheNoCacheId),
diff --git a/content/browser/appcache/appcache_url_loader_job.h b/content/browser/appcache/appcache_url_loader_job.h
index c7a79ed..f64748d 100644
--- a/content/browser/appcache/appcache_url_loader_job.h
+++ b/content/browser/appcache/appcache_url_loader_job.h
@@ -15,7 +15,7 @@
 #include "content/browser/appcache/appcache_request_handler.h"
 #include "content/browser/appcache/appcache_response.h"
 #include "content/browser/appcache/appcache_storage.h"
-#include "content/browser/loader/url_loader_request_handler.h"
+#include "content/browser/loader/navigation_loader_interceptor.h"
 #include "content/common/content_export.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/system/data_pipe.h"
@@ -68,9 +68,10 @@
   // AppCacheRequestHandler::CreateJob() creates this instance.
   friend class AppCacheRequestHandler;
 
-  AppCacheURLLoaderJob(AppCacheURLLoaderRequest* appcache_request,
-                       AppCacheStorage* storage,
-                       URLLoaderRequestHandler::LoaderCallback loader_callback);
+  AppCacheURLLoaderJob(
+      AppCacheURLLoaderRequest* appcache_request,
+      AppCacheStorage* storage,
+      NavigationLoaderInterceptor::LoaderCallback loader_callback);
 
   // Invokes the loader callback which is expected to setup the mojo binding.
   void CallLoaderCallback();
@@ -121,7 +122,7 @@
 
   // The Callback to be invoked in the network service land to indicate if
   // the resource request can be serviced via the AppCache.
-  URLLoaderRequestHandler::LoaderCallback loader_callback_;
+  NavigationLoaderInterceptor::LoaderCallback loader_callback_;
 
   // The AppCacheRequest instance, used to inform the loader job about range
   // request headers. Not owned by this class.
diff --git a/content/browser/browser_context.cc b/content/browser/browser_context.cc
index 8537bf4..91f87bb 100644
--- a/content/browser/browser_context.cc
+++ b/content/browser/browser_context.cc
@@ -382,6 +382,14 @@
 
 // static
 void BrowserContext::NotifyWillBeDestroyed(BrowserContext* browser_context) {
+  // Make sure NotifyWillBeDestroyed is idempotent.  This helps facilitate the
+  // pattern where NotifyWillBeDestroyed is called from *both*
+  // ShellBrowserContext and its derived classes (e.g.
+  // LayoutTestBrowserContext).
+  if (browser_context->was_notify_will_be_destroyed_called_)
+    return;
+  browser_context->was_notify_will_be_destroyed_called_ = true;
+
   // Service Workers must shutdown before the browser context is destroyed,
   // since they keep render process hosts alive and the codebase assumes that
   // render process hosts die before their profile (browser context) dies.
@@ -585,6 +593,8 @@
   DCHECK(!GetUserData(kStoragePartitionMapKeyName))
       << "StoragePartitionMap is not shut down properly";
 
+  DCHECK(was_notify_will_be_destroyed_called_);
+
 #if BUILDFLAG(ENABLE_WEBRTC)
   WebRtcEventLogger* const logger = WebRtcEventLogger::Get();
   if (logger) {
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index 796b8c1..1db7eb7 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -37,7 +37,6 @@
 #include "base/synchronization/waitable_event.h"
 #include "base/system_monitor/system_monitor.h"
 #include "base/task_scheduler/initialization_util.h"
-#include "base/threading/thread.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
@@ -55,7 +54,6 @@
 #include "components/viz/service/display_embedder/compositing_mode_reporter_impl.h"
 #include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
 #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
-#include "content/browser/browser_process_sub_thread.h"
 #include "content/browser/browser_thread_impl.h"
 #include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/compositor/gpu_process_transport_factory.h"
@@ -74,6 +72,7 @@
 #include "content/browser/leveldb_wrapper_impl.h"
 #include "content/browser/loader/resource_dispatcher_host_impl.h"
 #include "content/browser/loader_delegate_impl.h"
+#include "content/browser/media/capture/audio_mirroring_manager.h"
 #include "content/browser/media/media_internals.h"
 #include "content/browser/memory/memory_coordinator_impl.h"
 #include "content/browser/memory/swap_metrics_delegate_uma.h"
@@ -106,15 +105,15 @@
 #include "content/public/common/service_names.mojom.h"
 #include "content/public/common/zygote_buildflags.h"
 #include "device/gamepad/gamepad_service.h"
-#include "gpu/vulkan/features.h"
+#include "gpu/vulkan/buildflags.h"
 #include "media/audio/audio_manager.h"
 #include "media/audio/audio_system.h"
 #include "media/audio/audio_thread_impl.h"
 #include "media/base/media.h"
 #include "media/base/user_input_monitor.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "media/midi/midi_service.h"
-#include "media/mojo/features.h"
+#include "media/mojo/buildflags.h"
 #include "mojo/edk/embedder/embedder.h"
 #include "mojo/edk/embedder/scoped_ipc_support.h"
 #include "net/base/network_change_notifier.h"
@@ -372,11 +371,10 @@
 MSVC_DISABLE_OPTIMIZE()
 MSVC_PUSH_DISABLE_WARNING(4748)
 
-NOINLINE void ResetThread_IO(
-    std::unique_ptr<BrowserProcessSubThread> io_thread) {
-  volatile int line_number = __LINE__;
-  io_thread.reset();
-  CHECK_GT(line_number, 0);
+NOINLINE void ResetThread_IO(std::unique_ptr<BrowserProcessSubThread> thread) {
+  volatile int inhibit_comdat = __LINE__;
+  ALLOW_UNUSED_LOCAL(inhibit_comdat);
+  thread.reset();
 }
 
 MSVC_POP_WARNING()
@@ -1006,13 +1004,11 @@
         *task_scheduler_init_params.get());
   }
 
-  // The thread used for BrowserThread::IO is created in
-  // |PostMainMessageLoopStart()|, but it's only tagged as BrowserThread::IO
-  // here in order to prevent any code from statically posting to it before
-  // CreateThreads() (as such maintaining the invariant that PreCreateThreads()
-  // et al. "happen-before" BrowserThread::IO is "brought up").
+  // |io_thread_| is created by |PostMainMessageLoopStart()|, but its
+  // full initialization is deferred until this point because it requires
+  // several dependencies we don't want to depend on so early in startup.
   DCHECK(io_thread_);
-  io_thread_->RegisterAsBrowserThread();
+  io_thread_->InitIOThreadDelegate();
 
   created_threads_ = true;
   return result_code_;
@@ -1250,12 +1246,9 @@
   TRACE_EVENT0("startup", "BrowserMainLoop::InitializeMainThread");
   base::PlatformThread::SetName("CrBrowserMain");
 
-  // Register the main thread. The main thread's task runner should already have
-  // been initialized in MainMessageLoopStart() (or before if
-  // MessageLoop::current() was externally provided).
-  DCHECK(base::ThreadTaskRunnerHandle::IsSet());
-  main_thread_.reset(new BrowserThreadImpl(
-      BrowserThread::UI, base::ThreadTaskRunnerHandle::Get()));
+  // Register the main thread by instantiating it, but don't call any methods.
+  main_thread_.reset(
+      new BrowserThreadImpl(BrowserThread::UI, base::MessageLoop::current()));
 }
 
 int BrowserMainLoop::BrowserThreadsStarted() {
@@ -1427,7 +1420,7 @@
         "startup",
         "BrowserMainLoop::BrowserThreadsStarted::InitUserInputMonitor");
     user_input_monitor_ = media::UserInputMonitor::Create(
-        io_thread_->task_runner(), base::ThreadTaskRunnerHandle::Get());
+        io_thread_->task_runner(), main_thread_->task_runner());
   }
 
   {
@@ -1447,7 +1440,7 @@
 #endif
   ui::Clipboard::SetAllowedThreads(allowed_clipboard_threads);
 
-  if (GpuDataManagerImpl::GetInstance()->GpuAccessAllowed(nullptr) &&
+  if (GpuDataManagerImpl::GetInstance()->GpuProcessStartAllowed() &&
       !established_gpu_channel && always_uses_gpu && browser_is_viz_host) {
     TRACE_EVENT_INSTANT0("gpu", "Post task to launch GPU process",
                          TRACE_EVENT_SCOPE_THREAD);
@@ -1577,10 +1570,9 @@
   options.priority = base::ThreadPriority::DISPLAY;
 #endif
 
-  io_thread_ = std::make_unique<BrowserProcessSubThread>(BrowserThread::IO);
-
+  io_thread_.reset(new BrowserProcessSubThread(BrowserThread::IO));
   if (!io_thread_->StartWithOptions(options))
-    LOG(FATAL) << "Failed to start BrowserThread::IO";
+    LOG(FATAL) << "Failed to start the browser thread: IO";
 }
 
 void BrowserMainLoop::InitializeMojo() {
@@ -1730,6 +1722,12 @@
   }
   CHECK(audio_manager_);
 
+  AudioMirroringManager* const mirroring_manager =
+      AudioMirroringManager::GetInstance();
+  audio_manager_->SetDiverterCallbacks(
+      mirroring_manager->GetAddDiverterCallback(),
+      mirroring_manager->GetRemoveDiverterCallback());
+
   TRACE_EVENT_INSTANT0("startup", "Starting Audio service task runner",
                        TRACE_EVENT_SCOPE_THREAD);
   audio_service_runner_->StartWithTaskRunner(audio_manager_->GetTaskRunner());
diff --git a/content/browser/browser_main_loop.h b/content/browser/browser_main_loop.h
index 95fe392..c5311b7 100644
--- a/content/browser/browser_main_loop.h
+++ b/content/browser/browser_main_loop.h
@@ -13,8 +13,9 @@
 #include "base/memory/ref_counted.h"
 #include "base/timer/timer.h"
 #include "build/build_config.h"
+#include "content/browser/browser_process_sub_thread.h"
 #include "content/public/browser/browser_main_runner.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "services/viz/public/interfaces/compositing/compositing_mode_watcher.mojom.h"
 #include "ui/base/ui_features.h"
@@ -91,7 +92,6 @@
 namespace content {
 class BrowserMainParts;
 class BrowserOnlineStateObserver;
-class BrowserProcessSubThread;
 class BrowserThreadImpl;
 class LoaderDelegateImpl;
 class MediaStreamManager;
@@ -243,10 +243,7 @@
 
   void MainMessageLoopRun();
 
-  // Initializes |io_thread_|. It will not be promoted to BrowserThread::IO
-  // until CreateThreads().
   void InitializeIOThread();
-
   void InitializeMojo();
   base::FilePath GetStartupTraceFileName(
       const base::CommandLine& command_line) const;
@@ -288,7 +285,6 @@
   std::unique_ptr<base::MessageLoop> main_message_loop_;
 
   // Members initialized in |PostMainMessageLoopStart()| -----------------------
-  std::unique_ptr<BrowserProcessSubThread> io_thread_;
   std::unique_ptr<base::SystemMonitor> system_monitor_;
   std::unique_ptr<base::PowerMonitor> power_monitor_;
   std::unique_ptr<base::HighResolutionTimerManager> hi_res_timer_manager_;
@@ -339,6 +335,9 @@
       gpu_data_manager_visual_proxy_;
 #endif
 
+  // Members initialized in |CreateThreads()| ----------------------------------
+  std::unique_ptr<BrowserProcessSubThread> io_thread_;
+
   // Members initialized in |BrowserThreadsStarted()| --------------------------
   std::unique_ptr<ServiceManagerContext> service_manager_context_;
   std::unique_ptr<mojo::edk::ScopedIPCSupport> mojo_ipc_support_;
diff --git a/content/browser/browser_main_loop_unittest.cc b/content/browser/browser_main_loop_unittest.cc
index 728331b..61ec07ae 100644
--- a/content/browser/browser_main_loop_unittest.cc
+++ b/content/browser/browser_main_loop_unittest.cc
@@ -9,7 +9,6 @@
 #include "base/sys_info.h"
 #include "base/task_scheduler/task_scheduler.h"
 #include "base/test/scoped_command_line.h"
-#include "content/browser/browser_thread_impl.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/main_function_params.h"
diff --git a/content/browser/browser_main_runner.cc b/content/browser/browser_main_runner.cc
index b20f816..2563426 100644
--- a/content/browser/browser_main_runner.cc
+++ b/content/browser/browser_main_runner.cc
@@ -16,7 +16,6 @@
 #include "base/run_loop.h"
 #include "base/sampling_heap_profiler/sampling_heap_profiler.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/synchronization/atomic_flag.h"
 #include "base/time/time.h"
 #include "base/trace_event/heap_profiler_allocation_context_tracker.h"
 #include "base/trace_event/trace_event.h"
diff --git a/content/browser/browser_plugin/browser_plugin_guest.cc b/content/browser/browser_plugin/browser_plugin_guest.cc
index 5eaa8006..d892fc4f 100644
--- a/content/browser/browser_plugin/browser_plugin_guest.cc
+++ b/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -61,25 +61,6 @@
 
 namespace content {
 
-namespace {
-
-std::vector<ui::ImeTextSpan> ConvertToUiImeTextSpan(
-    const std::vector<blink::WebImeTextSpan>& ime_text_spans) {
-  std::vector<ui::ImeTextSpan> ui_ime_text_spans;
-  for (const auto& ime_text_span : ime_text_spans) {
-    ui_ime_text_spans.emplace_back(ui::ImeTextSpan(
-        ConvertWebImeTextSpanTypeToUiType(ime_text_span.type),
-        ime_text_span.start_offset, ime_text_span.end_offset,
-        ime_text_span.underline_color,
-        ConvertUiImeTextSpanThicknessToUiThickness(ime_text_span.thickness),
-        ime_text_span.background_color,
-        ime_text_span.suggestion_highlight_color, ime_text_span.suggestions));
-  }
-  return ui_ime_text_spans;
-}
-
-};  // namespace
-
 class BrowserPluginGuest::EmbedderVisibilityObserver
     : public WebContentsObserver {
  public:
@@ -913,7 +894,7 @@
     int browser_plugin_instance_id,
     const BrowserPluginHostMsg_SetComposition_Params& params) {
   std::vector<ui::ImeTextSpan> ui_ime_text_spans =
-      ConvertToUiImeTextSpan(params.ime_text_spans);
+      ConvertBlinkImeTextSpansToUiImeTextSpans(params.ime_text_spans);
   GetWebContents()
       ->GetRenderViewHost()
       ->GetWidget()
@@ -930,7 +911,7 @@
     const gfx::Range& replacement_range,
     int relative_cursor_pos) {
   std::vector<ui::ImeTextSpan> ui_ime_text_spans =
-      ConvertToUiImeTextSpan(ime_text_spans);
+      ConvertBlinkImeTextSpansToUiImeTextSpans(ime_text_spans);
   GetWebContents()
       ->GetRenderViewHost()
       ->GetWidget()
diff --git a/content/browser/browser_process_sub_thread.cc b/content/browser/browser_process_sub_thread.cc
index 9efb2d3..71f1396 100644
--- a/content/browser/browser_process_sub_thread.cc
+++ b/content/browser/browser_process_sub_thread.cc
@@ -4,165 +4,66 @@
 
 #include "content/browser/browser_process_sub_thread.h"
 
-#include "base/compiler_specific.h"
+#include "base/debug/leak_tracker.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/trace_event/memory_dump_manager.h"
+#include "build/build_config.h"
 #include "content/browser/browser_child_process_host_impl.h"
-#include "content/browser/browser_thread_impl.h"
 #include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
 #include "content/browser/notification_service_impl.h"
-#include "content/public/browser/browser_thread_delegate.h"
 #include "net/url_request/url_fetcher.h"
 #include "net/url_request/url_request.h"
 
-#if defined(OS_ANDROID)
-#include "base/android/jni_android.h"
-#endif
-
 #if defined(OS_WIN)
 #include "base/win/scoped_com_initializer.h"
 #endif
 
 namespace content {
 
-namespace {
-BrowserThreadDelegate* g_io_thread_delegate = nullptr;
-}  // namespace
-
-// static
-void BrowserThread::SetIOThreadDelegate(BrowserThreadDelegate* delegate) {
-  // |delegate| can only be set/unset while BrowserThread::IO isn't up.
-  DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::IO));
-  // and it cannot be set twice.
-  DCHECK(!g_io_thread_delegate || !delegate);
-
-  g_io_thread_delegate = delegate;
-}
-
 BrowserProcessSubThread::BrowserProcessSubThread(BrowserThread::ID identifier)
-    : base::Thread(BrowserThreadImpl::GetThreadName(identifier)),
-      identifier_(identifier) {
-  // Not bound to creation thread.
-  DETACH_FROM_THREAD(browser_thread_checker_);
-}
+    : BrowserThreadImpl(identifier) {}
+
+BrowserProcessSubThread::BrowserProcessSubThread(
+    BrowserThread::ID identifier,
+    base::MessageLoop* message_loop)
+    : BrowserThreadImpl(identifier, message_loop) {}
 
 BrowserProcessSubThread::~BrowserProcessSubThread() {
   Stop();
 }
 
-void BrowserProcessSubThread::RegisterAsBrowserThread() {
-  DCHECK(IsRunning());
-
-  DCHECK(!browser_thread_);
-  browser_thread_.reset(new BrowserThreadImpl(identifier_, task_runner()));
-
-  // Unretained(this) is safe as |this| outlives its underlying thread.
-  task_runner()->PostTask(
-      FROM_HERE,
-      base::BindOnce(
-          &BrowserProcessSubThread::CompleteInitializationOnBrowserThread,
-          Unretained(this)));
-}
-
-void BrowserProcessSubThread::AllowBlockingForTesting() {
-  DCHECK(!IsRunning());
-  is_blocking_allowed_for_testing_ = true;
-}
-
 void BrowserProcessSubThread::Init() {
-  DCHECK_CALLED_ON_VALID_THREAD(browser_thread_checker_);
-
 #if defined(OS_WIN)
-  com_initializer_ = std::make_unique<base::win::ScopedCOMInitializer>();
+  com_initializer_.reset(new base::win::ScopedCOMInitializer());
 #endif
 
-  if (!is_blocking_allowed_for_testing_) {
-    base::DisallowBlocking();
-    base::DisallowBaseSyncPrimitives();
-  }
-}
+  notification_service_.reset(new NotificationServiceImpl());
 
-void BrowserProcessSubThread::Run(base::RunLoop* run_loop) {
-  DCHECK_CALLED_ON_VALID_THREAD(browser_thread_checker_);
+  BrowserThreadImpl::Init();
 
-#if defined(OS_ANDROID)
-  // Not to reset thread name to "Thread-???" by VM, attach VM with thread name.
-  // Though it may create unnecessary VM thread objects, keeping thread name
-  // gives more benefit in debugging in the platform.
-  if (!thread_name().empty()) {
-    base::android::AttachCurrentThreadWithName(thread_name());
-  }
-#endif
-
-  switch (identifier_) {
-    case BrowserThread::UI:
-      // The main thread is usually promoted as the UI thread and doesn't go
-      // through Run() but some tests do run a separate UI thread.
-      UIThreadRun(run_loop);
-      break;
-    case BrowserThread::IO:
-      IOThreadRun(run_loop);
-      return;
-    case BrowserThread::ID_COUNT:
-      NOTREACHED();
-      break;
+  if (BrowserThread::CurrentlyOn(BrowserThread::IO)) {
+    // Though this thread is called the "IO" thread, it actually just routes
+    // messages around; it shouldn't be allowed to perform any blocking disk
+    // I/O.
+    base::ThreadRestrictions::SetIOAllowed(false);
+    base::ThreadRestrictions::DisallowWaiting();
   }
 }
 
 void BrowserProcessSubThread::CleanUp() {
-  DCHECK_CALLED_ON_VALID_THREAD(browser_thread_checker_);
-
-  // Run extra cleanup if this thread represents BrowserThread::IO.
   if (BrowserThread::CurrentlyOn(BrowserThread::IO))
-    IOThreadCleanUp();
+    IOThreadPreCleanUp();
 
-  if (identifier_ == BrowserThread::IO && g_io_thread_delegate)
-    g_io_thread_delegate->CleanUp();
+  BrowserThreadImpl::CleanUp();
 
   notification_service_.reset();
 
 #if defined(OS_WIN)
   com_initializer_.reset();
 #endif
-
-  browser_thread_.reset();
 }
 
-void BrowserProcessSubThread::CompleteInitializationOnBrowserThread() {
-  DCHECK_CALLED_ON_VALID_THREAD(browser_thread_checker_);
-
-  notification_service_ = std::make_unique<NotificationServiceImpl>();
-
-  if (identifier_ == BrowserThread::IO && g_io_thread_delegate) {
-    // Allow blocking calls while initializing the IO thread.
-    base::ScopedAllowBlocking allow_blocking_for_init;
-    g_io_thread_delegate->Init();
-  }
-}
-
-// We disable optimizations for Run specifications so the compiler doesn't merge
-// them all together.
-MSVC_DISABLE_OPTIMIZE()
-MSVC_PUSH_DISABLE_WARNING(4748)
-
-void BrowserProcessSubThread::UIThreadRun(base::RunLoop* run_loop) {
-  volatile int line_number = __LINE__;
-  Thread::Run(run_loop);
-  CHECK_GT(line_number, 0);
-}
-
-void BrowserProcessSubThread::IOThreadRun(base::RunLoop* run_loop) {
-  volatile int line_number = __LINE__;
-  Thread::Run(run_loop);
-  CHECK_GT(line_number, 0);
-}
-
-MSVC_POP_WARNING()
-MSVC_ENABLE_OPTIMIZE();
-
-void BrowserProcessSubThread::IOThreadCleanUp() {
-  DCHECK_CALLED_ON_VALID_THREAD(browser_thread_checker_);
-
+void BrowserProcessSubThread::IOThreadPreCleanUp() {
   // Kill all things that might be holding onto
   // net::URLRequest/net::URLRequestContexts.
 
diff --git a/content/browser/browser_process_sub_thread.h b/content/browser/browser_process_sub_thread.h
index f4b8799..8122cdb 100644
--- a/content/browser/browser_process_sub_thread.h
+++ b/content/browser/browser_process_sub_thread.h
@@ -8,9 +8,8 @@
 #include <memory>
 
 #include "base/macros.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_checker.h"
 #include "build/build_config.h"
+#include "content/browser/browser_thread_impl.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/browser_thread.h"
 
@@ -29,57 +28,29 @@
 namespace content {
 
 // ----------------------------------------------------------------------------
-// A BrowserProcessSubThread is a physical thread backing a BrowserThread.
+// BrowserProcessSubThread
+//
+// This simple thread object is used for the specialized threads that the
+// BrowserProcess spins up.
 //
 // Applications must initialize the COM library before they can call
 // COM library functions other than CoGetMalloc and memory allocation
 // functions, so this class initializes COM for those users.
-class CONTENT_EXPORT BrowserProcessSubThread : public base::Thread {
+class CONTENT_EXPORT BrowserProcessSubThread : public BrowserThreadImpl {
  public:
-  // Constructs a BrowserProcessSubThread for |identifier|.
   explicit BrowserProcessSubThread(BrowserThread::ID identifier);
+  BrowserProcessSubThread(BrowserThread::ID identifier,
+                          base::MessageLoop* message_loop);
   ~BrowserProcessSubThread() override;
 
-  // Registers this thread to represent |identifier_| in the browser_thread.h
-  // API. This thread must already be running when this is called. This can only
-  // be called once per BrowserProcessSubThread instance.
-  void RegisterAsBrowserThread();
-
-  // Ideally there wouldn't be a special blanket allowance to block the
-  // BrowserThreads in tests but TestBrowserThreadImpl previously bypassed
-  // BrowserProcessSubThread and hence wasn't subject to ThreadRestrictions...
-  // Flipping that around in favor of explicit scoped allowances would be
-  // preferable but a non-trivial amount of work. Can only be called before
-  // starting this BrowserProcessSubThread.
-  void AllowBlockingForTesting();
-
  protected:
   void Init() override;
-  void Run(base::RunLoop* run_loop) override;
   void CleanUp() override;
 
  private:
-  // Second Init() phase that must happen on this thread but can only happen
-  // after it's promoted to a BrowserThread in |RegisterAsBrowserThread()|.
-  void CompleteInitializationOnBrowserThread();
-
-  // These methods merely forwards to Thread::Run() but are useful to identify
-  // which BrowserThread this represents in stack traces.
-  void UIThreadRun(base::RunLoop* run_loop);
-  void IOThreadRun(base::RunLoop* run_loop);
-
-  // This method encapsulates cleanup that needs to happen on the IO thread.
-  void IOThreadCleanUp();
-
-  const BrowserThread::ID identifier_;
-
-  // BrowserThreads are not allowed to do file I/O nor wait on synchronization
-  // primivives except when explicitly allowed in tests.
-  bool is_blocking_allowed_for_testing_ = false;
-
-  // The BrowserThread registration for this |identifier_|, initialized in
-  // RegisterAsBrowserThread().
-  std::unique_ptr<BrowserThreadImpl> browser_thread_;
+  // These methods encapsulate cleanup that needs to happen on the IO thread
+  // before we call the embedder's CleanUp function.
+  void IOThreadPreCleanUp();
 
 #if defined (OS_WIN)
   std::unique_ptr<base::win::ScopedCOMInitializer> com_initializer_;
@@ -88,8 +59,6 @@
   // Each specialized thread has its own notification service.
   std::unique_ptr<NotificationService> notification_service_;
 
-  THREAD_CHECKER(browser_thread_checker_);
-
   DISALLOW_COPY_AND_ASSIGN(BrowserProcessSubThread);
 };
 
diff --git a/content/browser/browser_thread_impl.cc b/content/browser/browser_thread_impl.cc
index c679f3f..b8b6b20 100644
--- a/content/browser/browser_thread_impl.cc
+++ b/content/browser/browser_thread_impl.cc
@@ -7,21 +7,41 @@
 #include <string>
 #include <utility>
 
+#include "base/atomicops.h"
 #include "base/bind.h"
-#include "base/callback.h"
 #include "base/compiler_specific.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
 #include "base/threading/platform_thread.h"
-#include "base/time/time.h"
 #include "build/build_config.h"
+#include "content/public/browser/browser_thread_delegate.h"
 #include "content/public/browser/content_browser_client.h"
 
+#if defined(OS_ANDROID)
+#include "base/android/jni_android.h"
+#endif
+
 namespace content {
 
 namespace {
 
+// Friendly names for the well-known threads.
+static const char* const g_browser_thread_names[BrowserThread::ID_COUNT] = {
+  "",  // UI (name assembled in browser_main.cc).
+  "Chrome_IOThread",  // IO
+};
+
+static const char* GetThreadName(BrowserThread::ID thread) {
+  if (BrowserThread::UI < thread && thread < BrowserThread::ID_COUNT)
+    return g_browser_thread_names[thread];
+  if (thread == BrowserThread::UI)
+    return "Chrome_UIThread";
+  return "Unknown Thread";
+}
+
 // An implementation of SingleThreadTaskRunner to be used in conjunction
 // with BrowserThread.
 // TODO(gab): Consider replacing this with |g_globals->task_runners| -- only
@@ -79,12 +99,17 @@
 enum BrowserThreadState {
   // BrowserThread::ID isn't associated with anything yet.
   UNINITIALIZED = 0,
+  // BrowserThread::ID is associated with a BrowserThreadImpl instance but the
+  // underlying thread hasn't started yet.
+  INITIALIZED,
   // BrowserThread::ID is associated to a TaskRunner and is accepting tasks.
   RUNNING,
   // BrowserThread::ID no longer accepts tasks.
   SHUTDOWN
 };
 
+using BrowserThreadDelegateAtomicPtr = base::subtle::AtomicWord;
+
 struct BrowserThreadGlobals {
   // This lock protects |task_runners| and |states|. Do not read or modify those
   // arrays without holding this lock. Do not block while holding this lock.
@@ -99,18 +124,252 @@
 
   // Holds the state of each BrowserThread::ID.
   BrowserThreadState states[BrowserThread::ID_COUNT] = {};
+
+  // Only atomic operations are used on this pointer. The delegate isn't owned
+  // by BrowserThreadGlobals, rather by whoever calls
+  // BrowserThread::SetIOThreadDelegate.
+  BrowserThreadDelegateAtomicPtr io_thread_delegate = 0;
+
+  // This locks protects |is_io_thread_initialized|. Do not read or modify this
+  // variable without holding this lock.
+  base::Lock io_thread_lock;
+
+  // A flag indicates whether the BrowserThreadDelegate of the BrowserThread::IO
+  // thread has been initialized.
+  bool is_io_thread_initialized = false;
 };
 
 base::LazyInstance<BrowserThreadGlobals>::Leaky
     g_globals = LAZY_INSTANCE_INITIALIZER;
 
-bool PostTaskHelper(BrowserThread::ID identifier,
-                    const base::Location& from_here,
-                    base::OnceClosure task,
-                    base::TimeDelta delay,
-                    bool nestable) {
+void InitIOThreadDelegateOnIOThread() {
+  BrowserThreadDelegateAtomicPtr delegate =
+      base::subtle::NoBarrier_Load(&g_globals.Get().io_thread_delegate);
+  if (delegate)
+    reinterpret_cast<BrowserThreadDelegate*>(delegate)->Init();
+}
+
+bool IsIOThreadInitialized() {
+  BrowserThreadGlobals& globals = g_globals.Get();
+  base::AutoLock lock(globals.io_thread_lock);
+  return globals.is_io_thread_initialized;
+}
+
+void SetIsIOThreadInitialized(bool is_io_thread_initialized) {
+  BrowserThreadGlobals& globals = g_globals.Get();
+  base::AutoLock lock(globals.io_thread_lock);
+  globals.is_io_thread_initialized = is_io_thread_initialized;
+}
+
+}  // namespace
+
+BrowserThreadImpl::BrowserThreadImpl(ID identifier)
+    : Thread(GetThreadName(identifier)), identifier_(identifier) {
+  Initialize();
+}
+
+BrowserThreadImpl::BrowserThreadImpl(ID identifier,
+                                     base::MessageLoop* message_loop)
+    : Thread(GetThreadName(identifier)), identifier_(identifier) {
+  SetMessageLoop(message_loop);
+  Initialize();
+
+  // If constructed with an explicit message loop, this is a fake
+  // BrowserThread which runs on the current thread.
+  BrowserThreadGlobals& globals = g_globals.Get();
+  base::AutoLock lock(globals.lock);
+
+  DCHECK(!globals.task_runners[identifier_]);
+  globals.task_runners[identifier_] = task_runner();
+
+  DCHECK_EQ(globals.states[identifier_], BrowserThreadState::INITIALIZED);
+  globals.states[identifier_] = BrowserThreadState::RUNNING;
+}
+
+void BrowserThreadImpl::Init() {
+#if DCHECK_IS_ON()
+  {
+    BrowserThreadGlobals& globals = g_globals.Get();
+    base::AutoLock lock(globals.lock);
+    // |globals| should already have been initialized for |identifier_| in
+    // BrowserThreadImpl::StartWithOptions(). If this isn't the case it's likely
+    // because this BrowserThreadImpl's owner incorrectly used Thread::Start.*()
+    // instead of BrowserThreadImpl::Start.*().
+    DCHECK_EQ(globals.states[identifier_], BrowserThreadState::RUNNING);
+    DCHECK(globals.task_runners[identifier_]);
+    DCHECK(globals.task_runners[identifier_]->RunsTasksInCurrentSequence());
+  }
+#endif  // DCHECK_IS_ON()
+}
+
+// We disable optimizations for this block of functions so the compiler doesn't
+// merge them all together.
+MSVC_DISABLE_OPTIMIZE()
+MSVC_PUSH_DISABLE_WARNING(4748)
+
+NOINLINE void BrowserThreadImpl::UIThreadRun(base::RunLoop* run_loop) {
+  volatile int line_number = __LINE__;
+  Thread::Run(run_loop);
+  CHECK_GT(line_number, 0);
+}
+
+NOINLINE void BrowserThreadImpl::IOThreadRun(base::RunLoop* run_loop) {
+  volatile int line_number = __LINE__;
+  Thread::Run(run_loop);
+  CHECK_GT(line_number, 0);
+}
+
+MSVC_POP_WARNING()
+MSVC_ENABLE_OPTIMIZE();
+
+void BrowserThreadImpl::Run(base::RunLoop* run_loop) {
+#if defined(OS_ANDROID)
+  // Not to reset thread name to "Thread-???" by VM, attach VM with thread name.
+  // Though it may create unnecessary VM thread objects, keeping thread name
+  // gives more benefit in debugging in the platform.
+  if (!thread_name().empty()) {
+    base::android::AttachCurrentThreadWithName(thread_name());
+  }
+#endif
+
+  BrowserThread::ID thread_id = ID_COUNT;
+  CHECK(GetCurrentThreadIdentifier(&thread_id));
+  CHECK_EQ(identifier_, thread_id);
+
+  switch (identifier_) {
+    case BrowserThread::UI:
+      return UIThreadRun(run_loop);
+    case BrowserThread::IO:
+      return IOThreadRun(run_loop);
+    case BrowserThread::ID_COUNT:
+      CHECK(false);  // This shouldn't actually be reached!
+      break;
+  }
+
+  // |identifier_| must be set to a valid enum value in the constructor, so it
+  // should be impossible to reach here.
+  CHECK(false);
+}
+
+void BrowserThreadImpl::CleanUp() {
+  BrowserThreadGlobals& globals = g_globals.Get();
+
+  if (identifier_ == BrowserThread::IO && IsIOThreadInitialized()) {
+    BrowserThreadDelegateAtomicPtr delegate =
+        base::subtle::NoBarrier_Load(&globals.io_thread_delegate);
+    if (delegate)
+      reinterpret_cast<BrowserThreadDelegate*>(delegate)->CleanUp();
+    SetIsIOThreadInitialized(false);
+  }
+
+  // Change the state to SHUTDOWN so that PostTaskHelper stops accepting tasks
+  // for this thread. Do not clear globals.task_runners[identifier_] so that
+  // BrowserThread::CurrentlyOn() works from the MessageLoop's
+  // DestructionObservers.
+  base::AutoLock lock(globals.lock);
+  DCHECK_EQ(globals.states[identifier_], BrowserThreadState::RUNNING);
+  globals.states[identifier_] = BrowserThreadState::SHUTDOWN;
+}
+
+void BrowserThreadImpl::Initialize() {
+  BrowserThreadGlobals& globals = g_globals.Get();
+
+  base::AutoLock lock(globals.lock);
+  DCHECK_GE(identifier_, 0);
+  DCHECK_LT(identifier_, ID_COUNT);
+  DCHECK_EQ(globals.states[identifier_], BrowserThreadState::UNINITIALIZED);
+  globals.states[identifier_] = BrowserThreadState::INITIALIZED;
+}
+
+// static
+void BrowserThreadImpl::ResetGlobalsForTesting(BrowserThread::ID identifier) {
+  BrowserThreadGlobals& globals = g_globals.Get();
+
+  base::AutoLock lock(globals.lock);
+  DCHECK_EQ(globals.states[identifier], BrowserThreadState::SHUTDOWN);
+  globals.states[identifier] = BrowserThreadState::UNINITIALIZED;
+  globals.task_runners[identifier] = nullptr;
+  if (identifier == BrowserThread::IO)
+    SetIOThreadDelegate(nullptr);
+}
+
+void BrowserThreadImpl::InitIOThreadDelegate() {
+  DCHECK(!IsIOThreadInitialized());
+
+  SetIsIOThreadInitialized(true);
+  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+                          base::BindOnce(&InitIOThreadDelegateOnIOThread));
+}
+
+BrowserThreadImpl::~BrowserThreadImpl() {
+  // All Thread subclasses must call Stop() in the destructor. This is
+  // doubly important here as various bits of code check they are on
+  // the right BrowserThread.
+  Stop();
+
+  BrowserThreadGlobals& globals = g_globals.Get();
+  base::AutoLock lock(globals.lock);
+  // This thread should have gone through Cleanup() as part of Stop() and be in
+  // the SHUTDOWN state already (unless it uses an externally provided
+  // MessageLoop instead of a real underlying thread and thus doesn't go through
+  // Cleanup()).
+  if (using_external_message_loop()) {
+    DCHECK_EQ(globals.states[identifier_], BrowserThreadState::RUNNING);
+    globals.states[identifier_] = BrowserThreadState::SHUTDOWN;
+  } else {
+    DCHECK_EQ(globals.states[identifier_], BrowserThreadState::SHUTDOWN);
+  }
+#if DCHECK_IS_ON()
+  // Double check that the threads are ordered correctly in the enumeration.
+  for (int i = identifier_ + 1; i < ID_COUNT; ++i) {
+    DCHECK(globals.states[i] == BrowserThreadState::SHUTDOWN ||
+           globals.states[i] == BrowserThreadState::UNINITIALIZED)
+        << "Threads must be listed in the reverse order that they die";
+  }
+#endif
+}
+
+bool BrowserThreadImpl::Start() {
+  return StartWithOptions(base::Thread::Options());
+}
+
+bool BrowserThreadImpl::StartWithOptions(const Options& options) {
+  BrowserThreadGlobals& globals = g_globals.Get();
+
+  // Holding the lock is necessary when kicking off the thread to ensure
+  // |states| and |task_runners| are updated before it gets to query them.
+  base::AutoLock lock(globals.lock);
+
+  bool result = Thread::StartWithOptions(options);
+
+  // Although the thread is starting asynchronously, the MessageLoop is already
+  // ready to accept tasks and as such this BrowserThreadImpl is considered as
+  // "running".
+  DCHECK(!globals.task_runners[identifier_]);
+  globals.task_runners[identifier_] = task_runner();
+  DCHECK(globals.task_runners[identifier_]);
+
+  DCHECK_EQ(globals.states[identifier_], BrowserThreadState::INITIALIZED);
+  globals.states[identifier_] = BrowserThreadState::RUNNING;
+
+  return result;
+}
+
+bool BrowserThreadImpl::StartAndWaitForTesting() {
+  if (!Start())
+    return false;
+  WaitUntilThreadStarted();
+  return true;
+}
+
+// static
+bool BrowserThreadImpl::PostTaskHelper(BrowserThread::ID identifier,
+                                       const base::Location& from_here,
+                                       base::OnceClosure task,
+                                       base::TimeDelta delay,
+                                       bool nestable) {
   DCHECK_GE(identifier, 0);
-  DCHECK_LT(identifier, BrowserThread::ID_COUNT);
+  DCHECK_LT(identifier, ID_COUNT);
   // Optimization: to avoid unnecessary locks, we listed the ID enumeration in
   // order of lifetime.  So no need to lock if we know that the target thread
   // outlives current thread as that implies the current thread only ever sees
@@ -118,9 +377,9 @@
   // Note: since the array is so small, ok to loop instead of creating a map,
   // which would require a lock because std::map isn't thread safe, defeating
   // the whole purpose of this optimization.
-  BrowserThread::ID current_thread = BrowserThread::ID_COUNT;
+  BrowserThread::ID current_thread = ID_COUNT;
   bool target_thread_outlives_current =
-      BrowserThreadImpl::GetCurrentThreadIdentifier(&current_thread) &&
+      GetCurrentThreadIdentifier(&current_thread) &&
       current_thread >= identifier;
 
   BrowserThreadGlobals& globals = g_globals.Get();
@@ -153,56 +412,6 @@
   return accepting_tasks;
 }
 
-}  // namespace
-
-BrowserThreadImpl::BrowserThreadImpl(
-    ID identifier,
-    scoped_refptr<base::SingleThreadTaskRunner> task_runner)
-    : identifier_(identifier) {
-  DCHECK(task_runner);
-
-  BrowserThreadGlobals& globals = g_globals.Get();
-
-  base::AutoLock lock(globals.lock);
-  DCHECK_GE(identifier_, 0);
-  DCHECK_LT(identifier_, ID_COUNT);
-  DCHECK_EQ(globals.states[identifier_], BrowserThreadState::UNINITIALIZED);
-  globals.states[identifier_] = BrowserThreadState::RUNNING;
-  globals.task_runners[identifier_] = std::move(task_runner);
-}
-
-BrowserThreadImpl::~BrowserThreadImpl() {
-  BrowserThreadGlobals& globals = g_globals.Get();
-  base::AutoLock lock(globals.lock);
-
-  DCHECK_EQ(globals.states[identifier_], BrowserThreadState::RUNNING);
-  globals.states[identifier_] = BrowserThreadState::SHUTDOWN;
-}
-
-// static
-void BrowserThreadImpl::ResetGlobalsForTesting(BrowserThread::ID identifier) {
-  BrowserThreadGlobals& globals = g_globals.Get();
-
-  base::AutoLock lock(globals.lock);
-  DCHECK_EQ(globals.states[identifier], BrowserThreadState::SHUTDOWN);
-  globals.states[identifier] = BrowserThreadState::UNINITIALIZED;
-  globals.task_runners[identifier] = nullptr;
-}
-
-// static
-const char* BrowserThreadImpl::GetThreadName(BrowserThread::ID thread) {
-  static const char* const kBrowserThreadNames[BrowserThread::ID_COUNT] = {
-      "",                 // UI (name assembled in browser_main_loop.cc).
-      "Chrome_IOThread",  // IO
-  };
-
-  if (BrowserThread::UI < thread && thread < BrowserThread::ID_COUNT)
-    return kBrowserThreadNames[thread];
-  if (thread == BrowserThread::UI)
-    return "Chrome_UIThread";
-  return "Unknown Thread";
-}
-
 // static
 void BrowserThread::PostAfterStartupTask(
     const base::Location& from_here,
@@ -221,7 +430,13 @@
   base::AutoLock lock(globals.lock);
   DCHECK_GE(identifier, 0);
   DCHECK_LT(identifier, ID_COUNT);
-  return globals.states[identifier] == BrowserThreadState::RUNNING;
+  bool running =
+      globals.states[identifier] == BrowserThreadState::INITIALIZED ||
+      globals.states[identifier] == BrowserThreadState::RUNNING;
+  if (identifier != BrowserThread::IO)
+    return running;
+
+  return running && IsIOThreadInitialized();
 }
 
 // static
@@ -241,7 +456,7 @@
     actual_name = "Unknown Thread";
 
   std::string result = "Must be called on ";
-  result += BrowserThreadImpl::GetThreadName(expected);
+  result += GetThreadName(expected);
   result += "; actually called on ";
   result += actual_name;
   result += ".";
@@ -264,8 +479,8 @@
 bool BrowserThread::PostTask(ID identifier,
                              const base::Location& from_here,
                              base::OnceClosure task) {
-  return PostTaskHelper(identifier, from_here, std::move(task),
-                        base::TimeDelta(), true);
+  return BrowserThreadImpl::PostTaskHelper(
+      identifier, from_here, std::move(task), base::TimeDelta(), true);
 }
 
 // static
@@ -273,15 +488,16 @@
                                     const base::Location& from_here,
                                     base::OnceClosure task,
                                     base::TimeDelta delay) {
-  return PostTaskHelper(identifier, from_here, std::move(task), delay, true);
+  return BrowserThreadImpl::PostTaskHelper(identifier, from_here,
+                                           std::move(task), delay, true);
 }
 
 // static
 bool BrowserThread::PostNonNestableTask(ID identifier,
                                         const base::Location& from_here,
                                         base::OnceClosure task) {
-  return PostTaskHelper(identifier, from_here, std::move(task),
-                        base::TimeDelta(), false);
+  return BrowserThreadImpl::PostTaskHelper(
+      identifier, from_here, std::move(task), base::TimeDelta(), false);
 }
 
 // static
@@ -289,7 +505,8 @@
                                                const base::Location& from_here,
                                                base::OnceClosure task,
                                                base::TimeDelta delay) {
-  return PostTaskHelper(identifier, from_here, std::move(task), delay, false);
+  return BrowserThreadImpl::PostTaskHelper(identifier, from_here,
+                                           std::move(task), delay, false);
 }
 
 // static
@@ -328,4 +545,16 @@
   return g_task_runners.Get().proxies[identifier];
 }
 
+// static
+void BrowserThread::SetIOThreadDelegate(BrowserThreadDelegate* delegate) {
+  BrowserThreadGlobals& globals = g_globals.Get();
+  BrowserThreadDelegateAtomicPtr old_delegate =
+      base::subtle::NoBarrier_AtomicExchange(
+          &globals.io_thread_delegate,
+          reinterpret_cast<BrowserThreadDelegateAtomicPtr>(delegate));
+
+  // This catches registration when previously registered.
+  DCHECK(!delegate || !old_delegate);
+}
+
 }  // namespace content
diff --git a/content/browser/browser_thread_impl.h b/content/browser/browser_thread_impl.h
index 46ba1c8..5457e26 100644
--- a/content/browser/browser_thread_impl.h
+++ b/content/browser/browser_thread_impl.h
@@ -5,31 +5,47 @@
 #ifndef CONTENT_BROWSER_BROWSER_THREAD_IMPL_H_
 #define CONTENT_BROWSER_BROWSER_THREAD_IMPL_H_
 
-#include "base/memory/scoped_refptr.h"
+#include "base/callback.h"
 #include "base/single_thread_task_runner.h"
+#include "base/threading/thread.h"
+#include "base/time/time.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/browser_thread.h"
 
+namespace base {
+class MessageLoop;
+class RunLoop;
+}
+
+namespace base {
+class Location;
+}
+
 namespace content {
 
-class BrowserMainLoop;
-class BrowserProcessSubThread;
-class TestBrowserThread;
-
-// BrowserThreadImpl is a scoped object which maps a SingleThreadTaskRunner to a
-// BrowserThread::ID. On ~BrowserThreadImpl() that ID enters a SHUTDOWN state
-// (in which BrowserThread::IsThreadInitialized() returns false) but the mapping
-// isn't undone to avoid shutdown races (the task runner is free to stop
-// accepting tasks however).
-//
 // Very few users should use this directly. To mock BrowserThreads, tests should
 // use TestBrowserThreadBundle instead.
-class CONTENT_EXPORT BrowserThreadImpl : public BrowserThread {
+class CONTENT_EXPORT BrowserThreadImpl : public BrowserThread,
+                                         public base::Thread {
  public:
-  ~BrowserThreadImpl();
+  // Construct a BrowserThreadImpl with the supplied identifier.  It is an error
+  // to construct a BrowserThreadImpl that already exists.
+  explicit BrowserThreadImpl(BrowserThread::ID identifier);
 
-  // Returns the thread name for |identifier|.
-  static const char* GetThreadName(BrowserThread::ID identifier);
+  // Special constructor for the main (UI) thread and unittests. If a
+  // |message_loop| is provied, we use a dummy thread here since the main
+  // thread already exists.
+  BrowserThreadImpl(BrowserThread::ID identifier,
+                    base::MessageLoop* message_loop);
+  ~BrowserThreadImpl() override;
+
+  bool Start();
+  bool StartWithOptions(const Options& options);
+  bool StartAndWaitForTesting();
+  // Called only by the BrowserThread::IO thread to initialize its
+  // BrowserThreadDelegate after the thread is created. See
+  // https://crbug.com/729596.
+  void InitIOThreadDelegate();
 
   // Resets globals for |identifier|. Used in tests to clear global state that
   // would otherwise leak to the next test. Globals are not otherwise fully
@@ -39,19 +55,35 @@
   // |identifier|.
   static void ResetGlobalsForTesting(BrowserThread::ID identifier);
 
- private:
-  // Restrict instantiation to BrowserProcessSubThread as it performs important
-  // initialization that shouldn't be bypassed (except by BrowserMainLoop for
-  // the main thread).
-  friend class BrowserProcessSubThread;
-  friend class BrowserMainLoop;
-  // TestBrowserThread is also allowed to construct this when instantiating fake
-  // threads.
-  friend class TestBrowserThread;
+ protected:
+  void Init() override;
+  void Run(base::RunLoop* run_loop) override;
+  void CleanUp() override;
 
-  // Binds |identifier| to |task_runner| for the browser_thread.h API.
-  BrowserThreadImpl(BrowserThread::ID identifier,
-                    scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ private:
+  // We implement all the functionality of the public BrowserThread
+  // functions, but state is stored in the BrowserThreadImpl to keep
+  // the API cleaner. Therefore make BrowserThread a friend class.
+  friend class BrowserThread;
+
+  // The following are unique function names that makes it possible to tell
+  // the thread id from the callstack alone in crash dumps.
+  void UIThreadRun(base::RunLoop* run_loop);
+  void ProcessLauncherThreadRun(base::RunLoop* run_loop);
+  void IOThreadRun(base::RunLoop* run_loop);
+
+  static bool PostTaskHelper(BrowserThread::ID identifier,
+                             const base::Location& from_here,
+                             base::OnceClosure task,
+                             base::TimeDelta delay,
+                             bool nestable);
+
+  // Common initialization code for the constructors.
+  void Initialize();
+
+  // For testing.
+  friend class ContentTestSuiteBaseListener;
+  friend class TestBrowserThreadBundle;
 
   // The identifier of this thread.  Only one thread can exist with a given
   // identifier at a given time.
diff --git a/content/browser/browser_thread_unittest.cc b/content/browser/browser_thread_unittest.cc
index 703fe34..6fc8e70 100644
--- a/content/browser/browser_thread_unittest.cc
+++ b/content/browser/browser_thread_unittest.cc
@@ -12,7 +12,6 @@
 #include "base/sequenced_task_runner_helpers.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "content/browser/browser_process_sub_thread.h"
 #include "content/browser/browser_thread_impl.h"
 #include "content/public/test/test_browser_thread.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -32,22 +31,17 @@
 
  protected:
   void SetUp() override {
-    ui_thread_ = std::make_unique<BrowserProcessSubThread>(BrowserThread::UI);
+    ui_thread_.reset(new BrowserThreadImpl(BrowserThread::UI));
+    io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO));
     ui_thread_->Start();
-
-    io_thread_ = std::make_unique<BrowserProcessSubThread>(BrowserThread::IO);
-    base::Thread::Options io_options;
-    io_options.message_loop_type = base::MessageLoop::TYPE_IO;
-    io_thread_->StartWithOptions(io_options);
-
-    ui_thread_->RegisterAsBrowserThread();
-    io_thread_->RegisterAsBrowserThread();
+    io_thread_->Start();
   }
 
   void TearDown() override {
-    io_thread_.reset();
-    ui_thread_.reset();
-
+    StopUIThread();
+    io_thread_->Stop();
+    ui_thread_ = nullptr;
+    io_thread_ = nullptr;
     BrowserThreadImpl::ResetGlobalsForTesting(BrowserThread::UI);
     BrowserThreadImpl::ResetGlobalsForTesting(BrowserThread::IO);
   }
@@ -79,8 +73,8 @@
   };
 
  private:
-  std::unique_ptr<BrowserProcessSubThread> ui_thread_;
-  std::unique_ptr<BrowserProcessSubThread> io_thread_;
+  std::unique_ptr<BrowserThreadImpl> ui_thread_;
+  std::unique_ptr<BrowserThreadImpl> io_thread_;
   // It's kind of ugly to make this mutable - solely so we can post the Quit
   // Task from Release(). This should be fixed.
   mutable base::MessageLoop loop_;
diff --git a/content/browser/browser_url_handler_impl_unittest.cc b/content/browser/browser_url_handler_impl_unittest.cc
index daceffc..769fc670 100644
--- a/content/browser/browser_url_handler_impl_unittest.cc
+++ b/content/browser/browser_url_handler_impl_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "content/browser/browser_url_handler_impl.h"
 #include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
@@ -31,6 +32,7 @@
 }
 
 TEST_F(BrowserURLHandlerImplTest, BasicRewriteAndReverse) {
+  TestBrowserThreadBundle thread_bundle;
   TestBrowserContext browser_context;
   BrowserURLHandlerImpl handler;
 
@@ -60,6 +62,7 @@
 }
 
 TEST_F(BrowserURLHandlerImplTest, NullHandlerReverse) {
+  TestBrowserThreadBundle thread_bundle;
   TestBrowserContext browser_context;
   BrowserURLHandlerImpl handler;
 
@@ -82,6 +85,7 @@
 // Verify that the reverse handler for view-source does not duplicate query
 // parameters.
 TEST_F(BrowserURLHandlerImplTest, ViewSourceReverse) {
+  TestBrowserThreadBundle thread_bundle;
   TestBrowserContext browser_context;
   BrowserURLHandlerImpl handler;
 
diff --git a/content/browser/cache_storage/cache_storage_dispatcher_host.cc b/content/browser/cache_storage/cache_storage_dispatcher_host.cc
index e00dfda..58ff8d1 100644
--- a/content/browser/cache_storage/cache_storage_dispatcher_host.cc
+++ b/content/browser/cache_storage/cache_storage_dispatcher_host.cc
@@ -19,7 +19,6 @@
 #include "content/browser/cache_storage/cache_storage_cache_handle.h"
 #include "content/browser/cache_storage/cache_storage_context_impl.h"
 #include "content/browser/cache_storage/cache_storage_manager.h"
-#include "content/common/cache_storage/cache_storage_messages.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/common/origin_util.h"
diff --git a/content/browser/compositor/gpu_browser_compositor_output_surface.h b/content/browser/compositor/gpu_browser_compositor_output_surface.h
index ef06c3e8..95aa6d1 100644
--- a/content/browser/compositor/gpu_browser_compositor_output_surface.h
+++ b/content/browser/compositor/gpu_browser_compositor_output_surface.h
@@ -11,7 +11,7 @@
 #include "build/build_config.h"
 #include "content/browser/compositor/browser_compositor_output_surface.h"
 #include "content/browser/compositor/gpu_vsync_begin_frame_source.h"
-#include "gpu/vulkan/features.h"
+#include "gpu/vulkan/buildflags.h"
 #include "ui/gfx/swap_result.h"
 
 namespace viz {
diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc
index d58fcaf..ceda8ac9 100644
--- a/content/browser/compositor/gpu_process_transport_factory.cc
+++ b/content/browser/compositor/gpu_process_transport_factory.cc
@@ -61,7 +61,7 @@
 #include "gpu/config/gpu_feature_info.h"
 #include "gpu/ipc/client/gpu_channel_host.h"
 #include "gpu/ipc/host/gpu_memory_buffer_support.h"
-#include "gpu/vulkan/features.h"
+#include "gpu/vulkan/buildflags.h"
 #include "services/service_manager/runner/common/client_util.h"
 #include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
 #include "third_party/khronos/GLES2/gl2.h"
@@ -517,12 +517,13 @@
                                             disable_overlay_ca_layers),
             GetGpuMemoryBufferManager());
 #else
+        DCHECK(capabilities.texture_format_bgra8888);
         auto gpu_output_surface =
             std::make_unique<GpuSurfacelessBrowserCompositorOutputSurface>(
                 context_provider, data->surface_handle,
                 std::move(vsync_callback),
                 CreateOverlayCandidateValidator(compositor->widget()),
-                GL_TEXTURE_2D, GL_RGB,
+                GL_TEXTURE_2D, GL_BGRA_EXT,
                 display::DisplaySnapshot::PrimaryFormat(),
                 GetGpuMemoryBufferManager());
         gpu_vsync_control = gpu_output_surface.get();
diff --git a/content/browser/compositor/offscreen_browser_compositor_output_surface.h b/content/browser/compositor/offscreen_browser_compositor_output_surface.h
index abbcd19..a1f4e6df 100644
--- a/content/browser/compositor/offscreen_browser_compositor_output_surface.h
+++ b/content/browser/compositor/offscreen_browser_compositor_output_surface.h
@@ -14,7 +14,7 @@
 #include "base/memory/weak_ptr.h"
 #include "build/build_config.h"
 #include "content/browser/compositor/browser_compositor_output_surface.h"
-#include "gpu/vulkan/features.h"
+#include "gpu/vulkan/buildflags.h"
 #include "ui/latency/latency_info.h"
 
 namespace ui {
diff --git a/content/browser/compositor/software_browser_compositor_output_surface.h b/content/browser/compositor/software_browser_compositor_output_surface.h
index 4036e69..79bc9f5f 100644
--- a/content/browser/compositor/software_browser_compositor_output_surface.h
+++ b/content/browser/compositor/software_browser_compositor_output_surface.h
@@ -11,7 +11,7 @@
 #include "build/build_config.h"
 #include "content/browser/compositor/browser_compositor_output_surface.h"
 #include "content/common/content_export.h"
-#include "gpu/vulkan/features.h"
+#include "gpu/vulkan/buildflags.h"
 
 namespace cc {
 class SoftwareOutputDevice;
diff --git a/content/browser/cross_site_transfer_browsertest.cc b/content/browser/cross_site_transfer_browsertest.cc
index 5f1c338..693a7b8 100644
--- a/content/browser/cross_site_transfer_browsertest.cc
+++ b/content/browser/cross_site_transfer_browsertest.cc
@@ -33,6 +33,7 @@
 #include "content/public/test/test_navigation_observer.h"
 #include "content/shell/browser/shell.h"
 #include "content/shell/browser/shell_content_browser_client.h"
+#include "content/shell/common/shell_switches.h"
 #include "content/test/content_browser_test_utils_internal.h"
 #include "net/base/escape.h"
 #include "net/dns/mock_host_resolver.h"
@@ -472,4 +473,24 @@
       << "Request should have been cancelled before reaching the renderer.";
 }
 
+// Ensure that we don't send a referrer if a site tries to trigger the forking
+// heuristic, even if we would have forked anyways.
+IN_PROC_BROWSER_TEST_F(CrossSiteTransferTest, NoReferrerOnFork) {
+  base::CommandLine::ForCurrentProcess()->AppendSwitch(
+      switches::kContentShellAlwaysFork);
+
+  GURL start_url(embedded_test_server()->GetURL("a.com", "/fork-popup.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), start_url));
+  EXPECT_EQ(2u, shell()->windows().size());
+  Shell* popup = shell()->windows().back();
+  EXPECT_NE(popup, shell());
+
+  base::string16 expected_title = base::ASCIIToUTF16("Referrer = ''");
+  base::string16 failed_title = base::ASCIIToUTF16(
+      base::StringPrintf("Referrer = '%s'", start_url.spec().c_str()));
+  TitleWatcher watcher(popup->web_contents(), expected_title);
+  watcher.AlsoWaitForTitle(failed_title);
+  EXPECT_EQ(expected_title, watcher.WaitAndGetTitle());
+}
+
 }  // namespace content
diff --git a/content/browser/download/download_browsertest.cc b/content/browser/download/download_browsertest.cc
index eadc06c..c674773 100644
--- a/content/browser/download/download_browsertest.cc
+++ b/content/browser/download/download_browsertest.cc
@@ -2873,33 +2873,6 @@
   ASSERT_TRUE(server.ShutdownAndWaitUntilComplete());
 }
 
-// Test that the target attribute is ignored on anchors with a download
-// attribute.
-IN_PROC_BROWSER_TEST_F(DownloadContentTest,
-                       DownloadAttributeIgnoresTargetAttribute) {
-  net::EmbeddedTestServer server;
-  ASSERT_TRUE(server.InitializeAndListen());
-
-  GURL url = server.GetURL(std::string("/download-attribute-with-target.html"));
-  server.ServeFilesFromDirectory(GetTestFilePath("download", ""));
-  server.StartAcceptingConnections();
-
-  NavigateToURLAndWaitForDownload(shell(), url,
-                                  download::DownloadItem::COMPLETE);
-
-  std::vector<download::DownloadItem*> downloads;
-  DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
-  ASSERT_EQ(1u, downloads.size());
-
-  // The target="_blank" should have been ignored, and so no additional window
-  // was created.
-  ASSERT_EQ(1u, Shell::windows().size());
-
-  EXPECT_EQ(FILE_PATH_LITERAL("suggested-filename"),
-            downloads[0]->GetTargetFilePath().BaseName().value());
-  ASSERT_TRUE(server.ShutdownAndWaitUntilComplete());
-}
-
 // A request for a non-existent resource should result in an aborted navigation,
 // and the old site staying current.
 IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadAttributeServerError) {
diff --git a/content/browser/download/download_item_impl.cc b/content/browser/download/download_item_impl.cc
index 3f0847d..244592b 100644
--- a/content/browser/download/download_item_impl.cc
+++ b/content/browser/download/download_item_impl.cc
@@ -422,7 +422,8 @@
       is_updating_observers_(false),
       weak_ptr_factory_(this) {
   job_ = DownloadJobFactory::CreateJob(this, std::move(request_handle),
-                                       download::DownloadCreateInfo(), true);
+                                       download::DownloadCreateInfo(), true,
+                                       nullptr);
   delegate_->Attach();
   Init(true /* actively downloading */, TYPE_SAVE_PAGE_AS);
 }
@@ -1416,7 +1417,8 @@
 void DownloadItemImpl::Start(
     std::unique_ptr<download::DownloadFile> file,
     std::unique_ptr<download::DownloadRequestHandleInterface> req_handle,
-    const download::DownloadCreateInfo& new_create_info) {
+    const download::DownloadCreateInfo& new_create_info,
+    scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(!download_file_.get());
   DVLOG(20) << __func__ << "() this=" << DebugString(true);
@@ -1425,7 +1427,8 @@
 
   download_file_ = std::move(file);
   job_ = DownloadJobFactory::CreateJob(this, std::move(req_handle),
-                                       new_create_info, false);
+                                       new_create_info, false,
+                                       std::move(shared_url_loader_factory));
   if (job_->IsParallelizable()) {
     download::RecordParallelizableDownloadCount(download::START_COUNT,
                                                 IsParallelDownloadEnabled());
diff --git a/content/browser/download/download_item_impl.h b/content/browser/download/download_item_impl.h
index 6a46ad5..6c5a8ef 100644
--- a/content/browser/download/download_item_impl.h
+++ b/content/browser/download/download_item_impl.h
@@ -25,6 +25,7 @@
 #include "components/download/public/common/download_url_parameters.h"
 #include "components/download/public/common/resume_mode.h"
 #include "content/common/content_export.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "url/gurl.h"
 
 namespace download {
@@ -300,7 +301,8 @@
   virtual void Start(
       std::unique_ptr<download::DownloadFile> download_file,
       std::unique_ptr<download::DownloadRequestHandleInterface> req_handle,
-      const download::DownloadCreateInfo& new_create_info);
+      const download::DownloadCreateInfo& new_create_info,
+      scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory);
 
   // Needed because of intertwining with DownloadManagerImpl -------------------
 
diff --git a/content/browser/download/download_item_impl_unittest.cc b/content/browser/download/download_item_impl_unittest.cc
index 3715ba8..c2363a5 100644
--- a/content/browser/download/download_item_impl_unittest.cc
+++ b/content/browser/download/download_item_impl_unittest.cc
@@ -323,7 +323,7 @@
     std::unique_ptr<MockRequestHandle> request_handle =
         std::make_unique<NiceMock<MockRequestHandle>>();
     item->Start(std::move(download_file), std::move(request_handle),
-                *create_info_);
+                *create_info_, nullptr);
     task_environment_.RunUntilIdle();
 
     // So that we don't have a function writing to a stack variable
@@ -618,7 +618,7 @@
   EXPECT_CALL(*mock_download_file, Initialize(_, _, _, _));
   EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(_, _));
   item->Start(std::move(download_file), std::move(request_handle),
-              *create_info());
+              *create_info(), nullptr);
 
   item->Pause();
   ASSERT_TRUE(observer.CheckAndResetDownloadUpdated());
@@ -870,7 +870,7 @@
     // Copied key parts of DoIntermediateRename & CallDownloadItemStart
     // to allow for holding onto the request handle.
     item->Start(std::move(mock_download_file), std::move(mock_request_handle),
-                *create_info());
+                *create_info(), nullptr);
     task_environment_.RunUntilIdle();
 
     base::FilePath target_path(kDummyTargetPath);
@@ -1169,7 +1169,7 @@
       new NiceMock<MockRequestHandle>);
   EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item, _));
   item->Start(std::move(download_file), std::move(request_handle),
-              *create_info());
+              *create_info(), nullptr);
   task_environment_.RunUntilIdle();
 
   CleanupItem(item, mock_download_file, download::DownloadItem::IN_PROGRESS);
@@ -1194,7 +1194,8 @@
   EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item, _))
       .WillOnce(SaveArg<1>(&download_target_callback));
 
-  item->Start(std::move(file), std::move(request_handle), *create_info());
+  item->Start(std::move(file), std::move(request_handle), *create_info(),
+              nullptr);
   task_environment_.RunUntilIdle();
 
   download_target_callback.Run(
@@ -1232,7 +1233,7 @@
   EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item, _))
       .WillOnce(SaveArg<1>(&download_target_callback));
   item->Start(std::move(null_download_file), std::move(null_request_handle),
-              *create_info());
+              *create_info(), nullptr);
   EXPECT_EQ(download::DownloadItem::IN_PROGRESS, item->GetState());
   task_environment_.RunUntilIdle();
 
@@ -2299,7 +2300,8 @@
   download::DownloadFile::InitializeCallback initialize_callback;
   EXPECT_CALL(*file_, Initialize(_, _, _, _))
       .WillOnce(SaveArg<0>(&initialize_callback));
-  item_->Start(std::move(file_), std::move(request_handle_), *create_info());
+  item_->Start(std::move(file_), std::move(request_handle_), *create_info(),
+               nullptr);
   task_environment_.RunUntilIdle();
 
   base::WeakPtr<download::DownloadDestinationObserver> destination_observer =
@@ -2346,7 +2348,8 @@
   EXPECT_CALL(*file_, Initialize(_, _, _, _))
       .WillOnce(SaveArg<0>(&initialize_callback));
 
-  item_->Start(std::move(file_), std::move(request_handle_), *create_info());
+  item_->Start(std::move(file_), std::move(request_handle_), *create_info(),
+               nullptr);
   task_environment_.RunUntilIdle();
 
   base::WeakPtr<download::DownloadDestinationObserver> destination_observer =
@@ -2410,7 +2413,8 @@
   EXPECT_CALL(*file_, Initialize(_, _, _, _))
       .WillOnce(SaveArg<0>(&initialize_callback));
 
-  item_->Start(std::move(file_), std::move(request_handle_), *create_info());
+  item_->Start(std::move(file_), std::move(request_handle_), *create_info(),
+               nullptr);
   task_environment_.RunUntilIdle();
 
   base::WeakPtr<download::DownloadDestinationObserver> destination_observer =
diff --git a/content/browser/download/download_job_factory.cc b/content/browser/download/download_job_factory.cc
index e2140b7..4f9b3d3 100644
--- a/content/browser/download/download_job_factory.cc
+++ b/content/browser/download/download_job_factory.cc
@@ -14,6 +14,7 @@
 #include "content/browser/download/parallel_download_utils.h"
 #include "content/browser/download/save_package_download_job.h"
 #include "content/public/common/content_features.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 namespace content {
 
@@ -98,7 +99,8 @@
     download::DownloadItem* download_item,
     std::unique_ptr<download::DownloadRequestHandleInterface> req_handle,
     const download::DownloadCreateInfo& create_info,
-    bool is_save_package_download) {
+    bool is_save_package_download,
+    scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory) {
   if (is_save_package_download) {
     return std::make_unique<SavePackageDownloadJob>(download_item,
                                                     std::move(req_handle));
@@ -108,7 +110,8 @@
   // Build parallel download job.
   if (IsParallelDownloadEnabled() && is_parallelizable) {
     return std::make_unique<ParallelDownloadJob>(
-        download_item, std::move(req_handle), create_info);
+        download_item, std::move(req_handle), create_info,
+        std::move(shared_url_loader_factory));
   }
 
   // An ordinary download job.
diff --git a/content/browser/download/download_job_factory.h b/content/browser/download/download_job_factory.h
index 2da60e5..daf7431 100644
--- a/content/browser/download/download_job_factory.h
+++ b/content/browser/download/download_job_factory.h
@@ -16,6 +16,10 @@
 class DownloadRequestHandleInterface;
 }
 
+namespace network {
+class SharedURLLoaderFactory;
+}  // namespace network
+
 namespace content {
 
 // Factory class to create different kinds of DownloadJob.
@@ -25,7 +29,8 @@
       download::DownloadItem* download_item,
       std::unique_ptr<download::DownloadRequestHandleInterface> req_handle,
       const download::DownloadCreateInfo& create_info,
-      bool is_save_package_download);
+      bool is_save_package_download,
+      scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory);
 
  private:
   DISALLOW_COPY_AND_ASSIGN(DownloadJobFactory);
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc
index 2cc16fe..9f2290e 100644
--- a/content/browser/download/download_manager_impl.cc
+++ b/content/browser/download/download_manager_impl.cc
@@ -33,7 +33,9 @@
 #include "components/download/public/common/download_stats.h"
 #include "components/download/public/common/download_task_runner.h"
 #include "components/download/public/common/download_url_parameters.h"
+#include "components/download/public/common/download_utils.h"
 #include "components/download/public/common/resource_downloader.h"
+#include "components/download/public/common/url_download_handler_factory.h"
 #include "content/browser/byte_stream.h"
 #include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/download/byte_stream_input_stream.h"
@@ -42,6 +44,7 @@
 #include "content/browser/download/download_resource_handler.h"
 #include "content/browser/download/download_utils.h"
 #include "content/browser/download/url_downloader.h"
+#include "content/browser/download/url_downloader_factory.h"
 #include "content/browser/loader/resource_dispatcher_host_impl.h"
 #include "content/browser/loader/resource_request_info_impl.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
@@ -125,7 +128,7 @@
           &DownloadManager::StartDownload, download_manager,
           std::move(failed_created_info),
           std::make_unique<ByteStreamInputStream>(std::move(empty_byte_stream)),
-          params->callback()));
+          nullptr, params->callback()));
 }
 
 // Helper functions for DownloadItem -> DownloadEntry for InProgressCache.
@@ -407,6 +410,8 @@
   DCHECK(browser_context);
   download::SetIOTaskRunner(
       BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
+  if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
+    download::UrlDownloadHandlerFactory::Install(new UrlDownloaderFactory());
 }
 
 DownloadManagerImpl::~DownloadManagerImpl() {
@@ -561,6 +566,7 @@
 void DownloadManagerImpl::StartDownload(
     std::unique_ptr<download::DownloadCreateInfo> info,
     std::unique_ptr<download::InputStream> stream,
+    scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
     const download::DownloadUrlParameters::OnStartedCallback& on_started) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(info);
@@ -585,7 +591,8 @@
     download::RecordDownloadConnectionSecurity(info->url(), info->url_chain);
   base::Callback<void(uint32_t)> got_id(base::Bind(
       &DownloadManagerImpl::StartDownloadWithId, weak_factory_.GetWeakPtr(),
-      base::Passed(&info), base::Passed(&stream), on_started, new_download));
+      base::Passed(&info), base::Passed(&stream),
+      std::move(shared_url_loader_factory), on_started, new_download));
   if (new_download) {
     GetNextId(std::move(got_id));
   } else {
@@ -596,6 +603,7 @@
 void DownloadManagerImpl::StartDownloadWithId(
     std::unique_ptr<download::DownloadCreateInfo> info,
     std::unique_ptr<download::InputStream> stream,
+    scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
     const download::DownloadUrlParameters::OnStartedCallback& on_started,
     bool new_download,
     uint32_t id) {
@@ -688,7 +696,7 @@
   // resumption attempt.
 
   download->Start(std::move(download_file), std::move(info->request_handle),
-                  *info);
+                  *info, std::move(shared_url_loader_factory));
 
   // For interrupted downloads, Start() will transition the state to
   // IN_PROGRESS and consumers will be notified via OnDownloadUpdated().
@@ -1110,8 +1118,10 @@
 void DownloadManagerImpl::OnUrlDownloadStarted(
     std::unique_ptr<download::DownloadCreateInfo> download_create_info,
     std::unique_ptr<download::InputStream> stream,
+    scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
     const download::DownloadUrlParameters::OnStartedCallback& callback) {
-  StartDownload(std::move(download_create_info), std::move(stream), callback);
+  StartDownload(std::move(download_create_info), std::move(stream),
+                std::move(shared_url_loader_factory), callback);
 }
 
 void DownloadManagerImpl::OnUrlDownloadStopped(
@@ -1188,6 +1198,8 @@
       tab_referrer_url = entry->GetReferrer().url;
     }
   }
+  StoragePartitionImpl* storage_partition =
+      GetStoragePartition(browser_context_, render_process_id, render_frame_id);
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
       base::BindOnce(&DownloadManagerImpl::CreateDownloadHandlerForNavigation,
@@ -1196,6 +1208,7 @@
                      tab_referrer_url, std::move(url_chain), suggested_filename,
                      std::move(response), std::move(cert_status),
                      std::move(url_loader_client_endpoints),
+                     storage_partition->url_loader_factory_getter(),
                      base::MessageLoop::current()->task_runner()));
 }
 
@@ -1213,6 +1226,7 @@
     scoped_refptr<network::ResourceResponse> response,
     net::CertStatus cert_status,
     network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
+    scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter,
     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
@@ -1222,7 +1236,7 @@
           render_frame_id, site_url, tab_url, tab_referrer_url,
           std::move(url_chain), suggested_filename, std::move(response),
           std::move(cert_status), std::move(url_loader_client_endpoints),
-          task_runner)
+          url_loader_factory_getter->GetNetworkFactory(), task_runner)
           .release(),
       base::OnTaskRunnerDeleter(base::ThreadTaskRunnerHandle::Get()));
 
@@ -1239,7 +1253,7 @@
     StoragePartitionImpl* storage_partition) {
   if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
     std::unique_ptr<network::ResourceRequest> request =
-        CreateResourceRequest(params.get());
+        download::CreateResourceRequest(params.get());
     GURL site_url, tab_url, tab_referrer_url;
     auto* rfh = RenderFrameHost::FromID(params->render_process_host_id(),
                                         params->render_frame_host_routing_id());
diff --git a/content/browser/download/download_manager_impl.h b/content/browser/download/download_manager_impl.h
index 93d915b..9a4361b 100644
--- a/content/browser/download/download_manager_impl.h
+++ b/content/browser/download/download_manager_impl.h
@@ -41,6 +41,7 @@
 class DownloadItemFactory;
 class DownloadItemImpl;
 class ResourceContext;
+class URLLoaderFactoryGetter;
 
 class CONTENT_EXPORT DownloadManagerImpl
     : public DownloadManager,
@@ -74,10 +75,12 @@
   DownloadManagerDelegate* GetDelegate() const override;
   void Shutdown() override;
   void GetAllDownloads(DownloadVector* result) override;
-  void StartDownload(std::unique_ptr<download::DownloadCreateInfo> info,
-                     std::unique_ptr<download::InputStream> stream,
-                     const download::DownloadUrlParameters::OnStartedCallback&
-                         on_started) override;
+  void StartDownload(
+      std::unique_ptr<download::DownloadCreateInfo> info,
+      std::unique_ptr<download::InputStream> stream,
+      scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
+      const download::DownloadUrlParameters::OnStartedCallback& on_started)
+      override;
 
   int RemoveDownloadsByURLAndTime(
       const base::Callback<bool(const GURL&)>& url_filter,
@@ -130,6 +133,7 @@
   void OnUrlDownloadStarted(
       std::unique_ptr<download::DownloadCreateInfo> download_create_info,
       std::unique_ptr<download::InputStream> stream,
+      scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
       const download::DownloadUrlParameters::OnStartedCallback& callback)
       override;
   void OnUrlDownloadStopped(download::UrlDownloadHandler* downloader) override;
@@ -177,6 +181,7 @@
   void StartDownloadWithId(
       std::unique_ptr<download::DownloadCreateInfo> info,
       std::unique_ptr<download::InputStream> stream,
+      scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
       const download::DownloadUrlParameters::OnStartedCallback& on_started,
       bool new_download,
       uint32_t id);
@@ -263,6 +268,7 @@
       scoped_refptr<network::ResourceResponse> response,
       net::CertStatus cert_status,
       network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
+      scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter,
       const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
 
   // Factory for creation of downloads items.
diff --git a/content/browser/download/download_manager_impl_unittest.cc b/content/browser/download/download_manager_impl_unittest.cc
index 6c9e899..3b2c5afe 100644
--- a/content/browser/download/download_manager_impl_unittest.cc
+++ b/content/browser/download/download_manager_impl_unittest.cc
@@ -316,7 +316,7 @@
   MockBrowserContext() {
     content::BrowserContext::Initialize(this, base::FilePath());
   }
-  ~MockBrowserContext() {}
+  ~MockBrowserContext() { BrowserContext::NotifyWillBeDestroyed(this); }
 
   MOCK_CONST_METHOD0(GetPath, base::FilePath());
 #if !defined(OS_ANDROID)
@@ -469,7 +469,7 @@
     // in the factory.
     std::unique_ptr<download::DownloadRequestHandleInterface> req_handle;
     item.Start(std::unique_ptr<download::DownloadFile>(), std::move(req_handle),
-               info);
+               info, nullptr);
     DCHECK(id < download_urls_.size());
     EXPECT_CALL(item, GetURL()).WillRepeatedly(ReturnRef(download_urls_[id]));
 
@@ -579,7 +579,7 @@
       .WillOnce(Return(mock_file));
 
   download_manager_->StartDownload(
-      std::move(info), std::move(input_stream),
+      std::move(info), std::move(input_stream), nullptr,
       download::DownloadUrlParameters::OnStartedCallback());
   EXPECT_TRUE(download_manager_->GetDownload(local_id));
 
diff --git a/content/browser/download/download_resource_handler.cc b/content/browser/download/download_resource_handler.cc
index 9bb5292..d409db6 100644
--- a/content/browser/download/download_resource_handler.cc
+++ b/content/browser/download/download_resource_handler.cc
@@ -93,7 +93,8 @@
 
   download_manager->StartDownload(
       std::move(info),
-      std::make_unique<ByteStreamInputStream>(std::move(stream)), started_cb);
+      std::make_unique<ByteStreamInputStream>(std::move(stream)), nullptr,
+      started_cb);
 }
 
 void InitializeDownloadTabInfoOnUIThread(
diff --git a/content/browser/download/download_utils.cc b/content/browser/download/download_utils.cc
index edf8cf5..1c93efb 100644
--- a/content/browser/download/download_utils.cc
+++ b/content/browser/download/download_utils.cc
@@ -15,6 +15,7 @@
 #include "components/download/public/common/download_interrupt_reasons_utils.h"
 #include "components/download/public/common/download_save_info.h"
 #include "components/download/public/common/download_url_parameters.h"
+#include "components/download/public/common/download_utils.h"
 #include "content/browser/blob_storage/chrome_blob_storage_context.h"
 #include "content/browser/loader/upload_data_stream_builder.h"
 #include "content/browser/resource_context_impl.h"
@@ -24,103 +25,12 @@
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "net/base/elements_upload_data_stream.h"
-#include "net/base/load_flags.h"
 #include "net/base/upload_bytes_element_reader.h"
 #include "net/http/http_request_headers.h"
 #include "net/url_request/url_request_context.h"
-#include "services/network/public/cpp/resource_request.h"
 
 namespace content {
 
-namespace {
-
-void AppendExtraHeaders(net::HttpRequestHeaders* headers,
-                        download::DownloadUrlParameters* params) {
-  for (const auto& header : params->request_headers())
-    headers->SetHeaderIfMissing(header.first, header.second);
-}
-
-int GetLoadFlags(download::DownloadUrlParameters* params,
-                 bool has_upload_data) {
-  int load_flags = 0;
-  if (params->prefer_cache()) {
-    // If there is upload data attached, only retrieve from cache because there
-    // is no current mechanism to prompt the user for their consent for a
-    // re-post. For GETs, try to retrieve data from the cache and skip
-    // validating the entry if present.
-    if (has_upload_data)
-      load_flags |= net::LOAD_ONLY_FROM_CACHE | net::LOAD_SKIP_CACHE_VALIDATION;
-    else
-      load_flags |= net::LOAD_SKIP_CACHE_VALIDATION;
-  } else {
-    load_flags |= net::LOAD_DISABLE_CACHE;
-  }
-  return load_flags;
-}
-
-std::unique_ptr<net::HttpRequestHeaders> GetAdditionalRequestHeaders(
-    download::DownloadUrlParameters* params) {
-  auto headers = std::make_unique<net::HttpRequestHeaders>();
-  if (params->offset() == 0 &&
-      params->length() == download::DownloadSaveInfo::kLengthFullContent) {
-    AppendExtraHeaders(headers.get(), params);
-    return headers;
-  }
-
-  bool has_last_modified = !params->last_modified().empty();
-  bool has_etag = !params->etag().empty();
-
-  // Strong validator(i.e. etag or last modified) is required in range requests
-  // for download resumption and parallel download.
-  DCHECK(has_etag || has_last_modified);
-  if (!has_etag && !has_last_modified) {
-    DVLOG(1) << "Creating partial request without strong validators.";
-    AppendExtraHeaders(headers.get(), params);
-    return headers;
-  }
-
-  // Add "Range" header.
-  std::string range_header =
-      (params->length() == download::DownloadSaveInfo::kLengthFullContent)
-          ? base::StringPrintf("bytes=%" PRId64 "-", params->offset())
-          : base::StringPrintf("bytes=%" PRId64 "-%" PRId64, params->offset(),
-                               params->offset() + params->length() - 1);
-  headers->SetHeader(net::HttpRequestHeaders::kRange, range_header);
-
-  // Add "If-Range" headers.
-  if (params->use_if_range()) {
-    // In accordance with RFC 7233 Section 3.2, use If-Range to specify that
-    // the server return the entire entity if the validator doesn't match.
-    // Last-Modified can be used in the absence of ETag as a validator if the
-    // response headers satisfied the HttpUtil::HasStrongValidators()
-    // predicate.
-    //
-    // This function assumes that HasStrongValidators() was true and that the
-    // ETag and Last-Modified header values supplied are valid.
-    headers->SetHeader(net::HttpRequestHeaders::kIfRange,
-                       has_etag ? params->etag() : params->last_modified());
-    AppendExtraHeaders(headers.get(), params);
-    return headers;
-  }
-
-  // Add "If-Match"/"If-Unmodified-Since" headers.
-  if (has_etag)
-    headers->SetHeader(net::HttpRequestHeaders::kIfMatch, params->etag());
-
-  // According to RFC 7232 section 3.4, "If-Unmodified-Since" is mainly for
-  // old servers that didn't implement "If-Match" and must be ignored when
-  // "If-Match" presents.
-  if (has_last_modified) {
-    headers->SetHeader(net::HttpRequestHeaders::kIfUnmodifiedSince,
-                       params->last_modified());
-  }
-
-  AppendExtraHeaders(headers.get(), params);
-  return headers;
-}
-
-}  // namespace
-
 storage::BlobStorageContext* BlobStorageContextGetter(
     ResourceContext* resource_context) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -129,53 +39,6 @@
   return blob_context->context();
 }
 
-std::unique_ptr<network::ResourceRequest> CreateResourceRequest(
-    download::DownloadUrlParameters* params) {
-  DCHECK(params->offset() >= 0);
-
-  std::unique_ptr<network::ResourceRequest> request(
-      new network::ResourceRequest);
-  request->method = params->method();
-  request->url = params->url();
-  request->request_initiator = params->initiator();
-  request->do_not_prompt_for_login = params->do_not_prompt_for_login();
-  request->site_for_cookies = params->url();
-  request->referrer = params->referrer();
-  request->referrer_policy = params->referrer_policy();
-  request->allow_download = true;
-  request->is_main_frame = true;
-
-  if (params->render_process_host_id() >= 0)
-    request->render_frame_id = params->render_frame_host_routing_id();
-
-  bool has_upload_data = false;
-  if (params->post_body()) {
-    request->request_body = params->post_body();
-    has_upload_data = true;
-  }
-
-  if (params->post_id() >= 0) {
-    // The POST in this case does not have an actual body, and only works
-    // when retrieving data from cache. This is done because we don't want
-    // to do a re-POST without user consent, and currently don't have a good
-    // plan on how to display the UI for that.
-    DCHECK(params->prefer_cache());
-    DCHECK_EQ("POST", params->method());
-    request->request_body = new network::ResourceRequestBody();
-    request->request_body->set_identifier(params->post_id());
-    has_upload_data = true;
-  }
-
-  request->load_flags = GetLoadFlags(params, has_upload_data);
-
-  // Add additional request headers.
-  std::unique_ptr<net::HttpRequestHeaders> headers =
-      GetAdditionalRequestHeaders(params);
-  request->headers.Swap(headers.get());
-
-  return request;
-}
-
 std::unique_ptr<net::URLRequest> CreateURLRequestOnIOThread(
     download::DownloadUrlParameters* params) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -217,11 +80,11 @@
         std::move(element_readers), params->post_id()));
   }
 
-  request->SetLoadFlags(GetLoadFlags(params, request->get_upload()));
+  request->SetLoadFlags(download::GetLoadFlags(params, request->get_upload()));
 
   // Add additional request headers.
   std::unique_ptr<net::HttpRequestHeaders> headers =
-      GetAdditionalRequestHeaders(params);
+      download::GetAdditionalRequestHeaders(params);
   if (!headers->IsEmpty())
     request->SetExtraRequestHeaders(*headers);
 
diff --git a/content/browser/download/download_utils.h b/content/browser/download/download_utils.h
index 7747f3fc..1b52010 100644
--- a/content/browser/download/download_utils.h
+++ b/content/browser/download/download_utils.h
@@ -19,10 +19,6 @@
 class URLRequest;
 }  // namespace net
 
-namespace network {
-struct ResourceRequest;
-}
-
 namespace storage {
 class BlobStorageContext;
 }
@@ -32,10 +28,6 @@
 class BrowserContext;
 class ResourceContext;
 
-// Create a ResourceRequest from |params|.
-std::unique_ptr<network::ResourceRequest> CONTENT_EXPORT
-CreateResourceRequest(download::DownloadUrlParameters* params);
-
 // Create a URLRequest from |params|.
 std::unique_ptr<net::URLRequest> CONTENT_EXPORT
 CreateURLRequestOnIOThread(download::DownloadUrlParameters* params);
diff --git a/content/browser/download/download_worker.cc b/content/browser/download/download_worker.cc
deleted file mode 100644
index 1bde3542..0000000
--- a/content/browser/download/download_worker.cc
+++ /dev/null
@@ -1,176 +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 "content/browser/download/download_worker.h"
-
-#include "base/message_loop/message_loop.h"
-#include "components/download/public/common/download_create_info.h"
-#include "components/download/public/common/download_interrupt_reasons.h"
-#include "components/download/public/common/download_task_runner.h"
-#include "components/download/public/common/input_stream.h"
-#include "components/download/public/common/resource_downloader.h"
-#include "content/browser/download/download_utils.h"
-#include "content/browser/download/url_downloader.h"
-#include "content/public/common/content_features.h"
-#include "services/network/public/cpp/features.h"
-#include "services/network/public/cpp/shared_url_loader_factory.h"
-
-namespace content {
-namespace {
-
-const int kWorkerVerboseLevel = 1;
-
-class CompletedInputStream : public download::InputStream {
- public:
-  CompletedInputStream(download::DownloadInterruptReason status)
-      : status_(status){};
-  ~CompletedInputStream() override = default;
-
-  // download::InputStream
-  bool IsEmpty() override { return false; }
-  download::InputStream::StreamState Read(scoped_refptr<net::IOBuffer>* data,
-                                          size_t* length) override {
-    *length = 0;
-    return InputStream::StreamState::COMPLETE;
-  }
-
-  download::DownloadInterruptReason GetCompletionStatus() override {
-    return status_;
-  }
-
- private:
-  download::DownloadInterruptReason status_;
-  DISALLOW_COPY_AND_ASSIGN(CompletedInputStream);
-};
-
-void CreateUrlDownloadHandler(
-    std::unique_ptr<download::DownloadUrlParameters> params,
-    base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate,
-    scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter,
-    const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
-  download::UrlDownloadHandler::UniqueUrlDownloadHandlerPtr downloader(
-      nullptr, base::OnTaskRunnerDeleter(base::ThreadTaskRunnerHandle::Get()));
-
-  if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
-    std::unique_ptr<network::ResourceRequest> request =
-        CreateResourceRequest(params.get());
-    downloader.reset(download::ResourceDownloader::BeginDownload(
-                         delegate, std::move(params), std::move(request),
-                         url_loader_factory_getter->GetNetworkFactory(), GURL(),
-                         GURL(), GURL(), download::DownloadItem::kInvalidId,
-                         true, task_runner)
-                         .release());
-  } else {
-    // Build the URLRequest, BlobDataHandle is hold in original request for
-    // image download.
-    std::unique_ptr<net::URLRequest> url_request =
-        DownloadRequestCore::CreateRequestOnIOThread(
-            download::DownloadItem::kInvalidId, params.get());
-
-    downloader.reset(UrlDownloader::BeginDownload(
-                         delegate, std::move(url_request), params.get(), true)
-                         .release());
-  }
-  task_runner->PostTask(
-      FROM_HERE,
-      base::BindOnce(
-          &download::UrlDownloadHandler::Delegate::OnUrlDownloadHandlerCreated,
-          delegate, std::move(downloader)));
-}
-
-}  // namespace
-
-DownloadWorker::DownloadWorker(DownloadWorker::Delegate* delegate,
-                               int64_t offset,
-                               int64_t length)
-    : delegate_(delegate),
-      offset_(offset),
-      length_(length),
-      is_paused_(false),
-      is_canceled_(false),
-      is_user_cancel_(false),
-      url_download_handler_(nullptr, base::OnTaskRunnerDeleter(nullptr)),
-      weak_factory_(this) {
-  DCHECK(delegate_);
-}
-
-DownloadWorker::~DownloadWorker() = default;
-
-void DownloadWorker::SendRequest(
-    std::unique_ptr<download::DownloadUrlParameters> params,
-    scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter) {
-  download::GetIOTaskRunner()->PostTask(
-      FROM_HERE,
-      base::BindOnce(&CreateUrlDownloadHandler, std::move(params),
-                     weak_factory_.GetWeakPtr(), url_loader_factory_getter,
-                     base::ThreadTaskRunnerHandle::Get()));
-}
-
-void DownloadWorker::Pause() {
-  is_paused_ = true;
-  if (request_handle_)
-    request_handle_->PauseRequest();
-}
-
-void DownloadWorker::Resume() {
-  is_paused_ = false;
-  if (request_handle_)
-    request_handle_->ResumeRequest();
-}
-
-void DownloadWorker::Cancel(bool user_cancel) {
-  is_canceled_ = true;
-  is_user_cancel_ = user_cancel;
-  if (request_handle_)
-    request_handle_->CancelRequest(user_cancel);
-}
-
-void DownloadWorker::OnUrlDownloadStarted(
-    std::unique_ptr<download::DownloadCreateInfo> create_info,
-    std::unique_ptr<download::InputStream> input_stream,
-    const download::DownloadUrlParameters::OnStartedCallback& callback) {
-  // |callback| is not used in subsequent requests.
-  DCHECK(callback.is_null());
-
-  // Destroy the request if user canceled.
-  if (is_canceled_) {
-    VLOG(kWorkerVerboseLevel)
-        << "Byte stream arrived after user cancel the request.";
-    create_info->request_handle->CancelRequest(is_user_cancel_);
-    return;
-  }
-
-  // TODO(xingliu): Add metric for error handling.
-  if (create_info->result != download::DOWNLOAD_INTERRUPT_REASON_NONE) {
-    VLOG(kWorkerVerboseLevel)
-        << "Parallel download sub-request failed. reason = "
-        << create_info->result;
-    input_stream.reset(new CompletedInputStream(create_info->result));
-  }
-
-  request_handle_ = std::move(create_info->request_handle);
-
-  // Pause the stream if user paused, still push the stream reader to the sink.
-  if (is_paused_) {
-    VLOG(kWorkerVerboseLevel)
-        << "Byte stream arrived after user pause the request.";
-    Pause();
-  }
-
-  delegate_->OnInputStreamReady(this, std::move(input_stream));
-}
-
-void DownloadWorker::OnUrlDownloadStopped(
-    download::UrlDownloadHandler* downloader) {
-  // Release the |url_download_handler_|, the object will be deleted on IO
-  // thread.
-  url_download_handler_.reset();
-}
-
-void DownloadWorker::OnUrlDownloadHandlerCreated(
-    download::UrlDownloadHandler::UniqueUrlDownloadHandlerPtr downloader) {
-  url_download_handler_ = std::move(downloader);
-}
-
-}  // namespace content
diff --git a/content/browser/download/download_worker.h b/content/browser/download/download_worker.h
deleted file mode 100644
index 7ccc36b..0000000
--- a/content/browser/download/download_worker.h
+++ /dev/null
@@ -1,95 +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 CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_WORKER_H_
-#define CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_WORKER_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "components/download/public/common/download_request_handle_interface.h"
-#include "components/download/public/common/download_url_parameters.h"
-#include "components/download/public/common/url_download_handler.h"
-#include "content/browser/download/download_request_core.h"
-#include "content/browser/url_loader_factory_getter.h"
-#include "content/common/content_export.h"
-
-namespace content {
-
-// Helper class used to send subsequent range requests to fetch slices of the
-// file after handling response of the original non-range request.
-// TODO(xingliu): we should consider to reuse this class for single connection
-// download.
-class CONTENT_EXPORT DownloadWorker
-    : public download::UrlDownloadHandler::Delegate {
- public:
-  class Delegate {
-   public:
-    // Called when the the input stream is established after server response is
-    // handled. The stream contains data starts from |offset| of the
-    // destination file.
-    virtual void OnInputStreamReady(
-        DownloadWorker* worker,
-        std::unique_ptr<download::InputStream> input_stream) = 0;
-  };
-
-  DownloadWorker(DownloadWorker::Delegate* delegate,
-                 int64_t offset,
-                 int64_t length);
-  virtual ~DownloadWorker();
-
-  int64_t offset() const { return offset_; }
-  int64_t length() const { return length_; }
-
-  // Send network request to ask for a download.
-  void SendRequest(
-      std::unique_ptr<download::DownloadUrlParameters> params,
-      scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter);
-
-  // Download operations.
-  void Pause();
-  void Resume();
-  void Cancel(bool user_cancel);
-
- private:
-  // UrlDownloader::Delegate implementation.
-  void OnUrlDownloadStarted(
-      std::unique_ptr<download::DownloadCreateInfo> create_info,
-      std::unique_ptr<download::InputStream> input_stream,
-      const download::DownloadUrlParameters::OnStartedCallback& callback)
-      override;
-  void OnUrlDownloadStopped(download::UrlDownloadHandler* downloader) override;
-  void OnUrlDownloadHandlerCreated(
-      download::UrlDownloadHandler::UniqueUrlDownloadHandlerPtr downloader)
-      override;
-
-  DownloadWorker::Delegate* const delegate_;
-
-  // The starting position of the content for this worker to download.
-  int64_t offset_;
-
-  // The length of the request. May be 0 to fetch to the end of the file.
-  int64_t length_;
-
-  // States of the worker.
-  bool is_paused_;
-  bool is_canceled_;
-  bool is_user_cancel_;
-
-  // Used to control the network request. Live on UI thread.
-  std::unique_ptr<download::DownloadRequestHandleInterface> request_handle_;
-
-  // Used to handle the url request. Live and die on IO thread.
-  download::UrlDownloadHandler::UniqueUrlDownloadHandlerPtr
-      url_download_handler_;
-
-  base::WeakPtrFactory<DownloadWorker> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(DownloadWorker);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_WORKER_H_
diff --git a/content/browser/download/mock_download_item_impl.h b/content/browser/download/mock_download_item_impl.h
index abdc590..a951838 100644
--- a/content/browser/download/mock_download_item_impl.h
+++ b/content/browser/download/mock_download_item_impl.h
@@ -52,7 +52,9 @@
   void Start(
       std::unique_ptr<download::DownloadFile> download_file,
       std::unique_ptr<download::DownloadRequestHandleInterface> req_handle,
-      const download::DownloadCreateInfo& create_info) override {
+      const download::DownloadCreateInfo& create_info,
+      scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory)
+      override {
     MockStart(download_file.get(), req_handle.get());
   }
 
diff --git a/content/browser/download/parallel_download_job.cc b/content/browser/download/parallel_download_job.cc
index 37c82bd..3aefcb6 100644
--- a/content/browser/download/parallel_download_job.cc
+++ b/content/browser/download/parallel_download_job.cc
@@ -31,13 +31,15 @@
 ParallelDownloadJob::ParallelDownloadJob(
     download::DownloadItem* download_item,
     std::unique_ptr<download::DownloadRequestHandleInterface> request_handle,
-    const download::DownloadCreateInfo& create_info)
+    const download::DownloadCreateInfo& create_info,
+    scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory)
     : download::DownloadJobImpl(download_item, std::move(request_handle), true),
       initial_request_offset_(create_info.offset),
       initial_received_slices_(download_item->GetReceivedSlices()),
       content_length_(create_info.total_bytes),
       requests_sent_(false),
-      is_canceled_(false) {}
+      is_canceled_(false),
+      shared_url_loader_factory_(std::move(shared_url_loader_factory)) {}
 
 ParallelDownloadJob::~ParallelDownloadJob() = default;
 
@@ -125,7 +127,7 @@
 }
 
 void ParallelDownloadJob::OnInputStreamReady(
-    DownloadWorker* worker,
+    download::DownloadWorker* worker,
     std::unique_ptr<download::InputStream> input_stream) {
   bool success = DownloadJob::AddInputStream(
       std::move(input_stream), worker->offset(), worker->length());
@@ -245,8 +247,8 @@
   DCHECK(download_item_);
   DCHECK_EQ(download::DownloadSaveInfo::kLengthFullContent, length);
 
-  std::unique_ptr<DownloadWorker> worker =
-      std::make_unique<DownloadWorker>(this, offset, length);
+  auto worker =
+      std::make_unique<download::DownloadWorker>(this, offset, length);
 
   StoragePartition* storage_partition =
       BrowserContext::GetStoragePartitionForSite(
@@ -297,15 +299,8 @@
   download_params->set_referrer(download_item_->GetReferrerUrl());
   download_params->set_referrer_policy(net::URLRequest::NEVER_CLEAR_REFERRER);
 
-  download_params->set_blob_storage_context_getter(
-      base::BindOnce(&BlobStorageContextGetter,
-                     DownloadItemUtils::GetBrowserContext(download_item_)
-                         ->GetResourceContext()));
-
   // Send the request.
-  worker->SendRequest(std::move(download_params),
-                      static_cast<StoragePartitionImpl*>(storage_partition)
-                          ->url_loader_factory_getter());
+  worker->SendRequest(std::move(download_params), shared_url_loader_factory_);
   DCHECK(workers_.find(offset) == workers_.end());
   workers_[offset] = std::move(worker);
 }
diff --git a/content/browser/download/parallel_download_job.h b/content/browser/download/parallel_download_job.h
index 0769766..5a32b8ab 100644
--- a/content/browser/download/parallel_download_job.h
+++ b/content/browser/download/parallel_download_job.h
@@ -12,7 +12,7 @@
 #include "base/macros.h"
 #include "base/timer/timer.h"
 #include "components/download/public/common/download_job_impl.h"
-#include "content/browser/download/download_worker.h"
+#include "components/download/public/common/download_worker.h"
 #include "content/common/content_export.h"
 
 namespace content {
@@ -20,13 +20,15 @@
 // DownloadJob that can create concurrent range requests to fetch different
 // parts of the file.
 // The original request is hold in base class.
-class CONTENT_EXPORT ParallelDownloadJob : public download::DownloadJobImpl,
-                                           public DownloadWorker::Delegate {
+class CONTENT_EXPORT ParallelDownloadJob
+    : public download::DownloadJobImpl,
+      public download::DownloadWorker::Delegate {
  public:
   ParallelDownloadJob(
       download::DownloadItem* download_item,
       std::unique_ptr<download::DownloadRequestHandleInterface> request_handle,
-      const download::DownloadCreateInfo& create_info);
+      const download::DownloadCreateInfo& create_info,
+      scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory);
   ~ParallelDownloadJob() override;
 
   // DownloadJobImpl implementation.
@@ -48,7 +50,7 @@
   virtual int GetMinRemainingTimeInSeconds() const;
 
   using WorkerMap =
-      std::unordered_map<int64_t, std::unique_ptr<DownloadWorker>>;
+      std::unordered_map<int64_t, std::unique_ptr<download::DownloadWorker>>;
 
   // Map from the offset position of the slice to the worker that downloads the
   // slice.
@@ -59,7 +61,7 @@
 
   // DownloadWorker::Delegate implementation.
   void OnInputStreamReady(
-      DownloadWorker* worker,
+      download::DownloadWorker* worker,
       std::unique_ptr<download::InputStream> input_stream) override;
 
   // Build parallel requests after a delay, to effectively measure the single
@@ -103,6 +105,9 @@
   // If the download progress is canceled.
   bool is_canceled_;
 
+  // SharedURLLoaderFactory to issue network requests.
+  scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(ParallelDownloadJob);
 };
 
diff --git a/content/browser/download/parallel_download_job_unittest.cc b/content/browser/download/parallel_download_job_unittest.cc
index b6fe144..e39ab4a 100644
--- a/content/browser/download/parallel_download_job_unittest.cc
+++ b/content/browser/download/parallel_download_job_unittest.cc
@@ -70,14 +70,15 @@
       int min_remaining_time)
       : ParallelDownloadJob(download_item,
                             std::move(request_handle),
-                            create_info),
+                            create_info,
+                            nullptr),
         request_count_(request_count),
         min_slice_size_(min_slice_size),
         min_remaining_time_(min_remaining_time) {}
 
   void CreateRequest(int64_t offset, int64_t length) override {
-    std::unique_ptr<DownloadWorker> worker =
-        std::make_unique<DownloadWorker>(this, offset, length);
+    auto worker =
+        std::make_unique<download::DownloadWorker>(this, offset, length);
 
     DCHECK(workers_.find(offset) == workers_.end());
     workers_[offset] = std::move(worker);
@@ -98,7 +99,7 @@
   }
 
   void OnInputStreamReady(
-      DownloadWorker* worker,
+      download::DownloadWorker* worker,
       std::unique_ptr<download::InputStream> input_stream) override {
     CountOnInputStreamReady();
   }
@@ -165,7 +166,7 @@
   bool IsJobCanceled() const { return job_->is_canceled_; };
 
   void MakeWorkerReady(
-      DownloadWorker* worker,
+      download::DownloadWorker* worker,
       std::unique_ptr<MockDownloadRequestHandle> request_handle) {
     download::UrlDownloadHandler::Delegate* delegate =
         static_cast<download::UrlDownloadHandler::Delegate*>(worker);
@@ -174,7 +175,7 @@
     create_info->request_handle = std::move(request_handle);
     delegate->OnUrlDownloadStarted(
         std::move(create_info), std::make_unique<download::MockInputStream>(),
-        download::DownloadUrlParameters::OnStartedCallback());
+        nullptr, download::DownloadUrlParameters::OnStartedCallback());
   }
 
   void VerifyWorker(int64_t offset, int64_t length) const {
diff --git a/content/browser/download/url_downloader.cc b/content/browser/download/url_downloader.cc
index addee1e9a..034fadd 100644
--- a/content/browser/download/url_downloader.cc
+++ b/content/browser/download/url_downloader.cc
@@ -230,7 +230,7 @@
           &download::UrlDownloadHandler::Delegate::OnUrlDownloadStarted,
           delegate_, std::move(create_info),
           std::make_unique<ByteStreamInputStream>(std::move(stream_reader)),
-          callback));
+          nullptr, callback));
 }
 
 void UrlDownloader::OnReadyToRead() {
diff --git a/content/browser/download/url_downloader_factory.cc b/content/browser/download/url_downloader_factory.cc
new file mode 100644
index 0000000..342a24a
--- /dev/null
+++ b/content/browser/download/url_downloader_factory.cc
@@ -0,0 +1,34 @@
+// Copyright 2018 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 "content/browser/download/url_downloader_factory.h"
+
+#include "components/download/public/common/download_item.h"
+#include "content/browser/download/download_request_core.h"
+#include "content/browser/download/url_downloader.h"
+
+namespace content {
+
+UrlDownloaderFactory::UrlDownloaderFactory() = default;
+
+UrlDownloaderFactory::~UrlDownloaderFactory() = default;
+
+download::UrlDownloadHandler::UniqueUrlDownloadHandlerPtr
+UrlDownloaderFactory::CreateUrlDownloadHandler(
+    std::unique_ptr<download::DownloadUrlParameters> params,
+    base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate,
+    scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
+    const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
+  std::unique_ptr<net::URLRequest> url_request =
+      DownloadRequestCore::CreateRequestOnIOThread(
+          download::DownloadItem::kInvalidId, params.get());
+
+  return download::UrlDownloadHandler::UniqueUrlDownloadHandlerPtr(
+      UrlDownloader::BeginDownload(delegate, std::move(url_request),
+                                   params.get(), true)
+          .release(),
+      base::OnTaskRunnerDeleter(base::ThreadTaskRunnerHandle::Get()));
+}
+
+}  // namespace content
diff --git a/content/browser/download/url_downloader_factory.h b/content/browser/download/url_downloader_factory.h
new file mode 100644
index 0000000..cd187b55
--- /dev/null
+++ b/content/browser/download/url_downloader_factory.h
@@ -0,0 +1,30 @@
+// Copyright 2018 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 CONTENT_BROWSER_DOWNLOAD_URL_DOWNLOADER_FACTORY_H_
+#define CONTENT_BROWSER_DOWNLOAD_URL_DOWNLOADER_FACTORY_H_
+
+#include "components/download/public/common/url_download_handler_factory.h"
+
+namespace content {
+
+// Class for creating UrlDownloader object.
+// TODO(qinmin): remove this once network service is fully enabled.
+class UrlDownloaderFactory : public download::UrlDownloadHandlerFactory {
+ public:
+  UrlDownloaderFactory();
+  ~UrlDownloaderFactory() override;
+
+  // download::UrlDownloadHandlerFactory
+  download::UrlDownloadHandler::UniqueUrlDownloadHandlerPtr
+  CreateUrlDownloadHandler(
+      std::unique_ptr<download::DownloadUrlParameters> params,
+      base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate,
+      scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
+      const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) override;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_DOWNLOAD_URL_DOWNLOADER_FACTORY_H_
diff --git a/content/browser/frame_host/input/legacy_ipc_frame_input_handler.cc b/content/browser/frame_host/input/legacy_ipc_frame_input_handler.cc
index 3c26e080..9c14f573 100644
--- a/content/browser/frame_host/input/legacy_ipc_frame_input_handler.cc
+++ b/content/browser/frame_host/input/legacy_ipc_frame_input_handler.cc
@@ -22,20 +22,9 @@
     int32_t start,
     int32_t end,
     const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) {
-  std::vector<blink::WebImeTextSpan> ime_text_spans;
-  for (const auto& ime_text_span : ui_ime_text_spans) {
-    blink::WebImeTextSpan blink_ime_text_span(
-        ConvertUiImeTextSpanTypeToWebType(ime_text_span.type),
-        ime_text_span.start_offset, ime_text_span.end_offset,
-        ime_text_span.underline_color,
-        ConvertUiThicknessToUiImeTextSpanThickness(ime_text_span.thickness),
-        ime_text_span.background_color,
-        ime_text_span.suggestion_highlight_color, ime_text_span.suggestions);
-    ime_text_spans.push_back(blink_ime_text_span);
-  }
-
   SendInput(std::make_unique<InputMsg_SetCompositionFromExistingText>(
-      routing_id_, start, end, ime_text_spans));
+      routing_id_, start, end,
+      ConvertUiImeTextSpansToBlinkImeTextSpans(ui_ime_text_spans)));
 }
 
 void LegacyIPCFrameInputHandler::ExtendSelectionAndDelete(int32_t before,
diff --git a/content/browser/frame_host/navigation_controller_impl_browsertest.cc b/content/browser/frame_host/navigation_controller_impl_browsertest.cc
index d288de7..23235d3 100644
--- a/content/browser/frame_host/navigation_controller_impl_browsertest.cc
+++ b/content/browser/frame_host/navigation_controller_impl_browsertest.cc
@@ -4057,9 +4057,6 @@
 // replaced data.
 IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
                        ReplacedNavigationEntryData_ClientSideRedirect) {
-  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
-                            ->GetFrameTree()
-                            ->root();
   const NavigationControllerImpl& controller =
       static_cast<const NavigationControllerImpl&>(
           shell()->web_contents()->GetController());
@@ -4069,11 +4066,13 @@
       "/navigation_controller/simple_page_1.html"));
 
   {
-    // Load the redirecting page.
-    FrameNavigateParamsCapturer capturer(root);
-    capturer.set_navigations_remaining(2);
-    ASSERT_TRUE(NavigateToURL(shell(), url1));
-    capturer.Wait();
+    TestNavigationManager navigation_manager_1(shell()->web_contents(), url1);
+    TestNavigationManager navigation_manager_2(shell()->web_contents(), url2);
+
+    shell()->LoadURL(url1);
+
+    navigation_manager_1.WaitForNavigationFinished();  // Initial navigation.
+    navigation_manager_2.WaitForNavigationFinished();  // Client-side redirect.
 
     ASSERT_EQ(1, controller.GetEntryCount());
     NavigationEntry* entry1 = controller.GetEntryAtIndex(0);
diff --git a/content/browser/frame_host/render_frame_host_delegate.h b/content/browser/frame_host/render_frame_host_delegate.h
index 78f3ce8..0d3b28e6 100644
--- a/content/browser/frame_host/render_frame_host_delegate.h
+++ b/content/browser/frame_host/render_frame_host_delegate.h
@@ -345,7 +345,11 @@
   virtual bool IsBeingDestroyed() const;
 
   // Notifies that the render frame started loading a subresource.
-  virtual void SubresourceResponseStarted(
+  virtual void SubresourceResponseStarted(const GURL& url,
+                                          net::CertStatus cert_status) {}
+
+  // Notifies that the render finished loading a subresource.
+  virtual void SubresourceLoadComplete(
       mojom::SubresourceLoadInfoPtr subresource_load_info) {}
 
   // Request to print a frame that is in a different process than its parent.
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 53540189..aeadd1ab 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -131,7 +131,7 @@
 #include "media/audio/audio_manager.h"
 #include "media/base/media_switches.h"
 #include "media/base/user_input_monitor.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "media/mojo/interfaces/remoting.mojom.h"
 #include "media/mojo/services/media_interface_provider.h"
 #include "media/mojo/services/media_metrics_provider.h"
@@ -3010,8 +3010,14 @@
 }
 
 void RenderFrameHostImpl::SubresourceResponseStarted(
+    const GURL& url,
+    net::CertStatus cert_status) {
+  delegate_->SubresourceResponseStarted(url, cert_status);
+}
+
+void RenderFrameHostImpl::SubresourceLoadComplete(
     mojom::SubresourceLoadInfoPtr subresource_load_info) {
-  delegate_->SubresourceResponseStarted(std::move(subresource_load_info));
+  delegate_->SubresourceLoadComplete(std::move(subresource_load_info));
 }
 
 namespace {
@@ -3101,11 +3107,8 @@
       base::Bind(&RenderFrameHostImpl::BindMediaInterfaceFactoryRequest,
                  base::Unretained(this)));
 
-  // This is to support usage of WebSockets in cases in which there is an
-  // associated RenderFrame. This is important for showing the correct security
-  // state of the page and also honoring user override of bad certificates.
-  registry_->AddInterface(base::Bind(&WebSocketManager::CreateWebSocketForFrame,
-                                     process_->GetID(), routing_id_));
+  registry_->AddInterface(base::BindRepeating(
+      &RenderFrameHostImpl::CreateWebSocket, base::Unretained(this)));
 
   registry_->AddInterface(base::Bind(&SharedWorkerConnectorImpl::Create,
                                      process_->GetID(), routing_id_));
@@ -4085,6 +4088,10 @@
 
 void RenderFrameHostImpl::UpdateSubresourceLoaderFactories() {
   DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
+  // We only send loader factory bundle upon navigation, so
+  // bail out if the frame hasn't commited any yet.
+  if (!has_committed_any_navigation_)
+    return;
   DCHECK(network_service_connection_error_handler_holder_.is_bound());
 
   network::mojom::URLLoaderFactoryPtrInfo default_factory_info;
@@ -4355,6 +4362,25 @@
                  base::Unretained(this))));
 }
 
+void RenderFrameHostImpl::CreateWebSocket(
+    network::mojom::WebSocketRequest request) {
+  if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+    auto* context = GetSiteInstance()->GetBrowserContext();
+    auto* storage_partition = static_cast<StoragePartitionImpl*>(
+        BrowserContext::GetStoragePartition(context, GetSiteInstance()));
+    storage_partition->GetNetworkContext()->CreateWebSocket(
+        std::move(request), process_->GetID(), routing_id_,
+        last_committed_origin_);
+  } else {
+    // This is to support usage of WebSockets in cases in which there is an
+    // associated RenderFrame. This is important for showing the correct
+    // security state of the page and also honoring user override of bad
+    // certificates.
+    WebSocketManager::CreateWebSocketForFrame(process_->GetID(), routing_id_,
+                                              std::move(request));
+  }
+}
+
 void RenderFrameHostImpl::OnMediaInterfaceFactoryConnectionError() {
   DCHECK(media_interface_proxy_);
   media_interface_proxy_.reset();
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index 8e80d51..6bee49d 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -896,7 +896,9 @@
           validated_params) override;
   void BeginNavigation(const CommonNavigationParams& common_params,
                        mojom::BeginNavigationParamsPtr begin_params) override;
-  void SubresourceResponseStarted(
+  void SubresourceResponseStarted(const GURL& url,
+                                  net::CertStatus cert_status) override;
+  void SubresourceLoadComplete(
       mojom::SubresourceLoadInfoPtr subresource_load_info) override;
   void DidChangeName(const std::string& name,
                      const std::string& unique_name) override;
@@ -1018,6 +1020,8 @@
   void BindMediaInterfaceFactoryRequest(
       media::mojom::InterfaceFactoryRequest request);
 
+  void CreateWebSocket(network::mojom::WebSocketRequest request);
+
   // Callback for connection error on the media::mojom::InterfaceFactory client.
   void OnMediaInterfaceFactoryConnectionError();
 
diff --git a/content/browser/frame_host/render_widget_host_view_guest_unittest.cc b/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
index d902193..8c5afa6 100644
--- a/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
+++ b/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
@@ -10,7 +10,6 @@
 #include "base/macros.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
-#include "base/test/scoped_task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
@@ -26,6 +25,7 @@
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "content/test/fake_renderer_compositor_frame_sink.h"
 #include "content/test/mock_render_widget_host_delegate.h"
 #include "content/test/mock_widget_impl.h"
@@ -40,9 +40,7 @@
 
 class RenderWidgetHostViewGuestTest : public testing::Test {
  public:
-  RenderWidgetHostViewGuestTest()
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
+  RenderWidgetHostViewGuestTest() {}
 
   void SetUp() override {
 #if !defined(OS_ANDROID)
@@ -79,8 +77,7 @@
   }
 
  protected:
-  // Needed by base::PostTaskWithTraits in RenderWidgetHostImpl constructor.
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
+  TestBrowserThreadBundle thread_bundle_;
 
   std::unique_ptr<BrowserContext> browser_context_;
   MockRenderWidgetHostDelegate delegate_;
diff --git a/content/browser/gpu/compositor_util.cc b/content/browser/gpu/compositor_util.cc
index 7f728be9..16571a8 100644
--- a/content/browser/gpu/compositor_util.cc
+++ b/content/browser/gpu/compositor_util.cc
@@ -28,7 +28,7 @@
 #include "gpu/config/gpu_finch_features.h"
 #include "gpu/config/gpu_switches.h"
 #include "gpu/ipc/host/gpu_memory_buffer_support.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "ui/gl/gl_switches.h"
 
 namespace content {
diff --git a/content/browser/gpu/gpu_data_manager_impl.cc b/content/browser/gpu/gpu_data_manager_impl.cc
index a8ad7fb..a64645c 100644
--- a/content/browser/gpu/gpu_data_manager_impl.cc
+++ b/content/browser/gpu/gpu_data_manager_impl.cc
@@ -89,6 +89,11 @@
   private_->BlockSwiftShader();
 }
 
+bool GpuDataManagerImpl::SwiftShaderAllowed() const {
+  base::AutoLock auto_lock(lock_);
+  return private_->SwiftShaderAllowed();
+}
+
 bool GpuDataManagerImpl::HardwareAccelerationEnabled() const {
   base::AutoLock auto_lock(lock_);
   return private_->HardwareAccelerationEnabled();
@@ -100,6 +105,11 @@
   private_->GetDisabledExtensions(disabled_extensions);
 }
 
+bool GpuDataManagerImpl::GpuProcessStartAllowed() const {
+  base::AutoLock auto_lock(lock_);
+  return private_->GpuProcessStartAllowed();
+}
+
 void GpuDataManagerImpl::GetDisabledWebGLExtensions(
     std::string* disabled_webgl_extensions) const {
   base::AutoLock auto_lock(lock_);
diff --git a/content/browser/gpu/gpu_data_manager_impl.h b/content/browser/gpu/gpu_data_manager_impl.h
index 0fa3ce2..f4118d20 100644
--- a/content/browser/gpu/gpu_data_manager_impl.h
+++ b/content/browser/gpu/gpu_data_manager_impl.h
@@ -84,6 +84,8 @@
   bool HardwareAccelerationEnabled() const override;
   void GetDisabledExtensions(std::string* disabled_extensions) const override;
 
+  bool GpuProcessStartAllowed() const;
+
   void GetDisabledWebGLExtensions(std::string* disabled_webgl_extensions) const;
 
   bool IsGpuFeatureInfoAvailable() const;
@@ -159,6 +161,7 @@
   void OnGpuProcessInitFailure();
 
   void BlockSwiftShader();
+  bool SwiftShaderAllowed() const;
 
  private:
   friend class GpuDataManagerImplPrivate;
diff --git a/content/browser/gpu/gpu_data_manager_impl_private.cc b/content/browser/gpu/gpu_data_manager_impl_private.cc
index 706f45fd..833f2db 100644
--- a/content/browser/gpu/gpu_data_manager_impl_private.cc
+++ b/content/browser/gpu/gpu_data_manager_impl_private.cc
@@ -12,6 +12,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/command_line.h"
+#include "base/feature_list.h"
 #include "base/memory/ptr_util.h"
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram_functions.h"
@@ -21,6 +22,7 @@
 #include "base/version.h"
 #include "build/build_config.h"
 #include "cc/base/switches.h"
+#include "components/viz/common/features.h"
 #include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
 #include "content/browser/gpu/compositor_util.h"
 #include "content/browser/gpu/gpu_process_host.h"
@@ -44,7 +46,7 @@
 #include "gpu/ipc/common/gpu_preferences_util.h"
 #include "gpu/ipc/common/memory_stats.h"
 #include "gpu/ipc/host/shader_disk_cache.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "ui/base/ui_base_switches.h"
 #include "ui/gfx/switches.h"
 #include "ui/gl/gl_features.h"
@@ -315,6 +317,11 @@
   return true;
 }
 
+bool GpuDataManagerImplPrivate::GpuProcessStartAllowed() const {
+  return base::FeatureList::IsEnabled(features::kVizDisplayCompositor) ||
+         GpuAccessAllowed(nullptr);
+}
+
 void GpuDataManagerImplPrivate::RequestCompleteGpuInfoIfNeeded() {
   if (complete_gpu_info_already_requested_)
     return;
@@ -440,8 +447,7 @@
                                   gpu::GpuPreferencesToSwitchValue(gpu_prefs));
 
   std::string use_gl;
-  if (card_disabled_ && !swiftshader_blocked_ &&
-      !browser_command_line->HasSwitch(switches::kDisableSoftwareRasterizer)) {
+  if (card_disabled_ && SwiftShaderAllowed()) {
     use_gl = gl::kGLImplementationSwiftShaderForWebGLName;
   } else {
     use_gl = browser_command_line->GetSwitchValueASCII(switches::kUseGL);
@@ -492,15 +498,8 @@
 
 void GpuDataManagerImplPrivate::DisableHardwareAcceleration() {
   card_disabled_ = true;
-  bool gpu_process_blocked = true;
-#if BUILDFLAG(ENABLE_SWIFTSHADER)
-  if (!swiftshader_blocked_ &&
-      !base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kDisableSoftwareRasterizer))
-    gpu_process_blocked = false;
-#endif
-  if (gpu_process_blocked)
-    OnGpuProcessBlocked();
+  if (!SwiftShaderAllowed())
+    OnGpuBlocked();
 }
 
 bool GpuDataManagerImplPrivate::HardwareAccelerationEnabled() const {
@@ -509,12 +508,21 @@
 
 void GpuDataManagerImplPrivate::BlockSwiftShader() {
   swiftshader_blocked_ = true;
-  OnGpuProcessBlocked();
+  OnGpuBlocked();
 }
 
-void GpuDataManagerImplPrivate::OnGpuProcessBlocked() {
-  gpu::GpuFeatureInfo gpu_feature_info =
-      gpu::ComputeGpuFeatureInfoWithNoGpuProcess();
+bool GpuDataManagerImplPrivate::SwiftShaderAllowed() const {
+#if !BUILDFLAG(ENABLE_SWIFTSHADER)
+  return false;
+#else
+  return !swiftshader_blocked_ &&
+         !base::CommandLine::ForCurrentProcess()->HasSwitch(
+             switches::kDisableSoftwareRasterizer);
+#endif
+}
+
+void GpuDataManagerImplPrivate::OnGpuBlocked() {
+  gpu::GpuFeatureInfo gpu_feature_info = gpu::ComputeGpuFeatureInfoWithNoGpu();
   UpdateGpuFeatureInfo(gpu_feature_info);
 
   // Some observers might be waiting.
@@ -834,15 +842,16 @@
     DisableHardwareAcceleration();
     return;
   }
-  if (!swiftshader_blocked_) {
+  if (SwiftShaderAllowed()) {
     BlockSwiftShader();
     return;
   }
-  // If GPU process fails to launch with hardware GPU, and then fails
-  // to launch with SwiftShader if available, then GPU process should
-  // not launch again.
-  // TODO(zmo): In viz mode, we will have a GPU process no matter what.
-  NOTREACHED();
+  if (!base::FeatureList::IsEnabled(features::kVizDisplayCompositor)) {
+    // When Viz display compositor is not enabled, if GPU process fails to
+    // launch with hardware GPU, and then fails to launch with SwiftShader if
+    // available, then GPU process should not launch again.
+    NOTREACHED();
+  }
 }
 
 }  // namespace content
diff --git a/content/browser/gpu/gpu_data_manager_impl_private.h b/content/browser/gpu/gpu_data_manager_impl_private.h
index 9fc03cd..7991d7f5 100644
--- a/content/browser/gpu/gpu_data_manager_impl_private.h
+++ b/content/browser/gpu/gpu_data_manager_impl_private.h
@@ -42,6 +42,7 @@
   void BlacklistWebGLForTesting();
   gpu::GPUInfo GetGPUInfo() const;
   bool GpuAccessAllowed(std::string* reason) const;
+  bool GpuProcessStartAllowed() const;
   void RequestCompleteGpuInfoIfNeeded();
   bool IsEssentialGpuInfoAvailable() const;
   bool IsGpuFeatureInfoAvailable() const;
@@ -55,6 +56,7 @@
   void DisableHardwareAcceleration();
   bool HardwareAccelerationEnabled() const;
   void BlockSwiftShader();
+  bool SwiftShaderAllowed() const;
 
   void UpdateGpuInfo(const gpu::GPUInfo& gpu_info);
   void UpdateGpuFeatureInfo(const gpu::GpuFeatureInfo& gpu_feature_info);
@@ -144,8 +146,9 @@
   // Notify all observers whenever there is a GPU info update.
   void NotifyGpuInfoUpdate();
 
-  // Called when gpu process becomes blocked.
-  void OnGpuProcessBlocked();
+  // Called when GPU access (hardware acceleration and swiftshader) becomes
+  // blocked.
+  void OnGpuBlocked();
 
   // Helper to extract the domain from a given URL.
   std::string GetDomainFromURL(const GURL& url) const;
diff --git a/content/browser/gpu/gpu_internals_ui.cc b/content/browser/gpu/gpu_internals_ui.cc
index 5b72581..a8d97e81 100644
--- a/content/browser/gpu/gpu_internals_ui.cc
+++ b/content/browser/gpu/gpu_internals_ui.cc
@@ -498,12 +498,13 @@
 void GpuMessageHandler::RegisterMessages() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-  web_ui()->RegisterMessageCallback("browserBridgeInitialized",
-      base::Bind(&GpuMessageHandler::OnBrowserBridgeInitialized,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("callAsync",
-      base::Bind(&GpuMessageHandler::OnCallAsync,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "browserBridgeInitialized",
+      base::BindRepeating(&GpuMessageHandler::OnBrowserBridgeInitialized,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "callAsync", base::BindRepeating(&GpuMessageHandler::OnCallAsync,
+                                       base::Unretained(this)));
 }
 
 void GpuMessageHandler::OnCallAsync(const base::ListValue* args) {
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc
index aa0ef77..9df5bca7 100644
--- a/content/browser/gpu/gpu_process_host.cc
+++ b/content/browser/gpu/gpu_process_host.cc
@@ -15,6 +15,7 @@
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/command_line.h"
+#include "base/feature_list.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
@@ -30,6 +31,7 @@
 #include "build/build_config.h"
 #include "components/discardable_memory/service/discardable_shared_memory_manager.h"
 #include "components/tracing/common/tracing_switches.h"
+#include "components/viz/common/features.h"
 #include "components/viz/common/switches.h"
 #include "content/browser/browser_child_process_host_impl.h"
 #include "content/browser/browser_main_loop.h"
@@ -61,7 +63,7 @@
 #include "gpu/config/gpu_driver_bug_workaround_type.h"
 #include "gpu/ipc/host/shader_disk_cache.h"
 #include "media/base/media_switches.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "mojo/edk/embedder/embedder.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
 #include "services/service_manager/public/cpp/connector.h"
@@ -106,12 +108,13 @@
 
 namespace content {
 
-bool GpuProcessHost::gpu_enabled_ = true;
-bool GpuProcessHost::hardware_gpu_enabled_ = true;
 base::subtle::Atomic32 GpuProcessHost::gpu_crash_count_ = 0;
 int GpuProcessHost::gpu_recent_crash_count_ = 0;
 bool GpuProcessHost::crashed_before_ = false;
 int GpuProcessHost::swiftshader_crash_count_ = 0;
+int GpuProcessHost::swiftshader_recent_crash_count_ = 0;
+int GpuProcessHost::display_compositor_crash_count_ = 0;
+int GpuProcessHost::display_compositor_recent_crash_count_ = 0;
 
 namespace {
 
@@ -463,8 +466,8 @@
   // Don't grant further access to GPU if it is not allowed.
   GpuDataManagerImpl* gpu_data_manager = GpuDataManagerImpl::GetInstance();
   DCHECK(gpu_data_manager);
-  if (!gpu_data_manager->GpuAccessAllowed(nullptr)) {
-    DLOG(ERROR) << "!GpuDataManagerImpl::GpuAccessAllowed()";
+  if (!gpu_data_manager->GpuProcessStartAllowed()) {
+    DLOG(ERROR) << "!GpuDataManagerImpl::GpuProcessStartAllowed()";
     return nullptr;
   }
 
@@ -554,11 +557,29 @@
   return static_cast<int>(base::subtle::NoBarrier_Load(&gpu_crash_count_));
 }
 
+// static
+void GpuProcessHost::IncrementCrashCount(int* crash_count) {
+  // Last time the process crashed.
+  static base::Time last_crash_time;
+
+  // Allow about 1 crash per hour to be removed from the crash count, so very
+  // occasional crashes won't eventually add up and prevent the process from
+  // launching.
+  base::Time current_time = base::Time::Now();
+  if (crashed_before_) {
+    int hours_different = (current_time - last_crash_time).InHours();
+    *crash_count = std::max(0, *crash_count - hours_different);
+  }
+  ++(*crash_count);
+
+  crashed_before_ = true;
+  last_crash_time = current_time;
+}
+
 GpuProcessHost::GpuProcessHost(int host_id, GpuProcessKind kind)
     : host_id_(host_id),
       valid_(true),
       in_process_(false),
-      swiftshader_rendering_(false),
       kind_(kind),
       process_launched_(false),
       status_(UNKNOWN),
@@ -1230,20 +1251,12 @@
       cmd_line.get(), process_->GetData().id);
 
   GpuDataManagerImpl::GetInstance()->AppendGpuCommandLine(cmd_line.get());
-  if (cmd_line->HasSwitch(switches::kUseGL)) {
-    swiftshader_rendering_ = (cmd_line->GetSwitchValueASCII(switches::kUseGL) ==
-                              gl::kGLImplementationSwiftShaderForWebGLName);
-  }
-
-  bool current_gpu_type_enabled =
-      swiftshader_rendering_ ? gpu_enabled_ : hardware_gpu_enabled_;
-  if (!current_gpu_type_enabled) {
-    SendOutstandingReplies(EstablishChannelStatus::GPU_ACCESS_DENIED);
-    return false;
-  }
+  bool swiftshader_rendering =
+      (cmd_line->GetSwitchValueASCII(switches::kUseGL) ==
+       gl::kGLImplementationSwiftShaderForWebGLName);
 
   UMA_HISTOGRAM_BOOLEAN("GPU.GPUProcessSoftwareRendering",
-                        swiftshader_rendering_);
+                        swiftshader_rendering);
 
   // If specified, prepend a launcher program to the command line.
   if (!gpu_launcher.empty())
@@ -1315,9 +1328,6 @@
   const int kGpuMaxCrashCount = 6;
 #endif
 
-  // Last time the GPU process crashed.
-  static base::Time last_gpu_crash_time;
-
   bool disable_crash_limit = base::CommandLine::ForCurrentProcess()->HasSwitch(
       switches::kDisableGpuProcessCrashLimit);
 
@@ -1325,19 +1335,7 @@
   // was intended for actual rendering (and not just checking caps or other
   // options).
   if (process_launched_ && kind_ == GPU_PROCESS_KIND_SANDBOXED) {
-    if (swiftshader_rendering_) {
-      UMA_HISTOGRAM_EXACT_LINEAR(
-          "GPU.SwiftShaderLifetimeEvents",
-          DIED_FIRST_TIME + swiftshader_crash_count_,
-          static_cast<int>(GPU_PROCESS_LIFETIME_EVENT_MAX));
-
-      if (++swiftshader_crash_count_ >= kGpuMaxCrashCount &&
-          !disable_crash_limit) {
-        // SwiftShader is too unstable to use. Disable it for current session.
-        gpu_enabled_ = false;
-        GpuDataManagerImpl::GetInstance()->BlockSwiftShader();
-      }
-    } else {
+    if (GpuDataManagerImpl::GetInstance()->HardwareAccelerationEnabled()) {
       int count = static_cast<int>(
           base::subtle::NoBarrier_AtomicIncrement(&gpu_crash_count_, 1));
       UMA_HISTOGRAM_EXACT_LINEAR(
@@ -1345,20 +1343,7 @@
           std::min(DIED_FIRST_TIME + count, GPU_PROCESS_LIFETIME_EVENT_MAX - 1),
           static_cast<int>(GPU_PROCESS_LIFETIME_EVENT_MAX));
 
-      // Allow about 1 GPU crash per hour to be removed from the crash count,
-      // so very occasional crashes won't eventually add up and prevent the
-      // GPU process from launching.
-      ++gpu_recent_crash_count_;
-      base::Time current_time = base::Time::Now();
-      if (crashed_before_) {
-        int hours_different = (current_time - last_gpu_crash_time).InHours();
-        gpu_recent_crash_count_ =
-            std::max(0, gpu_recent_crash_count_ - hours_different);
-      }
-
-      crashed_before_ = true;
-      last_gpu_crash_time = current_time;
-
+      IncrementCrashCount(&gpu_recent_crash_count_);
       if ((gpu_recent_crash_count_ >= kGpuMaxCrashCount ||
            status_ == FAILURE) &&
           !disable_crash_limit) {
@@ -1374,10 +1359,36 @@
 #else
         // The GPU process is too unstable to use. Disable it for current
         // session.
-        hardware_gpu_enabled_ = false;
         GpuDataManagerImpl::GetInstance()->DisableHardwareAcceleration();
 #endif
       }
+    } else if (GpuDataManagerImpl::GetInstance()->SwiftShaderAllowed()) {
+      UMA_HISTOGRAM_EXACT_LINEAR(
+          "GPU.SwiftShaderLifetimeEvents",
+          DIED_FIRST_TIME + swiftshader_crash_count_,
+          static_cast<int>(GPU_PROCESS_LIFETIME_EVENT_MAX));
+      ++swiftshader_crash_count_;
+
+      IncrementCrashCount(&swiftshader_recent_crash_count_);
+      if (swiftshader_recent_crash_count_ >= kGpuMaxCrashCount &&
+          !disable_crash_limit) {
+        // SwiftShader is too unstable to use. Disable it for current session.
+        GpuDataManagerImpl::GetInstance()->BlockSwiftShader();
+      }
+    } else {
+      UMA_HISTOGRAM_EXACT_LINEAR(
+          "GPU.DisplayCompositorLifetimeEvents",
+          DIED_FIRST_TIME + display_compositor_crash_count_,
+          static_cast<int>(GPU_PROCESS_LIFETIME_EVENT_MAX));
+      ++display_compositor_crash_count_;
+
+      IncrementCrashCount(&display_compositor_recent_crash_count_);
+      if (display_compositor_recent_crash_count_ >= kGpuMaxCrashCount &&
+          !disable_crash_limit) {
+        // Viz display compositor is too unstable. Crash chrome to reset
+        // everything.
+        LOG(FATAL) << "Unable to start viz process, giving up.";
+      }
     }
   }
 }
diff --git a/content/browser/gpu/gpu_process_host.h b/content/browser/gpu/gpu_process_host.h
index 51e8412..51b57b6 100644
--- a/content/browser/gpu/gpu_process_host.h
+++ b/content/browser/gpu/gpu_process_host.h
@@ -182,6 +182,10 @@
 
   static bool ValidateHost(GpuProcessHost* host);
 
+  // Increments the given crash count. Also, for each hour passed since the
+  // previous crash, removes an old crash from the count.
+  static void IncrementCrashCount(int* crash_count);
+
   GpuProcessHost(int host_id, GpuProcessKind kind);
   ~GpuProcessHost() override;
 
@@ -269,7 +273,6 @@
   // of a separate GPU process.
   bool in_process_;
 
-  bool swiftshader_rendering_;
   GpuProcessKind kind_;
 
   // Whether we actually launched a GPU process.
@@ -280,16 +283,13 @@
   // Time Init started.  Used to log total GPU process startup time to UMA.
   base::TimeTicks init_start_time_;
 
-  // Master switch for enabling/disabling GPU acceleration for the current
-  // browser session.
-  static bool gpu_enabled_;
-
-  static bool hardware_gpu_enabled_;
-
   static base::subtle::Atomic32 gpu_crash_count_;
   static int gpu_recent_crash_count_;
   static bool crashed_before_;
   static int swiftshader_crash_count_;
+  static int swiftshader_recent_crash_count_;
+  static int display_compositor_crash_count_;
+  static int display_compositor_recent_crash_count_;
 
   // Here the bottom-up destruction order matters:
   // The GPU thread depends on its host so stop the host last.
diff --git a/content/browser/indexed_db/indexed_db_internals_ui.cc b/content/browser/indexed_db/indexed_db_internals_ui.cc
index 9b5c075..48bf8b2 100644
--- a/content/browser/indexed_db/indexed_db_internals_ui.cc
+++ b/content/browser/indexed_db/indexed_db_internals_ui.cc
@@ -52,17 +52,16 @@
 IndexedDBInternalsUI::IndexedDBInternalsUI(WebUI* web_ui)
     : WebUIController(web_ui) {
   web_ui->RegisterMessageCallback(
-      "getAllOrigins",
-      base::Bind(&IndexedDBInternalsUI::GetAllOrigins, base::Unretained(this)));
+      "getAllOrigins", base::BindRepeating(&IndexedDBInternalsUI::GetAllOrigins,
+                                           base::Unretained(this)));
 
   web_ui->RegisterMessageCallback(
       "downloadOriginData",
-      base::Bind(&IndexedDBInternalsUI::DownloadOriginData,
-                 base::Unretained(this)));
+      base::BindRepeating(&IndexedDBInternalsUI::DownloadOriginData,
+                          base::Unretained(this)));
   web_ui->RegisterMessageCallback(
-      "forceClose",
-      base::Bind(&IndexedDBInternalsUI::ForceCloseOrigin,
-                 base::Unretained(this)));
+      "forceClose", base::BindRepeating(&IndexedDBInternalsUI::ForceCloseOrigin,
+                                        base::Unretained(this)));
 
   WebUIDataSource* source =
       WebUIDataSource::Create(kChromeUIIndexedDBInternalsHost);
diff --git a/content/browser/loader/navigation_loader_interceptor.cc b/content/browser/loader/navigation_loader_interceptor.cc
new file mode 100644
index 0000000..957753b
--- /dev/null
+++ b/content/browser/loader/navigation_loader_interceptor.cc
@@ -0,0 +1,24 @@
+// 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 "content/browser/loader/navigation_loader_interceptor.h"
+
+#include "content/common/navigation_subresource_loader_params.h"
+
+namespace content {
+
+base::Optional<SubresourceLoaderParams>
+NavigationLoaderInterceptor::MaybeCreateSubresourceLoaderParams() {
+  return base::nullopt;
+}
+
+bool NavigationLoaderInterceptor::MaybeCreateLoaderForResponse(
+    const network::ResourceResponseHead& response,
+    network::mojom::URLLoaderPtr* loader,
+    network::mojom::URLLoaderClientRequest* client_request,
+    ThrottlingURLLoader* url_loader) {
+  return false;
+}
+
+}  // namespace content
diff --git a/content/browser/loader/navigation_loader_interceptor.h b/content/browser/loader/navigation_loader_interceptor.h
new file mode 100644
index 0000000..2f4ad19
--- /dev/null
+++ b/content/browser/loader/navigation_loader_interceptor.h
@@ -0,0 +1,79 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_LOADER_NAVIGATION_LOADER_INTERCEPTOR_H_
+#define CONTENT_BROWSER_LOADER_NAVIGATION_LOADER_INTERCEPTOR_H_
+
+#include <memory>
+
+#include "base/callback_forward.h"
+#include "base/macros.h"
+#include "base/optional.h"
+#include "content/common/content_export.h"
+#include "content/common/single_request_url_loader_factory.h"
+#include "net/url_request/redirect_info.h"
+#include "services/network/public/mojom/url_loader.mojom.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
+
+namespace content {
+
+class ResourceContext;
+struct ResourceRequest;
+struct SubresourceLoaderParams;
+class ThrottlingURLLoader;
+
+// NavigationLoaderInterceptor is given a chance to create a URLLoader and
+// intercept a navigation request before the request is handed off to the
+// default URLLoader, e.g. the one from the network service.
+// NavigationLoaderInterceptor is a per-request object and kept around during
+// the lifetime of a navigation request (including multiple redirect legs).
+class CONTENT_EXPORT NavigationLoaderInterceptor {
+ public:
+  NavigationLoaderInterceptor() = default;
+  virtual ~NavigationLoaderInterceptor() = default;
+
+  using LoaderCallback =
+      base::OnceCallback<void(SingleRequestURLLoaderFactory::RequestHandler)>;
+
+  // Asks this handler to handle this resource load request.
+  // The handler must invoke |callback| eventually with either a non-null
+  // RequestHandler indicating its willingness to handle the request, or a null
+  // RequestHandler to indicate that someone else should handle the request.
+  virtual void MaybeCreateLoader(
+      const network::ResourceRequest& resource_request,
+      ResourceContext* resource_context,
+      LoaderCallback callback) = 0;
+
+  // Returns a SubresourceLoaderParams if any to be used for subsequent URL
+  // requests going forward. Subclasses who want to set-up custom loader for
+  // subresource requests may want to override this.
+  // Note that the handler can return a null callback to MaybeCreateLoader(),
+  // and at the same time can return non-null SubresourceLoaderParams here if it
+  // does NOT want to handle the specific request given to MaybeCreateLoader()
+  // but wants to handle the subsequent resource requests.
+  virtual base::Optional<SubresourceLoaderParams>
+  MaybeCreateSubresourceLoaderParams();
+
+  // Returns true if the handler creates a loader for the |response| passed.
+  // An example of where this is used is AppCache, where the handler returns
+  // fallback content for the response passed in.
+  // The URLLoader interface pointer is returned in the |loader| parameter.
+  // The interface request for the URLLoaderClient is returned in the
+  // |client_request| parameter.
+  // The |url_loader| points to the ThrottlingURLLoader that currently controls
+  // the request. It can be optionally consumed to get the current
+  // URLLoaderClient and URLLoader so that the implementation can rebind them to
+  // intercept the inflight loading if necessary.  Note that the |url_loader|
+  // will be reset after this method is called, which will also drop the
+  // URLLoader held by |url_loader_| if it is not unbound yet.
+  virtual bool MaybeCreateLoaderForResponse(
+      const network::ResourceResponseHead& response,
+      network::mojom::URLLoaderPtr* loader,
+      network::mojom::URLLoaderClientRequest* client_request,
+      ThrottlingURLLoader* url_loader);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_LOADER_NAVIGATION_LOADER_INTERCEPTOR_H_
diff --git a/content/browser/loader/navigation_url_loader.cc b/content/browser/loader/navigation_url_loader.cc
index 3eecf60..4b1e826 100644
--- a/content/browser/loader/navigation_url_loader.cc
+++ b/content/browser/loader/navigation_url_loader.cc
@@ -9,10 +9,10 @@
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
 #include "content/browser/frame_host/navigation_request_info.h"
+#include "content/browser/loader/navigation_loader_interceptor.h"
 #include "content/browser/loader/navigation_url_loader_factory.h"
 #include "content/browser/loader/navigation_url_loader_impl.h"
 #include "content/browser/loader/navigation_url_loader_network_service.h"
-#include "content/browser/loader/url_loader_request_handler.h"
 #include "content/public/browser/navigation_ui_data.h"
 #include "content/public/common/browser_side_navigation_policy.h"
 #include "services/network/public/cpp/features.h"
@@ -39,7 +39,7 @@
     return std::make_unique<NavigationURLLoaderNetworkService>(
         resource_context, storage_partition, std::move(request_info),
         std::move(navigation_ui_data), service_worker_handle, appcache_handle,
-        delegate, std::vector<std::unique_ptr<URLLoaderRequestHandler>>());
+        delegate, std::vector<std::unique_ptr<NavigationLoaderInterceptor>>());
   } else {
     return std::make_unique<NavigationURLLoaderImpl>(
         resource_context, storage_partition, std::move(request_info),
diff --git a/content/browser/loader/navigation_url_loader_network_service.cc b/content/browser/loader/navigation_url_loader_network_service.cc
index a5f840c..70ab9b20 100644
--- a/content/browser/loader/navigation_url_loader_network_service.cc
+++ b/content/browser/loader/navigation_url_loader_network_service.cc
@@ -20,11 +20,11 @@
 #include "content/browser/file_url_loader_factory.h"
 #include "content/browser/frame_host/frame_tree_node.h"
 #include "content/browser/frame_host/navigation_request_info.h"
+#include "content/browser/loader/navigation_loader_interceptor.h"
 #include "content/browser/loader/navigation_resource_handler.h"
 #include "content/browser/loader/navigation_url_loader_delegate.h"
 #include "content/browser/loader/resource_dispatcher_host_impl.h"
 #include "content/browser/loader/resource_request_info_impl.h"
-#include "content/browser/loader/url_loader_request_handler.h"
 #include "content/browser/resource_context_impl.h"
 #include "content/browser/service_worker/service_worker_navigation_handle.h"
 #include "content/browser/service_worker/service_worker_navigation_handle_core.h"
@@ -72,7 +72,8 @@
 
 namespace {
 
-bool IsRequestHandlerEnabled() {
+// Returns true if interception by NavigationLoaderInterceptors is enabled.
+bool IsLoaderInterceptionEnabled() {
   return base::FeatureList::IsEnabled(network::features::kNetworkService) ||
          base::FeatureList::IsEnabled(features::kSignedHTTPExchange);
 }
@@ -276,7 +277,7 @@
 // Kept around during the lifetime of the navigation request, and is
 // responsible for dispatching a ResourceRequest to the appropriate
 // URLLoader.  In order to get the right URLLoader it builds a vector
-// of URLLoaderRequestHandler's and successively calls MaybeCreateLoader
+// of NavigationLoaderInterceptors and successively calls MaybeCreateLoader
 // on each until the request is successfully handled. The same sequence
 // may be performed multiple times when redirects happen.
 // TODO(michaeln): Expose this class and add more unittests.
@@ -284,7 +285,8 @@
     : public network::mojom::URLLoaderClient {
  public:
   URLLoaderRequestController(
-      std::vector<std::unique_ptr<URLLoaderRequestHandler>> initial_handlers,
+      std::vector<std::unique_ptr<NavigationLoaderInterceptor>>
+          initial_interceptors,
       std::unique_ptr<network::ResourceRequest> resource_request,
       ResourceContext* resource_context,
       scoped_refptr<URLLoaderFactoryGetter> default_url_loader_factory_getter,
@@ -295,7 +297,7 @@
       network::mojom::URLLoaderFactoryPtrInfo proxied_factory_info,
       std::set<std::string> known_schemes,
       const base::WeakPtr<NavigationURLLoaderNetworkService>& owner)
-      : handlers_(std::move(initial_handlers)),
+      : interceptors_(std::move(initial_interceptors)),
         resource_request_(std::move(resource_request)),
         resource_context_(resource_context),
         default_url_loader_factory_getter_(default_url_loader_factory_getter),
@@ -349,7 +351,7 @@
       // unretained |this|, because the passed callback will be used by a
       // SignedExchangeHandler which is indirectly owned by |this| until its
       // header is verified and parsed, that's where the getter is used.
-      handlers_.push_back(std::make_unique<WebPackageRequestHandler>(
+      interceptors_.push_back(std::make_unique<WebPackageRequestHandler>(
           url::Origin::Create(request_info->common_params.url),
           GetURLLoaderOptions(request_info->is_main_frame),
           base::MakeRefCounted<
@@ -469,7 +471,7 @@
 
       storage::BlobStorageContext* blob_storage_context = GetBlobStorageContext(
           GetChromeBlobStorageContextForResourceContext(resource_context_));
-      std::unique_ptr<URLLoaderRequestHandler> service_worker_handler =
+      std::unique_ptr<NavigationLoaderInterceptor> service_worker_interceptor =
           ServiceWorkerRequestHandler::InitializeForNavigationNetworkService(
               *resource_request_, resource_context_,
               service_worker_navigation_handle_core, blob_storage_context,
@@ -477,17 +479,17 @@
               request_info->begin_params->request_context_type, frame_type,
               request_info->are_ancestors_secure,
               request_info->common_params.post_data, web_contents_getter_);
-      if (service_worker_handler)
-        handlers_.push_back(std::move(service_worker_handler));
+      if (service_worker_interceptor)
+        interceptors_.push_back(std::move(service_worker_interceptor));
     }
 
     if (appcache_handle_core) {
-      std::unique_ptr<URLLoaderRequestHandler> appcache_handler =
+      std::unique_ptr<NavigationLoaderInterceptor> appcache_interceptor =
           AppCacheRequestHandler::InitializeForNavigationNetworkService(
               *resource_request_, appcache_handle_core,
               default_url_loader_factory_getter_.get());
-      if (appcache_handler)
-        handlers_.push_back(std::move(appcache_handler));
+      if (appcache_interceptor)
+        interceptors_.push_back(std::move(appcache_interceptor));
     }
 
     if (base::FeatureList::IsEnabled(features::kSignedHTTPExchange)) {
@@ -495,7 +497,7 @@
       // unretained |this|, because the passed callback will be used by a
       // SignedExchangeHandler which is indirectly owned by |this| until its
       // header is verified and parsed, that's where the getter is used.
-      handlers_.push_back(std::make_unique<WebPackageRequestHandler>(
+      interceptors_.push_back(std::make_unique<WebPackageRequestHandler>(
           url::Origin::Create(request_info->common_params.url),
           GetURLLoaderOptions(request_info->is_main_frame),
           default_url_loader_factory_getter_->GetNetworkFactory(),
@@ -510,30 +512,32 @@
 
   // This could be called multiple times to follow a chain of redirects.
   void Restart() {
-    DCHECK(IsRequestHandlerEnabled());
+    DCHECK(IsLoaderInterceptionEnabled());
     // Clear |url_loader_| if it's not the default one (network). This allows
     // the restarted request to use a new loader, instead of, e.g., reusing the
     // AppCache or service worker loader. For an optimization, we keep and reuse
-    // the default url loader if the all |handlers_| doesn't handle the
+    // the default url loader if the all |interceptors_| doesn't handle the
     // redirected request.
     if (!default_loader_used_)
       url_loader_.reset();
-    handler_index_ = 0;
+    interceptor_index_ = 0;
     received_response_ = false;
-    MaybeStartLoader(nullptr /* handler */, {} /* single_request_handler */);
+    MaybeStartLoader(nullptr /* interceptor */,
+                     {} /* single_request_handler */);
   }
 
-  // |handler| is the one who called this method (as a LoaderCallback), nullptr
-  // if this method is not called by a handler.
-  // |single_request_handler| is the RequestHandler given by the |handler|,
-  // non-null if the handler wants to handle the request.
+  // |interceptor| is non-null if this is called by one of the interceptors
+  // (via a LoaderCallback).
+  // |single_request_handler| is the RequestHandler given by the |interceptor|,
+  // non-null if the interceptor wants to handle the request.
   void MaybeStartLoader(
-      URLLoaderRequestHandler* handler,
+      NavigationLoaderInterceptor* interceptor,
       SingleRequestURLLoaderFactory::RequestHandler single_request_handler) {
-    DCHECK(IsRequestHandlerEnabled());
+    DCHECK(IsLoaderInterceptionEnabled());
     if (single_request_handler) {
-      // |handler| wants to handle the request.
-      DCHECK(handler);
+      // |interceptor| wants to handle the request with
+      // |single_request_handler|.
+      DCHECK(interceptor);
       default_loader_used_ = false;
       url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
           base::MakeRefCounted<SingleRequestURLLoaderFactory>(
@@ -544,39 +548,42 @@
           base::ThreadTaskRunnerHandle::Get());
 
       subresource_loader_params_ =
-          handler->MaybeCreateSubresourceLoaderParams();
+          interceptor->MaybeCreateSubresourceLoaderParams();
 
       return;
     }
 
-    // Before falling back to the next handler, see if |handler| still wants
-    // to give additional info to the frame for subresource loading.
-    // In that case we will just fall back to the default loader (i.e.
-    // won't go on to the next handlers) but send the subresource_loader_params
-    // to the child process. This is necessary for correctness in the cases
-    // where, e.g. there's a controlling ServiceWorker that doesn't handle main
-    // resource loading, but may still want to control the page and/or handle
-    // subresource loading. In that case we want to skip AppCache.
-    if (handler) {
+    // Before falling back to the next interceptor, see if |interceptor| still
+    // wants to give additional info to the frame for subresource loading. In
+    // that case we will just fall back to the default loader (i.e. won't go on
+    // to the next interceptors) but send the subresource_loader_params to the
+    // child process. This is necessary for correctness in the cases where, e.g.
+    // there's a controlling ServiceWorker that doesn't handle main resource
+    // loading, but may still want to control the page and/or handle subresource
+    // loading. In that case we want to skip AppCache.
+    if (interceptor) {
       subresource_loader_params_ =
-          handler->MaybeCreateSubresourceLoaderParams();
+          interceptor->MaybeCreateSubresourceLoaderParams();
 
       // If non-null |subresource_loader_params_| is returned, make sure
-      // we skip the next handlers.
+      // we skip the next interceptors.
       if (subresource_loader_params_)
-        handler_index_ = handlers_.size();
+        interceptor_index_ = interceptors_.size();
     }
 
-    // See if the next handler wants to handle the request.
-    if (handler_index_ < handlers_.size()) {
-      auto* next_handler = handlers_[handler_index_++].get();
-      next_handler->MaybeCreateLoader(
+    // See if the next interceptor wants to handle the request.
+    if (interceptor_index_ < interceptors_.size()) {
+      auto* next_interceptor = interceptors_[interceptor_index_++].get();
+      next_interceptor->MaybeCreateLoader(
           *resource_request_, resource_context_,
           base::BindOnce(&URLLoaderRequestController::MaybeStartLoader,
-                         base::Unretained(this), next_handler));
+                         base::Unretained(this), next_interceptor));
       return;
     }
 
+    // If we already have the default |url_loader_| we must come here after
+    // a redirect. No interceptors wanted to intercept the redirected request,
+    // so let it just follow the redirect.
     if (url_loader_) {
       DCHECK(!redirect_info_.new_url.is_empty());
       url_loader_->FollowRedirect();
@@ -587,7 +594,7 @@
     // mojom::URLLoaderFactory pointers into SharedURLLoaderFactory. Need to
     // further refactor the factory getters to avoid this.
     scoped_refptr<network::SharedURLLoaderFactory> factory;
-    DCHECK_EQ(handlers_.size(), handler_index_);
+    DCHECK_EQ(interceptors_.size(), interceptor_index_);
     if (resource_request_->url.SchemeIs(url::kBlobScheme)) {
       factory = base::MakeRefCounted<WeakWrapperSharedURLLoaderFactory>(
           default_url_loader_factory_getter_->GetBlobFactory());
@@ -622,11 +629,11 @@
       default_loader_used_ = true;
 
       // NOTE: We only support embedders proxying network-service-bound requests
-      // not handled by URLLoaderRequestHandlers above (e.g. Service Worker or
-      // AppCache). Hence this code is only reachable when one of the above
-      // handlers isn't used and the URL is either a data URL or has a scheme
-      // which is handled by the network service. We explicitly avoid proxying
-      // the data URL case here.
+      // not handled by NavigationLoaderInterceptors above (e.g. Service Worker
+      // or AppCache). Hence this code is only reachable when one of the above
+      // interceptors isn't used and the URL is either a data URL or has a
+      // scheme which is handled by the network service. We explicitly avoid
+      // proxying the data URL case here.
       if (proxied_factory_request_.is_pending() &&
           !resource_request_->url.SchemeIs(url::kDataScheme)) {
         DCHECK(proxied_factory_info_.is_valid());
@@ -653,14 +660,15 @@
     DCHECK_CURRENTLY_ON(BrowserThread::IO);
     DCHECK(!redirect_info_.new_url.is_empty());
 
-    if (!IsRequestHandlerEnabled()) {
+    if (!IsLoaderInterceptionEnabled()) {
       url_loader_->FollowRedirect();
       return;
     }
 
-    // Update resource_request_ and call Restart to give our handlers_ a chance
-    // at handling the new location. If no handler wants to take over, we'll
-    // use the existing url_loader to follow the redirect, see MaybeStartLoader.
+    // Update |resource_request_| and call Restart to give our |interceptors_| a
+    // chance at handling the new location. If no interceptor wants to take
+    // over, we'll use the existing url_loader to follow the redirect, see
+    // MaybeStartLoader.
     // TODO(michaeln): This is still WIP and is based on URLRequest::Redirect,
     // there likely remains more to be done.
     // a. For subframe navigations, the Origin header may need to be modified
@@ -700,8 +708,8 @@
     received_response_ = true;
 
     // If the default loader (network) was used to handle the URL load request
-    // we need to see if the handlers want to potentially create a new loader
-    // for the response. e.g. AppCache.
+    // we need to see if the interceptors want to potentially create a new
+    // loader for the response. e.g. AppCache.
     if (MaybeCreateLoaderForResponse(head))
       return;
 
@@ -727,7 +735,7 @@
     bool is_download;
     bool is_stream;
     std::unique_ptr<NavigationData> cloned_navigation_data;
-    if (IsRequestHandlerEnabled()) {
+    if (IsLoaderInterceptionEnabled()) {
       is_download = !response_intercepted &&
                     IsDownload(*response.get(), url_, url_chain_,
                                initiator_origin_, suggested_filename_);
@@ -795,7 +803,7 @@
     }
 
     // Store the redirect_info for later use in FollowRedirect where we give
-    // our handlers_ a chance to intercept the request for the new location.
+    // our interceptors_ a chance to intercept the request for the new location.
     redirect_info_ = redirect_info;
 
     scoped_refptr<network::ResourceResponse> response(
@@ -840,7 +848,7 @@
 
     if (status.error_code != net::OK && !received_response_) {
       // If the default loader (network) was used to handle the URL load
-      // request we need to see if the handlers want to potentially create a
+      // request we need to see if the interceptors want to potentially create a
       // new loader for the response. e.g. AppCache.
       if (MaybeCreateLoaderForResponse(network::ResourceResponseHead()))
         return;
@@ -853,21 +861,21 @@
                        status));
   }
 
-  // Returns true if a handler wants to handle the response, i.e. return a
+  // Returns true if an interceptor wants to handle the response, i.e. return a
   // different response. For e.g. AppCache may have fallback content.
   bool MaybeCreateLoaderForResponse(
       const network::ResourceResponseHead& response) {
-    if (!IsRequestHandlerEnabled())
+    if (!IsLoaderInterceptionEnabled())
       return false;
 
     if (!default_loader_used_)
       return false;
 
-    for (auto& handler : handlers_) {
+    for (auto& interceptor : interceptors_) {
       network::mojom::URLLoaderClientRequest response_client_request;
-      if (handler->MaybeCreateLoaderForResponse(response, &response_url_loader_,
-                                                &response_client_request,
-                                                url_loader_.get())) {
+      if (interceptor->MaybeCreateLoaderForResponse(
+              response, &response_url_loader_, &response_client_request,
+              url_loader_.get())) {
         response_loader_binding_.Bind(std::move(response_client_request));
         default_loader_used_ = false;
         url_loader_.reset();
@@ -884,8 +892,8 @@
         navigation_ui_data_.get(), frame_tree_node_id_);
   }
 
-  std::vector<std::unique_ptr<URLLoaderRequestHandler>> handlers_;
-  size_t handler_index_ = 0;
+  std::vector<std::unique_ptr<NavigationLoaderInterceptor>> interceptors_;
+  size_t interceptor_index_ = 0;
 
   std::unique_ptr<network::ResourceRequest> resource_request_;
   int frame_tree_node_id_ = 0;
@@ -977,7 +985,8 @@
     ServiceWorkerNavigationHandle* service_worker_navigation_handle,
     AppCacheNavigationHandle* appcache_handle,
     NavigationURLLoaderDelegate* delegate,
-    std::vector<std::unique_ptr<URLLoaderRequestHandler>> initial_handlers)
+    std::vector<std::unique_ptr<NavigationLoaderInterceptor>>
+        initial_interceptors)
     : delegate_(delegate),
       allow_download_(request_info->common_params.allow_download),
       weak_factory_(this) {
@@ -1003,8 +1012,8 @@
   if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
     DCHECK(!request_controller_);
     request_controller_ = std::make_unique<URLLoaderRequestController>(
-        /* initial_handlers = */
-        std::vector<std::unique_ptr<URLLoaderRequestHandler>>(),
+        /* initial_interceptors = */
+        std::vector<std::unique_ptr<NavigationLoaderInterceptor>>(),
         std::move(new_request), resource_context,
         /* default_url_factory_getter = */ nullptr,
         request_info->common_params.url,
@@ -1081,7 +1090,7 @@
 
   DCHECK(!request_controller_);
   request_controller_ = std::make_unique<URLLoaderRequestController>(
-      std::move(initial_handlers), std::move(new_request), resource_context,
+      std::move(initial_interceptors), std::move(new_request), resource_context,
       partition->url_loader_factory_getter(), request_info->common_params.url,
       request_info->begin_params->initiator_origin,
       request_info->common_params.suggested_filename,
diff --git a/content/browser/loader/navigation_url_loader_network_service.h b/content/browser/loader/navigation_url_loader_network_service.h
index 4247377..57708e5 100644
--- a/content/browser/loader/navigation_url_loader_network_service.h
+++ b/content/browser/loader/navigation_url_loader_network_service.h
@@ -25,7 +25,7 @@
 class NavigationPostDataHandler;
 class ResourceContext;
 class StoragePartition;
-class URLLoaderRequestHandler;
+class NavigationLoaderInterceptor;
 struct GlobalRequestID;
 
 // This is an implementation of NavigationURLLoader used when
@@ -34,7 +34,7 @@
     : public NavigationURLLoader {
  public:
   // The caller is responsible for ensuring that |delegate| outlives the loader.
-  // Note |initial_handlers| is there for test purposes only.
+  // Note |initial_interceptors| is there for test purposes only.
   NavigationURLLoaderNetworkService(
       ResourceContext* resource_context,
       StoragePartition* storage_partition,
@@ -43,7 +43,8 @@
       ServiceWorkerNavigationHandle* service_worker_handle,
       AppCacheNavigationHandle* appcache_handle,
       NavigationURLLoaderDelegate* delegate,
-      std::vector<std::unique_ptr<URLLoaderRequestHandler>> initial_handlers);
+      std::vector<std::unique_ptr<NavigationLoaderInterceptor>>
+          initial_interceptors);
   ~NavigationURLLoaderNetworkService() override;
 
   // NavigationURLLoader implementation:
diff --git a/content/browser/loader/navigation_url_loader_network_service_unittest.cc b/content/browser/loader/navigation_url_loader_network_service_unittest.cc
index 7cd85f7..ce04d90f 100644
--- a/content/browser/loader/navigation_url_loader_network_service_unittest.cc
+++ b/content/browser/loader/navigation_url_loader_network_service_unittest.cc
@@ -7,8 +7,8 @@
 #include "base/run_loop.h"
 #include "base/test/scoped_feature_list.h"
 #include "content/browser/frame_host/navigation_request_info.h"
+#include "content/browser/loader/navigation_loader_interceptor.h"
 #include "content/browser/loader/navigation_url_loader.h"
-#include "content/browser/loader/url_loader_request_handler.h"
 #include "content/common/navigation_params.h"
 #include "content/common/navigation_params.mojom.h"
 #include "content/common/service_manager/service_manager_connection_impl.h"
@@ -38,9 +38,9 @@
 
 namespace {
 
-class TestURLLoaderRequestHandler : public URLLoaderRequestHandler {
+class TestNavigationLoaderInterceptor : public NavigationLoaderInterceptor {
  public:
-  explicit TestURLLoaderRequestHandler(
+  explicit TestNavigationLoaderInterceptor(
       base::Optional<network::ResourceRequest>* most_recent_resource_request)
       : most_recent_resource_request_(most_recent_resource_request),
         resource_scheduler_(false) {
@@ -57,7 +57,7 @@
             context_->GetURLRequestContext()->network_quality_estimator());
   }
 
-  ~TestURLLoaderRequestHandler() override {
+  ~TestNavigationLoaderInterceptor() override {
     resource_scheduler_client_ = nullptr;
     context_->NotifyContextShuttingDown();
   }
@@ -66,7 +66,7 @@
                          ResourceContext* resource_context,
                          LoaderCallback callback) override {
     std::move(callback).Run(
-        base::BindOnce(&TestURLLoaderRequestHandler::StartLoader,
+        base::BindOnce(&TestNavigationLoaderInterceptor::StartLoader,
                        base::Unretained(this), resource_request));
   }
 
@@ -153,9 +153,9 @@
             false /* parent_is_main_frame */, false /* are_ancestors_secure */,
             -1 /* frame_tree_node_id */, false /* is_for_guests_only */,
             false /* report_raw_headers */, false /* is_prerenering */));
-    std::vector<std::unique_ptr<URLLoaderRequestHandler>> handlers;
+    std::vector<std::unique_ptr<NavigationLoaderInterceptor>> interceptors;
     most_recent_resource_request_ = base::nullopt;
-    handlers.push_back(std::make_unique<TestURLLoaderRequestHandler>(
+    interceptors.push_back(std::make_unique<TestNavigationLoaderInterceptor>(
         &most_recent_resource_request_));
 
     return std::make_unique<NavigationURLLoaderNetworkService>(
@@ -163,7 +163,7 @@
         BrowserContext::GetDefaultStoragePartition(browser_context_.get()),
         std::move(request_info), nullptr /* navigation_ui_data */,
         nullptr /* service_worker_handle */, nullptr /* appcache_handle */,
-        delegate, std::move(handlers));
+        delegate, std::move(interceptors));
   }
 
   // Requests |redirect_url|, which must return a HTTP 3xx redirect. It's also
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc
index 5a63134..a7bf2038 100644
--- a/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -1116,6 +1116,8 @@
 
     new_request->set_method(request_data.method);
     new_request->set_site_for_cookies(request_data.site_for_cookies);
+    new_request->set_attach_same_site_cookies(
+        request_data.attach_same_site_cookies);
 
     // The initiator should normally be present, unless this is a navigation.
     // Browser-initiated navigations don't have an initiator document, the
diff --git a/content/browser/loader/url_loader_request_handler.cc b/content/browser/loader/url_loader_request_handler.cc
deleted file mode 100644
index d4aa8e2..0000000
--- a/content/browser/loader/url_loader_request_handler.cc
+++ /dev/null
@@ -1,24 +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 "content/browser/loader/url_loader_request_handler.h"
-
-#include "content/common/navigation_subresource_loader_params.h"
-
-namespace content {
-
-base::Optional<SubresourceLoaderParams>
-URLLoaderRequestHandler::MaybeCreateSubresourceLoaderParams() {
-  return base::nullopt;
-}
-
-bool URLLoaderRequestHandler::MaybeCreateLoaderForResponse(
-    const network::ResourceResponseHead& response,
-    network::mojom::URLLoaderPtr* loader,
-    network::mojom::URLLoaderClientRequest* client_request,
-    ThrottlingURLLoader* url_loader) {
-  return false;
-}
-
-}  // namespace content
diff --git a/content/browser/loader/url_loader_request_handler.h b/content/browser/loader/url_loader_request_handler.h
deleted file mode 100644
index 46976df..0000000
--- a/content/browser/loader/url_loader_request_handler.h
+++ /dev/null
@@ -1,76 +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 CONTENT_BROWSER_LOADER_URL_LOADER_REQUEST_HANDLER_H_
-#define CONTENT_BROWSER_LOADER_URL_LOADER_REQUEST_HANDLER_H_
-
-#include <memory>
-
-#include "base/callback_forward.h"
-#include "base/macros.h"
-#include "base/optional.h"
-#include "content/common/content_export.h"
-#include "content/common/single_request_url_loader_factory.h"
-#include "net/url_request/redirect_info.h"
-#include "services/network/public/mojom/url_loader.mojom.h"
-#include "services/network/public/mojom/url_loader_factory.mojom.h"
-
-namespace content {
-
-class ResourceContext;
-struct ResourceRequest;
-struct SubresourceLoaderParams;
-class ThrottlingURLLoader;
-
-// An instance of this class is a per-request object and kept around during
-// the lifetime of a request (including multiple redirect legs) on IO thread.
-class CONTENT_EXPORT URLLoaderRequestHandler {
- public:
-  URLLoaderRequestHandler() = default;
-  virtual ~URLLoaderRequestHandler() = default;
-
-  using LoaderCallback =
-      base::OnceCallback<void(SingleRequestURLLoaderFactory::RequestHandler)>;
-
-  // Asks this handler to handle this resource load request.
-  // The handler must invoke |callback| eventually with either a non-null
-  // RequestHandler indicating its willingness to handle the request, or a null
-  // RequestHandler to indicate that someone else should handle the request.
-  virtual void MaybeCreateLoader(
-      const network::ResourceRequest& resource_request,
-      ResourceContext* resource_context,
-      LoaderCallback callback) = 0;
-
-  // Returns a SubresourceLoaderParams if any to be used for subsequent URL
-  // requests going forward. Subclasses who want to set-up custom loader for
-  // subresource requests may want to override this.
-  // Note that the handler can return a null callback to MaybeCreateLoader(),
-  // and at the same time can return non-null SubresourceLoaderParams here if it
-  // does NOT want to handle the specific request given to MaybeCreateLoader()
-  // but wants to handle the subsequent resource requests.
-  virtual base::Optional<SubresourceLoaderParams>
-  MaybeCreateSubresourceLoaderParams();
-
-  // Returns true if the handler creates a loader for the |response| passed.
-  // An example of where this is used is AppCache, where the handler returns
-  // fallback content for the response passed in.
-  // The URLLoader interface pointer is returned in the |loader| parameter.
-  // The interface request for the URLLoaderClient is returned in the
-  // |client_request| parameter.
-  // The |url_loader| points to the ThrottlingURLLoader that currently controls
-  // the request. It can be optionally consumed to get the current
-  // URLLoaderClient and URLLoader so that the implementation can rebind them to
-  // intercept the inflight loading if necessary.  Note that the |url_loader|
-  // will be reset after this method is called, which will also drop the
-  // URLLoader held by |url_loader_| if it is not unbound yet.
-  virtual bool MaybeCreateLoaderForResponse(
-      const network::ResourceResponseHead& response,
-      network::mojom::URLLoaderPtr* loader,
-      network::mojom::URLLoaderClientRequest* client_request,
-      ThrottlingURLLoader* url_loader);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_LOADER_URL_LOADER_REQUEST_HANDLER_H_
diff --git a/content/browser/media/capture/audio_mirroring_manager.cc b/content/browser/media/capture/audio_mirroring_manager.cc
index 35793ad3..1daaf6bf 100644
--- a/content/browser/media/capture/audio_mirroring_manager.cc
+++ b/content/browser/media/capture/audio_mirroring_manager.cc
@@ -4,6 +4,7 @@
 
 #include "content/browser/media/capture/audio_mirroring_manager.h"
 
+#include <stdint.h>
 #include <algorithm>
 
 #include "base/bind.h"
@@ -17,19 +18,16 @@
   return manager;
 }
 
-AudioMirroringManager::AudioMirroringManager() {
-  // Only *after* construction, check that AudioMirroringManager is being
-  // invoked on the same single thread.
-  thread_checker_.DetachFromThread();
-}
+AudioMirroringManager::AudioMirroringManager() {}
 
 AudioMirroringManager::~AudioMirroringManager() {}
 
 void AudioMirroringManager::AddDiverter(
     int render_process_id, int render_frame_id, Diverter* diverter) {
-  DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(diverter);
 
+  base::AutoLock scoped_lock(lock_);
+
   // DCHECK(diverter not already in routes_)
 #ifndef NDEBUG
   for (StreamRoutes::const_iterator it = routes_.begin();
@@ -49,7 +47,7 @@
 }
 
 void AudioMirroringManager::RemoveDiverter(Diverter* diverter) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  base::AutoLock scoped_lock(lock_);
 
   // Find and remove the entry from the routing table.  If the stream is being
   // diverted, it is stopped.
@@ -70,9 +68,10 @@
 }
 
 void AudioMirroringManager::StartMirroring(MirroringDestination* destination) {
-  DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(destination);
 
+  base::AutoLock scoped_lock(lock_);
+
   // Insert an entry into the set of active mirroring sessions, if this is a
   // previously-unknown destination.
   if (std::find(sessions_.begin(), sessions_.end(), destination) ==
@@ -99,7 +98,7 @@
 }
 
 void AudioMirroringManager::StopMirroring(MirroringDestination* destination) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  base::AutoLock scoped_lock(lock_);
 
   // Stop diverting each audio stream in the mirroring session being stopped.
   // Each stopped stream becomes a candidate to be diverted to another
@@ -129,10 +128,38 @@
   sessions_.erase(dest_it);
 }
 
+AudioMirroringManager::AddDiverterCallback
+AudioMirroringManager::GetAddDiverterCallback() {
+  return base::BindRepeating(
+      [](AudioMirroringManager* self,
+         const base::UnguessableToken& guessable_token, Diverter* diverter) {
+        const int render_process_id =
+            static_cast<int>(guessable_token.GetHighForSerialization());
+        const int render_frame_id =
+            static_cast<int>(guessable_token.GetLowForSerialization());
+        self->AddDiverter(render_process_id, render_frame_id, diverter);
+      },
+      base::Unretained(this));
+}
+
+AudioMirroringManager::RemoveDiverterCallback
+AudioMirroringManager::GetRemoveDiverterCallback() {
+  return base::BindRepeating(&AudioMirroringManager::RemoveDiverter,
+                             base::Unretained(this));
+}
+
+// static
+base::UnguessableToken AudioMirroringManager::ToGroupId(int render_process_id,
+                                                        int render_frame_id) {
+  return base::UnguessableToken::Deserialize(
+      static_cast<uint64_t>(render_process_id),
+      static_cast<uint64_t>(render_frame_id));
+}
+
 void AudioMirroringManager::InitiateQueriesToFindNewDestination(
     MirroringDestination* old_destination,
     const std::set<SourceFrameRef>& candidates) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  lock_.AssertAcquired();
 
   for (Destinations::const_iterator it = sessions_.begin();
        it != sessions_.end(); ++it) {
@@ -151,6 +178,8 @@
     bool add_only,
     const std::set<SourceFrameRef>& matches,
     bool is_duplicate) {
+  base::AutoLock scoped_lock(lock_);
+
   if (is_duplicate)
     UpdateRoutesToDuplicateDestination(destination, add_only, matches);
   else
@@ -161,7 +190,7 @@
     MirroringDestination* destination,
     bool add_only,
     const std::set<SourceFrameRef>& matches) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  lock_.AssertAcquired();
 
   if (std::find(sessions_.begin(), sessions_.end(), destination) ==
           sessions_.end()) {
@@ -195,7 +224,8 @@
     MirroringDestination* destination,
     bool add_only,
     const std::set<SourceFrameRef>& matches) {
-  DCHECK(thread_checker_.CalledOnValidThread());
+  lock_.AssertAcquired();
+
   if (std::find(sessions_.begin(), sessions_.end(), destination) ==
       sessions_.end()) {
     return;  // Query result callback invoked after StopMirroring().
diff --git a/content/browser/media/capture/audio_mirroring_manager.h b/content/browser/media/capture/audio_mirroring_manager.h
index b98cf01..67ee6fb 100644
--- a/content/browser/media/capture/audio_mirroring_manager.h
+++ b/content/browser/media/capture/audio_mirroring_manager.h
@@ -4,8 +4,7 @@
 //
 // AudioMirroringManager is a singleton object that maintains a set of active
 // audio mirroring destinations and auto-connects/disconnects audio streams
-// to/from those destinations.  It is meant to be used exclusively on the IO
-// thread.
+// to/from those destinations.
 //
 // How it works:
 //
@@ -39,7 +38,8 @@
 
 #include "base/callback_forward.h"
 #include "base/macros.h"
-#include "base/threading/thread_checker.h"
+#include "base/synchronization/lock.h"
+#include "base/unguessable_token.h"
 #include "content/common/content_export.h"
 #include "media/audio/audio_source_diverter.h"
 
@@ -119,6 +119,20 @@
   virtual void StartMirroring(MirroringDestination* destination);
   virtual void StopMirroring(MirroringDestination* destination);
 
+  // TODO(crbug/824019): The following are temporary, as a middle-ground step
+  // necessary to resolve a chicken-and-egg problem as we migrate audio
+  // mirroring into the new AudioService. See media::AudioManager::AddDiverter()
+  // comments for further details.
+  using AddDiverterCallback =
+      base::RepeatingCallback<void(const base::UnguessableToken&,
+                                   media::AudioSourceDiverter*)>;
+  AddDiverterCallback GetAddDiverterCallback();
+  using RemoveDiverterCallback =
+      base::RepeatingCallback<void(media::AudioSourceDiverter*)>;
+  RemoveDiverterCallback GetRemoveDiverterCallback();
+  static base::UnguessableToken ToGroupId(int render_process_id,
+                                          int render_frame_id);
+
  private:
   friend class AudioMirroringManagerTest;
 
@@ -190,8 +204,9 @@
   // All active mirroring sessions.
   Destinations sessions_;
 
-  // Used to check that all AudioMirroringManager code runs on the same thread.
-  base::ThreadChecker thread_checker_;
+  // Allows calls to Add/RemoveDiverter() and Start/StopMirroring() to be made
+  // from different threads.
+  base::Lock lock_;
 
   DISALLOW_COPY_AND_ASSIGN(AudioMirroringManager);
 };
diff --git a/content/browser/media/capture/audio_mirroring_manager_unittest.cc b/content/browser/media/capture/audio_mirroring_manager_unittest.cc
index 94e796f..2d6efe0 100644
--- a/content/browser/media/capture/audio_mirroring_manager_unittest.cc
+++ b/content/browser/media/capture/audio_mirroring_manager_unittest.cc
@@ -11,7 +11,9 @@
 #include "base/bind_helpers.h"
 #include "base/macros.h"
 #include "base/synchronization/waitable_event.h"
+#include "content/public/browser/browser_thread.h"
 #include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_utils.h"
 #include "media/base/audio_parameters.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -70,7 +72,9 @@
             candidates.end()) {
       result.insert(SourceFrameRef(render_process_id_, render_frame_id_));
     }
-    results_callback.Run(result, is_duplication_);
+    BrowserThread::PostTask(
+        BrowserThread::IO, FROM_HERE,
+        base::BindOnce(results_callback, std::move(result), is_duplication_));
   }
 
   media::AudioOutputStream* SimulateAddInput(
@@ -141,6 +145,7 @@
 
     mirroring_manager_.AddDiverter(
         render_process_id, render_frame_id, diverter);
+    RunAllPendingInMessageLoop();
 
     return diverter;
   }
@@ -173,10 +178,12 @@
     }
 
     mirroring_manager_.StartMirroring(dest.get());
+    RunAllPendingInMessageLoop();
   }
 
   void StopMirroringTo(const std::unique_ptr<MockMirroringDestination>& dest) {
     mirroring_manager_.StopMirroring(dest.get());
+    RunAllPendingInMessageLoop();
   }
 
   int CountStreamsDivertedTo(
diff --git a/content/browser/media/encrypted_media_browsertest.cc b/content/browser/media/encrypted_media_browsertest.cc
index 9b6b67df..46372c47 100644
--- a/content/browser/media/encrypted_media_browsertest.cc
+++ b/content/browser/media/encrypted_media_browsertest.cc
@@ -14,8 +14,8 @@
 #include "media/base/media.h"
 #include "media/base/media_switches.h"
 #include "media/base/test_data_util.h"
-#include "media/media_features.h"
-#include "media/mojo/features.h"
+#include "media/media_buildflags.h"
+#include "media/mojo/buildflags.h"
 
 #if defined(OS_ANDROID)
 #include "base/android/build_info.h"
diff --git a/content/browser/media/media_browsertest.cc b/content/browser/media/media_browsertest.cc
index 9fc250d8..8e6045d5 100644
--- a/content/browser/media/media_browsertest.cc
+++ b/content/browser/media/media_browsertest.cc
@@ -15,7 +15,7 @@
 #include "content/shell/browser/shell.h"
 #include "media/base/media_switches.h"
 #include "media/base/test_data_util.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "url/url_util.h"
 
diff --git a/content/browser/media/media_canplaytype_browsertest.cc b/content/browser/media/media_canplaytype_browsertest.cc
index 6bab3960..11bfbc8 100644
--- a/content/browser/media/media_canplaytype_browsertest.cc
+++ b/content/browser/media/media_canplaytype_browsertest.cc
@@ -14,7 +14,7 @@
 #include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
 #include "media/base/media_switches.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "third_party/libaom/av1_features.h"
 #include "ui/display/display_switches.h"
 
diff --git a/content/browser/media/media_color_browsertest.cc b/content/browser/media/media_color_browsertest.cc
index 55d4cdc5..1581091 100644
--- a/content/browser/media/media_color_browsertest.cc
+++ b/content/browser/media/media_color_browsertest.cc
@@ -6,7 +6,7 @@
 #include "content/browser/media/media_browsertest.h"
 #include "content/public/test/browser_test_utils.h"
 #include "media/base/test_data_util.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 namespace content {
 
diff --git a/content/browser/media/media_interface_proxy.cc b/content/browser/media/media_interface_proxy.cc
index 074f9f43..31bf2c0 100644
--- a/content/browser/media/media_interface_proxy.cc
+++ b/content/browser/media/media_interface_proxy.cc
@@ -16,7 +16,7 @@
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/common/content_client.h"
 #include "content/public/common/service_manager_connection.h"
-#include "media/mojo/features.h"
+#include "media/mojo/buildflags.h"
 #include "media/mojo/interfaces/constants.mojom.h"
 #include "media/mojo/interfaces/media_service.mojom.h"
 #include "media/mojo/services/media_interface_provider.h"
diff --git a/content/browser/media/media_interface_proxy.h b/content/browser/media/media_interface_proxy.h
index aa06d8c..08b7661 100644
--- a/content/browser/media/media_interface_proxy.h
+++ b/content/browser/media/media_interface_proxy.h
@@ -12,7 +12,7 @@
 #include "base/macros.h"
 #include "base/threading/thread_checker.h"
 #include "build/build_config.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "media/mojo/interfaces/content_decryption_module.mojom.h"
 #include "media/mojo/interfaces/interface_factory.mojom.h"
 #include "mojo/public/cpp/bindings/binding.h"
diff --git a/content/browser/media/media_internals_handler.cc b/content/browser/media/media_internals_handler.cc
index aafe26e..196e7675 100644
--- a/content/browser/media/media_internals_handler.cc
+++ b/content/browser/media/media_internals_handler.cc
@@ -27,9 +27,10 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   proxy_->Attach(this);
 
-  web_ui()->RegisterMessageCallback("getEverything",
-      base::Bind(&MediaInternalsMessageHandler::OnGetEverything,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "getEverything",
+      base::BindRepeating(&MediaInternalsMessageHandler::OnGetEverything,
+                          base::Unretained(this)));
 }
 
 void MediaInternalsMessageHandler::OnGetEverything(
diff --git a/content/browser/media/media_redirect_browsertest.cc b/content/browser/media/media_redirect_browsertest.cc
index 8be45ca..c1f24e8e2 100644
--- a/content/browser/media/media_redirect_browsertest.cc
+++ b/content/browser/media/media_redirect_browsertest.cc
@@ -7,7 +7,7 @@
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/content_browser_test_utils.h"
 #include "media/base/test_data_util.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/test/embedded_test_server/http_request.h"
 #include "net/test/embedded_test_server/http_response.h"
diff --git a/content/browser/media/media_source_browsertest.cc b/content/browser/media/media_source_browsertest.cc
index f19606c..e5571a3b 100644
--- a/content/browser/media/media_source_browsertest.cc
+++ b/content/browser/media/media_source_browsertest.cc
@@ -8,7 +8,7 @@
 #include "content/browser/media/media_browsertest.h"
 #include "media/base/media_switches.h"
 #include "media/base/test_data_util.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 #if defined(OS_ANDROID)
 #include "base/android/build_info.h"
diff --git a/content/browser/media/media_web_contents_observer.cc b/content/browser/media/media_web_contents_observer.cc
index 5c6a772..f061a46 100644
--- a/content/browser/media/media_web_contents_observer.cc
+++ b/content/browser/media/media_web_contents_observer.cc
@@ -105,6 +105,11 @@
   return fullscreen_player_;
 }
 
+const base::Optional<WebContentsObserver::MediaPlayerId>&
+MediaWebContentsObserver::GetPictureInPictureVideoMediaPlayerId() const {
+  return pip_player_;
+}
+
 bool MediaWebContentsObserver::OnMessageReceived(
     const IPC::Message& msg,
     RenderFrameHost* render_frame_host) {
@@ -123,6 +128,9 @@
         OnMediaEffectivelyFullscreenChanged)
     IPC_MESSAGE_HANDLER(MediaPlayerDelegateHostMsg_OnMediaSizeChanged,
                         OnMediaSizeChanged)
+    IPC_MESSAGE_HANDLER(
+        MediaPlayerDelegateHostMsg_OnPictureInPictureSourceChanged,
+        OnPictureInPictureSourceChanged)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
   return handled;
@@ -165,6 +173,11 @@
     RenderFrameHost* render_frame_host,
     int delegate_id) {
   OnMediaPaused(render_frame_host, delegate_id, true);
+
+  if (pip_player_ &&
+      pip_player_ == MediaPlayerId(render_frame_host, delegate_id)) {
+    pip_player_.reset();
+  }
 }
 
 void MediaWebContentsObserver::OnMediaPaused(RenderFrameHost* render_frame_host,
@@ -268,6 +281,12 @@
   web_contents_impl()->MediaResized(size, id);
 }
 
+void MediaWebContentsObserver::OnPictureInPictureSourceChanged(
+    RenderFrameHost* render_frame_host,
+    int delegate_id) {
+  pip_player_ = MediaPlayerId(render_frame_host, delegate_id);
+}
+
 void MediaWebContentsObserver::ClearWakeLocks(
     RenderFrameHost* render_frame_host) {
   std::set<MediaPlayerId> video_players;
diff --git a/content/browser/media/media_web_contents_observer.h b/content/browser/media/media_web_contents_observer.h
index 7012c14..92251e9 100644
--- a/content/browser/media/media_web_contents_observer.h
+++ b/content/browser/media/media_web_contents_observer.h
@@ -62,6 +62,10 @@
   // Gets the MediaPlayerId of the fullscreen video if it exists.
   const base::Optional<MediaPlayerId>& GetFullscreenVideoMediaPlayerId() const;
 
+  // Gets the MediaPlayerId of the picture in picture video if it exists.
+  const base::Optional<MediaPlayerId>& GetPictureInPictureVideoMediaPlayerId()
+      const;
+
   // WebContentsObserver implementation.
   void WebContentsDestroyed() override;
   void RenderFrameDeleted(RenderFrameHost* render_frame_host) override;
@@ -109,6 +113,8 @@
   void OnMediaMutedStatusChanged(RenderFrameHost* render_frame_host,
                                  int delegate_id,
                                  bool muted);
+  void OnPictureInPictureSourceChanged(RenderFrameHost* render_frame_host,
+                                       int delegate_id);
 
   // Clear |render_frame_host|'s tracking entry for its WakeLocks.
   void ClearWakeLocks(RenderFrameHost* render_frame_host);
@@ -146,6 +152,7 @@
   device::mojom::WakeLockPtr audio_wake_lock_;
   device::mojom::WakeLockPtr video_wake_lock_;
   base::Optional<MediaPlayerId> fullscreen_player_;
+  base::Optional<MediaPlayerId> pip_player_;
   base::Optional<bool> picture_in_picture_allowed_in_fullscreen_;
   bool has_audio_wake_lock_for_testing_ = false;
   bool has_video_wake_lock_for_testing_ = false;
diff --git a/content/browser/memory/memory_coordinator_impl_unittest.cc b/content/browser/memory/memory_coordinator_impl_unittest.cc
index 43f703e..b29de29 100644
--- a/content/browser/memory/memory_coordinator_impl_unittest.cc
+++ b/content/browser/memory/memory_coordinator_impl_unittest.cc
@@ -18,6 +18,7 @@
 #include "content/public/common/content_features.h"
 #include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -220,7 +221,8 @@
     scoped_feature_list_.InitAndEnableFeature(features::kMemoryCoordinator);
 
     task_runner_ = new base::TestMockTimeTaskRunner();
-    coordinator_.reset(new TestMemoryCoordinatorImpl(task_runner_));
+    thread_bundle_ = std::make_unique<TestBrowserThreadBundle>();
+    coordinator_ = std::make_unique<TestMemoryCoordinatorImpl>(task_runner_);
   }
 
   MockMemoryMonitor* GetMockMemoryMonitor() {
@@ -228,10 +230,10 @@
   }
 
  protected:
-  std::unique_ptr<TestMemoryCoordinatorImpl> coordinator_;
-  scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
-  base::MessageLoop message_loop_;
   base::test::ScopedFeatureList scoped_feature_list_;
+  scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
+  std::unique_ptr<content::TestBrowserThreadBundle> thread_bundle_;
+  std::unique_ptr<TestMemoryCoordinatorImpl> coordinator_;
 };
 
 TEST_F(MemoryCoordinatorImplTest, ChildRemovedOnConnectionError) {
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index 6026c43f..ad3d9c7 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -65,7 +65,7 @@
 #include "gpu/ipc/client/command_buffer_proxy_impl.h"
 #include "gpu/ipc/client/gpu_channel_host.h"
 #include "gpu/ipc/common/gpu_surface_tracker.h"
-#include "gpu/vulkan/features.h"
+#include "gpu/vulkan/buildflags.h"
 #include "gpu/vulkan/vulkan_surface.h"
 #include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
 #include "third_party/khronos/GLES2/gl2.h"
diff --git a/content/browser/renderer_host/compositor_impl_android.h b/content/browser/renderer_host/compositor_impl_android.h
index 716f928..48da07d 100644
--- a/content/browser/renderer_host/compositor_impl_android.h
+++ b/content/browser/renderer_host/compositor_impl_android.h
@@ -22,7 +22,7 @@
 #include "content/public/browser/android/compositor.h"
 #include "gpu/command_buffer/common/capabilities.h"
 #include "gpu/ipc/common/surface_handle.h"
-#include "gpu/vulkan/features.h"
+#include "gpu/vulkan/buildflags.h"
 #include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
 #include "third_party/khronos/GLES2/gl2.h"
 #include "ui/android/resources/resource_manager_impl.h"
diff --git a/content/browser/renderer_host/cursor_manager_unittest.cc b/content/browser/renderer_host/cursor_manager_unittest.cc
index b1773b5..80b769d 100644
--- a/content/browser/renderer_host/cursor_manager_unittest.cc
+++ b/content/browser/renderer_host/cursor_manager_unittest.cc
@@ -4,7 +4,6 @@
 
 #include "content/browser/renderer_host/cursor_manager.h"
 
-#include "base/test/scoped_task_environment.h"
 #include "build/build_config.h"
 #include "content/browser/renderer_host/render_widget_host_delegate.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
@@ -13,6 +12,7 @@
 #include "content/public/common/cursor_info.h"
 #include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "content/test/mock_render_widget_host_delegate.h"
 #include "content/test/mock_widget_impl.h"
 #include "content/test/test_render_view_host.h"
@@ -79,9 +79,7 @@
 
 class CursorManagerTest : public testing::Test {
  public:
-  CursorManagerTest()
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
+  CursorManagerTest() {}
 
   void SetUp() override {
     browser_context_.reset(new TestBrowserContext);
@@ -106,7 +104,7 @@
   }
 
  protected:
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
+  TestBrowserThreadBundle thread_bundle_;
 
   std::unique_ptr<BrowserContext> browser_context_;
   std::unique_ptr<MockRenderProcessHost> process_host_;
diff --git a/content/browser/renderer_host/input/legacy_input_router_impl_unittest.cc b/content/browser/renderer_host/input/legacy_input_router_impl_unittest.cc
index 5a6f958..8de0888 100644
--- a/content/browser/renderer_host/input/legacy_input_router_impl_unittest.cc
+++ b/content/browser/renderer_host/input/legacy_input_router_impl_unittest.cc
@@ -21,7 +21,6 @@
 #include "base/single_thread_task_runner.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "cc/input/touch_action.h"
@@ -38,6 +37,7 @@
 #include "content/public/common/content_switches.h"
 #include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/events/base_event_utils.h"
 #include "ui/events/blink/blink_features.h"
@@ -134,9 +134,7 @@
   LegacyInputRouterImplTest(
       WheelScrollingMode wheel_scrolling_mode = kWheelScrollLatching)
       : wheel_scroll_latching_enabled_(wheel_scrolling_mode !=
-                                       kWheelScrollingModeNone),
-        scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::UI) {
+                                       kWheelScrollingModeNone) {
     if (wheel_scrolling_mode == kAsyncWheelEvents) {
       feature_list_.InitWithFeatures({features::kTouchpadAndWheelScrollLatching,
                                       features::kAsyncWheelEvents},
@@ -398,7 +396,7 @@
   bool wheel_scroll_latching_enabled_;
 
  private:
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
+  TestBrowserThreadBundle thread_bundle_;
   SyntheticWebTouchEvent touch_event_;
 
   base::test::ScopedFeatureList vsync_feature_list_;
diff --git a/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.cc b/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.cc
index 3d6fe16..a620b59 100644
--- a/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.cc
+++ b/content/browser/renderer_host/input/legacy_ipc_widget_input_handler.cc
@@ -13,25 +13,6 @@
 
 namespace content {
 
-namespace {
-
-std::vector<blink::WebImeTextSpan> ConvertToBlinkImeTextSpan(
-    const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) {
-  std::vector<blink::WebImeTextSpan> ime_text_spans;
-  for (const auto& ime_text_span : ui_ime_text_spans) {
-    ime_text_spans.emplace_back(blink::WebImeTextSpan(
-        ConvertUiImeTextSpanTypeToWebType(ime_text_span.type),
-        ime_text_span.start_offset, ime_text_span.end_offset,
-        ime_text_span.underline_color,
-        ConvertUiThicknessToUiImeTextSpanThickness(ime_text_span.thickness),
-        ime_text_span.background_color,
-        ime_text_span.suggestion_highlight_color, ime_text_span.suggestions));
-  }
-  return ime_text_spans;
-}
-
-}  // namespace
-
 LegacyIPCWidgetInputHandler::LegacyIPCWidgetInputHandler(
     LegacyInputRouterImpl* input_router)
     : input_router_(input_router) {}
@@ -62,7 +43,7 @@
     int32_t start,
     int32_t end) {
   std::vector<blink::WebImeTextSpan> ime_text_spans =
-      ConvertToBlinkImeTextSpan(ui_ime_text_spans);
+      ConvertUiImeTextSpansToBlinkImeTextSpans(ui_ime_text_spans);
   SendInput(std::make_unique<InputMsg_ImeSetComposition>(
       input_router_->routing_id(), text, ime_text_spans, range, start, end));
 }
@@ -73,7 +54,7 @@
     const gfx::Range& range,
     int32_t relative_cursor_position) {
   std::vector<blink::WebImeTextSpan> ime_text_spans =
-      ConvertToBlinkImeTextSpan(ui_ime_text_spans);
+      ConvertUiImeTextSpansToBlinkImeTextSpans(ui_ime_text_spans);
   SendInput(std::make_unique<InputMsg_ImeCommitText>(
       input_router_->routing_id(), text, ime_text_spans, range,
       relative_cursor_position));
diff --git a/content/browser/renderer_host/media/audio_output_delegate_impl.cc b/content/browser/renderer_host/media/audio_output_delegate_impl.cc
index 98e7b64e2..366872c 100644
--- a/content/browser/renderer_host/media/audio_output_delegate_impl.cc
+++ b/content/browser/renderer_host/media/audio_output_delegate_impl.cc
@@ -100,7 +100,6 @@
     EventHandler* handler,
     media::AudioManager* audio_manager,
     media::mojom::AudioLogPtr audio_log,
-    AudioMirroringManager* mirroring_manager,
     MediaObserver* media_observer,
     int stream_id,
     int render_frame_id,
@@ -117,9 +116,8 @@
 
   return std::make_unique<AudioOutputDelegateImpl>(
       std::move(reader), std::move(socket), handler, audio_manager,
-      std::move(audio_log), mirroring_manager, media_observer, stream_id,
-      render_frame_id, render_process_id, params, std::move(observer),
-      output_device_id);
+      std::move(audio_log), media_observer, stream_id, render_frame_id,
+      render_process_id, params, std::move(observer), output_device_id);
 }
 
 AudioOutputDelegateImpl::AudioOutputDelegateImpl(
@@ -128,7 +126,6 @@
     EventHandler* handler,
     media::AudioManager* audio_manager,
     media::mojom::AudioLogPtr audio_log,
-    AudioMirroringManager* mirroring_manager,
     MediaObserver* media_observer,
     int stream_id,
     int render_frame_id,
@@ -140,17 +137,13 @@
       audio_log_(std::move(audio_log)),
       reader_(std::move(reader)),
       foreign_socket_(std::move(foreign_socket)),
-      mirroring_manager_(mirroring_manager),
       stream_id_(stream_id),
-      render_frame_id_(render_frame_id),
-      render_process_id_(render_process_id),
       observer_(std::move(observer)),
       weak_factory_(this) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(subscriber_);
   DCHECK(audio_manager);
   DCHECK(audio_log_);
-  DCHECK(mirroring_manager_);
   DCHECK(reader_);
   DCHECK(observer_);
   // Since the event handler never directly calls functions on |this| but rather
@@ -160,12 +153,11 @@
       weak_factory_.GetWeakPtr(), stream_id_);
   controller_ = media::AudioOutputController::Create(
       audio_manager, controller_event_handler_.get(), params, output_device_id,
+      AudioMirroringManager::ToGroupId(render_process_id, render_frame_id),
       reader_.get());
   DCHECK(controller_);
   if (media_observer)
     media_observer->OnCreatingAudioStream(render_process_id, render_frame_id);
-  mirroring_manager_->AddDiverter(render_process_id, render_frame_id,
-                                  controller_.get());
 }
 
 AudioOutputDelegateImpl::~AudioOutputDelegateImpl() {
@@ -178,26 +170,14 @@
   // the IO thread) when it's done closing, and it is only after that call that
   // we can delete |controller_event_handler_| and |reader_|. By giving the
   // closure ownership of these, we keep them alive until |controller_| is
-  // closed. |mirroring_manager_| is a lazy instance, so passing it is safe.
+  // closed.
   controller_->Close(base::BindOnce(
-      [](AudioMirroringManager* mirroring_manager,
-         std::unique_ptr<ControllerEventHandler> event_handler,
+      [](std::unique_ptr<ControllerEventHandler> event_handler,
          std::unique_ptr<media::AudioSyncReader> reader,
          scoped_refptr<media::AudioOutputController> controller) {
-        // De-register the controller from the AudioMirroringManager now that
-        // the controller has closed the AudioOutputStream and shut itself down.
-        // This ensures that calling RemoveDiverter() here won't trigger the
-        // controller to re-start the default AudioOutputStream and cause a
-        // brief audio blip to come out the user's speakers.
-        // http://crbug.com/474432
-        //
-        // It's fine if this task is canceled during shutdown, since the
-        // mirroring manager doesn't require that all diverters are
-        // removed.
-        mirroring_manager->RemoveDiverter(controller.get());
+        // Objects pointed to by the arguments are deleted on out-of-scope here.
       },
-      mirroring_manager_, std::move(controller_event_handler_),
-      std::move(reader_), controller_));
+      std::move(controller_event_handler_), std::move(reader_), controller_));
 }
 
 int AudioOutputDelegateImpl::GetStreamId() {
diff --git a/content/browser/renderer_host/media/audio_output_delegate_impl.h b/content/browser/renderer_host/media/audio_output_delegate_impl.h
index dae9af1..824a99ce 100644
--- a/content/browser/renderer_host/media/audio_output_delegate_impl.h
+++ b/content/browser/renderer_host/media/audio_output_delegate_impl.h
@@ -16,7 +16,6 @@
 #include "media/mojo/interfaces/audio_output_stream.mojom.h"
 
 namespace content {
-class AudioMirroringManager;
 class MediaObserver;
 }
 
@@ -38,7 +37,6 @@
       EventHandler* handler,
       media::AudioManager* audio_manager,
       media::mojom::AudioLogPtr audio_log,
-      AudioMirroringManager* mirroring_manager,
       MediaObserver* media_observer,
       int stream_id,
       int render_frame_id,
@@ -53,7 +51,6 @@
       EventHandler* handler,
       media::AudioManager* audio_manager,
       media::mojom::AudioLogPtr audio_log,
-      AudioMirroringManager* mirroring_manager,
       MediaObserver* media_observer,
       int stream_id,
       int render_frame_id,
@@ -85,16 +82,13 @@
   EventHandler* subscriber_;
   const media::mojom::AudioLogPtr audio_log_;
   // |controller_event_handler_| proxies events from controller to |this|.
-  // |controller_event_handler_|, |reader_| and |mirroring_manager_| will
-  // outlive |this|, see the destructor for details.
+  // |controller_event_handler_|, and |reader_| will outlive |this|, see the
+  // destructor for details.
   std::unique_ptr<ControllerEventHandler> controller_event_handler_;
   std::unique_ptr<media::AudioSyncReader> reader_;
   std::unique_ptr<base::CancelableSyncSocket> foreign_socket_;
-  AudioMirroringManager* mirroring_manager_;
   scoped_refptr<media::AudioOutputController> controller_;
   const int stream_id_;
-  const int render_frame_id_;
-  const int render_process_id_;
 
   // This flag ensures that we only send OnStreamStateChanged notifications
   // and (de)register with the stream monitor when the state actually changes.
diff --git a/content/browser/renderer_host/media/audio_output_delegate_impl_unittest.cc b/content/browser/renderer_host/media/audio_output_delegate_impl_unittest.cc
index ffa32c3..c3927d3 100644
--- a/content/browser/renderer_host/media/audio_output_delegate_impl_unittest.cc
+++ b/content/browser/renderer_host/media/audio_output_delegate_impl_unittest.cc
@@ -157,6 +157,9 @@
 
     audio_manager_.reset(new media::FakeAudioManager(
         std::make_unique<media::AudioThreadImpl>(), &log_factory_));
+    audio_manager_->SetDiverterCallbacks(
+        mirroring_manager_.GetAddDiverterCallback(),
+        mirroring_manager_.GetRemoveDiverterCallback());
   }
 
   ~AudioOutputDelegateTest() { audio_manager_->Shutdown(); }
@@ -194,9 +197,9 @@
                                                    Params(), socket.get());
       AudioOutputDelegateImpl delegate(
           std::move(reader), std::move(socket), &event_handler_,
-          audio_manager_.get(), CreateDummyMojoAudioLog(), &mirroring_manager_,
-          &media_observer_, kStreamId, kRenderFrameId, kRenderProcessId,
-          Params(), std::move(observer_ptr), kDefaultDeviceId);
+          audio_manager_.get(), CreateDummyMojoAudioLog(), &media_observer_,
+          kStreamId, kRenderFrameId, kRenderProcessId, Params(),
+          std::move(observer_ptr), kDefaultDeviceId);
 
       SyncWithAllThreads();
 
@@ -235,9 +238,9 @@
 
       AudioOutputDelegateImpl delegate(
           std::move(reader), std::move(socket), &event_handler_,
-          audio_manager_.get(), CreateDummyMojoAudioLog(), &mirroring_manager_,
-          &media_observer_, kStreamId, kRenderFrameId, kRenderProcessId,
-          Params(), std::move(observer_ptr), kDefaultDeviceId);
+          audio_manager_.get(), CreateDummyMojoAudioLog(), &media_observer_,
+          kStreamId, kRenderFrameId, kRenderProcessId, Params(),
+          std::move(observer_ptr), kDefaultDeviceId);
 
       if (!use_bound_observer)
         observer_binding->Close();
@@ -269,9 +272,9 @@
                                                    Params(), socket.get());
       AudioOutputDelegateImpl delegate(
           std::move(reader), std::move(socket), &event_handler_,
-          audio_manager_.get(), CreateDummyMojoAudioLog(), &mirroring_manager_,
-          &media_observer_, kStreamId, kRenderFrameId, kRenderProcessId,
-          Params(), std::move(observer_ptr), kDefaultDeviceId);
+          audio_manager_.get(), CreateDummyMojoAudioLog(), &media_observer_,
+          kStreamId, kRenderFrameId, kRenderProcessId, Params(),
+          std::move(observer_ptr), kDefaultDeviceId);
 
       delegate.OnPauseStream();
 
@@ -304,9 +307,9 @@
 
       AudioOutputDelegateImpl delegate(
           std::move(reader), std::move(socket), &event_handler_,
-          audio_manager_.get(), CreateDummyMojoAudioLog(), &mirroring_manager_,
-          &media_observer_, kStreamId, kRenderFrameId, kRenderProcessId,
-          Params(), std::move(observer_ptr), kDefaultDeviceId);
+          audio_manager_.get(), CreateDummyMojoAudioLog(), &media_observer_,
+          kStreamId, kRenderFrameId, kRenderProcessId, Params(),
+          std::move(observer_ptr), kDefaultDeviceId);
 
       delegate.OnPlayStream();
       delegate.OnPauseStream();
@@ -339,9 +342,9 @@
 
       AudioOutputDelegateImpl delegate(
           std::move(reader), std::move(socket), &event_handler_,
-          audio_manager_.get(), CreateDummyMojoAudioLog(), &mirroring_manager_,
-          &media_observer_, kStreamId, kRenderFrameId, kRenderProcessId,
-          Params(), std::move(observer_ptr), kDefaultDeviceId);
+          audio_manager_.get(), CreateDummyMojoAudioLog(), &media_observer_,
+          kStreamId, kRenderFrameId, kRenderProcessId, Params(),
+          std::move(observer_ptr), kDefaultDeviceId);
 
       delegate.OnPlayStream();
       delegate.OnPlayStream();
@@ -372,9 +375,9 @@
                                                    Params(), socket.get());
       AudioOutputDelegateImpl delegate(
           std::move(reader), std::move(socket), &event_handler_,
-          audio_manager_.get(), CreateDummyMojoAudioLog(), &mirroring_manager_,
-          &media_observer_, kStreamId, kRenderFrameId, kRenderProcessId,
-          Params(), std::move(observer_ptr), kDefaultDeviceId);
+          audio_manager_.get(), CreateDummyMojoAudioLog(), &media_observer_,
+          kStreamId, kRenderFrameId, kRenderProcessId, Params(),
+          std::move(observer_ptr), kDefaultDeviceId);
 
       delegate.GetControllerForTesting()->StartDiverting(&stream);
 
@@ -400,9 +403,9 @@
                                                    Params(), socket.get());
       AudioOutputDelegateImpl delegate(
           std::move(reader), std::move(socket), &event_handler_,
-          audio_manager_.get(), CreateDummyMojoAudioLog(), &mirroring_manager_,
-          &media_observer_, kStreamId, kRenderFrameId, kRenderProcessId,
-          Params(), nullptr, kDefaultDeviceId);
+          audio_manager_.get(), CreateDummyMojoAudioLog(), &media_observer_,
+          kStreamId, kRenderFrameId, kRenderProcessId, Params(), nullptr,
+          kDefaultDeviceId);
 
       delegate.GetControllerForTesting()->StartDiverting(&stream);
 
@@ -436,9 +439,9 @@
                                                    Params(), socket.get());
       AudioOutputDelegateImpl delegate(
           std::move(reader), std::move(socket), &event_handler_,
-          audio_manager_.get(), CreateDummyMojoAudioLog(), &mirroring_manager_,
-          &media_observer_, kStreamId, kRenderFrameId, kRenderProcessId,
-          Params(), std::move(observer_ptr), kDefaultDeviceId);
+          audio_manager_.get(), CreateDummyMojoAudioLog(), &media_observer_,
+          kStreamId, kRenderFrameId, kRenderProcessId, Params(),
+          std::move(observer_ptr), kDefaultDeviceId);
 
       delegate.OnPlayStream();
       delegate.GetControllerForTesting()->StartDiverting(&stream);
@@ -476,8 +479,8 @@
                                                  Params(), socket.get());
     auto delegate = std::make_unique<AudioOutputDelegateImpl>(
         std::move(reader), std::move(socket), &event_handler_,
-        audio_manager_.get(), CreateDummyMojoAudioLog(), &mirroring_manager_,
-        &media_observer_, kStreamId, kRenderFrameId, kRenderProcessId, Params(),
+        audio_manager_.get(), CreateDummyMojoAudioLog(), &media_observer_,
+        kStreamId, kRenderFrameId, kRenderProcessId, Params(),
         std::move(observer_ptr), kDefaultDeviceId);
 
     delegate->OnPlayStream();
@@ -509,9 +512,9 @@
                                                    Params(), socket.get());
       AudioOutputDelegateImpl delegate(
           std::move(reader), std::move(socket), &event_handler_,
-          audio_manager_.get(), CreateDummyMojoAudioLog(), &mirroring_manager_,
-          &media_observer_, kStreamId, kRenderFrameId, kRenderProcessId,
-          Params(), std::move(observer_ptr), kDefaultDeviceId);
+          audio_manager_.get(), CreateDummyMojoAudioLog(), &media_observer_,
+          kStreamId, kRenderFrameId, kRenderProcessId, Params(),
+          std::move(observer_ptr), kDefaultDeviceId);
     }
     SyncWithAllThreads();
     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, std::move(done));
@@ -535,9 +538,9 @@
                                                    Params(), socket.get());
       AudioOutputDelegateImpl delegate(
           std::move(reader), std::move(socket), &event_handler_,
-          audio_manager_.get(), CreateDummyMojoAudioLog(), &mirroring_manager_,
-          &media_observer_, kStreamId, kRenderFrameId, kRenderProcessId,
-          Params(), std::move(observer_ptr), kDefaultDeviceId);
+          audio_manager_.get(), CreateDummyMojoAudioLog(), &media_observer_,
+          kStreamId, kRenderFrameId, kRenderProcessId, Params(),
+          std::move(observer_ptr), kDefaultDeviceId);
 
       SyncWithAllThreads();
 
@@ -565,9 +568,9 @@
                                                    Params(), socket.get());
       AudioOutputDelegateImpl delegate(
           std::move(reader), std::move(socket), &event_handler_,
-          audio_manager_.get(), CreateDummyMojoAudioLog(), &mirroring_manager_,
-          &media_observer_, kStreamId, kRenderFrameId, kRenderProcessId,
-          Params(), std::move(observer_ptr), kDefaultDeviceId);
+          audio_manager_.get(), CreateDummyMojoAudioLog(), &media_observer_,
+          kStreamId, kRenderFrameId, kRenderProcessId, Params(),
+          std::move(observer_ptr), kDefaultDeviceId);
       SyncWithAllThreads();
 
       delegate.GetControllerForTesting()->OnError();
diff --git a/content/browser/renderer_host/media/audio_renderer_host.cc b/content/browser/renderer_host/media/audio_renderer_host.cc
index db43756..6637ebf 100644
--- a/content/browser/renderer_host/media/audio_renderer_host.cc
+++ b/content/browser/renderer_host/media/audio_renderer_host.cc
@@ -14,7 +14,6 @@
 #include "content/browser/bad_message.h"
 #include "content/browser/browser_main_loop.h"
 #include "content/browser/media/audio_stream_monitor.h"
-#include "content/browser/media/capture/audio_mirroring_manager.h"
 #include "content/browser/media/media_internals.h"
 #include "content/browser/renderer_host/media/audio_input_device_manager.h"
 #include "content/browser/renderer_host/media/audio_output_authorization_handler.h"
@@ -62,12 +61,10 @@
 AudioRendererHost::AudioRendererHost(int render_process_id,
                                      media::AudioManager* audio_manager,
                                      media::AudioSystem* audio_system,
-                                     AudioMirroringManager* mirroring_manager,
                                      MediaStreamManager* media_stream_manager)
     : BrowserMessageFilter(AudioMsgStart),
       render_process_id_(render_process_id),
       audio_manager_(audio_manager),
-      mirroring_manager_(mirroring_manager),
       media_stream_manager_(media_stream_manager),
       authorization_handler_(audio_system,
                              media_stream_manager,
@@ -297,9 +294,9 @@
                           mojo::MakeRequest(&observer_ptr));
 
   auto delegate = AudioOutputDelegateImpl::Create(
-      this, audio_manager_, std::move(audio_log_ptr), mirroring_manager_,
-      media_observer, stream_id, render_frame_id, render_process_id_, params,
-      std::move(observer_ptr), device_unique_id);
+      this, audio_manager_, std::move(audio_log_ptr), media_observer, stream_id,
+      render_frame_id, render_process_id_, params, std::move(observer_ptr),
+      device_unique_id);
   if (delegate)
     delegates_.push_back(std::move(delegate));
   else
diff --git a/content/browser/renderer_host/media/audio_renderer_host.h b/content/browser/renderer_host/media/audio_renderer_host.h
index f9506bf..d981ae8 100644
--- a/content/browser/renderer_host/media/audio_renderer_host.h
+++ b/content/browser/renderer_host/media/audio_renderer_host.h
@@ -65,7 +65,6 @@
 
 namespace content {
 
-class AudioMirroringManager;
 class MediaStreamManager;
 
 class CONTENT_EXPORT AudioRendererHost
@@ -76,7 +75,6 @@
   AudioRendererHost(int render_process_id,
                     media::AudioManager* audio_manager,
                     media::AudioSystem* audio_system,
-                    AudioMirroringManager* mirroring_manager,
                     MediaStreamManager* media_stream_manager);
 
   // BrowserMessageFilter implementation.
@@ -186,7 +184,6 @@
   const int render_process_id_;
 
   media::AudioManager* const audio_manager_;
-  AudioMirroringManager* const mirroring_manager_;
 
   // Used to access to AudioInputDeviceManager.
   MediaStreamManager* media_stream_manager_;
diff --git a/content/browser/renderer_host/media/audio_renderer_host_unittest.cc b/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
index 4518c17..b1400e94d 100644
--- a/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
+++ b/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
@@ -105,12 +105,10 @@
                         int render_process_id,
                         media::AudioManager* audio_manager,
                         media::AudioSystem* audio_system,
-                        AudioMirroringManager* mirroring_manager,
                         MediaStreamManager* media_stream_manager)
       : AudioRendererHost(render_process_id,
                           audio_manager,
                           audio_system,
-                          mirroring_manager,
                           media_stream_manager),
         shared_memory_length_(0),
         auth_run_loop_(auth_run_loop) {}
@@ -224,6 +222,9 @@
     RenderViewHostTestHarness::SetUp();
     audio_manager_ =
         std::make_unique<FakeAudioManagerWithAssociations>(&log_factory_);
+    audio_manager_->SetDiverterCallbacks(
+        mirroring_manager_.GetAddDiverterCallback(),
+        mirroring_manager_.GetRemoveDiverterCallback());
     audio_system_ =
         std::make_unique<media::AudioSystemImpl>(audio_manager_.get());
     media_stream_manager_ = std::make_unique<MediaStreamManager>(
@@ -231,7 +232,7 @@
     auth_run_loop_ = std::make_unique<base::RunLoop>();
     host_ = base::MakeRefCounted<MockAudioRendererHost>(
         auth_run_loop_.get(), process()->GetID(), audio_manager_.get(),
-        audio_system_.get(), &mirroring_manager_, media_stream_manager_.get());
+        audio_system_.get(), media_stream_manager_.get());
 
     // Simulate IPC channel connected.
     host_->set_peer_process_for_testing(base::Process::Current());
diff --git a/content/browser/renderer_host/media/renderer_audio_output_stream_factory_context_impl.cc b/content/browser/renderer_host/media/renderer_audio_output_stream_factory_context_impl.cc
index c1ea731..a879094 100644
--- a/content/browser/renderer_host/media/renderer_audio_output_stream_factory_context_impl.cc
+++ b/content/browser/renderer_host/media/renderer_audio_output_stream_factory_context_impl.cc
@@ -7,7 +7,6 @@
 #include <utility>
 
 #include "base/memory/ptr_util.h"
-#include "content/browser/media/capture/audio_mirroring_manager.h"
 #include "content/browser/media/media_internals.h"
 #include "content/browser/renderer_host/media/audio_output_delegate_impl.h"
 #include "content/browser/renderer_host/media/media_stream_manager.h"
@@ -72,10 +71,9 @@
   audio_log_ptr->OnCreated(params, unique_device_id);
 
   return AudioOutputDelegateImpl::Create(
-      handler, audio_manager_, std::move(audio_log_ptr),
-      AudioMirroringManager::GetInstance(), media_observer, stream_id,
-      render_frame_id, render_process_id_, params, std::move(stream_observer),
-      unique_device_id);
+      handler, audio_manager_, std::move(audio_log_ptr), media_observer,
+      stream_id, render_frame_id, render_process_id_, params,
+      std::move(stream_observer), unique_device_id);
 }
 
 // static
diff --git a/content/browser/renderer_host/overscroll_controller.cc b/content/browser/renderer_host/overscroll_controller.cc
index 3f51a8a..527809b 100644
--- a/content/browser/renderer_host/overscroll_controller.cc
+++ b/content/browser/renderer_host/overscroll_controller.cc
@@ -152,8 +152,7 @@
     const ui::DidOverscrollParams& params) {
   // TODO(sunyunjia): We should also decide whether to trigger overscroll,
   // update scroll_state_ here. See https://crbug.com/799467.
-  if (delegate_)
-    delegate_->OnOverscrollBehaviorUpdate(params.overscroll_behavior);
+  behavior_ = params.overscroll_behavior;
 }
 
 void OverscrollController::ReceivedEventACK(const blink::WebInputEvent& event,
@@ -499,8 +498,10 @@
     scroll_state_ = ScrollState::OVERSCROLLING;
     locked_mode_ = overscroll_mode_;
   }
-  if (delegate_)
-    delegate_->OnOverscrollModeChange(old_mode, overscroll_mode_, source);
+  if (delegate_) {
+    delegate_->OnOverscrollModeChange(old_mode, overscroll_mode_, source,
+                                      behavior_);
+  }
 }
 
 void OverscrollController::ResetScrollState() {
diff --git a/content/browser/renderer_host/overscroll_controller.h b/content/browser/renderer_host/overscroll_controller.h
index 48bf658e..f32f835 100644
--- a/content/browser/renderer_host/overscroll_controller.h
+++ b/content/browser/renderer_host/overscroll_controller.h
@@ -7,6 +7,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
+#include "cc/input/overscroll_behavior.h"
 #include "content/common/content_export.h"
 #include "third_party/WebKit/public/platform/WebGestureEvent.h"
 #include "third_party/WebKit/public/platform/WebInputEvent.h"
@@ -128,6 +129,10 @@
   // Helper function to reset |scroll_state_| and |locked_mode_|.
   void ResetScrollState();
 
+  // Current value of overscroll-behavior CSS property for the root element of
+  // the page.
+  cc::OverscrollBehavior behavior_;
+
   // The current state of overscroll gesture.
   OverscrollMode overscroll_mode_ = OVERSCROLL_NONE;
 
diff --git a/content/browser/renderer_host/overscroll_controller_delegate.h b/content/browser/renderer_host/overscroll_controller_delegate.h
index 3b8e09e..3ae6679 100644
--- a/content/browser/renderer_host/overscroll_controller_delegate.h
+++ b/content/browser/renderer_host/overscroll_controller_delegate.h
@@ -26,12 +26,6 @@
   // delegate.
   virtual gfx::Size GetDisplaySize() const = 0;
 
-  // This is called whenever an overscroll event is generated on the renderer
-  // side, and is called before OnOverscrollUpdate. The params contains an
-  // OverscrollBehavior that can prevent overscroll navigation.
-  virtual void OnOverscrollBehaviorUpdate(
-      cc::OverscrollBehavior overscroll_behavior) = 0;
-
   // This is called for each update in the overscroll amount. Returns true if
   // the delegate consumed the event.
   virtual bool OnOverscrollUpdate(float delta_x, float delta_y) = 0;
@@ -42,10 +36,12 @@
   // This is called when the direction of the overscroll changes. When a new
   // overscroll is started (i.e. when |new_mode| is not equal to
   // OVERSCROLL_NONE), |source| will be set to the device that triggered the
-  // overscroll gesture.
+  // overscroll gesture. |behavior| is the value of overscroll-behavior CSS
+  // property for the root element.
   virtual void OnOverscrollModeChange(OverscrollMode old_mode,
                                       OverscrollMode new_mode,
-                                      OverscrollSource source) = 0;
+                                      OverscrollSource source,
+                                      cc::OverscrollBehavior behavior) = 0;
 
   // Returns the optional maximum amount allowed for the absolute value of
   // overscroll delta corresponding to the current overscroll mode.
diff --git a/content/browser/renderer_host/render_process_host_browsertest.cc b/content/browser/renderer_host/render_process_host_browsertest.cc
index 796bc2f..fe592d8 100644
--- a/content/browser/renderer_host/render_process_host_browsertest.cc
+++ b/content/browser/renderer_host/render_process_host_browsertest.cc
@@ -33,7 +33,7 @@
 #include "media/base/bind_to_current_loop.h"
 #include "media/base/media_switches.h"
 #include "media/base/test_data_util.h"
-#include "media/mojo/features.h"
+#include "media/mojo/buildflags.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/test/embedded_test_server/http_request.h"
 #include "net/test/embedded_test_server/http_response.h"
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 9702d63..70df3f5 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -183,7 +183,7 @@
 #include "ipc/ipc_logging.h"
 #include "media/audio/audio_manager.h"
 #include "media/base/media_switches.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "media/mojo/services/video_decode_perf_history.h"
 #include "mojo/edk/embedder/embedder.h"
 #include "mojo/public/cpp/bindings/associated_interface_ptr.h"
@@ -1798,7 +1798,7 @@
     AddFilter(base::MakeRefCounted<AudioRendererHost>(
                   GetID(), audio_manager,
                   BrowserMainLoop::GetInstance()->audio_system(),
-                  AudioMirroringManager::GetInstance(), media_stream_manager)
+                  media_stream_manager)
                   .get());
   }
   AddFilter(
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h
index 4acb6bf..dfd4b5f 100644
--- a/content/browser/renderer_host/render_process_host_impl.h
+++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -46,7 +46,7 @@
 #include "content/public/common/service_manager_connection.h"
 #include "ipc/ipc_channel_proxy.h"
 #include "ipc/ipc_platform_file.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "mojo/edk/embedder/outgoing_broker_client_invitation.h"
 #include "mojo/public/cpp/bindings/associated_binding.h"
 #include "mojo/public/cpp/bindings/associated_binding_set.h"
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index afee464..df281c8 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -1745,7 +1745,7 @@
 }
 
 void RenderWidgetHostImpl::OnUpdateDragCursor(WebDragOperation current_op) {
-  if (delegate_ && delegate_->OnUpdateDragCursor())
+  if (delegate_->OnUpdateDragCursor())
     return;
 
   RenderViewHostDelegateView* view = delegate_->GetDelegateView();
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc b/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc
index 25fc3f8b..2b20e28 100644
--- a/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc
@@ -5,11 +5,11 @@
 #include "content/browser/renderer_host/render_widget_host_input_event_router.h"
 
 #include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
 #include "content/browser/renderer_host/render_widget_targeter.h"
 #include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "content/test/mock_render_widget_host_delegate.h"
 #include "content/test/mock_widget_impl.h"
 #include "content/test/test_render_view_host.h"
@@ -100,9 +100,7 @@
 
 class RenderWidgetHostInputEventRouterTest : public testing::Test {
  public:
-  RenderWidgetHostInputEventRouterTest()
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
+  RenderWidgetHostInputEventRouterTest() {}
 
  protected:
   // testing::Test:
@@ -149,8 +147,7 @@
     return rwhier_.touchscreen_gesture_target_.target;
   }
 
-  // Needed by RenderWidgetHostImpl constructor.
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
+  TestBrowserThreadBundle thread_bundle_;
 
   MockRenderWidgetHostDelegate delegate_;
   std::unique_ptr<BrowserContext> browser_context_;
@@ -167,7 +164,6 @@
   std::map<MockRenderWidgetHostView*, viz::FrameSinkId> frame_sink_id_map_;
 
   RenderWidgetHostInputEventRouter rwhier_;
-  TestBrowserThreadBundle thread_bundle_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostInputEventRouterTest);
diff --git a/content/browser/renderer_host/render_widget_host_ns_view_bridge.h b/content/browser/renderer_host/render_widget_host_ns_view_bridge.h
index db28e88..0c7056e 100644
--- a/content/browser/renderer_host/render_widget_host_ns_view_bridge.h
+++ b/content/browser/renderer_host/render_widget_host_ns_view_bridge.h
@@ -10,6 +10,7 @@
 #include <memory>
 
 #include "base/macros.h"
+#include "third_party/skia/include/core/SkColor.h"
 
 namespace content {
 
@@ -31,6 +32,12 @@
   // method is expected to go away).
   virtual RenderWidgetHostViewCocoa* GetRenderWidgetHostViewCocoa() = 0;
 
+  // Set the background color of the hosted CALayer.
+  virtual void SetBackgroundColor(SkColor color) = 0;
+
+  // Call the -[NSView setHidden:] method.
+  virtual void SetVisible(bool visible) = 0;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostNSViewBridge);
 };
diff --git a/content/browser/renderer_host/render_widget_host_ns_view_bridge.mm b/content/browser/renderer_host/render_widget_host_ns_view_bridge.mm
index 3ca81c2..458fb65f 100644
--- a/content/browser/renderer_host/render_widget_host_ns_view_bridge.mm
+++ b/content/browser/renderer_host/render_widget_host_ns_view_bridge.mm
@@ -4,8 +4,13 @@
 
 #import "content/browser/renderer_host/render_widget_host_ns_view_bridge.h"
 
+#import <Cocoa/Cocoa.h>
+
+#import "base/mac/scoped_nsobject.h"
 #import "content/browser/renderer_host/render_widget_host_view_cocoa.h"
 #include "content/browser/renderer_host/render_widget_host_view_mac.h"
+#import "skia/ext/skia_utils_mac.h"
+#import "ui/base/cocoa/animation_utils.h"
 
 namespace content {
 
@@ -18,26 +23,56 @@
     : public RenderWidgetHostNSViewBridge {
  public:
   explicit RenderWidgetHostViewNSViewBridgeLocal(
-      std::unique_ptr<RenderWidgetHostNSViewClient> client) {
-    // Since we autorelease |cocoa_view|, our caller must put |GetNativeView()|
-    // into the view hierarchy right after calling us.
-    cocoa_view_ = [[[RenderWidgetHostViewCocoa alloc]
-        initWithClient:std::move(client)] autorelease];
-  }
-  ~RenderWidgetHostViewNSViewBridgeLocal() override {}
+      std::unique_ptr<RenderWidgetHostNSViewClient> client);
+  ~RenderWidgetHostViewNSViewBridgeLocal() override;
+  RenderWidgetHostViewCocoa* GetRenderWidgetHostViewCocoa() override;
 
-  RenderWidgetHostViewCocoa* GetRenderWidgetHostViewCocoa() override {
-    return cocoa_view_;
-  }
+  void SetBackgroundColor(SkColor color) override;
+  void SetVisible(bool visible) override;
 
  private:
   // Weak, this is owned by |cocoa_view_|'s |client_|, and |cocoa_view_| owns
   // its |client_|.
   RenderWidgetHostViewCocoa* cocoa_view_ = nil;
 
+  // The background CoreAnimation layer which is hosted by |cocoa_view_|.
+  base::scoped_nsobject<CALayer> background_layer_;
+
   DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewNSViewBridgeLocal);
 };
 
+RenderWidgetHostViewNSViewBridgeLocal::RenderWidgetHostViewNSViewBridgeLocal(
+    std::unique_ptr<RenderWidgetHostNSViewClient> client) {
+  // Since we autorelease |cocoa_view|, our caller must put |GetNativeView()|
+  // into the view hierarchy right after calling us.
+  cocoa_view_ = [[[RenderWidgetHostViewCocoa alloc]
+      initWithClient:std::move(client)] autorelease];
+
+  background_layer_.reset([[CALayer alloc] init]);
+  [cocoa_view_ setLayer:background_layer_];
+  [cocoa_view_ setWantsLayer:YES];
+}
+
+RenderWidgetHostViewNSViewBridgeLocal::
+    ~RenderWidgetHostViewNSViewBridgeLocal() {}
+
+RenderWidgetHostViewCocoa*
+RenderWidgetHostViewNSViewBridgeLocal::GetRenderWidgetHostViewCocoa() {
+  return cocoa_view_;
+}
+
+void RenderWidgetHostViewNSViewBridgeLocal::SetBackgroundColor(SkColor color) {
+  ScopedCAActionDisabler disabler;
+  base::ScopedCFTypeRef<CGColorRef> cg_color(
+      skia::CGColorCreateFromSkColor(color));
+  [background_layer_ setBackgroundColor:cg_color];
+}
+
+void RenderWidgetHostViewNSViewBridgeLocal::SetVisible(bool visible) {
+  ScopedCAActionDisabler disabler;
+  [cocoa_view_ setHidden:!visible];
+}
+
 }  // namespace
 
 // static
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index d3b5b6d..ab41535 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -642,6 +642,13 @@
     const ui::MotionEventAndroid& event) {
   RecordToolTypeForActionDown(event);
 
+  if (event.GetAction() == ui::MotionEventAndroid::Action::DOWN) {
+    if (ime_adapter_android_)
+      ime_adapter_android_->UpdateOnTouchDown();
+    if (gesture_listener_manager_)
+      gesture_listener_manager_->UpdateOnTouchDown();
+  }
+
   if (event.for_touch_handle())
     return OnTouchHandleEvent(event);
 
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index 289b80b..febc9a4 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -1386,7 +1386,7 @@
 }
 
 void RenderWidgetHostViewAura::OnInputMethodChanged() {
-  // TODO(suzhe): implement the newly added “locale” property of HTML DOM
+  // TODO(suzhe): implement the newly added "locale" property of HTML DOM
   // TextEvent.
 }
 
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
index d3ef80ea..eff0c337 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -1474,12 +1474,12 @@
 
   // Focused segment
   composition_text.ime_text_spans.push_back(
-      ui::ImeTextSpan(ui::ImeTextSpan::Type::kComposition, 0, 3, 0xff000000,
+      ui::ImeTextSpan(ui::ImeTextSpan::Type::kComposition, 0, 3,
                       ui::ImeTextSpan::Thickness::kThick, 0x78563412));
 
   // Non-focused segment, with different background color.
   composition_text.ime_text_spans.push_back(
-      ui::ImeTextSpan(ui::ImeTextSpan::Type::kComposition, 3, 4, 0xff000000,
+      ui::ImeTextSpan(ui::ImeTextSpan::Type::kComposition, 3, 4,
                       ui::ImeTextSpan::Thickness::kThin, 0xefcdab90));
 
   const ui::ImeTextSpans& ime_text_spans = composition_text.ime_text_spans;
@@ -1532,12 +1532,12 @@
 
   // Focused segment
   composition_text.ime_text_spans.push_back(
-      ui::ImeTextSpan(ui::ImeTextSpan::Type::kComposition, 0, 3, 0xff000000,
+      ui::ImeTextSpan(ui::ImeTextSpan::Type::kComposition, 0, 3,
                       ui::ImeTextSpan::Thickness::kThick, 0x78563412));
 
   // Non-focused segment, with different background color.
   composition_text.ime_text_spans.push_back(
-      ui::ImeTextSpan(ui::ImeTextSpan::Type::kComposition, 3, 4, 0xff000000,
+      ui::ImeTextSpan(ui::ImeTextSpan::Type::kComposition, 3, 4,
                       ui::ImeTextSpan::Thickness::kThin, 0xefcdab90));
 
   // Caret is at the end. (This emulates Japanese MSIME 2007 and later)
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc b/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
index 7578357..5d62d996 100644
--- a/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
@@ -33,6 +33,7 @@
 #include "content/public/common/content_features.h"
 #include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "content/test/fake_renderer_compositor_frame_sink.h"
 #include "content/test/mock_render_widget_host_delegate.h"
 #include "content/test/mock_widget_impl.h"
@@ -81,9 +82,7 @@
 
 class RenderWidgetHostViewChildFrameTest : public testing::Test {
  public:
-  RenderWidgetHostViewChildFrameTest()
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
+  RenderWidgetHostViewChildFrameTest() {}
 
   void SetUp() override {
     SetUpEnvironment(false /* use_zoom_for_device_scale_factor */);
@@ -150,7 +149,7 @@
   }
 
  protected:
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
+  TestBrowserThreadBundle thread_bundle_;
 
   std::unique_ptr<BrowserContext> browser_context_;
   MockRenderWidgetHostDelegate delegate_;
diff --git a/content/browser/renderer_host/render_widget_host_view_cocoa.h b/content/browser/renderer_host/render_widget_host_view_cocoa.h
index 84ef1dc..a01b4f9 100644
--- a/content/browser/renderer_host/render_widget_host_view_cocoa.h
+++ b/content/browser/renderer_host/render_widget_host_view_cocoa.h
@@ -156,12 +156,6 @@
   // gesture ends.
   BOOL gestureBeginPinchSent_;
 
-  // If true then escape key down events are suppressed until the first escape
-  // key up event. (The up event is suppressed as well). This is used by the
-  // flash fullscreen code to avoid sending a key up event without a matching
-  // key down event.
-  BOOL suppressNextEscapeKeyUp_;
-
   // This is used to indicate if a stylus is currently in the proximity of the
   // tablet.
   bool isStylusEnteringProximity_;
@@ -179,7 +173,6 @@
 
 @property(nonatomic, assign) NSRange selectedRange;
 @property(nonatomic, assign) NSRange markedRange;
-@property(nonatomic, readonly) BOOL suppressNextEscapeKeyUp;
 
 // Common code path for handling begin gesture events. This helper method is
 // called via different codepaths based on OS version and SDK:
@@ -213,6 +206,7 @@
 - (void)showLookUpDictionaryOverlayAtPoint:(NSPoint)point;
 - (void)showLookUpDictionaryOverlayFromRange:(NSRange)range
                                   targetView:(NSView*)targetView;
+- (BOOL)suppressNextKeyUpForTesting:(int)keyCode;
 
 // Methods previously marked as private.
 - (id)initWithClient:
diff --git a/content/browser/renderer_host/render_widget_host_view_cocoa.mm b/content/browser/renderer_host/render_widget_host_view_cocoa.mm
index 1fdb587..9741074 100644
--- a/content/browser/renderer_host/render_widget_host_view_cocoa.mm
+++ b/content/browser/renderer_host/render_widget_host_view_cocoa.mm
@@ -113,9 +113,11 @@
       ui::ImeTextSpan::Thickness thickness =
           [style intValue] > 1 ? ui::ImeTextSpan::Thickness::kThick
                                : ui::ImeTextSpan::Thickness::kThin;
-      ime_text_spans->push_back(ui::ImeTextSpan(
-          ui::ImeTextSpan::Type::kComposition, range.location,
-          NSMaxRange(range), color, thickness, SK_ColorTRANSPARENT));
+      ui::ImeTextSpan ui_ime_text_span =
+          ui::ImeTextSpan(ui::ImeTextSpan::Type::kComposition, range.location,
+                          NSMaxRange(range), thickness, SK_ColorTRANSPARENT);
+      ui_ime_text_span.underline_color = color;
+      ime_text_spans->push_back(ui_ime_text_span);
     }
     i = range.location + range.length;
   }
@@ -134,7 +136,6 @@
 
 // Private methods:
 @interface RenderWidgetHostViewCocoa ()
-- (BOOL)shouldAutohideCursorForEvent:(NSEvent*)event;
 - (void)processedWheelEvent:(const blink::WebMouseWheelEvent&)event
                    consumed:(BOOL)consumed;
 - (void)keyEvent:(NSEvent*)theEvent wasKeyEquivalent:(BOOL)equiv;
@@ -150,7 +151,6 @@
 
 @implementation RenderWidgetHostViewCocoa
 @synthesize selectedRange = selectedRange_;
-@synthesize suppressNextEscapeKeyUp = suppressNextEscapeKeyUp_;
 @synthesize markedRange = markedRange_;
 
 - (id)initWithClient:(std::unique_ptr<RenderWidgetHostNSViewClient>)client {
@@ -476,6 +476,9 @@
 
 - (void)keyEvent:(NSEvent*)theEvent wasKeyEquivalent:(BOOL)equiv {
   TRACE_EVENT0("browser", "RenderWidgetHostViewCocoa::keyEvent");
+  NSEventType eventType = [theEvent type];
+  NSEventModifierFlags modifierFlags = [theEvent modifierFlags];
+  int keyCode = [theEvent keyCode];
 
   // If the user changes the system hotkey mapping after Chrome has been
   // launched, then it is possible that a formerly reserved system hotkey is no
@@ -489,15 +492,14 @@
   if (EventIsReservedBySystem(theEvent))
     return;
 
-  DCHECK([theEvent type] != NSKeyDown ||
-         !equiv == !([theEvent modifierFlags] & NSCommandKeyMask));
+  DCHECK(eventType != NSKeyDown ||
+         !equiv == !(modifierFlags & NSCommandKeyMask));
 
-  if ([theEvent type] == NSFlagsChanged) {
+  if (eventType == NSFlagsChanged) {
     // Ignore NSFlagsChanged events from the NumLock and Fn keys as
     // Safari does in -[WebHTMLView flagsChanged:] (of "WebHTMLView.mm").
     // Also ignore unsupported |keyCode| (255) generated by Convert, NonConvert
     // and KanaMode from JIS PC keyboard.
-    int keyCode = [theEvent keyCode];
     if (!keyCode || keyCode == 10 || keyCode == 63 || keyCode == 255)
       return;
   }
@@ -522,10 +524,6 @@
   if (event.GetType() == NativeWebKeyboardEvent::kRawKeyDown &&
       event.windows_key_code == ui::VKEY_ESCAPE &&
       renderWidgetHostView_->pepper_fullscreen_window()) {
-    RenderWidgetHostViewMac* parent =
-        renderWidgetHostView_->fullscreen_parent_host_view();
-    if (parent)
-      parent->cocoa_view()->suppressNextEscapeKeyUp_ = YES;
     widgetHost->ShutdownAndDestroyWidget(true);
     return;
   }
@@ -537,28 +535,26 @@
   if (!widgetHost)
     return;
 
-  // Suppress the escape key up event if necessary.
-  if (event.windows_key_code == ui::VKEY_ESCAPE && suppressNextEscapeKeyUp_) {
-    if (event.GetType() == NativeWebKeyboardEvent::kKeyUp)
-      suppressNextEscapeKeyUp_ = NO;
-    return;
-  }
-
   // Do not forward key up events unless preceded by a matching key down,
   // otherwise we might get an event from releasing the return key in the
-  // omnibox (http://crbug.com/338736).
-  if ([theEvent type] == NSKeyUp) {
-    auto numErased = keyDownCodes_.erase([theEvent keyCode]);
+  // omnibox (https://crbug.com/338736) or from closing another window
+  // (https://crbug.com/155492).
+  if (eventType == NSKeyUp) {
+    auto numErased = keyDownCodes_.erase(keyCode);
     if (numErased < 1)
       return;
   }
 
+  bool shouldAutohideCursor =
+      renderWidgetHostView_->GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE &&
+      eventType == NSKeyDown && !(modifierFlags & NSCommandKeyMask);
+
   // We only handle key down events and just simply forward other events.
-  if ([theEvent type] != NSKeyDown) {
+  if (eventType != NSKeyDown) {
     widgetHost->ForwardKeyboardEventWithLatencyInfo(event, latency_info);
 
     // Possibly autohide the cursor.
-    if ([self shouldAutohideCursorForEvent:theEvent]) {
+    if (shouldAutohideCursor) {
       [NSCursor setHiddenUntilMouseMoves:YES];
       cursorHidden_ = YES;
     }
@@ -566,7 +562,7 @@
     return;
   }
 
-  keyDownCodes_.insert([theEvent keyCode]);
+  keyDownCodes_.insert(keyCode);
 
   base::scoped_nsobject<RenderWidgetHostViewCocoa> keepSelfAlive([self retain]);
 
@@ -720,7 +716,7 @@
       widgetHost->ForwardKeyboardEventWithLatencyInfo(event, latency_info);
     } else if ((!textInserted || delayEventUntilAfterImeCompostion) &&
                event.text[0] != '\0' &&
-               (([theEvent modifierFlags] & kCtrlCmdKeyMask) ||
+               ((modifierFlags & kCtrlCmdKeyMask) ||
                 (hasEditCommands_ && editCommands_.empty()))) {
       // We don't get insertText: calls if ctrl or cmd is down, or the key event
       // generates an insert command. So synthesize a keypress event for these
@@ -732,12 +728,16 @@
   }
 
   // Possibly autohide the cursor.
-  if ([self shouldAutohideCursorForEvent:theEvent]) {
+  if (shouldAutohideCursor) {
     [NSCursor setHiddenUntilMouseMoves:YES];
     cursorHidden_ = YES;
   }
 }
 
+- (BOOL)suppressNextKeyUpForTesting:(int)keyCode {
+  return keyDownCodes_.count(keyCode) == 0;
+}
+
 - (void)forceTouchEvent:(NSEvent*)theEvent {
   if (ui::ForceClickInvokesQuickLook())
     [self quickLookWithEvent:theEvent];
@@ -1344,18 +1344,6 @@
   return renderWidgetHostView_;
 }
 
-// Determine whether we should autohide the cursor (i.e., hide it until mouse
-// move) for the given event. Customize here to be more selective about which
-// key presses to autohide on.
-- (BOOL)shouldAutohideCursorForEvent:(NSEvent*)event {
-  return (renderWidgetHostView_->GetTextInputType() !=
-              ui::TEXT_INPUT_TYPE_NONE &&
-          [event type] == NSKeyDown &&
-          !([event modifierFlags] & NSCommandKeyMask))
-             ? YES
-             : NO;
-}
-
 - (NSArray*)accessibilityArrayAttributeValues:(NSString*)attribute
                                         index:(NSUInteger)index
                                      maxCount:(NSUInteger)maxCount {
@@ -1738,7 +1726,7 @@
   } else {
     // Use a thin black underline by default.
     ime_text_spans_.push_back(ui::ImeTextSpan(
-        ui::ImeTextSpan::Type::kComposition, 0, length, SK_ColorBLACK,
+        ui::ImeTextSpan::Type::kComposition, 0, length,
         ui::ImeTextSpan::Thickness::kThin, SK_ColorTRANSPARENT));
   }
 
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h
index fb064ccb..2810dc6 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.h
+++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -257,9 +257,6 @@
   // These member variables should be private, but the associated ObjC class
   // needs access to them and can't be made a friend.
 
-  // The background CoreAnimation layer which is hosted by |cocoa_view_|.
-  base::scoped_nsobject<CALayer> background_layer_;
-
   // Delegated frame management and compositor interface.
   std::unique_ptr<BrowserCompositorMac> browser_compositor_;
   BrowserCompositorMac* BrowserCompositorForTesting() const {
@@ -283,10 +280,6 @@
 
   CONTENT_EXPORT void release_pepper_fullscreen_window_for_testing();
 
-  RenderWidgetHostViewMac* fullscreen_parent_host_view() const {
-    return fullscreen_parent_host_view_;
-  }
-
   int window_number() const;
 
   // Update the size, scale factor, color profile, and any other properties
@@ -385,6 +378,9 @@
   // Interface through which the NSView is to be manipulated.
   std::unique_ptr<RenderWidgetHostNSViewBridge> ns_view_bridge_;
 
+  // State tracked by Show/Hide/IsShowing.
+  bool is_visible_ = false;
+
   // Indicates if the page is loading.
   bool is_loading_;
 
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm
index 2901db41..a32c48d 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -259,7 +259,6 @@
       is_loading_(false),
       allow_pause_for_resize_or_repaint_(true),
       is_guest_view_hack_(is_guest_view_hack),
-      fullscreen_parent_host_view_(nullptr),
       weak_factory_(this) {
   // The NSView on the other side of |ns_view_bridge_| owns us. We will
   // be destroyed when it releases the unique_ptr that we pass to it here at
@@ -269,10 +268,6 @@
   ns_view_bridge_ = RenderWidgetHostNSViewBridge::Create(
       std::unique_ptr<RenderWidgetHostNSViewClient>(this));
 
-  background_layer_.reset([[CALayer alloc] init]);
-  [cocoa_view() setLayer:background_layer_];
-  [cocoa_view() setWantsLayer:YES];
-
   viz::FrameSinkId frame_sink_id = is_guest_view_hack_
                                        ? AllocateFrameSinkIdForGuestViewHack()
                                        : host()->GetFrameSinkId();
@@ -396,6 +391,7 @@
 void RenderWidgetHostViewMac::InitAsPopup(
     RenderWidgetHostView* parent_host_view,
     const gfx::Rect& pos) {
+  // This path is used by the time/date picker.
   bool activatable = popup_type_ == blink::kWebPopupTypeNone;
   [cocoa_view() setCloseOnDeactivate:YES];
   [cocoa_view() setCanBeKeyView:activatable ? YES : NO];
@@ -429,11 +425,13 @@
 // will enter fullscreen instead.
 void RenderWidgetHostViewMac::InitAsFullscreen(
     RenderWidgetHostView* reference_host_view) {
-  fullscreen_parent_host_view_ =
+  // TODO(ccameron): Delete this if it isn't used.
+  NOTREACHED();
+  RenderWidgetHostViewMac* parent_view =
       static_cast<RenderWidgetHostViewMac*>(reference_host_view);
   NSWindow* parent_window = nil;
-  if (reference_host_view)
-    parent_window = [reference_host_view->GetNativeView() window];
+  if (parent_view)
+    parent_window = [parent_view->cocoa_view() window];
   NSScreen* screen = [parent_window screen];
   if (!screen)
     screen = [NSScreen mainScreen];
@@ -567,9 +565,8 @@
 }
 
 void RenderWidgetHostViewMac::Show() {
-  ScopedCAActionDisabler disabler;
-  [cocoa_view() setHidden:NO];
-
+  is_visible_ = true;
+  ns_view_bridge_->SetVisible(is_visible_);
   browser_compositor_->SetRenderWidgetHostIsHidden(false);
 
   ui::LatencyInfo renderer_latency_info;
@@ -590,9 +587,8 @@
   if (!browser_compositor_)
     return;
 
-  ScopedCAActionDisabler disabler;
-  [cocoa_view() setHidden:YES];
-
+  is_visible_ = false;
+  ns_view_bridge_->SetVisible(is_visible_);
   host()->WasHidden();
   browser_compositor_->SetRenderWidgetHostIsHidden(true);
 }
@@ -691,7 +687,7 @@
 }
 
 bool RenderWidgetHostViewMac::IsShowing() {
-  return ![cocoa_view() isHidden];
+  return is_visible_;
 }
 
 gfx::Rect RenderWidgetHostViewMac::GetViewBounds() const {
@@ -1526,11 +1522,7 @@
   if (color == background_layer_color_)
     return;
   background_layer_color_ = color;
-
-  ScopedCAActionDisabler disabler;
-  base::ScopedCFTypeRef<CGColorRef> cg_color(
-      skia::CGColorCreateFromSkColor(color));
-  [background_layer_ setBackgroundColor:cg_color];
+  ns_view_bridge_->SetBackgroundColor(color);
 }
 
 BrowserAccessibilityManager*
diff --git a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
index 01f2a149..7f71590 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
@@ -368,6 +368,9 @@
     RenderViewHostImplTestHarness::SetUp();
     gpu::ImageTransportSurface::SetAllowOSMesaForTesting(true);
 
+    browser_context_ = std::make_unique<TestBrowserContext>();
+    process_host_ =
+        std::make_unique<MockRenderProcessHost>(browser_context_.get());
     process_host_->Init();
     host_ = MockRenderWidgetHostImpl::Create(&delegate_, process_host_.get(),
                                              process_host_->GetNextRoutingID());
@@ -382,6 +385,7 @@
     rwhv_cocoa_.reset();
     host_->ShutdownAndDestroyWidget(true);
     process_host_.reset();
+    browser_context_.reset();
     RecycleAndWait();
     RenderViewHostImplTestHarness::TearDown();
   }
@@ -434,9 +438,8 @@
 
   MockRenderWidgetHostDelegate delegate_;
 
-  TestBrowserContext browser_context_;
-  std::unique_ptr<MockRenderProcessHost> process_host_ =
-      std::make_unique<MockRenderProcessHost>(&browser_context_);
+  std::unique_ptr<TestBrowserContext> browser_context_;
+  std::unique_ptr<MockRenderProcessHost> process_host_;
   MockRenderWidgetHostImpl* host_ = nullptr;
   RenderWidgetHostViewMac* rwhv_mac_ = nullptr;
   base::scoped_nsobject<RenderWidgetHostViewCocoa> rwhv_cocoa_;
@@ -488,7 +491,8 @@
   EXPECT_EQ(0u, actualRange.length);
 }
 
-TEST_F(RenderWidgetHostViewMacTest, Fullscreen) {
+// Disabled to see if InitAsFullscreen is ever reached.
+TEST_F(RenderWidgetHostViewMacTest, Fullscreen_DISABLED) {
   rwhv_mac_->InitAsFullscreen(nullptr);
   EXPECT_TRUE(rwhv_mac_->pepper_fullscreen_window());
 
@@ -500,7 +504,8 @@
 
 // Verify that escape key down in fullscreen mode suppressed the keyup event on
 // the parent.
-TEST_F(RenderWidgetHostViewMacTest, FullscreenCloseOnEscape) {
+// Disabled to see if InitAsFullscreen is ever reached.
+TEST_F(RenderWidgetHostViewMacTest, FullscreenCloseOnEscape_DISABLED) {
   // Use our own RWH since we need to destroy it.
   MockRenderWidgetHostDelegate delegate;
   int32_t routing_id = process_host_->GetNextRoutingID();
@@ -514,24 +519,31 @@
   WindowedNotificationObserver observer(
       NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED,
       Source<RenderWidgetHost>(rwh));
-  EXPECT_FALSE([rwhv_mac_->cocoa_view() suppressNextEscapeKeyUp]);
+  EXPECT_TRUE([rwhv_mac_->cocoa_view() suppressNextKeyUpForTesting:53]);
+  [rwhv_mac_->cocoa_view() keyEvent:cocoa_test_event_utils::KeyEventWithKeyCode(
+                                        53, 27, NSKeyDown, 0)];
+  EXPECT_FALSE([rwhv_mac_->cocoa_view() suppressNextKeyUpForTesting:53]);
+  [rwhv_mac_->cocoa_view()
+      keyEvent:cocoa_test_event_utils::KeyEventWithKeyCode(53, 27, NSKeyUp, 0)];
+  EXPECT_TRUE([rwhv_mac_->cocoa_view() suppressNextKeyUpForTesting:53]);
 
-  // Escape key down. Should close window and set |suppressNextEscapeKeyUp| on
-  // the parent.
+  // Escape key down. Should close window, but the key up for the escape
+  // should not affect the parent.
   [view->cocoa_view() keyEvent:
       cocoa_test_event_utils::KeyEventWithKeyCode(53, 27, NSKeyDown, 0)];
   observer.Wait();
-  EXPECT_TRUE([rwhv_mac_->cocoa_view() suppressNextEscapeKeyUp]);
+  EXPECT_TRUE([rwhv_mac_->cocoa_view() suppressNextKeyUpForTesting:53]);
 
-  // Escape key up on the parent should clear |suppressNextEscapeKeyUp|.
-  [rwhv_mac_->cocoa_view() keyEvent:
-      cocoa_test_event_utils::KeyEventWithKeyCode(53, 27, NSKeyUp, 0)];
-  EXPECT_FALSE([rwhv_mac_->cocoa_view() suppressNextEscapeKeyUp]);
+  // Escape key down on the parent should clear the suppression.
+  [rwhv_mac_->cocoa_view() keyEvent:cocoa_test_event_utils::KeyEventWithKeyCode(
+                                        53, 27, NSKeyDown, 0)];
+  EXPECT_FALSE([rwhv_mac_->cocoa_view() suppressNextKeyUpForTesting:53]);
 }
 
 // Test that command accelerators which destroy the fullscreen window
 // don't crash when forwarded via the window's responder machinery.
-TEST_F(RenderWidgetHostViewMacTest, AcceleratorDestroy) {
+// Disabled to see if InitAsFullscreen is ever reached.
+TEST_F(RenderWidgetHostViewMacTest, AcceleratorDestroy_DISABLED) {
   // Use our own RWH since we need to destroy it.
   MockRenderWidgetHostDelegate delegate;
   TestBrowserContext browser_context;
@@ -1756,14 +1768,18 @@
 
   void SetUp() override {
     RenderWidgetHostViewMacTest::SetUp();
-    process_host_ = new MockRenderProcessHost(&browser_context_);
+
+    browser_context_ = std::make_unique<TestBrowserContext>();
+    process_host_ = new MockRenderProcessHost(browser_context_.get());
     process_host_->Init();
     widget_ = MockRenderWidgetHostImpl::Create(
         &delegate_, process_host_, process_host_->GetNextRoutingID());
     view_ = new RenderWidgetHostViewMac(widget_, false);
 
     // Initializing a child frame's view.
-    child_process_host_ = new MockRenderProcessHost(&child_browser_context_);
+    child_browser_context_ = std::make_unique<TestBrowserContext>();
+    child_process_host_ =
+        new MockRenderProcessHost(child_browser_context_.get());
     child_process_host_->Init();
     child_widget_ = MockRenderWidgetHostImpl::Create(
         &delegate_, child_process_host_,
@@ -1776,6 +1792,9 @@
     widget_->ShutdownAndDestroyWidget(true);
     child_widget_->ShutdownAndDestroyWidget(true);
 
+    child_browser_context_.reset();
+    browser_context_.reset();
+
     RenderWidgetHostViewMacTest::TearDown();
   }
 
@@ -1806,8 +1825,8 @@
   TestRenderWidgetHostView* child_view_;
 
  private:
-  TestBrowserContext browser_context_;
-  TestBrowserContext child_browser_context_;
+  std::unique_ptr<TestBrowserContext> browser_context_;
+  std::unique_ptr<TestBrowserContext> child_browser_context_;
 
   DISALLOW_COPY_AND_ASSIGN(InputMethodMacTest);
 };
diff --git a/content/browser/renderer_host/text_input_client_mac_unittest.mm b/content/browser/renderer_host/text_input_client_mac_unittest.mm
index 91fe5b7..576c256 100644
--- a/content/browser/renderer_host/text_input_client_mac_unittest.mm
+++ b/content/browser/renderer_host/text_input_client_mac_unittest.mm
@@ -10,7 +10,6 @@
 #include "base/bind.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
-#include "base/test/scoped_task_environment.h"
 #include "base/threading/thread.h"
 #include "content/browser/renderer_host/render_process_host_impl.h"
 #include "content/browser/renderer_host/render_widget_host_delegate.h"
@@ -19,6 +18,7 @@
 #include "content/common/text_input_client_messages.h"
 #include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "content/test/mock_widget_impl.h"
 #include "ipc/ipc_test_sink.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -50,9 +50,7 @@
 class TextInputClientMacTest : public testing::Test {
  public:
   TextInputClientMacTest()
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::UI),
-        browser_context_(),
+      : browser_context_(),
         process_factory_(),
         delegate_(),
         thread_("TextInputClientMacTestThread") {
@@ -103,7 +101,7 @@
   friend class ScopedTestingThread;
 
   // TaskScheduler is used by RenderWidgetHostImpl constructor.
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
+  TestBrowserThreadBundle thread_bundle_;
 
   TestBrowserContext browser_context_;
 
diff --git a/content/browser/renderer_interface_binders.cc b/content/browser/renderer_interface_binders.cc
index bef8f42..a7a6566 100644
--- a/content/browser/renderer_interface_binders.cc
+++ b/content/browser/renderer_interface_binders.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/feature_list.h"
 #include "content/browser/background_fetch/background_fetch_service_impl.h"
 #include "content/browser/dedicated_worker/dedicated_worker_host.h"
 #include "content/browser/locks/lock_manager.h"
@@ -25,6 +26,7 @@
 #include "content/public/common/content_switches.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/device/public/mojom/vibration_manager.mojom.h"
+#include "services/network/public/cpp/features.h"
 #include "services/network/restricted_cookie_manager.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
 #include "services/service_manager/public/cpp/connector.h"
@@ -73,6 +75,10 @@
  private:
   void InitializeParameterizedBinderRegistry();
 
+  static void CreateWebSocket(network::mojom::WebSocketRequest request,
+                              RenderProcessHost* host,
+                              const url::Origin& origin);
+
   service_manager::BinderRegistryWithArgs<RenderProcessHost*,
                                           const url::Origin&>
       parameterized_binder_registry_;
@@ -127,11 +133,7 @@
       base::Bind(&ForwardServiceRequest<device::mojom::VibrationManager>,
                  device::mojom::kServiceName));
   parameterized_binder_registry_.AddInterface(
-      base::Bind([](blink::mojom::WebSocketRequest request,
-                    RenderProcessHost* host, const url::Origin& origin) {
-        WebSocketManager::CreateWebSocketWithOrigin(
-            host->GetID(), origin, std::move(request), MSG_ROUTING_NONE);
-      }));
+      base::BindRepeating(CreateWebSocket));
   parameterized_binder_registry_.AddInterface(
       base::Bind([](payments::mojom::PaymentManagerRequest request,
                     RenderProcessHost* host, const url::Origin& origin) {
@@ -181,6 +183,22 @@
   return binders;
 }
 
+void RendererInterfaceBinders::CreateWebSocket(
+    network::mojom::WebSocketRequest request,
+    RenderProcessHost* host,
+    const url::Origin& origin) {
+  if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+    StoragePartition* storage_partition = host->GetStoragePartition();
+    network::mojom::NetworkContext* network_context =
+        storage_partition->GetNetworkContext();
+    network_context->CreateWebSocket(std::move(request), host->GetID(),
+                                     MSG_ROUTING_NONE, origin);
+  } else {
+    WebSocketManager::CreateWebSocketWithOrigin(
+        host->GetID(), origin, std::move(request), MSG_ROUTING_NONE);
+  }
+}
+
 }  // namespace
 
 void BindWorkerInterface(const std::string& interface_name,
diff --git a/content/browser/service_manager/service_manager_context.cc b/content/browser/service_manager/service_manager_context.cc
index 4e833222..cc27636 100644
--- a/content/browser/service_manager/service_manager_context.cc
+++ b/content/browser/service_manager/service_manager_context.cc
@@ -42,8 +42,8 @@
 #include "content/public/common/service_manager_connection.h"
 #include "content/public/common/service_names.mojom.h"
 #include "media/audio/audio_manager.h"
-#include "media/media_features.h"
-#include "media/mojo/features.h"
+#include "media/media_buildflags.h"
+#include "media/mojo/buildflags.h"
 #include "media/mojo/interfaces/constants.mojom.h"
 #include "mojo/edk/embedder/embedder.h"
 #include "mojo/edk/embedder/incoming_broker_client_invitation.h"
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler.cc b/content/browser/service_worker/service_worker_controllee_request_handler.cc
index 5b09f6d..6460145 100644
--- a/content/browser/service_worker/service_worker_controllee_request_handler.cc
+++ b/content/browser/service_worker/service_worker_controllee_request_handler.cc
@@ -232,7 +232,7 @@
                          resource_request.site_for_cookies);
 
   if (url_job_->ShouldFallbackToNetwork()) {
-    // We're falling back to the next URLLoaderRequestHandler, forward
+    // We're falling back to the next NavigationLoaderInterceptor, forward
     // the request and clear job now.
     url_job_->FallbackToNetwork();
     ClearJob();
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler.h b/content/browser/service_worker/service_worker_controllee_request_handler.h
index 5b874a5..f5b75068 100644
--- a/content/browser/service_worker/service_worker_controllee_request_handler.h
+++ b/content/browser/service_worker/service_worker_controllee_request_handler.h
@@ -76,7 +76,7 @@
   // This could get called multiple times during the lifetime in redirect
   // cases. (In fallback-to-network cases we basically forward the request
   // to the request to the next request handler)
-  // URLLoaderRequestHandler overrides:
+  // NavigationLoaderInterceptor overrides:
   void MaybeCreateLoader(const network::ResourceRequest& request,
                          ResourceContext* resource_context,
                          LoaderCallback callback) override;
diff --git a/content/browser/service_worker/service_worker_internals_ui.cc b/content/browser/service_worker/service_worker_internals_ui.cc
index 88476238..74ef7eb3 100644
--- a/content/browser/service_worker/service_worker_internals_ui.cc
+++ b/content/browser/service_worker/service_worker_internals_ui.cc
@@ -343,31 +343,27 @@
   WebUIDataSource::Add(browser_context, source);
 
   web_ui->RegisterMessageCallback(
-      "GetOptions",
-      base::Bind(&ServiceWorkerInternalsUI::GetOptions,
-                 base::Unretained(this)));
+      "GetOptions", base::BindRepeating(&ServiceWorkerInternalsUI::GetOptions,
+                                        base::Unretained(this)));
   web_ui->RegisterMessageCallback(
-      "SetOption",
-      base::Bind(&ServiceWorkerInternalsUI::SetOption, base::Unretained(this)));
+      "SetOption", base::BindRepeating(&ServiceWorkerInternalsUI::SetOption,
+                                       base::Unretained(this)));
   web_ui->RegisterMessageCallback(
       "getAllRegistrations",
-      base::Bind(&ServiceWorkerInternalsUI::GetAllRegistrations,
-                 base::Unretained(this)));
+      base::BindRepeating(&ServiceWorkerInternalsUI::GetAllRegistrations,
+                          base::Unretained(this)));
   web_ui->RegisterMessageCallback(
-      "stop", base::Bind(&ServiceWorkerInternalsUI::StopWorker,
-                         base::Unretained(this)));
+      "stop", base::BindRepeating(&ServiceWorkerInternalsUI::StopWorker,
+                                  base::Unretained(this)));
   web_ui->RegisterMessageCallback(
-      "inspect",
-      base::Bind(&ServiceWorkerInternalsUI::InspectWorker,
-                 base::Unretained(this)));
+      "inspect", base::BindRepeating(&ServiceWorkerInternalsUI::InspectWorker,
+                                     base::Unretained(this)));
   web_ui->RegisterMessageCallback(
-      "unregister",
-      base::Bind(&ServiceWorkerInternalsUI::Unregister,
-                 base::Unretained(this)));
+      "unregister", base::BindRepeating(&ServiceWorkerInternalsUI::Unregister,
+                                        base::Unretained(this)));
   web_ui->RegisterMessageCallback(
-      "start",
-      base::Bind(&ServiceWorkerInternalsUI::StartWorker,
-                 base::Unretained(this)));
+      "start", base::BindRepeating(&ServiceWorkerInternalsUI::StartWorker,
+                                   base::Unretained(this)));
 }
 
 ServiceWorkerInternalsUI::~ServiceWorkerInternalsUI() {
diff --git a/content/browser/service_worker/service_worker_navigation_loader.cc b/content/browser/service_worker/service_worker_navigation_loader.cc
index deaa6708..59ee781 100644
--- a/content/browser/service_worker/service_worker_navigation_loader.cc
+++ b/content/browser/service_worker/service_worker_navigation_loader.cc
@@ -71,7 +71,7 @@
 };
 
 ServiceWorkerNavigationLoader::ServiceWorkerNavigationLoader(
-    URLLoaderRequestHandler::LoaderCallback callback,
+    NavigationLoaderInterceptor::LoaderCallback callback,
     Delegate* delegate,
     const network::ResourceRequest& resource_request,
     scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter)
diff --git a/content/browser/service_worker/service_worker_navigation_loader.h b/content/browser/service_worker/service_worker_navigation_loader.h
index 29293f1..3312538 100644
--- a/content/browser/service_worker/service_worker_navigation_loader.h
+++ b/content/browser/service_worker/service_worker_navigation_loader.h
@@ -10,7 +10,7 @@
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "content/browser/loader/url_loader_request_handler.h"
+#include "content/browser/loader/navigation_loader_interceptor.h"
 #include "content/browser/service_worker/service_worker_fetch_dispatcher.h"
 #include "content/browser/service_worker/service_worker_metrics.h"
 #include "content/browser/service_worker/service_worker_response_type.h"
@@ -72,7 +72,7 @@
   //    This forwards the blob/stream data pipe to the NavigationURLLoader if
   //    the response body was sent as a blob/stream.
   ServiceWorkerNavigationLoader(
-      URLLoaderRequestHandler::LoaderCallback loader_callback,
+      NavigationLoaderInterceptor::LoaderCallback loader_callback,
       Delegate* delegate,
       const network::ResourceRequest& resource_request,
       scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter);
@@ -148,7 +148,7 @@
   void DeleteIfNeeded();
 
   ResponseType response_type_ = ResponseType::NOT_DETERMINED;
-  URLLoaderRequestHandler::LoaderCallback loader_callback_;
+  NavigationLoaderInterceptor::LoaderCallback loader_callback_;
 
   Delegate* delegate_;
   network::ResourceRequest resource_request_;
diff --git a/content/browser/service_worker/service_worker_navigation_loader_unittest.cc b/content/browser/service_worker/service_worker_navigation_loader_unittest.cc
index a2b7c72..90b13ec 100644
--- a/content/browser/service_worker/service_worker_navigation_loader_unittest.cc
+++ b/content/browser/service_worker/service_worker_navigation_loader_unittest.cc
@@ -6,7 +6,7 @@
 
 #include "base/run_loop.h"
 #include "base/test/scoped_feature_list.h"
-#include "content/browser/loader/url_loader_request_handler.h"
+#include "content/browser/loader/navigation_loader_interceptor.h"
 #include "content/browser/service_worker/embedded_worker_test_helper.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
 #include "content/browser/service_worker/service_worker_registration.h"
diff --git a/content/browser/service_worker/service_worker_request_handler.cc b/content/browser/service_worker/service_worker_request_handler.cc
index a0892b3..65eeb33 100644
--- a/content/browser/service_worker/service_worker_request_handler.cc
+++ b/content/browser/service_worker/service_worker_request_handler.cc
@@ -9,7 +9,7 @@
 
 #include "base/command_line.h"
 #include "base/macros.h"
-#include "content/browser/loader/url_loader_request_handler.h"
+#include "content/browser/loader/navigation_loader_interceptor.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
 #include "content/browser/service_worker/service_worker_navigation_handle_core.h"
@@ -131,7 +131,7 @@
 
 // S13nServiceWorker:
 // static
-std::unique_ptr<URLLoaderRequestHandler>
+std::unique_ptr<NavigationLoaderInterceptor>
 ServiceWorkerRequestHandler::InitializeForNavigationNetworkService(
     const network::ResourceRequest& resource_request,
     ResourceContext* resource_context,
@@ -181,7 +181,7 @@
   // ServiceWorkerNavigationHandleCore.
   navigation_handle_core->DidPreCreateProviderHost(std::move(provider_host));
 
-  return base::WrapUnique<URLLoaderRequestHandler>(handler.release());
+  return base::WrapUnique<NavigationLoaderInterceptor>(handler.release());
 }
 
 // static
diff --git a/content/browser/service_worker/service_worker_request_handler.h b/content/browser/service_worker/service_worker_request_handler.h
index ef6d7d2..b483853 100644
--- a/content/browser/service_worker/service_worker_request_handler.h
+++ b/content/browser/service_worker/service_worker_request_handler.h
@@ -12,7 +12,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/supports_user_data.h"
 #include "base/time/time.h"
-#include "content/browser/loader/url_loader_request_handler.h"
+#include "content/browser/loader/navigation_loader_interceptor.h"
 #include "content/common/content_export.h"
 #include "content/common/service_worker/service_worker_status_code.h"
 #include "content/common/service_worker/service_worker_types.h"
@@ -49,7 +49,7 @@
 // Created one per URLRequest and attached to each request.
 class CONTENT_EXPORT ServiceWorkerRequestHandler
     : public base::SupportsUserData::Data,
-      public URLLoaderRequestHandler {
+      public NavigationLoaderInterceptor {
  public:
   // PlzNavigate
   // Attaches a newly created handler if the given |request| needs to be handled
@@ -68,8 +68,8 @@
 
   // S13nServiceWorker:
   // Same as InitializeForNavigation() but instead of attaching to a URLRequest,
-  // just creates a URLLoaderRequestHandler and returns it.
-  static std::unique_ptr<URLLoaderRequestHandler>
+  // just creates a NavigationLoaderInterceptor and returns it.
+  static std::unique_ptr<NavigationLoaderInterceptor>
   InitializeForNavigationNetworkService(
       const network::ResourceRequest& resource_request,
       ResourceContext* resource_context,
@@ -134,7 +134,7 @@
       net::NetworkDelegate* network_delegate,
       ResourceContext* context) = 0;
 
-  // URLLoaderRequestHandler overrides.
+  // NavigationLoaderInterceptor overrides.
   void MaybeCreateLoader(const network::ResourceRequest& request,
                          ResourceContext* resource_context,
                          LoaderCallback callback) override;
diff --git a/content/browser/service_worker/service_worker_url_job_wrapper.h b/content/browser/service_worker/service_worker_url_job_wrapper.h
index bd12480..acaf609c 100644
--- a/content/browser/service_worker/service_worker_url_job_wrapper.h
+++ b/content/browser/service_worker/service_worker_url_job_wrapper.h
@@ -6,7 +6,7 @@
 #define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_JOB_WRAPPER_H_
 
 #include "base/macros.h"
-#include "content/browser/loader/url_loader_request_handler.h"
+#include "content/browser/loader/navigation_loader_interceptor.h"
 #include "content/browser/service_worker/service_worker_metrics.h"
 #include "content/common/content_export.h"
 
diff --git a/content/browser/site_isolation_policy.cc b/content/browser/site_isolation_policy.cc
index 6f5cd31..e924041e 100644
--- a/content/browser/site_isolation_policy.cc
+++ b/content/browser/site_isolation_policy.cc
@@ -26,19 +26,30 @@
 
 // static
 bool SiteIsolationPolicy::UseDedicatedProcessesForAllSites() {
-  return base::CommandLine::ForCurrentProcess()->HasSwitch(
-             switches::kSitePerProcess) ||
-         (base::FeatureList::IsEnabled(features::kSitePerProcess) &&
-          !base::CommandLine::ForCurrentProcess()->HasSwitch(
-              switches::kDisableSiteIsolationTrials));
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kSitePerProcess)) {
+    return true;
+  }
+
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kDisableSiteIsolationTrials)) {
+    return false;
+  }
+
+  // The switches above needs to be checked first, because if the
+  // ContentBrowserClient consults a base::Feature, then it will activate the
+  // field trial and assigns the client either to a control or an experiment
+  // group - such assignment should be final.
+  return GetContentClient()->browser()->ShouldEnableStrictSiteIsolation();
 }
 
 // static
 SiteIsolationPolicy::CrossSiteDocumentBlockingEnabledState
 SiteIsolationPolicy::IsCrossSiteDocumentBlockingEnabled() {
   if (base::FeatureList::IsEnabled(
-          ::features::kCrossSiteDocumentBlockingAlways))
+          ::features::kCrossSiteDocumentBlockingAlways)) {
     return XSDB_ENABLED_UNCONDITIONALLY;
+  }
 
   if (base::FeatureList::IsEnabled(
           ::features::kCrossSiteDocumentBlockingIfIsolating)) {
@@ -54,16 +65,33 @@
   if (UseDedicatedProcessesForAllSites())
     return false;
 
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kDisableSiteIsolationTrials)) {
+    return false;
+  }
+
+  // The feature needs to be checked last, because checking the feature
+  // activates the field trial and assigns the client either to a control or an
+  // experiment group - such assignment should be final.
   return base::FeatureList::IsEnabled(::features::kTopDocumentIsolation);
 }
 
 // static
 bool SiteIsolationPolicy::AreIsolatedOriginsEnabled() {
-  return base::CommandLine::ForCurrentProcess()->HasSwitch(
-             switches::kIsolateOrigins) ||
-         (base::FeatureList::IsEnabled(features::kIsolateOrigins) &&
-          !base::CommandLine::ForCurrentProcess()->HasSwitch(
-              switches::kDisableSiteIsolationTrials));
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kIsolateOrigins)) {
+    return true;
+  }
+
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kDisableSiteIsolationTrials)) {
+    return false;
+  }
+
+  // The feature needs to be checked last, because checking the feature
+  // activates the field trial and assigns the client either to a control or an
+  // experiment group - such assignment should be final.
+  return base::FeatureList::IsEnabled(features::kIsolateOrigins);
 }
 
 // static
@@ -80,15 +108,20 @@
     return cmdline_origins;
   }
 
-  if (base::FeatureList::IsEnabled(features::kIsolateOrigins) &&
-      !base::CommandLine::ForCurrentProcess()->HasSwitch(
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kDisableSiteIsolationTrials)) {
+    return std::vector<url::Origin>();
+  }
+
+  // The feature needs to be checked last, because checking the feature
+  // activates the field trial and assigns the client either to a control or an
+  // experiment group - such assignment should be final.
+  if (base::FeatureList::IsEnabled(features::kIsolateOrigins)) {
     std::string field_trial_arg = base::GetFieldTrialParamValueByFeature(
         features::kIsolateOrigins,
         features::kIsolateOriginsFieldTrialParamName);
     return ParseIsolatedOrigins(field_trial_arg);
   }
-
   return std::vector<url::Origin>();
 }
 
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index 30eb1ed6..25c4833 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -10928,14 +10928,6 @@
   GURL popup_url(embedded_test_server()->GetURL(
       "b.com", "/cross_site_iframe_factory.html?b(b)"));
   Shell* popup_shell = OpenPopup(shell()->web_contents(), popup_url, "popup");
-
-#if defined(OS_ANDROID)
-  // Workaround for https://crbug.com/823493 on Android content shell, where
-  // window.open() won't initially show the contents of the new window, and
-  // resizing it will force the contents to be shown.
-  popup_shell->SizeTo(gfx::Size(500, 500));
-#endif
-
   FrameTreeNode* popup_child =
       static_cast<WebContentsImpl*>(popup_shell->web_contents())
           ->GetFrameTree()
diff --git a/content/browser/site_per_process_hit_test_browsertest.cc b/content/browser/site_per_process_hit_test_browsertest.cc
index 2dbb8470..45f6e3b 100644
--- a/content/browser/site_per_process_hit_test_browsertest.cc
+++ b/content/browser/site_per_process_hit_test_browsertest.cc
@@ -438,7 +438,7 @@
 }  // namespace
 
 class SitePerProcessHitTestBrowserTest
-    : public testing::WithParamInterface<std::tuple<bool, float>>,
+    : public testing::WithParamInterface<std::tuple<int, float>>,
       public SitePerProcessBrowserTest {
  public:
   SitePerProcessHitTestBrowserTest() {}
@@ -446,8 +446,11 @@
  protected:
   void SetUpCommandLine(base::CommandLine* command_line) override {
     SitePerProcessBrowserTest::SetUpCommandLine(command_line);
-    if (std::get<0>(GetParam())) {
+    if (std::get<0>(GetParam()) == 1) {
       feature_list_.InitAndEnableFeature(features::kEnableVizHitTestDrawQuad);
+    } else if (std::get<0>(GetParam()) == 2) {
+      feature_list_.InitAndEnableFeature(
+          features::kEnableVizHitTestSurfaceLayer);
     }
   }
 
@@ -3494,11 +3497,12 @@
   }
 }
 
+static const int kHitTestOption[] = {0, 1, 2};
 static const float kOneScale[] = {1.f};
 
 INSTANTIATE_TEST_CASE_P(/* no prefix */,
                         SitePerProcessHitTestBrowserTest,
-                        testing::Combine(testing::Bool(),
+                        testing::Combine(testing::ValuesIn(kHitTestOption),
                                          testing::ValuesIn(kOneScale)));
 // TODO(wjmaclean): Since the next two test fixtures only differ in DSF
 // values, should we combine them into one using kMultiScale? This
@@ -3506,26 +3510,26 @@
 // particular platforms.
 INSTANTIATE_TEST_CASE_P(/* no prefix */,
                         SitePerProcessHighDPIHitTestBrowserTest,
-                        testing::Combine(testing::Bool(),
+                        testing::Combine(testing::ValuesIn(kHitTestOption),
                                          testing::ValuesIn(kOneScale)));
 INSTANTIATE_TEST_CASE_P(/* no prefix */,
                         SitePerProcessNonIntegerScaleFactorHitTestBrowserTest,
-                        testing::Combine(testing::Bool(),
+                        testing::Combine(testing::ValuesIn(kHitTestOption),
                                          testing::ValuesIn(kOneScale)));
 #if defined(USE_AURA)
 static const float kMultiScale[] = {1.f, 1.5f, 2.f};
 
 INSTANTIATE_TEST_CASE_P(/* no prefix */,
                         SitePerProcessInternalsHitTestBrowserTest,
-                        testing::Combine(testing::Bool(),
+                        testing::Combine(testing::ValuesIn(kHitTestOption),
                                          testing::ValuesIn(kMultiScale)));
 INSTANTIATE_TEST_CASE_P(/* no prefix */,
                         SitePerProcessMouseWheelHitTestBrowserTest,
-                        testing::Combine(testing::Bool(),
+                        testing::Combine(testing::ValuesIn(kHitTestOption),
                                          testing::ValuesIn(kOneScale)));
 INSTANTIATE_TEST_CASE_P(/* no prefix */,
                         SitePerProcessGestureHitTestBrowserTest,
-                        testing::Combine(testing::Bool(),
+                        testing::Combine(testing::ValuesIn(kHitTestOption),
                                          testing::ValuesIn(kOneScale)));
 #endif
 
diff --git a/content/browser/storage_partition_impl_map_unittest.cc b/content/browser/storage_partition_impl_map_unittest.cc
index 06dff80..89fc1685 100644
--- a/content/browser/storage_partition_impl_map_unittest.cc
+++ b/content/browser/storage_partition_impl_map_unittest.cc
@@ -8,8 +8,10 @@
 
 #include "base/files/file_util.h"
 #include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
+#include "content/public/browser/browser_thread.h"
 #include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace content {
@@ -65,8 +67,8 @@
 }
 
 TEST(StoragePartitionImplMapTest, GarbageCollect) {
+  TestBrowserThreadBundle thread_bundle;
   TestBrowserContext browser_context;
-  base::test::ScopedTaskEnvironment scoped_task_environment;
   StoragePartitionImplMap storage_partition_impl_map(&browser_context);
 
   std::unique_ptr<base::hash_set<base::FilePath>> active_paths(
@@ -87,7 +89,7 @@
   storage_partition_impl_map.GarbageCollect(std::move(active_paths),
                                             run_loop.QuitClosure());
   run_loop.Run();
-  scoped_task_environment.RunUntilIdle();
+  content::RunAllPendingInMessageLoop(content::BrowserThread::IO);
 
   EXPECT_TRUE(base::PathExists(active_path));
   EXPECT_FALSE(base::PathExists(inactive_path));
diff --git a/content/browser/tracing/tracing_ui.cc b/content/browser/tracing/tracing_ui.cc
index b0e07ce..fd922b3e9 100644
--- a/content/browser/tracing/tracing_ui.cc
+++ b/content/browser/tracing/tracing_ui.cc
@@ -168,10 +168,10 @@
       weak_factory_(this) {
   web_ui->RegisterMessageCallback(
       "doUpload",
-      base::Bind(&TracingUI::DoUpload, base::Unretained(this)));
+      base::BindRepeating(&TracingUI::DoUpload, base::Unretained(this)));
   web_ui->RegisterMessageCallback(
-      "doUploadBase64",
-      base::Bind(&TracingUI::DoUploadBase64Encoded, base::Unretained(this)));
+      "doUploadBase64", base::BindRepeating(&TracingUI::DoUploadBase64Encoded,
+                                            base::Unretained(this)));
 
   // Set up the chrome://tracing/ source.
   BrowserContext* browser_context =
diff --git a/content/browser/utility_process_host.cc b/content/browser/utility_process_host.cc
index 9185f9f..0358e9d7 100644
--- a/content/browser/utility_process_host.cc
+++ b/content/browser/utility_process_host.cc
@@ -267,6 +267,7 @@
 
     // Browser command-line switches to propagate to the utility process.
     static const char* const kSwitchNames[] = {
+      network::switches::kForceEffectiveConnectionType,
       network::switches::kHostResolverRules,
       network::switches::kIgnoreCertificateErrorsSPKIList,
       network::switches::kLogNetLog,
diff --git a/content/browser/web_contents/aura/gesture_nav_simple.cc b/content/browser/web_contents/aura/gesture_nav_simple.cc
index 2bf8f70..73945fb 100644
--- a/content/browser/web_contents/aura/gesture_nav_simple.cc
+++ b/content/browser/web_contents/aura/gesture_nav_simple.cc
@@ -597,7 +597,8 @@
 
 void GestureNavSimple::OnOverscrollModeChange(OverscrollMode old_mode,
                                               OverscrollMode new_mode,
-                                              OverscrollSource source) {
+                                              OverscrollSource source,
+                                              cc::OverscrollBehavior behavior) {
   DCHECK_EQ(mode_, old_mode);
   if (mode_ == new_mode)
     return;
diff --git a/content/browser/web_contents/aura/gesture_nav_simple.h b/content/browser/web_contents/aura/gesture_nav_simple.h
index 040da49..cf970b7 100644
--- a/content/browser/web_contents/aura/gesture_nav_simple.h
+++ b/content/browser/web_contents/aura/gesture_nav_simple.h
@@ -29,13 +29,12 @@
  private:
   // OverscrollControllerDelegate:
   gfx::Size GetDisplaySize() const override;
-  void OnOverscrollBehaviorUpdate(
-      cc::OverscrollBehavior overscroll_behavior) override {}
   bool OnOverscrollUpdate(float delta_x, float delta_y) override;
   void OnOverscrollComplete(OverscrollMode overscroll_mode) override;
   void OnOverscrollModeChange(OverscrollMode old_mode,
                               OverscrollMode new_mode,
-                              OverscrollSource source) override;
+                              OverscrollSource source,
+                              cc::OverscrollBehavior behavior) override;
   base::Optional<float> GetMaxOverscrollDelta() const override;
 
   WebContentsImpl* web_contents_ = nullptr;
diff --git a/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc b/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc
index c3d13d85..110658e 100644
--- a/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc
+++ b/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc
@@ -444,7 +444,8 @@
   ui::ScopedAnimationDurationScaleMode normal_duration_(
       ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
   GetOverlay()->owa_->OnOverscrollModeChange(OVERSCROLL_NONE, OVERSCROLL_EAST,
-                                             OverscrollSource::TOUCHSCREEN);
+                                             OverscrollSource::TOUCHSCREEN,
+                                             cc::OverscrollBehavior());
   GetOverlay()->owa_->OnOverscrollComplete(OVERSCROLL_EAST);
   EXPECT_EQ(GetOverlay()->direction_, NavigationDirection::BACK);
   OverscrollTestWebContents* test_web_contents =
@@ -463,7 +464,8 @@
   // navigation starts.
   ImmediateLoadObserver immediate_nav(contents());
   GetOverlay()->owa_->OnOverscrollModeChange(OVERSCROLL_NONE, OVERSCROLL_EAST,
-                                             OverscrollSource::TOUCHPAD);
+                                             OverscrollSource::TOUCHPAD,
+                                             cc::OverscrollBehavior());
   // This will start and immediately complete the navigation.
   GetOverlay()->owa_->OnOverscrollComplete(OVERSCROLL_EAST);
   EXPECT_FALSE(GetOverlay()->window_.get());
diff --git a/content/browser/web_contents/aura/overscroll_window_animation.cc b/content/browser/web_contents/aura/overscroll_window_animation.cc
index cd36565d..c7cf437 100644
--- a/content/browser/web_contents/aura/overscroll_window_animation.cc
+++ b/content/browser/web_contents/aura/overscroll_window_animation.cc
@@ -62,11 +62,6 @@
       .size();
 }
 
-void OverscrollWindowAnimation::OnOverscrollBehaviorUpdate(
-    cc::OverscrollBehavior overscroll_behavior) {
-  overscroll_behavior_ = overscroll_behavior;
-}
-
 bool OverscrollWindowAnimation::OnOverscrollUpdate(float delta_x,
                                                    float delta_y) {
   if (direction_ == SLIDE_NONE)
@@ -96,12 +91,13 @@
 void OverscrollWindowAnimation::OnOverscrollModeChange(
     OverscrollMode old_mode,
     OverscrollMode new_mode,
-    OverscrollSource source) {
+    OverscrollSource source,
+    cc::OverscrollBehavior behavior) {
   DCHECK_NE(old_mode, new_mode);
   Direction new_direction = GetDirectionForMode(new_mode);
   if (new_direction == SLIDE_NONE ||
-      overscroll_behavior_.x != cc::OverscrollBehavior::OverscrollBehaviorType::
-                                    kOverscrollBehaviorTypeAuto) {
+      behavior.x != cc::OverscrollBehavior::OverscrollBehaviorType::
+                        kOverscrollBehaviorTypeAuto) {
     // The user cancelled the in progress animation.
     if (is_active())
       CancelSlide();
diff --git a/content/browser/web_contents/aura/overscroll_window_animation.h b/content/browser/web_contents/aura/overscroll_window_animation.h
index 26e1f571..a29cc6b 100644
--- a/content/browser/web_contents/aura/overscroll_window_animation.h
+++ b/content/browser/web_contents/aura/overscroll_window_animation.h
@@ -85,13 +85,12 @@
 
   // OverscrollControllerDelegate:
   gfx::Size GetDisplaySize() const override;
-  void OnOverscrollBehaviorUpdate(
-      cc::OverscrollBehavior overscroll_behavior) override;
   bool OnOverscrollUpdate(float delta_x, float delta_y) override;
   void OnOverscrollComplete(OverscrollMode overscroll_mode) override;
   void OnOverscrollModeChange(OverscrollMode old_mode,
                               OverscrollMode new_mode,
-                              OverscrollSource source) override;
+                              OverscrollSource source,
+                              cc::OverscrollBehavior behavior) override;
   base::Optional<float> GetMaxOverscrollDelta() const override;
 
  private:
@@ -137,12 +136,6 @@
   // on the delegate.
   OverscrollSource overscroll_source_ = OverscrollSource::NONE;
 
-  // OverscrollBehavior of the current overscroll gesture. Updated by
-  // OnOverscrollBehaviorUpdate(). This happens before before
-  // OnOverscrollModeChange and OnOverscrollUpdate. It prevents overscroll
-  // navigation if its x value is not auto.
-  cc::OverscrollBehavior overscroll_behavior_;
-
   // Indicates if the current slide has been cancelled. True while the cancel
   // animation is in progress.
   bool overscroll_cancelled_;
diff --git a/content/browser/web_contents/aura/overscroll_window_animation_unittest.cc b/content/browser/web_contents/aura/overscroll_window_animation_unittest.cc
index 66c1599..9fc3c91 100644
--- a/content/browser/web_contents/aura/overscroll_window_animation_unittest.cc
+++ b/content/browser/web_contents/aura/overscroll_window_animation_unittest.cc
@@ -128,7 +128,8 @@
 
   // Start an OVERSCROLL_EAST gesture.
   owa()->OnOverscrollModeChange(OVERSCROLL_NONE, OVERSCROLL_EAST,
-                                OverscrollSource::TOUCHPAD);
+                                OverscrollSource::TOUCHPAD,
+                                cc::OverscrollBehavior());
   EXPECT_TRUE(owa()->is_active());
   EXPECT_EQ(OverscrollSource::TOUCHPAD, owa()->overscroll_source());
   EXPECT_TRUE(overscroll_started());
@@ -149,11 +150,13 @@
 TEST_F(OverscrollWindowAnimationTest, BasicAbort) {
   // Start an OVERSCROLL_EAST gesture.
   owa()->OnOverscrollModeChange(OVERSCROLL_NONE, OVERSCROLL_EAST,
-                                OverscrollSource::TOUCHSCREEN);
+                                OverscrollSource::TOUCHSCREEN,
+                                cc::OverscrollBehavior());
   EXPECT_EQ(OverscrollSource::TOUCHSCREEN, owa()->overscroll_source());
   // Abort the overscroll.
   owa()->OnOverscrollModeChange(OVERSCROLL_EAST, OVERSCROLL_NONE,
-                                OverscrollSource::TOUCHSCREEN);
+                                OverscrollSource::TOUCHSCREEN,
+                                cc::OverscrollBehavior());
   EXPECT_EQ(OverscrollSource::NONE, owa()->overscroll_source());
   EXPECT_FALSE(owa()->is_active());
   EXPECT_TRUE(overscroll_started());
@@ -167,7 +170,8 @@
   set_create_window(false);
   // Start an OVERSCROLL_EAST gesture.
   owa()->OnOverscrollModeChange(OVERSCROLL_NONE, OVERSCROLL_EAST,
-                                OverscrollSource::TOUCHPAD);
+                                OverscrollSource::TOUCHPAD,
+                                cc::OverscrollBehavior());
   EXPECT_FALSE(owa()->is_active());
   EXPECT_EQ(OverscrollSource::NONE, owa()->overscroll_source());
   EXPECT_TRUE(overscroll_started());
@@ -190,7 +194,8 @@
   ui::LayerAnimatorTestController test_controller(animator);
   // Start an OVERSCROLL_EAST gesture.
   owa()->OnOverscrollModeChange(OVERSCROLL_NONE, OVERSCROLL_EAST,
-                                OverscrollSource::TOUCHPAD);
+                                OverscrollSource::TOUCHPAD,
+                                cc::OverscrollBehavior());
 
   // Finishes the OVERSCROLL_EAST gesture. At this point the window should be
   // being animated to its final position.
@@ -204,7 +209,8 @@
 
   // Start another OVERSCROLL_EAST gesture.
   owa()->OnOverscrollModeChange(OVERSCROLL_NONE, OVERSCROLL_EAST,
-                                OverscrollSource::TOUCHSCREEN);
+                                OverscrollSource::TOUCHSCREEN,
+                                cc::OverscrollBehavior());
   EXPECT_TRUE(owa()->is_active());
   EXPECT_EQ(OverscrollSource::TOUCHSCREEN, owa()->overscroll_source());
   EXPECT_TRUE(overscroll_started());
@@ -249,9 +255,9 @@
   cc::OverscrollBehavior overscroll_behavior;
   overscroll_behavior.x = cc::OverscrollBehavior::OverscrollBehaviorType::
       kOverscrollBehaviorTypeAuto;
-  owa()->OnOverscrollBehaviorUpdate(overscroll_behavior);
   owa()->OnOverscrollModeChange(OVERSCROLL_NONE, OVERSCROLL_EAST,
-                                OverscrollSource::TOUCHPAD);
+                                OverscrollSource::TOUCHPAD,
+                                overscroll_behavior);
   EXPECT_TRUE(owa()->is_active());
   EXPECT_EQ(OverscrollSource::TOUCHPAD, owa()->overscroll_source());
   EXPECT_TRUE(overscroll_started());
@@ -271,9 +277,9 @@
   cc::OverscrollBehavior overscroll_behavior;
   overscroll_behavior.x = cc::OverscrollBehavior::OverscrollBehaviorType::
       kOverscrollBehaviorTypeContain;
-  owa()->OnOverscrollBehaviorUpdate(overscroll_behavior);
   owa()->OnOverscrollModeChange(OVERSCROLL_NONE, OVERSCROLL_EAST,
-                                OverscrollSource::TOUCHPAD);
+                                OverscrollSource::TOUCHPAD,
+                                overscroll_behavior);
   EXPECT_FALSE(owa()->is_active());
   EXPECT_FALSE(overscroll_started());
   EXPECT_FALSE(overscroll_completing());
@@ -292,9 +298,9 @@
   cc::OverscrollBehavior overscroll_behavior;
   overscroll_behavior.x = cc::OverscrollBehavior::OverscrollBehaviorType::
       kOverscrollBehaviorTypeNone;
-  owa()->OnOverscrollBehaviorUpdate(overscroll_behavior);
   owa()->OnOverscrollModeChange(OVERSCROLL_NONE, OVERSCROLL_EAST,
-                                OverscrollSource::TOUCHPAD);
+                                OverscrollSource::TOUCHPAD,
+                                overscroll_behavior);
   EXPECT_FALSE(owa()->is_active());
   EXPECT_FALSE(overscroll_started());
   EXPECT_FALSE(overscroll_completing());
@@ -315,9 +321,9 @@
       kOverscrollBehaviorTypeAuto;
   overscroll_behavior.y = cc::OverscrollBehavior::OverscrollBehaviorType::
       kOverscrollBehaviorTypeNone;
-  owa()->OnOverscrollBehaviorUpdate(overscroll_behavior);
   owa()->OnOverscrollModeChange(OVERSCROLL_NONE, OVERSCROLL_EAST,
-                                OverscrollSource::TOUCHPAD);
+                                OverscrollSource::TOUCHPAD,
+                                overscroll_behavior);
   EXPECT_TRUE(owa()->is_active());
   EXPECT_EQ(OverscrollSource::TOUCHPAD, owa()->overscroll_source());
   EXPECT_TRUE(overscroll_started());
diff --git a/content/browser/web_contents/aura/overscroll_window_delegate.cc b/content/browser/web_contents/aura/overscroll_window_delegate.cc
index 23aadf2..3e48518 100644
--- a/content/browser/web_contents/aura/overscroll_window_delegate.cc
+++ b/content/browser/web_contents/aura/overscroll_window_delegate.cc
@@ -43,14 +43,16 @@
     overscroll_mode_ = OVERSCROLL_EAST;
   else
     overscroll_mode_ = OVERSCROLL_WEST;
-  delegate_->OnOverscrollModeChange(old_mode, overscroll_mode_, source);
+  delegate_->OnOverscrollModeChange(old_mode, overscroll_mode_, source,
+                                    cc::OverscrollBehavior());
 }
 
 void OverscrollWindowDelegate::ResetOverscroll() {
   if (overscroll_mode_ == OVERSCROLL_NONE)
     return;
   delegate_->OnOverscrollModeChange(overscroll_mode_, OVERSCROLL_NONE,
-                                    OverscrollSource::NONE);
+                                    OverscrollSource::NONE,
+                                    cc::OverscrollBehavior());
   overscroll_mode_ = OVERSCROLL_NONE;
   delta_x_ = 0;
 }
diff --git a/content/browser/web_contents/aura/overscroll_window_delegate_unittest.cc b/content/browser/web_contents/aura/overscroll_window_delegate_unittest.cc
index f8f4828b..bddc9a00 100644
--- a/content/browser/web_contents/aura/overscroll_window_delegate_unittest.cc
+++ b/content/browser/web_contents/aura/overscroll_window_delegate_unittest.cc
@@ -81,9 +81,6 @@
     return gfx::Size(kTestDisplayWidth, kTestDisplayWidth);
   }
 
-  void OnOverscrollBehaviorUpdate(
-      cc::OverscrollBehavior overscroll_behavior) override {}
-
   bool OnOverscrollUpdate(float delta_x, float delta_y) override {
     return true;
   }
@@ -94,7 +91,8 @@
 
   void OnOverscrollModeChange(OverscrollMode old_mode,
                               OverscrollMode new_mode,
-                              OverscrollSource source) override {
+                              OverscrollSource source,
+                              cc::OverscrollBehavior behavior) override {
     mode_changed_ = true;
     current_mode_ = new_mode;
     if (current_mode_ != OVERSCROLL_NONE)
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 6cb03828..7184190d 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -177,8 +177,9 @@
 const void* const kWebContentsAndroidKey = &kWebContentsAndroidKey;
 #endif
 
-base::LazyInstance<std::vector<WebContentsImpl::CreatedCallback>>::
-    DestructorAtExit g_created_callbacks = LAZY_INSTANCE_INITIALIZER;
+base::LazyInstance<std::vector<
+    WebContentsImpl::FriendWrapper::CreatedCallback>>::DestructorAtExit
+    g_created_callbacks = LAZY_INSTANCE_INITIALIZER;
 
 void NotifyCacheOnIO(
     scoped_refptr<net::URLRequestContextGetter> request_context,
@@ -4100,15 +4101,17 @@
   // AddNewContents method call.
 }
 
-void WebContentsImpl::SubresourceResponseStarted(
+void WebContentsImpl::SubresourceResponseStarted(const GURL& url,
+                                                 net::CertStatus cert_status) {
+  controller_.ssl_manager()->DidStartResourceResponse(url, cert_status);
+  SetNotWaitingForResponse();
+}
+
+void WebContentsImpl::SubresourceLoadComplete(
     mojom::SubresourceLoadInfoPtr subresource_load_info) {
   for (auto& observer : observers_) {
-    observer.SubresourceResponseStarted(*subresource_load_info);
+    observer.SubresourceLoadComplete(*subresource_load_info);
   }
-
-  controller_.ssl_manager()->DidStartResourceResponse(
-      subresource_load_info->url, subresource_load_info->cert_status);
-  SetNotWaitingForResponse();
 }
 
 void WebContentsImpl::PrintCrossProcessSubframe(
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 04446a61..b97c76a 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -573,7 +573,9 @@
   base::android::ScopedJavaLocalRef<jobject> GetJavaRenderFrameHostDelegate()
       override;
 #endif
-  void SubresourceResponseStarted(
+  void SubresourceResponseStarted(const GURL& url,
+                                  net::CertStatus cert_status) override;
+  void SubresourceLoadComplete(
       mojom::SubresourceLoadInfoPtr subresource_load_information) override;
   void UpdatePictureInPictureSurfaceId(viz::SurfaceId surface_id) override;
 
@@ -846,8 +848,6 @@
   // Unpause the throbber if it was paused.
   void DidProceedOnInterstitial() override;
 
-  typedef base::Callback<void(WebContents*)> CreatedCallback;
-
   // Forces overscroll to be disabled (used by touch emulation).
   void SetForceDisableOverscrollContent(bool force_disable);
 
@@ -1712,6 +1712,9 @@
 // Dangerous methods which should never be made part of the public API, so we
 // grant their use only to an explicit friend list (c++ attorney/client idiom).
 class CONTENT_EXPORT WebContentsImpl::FriendWrapper {
+ public:
+  using CreatedCallback = base::RepeatingCallback<void(WebContents*)>;
+
  private:
   friend class TestNavigationObserver;
   friend class WebContentsAddedObserver;
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc
index 6916995..346898b 100644
--- a/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -524,6 +524,98 @@
   EXPECT_TRUE(new_web_contents_observer.RenderViewCreatedCalled());
 }
 
+// Observer class to track subresource loads.
+class SubresourceLoadObserver : public WebContentsObserver {
+ public:
+  explicit SubresourceLoadObserver(Shell* shell)
+      : WebContentsObserver(shell->web_contents()) {}
+
+  mojom::SubresourceLoadInfo* last_subresource_load_info() const {
+    return last_subresource_load_info_.get();
+  }
+
+  GURL last_memory_cached_loaded_url() const {
+    return last_memory_cached_loaded_url_;
+  }
+
+  void Reset() {
+    last_subresource_load_info_.reset();
+    last_memory_cached_loaded_url_ = GURL();
+  }
+
+ private:
+  // WebContentsObserver implementation:
+  void SubresourceLoadComplete(
+      const mojom::SubresourceLoadInfo& subresource_load_info) override {
+    last_subresource_load_info_ = subresource_load_info.Clone();
+  }
+
+  void DidLoadResourceFromMemoryCache(const GURL& url,
+                                      const std::string& mime_type,
+                                      ResourceType resource_type) override {
+    last_memory_cached_loaded_url_ = url;
+  }
+
+  GURL last_memory_cached_loaded_url_;
+  mojom::SubresourceLoadInfoPtr last_subresource_load_info_;
+
+  DISALLOW_COPY_AND_ASSIGN(SubresourceLoadObserver);
+};
+
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, SubresourceLoadComplete) {
+  SubresourceLoadObserver observer(shell());
+  ASSERT_TRUE(embedded_test_server()->Start());
+  GURL page_url(embedded_test_server()->GetURL("/page_with_image.html"));
+  NavigateToURL(shell(), page_url);
+  mojom::SubresourceLoadInfo* subresource_load_info =
+      observer.last_subresource_load_info();
+  ASSERT_TRUE(subresource_load_info);
+  EXPECT_EQ(embedded_test_server()->GetURL("/blank.jpg"),
+            subresource_load_info->url);
+  EXPECT_EQ(page_url, subresource_load_info->referrer);
+  EXPECT_EQ("GET", subresource_load_info->method);
+  EXPECT_EQ(content::RESOURCE_TYPE_IMAGE, subresource_load_info->resource_type);
+  ASSERT_TRUE(subresource_load_info->ip);
+  EXPECT_EQ("127.0.0.1", subresource_load_info->ip->ToString());
+}
+
+// Same as WebContentsImplBrowserTest.SubresourceLoadComplete but for a resource
+// retrieved from the network cache.
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+                       SubresourceLoadCompleteFromNetworkCache) {
+  SubresourceLoadObserver observer(shell());
+  ASSERT_TRUE(embedded_test_server()->Start());
+  GURL url(
+      embedded_test_server()->GetURL("/page_with_cached_subresource.html"));
+  NavigateToURL(shell(), url);
+
+  mojom::SubresourceLoadInfo* subresource_load_info =
+      observer.last_subresource_load_info();
+  GURL subresource_url = embedded_test_server()->GetURL("/cachetime");
+  ASSERT_TRUE(subresource_load_info);
+  EXPECT_EQ(subresource_url, subresource_load_info->url);
+  EXPECT_FALSE(subresource_load_info->was_cached);
+  observer.Reset();
+
+  // Loading again should serve the request out of the in-memory cache.
+  NavigateToURL(shell(), url);
+  ASSERT_FALSE(observer.last_subresource_load_info());
+  EXPECT_EQ(subresource_url, observer.last_memory_cached_loaded_url());
+  observer.Reset();
+
+  // Kill the renderer process so when the navigate again, it will be a fresh
+  // renderer with an empty in-memory cache.
+  NavigateToURL(shell(), GURL("chrome:crash"));
+
+  // Reload that URL, the subresource should be served from the network cache.
+  NavigateToURL(shell(), url);
+  subresource_load_info = observer.last_subresource_load_info();
+  ASSERT_TRUE(subresource_load_info);
+  EXPECT_EQ(subresource_url, subresource_load_info->url);
+  EXPECT_TRUE(subresource_load_info->was_cached);
+  EXPECT_FALSE(observer.last_memory_cached_loaded_url().is_valid());
+}
+
 struct LoadProgressDelegateAndObserver : public WebContentsDelegate,
                                          public WebContentsObserver {
   explicit LoadProgressDelegateAndObserver(Shell* shell)
diff --git a/content/browser/web_contents/web_contents_impl_unittest.cc b/content/browser/web_contents/web_contents_impl_unittest.cc
index 9490c80..9abeadd 100644
--- a/content/browser/web_contents/web_contents_impl_unittest.cc
+++ b/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -3463,6 +3463,32 @@
   EXPECT_EQ(SK_ColorGREEN, observer.last_theme_color());
 }
 
+TEST_F(WebContentsImplTest, PictureInPictureMediaPlayerIdWasChanged) {
+  const int kPlayerVideoOnlyId = 30; /* arbitrary and used for tests */
+
+  MediaWebContentsObserver* observer =
+      contents()->media_web_contents_observer();
+  TestRenderFrameHost* rfh = main_test_rfh();
+  rfh->InitializeRenderFrameIfNeeded();
+
+  // If Picture-in-Picture was never triggered, the media player id would not be
+  // set.
+  EXPECT_FALSE(observer->GetPictureInPictureVideoMediaPlayerId().has_value());
+
+  rfh->OnMessageReceived(
+      MediaPlayerDelegateHostMsg_OnPictureInPictureSourceChanged(
+          rfh->GetRoutingID(), kPlayerVideoOnlyId));
+  EXPECT_TRUE(observer->GetPictureInPictureVideoMediaPlayerId().has_value());
+  EXPECT_EQ(kPlayerVideoOnlyId,
+            observer->GetPictureInPictureVideoMediaPlayerId()->second);
+
+  // Picture-in-Picture media player id should be reset when the media is
+  // destroyed.
+  rfh->OnMessageReceived(MediaPlayerDelegateHostMsg_OnMediaDestroyed(
+      rfh->GetRoutingID(), kPlayerVideoOnlyId));
+  EXPECT_FALSE(observer->GetPictureInPictureVideoMediaPlayerId().has_value());
+}
+
 TEST_F(WebContentsImplTest, ParseDownloadHeaders) {
   download::DownloadUrlParameters::RequestHeadersType request_headers =
       WebContentsImpl::ParseDownloadHeaders("A: 1\r\nB: 2\r\nC: 3\r\n\r\n");
diff --git a/content/browser/web_contents/web_contents_view_android.cc b/content/browser/web_contents/web_contents_view_android.cc
index e9c134f..dd4158b 100644
--- a/content/browser/web_contents/web_contents_view_android.cc
+++ b/content/browser/web_contents/web_contents_view_android.cc
@@ -507,10 +507,9 @@
 }
 
 bool WebContentsViewAndroid::OnTouchEvent(const ui::MotionEventAndroid& event) {
-  if (event.GetAction() == ui::MotionEventAndroid::Action::DOWN) {
-    if (ShouldRequestUnbufferedDispatch())
-      view_.RequestUnbufferedDispatch(event);
-    content_view_core_->OnTouchDown(event.GetJavaObject());
+  if (event.GetAction() == ui::MotionEventAndroid::Action::DOWN &&
+      ShouldRequestUnbufferedDispatch()) {
+    view_.RequestUnbufferedDispatch(event);
   }
   return false;  // let the children handle the actual event.
 }
diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc
index 5d28247a..b18f720 100644
--- a/content/browser/web_contents/web_contents_view_aura.cc
+++ b/content/browser/web_contents/web_contents_view_aura.cc
@@ -993,12 +993,6 @@
       .size();
 }
 
-void WebContentsViewAura::OnOverscrollBehaviorUpdate(
-    cc::OverscrollBehavior overscroll_behavior) {
-  navigation_overlay_->relay_delegate()->OnOverscrollBehaviorUpdate(
-      overscroll_behavior);
-}
-
 bool WebContentsViewAura::OnOverscrollUpdate(float delta_x, float delta_y) {
   if (current_overscroll_gesture_ != OVERSCROLL_EAST &&
       current_overscroll_gesture_ != OVERSCROLL_WEST) {
@@ -1013,12 +1007,14 @@
   CompleteOverscrollNavigation(mode);
 }
 
-void WebContentsViewAura::OnOverscrollModeChange(OverscrollMode old_mode,
-                                                 OverscrollMode new_mode,
-                                                 OverscrollSource source) {
+void WebContentsViewAura::OnOverscrollModeChange(
+    OverscrollMode old_mode,
+    OverscrollMode new_mode,
+    OverscrollSource source,
+    cc::OverscrollBehavior behavior) {
   current_overscroll_gesture_ = new_mode;
   navigation_overlay_->relay_delegate()->OnOverscrollModeChange(
-      old_mode, new_mode, source);
+      old_mode, new_mode, source, behavior);
   completed_overscroll_gesture_ = OVERSCROLL_NONE;
 }
 
diff --git a/content/browser/web_contents/web_contents_view_aura.h b/content/browser/web_contents/web_contents_view_aura.h
index 4aa7af32..0cbe134 100644
--- a/content/browser/web_contents/web_contents_view_aura.h
+++ b/content/browser/web_contents/web_contents_view_aura.h
@@ -155,12 +155,12 @@
 
   // Overridden from OverscrollControllerDelegate:
   gfx::Size GetDisplaySize() const override;
-  void OnOverscrollBehaviorUpdate(cc::OverscrollBehavior) override;
   bool OnOverscrollUpdate(float delta_x, float delta_y) override;
   void OnOverscrollComplete(OverscrollMode overscroll_mode) override;
   void OnOverscrollModeChange(OverscrollMode old_mode,
                               OverscrollMode new_mode,
-                              OverscrollSource source) override;
+                              OverscrollSource source,
+                              cc::OverscrollBehavior behavior) override;
   base::Optional<float> GetMaxOverscrollDelta() const override;
 
   // Overridden from aura::WindowDelegate:
diff --git a/content/browser/web_package/signed_exchange_header.cc b/content/browser/web_package/signed_exchange_header.cc
index 343bf07..94b2008d 100644
--- a/content/browser/web_package/signed_exchange_header.cc
+++ b/content/browser/web_package/signed_exchange_header.cc
@@ -20,21 +20,25 @@
 // IsStateful{Request,Response}Header return true if |name| is a stateful
 // header field. Stateful header fields will cause validation failure of
 // signed exchanges.
+// Note that |name| must be lower-cased.
 // https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#rfc.section.4.1
 bool IsStatefulRequestHeader(base::StringPiece name) {
+  DCHECK_EQ(name, base::ToLowerASCII(name));
+
   const char* const kStatefulRequestHeaders[] = {
       "authorization", "cookie", "cookie2", "proxy-authorization",
       "sec-webSocket-key"};
 
-  std::string lower_name(base::ToLowerASCII(name));
   for (const char* field : kStatefulRequestHeaders) {
-    if (lower_name == field)
+    if (name == field)
       return true;
   }
   return false;
 }
 
 bool IsStatefulResponseHeader(base::StringPiece name) {
+  DCHECK_EQ(name, base::ToLowerASCII(name));
+
   const char* const kStatefulResponseHeaders[] = {
       "authentication-control",
       "authentication-info",
@@ -48,9 +52,8 @@
       "www-authenticate",
   };
 
-  std::string lower_name(base::ToLowerASCII(name));
   for (const char* field : kStatefulResponseHeaders) {
-    if (lower_name == field)
+    if (name == field)
       return true;
   }
   return false;
@@ -108,8 +111,18 @@
       return false;
     }
     base::StringPiece name_str = it.first.GetBytestringAsString();
-    if (name_str == kStatusKey)
+    if (name_str == kUrlKey || name_str == kMethodKey)
       continue;
+
+    // TODO(kouhei): Add spec ref here once
+    // https://github.com/WICG/webpackage/issues/161 is resolved.
+    if (name_str != base::ToLowerASCII(name_str)) {
+      TRACE_EVENT_END2(TRACE_DISABLED_BY_DEFAULT("loading"), "ParseRequestMap",
+                       "error", "Request header name should be lower-cased.",
+                       "header_name", name_str.as_string());
+      return false;
+    }
+
     // 4. If exchange’s headers contain a stateful header field, as defined in
     // Section 4.1, return “invalid”. [spec text]
     if (IsStatefulRequestHeader(name_str)) {
@@ -167,6 +180,16 @@
                        name_str.as_string());
       return false;
     }
+
+    // TODO(kouhei): Add spec ref here once
+    // https://github.com/WICG/webpackage/issues/161 is resolved.
+    if (name_str != base::ToLowerASCII(name_str)) {
+      TRACE_EVENT_END2(TRACE_DISABLED_BY_DEFAULT("loading"), "ParseResponseMap",
+                       "error", "Response header name should be lower-cased.",
+                       "header_name", name_str.as_string());
+      return false;
+    }
+
     // 4. If exchange’s headers contain a stateful header field, as defined in
     // Section 4.1, return “invalid”. [spec text]
     if (IsStatefulResponseHeader(name_str)) {
@@ -182,7 +205,12 @@
                        "error", "Invalid header value.");
       return false;
     }
-    out->AddResponseHeader(name_str, value_str);
+    if (!out->AddResponseHeader(name_str, value_str)) {
+      TRACE_EVENT_END2(TRACE_DISABLED_BY_DEFAULT("loading"), "ParseResponseMap",
+                       "error", "Duplicate header value.", "header_name",
+                       name_str.as_string());
+      return false;
+    }
   }
 
   TRACE_EVENT_END0(TRACE_DISABLED_BY_DEFAULT("loading"), "ParseResponseMap");
@@ -281,13 +309,16 @@
 SignedExchangeHeader& SignedExchangeHeader::operator=(SignedExchangeHeader&&) =
     default;
 
-void SignedExchangeHeader::AddResponseHeader(base::StringPiece name,
+bool SignedExchangeHeader::AddResponseHeader(base::StringPiece name,
                                              base::StringPiece value) {
-  std::string name_string;
-  std::string value_string;
-  name.CopyToString(&name_string);
-  value.CopyToString(&value_string);
-  response_headers_[name_string] = value_string;
+  std::string name_str = name.as_string();
+  DCHECK_EQ(name_str, base::ToLowerASCII(name))
+      << "Response header names should be always lower-cased.";
+  if (response_headers_.find(name_str) != response_headers_.end())
+    return false;
+
+  response_headers_.emplace(std::move(name_str), value.as_string());
+  return true;
 }
 
 scoped_refptr<net::HttpResponseHeaders>
diff --git a/content/browser/web_package/signed_exchange_header.h b/content/browser/web_package/signed_exchange_header.h
index 43671ed..1e608fb 100644
--- a/content/browser/web_package/signed_exchange_header.h
+++ b/content/browser/web_package/signed_exchange_header.h
@@ -11,6 +11,7 @@
 #include "base/containers/span.h"
 #include "base/optional.h"
 #include "base/strings/string_piece.h"
+#include "base/strings/string_util.h"
 #include "content/browser/web_package/signed_exchange_header_parser.h"
 #include "content/common/content_export.h"
 #include "net/http/http_response_headers.h"
@@ -31,18 +32,10 @@
   // |kEncodedHeaderLengthInBytes|.
   static size_t ParseHeadersLength(base::span<const uint8_t> input);
 
-  // Parse headers from the new serialization format currently being discussed.
-  // 1. The first 3 bytes of the content represents the length of the CBOR
-  // encoded section, encoded in network byte (big-endian) order. 2. Then,
-  // immediately follows a CBOR-encoded array containing 2 elements: (This is
-  // derived from the section 5 of the old spec) - a map of request header field
-  // names to values, encoded as byte strings, with ":method", and ":url" pseudo
-  // header fields - a map from response header field names to values, encoded
-  // as byte strings, with a ":status" pseudo-header field containing the status
-  // code (encoded as 3 ASCII letter byte string) 3. Then, immediately follows
-  // the response body, encoded in MI.
-  // TODO(kouhei): Replace above with spec reference when we actually have spec
-  // text.
+  using HeaderMap = std::map<std::string, std::string>;
+
+  // Parse headers from the application/signed-exchange;v=b0 format.
+  // https://wicg.github.io/webpackage/draft-yasskin-httpbis-origin-signed-exchanges-impl.html#rfc.section.5.3
   //
   // This also performs the step 3 and 4 of "Cross-origin trust" validation.
   // https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#rfc.section.4
@@ -54,7 +47,9 @@
   SignedExchangeHeader& operator=(SignedExchangeHeader&&);
   ~SignedExchangeHeader();
 
-  void AddResponseHeader(base::StringPiece name, base::StringPiece value);
+  // AddResponseHeader returns false on duplicated keys. |name| must be
+  // lower-cased.
+  bool AddResponseHeader(base::StringPiece name, base::StringPiece value);
   scoped_refptr<net::HttpResponseHeaders> BuildHttpResponseHeaders() const;
 
   const GURL& request_url() const { return request_url_; };
@@ -68,9 +63,7 @@
   net::HttpStatusCode response_code() const { return response_code_; }
   void set_response_code(net::HttpStatusCode c) { response_code_ = c; }
 
-  const std::map<std::string, std::string>& response_headers() const {
-    return response_headers_;
-  }
+  const HeaderMap& response_headers() const { return response_headers_; }
 
   const SignedExchangeHeaderParser::Signature& signature() const {
     return signature_;
@@ -85,7 +78,7 @@
   std::string request_method_;
 
   net::HttpStatusCode response_code_;
-  std::map<std::string, std::string> response_headers_;
+  HeaderMap response_headers_;
   SignedExchangeHeaderParser::Signature signature_;
 };
 
diff --git a/content/browser/web_package/signed_exchange_header_unittest.cc b/content/browser/web_package/signed_exchange_header_unittest.cc
index 4d3f193..d18b13d 100644
--- a/content/browser/web_package/signed_exchange_header_unittest.cc
+++ b/content/browser/web_package/signed_exchange_header_unittest.cc
@@ -72,7 +72,7 @@
   base::FilePath test_htxg_path;
   PathService::Get(content::DIR_TEST_DATA, &test_htxg_path);
   test_htxg_path = test_htxg_path.AppendASCII("htxg").AppendASCII(
-      "signed_exchange_header_test.htxg");
+      "test.example.org_test.htxg");
 
   std::string contents;
   ASSERT_TRUE(base::ReadFileToString(test_htxg_path, &contents));
@@ -93,7 +93,7 @@
   EXPECT_EQ(header->request_url(), GURL("https://test.example.org/test/"));
   EXPECT_EQ(header->request_method(), "GET");
   EXPECT_EQ(header->response_code(), static_cast<net::HttpStatusCode>(200u));
-  EXPECT_EQ(header->response_headers().size(), 5u);
+  EXPECT_EQ(header->response_headers().size(), 4u);
   EXPECT_EQ(header->response_headers().find("content-encoding")->second,
             "mi-sha256");
 }
@@ -129,7 +129,7 @@
       {
           {kUrlKey, "https://test.example.org/test/"},
           {kMethodKey, "GET"},
-          {"Authorization", "Basic Zm9vOmJhcg=="},
+          {"authorization", "Basic Zm9vOmJhcg=="},
       },
       {
           {kStatusKey, "200"}, {kSignature, kSignatureString},
@@ -145,9 +145,31 @@
       {
           {kStatusKey, "200"},
           {kSignature, kSignatureString},
-          {"Set-Cookie", "foo=bar"},
+          {"set-cookie", "foo=bar"},
       });
   ASSERT_FALSE(header.has_value());
 }
 
+TEST(SignedExchangeHeaderTest, UppercaseRequestMap) {
+  auto header = GenerateHeaderAndParse(
+      {{kUrlKey, "https://test.example.org/test/"},
+       {kMethodKey, "GET"},
+       {"Accept-Language", "en-us"}},
+      {
+          {kStatusKey, "200"}, {kSignature, kSignatureString},
+      });
+  ASSERT_FALSE(header.has_value());
+}
+
+TEST(SignedExchangeHeaderTest, UppercaseResponseMap) {
+  auto header = GenerateHeaderAndParse(
+      {
+          {kUrlKey, "https://test.example.org/test/"}, {kMethodKey, "GET"},
+      },
+      {{kStatusKey, "200"},
+       {kSignature, kSignatureString},
+       {"Content-Length", "123"}});
+  ASSERT_FALSE(header.has_value());
+}
+
 }  // namespace content
diff --git a/content/browser/web_package/web_package_request_handler.h b/content/browser/web_package/web_package_request_handler.h
index f0819b46b7..753653da 100644
--- a/content/browser/web_package/web_package_request_handler.h
+++ b/content/browser/web_package/web_package_request_handler.h
@@ -6,7 +6,7 @@
 #define CONTENT_BROWSER_WEB_PACKAGE_WEB_PACKAGE_REQUEST_HANDLER_H_
 
 #include "base/memory/weak_ptr.h"
-#include "content/browser/loader/url_loader_request_handler.h"
+#include "content/browser/loader/navigation_loader_interceptor.h"
 #include "content/public/common/resource_type.h"
 #include "url/origin.h"
 
@@ -23,7 +23,7 @@
 class URLLoaderThrottle;
 class WebPackageLoader;
 
-class WebPackageRequestHandler final : public URLLoaderRequestHandler {
+class WebPackageRequestHandler final : public NavigationLoaderInterceptor {
  public:
   using URLLoaderThrottlesGetter = base::RepeatingCallback<
       std::vector<std::unique_ptr<content::URLLoaderThrottle>>()>;
@@ -38,7 +38,7 @@
       scoped_refptr<net::URLRequestContextGetter> request_context_getter);
   ~WebPackageRequestHandler() override;
 
-  // URLLoaderRequestHandler implementation
+  // NavigationLoaderInterceptor implementation
   void MaybeCreateLoader(const network::ResourceRequest& resource_request,
                          ResourceContext* resource_context,
                          LoaderCallback callback) override;
diff --git a/content/browser/web_package/web_package_request_handler_browsertest.cc b/content/browser/web_package/web_package_request_handler_browsertest.cc
index 1fcdc09..038e49d 100644
--- a/content/browser/web_package/web_package_request_handler_browsertest.cc
+++ b/content/browser/web_package/web_package_request_handler_browsertest.cc
@@ -39,7 +39,7 @@
 
 namespace {
 
-const uint64_t kSignatureHeaderDate = 1520834000;
+const uint64_t kSignatureHeaderDate = 1520834000;  // 2018-03-12T05:53:20Z
 
 const char* kMockHeaderFileSuffix = ".mock-http-headers";
 
diff --git a/content/browser/webauth/authenticator_impl.cc b/content/browser/webauth/authenticator_impl.cc
index ab49fcd5..e834618b 100644
--- a/content/browser/webauth/authenticator_impl.cc
+++ b/content/browser/webauth/authenticator_impl.cc
@@ -23,7 +23,6 @@
 #include "crypto/sha2.h"
 #include "device/fido/u2f_register.h"
 #include "device/fido/u2f_request.h"
-#include "device/fido/u2f_return_code.h"
 #include "device/fido/u2f_sign.h"
 #include "device/fido/u2f_transport_protocol.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
@@ -230,13 +229,14 @@
 }
 
 webauth::mojom::MakeCredentialAuthenticatorResponsePtr
-CreateMakeCredentialResponse(const std::string& client_data_json,
-                             device::RegisterResponseData response_data) {
+CreateMakeCredentialResponse(
+    const std::string& client_data_json,
+    device::AuthenticatorMakeCredentialResponse response_data) {
   auto response = webauth::mojom::MakeCredentialAuthenticatorResponse::New();
   auto common_info = webauth::mojom::CommonCredentialInfo::New();
   common_info->client_data_json.assign(client_data_json.begin(),
                                        client_data_json.end());
-  common_info->raw_id = response_data.raw_id();
+  common_info->raw_id = response_data.raw_credential_id();
   common_info->id = response_data.GetId();
   response->info = std::move(common_info);
   response->attestation_object =
@@ -246,19 +246,22 @@
 
 webauth::mojom::GetAssertionAuthenticatorResponsePtr CreateGetAssertionResponse(
     const std::string& client_data_json,
-    device::SignResponseData response_data,
+    device::AuthenticatorGetAssertionResponse response_data,
     bool echo_appid_extension) {
   auto response = webauth::mojom::GetAssertionAuthenticatorResponse::New();
   auto common_info = webauth::mojom::CommonCredentialInfo::New();
   common_info->client_data_json.assign(client_data_json.begin(),
                                        client_data_json.end());
-  common_info->raw_id = response_data.raw_id();
+  common_info->raw_id = response_data.raw_credential_id();
   common_info->id = response_data.GetId();
   response->info = std::move(common_info);
-  response->authenticator_data = response_data.GetAuthenticatorDataBytes();
+  response->authenticator_data =
+      response_data.auth_data().SerializeToByteArray();
   response->signature = response_data.signature();
-  response->user_handle.emplace();
   response->echo_appid_extension = echo_appid_extension;
+  response_data.user_entity()
+      ? response->user_handle.emplace(response_data.user_entity()->user_id())
+      : response->user_handle.emplace();
   return response;
 }
 
@@ -529,14 +532,14 @@
 
 // Callback to handle the async registration response from a U2fDevice.
 void AuthenticatorImpl::OnRegisterResponse(
-    device::U2fReturnCode status_code,
-    base::Optional<device::RegisterResponseData> response_data) {
+    device::FidoReturnCode status_code,
+    base::Optional<device::AuthenticatorMakeCredentialResponse> response_data) {
   // If callback is called immediately, this code will call |Cleanup| before
   // |u2f_request_| has been assigned – violating invariants.
   DCHECK(u2f_request_) << "unsupported callback hairpin";
 
   switch (status_code) {
-    case device::U2fReturnCode::CONDITIONS_NOT_SATISFIED:
+    case device::FidoReturnCode::kConditionsNotSatisfied:
       // Duplicate registration: the new credential would be created on an
       // authenticator that already contains one of the credentials in
       // |exclude_credentials|.
@@ -544,16 +547,16 @@
           std::move(make_credential_response_callback_),
           webauth::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR, nullptr);
       return;
-    case device::U2fReturnCode::FAILURE:
+    case device::FidoReturnCode::kFailure:
       // The response from the authenticator was corrupted.
       InvokeCallbackAndCleanup(
           std::move(make_credential_response_callback_),
           webauth::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR, nullptr);
       return;
-    case device::U2fReturnCode::INVALID_PARAMS:
+    case device::FidoReturnCode::kInvalidParams:
       NOTREACHED();
       return;
-    case device::U2fReturnCode::SUCCESS:
+    case device::FidoReturnCode::kSuccess:
       DCHECK(response_data.has_value());
 
       if (attestation_preference_ !=
@@ -581,7 +584,7 @@
 }
 
 void AuthenticatorImpl::OnRegisterResponseAttestationDecided(
-    device::RegisterResponseData response_data,
+    device::AuthenticatorMakeCredentialResponse response_data,
     bool attestation_permitted) {
   DCHECK(attestation_preference_ !=
          webauth::mojom::AttestationConveyancePreference::NONE);
@@ -591,39 +594,62 @@
     // timeout run out.
     // See https://w3c.github.io/webauthn/#sec-assertion-privacy.
     return;
-  } else {
-    InvokeCallbackAndCleanup(
-        std::move(make_credential_response_callback_),
-        webauth::mojom::AuthenticatorStatus::SUCCESS,
-        CreateMakeCredentialResponse(std::move(client_data_json_),
-                                     std::move(response_data)));
   }
+
+  // The check for IsAttestationCertificateInappropriatelyIdentifying is
+  // performed after the permissions prompt, even though we know the answer
+  // before, because this still effectively discloses the make & model of the
+  // authenticator: If an RP sees a "none" attestation from Chrome after
+  // requesting direct attestation then it knows that it was one of the tokens
+  // with inappropriate certs.
+  if (response_data.IsAttestationCertificateInappropriatelyIdentifying() &&
+      !GetContentClient()
+           ->browser()
+           ->ShouldPermitIndividualAttestationForWebauthnRPID(
+               render_frame_host_->GetProcess()->GetBrowserContext(),
+               relying_party_id_)) {
+    // The attestation response is incorrectly individually identifiable, but
+    // the consent is for make & model information about a token, not for
+    // individually-identifiable information. Erase the attestation to stop it
+    // begin a tracking signal.
+
+    // The only way to get the underlying attestation will be to list the RP ID
+    // in the enterprise policy, because that enables the individual attestation
+    // bit in the register request and permits individual attestation generally.
+    response_data.EraseAttestationStatement();
+  }
+
+  InvokeCallbackAndCleanup(
+      std::move(make_credential_response_callback_),
+      webauth::mojom::AuthenticatorStatus::SUCCESS,
+      CreateMakeCredentialResponse(std::move(client_data_json_),
+                                   std::move(response_data)));
 }
 
 void AuthenticatorImpl::OnSignResponse(
-    device::U2fReturnCode status_code,
-    base::Optional<device::SignResponseData> response_data) {
+    device::FidoReturnCode status_code,
+    base::Optional<device::AuthenticatorGetAssertionResponse> response_data) {
   // If callback is called immediately, this code will call |Cleanup| before
   // |u2f_request_| has been assigned – violating invariants.
   DCHECK(u2f_request_) << "unsupported callback hairpin";
 
   switch (status_code) {
-    case device::U2fReturnCode::CONDITIONS_NOT_SATISFIED:
+    case device::FidoReturnCode::kConditionsNotSatisfied:
       // No authenticators contained the credential.
       InvokeCallbackAndCleanup(
           std::move(get_assertion_response_callback_),
           webauth::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR, nullptr);
       return;
-    case device::U2fReturnCode::FAILURE:
+    case device::FidoReturnCode::kFailure:
       // The response from the authenticator was corrupted.
       InvokeCallbackAndCleanup(
           std::move(make_credential_response_callback_),
           webauth::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR, nullptr);
       return;
-    case device::U2fReturnCode::INVALID_PARAMS:
+    case device::FidoReturnCode::kInvalidParams:
       NOTREACHED();
       return;
-    case device::U2fReturnCode::SUCCESS:
+    case device::FidoReturnCode::kSuccess:
       DCHECK(response_data.has_value());
       InvokeCallbackAndCleanup(
           std::move(get_assertion_response_callback_),
diff --git a/content/browser/webauth/authenticator_impl.h b/content/browser/webauth/authenticator_impl.h
index c372fb59..e2fbcdf 100644
--- a/content/browser/webauth/authenticator_impl.h
+++ b/content/browser/webauth/authenticator_impl.h
@@ -15,8 +15,9 @@
 #include "base/macros.h"
 #include "base/optional.h"
 #include "content/common/content_export.h"
-#include "device/fido/register_response_data.h"
-#include "device/fido/sign_response_data.h"
+#include "device/fido/authenticator_get_assertion_response.h"
+#include "device/fido/authenticator_make_credential_response.h"
+#include "device/fido/fido_constants.h"
 #include "device/fido/u2f_transport_protocol.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "third_party/WebKit/public/platform/modules/webauth/authenticator.mojom.h"
@@ -28,7 +29,7 @@
 
 namespace device {
 class U2fRequest;
-enum class U2fReturnCode : uint8_t;
+enum class FidoReturnCode : uint8_t;
 }  // namespace device
 
 namespace service_manager {
@@ -92,18 +93,20 @@
 
   // Callback to handle the async response from a U2fDevice.
   void OnRegisterResponse(
-      device::U2fReturnCode status_code,
-      base::Optional<device::RegisterResponseData> response_data);
+      device::FidoReturnCode status_code,
+      base::Optional<device::AuthenticatorMakeCredentialResponse>
+          response_data);
 
   // Callback to complete the registration process once a decision about
   // whether or not to return attestation data has been made.
   void OnRegisterResponseAttestationDecided(
-      device::RegisterResponseData response_data,
+      device::AuthenticatorMakeCredentialResponse response_data,
       bool attestation_permitted);
 
   // Callback to handle the async response from a U2fDevice.
-  void OnSignResponse(device::U2fReturnCode status_code,
-                      base::Optional<device::SignResponseData> response_data);
+  void OnSignResponse(
+      device::FidoReturnCode status_code,
+      base::Optional<device::AuthenticatorGetAssertionResponse> response_data);
 
   // Runs when timer expires and cancels all issued requests to a U2fDevice.
   void OnTimeout();
diff --git a/content/browser/webauth/authenticator_impl_unittest.cc b/content/browser/webauth/authenticator_impl_unittest.cc
index 7bc9be0..334072a1 100644
--- a/content/browser/webauth/authenticator_impl_unittest.cc
+++ b/content/browser/webauth/authenticator_impl_unittest.cc
@@ -22,7 +22,7 @@
 #include "content/public/test/test_service_manager_context.h"
 #include "content/test/test_render_frame_host.h"
 #include "device/fido/fake_hid_impl_for_testing.h"
-#include "device/fido/scoped_virtual_u2f_device.h"
+#include "device/fido/scoped_virtual_fido_device.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -613,7 +613,7 @@
 // Verify behavior for various combinations of origins and RP IDs.
 TEST_F(AuthenticatorImplTest, AppIdExtension) {
   TestServiceManagerContext smc;
-  device::test::ScopedVirtualU2fDevice virtual_device;
+  device::test::ScopedVirtualFidoDevice virtual_device;
 
   for (const auto& test_case : kAppIdCases) {
     SCOPED_TRACE(std::string(test_case.origin) + " " +
@@ -676,8 +676,6 @@
   EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, cb.GetResponseStatus());
 }
 
-namespace {
-
 enum class IndividualAttestation {
   REQUESTED,
   NOT_REQUESTED,
@@ -712,11 +710,21 @@
 };
 
 // A test class that installs and removes an
-// |AuthenticatorTestContentBrowserClient| automatically.
+// |AuthenticatorTestContentBrowserClient| automatically and can run tests
+// against simulated attestation results.
 class AuthenticatorContentBrowserClientTest : public AuthenticatorImplTest {
  public:
   AuthenticatorContentBrowserClientTest() = default;
 
+  struct TestCase {
+    AttestationConveyancePreference attestation_requested;
+    IndividualAttestation individual_attestation;
+    AttestationConsent attestation_consent;
+    AuthenticatorStatus expected_status;
+    const char* expected_attestation_format;
+    const char* expected_certificate_substring;
+  };
+
   void SetUp() override {
     AuthenticatorImplTest::SetUp();
     old_client_ = SetBrowserClientForTesting(&test_client_);
@@ -727,79 +735,122 @@
     AuthenticatorImplTest::TearDown();
   }
 
+  void RunTestCases(const std::vector<TestCase>& tests) {
+    TestServiceManagerContext smc_;
+    AuthenticatorPtr authenticator = ConnectToAuthenticator();
+
+    for (size_t i = 0; i < tests.size(); i++) {
+      const auto& test = tests[i];
+      SCOPED_TRACE(test.attestation_consent == AttestationConsent::GRANTED
+                       ? "consent granted"
+                       : "consent denied");
+      SCOPED_TRACE(test.individual_attestation ==
+                           IndividualAttestation::REQUESTED
+                       ? "individual attestation"
+                       : "no individual attestation");
+      SCOPED_TRACE(
+          AttestationConveyancePreferenceToString(test.attestation_requested));
+      SCOPED_TRACE(i);
+
+      test_client_.individual_attestation = test.individual_attestation;
+      test_client_.attestation_consent = test.attestation_consent;
+
+      PublicKeyCredentialCreationOptionsPtr options =
+          GetTestPublicKeyCredentialCreationOptions();
+      options->relying_party->id = "example.com";
+      options->adjusted_timeout = base::TimeDelta::FromSeconds(1);
+      options->attestation = test.attestation_requested;
+      TestMakeCredentialCallback cb;
+      authenticator->MakeCredential(std::move(options), cb.callback());
+      cb.WaitForCallback();
+      ASSERT_EQ(test.expected_status, cb.GetResponseStatus());
+
+      if (test.expected_status != AuthenticatorStatus::SUCCESS) {
+        ASSERT_STREQ("", test.expected_attestation_format);
+        continue;
+      }
+
+      base::Optional<CBORValue> attestation_value =
+          CBORReader::Read(cb.response()->attestation_object);
+      ASSERT_TRUE(attestation_value);
+      ASSERT_TRUE(attestation_value->is_map());
+      const auto& attestation = attestation_value->GetMap();
+      ExpectMapHasKeyWithStringValue(attestation, "fmt",
+                                     test.expected_attestation_format);
+      if (strlen(test.expected_certificate_substring) > 0) {
+        ExpectCertificateContainingSubstring(
+            attestation, test.expected_certificate_substring);
+      }
+    }
+  }
+
  protected:
   AuthenticatorTestContentBrowserClient test_client_;
+  device::test::ScopedVirtualFidoDevice virtual_device_;
 
  private:
+  static const char* AttestationConveyancePreferenceToString(
+      AttestationConveyancePreference v) {
+    switch (v) {
+      case AttestationConveyancePreference::NONE:
+        return "none";
+      case AttestationConveyancePreference::INDIRECT:
+        return "indirect";
+      case AttestationConveyancePreference::DIRECT:
+        return "direct";
+      default:
+        NOTREACHED();
+        return "";
+    }
+  }
+
+  // Expects that |map| contains the given key with a string-value equal to
+  // |expected|.
+  static void ExpectMapHasKeyWithStringValue(const CBORValue::MapValue& map,
+                                             const char* key,
+                                             const char* expected) {
+    const auto it = map.find(CBORValue(key));
+    ASSERT_TRUE(it != map.end()) << "No such key '" << key << "'";
+    const auto& value = it->second;
+    EXPECT_TRUE(value.is_string())
+        << "Value of '" << key << "' has type "
+        << static_cast<int>(value.type()) << ", but expected to find a string";
+    EXPECT_EQ(std::string(expected), value.GetString())
+        << "Value of '" << key << "' is '" << value.GetString()
+        << "', but expected to find '" << expected << "'";
+  }
+
+  // Asserts that the webauthn attestation CBOR map in |attestation| contains
+  // a single X.509 certificate containing |substring|.
+  static void ExpectCertificateContainingSubstring(
+      const CBORValue::MapValue& attestation,
+      const std::string& substring) {
+    const auto& attestation_statement_it =
+        attestation.find(CBORValue("attStmt"));
+    ASSERT_TRUE(attestation_statement_it != attestation.end());
+    ASSERT_TRUE(attestation_statement_it->second.is_map());
+    const auto& attestation_statement =
+        attestation_statement_it->second.GetMap();
+    const auto& x5c_it = attestation_statement.find(CBORValue("x5c"));
+    ASSERT_TRUE(x5c_it != attestation_statement.end());
+    ASSERT_TRUE(x5c_it->second.is_array());
+    const auto& x5c = x5c_it->second.GetArray();
+    ASSERT_EQ(1u, x5c.size());
+    ASSERT_TRUE(x5c[0].is_bytestring());
+    base::StringPiece cert = x5c[0].GetBytestringAsString();
+    EXPECT_TRUE(cert.find(substring) != cert.npos);
+  }
+
   ContentBrowserClient* old_client_ = nullptr;
 
   DISALLOW_COPY_AND_ASSIGN(AuthenticatorContentBrowserClientTest);
 };
 
-const char* AttestationConveyancePreferenceToString(
-    AttestationConveyancePreference v) {
-  switch (v) {
-    case AttestationConveyancePreference::NONE:
-      return "none";
-    case AttestationConveyancePreference::INDIRECT:
-      return "indirect";
-    case AttestationConveyancePreference::DIRECT:
-      return "direct";
-    default:
-      NOTREACHED();
-      return "";
-  }
-}
-
-// Expects that |map| contains the given key with a string-value equal to
-// |expected|.
-void ExpectMapHasKeyWithStringValue(const CBORValue::MapValue& map,
-                                    const char* key,
-                                    const char* expected) {
-  const auto it = map.find(CBORValue(key));
-  ASSERT_TRUE(it != map.end()) << "No such key '" << key << "'";
-  const auto& value = it->second;
-  EXPECT_TRUE(value.is_string())
-      << "Value of '" << key << "' has type " << static_cast<int>(value.type())
-      << ", but expected to find a string";
-  EXPECT_EQ(std::string(expected), value.GetString())
-      << "Value of '" << key << "' is '" << value.GetString()
-      << "', but expected to find '" << expected << "'";
-}
-
-// Asserts that the webauthn attestation CBOR map in |attestation| contains a
-// single X.509 certificate containing |substring|.
-void ExpectCertificateContainingSubstring(
-    const CBORValue::MapValue& attestation,
-    const std::string& substring) {
-  const auto& attestation_statement_it = attestation.find(CBORValue("attStmt"));
-  ASSERT_TRUE(attestation_statement_it != attestation.end());
-  ASSERT_TRUE(attestation_statement_it->second.is_map());
-  const auto& attestation_statement = attestation_statement_it->second.GetMap();
-  const auto& x5c_it = attestation_statement.find(CBORValue("x5c"));
-  ASSERT_TRUE(x5c_it != attestation_statement.end());
-  ASSERT_TRUE(x5c_it->second.is_array());
-  const auto& x5c = x5c_it->second.GetArray();
-  ASSERT_EQ(1u, x5c.size());
-  ASSERT_TRUE(x5c[0].is_bytestring());
-  base::StringPiece cert = x5c[0].GetBytestringAsString();
-  EXPECT_TRUE(cert.find(substring) != cert.npos);
-}
-
-}  // anonymous namespace
-
 TEST_F(AuthenticatorContentBrowserClientTest, AttestationBehaviour) {
   const char kStandardCommonName[] = "U2F Attestation";
   const char kIndividualCommonName[] = "Individual Cert";
 
-  const struct {
-    AttestationConveyancePreference attestation_requested;
-    IndividualAttestation individual_attestation;
-    AttestationConsent attestation_consent;
-    AuthenticatorStatus expected_status;
-    const char* expected_attestation_format;
-    const char* expected_certificate_substring;
-  } kTests[] = {
+  const std::vector<TestCase> kTests = {
       {
           AttestationConveyancePreference::NONE,
           IndividualAttestation::NOT_REQUESTED, AttestationConsent::DENIED,
@@ -852,56 +903,49 @@
       },
   };
 
-  TestServiceManagerContext smc;
-  device::test::ScopedVirtualU2fDevice virtual_device;
-  virtual_device.mutable_state()->attestation_cert_common_name =
+  virtual_device_.mutable_state()->attestation_cert_common_name =
       kStandardCommonName;
-  virtual_device.mutable_state()->individual_attestation_cert_common_name =
+  virtual_device_.mutable_state()->individual_attestation_cert_common_name =
       kIndividualCommonName;
   NavigateAndCommit(GURL("https://example.com"));
-  AuthenticatorPtr authenticator = ConnectToAuthenticator();
 
-  for (size_t i = 0; i < arraysize(kTests); i++) {
-    const auto& test = kTests[i];
-    SCOPED_TRACE(test.attestation_consent == AttestationConsent::GRANTED
-                     ? "consent granted"
-                     : "consent denied");
-    SCOPED_TRACE(test.individual_attestation == IndividualAttestation::REQUESTED
-                     ? "individual attestation"
-                     : "no individual attestation");
-    SCOPED_TRACE(
-        AttestationConveyancePreferenceToString(test.attestation_requested));
+  RunTestCases(kTests);
+}
 
-    test_client_.individual_attestation = test.individual_attestation;
-    test_client_.attestation_consent = test.attestation_consent;
+TEST_F(AuthenticatorContentBrowserClientTest,
+       InappropriatelyIdentifyingAttestation) {
+  // This common name is used by several devices that have inappropriately
+  // identifying attestation certificates.
+  const char kCommonName[] = "FT FIDO 0100";
 
-    PublicKeyCredentialCreationOptionsPtr options =
-        GetTestPublicKeyCredentialCreationOptions();
-    options->relying_party->id = "example.com";
-    options->adjusted_timeout = base::TimeDelta::FromSeconds(1);
-    options->attestation = test.attestation_requested;
-    TestMakeCredentialCallback cb;
-    authenticator->MakeCredential(std::move(options), cb.callback());
-    cb.WaitForCallback();
-    ASSERT_EQ(test.expected_status, cb.GetResponseStatus());
+  const std::vector<TestCase> kTests = {
+      {
+          AttestationConveyancePreference::DIRECT,
+          IndividualAttestation::NOT_REQUESTED, AttestationConsent::DENIED,
+          AuthenticatorStatus::NOT_ALLOWED_ERROR, "", "",
+      },
+      {
+          AttestationConveyancePreference::DIRECT,
+          IndividualAttestation::NOT_REQUESTED, AttestationConsent::GRANTED,
+          AuthenticatorStatus::SUCCESS,
+          // If individual attestation was not requested then the attestation
+          // certificate will be removed, even if consent is given, because
+          // the consent isn't to be tracked.
+          "none", "",
+      },
+      {
+          AttestationConveyancePreference::DIRECT,
+          IndividualAttestation::REQUESTED, AttestationConsent::GRANTED,
+          AuthenticatorStatus::SUCCESS, "fido-u2f", kCommonName,
+      },
+  };
 
-    if (test.expected_status != AuthenticatorStatus::SUCCESS) {
-      ASSERT_STREQ("", test.expected_attestation_format);
-      continue;
-    }
+  virtual_device_.mutable_state()->attestation_cert_common_name = kCommonName;
+  virtual_device_.mutable_state()->individual_attestation_cert_common_name =
+      kCommonName;
+  NavigateAndCommit(GURL("https://example.com"));
 
-    base::Optional<CBORValue> attestation_value =
-        CBORReader::Read(cb.response()->attestation_object);
-    ASSERT_TRUE(attestation_value);
-    ASSERT_TRUE(attestation_value->is_map());
-    const auto& attestation = attestation_value->GetMap();
-    ExpectMapHasKeyWithStringValue(attestation, "fmt",
-                                   test.expected_attestation_format);
-    if (strlen(test.expected_certificate_substring) > 0) {
-      ExpectCertificateContainingSubstring(attestation,
-                                           test.expected_certificate_substring);
-    }
-  }
+  RunTestCases(kTests);
 }
 
 }  // namespace content
diff --git a/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc b/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc
index f12dfb7..d4d59b8c 100644
--- a/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc
+++ b/content/browser/webrtc/webrtc_capture_from_element_browsertest.cc
@@ -10,7 +10,7 @@
 #include "content/shell/common/shell_switches.h"
 #include "media/base/media_switches.h"
 #include "media/base/test_data_util.h"
-#include "media/mojo/features.h"
+#include "media/mojo/buildflags.h"
 
 #if defined(OS_ANDROID)
 #include "base/android/build_info.h"
diff --git a/content/browser/webrtc/webrtc_internals.cc b/content/browser/webrtc/webrtc_internals.cc
index dac13223..a6c18ff3 100644
--- a/content/browser/webrtc/webrtc_internals.cc
+++ b/content/browser/webrtc/webrtc_internals.cc
@@ -25,7 +25,7 @@
 #include "ipc/ipc_platform_file.h"
 #include "media/audio/audio_debug_recording_session.h"
 #include "media/audio/audio_manager.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "services/audio/public/cpp/debug_recording_session_factory.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/device/public/mojom/wake_lock_provider.mojom.h"
diff --git a/content/browser/webrtc/webrtc_internals.h b/content/browser/webrtc/webrtc_internals.h
index 043c0c4..04c8e2a2 100644
--- a/content/browser/webrtc/webrtc_internals.h
+++ b/content/browser/webrtc/webrtc_internals.h
@@ -18,7 +18,7 @@
 #include "base/values.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/render_process_host_observer.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "services/device/public/mojom/wake_lock.mojom.h"
 #include "ui/shell_dialogs/select_file_dialog.h"
 
diff --git a/content/browser/webrtc/webrtc_internals_message_handler.cc b/content/browser/webrtc/webrtc_internals_message_handler.cc
index 82c50d4c..9f6d4fde 100644
--- a/content/browser/webrtc/webrtc_internals_message_handler.cc
+++ b/content/browser/webrtc/webrtc_internals_message_handler.cc
@@ -30,35 +30,39 @@
 }
 
 void WebRTCInternalsMessageHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback("getAllStats",
-      base::Bind(&WebRTCInternalsMessageHandler::OnGetAllStats,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "getAllStats",
+      base::BindRepeating(&WebRTCInternalsMessageHandler::OnGetAllStats,
+                          base::Unretained(this)));
 
-  web_ui()->RegisterMessageCallback("enableAudioDebugRecordings",
-      base::Bind(
+  web_ui()->RegisterMessageCallback(
+      "enableAudioDebugRecordings",
+      base::BindRepeating(
           &WebRTCInternalsMessageHandler::OnSetAudioDebugRecordingsEnabled,
-          base::Unretained(this),
-          true));
+          base::Unretained(this), true));
 
-  web_ui()->RegisterMessageCallback("disableAudioDebugRecordings",
-      base::Bind(
+  web_ui()->RegisterMessageCallback(
+      "disableAudioDebugRecordings",
+      base::BindRepeating(
           &WebRTCInternalsMessageHandler::OnSetAudioDebugRecordingsEnabled,
-          base::Unretained(this),
-          false));
+          base::Unretained(this), false));
 
   web_ui()->RegisterMessageCallback(
       "enableEventLogRecordings",
-      base::Bind(&WebRTCInternalsMessageHandler::OnSetEventLogRecordingsEnabled,
-                 base::Unretained(this), true));
+      base::BindRepeating(
+          &WebRTCInternalsMessageHandler::OnSetEventLogRecordingsEnabled,
+          base::Unretained(this), true));
 
   web_ui()->RegisterMessageCallback(
       "disableEventLogRecordings",
-      base::Bind(&WebRTCInternalsMessageHandler::OnSetEventLogRecordingsEnabled,
-                 base::Unretained(this), false));
+      base::BindRepeating(
+          &WebRTCInternalsMessageHandler::OnSetEventLogRecordingsEnabled,
+          base::Unretained(this), false));
 
-  web_ui()->RegisterMessageCallback("finishedDOMLoad",
-      base::Bind(&WebRTCInternalsMessageHandler::OnDOMLoadDone,
-                 base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "finishedDOMLoad",
+      base::BindRepeating(&WebRTCInternalsMessageHandler::OnDOMLoadDone,
+                          base::Unretained(this)));
 }
 
 RenderFrameHost* WebRTCInternalsMessageHandler::GetWebRTCInternalsHost() const {
diff --git a/content/browser/websockets/README.md b/content/browser/websockets/README.md
index 6f77941..80f5e442 100644
--- a/content/browser/websockets/README.md
+++ b/content/browser/websockets/README.md
@@ -1,5 +1,5 @@
 # WebSocket service
 
-This directory contains the blink::mojom::WebSocket implementation. It hosts
+This directory contains the network::mojom::WebSocket implementation. It hosts
 the WebSocket API implementations in Blink over Mojo, and exports the WebSocket
 protocol implementation in net/websockets/ as a service.
diff --git a/content/browser/websockets/websocket_impl.cc b/content/browser/websockets/websocket_impl.cc
deleted file mode 100644
index 7fe3088..0000000
--- a/content/browser/websockets/websocket_impl.cc
+++ /dev/null
@@ -1,533 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/websockets/websocket_impl.h"
-
-#include <inttypes.h>
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "content/browser/bad_message.h"
-#include "content/browser/child_process_security_policy_impl.h"
-#include "content/browser/ssl/ssl_error_handler.h"
-#include "content/browser/ssl/ssl_manager.h"
-#include "content/browser/websockets/websocket_handshake_request_info_impl.h"
-#include "content/public/browser/storage_partition.h"
-#include "ipc/ipc_message.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/http/http_request_headers.h"
-#include "net/http/http_response_headers.h"
-#include "net/http/http_util.h"
-#include "net/ssl/ssl_info.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "net/websockets/websocket_channel.h"
-#include "net/websockets/websocket_errors.h"
-#include "net/websockets/websocket_event_interface.h"
-#include "net/websockets/websocket_frame.h"  // for WebSocketFrameHeader::OpCode
-#include "net/websockets/websocket_handshake_request_info.h"
-#include "net/websockets/websocket_handshake_response_info.h"
-
-namespace content {
-namespace {
-
-typedef net::WebSocketEventInterface::ChannelState ChannelState;
-
-// Convert a blink::mojom::WebSocketMessageType to a
-// net::WebSocketFrameHeader::OpCode
-net::WebSocketFrameHeader::OpCode MessageTypeToOpCode(
-    blink::mojom::WebSocketMessageType type) {
-  DCHECK(type == blink::mojom::WebSocketMessageType::CONTINUATION ||
-         type == blink::mojom::WebSocketMessageType::TEXT ||
-         type == blink::mojom::WebSocketMessageType::BINARY);
-  typedef net::WebSocketFrameHeader::OpCode OpCode;
-  // These compile asserts verify that the same underlying values are used for
-  // both types, so we can simply cast between them.
-  static_assert(
-      static_cast<OpCode>(blink::mojom::WebSocketMessageType::CONTINUATION) ==
-          net::WebSocketFrameHeader::kOpCodeContinuation,
-      "enum values must match for opcode continuation");
-  static_assert(
-      static_cast<OpCode>(blink::mojom::WebSocketMessageType::TEXT) ==
-          net::WebSocketFrameHeader::kOpCodeText,
-      "enum values must match for opcode text");
-  static_assert(
-      static_cast<OpCode>(blink::mojom::WebSocketMessageType::BINARY) ==
-          net::WebSocketFrameHeader::kOpCodeBinary,
-      "enum values must match for opcode binary");
-  return static_cast<OpCode>(type);
-}
-
-blink::mojom::WebSocketMessageType OpCodeToMessageType(
-    net::WebSocketFrameHeader::OpCode opCode) {
-  DCHECK(opCode == net::WebSocketFrameHeader::kOpCodeContinuation ||
-         opCode == net::WebSocketFrameHeader::kOpCodeText ||
-         opCode == net::WebSocketFrameHeader::kOpCodeBinary);
-  // This cast is guaranteed valid by the static_assert() statements above.
-  return static_cast<blink::mojom::WebSocketMessageType>(opCode);
-}
-
-}  // namespace
-
-// Implementation of net::WebSocketEventInterface. Receives events from our
-// WebSocketChannel object.
-class WebSocketImpl::WebSocketEventHandler final
-    : public net::WebSocketEventInterface {
- public:
-  explicit WebSocketEventHandler(WebSocketImpl* impl);
-  ~WebSocketEventHandler() override;
-
-  // net::WebSocketEventInterface implementation
-
-  void OnCreateURLRequest(net::URLRequest* url_request) override;
-  ChannelState OnAddChannelResponse(const std::string& selected_subprotocol,
-                                    const std::string& extensions) override;
-  ChannelState OnDataFrame(bool fin,
-                           WebSocketMessageType type,
-                           scoped_refptr<net::IOBuffer> buffer,
-                           size_t buffer_size) override;
-  ChannelState OnClosingHandshake() override;
-  ChannelState OnFlowControl(int64_t quota) override;
-  ChannelState OnDropChannel(bool was_clean,
-                             uint16_t code,
-                             const std::string& reason) override;
-  ChannelState OnFailChannel(const std::string& message) override;
-  ChannelState OnStartOpeningHandshake(
-      std::unique_ptr<net::WebSocketHandshakeRequestInfo> request) override;
-  ChannelState OnFinishOpeningHandshake(
-      std::unique_ptr<net::WebSocketHandshakeResponseInfo> response) override;
-  ChannelState OnSSLCertificateError(
-      std::unique_ptr<net::WebSocketEventInterface::SSLErrorCallbacks>
-          callbacks,
-      const GURL& url,
-      const net::SSLInfo& ssl_info,
-      bool fatal) override;
-
- private:
-  class SSLErrorHandlerDelegate final : public SSLErrorHandler::Delegate {
-   public:
-    SSLErrorHandlerDelegate(
-        std::unique_ptr<net::WebSocketEventInterface::SSLErrorCallbacks>
-            callbacks);
-    ~SSLErrorHandlerDelegate() override;
-
-    base::WeakPtr<SSLErrorHandler::Delegate> GetWeakPtr();
-
-    // SSLErrorHandler::Delegate methods
-    void CancelSSLRequest(int error, const net::SSLInfo* ssl_info) override;
-    void ContinueSSLRequest() override;
-
-   private:
-    std::unique_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks_;
-    base::WeakPtrFactory<SSLErrorHandlerDelegate> weak_ptr_factory_;
-
-    DISALLOW_COPY_AND_ASSIGN(SSLErrorHandlerDelegate);
-  };
-
-  WebSocketImpl* const impl_;
-  std::unique_ptr<SSLErrorHandlerDelegate> ssl_error_handler_delegate_;
-
-  DISALLOW_COPY_AND_ASSIGN(WebSocketEventHandler);
-};
-
-WebSocketImpl::WebSocketEventHandler::WebSocketEventHandler(WebSocketImpl* impl)
-    : impl_(impl) {
-  DVLOG(1) << "WebSocketEventHandler created @"
-           << reinterpret_cast<void*>(this);
-}
-
-WebSocketImpl::WebSocketEventHandler::~WebSocketEventHandler() {
-  DVLOG(1) << "WebSocketEventHandler destroyed @"
-           << reinterpret_cast<void*>(this);
-}
-
-void WebSocketImpl::WebSocketEventHandler::OnCreateURLRequest(
-    net::URLRequest* url_request) {
-  WebSocketHandshakeRequestInfoImpl::CreateInfoAndAssociateWithRequest(
-      impl_->child_id_, impl_->frame_id_, url_request);
-}
-
-ChannelState WebSocketImpl::WebSocketEventHandler::OnAddChannelResponse(
-    const std::string& selected_protocol,
-    const std::string& extensions) {
-  DVLOG(3) << "WebSocketEventHandler::OnAddChannelResponse @"
-           << reinterpret_cast<void*>(this)
-           << " selected_protocol=\"" << selected_protocol << "\""
-           << " extensions=\"" << extensions << "\"";
-
-  impl_->delegate_->OnReceivedResponseFromServer(impl_);
-
-  impl_->client_->OnAddChannelResponse(selected_protocol, extensions);
-
-  return net::WebSocketEventInterface::CHANNEL_ALIVE;
-}
-
-ChannelState WebSocketImpl::WebSocketEventHandler::OnDataFrame(
-    bool fin,
-    net::WebSocketFrameHeader::OpCode type,
-    scoped_refptr<net::IOBuffer> buffer,
-    size_t buffer_size) {
-  DVLOG(3) << "WebSocketEventHandler::OnDataFrame @"
-           << reinterpret_cast<void*>(this)
-           << " fin=" << fin
-           << " type=" << type << " data is " << buffer_size << " bytes";
-
-  // TODO(darin): Avoid this copy.
-  std::vector<uint8_t> data_to_pass(buffer_size);
-  if (buffer_size > 0) {
-    std::copy(buffer->data(), buffer->data() + buffer_size,
-              data_to_pass.begin());
-  }
-
-  impl_->client_->OnDataFrame(fin, OpCodeToMessageType(type), data_to_pass);
-
-  return net::WebSocketEventInterface::CHANNEL_ALIVE;
-}
-
-ChannelState WebSocketImpl::WebSocketEventHandler::OnClosingHandshake() {
-  DVLOG(3) << "WebSocketEventHandler::OnClosingHandshake @"
-           << reinterpret_cast<void*>(this);
-
-  impl_->client_->OnClosingHandshake();
-
-  return net::WebSocketEventInterface::CHANNEL_ALIVE;
-}
-
-ChannelState WebSocketImpl::WebSocketEventHandler::OnFlowControl(
-    int64_t quota) {
-  DVLOG(3) << "WebSocketEventHandler::OnFlowControl @"
-           << reinterpret_cast<void*>(this)
-           << " quota=" << quota;
-
-  impl_->client_->OnFlowControl(quota);
-
-  return net::WebSocketEventInterface::CHANNEL_ALIVE;
-}
-
-ChannelState WebSocketImpl::WebSocketEventHandler::OnDropChannel(
-    bool was_clean,
-    uint16_t code,
-    const std::string& reason) {
-  DVLOG(3) << "WebSocketEventHandler::OnDropChannel @"
-           << reinterpret_cast<void*>(this)
-           << " was_clean=" << was_clean << " code=" << code
-           << " reason=\"" << reason << "\"";
-
-  impl_->client_->OnDropChannel(was_clean, code, reason);
-
-  // net::WebSocketChannel requires that we delete it at this point.
-  impl_->channel_.reset();
-
-  return net::WebSocketEventInterface::CHANNEL_DELETED;
-}
-
-ChannelState WebSocketImpl::WebSocketEventHandler::OnFailChannel(
-    const std::string& message) {
-  DVLOG(3) << "WebSocketEventHandler::OnFailChannel @"
-           << reinterpret_cast<void*>(this) << " message=\"" << message << "\"";
-
-  impl_->client_->OnFailChannel(message);
-
-  // net::WebSocketChannel requires that we delete it at this point.
-  impl_->channel_.reset();
-
-  return net::WebSocketEventInterface::CHANNEL_DELETED;
-}
-
-ChannelState WebSocketImpl::WebSocketEventHandler::OnStartOpeningHandshake(
-    std::unique_ptr<net::WebSocketHandshakeRequestInfo> request) {
-  bool should_send =
-      ChildProcessSecurityPolicyImpl::GetInstance()->CanReadRawCookies(
-          impl_->delegate_->GetClientProcessId());
-
-  DVLOG(3) << "WebSocketEventHandler::OnStartOpeningHandshake @"
-           << reinterpret_cast<void*>(this) << " should_send=" << should_send;
-
-  if (!should_send)
-    return WebSocketEventInterface::CHANNEL_ALIVE;
-
-  blink::mojom::WebSocketHandshakeRequestPtr request_to_pass(
-      blink::mojom::WebSocketHandshakeRequest::New());
-  request_to_pass->url.Swap(&request->url);
-  net::HttpRequestHeaders::Iterator it(request->headers);
-  while (it.GetNext()) {
-    blink::mojom::HttpHeaderPtr header(blink::mojom::HttpHeader::New());
-    header->name = it.name();
-    header->value = it.value();
-    request_to_pass->headers.push_back(std::move(header));
-  }
-  request_to_pass->headers_text =
-      base::StringPrintf("GET %s HTTP/1.1\r\n",
-                         request_to_pass->url.spec().c_str()) +
-      request->headers.ToString();
-
-  impl_->client_->OnStartOpeningHandshake(std::move(request_to_pass));
-
-  return WebSocketEventInterface::CHANNEL_ALIVE;
-}
-
-ChannelState WebSocketImpl::WebSocketEventHandler::OnFinishOpeningHandshake(
-    std::unique_ptr<net::WebSocketHandshakeResponseInfo> response) {
-  bool should_send =
-      ChildProcessSecurityPolicyImpl::GetInstance()->CanReadRawCookies(
-          impl_->delegate_->GetClientProcessId());
-
-  DVLOG(3) << "WebSocketEventHandler::OnFinishOpeningHandshake "
-           << reinterpret_cast<void*>(this) << " should_send=" << should_send;
-
-  if (!should_send)
-    return WebSocketEventInterface::CHANNEL_ALIVE;
-
-  blink::mojom::WebSocketHandshakeResponsePtr response_to_pass(
-      blink::mojom::WebSocketHandshakeResponse::New());
-  response_to_pass->url.Swap(&response->url);
-  response_to_pass->status_code = response->status_code;
-  response_to_pass->status_text = response->status_text;
-  size_t iter = 0;
-  std::string name, value;
-  while (response->headers->EnumerateHeaderLines(&iter, &name, &value)) {
-    blink::mojom::HttpHeaderPtr header(blink::mojom::HttpHeader::New());
-    header->name = name;
-    header->value = value;
-    response_to_pass->headers.push_back(std::move(header));
-  }
-  response_to_pass->headers_text =
-      net::HttpUtil::ConvertHeadersBackToHTTPResponse(
-          response->headers->raw_headers());
-
-  impl_->client_->OnFinishOpeningHandshake(std::move(response_to_pass));
-
-  return WebSocketEventInterface::CHANNEL_ALIVE;
-}
-
-ChannelState WebSocketImpl::WebSocketEventHandler::OnSSLCertificateError(
-    std::unique_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks,
-    const GURL& url,
-    const net::SSLInfo& ssl_info,
-    bool fatal) {
-  DVLOG(3) << "WebSocketEventHandler::OnSSLCertificateError"
-           << reinterpret_cast<void*>(this) << " url=" << url.spec()
-           << " cert_status=" << ssl_info.cert_status << " fatal=" << fatal;
-  ssl_error_handler_delegate_.reset(
-      new SSLErrorHandlerDelegate(std::move(callbacks)));
-  SSLManager::OnSSLCertificateSubresourceError(
-      ssl_error_handler_delegate_->GetWeakPtr(),
-      url,
-      impl_->delegate_->GetClientProcessId(),
-      impl_->frame_id_,
-      ssl_info,
-      fatal);
-  // The above method is always asynchronous.
-  return WebSocketEventInterface::CHANNEL_ALIVE;
-}
-
-WebSocketImpl::WebSocketEventHandler::SSLErrorHandlerDelegate::
-    SSLErrorHandlerDelegate(
-        std::unique_ptr<net::WebSocketEventInterface::SSLErrorCallbacks>
-            callbacks)
-    : callbacks_(std::move(callbacks)), weak_ptr_factory_(this) {}
-
-WebSocketImpl::WebSocketEventHandler::SSLErrorHandlerDelegate::
-    ~SSLErrorHandlerDelegate() {}
-
-base::WeakPtr<SSLErrorHandler::Delegate>
-WebSocketImpl::WebSocketEventHandler::SSLErrorHandlerDelegate::GetWeakPtr() {
-  return weak_ptr_factory_.GetWeakPtr();
-}
-
-void WebSocketImpl::WebSocketEventHandler::SSLErrorHandlerDelegate::
-    CancelSSLRequest(int error, const net::SSLInfo* ssl_info) {
-  DVLOG(3) << "SSLErrorHandlerDelegate::CancelSSLRequest"
-           << " error=" << error
-           << " cert_status=" << (ssl_info ? ssl_info->cert_status
-                                           : static_cast<net::CertStatus>(-1));
-  callbacks_->CancelSSLRequest(error, ssl_info);
-}
-
-void WebSocketImpl::WebSocketEventHandler::SSLErrorHandlerDelegate::
-    ContinueSSLRequest() {
-  DVLOG(3) << "SSLErrorHandlerDelegate::ContinueSSLRequest";
-  callbacks_->ContinueSSLRequest();
-}
-
-WebSocketImpl::WebSocketImpl(Delegate* delegate,
-                             blink::mojom::WebSocketRequest request,
-                             int child_id,
-                             int frame_id,
-                             url::Origin origin,
-                             base::TimeDelta delay)
-    : delegate_(delegate),
-      binding_(this, std::move(request)),
-      delay_(delay),
-      pending_flow_control_quota_(0),
-      child_id_(child_id),
-      frame_id_(frame_id),
-      origin_(std::move(origin)),
-      handshake_succeeded_(false),
-      weak_ptr_factory_(this) {
-  binding_.set_connection_error_handler(base::BindOnce(
-      &WebSocketImpl::OnConnectionError, base::Unretained(this)));
-}
-
-WebSocketImpl::~WebSocketImpl() {}
-
-void WebSocketImpl::GoAway() {
-  StartClosingHandshake(static_cast<uint16_t>(net::kWebSocketErrorGoingAway),
-                        "");
-}
-
-void WebSocketImpl::AddChannelRequest(
-    const GURL& socket_url,
-    const std::vector<std::string>& requested_protocols,
-    const GURL& site_for_cookies,
-    const std::string& user_agent_override,
-    blink::mojom::WebSocketClientPtr client) {
-  DVLOG(3) << "WebSocketImpl::AddChannelRequest @"
-           << reinterpret_cast<void*>(this) << " socket_url=\"" << socket_url
-           << "\" requested_protocols=\""
-           << base::JoinString(requested_protocols, ", ") << "\" origin=\""
-           << origin_ << "\" site_for_cookies=\"" << site_for_cookies
-           << "\" user_agent_override=\"" << user_agent_override << "\"";
-
-  if (client_ || !client) {
-    bad_message::ReceivedBadMessage(
-        delegate_->GetClientProcessId(),
-        bad_message::WSI_UNEXPECTED_ADD_CHANNEL_REQUEST);
-    return;
-  }
-
-  client_ = std::move(client);
-
-  DCHECK(!channel_);
-  if (delay_ > base::TimeDelta()) {
-    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-        FROM_HERE,
-        base::BindOnce(&WebSocketImpl::AddChannel,
-                       weak_ptr_factory_.GetWeakPtr(), socket_url,
-                       requested_protocols, site_for_cookies,
-                       user_agent_override),
-        delay_);
-  } else {
-    AddChannel(socket_url, requested_protocols, site_for_cookies,
-               user_agent_override);
-  }
-}
-
-void WebSocketImpl::SendFrame(bool fin,
-                              blink::mojom::WebSocketMessageType type,
-                              const std::vector<uint8_t>& data) {
-  DVLOG(3) << "WebSocketImpl::SendFrame @"
-           << reinterpret_cast<void*>(this) << " fin=" << fin
-           << " type=" << type << " data is " << data.size() << " bytes";
-
-  if (!channel_) {
-    // The client should not be sending us frames until after we've informed
-    // it that the channel has been opened (OnAddChannelResponse).
-    if (handshake_succeeded_) {
-      DVLOG(1) << "Dropping frame sent to closed websocket";
-    } else {
-      bad_message::ReceivedBadMessage(
-          delegate_->GetClientProcessId(),
-          bad_message::WSI_UNEXPECTED_SEND_FRAME);
-    }
-    return;
-  }
-
-  // TODO(darin): Avoid this copy.
-  scoped_refptr<net::IOBuffer> data_to_pass(new net::IOBuffer(data.size()));
-  std::copy(data.begin(), data.end(), data_to_pass->data());
-
-  channel_->SendFrame(fin, MessageTypeToOpCode(type), std::move(data_to_pass),
-                      data.size());
-}
-
-void WebSocketImpl::SendFlowControl(int64_t quota) {
-  DVLOG(3) << "WebSocketImpl::OnFlowControl @"
-           << reinterpret_cast<void*>(this) << " quota=" << quota;
-
-  if (!channel_) {
-    // WebSocketChannel is not yet created due to the delay introduced by
-    // per-renderer WebSocket throttling.
-    // SendFlowControl() is called after WebSocketChannel is created.
-    pending_flow_control_quota_ += quota;
-    return;
-  }
-
-  ignore_result(channel_->SendFlowControl(quota));
-}
-
-void WebSocketImpl::StartClosingHandshake(uint16_t code,
-                                          const std::string& reason) {
-  DVLOG(3) << "WebSocketImpl::StartClosingHandshake @"
-           << reinterpret_cast<void*>(this)
-           << " code=" << code << " reason=\"" << reason << "\"";
-
-  if (!channel_) {
-    // WebSocketChannel is not yet created due to the delay introduced by
-    // per-renderer WebSocket throttling.
-    if (client_)
-      client_->OnDropChannel(false, net::kWebSocketErrorAbnormalClosure, "");
-    return;
-  }
-
-  ignore_result(channel_->StartClosingHandshake(code, reason));
-}
-
-void WebSocketImpl::OnConnectionError() {
-  DVLOG(3) << "WebSocketImpl::OnConnectionError @"
-           << reinterpret_cast<void*>(this);
-
-  delegate_->OnLostConnectionToClient(this);
-}
-
-void WebSocketImpl::AddChannel(
-    const GURL& socket_url,
-    const std::vector<std::string>& requested_protocols,
-    const GURL& site_for_cookies,
-    const std::string& user_agent_override) {
-  DVLOG(3) << "WebSocketImpl::AddChannel @" << reinterpret_cast<void*>(this)
-           << " socket_url=\"" << socket_url << "\" requested_protocols=\""
-           << base::JoinString(requested_protocols, ", ") << "\" origin=\""
-           << origin_ << "\" site_for_cookies=\"" << site_for_cookies
-           << "\" user_agent_override=\"" << user_agent_override << "\"";
-
-  DCHECK(!channel_);
-
-  std::unique_ptr<net::WebSocketEventInterface> event_interface(
-      new WebSocketEventHandler(this));
-  channel_.reset(new net::WebSocketChannel(std::move(event_interface),
-                                           delegate_->GetURLRequestContext()));
-
-  int64_t quota = pending_flow_control_quota_;
-  pending_flow_control_quota_ = 0;
-
-  std::string additional_headers;
-  if (!user_agent_override.empty()) {
-    if (!net::HttpUtil::IsValidHeaderValue(user_agent_override)) {
-      bad_message::ReceivedBadMessage(
-          delegate_->GetClientProcessId(),
-          bad_message::WSI_INVALID_HEADER_VALUE);
-      return;
-    }
-    additional_headers = base::StringPrintf("%s:%s",
-                                            net::HttpRequestHeaders::kUserAgent,
-                                            user_agent_override.c_str());
-  }
-  channel_->SendAddChannelRequest(socket_url, requested_protocols, origin_,
-                                  site_for_cookies, additional_headers);
-  if (quota > 0)
-    SendFlowControl(quota);
-}
-
-}  // namespace content
diff --git a/content/browser/websockets/websocket_impl.h b/content/browser/websockets/websocket_impl.h
deleted file mode 100644
index 996a443c..0000000
--- a/content/browser/websockets/websocket_impl.h
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_WEBSOCKETS_WEBSOCKET_IMPL_H_
-#define CONTENT_BROWSER_WEBSOCKETS_WEBSOCKET_IMPL_H_
-
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/time/time.h"
-#include "content/common/content_export.h"
-#include "mojo/public/cpp/bindings/binding.h"
-#include "third_party/WebKit/public/platform/modules/websockets/websocket.mojom.h"
-#include "url/origin.h"
-
-class GURL;
-
-namespace net {
-class URLRequestContext;
-class WebSocketChannel;
-}  // namespace net
-
-namespace content {
-
-// Host of net::WebSocketChannel.
-class CONTENT_EXPORT WebSocketImpl : public blink::mojom::WebSocket {
- public:
-  class Delegate {
-   public:
-    virtual ~Delegate() {}
-    virtual int GetClientProcessId() = 0;
-    virtual net::URLRequestContext* GetURLRequestContext() = 0;
-    virtual void OnReceivedResponseFromServer(WebSocketImpl* impl) = 0;
-    virtual void OnLostConnectionToClient(WebSocketImpl* impl) = 0;
-  };
-
-  WebSocketImpl(Delegate* delegate,
-                blink::mojom::WebSocketRequest request,
-                int child_id,
-                int frame_id,
-                url::Origin origin,
-                base::TimeDelta delay);
-  ~WebSocketImpl() override;
-
-  // The renderer process is going away.
-  // This function is virtual for testing.
-  virtual void GoAway();
-
-  // blink::mojom::WebSocket methods:
-  void AddChannelRequest(const GURL& url,
-                         const std::vector<std::string>& requested_protocols,
-                         const GURL& site_for_cookies,
-                         const std::string& user_agent_override,
-                         blink::mojom::WebSocketClientPtr client) override;
-  void SendFrame(bool fin,
-                 blink::mojom::WebSocketMessageType type,
-                 const std::vector<uint8_t>& data) override;
-  void SendFlowControl(int64_t quota) override;
-  void StartClosingHandshake(uint16_t code, const std::string& reason) override;
-
-  bool handshake_succeeded() const { return handshake_succeeded_; }
-  void OnHandshakeSucceeded() { handshake_succeeded_ = true; }
-
- protected:
-  class WebSocketEventHandler;
-
-  void OnConnectionError();
-  void AddChannel(const GURL& socket_url,
-                  const std::vector<std::string>& requested_protocols,
-                  const GURL& site_for_cookies,
-                  const std::string& user_agent_override);
-
-  Delegate* delegate_;
-  mojo::Binding<blink::mojom::WebSocket> binding_;
-
-  blink::mojom::WebSocketClientPtr client_;
-
-  // The channel we use to send events to the network.
-  std::unique_ptr<net::WebSocketChannel> channel_;
-
-  // Delay used for per-renderer WebSocket throttling.
-  base::TimeDelta delay_;
-
-  // SendFlowControl() is delayed when OnFlowControl() is called before
-  // AddChannel() is called.
-  // Zero indicates there is no pending SendFlowControl().
-  int64_t pending_flow_control_quota_;
-
-  int child_id_;
-  int frame_id_;
-
-  // The web origin to use for the WebSocket.
-  const url::Origin origin_;
-
-  // handshake_succeeded_ is set and used by WebSocketManager to manage
-  // counters for per-renderer WebSocket throttling.
-  bool handshake_succeeded_;
-
-  base::WeakPtrFactory<WebSocketImpl> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(WebSocketImpl);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_WEBSOCKETS_WEBSOCKET_IMPL_H_
diff --git a/content/browser/websockets/websocket_manager.cc b/content/browser/websockets/websocket_manager.cc
index ce41b4a..fad1a1d3 100644
--- a/content/browser/websockets/websocket_manager.cc
+++ b/content/browser/websockets/websocket_manager.cc
@@ -11,8 +11,13 @@
 #include "base/callback.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
+#include "base/memory/weak_ptr.h"
 #include "base/numerics/safe_conversions.h"
-#include "base/rand_util.h"
+#include "content/browser/bad_message.h"
+#include "content/browser/child_process_security_policy_impl.h"
+#include "content/browser/ssl/ssl_error_handler.h"
+#include "content/browser/ssl/ssl_manager.h"
+#include "content/browser/websockets/websocket_handshake_request_info_impl.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
@@ -25,12 +30,109 @@
 
 const char kWebSocketManagerKeyName[] = "web_socket_manager";
 
-// Max number of pending connections per WebSocketManager used for per-renderer
-// WebSocket throttling.
-const int kMaxPendingWebSocketConnections = 255;
-
 }  // namespace
 
+class WebSocketManager::Delegate final : public network::WebSocket::Delegate {
+ public:
+  explicit Delegate(WebSocketManager* manager) : manager_(manager) {}
+  ~Delegate() override {}
+
+  net::URLRequestContext* GetURLRequestContext() override {
+    return manager_->GetURLRequestContext();
+  }
+
+  void OnLostConnectionToClient(network::WebSocket* impl) override {
+    manager_->OnLostConnectionToClient(impl);
+  }
+
+  void OnSSLCertificateError(
+      std::unique_ptr<net::WebSocketEventInterface::SSLErrorCallbacks>
+          callbacks,
+      const GURL& url,
+      int child_id,
+      int frame_id,
+      const net::SSLInfo& ssl_info,
+      bool fatal) override {
+    ssl_error_handler_delegate_ =
+        std::make_unique<SSLErrorHandlerDelegate>(std::move(callbacks));
+    SSLManager::OnSSLCertificateSubresourceError(
+        ssl_error_handler_delegate_->GetWeakPtr(), url, child_id, frame_id,
+        ssl_info, fatal);
+  }
+
+  void ReportBadMessage(BadMessageReason reason,
+                        network::WebSocket* impl) override {
+    bad_message::BadMessageReason reason_to_pass =
+        bad_message::WSI_INVALID_HEADER_VALUE;
+    switch (reason) {
+      case BadMessageReason::kInvalidHeaderValue:
+        reason_to_pass = bad_message::WSI_INVALID_HEADER_VALUE;
+        break;
+      case BadMessageReason::kUnexpectedAddChannelRequest:
+        reason_to_pass = bad_message::WSI_UNEXPECTED_ADD_CHANNEL_REQUEST;
+        break;
+      case BadMessageReason::kUnexpectedSendFrame:
+        reason_to_pass = bad_message::WSI_UNEXPECTED_SEND_FRAME;
+        break;
+    }
+    bad_message::ReceivedBadMessage(manager_->process_id_, reason_to_pass);
+    OnLostConnectionToClient(impl);
+  }
+
+  bool CanReadRawCookies() override {
+    return ChildProcessSecurityPolicyImpl::GetInstance()->CanReadRawCookies(
+        manager_->process_id_);
+  }
+
+  void OnCreateURLRequest(int child_id,
+                          int frame_id,
+                          net::URLRequest* url_request) override {
+    WebSocketHandshakeRequestInfoImpl::CreateInfoAndAssociateWithRequest(
+        child_id, frame_id, url_request);
+  }
+
+ private:
+  class SSLErrorHandlerDelegate final : public SSLErrorHandler::Delegate {
+   public:
+    explicit SSLErrorHandlerDelegate(
+        std::unique_ptr<net::WebSocketEventInterface::SSLErrorCallbacks>
+            callbacks)
+        : callbacks_(std::move(callbacks)), weak_ptr_factory_(this) {}
+    ~SSLErrorHandlerDelegate() override {}
+
+    base::WeakPtr<SSLErrorHandler::Delegate> GetWeakPtr() {
+      return weak_ptr_factory_.GetWeakPtr();
+    }
+
+    // SSLErrorHandler::Delegate methods
+    void CancelSSLRequest(int error, const net::SSLInfo* ssl_info) override {
+      DVLOG(3) << "SSLErrorHandlerDelegate::CancelSSLRequest"
+               << " error=" << error << " cert_status="
+               << (ssl_info ? ssl_info->cert_status
+                            : static_cast<net::CertStatus>(-1));
+      callbacks_->CancelSSLRequest(error, ssl_info);
+    }
+
+    void ContinueSSLRequest() override {
+      DVLOG(3) << "SSLErrorHandlerDelegate::ContinueSSLRequest";
+      callbacks_->ContinueSSLRequest();
+    }
+
+   private:
+    std::unique_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks_;
+
+    base::WeakPtrFactory<SSLErrorHandlerDelegate> weak_ptr_factory_;
+
+    DISALLOW_COPY_AND_ASSIGN(SSLErrorHandlerDelegate);
+  };
+
+  std::unique_ptr<SSLErrorHandlerDelegate> ssl_error_handler_delegate_;
+  // |manager_| outlives this object.
+  WebSocketManager* const manager_;
+
+  DISALLOW_COPY_AND_ASSIGN(Delegate);
+};
+
 class WebSocketManager::Handle : public base::SupportsUserData::Data,
                                  public RenderProcessHostObserver {
  public:
@@ -58,7 +160,7 @@
 void WebSocketManager::CreateWebSocketForFrame(
     int process_id,
     int frame_id,
-    blink::mojom::WebSocketRequest request) {
+    network::mojom::WebSocketRequest request) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   // ForFrame() implies a frame: DCHECK this pre-condition.
@@ -73,7 +175,7 @@
 void WebSocketManager::CreateWebSocketWithOrigin(
     int process_id,
     url::Origin origin,
-    blink::mojom::WebSocketRequest request,
+    network::mojom::WebSocketRequest request,
     int frame_id) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
@@ -105,11 +207,6 @@
 WebSocketManager::WebSocketManager(int process_id,
                                    StoragePartition* storage_partition)
     : process_id_(process_id),
-      num_pending_connections_(0),
-      num_current_succeeded_connections_(0),
-      num_previous_succeeded_connections_(0),
-      num_current_failed_connections_(0),
-      num_previous_failed_connections_(0),
       context_destroyed_(false) {
   if (storage_partition) {
     url_request_context_getter_ = storage_partition->GetURLRequestContext();
@@ -129,40 +226,39 @@
   if (!context_destroyed_ && url_request_context_getter_)
     url_request_context_getter_->RemoveObserver(this);
 
-  for (auto* impl : impls_) {
+  for (const auto& impl : impls_) {
     impl->GoAway();
-    delete impl;
   }
 }
 
 void WebSocketManager::DoCreateWebSocket(
     int frame_id,
     url::Origin origin,
-    blink::mojom::WebSocketRequest request) {
+    network::mojom::WebSocketRequest request) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
-  if (num_pending_connections_ >= kMaxPendingWebSocketConnections) {
+  if (throttler_.HasTooManyPendingConnections()) {
     // Too many websockets!
     request.ResetWithReason(
-        blink::mojom::WebSocket::kInsufficientResources,
+        network::mojom::WebSocket::kInsufficientResources,
         "Error in connection establishment: net::ERR_INSUFFICIENT_RESOURCES");
     return;
   }
 
   if (context_destroyed_) {
     request.ResetWithReason(
-        blink::mojom::WebSocket::kInsufficientResources,
+        network::mojom::WebSocket::kInsufficientResources,
         "Error in connection establishment: net::ERR_UNEXPECTED");
     return;
   }
 
-  // Keep all WebSocketImpls alive until either the client drops its
+  // Keep all network::WebSockets alive until either the client drops its
   // connection (see OnLostConnectionToClient) or we need to shutdown.
 
-  impls_.insert(CreateWebSocketImpl(this, std::move(request), process_id_,
-                                    frame_id, std::move(origin),
-                                    CalculateDelay()));
-  ++num_pending_connections_;
+  impls_.insert(CreateWebSocket(
+      std::make_unique<Delegate>(this), std::move(request),
+      throttler_.IssuePendingConnectionTracker(), process_id_, frame_id,
+      std::move(origin), throttler_.CalculateDelay()));
 
   if (!throttling_period_timer_.IsRunning()) {
     throttling_period_timer_.Start(
@@ -173,79 +269,43 @@
   }
 }
 
-// Calculate delay as described in the per-renderer WebSocket throttling
-// design doc: https://goo.gl/tldFNn
-base::TimeDelta WebSocketManager::CalculateDelay() const {
-  int64_t f = num_previous_failed_connections_ +
-              num_current_failed_connections_;
-  int64_t s = num_previous_succeeded_connections_ +
-              num_current_succeeded_connections_;
-  int p = num_pending_connections_;
-  return base::TimeDelta::FromMilliseconds(
-      base::RandInt(1000, 5000) *
-      (1 << std::min(p + f / (s + 1), INT64_C(16))) / 65536);
-}
-
 void WebSocketManager::ThrottlingPeriodTimerCallback() {
-  num_previous_failed_connections_ = num_current_failed_connections_;
-  num_current_failed_connections_ = 0;
-
-  num_previous_succeeded_connections_ = num_current_succeeded_connections_;
-  num_current_succeeded_connections_ = 0;
-
-  if (num_pending_connections_ == 0 &&
-      num_previous_failed_connections_ == 0 &&
-      num_previous_succeeded_connections_ == 0) {
+  throttler_.Roll();
+  if (throttler_.IsClean())
     throttling_period_timer_.Stop();
-  }
 }
 
-WebSocketImpl* WebSocketManager::CreateWebSocketImpl(
-    WebSocketImpl::Delegate* delegate,
-    blink::mojom::WebSocketRequest request,
+std::unique_ptr<network::WebSocket> WebSocketManager::CreateWebSocket(
+    std::unique_ptr<network::WebSocket::Delegate> delegate,
+    network::mojom::WebSocketRequest request,
+    network::WebSocketThrottler::PendingConnection pending_connection_tracker,
     int child_id,
     int frame_id,
     url::Origin origin,
     base::TimeDelta delay) {
-  return new WebSocketImpl(delegate, std::move(request), child_id, frame_id,
-                           std::move(origin), delay);
-}
-
-int WebSocketManager::GetClientProcessId() {
-  return process_id_;
+  return std::make_unique<network::WebSocket>(
+      std::move(delegate), std::move(request),
+      std::move(pending_connection_tracker), child_id, frame_id,
+      std::move(origin), delay);
 }
 
 net::URLRequestContext* WebSocketManager::GetURLRequestContext() {
   return url_request_context_getter_->GetURLRequestContext();
 }
 
-void WebSocketManager::OnReceivedResponseFromServer(WebSocketImpl* impl) {
-  // The server accepted this WebSocket connection.
-  impl->OnHandshakeSucceeded();
-  --num_pending_connections_;
-  DCHECK_GE(num_pending_connections_, 0);
-  ++num_current_succeeded_connections_;
-}
-
-void WebSocketManager::OnLostConnectionToClient(WebSocketImpl* impl) {
+void WebSocketManager::OnLostConnectionToClient(network::WebSocket* impl) {
   // The client is no longer interested in this WebSocket.
-  if (!impl->handshake_succeeded()) {
-    // Update throttling counters (failure).
-    --num_pending_connections_;
-    DCHECK_GE(num_pending_connections_, 0);
-    ++num_current_failed_connections_;
-  }
   impl->GoAway();
-  impls_.erase(impl);
-  delete impl;
+  const auto it = impls_.find(impl);
+  DCHECK(it != impls_.end());
+  impls_.erase(it);
 }
 
 void WebSocketManager::OnContextShuttingDown() {
   context_destroyed_ = true;
   url_request_context_getter_ = nullptr;
-  for (auto* impl : impls_) {
+  for (const auto& impl : impls_) {
     impl->GoAway();
-    delete impl;
   }
   impls_.clear();
 }
diff --git a/content/browser/websockets/websocket_manager.h b/content/browser/websockets/websocket_manager.h
index db02e6c..0893685 100644
--- a/content/browser/websockets/websocket_manager.h
+++ b/content/browser/websockets/websocket_manager.h
@@ -5,44 +5,48 @@
 #ifndef CONTENT_BROWSER_WEBSOCKETS_WEBSOCKET_MANAGER_H_
 #define CONTENT_BROWSER_WEBSOCKETS_WEBSOCKET_MANAGER_H_
 
+#include <memory>
 #include <set>
 
 #include "base/compiler_specific.h"
+#include "base/containers/unique_ptr_adapters.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/timer/timer.h"
-#include "content/browser/websockets/websocket_impl.h"
 #include "content/common/content_export.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "net/url_request/url_request_context_getter_observer.h"
+#include "services/network/websocket.h"
+#include "services/network/websocket_throttler.h"
 
 namespace content {
 class StoragePartition;
 
 // The WebSocketManager is a per child process instance that manages the
-// lifecycle of WebSocketImpl objects. It is responsible for creating
-// WebSocketImpl objects for each WebSocketRequest and throttling the number of
-// WebSocketImpl objects in use.
+// lifecycle of network::WebSocket objects. It is responsible for creating
+// network::WebSocket objects for each WebSocketRequest and throttling the
+// number of network::WebSocket objects in use.
 class CONTENT_EXPORT WebSocketManager
-    : public WebSocketImpl::Delegate,
-      public net::URLRequestContextGetterObserver {
+    : public net::URLRequestContextGetterObserver {
  public:
   // Called on the UI thread: create a websocket for a frame.
   static void CreateWebSocketForFrame(int process_id,
                                       int frame_id,
-                                      blink::mojom::WebSocketRequest request);
+                                      network::mojom::WebSocketRequest request);
 
   // Called on the UI thread: create a websocket for a worker. Web workers of
   // any type (dedicated, shared, service worker) do not have a frame.
-  static void CreateWebSocketWithOrigin(int process_id,
-                                        url::Origin origin,
-                                        blink::mojom::WebSocketRequest request,
-                                        int frame_id = MSG_ROUTING_NONE);
+  static void CreateWebSocketWithOrigin(
+      int process_id,
+      url::Origin origin,
+      network::mojom::WebSocketRequest request,
+      int frame_id = MSG_ROUTING_NONE);
 
   // net::URLRequestContextGetterObserver implementation.
   void OnContextShuttingDown() override;
 
  protected:
+  class Delegate;
   class Handle;
   friend class base::DeleteHelper<WebSocketManager>;
 
@@ -54,47 +58,34 @@
   ~WebSocketManager() override;
   void DoCreateWebSocket(int frame_id,
                          url::Origin origin,
-                         blink::mojom::WebSocketRequest request);
-  base::TimeDelta CalculateDelay() const;
+                         network::mojom::WebSocketRequest request);
   void ThrottlingPeriodTimerCallback();
 
   // This is virtual to support testing.
-  virtual WebSocketImpl* CreateWebSocketImpl(
-      WebSocketImpl::Delegate* delegate,
-      blink::mojom::WebSocketRequest request,
+  virtual std::unique_ptr<network::WebSocket> CreateWebSocket(
+      std::unique_ptr<network::WebSocket::Delegate> delegate,
+      network::mojom::WebSocketRequest request,
+      network::WebSocketThrottler::PendingConnection pending_connection_tracker,
       int child_id,
       int frame_id,
       url::Origin origin,
       base::TimeDelta delay);
 
-  // WebSocketImpl::Delegate methods:
-  int GetClientProcessId() override;
-  net::URLRequestContext* GetURLRequestContext() override;
-  void OnReceivedResponseFromServer(WebSocketImpl* impl) override;
-  void OnLostConnectionToClient(WebSocketImpl* impl) override;
+  net::URLRequestContext* GetURLRequestContext();
+  virtual void OnLostConnectionToClient(network::WebSocket* impl);
 
   void ObserveURLRequestContextGetter();
 
   int process_id_;
   scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
 
-  std::set<WebSocketImpl*> impls_;
+  std::set<std::unique_ptr<network::WebSocket>, base::UniquePtrComparator>
+      impls_;
 
   // Timer and counters for per-renderer WebSocket throttling.
   base::RepeatingTimer throttling_period_timer_;
 
-  // The current number of pending connections.
-  int num_pending_connections_;
-
-  // The number of handshakes that failed in the current and previous time
-  // period.
-  int64_t num_current_succeeded_connections_;
-  int64_t num_previous_succeeded_connections_;
-
-  // The number of handshakes that succeeded in the current and previous time
-  // period.
-  int64_t num_current_failed_connections_;
-  int64_t num_previous_failed_connections_;
+  network::WebSocketPerProcessThrottler throttler_;
 
   bool context_destroyed_;
 
diff --git a/content/browser/websockets/websocket_manager_unittest.cc b/content/browser/websockets/websocket_manager_unittest.cc
index d461496..5655e6f 100644
--- a/content/browser/websockets/websocket_manager_unittest.cc
+++ b/content/browser/websockets/websocket_manager_unittest.cc
@@ -6,6 +6,7 @@
 #include <memory>
 #include <vector>
 
+#include "base/memory/ptr_util.h"
 #include "content/browser/websockets/websocket_manager.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "ipc/ipc_message.h"
@@ -19,20 +20,24 @@
 // This number is unlikely to occur by chance.
 static const int kMagicRenderProcessId = 506116062;
 
-class TestWebSocketImpl : public WebSocketImpl {
+class TestWebSocketImpl : public network::WebSocket {
  public:
-  TestWebSocketImpl(Delegate* delegate,
-                    blink::mojom::WebSocketRequest request,
-                    int process_id,
-                    int frame_id,
-                    url::Origin origin,
-                    base::TimeDelta delay)
-      : WebSocketImpl(delegate,
-                      std::move(request),
-                      process_id,
-                      frame_id,
-                      std::move(origin),
-                      delay) {}
+  TestWebSocketImpl(
+      std::unique_ptr<Delegate> delegate,
+      network::mojom::WebSocketRequest request,
+      network::WebSocketThrottler::PendingConnection pending_connection_tracker,
+
+      int process_id,
+      int frame_id,
+      url::Origin origin,
+      base::TimeDelta delay)
+      : network::WebSocket(std::move(delegate),
+                           std::move(request),
+                           std::move(pending_connection_tracker),
+                           process_id,
+                           frame_id,
+                           std::move(origin),
+                           delay) {}
 
   base::TimeDelta delay() const { return delay_; }
 
@@ -50,38 +55,46 @@
     return sockets_;
   }
 
-  int num_pending_connections() const {
-    return num_pending_connections_;
+  int64_t num_pending_connections() const {
+    return throttler_.num_pending_connections();
   }
-  int64_t num_failed_connections() const {
-    return num_current_failed_connections_ + num_previous_failed_connections_;
+  int64_t num_current_succeeded_connections() const {
+    return throttler_.num_current_succeeded_connections();
   }
-  int64_t num_succeeded_connections() const {
-    return num_current_succeeded_connections_ +
-           num_previous_succeeded_connections_;
+  int64_t num_previous_succeeded_connections() const {
+    return throttler_.num_previous_succeeded_connections();
+  }
+  int64_t num_current_failed_connections() const {
+    return throttler_.num_current_failed_connections();
+  }
+  int64_t num_previous_failed_connections() const {
+    return throttler_.num_previous_failed_connections();
   }
 
-  void DoCreateWebSocket(blink::mojom::WebSocketRequest request) {
+  void DoCreateWebSocket(network::mojom::WebSocketRequest request) {
     WebSocketManager::DoCreateWebSocket(MSG_ROUTING_NONE, url::Origin(),
                                         std::move(request));
   }
 
  private:
-  WebSocketImpl* CreateWebSocketImpl(WebSocketImpl::Delegate* delegate,
-                                     blink::mojom::WebSocketRequest request,
-                                     int process_id,
-                                     int frame_id,
-                                     url::Origin origin,
-                                     base::TimeDelta delay) override {
-    TestWebSocketImpl* impl =
-        new TestWebSocketImpl(delegate, std::move(request), process_id,
-                              frame_id, std::move(origin), delay);
+  std::unique_ptr<network::WebSocket> CreateWebSocket(
+      std::unique_ptr<network::WebSocket::Delegate> delegate,
+      network::mojom::WebSocketRequest request,
+      network::WebSocketThrottler::PendingConnection pending_connection_tracker,
+      int process_id,
+      int frame_id,
+      url::Origin origin,
+      base::TimeDelta delay) override {
+    auto impl = std::make_unique<TestWebSocketImpl>(
+        std::move(delegate), std::move(request),
+        std::move(pending_connection_tracker), process_id, frame_id,
+        std::move(origin), delay);
     // We keep a vector of sockets here to track their creation order.
-    sockets_.push_back(impl);
+    sockets_.push_back(impl.get());
     return impl;
   }
 
-  void OnLostConnectionToClient(WebSocketImpl* impl) override {
+  void OnLostConnectionToClient(network::WebSocket* impl) override {
     auto it = std::find(sockets_.begin(), sockets_.end(),
                         static_cast<TestWebSocketImpl*>(impl));
     ASSERT_TRUE(it != sockets_.end());
@@ -102,14 +115,14 @@
 
   void AddMultipleChannels(int number_of_channels) {
     for (int i = 0; i < number_of_channels; ++i) {
-      blink::mojom::WebSocketPtr websocket;
+      network::mojom::WebSocketPtr websocket;
       websocket_manager_->DoCreateWebSocket(mojo::MakeRequest(&websocket));
     }
   }
 
   void AddAndCancelMultipleChannels(int number_of_channels) {
     for (int i = 0; i < number_of_channels; ++i) {
-      blink::mojom::WebSocketPtr websocket;
+      network::mojom::WebSocketPtr websocket;
       websocket_manager_->DoCreateWebSocket(mojo::MakeRequest(&websocket));
       websocket_manager_->sockets().back()->SimulateConnectionError();
     }
@@ -127,7 +140,7 @@
 }
 
 TEST_F(WebSocketManagerTest, CreateWebSocket) {
-  blink::mojom::WebSocketPtr websocket;
+  network::mojom::WebSocketPtr websocket;
 
   websocket_manager()->DoCreateWebSocket(mojo::MakeRequest(&websocket));
 
@@ -135,49 +148,13 @@
 }
 
 TEST_F(WebSocketManagerTest, SendFrameButNotConnectedYet) {
-  blink::mojom::WebSocketPtr websocket;
+  network::mojom::WebSocketPtr websocket;
 
   websocket_manager()->DoCreateWebSocket(mojo::MakeRequest(&websocket));
 
   // This should not crash.
   std::vector<uint8_t> data;
-  websocket->SendFrame(true, blink::mojom::WebSocketMessageType::TEXT, data);
-}
-
-TEST_F(WebSocketManagerTest, DelayFor4thPendingConnectionIsZero) {
-  AddMultipleChannels(4);
-
-  EXPECT_EQ(4, websocket_manager()->num_pending_connections());
-  EXPECT_EQ(0, websocket_manager()->num_failed_connections());
-  EXPECT_EQ(0, websocket_manager()->num_succeeded_connections());
-
-  ASSERT_EQ(4U, websocket_manager()->sockets().size());
-  EXPECT_EQ(base::TimeDelta(), websocket_manager()->sockets()[3]->delay());
-}
-
-TEST_F(WebSocketManagerTest, DelayFor8thPendingConnectionIsNonZero) {
-  AddMultipleChannels(8);
-
-  EXPECT_EQ(8, websocket_manager()->num_pending_connections());
-  EXPECT_EQ(0, websocket_manager()->num_failed_connections());
-  EXPECT_EQ(0, websocket_manager()->num_succeeded_connections());
-
-  ASSERT_EQ(8U, websocket_manager()->sockets().size());
-  EXPECT_LT(base::TimeDelta(), websocket_manager()->sockets()[7]->delay());
-}
-
-TEST_F(WebSocketManagerTest, DelayFor17thPendingConnection) {
-  AddMultipleChannels(17);
-
-  EXPECT_EQ(17, websocket_manager()->num_pending_connections());
-  EXPECT_EQ(0, websocket_manager()->num_failed_connections());
-  EXPECT_EQ(0, websocket_manager()->num_succeeded_connections());
-
-  ASSERT_EQ(17U, websocket_manager()->sockets().size());
-  EXPECT_LE(base::TimeDelta::FromMilliseconds(1000),
-            websocket_manager()->sockets()[16]->delay());
-  EXPECT_GE(base::TimeDelta::FromMilliseconds(5000),
-            websocket_manager()->sockets()[16]->delay());
+  websocket->SendFrame(true, network::mojom::WebSocketMessageType::TEXT, data);
 }
 
 // The 256th connection is rejected by per-renderer WebSocket throttling.
@@ -186,67 +163,13 @@
   AddMultipleChannels(256);
 
   EXPECT_EQ(255, websocket_manager()->num_pending_connections());
-  EXPECT_EQ(0, websocket_manager()->num_failed_connections());
-  EXPECT_EQ(0, websocket_manager()->num_succeeded_connections());
+  EXPECT_EQ(0, websocket_manager()->num_current_succeeded_connections());
+  EXPECT_EQ(0, websocket_manager()->num_previous_succeeded_connections());
+  EXPECT_EQ(0, websocket_manager()->num_current_failed_connections());
+  EXPECT_EQ(0, websocket_manager()->num_previous_failed_connections());
 
   ASSERT_EQ(255U, websocket_manager()->sockets().size());
 }
 
-TEST_F(WebSocketManagerTest, DelayIsZeroAfter3FailedConnections) {
-  AddAndCancelMultipleChannels(3);
-
-  EXPECT_EQ(0, websocket_manager()->num_pending_connections());
-  EXPECT_EQ(3, websocket_manager()->num_failed_connections());
-  EXPECT_EQ(0, websocket_manager()->num_succeeded_connections());
-
-  AddMultipleChannels(1);
-
-  ASSERT_EQ(1U, websocket_manager()->sockets().size());
-  EXPECT_EQ(base::TimeDelta(), websocket_manager()->sockets()[0]->delay());
-}
-
-TEST_F(WebSocketManagerTest, DelayIsNonZeroAfter7FailedConnections) {
-  AddAndCancelMultipleChannels(7);
-
-  EXPECT_EQ(0, websocket_manager()->num_pending_connections());
-  EXPECT_EQ(7, websocket_manager()->num_failed_connections());
-  EXPECT_EQ(0, websocket_manager()->num_succeeded_connections());
-
-  AddMultipleChannels(1);
-
-  ASSERT_EQ(1U, websocket_manager()->sockets().size());
-  EXPECT_LT(base::TimeDelta(), websocket_manager()->sockets()[0]->delay());
-}
-
-TEST_F(WebSocketManagerTest, DelayAfter16FailedConnections) {
-  AddAndCancelMultipleChannels(16);
-
-  EXPECT_EQ(0, websocket_manager()->num_pending_connections());
-  EXPECT_EQ(16, websocket_manager()->num_failed_connections());
-  EXPECT_EQ(0, websocket_manager()->num_succeeded_connections());
-
-  AddMultipleChannels(1);
-
-  ASSERT_EQ(1U, websocket_manager()->sockets().size());
-  EXPECT_LE(base::TimeDelta::FromMilliseconds(1000),
-            websocket_manager()->sockets()[0]->delay());
-  EXPECT_GE(base::TimeDelta::FromMilliseconds(5000),
-            websocket_manager()->sockets()[0]->delay());
-}
-
-TEST_F(WebSocketManagerTest, NotRejectedAfter255FailedConnections) {
-  AddAndCancelMultipleChannels(255);
-
-  EXPECT_EQ(0, websocket_manager()->num_pending_connections());
-  EXPECT_EQ(255, websocket_manager()->num_failed_connections());
-  EXPECT_EQ(0, websocket_manager()->num_succeeded_connections());
-
-  AddMultipleChannels(1);
-
-  EXPECT_EQ(1, websocket_manager()->num_pending_connections());
-  EXPECT_EQ(255, websocket_manager()->num_failed_connections());
-  EXPECT_EQ(0, websocket_manager()->num_succeeded_connections());
-}
-
 }  // namespace
 }  // namespace content
diff --git a/content/browser/webui/content_web_ui_controller_factory.cc b/content/browser/webui/content_web_ui_controller_factory.cc
index 0ca8a838..0f8982a83 100644
--- a/content/browser/webui/content_web_ui_controller_factory.cc
+++ b/content/browser/webui/content_web_ui_controller_factory.cc
@@ -17,7 +17,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/common/url_constants.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 #if BUILDFLAG(ENABLE_WEBRTC)
 #include "content/browser/webrtc/webrtc_internals_ui.h"
diff --git a/content/browser/webui/generic_handler.cc b/content/browser/webui/generic_handler.cc
index 71259a8..9b778bc6 100644
--- a/content/browser/webui/generic_handler.cc
+++ b/content/browser/webui/generic_handler.cc
@@ -21,8 +21,9 @@
 }
 
 void GenericHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback("navigateToUrl",
-      base::Bind(&GenericHandler::HandleNavigateToUrl, base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "navigateToUrl", base::BindRepeating(&GenericHandler::HandleNavigateToUrl,
+                                           base::Unretained(this)));
 }
 
 void GenericHandler::HandleNavigateToUrl(const base::ListValue* args) {
diff --git a/content/browser/webui/web_ui_impl.cc b/content/browser/webui/web_ui_impl.cc
index eabd4a4..7c7803f 100644
--- a/content/browser/webui/web_ui_impl.cc
+++ b/content/browser/webui/web_ui_impl.cc
@@ -251,11 +251,10 @@
     return;
 
   // Look up the callback for this message.
-  MessageCallbackMap::const_iterator callback =
-      message_callbacks_.find(message);
-  if (callback != message_callbacks_.end()) {
+  auto callback_pair = message_callbacks_.find(message);
+  if (callback_pair != message_callbacks_.end()) {
     // Forward this message and content on.
-    callback->second.Run(&args);
+    callback_pair->second.Run(&args);
   } else {
     NOTREACHED() << "Unhandled chrome.send(\"" << message << "\");";
   }
diff --git a/content/browser/webui/web_ui_impl.h b/content/browser/webui/web_ui_impl.h
index b13969e..387362f 100644
--- a/content/browser/webui/web_ui_impl.h
+++ b/content/browser/webui/web_ui_impl.h
@@ -51,7 +51,6 @@
   int GetBindings() const override;
   void SetBindings(int bindings) override;
   void AddMessageHandler(std::unique_ptr<WebUIMessageHandler> handler) override;
-  typedef base::Callback<void(const base::ListValue*)> MessageCallback;
   void RegisterMessageCallback(const std::string& message,
                                const MessageCallback& callback) override;
   void ProcessWebUIMessage(const GURL& source_url,
@@ -97,8 +96,7 @@
   void DisallowJavascriptOnAllHandlers();
 
   // A map of message name -> message handling callback.
-  typedef std::map<std::string, MessageCallback> MessageCallbackMap;
-  MessageCallbackMap message_callbacks_;
+  std::map<std::string, MessageCallback> message_callbacks_;
 
   // Options that may be overridden by individual Web UI implementations. The
   // bool options default to false. See the public getters for more information.
diff --git a/content/browser/webui/web_ui_url_loader_factory.cc b/content/browser/webui/web_ui_url_loader_factory.cc
index 8bd280f..d6e4728c 100644
--- a/content/browser/webui/web_ui_url_loader_factory.cc
+++ b/content/browser/webui/web_ui_url_loader_factory.cc
@@ -332,10 +332,6 @@
     RenderFrameHost* render_frame_host,
     const std::string& scheme,
     base::flat_set<std::string> allowed_hosts) {
-  // At present we have no use-case for a need to allow all hosts if
-  // constructing via this method. If this changes remove the DCHECK below and
-  // WebUIURLLoaderFactory will not filter.
-  DCHECK(!allowed_hosts.empty());
   return std::make_unique<WebUIURLLoaderFactory>(render_frame_host, scheme,
                                                  std::move(allowed_hosts));
 }
diff --git a/content/child/child_thread_impl.h b/content/child/child_thread_impl.h
index 01f1ced2..f875135 100644
--- a/content/child/child_thread_impl.h
+++ b/content/child/child_thread_impl.h
@@ -24,7 +24,7 @@
 #include "content/common/content_export.h"
 #include "content/public/child/child_thread.h"
 #include "ipc/ipc.mojom.h"
-#include "ipc/ipc_features.h"  // For BUILDFLAG(IPC_MESSAGE_LOG_ENABLED).
+#include "ipc/ipc_buildflags.h"  // For BUILDFLAG(IPC_MESSAGE_LOG_ENABLED).
 #include "ipc/ipc_platform_file.h"
 #include "ipc/message_router.h"
 #include "mojo/public/cpp/bindings/associated_binding.h"
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn
index 3ab75ac..e2988ce 100644
--- a/content/common/BUILD.gn
+++ b/content/common/BUILD.gn
@@ -65,7 +65,6 @@
     "browser_plugin/browser_plugin_constants.cc",
     "browser_plugin/browser_plugin_constants.h",
     "browser_plugin/browser_plugin_messages.h",
-    "cache_storage/cache_storage_messages.h",
     "cache_storage/cache_storage_types.cc",
     "cache_storage/cache_storage_types.h",
     "child_process_host_impl.cc",
@@ -353,7 +352,7 @@
     "//media/base/ipc",
     "//media/capture",
     "//media/capture/ipc",
-    "//media/gpu:features",
+    "//media/gpu:buildflags",
     "//media/gpu/ipc/client",
     "//media/gpu/ipc/common",
     "//media/midi",
@@ -612,7 +611,6 @@
     "//content/public/common:resource_type_bindings",
     "//ipc:mojom_constants",
     "//media/mojo/interfaces",
-    "//mojo/common:common_custom_types",
     "//mojo/public/mojom/base",
     "//services/network/public/mojom",
     "//services/service_manager/public/mojom",
diff --git a/content/common/cache_storage/cache_storage_messages.h b/content/common/cache_storage/cache_storage_messages.h
deleted file mode 100644
index f739e4bb..0000000
--- a/content/common/cache_storage/cache_storage_messages.h
+++ /dev/null
@@ -1,196 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_CACHE_STORAGE_CACHE_STORAGE_MESSAGES_H_
-#define CONTENT_COMMON_CACHE_STORAGE_CACHE_STORAGE_MESSAGES_H_
-
-#include <string>
-#include <vector>
-
-#include "base/strings/string16.h"
-#include "content/common/cache_storage/cache_storage_types.h"
-#include "content/common/service_worker/service_worker_types.h"
-#include "ipc/ipc_message_macros.h"
-#include "ipc/ipc_param_traits.h"
-#include "third_party/WebKit/public/platform/modules/cache_storage/cache_storage.mojom.h"
-#include "url/origin.h"
-
-#undef IPC_MESSAGE_EXPORT
-#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
-
-#define IPC_MESSAGE_START CacheStorageMsgStart
-
-// TODO(jsbell): This depends on traits for content::ServiceWorkerResponse
-// which are defined in service_worker_messages.h - correct this implicit
-// cross-dependency.
-
-IPC_STRUCT_TRAITS_BEGIN(content::CacheStorageCacheQueryParams)
-  IPC_STRUCT_TRAITS_MEMBER(ignore_search)
-  IPC_STRUCT_TRAITS_MEMBER(ignore_method)
-  IPC_STRUCT_TRAITS_MEMBER(ignore_vary)
-  IPC_STRUCT_TRAITS_MEMBER(cache_name)
-IPC_STRUCT_TRAITS_END()
-
-IPC_ENUM_TRAITS_MAX_VALUE(content::CacheStorageCacheOperationType,
-                          content::CACHE_STORAGE_CACHE_OPERATION_TYPE_LAST)
-
-IPC_STRUCT_TRAITS_BEGIN(content::CacheStorageBatchOperation)
-  IPC_STRUCT_TRAITS_MEMBER(operation_type)
-  IPC_STRUCT_TRAITS_MEMBER(request)
-  IPC_STRUCT_TRAITS_MEMBER(response)
-  IPC_STRUCT_TRAITS_MEMBER(match_params)
-IPC_STRUCT_TRAITS_END()
-
-IPC_ENUM_TRAITS_MAX_VALUE(blink::mojom::CacheStorageError,
-                          blink::mojom::CacheStorageError::kLast)
-
-//---------------------------------------------------------------------------
-// Messages sent from the child process to the browser.
-
-// CacheStorage operations in the browser.
-IPC_MESSAGE_CONTROL4(CacheStorageHostMsg_CacheStorageHas,
-                     int /* thread_id */,
-                     int /* request_id */,
-                     url::Origin /* origin */,
-                     base::string16 /* fetch_store_name */)
-
-IPC_MESSAGE_CONTROL4(CacheStorageHostMsg_CacheStorageOpen,
-                     int /* thread_id */,
-                     int /* request_id */,
-                     url::Origin /* origin */,
-                     base::string16 /* fetch_store_name */)
-
-IPC_MESSAGE_CONTROL4(CacheStorageHostMsg_CacheStorageDelete,
-                     int /* thread_id */,
-                     int /* request_id */,
-                     url::Origin /* origin */,
-                     base::string16 /* fetch_store_name */)
-
-IPC_MESSAGE_CONTROL3(CacheStorageHostMsg_CacheStorageKeys,
-                     int /* thread_id */,
-                     int /* request_id */,
-                     url::Origin /* origin */)
-
-IPC_MESSAGE_CONTROL5(CacheStorageHostMsg_CacheStorageMatch,
-                     int /* thread_id */,
-                     int /* request_id */,
-                     url::Origin /* origin */,
-                     content::ServiceWorkerFetchRequest,
-                     content::CacheStorageCacheQueryParams)
-
-// Cache operations in the browser.
-IPC_MESSAGE_CONTROL5(CacheStorageHostMsg_CacheMatch,
-                     int /* thread_id */,
-                     int /* request_id */,
-                     int /* cache_id */,
-                     content::ServiceWorkerFetchRequest,
-                     content::CacheStorageCacheQueryParams)
-
-IPC_MESSAGE_CONTROL5(CacheStorageHostMsg_CacheMatchAll,
-                     int /* thread_id */,
-                     int /* request_id */,
-                     int /* cache_id */,
-                     content::ServiceWorkerFetchRequest,
-                     content::CacheStorageCacheQueryParams)
-
-IPC_MESSAGE_CONTROL5(CacheStorageHostMsg_CacheKeys,
-                     int /* thread_id */,
-                     int /* request_id */,
-                     int /* cache_id */,
-                     content::ServiceWorkerFetchRequest,
-                     content::CacheStorageCacheQueryParams)
-
-IPC_MESSAGE_CONTROL4(CacheStorageHostMsg_CacheBatch,
-                     int /* thread_id */,
-                     int /* request_id */,
-                     int /* cache_id */,
-                     std::vector<content::CacheStorageBatchOperation>)
-
-IPC_MESSAGE_CONTROL1(CacheStorageHostMsg_CacheClosed,
-                     int /* cache_id */)
-
-IPC_MESSAGE_CONTROL1(CacheStorageHostMsg_BlobDataHandled,
-                     std::string /* uuid */)
-
-//---------------------------------------------------------------------------
-// Messages sent from the browser to the child process.
-//
-// All such messages must includes thread_id as the first int; it is read off
-// by CacheStorageMessageFilter::GetWorkerThreadIdForMessage to route delivery
-// to the appropriate thread.
-
-// Sent at successful completion of CacheStorage operations.
-IPC_MESSAGE_CONTROL2(CacheStorageMsg_CacheStorageHasSuccess,
-                     int /* thread_id */,
-                     int /* request_id */)
-IPC_MESSAGE_CONTROL3(CacheStorageMsg_CacheStorageOpenSuccess,
-                     int /* thread_id */,
-                     int /* request_id */,
-                     int /* fetch_store_id */)
-IPC_MESSAGE_CONTROL2(CacheStorageMsg_CacheStorageDeleteSuccess,
-                     int /* thread_id */,
-                     int /* request_id */)
-IPC_MESSAGE_CONTROL3(CacheStorageMsg_CacheStorageKeysSuccess,
-                     int /* thread_id */,
-                     int /* request_id */,
-                     std::vector<base::string16> /* keys */)
-IPC_MESSAGE_CONTROL3(CacheStorageMsg_CacheStorageMatchSuccess,
-                     int /* thread_id */,
-                     int /* request_id */,
-                     content::ServiceWorkerResponse)
-
-// Sent at erroneous completion of CacheStorage operations.
-IPC_MESSAGE_CONTROL3(CacheStorageMsg_CacheStorageHasError,
-                     int /* thread_id */,
-                     int /* request_id */,
-                     blink::mojom::CacheStorageError /* reason */)
-IPC_MESSAGE_CONTROL3(CacheStorageMsg_CacheStorageOpenError,
-                     int /* thread_id */,
-                     int /* request_id */,
-                     blink::mojom::CacheStorageError /* reason */)
-IPC_MESSAGE_CONTROL3(CacheStorageMsg_CacheStorageDeleteError,
-                     int /* thread_id */,
-                     int /* request_id */,
-                     blink::mojom::CacheStorageError /* reason */)
-IPC_MESSAGE_CONTROL3(CacheStorageMsg_CacheStorageMatchError,
-                     int /* thread_id */,
-                     int /* request_id */,
-                     blink::mojom::CacheStorageError)
-
-// Sent at successful completion of Cache operations.
-IPC_MESSAGE_CONTROL3(CacheStorageMsg_CacheMatchSuccess,
-                     int /* thread_id */,
-                     int /* request_id */,
-                     content::ServiceWorkerResponse)
-IPC_MESSAGE_CONTROL3(CacheStorageMsg_CacheMatchAllSuccess,
-                     int /* thread_id */,
-                     int /* request_id */,
-                     std::vector<content::ServiceWorkerResponse>)
-IPC_MESSAGE_CONTROL3(CacheStorageMsg_CacheKeysSuccess,
-                     int /* thread_id */,
-                     int /* request_id */,
-                     std::vector<content::ServiceWorkerFetchRequest>)
-IPC_MESSAGE_CONTROL2(CacheStorageMsg_CacheBatchSuccess,
-                     int /* thread_id */,
-                     int /* request_id */)
-
-// Sent at erroneous completion of CacheStorage operations.
-IPC_MESSAGE_CONTROL3(CacheStorageMsg_CacheMatchError,
-                     int /* thread_id */,
-                     int /* request_id */,
-                     blink::mojom::CacheStorageError)
-IPC_MESSAGE_CONTROL3(CacheStorageMsg_CacheMatchAllError,
-                     int /* thread_id */,
-                     int /* request_id */,
-                     blink::mojom::CacheStorageError)
-IPC_MESSAGE_CONTROL3(CacheStorageMsg_CacheKeysError,
-                     int /* thread_id */,
-                     int /* request_id */,
-                     blink::mojom::CacheStorageError)
-IPC_MESSAGE_CONTROL3(CacheStorageMsg_CacheBatchError,
-                     int /* thread_id */,
-                     int /* request_id */,
-                     blink::mojom::CacheStorageError)
-
-#endif  // CONTENT_COMMON_CACHE_STORAGE_CACHE_STORAGE_MESSAGES_H_
diff --git a/content/common/content_ipc_logging.cc b/content/common/content_ipc_logging.cc
index 6c5f4c9..9d2a27d 100644
--- a/content/common/content_ipc_logging.cc
+++ b/content/common/content_ipc_logging.cc
@@ -4,7 +4,7 @@
 
 #include <stdint.h>
 
-#include "ipc/ipc_features.h"
+#include "ipc/ipc_buildflags.h"
 
 #if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
 #define IPC_MESSAGE_MACROS_LOG_ENABLED
diff --git a/content/common/content_message_generator.h b/content/common/content_message_generator.h
index 24752ae..ab560944 100644
--- a/content/common/content_message_generator.h
+++ b/content/common/content_message_generator.h
@@ -16,11 +16,6 @@
 #error \
     "Failed to include content/common/browser_plugin/browser_plugin_messages.h"
 #endif
-#undef CONTENT_COMMON_CACHE_STORAGE_CACHE_STORAGE_MESSAGES_H_
-#include "content/common/cache_storage/cache_storage_messages.h"
-#ifndef CONTENT_COMMON_CACHE_STORAGE_CACHE_STORAGE_MESSAGES_H_
-#error "Failed to include content/common/cache_storage/cache_storage_messages.h"
-#endif
 #undef CONTENT_COMMON_DOM_STORAGE_DOM_STORAGE_MESSAGES_H_
 #include "content/common/dom_storage/dom_storage_messages.h"
 #ifndef CONTENT_COMMON_DOM_STORAGE_DOM_STORAGE_MESSAGES_H_
@@ -114,7 +109,7 @@
 #ifndef CONTENT_COMMON_VIEW_MESSAGES_H_
 #error "Failed to include content/common/view_messages.h"
 #endif
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 #undef CONTENT_COMMON_SYNC_COMPOSITOR_MESSAGES_H_
 #include "content/common/input/sync_compositor_messages.h"
diff --git a/content/common/frame.mojom b/content/common/frame.mojom
index 1d485095..51a274b 100644
--- a/content/common/frame.mojom
+++ b/content/common/frame.mojom
@@ -11,8 +11,8 @@
 import "content/public/common/subresource_load_info.mojom";
 import "content/public/common/transferrable_url_loader.mojom";
 import "content/public/common/window_container_type.mojom";
-import "mojo/common/unguessable_token.mojom";
 import "mojo/public/mojom/base/string16.mojom";
+import "mojo/public/mojom/base/unguessable_token.mojom";
 import "services/network/public/mojom/url_loader.mojom";
 import "services/service_manager/public/mojom/interface_provider.mojom";
 import "services/viz/public/interfaces/compositing/surface_id.mojom";
@@ -90,7 +90,7 @@
       URLLoaderFactoryBundle? subresource_loader_factories,
       array<TransferrableURLLoader>? subresource_overrides,
       ControllerServiceWorkerInfo? controller_service_worker_info,
-      mojo.common.mojom.UnguessableToken devtools_navigation_token);
+      mojo_base.mojom.UnguessableToken devtools_navigation_token);
 
   // Tells the renderer that a failed navigation is ready to commit.
   //
@@ -222,7 +222,7 @@
   // attribute them to the context frame.
   // |devtools_frame_token| is only defined by the browser and is never
   // sent back from the renderer in the control calls.
-  mojo.common.mojom.UnguessableToken devtools_main_frame_token;
+  mojo_base.mojom.UnguessableToken devtools_main_frame_token;
 };
 
 // An opaque handle that keeps alive the associated render process even after
@@ -272,8 +272,12 @@
       BeginNavigationParams begin_params);
 
   // Sent when a subresource response has started.
-  SubresourceResponseStarted(
-      SubresourceLoadInfo url_load_info);
+  // |cert_status| is the bitmask of status info of the SSL certificate. (see
+  // net/cert/cert_status_flags.h).
+  SubresourceResponseStarted(url.mojom.Url url, uint32 cert_status);
+
+  // Sent when a subresource load finished, successfully or not.
+  SubresourceLoadComplete(SubresourceLoadInfo url_load_info);
 
   // Sent when the frame changes its window.name.
   DidChangeName(string name, string unique_name);
diff --git a/content/common/input/ime_text_span_conversions.cc b/content/common/input/ime_text_span_conversions.cc
index 77eb93b..cd83e90 100644
--- a/content/common/input/ime_text_span_conversions.cc
+++ b/content/common/input/ime_text_span_conversions.cc
@@ -68,4 +68,50 @@
   return ui::ImeTextSpan::Thickness::kThin;
 }
 
+blink::WebImeTextSpan ConvertUiImeTextSpanToBlinkImeTextSpan(
+    const ui::ImeTextSpan& ui_ime_text_span) {
+  blink::WebImeTextSpan blink_ime_text_span = blink::WebImeTextSpan(
+      ConvertUiImeTextSpanTypeToWebType(ui_ime_text_span.type),
+      ui_ime_text_span.start_offset, ui_ime_text_span.end_offset,
+      ConvertUiThicknessToUiImeTextSpanThickness(ui_ime_text_span.thickness),
+      ui_ime_text_span.background_color,
+      ui_ime_text_span.suggestion_highlight_color,
+      ui_ime_text_span.suggestions);
+  blink_ime_text_span.underline_color = ui_ime_text_span.underline_color;
+  return blink_ime_text_span;
+}
+
+std::vector<blink::WebImeTextSpan> ConvertUiImeTextSpansToBlinkImeTextSpans(
+    const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) {
+  std::vector<blink::WebImeTextSpan> blink_ime_text_spans;
+  for (const auto& ui_ime_text_span : ui_ime_text_spans) {
+    blink_ime_text_spans.push_back(
+        ConvertUiImeTextSpanToBlinkImeTextSpan(ui_ime_text_span));
+  }
+  return blink_ime_text_spans;
+}
+
+ui::ImeTextSpan ConvertBlinkImeTextSpanToUiImeTextSpan(
+    const blink::WebImeTextSpan& blink_ime_text_span) {
+  ui::ImeTextSpan ui_ime_text_span = ui::ImeTextSpan(
+      ConvertWebImeTextSpanTypeToUiType(blink_ime_text_span.type),
+      blink_ime_text_span.start_offset, blink_ime_text_span.end_offset,
+      ConvertUiImeTextSpanThicknessToUiThickness(blink_ime_text_span.thickness),
+      blink_ime_text_span.background_color,
+      blink_ime_text_span.suggestion_highlight_color,
+      blink_ime_text_span.suggestions);
+  ui_ime_text_span.underline_color = blink_ime_text_span.underline_color;
+  return ui_ime_text_span;
+}
+
+std::vector<ui::ImeTextSpan> ConvertBlinkImeTextSpansToUiImeTextSpans(
+    const std::vector<blink::WebImeTextSpan>& blink_ime_text_spans) {
+  std::vector<ui::ImeTextSpan> ui_ime_text_spans;
+  for (const auto& blink_ime_text_span : blink_ime_text_spans) {
+    ui_ime_text_spans.push_back(
+        ConvertBlinkImeTextSpanToUiImeTextSpan(blink_ime_text_span));
+  }
+  return ui_ime_text_spans;
+}
+
 }  // namespace content
diff --git a/content/common/input/ime_text_span_conversions.h b/content/common/input/ime_text_span_conversions.h
index c5d92383..ed37546 100644
--- a/content/common/input/ime_text_span_conversions.h
+++ b/content/common/input/ime_text_span_conversions.h
@@ -18,6 +18,14 @@
     ui::ImeTextSpan::Thickness thickness);
 ui::ImeTextSpan::Thickness ConvertUiImeTextSpanThicknessToUiThickness(
     ui::mojom::ImeTextSpanThickness thickness);
+blink::WebImeTextSpan ConvertUiImeTextSpanToBlinkImeTextSpan(
+    const ui::ImeTextSpan&);
+ui::ImeTextSpan ConvertBlinkImeTextSpanToUiImeTextSpan(
+    const blink::WebImeTextSpan&);
+std::vector<blink::WebImeTextSpan> ConvertUiImeTextSpansToBlinkImeTextSpans(
+    const std::vector<ui::ImeTextSpan>&);
+std::vector<ui::ImeTextSpan> ConvertBlinkImeTextSpansToUiImeTextSpans(
+    const std::vector<blink::WebImeTextSpan>&);
 
 }  // namespace content
 
diff --git a/content/common/media/media_player_delegate_messages.h b/content/common/media/media_player_delegate_messages.h
index 14824d1..9573848 100644
--- a/content/common/media/media_player_delegate_messages.h
+++ b/content/common/media/media_player_delegate_messages.h
@@ -83,4 +83,7 @@
                     int /* delegate_id, distinguishes instances */,
                     gfx::Size /* new size of video */)
 
+IPC_MESSAGE_ROUTED1(MediaPlayerDelegateHostMsg_OnPictureInPictureSourceChanged,
+                    int /* delegate id */)
+
 #endif  // CONTENT_COMMON_MEDIA_MEDIA_PLAYER_DELEGATE_MESSAGES_H_
diff --git a/content/common/render_message_filter.mojom b/content/common/render_message_filter.mojom
index b0df0aa1..15d97f9 100644
--- a/content/common/render_message_filter.mojom
+++ b/content/common/render_message_filter.mojom
@@ -7,7 +7,7 @@
 import "content/common/input/input_handler.mojom";
 import "content/common/native_types.mojom";
 import "content/common/widget.mojom";
-import "mojo/common/thread_priority.mojom";
+import "mojo/public/mojom/base/thread_priority.mojom";
 import "mojo/public/mojom/base/time.mojom";
 import "url/mojom/origin.mojom";
 import "url/mojom/url.mojom";
@@ -43,5 +43,5 @@
   // Asks the browser to change the priority of thread.
   [EnableIf=supports_thread_priorities]
   SetThreadPriority(int32 platform_thread_id,
-                    mojo.common.mojom.ThreadPriority thread_priority);
+                    mojo_base.mojom.ThreadPriority thread_priority);
 };
diff --git a/content/common/render_widget_window_tree_client_factory.mojom b/content/common/render_widget_window_tree_client_factory.mojom
index 22cc65d..0c1ae21 100644
--- a/content/common/render_widget_window_tree_client_factory.mojom
+++ b/content/common/render_widget_window_tree_client_factory.mojom
@@ -4,14 +4,14 @@
 
 module content.mojom;
 
-import "mojo/common/unguessable_token.mojom";
+import "mojo/public/mojom/base/unguessable_token.mojom";
 import "services/ui/public/interfaces/window_tree.mojom";
 
 interface RenderWidgetWindowTreeClient {
   // Asks the renderer to create a Window for the frame with the routing id
   // |routing_id| and embeds the WindowTreeClient that was previously supplied
   // to ScheduleEmbed().
-  Embed(uint32 frame_routing_id, mojo.common.mojom.UnguessableToken token);
+  Embed(uint32 frame_routing_id, mojo_base.mojom.UnguessableToken token);
 
   // Called when a render frame has been destroyed. This is sent via mojom
   // to handle to ensure there aren't race conditions because of message order
diff --git a/content/common/renderer.mojom b/content/common/renderer.mojom
index ae90246..05886a7 100644
--- a/content/common/renderer.mojom
+++ b/content/common/renderer.mojom
@@ -8,7 +8,7 @@
 import "content/common/service_worker/embedded_worker.mojom";
 import "ipc/constants.mojom";
 import "mojo/public/mojom/base/time.mojom";
-import "mojo/common/unguessable_token.mojom";
+import "mojo/public/mojom/base/unguessable_token.mojom";
 import "services/network/public/mojom/network_types.mojom";
 import "services/service_manager/public/mojom/interface_provider.mojom";
 import "services/service_manager/public/mojom/service.mojom";
@@ -61,7 +61,7 @@
   // attribute them to the context frame.
   // |devtools_main_frame_token| is only defined by the browser and is never
   // sent back from the renderer in the control calls.
-  mojo.common.mojom.UnguessableToken devtools_main_frame_token;
+  mojo_base.mojom.UnguessableToken devtools_main_frame_token;
 
   // The ID of the proxy object for the main frame in this view. It is only
   // used if |swapped_out| is true.
@@ -148,7 +148,7 @@
   // attribute them to the context frame.
   // |devtools_frame_token| is only defined by the browser and is never
   // sent back from the renderer in the control calls.
-  mojo.common.mojom.UnguessableToken devtools_frame_token;
+  mojo_base.mojom.UnguessableToken devtools_frame_token;
 
   // When the new frame has a parent, |frame_owner_properties| holds the
   // properties of the HTMLFrameOwnerElement from the parent process.
@@ -210,7 +210,7 @@
   CreateFrameProxy(int32 routing_id, int32 render_view_routing_id,
                    int32 opener_routing_id, int32 parent_routing_id,
                    FrameReplicationState replication_state,
-                   mojo.common.mojom.UnguessableToken devtools_frame_token);
+                   mojo_base.mojom.UnguessableToken devtools_frame_token);
 
   // Tells the renderer that the network type has changed so that
   // navigator.onLine and navigator.connection can be updated.
diff --git a/content/common/sandbox_init_mac.cc b/content/common/sandbox_init_mac.cc
index a9823f7..583e283 100644
--- a/content/common/sandbox_init_mac.cc
+++ b/content/common/sandbox_init_mac.cc
@@ -4,7 +4,7 @@
 
 #include "content/public/common/sandbox_init.h"
 
-#include "base/callback.h"
+#include "base/bind.h"
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
@@ -13,6 +13,7 @@
 #include "gpu/config/gpu_info.h"
 #include "gpu/config/gpu_info_collector.h"
 #include "gpu/config/gpu_switches.h"
+#include "gpu/config/gpu_switching.h"
 #include "gpu/config/gpu_util.h"
 #include "gpu/ipc/common/gpu_preferences_util.h"
 #include "media/gpu/vt_video_decode_accelerator_mac.h"
@@ -56,6 +57,10 @@
             gpu_preferences.log_gpu_control_list_decisions, command_line,
             nullptr);
         gpu::CacheGpuFeatureInfo(gpu_feature_info);
+        if (gpu::SwitchableGPUsSupported(gpu_info, *command_line)) {
+          gpu::InitializeSwitchableGPUs(
+              gpu_feature_info.enabled_gpu_driver_bug_workarounds);
+        }
         // Preload either the desktop GL or the osmesa so, depending on the
         // --use-gl flag.
         gl::init::InitializeGLOneOff();
diff --git a/content/common/service_worker/embedded_worker.mojom b/content/common/service_worker/embedded_worker.mojom
index 4bc560f..c5a6aad 100644
--- a/content/common/service_worker/embedded_worker.mojom
+++ b/content/common/service_worker/embedded_worker.mojom
@@ -10,7 +10,7 @@
 import "content/common/service_worker/service_worker_provider.mojom";
 import "mojo/public/mojom/base/string16.mojom";
 import "mojo/public/mojom/base/time.mojom";
-import "mojo/common/unguessable_token.mojom";
+import "mojo/public/mojom/base/unguessable_token.mojom";
 import "services/service_manager/public/mojom/interface_provider.mojom";
 import "third_party/WebKit/public/mojom/service_worker/service_worker.mojom";
 import "third_party/WebKit/public/mojom/service_worker/service_worker_installed_scripts_manager.mojom";
@@ -38,7 +38,7 @@
   // The id to talk with the DevTools agent for the worker.
   int32 worker_devtools_agent_route_id;
   // Unique token identifying this worker for DevTools.
-  mojo.common.mojom.UnguessableToken devtools_worker_token;
+  mojo_base.mojom.UnguessableToken devtools_worker_token;
   // When true, worker script evaluation is blocked until
   // EmbeddedWorkerInstanceClient::ResumeAfterDownload() is called.
   bool pause_after_download;
diff --git a/content/common/shared_worker/shared_worker_factory.mojom b/content/common/shared_worker/shared_worker_factory.mojom
index ef8dffb..d322351 100644
--- a/content/common/shared_worker/shared_worker_factory.mojom
+++ b/content/common/shared_worker/shared_worker_factory.mojom
@@ -7,7 +7,7 @@
 import "content/common/shared_worker/shared_worker.mojom";
 import "content/common/shared_worker/shared_worker_host.mojom";
 import "content/common/shared_worker/shared_worker_info.mojom";
-import "mojo/common/unguessable_token.mojom";
+import "mojo/public/mojom/base/unguessable_token.mojom";
 import "services/service_manager/public/mojom/interface_provider.mojom";
 import "third_party/WebKit/public/web/worker_content_settings_proxy.mojom";
 
@@ -27,7 +27,7 @@
   CreateSharedWorker(
       SharedWorkerInfo info,
       bool pause_on_start,
-      mojo.common.mojom.UnguessableToken devtools_worker_token,
+      mojo_base.mojom.UnguessableToken devtools_worker_token,
       blink.mojom.WorkerContentSettingsProxy content_settings,
       SharedWorkerHost host,
       SharedWorker& shared_worker,
diff --git a/content/gpu/BUILD.gn b/content/gpu/BUILD.gn
index 5504b50..3e85872 100644
--- a/content/gpu/BUILD.gn
+++ b/content/gpu/BUILD.gn
@@ -66,9 +66,9 @@
     "//gpu/ipc/common:gpu_preferences_util",
     "//gpu/ipc/service",
     "//ipc",
-    "//media:media_features",
+    "//media:media_buildflags",
     "//media/gpu",
-    "//media/mojo:features",
+    "//media/mojo:buildflags",
 
     # TODO(jrummell): As //media/gpu/ipc/service is a source_set in a
     # component build, determine if it should not be included here.
diff --git a/content/gpu/gpu_main.cc b/content/gpu/gpu_main.cc
index 115f871..d9c8b6d 100644
--- a/content/gpu/gpu_main.cc
+++ b/content/gpu/gpu_main.cc
@@ -41,7 +41,7 @@
 #include "gpu/ipc/service/gpu_config.h"
 #include "gpu/ipc/service/gpu_init.h"
 #include "gpu/ipc/service/gpu_watchdog_thread.h"
-#include "media/gpu/features.h"
+#include "media/gpu/buildflags.h"
 #include "third_party/angle/src/gpu_info_util/SystemInfo.h"
 #include "third_party/skia/include/core/SkGraphics.h"
 #include "ui/events/platform/platform_event_source.h"
diff --git a/content/gpu/gpu_sandbox_hook_linux.cc b/content/gpu/gpu_sandbox_hook_linux.cc
index 5c4013c..ddd7b99 100644
--- a/content/gpu/gpu_sandbox_hook_linux.cc
+++ b/content/gpu/gpu_sandbox_hook_linux.cc
@@ -18,7 +18,7 @@
 #include "build/build_config.h"
 #include "build/buildflag.h"
 #include "content/public/common/content_switches.h"
-#include "media/gpu/features.h"
+#include "media/gpu/buildflags.h"
 #include "sandbox/linux/bpf_dsl/policy.h"
 #include "sandbox/linux/syscall_broker/broker_command.h"
 #include "sandbox/linux/syscall_broker/broker_file_permission.h"
diff --git a/content/gpu/gpu_service_factory.h b/content/gpu/gpu_service_factory.h
index bfda1120..ec30ff72 100644
--- a/content/gpu/gpu_service_factory.h
+++ b/content/gpu/gpu_service_factory.h
@@ -12,7 +12,7 @@
 #include "content/child/service_factory.h"
 #include "gpu/command_buffer/service/gpu_preferences.h"
 #include "media/base/android_overlay_mojo_factory.h"
-#include "media/mojo/features.h"
+#include "media/mojo/buildflags.h"
 
 namespace media {
 class MediaGpuChannelManager;
diff --git a/content/ppapi_plugin/BUILD.gn b/content/ppapi_plugin/BUILD.gn
index 3ed5cf0..da7a293 100644
--- a/content/ppapi_plugin/BUILD.gn
+++ b/content/ppapi_plugin/BUILD.gn
@@ -56,7 +56,7 @@
     "//content/public/child:child_sources",
     "//content/public/common:common_sources",
     "//gin",
-    "//media:media_features",
+    "//media:media_buildflags",
     "//ppapi/c",
     "//ppapi/proxy",
     "//ppapi/proxy:ipc",
diff --git a/content/ppapi_plugin/ppapi_thread.cc b/content/ppapi_plugin/ppapi_thread.cc
index 4aaef98..4de43c1 100644
--- a/content/ppapi_plugin/ppapi_thread.cc
+++ b/content/ppapi_plugin/ppapi_thread.cc
@@ -42,7 +42,7 @@
 #include "ipc/ipc_platform_file.h"
 #include "ipc/ipc_sync_channel.h"
 #include "ipc/ipc_sync_message_filter.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "ppapi/c/dev/ppp_network_state_dev.h"
 #include "ppapi/c/pp_errors.h"
 #include "ppapi/c/ppp.h"
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn
index 7010db6..c2645bb 100644
--- a/content/public/android/BUILD.gn
+++ b/content/public/android/BUILD.gn
@@ -208,6 +208,7 @@
     "java/src/org/chromium/content/browser/picker/WeekPickerDialog.java",
     "java/src/org/chromium/content/browser/remoteobjects/RemoteObjectAuditorImpl.java",
     "java/src/org/chromium/content/browser/remoteobjects/RemoteObjectImpl.java",
+    "java/src/org/chromium/content/browser/selection/AdditionalMenuItemProvider.java",
     "java/src/org/chromium/content/browser/selection/FloatingActionModeCallback.java",
     "java/src/org/chromium/content/browser/selection/FloatingPastePopupMenu.java",
     "java/src/org/chromium/content/browser/selection/HandleViewResources.java",
@@ -429,10 +430,10 @@
     "//media/capture/video/android:capture_java",
     "//media/mojo/interfaces:interfaces_java",
     "//mojo/android:system_java",
-    "//mojo/common:common_custom_types_java",
     "//mojo/public/interfaces/bindings/tests:test_interfaces_java",
     "//mojo/public/java:bindings_java",
     "//mojo/public/java:system_java",
+    "//mojo/public/mojom/base:base_java",
     "//net/android:net_java",
     "//net/android:net_java_test_support",
     "//third_party/android_support_test_runner:rules_java",
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentClassFactory.java b/content/public/android/java/src/org/chromium/content/browser/ContentClassFactory.java
index fd6e2af..45607c57 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentClassFactory.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentClassFactory.java
@@ -5,6 +5,7 @@
 package org.chromium.content.browser;
 
 import org.chromium.base.ThreadUtils;
+import org.chromium.content.browser.selection.AdditionalMenuItemProvider;
 import org.chromium.content.browser.selection.SelectionInsertionHandleObserver;
 import org.chromium.content.browser.selection.SelectionPopupControllerImpl;
 
@@ -46,4 +47,12 @@
         // Implemented by a subclass.
         return null;
     }
+
+    /**
+     * Creates AddtionalMenuItems object.
+     */
+    public AdditionalMenuItemProvider createAddtionalMenuItemProvider() {
+        // Implemented by a subclass.
+        return null;
+    }
 }
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCoreImpl.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCoreImpl.java
index 1896162..85152da1 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCoreImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCoreImpl.java
@@ -9,7 +9,6 @@
 import android.content.res.Configuration;
 import android.os.Build;
 import android.os.SystemClock;
-import android.view.HapticFeedbackConstants;
 import android.view.InputDevice;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
@@ -33,7 +32,6 @@
 import org.chromium.content_public.browser.ActionModeCallbackHelper;
 import org.chromium.content_public.browser.ContentViewCore;
 import org.chromium.content_public.browser.ContentViewCore.InternalAccessDelegate;
-import org.chromium.content_public.browser.GestureStateListener;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_public.browser.WebContentsObserver;
 import org.chromium.device.gamepad.GamepadList;
@@ -91,49 +89,6 @@
         }
     }
 
-    /**
-     * A {@link GestureStateListener} updating input/selection UI upon various
-     * gesture events notification.
-     */
-    private class ContentGestureStateListener implements GestureStateListener {
-        @Override
-        public void onFlingStartGesture(int scrollOffsetY, int scrollExtentY) {
-            getGestureListenerManager().setTouchScrollInProgress(false);
-        }
-
-        @Override
-        public void onFlingEndGesture(int scrollOffsetY, int scrollExtentY) {
-            // Note that mTouchScrollInProgress should normally be false at this
-            // point, but we reset it anyway as another failsafe.
-            getGestureListenerManager().setTouchScrollInProgress(false);
-        }
-
-        @Override
-        public void onScrollStarted(int scrollOffsetY, int scrollExtentY) {
-            getGestureListenerManager().setTouchScrollInProgress(false);
-        }
-
-        @Override
-        public void onScrollUpdateGestureConsumed() {
-            destroyPastePopup();
-        }
-
-        @Override
-        public void onScrollEnded(int scrollOffsetY, int scrollExtentY) {
-            getGestureListenerManager().setTouchScrollInProgress(false);
-        }
-
-        @Override
-        public void onSingleTap(boolean consumed) {
-            destroyPastePopup();
-        }
-
-        @Override
-        public void onLongPress() {
-            mContainerView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
-        }
-    }
-
     private Context mContext;
     private final ObserverList<WindowEventObserver> mWindowEventObservers = new ObserverList<>();
 
@@ -141,6 +96,7 @@
     private InternalAccessDelegate mContainerViewInternals;
     private WebContentsImpl mWebContents;
     private WebContentsObserver mWebContentsObserver;
+    private WindowAndroid mWindowAndroid;
 
     // Native pointer to C++ ContentViewCore object which will be set by nativeInit().
     private long mNativeContentViewCore;
@@ -205,10 +161,8 @@
         return mWebContents;
     }
 
-    @Override
-    public WindowAndroid getWindowAndroid() {
-        if (mNativeContentViewCore == 0) return null;
-        return nativeGetJavaWindowAndroid(mNativeContentViewCore);
+    private WindowAndroid getWindowAndroid() {
+        return mWindowAndroid;
     }
 
     /**
@@ -244,7 +198,7 @@
         mContext = context;
 
         mViewAndroidDelegate = viewDelegate;
-
+        mWindowAndroid = windowAndroid;
         final float dipScale = windowAndroid.getDisplay().getDipScale();
 
         mNativeContentViewCore =
@@ -274,8 +228,6 @@
         SelectPopup.create(mContext, mWebContents, containerView);
         mWebContentsObserver = new ContentViewWebContentsObserver(this);
 
-        getGestureListenerManager().addListener(new ContentGestureStateListener());
-
         mWindowEventObservers.addObserver(controller);
         mWindowEventObservers.addObserver(getGestureListenerManager());
         mWindowEventObservers.addObserver(textSuggestionHost);
@@ -291,6 +243,7 @@
     @Override
     public void updateWindowAndroid(WindowAndroid windowAndroid) {
         removeDisplayAndroidObserver();
+        mWindowAndroid = windowAndroid;
         nativeUpdateWindowAndroid(mNativeContentViewCore, windowAndroid);
 
         // TODO(yusufo): Rename this call to be general for tab reparenting.
@@ -493,18 +446,6 @@
         }
     }
 
-    @CalledByNative
-    private void onTouchDown(MotionEvent event) {
-        cancelRequestToScrollFocusedEditableNodeIntoView();
-        getGestureListenerManager().updateOnTouchDown();
-    }
-
-    private void cancelRequestToScrollFocusedEditableNodeIntoView() {
-        // Zero-ing the rect will prevent |updateAfterSizeChanged()| from
-        // issuing the delayed form focus event.
-        getImeAdapter().getFocusPreOSKViewportRect().setEmpty();
-    }
-
     @Override
     public void onPause() {
         onFocusChanged(false, true);
@@ -543,7 +484,7 @@
         if (gainFocus) {
             controller.restoreSelectionPopupsIfNecessary();
         } else {
-            cancelRequestToScrollFocusedEditableNodeIntoView();
+            getImeAdapter().cancelRequestToScrollFocusedEditableNodeIntoView();
             if (controller.getPreserveSelectionOnNextLossOfFocus()) {
                 controller.setPreserveSelectionOnNextLossOfFocus(false);
                 hidePopupsAndPreserveSelection();
@@ -786,7 +727,6 @@
     private native long nativeInit(WebContents webContents, ViewAndroidDelegate viewAndroidDelegate,
             WindowAndroid window, float dipScale);
     private native void nativeUpdateWindowAndroid(long nativeContentViewCore, WindowAndroid window);
-    private native WindowAndroid nativeGetJavaWindowAndroid(long nativeContentViewCore);
     private native void nativeOnJavaContentViewCoreDestroyed(long nativeContentViewCore);
     private native void nativeSetFocus(long nativeContentViewCore, boolean focused);
     private native void nativeSetDIPScale(long nativeContentViewCore, float dipScale);
diff --git a/content/public/android/java/src/org/chromium/content/browser/GestureListenerManagerImpl.java b/content/public/android/java/src/org/chromium/content/browser/GestureListenerManagerImpl.java
index f4d371f..4a0dc3f 100644
--- a/content/public/android/java/src/org/chromium/content/browser/GestureListenerManagerImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/GestureListenerManagerImpl.java
@@ -4,6 +4,7 @@
 
 package org.chromium.content.browser;
 
+import android.view.HapticFeedbackConstants;
 import android.view.View;
 
 import org.chromium.base.ObserverList;
@@ -97,7 +98,8 @@
     }
 
     /** Update all the listeners after touch down event occurred. */
-    public void updateOnTouchDown() {
+    @CalledByNative
+    private void updateOnTouchDown() {
         for (mIterator.rewind(); mIterator.hasNext();) mIterator.next().onTouchDown();
     }
 
@@ -128,6 +130,7 @@
 
     /** Update all the listeners after scrolling end event occurred. */
     public void updateOnScrollEnd() {
+        setTouchScrollInProgress(false);
         for (mIterator.rewind(); mIterator.hasNext();) {
             mIterator.next().onScrollEnded(verticalScrollOffset(), verticalScrollExtent());
         }
@@ -155,6 +158,9 @@
     @CalledByNative
     private void onFlingEnd() {
         if (mPotentiallyActiveFlingCount > 0) mPotentiallyActiveFlingCount--;
+        // Note that mTouchScrollInProgress should normally be false at this
+        // point, but we reset it anyway as another failsafe.
+        setTouchScrollInProgress(false);
         for (mIterator.rewind(); mIterator.hasNext();) {
             mIterator.next().onFlingEndGesture(verticalScrollOffset(), verticalScrollExtent());
         }
@@ -163,6 +169,7 @@
     @CalledByNative
     private void onFlingStartEventConsumed() {
         mPotentiallyActiveFlingCount++;
+        setTouchScrollInProgress(false);
         for (mIterator.rewind(); mIterator.hasNext();) {
             mIterator.next().onFlingStartGesture(verticalScrollOffset(), verticalScrollExtent());
         }
@@ -170,6 +177,7 @@
 
     @CalledByNative
     private void onScrollBeginEventAck() {
+        setTouchScrollInProgress(false);
         for (mIterator.rewind(); mIterator.hasNext();) {
             mIterator.next().onScrollStarted(verticalScrollOffset(), verticalScrollExtent());
         }
@@ -182,6 +190,8 @@
 
     @CalledByNative
     private void onScrollUpdateGestureConsumed() {
+        SelectionPopupControllerImpl controller = getSelectionPopupController();
+        if (controller != null) controller.destroyPastePopup();
         for (mIterator.rewind(); mIterator.hasNext();) {
             mIterator.next().onScrollUpdateGestureConsumed();
         }
@@ -199,11 +209,14 @@
 
     @CalledByNative
     private void onSingleTapEventAck(boolean consumed) {
+        SelectionPopupControllerImpl controller = getSelectionPopupController();
+        if (controller != null) controller.destroyPastePopup();
         for (mIterator.rewind(); mIterator.hasNext();) mIterator.next().onSingleTap(consumed);
     }
 
     @CalledByNative
     private void onLongPressAck() {
+        mContainerView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
         for (mIterator.rewind(); mIterator.hasNext();) mIterator.next().onLongPress();
     }
 
diff --git a/content/public/android/java/src/org/chromium/content/browser/NfcHost.java b/content/public/android/java/src/org/chromium/content/browser/NfcHost.java
index 3aa492b..ae7ffc4 100644
--- a/content/public/android/java/src/org/chromium/content/browser/NfcHost.java
+++ b/content/public/android/java/src/org/chromium/content/browser/NfcHost.java
@@ -69,14 +69,10 @@
         // a request to track activity changes while there is already such a request.
         assert mCallback == null : "Unexpected request to track activity changes";
         mCallback = callback;
-        Activity activity = null;
 
         mContentViewCore.addWindowAndroidChangedObserver(this);
-        if (mContentViewCore.getWindowAndroid() != null) {
-            activity = mContentViewCore.getWindowAndroid().getActivity().get();
-        }
-
-        mCallback.onResult(activity);
+        WindowAndroid window = mWebContents.getTopLevelNativeWindow();
+        mCallback.onResult(window != null ? window.getActivity().get() : null);
     }
 
     /**
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java b/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java
index 12908805..c6f1099 100644
--- a/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java
@@ -535,10 +535,6 @@
         }
     }
 
-    public Rect getFocusPreOSKViewportRect() {
-        return mFocusPreOSKViewportRect;
-    }
-
     @CalledByNative
     private void updateAfterViewSizeChanged() {
         // Execute a delayed form focus operation because the OSK was brought up earlier.
@@ -553,11 +549,20 @@
                 }
                 // Zero the rect to prevent the above operation from issuing the delayed
                 // form focus event.
-                mFocusPreOSKViewportRect.setEmpty();
+                cancelRequestToScrollFocusedEditableNodeIntoView();
             }
         }
     }
 
+    @CalledByNative
+    private void updateOnTouchDown() {
+        cancelRequestToScrollFocusedEditableNodeIntoView();
+    }
+
+    public void cancelRequestToScrollFocusedEditableNodeIntoView() {
+        mFocusPreOSKViewportRect.setEmpty();
+    }
+
     @Override
     public ResultReceiver getNewShowKeyboardReceiver() {
         if (mShowKeyboardResultReceiver == null) {
diff --git a/content/public/android/java/src/org/chromium/content/browser/selection/AdditionalMenuItemProvider.java b/content/public/android/java/src/org/chromium/content/browser/selection/AdditionalMenuItemProvider.java
new file mode 100644
index 0000000..777d4f9
--- /dev/null
+++ b/content/public/android/java/src/org/chromium/content/browser/selection/AdditionalMenuItemProvider.java
@@ -0,0 +1,36 @@
+// Copyright 2018 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.
+
+package org.chromium.content.browser.selection;
+
+import android.content.Context;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.textclassifier.TextClassification;
+
+/**
+ * An interface for adding more menu items.
+ */
+public interface AdditionalMenuItemProvider {
+    /**
+     * Add menu items to the menu passed in.
+     * @param context The context from app.
+     * @param menu Add menu items to this menu.
+     * @param classification Providing info to generate menu items.
+     */
+    void addMenuItems(Context context, Menu menu, TextClassification classification);
+
+    /**
+     * Call this to trigger internal cleanup.
+     */
+    void clearMenuItemListeners();
+
+    /**
+     * Perform action for menu item.
+     * @param item The clicked menu item.
+     * @param view Perform action on this view.
+     */
+    void performAction(MenuItem item, View view);
+}
diff --git a/content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java b/content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java
index c696d51..ead39d3 100644
--- a/content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java
@@ -173,6 +173,8 @@
      */
     private SelectionInsertionHandleObserver mHandleObserver;
 
+    private AdditionalMenuItemProvider mAdditionalMenuItemProvider;
+
     /**
      * An interface for getting {@link View} for readback.
      */
@@ -274,6 +276,7 @@
         mResultCallback = new SmartSelectionCallback();
         mLastSelectedText = "";
         initHandleObserver();
+        mAdditionalMenuItemProvider = ContentClassFactory.get().createAddtionalMenuItemProvider();
         if (initializeNative) mNativeSelectionPopupController = nativeInit(mWebContents);
         getPopupController().registerPopup(this);
         mInitialized = true;
@@ -663,9 +666,14 @@
 
     @Override
     public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+        if (mAdditionalMenuItemProvider != null) {
+            mAdditionalMenuItemProvider.clearMenuItemListeners();
+        }
+        // Only remove action mode items we added. See more http://crbug.com/709878.
         menu.removeGroup(R.id.select_action_menu_default_items);
         menu.removeGroup(R.id.select_action_menu_assist_items);
         menu.removeGroup(R.id.select_action_menu_text_processing_menus);
+        menu.removeGroup(android.R.id.textAssist);
         createActionMenu(mode, menu);
         return true;
     }
@@ -703,6 +711,11 @@
 
         setPasteAsPlainTextMenuItemTitle(menu);
 
+        if (mClassificationResult != null && mAdditionalMenuItemProvider != null) {
+            mAdditionalMenuItemProvider.addMenuItems(
+                    mContext, menu, mClassificationResult.textClassification);
+        }
+
         if (!hasSelection() || isSelectionPassword()) return;
 
         initializeTextProcessingMenu(menu);
@@ -857,10 +870,10 @@
 
         if (hasSelection() && mSelectionMetricsLogger != null) {
             mSelectionMetricsLogger.logSelectionAction(mLastSelectedText, mLastSelectionOffset,
-                    getActionType(id), mClassificationResult);
+                    getActionType(id, groupId), mClassificationResult);
         }
 
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && id == android.R.id.textAssist) {
+        if (groupId == R.id.select_action_menu_assist_items && id == android.R.id.textAssist) {
             doAssistAction();
             mode.finish();
         } else if (id == R.id.select_action_menu_select_all) {
@@ -888,6 +901,11 @@
             processText(item.getIntent());
             // The ActionMode is not dismissed to match the behavior with
             // TextView in Android M.
+        } else if (groupId == android.R.id.textAssist) {
+            if (mAdditionalMenuItemProvider != null) {
+                mAdditionalMenuItemProvider.performAction(item, mView);
+                mode.finish();
+            }
         } else {
             return false;
         }
@@ -937,7 +955,10 @@
         return mWebContents.getRenderCoordinates().getDeviceScaleFactor();
     }
 
-    private int getActionType(int menuItemId) {
+    private int getActionType(int menuItemId, int menuItemGroupId) {
+        if (menuItemGroupId == android.R.id.textAssist) {
+            return SmartSelectionMetricsLogger.ActionType.SMART_SHARE;
+        }
         if (menuItemId == R.id.select_action_menu_select_all) {
             return SmartSelectionMetricsLogger.ActionType.SELECT_ALL;
         }
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/ContentViewCore.java b/content/public/android/java/src/org/chromium/content_public/browser/ContentViewCore.java
index a9de30f..54d55ca 100644
--- a/content/public/android/java/src/org/chromium/content_public/browser/ContentViewCore.java
+++ b/content/public/android/java/src/org/chromium/content_public/browser/ContentViewCore.java
@@ -98,11 +98,6 @@
     WebContents getWebContents();
 
     /**
-     * @return The WindowAndroid associated with this ContentViewCore.
-     */
-    WindowAndroid getWindowAndroid();
-
-    /**
      * Updates the native {@link ContentViewCore} with a new window. This moves the NativeView and
      * attached it to the new NativeWindow linked with the given {@link WindowAndroid}.
      * @param windowAndroid The new {@link WindowAndroid} for this {@link ContentViewCore}.
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ScreenOrientationListenerTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ScreenOrientationListenerTest.java
index 3b2d3c1..6b88b3f 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/ScreenOrientationListenerTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/ScreenOrientationListenerTest.java
@@ -70,7 +70,7 @@
             @Override
             public void run() {
                 mDisplayAndroid =
-                        mActivityTestRule.getContentViewCore().getWindowAndroid().getDisplay();
+                        mActivityTestRule.getWebContents().getTopLevelNativeWindow().getDisplay();
                 mDisplayAndroid.addObserver(mCallbackHelper);
                 DisplayAndroid.startAccurateListening();
             }
@@ -246,7 +246,7 @@
             @Override
             public void run() {
                 ScreenOrientationProvider.lockOrientation(
-                        mActivityTestRule.getContentViewCore().getWindowAndroid(),
+                        mActivityTestRule.getWebContents().getTopLevelNativeWindow(),
                         (byte) orientationValue);
             }
         });
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/VSyncPausedTest.java b/content/public/android/javatests/src/org/chromium/content/browser/VSyncPausedTest.java
index b7a9f5d..daf8ac7 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/VSyncPausedTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/VSyncPausedTest.java
@@ -73,8 +73,10 @@
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                mActivity.getActiveShell().getContentViewCore().getWindowAndroid().setVSyncPaused(
-                        true);
+                mActivity.getActiveShell()
+                        .getWebContents()
+                        .getTopLevelNativeWindow()
+                        .setVSyncPaused(true);
             }
         });
         callCount = mOnTitleUpdatedHelper.getCallCount();
@@ -104,8 +106,10 @@
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                mActivity.getActiveShell().getContentViewCore().getWindowAndroid().setVSyncPaused(
-                        false);
+                mActivity.getActiveShell()
+                        .getWebContents()
+                        .getTopLevelNativeWindow()
+                        .setVSyncPaused(false);
             }
         });
         mOnTitleUpdatedHelper.waitForCallback(callCount);
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/androidoverlay/DialogOverlayImplTestRule.java b/content/public/android/javatests/src/org/chromium/content/browser/androidoverlay/DialogOverlayImplTestRule.java
index cb6f8e7..031fef0 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/androidoverlay/DialogOverlayImplTestRule.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/androidoverlay/DialogOverlayImplTestRule.java
@@ -17,8 +17,8 @@
 import org.chromium.content_shell_apk.ContentShellActivityTestRule;
 import org.chromium.media.mojom.AndroidOverlayClient;
 import org.chromium.media.mojom.AndroidOverlayConfig;
-import org.chromium.mojo.common.mojom.UnguessableToken;
 import org.chromium.mojo.system.MojoException;
+import org.chromium.mojo_base.mojom.UnguessableToken;
 
 import java.util.concurrent.ArrayBlockingQueue;
 import java.util.concurrent.Callable;
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java b/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java
index 1c80681..daecbc6 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java
@@ -1676,14 +1676,14 @@
                                         + "  document.getElementById('div').firstChild, "
                                         + "  'composition', 1)")));
 
-        Assert.assertEquals(0x0000000L,
+        Assert.assertEquals(0x00000000L,
                 (long) Double.parseDouble(
                         JavaScriptUtils.executeJavaScriptAndWaitForResult(webContents,
                                 "internals.markerUnderlineColorForNode("
                                         + "  document.getElementById('div').firstChild, "
                                         + "  'composition', 0)")));
 
-        Assert.assertEquals(0xFF000000L,
+        Assert.assertEquals(0x00000000L,
                 (long) Double.parseDouble(
                         JavaScriptUtils.executeJavaScriptAndWaitForResult(webContents,
                                 "internals.markerUnderlineColorForNode("
diff --git a/content/public/app/mojo/content_browser_manifest.json b/content/public/app/mojo/content_browser_manifest.json
index 24509e4..138da657 100644
--- a/content/public/app/mojo/content_browser_manifest.json
+++ b/content/public/app/mojo/content_browser_manifest.json
@@ -154,7 +154,6 @@
           "blink::mojom::TextSuggestionHost",
           "blink::mojom::UnhandledTapNotifier",
           "blink::mojom::WebBluetoothService",
-          "blink::mojom::WebSocket",
 
           // TODO(beng): figure out how to overlay test interfaces like this.
           "content::mojom::BrowserTarget",
@@ -183,6 +182,7 @@
           "media::mojom::RemoterFactory",
           "media::mojom::Renderer",
           "network::mojom::RestrictedCookieManager",
+          "network::mojom::WebSocket",
           "password_manager::mojom::CredentialManager",
           "payments::mojom::PaymentManager",
           "payments::mojom::PaymentRequest",
@@ -224,8 +224,8 @@
           "blink::mojom::NotificationService",
           "blink::mojom::PermissionService",
           "blink::mojom::QuotaDispatcherHost",
-          "blink::mojom::WebSocket",
           "network::mojom::RestrictedCookieManager",
+          "network::mojom::WebSocket",
           "payments::mojom::PaymentManager",
           "shape_detection::mojom::BarcodeDetection",
           "shape_detection::mojom::FaceDetectionProvider",
@@ -242,7 +242,7 @@
           "blink::mojom::NotificationService",
           "blink::mojom::PermissionService",
           "blink::mojom::QuotaDispatcherHost",
-          "blink::mojom::WebSocket",
+          "network::mojom::WebSocket",
           "payments::mojom::PaymentManager",
           "shape_detection::mojom::BarcodeDetection",
           "shape_detection::mojom::FaceDetectionProvider",
diff --git a/content/public/browser/browser_context.h b/content/public/browser/browser_context.h
index 9edd7b1..e3474b4 100644
--- a/content/public/browser/browser_context.h
+++ b/content/public/browser/browser_context.h
@@ -319,6 +319,7 @@
 
  private:
   const std::string media_device_id_salt_;
+  bool was_notify_will_be_destroyed_called_ = false;
 };
 
 }  // namespace content
diff --git a/content/public/browser/browser_ipc_logging.h b/content/public/browser/browser_ipc_logging.h
index bcbd0b1..a893e6a9 100644
--- a/content/public/browser/browser_ipc_logging.h
+++ b/content/public/browser/browser_ipc_logging.h
@@ -6,7 +6,7 @@
 #define CONTENT_PUBLIC_BROWSER_BROWSER_IPC_LOGGING_H_
 
 #include "content/common/content_export.h"
-#include "ipc/ipc_features.h"
+#include "ipc/ipc_buildflags.h"
 
 namespace content {
 
diff --git a/content/public/browser/browser_thread.h b/content/public/browser/browser_thread.h
index 3869201..666ab793 100644
--- a/content/public/browser/browser_thread.h
+++ b/content/public/browser/browser_thread.h
@@ -172,11 +172,9 @@
   // thread.  To DCHECK this, use the DCHECK_CURRENTLY_ON() macro above.
   static bool CurrentlyOn(ID identifier) WARN_UNUSED_RESULT;
 
-  // Deprecated: This is equivalent to IsThreadInitialized().
   // Callable on any thread.  Returns whether the threads message loop is valid.
   // If this returns false it means the thread is in the process of shutting
   // down.
-  // TODO(gab): Replace callers with IsThreadInitialized().
   static bool IsMessageLoopValid(ID identifier) WARN_UNUSED_RESULT;
 
   // If the current message loop is one of the known threads, returns true and
@@ -190,12 +188,16 @@
 
   // Sets the delegate for BrowserThread::IO.
   //
+  // This only supports the IO thread as it doesn't work for potentially
+  // redirected threads (ref. http://crbug.com/653916) and also doesn't make
+  // sense for the UI thread.
+  //
   // Only one delegate may be registered at a time. The delegate may be
   // unregistered by providing a nullptr pointer.
   //
-  // The delegate can only be registered through this call before
-  // BrowserThreadImpl(BrowserThread::IO) is created and unregistered after
-  // it was destroyed and its underlying thread shutdown.
+  // If the caller unregisters the delegate before CleanUp has been called, it
+  // must perform its own locking to ensure the delegate is not deleted while
+  // unregistering.
   static void SetIOThreadDelegate(BrowserThreadDelegate* delegate);
 
   // Use these templates in conjunction with RefCountedThreadSafe or scoped_ptr
diff --git a/content/public/browser/browser_thread_delegate.h b/content/public/browser/browser_thread_delegate.h
index 3eb823c..696b76d 100644
--- a/content/public/browser/browser_thread_delegate.h
+++ b/content/public/browser/browser_thread_delegate.h
@@ -5,20 +5,22 @@
 #ifndef CONTENT_PUBLIC_BROWSER_BROWSER_THREAD_DELEGATE_H_
 #define CONTENT_PUBLIC_BROWSER_BROWSER_THREAD_DELEGATE_H_
 
-#include "content/common/content_export.h"
-
 namespace content {
 
-// A Delegate for content embedders to perform extra initialization/cleanup on
-// BrowserThread::IO.
+// BrowserThread::SetDelegate was deprecated, this is now only used by
+// BrowserThread::SetIOThreadDelegate.
+//
+// When registered as such, it will schedule to run Init() before the message
+// loop begins and receive a CleanUp call right after the message loop ends (and
+// before the BrowserThread has done its own clean-up).
 class BrowserThreadDelegate {
  public:
   virtual ~BrowserThreadDelegate() = default;
 
-  // Called prior to completing initialization of BrowserThread::IO.
+  // Called prior to starting the message loop
   virtual void Init() = 0;
 
-  // Called during teardown of BrowserThread::IO.
+  // Called just after the message loop ends.
   virtual void CleanUp() = 0;
 };
 
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
index 790f9c1..d0165a7 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -11,6 +11,7 @@
 #include "base/guid.h"
 #include "base/logging.h"
 #include "build/build_config.h"
+#include "content/browser/site_isolation_policy.h"
 #include "content/public/browser/client_certificate_delegate.h"
 #include "content/public/browser/login_delegate.h"
 #include "content/public/browser/memory_coordinator_delegate.h"
@@ -22,7 +23,7 @@
 #include "device/geolocation/public/cpp/location_provider.h"
 #include "media/audio/audio_manager.h"
 #include "media/base/cdm_factory.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "mojo/public/cpp/bindings/associated_interface_ptr.h"
 #include "net/ssl/client_cert_identity.h"
 #include "net/ssl/client_cert_store.h"
@@ -178,6 +179,18 @@
   return std::vector<url::Origin>();
 }
 
+bool ContentBrowserClient::ShouldEnableStrictSiteIsolation() {
+  // By default --site-per-process is turned off for //content embedders.
+  // This ensures that embedders like ChromeCast and/or Opera are not forced
+  // into --site-per-process.
+  return false;
+}
+
+// static
+bool ContentBrowserClient::IsStrictSiteIsolationEnabled() {
+  return SiteIsolationPolicy::UseDedicatedProcessesForAllSites();
+}
+
 bool ContentBrowserClient::IsFileAccessAllowed(
     const base::FilePath& path,
     const base::FilePath& absolute_path,
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index ff7a724..7411c6d 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -28,7 +28,7 @@
 #include "content/public/common/window_container_type.mojom.h"
 #include "device/usb/public/mojom/chooser_service.mojom.h"
 #include "device/usb/public/mojom/device_manager.mojom.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "media/mojo/interfaces/remoting.mojom.h"
 #include "net/base/mime_util.h"
 #include "net/cookies/canonical_cookie.h"
@@ -356,10 +356,25 @@
   // current SiteInstance, if it does not yet have a site.
   virtual bool ShouldAssignSiteForURL(const GURL& url);
 
-  // Allows the embedder to provide a list of origins that require a dedicated
-  // process.
+  // Allows the embedder to programmatically provide some origins that should be
+  // opted into --isolate-origins mode of Site Isolation.
   virtual std::vector<url::Origin> GetOriginsRequiringDedicatedProcess();
 
+  // Allows the embedder to programmatically opt into --site-per-process mode of
+  // Site Isolation.
+  //
+  // Note that for correctness, the same value should be consistently returned.
+  // See also https://crbug.com/825369
+  virtual bool ShouldEnableStrictSiteIsolation();
+
+  // Allows //content embedders to check if --site-per-process has been enabled
+  // (via cmdline flag or via a field trial).
+  //
+  // TODO(lukasza, weili): https://crbug.com/824867: Remove this method after
+  // shipping OOPIF printing (the only caller is in
+  // components/printing/browser/print_manager_utils.cc).
+  static bool IsStrictSiteIsolationEnabled();
+
   // Indicates whether a file path should be accessible via file URL given a
   // request from a browser context which lives within |profile_path|.
   virtual bool IsFileAccessAllowed(const base::FilePath& path,
diff --git a/content/public/browser/download_manager.h b/content/public/browser/download_manager.h
index 11dccbcd..e9480a6 100644
--- a/content/public/browser/download_manager.h
+++ b/content/public/browser/download_manager.h
@@ -51,6 +51,10 @@
 struct DownloadCreateInfo;
 }  // namespace download
 
+namespace network {
+class SharedURLLoaderFactory;
+}  // namespace network
+
 namespace content {
 
 class BrowserContext;
@@ -116,11 +120,13 @@
 
   // Called by a download source (Currently DownloadResourceHandler)
   // to initiate the non-source portions of a download.
-  // Returns the id assigned to the download.  If the DownloadCreateInfo
-  // specifies an id, that id will be used.
+  // If the DownloadCreateInfo specifies an id, that id will be used.
+  // If |shared_url_loader_factory| is provided, it can be used to issue
+  // parallel download requests.
   virtual void StartDownload(
       std::unique_ptr<download::DownloadCreateInfo> info,
       std::unique_ptr<download::InputStream> stream,
+      scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
       const download::DownloadUrlParameters::OnStartedCallback& on_started) = 0;
 
   // Remove downloads whose URLs match the |url_filter| and are within
diff --git a/content/public/browser/gpu_data_manager.h b/content/public/browser/gpu_data_manager.h
index fb7e369..f76ea01 100644
--- a/content/public/browser/gpu_data_manager.h
+++ b/content/public/browser/gpu_data_manager.h
@@ -36,9 +36,8 @@
 
   // This indicator might change because we could collect more GPU info or
   // because the GPU blacklist could be updated.
-  // If this returns false, any further GPU access, including launching GPU
-  // process, establish GPU channel, and GPU info collection, should be
-  // blocked.
+  // If this returns false, any further GPU access, including establishing GPU
+  // channel, and GPU info collection, should be blocked.
   // Can be called on any thread.
   // If |reason| is not nullptr and GPU access is blocked, upon return, |reason|
   // contains a description of the reason why GPU access is blocked.
diff --git a/content/public/browser/gpu_utils.cc b/content/public/browser/gpu_utils.cc
index 7c093dd..b2fd385 100644
--- a/content/public/browser/gpu_utils.cc
+++ b/content/public/browser/gpu_utils.cc
@@ -13,7 +13,7 @@
 #include "gpu/command_buffer/service/gpu_switches.h"
 #include "gpu/command_buffer/service/service_utils.h"
 #include "gpu/config/gpu_switches.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "ui/gl/gl_switches.h"
 
 namespace {
diff --git a/content/public/browser/notification_types.h b/content/public/browser/notification_types.h
index 8fa3bee..778269a 100644
--- a/content/public/browser/notification_types.h
+++ b/content/public/browser/notification_types.h
@@ -96,16 +96,19 @@
   // Indicates that a RenderProcessHost was created and its handle is now
   // available. The source will be the RenderProcessHost that corresponds to
   // the process.
+  // DEPRECATED: Use RenderProcessHostObserver::RenderProcessReady()
   NOTIFICATION_RENDERER_PROCESS_CREATED,
 
   // Indicates that a RenderProcessHost is destructing. The source will be the
   // RenderProcessHost that corresponds to the process.
+  // DEPRECATED: Use RenderProcessHostObserver::RenderProcessHostDestroyed()
   NOTIFICATION_RENDERER_PROCESS_TERMINATED,
 
   // Indicates that a render process was closed (meaning it exited, but the
   // RenderProcessHost might be reused).  The source will be the corresponding
   // RenderProcessHost.  The details will be a RendererClosedDetails struct.
   // This may get sent along with RENDERER_PROCESS_TERMINATED.
+  // DEPRECATED: Use RenderProcessHostObserver::RenderProcessExited()
   NOTIFICATION_RENDERER_PROCESS_CLOSED,
 
   // Indicates that a RenderWidgetHost has become unresponsive for a period of
diff --git a/content/public/browser/render_process_host.h b/content/public/browser/render_process_host.h
index a87b4c6..9bbe37cb 100644
--- a/content/public/browser/render_process_host.h
+++ b/content/public/browser/render_process_host.h
@@ -20,7 +20,7 @@
 #include "content/public/common/bind_interface_helpers.h"
 #include "ipc/ipc_channel_proxy.h"
 #include "ipc/ipc_sender.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "ui/gfx/native_widget_types.h"
 
 #if defined(OS_ANDROID)
diff --git a/content/public/browser/web_contents_observer.h b/content/public/browser/web_contents_observer.h
index 1d99fcc2..5045fd0 100644
--- a/content/public/browser/web_contents_observer.h
+++ b/content/public/browser/web_contents_observer.h
@@ -256,9 +256,9 @@
       const std::string& mime_type,
       ResourceType resource_type) {}
 
-  // This method is invoked when a response has been received for a subresource
-  // request.
-  virtual void SubresourceResponseStarted(
+  // This method is invoked when a subresource has been loaded, successfully or
+  // not.
+  virtual void SubresourceLoadComplete(
       const mojom::SubresourceLoadInfo& subresource_load_info) {}
 
   // This method is invoked when a new non-pending navigation entry is created.
diff --git a/content/public/browser/web_ui.h b/content/public/browser/web_ui.h
index 76bd6a5f..a95b5aa 100644
--- a/content/public/browser/web_ui.h
+++ b/content/public/browser/web_ui.h
@@ -71,7 +71,7 @@
 
   // Used by WebUIMessageHandlers. If the given message is already registered,
   // the call has no effect.
-  typedef base::Callback<void(const base::ListValue*)> MessageCallback;
+  using MessageCallback = base::RepeatingCallback<void(const base::ListValue*)>;
   virtual void RegisterMessageCallback(const std::string& message,
                                        const MessageCallback& callback) = 0;
 
diff --git a/content/public/browser/webrtc_event_logger.h b/content/public/browser/webrtc_event_logger.h
index 926e61d5b..84d6871 100644
--- a/content/public/browser/webrtc_event_logger.h
+++ b/content/public/browser/webrtc_event_logger.h
@@ -11,6 +11,8 @@
 #include "base/files/file_path.h"
 #include "content/common/content_export.h"
 
+class WebRTCInternalsIntegrationBrowserTest;
+
 namespace content {
 
 class BrowserContext;
@@ -133,7 +135,15 @@
           base::OnceCallback<void(std::pair<bool, bool>)>()) = 0;
 
  protected:
+  friend WebRTCInternalsIntegrationBrowserTest;  // (PostNullTaskForTesting)
+
   WebRtcEventLogger();
+
+  // Allows tests to synchronize with internal task queues (if such exist in
+  // the subclass). This allows tests to only examine products (such as log
+  // files) at a time when, if the program is behaving as expected, they would
+  // be guaranteed to be ready.
+  virtual void PostNullTaskForTesting(base::OnceClosure reply) = 0;
 };
 
 }  // namespace content
diff --git a/content/public/browser/webrtc_log.h b/content/public/browser/webrtc_log.h
index 16fefc7..0cc7ab8 100644
--- a/content/public/browser/webrtc_log.h
+++ b/content/public/browser/webrtc_log.h
@@ -10,7 +10,7 @@
 #include "base/callback_forward.h"
 #include "base/macros.h"
 #include "content/common/content_export.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 #if !BUILDFLAG(ENABLE_WEBRTC)
 #error "WebRTC not enabled."
diff --git a/content/public/common/BUILD.gn b/content/public/common/BUILD.gn
index 51ce769..32bd59a 100644
--- a/content/public/common/BUILD.gn
+++ b/content/public/common/BUILD.gn
@@ -82,7 +82,7 @@
 
   # Deps required by the above headers.
   deps = [
-    "//media:media_features",
+    "//media:media_buildflags",
   ]
 }
 
@@ -341,7 +341,7 @@
   deps = [
     ":buildflags",
     "//base",
-    "//media:media_features",
+    "//media:media_buildflags",
   ]
   sources = [
     "feature_h264_with_openh264_ffmpeg.cc",
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index 0fb941dd..6ad786b8 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -347,11 +347,6 @@
 const base::Feature kSignInProcessIsolation{"sign-in-process-isolation",
                                             base::FEATURE_ENABLED_BY_DEFAULT};
 
-// Alternative to switches::kSitePerProcess, for turning on full site isolation.
-// Launch bug: https://crbug.com/739418.
-const base::Feature kSitePerProcess{"site-per-process",
-                                    base::FEATURE_DISABLED_BY_DEFAULT};
-
 // Slimming Paint V1.75. See http://crbug.com/771643.
 const base::Feature kSlimmingPaintV175{"SlimmingPaintV175",
                                        base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index e203073..20a5c65 100644
--- a/content/public/common/content_features.h
+++ b/content/public/common/content_features.h
@@ -86,7 +86,6 @@
 CONTENT_EXPORT extern const base::Feature kSharedArrayBuffer;
 CONTENT_EXPORT extern const base::Feature kSignedHTTPExchange;
 CONTENT_EXPORT extern const base::Feature kSignInProcessIsolation;
-CONTENT_EXPORT extern const base::Feature kSitePerProcess;
 CONTENT_EXPORT extern const base::Feature kSlimmingPaintV175;
 CONTENT_EXPORT extern const base::Feature kStopInBackground;
 CONTENT_EXPORT extern const base::Feature kStopLoadingInBackground;
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index 006e473..c65520b 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -5,7 +5,7 @@
 #include "content/public/common/content_switches.h"
 
 #include "build/build_config.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 namespace switches {
 
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h
index 01da301..654abd3 100644
--- a/content/public/common/content_switches.h
+++ b/content/public/common/content_switches.h
@@ -9,7 +9,7 @@
 
 #include "build/build_config.h"
 #include "content/common/content_export.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 namespace switches {
 
diff --git a/content/public/common/feature_h264_with_openh264_ffmpeg.h b/content/public/common/feature_h264_with_openh264_ffmpeg.h
index 6d81d73..28ac388 100644
--- a/content/public/common/feature_h264_with_openh264_ffmpeg.h
+++ b/content/public/common/feature_h264_with_openh264_ffmpeg.h
@@ -7,7 +7,7 @@
 
 #include "base/feature_list.h"
 #include "content/public/common/buildflags.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 namespace content {
 
diff --git a/content/public/common/subresource_load_info.mojom b/content/public/common/subresource_load_info.mojom
index 4f45ddb9..3cb15c9 100644
--- a/content/public/common/subresource_load_info.mojom
+++ b/content/public/common/subresource_load_info.mojom
@@ -26,7 +26,6 @@
   // The host IP.
   net.interfaces.IPAddress? ip;
 
-  // Bitmask of status info of the SSL certificate.
-  // See net/cert/cert_status_flags.h
-  uint32 cert_status;
+  // True if the response was fetched from the network cache.
+  bool was_cached;
 };
diff --git a/content/public/gpu/content_gpu_client.h b/content/public/gpu/content_gpu_client.h
index 2a0f76c7..1fd10b0 100644
--- a/content/public/gpu/content_gpu_client.h
+++ b/content/public/gpu/content_gpu_client.h
@@ -11,7 +11,7 @@
 #include "base/metrics/field_trial.h"
 #include "base/single_thread_task_runner.h"
 #include "content/public/common/content_client.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
 
 namespace gpu {
diff --git a/content/public/renderer/content_renderer_client.cc b/content/public/renderer/content_renderer_client.cc
index b79384d..816a6a8 100644
--- a/content/public/renderer/content_renderer_client.cc
+++ b/content/public/renderer/content_renderer_client.cc
@@ -134,13 +134,12 @@
   return false;
 }
 
-bool ContentRendererClient::WillSendRequest(
-    blink::WebLocalFrame* frame,
-    ui::PageTransition transition_type,
-    const blink::WebURL& url,
-    GURL* new_url) {
-  return false;
-}
+void ContentRendererClient::WillSendRequest(blink::WebLocalFrame* frame,
+                                            ui::PageTransition transition_type,
+                                            const blink::WebURL& url,
+                                            const url::Origin* initiator_origin,
+                                            GURL* new_url,
+                                            bool* attach_same_site_cookies) {}
 
 bool ContentRendererClient::IsPrefetchOnly(
     RenderFrame* render_frame,
diff --git a/content/public/renderer/content_renderer_client.h b/content/public/renderer/content_renderer_client.h
index 4c8cc50..02815ce 100644
--- a/content/public/renderer/content_renderer_client.h
+++ b/content/public/renderer/content_renderer_client.h
@@ -237,12 +237,18 @@
                           bool* send_referrer);
 
   // Notifies the embedder that the given frame is requesting the resource at
-  // |url|. If the function returns true, the url is changed to |new_url|.
-  virtual bool WillSendRequest(
-      blink::WebLocalFrame* frame,
-      ui::PageTransition transition_type,
-      const blink::WebURL& url,
-      GURL* new_url);
+  // |url|. If the function returns a valid |new_url|, the request must be
+  // updated to use it. The |attach_same_site_cookies| output parameter
+  // determines whether SameSite cookies should be attached to the request.
+  // TODO(nasko): When moved over to Network Service, find a way to perform
+  // this check on the browser side, so untrusted renderer processes cannot
+  // influence whether SameSite cookies are attached.
+  virtual void WillSendRequest(blink::WebLocalFrame* frame,
+                               ui::PageTransition transition_type,
+                               const blink::WebURL& url,
+                               const url::Origin* initiator_origin,
+                               GURL* new_url,
+                               bool* attach_same_site_cookies);
 
   // Returns true if the request is associated with a document that is in
   // ""prefetch only" mode, and will not be rendered.
diff --git a/content/public/renderer/media_stream_utils.cc b/content/public/renderer/media_stream_utils.cc
index 6dff838..8e8977c9 100644
--- a/content/public/renderer/media_stream_utils.cc
+++ b/content/public/renderer/media_stream_utils.cc
@@ -92,6 +92,8 @@
   blink::WebMediaStreamSource::Capabilities capabilities;
   capabilities.device_id = track_id;
   capabilities.echo_cancellation = std::vector<bool>({false});
+  capabilities.auto_gain_control = std::vector<bool>({false});
+  capabilities.noise_suppression = std::vector<bool>({false});
   web_media_stream_source.SetCapabilities(capabilities);
 
   blink::WebMediaStreamTrack web_media_stream_track;
diff --git a/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/DOMUtils.java b/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/DOMUtils.java
index b619ab0..04aee94 100644
--- a/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/DOMUtils.java
+++ b/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/DOMUtils.java
@@ -489,15 +489,15 @@
      * @return the click target of the node in the form of a [ x, y ] array.
      */
     private static int[] getClickTargetForBounds(ContentViewCore viewCore, Rect bounds) {
-        RenderCoordinates coord =
-                ((WebContentsImpl) viewCore.getWebContents()).getRenderCoordinates();
+        WebContentsImpl webContents = (WebContentsImpl) viewCore.getWebContents();
+        RenderCoordinates coord = webContents.getRenderCoordinates();
         int clickX = (int) coord.fromLocalCssToPix(bounds.exactCenterX());
         int clickY = (int) coord.fromLocalCssToPix(bounds.exactCenterY())
                 + getMaybeTopControlsHeight(viewCore);
 
         // This scale will almost always be 1. See the comments on
         // DisplayAndroid#getAndroidUIScaling().
-        float scale = viewCore.getWindowAndroid().getDisplay().getAndroidUIScaling();
+        float scale = webContents.getTopLevelNativeWindow().getDisplay().getAndroidUIScaling();
 
         return new int[] {(int) (clickX * scale), (int) (clickY * scale)};
     }
diff --git a/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/TestContentViewCore.java b/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/TestContentViewCore.java
index d484ab1..91e9dbb4 100644
--- a/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/TestContentViewCore.java
+++ b/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/TestContentViewCore.java
@@ -33,11 +33,6 @@
     }
 
     @Override
-    public WindowAndroid getWindowAndroid() {
-        return null;
-    }
-
-    @Override
     public void updateWindowAndroid(WindowAndroid windowAndroid) {}
 
     @Override
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc
index b634d4a2..194a921 100644
--- a/content/public/test/browser_test_utils.cc
+++ b/content/public/test/browser_test_utils.cc
@@ -1879,6 +1879,14 @@
   Wait();
 }
 
+void RenderFrameSubmissionObserver::WaitForScrollOffset(
+    const gfx::Vector2dF& expected_offset) {
+  while (render_frame_metadata_provider_->LastRenderFrameMetadata()
+             .root_scroll_offset != expected_offset) {
+    WaitForMetadataChange();
+  }
+}
+
 const cc::RenderFrameMetadata&
 RenderFrameSubmissionObserver::LastRenderFrameMetadata() const {
   return render_frame_metadata_provider_->LastRenderFrameMetadata();
diff --git a/content/public/test/browser_test_utils.h b/content/public/test/browser_test_utils.h
index 36a1b4a6..236488a 100644
--- a/content/public/test/browser_test_utils.h
+++ b/content/public/test/browser_test_utils.h
@@ -709,6 +709,10 @@
   // Blocks the browser ui thread until the next OnRenderFrameMetadataChanged.
   void WaitForMetadataChange();
 
+  // Blocks the browser ui thread until RenderFrameMetadata arrives where its
+  // scroll offset matches |expected_offset|.
+  void WaitForScrollOffset(const gfx::Vector2dF& expected_offset);
+
   const cc::RenderFrameMetadata& LastRenderFrameMetadata() const;
 
   // Returns the number of frames submitted since the observer's creation.
diff --git a/content/public/test/mock_download_manager.cc b/content/public/test/mock_download_manager.cc
index 3fd2358..411fa48 100644
--- a/content/public/test/mock_download_manager.cc
+++ b/content/public/test/mock_download_manager.cc
@@ -6,6 +6,7 @@
 
 #include "components/download/public/common/download_create_info.h"
 #include "content/browser/byte_stream.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 namespace content {
 
@@ -111,6 +112,7 @@
 void MockDownloadManager::StartDownload(
     std::unique_ptr<download::DownloadCreateInfo> info,
     std::unique_ptr<download::InputStream> stream,
+    scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
     const download::DownloadUrlParameters::OnStartedCallback& callback) {
   MockStartDownload(info.get(), stream.get());
 }
diff --git a/content/public/test/mock_download_manager.h b/content/public/test/mock_download_manager.h
index c60b5ad..2603082 100644
--- a/content/public/test/mock_download_manager.h
+++ b/content/public/test/mock_download_manager.h
@@ -101,10 +101,12 @@
   MOCK_METHOD1(Init, bool(BrowserContext* browser_context));
 
   // Gasket for handling scoped_ptr arguments.
-  void StartDownload(std::unique_ptr<download::DownloadCreateInfo> info,
-                     std::unique_ptr<download::InputStream> stream,
-                     const download::DownloadUrlParameters::OnStartedCallback&
-                         callback) override;
+  void StartDownload(
+      std::unique_ptr<download::DownloadCreateInfo> info,
+      std::unique_ptr<download::InputStream> stream,
+      scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
+      const download::DownloadUrlParameters::OnStartedCallback& callback)
+      override;
 
   MOCK_METHOD2(MockStartDownload,
                void(download::DownloadCreateInfo*, download::InputStream*));
diff --git a/content/public/test/mock_render_process_host.cc b/content/public/test/mock_render_process_host.cc
index e78b20a..1635d51 100644
--- a/content/public/test/mock_render_process_host.cc
+++ b/content/public/test/mock_render_process_host.cc
@@ -36,7 +36,7 @@
 #include "content/public/browser/storage_partition.h"
 #include "content/public/common/service_manager_connection.h"
 #include "content/public/common/service_names.mojom.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "mojo/public/cpp/bindings/associated_interface_ptr.h"
 #include "services/resource_coordinator/public/mojom/coordination_unit.mojom.h"
 
diff --git a/content/public/test/mock_render_process_host.h b/content/public/test/mock_render_process_host.h
index 4e69482..3a9a326 100644
--- a/content/public/test/mock_render_process_host.h
+++ b/content/public/test/mock_render_process_host.h
@@ -25,7 +25,7 @@
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_process_host_factory.h"
 #include "ipc/ipc_test_sink.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "mojo/public/cpp/bindings/associated_interface_ptr.h"
 #include "services/resource_coordinator/public/cpp/process_resource_coordinator.h"
 #include "services/service_manager/public/cpp/identity.h"
diff --git a/content/public/test/render_view_test.cc b/content/public/test/render_view_test.cc
index 05c36b2..550abc2 100644
--- a/content/public/test/render_view_test.cc
+++ b/content/public/test/render_view_test.cc
@@ -397,6 +397,7 @@
   EXPECT_EQ(0u, result.number_of_live_frames);
   EXPECT_EQ(0u, result.number_of_live_v8_per_context_data);
   EXPECT_EQ(0u, result.number_of_worker_global_scopes);
+  EXPECT_EQ(0u, result.number_of_live_resource_fetchers);
 }
 
 void RenderViewTest::SendNativeKeyEvent(
diff --git a/content/public/test/test_browser_context.cc b/content/public/test/test_browser_context.cc
index 500973c..1b98904 100644
--- a/content/public/test/test_browser_context.cc
+++ b/content/public/test/test_browser_context.cc
@@ -10,6 +10,7 @@
 #include "base/logging.h"
 #include "base/single_thread_task_runner.h"
 #include "base/test/null_task_runner.h"
+#include "content/public/browser/browser_thread.h"
 #include "content/public/browser/permission_manager.h"
 #include "content/public/test/mock_resource_context.h"
 #include "content/test/mock_background_sync_controller.h"
@@ -48,6 +49,11 @@
 
 TestBrowserContext::TestBrowserContext(
     base::FilePath browser_context_dir_path) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI))
+      << "Please construct content::TestBrowserTheadBundle before constructing "
+      << "TestBrowserContext instances.  "
+      << BrowserThread::GetDCheckCurrentlyOnErrorMessage(BrowserThread::UI);
+
   if (browser_context_dir_path.empty()) {
     EXPECT_TRUE(browser_context_dir_.CreateUniqueTempDir());
   } else {
@@ -57,6 +63,12 @@
 }
 
 TestBrowserContext::~TestBrowserContext() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI))
+      << "Please destruct content::TestBrowserContext before destructing "
+      << "the TestBrowserThreadBundle instance.  "
+      << BrowserThread::GetDCheckCurrentlyOnErrorMessage(BrowserThread::UI);
+
+  NotifyWillBeDestroyed(this);
   ShutdownStoragePartitions();
 }
 
diff --git a/content/public/test/test_browser_thread.cc b/content/public/test/test_browser_thread.cc
index 63876d0a..d2a4bcd 100644
--- a/content/public/test/test_browser_thread.cc
+++ b/content/public/test/test_browser_thread.cc
@@ -9,32 +9,71 @@
 #include "base/message_loop/message_loop.h"
 #include "base/threading/thread.h"
 #include "build/build_config.h"
-#include "content/browser/browser_process_sub_thread.h"
 #include "content/browser/browser_thread_impl.h"
+#include "content/browser/notification_service_impl.h"
+
+#if defined(OS_WIN)
+#include "base/win/scoped_com_initializer.h"
+#endif
 
 namespace content {
 
+class TestBrowserThreadImpl : public BrowserThreadImpl {
+ public:
+  explicit TestBrowserThreadImpl(BrowserThread::ID identifier)
+      : BrowserThreadImpl(identifier) {}
+
+  TestBrowserThreadImpl(BrowserThread::ID identifier,
+                        base::MessageLoop* message_loop)
+      : BrowserThreadImpl(identifier, message_loop) {}
+
+  ~TestBrowserThreadImpl() override { Stop(); }
+
+  void Init() override {
+#if defined(OS_WIN)
+    com_initializer_ = std::make_unique<base::win::ScopedCOMInitializer>();
+#endif
+
+    notification_service_ = std::make_unique<NotificationServiceImpl>();
+    BrowserThreadImpl::Init();
+  }
+
+  void CleanUp() override {
+    BrowserThreadImpl::CleanUp();
+    notification_service_.reset();
+#if defined(OS_WIN)
+    com_initializer_.reset();
+#endif
+  }
+
+ private:
+#if defined(OS_WIN)
+  std::unique_ptr<base::win::ScopedCOMInitializer> com_initializer_;
+#endif
+
+  std::unique_ptr<NotificationService> notification_service_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestBrowserThreadImpl);
+};
+
 TestBrowserThread::TestBrowserThread(BrowserThread::ID identifier)
-    : identifier_(identifier),
-      real_thread_(std::make_unique<BrowserProcessSubThread>(identifier_)) {
-  real_thread_->AllowBlockingForTesting();
-}
+    : impl_(new TestBrowserThreadImpl(identifier)), identifier_(identifier) {}
 
 TestBrowserThread::TestBrowserThread(BrowserThread::ID identifier,
                                      base::MessageLoop* message_loop)
-    : identifier_(identifier),
-      fake_thread_(
-          new BrowserThreadImpl(identifier_, message_loop->task_runner())) {}
+    : impl_(new TestBrowserThreadImpl(identifier, message_loop)),
+      identifier_(identifier) {}
 
 TestBrowserThread::~TestBrowserThread() {
   // The upcoming BrowserThreadImpl::ResetGlobalsForTesting() call requires that
-  // |identifier_| have completed its SHUTDOWN phase.
-  real_thread_.reset();
-  fake_thread_.reset();
+  // |impl_| have triggered the shutdown phase for its BrowserThread::ID. This
+  // either happens when the thread is stopped (if real) or destroyed (when fake
+  // -- i.e. using an externally provided MessageLoop).
+  impl_.reset();
 
-  // Resets BrowserThreadImpl's globals so that |identifier_| is no longer
-  // bound. This is fine since the underlying MessageLoop has already been
-  // flushed and deleted above. In the case of an externally provided
+  // Resets BrowserThreadImpl's globals so that |impl_| is no longer bound to
+  // |identifier_|. This is fine since the underlying MessageLoop has already
+  // been flushed and deleted in Stop(). In the case of an externally provided
   // MessageLoop however, this means that TaskRunners obtained through
   // |BrowserThreadImpl::GetTaskRunnerForThread(identifier_)| will no longer
   // recognize their BrowserThreadImpl for RunsTasksInCurrentSequence(). This
@@ -48,34 +87,30 @@
   BrowserThreadImpl::ResetGlobalsForTesting(identifier_);
 }
 
-void TestBrowserThread::Start() {
-  CHECK(real_thread_->Start());
-  RegisterAsBrowserThread();
+bool TestBrowserThread::Start() {
+  return impl_->Start();
 }
 
-void TestBrowserThread::StartAndWaitForTesting() {
-  CHECK(real_thread_->StartAndWaitForTesting());
-  RegisterAsBrowserThread();
+bool TestBrowserThread::StartAndWaitForTesting() {
+  return impl_->StartAndWaitForTesting();
 }
 
-void TestBrowserThread::StartIOThread() {
-  StartIOThreadUnregistered();
-  RegisterAsBrowserThread();
-}
-
-void TestBrowserThread::StartIOThreadUnregistered() {
+bool TestBrowserThread::StartIOThread() {
   base::Thread::Options options;
   options.message_loop_type = base::MessageLoop::TYPE_IO;
-  CHECK(real_thread_->StartWithOptions(options));
+  return impl_->StartWithOptions(options);
 }
 
-void TestBrowserThread::RegisterAsBrowserThread() {
-  real_thread_->RegisterAsBrowserThread();
+void TestBrowserThread::InitIOThreadDelegate() {
+  impl_->InitIOThreadDelegate();
 }
 
 void TestBrowserThread::Stop() {
-  if (real_thread_)
-    real_thread_->Stop();
+  impl_->Stop();
+}
+
+bool TestBrowserThread::IsRunning() {
+  return impl_->IsRunning();
 }
 
 }  // namespace content
diff --git a/content/public/test/test_browser_thread.h b/content/public/test/test_browser_thread.h
index 161142c..ceb39ca 100644
--- a/content/public/test/test_browser_thread.h
+++ b/content/public/test/test_browser_thread.h
@@ -12,27 +12,20 @@
 
 namespace base {
 class MessageLoop;
-class Thread;
 }
 
 namespace content {
 
-class BrowserProcessSubThread;
-class BrowserThreadImpl;
+class TestBrowserThreadImpl;
 
 // DEPRECATED: use TestBrowserThreadBundle instead. See http://crbug.com/272091
 // A BrowserThread for unit tests; this lets unit tests in chrome/ create
 // BrowserThread instances.
 class TestBrowserThread {
  public:
-  // Constructs a TestBrowserThread with a |real_thread_| and starts it (with a
-  // MessageLoopForIO if |identifier == BrowserThread::IO|.
   explicit TestBrowserThread(BrowserThread::ID identifier);
-
-  // Constructs a TestBrowserThread based on |message_loop| (no |real_thread_|).
   TestBrowserThread(BrowserThread::ID identifier,
                     base::MessageLoop* message_loop);
-
   ~TestBrowserThread();
 
   // We provide a subset of the capabilities of the Thread interface
@@ -41,35 +34,29 @@
   // interface.
 
   // Starts the thread with a generic message loop.
-  void Start();
+  bool Start();
 
   // Starts the thread with a generic message loop and waits for the
   // thread to run.
-  void StartAndWaitForTesting();
+  bool StartAndWaitForTesting();
 
   // Starts the thread with an IOThread message loop.
-  void StartIOThread();
+  bool StartIOThread();
 
-  // Together these are the same as StartIOThread(). They can be called in
-  // phases to test binding BrowserThread::IO after its underlying thread was
-  // started.
-  void StartIOThreadUnregistered();
-  void RegisterAsBrowserThread();
+  // Initializes the BrowserThreadDelegate.
+  void InitIOThreadDelegate();
 
-  // Stops the thread, no-op if this is not a real thread.
+  // Stops the thread.
   void Stop();
 
+  // Returns true if the thread is running.
+  bool IsRunning();
+
  private:
+  std::unique_ptr<TestBrowserThreadImpl> impl_;
+
   const BrowserThread::ID identifier_;
 
-  // A real thread which represents |identifier_| when constructor #1 is used
-  // (null otherwise).
-  std::unique_ptr<BrowserProcessSubThread> real_thread_;
-
-  // Binds |identifier_| to |message_loop| when constructor #2 is used (null
-  // otherwise).
-  std::unique_ptr<BrowserThreadImpl> fake_thread_;
-
   DISALLOW_COPY_AND_ASSIGN(TestBrowserThread);
 };
 
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index e629f87..f26a29f 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -550,7 +550,7 @@
     "//gpu/command_buffer/client:gles2_interface",
     "//gpu/command_buffer/client:raster_interface",
     "//media",
-    "//media:media_features",
+    "//media:media_buildflags",
     "//media/blink",
     "//media/capture",
     "//media/gpu",
@@ -558,7 +558,7 @@
     "//media/gpu/ipc/common",
     "//media/midi",
     "//media/midi:mojo",
-    "//media/mojo:features",
+    "//media/mojo:buildflags",
     "//media/mojo/clients",
     "//media/mojo/interfaces",
     "//media/mojo/interfaces:remoting",
diff --git a/content/renderer/cache_storage/webserviceworkercachestorage_impl.cc b/content/renderer/cache_storage/webserviceworkercachestorage_impl.cc
index 18827b0..7e27c71 100644
--- a/content/renderer/cache_storage/webserviceworkercachestorage_impl.cc
+++ b/content/renderer/cache_storage/webserviceworkercachestorage_impl.cc
@@ -16,7 +16,6 @@
 #include "base/threading/thread_local.h"
 #include "content/child/child_thread_impl.h"
 #include "content/child/thread_safe_sender.h"
-#include "content/common/cache_storage/cache_storage_messages.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/referrer.h"
 #include "content/public/common/service_names.mojom.h"
diff --git a/content/renderer/child_frame_compositing_helper.cc b/content/renderer/child_frame_compositing_helper.cc
index 08717a4..a2f2001 100644
--- a/content/renderer/child_frame_compositing_helper.cc
+++ b/content/renderer/child_frame_compositing_helper.cc
@@ -80,6 +80,7 @@
 
   surface_layer_ = cc::SurfaceLayer::Create();
   surface_layer_->SetMasksToBounds(true);
+  surface_layer_->SetHitTestable(true);
   surface_layer_->SetBackgroundColor(SK_ColorTRANSPARENT);
 
   surface_layer_->SetPrimarySurfaceId(surface_id,
diff --git a/content/renderer/dom_storage/local_storage_cached_area.cc b/content/renderer/dom_storage/local_storage_cached_area.cc
index ca8d1bd3..fbec576b 100644
--- a/content/renderer/dom_storage/local_storage_cached_area.cc
+++ b/content/renderer/dom_storage/local_storage_cached_area.cc
@@ -84,9 +84,11 @@
 
   mojom::LevelDBWrapperAssociatedPtrInfo wrapper_ptr_info;
   session_namespace->OpenArea(origin_, mojo::MakeRequest(&wrapper_ptr_info));
-  leveldb_.Bind(std::move(wrapper_ptr_info));
+  leveldb_.Bind(std::move(wrapper_ptr_info),
+                renderer_scheduler->IPCTaskRunner());
   mojom::LevelDBObserverAssociatedPtrInfo ptr_info;
-  binding_.Bind(mojo::MakeRequest(&ptr_info));
+  binding_.Bind(mojo::MakeRequest(&ptr_info),
+                renderer_scheduler->IPCTaskRunner());
   leveldb_->AddObserver(std::move(ptr_info));
 }
 
@@ -104,9 +106,11 @@
   mojom::LevelDBWrapperPtrInfo wrapper_ptr_info;
   storage_partition_service->OpenLocalStorage(
       origin_, mojo::MakeRequest(&wrapper_ptr_info));
-  leveldb_.Bind(std::move(wrapper_ptr_info));
+  leveldb_.Bind(std::move(wrapper_ptr_info),
+                renderer_scheduler->IPCTaskRunner());
   mojom::LevelDBObserverAssociatedPtrInfo ptr_info;
-  binding_.Bind(mojo::MakeRequest(&ptr_info));
+  binding_.Bind(mojo::MakeRequest(&ptr_info),
+                renderer_scheduler->IPCTaskRunner());
   leveldb_->AddObserver(std::move(ptr_info));
 }
 
diff --git a/content/renderer/input/frame_input_handler_impl.cc b/content/renderer/input/frame_input_handler_impl.cc
index a58e0c9..6e6294cf 100644
--- a/content/renderer/input/frame_input_handler_impl.cc
+++ b/content/renderer/input/frame_input_handler_impl.cc
@@ -80,20 +80,9 @@
     return;
 
   ImeEventGuard guard(render_frame_->GetRenderWidget());
-  std::vector<blink::WebImeTextSpan> ime_text_spans;
-  for (const auto& ime_text_span : ui_ime_text_spans) {
-    blink::WebImeTextSpan blink_ime_text_span(
-        ConvertUiImeTextSpanTypeToWebType(ime_text_span.type),
-        ime_text_span.start_offset, ime_text_span.end_offset,
-        ime_text_span.underline_color,
-        ConvertUiThicknessToUiImeTextSpanThickness(ime_text_span.thickness),
-        ime_text_span.background_color,
-        ime_text_span.suggestion_highlight_color, ime_text_span.suggestions);
-    ime_text_spans.push_back(blink_ime_text_span);
-  }
 
-  render_frame_->GetWebFrame()->SetCompositionFromExistingText(start, end,
-                                                               ime_text_spans);
+  render_frame_->GetWebFrame()->SetCompositionFromExistingText(
+      start, end, ConvertUiImeTextSpansToBlinkImeTextSpans(ui_ime_text_spans));
 }
 
 void FrameInputHandlerImpl::ExtendSelectionAndDelete(int32_t before,
diff --git a/content/renderer/input/widget_input_handler_impl.cc b/content/renderer/input/widget_input_handler_impl.cc
index 0dac1c9..f08c639 100644
--- a/content/renderer/input/widget_input_handler_impl.cc
+++ b/content/renderer/input/widget_input_handler_impl.cc
@@ -25,22 +25,6 @@
 
 namespace {
 
-std::vector<blink::WebImeTextSpan> ConvertUIImeTextSpansToBlinkImeTextSpans(
-    const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) {
-  std::vector<blink::WebImeTextSpan> ime_text_spans;
-  for (const auto& ime_text_span : ui_ime_text_spans) {
-    blink::WebImeTextSpan blink_ime_text_span(
-        ConvertUiImeTextSpanTypeToWebType(ime_text_span.type),
-        ime_text_span.start_offset, ime_text_span.end_offset,
-        ime_text_span.underline_color,
-        ConvertUiThicknessToUiImeTextSpanThickness(ime_text_span.thickness),
-        ime_text_span.background_color,
-        ime_text_span.suggestion_highlight_color, ime_text_span.suggestions);
-    ime_text_spans.push_back(blink_ime_text_span);
-  }
-  return ime_text_spans;
-}
-
 void RunClosureIfNotSwappedOut(base::WeakPtr<RenderWidget> render_widget,
                                base::OnceClosure closure) {
   // Input messages must not be processed if the RenderWidget is in swapped out
@@ -112,7 +96,7 @@
     int32_t end) {
   RunOnMainThread(
       base::BindOnce(&RenderWidget::OnImeSetComposition, render_widget_, text,
-                     ConvertUIImeTextSpansToBlinkImeTextSpans(ime_text_spans),
+                     ConvertUiImeTextSpansToBlinkImeTextSpans(ime_text_spans),
                      range, start, end));
 }
 
@@ -123,7 +107,7 @@
     int32_t relative_cursor_position) {
   RunOnMainThread(
       base::BindOnce(&RenderWidget::OnImeCommitText, render_widget_, text,
-                     ConvertUIImeTextSpansToBlinkImeTextSpans(ime_text_spans),
+                     ConvertUiImeTextSpansToBlinkImeTextSpans(ime_text_spans),
                      range, relative_cursor_position));
 }
 
diff --git a/content/renderer/loader/ftp_directory_listing_response_delegate.cc b/content/renderer/loader/ftp_directory_listing_response_delegate.cc
index fb99d33..fc265713 100644
--- a/content/renderer/loader/ftp_directory_listing_response_delegate.cc
+++ b/content/renderer/loader/ftp_directory_listing_response_delegate.cc
@@ -21,7 +21,7 @@
 #include "net/base/escape.h"
 #include "net/base/net_errors.h"
 #include "net/ftp/ftp_directory_listing_parser.h"
-#include "net/net_features.h"
+#include "net/net_buildflags.h"
 #include "third_party/WebKit/public/platform/WebURL.h"
 #include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
 
diff --git a/content/renderer/loader/request_extra_data.cc b/content/renderer/loader/request_extra_data.cc
index b9fce63a..3b52397 100644
--- a/content/renderer/loader/request_extra_data.cc
+++ b/content/renderer/loader/request_extra_data.cc
@@ -24,7 +24,8 @@
       is_for_no_state_prefetch_(false),
       download_to_network_cache_only_(false),
       block_mixed_plugin_content_(false),
-      navigation_initiated_by_renderer_(false) {}
+      navigation_initiated_by_renderer_(false),
+      attach_same_site_cookies_(false) {}
 
 RequestExtraData::~RequestExtraData() {
 }
@@ -43,6 +44,7 @@
   request->originated_from_service_worker = originated_from_service_worker_;
 
   request->initiated_in_secure_context = initiated_in_secure_context_;
+  request->attach_same_site_cookies = attach_same_site_cookies_;
 }
 
 }  // namespace content
diff --git a/content/renderer/loader/request_extra_data.h b/content/renderer/loader/request_extra_data.h
index 410d448..6c08526e 100644
--- a/content/renderer/loader/request_extra_data.h
+++ b/content/renderer/loader/request_extra_data.h
@@ -140,6 +140,13 @@
     navigation_initiated_by_renderer_ = navigation_by_renderer;
   }
 
+  // Determines whether SameSite cookies will be attached to the request
+  // even when the request looks cross-site.
+  bool attach_same_site_cookies() const { return attach_same_site_cookies_; }
+  void set_attach_same_site_cookies(bool attach) {
+    attach_same_site_cookies_ = attach;
+  }
+
   std::vector<std::unique_ptr<URLLoaderThrottle>> TakeURLLoaderThrottles() {
     return std::move(url_loader_throttles_);
   }
@@ -170,6 +177,7 @@
   bool download_to_network_cache_only_;
   bool block_mixed_plugin_content_;
   bool navigation_initiated_by_renderer_;
+  bool attach_same_site_cookies_;
   std::vector<std::unique_ptr<URLLoaderThrottle>> url_loader_throttles_;
 
   DISALLOW_COPY_AND_ASSIGN(RequestExtraData);
diff --git a/content/renderer/loader/resource_dispatcher.cc b/content/renderer/loader/resource_dispatcher.cc
index bf22236..4f23b60 100644
--- a/content/renderer/loader/resource_dispatcher.cc
+++ b/content/renderer/loader/resource_dispatcher.cc
@@ -37,6 +37,7 @@
 #include "net/base/load_flags.h"
 #include "net/base/net_errors.h"
 #include "net/base/request_priority.h"
+#include "net/cert/cert_status_flags.h"
 #include "net/http/http_response_headers.h"
 #include "services/network/public/cpp/features.h"
 #include "services/network/public/cpp/resource_request.h"
@@ -73,6 +74,29 @@
 void NotifySubresourceStarted(
     scoped_refptr<base::SingleThreadTaskRunner> thread_task_runner,
     int render_frame_id,
+    const GURL& url,
+    net::CertStatus cert_status) {
+  if (!thread_task_runner)
+    return;
+
+  if (!thread_task_runner->BelongsToCurrentThread()) {
+    thread_task_runner->PostTask(
+        FROM_HERE, base::BindOnce(NotifySubresourceStarted, thread_task_runner,
+                                  render_frame_id, url, cert_status));
+    return;
+  }
+
+  RenderFrameImpl* render_frame =
+      RenderFrameImpl::FromRoutingID(render_frame_id);
+  if (!render_frame)
+    return;
+
+  render_frame->GetFrameHost()->SubresourceResponseStarted(url, cert_status);
+}
+
+void NotifySubresourceLoadComplete(
+    scoped_refptr<base::SingleThreadTaskRunner> thread_task_runner,
+    int render_frame_id,
     mojom::SubresourceLoadInfoPtr subresource_load_info) {
   if (!thread_task_runner)
     return;
@@ -80,7 +104,7 @@
   if (!thread_task_runner->BelongsToCurrentThread()) {
     thread_task_runner->PostTask(
         FROM_HERE,
-        base::BindOnce(NotifySubresourceStarted, thread_task_runner,
+        base::BindOnce(NotifySubresourceLoadComplete, thread_task_runner,
                        render_frame_id, std::move(subresource_load_info)));
     return;
   }
@@ -90,7 +114,7 @@
   if (!render_frame)
     return;
 
-  render_frame->GetFrameHost()->SubresourceResponseStarted(
+  render_frame->GetFrameHost()->SubresourceLoadComplete(
       std::move(subresource_load_info));
 }
 
@@ -148,22 +172,16 @@
     request_info->peer = std::move(new_peer);
   }
 
+  if (!response_head.socket_address.host().empty()) {
+    ignore_result(request_info->parsed_ip.AssignFromIPLiteral(
+        response_head.socket_address.host()));
+  }
+
   if (!IsResourceTypeFrame(request_info->resource_type)) {
-    auto subresource_load_info = mojom::SubresourceLoadInfo::New();
-    subresource_load_info->url = request_info->response_url;
-    subresource_load_info->referrer = request_info->response_referrer;
-    subresource_load_info->method = request_info->response_method;
-    subresource_load_info->resource_type = request_info->resource_type;
-    if (!response_head.socket_address.host().empty()) {
-      net::IPAddress parsed_ip;
-      if (parsed_ip.AssignFromIPLiteral(response_head.socket_address.host())) {
-        subresource_load_info->ip = parsed_ip;
-      }
-    }
-    subresource_load_info->cert_status = response_head.cert_status;
     NotifySubresourceStarted(RenderThreadImpl::DeprecatedGetMainTaskRunner(),
                              request_info->render_frame_id,
-                             std::move(subresource_load_info));
+                             request_info->response_url,
+                             response_head.cert_status);
   }
 
   network::ResourceResponseInfo renderer_response_info;
@@ -247,6 +265,20 @@
   request_info->buffer.reset();
   request_info->buffer_size = 0;
 
+  if (!IsResourceTypeFrame(request_info->resource_type)) {
+    auto subresource_load_info = mojom::SubresourceLoadInfo::New();
+    subresource_load_info->url = request_info->response_url;
+    subresource_load_info->referrer = request_info->response_referrer;
+    subresource_load_info->method = request_info->response_method;
+    subresource_load_info->resource_type = request_info->resource_type;
+    if (request_info->parsed_ip.IsValid())
+      subresource_load_info->ip = request_info->parsed_ip;
+    subresource_load_info->was_cached = status.exists_in_cache;
+    NotifySubresourceLoadComplete(
+        RenderThreadImpl::DeprecatedGetMainTaskRunner(),
+        request_info->render_frame_id, std::move(subresource_load_info));
+  }
+
   RequestPeer* peer = request_info->peer.get();
 
   if (delegate_) {
@@ -269,6 +301,17 @@
   peer->OnCompletedRequest(renderer_status);
 }
 
+network::mojom::DownloadedTempFilePtr
+ResourceDispatcher::TakeDownloadedTempFile(int request_id) {
+  PendingRequestMap::iterator it = pending_requests_.find(request_id);
+  if (it == pending_requests_.end())
+    return nullptr;
+  PendingRequestInfo* request_info = it->second.get();
+  if (!request_info->url_loader_client)
+    return nullptr;
+  return request_info->url_loader_client->TakeDownloadedTempFile();
+}
+
 bool ResourceDispatcher::RemovePendingRequest(
     int request_id,
     scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
@@ -369,13 +412,15 @@
     const net::NetworkTrafficAnnotationTag& traffic_annotation,
     SyncLoadResponse* response,
     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
-    std::vector<std::unique_ptr<URLLoaderThrottle>> throttles) {
+    std::vector<std::unique_ptr<URLLoaderThrottle>> throttles,
+    double timeout) {
   CheckSchemeForReferrerPolicy(*request);
 
   std::unique_ptr<network::SharedURLLoaderFactoryInfo> factory_info =
       url_loader_factory->Clone();
-  base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
-                            base::WaitableEvent::InitialState::NOT_SIGNALED);
+  base::WaitableEvent completed_event(
+      base::WaitableEvent::ResetPolicy::MANUAL,
+      base::WaitableEvent::InitialState::NOT_SIGNALED);
 
   // Prepare the configured throttles for use on a separate thread.
   for (const auto& throttle : throttles)
@@ -393,9 +438,9 @@
                      std::move(request), routing_id, task_runner,
                      traffic_annotation, std::move(factory_info),
                      std::move(throttles), base::Unretained(response),
-                     base::Unretained(&event)));
-
-  event.Wait();
+                     base::Unretained(&completed_event),
+                     base::Unretained(terminate_sync_load_event_), timeout));
+  completed_event.Wait();
 }
 
 int ResourceDispatcher::StartAsync(
diff --git a/content/renderer/loader/resource_dispatcher.h b/content/renderer/loader/resource_dispatcher.h
index 6f41e2af..4f81b7d7 100644
--- a/content/renderer/loader/resource_dispatcher.h
+++ b/content/renderer/loader/resource_dispatcher.h
@@ -32,6 +32,10 @@
 #include "third_party/WebKit/public/platform/WebURLRequest.h"
 #include "url/gurl.h"
 
+namespace base {
+class WaitableEvent;
+}
+
 namespace net {
 struct RedirectInfo;
 }
@@ -80,13 +84,15 @@
   //
   // |routing_id| is used to associated the bridge with a frame's network
   // context.
+  // |timeout| (in seconds) is used to abort the sync request on timeouts.
   virtual void StartSync(
       std::unique_ptr<network::ResourceRequest> request,
       int routing_id,
       const net::NetworkTrafficAnnotationTag& traffic_annotation,
       SyncLoadResponse* response,
       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
-      std::vector<std::unique_ptr<URLLoaderThrottle>> throttles);
+      std::vector<std::unique_ptr<URLLoaderThrottle>> throttles,
+      double timeout);
 
   // Call this method to initiate the request. If this method succeeds, then
   // the peer's methods will be called asynchronously to report various events.
@@ -109,6 +115,8 @@
       network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
       base::OnceClosure* continue_navigation_function);
 
+  network::mojom::DownloadedTempFilePtr TakeDownloadedTempFile(int request_id);
+
   // Removes a request from the |pending_requests_| list, returning true if the
   // request was found and removed.
   bool RemovePendingRequest(
@@ -140,6 +148,15 @@
 
   void OnTransferSizeUpdated(int request_id, int32_t transfer_size_diff);
 
+  // This is used only when |this| is created for a worker thread.
+  // Sets |terminate_sync_load_event_| which will be signaled from the main
+  // thread when the worker thread is being terminated so that the sync requests
+  // requested on the worker thread can be aborted.
+  void set_terminate_sync_load_event(
+      base::WaitableEvent* terminate_sync_load_event) {
+    terminate_sync_load_event_ = terminate_sync_load_event;
+  }
+
  private:
   friend class URLLoaderClientImpl;
   friend class URLResponseBodyConsumer;
@@ -174,6 +191,7 @@
     base::TimeTicks completion_time;
     linked_ptr<base::SharedMemory> buffer;
     int buffer_size;
+    net::IPAddress parsed_ip;
 
     // For mojo loading.
     std::unique_ptr<ThrottlingURLLoader> url_loader;
@@ -220,6 +238,8 @@
 
   ResourceDispatcherDelegate* delegate_;
 
+  base::WaitableEvent* terminate_sync_load_event_ = nullptr;
+
   base::WeakPtrFactory<ResourceDispatcher> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ResourceDispatcher);
diff --git a/content/renderer/loader/sync_load_context.cc b/content/renderer/loader/sync_load_context.cc
index 85db10a..33f6daa 100644
--- a/content/renderer/loader/sync_load_context.cc
+++ b/content/renderer/loader/sync_load_context.cc
@@ -26,11 +26,12 @@
         url_loader_factory_info,
     std::vector<std::unique_ptr<URLLoaderThrottle>> throttles,
     SyncLoadResponse* response,
-    base::WaitableEvent* event) {
-  auto* context =
-      new SyncLoadContext(request.get(), std::move(url_loader_factory_info),
-                          response, event, loading_task_runner);
-
+    base::WaitableEvent* completed_event,
+    base::WaitableEvent* abort_event,
+    double timeout) {
+  auto* context = new SyncLoadContext(
+      request.get(), std::move(url_loader_factory_info), response,
+      completed_event, abort_event, timeout, loading_task_runner);
   context->request_id_ = context->resource_dispatcher_->StartAsync(
       std::move(request), routing_id, std::move(loading_task_runner),
       traffic_annotation, true /* is_sync */, base::WrapUnique(context),
@@ -43,11 +44,25 @@
     network::ResourceRequest* request,
     std::unique_ptr<network::SharedURLLoaderFactoryInfo> url_loader_factory,
     SyncLoadResponse* response,
-    base::WaitableEvent* event,
+    base::WaitableEvent* completed_event,
+    base::WaitableEvent* abort_event,
+    double timeout,
     scoped_refptr<base::SingleThreadTaskRunner> task_runner)
-    : response_(response), event_(event), task_runner_(std::move(task_runner)) {
+    : response_(response),
+      completed_event_(completed_event),
+      task_runner_(std::move(task_runner)) {
   url_loader_factory_ =
       network::SharedURLLoaderFactory::Create(std::move(url_loader_factory));
+  if (abort_event) {
+    abort_watcher_.StartWatching(
+        abort_event,
+        base::BindOnce(&SyncLoadContext::OnAbort, base::Unretained(this)),
+        task_runner_);
+  }
+  if (timeout) {
+    timeout_timer_.Start(FROM_HERE, base::TimeDelta::FromSecondsD(timeout),
+                         this, &SyncLoadContext::OnTimeout);
+  }
 
   // Constructs a new ResourceDispatcher specifically for this request.
   resource_dispatcher_ = std::make_unique<ResourceDispatcher>();
@@ -64,10 +79,12 @@
 bool SyncLoadContext::OnReceivedRedirect(
     const net::RedirectInfo& redirect_info,
     const network::ResourceResponseInfo& info) {
+  DCHECK(!Completed());
   if (redirect_info.new_url.GetOrigin() != response_->url.GetOrigin()) {
     LOG(ERROR) << "Cross origin redirect denied";
     response_->error_code = net::ERR_ABORTED;
-    event_->Signal();
+
+    CompleteRequest(false /* remove_pending_request */);
 
     // Returning false here will cause the request to be cancelled and this
     // object deleted.
@@ -80,24 +97,17 @@
 
 void SyncLoadContext::OnReceivedResponse(
     const network::ResourceResponseInfo& info) {
-  response_->headers = info.headers;
-  response_->mime_type = info.mime_type;
-  response_->charset = info.charset;
-  response_->request_time = info.request_time;
-  response_->response_time = info.response_time;
-  response_->load_timing = info.load_timing;
-  response_->raw_request_response_info = info.raw_request_response_info;
-  response_->download_file_path = info.download_file_path;
-  response_->socket_address = info.socket_address;
+  DCHECK(!Completed());
+  response_->info = info;
 }
 
 void SyncLoadContext::OnDownloadedData(int len, int encoded_data_length) {
-  // This method is only called when RequestInfo::download_to_file is true which
-  // is not allowed when processing a synchronous request.
-  NOTREACHED();
+  downloaded_file_length_ =
+      (downloaded_file_length_ ? *downloaded_file_length_ : 0) + len;
 }
 
 void SyncLoadContext::OnReceivedData(std::unique_ptr<ReceivedData> data) {
+  DCHECK(!Completed());
   response_->data.append(data->payload(), data->length());
 }
 
@@ -105,16 +115,55 @@
 
 void SyncLoadContext::OnCompletedRequest(
     const network::URLLoaderCompletionStatus& status) {
+  DCHECK(!Completed());
   response_->error_code = status.error_code;
   response_->extended_error_code = status.extended_error_code;
   if (status.cors_error_status)
     response_->cors_error = status.cors_error_status->cors_error;
-  response_->encoded_data_length = status.encoded_data_length;
-  response_->encoded_body_length = status.encoded_body_length;
-  event_->Signal();
+  response_->info.encoded_data_length = status.encoded_data_length;
+  response_->info.encoded_body_length = status.encoded_body_length;
+  response_->downloaded_file_length = downloaded_file_length_;
+  // Need to pass |downloaded_tmp_file| to the caller thread. Otherwise the blob
+  // creation in ResourceResponse::SetDownloadedFilePath() fails.
+  response_->downloaded_tmp_file =
+      resource_dispatcher_->TakeDownloadedTempFile(request_id_);
+  DCHECK_EQ(!response_->downloaded_file_length,
+            !response_->downloaded_tmp_file);
+  CompleteRequest(true /* remove_pending_request */);
+}
 
-  // This will indirectly cause this object to be deleted.
-  resource_dispatcher_->RemovePendingRequest(request_id_, task_runner_);
+void SyncLoadContext::OnAbort(base::WaitableEvent* event) {
+  DCHECK(!Completed());
+  response_->error_code = net::ERR_ABORTED;
+  CompleteRequest(true /* remove_pending_request */);
+}
+
+void SyncLoadContext::OnTimeout() {
+  // OnTimeout() must not be called after CompleteRequest() was called, because
+  // the OneShotTimer must have been stopped.
+  DCHECK(!Completed());
+  response_->error_code = net::ERR_TIMED_OUT;
+  CompleteRequest(true /* remove_pending_request */);
+}
+
+void SyncLoadContext::CompleteRequest(bool remove_pending_request) {
+  abort_watcher_.StopWatching();
+  timeout_timer_.AbandonAndStop();
+
+  completed_event_->Signal();
+
+  completed_event_ = nullptr;
+  response_ = nullptr;
+
+  if (remove_pending_request) {
+    // This will indirectly cause this object to be deleted.
+    resource_dispatcher_->RemovePendingRequest(request_id_, task_runner_);
+  }
+}
+
+bool SyncLoadContext::Completed() const {
+  DCHECK_EQ(!completed_event_, !response_);
+  return !response_;
 }
 
 }  // namespace content
diff --git a/content/renderer/loader/sync_load_context.h b/content/renderer/loader/sync_load_context.h
index d32d25f..2e067d7a 100644
--- a/content/renderer/loader/sync_load_context.h
+++ b/content/renderer/loader/sync_load_context.h
@@ -6,6 +6,9 @@
 #define CONTENT_RENDERER_LOADER_SYNC_LOAD_CONTEXT_H_
 
 #include "base/macros.h"
+#include "base/optional.h"
+#include "base/synchronization/waitable_event_watcher.h"
+#include "base/timer/timer.h"
 #include "content/public/renderer/request_peer.h"
 #include "content/renderer/loader/resource_dispatcher.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
@@ -28,8 +31,10 @@
 class SyncLoadContext : public RequestPeer {
  public:
   // Begins a new asynchronous request on whatever sequence this method is
-  // called on. |event| will be signalled when the request is complete and
-  // |response| will be populated with the response data.
+  // called on. |completed_event| will be signalled when the request is complete
+  // and |response| will be populated with the response data. |abort_event|
+  // will be signalled from the main thread to abort the sync request on a
+  // worker thread when the worker thread is being terminated.
   static void StartAsyncWithWaitableEvent(
       std::unique_ptr<network::ResourceRequest> request,
       int routing_id,
@@ -39,17 +44,21 @@
           url_loader_factory_info,
       std::vector<std::unique_ptr<URLLoaderThrottle>> throttles,
       SyncLoadResponse* response,
-      base::WaitableEvent* event);
+      base::WaitableEvent* completed_event,
+      base::WaitableEvent* abort_event,
+      double timeout);
 
+  ~SyncLoadContext() override;
+
+ private:
   SyncLoadContext(
       network::ResourceRequest* request,
       std::unique_ptr<network::SharedURLLoaderFactoryInfo> url_loader_factory,
       SyncLoadResponse* response,
-      base::WaitableEvent* event,
+      base::WaitableEvent* completed_event,
+      base::WaitableEvent* abort_event,
+      double timeout,
       scoped_refptr<base::SingleThreadTaskRunner> task_runner);
-  ~SyncLoadContext() override;
-
- private:
   // RequestPeer implementation:
   void OnUploadProgress(uint64_t position, uint64_t size) override;
   bool OnReceivedRedirect(const net::RedirectInfo& redirect_info,
@@ -61,12 +70,20 @@
   void OnCompletedRequest(
       const network::URLLoaderCompletionStatus& status) override;
 
+  void OnAbort(base::WaitableEvent* event);
+  void OnTimeout();
+
+  void CompleteRequest(bool remove_pending_request);
+  bool Completed() const;
+
   // This raw pointer will remain valid for the lifetime of this object because
   // it remains on the stack until |event_| is signaled.
+  // Set to null after CompleteRequest() is called.
   SyncLoadResponse* response_;
 
   // This event is signaled when the request is complete.
-  base::WaitableEvent* event_;
+  // Set to null after CompleteRequest() is called.
+  base::WaitableEvent* completed_event_;
 
   // State necessary to run a request on an independent thread.
   scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
@@ -76,6 +93,11 @@
 
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
 
+  base::Optional<int64_t> downloaded_file_length_;
+
+  base::WaitableEventWatcher abort_watcher_;
+  base::OneShotTimer timeout_timer_;
+
   DISALLOW_COPY_AND_ASSIGN(SyncLoadContext);
 };
 
diff --git a/content/renderer/loader/sync_load_response.cc b/content/renderer/loader/sync_load_response.cc
index a9e8ee12..d3a5ef8 100644
--- a/content/renderer/loader/sync_load_response.cc
+++ b/content/renderer/loader/sync_load_response.cc
@@ -8,6 +8,11 @@
 
 SyncLoadResponse::SyncLoadResponse() {}
 
+SyncLoadResponse::SyncLoadResponse(SyncLoadResponse&& other) = default;
+
 SyncLoadResponse::~SyncLoadResponse() {}
 
+SyncLoadResponse& SyncLoadResponse::operator=(SyncLoadResponse&& other) =
+    default;
+
 }  // namespace content
diff --git a/content/renderer/loader/sync_load_response.h b/content/renderer/loader/sync_load_response.h
index 03b26fef..89901b79 100644
--- a/content/renderer/loader/sync_load_response.h
+++ b/content/renderer/loader/sync_load_response.h
@@ -11,18 +11,24 @@
 #include "content/common/content_export.h"
 #include "services/network/public/cpp/resource_response_info.h"
 #include "services/network/public/mojom/cors.mojom.h"
+#include "services/network/public/mojom/url_loader.mojom.h"
 #include "url/gurl.h"
 
 namespace content {
 
 // See the SyncLoad method. (The name of this struct is not
 // suffixed with "Info" because it also contains the response data.)
-struct CONTENT_EXPORT SyncLoadResponse : network::ResourceResponseInfo {
+struct CONTENT_EXPORT SyncLoadResponse {
   SyncLoadResponse();
+  SyncLoadResponse(SyncLoadResponse&& other);
   ~SyncLoadResponse();
 
+  SyncLoadResponse& operator=(SyncLoadResponse&& other);
+
+  network::ResourceResponseInfo info;
+
   // The response error code.
-  int error_code = 0;
+  int error_code;
 
   // The response extended error code.
   int extended_error_code = 0;
@@ -36,6 +42,10 @@
 
   // The response data.
   std::string data;
+
+  // Used for blob response type XMLHttpRequest.
+  base::Optional<int64_t> downloaded_file_length;
+  network::mojom::DownloadedTempFilePtr downloaded_tmp_file;
 };
 
 }  // namespace content
diff --git a/content/renderer/loader/url_loader_client_impl.cc b/content/renderer/loader/url_loader_client_impl.cc
index 71c67f8..4d7badc 100644
--- a/content/renderer/loader/url_loader_client_impl.cc
+++ b/content/renderer/loader/url_loader_client_impl.cc
@@ -331,6 +331,11 @@
   body_consumer_->OnComplete(status);
 }
 
+network::mojom::DownloadedTempFilePtr
+URLLoaderClientImpl::TakeDownloadedTempFile() {
+  return std::move(downloaded_file_);
+}
+
 bool URLLoaderClientImpl::NeedsStoringMessage() const {
   return is_deferred_ || deferred_messages_.size() > 0;
 }
diff --git a/content/renderer/loader/url_loader_client_impl.h b/content/renderer/loader/url_loader_client_impl.h
index d42044a..375aa92 100644
--- a/content/renderer/loader/url_loader_client_impl.h
+++ b/content/renderer/loader/url_loader_client_impl.h
@@ -77,6 +77,9 @@
       mojo::ScopedDataPipeConsumerHandle body) override;
   void OnComplete(const network::URLLoaderCompletionStatus& status) override;
 
+  // Takes |downloaded_file_|.
+  network::mojom::DownloadedTempFilePtr TakeDownloadedTempFile();
+
  private:
   class DeferredMessage;
   class DeferredOnReceiveResponse;
diff --git a/content/renderer/loader/web_url_loader_impl.cc b/content/renderer/loader/web_url_loader_impl.cc
index adebe3e1..af41e0a 100644
--- a/content/renderer/loader/web_url_loader_impl.cc
+++ b/content/renderer/loader/web_url_loader_impl.cc
@@ -604,7 +604,7 @@
       // This is a sync load. Do the work now.
       sync_load_response->url = url_;
       sync_load_response->error_code =
-          GetInfoFromDataURL(sync_load_response->url, sync_load_response,
+          GetInfoFromDataURL(sync_load_response->url, &sync_load_response->info,
                              &sync_load_response->data);
     } else {
       task_runner_->PostTask(FROM_HERE,
@@ -740,7 +740,8 @@
     resource_dispatcher_->StartSync(
         std::move(resource_request), request.RequestorID(),
         GetTrafficAnnotationTag(request), sync_load_response,
-        url_loader_factory_, extra_data->TakeURLLoaderThrottles());
+        url_loader_factory_, extra_data->TakeURLLoaderThrottles(),
+        request.TimeoutInterval());
     return;
   }
 
@@ -1297,12 +1298,14 @@
   }
 }
 
-void WebURLLoaderImpl::LoadSynchronously(const WebURLRequest& request,
-                                         WebURLResponse& response,
-                                         base::Optional<WebURLError>& error,
-                                         WebData& data,
-                                         int64_t& encoded_data_length,
-                                         int64_t& encoded_body_length) {
+void WebURLLoaderImpl::LoadSynchronously(
+    const WebURLRequest& request,
+    WebURLResponse& response,
+    base::Optional<WebURLError>& error,
+    WebData& data,
+    int64_t& encoded_data_length,
+    int64_t& encoded_body_length,
+    base::Optional<int64_t>& downloaded_file_length) {
   TRACE_EVENT0("loading", "WebURLLoaderImpl::loadSynchronously");
   SyncLoadResponse sync_load_response;
   context_->Start(request, &sync_load_response);
@@ -1332,10 +1335,11 @@
     return;
   }
 
-  PopulateURLResponse(final_url, sync_load_response, &response,
+  PopulateURLResponse(final_url, sync_load_response.info, &response,
                       request.ReportRawHeaders());
-  encoded_data_length = sync_load_response.encoded_data_length;
-  encoded_body_length = sync_load_response.encoded_body_length;
+  encoded_data_length = sync_load_response.info.encoded_data_length;
+  encoded_body_length = sync_load_response.info.encoded_body_length;
+  downloaded_file_length = sync_load_response.downloaded_file_length;
 
   data.Assign(sync_load_response.data.data(), sync_load_response.data.size());
 }
diff --git a/content/renderer/loader/web_url_loader_impl.h b/content/renderer/loader/web_url_loader_impl.h
index 72f37a3f..674a992 100644
--- a/content/renderer/loader/web_url_loader_impl.h
+++ b/content/renderer/loader/web_url_loader_impl.h
@@ -94,12 +94,14 @@
                                   blink::WebURLResponse* response,
                                   bool report_security_info);
   // WebURLLoader methods:
-  void LoadSynchronously(const blink::WebURLRequest& request,
-                         blink::WebURLResponse& response,
-                         base::Optional<blink::WebURLError>& error,
-                         blink::WebData& data,
-                         int64_t& encoded_data_length,
-                         int64_t& encoded_body_length) override;
+  void LoadSynchronously(
+      const blink::WebURLRequest& request,
+      blink::WebURLResponse& response,
+      base::Optional<blink::WebURLError>& error,
+      blink::WebData& data,
+      int64_t& encoded_data_length,
+      int64_t& encoded_body_length,
+      base::Optional<int64_t>& downloaded_file_length) override;
   void LoadAsynchronously(const blink::WebURLRequest& request,
                           blink::WebURLLoaderClient* client) override;
   void Cancel() override;
diff --git a/content/renderer/loader/web_url_loader_impl_unittest.cc b/content/renderer/loader/web_url_loader_impl_unittest.cc
index 142e2cd..aa92d4c24 100644
--- a/content/renderer/loader/web_url_loader_impl_unittest.cc
+++ b/content/renderer/loader/web_url_loader_impl_unittest.cc
@@ -76,8 +76,9 @@
       const net::NetworkTrafficAnnotationTag& traffic_annotation,
       SyncLoadResponse* response,
       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
-      std::vector<std::unique_ptr<URLLoaderThrottle>> throttles) override {
-    *response = sync_load_response_;
+      std::vector<std::unique_ptr<URLLoaderThrottle>> throttles,
+      double timeout) override {
+    *response = std::move(sync_load_response_);
   }
 
   int StartAsync(
@@ -92,7 +93,7 @@
       network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
       base::OnceClosure* continue_navigation_function) override {
     EXPECT_FALSE(peer_);
-    if (sync_load_response_.encoded_body_length != -1)
+    if (sync_load_response_.info.encoded_body_length != -1)
       EXPECT_TRUE(is_sync);
     peer_ = std::move(peer);
     url_ = request->url;
@@ -119,8 +120,8 @@
   }
   bool defers_loading() const { return defers_loading_; }
 
-  void set_sync_load_response(const SyncLoadResponse& sync_load_response) {
-    sync_load_response_ = sync_load_response;
+  void set_sync_load_response(SyncLoadResponse&& sync_load_response) {
+    sync_load_response_ = std::move(sync_load_response);
   }
 
  private:
@@ -770,20 +771,23 @@
   sync_load_response.url = url;
   sync_load_response.data = kBodyData;
   ASSERT_EQ(17u, sync_load_response.data.size());
-  sync_load_response.encoded_body_length = kEncodedBodyLength;
-  sync_load_response.encoded_data_length = kEncodedDataLength;
-  dispatcher()->set_sync_load_response(sync_load_response);
+  sync_load_response.info.encoded_body_length = kEncodedBodyLength;
+  sync_load_response.info.encoded_data_length = kEncodedDataLength;
+  dispatcher()->set_sync_load_response(std::move(sync_load_response));
 
   blink::WebURLResponse response;
   base::Optional<blink::WebURLError> error;
   blink::WebData data;
   int64_t encoded_data_length = 0;
   int64_t encoded_body_length = 0;
+  base::Optional<int64_t> downloaded_file_length;
   client()->loader()->LoadSynchronously(
-      request, response, error, data, encoded_data_length, encoded_body_length);
+      request, response, error, data, encoded_data_length, encoded_body_length,
+      downloaded_file_length);
 
   EXPECT_EQ(kEncodedBodyLength, encoded_body_length);
   EXPECT_EQ(kEncodedDataLength, encoded_data_length);
+  EXPECT_FALSE(downloaded_file_length);
 }
 
 }  // namespace
diff --git a/content/renderer/media/audio_decoder.cc b/content/renderer/media/audio_decoder.cc
index 5fcc4ec..61d455b 100644
--- a/content/renderer/media/audio_decoder.cc
+++ b/content/renderer/media/audio_decoder.cc
@@ -14,7 +14,7 @@
 #include "media/base/limits.h"
 #include "media/filters/audio_file_reader.h"
 #include "media/filters/in_memory_url_protocol.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "third_party/WebKit/public/platform/WebAudioBus.h"
 
 using media::AudioBus;
diff --git a/content/renderer/media/media_factory.cc b/content/renderer/media/media_factory.cc
index e7a4ba3..3ec1d89d 100644
--- a/content/renderer/media/media_factory.cc
+++ b/content/renderer/media/media_factory.cc
@@ -30,7 +30,7 @@
 #include "media/blink/webencryptedmediaclient_impl.h"
 #include "media/blink/webmediaplayer_impl.h"
 #include "media/filters/context_3d.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "media/renderers/default_renderer_factory.h"
 #include "media/video/gpu_video_accelerator_factories.h"
 #include "mojo/public/cpp/bindings/associated_interface_ptr.h"
diff --git a/content/renderer/media/media_factory.h b/content/renderer/media/media_factory.h
index 36171f7..f737371f 100644
--- a/content/renderer/media/media_factory.h
+++ b/content/renderer/media/media_factory.h
@@ -12,8 +12,8 @@
 #include "media/base/renderer_factory_selector.h"
 #include "media/base/routing_token_callback.h"
 #include "media/blink/url_index.h"
-#include "media/media_features.h"
-#include "media/mojo/features.h"
+#include "media/media_buildflags.h"
+#include "media/mojo/buildflags.h"
 #include "media/mojo/interfaces/remoting.mojom.h"
 #include "third_party/WebKit/public/platform/WebMediaPlayerSource.h"
 #include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
diff --git a/content/renderer/media/renderer_webmediaplayer_delegate.cc b/content/renderer/media/renderer_webmediaplayer_delegate.cc
index f773ac55..0b77bbe 100644
--- a/content/renderer/media/renderer_webmediaplayer_delegate.cc
+++ b/content/renderer/media/renderer_webmediaplayer_delegate.cc
@@ -116,6 +116,12 @@
                                                            delegate_id, muted));
 }
 
+void RendererWebMediaPlayerDelegate::DidPictureInPictureSourceChange(
+    int delegate_id) {
+  Send(new MediaPlayerDelegateHostMsg_OnPictureInPictureSourceChanged(
+      routing_id(), delegate_id));
+}
+
 void RendererWebMediaPlayerDelegate::DidPause(int player_id) {
   DVLOG(2) << __func__ << "(" << player_id << ")";
   DCHECK(id_map_.Lookup(player_id));
diff --git a/content/renderer/media/renderer_webmediaplayer_delegate.h b/content/renderer/media/renderer_webmediaplayer_delegate.h
index 8f1fcbe..82f8f7d 100644
--- a/content/renderer/media/renderer_webmediaplayer_delegate.h
+++ b/content/renderer/media/renderer_webmediaplayer_delegate.h
@@ -65,6 +65,7 @@
       blink::WebFullscreenVideoStatus fullscreen_video_status) override;
   void DidPlayerSizeChange(int delegate_id, const gfx::Size& size) override;
   void DidPlayerMutedStatusChange(int delegate_id, bool muted) override;
+  void DidPictureInPictureSourceChange(int delegate_id) override;
 
   // content::RenderFrameObserver overrides.
   void WasHidden() override;
diff --git a/content/renderer/media/stream/media_stream_center.cc b/content/renderer/media/stream/media_stream_center.cc
index ab26e3ba..af1f3c1 100644
--- a/content/renderer/media/stream/media_stream_center.cc
+++ b/content/renderer/media/stream/media_stream_center.cc
@@ -55,6 +55,8 @@
     blink::WebMediaStreamSource::Capabilities capabilities;
     capabilities.device_id = source.Id();
     capabilities.echo_cancellation = std::vector<bool>({false});
+    capabilities.auto_gain_control = std::vector<bool>({false});
+    capabilities.noise_suppression = std::vector<bool>({false});
     source.SetCapabilities(capabilities);
   }
 
diff --git a/content/renderer/media/stream/remote_media_stream_track_adapter.cc b/content/renderer/media/stream/remote_media_stream_track_adapter.cc
index da35517..72b0c2f 100644
--- a/content/renderer/media/stream/remote_media_stream_track_adapter.cc
+++ b/content/renderer/media/stream/remote_media_stream_track_adapter.cc
@@ -92,6 +92,8 @@
   blink::WebMediaStreamSource::Capabilities capabilities;
   capabilities.device_id = blink::WebString::FromUTF8(id());
   capabilities.echo_cancellation = std::vector<bool>({false});
+  capabilities.auto_gain_control = std::vector<bool>({false});
+  capabilities.noise_suppression = std::vector<bool>({false});
   web_track()->Source().SetCapabilities(capabilities);
 
   source->ConnectToTrack(*(web_track()));
diff --git a/content/renderer/media/stream/track_audio_renderer.cc b/content/renderer/media/stream/track_audio_renderer.cc
index 5be9f60..bab5cdd 100644
--- a/content/renderer/media/stream/track_audio_renderer.cc
+++ b/content/renderer/media/stream/track_audio_renderer.cc
@@ -4,6 +4,8 @@
 
 #include "content/renderer/media/stream/track_audio_renderer.h"
 
+#include <utility>
+
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
@@ -264,6 +266,7 @@
   media::OutputDeviceStatus new_sink_status =
       new_sink->GetOutputDeviceInfo().device_status();
   if (new_sink_status != media::OUTPUT_DEVICE_STATUS_OK) {
+    new_sink->Stop();
     callback.Run(new_sink_status);
     return;
   }
diff --git a/content/renderer/media/stream/track_audio_renderer.h b/content/renderer/media/stream/track_audio_renderer.h
index 6c8cfc6..f85eb0892 100644
--- a/content/renderer/media/stream/track_audio_renderer.h
+++ b/content/renderer/media/stream/track_audio_renderer.h
@@ -7,6 +7,7 @@
 
 #include <stdint.h>
 
+#include <memory>
 #include <string>
 #include <vector>
 
diff --git a/content/renderer/media/stream/user_media_processor.cc b/content/renderer/media/stream/user_media_processor.cc
index ba74b41b..603e1b49 100644
--- a/content/renderer/media/stream/user_media_processor.cc
+++ b/content/renderer/media/stream/user_media_processor.cc
@@ -824,6 +824,8 @@
 
   blink::WebMediaStreamSource::Capabilities capabilities;
   capabilities.echo_cancellation = {true, false};
+  capabilities.auto_gain_control = {true, false};
+  capabilities.noise_suppression = {true, false};
   capabilities.device_id = blink::WebString::FromUTF8(device.id);
 
   source.SetExtraData(audio_source);  // Takes ownership.
diff --git a/content/renderer/media/stream/webmediaplayer_ms.cc b/content/renderer/media/stream/webmediaplayer_ms.cc
index dfe5b25b..2ce8813 100644
--- a/content/renderer/media/stream/webmediaplayer_ms.cc
+++ b/content/renderer/media/stream/webmediaplayer_ms.cc
@@ -88,7 +88,7 @@
   ~FrameDeliverer() {
     DCHECK(io_thread_checker_.CalledOnValidThread());
     if (gpu_memory_buffer_pool_) {
-      gpu_memory_buffer_pool_->Abort();
+      DropCurrentPoolTasks();
       media_task_runner_->DeleteSoon(FROM_HERE,
                                      gpu_memory_buffer_pool_.release());
     }
@@ -104,7 +104,7 @@
 #endif  // defined(OS_ANDROID)
 
     if (!gpu_memory_buffer_pool_) {
-      FrameReady(frame);
+      EnqueueFrame(std::move(frame));
       return;
     }
 
@@ -113,38 +113,50 @@
     // frames is unnecessary, because the frames are not going to be shown for
     // the time period.
     if (render_frame_suspended_) {
-      FrameReady(frame);
+      EnqueueFrame(std::move(frame));
       // If there are any existing MaybeCreateHardwareFrame() calls, we do not
       // want those frames to be placed after the current one, so just drop
       // them.
-      gpu_memory_buffer_pool_->Abort();
-      weak_factory_for_pool_.InvalidateWeakPtrs();
+      DropCurrentPoolTasks();
       return;
     }
 
-    //  |gpu_memory_buffer_pool_| deletion is going to be posted to
-    //  |media_task_runner_|. base::Unretained() usage is fine since
-    //  |gpu_memory_buffer_pool_| outlives the task.
+    // |gpu_memory_buffer_pool_| deletion is going to be posted to
+    // |media_task_runner_|. base::Unretained() usage is fine since
+    // |gpu_memory_buffer_pool_| outlives the task.
     media_task_runner_->PostTask(
         FROM_HERE,
         base::BindOnce(
             &media::GpuMemoryBufferVideoFramePool::MaybeCreateHardwareFrame,
             base::Unretained(gpu_memory_buffer_pool_.get()), frame,
             media::BindToCurrentLoop(
-                base::BindOnce(&FrameDeliverer::FrameReady,
+                base::BindOnce(&FrameDeliverer::EnqueueFrame,
                                weak_factory_for_pool_.GetWeakPtr()))));
   }
 
-  void FrameReady(const scoped_refptr<media::VideoFrame>& frame) {
+  void SetRenderFrameSuspended(bool render_frame_suspended) {
+    DCHECK(io_thread_checker_.CalledOnValidThread());
+    render_frame_suspended_ = render_frame_suspended;
+  }
+
+  MediaStreamVideoRenderer::RepaintCB GetRepaintCallback() {
+    return base::Bind(&FrameDeliverer::OnVideoFrame,
+                      weak_factory_.GetWeakPtr());
+  }
+
+ private:
+  friend class WebMediaPlayerMS;
+
+  void EnqueueFrame(const scoped_refptr<media::VideoFrame>& frame) {
     DCHECK(io_thread_checker_.CalledOnValidThread());
 
     base::TimeTicks render_time;
     if (frame->metadata()->GetTimeTicks(
             media::VideoFrameMetadata::REFERENCE_TIME, &render_time)) {
-      TRACE_EVENT1("media", "FrameReady", "Ideal Render Instant",
+      TRACE_EVENT1("media", "EnqueueFrame", "Ideal Render Instant",
                    render_time.ToInternalValue());
     } else {
-      TRACE_EVENT0("media", "FrameReady");
+      TRACE_EVENT0("media", "EnqueueFrame");
     }
 
     const bool is_opaque = media::IsOpaque(frame->format());
@@ -177,18 +189,22 @@
     enqueue_frame_cb_.Run(frame);
   }
 
-  void SetRenderFrameSuspended(bool render_frame_suspended) {
+  void DropCurrentPoolTasks() {
     DCHECK(io_thread_checker_.CalledOnValidThread());
-    render_frame_suspended_ = render_frame_suspended;
-  }
+    DCHECK(gpu_memory_buffer_pool_);
 
-  MediaStreamVideoRenderer::RepaintCB GetRepaintCallback() {
-    return base::Bind(&FrameDeliverer::OnVideoFrame,
-                      weak_factory_.GetWeakPtr());
-  }
+    if (!weak_factory_for_pool_.HasWeakPtrs())
+      return;
 
- private:
-  friend class WebMediaPlayerMS;
+    //  |gpu_memory_buffer_pool_| deletion is going to be posted to
+    //  |media_task_runner_|. base::Unretained() usage is fine since
+    //  |gpu_memory_buffer_pool_| outlives the task.
+    media_task_runner_->PostTask(
+        FROM_HERE,
+        base::BindOnce(&media::GpuMemoryBufferVideoFramePool::Abort,
+                       base::Unretained(gpu_memory_buffer_pool_.get())));
+    weak_factory_for_pool_.InvalidateWeakPtrs();
+  }
 
   bool last_frame_opaque_;
   media::VideoRotation last_frame_rotation_;
diff --git a/content/renderer/media/stream/webmediaplayer_ms_unittest.cc b/content/renderer/media/stream/webmediaplayer_ms_unittest.cc
index 6f02524..edce0b5 100644
--- a/content/renderer/media/stream/webmediaplayer_ms_unittest.cc
+++ b/content/renderer/media/stream/webmediaplayer_ms_unittest.cc
@@ -73,6 +73,10 @@
     EXPECT_EQ(delegate_id_, delegate_id);
   }
 
+  void DidPictureInPictureSourceChange(int delegate_id) override {
+    EXPECT_EQ(delegate_id_, delegate_id);
+  }
+
   void DidPause(int delegate_id) override {
     EXPECT_EQ(delegate_id_, delegate_id);
     EXPECT_TRUE(playing_);
@@ -239,8 +243,8 @@
   started_ = true;
   paused_ = false;
   task_runner_->PostTask(
-      FROM_HERE, base::BindOnce(&MockMediaStreamVideoRenderer::InjectFrame,
-                                base::Unretained(this)));
+      FROM_HERE,
+      base::BindOnce(&MockMediaStreamVideoRenderer::InjectFrame, this));
 }
 
 void MockMediaStreamVideoRenderer::Stop() {
@@ -348,8 +352,7 @@
 
   task_runner_->PostDelayedTask(
       FROM_HERE,
-      base::BindOnce(&MockMediaStreamVideoRenderer::InjectFrame,
-                     base::Unretained(this)),
+      base::BindOnce(&MockMediaStreamVideoRenderer::InjectFrame, this),
       delay_till_next_generated_frame_);
 
   // This will pause the |message_loop_|, and the purpose is to allow the main
@@ -1094,7 +1097,7 @@
 
 // Hidden and closed trigger different events on Android and this test doesn't
 // cover that, see HiddenPlayerTests for specifics.
-#if !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
+#if !defined(OS_ANDROID)
 // Tests that GpuMemoryBufferVideoFramePool is not called when page is hidden.
 TEST_F(WebMediaPlayerMSTest, StopsCreatingHardwareFramesWhenHiddenOrClosed) {
   MockMediaStreamVideoRenderer* provider = LoadAndGetFrameProvider(true);
diff --git a/content/renderer/media/webrtc/peer_connection_dependency_factory.cc b/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
index 51679b7..f614e28 100644
--- a/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
+++ b/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
@@ -53,7 +53,7 @@
 #include "crypto/openssl_util.h"
 #include "jingle/glue/thread_wrapper.h"
 #include "media/base/media_permission.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "media/video/gpu_video_accelerator_factories.h"
 #include "third_party/WebKit/public/platform/WebMediaConstraints.h"
 #include "third_party/WebKit/public/platform/WebMediaStream.h"
diff --git a/content/renderer/media/webrtc/rtc_certificate_generator.cc b/content/renderer/media/webrtc/rtc_certificate_generator.cc
index 3daabb6f..1c14fb2 100644
--- a/content/renderer/media/webrtc/rtc_certificate_generator.cc
+++ b/content/renderer/media/webrtc/rtc_certificate_generator.cc
@@ -15,7 +15,7 @@
 #include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
 #include "content/renderer/media/webrtc/rtc_certificate.h"
 #include "content/renderer/render_thread_impl.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "third_party/webrtc/rtc_base/rtccertificate.h"
 #include "third_party/webrtc/rtc_base/rtccertificategenerator.h"
 #include "third_party/webrtc/rtc_base/scoped_ref_ptr.h"
diff --git a/content/renderer/media/webrtc/rtc_video_encoder_factory.cc b/content/renderer/media/webrtc/rtc_video_encoder_factory.cc
index 25104c2..3307c40 100644
--- a/content/renderer/media/webrtc/rtc_video_encoder_factory.cc
+++ b/content/renderer/media/webrtc/rtc_video_encoder_factory.cc
@@ -12,7 +12,7 @@
 #include "content/public/common/content_switches.h"
 #include "content/public/common/feature_h264_with_openh264_ffmpeg.h"
 #include "content/renderer/media/webrtc/rtc_video_encoder.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "media/video/gpu_video_accelerator_factories.h"
 #include "third_party/webrtc/common_video/h264/profile_level_id.h"
 
diff --git a/content/renderer/media/webrtc/webrtc_audio_renderer.cc b/content/renderer/media/webrtc/webrtc_audio_renderer.cc
index b34f7f8..323cf397 100644
--- a/content/renderer/media/webrtc/webrtc_audio_renderer.cc
+++ b/content/renderer/media/webrtc/webrtc_audio_renderer.cc
@@ -207,6 +207,7 @@
 
   if (sink_->GetOutputDeviceInfo().device_status() !=
       media::OUTPUT_DEVICE_STATUS_OK) {
+    sink_->Stop();
     return false;
   }
 
@@ -391,6 +392,7 @@
   media::OutputDeviceStatus status =
       new_sink->GetOutputDeviceInfo().device_status();
   if (status != media::OUTPUT_DEVICE_STATUS_OK) {
+    new_sink->Stop();
     callback.Run(status);
     return;
   }
diff --git a/content/renderer/media/webrtc/webrtc_audio_renderer_unittest.cc b/content/renderer/media/webrtc/webrtc_audio_renderer_unittest.cc
index 45e7dc9..8719d8b 100644
--- a/content/renderer/media/webrtc/webrtc_audio_renderer_unittest.cc
+++ b/content/renderer/media/webrtc/webrtc_audio_renderer_unittest.cc
@@ -105,24 +105,25 @@
       int session_id,
       const std::string& device_id,
       const url::Origin& security_origin) {
-    scoped_refptr<media::MockAudioRendererSink> fake_sink(
-        new media::MockAudioRendererSink(
-            device_id, device_id == kInvalidOutputDeviceId
-                           ? media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL
-                           : media::OUTPUT_DEVICE_STATUS_OK,
-            media::AudioParameters(
-                media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
-                media::CHANNEL_LAYOUT_STEREO, kHardwareSampleRate, 16,
-                kHardwareBufferSize)));
+    mock_sink_ = new media::MockAudioRendererSink(
+        device_id,
+        device_id == kInvalidOutputDeviceId
+            ? media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL
+            : media::OUTPUT_DEVICE_STATUS_OK,
+        media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+                               media::CHANNEL_LAYOUT_STEREO,
+                               kHardwareSampleRate, 16, kHardwareBufferSize));
+
     if (device_id != kInvalidOutputDeviceId) {
-      mock_sink_ = fake_sink;
       EXPECT_CALL(*mock_sink_.get(), Start());
       EXPECT_CALL(*mock_sink_.get(), Play());
+    } else {
+      EXPECT_CALL(*mock_sink_.get(), Stop());
     }
 
     MockCreateAudioRendererSink(source_type, render_frame_id, session_id,
                                 device_id, security_origin);
-    return fake_sink;
+    return mock_sink_;
   }
 
   void TearDown() override {
@@ -260,6 +261,7 @@
   SetupRenderer(kDefaultOutputDeviceId);
   EXPECT_EQ(kDefaultOutputDeviceId,
             mock_sink_->GetOutputDeviceInfo().device_id());
+  auto original_sink = mock_sink_;
   renderer_proxy_->Start();
 
   EXPECT_CALL(*this,
@@ -274,11 +276,27 @@
                  base::Unretained(this), &loop));
   loop.Run();
   EXPECT_EQ(kDefaultOutputDeviceId,
-            mock_sink_->GetOutputDeviceInfo().device_id());
+            original_sink->GetOutputDeviceInfo().device_id());
 
-  EXPECT_CALL(*mock_sink_.get(), Stop());
+  EXPECT_CALL(*original_sink.get(), Stop());
   EXPECT_CALL(*source_.get(), RemoveAudioRenderer(renderer_.get()));
   renderer_proxy_->Stop();
 }
 
+TEST_F(WebRtcAudioRendererTest, InitializeWithInvalidDevice) {
+  renderer_ = new WebRtcAudioRenderer(message_loop_->task_runner(), stream_, 1,
+                                      1, kInvalidOutputDeviceId, url::Origin());
+
+  EXPECT_CALL(*this,
+              MockCreateAudioRendererSink(AudioDeviceFactory::kSourceWebRtc, _,
+                                          _, kInvalidOutputDeviceId, _));
+
+  EXPECT_FALSE(renderer_->Initialize(source_.get()));
+
+  renderer_proxy_ = renderer_->CreateSharedAudioRendererProxy(stream_);
+
+  EXPECT_EQ(kInvalidOutputDeviceId,
+            mock_sink_->GetOutputDeviceInfo().device_id());
+}
+
 }  // namespace content
diff --git a/content/renderer/mus/renderer_window_tree_client.cc b/content/renderer/mus/renderer_window_tree_client.cc
index 1907fde..1a9d6b64 100644
--- a/content/renderer/mus/renderer_window_tree_client.cc
+++ b/content/renderer/mus/renderer_window_tree_client.cc
@@ -12,6 +12,7 @@
 #include "components/viz/client/client_layer_tree_frame_sink.h"
 #include "components/viz/client/hit_test_data_provider.h"
 #include "components/viz/client/hit_test_data_provider_draw_quad.h"
+#include "components/viz/client/hit_test_data_provider_surface_layer.h"
 #include "components/viz/client/local_surface_id_provider.h"
 #include "components/viz/common/features.h"
 #include "content/renderer/mus/mus_embedded_frame.h"
@@ -144,6 +145,9 @@
     params.hit_test_data_provider =
         std::make_unique<viz::HitTestDataProviderDrawQuad>(
             true /* should_ask_for_child_region */);
+  } else if (features::IsVizHitTestingSurfaceLayerEnabled()) {
+    params.hit_test_data_provider =
+        std::make_unique<viz::HitTestDataProviderSurfaceLayer>();
   }
   auto frame_sink = std::make_unique<viz::ClientLayerTreeFrameSink>(
       std::move(context_provider), nullptr /* worker_context_provider */,
diff --git a/content/renderer/pepper/content_renderer_pepper_host_factory.cc b/content/renderer/pepper/content_renderer_pepper_host_factory.cc
index 06866d3..a79c6a0 100644
--- a/content/renderer/pepper/content_renderer_pepper_host_factory.cc
+++ b/content/renderer/pepper/content_renderer_pepper_host_factory.cc
@@ -33,7 +33,7 @@
 #include "content/renderer/pepper/pepper_websocket_host.h"
 #include "content/renderer/pepper/ppb_image_data_impl.h"
 #include "content/renderer/pepper/renderer_ppapi_host_impl.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "ppapi/host/resource_host.h"
 #include "ppapi/proxy/ppapi_message_utils.h"
 #include "ppapi/proxy/ppapi_messages.h"
diff --git a/content/renderer/pepper/pepper_media_device_manager.cc b/content/renderer/pepper/pepper_media_device_manager.cc
index 445c1cc6..2a1593af 100644
--- a/content/renderer/pepper/pepper_media_device_manager.cc
+++ b/content/renderer/pepper/pepper_media_device_manager.cc
@@ -15,7 +15,7 @@
 #include "content/renderer/media/stream/media_stream_device_observer.h"
 #include "content/renderer/pepper/renderer_ppapi_host_impl.h"
 #include "content/renderer/render_frame_impl.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "ppapi/shared_impl/ppb_device_ref_shared.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
 
diff --git a/content/renderer/pepper/resource_converter.cc b/content/renderer/pepper/resource_converter.cc
index 4c33c05..7d5fa38a 100644
--- a/content/renderer/pepper/resource_converter.cc
+++ b/content/renderer/pepper/resource_converter.cc
@@ -13,7 +13,7 @@
 #include "content/renderer/pepper/pepper_media_stream_audio_track_host.h"
 #include "content/renderer/pepper/pepper_media_stream_video_track_host.h"
 #include "ipc/ipc_message.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "ppapi/host/ppapi_host.h"
 #include "ppapi/host/resource_host.h"
 #include "ppapi/proxy/ppapi_messages.h"
diff --git a/content/renderer/pepper/url_request_info_util.cc b/content/renderer/pepper/url_request_info_util.cc
index b50ab70..87db75f 100644
--- a/content/renderer/pepper/url_request_info_util.cc
+++ b/content/renderer/pepper/url_request_info_util.cc
@@ -29,6 +29,7 @@
 #include "third_party/WebKit/public/platform/WebHTTPBody.h"
 #include "third_party/WebKit/public/platform/WebURL.h"
 #include "third_party/WebKit/public/platform/WebURLRequest.h"
+#include "third_party/WebKit/public/platform/web_feature.mojom.h"
 #include "third_party/WebKit/public/web/WebDocument.h"
 #include "third_party/WebKit/public/web/WebLocalFrame.h"
 #include "url/gurl.h"
@@ -173,6 +174,11 @@
   dest->SetDownloadToFile(data->stream_to_file);
   dest->SetReportUploadProgress(data->record_upload_progress);
 
+  if (data->stream_to_file) {
+    frame->BlinkFeatureUsageReport({static_cast<int>(
+        blink::mojom::WebFeature::kPPAPIURLRequestStreamToFile)});
+  }
+
   if (!data->method.empty())
     dest->SetHTTPMethod(WebString::FromUTF8(data->method));
 
diff --git a/content/renderer/pepper/video_decoder_shim.cc b/content/renderer/pepper/video_decoder_shim.cc
index a20432f7..ee5593f 100644
--- a/content/renderer/pepper/video_decoder_shim.cc
+++ b/content/renderer/pepper/video_decoder_shim.cc
@@ -31,7 +31,7 @@
 #include "media/base/video_decoder.h"
 #include "media/filters/ffmpeg_video_decoder.h"
 #include "media/filters/vpx_video_decoder.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "media/video/picture.h"
 #include "media/video/video_decode_accelerator.h"
 #include "ppapi/c/pp_errors.h"
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index e2f3492..21d09e8 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -4057,7 +4057,7 @@
 
   // Set the navigation start time in blink.
   document_loader->SetNavigationStartTime(
-      ConvertToBlinkTime(navigation_state->common_params().navigation_start));
+      navigation_state->common_params().navigation_start);
 
   // If an actual navigation took place, inform the document loader of what
   // happened in the browser.
@@ -4065,12 +4065,12 @@
            .navigation_timing.fetch_start.is_null()) {
     // Set timing of several events that happened during navigation.
     // They will be used in blink for the Navigation Timing API.
-    double redirect_start = ConvertToBlinkTime(
-        navigation_state->request_params().navigation_timing.redirect_start);
-    double redirect_end = ConvertToBlinkTime(
-        navigation_state->request_params().navigation_timing.redirect_end);
-    double fetch_start = ConvertToBlinkTime(
-        navigation_state->request_params().navigation_timing.fetch_start);
+    base::TimeTicks redirect_start =
+        navigation_state->request_params().navigation_timing.redirect_start;
+    base::TimeTicks redirect_end =
+        navigation_state->request_params().navigation_timing.redirect_end;
+    base::TimeTicks fetch_start =
+        navigation_state->request_params().navigation_timing.fetch_start;
 
     document_loader->UpdateNavigation(
         redirect_start, redirect_end, fetch_start,
@@ -4805,7 +4805,6 @@
   WebDocumentLoader* document_loader = provisional_document_loader
                                            ? provisional_document_loader
                                            : frame_->GetDocumentLoader();
-
   DocumentState* document_state =
       DocumentState::FromDocumentLoader(document_loader);
   DCHECK(document_state);
@@ -4821,10 +4820,17 @@
   }
 
   GURL new_url;
-  if (GetContentClient()->renderer()->WillSendRequest(
-          frame_, transition_type, request.Url(), &new_url)) {
+  bool attach_same_site_cookies = false;
+  base::Optional<url::Origin> initiator_origin =
+      request.RequestorOrigin().IsNull()
+          ? base::Optional<url::Origin>()
+          : base::Optional<url::Origin>(request.RequestorOrigin());
+  GetContentClient()->renderer()->WillSendRequest(
+      frame_, transition_type, request.Url(),
+      base::OptionalOrNullptr(initiator_origin), &new_url,
+      &attach_same_site_cookies);
+  if (!new_url.is_empty())
     request.SetURL(WebURL(new_url));
-  }
 
   if (internal_data->is_cache_policy_override_set())
     request.SetCacheMode(internal_data->cache_policy_override());
@@ -4893,6 +4899,7 @@
   extra_data->set_download_to_network_cache_only(
       is_for_no_state_prefetch && resource_type != RESOURCE_TYPE_MAIN_FRAME);
   extra_data->set_initiated_in_secure_context(frame_document.IsSecureContext());
+  extra_data->set_attach_same_site_cookies(attach_same_site_cookies);
 
   // Renderer process transfers apply only to navigational requests.
   bool is_navigational_request =
@@ -6052,6 +6059,46 @@
   // See http://crbug.com/93517.
   GURL old_url(frame_->GetDocumentLoader()->GetRequest().Url());
 
+  // Detect when a page is "forking" a new tab that can be safely rendered in
+  // its own process.  This is done by sites like Gmail that try to open links
+  // in new windows without script connections back to the original page.  We
+  // treat such cases as browser navigations (in which we will create a new
+  // renderer for a cross-site navigation), rather than WebKit navigations.
+  //
+  // We use the following heuristic to decide whether to fork a new page in its
+  // own process:
+  // The parent page must open a new tab to about:blank, set the new tab's
+  // window.opener to null, and then redirect the tab to a cross-site URL using
+  // JavaScript.
+  //
+  // TODO(creis): Deprecate this logic once we can rely on rel=noreferrer
+  // (see below).
+  bool is_fork =
+      // Must start from a tab showing about:blank, which is later redirected.
+      old_url == url::kAboutBlankURL &&
+      // Must be the first real navigation of the tab.
+      render_view_->HistoryBackListCount() < 1 &&
+      render_view_->HistoryForwardListCount() < 1 &&
+      // The parent page must have set the child's window.opener to null before
+      // redirecting to the desired URL.
+      frame_->Opener() == nullptr &&
+      // Must be a top-level frame.
+      frame_->Parent() == nullptr &&
+      // Must not have issued the request from this page.
+      is_content_initiated &&
+      // Must be targeted at the current tab.
+      info.default_policy == blink::kWebNavigationPolicyCurrentTab &&
+      // Must be a JavaScript navigation, which appears as "other".
+      info.navigation_type == blink::kWebNavigationTypeOther;
+
+  if (is_fork) {
+    // Open the URL via the browser, not via WebKit. Make sure the referrer is
+    // stripped.
+    OpenURL(info, /*send_referrer=*/false,
+            /*is_history_navigation_in_new_child=*/false);
+    return blink::kWebNavigationPolicyIgnore;
+  }
+
   // Detect when we're crossing a permission-based boundary (e.g. into or out of
   // an extension or app origin, leaving a WebUI page, etc). We only care about
   // top-level navigations (not iframes). But we sometimes navigate to
@@ -6099,46 +6146,6 @@
     }
   }
 
-  // Detect when a page is "forking" a new tab that can be safely rendered in
-  // its own process.  This is done by sites like Gmail that try to open links
-  // in new windows without script connections back to the original page.  We
-  // treat such cases as browser navigations (in which we will create a new
-  // renderer for a cross-site navigation), rather than WebKit navigations.
-  //
-  // We use the following heuristic to decide whether to fork a new page in its
-  // own process:
-  // The parent page must open a new tab to about:blank, set the new tab's
-  // window.opener to null, and then redirect the tab to a cross-site URL using
-  // JavaScript.
-  //
-  // TODO(creis): Deprecate this logic once we can rely on rel=noreferrer
-  // (see below).
-  bool is_fork =
-      // Must start from a tab showing about:blank, which is later redirected.
-      old_url == url::kAboutBlankURL &&
-      // Must be the first real navigation of the tab.
-      render_view_->HistoryBackListCount() < 1 &&
-      render_view_->HistoryForwardListCount() < 1 &&
-      // The parent page must have set the child's window.opener to null before
-      // redirecting to the desired URL.
-      frame_->Opener() == nullptr &&
-      // Must be a top-level frame.
-      frame_->Parent() == nullptr &&
-      // Must not have issued the request from this page.
-      is_content_initiated &&
-      // Must be targeted at the current tab.
-      info.default_policy == blink::kWebNavigationPolicyCurrentTab &&
-      // Must be a JavaScript navigation, which appears as "other".
-      info.navigation_type == blink::kWebNavigationTypeOther;
-
-  if (is_fork) {
-    // Open the URL via the browser, not via WebKit. Make sure the referrer is
-    // stripped.
-    OpenURL(info, /*send_referrer=*/false,
-            /*is_history_navigation_in_new_child=*/false);
-    return blink::kWebNavigationPolicyIgnore;
-  }
-
   bool should_dispatch_before_unload =
       info.default_policy == blink::kWebNavigationPolicyCurrentTab &&
       // There is no need to execute the BeforeUnload event during a redirect,
@@ -6540,6 +6547,8 @@
 void RenderFrameImpl::OnSelectPopupMenuItem(int selected_index) {
   if (external_popup_menu_ == NULL)
     return;
+
+  blink::WebScopedUserGesture gesture(frame_);
   external_popup_menu_->DidSelectItem(selected_index);
   external_popup_menu_.reset();
 }
@@ -6554,6 +6563,7 @@
   if (!external_popup_menu_)
     return;
 
+  blink::WebScopedUserGesture gesture(frame_);
   external_popup_menu_->DidSelectItems(canceled, selected_indices);
   external_popup_menu_.reset();
 }
diff --git a/content/renderer/render_frame_metadata_observer_impl.cc b/content/renderer/render_frame_metadata_observer_impl.cc
index 3230f7d..35a4dbd4 100644
--- a/content/renderer/render_frame_metadata_observer_impl.cc
+++ b/content/renderer/render_frame_metadata_observer_impl.cc
@@ -27,37 +27,56 @@
 
 void RenderFrameMetadataObserverImpl::OnRenderFrameSubmission(
     cc::RenderFrameMetadata metadata) {
-  if (!render_frame_metadata_observer_client_)
-    return;
-
   // By default only report metadata changes for fields which have a low
-  // frequency of change. However if there are changes in high frequency fields
-  // these can be reported while testing is enabled.
+  // frequency of change. However if there are changes in high frequency
+  // fields these can be reported while testing is enabled.
   bool send_metadata = false;
-  if (report_all_frame_submissions_for_testing_enabled_) {
-    render_frame_metadata_observer_client_->OnFrameSubmissionForTesting(
-        frame_token_allocator_->GetOrAllocateFrameToken());
-    send_metadata = last_render_frame_metadata_ != metadata;
-  } else {
-    // Sending |root_scroll_offset| outside of tests would leave the browser
-    // process with out of date information. It is an optional parameter which
-    // we clear here.
-    metadata.root_scroll_offset = base::nullopt;
-    send_metadata = cc::RenderFrameMetadata::HasAlwaysUpdateMetadataChanged(
-        last_render_frame_metadata_, metadata);
+  if (render_frame_metadata_observer_client_) {
+    if (report_all_frame_submissions_for_testing_enabled_) {
+      last_frame_token_ = frame_token_allocator_->GetOrAllocateFrameToken();
+      render_frame_metadata_observer_client_->OnFrameSubmissionForTesting(
+          last_frame_token_);
+      send_metadata = last_render_frame_metadata_ != metadata;
+    } else {
+      send_metadata = cc::RenderFrameMetadata::HasAlwaysUpdateMetadataChanged(
+          last_render_frame_metadata_, metadata);
+    }
   }
 
-  if (send_metadata) {
-    render_frame_metadata_observer_client_->OnRenderFrameMetadataChanged(
-        frame_token_allocator_->GetOrAllocateFrameToken(), metadata);
-  }
-
+  // Allways cache the full metadata, so that it can correctly be sent upon
+  // ReportAllFrameSubmissionsForTesting. This must only be done after we've
+  // compared the two for changes.
   last_render_frame_metadata_ = metadata;
+
+  if (send_metadata && render_frame_metadata_observer_client_) {
+    // Sending |root_scroll_offset| outside of tests would leave the browser
+    // process with out of date information. It is an optional parameter
+    // which we clear here.
+    if (!render_frame_metadata_observer_client_)
+      metadata.root_scroll_offset = base::nullopt;
+
+    last_frame_token_ = frame_token_allocator_->GetOrAllocateFrameToken();
+    render_frame_metadata_observer_client_->OnRenderFrameMetadataChanged(
+        last_frame_token_, metadata);
+  }
+
+  // Always cache the initial frame token, so that if a test connects later on
+  // it can be notified of the initial state.
+  if (!last_frame_token_)
+    last_frame_token_ = frame_token_allocator_->GetOrAllocateFrameToken();
 }
 
 void RenderFrameMetadataObserverImpl::ReportAllFrameSubmissionsForTesting(
     bool enabled) {
   report_all_frame_submissions_for_testing_enabled_ = enabled;
+
+  if (!enabled || !last_frame_token_)
+    return;
+
+  // When enabled for testing send the cached metadata.
+  DCHECK(render_frame_metadata_observer_client_);
+  render_frame_metadata_observer_client_->OnRenderFrameMetadataChanged(
+      last_frame_token_, last_render_frame_metadata_);
 }
 
 }  // namespace content
diff --git a/content/renderer/render_frame_metadata_observer_impl.h b/content/renderer/render_frame_metadata_observer_impl.h
index b963608..cc07fe99 100644
--- a/content/renderer/render_frame_metadata_observer_impl.h
+++ b/content/renderer/render_frame_metadata_observer_impl.h
@@ -47,10 +47,11 @@
   // frame submissions.
   bool report_all_frame_submissions_for_testing_enabled_ = false;
 
+  uint32_t last_frame_token_ = 0;
   cc::RenderFrameMetadata last_render_frame_metadata_;
 
   // Not owned.
-  cc::FrameTokenAllocator* frame_token_allocator_;
+  cc::FrameTokenAllocator* frame_token_allocator_ = nullptr;
 
   // These are destroyed when BindToCurrentThread() is called.
   mojom::RenderFrameMetadataObserverRequest request_;
diff --git a/content/renderer/render_process_impl.cc b/content/renderer/render_process_impl.cc
index b01a33f..511fcd7c 100644
--- a/content/renderer/render_process_impl.cc
+++ b/content/renderer/render_process_impl.cc
@@ -85,13 +85,13 @@
                                       kSuggestedReclaimTime));
 }
 
-#if DCHECK_IS_ON() && defined(SYZYASAN)
+#if DCHECK_IS_CONFIGURABLE
 void V8DcheckCallbackHandler(const char* file, int line, const char* message) {
   // TODO(siggi): Set a crash key or a breadcrumb so the fact that we hit a
   //     V8 DCHECK gets out in the crash report.
   ::logging::LogMessage(file, line, logging::LOG_DCHECK).stream() << message;
 }
-#endif  // DCHECK_IS_ON() && defined(SYZYASAN)
+#endif  // DCHECK_IS_CONFIGURABLE
 
 }  // namespace
 
@@ -101,15 +101,14 @@
     std::unique_ptr<base::TaskScheduler::InitParams> task_scheduler_init_params)
     : RenderProcess("Renderer", std::move(task_scheduler_init_params)),
       enabled_bindings_(0) {
-
-#if DCHECK_IS_ON() && defined(SYZYASAN)
-  // SyzyASAN official builds can ship with DCHECKs compiled in. Failing DCHECKs
-  // then are either fatal or simply log the error, based on a feature flag.
+#if DCHECK_IS_CONFIGURABLE
+  // Some official builds ship with DCHECKs compiled in. Failing DCHECKs then
+  // are either fatal or simply log the error, based on a feature flag.
   // Make sure V8 follows suit by setting a Dcheck handler that forwards to
   // the Chrome base logging implementation.
   v8::V8::SetDcheckErrorHandler(&V8DcheckCallbackHandler);
 
-  if (!base::FeatureList::IsEnabled(base::kSyzyAsanDCheckIsFatalFeature)) {
+  if (!base::FeatureList::IsEnabled(base::kDCheckIsFatalFeature)) {
     // These V8 flags default on in this build configuration. This triggers
     // additional verification and code generation, which both slows down V8,
     // and can lead to fatal CHECKs. Turn these flags down to get something
@@ -122,7 +121,7 @@
 
     v8::V8::SetFlagsFromString(kDisabledFlags, sizeof(kDisabledFlags));
   }
-#endif  // DCHECK_IS_ON() && defined(SYZYASAN)
+#endif  // DCHECK_IS_CONFIGURABLE
 
   if (base::SysInfo::IsLowEndDevice()) {
     std::string optimize_flag("--optimize-for-size");
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index 417b891..cc58867 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -54,6 +54,7 @@
 #include "components/viz/client/client_shared_bitmap_manager.h"
 #include "components/viz/client/hit_test_data_provider.h"
 #include "components/viz/client/hit_test_data_provider_draw_quad.h"
+#include "components/viz/client/hit_test_data_provider_surface_layer.h"
 #include "components/viz/client/local_surface_id_provider.h"
 #include "components/viz/common/features.h"
 #include "components/viz/common/frame_sinks/copy_output_request.h"
@@ -135,7 +136,7 @@
 #include "ipc/ipc_platform_file.h"
 #include "media/base/media.h"
 #include "media/base/media_switches.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "media/video/gpu_video_accelerator_factories.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "mojo/public/cpp/system/message_pipe.h"
@@ -2075,6 +2076,9 @@
     params.hit_test_data_provider =
         std::make_unique<viz::HitTestDataProviderDrawQuad>(
             true /* should_ask_for_child_region */);
+  } else if (features::IsVizHitTestingSurfaceLayerEnabled()) {
+    params.hit_test_data_provider =
+        std::make_unique<viz::HitTestDataProviderSurfaceLayer>();
   }
 
   // The renderer runs animations and layout for animate_only BeginFrames.
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h
index 83701a3dd..4a9978b 100644
--- a/content/renderer/render_thread_impl.h
+++ b/content/renderer/render_thread_impl.h
@@ -49,7 +49,7 @@
 #include "content/renderer/media/audio_output_ipc_factory.h"
 #include "gpu/ipc/client/gpu_channel_host.h"
 #include "ipc/ipc_sync_channel.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "mojo/public/cpp/bindings/associated_binding.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/bindings/thread_safe_interface_ptr.h"
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index f915ac0..b1bf2a9 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -2436,6 +2436,54 @@
   render_thread_->sink().RemoveFilter(callback_filter.get());
 }
 
+// IPC Listener that runs a callback when a javascript modal dialog is
+// triggered.
+class AlertCallbackFilter : public IPC::Listener {
+ public:
+  explicit AlertCallbackFilter(
+      base::RepeatingCallback<void(const base::string16&)> callback)
+      : callback_(std::move(callback)) {}
+
+  bool OnMessageReceived(const IPC::Message& msg) override {
+    bool handled = true;
+    IPC_BEGIN_MESSAGE_MAP(AlertCallbackFilter, msg)
+      IPC_MESSAGE_HANDLER(FrameHostMsg_RunJavaScriptDialog,
+                          OnRunJavaScriptDialog)
+      IPC_MESSAGE_UNHANDLED(handled = false)
+    IPC_END_MESSAGE_MAP()
+    return handled;
+  }
+
+  // Not really part of IPC::Listener but required to intercept a sync msg.
+  void Send(const IPC::Message* msg) { delete msg; }
+
+  void OnRunJavaScriptDialog(const base::string16& message,
+                             const base::string16&,
+                             JavaScriptDialogType,
+                             bool*,
+                             base::string16*) {
+    callback_.Run(message);
+  }
+
+ private:
+  base::RepeatingCallback<void(const base::string16&)> callback_;
+};
+
+// Test that invoking one of the modal dialogs doesn't crash.
+TEST_F(RenderViewImplTest, ModalDialogs) {
+  LoadHTML("<body></body>");
+
+  std::unique_ptr<AlertCallbackFilter> callback_filter(new AlertCallbackFilter(
+      base::BindRepeating([](const base::string16& msg) {
+        EXPECT_EQ(base::UTF8ToUTF16("Please don't crash"), msg);
+      })));
+  render_thread_->sink().AddFilter(callback_filter.get());
+
+  frame()->GetWebFrame()->Alert(WebString::FromUTF8("Please don't crash"));
+
+  render_thread_->sink().RemoveFilter(callback_filter.get());
+}
+
 TEST_F(RenderViewImplBlinkSettingsTest, Default) {
   DoSetUp();
   EXPECT_FALSE(settings()->ViewportEnabled());
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index ed59511..230c63d 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -97,7 +97,7 @@
 #include "content/renderer/web_ui_extension_data.h"
 #include "media/audio/audio_output_device.h"
 #include "media/base/media_switches.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "media/renderers/audio_renderer_impl.h"
 #include "media/video/gpu_video_accelerator_factories.h"
 #include "net/base/data_url.h"
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc
index 1bbcdd0..3b161536 100644
--- a/content/renderer/renderer_blink_platform_impl.cc
+++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -1007,6 +1007,8 @@
   blink::WebMediaStreamSource::Capabilities capabilities;
   capabilities.device_id = track_id;
   capabilities.echo_cancellation = std::vector<bool>({false});
+  capabilities.auto_gain_control = std::vector<bool>({false});
+  capabilities.noise_suppression = std::vector<bool>({false});
   web_media_stream_source.SetCapabilities(capabilities);
 
   media_stream_source->ConnectToTrack(web_media_stream_track);
diff --git a/content/renderer/renderer_main.cc b/content/renderer/renderer_main.cc
index 91bb5b4..b7c1911 100644
--- a/content/renderer/renderer_main.cc
+++ b/content/renderer/renderer_main.cc
@@ -31,7 +31,7 @@
 #include "content/renderer/render_process_impl.h"
 #include "content/renderer/render_thread_impl.h"
 #include "content/renderer/renderer_main_platform_delegate.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "ppapi/features/features.h"
 #include "third_party/WebKit/public/platform/scheduler/renderer/renderer_scheduler.h"
 #include "third_party/skia/include/core/SkGraphics.h"
diff --git a/content/renderer/service_worker/service_worker_fetch_context_impl.cc b/content/renderer/service_worker/service_worker_fetch_context_impl.cc
index dd9d0ce..ed9bcd7 100644
--- a/content/renderer/service_worker/service_worker_fetch_context_impl.cc
+++ b/content/renderer/service_worker/service_worker_fetch_context_impl.cc
@@ -25,12 +25,22 @@
     : worker_script_url_(worker_script_url),
       url_loader_factory_info_(std::move(url_loader_factory_info)),
       service_worker_provider_id_(service_worker_provider_id),
-      throttle_provider_(std::move(throttle_provider)) {}
+      throttle_provider_(std::move(throttle_provider)),
+      terminate_sync_load_event_(
+          base::WaitableEvent::ResetPolicy::MANUAL,
+          base::WaitableEvent::InitialState::NOT_SIGNALED) {}
 
 ServiceWorkerFetchContextImpl::~ServiceWorkerFetchContextImpl() {}
 
+base::WaitableEvent*
+ServiceWorkerFetchContextImpl::GetTerminateSyncLoadEvent() {
+  return &terminate_sync_load_event_;
+}
+
 void ServiceWorkerFetchContextImpl::InitializeOnWorkerThread() {
   resource_dispatcher_ = std::make_unique<ResourceDispatcher>();
+  resource_dispatcher_->set_terminate_sync_load_event(
+      &terminate_sync_load_event_);
 
   url_loader_factory_ = network::SharedURLLoaderFactory::Create(
       std::move(url_loader_factory_info_));
diff --git a/content/renderer/service_worker/service_worker_fetch_context_impl.h b/content/renderer/service_worker/service_worker_fetch_context_impl.h
index 1a009948..2bf1830 100644
--- a/content/renderer/service_worker/service_worker_fetch_context_impl.h
+++ b/content/renderer/service_worker/service_worker_fetch_context_impl.h
@@ -24,6 +24,7 @@
   ~ServiceWorkerFetchContextImpl() override;
 
   // blink::WebWorkerFetchContext implementation:
+  base::WaitableEvent* GetTerminateSyncLoadEvent() override;
   void InitializeOnWorkerThread() override;
   std::unique_ptr<blink::WebURLLoaderFactory> CreateURLLoaderFactory() override;
   std::unique_ptr<blink::WebURLLoaderFactory> WrapURLLoaderFactory(
@@ -40,9 +41,12 @@
 
   // Initialized on the worker thread when InitializeOnWorkerThread() is called.
   std::unique_ptr<ResourceDispatcher> resource_dispatcher_;
+
   scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
 
   std::unique_ptr<URLLoaderThrottleProvider> throttle_provider_;
+
+  base::WaitableEvent terminate_sync_load_event_;
 };
 
 }  // namespace content
diff --git a/content/renderer/service_worker/worker_fetch_context_impl.cc b/content/renderer/service_worker/worker_fetch_context_impl.cc
index d7d886d..3b3a6e40 100644
--- a/content/renderer/service_worker/worker_fetch_context_impl.cc
+++ b/content/renderer/service_worker/worker_fetch_context_impl.cc
@@ -111,6 +111,9 @@
       direct_network_loader_factory_info_(
           std::move(direct_network_factory_info)),
       thread_safe_sender_(ChildThreadImpl::current()->thread_safe_sender()),
+      terminate_sync_load_event_(
+          base::WaitableEvent::ResetPolicy::MANUAL,
+          base::WaitableEvent::InitialState::NOT_SIGNALED),
       throttle_provider_(std::move(throttle_provider)) {
   if (ServiceWorkerUtils::IsServicificationEnabled()) {
     ChildThreadImpl::current()->GetConnector()->BindInterface(
@@ -121,10 +124,16 @@
 
 WorkerFetchContextImpl::~WorkerFetchContextImpl() {}
 
+base::WaitableEvent* WorkerFetchContextImpl::GetTerminateSyncLoadEvent() {
+  return &terminate_sync_load_event_;
+}
+
 void WorkerFetchContextImpl::InitializeOnWorkerThread() {
   DCHECK(!resource_dispatcher_);
   DCHECK(!binding_.is_bound());
   resource_dispatcher_ = std::make_unique<ResourceDispatcher>();
+  resource_dispatcher_->set_terminate_sync_load_event(
+      &terminate_sync_load_event_);
 
   shared_url_loader_factory_ = network::SharedURLLoaderFactory::Create(
       std::move(url_loader_factory_info_));
diff --git a/content/renderer/service_worker/worker_fetch_context_impl.h b/content/renderer/service_worker/worker_fetch_context_impl.h
index 1da9db08..94bed59 100644
--- a/content/renderer/service_worker/worker_fetch_context_impl.h
+++ b/content/renderer/service_worker/worker_fetch_context_impl.h
@@ -5,6 +5,7 @@
 #ifndef CONTENT_RENDERER_SERVICE_WORKER_WORKER_FETCH_CONTEXT_IMPL_H_
 #define CONTENT_RENDERER_SERVICE_WORKER_WORKER_FETCH_CONTEXT_IMPL_H_
 
+#include "base/synchronization/waitable_event.h"
 #include "content/common/service_worker/service_worker_provider.mojom.h"
 #include "content/common/service_worker/service_worker_types.h"
 #include "ipc/ipc_message.h"
@@ -53,6 +54,7 @@
   ~WorkerFetchContextImpl() override;
 
   // blink::WebWorkerFetchContext implementation:
+  base::WaitableEvent* GetTerminateSyncLoadEvent() override;
   void InitializeOnWorkerThread() override;
   std::unique_ptr<blink::WebURLLoaderFactory> CreateURLLoaderFactory() override;
   std::unique_ptr<blink::WebURLLoaderFactory> WrapURLLoaderFactory(
@@ -151,6 +153,8 @@
   GURL origin_url_;
   int appcache_host_id_ = blink::WebApplicationCacheHost::kAppCacheNoHostId;
 
+  base::WaitableEvent terminate_sync_load_event_;
+
   // A weak ptr to blink::WebURLLoaderFactory which was created and passed to
   // Blink by CreateURLLoaderFactory().
   base::WeakPtr<URLLoaderFactoryImpl> url_loader_factory_;
diff --git a/content/shell/BUILD.gn b/content/shell/BUILD.gn
index 36d89f7..a111d58 100644
--- a/content/shell/BUILD.gn
+++ b/content/shell/BUILD.gn
@@ -269,7 +269,7 @@
     "//gpu",
     "//media",
     "//media/capture",
-    "//media/mojo:features",
+    "//media/mojo:buildflags",
     "//net",
     "//net:net_resources",
     "//net:test_support",
diff --git a/content/shell/app/shell_main_delegate.cc b/content/shell/app/shell_main_delegate.cc
index 8be76edc..243f321 100644
--- a/content/shell/app/shell_main_delegate.cc
+++ b/content/shell/app/shell_main_delegate.cc
@@ -37,7 +37,7 @@
 #include "content/shell/renderer/shell_content_renderer_client.h"
 #include "content/shell/utility/shell_content_utility_client.h"
 #include "gpu/config/gpu_switches.h"
-#include "ipc/ipc_features.h"
+#include "ipc/ipc_buildflags.h"
 #include "media/base/media_switches.h"
 #include "net/cookies/cookie_monster.h"
 #include "ppapi/features/features.h"
diff --git a/content/shell/browser/layout_test/layout_test_browser_context.cc b/content/shell/browser/layout_test/layout_test_browser_context.cc
index ca6f4568..888dc81 100644
--- a/content/shell/browser/layout_test/layout_test_browser_context.cc
+++ b/content/shell/browser/layout_test/layout_test_browser_context.cc
@@ -42,7 +42,9 @@
       std::make_unique<device::ScopedGeolocationOverrider>(0, 0);
 }
 
-LayoutTestBrowserContext::~LayoutTestBrowserContext() {}
+LayoutTestBrowserContext::~LayoutTestBrowserContext() {
+  BrowserContext::NotifyWillBeDestroyed(this);
+}
 
 ShellURLRequestContextGetter*
 LayoutTestBrowserContext::CreateURLRequestContextGetter(
diff --git a/content/shell/browser/layout_test/layout_test_browser_context.h b/content/shell/browser/layout_test/layout_test_browser_context.h
index 693ca7c..338b416 100644
--- a/content/shell/browser/layout_test/layout_test_browser_context.h
+++ b/content/shell/browser/layout_test/layout_test_browser_context.h
@@ -26,7 +26,7 @@
 class PermissionManager;
 class PushMessagingService;
 
-class LayoutTestBrowserContext : public ShellBrowserContext {
+class LayoutTestBrowserContext final : public ShellBrowserContext {
  public:
   LayoutTestBrowserContext(bool off_the_record, net::NetLog* net_log);
   ~LayoutTestBrowserContext() override;
diff --git a/content/shell/browser/shell.cc b/content/shell/browser/shell.cc
index 6b3e245..9b1bac2 100644
--- a/content/shell/browser/shell.cc
+++ b/content/shell/browser/shell.cc
@@ -42,7 +42,7 @@
 #include "content/shell/common/layout_test/layout_test_switches.h"
 #include "content/shell/common/shell_messages.h"
 #include "content/shell/common/shell_switches.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "third_party/WebKit/public/web/WebPresentationReceiverFlags.h"
 
 namespace content {
diff --git a/content/shell/browser/shell_browser_context.cc b/content/shell/browser/shell_browser_context.cc
index 9fadbe9..4a84313 100644
--- a/content/shell/browser/shell_browser_context.cc
+++ b/content/shell/browser/shell_browser_context.cc
@@ -68,6 +68,8 @@
 }
 
 ShellBrowserContext::~ShellBrowserContext() {
+  NotifyWillBeDestroyed(this);
+
   BrowserContextDependencyManager::GetInstance()->
       DestroyBrowserContextServices(this);
   // Need to destruct the ResourceContext before posting tasks which may delete
diff --git a/content/shell/browser/shell_browser_main_parts.cc b/content/shell/browser/shell_browser_main_parts.cc
index 4801819..4829736 100644
--- a/content/shell/browser/shell_browser_main_parts.cc
+++ b/content/shell/browser/shell_browser_main_parts.cc
@@ -159,8 +159,6 @@
   DCHECK(!field_trial_list_);
   field_trial_list_.reset(new base::FieldTrialList(nullptr));
 
-  std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
-
   const base::CommandLine* command_line =
       base::CommandLine::ForCurrentProcess();
 
@@ -174,10 +172,6 @@
     CHECK(result) << "Invalid --" << ::switches::kForceFieldTrials
                   << " list specified.";
   }
-
-  feature_list->InitializeFromCommandLine(
-      command_line->GetSwitchValueASCII(switches::kEnableFeatures),
-      command_line->GetSwitchValueASCII(switches::kDisableFeatures));
 }
 
 int ShellBrowserMainParts::PreCreateThreads() {
diff --git a/content/shell/browser/shell_content_browser_client.cc b/content/shell/browser/shell_content_browser_client.cc
index 47cf05f..a092307 100644
--- a/content/shell/browser/shell_content_browser_client.cc
+++ b/content/shell/browser/shell_content_browser_client.cc
@@ -41,7 +41,7 @@
 #include "content/shell/common/shell_messages.h"
 #include "content/shell/common/shell_switches.h"
 #include "content/shell/grit/shell_resources.h"
-#include "media/mojo/features.h"
+#include "media/mojo/buildflags.h"
 #include "net/ssl/client_cert_identity.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_context_getter.h"
diff --git a/content/shell/browser/shell_url_request_context_getter.cc b/content/shell/browser/shell_url_request_context_getter.cc
index dcb1541..e4cf8769 100644
--- a/content/shell/browser/shell_url_request_context_getter.cc
+++ b/content/shell/browser/shell_url_request_context_getter.cc
@@ -32,7 +32,7 @@
 #include "net/dns/host_resolver.h"
 #include "net/dns/mapped_host_resolver.h"
 #include "net/http/http_network_session.h"
-#include "net/net_features.h"
+#include "net/net_buildflags.h"
 #include "net/proxy_resolution/proxy_config_service.h"
 #include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/ssl/channel_id_service.h"
diff --git a/content/shell/common/shell_switches.cc b/content/shell/common/shell_switches.cc
index 5f56df2a..d196d3c 100644
--- a/content/shell/common/shell_switches.cc
+++ b/content/shell/common/shell_switches.cc
@@ -42,6 +42,10 @@
 // Hides toolbar from content_shell's host window.
 const char kContentShellHideToolbar[] = "content-shell-hide-toolbar";
 
+// Forces all navigations to go through the browser process (in a
+// non-PlzNavigate way).
+const char kContentShellAlwaysFork[] = "content-shell-always-fork";
+
 std::vector<std::string> GetSideloadFontFiles() {
   std::vector<std::string> files;
   const base::CommandLine& command_line =
diff --git a/content/shell/common/shell_switches.h b/content/shell/common/shell_switches.h
index 06554041..a06d39e 100644
--- a/content/shell/common/shell_switches.h
+++ b/content/shell/common/shell_switches.h
@@ -20,6 +20,7 @@
 extern const char kRegisterFontFiles[];
 extern const char kContentShellHostWindowSize[];
 extern const char kContentShellHideToolbar[];
+extern const char kContentShellAlwaysFork[];
 
 // Returns list of extra font files to be made accessible to the renderer.
 std::vector<std::string> GetSideloadFontFiles();
diff --git a/content/shell/renderer/layout_test/blink_test_runner.cc b/content/shell/renderer/layout_test/blink_test_runner.cc
index e8a0363..d00750ad 100644
--- a/content/shell/renderer/layout_test/blink_test_runner.cc
+++ b/content/shell/renderer/layout_test/blink_test_runner.cc
@@ -59,7 +59,7 @@
 #include "media/base/audio_capturer_source.h"
 #include "media/base/audio_parameters.h"
 #include "media/capture/video_capturer_source.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "net/base/filename_util.h"
 #include "net/base/net_errors.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
diff --git a/content/shell/renderer/layout_test/layout_test_content_renderer_client.cc b/content/shell/renderer/layout_test/layout_test_content_renderer_client.cc
index 8dda39e..c540054 100644
--- a/content/shell/renderer/layout_test/layout_test_content_renderer_client.cc
+++ b/content/shell/renderer/layout_test/layout_test_content_renderer_client.cc
@@ -35,7 +35,7 @@
 #include "content/test/mock_webclipboard_impl.h"
 #include "media/base/audio_latency.h"
 #include "media/base/mime_util.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "third_party/WebKit/public/platform/WebAudioLatencyHint.h"
 #include "third_party/WebKit/public/platform/WebMediaStreamCenter.h"
 #include "third_party/WebKit/public/platform/WebRTCPeerConnectionHandler.h"
diff --git a/content/shell/renderer/layout_test/leak_detector.cc b/content/shell/renderer/layout_test/leak_detector.cc
index fff07b9..8ebc1b7 100644
--- a/content/shell/renderer/layout_test/leak_detector.cc
+++ b/content/shell/renderer/layout_test/leak_detector.cc
@@ -32,6 +32,7 @@
 const int kInitialNumberOfScriptPromises = 0;
 const int kInitialNumberOfLiveFrames = 1;
 const int kInitialNumberOfWorkerGlobalScopes = 0;
+const int kInitialNumberOfLiveResourceFetchers = 1;
 
 // In the initial state, there are two PausableObjects (FontFaceSet created
 // by HTMLDocument and PausableTimer created by DocumentLoader).
@@ -60,6 +61,8 @@
       kInitialNumberOfV8PerContextData;
   previous_result_.number_of_worker_global_scopes =
       kInitialNumberOfWorkerGlobalScopes;
+  previous_result_.number_of_live_resource_fetchers =
+      kInitialNumberOfLiveResourceFetchers;
 }
 
 LeakDetector::~LeakDetector() {
@@ -149,6 +152,13 @@
     list->AppendInteger(result.number_of_worker_global_scopes);
     detail.Set("numberOfWorkerGlobalScopes", std::move(list));
   }
+  if (previous_result_.number_of_live_resource_fetchers <
+      result.number_of_live_resource_fetchers) {
+    auto list = std::make_unique<base::ListValue>();
+    list->AppendInteger(previous_result_.number_of_live_resource_fetchers);
+    list->AppendInteger(result.number_of_live_resource_fetchers);
+    detail.Set("numberOfLiveResourceFetchers", std::move(list));
+  }
 
   if (!detail.empty()) {
     std::string detail_str;
diff --git a/content/shell/renderer/layout_test/test_media_stream_renderer_factory.cc b/content/shell/renderer/layout_test/test_media_stream_renderer_factory.cc
index 17b6359..7a2f7c2 100644
--- a/content/shell/renderer/layout_test/test_media_stream_renderer_factory.cc
+++ b/content/shell/renderer/layout_test/test_media_stream_renderer_factory.cc
@@ -5,7 +5,7 @@
 #include "content/shell/renderer/layout_test/test_media_stream_renderer_factory.h"
 
 #include "content/shell/renderer/layout_test/test_media_stream_video_renderer.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "third_party/WebKit/public/platform/WebMediaStream.h"
 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
 #include "third_party/WebKit/public/web/WebMediaStreamRegistry.h"
diff --git a/content/shell/renderer/shell_content_renderer_client.cc b/content/shell/renderer/shell_content_renderer_client.cc
index d2d8144..725d161 100644
--- a/content/shell/renderer/shell_content_renderer_client.cc
+++ b/content/shell/renderer/shell_content_renderer_client.cc
@@ -186,6 +186,20 @@
   }
 }
 
+bool ShellContentRendererClient::ShouldFork(blink::WebLocalFrame* frame,
+                                            const GURL& url,
+                                            const std::string& http_method,
+                                            bool is_initial_navigation,
+                                            bool is_server_redirect,
+                                            bool* send_referrer) {
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kContentShellAlwaysFork)) {
+    *send_referrer = true;
+    return true;
+  }
+  return false;
+}
+
 #if BUILDFLAG(ENABLE_MOJO_CDM)
 void ShellContentRendererClient::AddSupportedKeySystems(
     std::vector<std::unique_ptr<media::KeySystemProperties>>* key_systems) {
diff --git a/content/shell/renderer/shell_content_renderer_client.h b/content/shell/renderer/shell_content_renderer_client.h
index 5e47780..41cc6bb8 100644
--- a/content/shell/renderer/shell_content_renderer_client.h
+++ b/content/shell/renderer/shell_content_renderer_client.h
@@ -11,7 +11,7 @@
 #include "base/compiler_specific.h"
 #include "build/build_config.h"
 #include "content/public/renderer/content_renderer_client.h"
-#include "media/mojo/features.h"
+#include "media/mojo/buildflags.h"
 
 namespace web_cache {
 class WebCacheImpl;
@@ -49,6 +49,13 @@
   void DidInitializeWorkerContextOnWorkerThread(
       v8::Local<v8::Context> context) override;
 
+  bool ShouldFork(blink::WebLocalFrame* frame,
+                  const GURL& url,
+                  const std::string& http_method,
+                  bool is_initial_navigation,
+                  bool is_server_redirect,
+                  bool* send_referrer) override;
+
 #if BUILDFLAG(ENABLE_MOJO_CDM)
   void AddSupportedKeySystems(
       std::vector<std::unique_ptr<media::KeySystemProperties>>* key_systems)
diff --git a/content/shell/test_runner/test_interfaces.cc b/content/shell/test_runner/test_interfaces.cc
index 25a283b..ba8af9b 100644
--- a/content/shell/test_runner/test_interfaces.cc
+++ b/content/shell/test_runner/test_interfaces.cc
@@ -96,7 +96,8 @@
     spec = spec.substr(path_start);
   bool is_devtools_test = spec.find("/devtools/") != std::string::npos;
   test_runner_->setShouldGeneratePixelResults(generate_pixels);
-  if (spec.find("loading/") != std::string::npos)
+  // For http/tests/loading/, which is served via httpd and becomes /loading/.
+  if (spec.find("/loading/") != std::string::npos)
     test_runner_->setShouldDumpFrameLoadCallbacks(true);
   if (spec.find("/dumpAsText/") != std::string::npos) {
     test_runner_->setShouldDumpAsText(true);
diff --git a/content/shell/test_runner/text_input_controller.cc b/content/shell/test_runner/text_input_controller.cc
index 3193a76..3bb08a6 100644
--- a/content/shell/test_runner/text_input_controller.cc
+++ b/content/shell/test_runner/text_input_controller.cc
@@ -382,7 +382,7 @@
 
   std::vector<blink::WebImeTextSpan> ime_text_spans;
   ime_text_spans.push_back(blink::WebImeTextSpan(
-      blink::WebImeTextSpan::Type::kComposition, 0, textLength, SK_ColorBLACK,
+      blink::WebImeTextSpan::Type::kComposition, 0, textLength,
       ui::mojom::ImeTextSpanThickness::kThin, SK_ColorTRANSPARENT));
   if (auto* controller = GetInputMethodController()) {
     controller->SetComposition(
diff --git a/content/test/data/download/download-attribute-with-target.html b/content/test/data/download/download-attribute-with-target.html
deleted file mode 100644
index e658fcc3..0000000
--- a/content/test/data/download/download-attribute-with-target.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<!doctype html>
-<html>
-<body>
-<a download="suggested-filename" href="data:application/octet-stream, ..." target="_blank">link</a>
-<script>
-  var anchorElement = document.querySelector('a[download]');
-  anchorElement.click();
-</script>
-</body>
-</html>
diff --git a/content/test/data/echo-referrer.html b/content/test/data/echo-referrer.html
new file mode 100644
index 0000000..c6d4fe0d
--- /dev/null
+++ b/content/test/data/echo-referrer.html
@@ -0,0 +1,4 @@
+<!doctype html>
+<script>
+document.title = "Referrer = '" + document.referrer + "'";
+</script>
diff --git a/content/test/data/fork-popup.html b/content/test/data/fork-popup.html
new file mode 100644
index 0000000..ccc9268
--- /dev/null
+++ b/content/test/data/fork-popup.html
@@ -0,0 +1,8 @@
+<!doctype html>
+<script>
+let win = window.open('', '_blank', '');
+win.opener = null;
+win.document.write('<META HTTP-EQUIV="refresh" content="0; url=' + location.origin + '/echo-referrer.html">')
+win.document.close();
+</script>
+
diff --git a/content/test/data/htxg/README b/content/test/data/htxg/README
index a6b8ff2..607c0ef 100644
--- a/content/test/data/htxg/README
+++ b/content/test/data/htxg/README
@@ -1,8 +1,22 @@
 The certificate message files (*.msg) and the signed exchange files (*.htxg) in
 this directory are generated using the following commands.
 
-gen-certurl and gen-signedexchange are available in webpackage repository.
+gen-certurl and gen-signedexchange are available in webpackage repository [1].
+We're using a fork of this repository [2] that implements the "Implementation
+Checkpoints" of the signed-exchange spec [3].
+
  [1] https://github.com/WICG/webpackage
+ [2] https://github.com/nyaxt/webpackage
+ [3] https://jyasskin.github.io/webpackage/implementation-draft/draft-yasskin-httpbis-origin-signed-exchanges-impl.html
+
+# Download the webpackage repository
+go get -d github.com/WICG/webpackage/go/signedexchange
+
+# Switch to the fork repository
+cd ${GOPATH:-~/go}/src/github.com/WICG/webpackage
+git remote add impl https://github.com/nyaxt/webpackage.git
+git fetch impl master
+git checkout -b impl impl/master
 
 # Install gen-certurl command
 go get github.com/WICG/webpackage/go/signedexchange/cmd/gen-certurl
@@ -42,6 +56,7 @@
   -certUrl https://cert.example.org/cert.msg \
   -validityUrl https://cert.example.org/resource.validity.msg \
   -privateKey /tmp/wildcard_example.org.private.pem \
+  -date 2018-03-12T05:53:20Z \
   -o test.example.org_test.htxg \
   -miRecordSize 100
 
@@ -54,9 +69,11 @@
   -certUrl https://cert.example.org/cert.msg \
   -validityUrl https://cert.example.org/resource.validity.msg \
   -privateKey /tmp/wildcard_example.org.private.pem \
+  -date 2018-03-12T05:53:20Z \
   -o test.example.com_invalid_test.htxg \
   -miRecordSize 100
 
+# Generate the signed exchange for a plain text file.
 gen-signedexchange \
   -uri https://test.example.org/hello.txt \
   -status 200 \
@@ -66,4 +83,5 @@
   -validityUrl https://cert.example.org/resource.validity.msg \
   -privateKey /tmp/wildcard_example.org.private.pem \
   -responseHeader 'Content-Type: text/plain; charset=iso-8859-1' \
+  -date 2018-03-12T05:53:20Z \
   -o test.example.org_hello.txt.htxg
diff --git a/content/test/data/htxg/signed_exchange_header_test.htxg b/content/test/data/htxg/signed_exchange_header_test.htxg
deleted file mode 100644
index c7c65e9..0000000
--- a/content/test/data/htxg/signed_exchange_header_test.htxg
+++ /dev/null
Binary files differ
diff --git a/content/test/data/htxg/test.example.com_invalid_test.htxg b/content/test/data/htxg/test.example.com_invalid_test.htxg
index c6d20b6..1349415 100644
--- a/content/test/data/htxg/test.example.com_invalid_test.htxg
+++ b/content/test/data/htxg/test.example.com_invalid_test.htxg
Binary files differ
diff --git a/content/test/data/htxg/test.example.org_hello.txt.htxg b/content/test/data/htxg/test.example.org_hello.txt.htxg
index a084d05d..b3ddc29 100644
--- a/content/test/data/htxg/test.example.org_hello.txt.htxg
+++ b/content/test/data/htxg/test.example.org_hello.txt.htxg
Binary files differ
diff --git a/content/test/data/htxg/test.example.org_test.htxg b/content/test/data/htxg/test.example.org_test.htxg
index cef4177..8bd13b4 100644
--- a/content/test/data/htxg/test.example.org_test.htxg
+++ b/content/test/data/htxg/test.example.org_test.htxg
Binary files differ
diff --git a/content/test/data/media/peerconnection-call.html b/content/test/data/media/peerconnection-call.html
index 96ef18e1b..243a54d 100644
--- a/content/test/data/media/peerconnection-call.html
+++ b/content/test/data/media/peerconnection-call.html
@@ -238,10 +238,10 @@
     createConnections(null);
     setOfferSdpTransform(removeCrypto);
     setOnLocalDescriptionError(function(error) {
-      var expectedMsg = 'Failed to set local offer sdp:' +
-          ' Called with SDP without DTLS fingerprint.';
-
-      assertEquals(expectedMsg, error.message);
+      // Note: Per spec, error should be 'IllegalModificationError'
+      // https://crbug.com/823036
+      var expectedError = 'OperationError';
+      assertEquals(expectedError, error.name);
       reportTestSuccess();
     });
     navigator.mediaDevices.getUserMedia({audio: true, video: true})
diff --git a/content/test/data/page_with_cached_subresource.html b/content/test/data/page_with_cached_subresource.html
new file mode 100644
index 0000000..2fc67bc
--- /dev/null
+++ b/content/test/data/page_with_cached_subresource.html
@@ -0,0 +1,7 @@
+<html>
+<head>
+<script src="cachetime"></script>
+</head>
+<body>
+</body>
+</html>
\ No newline at end of file
diff --git a/content/test/fuzzer/BUILD.gn b/content/test/fuzzer/BUILD.gn
index 7a8bc2a..98ddcb9 100644
--- a/content/test/fuzzer/BUILD.gn
+++ b/content/test/fuzzer/BUILD.gn
@@ -102,6 +102,18 @@
   testonly = true
 }
 
+fuzzer_test("signed_exchange_header_fuzzer") {
+  sources = [
+    "signed_exchange_header_fuzzer.cc",
+  ]
+  deps = [
+    ":fuzzer_support",
+    "//base:i18n",
+    "//content/browser:for_content_tests",
+  ]
+  seed_corpus = "//content/test/data/htxg/"
+}
+
 fuzzer_test("signed_exchange_header_parser_fuzzer") {
   sources = [
     "signed_exchange_header_parser_fuzzer.cc",
diff --git a/content/test/fuzzer/signed_exchange_header_fuzzer.cc b/content/test/fuzzer/signed_exchange_header_fuzzer.cc
new file mode 100644
index 0000000..e0362bc5
--- /dev/null
+++ b/content/test/fuzzer/signed_exchange_header_fuzzer.cc
@@ -0,0 +1,25 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/at_exit.h"
+#include "base/containers/span.h"
+#include "base/i18n/icu_util.h"
+#include "content/browser/web_package/signed_exchange_header.h"  // nogncheck
+
+namespace content {
+
+struct IcuEnvironment {
+  IcuEnvironment() { CHECK(base::i18n::InitializeICU()); }
+  // used by ICU integration.
+  base::AtExitManager at_exit_manager;
+};
+
+IcuEnvironment* env = new IcuEnvironment();
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  SignedExchangeHeader::Parse(base::make_span(data, size));
+  return 0;
+}
+
+}  // namespace content
diff --git a/content/test/fuzzer/signed_exchange_header_parser_fuzzer.cc b/content/test/fuzzer/signed_exchange_header_parser_fuzzer.cc
index 1866a46..c60acee 100644
--- a/content/test/fuzzer/signed_exchange_header_parser_fuzzer.cc
+++ b/content/test/fuzzer/signed_exchange_header_parser_fuzzer.cc
@@ -17,7 +17,7 @@
 IcuEnvironment* env = new IcuEnvironment();
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  std::string input(reinterpret_cast<const char*>(data), size);
+  base::StringPiece input(reinterpret_cast<const char*>(data), size);
   SignedExchangeHeaderParser::ParseSignature(input);
   return 0;
 }
diff --git a/content/test/gpu/generate_buildbot_json.py b/content/test/gpu/generate_buildbot_json.py
index 0921860c..08f64a7 100755
--- a/content/test/gpu/generate_buildbot_json.py
+++ b/content/test/gpu/generate_buildbot_json.py
@@ -2436,7 +2436,7 @@
     'tester_configs': [
       {
         'predicate': Predicates.FYI_AND_OPTIONAL,
-        # Run on the Win/Linux Release NVIDIA bots and Nexus 5X and 6P
+        # Run on the Win/Linux Release NVIDIA bots and Android
         'build_configs': ['Release', 'android-chromium'],
         'swarming_dimension_sets': [
           {
@@ -2447,19 +2447,9 @@
             'gpu': LINUX_QUADRO_P400_STABLE_DRIVER,
             'os': 'Ubuntu'
           },
-          # Nexus 5X
           {
-            'device_type': 'bullhead',
-            'device_os': 'MMB29Q',
             'os': 'Android'
           },
-          # Nexus 6P
-          {
-            'device_type': 'angler',
-            'device_os': 'M',
-            'os': 'Android',
-            'pool': 'Chrome-GPU',
-          }
         ],
       },
     ],
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
index f80c963..780b06d 100644
--- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -258,6 +258,9 @@
         'teximage3d_pbo_3d*',
         ['win', 'amd', 'd3d11'], bug=2424) # ANGLE bug ID
     self.Fail('deqp/functional/gles3/texturespecification/' +
+        'teximage3d_unpack_params.html',
+        ['win', 'amd', 'd3d11'], bug=2424) # ANGLE bug ID
+    self.Fail('deqp/functional/gles3/texturespecification/' +
         'texsubimage3d_unpack_params.html',
         ['win', 'amd', 'd3d11'], bug=2424) # ANGLE bug ID
 
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
index 944ce938..8f3488b 100644
--- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -281,6 +281,8 @@
         ['win7', 'nvidia', 'd3d9'], bug=690248)
 
     # Win / Intel
+    self.Flaky('conformance/extensions/oes-texture-float-with-video.html',
+        ['win', 'intel'], bug=825338)
     self.Fail('conformance/rendering/rendering-stencil-large-viewport.html',
         ['win', 'intel', 'd3d11'], bug=782317)
 
diff --git a/content/test/mock_overscroll_controller_delegate_aura.cc b/content/test/mock_overscroll_controller_delegate_aura.cc
index e6f4c1e..9f34812c8 100644
--- a/content/test/mock_overscroll_controller_delegate_aura.cc
+++ b/content/test/mock_overscroll_controller_delegate_aura.cc
@@ -46,7 +46,8 @@
 void MockOverscrollControllerDelegateAura::OnOverscrollModeChange(
     OverscrollMode old_mode,
     OverscrollMode new_mode,
-    OverscrollSource source) {
+    OverscrollSource source,
+    cc::OverscrollBehavior behavior) {
   if (new_mode == OVERSCROLL_NONE)
     OnOverscrollEnd();
 }
diff --git a/content/test/mock_overscroll_controller_delegate_aura.h b/content/test/mock_overscroll_controller_delegate_aura.h
index b872513b..4b81a30 100644
--- a/content/test/mock_overscroll_controller_delegate_aura.h
+++ b/content/test/mock_overscroll_controller_delegate_aura.h
@@ -26,12 +26,12 @@
   // OverscrollControllerDelegate:
   gfx::Size GetDisplaySize() const override;
   base::Optional<float> GetMaxOverscrollDelta() const override;
-  void OnOverscrollBehaviorUpdate(cc::OverscrollBehavior) override {}
   bool OnOverscrollUpdate(float, float) override;
   void OnOverscrollComplete(OverscrollMode) override;
   void OnOverscrollModeChange(OverscrollMode old_mode,
                               OverscrollMode new_mode,
-                              OverscrollSource source) override;
+                              OverscrollSource source,
+                              cc::OverscrollBehavior behavior) override;
 
   // MockOverscrollObserver:
   void WaitForUpdate() override;
diff --git a/content/test/test_blink_web_unit_test_support.cc b/content/test/test_blink_web_unit_test_support.cc
index dd75dbe7..225a880f 100644
--- a/content/test/test_blink_web_unit_test_support.cc
+++ b/content/test/test_blink_web_unit_test_support.cc
@@ -25,7 +25,7 @@
 #include "content/test/mock_webclipboard_impl.h"
 #include "content/test/web_gesture_curve_mock.h"
 #include "media/base/media.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "net/cookies/cookie_monster.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
 #include "third_party/WebKit/public/platform/WebConnectionType.h"
diff --git a/content/test/test_overscroll_delegate.cc b/content/test/test_overscroll_delegate.cc
index 83733490..84114970 100644
--- a/content/test/test_overscroll_delegate.cc
+++ b/content/test/test_overscroll_delegate.cc
@@ -39,9 +39,11 @@
   current_mode_ = OVERSCROLL_NONE;
 }
 
-void TestOverscrollDelegate::OnOverscrollModeChange(OverscrollMode old_mode,
-                                                    OverscrollMode new_mode,
-                                                    OverscrollSource source) {
+void TestOverscrollDelegate::OnOverscrollModeChange(
+    OverscrollMode old_mode,
+    OverscrollMode new_mode,
+    OverscrollSource source,
+    cc::OverscrollBehavior behavior) {
   DCHECK_EQ(current_mode_, old_mode);
   current_mode_ = new_mode;
   historical_modes_.push_back(new_mode);
diff --git a/content/test/test_overscroll_delegate.h b/content/test/test_overscroll_delegate.h
index 6fdd9d85..7b42430 100644
--- a/content/test/test_overscroll_delegate.h
+++ b/content/test/test_overscroll_delegate.h
@@ -38,9 +38,8 @@
   void OnOverscrollComplete(OverscrollMode overscroll_mode) override;
   void OnOverscrollModeChange(OverscrollMode old_mode,
                               OverscrollMode new_mode,
-                              OverscrollSource source) override;
-  void OnOverscrollBehaviorUpdate(
-      cc::OverscrollBehavior overscroll_behavior) override {}
+                              OverscrollSource source,
+                              cc::OverscrollBehavior behavior) override;
   base::Optional<float> GetMaxOverscrollDelta() const override;
 
   gfx::Size display_size_;
diff --git a/content/test/test_render_frame.cc b/content/test/test_render_frame.cc
index a09d1ea..b0c0ffd 100644
--- a/content/test/test_render_frame.cc
+++ b/content/test/test_render_frame.cc
@@ -84,7 +84,10 @@
   void BeginNavigation(const CommonNavigationParams& common_params,
                        mojom::BeginNavigationParamsPtr begin_params) override {}
 
-  void SubresourceResponseStarted(
+  void SubresourceResponseStarted(const GURL& url,
+                                  net::CertStatus cert_status) override {}
+
+  void SubresourceLoadComplete(
       mojom::SubresourceLoadInfoPtr subresource_load_info) override {}
 
   void DidChangeName(const std::string& name,
diff --git a/content/test/web_contents_observer_sanity_checker.cc b/content/test/web_contents_observer_sanity_checker.cc
index 115cc21..89ee990 100644
--- a/content/test/web_contents_observer_sanity_checker.cc
+++ b/content/test/web_contents_observer_sanity_checker.cc
@@ -194,6 +194,10 @@
   CHECK(navigation_handle->GetRenderFrameHost());
   CHECK_EQ(navigation_handle->GetWebContents(), web_contents());
   CHECK(navigation_handle->GetRenderFrameHost() != nullptr);
+
+  ready_to_commit_hosts_.insert(
+      std::make_pair(navigation_handle->GetNavigationId(),
+                     navigation_handle->GetRenderFrameHost()));
 }
 
 void WebContentsObserverSanityChecker::DidFinishNavigation(
@@ -208,6 +212,16 @@
   CHECK(!navigation_handle->HasCommitted() ||
         navigation_handle->GetRenderFrameHost() != nullptr);
 
+  // If ReadyToCommitNavigation was dispatched, verify that the
+  // |navigation_handle| has the same RenderFrameHost at this time as the one
+  // returned at ReadyToCommitNavigation.
+  if (base::ContainsKey(ready_to_commit_hosts_,
+                        navigation_handle->GetNavigationId())) {
+    CHECK_EQ(ready_to_commit_hosts_[navigation_handle->GetNavigationId()],
+             navigation_handle->GetRenderFrameHost());
+    ready_to_commit_hosts_.erase(navigation_handle->GetNavigationId());
+  }
+
   ongoing_navigations_.erase(navigation_handle);
 }
 
@@ -313,6 +327,7 @@
 
 WebContentsObserverSanityChecker::~WebContentsObserverSanityChecker() {
   CHECK(web_contents_destroyed_);
+  CHECK(ready_to_commit_hosts_.empty());
 }
 
 void WebContentsObserverSanityChecker::AssertRenderFrameExists(
diff --git a/content/test/web_contents_observer_sanity_checker.h b/content/test/web_contents_observer_sanity_checker.h
index d7da234..e9794e0d3 100644
--- a/content/test/web_contents_observer_sanity_checker.h
+++ b/content/test/web_contents_observer_sanity_checker.h
@@ -89,6 +89,7 @@
   void EnsureStableParentValue(RenderFrameHost* render_frame_host);
   bool HasAnyChildren(RenderFrameHost* render_frame_host);
 
+  std::map<int64_t, RenderFrameHost*> ready_to_commit_hosts_;
   std::set<GlobalRoutingID> current_hosts_;
   std::set<GlobalRoutingID> live_routes_;
   std::set<GlobalRoutingID> deleted_routes_;
diff --git a/content/utility/BUILD.gn b/content/utility/BUILD.gn
index 818c6cd..e162cbf5 100644
--- a/content/utility/BUILD.gn
+++ b/content/utility/BUILD.gn
@@ -36,7 +36,7 @@
     "//content/child",
     "//content/public/child:child_sources",
     "//content/public/common:common_sources",
-    "//media:media_features",
+    "//media:media_buildflags",
     "//mojo/common",
     "//mojo/public/cpp/bindings",
     "//net:net_with_v8",
@@ -62,7 +62,7 @@
   if (enable_library_cdms) {
     deps += [
       "//media",
-      "//media/mojo:features",
+      "//media/mojo:buildflags",
       "//media/mojo/interfaces:constants",
       "//media/mojo/services",
     ]
diff --git a/content/utility/utility_service_factory.cc b/content/utility/utility_service_factory.cc
index 3641e79c..290428e 100644
--- a/content/utility/utility_service_factory.cc
+++ b/content/utility/utility_service_factory.cc
@@ -18,7 +18,7 @@
 #include "content/public/utility/content_utility_client.h"
 #include "content/public/utility/utility_thread.h"
 #include "content/utility/utility_thread_impl.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "services/data_decoder/data_decoder_service.h"
 #include "services/data_decoder/public/mojom/constants.mojom.h"
 #include "services/network/network_service.h"
diff --git a/content/zygote/zygote_main_linux.cc b/content/zygote/zygote_main_linux.cc
index 4e424bd..7485478d 100644
--- a/content/zygote/zygote_main_linux.cc
+++ b/content/zygote/zygote_main_linux.cc
@@ -38,7 +38,7 @@
 #include "content/public/common/content_switches.h"
 #include "content/public/common/zygote_fork_delegate_linux.h"
 #include "content/zygote/zygote_linux.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "ppapi/features/features.h"
 #include "sandbox/linux/services/credentials.h"
 #include "sandbox/linux/services/init_process_reaper.h"
diff --git a/device/BUILD.gn b/device/BUILD.gn
index 159adca..6ad94e4 100644
--- a/device/BUILD.gn
+++ b/device/BUILD.gn
@@ -72,6 +72,7 @@
     "fido/fido_ble_frames_unittest.cc",
     "fido/fido_discovery_unittest.cc",
     "fido/fido_hid_message_unittest.cc",
+    "fido/make_credential_task_unittest.cc",
     "fido/test_callback_receiver_unittest.cc",
     "fido/u2f_parsing_utils_unittest.cc",
     "fido/u2f_register_unittest.cc",
diff --git a/device/base/features.cc b/device/base/features.cc
index 822c0da..0cb9b24 100644
--- a/device/base/features.cc
+++ b/device/base/features.cc
@@ -13,4 +13,10 @@
                                    base::FEATURE_DISABLED_BY_DEFAULT};
 #endif  // defined(OS_WIN)
 
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
+// Enables or disables the use of newblue Bluetooth daemon on Chrome OS.
+const base::Feature kNewblueDaemon{"Newblue",
+                                   base::FEATURE_DISABLED_BY_DEFAULT};
+#endif  // defined(OS_LINUX) || defined(OS_CHROMEOS)
+
 }  // namespace device
diff --git a/device/base/features.h b/device/base/features.h
index efb9979..062f03f 100644
--- a/device/base/features.h
+++ b/device/base/features.h
@@ -15,6 +15,10 @@
 DEVICE_BASE_EXPORT extern const base::Feature kNewUsbBackend;
 #endif  // defined(OS_WIN)
 
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
+DEVICE_BASE_EXPORT extern const base::Feature kNewblueDaemon;
+#endif  // defined(OS_LINUX) || defined(OS_CHROMEOS)
+
 }  // namespace device
 
 #endif  // DEVICE_BASE_FEATURES_H_
diff --git a/device/bluetooth/BUILD.gn b/device/bluetooth/BUILD.gn
index 071d0ad..3d888d36 100644
--- a/device/bluetooth/BUILD.gn
+++ b/device/bluetooth/BUILD.gn
@@ -209,6 +209,7 @@
     "//base",
     "//components/device_event_log",
     "//crypto",
+    "//device/base",
     "//device/bluetooth/strings",
     "//device/bluetooth/uribeacon",
     "//ipc",
diff --git a/device/bluetooth/dbus/bluetooth_adapter_client.cc b/device/bluetooth/dbus/bluetooth_adapter_client.cc
index 69e8739..a707cc7 100644
--- a/device/bluetooth/dbus/bluetooth_adapter_client.cc
+++ b/device/bluetooth/dbus/bluetooth_adapter_client.cc
@@ -412,9 +412,10 @@
   }
 
  protected:
-  void Init(dbus::Bus* bus) override {
+  void Init(dbus::Bus* bus,
+            const std::string& bluetooth_service_name) override {
     object_manager_ = bus->GetObjectManager(
-        bluetooth_object_manager::kBluetoothObjectManagerServiceName,
+        bluetooth_service_name,
         dbus::ObjectPath(
             bluetooth_object_manager::kBluetoothObjectManagerServicePath));
     object_manager_->RegisterInterface(
diff --git a/device/bluetooth/dbus/bluetooth_agent_manager_client.cc b/device/bluetooth/dbus/bluetooth_agent_manager_client.cc
index 35fe7fa8..dde927be 100644
--- a/device/bluetooth/dbus/bluetooth_agent_manager_client.cc
+++ b/device/bluetooth/dbus/bluetooth_agent_manager_client.cc
@@ -84,10 +84,11 @@
   }
 
  protected:
-  void Init(dbus::Bus* bus) override {
+  void Init(dbus::Bus* bus,
+            const std::string& bluetooth_service_name) override {
     DCHECK(bus);
     object_proxy_ = bus->GetObjectProxy(
-        bluetooth_agent_manager::kBluetoothAgentManagerServiceName,
+        bluetooth_service_name,
         dbus::ObjectPath(
             bluetooth_agent_manager::kBluetoothAgentManagerServicePath));
   }
diff --git a/device/bluetooth/dbus/bluetooth_device_client.cc b/device/bluetooth/dbus/bluetooth_device_client.cc
index a6f6237..df13ba3 100644
--- a/device/bluetooth/dbus/bluetooth_device_client.cc
+++ b/device/bluetooth/dbus/bluetooth_device_client.cc
@@ -503,9 +503,10 @@
   }
 
  protected:
-  void Init(dbus::Bus* bus) override {
+  void Init(dbus::Bus* bus,
+            const std::string& bluetooth_service_name) override {
     object_manager_ = bus->GetObjectManager(
-        bluetooth_object_manager::kBluetoothObjectManagerServiceName,
+        bluetooth_service_name,
         dbus::ObjectPath(
             bluetooth_object_manager::kBluetoothObjectManagerServicePath));
     object_manager_->RegisterInterface(
diff --git a/device/bluetooth/dbus/bluetooth_gatt_characteristic_client.cc b/device/bluetooth/dbus/bluetooth_gatt_characteristic_client.cc
index 2d02d2d..0633898a 100644
--- a/device/bluetooth/dbus/bluetooth_gatt_characteristic_client.cc
+++ b/device/bluetooth/dbus/bluetooth_gatt_characteristic_client.cc
@@ -216,9 +216,10 @@
 
  protected:
   // bluez::DBusClient override.
-  void Init(dbus::Bus* bus) override {
+  void Init(dbus::Bus* bus,
+            const std::string& bluetooth_service_name) override {
     object_manager_ = bus->GetObjectManager(
-        bluetooth_object_manager::kBluetoothObjectManagerServiceName,
+        bluetooth_service_name,
         dbus::ObjectPath(
             bluetooth_object_manager::kBluetoothObjectManagerServicePath));
     object_manager_->RegisterInterface(
diff --git a/device/bluetooth/dbus/bluetooth_gatt_descriptor_client.cc b/device/bluetooth/dbus/bluetooth_gatt_descriptor_client.cc
index 68d0b17..685f453 100644
--- a/device/bluetooth/dbus/bluetooth_gatt_descriptor_client.cc
+++ b/device/bluetooth/dbus/bluetooth_gatt_descriptor_client.cc
@@ -174,9 +174,10 @@
 
  protected:
   // bluez::DBusClient override.
-  void Init(dbus::Bus* bus) override {
+  void Init(dbus::Bus* bus,
+            const std::string& bluetooth_service_name) override {
     object_manager_ = bus->GetObjectManager(
-        bluetooth_object_manager::kBluetoothObjectManagerServiceName,
+        bluetooth_service_name,
         dbus::ObjectPath(
             bluetooth_object_manager::kBluetoothObjectManagerServicePath));
     object_manager_->RegisterInterface(
diff --git a/device/bluetooth/dbus/bluetooth_gatt_manager_client.cc b/device/bluetooth/dbus/bluetooth_gatt_manager_client.cc
index 9a48bba..8f22ec7a 100644
--- a/device/bluetooth/dbus/bluetooth_gatt_manager_client.cc
+++ b/device/bluetooth/dbus/bluetooth_gatt_manager_client.cc
@@ -85,11 +85,12 @@
 
  protected:
   // bluez::DBusClient override.
-  void Init(dbus::Bus* bus) override {
+  void Init(dbus::Bus* bus,
+            const std::string& bluetooth_service_name) override {
     DCHECK(bus);
     DCHECK(bus);
     object_manager_ = bus->GetObjectManager(
-        bluetooth_object_manager::kBluetoothObjectManagerServiceName,
+        bluetooth_service_name,
         dbus::ObjectPath(
             bluetooth_object_manager::kBluetoothObjectManagerServicePath));
   }
diff --git a/device/bluetooth/dbus/bluetooth_gatt_service_client.cc b/device/bluetooth/dbus/bluetooth_gatt_service_client.cc
index 2eebc85..f4178a4 100644
--- a/device/bluetooth/dbus/bluetooth_gatt_service_client.cc
+++ b/device/bluetooth/dbus/bluetooth_gatt_service_client.cc
@@ -95,9 +95,10 @@
 
  protected:
   // bluez::DBusClient override.
-  void Init(dbus::Bus* bus) override {
+  void Init(dbus::Bus* bus,
+            const std::string& bluetooth_service_name) override {
     object_manager_ = bus->GetObjectManager(
-        bluetooth_object_manager::kBluetoothObjectManagerServiceName,
+        bluetooth_service_name,
         dbus::ObjectPath(
             bluetooth_object_manager::kBluetoothObjectManagerServicePath));
     object_manager_->RegisterInterface(
diff --git a/device/bluetooth/dbus/bluetooth_input_client.cc b/device/bluetooth/dbus/bluetooth_input_client.cc
index ed83dc1..b909b0c 100644
--- a/device/bluetooth/dbus/bluetooth_input_client.cc
+++ b/device/bluetooth/dbus/bluetooth_input_client.cc
@@ -69,9 +69,10 @@
   }
 
  protected:
-  void Init(dbus::Bus* bus) override {
+  void Init(dbus::Bus* bus,
+            const std::string& bluetooth_service_name) override {
     object_manager_ = bus->GetObjectManager(
-        bluetooth_object_manager::kBluetoothObjectManagerServiceName,
+        bluetooth_service_name,
         dbus::ObjectPath(
             bluetooth_object_manager::kBluetoothObjectManagerServicePath));
     object_manager_->RegisterInterface(
diff --git a/device/bluetooth/dbus/bluetooth_le_advertising_manager_client.cc b/device/bluetooth/dbus/bluetooth_le_advertising_manager_client.cc
index c513fba7..58e90429 100644
--- a/device/bluetooth/dbus/bluetooth_le_advertising_manager_client.cc
+++ b/device/bluetooth/dbus/bluetooth_le_advertising_manager_client.cc
@@ -124,10 +124,11 @@
   }
 
  protected:
-  void Init(dbus::Bus* bus) override {
+  void Init(dbus::Bus* bus,
+            const std::string& bluetooth_service_name) override {
     DCHECK(bus);
     object_manager_ = bus->GetObjectManager(
-        bluetooth_object_manager::kBluetoothObjectManagerServiceName,
+        bluetooth_service_name,
         dbus::ObjectPath(
             bluetooth_object_manager::kBluetoothObjectManagerServicePath));
     object_manager_->RegisterInterface(
diff --git a/device/bluetooth/dbus/bluetooth_media_client.cc b/device/bluetooth/dbus/bluetooth_media_client.cc
index d912e01..cfa2004 100644
--- a/device/bluetooth/dbus/bluetooth_media_client.cc
+++ b/device/bluetooth/dbus/bluetooth_media_client.cc
@@ -172,10 +172,11 @@
   }
 
  protected:
-  void Init(dbus::Bus* bus) override {
+  void Init(dbus::Bus* bus,
+            const std::string& bluetooth_service_name) override {
     DCHECK(bus);
     object_manager_ = bus->GetObjectManager(
-        bluetooth_object_manager::kBluetoothObjectManagerServiceName,
+        bluetooth_service_name,
         dbus::ObjectPath(
             bluetooth_object_manager::kBluetoothObjectManagerServicePath));
     object_manager_->RegisterInterface(kBluetoothMediaInterface, this);
diff --git a/device/bluetooth/dbus/bluetooth_media_transport_client.cc b/device/bluetooth/dbus/bluetooth_media_transport_client.cc
index cc00f186..23eadd0 100644
--- a/device/bluetooth/dbus/bluetooth_media_transport_client.cc
+++ b/device/bluetooth/dbus/bluetooth_media_transport_client.cc
@@ -192,10 +192,11 @@
   }
 
  protected:
-  void Init(dbus::Bus* bus) override {
+  void Init(dbus::Bus* bus,
+            const std::string& bluetooth_service_name) override {
     DCHECK(bus);
     object_manager_ = bus->GetObjectManager(
-        bluetooth_object_manager::kBluetoothObjectManagerServiceName,
+        bluetooth_service_name,
         dbus::ObjectPath(
             bluetooth_object_manager::kBluetoothObjectManagerServicePath));
     object_manager_->RegisterInterface(kBluetoothMediaTransportInterface, this);
diff --git a/device/bluetooth/dbus/bluetooth_profile_manager_client.cc b/device/bluetooth/dbus/bluetooth_profile_manager_client.cc
index 29a4b133..5eb4b1e 100644
--- a/device/bluetooth/dbus/bluetooth_profile_manager_client.cc
+++ b/device/bluetooth/dbus/bluetooth_profile_manager_client.cc
@@ -181,10 +181,11 @@
   }
 
  protected:
-  void Init(dbus::Bus* bus) override {
+  void Init(dbus::Bus* bus,
+            const std::string& bluetooth_service_name) override {
     DCHECK(bus);
     object_proxy_ = bus->GetObjectProxy(
-        bluetooth_profile_manager::kBluetoothProfileManagerServiceName,
+        bluetooth_service_name,
         dbus::ObjectPath(
             bluetooth_profile_manager::kBluetoothProfileManagerServicePath));
   }
diff --git a/device/bluetooth/dbus/bluez_dbus_client.h b/device/bluetooth/dbus/bluez_dbus_client.h
index 9d45520..685eb5c 100644
--- a/device/bluetooth/dbus/bluez_dbus_client.h
+++ b/device/bluetooth/dbus/bluez_dbus_client.h
@@ -24,7 +24,8 @@
   // This function is called by DBusThreadManager. Only in unit tests, which
   // don't use DBusThreadManager, this function can be called through Stub
   // implementations (they change Init's member visibility to public).
-  virtual void Init(dbus::Bus* bus) = 0;
+  virtual void Init(dbus::Bus* bus,
+                    const std::string& bluetooth_service_name) = 0;
 
  private:
   friend class BluezDBusManager;
diff --git a/device/bluetooth/dbus/bluez_dbus_manager.cc b/device/bluetooth/dbus/bluez_dbus_manager.cc
index fe22ed9c..4619ef84 100644
--- a/device/bluetooth/dbus/bluez_dbus_manager.cc
+++ b/device/bluetooth/dbus/bluez_dbus_manager.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/command_line.h"
+#include "base/feature_list.h"
 #include "base/memory/ptr_util.h"
 #include "base/sys_info.h"
 #include "base/threading/thread.h"
@@ -16,6 +17,7 @@
 #include "dbus/message.h"
 #include "dbus/object_manager.h"
 #include "dbus/object_proxy.h"
+#include "device/base/features.h"
 #include "device/bluetooth/dbus/bluetooth_adapter_client.h"
 #include "device/bluetooth/dbus/bluetooth_agent_manager_client.h"
 #include "device/bluetooth/dbus/bluetooth_device_client.h"
@@ -182,19 +184,34 @@
 }
 
 void BluezDBusManager::InitializeClients() {
-  client_bundle_->bluetooth_adapter_client()->Init(GetSystemBus());
-  client_bundle_->bluetooth_agent_manager_client()->Init(GetSystemBus());
-  client_bundle_->bluetooth_device_client()->Init(GetSystemBus());
-  client_bundle_->bluetooth_gatt_characteristic_client()->Init(GetSystemBus());
-  client_bundle_->bluetooth_gatt_descriptor_client()->Init(GetSystemBus());
-  client_bundle_->bluetooth_gatt_manager_client()->Init(GetSystemBus());
-  client_bundle_->bluetooth_gatt_service_client()->Init(GetSystemBus());
-  client_bundle_->bluetooth_input_client()->Init(GetSystemBus());
+  std::string bluetooth_service_name =
+      base::FeatureList::IsEnabled(device::kNewblueDaemon)
+          ? bluetooth_object_manager::kBluetoothObjectManagerServiceName
+          : bluez_object_manager::kBluezObjectManagerServiceName;
+  client_bundle_->bluetooth_adapter_client()->Init(GetSystemBus(),
+                                                   bluetooth_service_name);
+  client_bundle_->bluetooth_agent_manager_client()->Init(
+      GetSystemBus(), bluetooth_service_name);
+  client_bundle_->bluetooth_device_client()->Init(GetSystemBus(),
+                                                  bluetooth_service_name);
+  client_bundle_->bluetooth_gatt_characteristic_client()->Init(
+      GetSystemBus(), bluetooth_service_name);
+  client_bundle_->bluetooth_gatt_descriptor_client()->Init(
+      GetSystemBus(), bluetooth_service_name);
+  client_bundle_->bluetooth_gatt_manager_client()->Init(GetSystemBus(),
+                                                        bluetooth_service_name);
+  client_bundle_->bluetooth_gatt_service_client()->Init(GetSystemBus(),
+                                                        bluetooth_service_name);
+  client_bundle_->bluetooth_input_client()->Init(GetSystemBus(),
+                                                 bluetooth_service_name);
   client_bundle_->bluetooth_le_advertising_manager_client()->Init(
-      GetSystemBus());
-  client_bundle_->bluetooth_media_client()->Init(GetSystemBus());
-  client_bundle_->bluetooth_media_transport_client()->Init(GetSystemBus());
-  client_bundle_->bluetooth_profile_manager_client()->Init(GetSystemBus());
+      GetSystemBus(), bluetooth_service_name);
+  client_bundle_->bluetooth_media_client()->Init(GetSystemBus(),
+                                                 bluetooth_service_name);
+  client_bundle_->bluetooth_media_transport_client()->Init(
+      GetSystemBus(), bluetooth_service_name);
+  client_bundle_->bluetooth_profile_manager_client()->Init(
+      GetSystemBus(), bluetooth_service_name);
 }
 
 // static
diff --git a/device/bluetooth/dbus/fake_bluetooth_adapter_client.cc b/device/bluetooth/dbus/fake_bluetooth_adapter_client.cc
index 6c9edd83..2f24e8c 100644
--- a/device/bluetooth/dbus/fake_bluetooth_adapter_client.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_adapter_client.cc
@@ -99,7 +99,9 @@
 
 FakeBluetoothAdapterClient::~FakeBluetoothAdapterClient() = default;
 
-void FakeBluetoothAdapterClient::Init(dbus::Bus* bus) {}
+void FakeBluetoothAdapterClient::Init(
+    dbus::Bus* bus,
+    const std::string& bluetooth_service_name) {}
 
 void FakeBluetoothAdapterClient::AddObserver(Observer* observer) {
   observers_.AddObserver(observer);
diff --git a/device/bluetooth/dbus/fake_bluetooth_adapter_client.h b/device/bluetooth/dbus/fake_bluetooth_adapter_client.h
index a38fc0c..f43bddd4 100644
--- a/device/bluetooth/dbus/fake_bluetooth_adapter_client.h
+++ b/device/bluetooth/dbus/fake_bluetooth_adapter_client.h
@@ -41,7 +41,7 @@
   ~FakeBluetoothAdapterClient() override;
 
   // BluetoothAdapterClient overrides
-  void Init(dbus::Bus* bus) override;
+  void Init(dbus::Bus* bus, const std::string& bluetooth_service_name) override;
   void AddObserver(Observer* observer) override;
   void RemoveObserver(Observer* observer) override;
   std::vector<dbus::ObjectPath> GetAdapters() override;
diff --git a/device/bluetooth/dbus/fake_bluetooth_agent_manager_client.cc b/device/bluetooth/dbus/fake_bluetooth_agent_manager_client.cc
index cd5787e..eb1392f 100644
--- a/device/bluetooth/dbus/fake_bluetooth_agent_manager_client.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_agent_manager_client.cc
@@ -15,7 +15,9 @@
 
 FakeBluetoothAgentManagerClient::~FakeBluetoothAgentManagerClient() = default;
 
-void FakeBluetoothAgentManagerClient::Init(dbus::Bus* bus) {}
+void FakeBluetoothAgentManagerClient::Init(
+    dbus::Bus* bus,
+    const std::string& bluetooth_service_name) {}
 
 void FakeBluetoothAgentManagerClient::RegisterAgent(
     const dbus::ObjectPath& agent_path,
diff --git a/device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h b/device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h
index d5c83cf..ccd2c9b 100644
--- a/device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h
+++ b/device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h
@@ -27,7 +27,7 @@
   ~FakeBluetoothAgentManagerClient() override;
 
   // BluetoothAgentManagerClient overrides
-  void Init(dbus::Bus* bus) override;
+  void Init(dbus::Bus* bus, const std::string& bluetooth_service_name) override;
   void RegisterAgent(const dbus::ObjectPath& agent_path,
                      const std::string& capability,
                      const base::Closure& callback,
diff --git a/device/bluetooth/dbus/fake_bluetooth_device_client.cc b/device/bluetooth/dbus/fake_bluetooth_device_client.cc
index 5cdc4d0..ebe5e78 100644
--- a/device/bluetooth/dbus/fake_bluetooth_device_client.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_device_client.cc
@@ -366,7 +366,9 @@
 
 FakeBluetoothDeviceClient::~FakeBluetoothDeviceClient() = default;
 
-void FakeBluetoothDeviceClient::Init(dbus::Bus* bus) {}
+void FakeBluetoothDeviceClient::Init(
+    dbus::Bus* bus,
+    const std::string& bluetooth_service_name) {}
 
 void FakeBluetoothDeviceClient::AddObserver(Observer* observer) {
   observers_.AddObserver(observer);
diff --git a/device/bluetooth/dbus/fake_bluetooth_device_client.h b/device/bluetooth/dbus/fake_bluetooth_device_client.h
index c29b93a..cef8554 100644
--- a/device/bluetooth/dbus/fake_bluetooth_device_client.h
+++ b/device/bluetooth/dbus/fake_bluetooth_device_client.h
@@ -73,7 +73,7 @@
   ~FakeBluetoothDeviceClient() override;
 
   // BluetoothDeviceClient overrides
-  void Init(dbus::Bus* bus) override;
+  void Init(dbus::Bus* bus, const std::string& bluetooth_service_name) override;
   void AddObserver(Observer* observer) override;
   void RemoveObserver(Observer* observer) override;
   std::vector<dbus::ObjectPath> GetDevicesForAdapter(
diff --git a/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.cc b/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.cc
index aac4614..8973c60 100644
--- a/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.cc
@@ -91,7 +91,9 @@
   action_extra_requests_.clear();
 }
 
-void FakeBluetoothGattCharacteristicClient::Init(dbus::Bus* bus) {}
+void FakeBluetoothGattCharacteristicClient::Init(
+    dbus::Bus* bus,
+    const std::string& bluetooth_service_name) {}
 
 void FakeBluetoothGattCharacteristicClient::AddObserver(Observer* observer) {
   observers_.AddObserver(observer);
diff --git a/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.h b/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.h
index 6fcc8b1..564e701 100644
--- a/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.h
+++ b/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.h
@@ -44,7 +44,7 @@
   ~FakeBluetoothGattCharacteristicClient() override;
 
   // DBusClient override.
-  void Init(dbus::Bus* bus) override;
+  void Init(dbus::Bus* bus, const std::string& bluetooth_service_name) override;
 
   // BluetoothGattCharacteristicClient overrides.
   void AddObserver(Observer* observer) override;
diff --git a/device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.cc b/device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.cc
index 4e1f77e2..1d4783a 100644
--- a/device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.cc
@@ -64,7 +64,9 @@
     delete iter->second;
 }
 
-void FakeBluetoothGattDescriptorClient::Init(dbus::Bus* bus) {}
+void FakeBluetoothGattDescriptorClient::Init(
+    dbus::Bus* bus,
+    const std::string& bluetooth_service_name) {}
 
 void FakeBluetoothGattDescriptorClient::AddObserver(Observer* observer) {
   observers_.AddObserver(observer);
diff --git a/device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.h b/device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.h
index 370a6cb..d67fec62 100644
--- a/device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.h
+++ b/device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.h
@@ -42,7 +42,7 @@
   ~FakeBluetoothGattDescriptorClient() override;
 
   // DBusClient override.
-  void Init(dbus::Bus* bus) override;
+  void Init(dbus::Bus* bus, const std::string& bluetooth_service_name) override;
 
   // BluetoothGattDescriptorClient overrides.
   void AddObserver(Observer* observer) override;
diff --git a/device/bluetooth/dbus/fake_bluetooth_gatt_manager_client.cc b/device/bluetooth/dbus/fake_bluetooth_gatt_manager_client.cc
index 9022ef4..b2fdd2c 100644
--- a/device/bluetooth/dbus/fake_bluetooth_gatt_manager_client.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_gatt_manager_client.cc
@@ -93,7 +93,9 @@
 FakeBluetoothGattManagerClient::~FakeBluetoothGattManagerClient() = default;
 
 // DBusClient override.
-void FakeBluetoothGattManagerClient::Init(dbus::Bus* bus) {}
+void FakeBluetoothGattManagerClient::Init(
+    dbus::Bus* bus,
+    const std::string& bluetooth_service_name) {}
 
 // BluetoothGattManagerClient overrides.
 void FakeBluetoothGattManagerClient::RegisterApplication(
diff --git a/device/bluetooth/dbus/fake_bluetooth_gatt_manager_client.h b/device/bluetooth/dbus/fake_bluetooth_gatt_manager_client.h
index df808dc..bf27589 100644
--- a/device/bluetooth/dbus/fake_bluetooth_gatt_manager_client.h
+++ b/device/bluetooth/dbus/fake_bluetooth_gatt_manager_client.h
@@ -37,7 +37,7 @@
   ~FakeBluetoothGattManagerClient() override;
 
   // DBusClient override.
-  void Init(dbus::Bus* bus) override;
+  void Init(dbus::Bus* bus, const std::string& bluetooth_service_name) override;
 
   // BluetoothGattManagerClient overrides.
   void RegisterApplication(const dbus::ObjectPath& adapter_object_path,
diff --git a/device/bluetooth/dbus/fake_bluetooth_gatt_service_client.cc b/device/bluetooth/dbus/fake_bluetooth_gatt_service_client.cc
index ff77f0e..37a84ac 100644
--- a/device/bluetooth/dbus/fake_bluetooth_gatt_service_client.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_gatt_service_client.cc
@@ -60,7 +60,9 @@
 
 FakeBluetoothGattServiceClient::~FakeBluetoothGattServiceClient() = default;
 
-void FakeBluetoothGattServiceClient::Init(dbus::Bus* bus) {}
+void FakeBluetoothGattServiceClient::Init(
+    dbus::Bus* bus,
+    const std::string& bluetooth_service_name) {}
 
 void FakeBluetoothGattServiceClient::AddObserver(Observer* observer) {
   observers_.AddObserver(observer);
diff --git a/device/bluetooth/dbus/fake_bluetooth_gatt_service_client.h b/device/bluetooth/dbus/fake_bluetooth_gatt_service_client.h
index 7ecf8057..0969fe7 100644
--- a/device/bluetooth/dbus/fake_bluetooth_gatt_service_client.h
+++ b/device/bluetooth/dbus/fake_bluetooth_gatt_service_client.h
@@ -41,7 +41,7 @@
   ~FakeBluetoothGattServiceClient() override;
 
   // DBusClient override.
-  void Init(dbus::Bus* bus) override;
+  void Init(dbus::Bus* bus, const std::string& bluetooth_service_name) override;
 
   // BluetoothGattServiceClient overrides.
   void AddObserver(Observer* observer) override;
diff --git a/device/bluetooth/dbus/fake_bluetooth_input_client.cc b/device/bluetooth/dbus/fake_bluetooth_input_client.cc
index 2431fda..5c2a1aa 100644
--- a/device/bluetooth/dbus/fake_bluetooth_input_client.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_input_client.cc
@@ -48,7 +48,9 @@
 
 FakeBluetoothInputClient::~FakeBluetoothInputClient() = default;
 
-void FakeBluetoothInputClient::Init(dbus::Bus* bus) {}
+void FakeBluetoothInputClient::Init(dbus::Bus* bus,
+                                    const std::string& bluetooth_service_name) {
+}
 
 void FakeBluetoothInputClient::AddObserver(Observer* observer) {
   observers_.AddObserver(observer);
diff --git a/device/bluetooth/dbus/fake_bluetooth_input_client.h b/device/bluetooth/dbus/fake_bluetooth_input_client.h
index 3860749a..a513db0 100644
--- a/device/bluetooth/dbus/fake_bluetooth_input_client.h
+++ b/device/bluetooth/dbus/fake_bluetooth_input_client.h
@@ -39,7 +39,7 @@
   ~FakeBluetoothInputClient() override;
 
   // BluetoothInputClient overrides
-  void Init(dbus::Bus* bus) override;
+  void Init(dbus::Bus* bus, const std::string& bluetooth_service_name) override;
   void AddObserver(Observer* observer) override;
   void RemoveObserver(Observer* observer) override;
   Properties* GetProperties(const dbus::ObjectPath& object_path) override;
diff --git a/device/bluetooth/dbus/fake_bluetooth_le_advertising_manager_client.cc b/device/bluetooth/dbus/fake_bluetooth_le_advertising_manager_client.cc
index da51eade..24623377 100644
--- a/device/bluetooth/dbus/fake_bluetooth_le_advertising_manager_client.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_le_advertising_manager_client.cc
@@ -31,7 +31,9 @@
 FakeBluetoothLEAdvertisingManagerClient::
     ~FakeBluetoothLEAdvertisingManagerClient() = default;
 
-void FakeBluetoothLEAdvertisingManagerClient::Init(dbus::Bus* bus) {}
+void FakeBluetoothLEAdvertisingManagerClient::Init(
+    dbus::Bus* bus,
+    const std::string& bluetooth_service_name) {}
 
 void FakeBluetoothLEAdvertisingManagerClient::AddObserver(Observer* observer) {}
 
diff --git a/device/bluetooth/dbus/fake_bluetooth_le_advertising_manager_client.h b/device/bluetooth/dbus/fake_bluetooth_le_advertising_manager_client.h
index eeb1f0f7..50f502eb 100644
--- a/device/bluetooth/dbus/fake_bluetooth_le_advertising_manager_client.h
+++ b/device/bluetooth/dbus/fake_bluetooth_le_advertising_manager_client.h
@@ -32,7 +32,7 @@
   ~FakeBluetoothLEAdvertisingManagerClient() override;
 
   // DBusClient overrides:
-  void Init(dbus::Bus* bus) override;
+  void Init(dbus::Bus* bus, const std::string& bluetooth_service_name) override;
 
   // BluetoothAdvertisingManagerClient overrides:
   void AddObserver(Observer* observer) override;
diff --git a/device/bluetooth/dbus/fake_bluetooth_media_client.cc b/device/bluetooth/dbus/fake_bluetooth_media_client.cc
index e856ab2..d33f380 100644
--- a/device/bluetooth/dbus/fake_bluetooth_media_client.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_media_client.cc
@@ -34,7 +34,9 @@
 
 FakeBluetoothMediaClient::~FakeBluetoothMediaClient() = default;
 
-void FakeBluetoothMediaClient::Init(dbus::Bus* bus) {}
+void FakeBluetoothMediaClient::Init(dbus::Bus* bus,
+                                    const std::string& bluetooth_service_name) {
+}
 
 void FakeBluetoothMediaClient::AddObserver(
     BluetoothMediaClient::Observer* observer) {
diff --git a/device/bluetooth/dbus/fake_bluetooth_media_client.h b/device/bluetooth/dbus/fake_bluetooth_media_client.h
index c085f6e..346a2f2 100644
--- a/device/bluetooth/dbus/fake_bluetooth_media_client.h
+++ b/device/bluetooth/dbus/fake_bluetooth_media_client.h
@@ -30,7 +30,7 @@
   ~FakeBluetoothMediaClient() override;
 
   // DBusClient override.
-  void Init(dbus::Bus* bus) override;
+  void Init(dbus::Bus* bus, const std::string& bluetooth_service_name) override;
 
   // BluetoothMediaClient overrides.
   void AddObserver(BluetoothMediaClient::Observer* observer) override;
diff --git a/device/bluetooth/dbus/fake_bluetooth_media_transport_client.cc b/device/bluetooth/dbus/fake_bluetooth_media_transport_client.cc
index e086243..6fd6336ff 100644
--- a/device/bluetooth/dbus/fake_bluetooth_media_transport_client.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_media_transport_client.cc
@@ -104,7 +104,9 @@
     default;
 
 // DBusClient override.
-void FakeBluetoothMediaTransportClient::Init(dbus::Bus* bus) {}
+void FakeBluetoothMediaTransportClient::Init(
+    dbus::Bus* bus,
+    const std::string& bluetooth_service_name) {}
 
 void FakeBluetoothMediaTransportClient::AddObserver(
     BluetoothMediaTransportClient::Observer* observer) {
diff --git a/device/bluetooth/dbus/fake_bluetooth_media_transport_client.h b/device/bluetooth/dbus/fake_bluetooth_media_transport_client.h
index 4415dda..1b62f7a 100644
--- a/device/bluetooth/dbus/fake_bluetooth_media_transport_client.h
+++ b/device/bluetooth/dbus/fake_bluetooth_media_transport_client.h
@@ -57,7 +57,7 @@
   ~FakeBluetoothMediaTransportClient() override;
 
   // DBusClient override.
-  void Init(dbus::Bus* bus) override;
+  void Init(dbus::Bus* bus, const std::string& bluetooth_service_name) override;
 
   // BluetoothMediaTransportClient override.
   void AddObserver(Observer* observer) override;
diff --git a/device/bluetooth/dbus/fake_bluetooth_profile_manager_client.cc b/device/bluetooth/dbus/fake_bluetooth_profile_manager_client.cc
index 10e8db9..771a8ec1 100644
--- a/device/bluetooth/dbus/fake_bluetooth_profile_manager_client.cc
+++ b/device/bluetooth/dbus/fake_bluetooth_profile_manager_client.cc
@@ -29,7 +29,9 @@
 FakeBluetoothProfileManagerClient::~FakeBluetoothProfileManagerClient() =
     default;
 
-void FakeBluetoothProfileManagerClient::Init(dbus::Bus* bus) {}
+void FakeBluetoothProfileManagerClient::Init(
+    dbus::Bus* bus,
+    const std::string& bluetooth_service_name) {}
 
 void FakeBluetoothProfileManagerClient::RegisterProfile(
     const dbus::ObjectPath& profile_path,
diff --git a/device/bluetooth/dbus/fake_bluetooth_profile_manager_client.h b/device/bluetooth/dbus/fake_bluetooth_profile_manager_client.h
index 8ed7826d..4f0978b 100644
--- a/device/bluetooth/dbus/fake_bluetooth_profile_manager_client.h
+++ b/device/bluetooth/dbus/fake_bluetooth_profile_manager_client.h
@@ -30,7 +30,7 @@
   ~FakeBluetoothProfileManagerClient() override;
 
   // BluetoothProfileManagerClient overrides
-  void Init(dbus::Bus* bus) override;
+  void Init(dbus::Bus* bus, const std::string& bluetooth_service_name) override;
   void RegisterProfile(const dbus::ObjectPath& profile_path,
                        const std::string& uuid,
                        const Options& options,
diff --git a/device/bluetooth/public/mojom/test/fake_bluetooth.mojom b/device/bluetooth/public/mojom/test/fake_bluetooth.mojom
index c0cbddf..6596473 100644
--- a/device/bluetooth/public/mojom/test/fake_bluetooth.mojom
+++ b/device/bluetooth/public/mojom/test/fake_bluetooth.mojom
@@ -235,6 +235,15 @@
                     string service_id,
                     string peripheral_address) => (string? descriptor_id);
 
+  // Removes a fake GATT Descriptor with |descriptor_id| from the fake
+  // characteristic with |characteristic_id| in |service_id| fake service in
+  // |peripheral_address| peripheral.
+  RemoveFakeDescriptor(
+        string descriptor_id,
+        string characteristic_id,
+        string service_id,
+        string peripheral_address) => (bool success);
+
   // Sets the next read response for characteristic with |characteristics_id|
   // in |service_id| and in |peripheral_address| to |code| and |value|.
   // |code| could be a GATT Error Response from
@@ -284,7 +293,7 @@
   // If the value can't be retrieved calls its callback with false. Calls its
   // callback with null value if no value has been written to the
   // characteristic.
-  GetLastWrittenValue(
+  GetLastWrittenCharacteristicValue(
       string characteristic_id,
       string service_id,
       string peripheral_address) => (bool success, array<uint8>? value);
@@ -305,4 +314,30 @@
       string characteristic_id,
       string service_id,
       string peripheral_address) => (bool success);
+
+  // Sets the next write response for descriptor with |descriptor_id| in
+  // |characteristic_id| in |service_id| and in |peripheral_address| to |code|.
+  // |code| could be a GATT Error Response from BT 4.2 Vol 3 Part F 3.4.1.1
+  // Error Response or a number outside that range returned by specific
+  // platforms e.g. Android returns 0x101 to signal a GATT failure.
+  // https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#GATT_FAILURE
+  // Calls callback with false if there was any error when simulating the next
+  // response.
+  SetNextWriteDescriptorResponse(
+      uint16 gatt_code,
+      string descriptor_id,
+      string characteristic_id,
+      string service_id,
+      string peripheral_address) => (bool success);
+
+  // Gets the last successfully written value to the descriptor with
+  // |descriptor_id| in |characteristic_id| in |service_id| and in
+  // |peripheral_address|. If the value can't be retrieved, calls its callback
+  // with false. Calls its callback with null value if no value has been
+  // written to the descriptor.
+  GetLastWrittenDescriptorValue(
+      string descriptor_id,
+      string characteristic_id,
+      string service_id,
+      string peripheral_address) => (bool success, array<uint8>? value);
 };
diff --git a/device/bluetooth/test/fake_central.cc b/device/bluetooth/test/fake_central.cc
index 95f918a..1b5fdc0 100644
--- a/device/bluetooth/test/fake_central.cc
+++ b/device/bluetooth/test/fake_central.cc
@@ -247,6 +247,23 @@
       fake_remote_gatt_characteristic->AddFakeDescriptor(descriptor_uuid));
 }
 
+void FakeCentral::RemoveFakeDescriptor(const std::string& descriptor_id,
+                                       const std::string& characteristic_id,
+                                       const std::string& service_id,
+                                       const std::string& peripheral_address,
+                                       RemoveFakeDescriptorCallback callback) {
+  FakeRemoteGattCharacteristic* fake_remote_gatt_characteristic =
+      GetFakeRemoteGattCharacteristic(peripheral_address, service_id,
+                                      characteristic_id);
+  if (!fake_remote_gatt_characteristic) {
+    std::move(callback).Run(false);
+    return;
+  }
+
+  std::move(callback).Run(
+      fake_remote_gatt_characteristic->RemoveFakeDescriptor(descriptor_id));
+}
+
 void FakeCentral::SetNextReadCharacteristicResponse(
     uint16_t gatt_code,
     const base::Optional<std::vector<uint8_t>>& value,
@@ -300,10 +317,11 @@
   std::move(callback).Run(true);
 }
 
-void FakeCentral::GetLastWrittenValue(const std::string& characteristic_id,
-                                      const std::string& service_id,
-                                      const std::string& peripheral_address,
-                                      GetLastWrittenValueCallback callback) {
+void FakeCentral::GetLastWrittenCharacteristicValue(
+    const std::string& characteristic_id,
+    const std::string& service_id,
+    const std::string& peripheral_address,
+    GetLastWrittenCharacteristicValueCallback callback) {
   FakeRemoteGattCharacteristic* fake_remote_gatt_characteristic =
       GetFakeRemoteGattCharacteristic(peripheral_address, service_id,
                                       characteristic_id);
@@ -334,6 +352,41 @@
   std::move(callback).Run(true);
 }
 
+void FakeCentral::SetNextWriteDescriptorResponse(
+    uint16_t gatt_code,
+    const std::string& descriptor_id,
+    const std::string& characteristic_id,
+    const std::string& service_id,
+    const std::string& peripheral_address,
+    SetNextWriteDescriptorResponseCallback callback) {
+  FakeRemoteGattDescriptor* fake_remote_gatt_descriptor =
+      GetFakeRemoteGattDescriptor(peripheral_address, service_id,
+                                  characteristic_id, descriptor_id);
+  if (!fake_remote_gatt_descriptor) {
+    std::move(callback).Run(false);
+  }
+
+  fake_remote_gatt_descriptor->SetNextWriteResponse(gatt_code);
+  std::move(callback).Run(true);
+}
+
+void FakeCentral::GetLastWrittenDescriptorValue(
+    const std::string& descriptor_id,
+    const std::string& characteristic_id,
+    const std::string& service_id,
+    const std::string& peripheral_address,
+    GetLastWrittenDescriptorValueCallback callback) {
+  FakeRemoteGattDescriptor* fake_remote_gatt_descriptor =
+      GetFakeRemoteGattDescriptor(peripheral_address, service_id,
+                                  characteristic_id, descriptor_id);
+  if (!fake_remote_gatt_descriptor) {
+    std::move(callback).Run(false, base::nullopt);
+  }
+
+  std::move(callback).Run(true,
+                          fake_remote_gatt_descriptor->last_written_value());
+}
+
 std::string FakeCentral::GetAddress() const {
   NOTREACHED();
   return std::string();
diff --git a/device/bluetooth/test/fake_central.h b/device/bluetooth/test/fake_central.h
index 0595a75..18a35ea6 100644
--- a/device/bluetooth/test/fake_central.h
+++ b/device/bluetooth/test/fake_central.h
@@ -75,6 +75,11 @@
                          const std::string& service_id,
                          const std::string& peripheral_address,
                          AddFakeDescriptorCallback callback) override;
+  void RemoveFakeDescriptor(const std::string& descriptor_id,
+                            const std::string& characteristic_id,
+                            const std::string& service_id,
+                            const std::string& peripheral_address,
+                            RemoveFakeDescriptorCallback callback) override;
   void SetNextReadCharacteristicResponse(
       uint16_t gatt_code,
       const base::Optional<std::vector<uint8_t>>& value,
@@ -94,10 +99,11 @@
       const std::string& service_id,
       const std::string& peripheral_address,
       SetNextWriteCharacteristicResponseCallback callback) override;
-  void GetLastWrittenValue(const std::string& characteristic_id,
-                           const std::string& service_id,
-                           const std::string& peripheral_address,
-                           GetLastWrittenValueCallback callback) override;
+  void GetLastWrittenCharacteristicValue(
+      const std::string& characteristic_id,
+      const std::string& service_id,
+      const std::string& peripheral_address,
+      GetLastWrittenCharacteristicValueCallback callback) override;
   void SetNextReadDescriptorResponse(
       uint16_t gatt_code,
       const base::Optional<std::vector<uint8_t>>& value,
@@ -106,6 +112,19 @@
       const std::string& service_id,
       const std::string& peripheral_address,
       SetNextReadDescriptorResponseCallback callback) override;
+  void SetNextWriteDescriptorResponse(
+      uint16_t gatt_code,
+      const std::string& descriptor_id,
+      const std::string& characteristic_id,
+      const std::string& service_id,
+      const std::string& peripheral_address,
+      SetNextWriteDescriptorResponseCallback callback) override;
+  void GetLastWrittenDescriptorValue(
+      const std::string& descriptor_id,
+      const std::string& characteristic_id,
+      const std::string& service_id,
+      const std::string& peripheral_address,
+      GetLastWrittenDescriptorValueCallback callback) override;
 
   // BluetoothAdapter overrides:
   std::string GetAddress() const override;
diff --git a/device/bluetooth/test/fake_remote_gatt_characteristic.cc b/device/bluetooth/test/fake_remote_gatt_characteristic.cc
index c8fba1c..8e0a8077 100644
--- a/device/bluetooth/test/fake_remote_gatt_characteristic.cc
+++ b/device/bluetooth/test/fake_remote_gatt_characteristic.cc
@@ -62,6 +62,17 @@
   return it->second->GetIdentifier();
 }
 
+bool FakeRemoteGattCharacteristic::RemoveFakeDescriptor(
+    const std::string& identifier) {
+  auto it = fake_descriptors_.find(identifier);
+  if (it == fake_descriptors_.end()) {
+    return false;
+  }
+
+  fake_descriptors_.erase(it);
+  return true;
+}
+
 void FakeRemoteGattCharacteristic::SetNextReadResponse(
     uint16_t gatt_code,
     const base::Optional<std::vector<uint8_t>>& value) {
diff --git a/device/bluetooth/test/fake_remote_gatt_characteristic.h b/device/bluetooth/test/fake_remote_gatt_characteristic.h
index 53334c1e..48ce0e6d 100644
--- a/device/bluetooth/test/fake_remote_gatt_characteristic.h
+++ b/device/bluetooth/test/fake_remote_gatt_characteristic.h
@@ -41,6 +41,9 @@
   // Returns the descriptor's Id.
   std::string AddFakeDescriptor(const device::BluetoothUUID& descriptor_uuid);
 
+  // Removes a fake descriptor with |identifier| from this characteristic.
+  bool RemoveFakeDescriptor(const std::string& identifier);
+
   // If |gatt_code| is mojom::kGATTSuccess the next read request will call
   // its success callback with |value|. Otherwise it will call its error
   // callback.
diff --git a/device/bluetooth/test/fake_remote_gatt_descriptor.cc b/device/bluetooth/test/fake_remote_gatt_descriptor.cc
index cd185b1..da63dca 100644
--- a/device/bluetooth/test/fake_remote_gatt_descriptor.cc
+++ b/device/bluetooth/test/fake_remote_gatt_descriptor.cc
@@ -29,10 +29,13 @@
   next_read_response_.emplace(gatt_code, value);
 }
 
+void FakeRemoteGattDescriptor::SetNextWriteResponse(uint16_t gatt_code) {
+  DCHECK(!next_write_response_);
+  next_write_response_.emplace(gatt_code);
+}
+
 bool FakeRemoteGattDescriptor::AllResponsesConsumed() {
-  // TODO(crbug.com/569709): Update this when SetNextWriteResponse is
-  // implemented.
-  return !next_read_response_;
+  return !next_read_response_ && !next_write_response_;
 }
 
 std::string FakeRemoteGattDescriptor::GetIdentifier() const {
@@ -70,8 +73,14 @@
 
 void FakeRemoteGattDescriptor::WriteRemoteDescriptor(
     const std::vector<uint8_t>& value,
-    const base::Closure& callback,
-    const ErrorCallback& error_callback) {}
+    const base::RepeatingClosure& callback,
+    const ErrorCallback& error_callback) {
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE,
+      base::BindRepeating(&FakeRemoteGattDescriptor::DispatchWriteResponse,
+                          weak_ptr_factory_.GetWeakPtr(), callback,
+                          error_callback, value));
+}
 
 void FakeRemoteGattDescriptor::DispatchReadResponse(
     const ValueCallback& callback,
@@ -93,4 +102,25 @@
   }
 }
 
+void FakeRemoteGattDescriptor::DispatchWriteResponse(
+    const base::RepeatingClosure& callback,
+    const ErrorCallback& error_callback,
+    const std::vector<uint8_t>& value) {
+  DCHECK(next_write_response_);
+  uint16_t gatt_code = next_write_response_.value();
+  next_write_response_.reset();
+
+  switch (gatt_code) {
+    case mojom::kGATTSuccess:
+      last_written_value_ = value;
+      callback.Run();
+      break;
+    case mojom::kGATTInvalidHandle:
+      error_callback.Run(device::BluetoothGattService::GATT_ERROR_FAILED);
+      break;
+    default:
+      NOTREACHED();
+  }
+}
+
 }  // namespace bluetooth
diff --git a/device/bluetooth/test/fake_remote_gatt_descriptor.h b/device/bluetooth/test/fake_remote_gatt_descriptor.h
index 4ceb9cd5..f12770f 100644
--- a/device/bluetooth/test/fake_remote_gatt_descriptor.h
+++ b/device/bluetooth/test/fake_remote_gatt_descriptor.h
@@ -35,6 +35,16 @@
   void SetNextReadResponse(uint16_t gatt_code,
                            const base::Optional<std::vector<uint8_t>>& value);
 
+  // If |gatt_code| is mojom::kGATTSuccess the next write request will call its
+  // success callback. Otherwise it will call its error callback.
+  void SetNextWriteResponse(uint16_t gatt_code);
+
+  // Returns the last successfully written value to the descriptor. Returns
+  // nullopt if no value has been written yet.
+  const base::Optional<std::vector<uint8_t>>& last_written_value() {
+    return last_written_value_;
+  }
+
   // Returns true if there are no pending responses for this descriptor.
   bool AllResponsesConsumed();
 
@@ -50,22 +60,33 @@
   void ReadRemoteDescriptor(const ValueCallback& callback,
                             const ErrorCallback& error_callback) override;
   void WriteRemoteDescriptor(const std::vector<uint8_t>& value,
-                             const base::Closure& callback,
+                             const base::RepeatingClosure& callback,
                              const ErrorCallback& error_callback) override;
 
  private:
   void DispatchReadResponse(const ValueCallback& callback,
                             const ErrorCallback& error_callback);
 
+  void DispatchWriteResponse(const base::RepeatingClosure& callback,
+                             const ErrorCallback& error_callback,
+                             const std::vector<uint8_t>& value);
+
   const std::string descriptor_id_;
   const device::BluetoothUUID descriptor_uuid_;
   device::BluetoothRemoteGattCharacteristic* characteristic_;
   std::vector<uint8_t> value_;
 
+  // Last successfully written value to the descriptor.
+  base::Optional<std::vector<uint8_t>> last_written_value_;
+
   // Used to decide which callback should be called when
   // ReadRemoteDescriptor is called.
   base::Optional<FakeReadResponse> next_read_response_;
 
+  // Used to decide which callback should be called when WriteRemoteDescriptor
+  // is called.
+  base::Optional<uint16_t> next_write_response_;
+
   base::WeakPtrFactory<FakeRemoteGattDescriptor> weak_ptr_factory_;
 };
 
diff --git a/device/fido/BUILD.gn b/device/fido/BUILD.gn
index f7abe184..5a1b5e0 100644
--- a/device/fido/BUILD.gn
+++ b/device/fido/BUILD.gn
@@ -57,6 +57,14 @@
     "fido_hid_message.h",
     "fido_hid_packet.cc",
     "fido_hid_packet.h",
+    "fido_task.cc",
+    "fido_task.h",
+    "make_credential_task.cc",
+    "make_credential_task.h",
+    "opaque_attestation_statement.cc",
+    "opaque_attestation_statement.h",
+    "opaque_public_key.cc",
+    "opaque_public_key.h",
     "public_key.cc",
     "public_key.h",
     "public_key_credential_descriptor.cc",
@@ -67,24 +75,19 @@
     "public_key_credential_rp_entity.h",
     "public_key_credential_user_entity.cc",
     "public_key_credential_user_entity.h",
-    "register_response_data.cc",
-    "register_response_data.h",
     "response_data.cc",
     "response_data.h",
-    "sign_response_data.cc",
-    "sign_response_data.h",
     "u2f_parsing_utils.cc",
     "u2f_parsing_utils.h",
     "u2f_register.cc",
     "u2f_register.h",
     "u2f_request.cc",
     "u2f_request.h",
-    "u2f_return_code.h",
     "u2f_sign.cc",
     "u2f_sign.h",
     "u2f_transport_protocol.h",
-    "virtual_u2f_device.cc",
-    "virtual_u2f_device.h",
+    "virtual_fido_device.cc",
+    "virtual_fido_device.h",
   ]
 
   defines = [ "IS_DEVICE_FIDO_IMPL" ]
@@ -162,30 +165,6 @@
   libfuzzer_options = [ "max_len=65535" ]
 }
 
-fuzzer_test("sign_response_data_fuzzer") {
-  sources = [
-    "sign_response_data_fuzzer.cc",
-  ]
-  deps = [
-    ":fido",
-    "//base",
-  ]
-  seed_corpus = "response_data_fuzzer_corpus/"
-  libfuzzer_options = [ "max_len=65537" ]
-}
-
-fuzzer_test("register_response_data_fuzzer") {
-  sources = [
-    "register_response_data_fuzzer.cc",
-  ]
-  deps = [
-    ":fido",
-  ]
-
-  seed_corpus = "response_data_fuzzer_corpus/"
-  libfuzzer_options = [ "max_len=65537" ]
-}
-
 fuzzer_test("ctap_response_fuzzer") {
   sources = [
     "ctap_response_fuzzer.cc",
@@ -195,7 +174,7 @@
     "//base",
     "//base:i18n",
   ]
-  seed_corpus = "ctap_response_fuzzer_corpus/"
+  seed_corpus = "response_data_fuzzer_corpus/"
   libfuzzer_options = [ "max_len=65537" ]
 }
 
@@ -206,8 +185,8 @@
   sources = [
     "fake_fido_discovery.cc",
     "fake_fido_discovery.h",
-    "scoped_virtual_u2f_device.cc",
-    "scoped_virtual_u2f_device.h",
+    "scoped_virtual_fido_device.cc",
+    "scoped_virtual_fido_device.h",
     "test_callback_receiver.h",
   ]
   deps = [
diff --git a/device/fido/attestation_object.cc b/device/fido/attestation_object.cc
index f1c0eef..1ddb1c9 100644
--- a/device/fido/attestation_object.cc
+++ b/device/fido/attestation_object.cc
@@ -9,15 +9,10 @@
 #include "components/cbor/cbor_values.h"
 #include "components/cbor/cbor_writer.h"
 #include "device/fido/attestation_statement.h"
+#include "device/fido/fido_constants.h"
 
 namespace device {
 
-namespace {
-constexpr char kAuthDataKey[] = "authData";
-constexpr char kFormatKey[] = "fmt";
-constexpr char kAttestationKey[] = "attStmt";
-}  // namespace
-
 AttestationObject::AttestationObject(
     AuthenticatorData data,
     std::unique_ptr<AttestationStatement> statement)
@@ -30,29 +25,39 @@
 
 AttestationObject::~AttestationObject() = default;
 
-void AttestationObject::EraseAttestationStatement() {
-  attestation_statement_.reset(new NoneAttestationStatement);
+std::vector<uint8_t> AttestationObject::GetCredentialId() const {
+  return authenticator_data_.GetCredentialId();
+}
 
-#if !defined(NDEBUG)
+void AttestationObject::EraseAttestationStatement() {
+  attestation_statement_ = std::make_unique<NoneAttestationStatement>();
+  authenticator_data_.DeleteDeviceAaguid();
+
+#if DCHECK_IS_ON()
   std::vector<uint8_t> auth_data = authenticator_data_.SerializeToByteArray();
   // See diagram at https://w3c.github.io/webauthn/#sctn-attestation
-  constexpr size_t kAAGUIDOffset =
+  constexpr size_t kAaguidOffset =
       32 /* RP ID hash */ + 1 /* flags */ + 4 /* signature counter */;
-  constexpr size_t kAAGUIDSize = 16;
-  DCHECK(auth_data.size() >= kAAGUIDOffset + kAAGUIDSize);
-  DCHECK(std::all_of(&auth_data[kAAGUIDOffset],
-                     &auth_data[kAAGUIDOffset + kAAGUIDSize],
+  constexpr size_t kAaguidSize = 16;
+  DCHECK_GE(auth_data.size(), kAaguidOffset + kAaguidSize);
+  DCHECK(std::all_of(auth_data.data() + kAaguidOffset,
+                     auth_data.data() + kAaguidOffset + kAaguidSize,
                      [](uint8_t v) { return v == 0; }));
 #endif
 }
 
+bool AttestationObject::IsAttestationCertificateInappropriatelyIdentifying() {
+  return attestation_statement_
+      ->IsAttestationCertificateInappropriatelyIdentifying();
+}
+
 std::vector<uint8_t> AttestationObject::SerializeToCBOREncodedBytes() const {
   cbor::CBORValue::MapValue map;
   map[cbor::CBORValue(kFormatKey)] =
       cbor::CBORValue(attestation_statement_->format_name());
   map[cbor::CBORValue(kAuthDataKey)] =
       cbor::CBORValue(authenticator_data_.SerializeToByteArray());
-  map[cbor::CBORValue(kAttestationKey)] =
+  map[cbor::CBORValue(kAttestationStatementKey)] =
       cbor::CBORValue(attestation_statement_->GetAsCBORMap());
   return cbor::CBORWriter::Write(cbor::CBORValue(std::move(map)))
       .value_or(std::vector<uint8_t>());
diff --git a/device/fido/attestation_object.h b/device/fido/attestation_object.h
index 12b173c..382d655 100644
--- a/device/fido/attestation_object.h
+++ b/device/fido/attestation_object.h
@@ -31,17 +31,19 @@
 
   ~AttestationObject();
 
-  // Replaces the attestation statement with a “none” attestation, as
-  // specified for step 20.3 in
-  // https://w3c.github.io/webauthn/#createCredential. (This does not,
-  // currently, erase the AAGUID (in AttestedCredentialData in
-  // |authenticator_data_|) because it is already always zero for U2F devices.
-  // If CTAP2 is supported in the future, that will need to be taken into
-  // account.)
-  //
-  // TODO(https://crbug.com/780078): erase AAGUID when CTAP2 is supported.
+  std::vector<uint8_t> GetCredentialId() const;
+
+  // Replaces the attestation statement with a “none” attestation and replaces
+  // device AAGUID with zero bytes as specified for step 20.3 in
+  // https://w3c.github.io/webauthn/#createCredential.
   void EraseAttestationStatement();
 
+  // Returns true if the attestation certificate is known to be inappropriately
+  // identifying. Some tokens return unique attestation certificates even when
+  // the bit to request that is not set. (Normal attestation certificates are
+  // not indended to be trackable.)
+  bool IsAttestationCertificateInappropriatelyIdentifying();
+
   // Produces a CBOR-encoded byte-array in the following format:
   // {"authData": authenticator data bytes,
   //  "fmt": attestation format name,
diff --git a/device/fido/attestation_statement.cc b/device/fido/attestation_statement.cc
index bbb1638..e03c499 100644
--- a/device/fido/attestation_statement.cc
+++ b/device/fido/attestation_statement.cc
@@ -7,6 +7,8 @@
 #include <string>
 #include <utility>
 
+#include "device/fido/fido_constants.h"
+
 namespace device {
 
 AttestationStatement::~AttestationStatement() = default;
@@ -15,11 +17,16 @@
     : format_(std::move(format)) {}
 
 NoneAttestationStatement::NoneAttestationStatement()
-    : AttestationStatement("none") {}
+    : AttestationStatement(kNoneAttestationValue) {}
 
 NoneAttestationStatement::~NoneAttestationStatement() = default;
 
-cbor::CBORValue::MapValue NoneAttestationStatement::GetAsCBORMap() {
+bool NoneAttestationStatement::
+    IsAttestationCertificateInappropriatelyIdentifying() {
+  return false;
+}
+
+cbor::CBORValue::MapValue NoneAttestationStatement::GetAsCBORMap() const {
   return cbor::CBORValue::MapValue();
 }
 
diff --git a/device/fido/attestation_statement.h b/device/fido/attestation_statement.h
index 8593e911..c4128967 100644
--- a/device/fido/attestation_statement.h
+++ b/device/fido/attestation_statement.h
@@ -29,12 +29,18 @@
   // https://www.w3.org/TR/2017/WD-webauthn-20170505/#defined-attestation-formats
   // This is not a CBOR-encoded byte array, but the map that will be
   // nested within another CBOR object and encoded then.
-  virtual cbor::CBORValue::MapValue GetAsCBORMap() = 0;
+  virtual cbor::CBORValue::MapValue GetAsCBORMap() const = 0;
+
+  // Returns true if the attestation is known to be inappropriately identifying.
+  // Some tokens return unique attestation certificates even when the bit to
+  // request that is not set. (Normal attestation certificates are not
+  // indended to be trackable.)
+  virtual bool IsAttestationCertificateInappropriatelyIdentifying() = 0;
 
   const std::string& format_name() { return format_; }
 
  protected:
-  AttestationStatement(std::string format);
+  explicit AttestationStatement(std::string format);
 
  private:
   const std::string format_;
@@ -49,9 +55,10 @@
     : public AttestationStatement {
  public:
   NoneAttestationStatement();
-
   ~NoneAttestationStatement() override;
-  cbor::CBORValue::MapValue GetAsCBORMap() override;
+
+  bool IsAttestationCertificateInappropriatelyIdentifying() override;
+  cbor::CBORValue::MapValue GetAsCBORMap() const override;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(NoneAttestationStatement);
diff --git a/device/fido/attested_credential_data.cc b/device/fido/attested_credential_data.cc
index d00efce..efada48b 100644
--- a/device/fido/attested_credential_data.cc
+++ b/device/fido/attested_credential_data.cc
@@ -4,14 +4,62 @@
 
 #include "device/fido/attested_credential_data.h"
 
+#include <stddef.h>
+
 #include <utility>
 
 #include "base/numerics/safe_math.h"
+#include "device/fido/opaque_public_key.h"
 #include "device/fido/public_key.h"
 #include "device/fido/u2f_parsing_utils.h"
 
 namespace device {
 
+namespace {
+
+constexpr size_t kAaguidLength = 16;
+
+// Number of bytes used to represent length of credential ID.
+constexpr size_t kCredentialIdLengthLength = 2;
+
+}  // namespace
+
+// static
+base::Optional<AttestedCredentialData>
+AttestedCredentialData::DecodeFromCtapResponse(
+    base::span<const uint8_t> buffer) {
+  if (buffer.size() < kAaguidLength + kCredentialIdLengthLength)
+    return base::nullopt;
+
+  auto aaguid = u2f_parsing_utils::Extract(buffer, 0, kAaguidLength);
+  auto credential_id_length_span = u2f_parsing_utils::ExtractSpan(
+      buffer, kAaguidLength, kCredentialIdLengthLength);
+
+  if (aaguid.empty() || credential_id_length_span.empty())
+    return base::nullopt;
+
+  static_assert(kCredentialIdLengthLength == 2u, "L must be 2 bytes");
+  const size_t credential_id_length =
+      credential_id_length_span[0] << 8 | credential_id_length_span[1];
+
+  auto credential_id = u2f_parsing_utils::Extract(
+      buffer, kAaguidLength + kCredentialIdLengthLength, credential_id_length);
+  if (credential_id.empty())
+    return base::nullopt;
+
+  DCHECK_LE(kAaguidLength + kCredentialIdLengthLength + credential_id_length,
+            buffer.size());
+  auto credential_public_key_data =
+      std::make_unique<OpaquePublicKey>(buffer.subspan(
+          kAaguidLength + kCredentialIdLengthLength + credential_id_length));
+
+  return AttestedCredentialData(
+      std::move(aaguid),
+      std::vector<uint8_t>(credential_id_length_span.begin(),
+                           credential_id_length_span.end()),
+      std::move(credential_id), std::move(credential_public_key_data));
+}
+
 // static
 base::Optional<AttestedCredentialData>
 AttestedCredentialData::CreateFromU2fRegisterResponse(
@@ -63,6 +111,10 @@
 
 AttestedCredentialData::~AttestedCredentialData() = default;
 
+void AttestedCredentialData::DeleteAaguid() {
+  aaguid_ = std::vector<uint8_t>(kAaguidLength, 0);
+}
+
 std::vector<uint8_t> AttestedCredentialData::SerializeAsBytes() const {
   std::vector<uint8_t> attestation_data;
   u2f_parsing_utils::Append(&attestation_data, aaguid_);
diff --git a/device/fido/attested_credential_data.h b/device/fido/attested_credential_data.h
index cef4a9f..323e1e5 100644
--- a/device/fido/attested_credential_data.h
+++ b/device/fido/attested_credential_data.h
@@ -21,6 +21,9 @@
 // https://www.w3.org/TR/2017/WD-webauthn-20170505/#sec-attestation-data
 class COMPONENT_EXPORT(DEVICE_FIDO) AttestedCredentialData {
  public:
+  static base::Optional<AttestedCredentialData> DecodeFromCtapResponse(
+      base::span<const uint8_t> buffer);
+
   static base::Optional<AttestedCredentialData> CreateFromU2fRegisterResponse(
       base::span<const uint8_t> u2f_data,
       std::vector<uint8_t> aaguid,
@@ -37,7 +40,11 @@
 
   ~AttestedCredentialData();
 
-  const std::vector<uint8_t>& credential_id() { return credential_id_; }
+  const std::vector<uint8_t>& credential_id() const { return credential_id_; }
+
+  // Invoked when sending "none" attestation statement to the relying party.
+  // Replaces AAGUID with zero bytes.
+  void DeleteAaguid();
 
   // Produces a byte array consisting of:
   // * AAGUID (16 bytes)
diff --git a/device/fido/authenticator_data.cc b/device/fido/authenticator_data.cc
index d5411350..cfd6769 100644
--- a/device/fido/authenticator_data.cc
+++ b/device/fido/authenticator_data.cc
@@ -6,10 +6,41 @@
 
 #include <utility>
 
+#include "device/fido/attested_credential_data.h"
 #include "device/fido/u2f_parsing_utils.h"
 
 namespace device {
 
+namespace {
+
+constexpr size_t kApplicationParameterLength = 32;
+constexpr size_t kAuthDataCounterLength = 4;
+constexpr size_t kAaguidOffset =
+    32 /* RP ID hash */ + 1 /* flags */ + 4 /* signature counter */;
+
+}  // namespace
+
+// static
+base::Optional<AuthenticatorData> AuthenticatorData::DecodeAuthenticatorData(
+    base::span<const uint8_t> auth_data) {
+  if (auth_data.size() < kAaguidOffset)
+    return base::nullopt;
+  std::vector<uint8_t> application_parameter(
+      auth_data.data(), auth_data.data() + kApplicationParameterLength);
+  uint8_t flag_byte = auth_data[kApplicationParameterLength];
+  std::vector<uint8_t> counter(
+      auth_data.data() + kApplicationParameterLength + 1,
+      auth_data.data() + kApplicationParameterLength + 1 +
+          kAuthDataCounterLength);
+  auto attested_credential_data =
+      AttestedCredentialData::DecodeFromCtapResponse(
+          auth_data.subspan(kAaguidOffset));
+
+  return AuthenticatorData(std::move(application_parameter), flag_byte,
+                           std::move(counter),
+                           std::move(attested_credential_data));
+}
+
 AuthenticatorData::AuthenticatorData(
     std::vector<uint8_t> application_parameter,
     uint8_t flags,
@@ -29,6 +60,13 @@
 
 AuthenticatorData::~AuthenticatorData() = default;
 
+void AuthenticatorData::DeleteDeviceAaguid() {
+  if (!attested_data_)
+    return;
+
+  attested_data_->DeleteAaguid();
+}
+
 std::vector<uint8_t> AuthenticatorData::SerializeToByteArray() const {
   std::vector<uint8_t> authenticator_data;
   u2f_parsing_utils::Append(&authenticator_data, application_parameter_);
@@ -43,4 +81,11 @@
   return authenticator_data;
 }
 
+std::vector<uint8_t> AuthenticatorData::GetCredentialId() const {
+  if (!attested_data_)
+    return std::vector<uint8_t>();
+
+  return attested_data_->credential_id();
+}
+
 }  // namespace device
diff --git a/device/fido/authenticator_data.h b/device/fido/authenticator_data.h
index df94b56..5ea8e48 100644
--- a/device/fido/authenticator_data.h
+++ b/device/fido/authenticator_data.h
@@ -21,9 +21,14 @@
  public:
   enum class Flag : uint8_t {
     kTestOfUserPresence = 1u << 0,
-    kAttestation = 1u << 6
+    kTestOfUserVerification = 1u << 2,
+    kAttestation = 1u << 6,
+    kExtensionDataIncluded = 1u << 7,
   };
 
+  static base::Optional<AuthenticatorData> DecodeAuthenticatorData(
+      base::span<const uint8_t> auth_data);
+
   AuthenticatorData(std::vector<uint8_t> application_parameter,
                     uint8_t flags,
                     std::vector<uint8_t> counter,
@@ -35,6 +40,10 @@
 
   ~AuthenticatorData();
 
+  // Replaces device AAGUID in attested credential data section with zeros.
+  // https://w3c.github.io/webauthn/#attested-credential-data
+  void DeleteDeviceAaguid();
+
   // Produces a byte array consisting of:
   // * hash(relying_party_id / appid)
   // * flags
@@ -42,6 +51,10 @@
   // * attestation_data.
   std::vector<uint8_t> SerializeToByteArray() const;
 
+  // Retrieve credential ID from attested credential data section of the
+  // authenticator data.
+  std::vector<uint8_t> GetCredentialId() const;
+
  private:
   // The application parameter: a SHA-256 hash of either the RP ID or the AppID
   // associated with the credential.
diff --git a/device/fido/authenticator_get_assertion_response.cc b/device/fido/authenticator_get_assertion_response.cc
index 4c72c109..3ed72c9 100644
--- a/device/fido/authenticator_get_assertion_response.cc
+++ b/device/fido/authenticator_get_assertion_response.cc
@@ -6,17 +6,61 @@
 
 #include <utility>
 
+#include "base/optional.h"
+#include "device/fido/authenticator_data.h"
+#include "device/fido/u2f_parsing_utils.h"
+
 namespace device {
 
+namespace {
+
+constexpr size_t kFlagIndex = 0;
+constexpr size_t kFlagLength = 1;
+constexpr size_t kCounterIndex = 1;
+constexpr size_t kCounterLength = 4;
+constexpr size_t kSignatureIndex = 5;
+
+}  // namespace
+
+// static
+base::Optional<AuthenticatorGetAssertionResponse>
+AuthenticatorGetAssertionResponse::CreateFromU2fSignResponse(
+    const std::vector<uint8_t>& relying_party_id_hash,
+    const std::vector<uint8_t>& u2f_data,
+    const std::vector<uint8_t>& key_handle) {
+  if (key_handle.empty())
+    return base::nullopt;
+
+  auto flags = u2f_parsing_utils::Extract(u2f_data, kFlagIndex, kFlagLength);
+  if (flags.empty())
+    return base::nullopt;
+
+  auto counter =
+      u2f_parsing_utils::Extract(u2f_data, kCounterIndex, kCounterLength);
+  if (counter.empty())
+    return base::nullopt;
+
+  AuthenticatorData authenticator_data(relying_party_id_hash, flags[0],
+                                       std::move(counter), base::nullopt);
+
+  auto signature = u2f_parsing_utils::Extract(
+      u2f_data, kSignatureIndex, u2f_data.size() - kSignatureIndex);
+  if (signature.empty())
+    return base::nullopt;
+
+  auto response = AuthenticatorGetAssertionResponse(
+      std::move(authenticator_data), std::move(signature));
+  response.SetCredential(
+      PublicKeyCredentialDescriptor(kU2fCredentialType, key_handle));
+
+  return std::move(response);
+}
+
 AuthenticatorGetAssertionResponse::AuthenticatorGetAssertionResponse(
-    CtapDeviceResponseCode response_code,
-    std::vector<uint8_t> auth_data,
-    std::vector<uint8_t> signature,
-    PublicKeyCredentialUserEntity user)
-    : response_code_(response_code),
-      auth_data_(std::move(auth_data)),
-      signature_(std::move(signature)),
-      user_(std::move(user)) {}
+    AuthenticatorData authenticator_data,
+    std::vector<uint8_t> signature)
+    : authenticator_data_(std::move(authenticator_data)),
+      signature_(std::move(signature)) {}
 
 AuthenticatorGetAssertionResponse::AuthenticatorGetAssertionResponse(
     AuthenticatorGetAssertionResponse&& that) = default;
@@ -28,15 +72,23 @@
     default;
 
 AuthenticatorGetAssertionResponse&
-AuthenticatorGetAssertionResponse::SetNumCredentials(uint8_t num_credentials) {
-  num_credentials_ = num_credentials;
+AuthenticatorGetAssertionResponse::SetCredential(
+    PublicKeyCredentialDescriptor credential) {
+  credential_ = std::move(credential);
+  raw_credential_id_ = credential_->id();
   return *this;
 }
 
 AuthenticatorGetAssertionResponse&
-AuthenticatorGetAssertionResponse::SetCredential(
-    PublicKeyCredentialDescriptor credential) {
-  credential_ = std::move(credential);
+AuthenticatorGetAssertionResponse::SetUserEntity(
+    PublicKeyCredentialUserEntity user_entity) {
+  user_entity_ = std::move(user_entity);
+  return *this;
+}
+
+AuthenticatorGetAssertionResponse&
+AuthenticatorGetAssertionResponse::SetNumCredentials(uint8_t num_credentials) {
+  num_credentials_ = num_credentials;
   return *this;
 }
 
diff --git a/device/fido/authenticator_get_assertion_response.h b/device/fido/authenticator_get_assertion_response.h
index 2506505a..b985a81 100644
--- a/device/fido/authenticator_get_assertion_response.h
+++ b/device/fido/authenticator_get_assertion_response.h
@@ -12,48 +12,56 @@
 #include "base/component_export.h"
 #include "base/macros.h"
 #include "base/optional.h"
+#include "device/fido/authenticator_data.h"
 #include "device/fido/fido_constants.h"
 #include "device/fido/public_key_credential_descriptor.h"
 #include "device/fido/public_key_credential_user_entity.h"
+#include "device/fido/response_data.h"
 
 namespace device {
 
 // Represents response from authenticators for AuthenticatorGetAssertion and
 // AuthenticatorGetNextAssertion requests.
 // https://fidoalliance.org/specs/fido-v2.0-rd-20170927/fido-client-to-authenticator-protocol-v2.0-rd-20170927.html#authenticatorGetAssertion
-class COMPONENT_EXPORT(DEVICE_FIDO) AuthenticatorGetAssertionResponse {
+class COMPONENT_EXPORT(DEVICE_FIDO) AuthenticatorGetAssertionResponse
+    : public ResponseData {
  public:
-  AuthenticatorGetAssertionResponse(CtapDeviceResponseCode response_code,
-                                    std::vector<uint8_t> auth_data,
-                                    std::vector<uint8_t> signature,
-                                    PublicKeyCredentialUserEntity user);
+  static base::Optional<AuthenticatorGetAssertionResponse>
+  CreateFromU2fSignResponse(const std::vector<uint8_t>& relying_party_id_hash,
+                            const std::vector<uint8_t>& u2f_data,
+                            const std::vector<uint8_t>& key_handle);
+
+  AuthenticatorGetAssertionResponse(AuthenticatorData authenticator_data,
+                                    std::vector<uint8_t> signature);
   AuthenticatorGetAssertionResponse(AuthenticatorGetAssertionResponse&& that);
   AuthenticatorGetAssertionResponse& operator=(
       AuthenticatorGetAssertionResponse&& other);
   ~AuthenticatorGetAssertionResponse();
 
-  AuthenticatorGetAssertionResponse& SetNumCredentials(uint8_t num_credentials);
   AuthenticatorGetAssertionResponse& SetCredential(
       PublicKeyCredentialDescriptor credential);
+  AuthenticatorGetAssertionResponse& SetUserEntity(
+      PublicKeyCredentialUserEntity user_entity);
+  AuthenticatorGetAssertionResponse& SetNumCredentials(uint8_t num_credentials);
 
-  CtapDeviceResponseCode response_code() const { return response_code_; }
-  const std::vector<uint8_t>& auth_data() const { return auth_data_; }
-  const std::vector<uint8_t>& signature() const { return signature_; }
-  const PublicKeyCredentialUserEntity& user() const { return user_; }
-  const base::Optional<uint8_t>& num_credentials() const {
-    return num_credentials_;
-  }
   const base::Optional<PublicKeyCredentialDescriptor>& credential() const {
     return credential_;
   }
+  const AuthenticatorData& auth_data() const { return authenticator_data_; }
+  const std::vector<uint8_t>& signature() const { return signature_; }
+  const base::Optional<PublicKeyCredentialUserEntity>& user_entity() const {
+    return user_entity_;
+  }
+  const base::Optional<uint8_t>& num_credentials() const {
+    return num_credentials_;
+  }
 
  private:
-  CtapDeviceResponseCode response_code_;
-  std::vector<uint8_t> auth_data_;
-  std::vector<uint8_t> signature_;
-  PublicKeyCredentialUserEntity user_;
-  base::Optional<uint8_t> num_credentials_;
   base::Optional<PublicKeyCredentialDescriptor> credential_;
+  AuthenticatorData authenticator_data_;
+  std::vector<uint8_t> signature_;
+  base::Optional<PublicKeyCredentialUserEntity> user_entity_;
+  base::Optional<uint8_t> num_credentials_;
 
   DISALLOW_COPY_AND_ASSIGN(AuthenticatorGetAssertionResponse);
 };
diff --git a/device/fido/authenticator_get_info_response.cc b/device/fido/authenticator_get_info_response.cc
index 83d75b1..9645c5b2 100644
--- a/device/fido/authenticator_get_info_response.cc
+++ b/device/fido/authenticator_get_info_response.cc
@@ -9,12 +9,9 @@
 namespace device {
 
 AuthenticatorGetInfoResponse::AuthenticatorGetInfoResponse(
-    CtapDeviceResponseCode response_code,
     std::vector<std::string> versions,
     std::vector<uint8_t> aaguid)
-    : response_code_(response_code),
-      versions_(std::move(versions)),
-      aaguid_(std::move(aaguid)) {}
+    : versions_(std::move(versions)), aaguid_(std::move(aaguid)) {}
 
 AuthenticatorGetInfoResponse::AuthenticatorGetInfoResponse(
     AuthenticatorGetInfoResponse&& that) = default;
diff --git a/device/fido/authenticator_get_info_response.h b/device/fido/authenticator_get_info_response.h
index 230b385..ef84cb1 100644
--- a/device/fido/authenticator_get_info_response.h
+++ b/device/fido/authenticator_get_info_response.h
@@ -24,8 +24,7 @@
 // https://fidoalliance.org/specs/fido-v2.0-rd-20170927/fido-client-to-authenticator-protocol-v2.0-rd-20170927.html#authenticatorGetInfo
 class COMPONENT_EXPORT(DEVICE_FIDO) AuthenticatorGetInfoResponse {
  public:
-  AuthenticatorGetInfoResponse(CtapDeviceResponseCode response_code,
-                               std::vector<std::string> versions,
+  AuthenticatorGetInfoResponse(std::vector<std::string> versions,
                                std::vector<uint8_t> aaguid);
   AuthenticatorGetInfoResponse(AuthenticatorGetInfoResponse&& that);
   AuthenticatorGetInfoResponse& operator=(AuthenticatorGetInfoResponse&& other);
@@ -39,7 +38,6 @@
   AuthenticatorGetInfoResponse& SetOptions(
       AuthenticatorSupportedOptions options);
 
-  CtapDeviceResponseCode response_code() const { return response_code_; }
   const std::vector<std::string>& versions() { return versions_; }
   const std::vector<uint8_t>& aaguid() const { return aaguid_; }
   const base::Optional<uint8_t>& max_msg_size() const { return max_msg_size_; }
@@ -54,7 +52,6 @@
   }
 
  private:
-  CtapDeviceResponseCode response_code_;
   std::vector<std::string> versions_;
   std::vector<uint8_t> aaguid_;
   base::Optional<uint8_t> max_msg_size_;
diff --git a/device/fido/authenticator_make_credential_response.cc b/device/fido/authenticator_make_credential_response.cc
index 07fdf30f2f..a6e4a8df 100644
--- a/device/fido/authenticator_make_credential_response.cc
+++ b/device/fido/authenticator_make_credential_response.cc
@@ -6,12 +6,62 @@
 
 #include <utility>
 
+#include "device/fido/attestation_object.h"
+#include "device/fido/attested_credential_data.h"
+#include "device/fido/authenticator_data.h"
+#include "device/fido/ec_public_key.h"
+#include "device/fido/fido_attestation_statement.h"
+#include "device/fido/u2f_parsing_utils.h"
+
 namespace device {
 
+// static
+base::Optional<AuthenticatorMakeCredentialResponse>
+AuthenticatorMakeCredentialResponse::CreateFromU2fRegisterResponse(
+    const std::vector<uint8_t>& relying_party_id_hash,
+    base::span<const uint8_t> u2f_data) {
+  auto public_key = ECPublicKey::ExtractFromU2fRegistrationResponse(
+      u2f_parsing_utils::kEs256, u2f_data);
+  if (!public_key)
+    return base::nullopt;
+
+  // AAGUID is zeroed out for U2F responses.
+  std::vector<uint8_t> aaguid(16u);
+
+  auto attested_credential_data =
+      AttestedCredentialData::CreateFromU2fRegisterResponse(
+          u2f_data, std::move(aaguid), std::move(public_key));
+
+  if (!attested_credential_data)
+    return base::nullopt;
+
+  // Extract the credential_id for packing into the response data.
+  std::vector<uint8_t> credential_id =
+      attested_credential_data->credential_id();
+
+  // The counter is zeroed out for Register requests.
+  std::vector<uint8_t> counter(4u);
+  constexpr uint8_t flags =
+      static_cast<uint8_t>(AuthenticatorData::Flag::kTestOfUserPresence) |
+      static_cast<uint8_t>(AuthenticatorData::Flag::kAttestation);
+
+  AuthenticatorData authenticator_data(std::move(relying_party_id_hash), flags,
+                                       std::move(counter),
+                                       std::move(attested_credential_data));
+
+  auto fido_attestation_statement =
+      FidoAttestationStatement::CreateFromU2fRegisterResponse(u2f_data);
+
+  if (!fido_attestation_statement)
+    return base::nullopt;
+
+  return AuthenticatorMakeCredentialResponse(AttestationObject(
+      std::move(authenticator_data), std::move(fido_attestation_statement)));
+}
+
 AuthenticatorMakeCredentialResponse::AuthenticatorMakeCredentialResponse(
-    CtapDeviceResponseCode response_code,
-    std::vector<uint8_t> attestation_object)
-    : response_code_(response_code),
+    AttestationObject attestation_object)
+    : ResponseData(attestation_object.GetCredentialId()),
       attestation_object_(std::move(attestation_object)) {}
 
 AuthenticatorMakeCredentialResponse::AuthenticatorMakeCredentialResponse(
@@ -23,4 +73,19 @@
 AuthenticatorMakeCredentialResponse::~AuthenticatorMakeCredentialResponse() =
     default;
 
+std::vector<uint8_t>
+AuthenticatorMakeCredentialResponse::GetCBOREncodedAttestationObject() const {
+  return attestation_object_.SerializeToCBOREncodedBytes();
+}
+
+void AuthenticatorMakeCredentialResponse::EraseAttestationStatement() {
+  attestation_object_.EraseAttestationStatement();
+}
+
+bool AuthenticatorMakeCredentialResponse::
+    IsAttestationCertificateInappropriatelyIdentifying() {
+  return attestation_object_
+      .IsAttestationCertificateInappropriatelyIdentifying();
+}
+
 }  // namespace device
diff --git a/device/fido/authenticator_make_credential_response.h b/device/fido/authenticator_make_credential_response.h
index 5682fa8..56e8ab9 100644
--- a/device/fido/authenticator_make_credential_response.h
+++ b/device/fido/authenticator_make_credential_response.h
@@ -10,8 +10,12 @@
 #include <vector>
 
 #include "base/component_export.h"
+#include "base/containers/span.h"
 #include "base/macros.h"
+#include "base/optional.h"
+#include "device/fido/attestation_object.h"
 #include "device/fido/fido_constants.h"
+#include "device/fido/response_data.h"
 
 namespace device {
 
@@ -19,25 +23,36 @@
 // data, and attestation statement returned by the authenticator as a response
 // to MakeCredential request.
 // https://fidoalliance.org/specs/fido-v2.0-rd-20170927/fido-client-to-authenticator-protocol-v2.0-rd-20170927.html#authenticatorMakeCredential
-class COMPONENT_EXPORT(DEVICE_FIDO) AuthenticatorMakeCredentialResponse {
+class COMPONENT_EXPORT(DEVICE_FIDO) AuthenticatorMakeCredentialResponse
+    : public ResponseData {
  public:
-  AuthenticatorMakeCredentialResponse(CtapDeviceResponseCode response_code,
-                                      std::vector<uint8_t> attestation_object);
+  static base::Optional<AuthenticatorMakeCredentialResponse>
+  CreateFromU2fRegisterResponse(
+      const std::vector<uint8_t>& relying_party_id_hash,
+      base::span<const uint8_t> u2f_data);
 
+  AuthenticatorMakeCredentialResponse(AttestationObject attestation_object);
   AuthenticatorMakeCredentialResponse(
       AuthenticatorMakeCredentialResponse&& that);
   AuthenticatorMakeCredentialResponse& operator=(
       AuthenticatorMakeCredentialResponse&& other);
   ~AuthenticatorMakeCredentialResponse();
 
-  CtapDeviceResponseCode response_code() const { return response_code_; }
-  const std::vector<uint8_t>& attestation_object() const {
-    return attestation_object_;
-  }
+  std::vector<uint8_t> GetCBOREncodedAttestationObject() const;
+
+  // Replaces the attestation statement with a “none” attestation and removes
+  // AAGUID from authenticator data section.
+  // https://w3c.github.io/webauthn/#createCredential
+  void EraseAttestationStatement();
+
+  // Returns true if the attestation certificate is known to be inappropriately
+  // identifying. Some tokens return unique attestation certificates even when
+  // the bit to request that is not set. (Normal attestation certificates are
+  // not indended to be trackable.)
+  bool IsAttestationCertificateInappropriatelyIdentifying();
 
  private:
-  CtapDeviceResponseCode response_code_;
-  std::vector<uint8_t> attestation_object_;
+  AttestationObject attestation_object_;
 
   DISALLOW_COPY_AND_ASSIGN(AuthenticatorMakeCredentialResponse);
 };
diff --git a/device/fido/ctap_response_fuzzer.cc b/device/fido/ctap_response_fuzzer.cc
index 53ca4e7..989c7328 100644
--- a/device/fido/ctap_response_fuzzer.cc
+++ b/device/fido/ctap_response_fuzzer.cc
@@ -5,7 +5,6 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#include <algorithm>
 #include <vector>
 
 #include "base/at_exit.h"
@@ -14,7 +13,6 @@
 #include "device/fido/authenticator_get_info_response.h"
 #include "device/fido/authenticator_make_credential_response.h"
 #include "device/fido/device_response_converter.h"
-#include "device/fido/fido_constants.h"
 
 namespace device {
 
@@ -32,13 +30,23 @@
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
   std::vector<uint8_t> input(data, data + size);
-  device::ReadCTAPMakeCredentialResponse(
-      device::CtapDeviceResponseCode::kSuccess, input);
-  device::ReadCTAPGetAssertionResponse(device::CtapDeviceResponseCode::kSuccess,
-                                       input);
-  device::ReadCTAPGetInfoResponse(device::CtapDeviceResponseCode::kSuccess,
-                                  input);
+  std::vector<uint8_t> relying_party_id_hash(32);
+  auto response = device::ReadCTAPMakeCredentialResponse(input);
+  if (response)
+    response->EraseAttestationStatement();
 
+  response = device::AuthenticatorMakeCredentialResponse::
+      CreateFromU2fRegisterResponse(relying_party_id_hash, input);
+  if (response)
+    response->EraseAttestationStatement();
+
+  device::ReadCTAPGetAssertionResponse(input);
+  std::vector<uint8_t> u2f_response_data(data, data + size);
+  std::vector<uint8_t> key_handle(data, data + size);
+  device::AuthenticatorGetAssertionResponse::CreateFromU2fSignResponse(
+      relying_party_id_hash, u2f_response_data, key_handle);
+
+  device::ReadCTAPGetInfoResponse(input);
   return 0;
 }
 
diff --git a/device/fido/ctap_response_unittest.cc b/device/fido/ctap_response_unittest.cc
index e71df1b..dcafb902 100644
--- a/device/fido/ctap_response_unittest.cc
+++ b/device/fido/ctap_response_unittest.cc
@@ -13,11 +13,99 @@
 
 namespace device {
 
+namespace {
+
+const uint8_t kDeviceMakeCredentialResponse[] = {
+    // clang-format off
+    0x00,  // Success response code
+    0xa3,  // map(3)
+    0x01,  // unsigned(1)
+    0x66,  // text(6)
+    // "packed"
+    0x70, 0x61, 0x63, 0x6b, 0x65, 0x64,
+
+    0x02,        // unsigned(2)
+    0x58, 0x9a,  // bytes(154)
+    // auth data
+    0xc2, 0x89, 0xc5, 0xca, 0x9b, 0x04, 0x60, 0xf9, 0x34, 0x6a, 0xb4, 0xe4,
+    0x2d, 0x84, 0x27, 0x43, 0x40, 0x4d, 0x31, 0xf4, 0x84, 0x68, 0x25, 0xa6,
+    0xd0, 0x65, 0xbe, 0x59, 0x7a, 0x87, 0x05, 0x1d, 0x41, 0x00, 0x00, 0x00,
+    0x0b, 0xf8, 0xa0, 0x11, 0xf3, 0x8c, 0x0a, 0x4d, 0x15, 0x80, 0x06, 0x17,
+    0x11, 0x1f, 0x9e, 0xdc, 0x7d, 0x00, 0x10, 0x89, 0x59, 0xce, 0xad, 0x5b,
+    0x5c, 0x48, 0x16, 0x4e, 0x8a, 0xbc, 0xd6, 0xd9, 0x43, 0x5c, 0x6f, 0xa3,
+    0x63, 0x61, 0x6c, 0x67, 0x65, 0x45, 0x53, 0x32, 0x35, 0x36, 0x61, 0x78,
+    0x58, 0x20, 0xf7, 0xc4, 0xf4, 0xa6, 0xf1, 0xd7, 0x95, 0x38, 0xdf, 0xa4,
+    0xc9, 0xac, 0x50, 0x84, 0x8d, 0xf7, 0x08, 0xbc, 0x1c, 0x99, 0xf5, 0xe6,
+    0x0e, 0x51, 0xb4, 0x2a, 0x52, 0x1b, 0x35, 0xd3, 0xb6, 0x9a, 0x61, 0x79,
+    0x58, 0x20, 0xde, 0x7b, 0x7d, 0x6c, 0xa5, 0x64, 0xe7, 0x0e, 0xa3, 0x21,
+    0xa4, 0xd5, 0xd9, 0x6e, 0xa0, 0x0e, 0xf0, 0xe2, 0xdb, 0x89, 0xdd, 0x61,
+    0xd4, 0x89, 0x4c, 0x15, 0xac, 0x58, 0x5b, 0xd2, 0x36, 0x84,
+
+    0x03,              // unsigned(3)
+    0xa3,              // map(3)
+    0x63,              // text(3)
+    0x61, 0x6c, 0x67,  // "alg"
+    0x07,              // 7
+    0x63,              // text(3)
+    0x73, 0x69, 0x67,  // "sig"
+    0x58, 0x47,        // bytes(71)
+    // signature
+    0x30, 0x45, 0x02, 0x20, 0x13, 0xf7, 0x3c, 0x5d, 0x9d, 0x53, 0x0e, 0x8c,
+    0xc1, 0x5c, 0xc9, 0xbd, 0x96, 0xad, 0x58, 0x6d, 0x39, 0x36, 0x64, 0xe4,
+    0x62, 0xd5, 0xf0, 0x56, 0x12, 0x35, 0xe6, 0x35, 0x0f, 0x2b, 0x72, 0x89,
+    0x02, 0x21, 0x00, 0x90, 0x35, 0x7f, 0xf9, 0x10, 0xcc, 0xb5, 0x6a, 0xc5,
+    0xb5, 0x96, 0x51, 0x19, 0x48, 0x58, 0x1c, 0x8f, 0xdd, 0xb4, 0xa2, 0xb7,
+    0x99, 0x59, 0x94, 0x80, 0x78, 0xb0, 0x9f, 0x4b, 0xdc, 0x62, 0x29,
+
+    0x63,              // text(3)
+    0x78, 0x35, 0x63,  // "x5c"
+    0x81,              // array(1)
+    0x59, 0x01, 0x97,  // bytes(407)
+    // certificate
+    0x30, 0x82, 0x01, 0x93, 0x30, 0x82, 0x01, 0x38, 0xa0, 0x03, 0x02, 0x01,
+    0x02, 0x02, 0x09, 0x00, 0x85, 0x9b, 0x72, 0x6c, 0xb2, 0x4b, 0x4c, 0x29,
+    0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02,
+    0x30, 0x47, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+    0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a,
+    0x0c, 0x0b, 0x59, 0x75, 0x62, 0x69, 0x63, 0x6f, 0x20, 0x54, 0x65, 0x73,
+    0x74, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x19,
+    0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x6f,
+    0x72, 0x20, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f,
+    0x6e, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x31, 0x32, 0x30, 0x34, 0x31,
+    0x31, 0x35, 0x35, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x36, 0x31, 0x32,
+    0x30, 0x32, 0x31, 0x31, 0x35, 0x35, 0x30, 0x30, 0x5a, 0x30, 0x47, 0x31,
+    0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53,
+    0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x59,
+    0x75, 0x62, 0x69, 0x63, 0x6f, 0x20, 0x54, 0x65, 0x73, 0x74, 0x31, 0x22,
+    0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x19, 0x41, 0x75, 0x74,
+    0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x41,
+    0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x30, 0x59,
+    0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06,
+    0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00,
+    0x04, 0xad, 0x11, 0xeb, 0x0e, 0x88, 0x52, 0xe5, 0x3a, 0xd5, 0xdf, 0xed,
+    0x86, 0xb4, 0x1e, 0x61, 0x34, 0xa1, 0x8e, 0xc4, 0xe1, 0xaf, 0x8f, 0x22,
+    0x1a, 0x3c, 0x7d, 0x6e, 0x63, 0x6c, 0x80, 0xea, 0x13, 0xc3, 0xd5, 0x04,
+    0xff, 0x2e, 0x76, 0x21, 0x1b, 0xb4, 0x45, 0x25, 0xb1, 0x96, 0xc4, 0x4c,
+    0xb4, 0x84, 0x99, 0x79, 0xcf, 0x6f, 0x89, 0x6e, 0xcd, 0x2b, 0xb8, 0x60,
+    0xde, 0x1b, 0xf4, 0x37, 0x6b, 0xa3, 0x0d, 0x30, 0x0b, 0x30, 0x09, 0x06,
+    0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0a, 0x06, 0x08,
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x49, 0x00, 0x30,
+    0x46, 0x02, 0x21, 0x00, 0xe9, 0xa3, 0x9f, 0x1b, 0x03, 0x19, 0x75, 0x25,
+    0xf7, 0x37, 0x3e, 0x10, 0xce, 0x77, 0xe7, 0x80, 0x21, 0x73, 0x1b, 0x94,
+    0xd0, 0xc0, 0x3f, 0x3f, 0xda, 0x1f, 0xd2, 0x2d, 0xb3, 0xd0, 0x30, 0xe7,
+    0x02, 0x21, 0x00, 0xc4, 0xfa, 0xec, 0x34, 0x45, 0xa8, 0x20, 0xcf, 0x43,
+    0x12, 0x9c, 0xdb, 0x00, 0xaa, 0xbe, 0xfd, 0x9a, 0xe2, 0xd8, 0x74, 0xf9,
+    0xc5, 0xd3, 0x43, 0xcb, 0x2f, 0x11, 0x3d, 0xa2, 0x37, 0x23, 0xf3
+    // clang-format on
+};
+
+}  // namespace
+
 // Leveraging example 4 of section 6.1 of the spec https://fidoalliance.org
 // /specs/fido-v2.0-rd-20170927/fido-client-to-authenticator-protocol-v2.0-rd-
 // 20170927.html
 TEST(CTAPResponseTest, TestReadMakeCredentialResponse) {
-  const std::vector<uint8_t> kCertificate = {
+  constexpr uint8_t kCertificate[] = {
       0x30, 0x82, 0x01, 0x93, 0x30, 0x82, 0x01, 0x38, 0xa0, 0x03, 0x02, 0x01,
       0x02, 0x02, 0x09, 0x00, 0x85, 0x9b, 0x72, 0x6c, 0xb2, 0x4b, 0x4c, 0x29,
       0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02,
@@ -53,7 +141,7 @@
       0x12, 0x9c, 0xdb, 0x00, 0xaa, 0xbe, 0xfd, 0x9a, 0xe2, 0xd8, 0x74, 0xf9,
       0xc5, 0xd3, 0x43, 0xcb, 0x2f, 0x11, 0x3d, 0xa2, 0x37, 0x23, 0xf3};
 
-  const std::vector<uint8_t> kAuthData = {
+  constexpr uint8_t kAuthData[] = {
       0xc2, 0x89, 0xc5, 0xca, 0x9b, 0x04, 0x60, 0xf9, 0x34, 0x6a, 0xb4, 0xe4,
       0x2d, 0x84, 0x27, 0x43, 0x40, 0x4d, 0x31, 0xf4, 0x84, 0x68, 0x25, 0xa6,
       0xd0, 0x65, 0xbe, 0x59, 0x7a, 0x87, 0x05, 0x1d, 0x41, 0x00, 0x00, 0x00,
@@ -68,7 +156,7 @@
       0xa4, 0xd5, 0xd9, 0x6e, 0xa0, 0x0e, 0xf0, 0xe2, 0xdb, 0x89, 0xdd, 0x61,
       0xd4, 0x89, 0x4c, 0x15, 0xac, 0x58, 0x5b, 0xd2, 0x36, 0x84};
 
-  const std::vector<uint8_t> kSignature = {
+  constexpr uint8_t kSignature[] = {
       0x30, 0x45, 0x02, 0x20, 0x13, 0xf7, 0x3c, 0x5d, 0x9d, 0x53, 0x0e, 0x8c,
       0xc1, 0x5c, 0xc9, 0xbd, 0x96, 0xad, 0x58, 0x6d, 0x39, 0x36, 0x64, 0xe4,
       0x62, 0xd5, 0xf0, 0x56, 0x12, 0x35, 0xe6, 0x35, 0x0f, 0x2b, 0x72, 0x89,
@@ -76,113 +164,32 @@
       0xb5, 0x96, 0x51, 0x19, 0x48, 0x58, 0x1c, 0x8f, 0xdd, 0xb4, 0xa2, 0xb7,
       0x99, 0x59, 0x94, 0x80, 0x78, 0xb0, 0x9f, 0x4b, 0xdc, 0x62, 0x29};
 
-  const std::vector<uint8_t> kDeviceResponse = {
-      // clang-format off
-      0xa3,  // map(3)
-      0x01,  // unsigned(1)
-      0x66,  // text(6)
-      // "packed"
-      0x70, 0x61, 0x63, 0x6b, 0x65, 0x64,
-
-      0x02,        // unsigned(2)
-      0x58, 0x9a,  // bytes(154)
-      // auth data
-      0xc2, 0x89, 0xc5, 0xca, 0x9b, 0x04, 0x60, 0xf9, 0x34, 0x6a, 0xb4, 0xe4,
-      0x2d, 0x84, 0x27, 0x43, 0x40, 0x4d, 0x31, 0xf4, 0x84, 0x68, 0x25, 0xa6,
-      0xd0, 0x65, 0xbe, 0x59, 0x7a, 0x87, 0x05, 0x1d, 0x41, 0x00, 0x00, 0x00,
-      0x0b, 0xf8, 0xa0, 0x11, 0xf3, 0x8c, 0x0a, 0x4d, 0x15, 0x80, 0x06, 0x17,
-      0x11, 0x1f, 0x9e, 0xdc, 0x7d, 0x00, 0x10, 0x89, 0x59, 0xce, 0xad, 0x5b,
-      0x5c, 0x48, 0x16, 0x4e, 0x8a, 0xbc, 0xd6, 0xd9, 0x43, 0x5c, 0x6f, 0xa3,
-      0x63, 0x61, 0x6c, 0x67, 0x65, 0x45, 0x53, 0x32, 0x35, 0x36, 0x61, 0x78,
-      0x58, 0x20, 0xf7, 0xc4, 0xf4, 0xa6, 0xf1, 0xd7, 0x95, 0x38, 0xdf, 0xa4,
-      0xc9, 0xac, 0x50, 0x84, 0x8d, 0xf7, 0x08, 0xbc, 0x1c, 0x99, 0xf5, 0xe6,
-      0x0e, 0x51, 0xb4, 0x2a, 0x52, 0x1b, 0x35, 0xd3, 0xb6, 0x9a, 0x61, 0x79,
-      0x58, 0x20, 0xde, 0x7b, 0x7d, 0x6c, 0xa5, 0x64, 0xe7, 0x0e, 0xa3, 0x21,
-      0xa4, 0xd5, 0xd9, 0x6e, 0xa0, 0x0e, 0xf0, 0xe2, 0xdb, 0x89, 0xdd, 0x61,
-      0xd4, 0x89, 0x4c, 0x15, 0xac, 0x58, 0x5b, 0xd2, 0x36, 0x84,
-
-      0x03,              // unsigned(3)
-      0xa3,              // map(3)
-      0x63,              // text(3)
-      0x61, 0x6c, 0x67,  // "alg"
-      0x07,              // 7
-      0x63,              // text(3)
-      0x73, 0x69, 0x67,  // "sig"
-      0x58, 0x47,        // bytes(71)
-      // signature
-      0x30, 0x45, 0x02, 0x20, 0x13, 0xf7, 0x3c, 0x5d, 0x9d, 0x53, 0x0e, 0x8c,
-      0xc1, 0x5c, 0xc9, 0xbd, 0x96, 0xad, 0x58, 0x6d, 0x39, 0x36, 0x64, 0xe4,
-      0x62, 0xd5, 0xf0, 0x56, 0x12, 0x35, 0xe6, 0x35, 0x0f, 0x2b, 0x72, 0x89,
-      0x02, 0x21, 0x00, 0x90, 0x35, 0x7f, 0xf9, 0x10, 0xcc, 0xb5, 0x6a, 0xc5,
-      0xb5, 0x96, 0x51, 0x19, 0x48, 0x58, 0x1c, 0x8f, 0xdd, 0xb4, 0xa2, 0xb7,
-      0x99, 0x59, 0x94, 0x80, 0x78, 0xb0, 0x9f, 0x4b, 0xdc, 0x62, 0x29,
-
-      0x63,              // text(3)
-      0x78, 0x35, 0x63,  // "x5c"
-      0x81,              // array(1)
-      0x59, 0x01, 0x97,  // bytes(407)
-      // certificate
-      0x30, 0x82, 0x01, 0x93, 0x30, 0x82, 0x01, 0x38, 0xa0, 0x03, 0x02, 0x01,
-      0x02, 0x02, 0x09, 0x00, 0x85, 0x9b, 0x72, 0x6c, 0xb2, 0x4b, 0x4c, 0x29,
-      0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02,
-      0x30, 0x47, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
-      0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a,
-      0x0c, 0x0b, 0x59, 0x75, 0x62, 0x69, 0x63, 0x6f, 0x20, 0x54, 0x65, 0x73,
-      0x74, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x19,
-      0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x6f,
-      0x72, 0x20, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f,
-      0x6e, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x31, 0x32, 0x30, 0x34, 0x31,
-      0x31, 0x35, 0x35, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x36, 0x31, 0x32,
-      0x30, 0x32, 0x31, 0x31, 0x35, 0x35, 0x30, 0x30, 0x5a, 0x30, 0x47, 0x31,
-      0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53,
-      0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x59,
-      0x75, 0x62, 0x69, 0x63, 0x6f, 0x20, 0x54, 0x65, 0x73, 0x74, 0x31, 0x22,
-      0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x19, 0x41, 0x75, 0x74,
-      0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x41,
-      0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x30, 0x59,
-      0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06,
-      0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00,
-      0x04, 0xad, 0x11, 0xeb, 0x0e, 0x88, 0x52, 0xe5, 0x3a, 0xd5, 0xdf, 0xed,
-      0x86, 0xb4, 0x1e, 0x61, 0x34, 0xa1, 0x8e, 0xc4, 0xe1, 0xaf, 0x8f, 0x22,
-      0x1a, 0x3c, 0x7d, 0x6e, 0x63, 0x6c, 0x80, 0xea, 0x13, 0xc3, 0xd5, 0x04,
-      0xff, 0x2e, 0x76, 0x21, 0x1b, 0xb4, 0x45, 0x25, 0xb1, 0x96, 0xc4, 0x4c,
-      0xb4, 0x84, 0x99, 0x79, 0xcf, 0x6f, 0x89, 0x6e, 0xcd, 0x2b, 0xb8, 0x60,
-      0xde, 0x1b, 0xf4, 0x37, 0x6b, 0xa3, 0x0d, 0x30, 0x0b, 0x30, 0x09, 0x06,
-      0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0a, 0x06, 0x08,
-      0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x49, 0x00, 0x30,
-      0x46, 0x02, 0x21, 0x00, 0xe9, 0xa3, 0x9f, 0x1b, 0x03, 0x19, 0x75, 0x25,
-      0xf7, 0x37, 0x3e, 0x10, 0xce, 0x77, 0xe7, 0x80, 0x21, 0x73, 0x1b, 0x94,
-      0xd0, 0xc0, 0x3f, 0x3f, 0xda, 0x1f, 0xd2, 0x2d, 0xb3, 0xd0, 0x30, 0xe7,
-      0x02, 0x21, 0x00, 0xc4, 0xfa, 0xec, 0x34, 0x45, 0xa8, 0x20, 0xcf, 0x43,
-      0x12, 0x9c, 0xdb, 0x00, 0xaa, 0xbe, 0xfd, 0x9a, 0xe2, 0xd8, 0x74, 0xf9,
-      0xc5, 0xd3, 0x43, 0xcb, 0x2f, 0x11, 0x3d, 0xa2, 0x37, 0x23, 0xf3
-      // clang-format on
+  constexpr uint8_t kCredentialId[] = {
+      0x89, 0x59, 0xce, 0xad, 0x5b, 0x5c, 0x48, 0x16,
+      0x4e, 0x8a, 0xbc, 0xd6, 0xd9, 0x43, 0x5c, 0x6f,
   };
 
-  auto make_credential_response = ReadCTAPMakeCredentialResponse(
-      CtapDeviceResponseCode::kSuccess, kDeviceResponse);
+  auto make_credential_response =
+      ReadCTAPMakeCredentialResponse(kDeviceMakeCredentialResponse);
   ASSERT_TRUE(make_credential_response);
-  EXPECT_EQ(make_credential_response->response_code(),
-            CtapDeviceResponseCode::kSuccess);
-
-  auto cbor_attestation_object =
-      cbor::CBORReader::Read(make_credential_response->attestation_object());
+  auto cbor_attestation_object = cbor::CBORReader::Read(
+      make_credential_response->GetCBOREncodedAttestationObject());
   ASSERT_TRUE(cbor_attestation_object);
   ASSERT_TRUE(cbor_attestation_object->is_map());
 
   const auto& attestation_object_map = cbor_attestation_object->GetMap();
-  auto it = attestation_object_map.find(cbor::CBORValue("fmt"));
+  auto it = attestation_object_map.find(cbor::CBORValue(kFormatKey));
   ASSERT_TRUE(it != attestation_object_map.end());
   ASSERT_TRUE(it->second.is_string());
   EXPECT_EQ(it->second.GetString(), "packed");
 
-  it = attestation_object_map.find(cbor::CBORValue("authData"));
+  it = attestation_object_map.find(cbor::CBORValue(kAuthDataKey));
   ASSERT_TRUE(it != attestation_object_map.end());
   ASSERT_TRUE(it->second.is_bytestring());
   EXPECT_THAT(it->second.GetBytestring(),
               ::testing::ElementsAreArray(kAuthData));
 
-  it = attestation_object_map.find(cbor::CBORValue("attStmt"));
+  it = attestation_object_map.find(cbor::CBORValue(kAttestationStatementKey));
   ASSERT_TRUE(it != attestation_object_map.end());
   ASSERT_TRUE(it->second.is_map());
 
@@ -207,19 +214,67 @@
   ASSERT_TRUE(certificate.GetArray()[0].is_bytestring());
   EXPECT_THAT(certificate.GetArray()[0].GetBytestring(),
               ::testing::ElementsAreArray(kCertificate));
+  EXPECT_THAT(make_credential_response->raw_credential_id(),
+              ::testing::ElementsAreArray(kCredentialId));
+}
+
+TEST(CTAPResponseTest, TestMakeCredentialNoneAttestationResponse) {
+  constexpr uint8_t kNoneAttestationResponse[] = {
+      // clang-format off
+    0xa3,  // map(3)
+    // Format
+    0x63,  // text(3)
+    0x66, 0x6D, 0x74,  // "fmt"
+    0x64,  // text(6)
+    // "none"
+    0x6E, 0x6F, 0x6E, 0x65,
+    // Attestation statement
+    0x67,              // text(7)
+    0x61, 0x74, 0x74, 0x53, 0x74, 0x6D, 0x74,  // "attStmt"
+    0xa0,              // Empty CBOR Map
+    // Authenticator data
+    0x68,        // text(8)
+    0x61, 0x75, 0x74, 0x68, 0x44, 0x61, 0x74, 0x61,
+    0x58, 0x9a,  // bytes(154)
+    0xc2, 0x89, 0xc5, 0xca, 0x9b, 0x04, 0x60, 0xf9, 0x34, 0x6a, 0xb4, 0xe4,
+    0x2d, 0x84, 0x27, 0x43, 0x40, 0x4d, 0x31, 0xf4, 0x84, 0x68, 0x25, 0xa6,
+    0xd0, 0x65, 0xbe, 0x59, 0x7a, 0x87, 0x05, 0x1d, 0x41, 0x00, 0x00, 0x00,
+    0x0b,
+    // Replaced device AAGUID
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00,
+    // Credential information
+    0x00, 0x10, 0x89, 0x59, 0xce, 0xad, 0x5b,
+    0x5c, 0x48, 0x16, 0x4e, 0x8a, 0xbc, 0xd6, 0xd9, 0x43, 0x5c, 0x6f, 0xa3,
+    0x63, 0x61, 0x6c, 0x67, 0x65, 0x45, 0x53, 0x32, 0x35, 0x36, 0x61, 0x78,
+    0x58, 0x20, 0xf7, 0xc4, 0xf4, 0xa6, 0xf1, 0xd7, 0x95, 0x38, 0xdf, 0xa4,
+    0xc9, 0xac, 0x50, 0x84, 0x8d, 0xf7, 0x08, 0xbc, 0x1c, 0x99, 0xf5, 0xe6,
+    0x0e, 0x51, 0xb4, 0x2a, 0x52, 0x1b, 0x35, 0xd3, 0xb6, 0x9a, 0x61, 0x79,
+    0x58, 0x20, 0xde, 0x7b, 0x7d, 0x6c, 0xa5, 0x64, 0xe7, 0x0e, 0xa3, 0x21,
+    0xa4, 0xd5, 0xd9, 0x6e, 0xa0, 0x0e, 0xf0, 0xe2, 0xdb, 0x89, 0xdd, 0x61,
+    0xd4, 0x89, 0x4c, 0x15, 0xac, 0x58, 0x5b, 0xd2, 0x36, 0x84,
+      // clang-format on
+  };
+
+  auto make_credential_response =
+      ReadCTAPMakeCredentialResponse(kDeviceMakeCredentialResponse);
+  ASSERT_TRUE(make_credential_response);
+  make_credential_response->EraseAttestationStatement();
+  EXPECT_THAT(make_credential_response->GetCBOREncodedAttestationObject(),
+              ::testing::ElementsAreArray(kNoneAttestationResponse));
 }
 
 // Leveraging example 5 of section 6.1 of the spec https://fidoalliance.org
 // /specs/fido-v2.0-rd-20170927/fido-client-to-authenticator-protocol-v2.0-rd-
 // 20170927.html
 TEST(CTAPResponseTest, TestReadGetAssertionResponse) {
-  const std::vector<uint8_t> kAuthData = {
+  constexpr uint8_t kAuthData[] = {
       0x62, 0x5d, 0xda, 0xdf, 0x74, 0x3f, 0x57, 0x27, 0xe6, 0x6b,
       0xba, 0x8c, 0x2e, 0x38, 0x79, 0x22, 0xd1, 0xaf, 0x43, 0xc5,
       0x03, 0xd9, 0x11, 0x4a, 0x8f, 0xba, 0x10, 0x4d, 0x84, 0xd0,
       0x2b, 0xfa, 0x01, 0x00, 0x00, 0x00, 0x11};
 
-  const std::vector<uint8_t> kSignature = {
+  constexpr uint8_t kSignature[] = {
       0x30, 0x45, 0x02, 0x20, 0x4a, 0x5a, 0x9d, 0xd3, 0x92, 0x98, 0x14, 0x9d,
       0x90, 0x47, 0x69, 0xb5, 0x1a, 0x45, 0x14, 0x33, 0x00, 0x6f, 0x18, 0x2a,
       0x34, 0xfb, 0xdf, 0x66, 0xde, 0x5f, 0xc7, 0x17, 0xd7, 0x5f, 0xb3, 0x50,
@@ -228,8 +283,9 @@
       0x74, 0xc7, 0x47, 0x90, 0xea, 0xab, 0xb1, 0x44, 0x11, 0xe7, 0xa0,
   };
 
-  const std::vector<uint8_t> kDeviceResponse = {
+  constexpr uint8_t kDeviceGetAssertionResponse[] = {
       // clang-format off
+      0x00,        // Success response code
       0xa5,        // map(5)
       0x01,        // unsigned(1) - Credential
       0xa2,        // map(2)
@@ -302,16 +358,13 @@
       // clang-format on
   };
 
-  auto get_assertion_response = ReadCTAPGetAssertionResponse(
-      CtapDeviceResponseCode::kSuccess, kDeviceResponse);
+  auto get_assertion_response =
+      ReadCTAPGetAssertionResponse(kDeviceGetAssertionResponse);
   ASSERT_TRUE(get_assertion_response);
-
-  EXPECT_EQ(get_assertion_response->response_code(),
-            CtapDeviceResponseCode::kSuccess);
   ASSERT_TRUE(get_assertion_response->num_credentials());
   EXPECT_EQ(*get_assertion_response->num_credentials(), 1u);
 
-  EXPECT_THAT(get_assertion_response->auth_data(),
+  EXPECT_THAT(get_assertion_response->auth_data().SerializeToByteArray(),
               ::testing::ElementsAreArray(kAuthData));
   EXPECT_THAT(get_assertion_response->signature(),
               ::testing::ElementsAreArray(kSignature));
diff --git a/device/fido/device_response_converter.cc b/device/fido/device_response_converter.cc
index e0974ed0..152b4eba 100644
--- a/device/fido/device_response_converter.cc
+++ b/device/fido/device_response_converter.cc
@@ -4,6 +4,7 @@
 
 #include "device/fido/device_response_converter.h"
 
+#include <memory>
 #include <string>
 #include <utility>
 
@@ -12,14 +13,20 @@
 #include "base/stl_util.h"
 #include "components/cbor/cbor_reader.h"
 #include "components/cbor/cbor_writer.h"
+#include "device/fido/authenticator_data.h"
 #include "device/fido/authenticator_supported_options.h"
 #include "device/fido/fido_constants.h"
+#include "device/fido/opaque_attestation_statement.h"
 
 namespace device {
 
+namespace {
+constexpr size_t kResponseCodeLength = 1;
+}
+
 using CBOR = cbor::CBORValue;
 
-CtapDeviceResponseCode GetResponseCode(const std::vector<uint8_t>& buffer) {
+CtapDeviceResponseCode GetResponseCode(base::span<const uint8_t> buffer) {
   if (buffer.empty())
     return CtapDeviceResponseCode::kCtap2ErrInvalidCBOR;
 
@@ -30,87 +37,87 @@
 }
 
 // Decodes byte array response from authenticator to CBOR value object and
-// checks for correct encoding format. Then re-serialize the decoded CBOR value
-// to byte array in format specified by the WebAuthN spec (i.e the keys for
-// CBOR map value are converted from unsigned integers to string type.)
+// checks for correct encoding format.
 base::Optional<AuthenticatorMakeCredentialResponse>
-ReadCTAPMakeCredentialResponse(CtapDeviceResponseCode response_code,
-                               const std::vector<uint8_t>& buffer) {
-  base::Optional<CBOR> decoded_response = cbor::CBORReader::Read(buffer);
+ReadCTAPMakeCredentialResponse(base::span<const uint8_t> buffer) {
+  if (buffer.size() <= kResponseCodeLength)
+    return base::nullopt;
 
+  base::Optional<CBOR> decoded_response =
+      cbor::CBORReader::Read(buffer.subspan(1));
   if (!decoded_response || !decoded_response->is_map())
     return base::nullopt;
 
   const auto& decoded_map = decoded_response->GetMap();
-  CBOR::MapValue response_map;
-
   auto it = decoded_map.find(CBOR(1));
   if (it == decoded_map.end() || !it->second.is_string())
     return base::nullopt;
-
-  response_map[CBOR("fmt")] = it->second.Clone();
+  auto format = it->second.GetString();
 
   it = decoded_map.find(CBOR(2));
   if (it == decoded_map.end() || !it->second.is_bytestring())
     return base::nullopt;
 
-  response_map[CBOR("authData")] = it->second.Clone();
+  auto authenticator_data =
+      AuthenticatorData::DecodeAuthenticatorData(it->second.GetBytestring());
+  if (!authenticator_data)
+    return base::nullopt;
 
   it = decoded_map.find(CBOR(3));
   if (it == decoded_map.end() || !it->second.is_map())
     return base::nullopt;
 
-  response_map[CBOR("attStmt")] = it->second.Clone();
-
-  auto attestation_object =
-      cbor::CBORWriter::Write(CBOR(std::move(response_map)));
-  if (!attestation_object)
-    return base::nullopt;
-
-  return AuthenticatorMakeCredentialResponse(response_code,
-                                             std::move(*attestation_object));
+  return AuthenticatorMakeCredentialResponse(
+      AttestationObject(std::move(*authenticator_data),
+                        std::make_unique<OpaqueAttestationStatement>(
+                            format, it->second.Clone())));
 }
 
 base::Optional<AuthenticatorGetAssertionResponse> ReadCTAPGetAssertionResponse(
-    CtapDeviceResponseCode response_code,
-    const std::vector<uint8_t>& buffer) {
-  base::Optional<CBOR> decoded_response = cbor::CBORReader::Read(buffer);
+    base::span<const uint8_t> buffer) {
+  if (buffer.size() <= kResponseCodeLength)
+    return base::nullopt;
+
+  base::Optional<CBOR> decoded_response =
+      cbor::CBORReader::Read(buffer.subspan(1));
 
   if (!decoded_response || !decoded_response->is_map())
     return base::nullopt;
 
   auto& response_map = decoded_response->GetMap();
 
-  auto it = response_map.find(CBOR(4));
-  if (it == response_map.end() || !it->second.is_map())
-    return base::nullopt;
-
-  auto user = PublicKeyCredentialUserEntity::CreateFromCBORValue(it->second);
-  if (!user)
-    return base::nullopt;
-
-  it = response_map.find(CBOR(2));
+  auto it = response_map.find(CBOR(2));
   if (it == response_map.end() || !it->second.is_bytestring())
     return base::nullopt;
-  auto auth_data = it->second.GetBytestring();
+
+  auto auth_data =
+      AuthenticatorData::DecodeAuthenticatorData(it->second.GetBytestring());
+  if (!auth_data)
+    return base::nullopt;
 
   it = response_map.find(CBOR(3));
   if (it == response_map.end() || !it->second.is_bytestring())
     return base::nullopt;
-  auto signature = it->second.GetBytestring();
 
-  AuthenticatorGetAssertionResponse response(
-      response_code, std::move(auth_data), std::move(signature),
-      std::move(*user));
+  auto signature = it->second.GetBytestring();
+  AuthenticatorGetAssertionResponse response(std::move(*auth_data),
+                                             std::move(signature));
 
   it = response_map.find(CBOR(1));
   if (it != response_map.end()) {
-    auto descriptor =
+    auto credential =
         PublicKeyCredentialDescriptor::CreateFromCBORValue(it->second);
-    if (!descriptor)
+    if (!credential)
       return base::nullopt;
+    response.SetCredential(std::move(*credential));
+  }
 
-    response.SetCredential(std::move(*descriptor));
+  it = response_map.find(CBOR(4));
+  if (it != response_map.end()) {
+    auto user = PublicKeyCredentialUserEntity::CreateFromCBORValue(it->second);
+    if (!user)
+      return base::nullopt;
+    response.SetUserEntity(std::move(*user));
   }
 
   it = response_map.find(CBOR(5));
@@ -125,9 +132,13 @@
 }
 
 base::Optional<AuthenticatorGetInfoResponse> ReadCTAPGetInfoResponse(
-    CtapDeviceResponseCode response_code,
-    const std::vector<uint8_t>& buffer) {
-  base::Optional<CBOR> decoded_response = cbor::CBORReader::Read(buffer);
+    base::span<const uint8_t> buffer) {
+  if (buffer.size() <= kResponseCodeLength ||
+      GetResponseCode(buffer) != CtapDeviceResponseCode::kSuccess)
+    return base::nullopt;
+
+  base::Optional<CBOR> decoded_response =
+      cbor::CBORReader::Read(buffer.subspan(1));
 
   if (!decoded_response || !decoded_response->is_map())
     return base::nullopt;
@@ -150,7 +161,7 @@
   if (it == response_map.end() || !it->second.is_bytestring())
     return base::nullopt;
 
-  AuthenticatorGetInfoResponse response(response_code, std::move(versions),
+  AuthenticatorGetInfoResponse response(std::move(versions),
                                         it->second.GetBytestring());
 
   it = response_map.find(CBOR(2));
diff --git a/device/fido/device_response_converter.h b/device/fido/device_response_converter.h
index 5f957c0..db6ca92 100644
--- a/device/fido/device_response_converter.h
+++ b/device/fido/device_response_converter.h
@@ -24,7 +24,7 @@
 // Parses response code from response received from the authenticator. If
 // unknown response code value is received, then CTAP2_ERR_OTHER is returned.
 COMPONENT_EXPORT(DEVICE_FIDO)
-CtapDeviceResponseCode GetResponseCode(const std::vector<uint8_t>& buffer);
+CtapDeviceResponseCode GetResponseCode(base::span<const uint8_t> buffer);
 
 // De-serializes CBOR encoded response, checks for valid CBOR map formatting,
 // and converts response to AuthenticatorMakeCredentialResponse object with
@@ -32,23 +32,20 @@
 // WebAuthN spec : https://w3c.github.io/webauthn/#fig-attStructs
 COMPONENT_EXPORT(DEVICE_FIDO)
 base::Optional<AuthenticatorMakeCredentialResponse>
-ReadCTAPMakeCredentialResponse(CtapDeviceResponseCode response_code,
-                               const std::vector<uint8_t>& buffer);
+ReadCTAPMakeCredentialResponse(base::span<const uint8_t> buffer);
 
 // De-serializes CBOR encoded response to AuthenticatorGetAssertion /
 // AuthenticatorGetNextAssertion request to AuthenticatorGetAssertionResponse
 // object.
 COMPONENT_EXPORT(DEVICE_FIDO)
 base::Optional<AuthenticatorGetAssertionResponse> ReadCTAPGetAssertionResponse(
-    CtapDeviceResponseCode response_code,
-    const std::vector<uint8_t>& buffer);
+    base::span<const uint8_t> buffer);
 
 // De-serializes CBOR encoded response to AuthenticatorGetInfo request to
 // AuthenticatorGetInfoResponse object.
 COMPONENT_EXPORT(DEVICE_FIDO)
 base::Optional<AuthenticatorGetInfoResponse> ReadCTAPGetInfoResponse(
-    CtapDeviceResponseCode response_code,
-    const std::vector<uint8_t>& buffer);
+    base::span<const uint8_t> buffer);
 
 }  // namespace device
 
diff --git a/device/fido/fido_attestation_statement.cc b/device/fido/fido_attestation_statement.cc
index 9198cc8..77a30b2 100644
--- a/device/fido/fido_attestation_statement.cc
+++ b/device/fido/fido_attestation_statement.cc
@@ -16,6 +16,66 @@
 constexpr char kFidoFormatName[] = "fido-u2f";
 constexpr char kSignatureKey[] = "sig";
 constexpr char kX509CertKey[] = "x5c";
+
+bool IsCertificateInappropriatelyIdentifying(
+    const std::vector<uint8_t>& der_bytes) {
+  constexpr int kVersionTag = 0;
+  CBS cert(der_bytes);
+  CBS top_level, to_be_signed_cert, issuer;
+  if (!CBS_get_asn1(&cert, &top_level, CBS_ASN1_SEQUENCE) ||
+      CBS_len(&cert) != 0 ||
+      !CBS_get_asn1(&top_level, &to_be_signed_cert, CBS_ASN1_SEQUENCE) ||
+      // version, explicitly tagged with tag zero.
+      !CBS_get_optional_asn1(
+          &to_be_signed_cert, NULL, NULL,
+          CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | kVersionTag) ||
+      // serialNumber
+      !CBS_get_asn1(&to_be_signed_cert, NULL, CBS_ASN1_INTEGER) ||
+      // signature algorithm
+      !CBS_get_asn1(&to_be_signed_cert, NULL, CBS_ASN1_SEQUENCE) ||
+      !CBS_get_asn1(&to_be_signed_cert, &issuer, CBS_ASN1_SEQUENCE)) {
+    return false;
+  }
+
+  while (CBS_len(&issuer) != 0) {
+    CBS relative_distinguished_names;
+    if (!CBS_get_asn1(&issuer, &relative_distinguished_names, CBS_ASN1_SET)) {
+      return false;
+    }
+    while (CBS_len(&relative_distinguished_names) != 0) {
+      CBS relative_distinguished_name, object_id;
+      if (!CBS_get_asn1(&relative_distinguished_names,
+                        &relative_distinguished_name, CBS_ASN1_SEQUENCE) ||
+          !CBS_get_asn1(&relative_distinguished_name, &object_id,
+                        CBS_ASN1_OBJECT)) {
+        return false;
+      }
+
+      // Encoding of OID 2.5.4.3 in DER form. See "OBJECT IDENTIFER" in
+      // http://luca.ntop.org/Teaching/Appunti/asn1.html
+      static constexpr uint8_t kCommonNameOID[] = {40 * 2 + 5, 4, 3};
+      if (!CBS_mem_equal(&object_id, kCommonNameOID, sizeof(kCommonNameOID))) {
+        continue;
+      }
+
+      CBS value;
+      unsigned tag;
+      if (!CBS_get_any_asn1(&relative_distinguished_name, &value, &tag)) {
+        return false;
+      }
+
+      static constexpr uint8_t kCommonName[] = "FT FIDO 0100";
+      if ((tag == CBS_ASN1_IA5STRING || tag == CBS_ASN1_UTF8STRING ||
+           tag == CBS_ASN1_PRINTABLESTRING) &&
+          CBS_mem_equal(&value, kCommonName, sizeof(kCommonName) - 1)) {
+        return true;
+      }
+    }
+  }
+
+  return false;
+}
+
 }  // namespace
 
 // static
@@ -57,7 +117,7 @@
 
 FidoAttestationStatement::~FidoAttestationStatement() = default;
 
-cbor::CBORValue::MapValue FidoAttestationStatement::GetAsCBORMap() {
+cbor::CBORValue::MapValue FidoAttestationStatement::GetAsCBORMap() const {
   cbor::CBORValue::MapValue attestation_statement_map;
   attestation_statement_map[cbor::CBORValue(kSignatureKey)] =
       cbor::CBORValue(signature_);
@@ -73,4 +133,18 @@
   return attestation_statement_map;
 }
 
+bool FidoAttestationStatement::
+    IsAttestationCertificateInappropriatelyIdentifying() {
+  // An attestation certificate is considered inappropriately identifying if it
+  // contains a common name of "FT FIDO 0100". See "Inadequately batched
+  // attestation certificates" on https://www.chromium.org/security-keys
+  for (const auto& der_bytes : x509_certificates_) {
+    if (IsCertificateInappropriatelyIdentifying(der_bytes)) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
 }  // namespace device
diff --git a/device/fido/fido_attestation_statement.h b/device/fido/fido_attestation_statement.h
index a817b72b..4ecd75a5f 100644
--- a/device/fido/fido_attestation_statement.h
+++ b/device/fido/fido_attestation_statement.h
@@ -32,7 +32,9 @@
 
   // Produces a map in the following format:
   // { "x5c": [ x509_certs bytes ], "sig": signature bytes ] }
-  cbor::CBORValue::MapValue GetAsCBORMap() override;
+  cbor::CBORValue::MapValue GetAsCBORMap() const override;
+
+  bool IsAttestationCertificateInappropriatelyIdentifying() override;
 
  private:
   const std::vector<uint8_t> signature_;
diff --git a/device/fido/fido_constants.cc b/device/fido/fido_constants.cc
index c48cffe..b272c7bc 100644
--- a/device/fido/fido_constants.cc
+++ b/device/fido/fido_constants.cc
@@ -6,6 +6,8 @@
 
 namespace device {
 
+const char kU2fCredentialType[] = "public-key";
+
 const std::array<uint8_t, 32> kBogusAppParam = {
     0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
     0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
@@ -48,4 +50,9 @@
 
 const base::TimeDelta kDeviceTimeout = base::TimeDelta::FromSeconds(3);
 
+const char kFormatKey[] = "fmt";
+const char kAttestationStatementKey[] = "attStmt";
+const char kAuthDataKey[] = "authData";
+const char kNoneAttestationValue[] = "none";
+
 }  // namespace device
diff --git a/device/fido/fido_constants.h b/device/fido/fido_constants.h
index 2b82355..07feadc 100644
--- a/device/fido/fido_constants.h
+++ b/device/fido/fido_constants.h
@@ -15,6 +15,13 @@
 
 namespace device {
 
+enum class FidoReturnCode : uint8_t {
+  kSuccess,
+  kFailure,
+  kInvalidParams,
+  kConditionsNotSatisfied,
+};
+
 enum class ProtocolVersion {
   kCtap,
   kU2f,
@@ -188,6 +195,9 @@
   kVenderLast = 0xBF,
 };
 
+// Credential type used for U2F requests.
+COMPONENT_EXPORT(DEVICE_FIDO) extern const char kU2fCredentialType[];
+
 // Parameters for fake U2F registration used to check for user presence.
 COMPONENT_EXPORT(DEVICE_FIDO)
 extern const std::array<uint8_t, 32> kBogusAppParam;
@@ -247,6 +257,13 @@
 // Maximum wait time before client error outs on device.
 COMPONENT_EXPORT(DEVICE_FIDO) extern const base::TimeDelta kDeviceTimeout;
 
+// String key values for attestation object as a response to MakeCredential
+// request.
+COMPONENT_EXPORT(DEVICE_FIDO) extern const char kFormatKey[];
+COMPONENT_EXPORT(DEVICE_FIDO) extern const char kAttestationStatementKey[];
+COMPONENT_EXPORT(DEVICE_FIDO) extern const char kAuthDataKey[];
+COMPONENT_EXPORT(DEVICE_FIDO) extern const char kNoneAttestationValue[];
+
 }  // namespace device
 
 #endif  // DEVICE_FIDO_FIDO_CONSTANTS_H_
diff --git a/device/fido/fido_device.cc b/device/fido/fido_device.cc
index 98bdbee..1646e652 100644
--- a/device/fido/fido_device.cc
+++ b/device/fido/fido_device.cc
@@ -4,9 +4,15 @@
 
 #include "device/fido/fido_device.h"
 
+#include <utility>
+
 namespace device {
 
 FidoDevice::FidoDevice() = default;
 FidoDevice::~FidoDevice() = default;
 
+void FidoDevice::SetDeviceInfo(AuthenticatorGetInfoResponse device_info) {
+  device_info_ = std::move(device_info);
+}
+
 }  // namespace device
diff --git a/device/fido/fido_device.h b/device/fido/fido_device.h
index 3c98f7ad..2fec718d 100644
--- a/device/fido/fido_device.h
+++ b/device/fido/fido_device.h
@@ -15,7 +15,8 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
-#include "base/time/time.h"
+#include "device/fido/authenticator_get_info_response.h"
+#include "device/fido/fido_constants.h"
 
 namespace device {
 
@@ -39,9 +40,25 @@
   virtual void TryWink(WinkCallback callback) = 0;
   virtual std::string GetId() const = 0;
 
+  void SetDeviceInfo(AuthenticatorGetInfoResponse device_info);
+  void set_supported_protocol(ProtocolVersion supported_protocol) {
+    supported_protocol_ = supported_protocol;
+  }
+  void set_state(State state) { state_ = state; }
+
+  ProtocolVersion supported_protocol() const { return supported_protocol_; }
+  const base::Optional<AuthenticatorGetInfoResponse>& device_info() const {
+    return device_info_;
+  }
+  State state() const { return state_; }
+
  protected:
   virtual base::WeakPtr<FidoDevice> GetWeakPtr() = 0;
 
+  State state_ = State::kInit;
+  ProtocolVersion supported_protocol_ = ProtocolVersion::kUnknown;
+  base::Optional<AuthenticatorGetInfoResponse> device_info_;
+
   DISALLOW_COPY_AND_ASSIGN(FidoDevice);
 };
 
diff --git a/device/fido/fido_response_test_data.h b/device/fido/fido_response_test_data.h
new file mode 100644
index 0000000..ad399c65
--- /dev/null
+++ b/device/fido/fido_response_test_data.h
@@ -0,0 +1,187 @@
+// 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.
+
+// This file contains common data used to test CTAP/U2F register and sign
+// responses.
+
+#ifndef DEVICE_FIDO_FIDO_RESPONSE_TEST_DATA_H_
+#define DEVICE_FIDO_FIDO_RESPONSE_TEST_DATA_H_
+
+#include <stdint.h>
+
+namespace device {
+
+namespace test_data {
+
+constexpr uint8_t kTestCredentialRawIdBytes[] = {
+    0x89, 0xAF, 0xB5, 0x24, 0x91, 0x1C, 0x40, 0x2B, 0x7F, 0x74, 0x59,
+    0xC9, 0xF2, 0x21, 0xAF, 0xE6, 0xE5, 0x56, 0x65, 0x85, 0x04, 0xE8,
+    0x5B, 0x49, 0x4D, 0x07, 0x55, 0x55, 0xF4, 0x6A, 0xBC, 0x44, 0x7B,
+    0x15, 0xFC, 0x62, 0x61, 0x90, 0xA5, 0xFE, 0xEB, 0xE5, 0x9F, 0x5E,
+    0xDC, 0x75, 0x32, 0x98, 0x6F, 0x44, 0x69, 0xD7, 0xF6, 0x13, 0xEB,
+    0xAA, 0xEA, 0x33, 0xFB, 0xD5, 0x8E, 0xBF, 0xC6, 0x09};
+
+// U2F response blob produced by a U2F registration request. This example
+// data uses testClientDataJson and 'created' a key with testCredentialRawId
+// as its key handle and with the above x- and y- coordinates.
+constexpr uint8_t kTestU2fRegisterResponse[] = {
+    0x05, 0x04, 0xF8, 0x68, 0xCE, 0x38, 0x69, 0x60, 0x52, 0x24, 0xCE, 0x10,
+    0x59, 0xC0, 0x04, 0x7E, 0xF0, 0x1B, 0x83, 0x0F, 0x2A, 0xD9, 0x3B, 0xE2,
+    0x7A, 0x32, 0x11, 0xF4, 0x4E, 0x89, 0x45, 0x60, 0xE6, 0x95, 0x4E, 0x11,
+    0x53, 0x8C, 0xAB, 0xA2, 0xDF, 0x1C, 0xC1, 0xA6, 0xF2, 0x50, 0xED, 0x9F,
+    0x0C, 0x8B, 0x28, 0xB3, 0x9D, 0xA4, 0x45, 0x39, 0xDF, 0xAB, 0xD4, 0x6B,
+    0x58, 0x9C, 0xD0, 0xE2, 0x02, 0xE5, 0x40, 0x89, 0xAF, 0xB5, 0x24, 0x91,
+    0x1C, 0x40, 0x2B, 0x7F, 0x74, 0x59, 0xC9, 0xF2, 0x21, 0xAF, 0xE6, 0xE5,
+    0x56, 0x65, 0x85, 0x04, 0xE8, 0x5B, 0x49, 0x4D, 0x07, 0x55, 0x55, 0xF4,
+    0x6A, 0xBC, 0x44, 0x7B, 0x15, 0xFC, 0x62, 0x61, 0x90, 0xA5, 0xFE, 0xEB,
+    0xE5, 0x9F, 0x5E, 0xDC, 0x75, 0x32, 0x98, 0x6F, 0x44, 0x69, 0xD7, 0xF6,
+    0x13, 0xEB, 0xAA, 0xEA, 0x33, 0xFB, 0xD5, 0x8E, 0xBF, 0xC6, 0x09, 0x30,
+    0x82, 0x02, 0x4A, 0x30, 0x82, 0x01, 0x32, 0xA0, 0x03, 0x02, 0x01, 0x02,
+    0x02, 0x04, 0x04, 0x6C, 0x88, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86,
+    0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x2E, 0x31,
+    0x2C, 0x30, 0x2A, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x23, 0x59, 0x75,
+    0x62, 0x69, 0x63, 0x6F, 0x20, 0x55, 0x32, 0x46, 0x20, 0x52, 0x6F, 0x6F,
+    0x74, 0x20, 0x43, 0x41, 0x20, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6C, 0x20,
+    0x34, 0x35, 0x37, 0x32, 0x30, 0x30, 0x36, 0x33, 0x31, 0x30, 0x20, 0x17,
+    0x0D, 0x31, 0x34, 0x30, 0x38, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
+    0x30, 0x5A, 0x18, 0x0F, 0x32, 0x30, 0x35, 0x30, 0x30, 0x39, 0x30, 0x34,
+    0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x30, 0x2C, 0x31, 0x2A, 0x30,
+    0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x21, 0x59, 0x75, 0x62, 0x69,
+    0x63, 0x6F, 0x20, 0x55, 0x32, 0x46, 0x20, 0x45, 0x45, 0x20, 0x53, 0x65,
+    0x72, 0x69, 0x61, 0x6C, 0x20, 0x32, 0x34, 0x39, 0x31, 0x38, 0x32, 0x33,
+    0x32, 0x34, 0x37, 0x37, 0x30, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A,
+    0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
+    0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x3C, 0xCA, 0xB9, 0x2C,
+    0xCB, 0x97, 0x28, 0x7E, 0xE8, 0xE6, 0x39, 0x43, 0x7E, 0x21, 0xFC, 0xD6,
+    0xB6, 0xF1, 0x65, 0xB2, 0xD5, 0xA3, 0xF3, 0xDB, 0x13, 0x1D, 0x31, 0xC1,
+    0x6B, 0x74, 0x2B, 0xB4, 0x76, 0xD8, 0xD1, 0xE9, 0x90, 0x80, 0xEB, 0x54,
+    0x6C, 0x9B, 0xBD, 0xF5, 0x56, 0xE6, 0x21, 0x0F, 0xD4, 0x27, 0x85, 0x89,
+    0x9E, 0x78, 0xCC, 0x58, 0x9E, 0xBE, 0x31, 0x0F, 0x6C, 0xDB, 0x9F, 0xF4,
+    0xA3, 0x3B, 0x30, 0x39, 0x30, 0x22, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04,
+    0x01, 0x82, 0xC4, 0x0A, 0x02, 0x04, 0x15, 0x31, 0x2E, 0x33, 0x2E, 0x36,
+    0x2E, 0x31, 0x2E, 0x34, 0x2E, 0x31, 0x2E, 0x34, 0x31, 0x34, 0x38, 0x32,
+    0x2E, 0x31, 0x2E, 0x32, 0x30, 0x13, 0x06, 0x0B, 0x2B, 0x06, 0x01, 0x04,
+    0x01, 0x82, 0xE5, 0x1C, 0x02, 0x01, 0x01, 0x04, 0x04, 0x03, 0x02, 0x04,
+    0x30, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
+    0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x9F, 0x9B, 0x05,
+    0x22, 0x48, 0xBC, 0x4C, 0xF4, 0x2C, 0xC5, 0x99, 0x1F, 0xCA, 0xAB, 0xAC,
+    0x9B, 0x65, 0x1B, 0xBE, 0x5B, 0xDC, 0xDC, 0x8E, 0xF0, 0xAD, 0x2C, 0x1C,
+    0x1F, 0xFB, 0x36, 0xD1, 0x87, 0x15, 0xD4, 0x2E, 0x78, 0xB2, 0x49, 0x22,
+    0x4F, 0x92, 0xC7, 0xE6, 0xE7, 0xA0, 0x5C, 0x49, 0xF0, 0xE7, 0xE4, 0xC8,
+    0x81, 0xBF, 0x2E, 0x94, 0xF4, 0x5E, 0x4A, 0x21, 0x83, 0x3D, 0x74, 0x56,
+    0x85, 0x1D, 0x0F, 0x6C, 0x14, 0x5A, 0x29, 0x54, 0x0C, 0x87, 0x4F, 0x30,
+    0x92, 0xC9, 0x34, 0xB4, 0x3D, 0x22, 0x2B, 0x89, 0x62, 0xC0, 0xF4, 0x10,
+    0xCE, 0xF1, 0xDB, 0x75, 0x89, 0x2A, 0xF1, 0x16, 0xB4, 0x4A, 0x96, 0xF5,
+    0xD3, 0x5A, 0xDE, 0xA3, 0x82, 0x2F, 0xC7, 0x14, 0x6F, 0x60, 0x04, 0x38,
+    0x5B, 0xCB, 0x69, 0xB6, 0x5C, 0x99, 0xE7, 0xEB, 0x69, 0x19, 0x78, 0x67,
+    0x03, 0xC0, 0xD8, 0xCD, 0x41, 0xE8, 0xF7, 0x5C, 0xCA, 0x44, 0xAA, 0x8A,
+    0xB7, 0x25, 0xAD, 0x8E, 0x79, 0x9F, 0xF3, 0xA8, 0x69, 0x6A, 0x6F, 0x1B,
+    0x26, 0x56, 0xE6, 0x31, 0xB1, 0xE4, 0x01, 0x83, 0xC0, 0x8F, 0xDA, 0x53,
+    0xFA, 0x4A, 0x8F, 0x85, 0xA0, 0x56, 0x93, 0x94, 0x4A, 0xE1, 0x79, 0xA1,
+    0x33, 0x9D, 0x00, 0x2D, 0x15, 0xCA, 0xBD, 0x81, 0x00, 0x90, 0xEC, 0x72,
+    0x2E, 0xF5, 0xDE, 0xF9, 0x96, 0x5A, 0x37, 0x1D, 0x41, 0x5D, 0x62, 0x4B,
+    0x68, 0xA2, 0x70, 0x7C, 0xAD, 0x97, 0xBC, 0xDD, 0x17, 0x85, 0xAF, 0x97,
+    0xE2, 0x58, 0xF3, 0x3D, 0xF5, 0x6A, 0x03, 0x1A, 0xA0, 0x35, 0x6D, 0x8E,
+    0x8D, 0x5E, 0xBC, 0xAD, 0xC7, 0x4E, 0x07, 0x16, 0x36, 0xC6, 0xB1, 0x10,
+    0xAC, 0xE5, 0xCC, 0x9B, 0x90, 0xDF, 0xEA, 0xCA, 0xE6, 0x40, 0xFF, 0x1B,
+    0xB0, 0xF1, 0xFE, 0x5D, 0xB4, 0xEF, 0xF7, 0xA9, 0x5F, 0x06, 0x07, 0x33,
+    0xF5, 0x30, 0x44, 0x02, 0x20, 0x08, 0xC3, 0xF8, 0xDB, 0x6E, 0x29, 0xFD,
+    0x8B, 0x14, 0xD9, 0xDE, 0x1B, 0xD9, 0x8E, 0x84, 0x07, 0x2C, 0xB8, 0x13,
+    0x38, 0x59, 0x89, 0xAA, 0x2C, 0xA2, 0x89, 0x39, 0x5E, 0x00, 0x09, 0xB8,
+    0xB7, 0x02, 0x20, 0x26, 0x07, 0xB4, 0xF9, 0xAD, 0x05, 0xDE, 0x26, 0xF5,
+    0x6F, 0x48, 0xB8, 0x25, 0x69, 0xEA, 0xD8, 0x23, 0x1A, 0x5A, 0x6C, 0x3A,
+    0x14, 0x48, 0xDE, 0xAA, 0xAF, 0x15, 0xC0, 0xEF, 0x29, 0x63, 0x1A};
+
+// U2F response blob produced by a U2F sign request.
+constexpr uint8_t kTestU2fSignResponse[] = {
+    0x01, 0x00, 0x00, 0x00, 0x25, 0x30, 0x45, 0x02, 0x21, 0x00, 0xCA,
+    0xA5, 0x3E, 0x91, 0x0D, 0xB7, 0x5E, 0xDE, 0xAF, 0x72, 0xCF, 0x9F,
+    0x6F, 0x54, 0xE5, 0x20, 0x5B, 0xBB, 0xB9, 0x2F, 0x0B, 0x9F, 0x7D,
+    0xC6, 0xF8, 0xD4, 0x7B, 0x19, 0x70, 0xED, 0xFE, 0xBC, 0x02, 0x20,
+    0x06, 0x32, 0x83, 0x65, 0x26, 0x4E, 0xBE, 0xFE, 0x35, 0x3C, 0x95,
+    0x91, 0xDF, 0xCE, 0x7D, 0x73, 0x15, 0x98, 0x64, 0xDF, 0xEA, 0xB7,
+    0x87, 0xF1, 0x5D, 0xF8, 0xA5, 0x97, 0xD0, 0x85, 0x0C, 0xA2};
+
+// A sample corrupted response to a U2F sign request.
+constexpr uint8_t kTestCorruptedU2fSignResponse[] = {0x01, 0x00, 0x00, 0x00};
+
+// A sample well formed response to CTAP AuthenticatorGetInfo request.
+constexpr uint8_t kTestAuthenticatorGetInfoResponse[] = {
+    0x00, 0xA6, 0x01, 0x82, 0x68, 0x46, 0x49, 0x44, 0x4F, 0x5F, 0x32, 0x5F,
+    0x30, 0x66, 0x55, 0x32, 0x46, 0x5F, 0x56, 0x32, 0x02, 0x82, 0x63, 0x75,
+    0x76, 0x6D, 0x6B, 0x68, 0x6D, 0x61, 0x63, 0x2D, 0x73, 0x65, 0x63, 0x72,
+    0x65, 0x74, 0x03, 0x50, 0xF8, 0xA0, 0x11, 0xF3, 0x8C, 0x0A, 0x4D, 0x15,
+    0x80, 0x06, 0x17, 0x11, 0x1F, 0x9E, 0xDC, 0x7D, 0x04, 0xA4, 0x62, 0x72,
+    0x6B, 0xF4, 0x62, 0x75, 0x70, 0xF5, 0x64, 0x70, 0x6C, 0x61, 0x74, 0xF4,
+    0x69, 0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x50, 0x69, 0x6E, 0xF4, 0x05,
+    0x19, 0x04, 0xB0, 0x06, 0x81, 0x01};
+
+// A Sample well formed response to CTAP MakeCredential request.
+constexpr uint8_t kTestMakeCredentialResponse[] = {
+    0x00, 0xA3, 0x01, 0x66, 0x70, 0x61, 0x63, 0x6B, 0x65, 0x64, 0x02, 0x58,
+    0xC4, 0x46, 0xCC, 0x7F, 0xB9, 0x67, 0x9D, 0x55, 0xB2, 0xDB, 0x90, 0x92,
+    0xE1, 0xC8, 0xD9, 0xE5, 0xE1, 0xD0, 0x2B, 0x75, 0x80, 0xF0, 0xB4, 0x81,
+    0x2C, 0x77, 0x09, 0x62, 0xE1, 0xE4, 0x8F, 0x5A, 0xD8, 0x41, 0x00, 0x00,
+    0x00, 0x52, 0xF8, 0xA0, 0x11, 0xF3, 0x8C, 0x0A, 0x4D, 0x15, 0x80, 0x06,
+    0x17, 0x11, 0x1F, 0x9E, 0xDC, 0x7D, 0x00, 0x40, 0x2C, 0xC4, 0x73, 0x23,
+    0xA0, 0xEE, 0x0D, 0x5F, 0x66, 0x35, 0x4A, 0x2B, 0x35, 0xC5, 0xFA, 0xFB,
+    0xE7, 0x3D, 0x98, 0x18, 0xB4, 0xC0, 0x53, 0xE9, 0x29, 0x19, 0xAE, 0x3B,
+    0x67, 0xD7, 0xAF, 0x4F, 0x15, 0x6E, 0x67, 0xD0, 0x46, 0x5B, 0x39, 0x06,
+    0x70, 0x93, 0x2F, 0xCE, 0x79, 0x33, 0xDD, 0xD5, 0x96, 0x8F, 0xD0, 0xBF,
+    0xFF, 0x85, 0x62, 0x1F, 0xFD, 0x12, 0x95, 0xBD, 0x0A, 0x41, 0x81, 0x24,
+    0xA5, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0xEB, 0x78,
+    0x4F, 0x0B, 0x6C, 0x78, 0x1E, 0xA1, 0x1E, 0xC8, 0x14, 0x24, 0x36, 0x66,
+    0x07, 0x2F, 0x4B, 0xDB, 0x53, 0xF6, 0x95, 0x8D, 0xDF, 0xC2, 0xCB, 0x6B,
+    0xA0, 0xC2, 0x69, 0xA4, 0x16, 0x03, 0x22, 0x58, 0x20, 0xD4, 0xC3, 0xDC,
+    0xD9, 0x3D, 0xF9, 0x60, 0x9A, 0xF8, 0x56, 0x96, 0xE2, 0xA6, 0x62, 0xF1,
+    0x05, 0xAE, 0x9C, 0x76, 0x9A, 0x0B, 0x3F, 0xFA, 0x5C, 0x05, 0xED, 0xE5,
+    0x7C, 0x64, 0x0A, 0x60, 0x28, 0x03, 0xA3, 0x63, 0x61, 0x6C, 0x67, 0x26,
+    0x63, 0x73, 0x69, 0x67, 0x58, 0x47, 0x30, 0x45, 0x02, 0x21, 0x00, 0xA2,
+    0xA4, 0x1B, 0x2A, 0xE3, 0xA2, 0x0D, 0xFA, 0xF8, 0x0B, 0xB6, 0x96, 0xA0,
+    0x9A, 0xC4, 0x37, 0x84, 0xA7, 0x96, 0x08, 0x90, 0xB8, 0x96, 0xA1, 0x52,
+    0xC8, 0x59, 0x19, 0x68, 0xA3, 0xED, 0x6D, 0x02, 0x20, 0x4B, 0xD3, 0x1E,
+    0xBF, 0x6B, 0xA0, 0x05, 0x5A, 0x73, 0x12, 0x6F, 0x3E, 0x4B, 0xC2, 0x7D,
+    0xA1, 0xCD, 0x68, 0x5E, 0xBB, 0x86, 0x77, 0x8C, 0xC0, 0x7F, 0x8E, 0xA3,
+    0x91, 0x44, 0x19, 0x50, 0x19, 0x63, 0x78, 0x35, 0x63, 0x81, 0x59, 0x01,
+    0x97, 0x30, 0x82, 0x01, 0x93, 0x30, 0x82, 0x01, 0x38, 0xA0, 0x03, 0x02,
+    0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0x9B, 0x72, 0x6C, 0xB2, 0x4B, 0x4C,
+    0x29, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03,
+    0x02, 0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+    0x13, 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04,
+    0x0A, 0x0C, 0x0B, 0x59, 0x75, 0x62, 0x69, 0x63, 0x6F, 0x20, 0x54, 0x65,
+    0x73, 0x74, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C,
+    0x19, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, 0x61, 0x74,
+    0x6F, 0x72, 0x20, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69,
+    0x6F, 0x6E, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x36, 0x31, 0x32, 0x30, 0x34,
+    0x31, 0x31, 0x35, 0x35, 0x30, 0x30, 0x5A, 0x17, 0x0D, 0x32, 0x36, 0x31,
+    0x32, 0x30, 0x32, 0x31, 0x31, 0x35, 0x35, 0x30, 0x30, 0x5A, 0x30, 0x47,
+    0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55,
+    0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0B,
+    0x59, 0x75, 0x62, 0x69, 0x63, 0x6F, 0x20, 0x54, 0x65, 0x73, 0x74, 0x31,
+    0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x19, 0x41, 0x75,
+    0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, 0x61, 0x74, 0x6F, 0x72, 0x20,
+    0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x30,
+    0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01,
+    0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42,
+    0x00, 0x04, 0xAD, 0x11, 0xEB, 0x0E, 0x88, 0x52, 0xE5, 0x3A, 0xD5, 0xDF,
+    0xED, 0x86, 0xB4, 0x1E, 0x61, 0x34, 0xA1, 0x8E, 0xC4, 0xE1, 0xAF, 0x8F,
+    0x22, 0x1A, 0x3C, 0x7D, 0x6E, 0x63, 0x6C, 0x80, 0xEA, 0x13, 0xC3, 0xD5,
+    0x04, 0xFF, 0x2E, 0x76, 0x21, 0x1B, 0xB4, 0x45, 0x25, 0xB1, 0x96, 0xC4,
+    0x4C, 0xB4, 0x84, 0x99, 0x79, 0xCF, 0x6F, 0x89, 0x6E, 0xCD, 0x2B, 0xB8,
+    0x60, 0xDE, 0x1B, 0xF4, 0x37, 0x6B, 0xA3, 0x0D, 0x30, 0x0B, 0x30, 0x09,
+    0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0A, 0x06,
+    0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x49, 0x00,
+    0x30, 0x46, 0x02, 0x21, 0x00, 0xE9, 0xA3, 0x9F, 0x1B, 0x03, 0x19, 0x75,
+    0x25, 0xF7, 0x37, 0x3E, 0x10, 0xCE, 0x77, 0xE7, 0x80, 0x21, 0x73, 0x1B,
+    0x94, 0xD0, 0xC0, 0x3F, 0x3F, 0xDA, 0x1F, 0xD2, 0x2D, 0xB3, 0xD0, 0x30,
+    0xE7, 0x02, 0x21, 0x00, 0xC4, 0xFA, 0xEC, 0x34, 0x45, 0xA8, 0x20, 0xCF,
+    0x43, 0x12, 0x9C, 0xDB, 0x00, 0xAA, 0xBE, 0xFD, 0x9A, 0xE2, 0xD8, 0x74,
+    0xF9, 0xC5, 0xD3, 0x43, 0xCB, 0x2F, 0x11, 0x3D, 0xA2, 0x37, 0x23, 0xF3,
+};
+
+}  // namespace test_data
+
+}  // namespace device
+
+#endif  // DEVICE_FIDO_FIDO_RESPONSE_TEST_DATA_H_
diff --git a/device/fido/fido_task.cc b/device/fido/fido_task.cc
new file mode 100644
index 0000000..ab8f265
--- /dev/null
+++ b/device/fido/fido_task.cc
@@ -0,0 +1,62 @@
+// Copyright 2018 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 "device/fido/fido_task.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "device/fido/ctap_empty_authenticator_request.h"
+#include "device/fido/device_response_converter.h"
+#include "device/fido/fido_constants.h"
+
+namespace device {
+
+FidoTask::FidoTask(FidoDevice* device) : device_(device), weak_factory_(this) {
+  DCHECK(device_);
+  base::SequencedTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE,
+      base::BindOnce(&FidoTask::StartTask, weak_factory_.GetWeakPtr()));
+}
+
+FidoTask::~FidoTask() = default;
+
+void FidoTask::CancelTask() {
+  if (device()->supported_protocol() != ProtocolVersion::kCtap)
+    return;
+
+  device()->DeviceTransact(AuthenticatorCancelRequest().Serialize(),
+                           base::DoNothing());
+}
+
+void FidoTask::GetAuthenticatorInfo(base::OnceClosure ctap_callback,
+                                    base::OnceClosure u2f_callback) {
+  device()->DeviceTransact(
+      AuthenticatorGetInfoRequest().Serialize(),
+      base::BindOnce(&FidoTask::OnAuthenticatorInfoReceived,
+                     weak_factory_.GetWeakPtr(), std::move(ctap_callback),
+                     std::move(u2f_callback)));
+}
+
+void FidoTask::OnAuthenticatorInfoReceived(
+    base::OnceClosure ctap_callback,
+    base::OnceClosure u2f_callback,
+    base::Optional<std::vector<uint8_t>> response) {
+  device()->set_state(FidoDevice::State::kReady);
+
+  base::Optional<AuthenticatorGetInfoResponse> get_info_response;
+  if (!response || !(get_info_response = ReadCTAPGetInfoResponse(*response))) {
+    device()->set_supported_protocol(ProtocolVersion::kU2f);
+    std::move(u2f_callback).Run();
+    return;
+  }
+
+  device()->SetDeviceInfo(std::move(*get_info_response));
+  device()->set_supported_protocol(ProtocolVersion::kCtap);
+  std::move(ctap_callback).Run();
+}
+
+}  // namespace device
diff --git a/device/fido/fido_task.h b/device/fido/fido_task.h
new file mode 100644
index 0000000..773b145b
--- /dev/null
+++ b/device/fido/fido_task.h
@@ -0,0 +1,74 @@
+// Copyright 2018 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 DEVICE_FIDO_FIDO_TASK_H_
+#define DEVICE_FIDO_FIDO_TASK_H_
+
+#include <stdint.h>
+
+#include <vector>
+
+#include "base/callback.h"
+#include "base/component_export.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
+#include "device/fido/fido_device.h"
+
+namespace device {
+
+// Encapsulates per-device request logic shared between MakeCredential and
+// GetAssertion. Handles issuing the AuthenticatorGetInfo command to tokens,
+// caching device info, and distinguishing U2F tokens from CTAP tokens.
+//
+// FidoTask is owned by FidoRequestHandler and manages all interaction with
+// |device_|. It is created when a new device is discovered by FidoDiscovery and
+// destroyed when the device is removed or when a successful response has been
+// issued to the relying party from another authenticator.
+class COMPONENT_EXPORT(DEVICE_FIDO) FidoTask {
+ public:
+  // The |device| must outlive the FidoTask instance.
+  explicit FidoTask(FidoDevice* device);
+  virtual ~FidoTask();
+
+  // Invokes the AuthenticatorCancel method on |device_| if it supports the
+  // CTAP protocol. Upon receiving AuthenticatorCancel request, authenticators
+  // cancel ongoing requests (if any) immediately. Calling this method itself
+  // neither destructs |this| instance nor destroys |device_|.
+  void CancelTask();
+
+ protected:
+  // Asynchronously initiates CTAP request operation for a single device.
+  virtual void StartTask() = 0;
+
+  // Invokes the AuthenticatorGetInfo method on |device_|. If successful and a
+  // well formed response is received, then |device_| is deemed to support CTAP
+  // protocol and |ctap_callback| is invoked, which sends CBOR encoded command
+  // to the authenticator. For all failure cases, |device_| is assumed to
+  // support the U2F protocol as FidoDiscovery selects only devices that support
+  // either the U2F or CTAP protocols during discovery. Therefore |u2f_callback|
+  // is invoked, which sends APDU encoded request to authenticator.
+  void GetAuthenticatorInfo(base::OnceClosure ctap_callback,
+                            base::OnceClosure u2f_callback);
+
+  FidoDevice* device() const {
+    DCHECK(device_);
+    return device_;
+  }
+
+ private:
+  void OnAuthenticatorInfoReceived(
+      base::OnceClosure ctap_callback,
+      base::OnceClosure u2f_callback,
+      base::Optional<std::vector<uint8_t>> response);
+
+  FidoDevice* const device_;
+  base::WeakPtrFactory<FidoTask> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(FidoTask);
+};
+
+}  // namespace device
+
+#endif  // DEVICE_FIDO_FIDO_TASK_H_
diff --git a/device/fido/make_credential_task.cc b/device/fido/make_credential_task.cc
new file mode 100644
index 0000000..e547379
--- /dev/null
+++ b/device/fido/make_credential_task.cc
@@ -0,0 +1,61 @@
+// Copyright 2018 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 "device/fido/make_credential_task.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "device/fido/ctap_empty_authenticator_request.h"
+#include "device/fido/device_response_converter.h"
+
+namespace device {
+
+MakeCredentialTask::MakeCredentialTask(
+    FidoDevice* device,
+    CtapMakeCredentialRequest request_parameter,
+    MakeCredentialTaskCallback callback)
+    : FidoTask(device),
+      request_parameter_(std::move(request_parameter)),
+      callback_(std::move(callback)),
+      weak_factory_(this) {}
+
+MakeCredentialTask::~MakeCredentialTask() = default;
+
+void MakeCredentialTask::StartTask() {
+  GetAuthenticatorInfo(base::BindOnce(&MakeCredentialTask::MakeCredential,
+                                      weak_factory_.GetWeakPtr()),
+                       base::BindOnce(&MakeCredentialTask::U2fRegister,
+                                      weak_factory_.GetWeakPtr()));
+}
+
+void MakeCredentialTask::MakeCredential() {
+  device()->DeviceTransact(
+      request_parameter_.EncodeAsCBOR(),
+      base::BindOnce(&MakeCredentialTask::OnCtapMakeCredentialResponseReceived,
+                     weak_factory_.GetWeakPtr()));
+}
+
+void MakeCredentialTask::U2fRegister() {
+  // TODO(hongjunchoi): Implement U2F register request logic to support
+  // interoperability with U2F protocol. Currently all U2F devices are not
+  // supported and request to U2F devices will be silently dropped.
+  // See: https://crbug.com/798573
+  std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOther,
+                           base::nullopt);
+}
+
+void MakeCredentialTask::OnCtapMakeCredentialResponseReceived(
+    base::Optional<std::vector<uint8_t>> device_response) {
+  if (!device_response) {
+    std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOther,
+                             base::nullopt);
+    return;
+  }
+
+  std::move(callback_).Run(GetResponseCode(*device_response),
+                           ReadCTAPMakeCredentialResponse(*device_response));
+}
+
+}  // namespace device
diff --git a/device/fido/make_credential_task.h b/device/fido/make_credential_task.h
new file mode 100644
index 0000000..04672532
--- /dev/null
+++ b/device/fido/make_credential_task.h
@@ -0,0 +1,56 @@
+// Copyright 2018 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 DEVICE_FIDO_MAKE_CREDENTIAL_TASK_H_
+#define DEVICE_FIDO_MAKE_CREDENTIAL_TASK_H_
+
+#include <stdint.h>
+
+#include <vector>
+
+#include "base/callback.h"
+#include "base/component_export.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
+#include "device/fido/authenticator_make_credential_response.h"
+#include "device/fido/ctap_make_credential_request.h"
+#include "device/fido/fido_constants.h"
+#include "device/fido/fido_task.h"
+
+namespace device {
+
+// Represents one register operation on one single CTAP 1.0/2.0 authenticator.
+// https://fidoalliance.org/specs/fido-v2.0-rd-20161004/fido-client-to-authenticator-protocol-v2.0-rd-20161004.html#authenticatormakecredential
+class COMPONENT_EXPORT(DEVICE_FIDO) MakeCredentialTask : public FidoTask {
+ public:
+  using MakeCredentialTaskCallback = base::OnceCallback<void(
+      CtapDeviceResponseCode return_code,
+      base::Optional<AuthenticatorMakeCredentialResponse> response_data)>;
+
+  MakeCredentialTask(FidoDevice* device,
+                     CtapMakeCredentialRequest request_parameter,
+                     MakeCredentialTaskCallback callback);
+  ~MakeCredentialTask() override;
+
+ private:
+  // FidoTask:
+  void StartTask() final;
+
+  void MakeCredential();
+  void U2fRegister();
+  void OnCtapMakeCredentialResponseReceived(
+      base::Optional<std::vector<uint8_t>> device_response);
+
+  CtapMakeCredentialRequest request_parameter_;
+  MakeCredentialTaskCallback callback_;
+
+  base::WeakPtrFactory<MakeCredentialTask> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(MakeCredentialTask);
+};
+
+}  // namespace device
+
+#endif  // DEVICE_FIDO_MAKE_CREDENTIAL_TASK_H_
diff --git a/device/fido/make_credential_task_unittest.cc b/device/fido/make_credential_task_unittest.cc
new file mode 100644
index 0000000..94f2b68
--- /dev/null
+++ b/device/fido/make_credential_task_unittest.cc
@@ -0,0 +1,126 @@
+// Copyright 2018 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 <memory>
+#include <string>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
+#include "device/fido/authenticator_make_credential_response.h"
+#include "device/fido/ctap_make_credential_request.h"
+#include "device/fido/fido_constants.h"
+#include "device/fido/make_credential_task.h"
+#include "device/fido/mock_fido_device.h"
+#include "device/fido/test_callback_receiver.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+
+namespace device {
+
+namespace {
+
+constexpr uint8_t kClientDataHash[] = {0x01, 0x02, 0x03};
+constexpr uint8_t kUserId[] = {0x01, 0x02, 0x03};
+constexpr char kRpId[] = "google.com";
+
+using TestMakeCredentialTaskCallback =
+    ::device::test::StatusAndValueCallbackReceiver<
+        CtapDeviceResponseCode,
+        base::Optional<AuthenticatorMakeCredentialResponse>>;
+
+}  // namespace
+
+class FidoMakeCredentialTaskTest : public testing::Test {
+ public:
+  FidoMakeCredentialTaskTest()
+      : scoped_task_environment_(
+            base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
+
+  std::unique_ptr<MakeCredentialTask> CreateMakeCredentialTask(
+      FidoDevice* device) {
+    PublicKeyCredentialRpEntity rp(kRpId);
+    PublicKeyCredentialUserEntity user(
+        std::vector<uint8_t>(std::begin(kUserId), std::end(kUserId)));
+    return std::make_unique<MakeCredentialTask>(
+        device,
+        CtapMakeCredentialRequest(
+            std::vector<uint8_t>(std::begin(kClientDataHash),
+                                 std::end(kClientDataHash)),
+            std::move(rp), std::move(user),
+            PublicKeyCredentialParams(
+                {{kU2fCredentialType,
+                  base::strict_cast<int>(
+                      CoseAlgorithmIdentifier::kCoseEs256)}})),
+        callback_receiver_.callback());
+  }
+
+  TestMakeCredentialTaskCallback& make_credential_callback_receiver() {
+    return callback_receiver_;
+  }
+
+ protected:
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
+  TestMakeCredentialTaskCallback callback_receiver_;
+};
+
+MATCHER_P(IndicatesDeviceTransactWithCommand, expected, "") {
+  return !arg.empty() && (arg[0] == expected);
+}
+
+TEST_F(FidoMakeCredentialTaskTest, TestMakeCredentialSuccess) {
+  auto device = std::make_unique<MockFidoDevice>();
+
+  EXPECT_CALL(*device, TryWinkRef(_))
+      .WillRepeatedly(testing::Invoke(MockFidoDevice::WinkDoNothing));
+
+  EXPECT_CALL(*device,
+              DeviceTransactPtr(
+                  IndicatesDeviceTransactWithCommand(base::strict_cast<uint8_t>(
+                      CtapRequestCommand::kAuthenticatorGetInfo)),
+                  _))
+      .WillOnce(testing::Invoke(MockFidoDevice::NoErrorGetInfo));
+
+  EXPECT_CALL(*device,
+              DeviceTransactPtr(
+                  IndicatesDeviceTransactWithCommand(base::strict_cast<uint8_t>(
+                      CtapRequestCommand::kAuthenticatorMakeCredential)),
+                  _))
+      .WillOnce(testing::Invoke(MockFidoDevice::NoErrorMakeCredential));
+
+  const auto task = CreateMakeCredentialTask(device.get());
+  make_credential_callback_receiver().WaitForCallback();
+
+  EXPECT_EQ(CtapDeviceResponseCode::kSuccess,
+            make_credential_callback_receiver().status());
+  EXPECT_TRUE(make_credential_callback_receiver().value());
+  EXPECT_EQ(device->supported_protocol(), ProtocolVersion::kCtap);
+  EXPECT_TRUE(device->device_info());
+}
+
+TEST_F(FidoMakeCredentialTaskTest, TestIncorrectAuthenticatorGetInfoResponse) {
+  auto device = std::make_unique<MockFidoDevice>();
+
+  EXPECT_CALL(*device, TryWinkRef(_))
+      .WillRepeatedly(testing::Invoke(MockFidoDevice::WinkDoNothing));
+  EXPECT_CALL(*device,
+              DeviceTransactPtr(
+                  IndicatesDeviceTransactWithCommand(base::strict_cast<uint8_t>(
+                      CtapRequestCommand::kAuthenticatorGetInfo)),
+                  _))
+      .WillOnce(testing::Invoke(MockFidoDevice::CtapDeviceError));
+
+  const auto task = CreateMakeCredentialTask(device.get());
+  make_credential_callback_receiver().WaitForCallback();
+  EXPECT_EQ(CtapDeviceResponseCode::kCtap2ErrOther,
+            make_credential_callback_receiver().status());
+  EXPECT_EQ(ProtocolVersion::kU2f, device->supported_protocol());
+  EXPECT_FALSE(device->device_info());
+}
+
+}  // namespace device
diff --git a/device/fido/mock_fido_device.cc b/device/fido/mock_fido_device.cc
index 39a2db0..15feea04 100644
--- a/device/fido/mock_fido_device.cc
+++ b/device/fido/mock_fido_device.cc
@@ -8,7 +8,7 @@
 
 #include "components/apdu/apdu_response.h"
 #include "device/fido/fido_constants.h"
-#include "device/fido/u2f_response_test_data.h"
+#include "device/fido/fido_response_test_data.h"
 
 namespace device {
 
@@ -43,6 +43,28 @@
 }
 
 // static
+void MockFidoDevice::NoErrorGetInfo(const std::vector<uint8_t>& command,
+                                    DeviceCallback& cb) {
+  std::move(cb).Run(std::vector<uint8_t>(
+      std::begin(test_data::kTestAuthenticatorGetInfoResponse),
+      std::end(test_data::kTestAuthenticatorGetInfoResponse)));
+}
+
+// static
+void MockFidoDevice::CtapDeviceError(const std::vector<uint8_t>& command,
+                                     DeviceCallback& cb) {
+  std::move(cb).Run(base::nullopt);
+}
+
+// static
+void MockFidoDevice::NoErrorMakeCredential(const std::vector<uint8_t>& command,
+                                           DeviceCallback& cb) {
+  std::move(cb).Run(
+      std::vector<uint8_t>(std::begin(test_data::kTestMakeCredentialResponse),
+                           std::end(test_data::kTestMakeCredentialResponse)));
+}
+
+// static
 void MockFidoDevice::NoErrorSign(const std::vector<uint8_t>& command,
                                  DeviceCallback& cb) {
   std::move(cb).Run(
diff --git a/device/fido/mock_fido_device.h b/device/fido/mock_fido_device.h
index fd4f329..21918ac 100644
--- a/device/fido/mock_fido_device.h
+++ b/device/fido/mock_fido_device.h
@@ -41,6 +41,12 @@
                            DeviceCallback& cb);
   static void WrongData(const std::vector<uint8_t>& command,
                         DeviceCallback& cb);
+  static void NoErrorGetInfo(const std::vector<uint8_t>& command,
+                             DeviceCallback& cb);
+  static void CtapDeviceError(const std::vector<uint8_t>& command,
+                              DeviceCallback& cb);
+  static void NoErrorMakeCredential(const std::vector<uint8_t>& command,
+                                    DeviceCallback& cb);
   static void NoErrorSign(const std::vector<uint8_t>& command,
                           DeviceCallback& cb);
   static void NoErrorRegister(const std::vector<uint8_t>& command,
diff --git a/device/fido/opaque_attestation_statement.cc b/device/fido/opaque_attestation_statement.cc
new file mode 100644
index 0000000..147bd7d
--- /dev/null
+++ b/device/fido/opaque_attestation_statement.cc
@@ -0,0 +1,38 @@
+// Copyright 2018 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 "device/fido/opaque_attestation_statement.h"
+
+#include <utility>
+
+#include "components/cbor/cbor_values.h"
+
+namespace device {
+
+OpaqueAttestationStatement::OpaqueAttestationStatement(
+    std::string attestation_format,
+    cbor::CBORValue attestation_statement_map)
+    : AttestationStatement(std::move(attestation_format)),
+      attestation_statement_map_(std::move(attestation_statement_map)) {}
+
+OpaqueAttestationStatement::~OpaqueAttestationStatement() = default;
+
+// Returns the deep copied cbor map value of |attestation_statement_map_|.
+cbor::CBORValue::MapValue OpaqueAttestationStatement::GetAsCBORMap() const {
+  DCHECK(attestation_statement_map_.is_map());
+  cbor::CBORValue::MapValue new_map;
+  new_map.reserve(attestation_statement_map_.GetMap().size());
+  for (const auto& map_it : attestation_statement_map_.GetMap()) {
+    new_map.try_emplace(new_map.end(), map_it.first.Clone(),
+                        map_it.second.Clone());
+  }
+  return new_map;
+}
+
+bool OpaqueAttestationStatement::
+    IsAttestationCertificateInappropriatelyIdentifying() {
+  return false;
+}
+
+}  // namespace device
diff --git a/device/fido/opaque_attestation_statement.h b/device/fido/opaque_attestation_statement.h
new file mode 100644
index 0000000..89e281c1
--- /dev/null
+++ b/device/fido/opaque_attestation_statement.h
@@ -0,0 +1,37 @@
+// Copyright 2018 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 DEVICE_FIDO_OPAQUE_ATTESTATION_STATEMENT_H_
+#define DEVICE_FIDO_OPAQUE_ATTESTATION_STATEMENT_H_
+
+#include <string>
+
+#include "base/component_export.h"
+#include "base/macros.h"
+#include "components/cbor/cbor_values.h"
+#include "device/fido/attestation_statement.h"
+
+namespace device {
+
+// https://www.w3.org/TR/2017/WD-webauthn-20170505/#fido-u2f-attestation
+class COMPONENT_EXPORT(DEVICE_FIDO) OpaqueAttestationStatement
+    : public AttestationStatement {
+ public:
+  OpaqueAttestationStatement(std::string attestation_format,
+                             cbor::CBORValue attestation_statement_map);
+  ~OpaqueAttestationStatement() override;
+
+  // AttestationStatement:
+  cbor::CBORValue::MapValue GetAsCBORMap() const override;
+  bool IsAttestationCertificateInappropriatelyIdentifying() override;
+
+ private:
+  cbor::CBORValue attestation_statement_map_;
+
+  DISALLOW_COPY_AND_ASSIGN(OpaqueAttestationStatement);
+};
+
+}  // namespace device
+
+#endif  // DEVICE_FIDO_OPAQUE_ATTESTATION_STATEMENT_H_
diff --git a/device/fido/opaque_public_key.cc b/device/fido/opaque_public_key.cc
new file mode 100644
index 0000000..c8a6874
--- /dev/null
+++ b/device/fido/opaque_public_key.cc
@@ -0,0 +1,21 @@
+// Copyright 2018 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 "device/fido/opaque_public_key.h"
+
+namespace device {
+
+OpaquePublicKey::OpaquePublicKey(
+    base::span<const uint8_t> cose_encoded_public_key)
+    : PublicKey(),
+      cose_encoding_(std::vector<uint8_t>(cose_encoded_public_key.cbegin(),
+                                          cose_encoded_public_key.cend())) {}
+
+OpaquePublicKey::~OpaquePublicKey() = default;
+
+std::vector<uint8_t> OpaquePublicKey::EncodeAsCOSEKey() const {
+  return cose_encoding_;
+}
+
+}  // namespace device
diff --git a/device/fido/opaque_public_key.h b/device/fido/opaque_public_key.h
new file mode 100644
index 0000000..4aeb4a91
--- /dev/null
+++ b/device/fido/opaque_public_key.h
@@ -0,0 +1,39 @@
+// Copyright 2018 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 DEVICE_FIDO_OPAQUE_PUBLIC_KEY_H_
+#define DEVICE_FIDO_OPAQUE_PUBLIC_KEY_H_
+
+#include <stdint.h>
+#include <vector>
+
+#include "base/component_export.h"
+#include "base/containers/span.h"
+#include "base/macros.h"
+#include "device/fido/public_key.h"
+
+namespace device {
+
+// An COSE key format encoded public key representation received from CTAP2
+// device as defined in section 7 of the RFC 8152.
+// https://tools.ietf.org/html/rfc8152#section-7
+class COMPONENT_EXPORT(DEVICE_FIDO) OpaquePublicKey : public PublicKey {
+ public:
+  // TODO(hongjunchoi): Add static factory method that checks COSE encoding
+  // format of the received byte array.
+  // See https://www.crbug.com/824636
+  OpaquePublicKey(base::span<const uint8_t> cose_encoded_public_key);
+  ~OpaquePublicKey() override;
+
+  std::vector<uint8_t> EncodeAsCOSEKey() const override;
+
+ private:
+  const std::vector<uint8_t> cose_encoding_;
+
+  DISALLOW_COPY_AND_ASSIGN(OpaquePublicKey);
+};
+
+}  // namespace device
+
+#endif  // DEVICE_FIDO_OPAQUE_PUBLIC_KEY_H_
diff --git a/device/fido/public_key.cc b/device/fido/public_key.cc
index 756a24c..2273bb1 100644
--- a/device/fido/public_key.cc
+++ b/device/fido/public_key.cc
@@ -10,6 +10,8 @@
 
 PublicKey::~PublicKey() = default;
 
+PublicKey::PublicKey() = default;
+
 PublicKey::PublicKey(std::string algorithm)
     : algorithm_(std::move(algorithm)) {}
 
diff --git a/device/fido/public_key.h b/device/fido/public_key.h
index 70cdbc2..0928db80 100644
--- a/device/fido/public_key.h
+++ b/device/fido/public_key.h
@@ -24,6 +24,7 @@
   virtual std::vector<uint8_t> EncodeAsCOSEKey() const = 0;
 
  protected:
+  PublicKey();
   explicit PublicKey(std::string algorithm);
 
   const std::string algorithm_;
diff --git a/device/fido/register_response_data.cc b/device/fido/register_response_data.cc
deleted file mode 100644
index b3655c2..0000000
--- a/device/fido/register_response_data.cc
+++ /dev/null
@@ -1,97 +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 "device/fido/register_response_data.h"
-
-#include <utility>
-
-#include "device/fido/attestation_object.h"
-#include "device/fido/attested_credential_data.h"
-#include "device/fido/authenticator_data.h"
-#include "device/fido/ec_public_key.h"
-#include "device/fido/fido_attestation_statement.h"
-#include "device/fido/u2f_parsing_utils.h"
-
-namespace device {
-
-// static
-base::Optional<RegisterResponseData>
-RegisterResponseData::CreateFromU2fRegisterResponse(
-    const std::vector<uint8_t>& relying_party_id_hash,
-    base::span<const uint8_t> u2f_data) {
-  std::unique_ptr<ECPublicKey> public_key =
-      ECPublicKey::ExtractFromU2fRegistrationResponse(u2f_parsing_utils::kEs256,
-                                                      u2f_data);
-
-  if (!public_key) {
-    return base::nullopt;
-  }
-
-  // Construct the attestation data.
-  // AAGUID is zeroed out for U2F responses.
-  std::vector<uint8_t> aaguid(16u);
-
-  auto attested_credential_data =
-      AttestedCredentialData::CreateFromU2fRegisterResponse(
-          u2f_data, std::move(aaguid), std::move(public_key));
-
-  if (!attested_credential_data) {
-    return base::nullopt;
-  }
-
-  // Extract the credential_id for packing into the reponse data.
-  std::vector<uint8_t> credential_id =
-      attested_credential_data->credential_id();
-
-  // Construct the authenticator data.
-  // The counter is zeroed out for Register requests.
-  std::vector<uint8_t> counter(4u);
-  constexpr uint8_t flags =
-      static_cast<uint8_t>(AuthenticatorData::Flag::kTestOfUserPresence) |
-      static_cast<uint8_t>(AuthenticatorData::Flag::kAttestation);
-
-  AuthenticatorData authenticator_data(relying_party_id_hash, flags,
-                                       std::move(counter),
-                                       std::move(attested_credential_data));
-
-  // Construct the attestation statement.
-  auto fido_attestation_statement =
-      FidoAttestationStatement::CreateFromU2fRegisterResponse(u2f_data);
-
-  if (!fido_attestation_statement) {
-    return base::nullopt;
-  }
-
-  return RegisterResponseData(std::move(credential_id),
-                              std::make_unique<AttestationObject>(
-                                  std::move(authenticator_data),
-                                  std::move(fido_attestation_statement)));
-}
-
-RegisterResponseData::RegisterResponseData() = default;
-
-RegisterResponseData::RegisterResponseData(
-    std::vector<uint8_t> credential_id,
-    std::unique_ptr<AttestationObject> object)
-    : ResponseData(std::move(credential_id)),
-      attestation_object_(std::move(object)) {}
-
-RegisterResponseData::RegisterResponseData(RegisterResponseData&& other) =
-    default;
-
-RegisterResponseData& RegisterResponseData::operator=(
-    RegisterResponseData&& other) = default;
-
-RegisterResponseData::~RegisterResponseData() = default;
-
-void RegisterResponseData::EraseAttestationStatement() {
-  attestation_object_->EraseAttestationStatement();
-}
-
-std::vector<uint8_t> RegisterResponseData::GetCBOREncodedAttestationObject()
-    const {
-  return attestation_object_->SerializeToCBOREncodedBytes();
-}
-
-}  // namespace device
diff --git a/device/fido/register_response_data.h b/device/fido/register_response_data.h
deleted file mode 100644
index 664b773..0000000
--- a/device/fido/register_response_data.h
+++ /dev/null
@@ -1,60 +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 DEVICE_FIDO_REGISTER_RESPONSE_DATA_H_
-#define DEVICE_FIDO_REGISTER_RESPONSE_DATA_H_
-
-#include <stdint.h>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/component_export.h"
-#include "base/containers/span.h"
-#include "base/macros.h"
-#include "base/optional.h"
-#include "device/fido/response_data.h"
-
-namespace device {
-
-class AttestationObject;
-
-// See figure 2: https://goo.gl/rsgvXk
-class COMPONENT_EXPORT(DEVICE_FIDO) RegisterResponseData : public ResponseData {
- public:
-  static base::Optional<RegisterResponseData> CreateFromU2fRegisterResponse(
-      const std::vector<uint8_t>& relying_party_id_hash,
-      base::span<const uint8_t> u2f_data);
-
-  RegisterResponseData();
-
-  RegisterResponseData(std::vector<uint8_t> credential_id,
-                       std::unique_ptr<AttestationObject> object);
-
-  // Moveable.
-  RegisterResponseData(RegisterResponseData&& other);
-  RegisterResponseData& operator=(RegisterResponseData&& other);
-
-  ~RegisterResponseData();
-
-  // Replaces the attestation statement with a “none” attestation, as specified
-  // for step 20.3 in https://w3c.github.io/webauthn/#createCredential.  (This
-  // does not, currently, erase the AAGUID because it is already always zero
-  // for U2F devices. If CTAP2 is supported in the future, that will need to be
-  // taken into account.)
-  //
-  // TODO(https://crbug.com/780078): erase AAGUID when CTAP2 is supported.
-  void EraseAttestationStatement();
-
-  std::vector<uint8_t> GetCBOREncodedAttestationObject() const;
-
- private:
-  std::unique_ptr<AttestationObject> attestation_object_;
-
-  DISALLOW_COPY_AND_ASSIGN(RegisterResponseData);
-};
-
-}  // namespace device
-
-#endif  // DEVICE_FIDO_REGISTER_RESPONSE_DATA_H_
diff --git a/device/fido/register_response_data_fuzzer.cc b/device/fido/register_response_data_fuzzer.cc
deleted file mode 100644
index 4fb89fb9..0000000
--- a/device/fido/register_response_data_fuzzer.cc
+++ /dev/null
@@ -1,17 +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 <stddef.h>
-#include <stdint.h>
-#include <vector>
-
-#include "device/fido/register_response_data.h"
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  std::vector<uint8_t> input(data, data + size);
-  std::vector<uint8_t> relying_party_id_hash(32);
-  auto response = device::RegisterResponseData::CreateFromU2fRegisterResponse(
-      relying_party_id_hash, input);
-  return 0;
-}
diff --git a/device/fido/response_data.cc b/device/fido/response_data.cc
index 3a4d6d6..d392a7e 100644
--- a/device/fido/response_data.cc
+++ b/device/fido/response_data.cc
@@ -13,8 +13,8 @@
 
 ResponseData::ResponseData() = default;
 
-ResponseData::ResponseData(std::vector<uint8_t> credential_id)
-    : raw_id_(std::move(credential_id)) {}
+ResponseData::ResponseData(std::vector<uint8_t> raw_credential_id)
+    : raw_credential_id_(std::move(raw_credential_id)) {}
 
 ResponseData::ResponseData(ResponseData&& other) = default;
 
@@ -24,10 +24,10 @@
 
 std::string ResponseData::GetId() const {
   std::string id;
-  base::Base64UrlEncode(
-      base::StringPiece(reinterpret_cast<const char*>(raw_id_.data()),
-                        raw_id_.size()),
-      base::Base64UrlEncodePolicy::OMIT_PADDING, &id);
+  base::Base64UrlEncode(base::StringPiece(reinterpret_cast<const char*>(
+                                              raw_credential_id_.data()),
+                                          raw_credential_id_.size()),
+                        base::Base64UrlEncodePolicy::OMIT_PADDING, &id);
   return id;
 }
 
diff --git a/device/fido/response_data.h b/device/fido/response_data.h
index 910f055..9f92028 100644
--- a/device/fido/response_data.h
+++ b/device/fido/response_data.h
@@ -19,11 +19,12 @@
 class COMPONENT_EXPORT(DEVICE_FIDO) ResponseData {
  public:
   std::string GetId() const;
-  const std::vector<uint8_t>& raw_id() const { return raw_id_; }
+  const std::vector<uint8_t>& raw_credential_id() const {
+    return raw_credential_id_;
+  }
 
  protected:
-  explicit ResponseData(std::vector<uint8_t> credential_id);
-
+  explicit ResponseData(std::vector<uint8_t> raw_credential_id);
   ResponseData();
 
   // Moveable.
@@ -32,7 +33,7 @@
 
   ~ResponseData();
 
-  std::vector<uint8_t> raw_id_;
+  std::vector<uint8_t> raw_credential_id_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ResponseData);
diff --git a/device/fido/ctap_response_fuzzer_corpus/get_assertion_response_corpus b/device/fido/response_data_fuzzer_corpus/get_assertion_response_corpus
similarity index 100%
rename from device/fido/ctap_response_fuzzer_corpus/get_assertion_response_corpus
rename to device/fido/response_data_fuzzer_corpus/get_assertion_response_corpus
Binary files differ
diff --git a/device/fido/ctap_response_fuzzer_corpus/make_credential_response_corpus b/device/fido/response_data_fuzzer_corpus/make_credential_response_corpus
similarity index 100%
rename from device/fido/ctap_response_fuzzer_corpus/make_credential_response_corpus
rename to device/fido/response_data_fuzzer_corpus/make_credential_response_corpus
Binary files differ
diff --git a/device/fido/scoped_virtual_fido_device.cc b/device/fido/scoped_virtual_fido_device.cc
new file mode 100644
index 0000000..da7cc033
--- /dev/null
+++ b/device/fido/scoped_virtual_fido_device.cc
@@ -0,0 +1,60 @@
+// Copyright 2018 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 "device/fido/scoped_virtual_fido_device.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/location.h"
+#include "base/macros.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+
+namespace device {
+namespace test {
+
+// A FidoDiscovery that always vends a single |VirtualFidoDevice|.
+class VirtualFidoDeviceDiscovery : public FidoDiscovery {
+ public:
+  explicit VirtualFidoDeviceDiscovery(
+      scoped_refptr<VirtualFidoDevice::State> state)
+      : FidoDiscovery(U2fTransportProtocol::kUsbHumanInterfaceDevice),
+        state_(std::move(state)) {}
+  ~VirtualFidoDeviceDiscovery() override = default;
+
+ protected:
+  void StartInternal() override {
+    auto device = std::make_unique<VirtualFidoDevice>(state_);
+    AddDevice(std::move(device));
+    base::SequencedTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE,
+        base::BindOnce(&VirtualFidoDeviceDiscovery::NotifyDiscoveryStarted,
+                       base::Unretained(this), true /* success */));
+  }
+
+ private:
+  scoped_refptr<VirtualFidoDevice::State> state_;
+  DISALLOW_COPY_AND_ASSIGN(VirtualFidoDeviceDiscovery);
+};
+
+ScopedVirtualFidoDevice::ScopedVirtualFidoDevice()
+    : state_(new VirtualFidoDevice::State) {}
+ScopedVirtualFidoDevice::~ScopedVirtualFidoDevice() = default;
+
+VirtualFidoDevice::State* ScopedVirtualFidoDevice::mutable_state() {
+  return state_.get();
+}
+
+std::unique_ptr<FidoDiscovery> ScopedVirtualFidoDevice::CreateFidoDiscovery(
+    U2fTransportProtocol transport,
+    ::service_manager::Connector* connector) {
+  if (transport != U2fTransportProtocol::kUsbHumanInterfaceDevice) {
+    return nullptr;
+  }
+  return std::make_unique<VirtualFidoDeviceDiscovery>(state_);
+}
+
+}  // namespace test
+}  // namespace device
diff --git a/device/fido/scoped_virtual_fido_device.h b/device/fido/scoped_virtual_fido_device.h
new file mode 100644
index 0000000..92fe760
--- /dev/null
+++ b/device/fido/scoped_virtual_fido_device.h
@@ -0,0 +1,41 @@
+// Copyright 2018 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 DEVICE_FIDO_SCOPED_VIRTUAL_FIDO_DEVICE_H_
+#define DEVICE_FIDO_SCOPED_VIRTUAL_FIDO_DEVICE_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "device/fido/fido_discovery.h"
+#include "device/fido/virtual_fido_device.h"
+
+namespace device {
+namespace test {
+
+// Creating a |ScopedVirtualFidoDevice| causes normal device discovery to be
+// hijacked while the object is in scope. Instead a |VirtualFidoDevice| will
+// always be discovered. This object pretends to be a HID device.
+class ScopedVirtualFidoDevice
+    : public ::device::internal::ScopedFidoDiscoveryFactory {
+ public:
+  ScopedVirtualFidoDevice();
+  ~ScopedVirtualFidoDevice() override;
+
+  VirtualFidoDevice::State* mutable_state();
+
+ protected:
+  std::unique_ptr<FidoDiscovery> CreateFidoDiscovery(
+      U2fTransportProtocol transport,
+      ::service_manager::Connector* connector) override;
+
+ private:
+  scoped_refptr<VirtualFidoDevice::State> state_;
+  DISALLOW_COPY_AND_ASSIGN(ScopedVirtualFidoDevice);
+};
+
+}  // namespace test
+}  // namespace device
+
+#endif  // DEVICE_FIDO_SCOPED_VIRTUAL_FIDO_DEVICE_H_
diff --git a/device/fido/scoped_virtual_u2f_device.cc b/device/fido/scoped_virtual_u2f_device.cc
deleted file mode 100644
index 862ec10..0000000
--- a/device/fido/scoped_virtual_u2f_device.cc
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2018 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 "device/fido/scoped_virtual_u2f_device.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/location.h"
-#include "base/macros.h"
-#include "base/threading/sequenced_task_runner_handle.h"
-
-namespace device {
-namespace test {
-
-// A FidoDiscovery that always vends a single |VirtualU2fDevice|.
-class VirtualU2fDeviceDiscovery : public FidoDiscovery {
- public:
-  explicit VirtualU2fDeviceDiscovery(
-      scoped_refptr<VirtualU2fDevice::State> state)
-      : FidoDiscovery(U2fTransportProtocol::kUsbHumanInterfaceDevice),
-        state_(std::move(state)) {}
-  ~VirtualU2fDeviceDiscovery() override = default;
-
- protected:
-  void StartInternal() override {
-    auto device = std::make_unique<VirtualU2fDevice>(state_);
-    AddDevice(std::move(device));
-    base::SequencedTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE,
-        base::BindOnce(&VirtualU2fDeviceDiscovery::NotifyDiscoveryStarted,
-                       base::Unretained(this), true /* success */));
-  }
-
- private:
-  scoped_refptr<VirtualU2fDevice::State> state_;
-  DISALLOW_COPY_AND_ASSIGN(VirtualU2fDeviceDiscovery);
-};
-
-ScopedVirtualU2fDevice::ScopedVirtualU2fDevice()
-    : state_(new VirtualU2fDevice::State) {}
-ScopedVirtualU2fDevice::~ScopedVirtualU2fDevice() = default;
-
-VirtualU2fDevice::State* ScopedVirtualU2fDevice::mutable_state() {
-  return state_.get();
-}
-
-std::unique_ptr<FidoDiscovery> ScopedVirtualU2fDevice::CreateFidoDiscovery(
-    U2fTransportProtocol transport,
-    ::service_manager::Connector* connector) {
-  if (transport != U2fTransportProtocol::kUsbHumanInterfaceDevice) {
-    return nullptr;
-  }
-  return std::make_unique<VirtualU2fDeviceDiscovery>(state_);
-}
-
-}  // namespace test
-}  // namespace device
diff --git a/device/fido/scoped_virtual_u2f_device.h b/device/fido/scoped_virtual_u2f_device.h
deleted file mode 100644
index 44ab07a..0000000
--- a/device/fido/scoped_virtual_u2f_device.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2018 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 DEVICE_FIDO_SCOPED_VIRTUAL_U2F_DEVICE_H_
-#define DEVICE_FIDO_SCOPED_VIRTUAL_U2F_DEVICE_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "device/fido/fido_discovery.h"
-#include "device/fido/virtual_u2f_device.h"
-
-namespace device {
-namespace test {
-
-// Creating a |ScopedVirtualU2fDevice| causes normal device discovery to be
-// hijacked while the object is in scope. Instead a |VirtualU2fDevice| will
-// always be discovered. This object pretends to be a HID device.
-class ScopedVirtualU2fDevice
-    : public ::device::internal::ScopedFidoDiscoveryFactory {
- public:
-  ScopedVirtualU2fDevice();
-  ~ScopedVirtualU2fDevice() override;
-
-  VirtualU2fDevice::State* mutable_state();
-
- protected:
-  std::unique_ptr<FidoDiscovery> CreateFidoDiscovery(
-      U2fTransportProtocol transport,
-      ::service_manager::Connector* connector) override;
-
- private:
-  scoped_refptr<VirtualU2fDevice::State> state_;
-  DISALLOW_COPY_AND_ASSIGN(ScopedVirtualU2fDevice);
-};
-
-}  // namespace test
-}  // namespace device
-
-#endif  // DEVICE_FIDO_SCOPED_VIRTUAL_U2F_DEVICE_H_
diff --git a/device/fido/sign_response_data.cc b/device/fido/sign_response_data.cc
deleted file mode 100644
index 7e59240..0000000
--- a/device/fido/sign_response_data.cc
+++ /dev/null
@@ -1,71 +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 "device/fido/sign_response_data.h"
-
-#include <utility>
-
-#include "base/optional.h"
-#include "device/fido/u2f_parsing_utils.h"
-
-namespace device {
-
-constexpr size_t kFlagIndex = 0;
-constexpr size_t kFlagLength = 1;
-constexpr size_t kCounterIndex = 1;
-constexpr size_t kCounterLength = 4;
-constexpr size_t kSignatureIndex = 5;
-
-// static
-base::Optional<SignResponseData> SignResponseData::CreateFromU2fSignResponse(
-    const std::vector<uint8_t>& relying_party_id_hash,
-    const std::vector<uint8_t>& u2f_data,
-    const std::vector<uint8_t>& key_handle) {
-  if (key_handle.empty())
-    return base::nullopt;
-
-  std::vector<uint8_t> flags =
-      u2f_parsing_utils::Extract(u2f_data, kFlagIndex, kFlagLength);
-  if (flags.empty())
-    return base::nullopt;
-
-  // Extract the 4-byte counter following the flag byte.
-  std::vector<uint8_t> counter =
-      u2f_parsing_utils::Extract(u2f_data, kCounterIndex, kCounterLength);
-  if (counter.empty())
-    return base::nullopt;
-
-  // Construct the authenticator data.
-  AuthenticatorData authenticator_data(relying_party_id_hash, flags[0],
-                                       std::move(counter), base::nullopt);
-
-  // Extract the signature from the remainder of the U2fResponse bytes.
-  std::vector<uint8_t> signature = u2f_parsing_utils::Extract(
-      u2f_data, kSignatureIndex, u2f_data.size() - kSignatureIndex);
-  if (signature.empty())
-    return base::nullopt;
-
-  return SignResponseData(std::move(key_handle), std::move(authenticator_data),
-                          std::move(signature));
-}
-
-SignResponseData::SignResponseData(std::vector<uint8_t> credential_id,
-                                   AuthenticatorData authenticator_data,
-                                   std::vector<uint8_t> signature)
-    : ResponseData(std::move(credential_id)),
-      authenticator_data_(std::move(authenticator_data)),
-      signature_(std::move(signature)) {}
-
-SignResponseData::SignResponseData(SignResponseData&& other) = default;
-
-SignResponseData& SignResponseData::operator=(SignResponseData&& other) =
-    default;
-
-SignResponseData::~SignResponseData() = default;
-
-std::vector<uint8_t> SignResponseData::GetAuthenticatorDataBytes() const {
-  return authenticator_data_.SerializeToByteArray();
-}
-
-}  // namespace device
diff --git a/device/fido/sign_response_data.h b/device/fido/sign_response_data.h
deleted file mode 100644
index c296e911..0000000
--- a/device/fido/sign_response_data.h
+++ /dev/null
@@ -1,50 +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 DEVICE_FIDO_SIGN_RESPONSE_DATA_H_
-#define DEVICE_FIDO_SIGN_RESPONSE_DATA_H_
-
-#include <stdint.h>
-#include <string>
-#include <vector>
-
-#include "base/component_export.h"
-#include "base/macros.h"
-#include "device/fido/authenticator_data.h"
-#include "device/fido/response_data.h"
-
-namespace device {
-
-// Corresponds to a CTAP AuthenticatorGetAssertion response.
-// See mapping from a U2F response to a CTAP response
-// at https://goo.gl/eZTacx.
-class COMPONENT_EXPORT(DEVICE_FIDO) SignResponseData : public ResponseData {
- public:
-  static base::Optional<SignResponseData> CreateFromU2fSignResponse(
-      const std::vector<uint8_t>& relying_party_id_hash,
-      const std::vector<uint8_t>& u2f_data,
-      const std::vector<uint8_t>& key_handle);
-
-  SignResponseData(std::vector<uint8_t> credential_id,
-                   AuthenticatorData authenticator_data,
-                   std::vector<uint8_t> signature);
-
-  SignResponseData(SignResponseData&& other);
-  SignResponseData& operator=(SignResponseData&& other);
-
-  ~SignResponseData();
-
-  std::vector<uint8_t> GetAuthenticatorDataBytes() const;
-  const std::vector<uint8_t>& signature() const { return signature_; }
-
- private:
-  AuthenticatorData authenticator_data_;
-  std::vector<uint8_t> signature_;
-
-  DISALLOW_COPY_AND_ASSIGN(SignResponseData);
-};
-
-}  // namespace device
-
-#endif  // DEVICE_FIDO_SIGN_RESPONSE_DATA_H_
diff --git a/device/fido/sign_response_data_fuzzer.cc b/device/fido/sign_response_data_fuzzer.cc
deleted file mode 100644
index 711ace8f..0000000
--- a/device/fido/sign_response_data_fuzzer.cc
+++ /dev/null
@@ -1,19 +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 <stddef.h>
-#include <stdint.h>
-#include <vector>
-
-#include "base/optional.h"
-#include "device/fido/sign_response_data.h"
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  std::vector<uint8_t> u2f_response_data(data, data + size);
-  std::vector<uint8_t> key_handle(data, data + size);
-  std::vector<uint8_t> relying_party_id_hash(32);
-  auto response = device::SignResponseData::CreateFromU2fSignResponse(
-      relying_party_id_hash, u2f_response_data, key_handle);
-  return 0;
-}
diff --git a/device/fido/u2f_register.cc b/device/fido/u2f_register.cc
index e743fbf..21cfadb0 100644
--- a/device/fido/u2f_register.cc
+++ b/device/fido/u2f_register.cc
@@ -9,7 +9,7 @@
 #include "base/stl_util.h"
 #include "components/apdu/apdu_command.h"
 #include "components/apdu/apdu_response.h"
-#include "device/fido/register_response_data.h"
+#include "device/fido/authenticator_make_credential_response.h"
 #include "services/service_manager/public/cpp/connector.h"
 
 namespace device {
@@ -142,19 +142,20 @@
       state_ = State::COMPLETE;
       if (is_duplicate_registration) {
         std::move(completion_callback_)
-            .Run(U2fReturnCode::CONDITIONS_NOT_SATISFIED, base::nullopt);
+            .Run(FidoReturnCode::kConditionsNotSatisfied, base::nullopt);
         break;
       }
-      auto response = RegisterResponseData::CreateFromU2fRegisterResponse(
-          application_parameter_, apdu_response->data());
+      auto response =
+          AuthenticatorMakeCredentialResponse::CreateFromU2fRegisterResponse(
+              application_parameter_, apdu_response->data());
       if (!response) {
         // The response data was corrupted / didn't parse properly.
         std::move(completion_callback_)
-            .Run(U2fReturnCode::FAILURE, base::nullopt);
+            .Run(FidoReturnCode::kFailure, base::nullopt);
         break;
       }
       std::move(completion_callback_)
-          .Run(U2fReturnCode::SUCCESS, std::move(response));
+          .Run(FidoReturnCode::kSuccess, std::move(response));
       break;
     }
     case apdu::ApduResponse::Status::SW_CONDITIONS_NOT_SATISFIED:
diff --git a/device/fido/u2f_register.h b/device/fido/u2f_register.h
index f04a94a..0b26efe 100644
--- a/device/fido/u2f_register.h
+++ b/device/fido/u2f_register.h
@@ -14,8 +14,9 @@
 #include "base/containers/flat_set.h"
 #include "base/macros.h"
 #include "base/optional.h"
+#include "device/fido/authenticator_make_credential_response.h"
+#include "device/fido/fido_constants.h"
 #include "device/fido/u2f_request.h"
-#include "device/fido/u2f_return_code.h"
 #include "device/fido/u2f_transport_protocol.h"
 
 namespace service_manager {
@@ -24,13 +25,11 @@
 
 namespace device {
 
-class RegisterResponseData;
-
 class COMPONENT_EXPORT(DEVICE_FIDO) U2fRegister : public U2fRequest {
  public:
   using RegisterResponseCallback = base::OnceCallback<void(
-      U2fReturnCode status_code,
-      base::Optional<RegisterResponseData> response_data)>;
+      FidoReturnCode status_code,
+      base::Optional<AuthenticatorMakeCredentialResponse> response_data)>;
 
   static std::unique_ptr<U2fRequest> TryRegistration(
       service_manager::Connector* connector,
diff --git a/device/fido/u2f_register_unittest.cc b/device/fido/u2f_register_unittest.cc
index 63367139..716e4c6f 100644
--- a/device/fido/u2f_register_unittest.cc
+++ b/device/fido/u2f_register_unittest.cc
@@ -13,16 +13,16 @@
 #include "device/fido/attestation_object.h"
 #include "device/fido/attested_credential_data.h"
 #include "device/fido/authenticator_data.h"
+#include "device/fido/authenticator_make_credential_response.h"
 #include "device/fido/ec_public_key.h"
 #include "device/fido/fake_fido_discovery.h"
 #include "device/fido/fido_attestation_statement.h"
 #include "device/fido/fido_constants.h"
+#include "device/fido/fido_response_test_data.h"
 #include "device/fido/mock_fido_device.h"
-#include "device/fido/register_response_data.h"
 #include "device/fido/test_callback_receiver.h"
 #include "device/fido/u2f_parsing_utils.h"
-#include "device/fido/u2f_response_test_data.h"
-#include "device/fido/virtual_u2f_device.h"
+#include "device/fido/virtual_fido_device.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -289,8 +289,8 @@
 }
 
 using TestRegisterCallback = ::device::test::StatusAndValueCallbackReceiver<
-    U2fReturnCode,
-    base::Optional<RegisterResponseData>>;
+    FidoReturnCode,
+    base::Optional<AuthenticatorMakeCredentialResponse>>;
 
 }  // namespace
 
@@ -438,10 +438,10 @@
   discovery()->AddDevice(std::move(device));
 
   register_callback_receiver().WaitForCallback();
-  EXPECT_EQ(U2fReturnCode::SUCCESS, register_callback_receiver().status());
+  EXPECT_EQ(FidoReturnCode::kSuccess, register_callback_receiver().status());
   ASSERT_TRUE(register_callback_receiver().value());
   EXPECT_EQ(GetTestCredentialRawIdBytes(),
-            register_callback_receiver().value()->raw_id());
+            register_callback_receiver().value()->raw_credential_id());
 }
 
 TEST_F(U2fRegisterTest, TestRegisterSuccessWithFake) {
@@ -449,15 +449,16 @@
   request->Start();
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
-  auto device = std::make_unique<VirtualU2fDevice>();
+  auto device = std::make_unique<VirtualFidoDevice>();
   discovery()->AddDevice(std::move(device));
 
   register_callback_receiver().WaitForCallback();
-  EXPECT_EQ(U2fReturnCode::SUCCESS, register_callback_receiver().status());
+  EXPECT_EQ(FidoReturnCode::kSuccess, register_callback_receiver().status());
 
   // We don't verify the response from the fake, but do a quick sanity check.
   ASSERT_TRUE(register_callback_receiver().value());
-  EXPECT_EQ(32ul, register_callback_receiver().value()->raw_id().size());
+  EXPECT_EQ(32ul,
+            register_callback_receiver().value()->raw_credential_id().size());
 }
 
 TEST_F(U2fRegisterTest, TestDelayedSuccess) {
@@ -477,10 +478,10 @@
   discovery()->AddDevice(std::move(device));
 
   register_callback_receiver().WaitForCallback();
-  EXPECT_EQ(U2fReturnCode::SUCCESS, register_callback_receiver().status());
+  EXPECT_EQ(FidoReturnCode::kSuccess, register_callback_receiver().status());
   ASSERT_TRUE(register_callback_receiver().value());
   EXPECT_EQ(GetTestCredentialRawIdBytes(),
-            register_callback_receiver().value()->raw_id());
+            register_callback_receiver().value()->raw_credential_id());
 }
 
 TEST_F(U2fRegisterTest, TestMultipleDevices) {
@@ -508,10 +509,10 @@
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
   register_callback_receiver().WaitForCallback();
-  EXPECT_EQ(U2fReturnCode::SUCCESS, register_callback_receiver().status());
+  EXPECT_EQ(FidoReturnCode::kSuccess, register_callback_receiver().status());
   ASSERT_TRUE(register_callback_receiver().value());
   EXPECT_EQ(GetTestCredentialRawIdBytes(),
-            register_callback_receiver().value()->raw_id());
+            register_callback_receiver().value()->raw_credential_id());
 }
 
 // Tests a scenario where a single device is connected and registration call
@@ -547,10 +548,10 @@
   discovery()->AddDevice(std::move(device));
 
   register_callback_receiver().WaitForCallback();
-  EXPECT_EQ(U2fReturnCode::SUCCESS, register_callback_receiver().status());
   ASSERT_TRUE(register_callback_receiver().value());
+  EXPECT_EQ(FidoReturnCode::kSuccess, register_callback_receiver().status());
   EXPECT_EQ(GetTestCredentialRawIdBytes(),
-            register_callback_receiver().value()->raw_id());
+            register_callback_receiver().value()->raw_credential_id());
 }
 
 // Tests a scenario where two devices are connected and registration call is
@@ -600,10 +601,10 @@
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
   register_callback_receiver().WaitForCallback();
-  EXPECT_EQ(U2fReturnCode::SUCCESS, register_callback_receiver().status());
+  EXPECT_EQ(FidoReturnCode::kSuccess, register_callback_receiver().status());
   ASSERT_TRUE(register_callback_receiver().value());
   EXPECT_EQ(GetTestCredentialRawIdBytes(),
-            register_callback_receiver().value()->raw_id());
+            register_callback_receiver().value()->raw_credential_id());
 }
 
 // Tests a scenario where single device is connected and registration is called
@@ -641,7 +642,7 @@
   discovery()->AddDevice(std::move(device));
 
   register_callback_receiver().WaitForCallback();
-  EXPECT_EQ(U2fReturnCode::CONDITIONS_NOT_SATISFIED,
+  EXPECT_EQ(FidoReturnCode::kConditionsNotSatisfied,
             register_callback_receiver().status());
   EXPECT_FALSE(register_callback_receiver().value());
 }
@@ -693,7 +694,7 @@
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
   register_callback_receiver().WaitForCallback();
-  EXPECT_EQ(U2fReturnCode::CONDITIONS_NOT_SATISFIED,
+  EXPECT_EQ(FidoReturnCode::kConditionsNotSatisfied,
             register_callback_receiver().status());
   EXPECT_FALSE(register_callback_receiver().value());
 }
@@ -788,18 +789,18 @@
 
 // Test that a U2F register response is properly parsed.
 TEST_F(U2fRegisterTest, TestRegisterResponseData) {
-  base::Optional<RegisterResponseData> response =
-      RegisterResponseData::CreateFromU2fRegisterResponse(
+  base::Optional<AuthenticatorMakeCredentialResponse> response =
+      AuthenticatorMakeCredentialResponse::CreateFromU2fRegisterResponse(
           std::vector<uint8_t>(kTestRelyingPartyIdSHA256,
                                kTestRelyingPartyIdSHA256 + 32),
           GetTestRegisterResponse());
-  EXPECT_EQ(GetTestCredentialRawIdBytes(), response->raw_id());
+  EXPECT_EQ(GetTestCredentialRawIdBytes(), response->raw_credential_id());
   EXPECT_EQ(GetTestAttestationObjectBytes(),
             response->GetCBOREncodedAttestationObject());
 }
 
 MATCHER_P(IndicatesIndividualAttestation, expected, "") {
-  return arg.size() >= 2 && ((arg[2] & 0x80) == 0x80) == expected;
+  return arg.size() > 2 && ((arg[2] & 0x80) == 0x80) == expected;
 }
 
 TEST_F(U2fRegisterTest, TestIndividualAttestation) {
@@ -830,9 +831,9 @@
     discovery()->AddDevice(std::move(device));
 
     cb.WaitForCallback();
-    EXPECT_EQ(U2fReturnCode::SUCCESS, cb.status());
+    EXPECT_EQ(FidoReturnCode::kSuccess, cb.status());
     ASSERT_TRUE(cb.value());
-    EXPECT_EQ(GetTestCredentialRawIdBytes(), cb.value()->raw_id());
+    EXPECT_EQ(GetTestCredentialRawIdBytes(), cb.value()->raw_credential_id());
   }
 }
 
diff --git a/device/fido/u2f_request.cc b/device/fido/u2f_request.cc
index 9c16ccf..65e8c77 100644
--- a/device/fido/u2f_request.cc
+++ b/device/fido/u2f_request.cc
@@ -31,7 +31,7 @@
   for (const auto transport : transports) {
     auto discovery = FidoDiscovery::Create(transport, connector);
     if (discovery == nullptr) {
-      // This can occur in tests when a ScopedVirtualU2fDevice is in effect and
+      // This can occur in tests when a ScopedVirtualFidoDevice is in effect and
       // non-HID transports are configured.
       continue;
     }
diff --git a/device/fido/u2f_response_test_data.h b/device/fido/u2f_response_test_data.h
deleted file mode 100644
index 5be7674..0000000
--- a/device/fido/u2f_response_test_data.h
+++ /dev/null
@@ -1,109 +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.
-
-// This file contains common data used to test U2F register and sign responses.
-
-#ifndef DEVICE_FIDO_U2F_RESPONSE_TEST_DATA_H_
-#define DEVICE_FIDO_U2F_RESPONSE_TEST_DATA_H_
-
-namespace device {
-
-namespace test_data {
-
-constexpr uint8_t kTestCredentialRawIdBytes[] = {
-    0x89, 0xAF, 0xB5, 0x24, 0x91, 0x1C, 0x40, 0x2B, 0x7F, 0x74, 0x59,
-    0xC9, 0xF2, 0x21, 0xAF, 0xE6, 0xE5, 0x56, 0x65, 0x85, 0x04, 0xE8,
-    0x5B, 0x49, 0x4D, 0x07, 0x55, 0x55, 0xF4, 0x6A, 0xBC, 0x44, 0x7B,
-    0x15, 0xFC, 0x62, 0x61, 0x90, 0xA5, 0xFE, 0xEB, 0xE5, 0x9F, 0x5E,
-    0xDC, 0x75, 0x32, 0x98, 0x6F, 0x44, 0x69, 0xD7, 0xF6, 0x13, 0xEB,
-    0xAA, 0xEA, 0x33, 0xFB, 0xD5, 0x8E, 0xBF, 0xC6, 0x09};
-
-// U2F response blob produced by a U2F registration request. This example
-// data uses testClientDataJson and 'created' a key with testCredentialRawId
-// as its key handle and with the above x- and y- coordinates.
-constexpr uint8_t kTestU2fRegisterResponse[] = {
-    0x05, 0x04, 0xF8, 0x68, 0xCE, 0x38, 0x69, 0x60, 0x52, 0x24, 0xCE, 0x10,
-    0x59, 0xC0, 0x04, 0x7E, 0xF0, 0x1B, 0x83, 0x0F, 0x2A, 0xD9, 0x3B, 0xE2,
-    0x7A, 0x32, 0x11, 0xF4, 0x4E, 0x89, 0x45, 0x60, 0xE6, 0x95, 0x4E, 0x11,
-    0x53, 0x8C, 0xAB, 0xA2, 0xDF, 0x1C, 0xC1, 0xA6, 0xF2, 0x50, 0xED, 0x9F,
-    0x0C, 0x8B, 0x28, 0xB3, 0x9D, 0xA4, 0x45, 0x39, 0xDF, 0xAB, 0xD4, 0x6B,
-    0x58, 0x9C, 0xD0, 0xE2, 0x02, 0xE5, 0x40, 0x89, 0xAF, 0xB5, 0x24, 0x91,
-    0x1C, 0x40, 0x2B, 0x7F, 0x74, 0x59, 0xC9, 0xF2, 0x21, 0xAF, 0xE6, 0xE5,
-    0x56, 0x65, 0x85, 0x04, 0xE8, 0x5B, 0x49, 0x4D, 0x07, 0x55, 0x55, 0xF4,
-    0x6A, 0xBC, 0x44, 0x7B, 0x15, 0xFC, 0x62, 0x61, 0x90, 0xA5, 0xFE, 0xEB,
-    0xE5, 0x9F, 0x5E, 0xDC, 0x75, 0x32, 0x98, 0x6F, 0x44, 0x69, 0xD7, 0xF6,
-    0x13, 0xEB, 0xAA, 0xEA, 0x33, 0xFB, 0xD5, 0x8E, 0xBF, 0xC6, 0x09, 0x30,
-    0x82, 0x02, 0x4A, 0x30, 0x82, 0x01, 0x32, 0xA0, 0x03, 0x02, 0x01, 0x02,
-    0x02, 0x04, 0x04, 0x6C, 0x88, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86,
-    0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x2E, 0x31,
-    0x2C, 0x30, 0x2A, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x23, 0x59, 0x75,
-    0x62, 0x69, 0x63, 0x6F, 0x20, 0x55, 0x32, 0x46, 0x20, 0x52, 0x6F, 0x6F,
-    0x74, 0x20, 0x43, 0x41, 0x20, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6C, 0x20,
-    0x34, 0x35, 0x37, 0x32, 0x30, 0x30, 0x36, 0x33, 0x31, 0x30, 0x20, 0x17,
-    0x0D, 0x31, 0x34, 0x30, 0x38, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
-    0x30, 0x5A, 0x18, 0x0F, 0x32, 0x30, 0x35, 0x30, 0x30, 0x39, 0x30, 0x34,
-    0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x30, 0x2C, 0x31, 0x2A, 0x30,
-    0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x21, 0x59, 0x75, 0x62, 0x69,
-    0x63, 0x6F, 0x20, 0x55, 0x32, 0x46, 0x20, 0x45, 0x45, 0x20, 0x53, 0x65,
-    0x72, 0x69, 0x61, 0x6C, 0x20, 0x32, 0x34, 0x39, 0x31, 0x38, 0x32, 0x33,
-    0x32, 0x34, 0x37, 0x37, 0x30, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A,
-    0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
-    0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x3C, 0xCA, 0xB9, 0x2C,
-    0xCB, 0x97, 0x28, 0x7E, 0xE8, 0xE6, 0x39, 0x43, 0x7E, 0x21, 0xFC, 0xD6,
-    0xB6, 0xF1, 0x65, 0xB2, 0xD5, 0xA3, 0xF3, 0xDB, 0x13, 0x1D, 0x31, 0xC1,
-    0x6B, 0x74, 0x2B, 0xB4, 0x76, 0xD8, 0xD1, 0xE9, 0x90, 0x80, 0xEB, 0x54,
-    0x6C, 0x9B, 0xBD, 0xF5, 0x56, 0xE6, 0x21, 0x0F, 0xD4, 0x27, 0x85, 0x89,
-    0x9E, 0x78, 0xCC, 0x58, 0x9E, 0xBE, 0x31, 0x0F, 0x6C, 0xDB, 0x9F, 0xF4,
-    0xA3, 0x3B, 0x30, 0x39, 0x30, 0x22, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04,
-    0x01, 0x82, 0xC4, 0x0A, 0x02, 0x04, 0x15, 0x31, 0x2E, 0x33, 0x2E, 0x36,
-    0x2E, 0x31, 0x2E, 0x34, 0x2E, 0x31, 0x2E, 0x34, 0x31, 0x34, 0x38, 0x32,
-    0x2E, 0x31, 0x2E, 0x32, 0x30, 0x13, 0x06, 0x0B, 0x2B, 0x06, 0x01, 0x04,
-    0x01, 0x82, 0xE5, 0x1C, 0x02, 0x01, 0x01, 0x04, 0x04, 0x03, 0x02, 0x04,
-    0x30, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
-    0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x9F, 0x9B, 0x05,
-    0x22, 0x48, 0xBC, 0x4C, 0xF4, 0x2C, 0xC5, 0x99, 0x1F, 0xCA, 0xAB, 0xAC,
-    0x9B, 0x65, 0x1B, 0xBE, 0x5B, 0xDC, 0xDC, 0x8E, 0xF0, 0xAD, 0x2C, 0x1C,
-    0x1F, 0xFB, 0x36, 0xD1, 0x87, 0x15, 0xD4, 0x2E, 0x78, 0xB2, 0x49, 0x22,
-    0x4F, 0x92, 0xC7, 0xE6, 0xE7, 0xA0, 0x5C, 0x49, 0xF0, 0xE7, 0xE4, 0xC8,
-    0x81, 0xBF, 0x2E, 0x94, 0xF4, 0x5E, 0x4A, 0x21, 0x83, 0x3D, 0x74, 0x56,
-    0x85, 0x1D, 0x0F, 0x6C, 0x14, 0x5A, 0x29, 0x54, 0x0C, 0x87, 0x4F, 0x30,
-    0x92, 0xC9, 0x34, 0xB4, 0x3D, 0x22, 0x2B, 0x89, 0x62, 0xC0, 0xF4, 0x10,
-    0xCE, 0xF1, 0xDB, 0x75, 0x89, 0x2A, 0xF1, 0x16, 0xB4, 0x4A, 0x96, 0xF5,
-    0xD3, 0x5A, 0xDE, 0xA3, 0x82, 0x2F, 0xC7, 0x14, 0x6F, 0x60, 0x04, 0x38,
-    0x5B, 0xCB, 0x69, 0xB6, 0x5C, 0x99, 0xE7, 0xEB, 0x69, 0x19, 0x78, 0x67,
-    0x03, 0xC0, 0xD8, 0xCD, 0x41, 0xE8, 0xF7, 0x5C, 0xCA, 0x44, 0xAA, 0x8A,
-    0xB7, 0x25, 0xAD, 0x8E, 0x79, 0x9F, 0xF3, 0xA8, 0x69, 0x6A, 0x6F, 0x1B,
-    0x26, 0x56, 0xE6, 0x31, 0xB1, 0xE4, 0x01, 0x83, 0xC0, 0x8F, 0xDA, 0x53,
-    0xFA, 0x4A, 0x8F, 0x85, 0xA0, 0x56, 0x93, 0x94, 0x4A, 0xE1, 0x79, 0xA1,
-    0x33, 0x9D, 0x00, 0x2D, 0x15, 0xCA, 0xBD, 0x81, 0x00, 0x90, 0xEC, 0x72,
-    0x2E, 0xF5, 0xDE, 0xF9, 0x96, 0x5A, 0x37, 0x1D, 0x41, 0x5D, 0x62, 0x4B,
-    0x68, 0xA2, 0x70, 0x7C, 0xAD, 0x97, 0xBC, 0xDD, 0x17, 0x85, 0xAF, 0x97,
-    0xE2, 0x58, 0xF3, 0x3D, 0xF5, 0x6A, 0x03, 0x1A, 0xA0, 0x35, 0x6D, 0x8E,
-    0x8D, 0x5E, 0xBC, 0xAD, 0xC7, 0x4E, 0x07, 0x16, 0x36, 0xC6, 0xB1, 0x10,
-    0xAC, 0xE5, 0xCC, 0x9B, 0x90, 0xDF, 0xEA, 0xCA, 0xE6, 0x40, 0xFF, 0x1B,
-    0xB0, 0xF1, 0xFE, 0x5D, 0xB4, 0xEF, 0xF7, 0xA9, 0x5F, 0x06, 0x07, 0x33,
-    0xF5, 0x30, 0x44, 0x02, 0x20, 0x08, 0xC3, 0xF8, 0xDB, 0x6E, 0x29, 0xFD,
-    0x8B, 0x14, 0xD9, 0xDE, 0x1B, 0xD9, 0x8E, 0x84, 0x07, 0x2C, 0xB8, 0x13,
-    0x38, 0x59, 0x89, 0xAA, 0x2C, 0xA2, 0x89, 0x39, 0x5E, 0x00, 0x09, 0xB8,
-    0xB7, 0x02, 0x20, 0x26, 0x07, 0xB4, 0xF9, 0xAD, 0x05, 0xDE, 0x26, 0xF5,
-    0x6F, 0x48, 0xB8, 0x25, 0x69, 0xEA, 0xD8, 0x23, 0x1A, 0x5A, 0x6C, 0x3A,
-    0x14, 0x48, 0xDE, 0xAA, 0xAF, 0x15, 0xC0, 0xEF, 0x29, 0x63, 0x1A};
-
-// U2F response blob produced by a U2F sign request.
-constexpr uint8_t kTestU2fSignResponse[] = {
-    0x01, 0x00, 0x00, 0x00, 0x25, 0x30, 0x45, 0x02, 0x21, 0x00, 0xCA,
-    0xA5, 0x3E, 0x91, 0x0D, 0xB7, 0x5E, 0xDE, 0xAF, 0x72, 0xCF, 0x9F,
-    0x6F, 0x54, 0xE5, 0x20, 0x5B, 0xBB, 0xB9, 0x2F, 0x0B, 0x9F, 0x7D,
-    0xC6, 0xF8, 0xD4, 0x7B, 0x19, 0x70, 0xED, 0xFE, 0xBC, 0x02, 0x20,
-    0x06, 0x32, 0x83, 0x65, 0x26, 0x4E, 0xBE, 0xFE, 0x35, 0x3C, 0x95,
-    0x91, 0xDF, 0xCE, 0x7D, 0x73, 0x15, 0x98, 0x64, 0xDF, 0xEA, 0xB7,
-    0x87, 0xF1, 0x5D, 0xF8, 0xA5, 0x97, 0xD0, 0x85, 0x0C, 0xA2};
-
-// A sample corrupted response to a U2F sign request.
-constexpr uint8_t kTestCorruptedU2fSignResponse[] = {0x01, 0x00, 0x00, 0x00};
-}  // namespace test_data
-
-}  // namespace device
-
-#endif  // DEVICE_FIDO_U2F_RESPONSE_TEST_DATA_H_
diff --git a/device/fido/u2f_return_code.h b/device/fido/u2f_return_code.h
deleted file mode 100644
index c6ffd2d..0000000
--- a/device/fido/u2f_return_code.h
+++ /dev/null
@@ -1,19 +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 DEVICE_FIDO_U2F_RETURN_CODE_H_
-#define DEVICE_FIDO_U2F_RETURN_CODE_H_
-
-namespace device {
-
-enum class U2fReturnCode : uint8_t {
-  SUCCESS,
-  FAILURE,
-  INVALID_PARAMS,
-  CONDITIONS_NOT_SATISFIED,
-};
-
-}  // namespace device
-
-#endif  // DEVICE_FIDO_U2F_RETURN_CODE_H_
diff --git a/device/fido/u2f_sign.cc b/device/fido/u2f_sign.cc
index c4d5f298..e2190691 100644
--- a/device/fido/u2f_sign.cc
+++ b/device/fido/u2f_sign.cc
@@ -100,20 +100,21 @@
       if (it == registered_keys_.cend()) {
         // This was a response to a fake enrollment. Return an empty key handle.
         std::move(completion_callback_)
-            .Run(U2fReturnCode::CONDITIONS_NOT_SATISFIED, base::nullopt);
+            .Run(FidoReturnCode::kConditionsNotSatisfied, base::nullopt);
       } else {
         const std::vector<uint8_t>* const application_parameter_used =
             application_parameter_type == ApplicationParameterType::kPrimary
                 ? &application_parameter_
                 : &alt_application_parameter_.value();
-        auto sign_response = SignResponseData::CreateFromU2fSignResponse(
-            *application_parameter_used, std::move(response_data), *it);
+        auto sign_response =
+            AuthenticatorGetAssertionResponse::CreateFromU2fSignResponse(
+                *application_parameter_used, std::move(response_data), *it);
         if (!sign_response) {
           std::move(completion_callback_)
-              .Run(U2fReturnCode::FAILURE, base::nullopt);
+              .Run(FidoReturnCode::kFailure, base::nullopt);
         } else {
           std::move(completion_callback_)
-              .Run(U2fReturnCode::SUCCESS, std::move(sign_response));
+              .Run(FidoReturnCode::kSuccess, std::move(sign_response));
         }
       }
       break;
diff --git a/device/fido/u2f_sign.h b/device/fido/u2f_sign.h
index 9c6d21fe..5e76a3a 100644
--- a/device/fido/u2f_sign.h
+++ b/device/fido/u2f_sign.h
@@ -13,9 +13,9 @@
 #include "base/containers/flat_set.h"
 #include "base/macros.h"
 #include "base/optional.h"
-#include "device/fido/sign_response_data.h"
+#include "device/fido/authenticator_get_assertion_response.h"
+#include "device/fido/fido_constants.h"
 #include "device/fido/u2f_request.h"
-#include "device/fido/u2f_return_code.h"
 #include "device/fido/u2f_transport_protocol.h"
 
 namespace service_manager {
@@ -26,9 +26,9 @@
 
 class COMPONENT_EXPORT(DEVICE_FIDO) U2fSign : public U2fRequest {
  public:
-  using SignResponseCallback =
-      base::OnceCallback<void(U2fReturnCode status_code,
-                              base::Optional<SignResponseData> response_data)>;
+  using SignResponseCallback = base::OnceCallback<void(
+      FidoReturnCode status_code,
+      base::Optional<AuthenticatorGetAssertionResponse> response_data)>;
 
   static std::unique_ptr<U2fRequest> TrySign(
       service_manager::Connector* connector,
diff --git a/device/fido/u2f_sign_unittest.cc b/device/fido/u2f_sign_unittest.cc
index ec54a0e..eace420 100644
--- a/device/fido/u2f_sign_unittest.cc
+++ b/device/fido/u2f_sign_unittest.cc
@@ -11,12 +11,13 @@
 #include "crypto/ec_private_key.h"
 #include "crypto/sha2.h"
 #include "device/fido/authenticator_data.h"
+#include "device/fido/authenticator_get_assertion_response.h"
 #include "device/fido/fake_fido_discovery.h"
+#include "device/fido/fido_constants.h"
+#include "device/fido/fido_response_test_data.h"
 #include "device/fido/mock_fido_device.h"
-#include "device/fido/sign_response_data.h"
 #include "device/fido/test_callback_receiver.h"
-#include "device/fido/u2f_response_test_data.h"
-#include "device/fido/virtual_u2f_device.h"
+#include "device/fido/virtual_fido_device.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -109,8 +110,8 @@
 }
 
 using TestSignCallback = ::device::test::StatusAndValueCallbackReceiver<
-    U2fReturnCode,
-    base::Optional<SignResponseData>>;
+    FidoReturnCode,
+    base::Optional<AuthenticatorGetAssertionResponse>>;
 
 }  // namespace
 
@@ -234,14 +235,15 @@
   discovery()->AddDevice(std::move(device));
 
   sign_callback_receiver().WaitForCallback();
-  EXPECT_EQ(U2fReturnCode::SUCCESS, sign_callback_receiver().status());
+  EXPECT_EQ(FidoReturnCode::kSuccess, sign_callback_receiver().status());
 
   // Correct key was sent so a sign response is expected.
   EXPECT_EQ(GetTestAssertionSignature(),
             sign_callback_receiver().value()->signature());
 
   // Verify that we get the key handle used for signing.
-  EXPECT_EQ(signing_key_handle, sign_callback_receiver().value()->raw_id());
+  EXPECT_EQ(signing_key_handle,
+            sign_callback_receiver().value()->raw_credential_id());
 }
 
 TEST_F(U2fSignTest, TestSignSuccessWithFake) {
@@ -256,26 +258,30 @@
   request->Start();
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
-  auto device = std::make_unique<VirtualU2fDevice>();
+  auto device = std::make_unique<VirtualFidoDevice>();
   device->AddRegistration(key_handle, std::move(private_key),
                           GetTestRelyingPartyIdSHA256(), 42);
   discovery()->AddDevice(std::move(device));
 
   sign_callback_receiver().WaitForCallback();
-  EXPECT_EQ(U2fReturnCode::SUCCESS, sign_callback_receiver().status());
+  EXPECT_EQ(FidoReturnCode::kSuccess, sign_callback_receiver().status());
 
   // Just a sanity check, we don't verify the actual signature.
-  ASSERT_GE(
-      (size_t)(32 + 1 + 4 + 8),  // Minimal ECDSA signature is 8 bytes
-      sign_callback_receiver().value()->GetAuthenticatorDataBytes().size());
+  ASSERT_GE(32u + 1u + 4u + 8u,  // Minimal ECDSA signature is 8 bytes
+            sign_callback_receiver()
+                .value()
+                ->auth_data()
+                .SerializeToByteArray()
+                .size());
   EXPECT_EQ(0x01,
             sign_callback_receiver()
                 .value()
-                ->GetAuthenticatorDataBytes()[32]);  // UP flag
-  EXPECT_EQ(43,
-            sign_callback_receiver()
-                .value()
-                ->GetAuthenticatorDataBytes()[36]);  // counter
+                ->auth_data()
+                .SerializeToByteArray()[32]);  // UP flag
+  EXPECT_EQ(43, sign_callback_receiver()
+                    .value()
+                    ->auth_data()
+                    .SerializeToByteArray()[36]);  // counter
 }
 
 TEST_F(U2fSignTest, TestDelayedSuccess) {
@@ -296,14 +302,15 @@
   discovery()->AddDevice(std::move(device));
 
   sign_callback_receiver().WaitForCallback();
-  EXPECT_EQ(U2fReturnCode::SUCCESS, sign_callback_receiver().status());
+  EXPECT_EQ(FidoReturnCode::kSuccess, sign_callback_receiver().status());
 
   // Correct key was sent so a sign response is expected.
   EXPECT_EQ(GetTestAssertionSignature(),
             sign_callback_receiver().value()->signature());
 
   // Verify that we get the key handle used for signing.
-  EXPECT_EQ(signing_key_handle, sign_callback_receiver().value()->raw_id());
+  EXPECT_EQ(signing_key_handle,
+            sign_callback_receiver().value()->raw_credential_id());
 }
 
 TEST_F(U2fSignTest, TestMultipleHandles) {
@@ -330,14 +337,15 @@
   discovery()->AddDevice(std::move(device));
 
   sign_callback_receiver().WaitForCallback();
-  EXPECT_EQ(U2fReturnCode::SUCCESS, sign_callback_receiver().status());
+  EXPECT_EQ(FidoReturnCode::kSuccess, sign_callback_receiver().status());
 
   // Correct key was sent so a sign response is expected.
   EXPECT_EQ(GetTestAssertionSignature(),
             sign_callback_receiver().value()->signature());
 
   // Verify that we get the key handle used for signing.
-  EXPECT_EQ(correct_key_handle, sign_callback_receiver().value()->raw_id());
+  EXPECT_EQ(correct_key_handle,
+            sign_callback_receiver().value()->raw_credential_id());
 }
 
 TEST_F(U2fSignTest, TestMultipleDevices) {
@@ -368,14 +376,15 @@
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
   sign_callback_receiver().WaitForCallback();
-  EXPECT_EQ(U2fReturnCode::SUCCESS, sign_callback_receiver().status());
+  EXPECT_EQ(FidoReturnCode::kSuccess, sign_callback_receiver().status());
 
   // Correct key was sent so a sign response is expected.
   EXPECT_EQ(GetTestAssertionSignature(),
             sign_callback_receiver().value()->signature());
 
   // Verify that we get the key handle used for signing.
-  EXPECT_EQ(correct_key_handle, sign_callback_receiver().value()->raw_id());
+  EXPECT_EQ(correct_key_handle,
+            sign_callback_receiver().value()->raw_credential_id());
 }
 
 TEST_F(U2fSignTest, TestFakeEnroll) {
@@ -410,7 +419,7 @@
 
   sign_callback_receiver().WaitForCallback();
   // Device that responded had no correct keys.
-  EXPECT_EQ(U2fReturnCode::CONDITIONS_NOT_SATISFIED,
+  EXPECT_EQ(FidoReturnCode::kConditionsNotSatisfied,
             sign_callback_receiver().status());
   EXPECT_FALSE(sign_callback_receiver().value());
 }
@@ -428,20 +437,21 @@
 }
 
 TEST_F(U2fSignTest, TestSignResponseData) {
-  base::Optional<SignResponseData> response =
-      SignResponseData::CreateFromU2fSignResponse(
+  base::Optional<AuthenticatorGetAssertionResponse> response =
+      AuthenticatorGetAssertionResponse::CreateFromU2fSignResponse(
           std::vector<uint8_t>(kTestRelyingPartyIdSHA256,
                                kTestRelyingPartyIdSHA256 + 32),
           GetTestSignResponse(), GetTestCredentialRawIdBytes());
   ASSERT_TRUE(response.has_value());
-  EXPECT_EQ(GetTestCredentialRawIdBytes(), response->raw_id());
-  EXPECT_EQ(GetTestAuthenticatorData(), response->GetAuthenticatorDataBytes());
+  EXPECT_EQ(GetTestCredentialRawIdBytes(), response->raw_credential_id());
+  EXPECT_EQ(GetTestAuthenticatorData(),
+            response->auth_data().SerializeToByteArray());
   EXPECT_EQ(GetTestAssertionSignature(), response->signature());
 }
 
 TEST_F(U2fSignTest, TestNullKeyHandle) {
-  base::Optional<SignResponseData> response =
-      SignResponseData::CreateFromU2fSignResponse(
+  base::Optional<AuthenticatorGetAssertionResponse> response =
+      AuthenticatorGetAssertionResponse::CreateFromU2fSignResponse(
           std::vector<uint8_t>(kTestRelyingPartyIdSHA256,
                                kTestRelyingPartyIdSHA256 + 32),
           GetTestSignResponse(), std::vector<uint8_t>());
@@ -449,8 +459,8 @@
 }
 
 TEST_F(U2fSignTest, TestNullResponse) {
-  base::Optional<SignResponseData> response =
-      SignResponseData::CreateFromU2fSignResponse(
+  base::Optional<AuthenticatorGetAssertionResponse> response =
+      AuthenticatorGetAssertionResponse::CreateFromU2fSignResponse(
           std::vector<uint8_t>(kTestRelyingPartyIdSHA256,
                                kTestRelyingPartyIdSHA256 + 32),
           std::vector<uint8_t>(), GetTestCredentialRawIdBytes());
@@ -459,8 +469,8 @@
 
 TEST_F(U2fSignTest, TestCorruptedCounter) {
   // A sign response of less than 5 bytes.
-  base::Optional<SignResponseData> response =
-      SignResponseData::CreateFromU2fSignResponse(
+  base::Optional<AuthenticatorGetAssertionResponse> response =
+      AuthenticatorGetAssertionResponse::CreateFromU2fSignResponse(
           std::vector<uint8_t>(kTestRelyingPartyIdSHA256,
                                kTestRelyingPartyIdSHA256 + 32),
           GetTestCorruptedSignResponse(3), GetTestCredentialRawIdBytes());
@@ -469,8 +479,8 @@
 
 TEST_F(U2fSignTest, TestCorruptedSignature) {
   // A sign response no more than 5 bytes.
-  base::Optional<SignResponseData> response =
-      SignResponseData::CreateFromU2fSignResponse(
+  base::Optional<AuthenticatorGetAssertionResponse> response =
+      AuthenticatorGetAssertionResponse::CreateFromU2fSignResponse(
           std::vector<uint8_t>(kTestRelyingPartyIdSHA256,
                                kTestRelyingPartyIdSHA256 + 32),
           GetTestCorruptedSignResponse(5), GetTestCredentialRawIdBytes());
@@ -492,7 +502,7 @@
   discovery()->AddDevice(std::move(device));
 
   sign_callback_receiver().WaitForCallback();
-  EXPECT_EQ(U2fReturnCode::FAILURE, sign_callback_receiver().status());
+  EXPECT_EQ(FidoReturnCode::kFailure, sign_callback_receiver().status());
   EXPECT_FALSE(sign_callback_receiver().value());
 }
 
@@ -542,11 +552,12 @@
   discovery()->AddDevice(std::move(device));
 
   sign_callback_receiver().WaitForCallback();
-  EXPECT_EQ(U2fReturnCode::SUCCESS, sign_callback_receiver().status());
+  EXPECT_EQ(FidoReturnCode::kSuccess, sign_callback_receiver().status());
 
   EXPECT_EQ(GetTestAssertionSignature(),
             sign_callback_receiver().value()->signature());
-  EXPECT_EQ(signing_key_handle, sign_callback_receiver().value()->raw_id());
+  EXPECT_EQ(signing_key_handle,
+            sign_callback_receiver().value()->raw_credential_id());
 }
 
 }  // namespace device
diff --git a/device/fido/virtual_fido_device.cc b/device/fido/virtual_fido_device.cc
new file mode 100644
index 0000000..e13f8926
--- /dev/null
+++ b/device/fido/virtual_fido_device.cc
@@ -0,0 +1,319 @@
+// Copyright 2018 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 "device/fido/virtual_fido_device.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
+#include "components/apdu/apdu_command.h"
+#include "components/apdu/apdu_response.h"
+#include "crypto/ec_private_key.h"
+#include "crypto/ec_signature_creator.h"
+#include "crypto/sha2.h"
+#include "device/fido/fido_constants.h"
+#include "net/cert/x509_util.h"
+
+namespace device {
+
+struct RegistrationData {
+  RegistrationData() = default;
+  RegistrationData(std::unique_ptr<crypto::ECPrivateKey> private_key,
+                   std::vector<uint8_t> application_parameter,
+                   uint32_t counter)
+      : private_key(std::move(private_key)),
+        application_parameter(std::move(application_parameter)),
+        counter(counter) {}
+  RegistrationData(RegistrationData&& data) = default;
+  ~RegistrationData() = default;
+
+  RegistrationData& operator=(RegistrationData&& other) = default;
+
+  std::unique_ptr<crypto::ECPrivateKey> private_key;
+  std::vector<uint8_t> application_parameter;
+  uint32_t counter = 0;
+
+  DISALLOW_COPY_AND_ASSIGN(RegistrationData);
+};
+
+struct VirtualFidoDevice::State::Internal {
+  // Keyed on key handle (a.k.a. "credential ID").
+  std::map<std::vector<uint8_t>, RegistrationData> registrations;
+};
+
+VirtualFidoDevice::State::State()
+    : attestation_cert_common_name("Batch Certificate"),
+      individual_attestation_cert_common_name("Individual Certificate"),
+      internal_(new Internal) {}
+
+VirtualFidoDevice::State::~State() = default;
+
+namespace {
+
+// First byte of registration response is 0x05 for historical reasons
+// not detailed in the spec.
+constexpr uint8_t kU2fRegistrationResponseHeader = 0x05;
+
+// The example attestation private key from the U2F spec at
+// https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-raw-message-formats-v1.2-ps-20170411.html#registration-example
+//
+// PKCS.8 encoded without encryption.
+constexpr uint8_t kAttestationKey[]{
+    0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
+    0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
+    0x03, 0x01, 0x07, 0x04, 0x6d, 0x30, 0x6b, 0x02, 0x01, 0x01, 0x04, 0x20,
+    0xf3, 0xfc, 0xcc, 0x0d, 0x00, 0xd8, 0x03, 0x19, 0x54, 0xf9, 0x08, 0x64,
+    0xd4, 0x3c, 0x24, 0x7f, 0x4b, 0xf5, 0xf0, 0x66, 0x5c, 0x6b, 0x50, 0xcc,
+    0x17, 0x74, 0x9a, 0x27, 0xd1, 0xcf, 0x76, 0x64, 0xa1, 0x44, 0x03, 0x42,
+    0x00, 0x04, 0x8d, 0x61, 0x7e, 0x65, 0xc9, 0x50, 0x8e, 0x64, 0xbc, 0xc5,
+    0x67, 0x3a, 0xc8, 0x2a, 0x67, 0x99, 0xda, 0x3c, 0x14, 0x46, 0x68, 0x2c,
+    0x25, 0x8c, 0x46, 0x3f, 0xff, 0xdf, 0x58, 0xdf, 0xd2, 0xfa, 0x3e, 0x6c,
+    0x37, 0x8b, 0x53, 0xd7, 0x95, 0xc4, 0xa4, 0xdf, 0xfb, 0x41, 0x99, 0xed,
+    0xd7, 0x86, 0x2f, 0x23, 0xab, 0xaf, 0x02, 0x03, 0xb4, 0xb8, 0x91, 0x1b,
+    0xa0, 0x56, 0x99, 0x94, 0xe1, 0x01};
+
+std::vector<uint8_t> GetAttestationKey() {
+  return std::vector<uint8_t>(std::begin(kAttestationKey),
+                              std::end(kAttestationKey));
+}
+
+// Small helper to make the code below more readable.
+template <class T>
+void AppendTo(std::vector<uint8_t>* dst, const T& src) {
+  dst->insert(dst->end(), std::begin(src), std::end(src));
+}
+
+// Returns an error response with the given status.
+base::Optional<std::vector<uint8_t>> ErrorStatus(
+    apdu::ApduResponse::Status status) {
+  return apdu::ApduResponse(std::vector<uint8_t>(), status)
+      .GetEncodedResponse();
+}
+
+}  // namespace
+
+VirtualFidoDevice::VirtualFidoDevice()
+    : state_(new State), weak_factory_(this) {}
+
+VirtualFidoDevice::VirtualFidoDevice(scoped_refptr<State> state)
+    : state_(std::move(state)), weak_factory_(this) {}
+
+VirtualFidoDevice::~VirtualFidoDevice() = default;
+
+void VirtualFidoDevice::TryWink(WinkCallback cb) {
+  std::move(cb).Run();
+}
+
+std::string VirtualFidoDevice::GetId() const {
+  // Use our heap address to get a unique-ish number. (0xffe1 is a prime).
+  return "VirtualFidoDevice-" + std::to_string((size_t)this % 0xffe1);
+}
+
+void VirtualFidoDevice::AddRegistration(
+    std::vector<uint8_t> key_handle,
+    std::unique_ptr<crypto::ECPrivateKey> private_key,
+    std::vector<uint8_t> application_parameter,
+    uint32_t counter) {
+  state_->internal_->registrations[std::move(key_handle)] = RegistrationData(
+      std::move(private_key), std::move(application_parameter), counter);
+}
+
+void VirtualFidoDevice::DeviceTransact(std::vector<uint8_t> command,
+                                       DeviceCallback cb) {
+  // Note, here we are using the code-under-test in this fake.
+  auto parsed_command = apdu::ApduCommand::CreateFromMessage(command);
+
+  base::Optional<std::vector<uint8_t>> response;
+
+  switch (parsed_command->ins()) {
+    case base::strict_cast<uint8_t>(U2fApduInstruction::kVersion):
+      break;
+    case base::strict_cast<uint8_t>(U2fApduInstruction::kRegister):
+      response = DoRegister(parsed_command->ins(), parsed_command->p1(),
+                            parsed_command->p2(), parsed_command->data());
+      break;
+    case base::strict_cast<uint8_t>(U2fApduInstruction::kSign):
+      response = DoSign(parsed_command->ins(), parsed_command->p1(),
+                        parsed_command->p2(), parsed_command->data());
+      break;
+    default:
+      response = ErrorStatus(apdu::ApduResponse::Status::SW_INS_NOT_SUPPORTED);
+  }
+
+  // Call |callback| via the |MessageLoop| because |AuthenticatorImpl| doesn't
+  // support callback hairpinning.
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::BindOnce(std::move(cb), std::move(response)));
+}
+
+base::WeakPtr<FidoDevice> VirtualFidoDevice::GetWeakPtr() {
+  return weak_factory_.GetWeakPtr();
+}
+
+base::Optional<std::vector<uint8_t>> VirtualFidoDevice::DoRegister(
+    uint8_t ins,
+    uint8_t p1,
+    uint8_t p2,
+    base::span<const uint8_t> data) {
+  if (data.size() != 64) {
+    return ErrorStatus(apdu::ApduResponse::Status::SW_WRONG_LENGTH);
+  }
+
+  const bool individual_attestation_requested = p1 & kP1IndividualAttestation;
+  // The spec says that the other bits of P1 should be zero. However, Chrome
+  // sends Test User Presence (0x03) so we ignore those bits.
+
+  auto challenge_param = data.first(32);
+  auto application_parameter = data.last(32);
+
+  // Create key to register.
+  // Note: Non-deterministic, you need to mock this out if you rely on
+  // deterministic behavior.
+  auto private_key = crypto::ECPrivateKey::Create();
+  std::string public_key;
+  bool status = private_key->ExportRawPublicKey(&public_key);
+  DCHECK(status);
+  public_key.insert(0, 1, 0x04);
+  DCHECK_EQ(public_key.size(), 65ul);
+
+  // Our key handles are simple hashes of the public key.
+  std::vector<uint8_t> key_handle(32);
+  crypto::SHA256HashString(public_key, key_handle.data(), key_handle.size());
+
+  // Data to be signed.
+  std::vector<uint8_t> sign_buffer;
+  sign_buffer.reserve(1 + application_parameter.size() +
+                      challenge_param.size() + key_handle.size() +
+                      public_key.size());
+  sign_buffer.push_back(0x00);
+  AppendTo(&sign_buffer, application_parameter);
+  AppendTo(&sign_buffer, challenge_param);
+  AppendTo(&sign_buffer, key_handle);
+  AppendTo(&sign_buffer, public_key);
+
+  // Sign with attestation key.
+  // Note: Non-deterministic, you need to mock this out if you rely on
+  // deterministic behavior.
+  std::vector<uint8_t> sig;
+  std::unique_ptr<crypto::ECPrivateKey> attestation_private_key =
+      crypto::ECPrivateKey::CreateFromPrivateKeyInfo(GetAttestationKey());
+  auto signer =
+      crypto::ECSignatureCreator::Create(attestation_private_key.get());
+  status = signer->Sign(sign_buffer.data(), sign_buffer.size(), &sig);
+  DCHECK(status);
+
+  constexpr uint32_t kAttestationCertSerialNumber = 1;
+  std::string attestation_cert;
+  if (!net::x509_util::CreateSelfSignedCert(
+          attestation_private_key->key(), net::x509_util::DIGEST_SHA256,
+          "CN=" + (individual_attestation_requested
+                       ? state_->individual_attestation_cert_common_name
+                       : state_->attestation_cert_common_name),
+          kAttestationCertSerialNumber, base::Time::FromTimeT(1500000000),
+          base::Time::FromTimeT(1500000000), &attestation_cert)) {
+    DVLOG(2) << "Failed to create attestation certificate";
+    return ErrorStatus(apdu::ApduResponse::Status::SW_INS_NOT_SUPPORTED);
+  }
+
+  // U2F response data.
+  std::vector<uint8_t> response;
+  response.reserve(1 + public_key.size() + 1 + key_handle.size() +
+                   attestation_cert.size() + sig.size());
+  response.push_back(kU2fRegistrationResponseHeader);
+  AppendTo(&response, public_key);
+  response.push_back(key_handle.size());
+  AppendTo(&response, key_handle);
+  AppendTo(&response, attestation_cert);
+  AppendTo(&response, sig);
+
+  // Store the registration.
+  AddRegistration(std::move(key_handle), std::move(private_key),
+                  std::vector<uint8_t>(application_parameter.begin(),
+                                       application_parameter.end()),
+                  1);
+
+  return apdu::ApduResponse(std::move(response),
+                            apdu::ApduResponse::Status::SW_NO_ERROR)
+      .GetEncodedResponse();
+}
+
+base::Optional<std::vector<uint8_t>> VirtualFidoDevice::DoSign(
+    uint8_t ins,
+    uint8_t p1,
+    uint8_t p2,
+    base::span<const uint8_t> data) {
+  if (!(p1 == kP1CheckOnly || p1 == kP1TupRequiredConsumed ||
+        p1 == kP1IndividualAttestation) ||
+      p2 != 0) {
+    return ErrorStatus(apdu::ApduResponse::Status::SW_WRONG_DATA);
+  }
+
+  auto challenge_param = data.first(32);
+  auto application_parameter = data.subspan(32, 32);
+  size_t key_handle_length = data[64];
+  if (key_handle_length != 32) {
+    // Our own keyhandles are always 32 bytes long, if the request has something
+    // else then we already know it is not ours.
+    return ErrorStatus(apdu::ApduResponse::Status::SW_WRONG_DATA);
+  }
+  if (data.size() != 32 + 32 + 1 + key_handle_length) {
+    return ErrorStatus(apdu::ApduResponse::Status::SW_WRONG_LENGTH);
+  }
+  auto key_handle = data.last(key_handle_length);
+
+  // Check if this is our key_handle and it's for this appId.
+  auto it = state_->internal_->registrations.find(
+      std::vector<uint8_t>(key_handle.cbegin(), key_handle.cend()));
+
+  if (it == state_->internal_->registrations.end()) {
+    return ErrorStatus(apdu::ApduResponse::Status::SW_WRONG_DATA);
+  }
+
+  base::span<const uint8_t> registered_app_id_hash =
+      base::make_span(it->second.application_parameter);
+  if (application_parameter != registered_app_id_hash) {
+    // It's important this error looks identical to the previous one, as
+    // tokens should not reveal the existence of keyHandles to unrelated appIds.
+    return ErrorStatus(apdu::ApduResponse::Status::SW_WRONG_DATA);
+  }
+
+  auto& registration = it->second;
+  ++registration.counter;
+
+  // First create the part of the response that gets signed over.
+  std::vector<uint8_t> response;
+  response.push_back(0x01);  // Always pretend we got a touch.
+  response.push_back(registration.counter >> 24);
+  response.push_back(registration.counter >> 16);
+  response.push_back(registration.counter >> 8);
+  response.push_back(registration.counter);
+
+  std::vector<uint8_t> sign_buffer;
+  sign_buffer.reserve(application_parameter.size() + response.size() +
+                      challenge_param.size());
+  AppendTo(&sign_buffer, application_parameter);
+  AppendTo(&sign_buffer, response);
+  AppendTo(&sign_buffer, challenge_param);
+
+  // Sign with credential key.
+  std::vector<uint8_t> sig;
+  auto signer =
+      crypto::ECSignatureCreator::Create(registration.private_key.get());
+  bool status = signer->Sign(sign_buffer.data(), sign_buffer.size(), &sig);
+  DCHECK(status);
+
+  // Add signature for full response.
+  AppendTo(&response, sig);
+
+  return apdu::ApduResponse(std::move(response),
+                            apdu::ApduResponse::Status::SW_NO_ERROR)
+      .GetEncodedResponse();
+}
+
+}  // namespace device
diff --git a/device/fido/virtual_fido_device.h b/device/fido/virtual_fido_device.h
new file mode 100644
index 0000000..fcc2b046
--- /dev/null
+++ b/device/fido/virtual_fido_device.h
@@ -0,0 +1,95 @@
+// Copyright 2018 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 DEVICE_FIDO_VIRTUAL_FIDO_DEVICE_H_
+#define DEVICE_FIDO_VIRTUAL_FIDO_DEVICE_H_
+
+#include <stdint.h>
+
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/component_export.h"
+#include "base/containers/span.h"
+#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "device/fido/fido_device.h"
+
+namespace crypto {
+class ECPrivateKey;
+}  // namespace crypto
+
+namespace device {
+
+class COMPONENT_EXPORT(DEVICE_FIDO) VirtualFidoDevice : public FidoDevice {
+ public:
+  // Stores the state of the device. Since |U2fDevice| objects only persist for
+  // the lifetime of a single request, keeping state in an external object is
+  // neccessary in order to provide continuity between requests.
+  class COMPONENT_EXPORT(DEVICE_FIDO) State : public base::RefCounted<State> {
+   public:
+    State();
+
+    // The common name in the attestation certificate.
+    std::string attestation_cert_common_name;
+
+    // The common name in the attestation certificate if individual attestation
+    // is requested.
+    std::string individual_attestation_cert_common_name;
+
+   private:
+    friend class ::device::VirtualFidoDevice;
+    friend class base::RefCounted<State>;
+    ~State();
+
+    struct Internal;
+    std::unique_ptr<Internal> internal_;
+  };
+
+  // Constructs an object with ephemeral state. In order to have the state of
+  // the device persist between operations, use the constructor that takes a
+  // scoped_refptr<State>.
+  VirtualFidoDevice();
+
+  // Constructs an object that will read from, and write to, |state|.
+  explicit VirtualFidoDevice(scoped_refptr<State> state);
+
+  ~VirtualFidoDevice() override;
+
+  void AddRegistration(std::vector<uint8_t> key_handle,
+                       std::unique_ptr<crypto::ECPrivateKey> private_key,
+                       std::vector<uint8_t> application_parameter,
+                       uint32_t counter);
+
+ protected:
+  // U2fDevice:
+  void TryWink(WinkCallback cb) override;
+  std::string GetId() const override;
+  void DeviceTransact(std::vector<uint8_t> command, DeviceCallback cb) override;
+  base::WeakPtr<FidoDevice> GetWeakPtr() override;
+
+ private:
+  base::Optional<std::vector<uint8_t>> DoRegister(
+      uint8_t ins,
+      uint8_t p1,
+      uint8_t p2,
+      base::span<const uint8_t> data);
+
+  base::Optional<std::vector<uint8_t>> DoSign(uint8_t ins,
+                                              uint8_t p1,
+                                              uint8_t p2,
+                                              base::span<const uint8_t> data);
+
+  scoped_refptr<State> state_;
+  base::WeakPtrFactory<FidoDevice> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(VirtualFidoDevice);
+};
+
+}  // namespace device
+
+#endif  // DEVICE_FIDO_VIRTUAL_FIDO_DEVICE_H_
diff --git a/device/fido/virtual_u2f_device.cc b/device/fido/virtual_u2f_device.cc
deleted file mode 100644
index 8d030d1b..0000000
--- a/device/fido/virtual_u2f_device.cc
+++ /dev/null
@@ -1,318 +0,0 @@
-// Copyright 2018 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 "device/fido/virtual_u2f_device.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/numerics/safe_conversions.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/time/time.h"
-#include "components/apdu/apdu_command.h"
-#include "components/apdu/apdu_response.h"
-#include "crypto/ec_private_key.h"
-#include "crypto/ec_signature_creator.h"
-#include "crypto/sha2.h"
-#include "device/fido/fido_constants.h"
-#include "net/cert/x509_util.h"
-
-namespace device {
-
-struct RegistrationData {
-  RegistrationData() = default;
-  RegistrationData(std::unique_ptr<crypto::ECPrivateKey> private_key,
-                   std::vector<uint8_t> application_parameter,
-                   uint32_t counter)
-      : private_key(std::move(private_key)),
-        application_parameter(std::move(application_parameter)),
-        counter(counter) {}
-  RegistrationData(RegistrationData&& data) = default;
-  ~RegistrationData() = default;
-
-  RegistrationData& operator=(RegistrationData&& other) = default;
-
-  std::unique_ptr<crypto::ECPrivateKey> private_key;
-  std::vector<uint8_t> application_parameter;
-  uint32_t counter = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(RegistrationData);
-};
-
-struct VirtualU2fDevice::State::Internal {
-  // Keyed on key handle (a.k.a. "credential ID").
-  std::map<std::vector<uint8_t>, RegistrationData> registrations;
-};
-
-VirtualU2fDevice::State::State()
-    : attestation_cert_common_name("Batch Certificate"),
-      individual_attestation_cert_common_name("Individual Certificate"),
-      internal_(new Internal) {}
-
-VirtualU2fDevice::State::~State() = default;
-
-namespace {
-
-// First byte of registration response is 0x05 for historical reasons
-// not detailed in the spec.
-constexpr uint8_t kU2fRegistrationResponseHeader = 0x05;
-
-// The example attestation private key from the U2F spec at
-// https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-raw-message-formats-v1.2-ps-20170411.html#registration-example
-//
-// PKCS.8 encoded without encryption.
-constexpr uint8_t kAttestationKey[]{
-    0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
-    0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
-    0x03, 0x01, 0x07, 0x04, 0x6d, 0x30, 0x6b, 0x02, 0x01, 0x01, 0x04, 0x20,
-    0xf3, 0xfc, 0xcc, 0x0d, 0x00, 0xd8, 0x03, 0x19, 0x54, 0xf9, 0x08, 0x64,
-    0xd4, 0x3c, 0x24, 0x7f, 0x4b, 0xf5, 0xf0, 0x66, 0x5c, 0x6b, 0x50, 0xcc,
-    0x17, 0x74, 0x9a, 0x27, 0xd1, 0xcf, 0x76, 0x64, 0xa1, 0x44, 0x03, 0x42,
-    0x00, 0x04, 0x8d, 0x61, 0x7e, 0x65, 0xc9, 0x50, 0x8e, 0x64, 0xbc, 0xc5,
-    0x67, 0x3a, 0xc8, 0x2a, 0x67, 0x99, 0xda, 0x3c, 0x14, 0x46, 0x68, 0x2c,
-    0x25, 0x8c, 0x46, 0x3f, 0xff, 0xdf, 0x58, 0xdf, 0xd2, 0xfa, 0x3e, 0x6c,
-    0x37, 0x8b, 0x53, 0xd7, 0x95, 0xc4, 0xa4, 0xdf, 0xfb, 0x41, 0x99, 0xed,
-    0xd7, 0x86, 0x2f, 0x23, 0xab, 0xaf, 0x02, 0x03, 0xb4, 0xb8, 0x91, 0x1b,
-    0xa0, 0x56, 0x99, 0x94, 0xe1, 0x01};
-
-std::vector<uint8_t> GetAttestationKey() {
-  return std::vector<uint8_t>(std::begin(kAttestationKey),
-                              std::end(kAttestationKey));
-}
-
-// Small helper to make the code below more readable.
-template <class T>
-void AppendTo(std::vector<uint8_t>* dst, const T& src) {
-  dst->insert(dst->end(), std::begin(src), std::end(src));
-}
-
-// Returns an error response with the given status.
-base::Optional<std::vector<uint8_t>> ErrorStatus(
-    apdu::ApduResponse::Status status) {
-  return apdu::ApduResponse(std::vector<uint8_t>(), status)
-      .GetEncodedResponse();
-}
-
-}  // namespace
-
-VirtualU2fDevice::VirtualU2fDevice() : state_(new State), weak_factory_(this) {}
-
-VirtualU2fDevice::VirtualU2fDevice(scoped_refptr<State> state)
-    : state_(std::move(state)), weak_factory_(this) {}
-
-VirtualU2fDevice::~VirtualU2fDevice() = default;
-
-void VirtualU2fDevice::TryWink(WinkCallback cb) {
-  std::move(cb).Run();
-}
-
-std::string VirtualU2fDevice::GetId() const {
-  // Use our heap address to get a unique-ish number. (0xffe1 is a prime).
-  return "VirtualU2fDevice-" + std::to_string((size_t)this % 0xffe1);
-}
-
-void VirtualU2fDevice::AddRegistration(
-    std::vector<uint8_t> key_handle,
-    std::unique_ptr<crypto::ECPrivateKey> private_key,
-    std::vector<uint8_t> application_parameter,
-    uint32_t counter) {
-  state_->internal_->registrations[std::move(key_handle)] = RegistrationData(
-      std::move(private_key), std::move(application_parameter), counter);
-}
-
-void VirtualU2fDevice::DeviceTransact(std::vector<uint8_t> command,
-                                      DeviceCallback cb) {
-  // Note, here we are using the code-under-test in this fake.
-  auto parsed_command = apdu::ApduCommand::CreateFromMessage(command);
-
-  base::Optional<std::vector<uint8_t>> response;
-
-  switch (parsed_command->ins()) {
-    case base::strict_cast<uint8_t>(U2fApduInstruction::kVersion):
-      break;
-    case base::strict_cast<uint8_t>(U2fApduInstruction::kRegister):
-      response = DoRegister(parsed_command->ins(), parsed_command->p1(),
-                            parsed_command->p2(), parsed_command->data());
-      break;
-    case base::strict_cast<uint8_t>(U2fApduInstruction::kSign):
-      response = DoSign(parsed_command->ins(), parsed_command->p1(),
-                        parsed_command->p2(), parsed_command->data());
-      break;
-    default:
-      response = ErrorStatus(apdu::ApduResponse::Status::SW_INS_NOT_SUPPORTED);
-  }
-
-  // Call |callback| via the |MessageLoop| because |AuthenticatorImpl| doesn't
-  // support callback hairpinning.
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(std::move(cb), std::move(response)));
-}
-
-base::WeakPtr<FidoDevice> VirtualU2fDevice::GetWeakPtr() {
-  return weak_factory_.GetWeakPtr();
-}
-
-base::Optional<std::vector<uint8_t>> VirtualU2fDevice::DoRegister(
-    uint8_t ins,
-    uint8_t p1,
-    uint8_t p2,
-    base::span<const uint8_t> data) {
-  if (data.size() != 64) {
-    return ErrorStatus(apdu::ApduResponse::Status::SW_WRONG_LENGTH);
-  }
-
-  const bool individual_attestation_requested = p1 & kP1IndividualAttestation;
-  // The spec says that the other bits of P1 should be zero. However, Chrome
-  // sends Test User Presence (0x03) so we ignore those bits.
-
-  auto challenge_param = data.first(32);
-  auto application_parameter = data.last(32);
-
-  // Create key to register.
-  // Note: Non-deterministic, you need to mock this out if you rely on
-  // deterministic behavior.
-  auto private_key = crypto::ECPrivateKey::Create();
-  std::string public_key;
-  bool status = private_key->ExportRawPublicKey(&public_key);
-  DCHECK(status);
-  public_key.insert(0, 1, 0x04);
-  DCHECK_EQ(public_key.size(), 65ul);
-
-  // Our key handles are simple hashes of the public key.
-  std::vector<uint8_t> key_handle(32);
-  crypto::SHA256HashString(public_key, key_handle.data(), key_handle.size());
-
-  // Data to be signed.
-  std::vector<uint8_t> sign_buffer;
-  sign_buffer.reserve(1 + application_parameter.size() +
-                      challenge_param.size() + key_handle.size() +
-                      public_key.size());
-  sign_buffer.push_back(0x00);
-  AppendTo(&sign_buffer, application_parameter);
-  AppendTo(&sign_buffer, challenge_param);
-  AppendTo(&sign_buffer, key_handle);
-  AppendTo(&sign_buffer, public_key);
-
-  // Sign with attestation key.
-  // Note: Non-deterministic, you need to mock this out if you rely on
-  // deterministic behavior.
-  std::vector<uint8_t> sig;
-  std::unique_ptr<crypto::ECPrivateKey> attestation_private_key =
-      crypto::ECPrivateKey::CreateFromPrivateKeyInfo(GetAttestationKey());
-  auto signer =
-      crypto::ECSignatureCreator::Create(attestation_private_key.get());
-  status = signer->Sign(sign_buffer.data(), sign_buffer.size(), &sig);
-  DCHECK(status);
-
-  constexpr uint32_t kAttestationCertSerialNumber = 1;
-  std::string attestation_cert;
-  if (!net::x509_util::CreateSelfSignedCert(
-          attestation_private_key->key(), net::x509_util::DIGEST_SHA256,
-          "CN=" + (individual_attestation_requested
-                       ? state_->individual_attestation_cert_common_name
-                       : state_->attestation_cert_common_name),
-          kAttestationCertSerialNumber, base::Time::FromTimeT(1500000000),
-          base::Time::FromTimeT(1500000000), &attestation_cert)) {
-    DVLOG(2) << "Failed to create attestation certificate";
-    return ErrorStatus(apdu::ApduResponse::Status::SW_INS_NOT_SUPPORTED);
-  }
-
-  // U2F response data.
-  std::vector<uint8_t> response;
-  response.reserve(1 + public_key.size() + 1 + key_handle.size() +
-                   attestation_cert.size() + sig.size());
-  response.push_back(kU2fRegistrationResponseHeader);
-  AppendTo(&response, public_key);
-  response.push_back(key_handle.size());
-  AppendTo(&response, key_handle);
-  AppendTo(&response, attestation_cert);
-  AppendTo(&response, sig);
-
-  // Store the registration.
-  AddRegistration(std::move(key_handle), std::move(private_key),
-                  std::vector<uint8_t>(application_parameter.begin(),
-                                       application_parameter.end()),
-                  1);
-
-  return apdu::ApduResponse(std::move(response),
-                            apdu::ApduResponse::Status::SW_NO_ERROR)
-      .GetEncodedResponse();
-}
-
-base::Optional<std::vector<uint8_t>> VirtualU2fDevice::DoSign(
-    uint8_t ins,
-    uint8_t p1,
-    uint8_t p2,
-    base::span<const uint8_t> data) {
-  if (!(p1 == kP1CheckOnly || p1 == kP1TupRequiredConsumed ||
-        p1 == kP1IndividualAttestation) ||
-      p2 != 0) {
-    return ErrorStatus(apdu::ApduResponse::Status::SW_WRONG_DATA);
-  }
-
-  auto challenge_param = data.first(32);
-  auto application_parameter = data.subspan(32, 32);
-  size_t key_handle_length = data[64];
-  if (key_handle_length != 32) {
-    // Our own keyhandles are always 32 bytes long, if the request has something
-    // else then we already know it is not ours.
-    return ErrorStatus(apdu::ApduResponse::Status::SW_WRONG_DATA);
-  }
-  if (data.size() != 32 + 32 + 1 + key_handle_length) {
-    return ErrorStatus(apdu::ApduResponse::Status::SW_WRONG_LENGTH);
-  }
-  auto key_handle = data.last(key_handle_length);
-
-  // Check if this is our key_handle and it's for this appId.
-  auto it = state_->internal_->registrations.find(
-      std::vector<uint8_t>(key_handle.cbegin(), key_handle.cend()));
-
-  if (it == state_->internal_->registrations.end()) {
-    return ErrorStatus(apdu::ApduResponse::Status::SW_WRONG_DATA);
-  }
-
-  base::span<const uint8_t> registered_app_id_hash =
-      base::make_span(it->second.application_parameter);
-  if (application_parameter != registered_app_id_hash) {
-    // It's important this error looks identical to the previous one, as
-    // tokens should not reveal the existence of keyHandles to unrelated appIds.
-    return ErrorStatus(apdu::ApduResponse::Status::SW_WRONG_DATA);
-  }
-
-  auto& registration = it->second;
-  ++registration.counter;
-
-  // First create the part of the response that gets signed over.
-  std::vector<uint8_t> response;
-  response.push_back(0x01);  // Always pretend we got a touch.
-  response.push_back(registration.counter >> 24);
-  response.push_back(registration.counter >> 16);
-  response.push_back(registration.counter >> 8);
-  response.push_back(registration.counter);
-
-  std::vector<uint8_t> sign_buffer;
-  sign_buffer.reserve(application_parameter.size() + response.size() +
-                      challenge_param.size());
-  AppendTo(&sign_buffer, application_parameter);
-  AppendTo(&sign_buffer, response);
-  AppendTo(&sign_buffer, challenge_param);
-
-  // Sign with credential key.
-  std::vector<uint8_t> sig;
-  auto signer =
-      crypto::ECSignatureCreator::Create(registration.private_key.get());
-  bool status = signer->Sign(sign_buffer.data(), sign_buffer.size(), &sig);
-  DCHECK(status);
-
-  // Add signature for full response.
-  AppendTo(&response, sig);
-
-  return apdu::ApduResponse(std::move(response),
-                            apdu::ApduResponse::Status::SW_NO_ERROR)
-      .GetEncodedResponse();
-}
-
-}  // namespace device
diff --git a/device/fido/virtual_u2f_device.h b/device/fido/virtual_u2f_device.h
deleted file mode 100644
index 5fc2cfa..0000000
--- a/device/fido/virtual_u2f_device.h
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2018 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 DEVICE_FIDO_VIRTUAL_U2F_DEVICE_H_
-#define DEVICE_FIDO_VIRTUAL_U2F_DEVICE_H_
-
-#include <stdint.h>
-
-#include <map>
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/component_export.h"
-#include "base/containers/span.h"
-#include "base/macros.h"
-#include "base/memory/scoped_refptr.h"
-#include "device/fido/fido_device.h"
-
-namespace crypto {
-class ECPrivateKey;
-}  // namespace crypto
-
-namespace device {
-
-class COMPONENT_EXPORT(DEVICE_FIDO) VirtualU2fDevice : public FidoDevice {
- public:
-  // Stores the state of the device. Since |U2fDevice| objects only persist for
-  // the lifetime of a single request, keeping state in an external object is
-  // neccessary in order to provide continuity between requests.
-  class COMPONENT_EXPORT(DEVICE_FIDO) State : public base::RefCounted<State> {
-   public:
-    State();
-
-    // The common name in the attestation certificate.
-    std::string attestation_cert_common_name;
-
-    // The common name in the attestation certificate if individual attestation
-    // is requested.
-    std::string individual_attestation_cert_common_name;
-
-   private:
-    friend class ::device::VirtualU2fDevice;
-    friend class base::RefCounted<State>;
-    ~State();
-
-    struct Internal;
-    std::unique_ptr<Internal> internal_;
-  };
-
-  // Constructs an object with ephemeral state. In order to have the state of
-  // the device persist between operations, use the constructor that takes a
-  // scoped_refptr<State>.
-  VirtualU2fDevice();
-
-  // Constructs an object that will read from, and write to, |state|.
-  explicit VirtualU2fDevice(scoped_refptr<State> state);
-
-  ~VirtualU2fDevice() override;
-
-  void AddRegistration(std::vector<uint8_t> key_handle,
-                       std::unique_ptr<crypto::ECPrivateKey> private_key,
-                       std::vector<uint8_t> application_parameter,
-                       uint32_t counter);
-
- protected:
-  // U2fDevice:
-  void TryWink(WinkCallback cb) override;
-  std::string GetId() const override;
-  void DeviceTransact(std::vector<uint8_t> command, DeviceCallback cb) override;
-  base::WeakPtr<FidoDevice> GetWeakPtr() override;
-
- private:
-  base::Optional<std::vector<uint8_t>> DoRegister(
-      uint8_t ins,
-      uint8_t p1,
-      uint8_t p2,
-      base::span<const uint8_t> data);
-
-  base::Optional<std::vector<uint8_t>> DoSign(uint8_t ins,
-                                              uint8_t p1,
-                                              uint8_t p2,
-                                              base::span<const uint8_t> data);
-
-  scoped_refptr<State> state_;
-  base::WeakPtrFactory<FidoDevice> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(VirtualU2fDevice);
-};
-
-}  // namespace device
-
-#endif  // DEVICE_FIDO_VIRTUAL_U2F_DEVICE_H_
diff --git a/device/gamepad/xbox_controller_mac.mm b/device/gamepad/xbox_controller_mac.mm
index f85d4fb..e2f0f1f 100644
--- a/device/gamepad/xbox_controller_mac.mm
+++ b/device/gamepad/xbox_controller_mac.mm
@@ -35,6 +35,8 @@
 const int kXboxOneReadEndpoint = 2;
 const int kXboxOneControlEndpoint = 1;
 
+const double kXboxOneMaxEffectDurationMillis = 2500;  // 2.5 seconds
+
 enum {
   STATUS_MESSAGE_BUTTONS = 0,
   STATUS_MESSAGE_LED = 1,
@@ -368,11 +370,24 @@
     return;
   SetVibration(strong_magnitude, weak_magnitude);
 
-  playing_effect_task_runner_->PostDelayedTask(
-      FROM_HERE,
-      base::BindOnce(&XboxControllerMac::StopVibration, base::Unretained(this),
-                     sequence_id),
-      base::TimeDelta::FromMillisecondsD(duration));
+  // The Xbox One controller rumble packet specifies a duration for the rumble
+  // effect with a maximum length of about 3 seconds. Support longer durations
+  // by sending a second rumble packet to extend the duration.
+  if (duration > kXboxOneMaxEffectDurationMillis) {
+    double remaining = duration - kXboxOneMaxEffectDurationMillis;
+    playing_effect_task_runner_->PostDelayedTask(
+        FROM_HERE,
+        base::BindOnce(&XboxControllerMac::StartVibration,
+                       base::Unretained(this), sequence_id, remaining,
+                       strong_magnitude, weak_magnitude),
+        base::TimeDelta::FromMillisecondsD(kXboxOneMaxEffectDurationMillis));
+  } else {
+    playing_effect_task_runner_->PostDelayedTask(
+        FROM_HERE,
+        base::BindOnce(&XboxControllerMac::StopVibration,
+                       base::Unretained(this), sequence_id),
+        base::TimeDelta::FromMillisecondsD(duration));
+  }
 }
 
 void XboxControllerMac::StopVibration(int sequence_id) {
diff --git a/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderAdapter.java b/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderAdapter.java
index 7ce6066c..708a6cc 100644
--- a/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderAdapter.java
+++ b/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderAdapter.java
@@ -10,7 +10,6 @@
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.MainDex;
 
 import java.util.concurrent.FutureTask;
 
@@ -22,7 +21,6 @@
  * content/browser/geolocation/location_api_adapter_android.h.
  * Based on android.webkit.GeolocationService.java
  */
-@MainDex
 @VisibleForTesting
 public class LocationProviderAdapter {
     private static final String TAG = "cr_LocationProvider";
diff --git a/device/usb/BUILD.gn b/device/usb/BUILD.gn
index 6a66c3b3..5b183fcc 100644
--- a/device/usb/BUILD.gn
+++ b/device/usb/BUILD.gn
@@ -81,6 +81,7 @@
 
   if (is_win || is_mac) {
     sources += [
+      "scoped_libusb_device_ref.h",
       "usb_context.cc",
       "usb_context.h",
       "usb_device_handle_impl.cc",
diff --git a/device/usb/scoped_libusb_device_ref.h b/device/usb/scoped_libusb_device_ref.h
new file mode 100644
index 0000000..05a21b2
--- /dev/null
+++ b/device/usb/scoped_libusb_device_ref.h
@@ -0,0 +1,24 @@
+// Copyright 2018 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 DEVICE_USB_SCOPED_LIBUSB_DEVICE_REF_H_
+#define DEVICE_USB_SCOPED_LIBUSB_DEVICE_REF_H_
+
+#include "base/scoped_generic.h"
+#include "third_party/libusb/src/libusb/libusb.h"
+
+namespace device {
+
+struct LibusbDeviceRefTraits {
+  static libusb_device* InvalidValue() { return nullptr; }
+
+  static void Free(libusb_device* device) { libusb_unref_device(device); }
+};
+
+using ScopedLibusbDeviceRef =
+    base::ScopedGeneric<libusb_device*, LibusbDeviceRefTraits>;
+
+}  // namespace device
+
+#endif  // DEVICE_USB_SCOPED_LIBUSB_DEVICE_REF_H_
diff --git a/device/usb/usb_device_handle_impl.cc b/device/usb/usb_device_handle_impl.cc
index fd743e7..cce0691 100644
--- a/device/usb/usb_device_handle_impl.cc
+++ b/device/usb/usb_device_handle_impl.cc
@@ -29,8 +29,6 @@
 
 namespace device {
 
-typedef libusb_device* PlatformUsbDevice;
-
 void HandleTransferCompletion(PlatformUsbTransferHandle transfer);
 
 namespace {
diff --git a/device/usb/usb_device_impl.cc b/device/usb/usb_device_impl.cc
index 74639e44..73f31da 100644
--- a/device/usb/usb_device_impl.cc
+++ b/device/usb/usb_device_impl.cc
@@ -29,7 +29,7 @@
 namespace device {
 
 UsbDeviceImpl::UsbDeviceImpl(scoped_refptr<UsbContext> context,
-                             PlatformUsbDevice platform_device,
+                             ScopedLibusbDeviceRef platform_device,
                              const libusb_device_descriptor& descriptor)
     : UsbDevice(descriptor.bcdUSB,
                 descriptor.bDeviceClass,
@@ -41,17 +41,15 @@
                 base::string16(),
                 base::string16(),
                 base::string16()),
-      platform_device_(platform_device),
-      context_(context) {
-  CHECK(platform_device) << "platform_device cannot be NULL";
-  libusb_ref_device(platform_device);
+      platform_device_(std::move(platform_device)),
+      context_(std::move(context)) {
+  CHECK(platform_device_.is_valid()) << "platform_device must be valid";
   ReadAllConfigurations();
   RefreshActiveConfiguration();
 }
 
 UsbDeviceImpl::~UsbDeviceImpl() {
   // The destructor must be safe to call from any thread.
-  libusb_unref_device(platform_device_);
 }
 
 void UsbDeviceImpl::Open(OpenCallback callback) {
@@ -68,11 +66,11 @@
 
 void UsbDeviceImpl::ReadAllConfigurations() {
   libusb_device_descriptor device_descriptor;
-  int rv = libusb_get_device_descriptor(platform_device_, &device_descriptor);
+  int rv = libusb_get_device_descriptor(platform_device(), &device_descriptor);
   if (rv == LIBUSB_SUCCESS) {
     for (uint8_t i = 0; i < device_descriptor.bNumConfigurations; ++i) {
       unsigned char* buffer;
-      rv = libusb_get_raw_config_descriptor(platform_device_, i, &buffer);
+      rv = libusb_get_raw_config_descriptor(platform_device(), i, &buffer);
       if (rv < 0) {
         USB_LOG(EVENT) << "Failed to get config descriptor: "
                        << ConvertPlatformUsbErrorToString(rv);
@@ -91,7 +89,7 @@
 
 void UsbDeviceImpl::RefreshActiveConfiguration() {
   uint8_t config_value;
-  int rv = libusb_get_active_config_value(platform_device_, &config_value);
+  int rv = libusb_get_active_config_value(platform_device(), &config_value);
   if (rv != LIBUSB_SUCCESS) {
     USB_LOG(EVENT) << "Failed to get active configuration: "
                    << ConvertPlatformUsbErrorToString(rv);
@@ -107,7 +105,7 @@
     scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) {
   base::AssertBlockingAllowed();
   PlatformUsbDeviceHandle handle;
-  const int rv = libusb_open(platform_device_, &handle);
+  const int rv = libusb_open(platform_device(), &handle);
   if (LIBUSB_SUCCESS == rv) {
     task_runner->PostTask(
         FROM_HERE, base::BindOnce(&UsbDeviceImpl::Opened, this, handle,
diff --git a/device/usb/usb_device_impl.h b/device/usb/usb_device_impl.h
index d0b1fd1..d4dce81 100644
--- a/device/usb/usb_device_impl.h
+++ b/device/usb/usb_device_impl.h
@@ -17,13 +17,13 @@
 #include "base/macros.h"
 #include "base/threading/thread_checker.h"
 #include "build/build_config.h"
+#include "device/usb/scoped_libusb_device_ref.h"
 #include "device/usb/usb_descriptors.h"
 #include "device/usb/usb_device.h"
 
 struct libusb_device;
 struct libusb_device_descriptor;
 struct libusb_device_handle;
-struct libusb_config_descriptor;
 
 namespace base {
 class SequencedTaskRunner;
@@ -34,12 +34,14 @@
 class UsbDeviceHandleImpl;
 class UsbContext;
 
-typedef struct libusb_device* PlatformUsbDevice;
-typedef struct libusb_config_descriptor* PlatformUsbConfigDescriptor;
 typedef struct libusb_device_handle* PlatformUsbDeviceHandle;
 
 class UsbDeviceImpl : public UsbDevice {
  public:
+  UsbDeviceImpl(scoped_refptr<UsbContext> context,
+                ScopedLibusbDeviceRef platform_device,
+                const libusb_device_descriptor& descriptor);
+
   // UsbDevice implementation:
   void Open(OpenCallback callback) override;
 
@@ -56,17 +58,12 @@
   }
   void set_webusb_landing_page(const GURL& url) { webusb_landing_page_ = url; }
 
-  PlatformUsbDevice platform_device() const { return platform_device_; }
+  libusb_device* platform_device() const { return platform_device_.get(); }
 
  protected:
   friend class UsbServiceImpl;
   friend class UsbDeviceHandleImpl;
 
-  // Called by UsbServiceImpl only;
-  UsbDeviceImpl(scoped_refptr<UsbContext> context,
-                PlatformUsbDevice platform_device,
-                const libusb_device_descriptor& descriptor);
-
   ~UsbDeviceImpl() override;
 
   void ReadAllConfigurations();
@@ -87,11 +84,11 @@
               scoped_refptr<base::SequencedTaskRunner> blocking_task_runner);
 
   base::ThreadChecker thread_checker_;
-  PlatformUsbDevice platform_device_;
+  const ScopedLibusbDeviceRef platform_device_;
   bool visited_ = false;
 
   // Retain the context so that it will not be released before UsbDevice.
-  scoped_refptr<UsbContext> context_;
+  const scoped_refptr<UsbContext> context_;
 
   DISALLOW_COPY_AND_ASSIGN(UsbDeviceImpl);
 };
diff --git a/device/usb/usb_service_impl.cc b/device/usb/usb_service_impl.cc
index a4f98e8..83e14c6f0 100644
--- a/device/usb/usb_service_impl.cc
+++ b/device/usb/usb_service_impl.cc
@@ -103,13 +103,15 @@
     const std::string& new_device_path,
     scoped_refptr<UsbContext> usb_context,
     scoped_refptr<base::SequencedTaskRunner> task_runner,
-    const base::Callback<void(libusb_device**, size_t)>& callback) {
+    base::OnceCallback<void(base::Optional<std::vector<ScopedLibusbDeviceRef>>)>
+        callback) {
 #if defined(OS_WIN)
   if (!new_device_path.empty()) {
     if (!IsWinUsbInterface(new_device_path)) {
       // Wait to call libusb_get_device_list until libusb will be able to find
       // a WinUSB interface for the device.
-      task_runner->PostTask(FROM_HERE, base::BindOnce(callback, nullptr, 0));
+      task_runner->PostTask(FROM_HERE,
+                            base::BindOnce(std::move(callback), base::nullopt));
       return;
     }
   }
@@ -121,18 +123,28 @@
   if (device_count < 0) {
     USB_LOG(ERROR) << "Failed to get device list: "
                    << ConvertPlatformUsbErrorToString(device_count);
-    task_runner->PostTask(FROM_HERE, base::Bind(callback, nullptr, 0));
+    task_runner->PostTask(FROM_HERE,
+                          base::BindOnce(std::move(callback), base::nullopt));
     return;
   }
 
-  task_runner->PostTask(FROM_HERE,
-                        base::Bind(callback, platform_devices, device_count));
+  std::vector<ScopedLibusbDeviceRef> scoped_devices;
+  scoped_devices.reserve(device_count);
+  for (ssize_t i = 0; i < device_count; ++i)
+    scoped_devices.emplace_back(platform_devices[i]);
+
+  // Free the list but don't unref the devices because ownership has been
+  // been transfered to the elements of |scoped_devices|.
+  libusb_free_device_list(platform_devices, false);
+
+  task_runner->PostTask(FROM_HERE, base::BindOnce(std::move(callback),
+                                                  std::move(scoped_devices)));
 }
 
 void CloseHandleAndRunContinuation(scoped_refptr<UsbDeviceHandle> device_handle,
-                                   const base::Closure& continuation) {
+                                   base::OnceClosure continuation) {
   device_handle->Close();
-  continuation.Run();
+  std::move(continuation).Run();
 }
 
 void SaveStringsAndRunContinuation(
@@ -168,8 +180,8 @@
     uint8_t product,
     uint8_t serial_number,
     bool read_bos_descriptors,
-    const base::Closure& success_closure,
-    const base::Closure& failure_closure,
+    base::OnceClosure success_closure,
+    base::OnceClosure failure_closure,
     scoped_refptr<UsbDeviceHandle> device_handle) {
   if (device_handle) {
     std::unique_ptr<std::map<uint8_t, base::string16>> string_map(
@@ -188,9 +200,9 @@
       count++;
     DCHECK_GT(count, 0);
 
-    base::Closure barrier =
-        base::BarrierClosure(count, base::Bind(&CloseHandleAndRunContinuation,
-                                               device_handle, success_closure));
+    base::RepeatingClosure barrier = base::BarrierClosure(
+        count, base::BindOnce(&CloseHandleAndRunContinuation, device_handle,
+                              std::move(success_closure)));
 
     if (!string_map->empty()) {
       scoped_refptr<UsbDeviceImpl> device =
@@ -207,7 +219,7 @@
                                                       device_handle, barrier));
     }
   } else {
-    failure_closure.Run();
+    std::move(failure_closure).Run();
   }
 }
 
@@ -229,8 +241,6 @@
 UsbServiceImpl::~UsbServiceImpl() {
   if (hotplug_enabled_)
     libusb_hotplug_deregister_callback(context_->context(), hotplug_handle_);
-  for (auto* platform_device : ignored_devices_)
-    libusb_unref_device(platform_device);
 }
 
 void UsbServiceImpl::GetDevices(const GetDevicesCallback& callback) {
@@ -320,45 +330,38 @@
     pending_path_enumerations_.pop();
   }
 
-  base::PostTaskWithTraits(FROM_HERE, kBlockingTaskTraits,
-                           base::Bind(&GetDeviceListOnBlockingThread,
-                                      device_path, context_, task_runner(),
-                                      base::Bind(&UsbServiceImpl::OnDeviceList,
-                                                 weak_factory_.GetWeakPtr())));
+  base::PostTaskWithTraits(
+      FROM_HERE, kBlockingTaskTraits,
+      base::BindOnce(&GetDeviceListOnBlockingThread, device_path, context_,
+                     task_runner(),
+                     base::BindOnce(&UsbServiceImpl::OnDeviceList,
+                                    weak_factory_.GetWeakPtr())));
 }
 
-void UsbServiceImpl::OnDeviceList(libusb_device** platform_devices,
-                                  size_t device_count) {
+void UsbServiceImpl::OnDeviceList(
+    base::Optional<std::vector<ScopedLibusbDeviceRef>> devices) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  if (!platform_devices) {
+  if (!devices) {
     RefreshDevicesComplete();
     return;
   }
 
-  base::Closure refresh_complete =
-      base::BarrierClosure(static_cast<int>(device_count),
-                           base::Bind(&UsbServiceImpl::RefreshDevicesComplete,
-                                      weak_factory_.GetWeakPtr()));
-  std::list<PlatformUsbDevice> new_devices;
-  std::set<PlatformUsbDevice> existing_ignored_devices;
+  std::vector<ScopedLibusbDeviceRef> new_devices;
 
   // Look for new and existing devices.
-  for (size_t i = 0; i < device_count; ++i) {
-    PlatformUsbDevice platform_device = platform_devices[i];
-    // Ignore some devices.
-    if (base::ContainsKey(ignored_devices_, platform_device)) {
-      existing_ignored_devices.insert(platform_device);
-      refresh_complete.Run();
+  for (auto& device : *devices) {
+    // Ignore devices that have failed enumeration previously.
+    if (base::ContainsValue(ignored_devices_, device.get()))
       continue;
-    }
 
-    auto it = platform_devices_.find(platform_device);
-
+    auto it = platform_devices_.find(device.get());
     if (it == platform_devices_.end()) {
-      new_devices.push_back(platform_device);
+      new_devices.push_back(std::move(device));
     } else {
+      // Mark the existing device object visited and remove it from the list so
+      // it will not be ignored.
       it->second->set_visited(true);
-      refresh_complete.Run();
+      device.reset();
     }
   }
 
@@ -375,21 +378,21 @@
     }
   }
 
-  // Remove devices not seen in this enumeration from |ignored_devices_|.
-  for (auto it = ignored_devices_.begin(); it != ignored_devices_.end();
-       /* incremented internally */) {
-    auto current = it++;
-    if (!base::ContainsKey(existing_ignored_devices, *current)) {
-      libusb_unref_device(*current);
-      ignored_devices_.erase(current);
-    }
+  // Remaining devices are being ignored. Clear the old list so that devices
+  // that have been removed don't remain in |ignored_devices_| indefinitely.
+  ignored_devices_.clear();
+  for (auto& device : *devices) {
+    if (device.is_valid())
+      ignored_devices_.push_back(std::move(device));
   }
 
-  for (PlatformUsbDevice platform_device : new_devices) {
-    EnumerateDevice(platform_device, refresh_complete);
-  }
-
-  libusb_free_device_list(platform_devices, true);
+  // Enumerate new devices.
+  base::RepeatingClosure refresh_complete = base::BarrierClosure(
+      new_devices.size(),
+      base::BindOnce(&UsbServiceImpl::RefreshDevicesComplete,
+                     weak_factory_.GetWeakPtr()));
+  for (auto& device : new_devices)
+    EnumerateDevice(std::move(device), refresh_complete);
 }
 
 void UsbServiceImpl::RefreshDevicesComplete() {
@@ -417,58 +420,63 @@
   }
 }
 
-void UsbServiceImpl::EnumerateDevice(PlatformUsbDevice platform_device,
+void UsbServiceImpl::EnumerateDevice(ScopedLibusbDeviceRef platform_device,
                                      const base::Closure& refresh_complete) {
   DCHECK(context_);
-  devices_being_enumerated_.insert(platform_device);
 
   libusb_device_descriptor descriptor;
-  int rv = libusb_get_device_descriptor(platform_device, &descriptor);
-  if (rv == LIBUSB_SUCCESS) {
-    if (descriptor.bDeviceClass == LIBUSB_CLASS_HUB) {
-      // Don't try to enumerate hubs. We never want to connect to a hub.
-      libusb_ref_device(platform_device);
-      ignored_devices_.insert(platform_device);
-      refresh_complete.Run();
-      return;
-    }
-
-    scoped_refptr<UsbDeviceImpl> device(
-        new UsbDeviceImpl(context_, platform_device, descriptor));
-    base::Closure add_device =
-        base::Bind(&UsbServiceImpl::AddDevice, weak_factory_.GetWeakPtr(),
-                   refresh_complete, device);
-    base::Closure enumeration_failed = base::Bind(
-        &UsbServiceImpl::EnumerationFailed, weak_factory_.GetWeakPtr(),
-        platform_device, refresh_complete);
-    bool read_bos_descriptors = descriptor.bcdUSB >= kUsbVersion2_1;
-
-    if (descriptor.iManufacturer == 0 && descriptor.iProduct == 0 &&
-        descriptor.iSerialNumber == 0 && !read_bos_descriptors) {
-      // Don't bother disturbing the device if it has no descriptors to offer.
-      add_device.Run();
-    } else {
-      device->Open(base::Bind(&OnDeviceOpenedReadDescriptors,
-                              descriptor.iManufacturer, descriptor.iProduct,
-                              descriptor.iSerialNumber, read_bos_descriptors,
-                              add_device, enumeration_failed));
-    }
-  } else {
+  int rv = libusb_get_device_descriptor(platform_device.get(), &descriptor);
+  if (rv != LIBUSB_SUCCESS) {
     USB_LOG(EVENT) << "Failed to get device descriptor: "
                    << ConvertPlatformUsbErrorToString(rv);
-    refresh_complete.Run();
+    EnumerationFailed(std::move(platform_device), refresh_complete);
+    return;
+  }
+
+  if (descriptor.bDeviceClass == LIBUSB_CLASS_HUB) {
+    // Don't try to enumerate hubs. We never want to connect to a hub.
+    EnumerationFailed(std::move(platform_device), refresh_complete);
+    return;
+  }
+
+  devices_being_enumerated_.insert(platform_device.get());
+
+  auto device = base::MakeRefCounted<UsbDeviceImpl>(
+      context_, std::move(platform_device), descriptor);
+  base::OnceClosure add_device =
+      base::BindOnce(&UsbServiceImpl::AddDevice, weak_factory_.GetWeakPtr(),
+                     refresh_complete, device);
+
+  bool read_bos_descriptors = descriptor.bcdUSB >= kUsbVersion2_1;
+  if (descriptor.iManufacturer == 0 && descriptor.iProduct == 0 &&
+      descriptor.iSerialNumber == 0 && !read_bos_descriptors) {
+    // Don't bother disturbing the device if it has no descriptors to offer.
+    std::move(add_device).Run();
+  } else {
+    // Take an additional reference to the libusb_device object that will be
+    // owned by this callback.
+    libusb_ref_device(device->platform_device());
+    base::OnceClosure enumeration_failed = base::BindOnce(
+        &UsbServiceImpl::EnumerationFailed, weak_factory_.GetWeakPtr(),
+        ScopedLibusbDeviceRef(device->platform_device()), refresh_complete);
+
+    device->Open(base::BindOnce(
+        &OnDeviceOpenedReadDescriptors, descriptor.iManufacturer,
+        descriptor.iProduct, descriptor.iSerialNumber, read_bos_descriptors,
+        std::move(add_device), std::move(enumeration_failed)));
   }
 }
 
 void UsbServiceImpl::AddDevice(const base::Closure& refresh_complete,
                                scoped_refptr<UsbDeviceImpl> device) {
-  auto it = devices_being_enumerated_.find(device->platform_device());
-  if (it == devices_being_enumerated_.end()) {
+  if (!base::ContainsKey(devices_being_enumerated_,
+                         device->platform_device())) {
     // Device was removed while being enumerated.
     refresh_complete.Run();
     return;
   }
 
+  DCHECK(!base::ContainsKey(platform_devices_, device->platform_device()));
   platform_devices_[device->platform_device()] = device;
   DCHECK(!base::ContainsKey(devices(), device->guid()));
   devices()[device->guid()] = device;
@@ -479,9 +487,8 @@
                 << device->product_string() << "\", serial=\""
                 << device->serial_number() << "\", guid=" << device->guid();
 
-  if (enumeration_ready_) {
+  if (enumeration_ready_)
     NotifyDeviceAdded(device);
-  }
 
   refresh_complete.Run();
 }
@@ -498,7 +505,7 @@
 
 // static
 int LIBUSB_CALL UsbServiceImpl::HotplugCallback(libusb_context* context,
-                                                PlatformUsbDevice device,
+                                                libusb_device* device_raw,
                                                 libusb_hotplug_event event,
                                                 void* user_data) {
   // It is safe to access the UsbServiceImpl* here because libusb takes a lock
@@ -507,18 +514,22 @@
   // processing thread after it has been deregistered.
   UsbServiceImpl* self = reinterpret_cast<UsbServiceImpl*>(user_data);
   DCHECK(!self->task_runner()->BelongsToCurrentThread());
+
+  // libusb does not transfer ownership of |device_raw| to this function so a
+  // reference must be taken here.
+  libusb_ref_device(device_raw);
+  ScopedLibusbDeviceRef device(device_raw);
+
   switch (event) {
     case LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED:
-      libusb_ref_device(device);  // Released in OnPlatformDeviceAdded.
       self->task_runner()->PostTask(
-          FROM_HERE, base::Bind(&UsbServiceImpl::OnPlatformDeviceAdded,
-                                base::Unretained(self), device));
+          FROM_HERE, base::BindOnce(&UsbServiceImpl::OnPlatformDeviceAdded,
+                                    base::Unretained(self), std::move(device)));
       break;
     case LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT:
-      libusb_ref_device(device);  // Released in OnPlatformDeviceRemoved.
       self->task_runner()->PostTask(
-          FROM_HERE, base::Bind(&UsbServiceImpl::OnPlatformDeviceRemoved,
-                                base::Unretained(self), device));
+          FROM_HERE, base::BindOnce(&UsbServiceImpl::OnPlatformDeviceRemoved,
+                                    base::Unretained(self), std::move(device)));
       break;
     default:
       NOTREACHED();
@@ -527,29 +538,26 @@
   return 0;
 }
 
-void UsbServiceImpl::OnPlatformDeviceAdded(PlatformUsbDevice platform_device) {
+void UsbServiceImpl::OnPlatformDeviceAdded(
+    ScopedLibusbDeviceRef platform_device) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK(!base::ContainsKey(platform_devices_, platform_device));
-  EnumerateDevice(platform_device, base::DoNothing());
-  libusb_unref_device(platform_device);
+  DCHECK(!base::ContainsKey(platform_devices_, platform_device.get()));
+  EnumerateDevice(std::move(platform_device), base::DoNothing());
 }
 
 void UsbServiceImpl::OnPlatformDeviceRemoved(
-    PlatformUsbDevice platform_device) {
+    ScopedLibusbDeviceRef platform_device) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  PlatformDeviceMap::iterator it = platform_devices_.find(platform_device);
-  if (it != platform_devices_.end()) {
+  auto it = platform_devices_.find(platform_device.get());
+  if (it == platform_devices_.end())
+    devices_being_enumerated_.erase(platform_device.get());
+  else
     RemoveDevice(it->second);
-  } else {
-    devices_being_enumerated_.erase(platform_device);
-  }
-  libusb_unref_device(platform_device);
 }
 
-void UsbServiceImpl::EnumerationFailed(PlatformUsbDevice platform_device,
+void UsbServiceImpl::EnumerationFailed(ScopedLibusbDeviceRef platform_device,
                                        const base::Closure& refresh_complete) {
-  libusb_ref_device(platform_device);
-  ignored_devices_.insert(platform_device);
+  ignored_devices_.push_back(std::move(platform_device));
   refresh_complete.Run();
 }
 
diff --git a/device/usb/usb_service_impl.h b/device/usb/usb_service_impl.h
index 5d3dc89..eaf669d 100644
--- a/device/usb/usb_service_impl.h
+++ b/device/usb/usb_service_impl.h
@@ -11,11 +11,14 @@
 
 #include <map>
 #include <set>
+#include <vector>
 
 #include "base/containers/queue.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/optional.h"
 #include "build/build_config.h"
+#include "device/usb/scoped_libusb_device_ref.h"
 #include "device/usb/usb_context.h"
 #include "device/usb/usb_device_impl.h"
 #include "third_party/libusb/src/libusb/libusb.h"
@@ -25,12 +28,10 @@
 #include "device/base/device_monitor_win.h"
 #endif  // OS_WIN
 
-struct libusb_device;
 struct libusb_context;
 
 namespace device {
 
-typedef struct libusb_device* PlatformUsbDevice;
 typedef struct libusb_context* PlatformUsbContext;
 
 class UsbDeviceImpl;
@@ -60,11 +61,12 @@
 
   // Enumerate USB devices from OS and update devices_ map.
   void RefreshDevices();
-  void OnDeviceList(libusb_device** platform_devices, size_t device_count);
+  void OnDeviceList(
+      base::Optional<std::vector<ScopedLibusbDeviceRef>> platform_devices);
   void RefreshDevicesComplete();
 
   // Creates a new UsbDevice based on the given libusb device.
-  void EnumerateDevice(PlatformUsbDevice platform_device,
+  void EnumerateDevice(ScopedLibusbDeviceRef platform_device,
                        const base::Closure& refresh_complete);
 
   void AddDevice(const base::Closure& refresh_complete,
@@ -73,16 +75,16 @@
 
   // Handle hotplug events from libusb.
   static int LIBUSB_CALL HotplugCallback(libusb_context* context,
-                                         PlatformUsbDevice device,
+                                         libusb_device* device,
                                          libusb_hotplug_event event,
                                          void* user_data);
   // These functions release a reference to the provided platform device.
-  void OnPlatformDeviceAdded(PlatformUsbDevice platform_device);
-  void OnPlatformDeviceRemoved(PlatformUsbDevice platform_device);
+  void OnPlatformDeviceAdded(ScopedLibusbDeviceRef platform_device);
+  void OnPlatformDeviceRemoved(ScopedLibusbDeviceRef platform_device);
 
   // Add |platform_device| to the |ignored_devices_| and
   // run |refresh_complete|.
-  void EnumerationFailed(PlatformUsbDevice platform_device,
+  void EnumerationFailed(ScopedLibusbDeviceRef platform_device,
                          const base::Closure& refresh_complete);
 
   scoped_refptr<UsbContext> context_;
@@ -100,18 +102,20 @@
   base::queue<std::string> pending_path_enumerations_;
   std::vector<GetDevicesCallback> pending_enumeration_callbacks_;
 
-  // The map from PlatformUsbDevices to UsbDevices.
-  typedef std::map<PlatformUsbDevice, scoped_refptr<UsbDeviceImpl>>
+  // The map from libusb_device to UsbDeviceImpl. The key is a weak pointer to
+  // the libusb_device object owned by the UsbDeviceImpl.
+  typedef std::map<libusb_device*, scoped_refptr<UsbDeviceImpl>>
       PlatformDeviceMap;
   PlatformDeviceMap platform_devices_;
 
   // The set of devices that only need to be enumerated once and then can be
   // ignored (for example, hub devices, devices that failed enumeration, etc.).
-  std::set<PlatformUsbDevice> ignored_devices_;
+  std::vector<ScopedLibusbDeviceRef> ignored_devices_;
 
-  // Tracks PlatformUsbDevices that might be removed while they are being
-  // enumerated.
-  std::set<PlatformUsbDevice> devices_being_enumerated_;
+  // Tracks libusb_devices that might be removed while they are being
+  // enumerated. This is a weak pointer to a libusb_device object owned by a
+  // UsbDeviceImpl.
+  std::set<libusb_device*> devices_being_enumerated_;
 
 #if defined(OS_WIN)
   ScopedObserver<DeviceMonitorWin, DeviceMonitorWin::Observer> device_observer_;
diff --git a/docs/README.md b/docs/README.md
index 777b543..975dcb5b 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -194,7 +194,7 @@
     on crash dumping a process running in a seccomp sandbox.
 *   [Linux Password Storage](linux_password_storage.md) - Keychain integrations
     between Chromium and Linux.
-*   [Linux Sublime Development](linux_sublime_dev.md) - Using Sublime as an IDE
+*   [Linux Sublime Development](sublime_ide.md) - Using Sublime as an IDE
     for Chromium development on Linux.
 *   [Building and Debugging GTK](linux_building_debug_gtk.md) - Building
     Chromium against GTK using lower optimization levels and/or more debugging
diff --git a/docs/cipd.md b/docs/cipd.md
new file mode 100644
index 0000000..17eb176f
--- /dev/null
+++ b/docs/cipd.md
@@ -0,0 +1,216 @@
+# CIPD for chromium dependencies
+
+This document outlines how to use [CIPD][1] for managing binary dependencies in
+chromium.
+
+[TOC]
+
+## Adding a new CIPD dependency
+
+### 1. Set up a new directory for your dependency
+
+You'll first want somewhere in the repository in which your dependency will
+live. For third-party dependencies, this should typically be a subdirectory
+of `//third_party`. You'll need to add the same set of things to that
+directory that you'd add for a non-CIPD dependency -- OWNERS, README.chromium,
+etc.
+
+For example, if you want to add a package named `sample_cipd_dep`, you might
+create the following:
+
+```
+  third_party/
+    sample_cipd_dep/
+      LICENSE
+      OWNERS
+      README.chromium
+```
+
+For more on third-party dependencies, see [here][2].
+
+### 2. Acquire whatever you want to package
+
+Build it, download it, whatever. Once you've done that, lay it out
+in your local checkout the way you want it to be laid out in a typical
+checkout.
+
+Staying with the example from above, if you want to add a package named
+`sample_cipd_dep` that consists of two JARs, `foo.jar` and `bar.jar`, you might
+lay them out like so:
+
+```
+  third_party/
+    sample_cipd_dep/
+      ...
+      lib/
+        bar.jar
+        foo.jar
+```
+
+### 3. Create a cipd.yaml file
+
+CIPD knows how to create your package based on a .yaml file you provide to it.
+The .yaml file should take the following form:
+
+```
+# Comments are allowed.
+
+# The package name is required. Third-party chromium dependencies should
+# unsurprisingly all be prefixed with chromium/third_party/.
+package: chromium/third_party/sample_cipd_dep
+
+# The description is optional and is solely for the reader's benefit. It
+# isn't used in creating the CIPD package.
+description: A sample CIPD dependency.
+
+# The root is optional and, if unspecified, defaults to ".". It specifies the
+# root directory of the files and directories specified below in "data".
+#
+# You won't typically need to specify this explicitly.
+root: "."
+
+# The install mode is optional. If provided, it specifies how CIPD should
+# install a package: "copy", which will copy the contents of the package
+# to the installation directory; and "symlink", which will create symlinks
+# to the contents of the package in the CIPD root inside the installation
+# directory.
+#
+# You won't typically need to specify this explicitly.
+install_mode: "symlink"
+
+# The data is required and described what should be included in the CIPD
+# package.
+data:
+  # Data can include directories, files, or a version file.
+
+  - dir: "directory_name"
+
+    # Directories can include an optional "exclude" list of regexes.
+    # Files or directories within the given directory that match any of
+    # the provided regexes will not be included in the CIPD package.
+    exclude:
+      - .*\.pyc
+      - exclude_me
+      - keep_this/but_not_this
+
+  - file: keep_this_file.bin
+
+  # If included, CIPD will dump package version information to this path
+  # at package installation.
+  - version_file: CIPD_VERSION.json
+```
+
+For example, for `sample_cipd_dep`, we might write the following .yaml file:
+
+```
+package: chromium/third_party/sample_cipd_dep
+description: A sample CIPD dependency.
+data:
+  - file: bar.jar
+  - file: foo.jar
+```
+
+For more information about the package definition spec, see [the code][3].
+
+> **Note:** Committing the .yaml file to the repository isn't required,
+> but it is recommended. Doing so has benefits for visibility and ease of
+> future updates.
+
+### 4. Create your CIPD package
+
+To actually create your package, you'll need:
+
+ - the cipd.yaml file (described above)
+ - a package version. For third-party packages, this should typically include
+   the version of the third-party package itself. If you want to support future
+   modifications within a given version of a third-party package (e.g., if you
+   want to make chromium-specific changes), it's best to include a suffix with
+   a numerical component.
+ - [permission](#permissions-in-cipd).
+
+Once you have those, you can create your package like so:
+
+```
+# Assuming that the third-party dependency in question is at version 1.2.3
+# and this is the first chromium revision of that version.
+$ cipd create --pkg-def cipd.yaml -tag version:1.2.3-cr0
+```
+
+### 5. Add your CIPD package to DEPS
+
+You can add your package to DEPS by adding an entry of the following form to
+the `deps` dict:
+
+```
+deps = {
+  # ...
+
+  # This is the installation directory.
+  'src/third_party/sample_cipd_dep': {
+
+    # In this example, we're only installing one package in this location,
+    # but installing multiple package in a location is supported.
+    'packages': [
+      {
+        'package': 'chromium/third_party/sample_cipd_dep',
+        'version': 'version:1.2.3-cr0',
+      },
+    ],
+
+    # As with git-based DEPS entries, 'condition' is optional.
+    'condition': 'checkout_android',
+    'dep_type': 'cipd',
+  },
+
+  # ...
+}
+```
+
+This will result in CIPD package `chromium/third_party/sample_cipd_dep` at
+`version:1.2.3-cr0` being installed in `src/third_party/sample_cipd_dep`
+(relative to the gclient root directory).
+
+## Updating a CIPD dependency
+
+To modify a CIPD dependency, follow steps 2, 3, and 4 above, then modify the
+version listed in DEPS.
+
+## Miscellaneous
+
+### Permissions in CIPD
+
+You can check a package's ACLs with `cipd acl-list`:
+
+```
+$ cipd acl-list chromium/third_party/sample_cipd_dep
+...
+```
+
+Permissions in CIPD are handled hierarchically. You can check entries higher
+in the package hierarcy with `cipd acl-list`, too:
+
+```
+$ cipd acl-list chromium
+...
+```
+
+By default, [cria/project-chromium-cipd-owners][4] own all CIPD packages
+under `chromium/`. If you're adding a package, talk to one of them.
+
+## Troubleshooting
+
+ - **A file maintained by CIPD is missing, and gclient sync doesn't recreate it.**
+
+CIPD currently caches installation state. Modifying packages managed by CIPD
+will invalidate this cache in a way that CIPD doesn't detect - i.e., CIPD will
+assume that anything it installed is still installed, even if you deleted it.
+To clear the cache and force a full reinstallation, delete your
+`$GCLIENT_ROOT/.cipd` directory.
+
+Note that there is a [bug](crbug.com/794764) on file to add a mode to CIPD
+that is not so trusting of its own cache.
+
+[1]: https://chromium.googlesource.com/infra/luci/luci-go/+/master/cipd/
+[2]: /docs/adding_to_third_party.md
+[3]: https://chromium.googlesource.com/infra/luci/luci-go/+/master/cipd/client/cipd/local/pkgdef.go
+[4]: https://chrome-infra-auth.appspot.com/auth/groups/project-chromium-cipd-owners
diff --git a/docs/code_reviews.md b/docs/code_reviews.md
index 3be8a9a1..08af713 100644
--- a/docs/code_reviews.md
+++ b/docs/code_reviews.md
@@ -14,14 +14,13 @@
 for each directory you are touching. If you have doubts, look at the git blame
 for the file and the `OWNERS` files (see below).
 
-To indicate a positive review, the reviewer chooses "+1" in Code-Review field
-on Gerrit, or types "LGTM" (case insensitive) into a comment on Rietveld. This
-stands for "Looks Good To Me." "-1" in Code-Review field on Gerrit or the text
-"not LGTM" on Rietveld will cancel out a previous positive review.
+To indicate a positive review, the reviewer provides a "Code-Review +1" in
+Gerrit, also known as an LGTM ("Looks Good To Me"). A score of "-1" indicates
+the change should not be submitted as-is.
 
-If you have multiple reviewers, make it clear in the message you send
-requesting review what you expect from each reviewer. Otherwise people might
-assume their input is not required or waste time with redundant reviews.
+If you have multiple reviewers, provide a message indicating what you expect
+from each reviewer. Otherwise people might assume their input is not required
+or waste time with redundant reviews.
 
 Please also read [Respectful Changes](cl_respect.md) and
 [Respectful Code Reviews](cr_respect.md).
@@ -29,15 +28,15 @@
 #### Expectations for all reviewers
 
   * Aim to provide some kind of actionable response within 24 hours of receipt
-    (not counting weekends and holidays). This doesn't mean you have to have
-    done a complete review, but you should be able to give some initial
-    feedback, request more time, or suggest another reviewer.
+    (not counting weekends and holidays). This doesn't mean you have to do a
+    complete review, but you should be able to give some initial feedback,
+    request more time, or suggest another reviewer.
 
-  * It can be nice to indicate if you're away in your name in the code review
-    tool. If you do this, indicate when you'll be back.
+  * Use the status field in Gerrit settings to indicate if you're away and when
+  * you'll be back.
 
   * Don't generally discourage people from sending you code reviews. This
-    includes writing a blanket ("slow") after your name in the review tool.
+    includes using a blanket "slow" in your status field.
 
 ## OWNERS files
 
@@ -130,8 +129,6 @@
     reviewer2: Please review changes to bar/
     ```
 
-  * Push the "send mail" button.
-
 ### TBR-ing certain types of mechanical changes
 
 Sometimes you might do something that affects many callers in different
diff --git a/docs/fuchsia_sdk_updates.md b/docs/fuchsia_sdk_updates.md
index b8962d67..b78abf8 100644
--- a/docs/fuchsia_sdk_updates.md
+++ b/docs/fuchsia_sdk_updates.md
@@ -4,7 +4,7 @@
    job](https://luci-scheduler.appspot.com/jobs/fuchsia/sdk-x86_64-linux) for a
    recent green archive. On the "SUCCEEDED" link, copy the SHA-1 from the
    `gsutil.upload` link of the `upload fuchsia-sdk` step.
-0. Put that into Chromium's src.git `build/fuchsia/update_sdk.py` as `SDK_HASH`.
+0. Put that into Chromium's src.git `build/fuchsia/sdk.sha1`.
 0. `gclient sync && ninja ...` and make sure things go OK locally.
 0. Upload the roll CL, making sure to include the `fuchsia` trybot. Tag the roll
    with `Bug: 707030`.
@@ -31,4 +31,4 @@
 `cipd describe fuchsia/sdk/linux-amd64 -version <CIPD_HASH_HERE>`
 
 This description will show the `jiri_snapshot` "tag" for the CIPD package which
-corresponds to the SDK revision that's specified `update_sdk.py` here.
+corresponds to the SDK revision that's specified in `sdk.sha1` here.
diff --git a/docs/memory-infra/heap_profiler.md b/docs/memory-infra/heap_profiler.md
index 6a3ad2da..9cb8bf0 100644
--- a/docs/memory-infra/heap_profiler.md
+++ b/docs/memory-infra/heap_profiler.md
@@ -62,7 +62,8 @@
 
  3. Scroll down all the way to _Heap Details_.
 
- 4. Pinpoint the memory bug and live happily ever after.
+ 4. To navigate allocations, select a frame in the right-side pane and press
+    Enter/Return. To pop up the stack, press Backspace/Delete.
 
 [memory-infra]:    README.md
 [m-purple]:        https://storage.googleapis.com/chromium-docs.appspot.com/d7bdf4d16204c293688be2e5a0bcb2bf463dbbc3
diff --git a/docs/memory/debugging_memory_issues.md b/docs/memory/debugging_memory_issues.md
index 1ebd696..209f1a6 100644
--- a/docs/memory/debugging_memory_issues.md
+++ b/docs/memory/debugging_memory_issues.md
@@ -71,11 +71,11 @@
 real, high impact bugs being found in Chrome code ~90% of the time.
 
 * The first thing to do upon receiving a heap dump is to open it in the [trace
-  viewer](/docs/memory-infra/README.md). This will tell us the counts, sizes, and
-  allocating stack traces of the potentially leaked objects. Look for stacks
-  that result in >100 MB of live memory. Frequently, sets of objects will be
-  leaked with similar counts. This can provide insight into the nature of the
-  leak.
+  viewer](/docs/memory-infra/heap_profiler.md#how-to-manually-browse-a-heap-dump).
+  This will tell us the counts, sizes, and allocating stack traces of the
+  potentially leaked objects. Look for stacks that result in >100 MB of live
+  memory. Frequently, sets of objects will be leaked with similar counts. This
+  can provide insight into the nature of the leak.
     * Important note: Heap profiling in the field uses
       [poison process sampling](https://bugs.chromium.org/p/chromium/issues/detail?id=810748)
       with a rate parameter of 10000. This means that for large/frequent allocations
diff --git a/docs/security/mojo.md b/docs/security/mojo.md
index 7bc70770..8dfa241 100644
--- a/docs/security/mojo.md
+++ b/docs/security/mojo.md
@@ -320,7 +320,7 @@
 *   JSON: use `mojo.common.mojom.Value`, not `string`.
 *   Mojo interfaces: use `Interface` or `Interface&`, not `handle` or
     `handle<message_pipe>`.
-*   Nonces: use `mojo.common.mojom.UnguessableToken`, not `string`.
+*   Nonces: use `mojo_base.mojom.UnguessableToken`, not `string`.
 *   Origins: use `url.mojom.Origin`, not `url.mojom.Url` and certainly not
     `string`.
 *   Time types: use `mojo_base.mojom.TimeDelta` /
diff --git a/docs/sublime_ide.md b/docs/sublime_ide.md
index 6b39096..e3297d3 100644
--- a/docs/sublime_ide.md
+++ b/docs/sublime_ide.md
@@ -300,6 +300,8 @@
     cd SublimeClang
     # Copy libclang.so to the internals dir
     cp /usr/lib/llvm-3.9/lib/libclang.so.1 internals/libclang.so
+    # Fix src/main.cpp (shared_ptr -> std::shared_ptr)
+    sed -i -- 's/shared_ptr/std::shared_ptr/g' src/main.cpp
     # Make the project - should be really quick, since libclang.so is already built
     cd src && mkdir build && cd build
     cmake ..
@@ -460,7 +462,7 @@
     "cmd": ["ninja", "-j", "1000", "-C", "out/Debug", "chrome"],
 ```
 
-**Regex explanation:** Aims to capture these these error formats while respecting
+**Regex explanation:** Aims to capture these error formats while respecting
 [Sublime's perl-like group matching](http://docs.sublimetext.info/en/latest/reference/build_systems/configuration.html#build-capture-error-output):
 
 1.  `d:\src\chrome\src\base\threading\sequenced_worker_pool.cc(670): error
diff --git a/docs/webui_in_components.md b/docs/webui_in_components.md
index b808bd22..b06c0c16 100644
--- a/docs/webui_in_components.md
+++ b/docs/webui_in_components.md
@@ -241,8 +241,8 @@
 +
 +   // Register callback handler.
 +   RegisterMessageCallback("addNumbers",
-+       base::Bind(&HelloWorldUI::AddNumbers,
-+                  base::Unretained(this)));
++       base::BindRepeating(&HelloWorldUI::AddNumbers,
++                           base::Unretained(this)));
 
     // Localized strings.
 ...
diff --git a/docs/win_cross.md b/docs/win_cross.md
index 2ba25ad..c263974 100644
--- a/docs/win_cross.md
+++ b/docs/win_cross.md
@@ -62,9 +62,9 @@
 
 You can run the Windows binaries you built on swarming, like so:
 
-    tools/run_swarmed.py -C out/gnwin -t base_unittests [ --gtest_filter=... ]
+    tools/run-swarmed.py -C out/gnwin -t base_unittests [ --gtest_filter=... ]
 
-See the contents of run_swarmed.py for how to do this manually.
+See the contents of run-swarmed.py for how to do this manually.
 
 There's a bot doing 64-bit release cross builds at
 https://ci.chromium.org/buildbot/chromium.clang/linux-win_cross-rel/
diff --git a/extensions/browser/api/audio/audio_device_id_calculator_unittest.cc b/extensions/browser/api/audio/audio_device_id_calculator_unittest.cc
index d4ecd1a..287dcdc9 100644
--- a/extensions/browser/api/audio/audio_device_id_calculator_unittest.cc
+++ b/extensions/browser/api/audio/audio_device_id_calculator_unittest.cc
@@ -5,6 +5,7 @@
 #include "extensions/browser/api/audio/audio_device_id_calculator.h"
 #include "components/prefs/testing_pref_service.h"
 #include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "extensions/browser/api/audio/audio_api.h"
 #include "extensions/browser/test_extensions_browser_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -51,6 +52,7 @@
   content::BrowserContext* browser_context() { return &browser_context_; }
 
  private:
+  content::TestBrowserThreadBundle thread_bundle_;
   content::TestBrowserContext browser_context_;
   TestExtensionsBrowserClientWithPrefService test_browser_client_;
 
diff --git a/extensions/browser/api/bluetooth/bluetooth_event_router_unittest.cc b/extensions/browser/api/bluetooth/bluetooth_event_router_unittest.cc
index f41e6e7..ad7d3e4 100644
--- a/extensions/browser/api/bluetooth/bluetooth_event_router_unittest.cc
+++ b/extensions/browser/api/bluetooth/bluetooth_event_router_unittest.cc
@@ -12,7 +12,6 @@
 #include "base/memory/ref_counted.h"
 #include "base/run_loop.h"
 #include "content/public/test/test_browser_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "device/bluetooth/bluetooth_common.h"
 #include "device/bluetooth/bluetooth_uuid.h"
 #include "device/bluetooth/test/mock_bluetooth_adapter.h"
@@ -42,8 +41,7 @@
 class BluetoothEventRouterTest : public ExtensionsTest {
  public:
   BluetoothEventRouterTest()
-      : ExtensionsTest(std::make_unique<content::TestBrowserThreadBundle>()),
-        mock_adapter_(new testing::StrictMock<device::MockBluetoothAdapter>()) {
+      : mock_adapter_(new testing::StrictMock<device::MockBluetoothAdapter>()) {
   }
 
   void SetUp() override {
diff --git a/extensions/browser/api/file_handlers/mime_util_unittest.cc b/extensions/browser/api/file_handlers/mime_util_unittest.cc
index 50ba11b..409b0a016 100644
--- a/extensions/browser/api/file_handlers/mime_util_unittest.cc
+++ b/extensions/browser/api/file_handlers/mime_util_unittest.cc
@@ -12,7 +12,6 @@
 #include "base/files/file_util.h"
 #include "base/run_loop.h"
 #include "content/public/browser/browser_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_utils.h"
 #include "extensions/browser/api/extensions_api_client.h"
 #include "extensions/browser/extensions_test.h"
@@ -51,8 +50,7 @@
 
 class FileHandlersMimeUtilTest : public ExtensionsTest {
  protected:
-  FileHandlersMimeUtilTest()
-      : ExtensionsTest(std::make_unique<content::TestBrowserThreadBundle>()) {}
+  FileHandlersMimeUtilTest() {}
   ~FileHandlersMimeUtilTest() override {}
 
   void SetUp() override {
diff --git a/extensions/browser/api/lock_screen_data/lock_screen_item_storage_unittest.cc b/extensions/browser/api/lock_screen_data/lock_screen_item_storage_unittest.cc
index bd918d7..18fd7c2 100644
--- a/extensions/browser/api/lock_screen_data/lock_screen_item_storage_unittest.cc
+++ b/extensions/browser/api/lock_screen_data/lock_screen_item_storage_unittest.cc
@@ -28,7 +28,6 @@
 #include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "components/user_prefs/user_prefs.h"
 #include "content/public/test/test_browser_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "extensions/browser/api/lock_screen_data/data_item.h"
 #include "extensions/browser/api/lock_screen_data/lock_screen_value_store_migrator.h"
 #include "extensions/browser/api/lock_screen_data/operation_result.h"
@@ -452,8 +451,7 @@
 
 class LockScreenItemStorageTest : public ExtensionsTest {
  public:
-  LockScreenItemStorageTest()
-      : ExtensionsTest(std::make_unique<content::TestBrowserThreadBundle>()) {}
+  LockScreenItemStorageTest() = default;
   ~LockScreenItemStorageTest() override = default;
 
   void SetUp() override {
diff --git a/extensions/browser/api/media_perception_private/media_perception_api_manager_unittest.cc b/extensions/browser/api/media_perception_private/media_perception_api_manager_unittest.cc
index a7666a1..0addbf7 100644
--- a/extensions/browser/api/media_perception_private/media_perception_api_manager_unittest.cc
+++ b/extensions/browser/api/media_perception_private/media_perception_api_manager_unittest.cc
@@ -168,8 +168,8 @@
   TestUpstartClient* upstart_client_;
 
  private:
-  content::TestBrowserContext browser_context_;
   content::TestBrowserThreadBundle thread_bundle_;
+  content::TestBrowserContext browser_context_;
 
   DISALLOW_COPY_AND_ASSIGN(MediaPerceptionAPIManagerTest);
 };
diff --git a/extensions/browser/api/storage/storage_frontend_unittest.cc b/extensions/browser/api/storage/storage_frontend_unittest.cc
index 0e4b565..82e49c85 100644
--- a/extensions/browser/api/storage/storage_frontend_unittest.cc
+++ b/extensions/browser/api/storage/storage_frontend_unittest.cc
@@ -12,7 +12,6 @@
 #include "base/strings/string_number_conversions.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/test/test_browser_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_utils.h"
 #include "extensions/browser/api/extensions_api_client.h"
 #include "extensions/browser/api/storage/settings_namespace.h"
@@ -39,9 +38,6 @@
 // history, the test names are unchanged.
 class ExtensionSettingsFrontendTest : public ExtensionsTest {
  public:
-  ExtensionSettingsFrontendTest()
-      : ExtensionsTest(std::make_unique<content::TestBrowserThreadBundle>()) {}
-
   void SetUp() override {
     ExtensionsTest::SetUp();
     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
diff --git a/extensions/browser/api/system_display/system_display_api.cc b/extensions/browser/api/system_display/system_display_api.cc
index fac6aac..f2f0bd00 100644
--- a/extensions/browser/api/system_display/system_display_api.cc
+++ b/extensions/browser/api/system_display/system_display_api.cc
@@ -185,6 +185,12 @@
   return true;
 }
 
+bool SystemDisplayGetInfoFunction::PreRunValidation(std::string* error) {
+  // Returns true to not block the method completely when in non-kiosk mode.
+  // Only the |edid| property is conditional to kiosk mode.
+  return true;
+}
+
 ExtensionFunction::ResponseAction SystemDisplayGetInfoFunction::Run() {
   std::unique_ptr<display::GetInfo::Params> params(
       display::GetInfo::Params::Create(*args_));
@@ -192,6 +198,12 @@
                         *params->flags->single_unified;
   DisplayInfoProvider::DisplayUnitInfoList all_displays_info =
       DisplayInfoProvider::Get()->GetAllDisplaysInfo(single_unified);
+
+  // Only |edid| is meant to be restricted to kiosk mode.
+  if (ShouldRestrictToKioskAndWebUI())
+    for (auto& display_info : all_displays_info)
+      display_info.edid.release();
+
   return RespondNow(
       ArgumentList(display::GetInfo::Results::Create(all_displays_info)));
 }
diff --git a/extensions/browser/api/system_display/system_display_api.h b/extensions/browser/api/system_display/system_display_api.h
index 3414c9f8..7434a7a 100644
--- a/extensions/browser/api/system_display/system_display_api.h
+++ b/extensions/browser/api/system_display/system_display_api.h
@@ -25,14 +25,16 @@
   virtual bool ShouldRestrictToKioskAndWebUI();
 };
 
-// This function inherits from UIThreadExtensionFunction because, unlike the
-// rest of this API, it's available on all platforms.
-class SystemDisplayGetInfoFunction : public UIThreadExtensionFunction {
+// GetInfo is a SystemDisplayFunction to limit some of the fields to kiosk mode
+// and web UI. The method itself is not kiosk-mode only.
+class SystemDisplayGetInfoFunction : public SystemDisplayFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("system.display.getInfo", SYSTEM_DISPLAY_GETINFO);
 
  protected:
   ~SystemDisplayGetInfoFunction() override {}
+
+  bool PreRunValidation(std::string* error) override;
   ResponseAction Run() override;
 };
 
diff --git a/extensions/browser/api_unittest.cc b/extensions/browser/api_unittest.cc
index cd455fd..6aefff6 100644
--- a/extensions/browser/api_unittest.cc
+++ b/extensions/browser/api_unittest.cc
@@ -14,7 +14,6 @@
 #include "content/public/common/content_client.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/test/test_browser_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/web_contents_tester.h"
 #include "extensions/browser/api_test_utils.h"
 #include "extensions/browser/extension_function.h"
@@ -29,8 +28,7 @@
 
 namespace extensions {
 
-ApiUnitTest::ApiUnitTest()
-    : ExtensionsTest(std::make_unique<content::TestBrowserThreadBundle>()) {}
+ApiUnitTest::ApiUnitTest() {}
 
 ApiUnitTest::~ApiUnitTest() {}
 
diff --git a/extensions/browser/app_window/app_window_geometry_cache_unittest.cc b/extensions/browser/app_window/app_window_geometry_cache_unittest.cc
index 6344e2b..b69d43d 100644
--- a/extensions/browser/app_window/app_window_geometry_cache_unittest.cc
+++ b/extensions/browser/app_window/app_window_geometry_cache_unittest.cc
@@ -14,7 +14,6 @@
 #include "base/strings/string_number_conversions.h"
 #include "components/prefs/mock_pref_change_callback.h"
 #include "content/public/test/test_browser_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_utils.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extensions_test.h"
@@ -41,9 +40,6 @@
 // Base class for tests.
 class AppWindowGeometryCacheTest : public ExtensionsTest {
  public:
-  AppWindowGeometryCacheTest()
-      : ExtensionsTest(std::make_unique<content::TestBrowserThreadBundle>()) {}
-
   // testing::Test overrides:
   void SetUp() override;
   void TearDown() override;
diff --git a/extensions/browser/content_hash_fetcher.cc b/extensions/browser/content_hash_fetcher.cc
index 3a674ec..05158ae 100644
--- a/extensions/browser/content_hash_fetcher.cc
+++ b/extensions/browser/content_hash_fetcher.cc
@@ -13,8 +13,9 @@
 #include "base/files/file_util.h"
 #include "base/json/json_reader.h"
 #include "base/macros.h"
-#include "base/synchronization/lock.h"
+#include "base/sequenced_task_runner.h"
 #include "base/task_scheduler/post_task.h"
+#include "base/threading/sequenced_task_runner_handle.h"
 #include "content/public/browser/browser_thread.h"
 #include "extensions/browser/content_verifier/content_hash.h"
 #include "extensions/browser/content_verifier_delegate.h"
@@ -25,446 +26,81 @@
 #include "net/base/load_flags.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "net/url_request/url_fetcher.h"
-#include "net/url_request/url_fetcher_delegate.h"
 #include "net/url_request/url_request_status.h"
 
 namespace extensions {
 
-namespace {
+namespace internals {
 
-std::unique_ptr<ContentHash> ReadContentHashAfterVerifiedContentsWritten(
-    const ContentHash::ExtensionKey& extension_key,
-    bool force,
-    const ContentHash::IsCancelledCallback& is_cancelled) {
-  // This function is called after writing verified_contents.json, so we'd
-  // expect a valid file at this point. Even in the case where the file turns
-  // out to be invalid right after writing it (malicous behavior?) don't delete
-  // it.
-  int mode = 0;
+ContentHashFetcher::ContentHashFetcher(
+    const ContentHash::ExtensionKey& key,
+    const ContentHash::FetchParams& fetch_params)
+    : extension_key_(key),
+      fetch_params_(fetch_params),
+      response_task_runner_(base::SequencedTaskRunnerHandle::Get()) {}
 
-  if (force)
-    mode |= ContentHash::Mode::kForceRecreateExistingComputedHashesFile;
-
-  return ContentHash::Create(extension_key, mode, is_cancelled);
-}
-
-}  // namespace
-
-// This class takes care of doing the disk and network I/O work to ensure we
-// have both verified_contents.json files from the webstore and
-// computed_hashes.json files computed over the files in an extension's
-// directory.
-class ContentHashFetcherJob
-    : public base::RefCountedThreadSafe<ContentHashFetcherJob>,
-      public net::URLFetcherDelegate {
- public:
-  using CompletionCallback =
-      base::Callback<void(scoped_refptr<ContentHashFetcherJob>)>;
-  ContentHashFetcherJob(net::URLRequestContextGetter* request_context,
-                        const ContentHash::ExtensionKey& extension_key,
-                        const GURL& fetch_url,
-                        bool force,
-                        const CompletionCallback& callback);
-
-  void Start();
-
-  // Cancels this job, which will attempt to stop I/O operations sooner than
-  // just waiting for the entire job to complete. Safe to call from any thread.
-  void Cancel();
-
-  // Checks whether this job has been cancelled. Safe to call from any thread.
-  bool IsCancelled();
-
-  // Returns whether this job was successful (we have both verified contents
-  // and computed hashes). Even if the job was a success, there might have been
-  // files that were found to have contents not matching expectations; these
-  // are available by calling hash_mismatch_unix_paths().
-  bool success() { return success_; }
-
-  bool force() const { return force_; }
-
-  const std::string& extension_id() { return extension_key_.extension_id; }
-
-  // Returns the set of paths (with unix style '/' separators) that had a hash
-  // mismatch.
-  const std::set<base::FilePath>& hash_mismatch_unix_paths() {
-    return hash_mismatch_unix_paths_;
-  }
-
- private:
-  friend class base::RefCountedThreadSafe<ContentHashFetcherJob>;
-  ~ContentHashFetcherJob() override;
-
-  // Methods called when job completes.
-  void Succeeded(const std::set<base::FilePath>& hash_mismatch_unix_paths);
-  void Failed();
-
-  // Returns content hashes after trying to load them.
-  // Invalid verified_contents.json will be removed from disk.
-  std::unique_ptr<ContentHash> LoadVerifiedContents();
-
-  // Callback for when we're done doing file I/O to see if we already have
-  // content hashes. If we don't have verified_contents.json, this will kick off
-  // a network request to get one.
-  void DoneCheckingForVerifiedContents(
-      std::unique_ptr<ContentHash> content_hash);
-
-  // URLFetcherDelegate interface
-  void OnURLFetchComplete(const net::URLFetcher* source) override;
-
-  // Callback for when we've read verified contents after fetching it from
-  // network and writing it to disk.
-  void ReadCompleteAfterWrite(std::unique_ptr<ContentHash> content_hash);
-
-  // Callback for the job to write the verified contents to the filesystem.
-  void OnVerifiedContentsWritten(size_t expected_size, int write_result);
-
-  // Will call the callback, if we haven't been cancelled.
-  void DispatchCallback();
-
-  net::URLRequestContextGetter* request_context_;
-
-  // Note: Read from multiple threads/sequences.
-  const ContentHash::ExtensionKey extension_key_;
-
-  // The url we'll need to use to fetch a verified_contents.json file.
-  GURL fetch_url_;
-
-  const bool force_;
-
-  CompletionCallback callback_;
-  content::BrowserThread::ID creation_thread_;
-
-  // Used for fetching content signatures.
-  // Created and destroyed on |creation_thread_|.
-  std::unique_ptr<net::URLFetcher> url_fetcher_;
-
-  // The parsed contents of the verified_contents.json file, either read from
-  // disk or fetched from the network and then written to disk.
-  std::unique_ptr<VerifiedContents> verified_contents_;
-
-  // Whether this job succeeded.
-  bool success_;
-
-  // Paths that were found to have a mismatching hash.
-  std::set<base::FilePath> hash_mismatch_unix_paths_;
-
-  // Note: this may be accessed from multiple threads, so all access should
-  // be protected by |cancelled_lock_|.
-  bool cancelled_;
-
-  // A lock for synchronizing access to |cancelled_|.
-  base::Lock cancelled_lock_;
-
-  DISALLOW_COPY_AND_ASSIGN(ContentHashFetcherJob);
-};
-
-ContentHashFetcherJob::ContentHashFetcherJob(
-    net::URLRequestContextGetter* request_context,
-    const ContentHash::ExtensionKey& extension_key,
-    const GURL& fetch_url,
-    bool force,
-    const CompletionCallback& callback)
-    : request_context_(request_context),
-      extension_key_(extension_key),
-      fetch_url_(fetch_url),
-      force_(force),
-      callback_(callback),
-      success_(false),
-      cancelled_(false) {
-  bool got_id =
-      content::BrowserThread::GetCurrentThreadIdentifier(&creation_thread_);
-  DCHECK(got_id);
-}
-
-void ContentHashFetcherJob::Start() {
-  base::PostTaskAndReplyWithResult(
-      GetExtensionFileTaskRunner().get(), FROM_HERE,
-      base::BindOnce(&ContentHashFetcherJob::LoadVerifiedContents, this),
-      base::BindOnce(&ContentHashFetcherJob::DoneCheckingForVerifiedContents,
-                     this));
-}
-
-void ContentHashFetcherJob::Cancel() {
-  base::AutoLock autolock(cancelled_lock_);
-  cancelled_ = true;
-}
-
-bool ContentHashFetcherJob::IsCancelled() {
-  base::AutoLock autolock(cancelled_lock_);
-  bool result = cancelled_;
-  return result;
-}
-
-ContentHashFetcherJob::~ContentHashFetcherJob() {
-  // Destroy |url_fetcher_| on correct thread.
-  // It was possible for it to be deleted on blocking pool. See
-  // https://crbug.com/702300 for details.
-  // TODO(lazyboy): Make ContentHashFetcherJob non ref-counted.
-  if (url_fetcher_ && !content::BrowserThread::CurrentlyOn(creation_thread_)) {
-    content::BrowserThread::DeleteSoon(creation_thread_, FROM_HERE,
-                                       url_fetcher_.release());
-  }
-}
-
-std::unique_ptr<ContentHash> ContentHashFetcherJob::LoadVerifiedContents() {
-  // Will delete invalid verified contents file.
-  int mode = ContentHash::Mode::kDeleteInvalidVerifiedContents;
-  if (force_)
-    mode |= ContentHash::Mode::kForceRecreateExistingComputedHashesFile;
-
-  return ContentHash::Create(
-      extension_key_, mode,
-      base::BindRepeating(&ContentHashFetcherJob::IsCancelled, this));
-}
-
-void ContentHashFetcherJob::DoneCheckingForVerifiedContents(
-    std::unique_ptr<ContentHash> content_hash) {
-  if (IsCancelled())
-    return;
-  if (content_hash->has_verified_contents()) {
-    VLOG(1) << "Found verified contents for " << extension_key_.extension_id;
-    if (content_hash->succeeded()) {
-      // We've found both verified_contents.json and computed_hashes.json, we're
-      // done.
-      Succeeded(content_hash->hash_mismatch_unix_paths());
-    } else {
-      // Even though we attempted to write computed_hashes.json after reading
-      // verified_contents.json, something went wrong.
-      Failed();
-    }
-  } else {
-    VLOG(1) << "Missing verified contents for " << extension_key_.extension_id
-            << ", fetching...";
-    net::NetworkTrafficAnnotationTag traffic_annotation =
-        net::DefineNetworkTrafficAnnotation("content_hash_verification_job", R"(
-          semantics {
-            sender: "Web Store Content Verification"
-            description:
-              "The request sent to retrieve the file required for content "
-              "verification for an extension from the Web Store."
-            trigger:
-              "An extension from the Web Store is missing the "
-              "verified_contents.json file required for extension content "
-              "verification."
-            data: "The extension id and extension version."
-            destination: GOOGLE_OWNED_SERVICE
-          }
-          policy {
-            cookies_allowed: NO
-            setting:
-              "This feature cannot be directly disabled; it is enabled if any "
-              "extension from the webstore is installed in the browser."
-            policy_exception_justification:
-              "Not implemented, not required. If the user has extensions from "
-              "the Web Store, this feature is required to ensure the "
-              "extensions match what is distributed by the store."
-          })");
-    url_fetcher_ = net::URLFetcher::Create(fetch_url_, net::URLFetcher::GET,
-                                           this, traffic_annotation);
-    url_fetcher_->SetRequestContext(request_context_);
-    url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
-                               net::LOAD_DO_NOT_SAVE_COOKIES |
-                               net::LOAD_DISABLE_CACHE);
-    url_fetcher_->SetAutomaticallyRetryOnNetworkChanges(3);
-    url_fetcher_->Start();
-  }
-}
-
-// Helper function to let us pass ownership of a string via base::Bind with the
-// contents to be written into a file. Also ensures that the directory for
-// |path| exists, creating it if needed.
-static int WriteFileHelper(const base::FilePath& path,
-                           std::unique_ptr<std::string> content) {
-  base::FilePath dir = path.DirName();
-  if (!base::CreateDirectoryAndGetError(dir, nullptr))
-    return -1;
-  return base::WriteFile(path, content->data(), content->size());
-}
-
-void ContentHashFetcherJob::OnURLFetchComplete(const net::URLFetcher* source) {
+void ContentHashFetcher::OnURLFetchComplete(const net::URLFetcher* source) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   VLOG(1) << "URLFetchComplete for " << extension_key_.extension_id
           << " is_success:" << url_fetcher_->GetStatus().is_success() << " "
-          << fetch_url_.possibly_invalid_spec();
-  // Delete |url_fetcher_| once we no longer need it.
+          << fetch_params_.fetch_url.possibly_invalid_spec();
+  DCHECK(hash_fetcher_callback_);
   std::unique_ptr<net::URLFetcher> url_fetcher = std::move(url_fetcher_);
-
-  if (IsCancelled())
-    return;
   std::unique_ptr<std::string> response(new std::string);
   if (!url_fetcher->GetStatus().is_success() ||
       !url_fetcher->GetResponseAsString(response.get())) {
-    Failed();
-    return;
+    // Failed.
+    response = nullptr;
   }
-
-  // Parse the response to make sure it is valid json (on staging sometimes it
-  // can be a login redirect html, xml file, etc. if you aren't logged in with
-  // the right cookies).  TODO(asargent) - It would be a nice enhancement to
-  // move to parsing this in a sandboxed helper (crbug.com/372878).
-  std::unique_ptr<base::Value> parsed(base::JSONReader::Read(*response));
-  if (!parsed) {
-    Failed();
-    return;
-  }
-
-  VLOG(1) << "JSON parsed ok for " << extension_key_.extension_id;
-
-  parsed.reset();  // no longer needed
-  base::FilePath destination =
-      file_util::GetVerifiedContentsPath(extension_key_.extension_root);
-  size_t size = response->size();
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
-      // TODO(lazyboy): Consider creating VerifiedContents directly from
-      // |response| instead of reading the file again.
-      base::BindOnce(&WriteFileHelper, destination, base::Passed(&response)),
-      base::BindOnce(&ContentHashFetcherJob::OnVerifiedContentsWritten, this,
-                     size));
+  response_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(std::move(hash_fetcher_callback_), extension_key_,
+                     fetch_params_, std::move(response)));
+  delete this;
 }
 
-void ContentHashFetcherJob::OnVerifiedContentsWritten(size_t expected_size,
-                                                      int write_result) {
-  bool success =
-      write_result >= 0 && static_cast<size_t>(write_result) == expected_size;
+void ContentHashFetcher::Start(HashFetcherCallback hash_fetcher_callback) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  if (!success) {
-    Failed();
-    return;
-  }
+  hash_fetcher_callback_ = std::move(hash_fetcher_callback);
 
-  base::PostTaskAndReplyWithResult(
-      GetExtensionFileTaskRunner().get(), FROM_HERE,
-      // TODO(lazyboy): Consider creating VerifiedContents directly from
-      // |response| instead of reading the file again.
-      base::BindOnce(
-          &ReadContentHashAfterVerifiedContentsWritten, extension_key_, force_,
-          base::BindRepeating(&ContentHashFetcherJob::IsCancelled, this)),
-      base::BindOnce(&ContentHashFetcherJob::ReadCompleteAfterWrite, this));
+  net::NetworkTrafficAnnotationTag traffic_annotation =
+      net::DefineNetworkTrafficAnnotation("content_hash_verification_job", R"(
+        semantics {
+          sender: "Web Store Content Verification"
+          description:
+            "The request sent to retrieve the file required for content "
+            "verification for an extension from the Web Store."
+          trigger:
+            "An extension from the Web Store is missing the "
+            "verified_contents.json file required for extension content "
+            "verification."
+          data: "The extension id and extension version."
+          destination: GOOGLE_OWNED_SERVICE
+        }
+        policy {
+          cookies_allowed: NO
+          setting:
+            "This feature cannot be directly disabled; it is enabled if any "
+            "extension from the webstore is installed in the browser."
+          policy_exception_justification:
+            "Not implemented, not required. If the user has extensions from "
+            "the Web Store, this feature is required to ensure the "
+            "extensions match what is distributed by the store."
+        })");
+  url_fetcher_ = net::URLFetcher::Create(
+      fetch_params_.fetch_url, net::URLFetcher::GET, this, traffic_annotation);
+  url_fetcher_->SetRequestContext(fetch_params_.request_context);
+  url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
+                             net::LOAD_DO_NOT_SAVE_COOKIES |
+                             net::LOAD_DISABLE_CACHE);
+  url_fetcher_->SetAutomaticallyRetryOnNetworkChanges(3);
+  url_fetcher_->Start();
 }
 
-void ContentHashFetcherJob::ReadCompleteAfterWrite(
-    std::unique_ptr<ContentHash> content_hash) {
-  if (IsCancelled())
-    return;
-
-  if (content_hash->succeeded()) {
-    Succeeded(content_hash->hash_mismatch_unix_paths());
-  } else {
-    Failed();
-  }
-}
-
-void ContentHashFetcherJob::Failed() {
-  success_ = false;
-  DispatchCallback();
-}
-
-void ContentHashFetcherJob::Succeeded(
-    const std::set<base::FilePath>& hash_mismatch_unix_paths) {
-  success_ = true;
-
-  // TODO(lazyboy): Avoid this copy.
-  hash_mismatch_unix_paths_ = hash_mismatch_unix_paths;
-
-  DispatchCallback();
-}
-
-void ContentHashFetcherJob::DispatchCallback() {
-  {
-    base::AutoLock autolock(cancelled_lock_);
-    if (cancelled_)
-      return;
-  }
-  callback_.Run(base::WrapRefCounted(this));
-}
-
-// ----
-
-ContentHashFetcher::ContentHashFetcher(
-    net::URLRequestContextGetter* context_getter,
-    ContentVerifierDelegate* delegate,
-    const FetchCallback& callback)
-    : context_getter_(context_getter),
-      delegate_(delegate),
-      fetch_callback_(callback),
-      weak_ptr_factory_(this) {}
-
 ContentHashFetcher::~ContentHashFetcher() {
-  for (JobMap::iterator i = jobs_.begin(); i != jobs_.end(); ++i) {
-    i->second->Cancel();
-  }
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
-void ContentHashFetcher::DoFetch(const Extension* extension, bool force) {
-  DCHECK(extension);
-
-  IdAndVersion key(extension->id(), extension->version().GetString());
-  JobMap::iterator found = jobs_.find(key);
-  if (found != jobs_.end()) {
-    if (!force || found->second->force()) {
-      // Just let the existing job keep running.
-      return;
-    } else {
-      // Kill the existing non-force job, so we can start a new one below.
-      found->second->Cancel();
-      jobs_.erase(found);
-    }
-  }
-
-  // TODO(asargent) - we should do something here to remember recent attempts
-  // to fetch signatures by extension id, and use exponential backoff to avoid
-  // hammering the server when we aren't successful in getting them.
-  // crbug.com/373397
-
-  GURL url =
-      delegate_->GetSignatureFetchUrl(extension->id(), extension->version());
-  ContentHashFetcherJob* job = new ContentHashFetcherJob(
-      context_getter_,
-      ContentHash::ExtensionKey(extension->id(), extension->path(),
-                                extension->version(),
-                                delegate_->GetPublicKey()),
-      url, force,
-      // TODO(lazyboy): Use BindOnce, ContentHashFetcherJob should respond at
-      // most once.
-      base::BindRepeating(&ContentHashFetcher::JobFinished,
-                          weak_ptr_factory_.GetWeakPtr()));
-  jobs_.insert(std::make_pair(key, job));
-  job->Start();
-}
-
-void ContentHashFetcher::ExtensionLoaded(const Extension* extension) {
-  CHECK(extension);
-  DoFetch(extension, false);
-}
-
-void ContentHashFetcher::ExtensionUnloaded(const Extension* extension) {
-  CHECK(extension);
-  IdAndVersion key(extension->id(), extension->version().GetString());
-  JobMap::iterator found = jobs_.find(key);
-  if (found != jobs_.end()) {
-    found->second->Cancel();
-    jobs_.erase(found);
-  }
-}
-
-void ContentHashFetcher::JobFinished(scoped_refptr<ContentHashFetcherJob> job) {
-  if (!job->IsCancelled()) {
-    // Note: Run can result in ContentHashFetcher::ExtensionUnloaded.
-    //
-    // TODO(lazyboy): Add a unit test to cover the case where Run can result in
-    // ContentHashFetcher::ExtensionUnloaded, once https://crbug.com/702300 is
-    // fixed.
-    fetch_callback_.Run(job->extension_id(), job->success(), job->force(),
-                        job->hash_mismatch_unix_paths());
-  }
-
-  for (JobMap::iterator i = jobs_.begin(); i != jobs_.end(); ++i) {
-    if (i->second.get() == job.get()) {
-      jobs_.erase(i);
-      break;
-    }
-  }
-}
-
+}  // namespace internals
 }  // namespace extensions
diff --git a/extensions/browser/content_hash_fetcher.h b/extensions/browser/content_hash_fetcher.h
index 2ae3de8..cac3a19 100644
--- a/extensions/browser/content_hash_fetcher.h
+++ b/extensions/browser/content_hash_fetcher.h
@@ -14,72 +14,73 @@
 #include "base/files/file_path.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "extensions/browser/content_verifier/content_hash.h"
 #include "extensions/common/extension_id.h"
+#include "net/url_request/url_fetcher_delegate.h"
+
+namespace base {
+class SequencedTaskRunner;
+}
 
 namespace net {
-class URLRequestContextGetter;
+class URLFetcher;
 }
 
 namespace extensions {
-class Extension;
-class ContentHashFetcherJob;
-class ContentVerifierDelegate;
+namespace internals {
 
 // This class is responsible for getting signed expected hashes for use in
-// extension content verification. As extensions are loaded it will fetch and
-// parse/validate/cache this data as needed, including calculating expected
-// hashes for each block of each file within an extension. (These unsigned leaf
-// node block level hashes will always be checked at time of use use to make
-// sure they match the signed treehash root hash).
-class ContentHashFetcher {
+// extension content verification.
+//
+// This class takes care of doing the network I/O work to ensure we
+// have the contents of verified_contents.json files from the webstore.
+//
+// Note: This class manages its own lifetime. It deletes itself when
+// Start() completes at OnURLFetchComplete().
+//
+// Note: This class is an internal implementation detail of ContentHash and is
+// not be used independently.
+// TODO(lazyboy): Consider changing BUILD rules to enforce the above, yet
+// keeping the class unit testable.
+class ContentHashFetcher : public net::URLFetcherDelegate {
  public:
-  // A callback for when a fetch is complete. This reports back:
-  // -extension id
-  // -whether we were successful or not (have verified_contents.json and
-  // -computed_hashes.json files)
-  // -was it a forced check?
-  // -a set of unix style paths whose contents didn't match expected values
-  typedef base::Callback<
-      void(const std::string&, bool, bool, const std::set<base::FilePath>&)>
-      FetchCallback;
+  // A callback for when fetch is complete.
+  // The response contents is passed through std::unique_ptr<std::string>.
+  using HashFetcherCallback =
+      base::OnceCallback<void(const ContentHash::ExtensionKey&,
+                              const ContentHash::FetchParams&,
+                              std::unique_ptr<std::string>)>;
 
-  // The consumer of this class needs to ensure that context and delegate
-  // outlive this object.
-  ContentHashFetcher(net::URLRequestContextGetter* context_getter,
-                     ContentVerifierDelegate* delegate,
-                     const FetchCallback& callback);
-  virtual ~ContentHashFetcher();
+  ContentHashFetcher(const ContentHash::ExtensionKey& extension_key,
+                     const ContentHash::FetchParams& fetch_params);
 
-  // Explicitly ask to fetch hashes for |extension|. If |force| is true,
-  // we will always check the validity of the verified_contents.json and
-  // re-check the contents of the files in the filesystem.
-  void DoFetch(const Extension* extension, bool force);
+  // net::URLFetcherDelegate:
+  void OnURLFetchComplete(const net::URLFetcher* source) override;
 
-  // These should be called when an extension is loaded or unloaded.
-  virtual void ExtensionLoaded(const Extension* extension);
-  virtual void ExtensionUnloaded(const Extension* extension);
+  // Note: |this| is deleted once OnURLFetchComplete() completes.
+  void Start(HashFetcherCallback hash_fetcher_callback);
 
  private:
-  // Callback for when a job getting content hashes has completed.
-  void JobFinished(scoped_refptr<ContentHashFetcherJob> job);
+  friend class base::RefCounted<ContentHashFetcher>;
 
-  net::URLRequestContextGetter* context_getter_;
-  ContentVerifierDelegate* delegate_;
-  FetchCallback fetch_callback_;
+  ~ContentHashFetcher() override;
 
-  // We keep around pointers to in-progress jobs, both so we can avoid
-  // scheduling duplicate work if fetching is already in progress, and so that
-  // we can cancel in-progress work at shutdown time.
-  typedef std::pair<ExtensionId, std::string> IdAndVersion;
-  typedef std::map<IdAndVersion, scoped_refptr<ContentHashFetcherJob> > JobMap;
-  JobMap jobs_;
+  ContentHash::ExtensionKey extension_key_;
+  ContentHash::FetchParams fetch_params_;
 
-  // Used for binding callbacks passed to jobs.
-  base::WeakPtrFactory<ContentHashFetcher> weak_ptr_factory_;
+  HashFetcherCallback hash_fetcher_callback_;
+
+  scoped_refptr<base::SequencedTaskRunner> response_task_runner_;
+
+  // Alive when url fetch is ongoing.
+  std::unique_ptr<net::URLFetcher> url_fetcher_;
+
+  SEQUENCE_CHECKER(sequence_checker_);
 
   DISALLOW_COPY_AND_ASSIGN(ContentHashFetcher);
 };
 
+}  // namespace internals
 }  // namespace extensions
 
 #endif  // EXTENSIONS_BROWSER_CONTENT_HASH_FETCHER_H_
diff --git a/extensions/browser/content_hash_fetcher_unittest.cc b/extensions/browser/content_hash_fetcher_unittest.cc
index e6ddc7ab..8edf20f 100644
--- a/extensions/browser/content_hash_fetcher_unittest.cc
+++ b/extensions/browser/content_hash_fetcher_unittest.cc
@@ -19,6 +19,7 @@
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "extensions/browser/content_hash_fetcher.h"
 #include "extensions/browser/content_verifier/test_utils.h"
+#include "extensions/browser/extension_file_task_runner.h"
 #include "extensions/browser/extensions_test.h"
 #include "extensions/common/constants.h"
 #include "extensions/common/extension_paths.h"
@@ -35,58 +36,69 @@
 struct ContentHashFetcherResult {
   std::string extension_id;
   bool success;
-  bool force;
+  bool was_cancelled;
   std::set<base::FilePath> mismatch_paths;
 };
 
-// Allows waiting for the callback from a ContentHashFetcher, returning the
+// Allows waiting for the callback from a ContentHash, returning the
 // data that was passed to that callback.
-class ContentHashFetcherWaiter {
+class ContentHashWaiter {
  public:
-  ContentHashFetcherWaiter() : weak_factory_(this) {}
+  ContentHashWaiter()
+      : reply_task_runner_(base::SequencedTaskRunnerHandle::Get()) {}
 
-  ContentHashFetcher::FetchCallback GetCallback() {
-    return base::Bind(&ContentHashFetcherWaiter::Callback,
-                      weak_factory_.GetWeakPtr());
-  }
-
-  std::unique_ptr<ContentHashFetcherResult> WaitForCallback() {
-    if (!result_) {
-      base::RunLoop run_loop;
-      run_loop_quit_ = run_loop.QuitClosure();
-      run_loop.Run();
-    }
+  std::unique_ptr<ContentHashFetcherResult> CreateAndWaitForCallback(
+      const ContentHash::ExtensionKey& key,
+      const ContentHash::FetchParams& fetch_params) {
+    GetExtensionFileTaskRunner()->PostTask(
+        FROM_HERE, base::BindOnce(&ContentHashWaiter::CreateContentHash,
+                                  base::Unretained(this), key, fetch_params));
+    run_loop_.Run();
+    DCHECK(result_);
     return std::move(result_);
   }
 
  private:
-  // Matches signature of ContentHashFetcher::FetchCallback.
-  void Callback(const std::string& extension_id,
-                bool success,
-                bool force,
-                const std::set<base::FilePath>& mismatch_paths) {
+  void CreatedCallback(const scoped_refptr<ContentHash>& content_hash,
+                       bool was_cancelled) {
+    if (!reply_task_runner_->RunsTasksInCurrentSequence()) {
+      reply_task_runner_->PostTask(
+          FROM_HERE,
+          base::BindOnce(&ContentHashWaiter::CreatedCallback,
+                         base::Unretained(this), content_hash, was_cancelled));
+      return;
+    }
+
     result_ = std::make_unique<ContentHashFetcherResult>();
-    result_->extension_id = extension_id;
-    result_->success = success;
-    result_->force = force;
-    result_->mismatch_paths = mismatch_paths;
-    if (run_loop_quit_)
-      std::move(run_loop_quit_).Run();
+    result_->extension_id = content_hash->extension_key().extension_id;
+    result_->success = content_hash->succeeded();
+    result_->was_cancelled = was_cancelled;
+    result_->mismatch_paths = content_hash->hash_mismatch_unix_paths();
+
+    run_loop_.QuitWhenIdle();
   }
 
-  base::OnceClosure run_loop_quit_;
+  void CreateContentHash(const ContentHash::ExtensionKey& key,
+                         const ContentHash::FetchParams& fetch_params) {
+    ContentHash::Create(key, fetch_params, ContentHash::IsCancelledCallback(),
+                        base::BindOnce(&ContentHashWaiter::CreatedCallback,
+                                       base::Unretained(this)));
+  }
+
+  scoped_refptr<base::SequencedTaskRunner> reply_task_runner_;
+  base::RunLoop run_loop_;
   std::unique_ptr<ContentHashFetcherResult> result_;
-  base::WeakPtrFactory<ContentHashFetcherWaiter> weak_factory_;
-  DISALLOW_COPY_AND_ASSIGN(ContentHashFetcherWaiter);
+  DISALLOW_COPY_AND_ASSIGN(ContentHashWaiter);
 };
 
+// Installs and tests various functionality of an extension loaded without
+// verified_contents.json file.
 class ContentHashFetcherTest : public ExtensionsTest {
  public:
   ContentHashFetcherTest()
       // We need a real IO thread to be able to intercept the network request
       // for the missing verified_contents.json file.
-      : ExtensionsTest(std::make_unique<content::TestBrowserThreadBundle>(
-            content::TestBrowserThreadBundle::REAL_IO_THREAD)) {
+      : ExtensionsTest(content::TestBrowserThreadBundle::REAL_IO_THREAD) {
     request_context_ = new net::TestURLRequestContextGetter(
         content::BrowserThread::GetTaskRunnerForThread(
             content::BrowserThread::IO));
@@ -121,12 +133,18 @@
       return nullptr;
     }
 
-    ContentHashFetcherWaiter waiter;
-    ContentHashFetcher fetcher(request_context(), delegate_.get(),
-                               waiter.GetCallback());
-    fetcher.DoFetch(extension_.get(), true /* force */);
-    return waiter.WaitForCallback();
+    std::unique_ptr<ContentHashFetcherResult> result =
+        ContentHashWaiter().CreateAndWaitForCallback(
+            ContentHash::ExtensionKey(extension_->id(), extension_->path(),
+                                      extension_->version(),
+                                      delegate_->GetPublicKey()),
+            ContentHash::FetchParams(request_context(), fetch_url_));
+
+    delegate_.reset();
+
+    return result;
   }
+
   const GURL& fetch_url() { return fetch_url_; }
 
   const base::FilePath& extension_root() { return extension_->path(); }
@@ -150,8 +168,7 @@
         url.scheme(), url.host(),
         content::BrowserThread::GetTaskRunnerForThread(
             content::BrowserThread::IO),
-        base::CreateTaskRunnerWithTraits(
-            {base::MayBlock(), base::TaskPriority::BACKGROUND}));
+        GetExtensionFileTaskRunner());
     interceptor_->SetResponse(url, response_path);
   }
 
@@ -207,7 +224,7 @@
   std::unique_ptr<ContentHashFetcherResult> result = DoHashFetch();
   ASSERT_TRUE(result.get());
   EXPECT_TRUE(result->success);
-  EXPECT_TRUE(result->force);
+  EXPECT_FALSE(result->was_cancelled);
   EXPECT_TRUE(result->mismatch_paths.empty());
 
   // Make sure the verified_contents.json file was written into the extension's
@@ -230,7 +247,7 @@
   std::unique_ptr<ContentHashFetcherResult> result = DoHashFetch();
   ASSERT_TRUE(result.get());
   EXPECT_FALSE(result->success);
-  EXPECT_TRUE(result->force);
+  EXPECT_FALSE(result->was_cancelled);
   EXPECT_TRUE(result->mismatch_paths.empty());
 
   // TODO(lazyboy): This should be EXPECT_FALSE, we shouldn't be writing
@@ -252,7 +269,7 @@
   std::unique_ptr<ContentHashFetcherResult> result = DoHashFetch();
   ASSERT_TRUE(result.get());
   EXPECT_FALSE(result->success);
-  EXPECT_TRUE(result->force);
+  EXPECT_FALSE(result->was_cancelled);
   EXPECT_TRUE(result->mismatch_paths.empty());
 
   // Make sure the verified_contents.json file was *not* written into the
@@ -277,7 +294,7 @@
   std::unique_ptr<ContentHashFetcherResult> result = DoHashFetch();
   ASSERT_NE(nullptr, result.get());
   EXPECT_TRUE(result->success);
-  EXPECT_TRUE(result->force);
+  EXPECT_FALSE(result->was_cancelled);
   EXPECT_TRUE(
       base::ContainsKey(result->mismatch_paths, script_path.BaseName()));
 
diff --git a/extensions/browser/content_hash_reader.cc b/extensions/browser/content_hash_reader.cc
index 0fd580c..bce1e66 100644
--- a/extensions/browser/content_hash_reader.cc
+++ b/extensions/browser/content_hash_reader.cc
@@ -8,6 +8,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_util.h"
+#include "base/threading/thread_restrictions.h"
 #include "base/timer/elapsed_timer.h"
 #include "base/values.h"
 #include "crypto/sha2.h"
@@ -24,16 +25,13 @@
 
 // static.
 std::unique_ptr<const ContentHashReader> ContentHashReader::Create(
-    const ExtensionId& extension_id,
-    const base::Version& extension_version,
-    const base::FilePath& extension_root,
     const base::FilePath& relative_path,
-    const ContentVerifierKey& key) {
+    const scoped_refptr<const ContentHash>& content_hash) {
+  base::AssertBlockingAllowed();
   base::ElapsedTimer timer;
 
-  std::unique_ptr<ContentHash> content_hash =
-      ContentHash::Create(ContentHash::ExtensionKey(
-          extension_id, extension_root, extension_version, key));
+  const ContentHash::ExtensionKey& extension_key =
+      content_hash->extension_key();
   auto hash_reader = base::WrapUnique(new ContentHashReader);
 
   if (!content_hash->succeeded())
@@ -47,7 +45,8 @@
   // verified_contents.json. This can happen when an extension sends an XHR to a
   // resource.
   if (!verified_contents.HasTreeHashRoot(relative_path)) {
-    base::FilePath full_path = extension_root.Append(relative_path);
+    base::FilePath full_path =
+        extension_key.extension_root.Append(relative_path);
     // Making a request to a non-existent file or to a directory should not
     // result in content verification failure.
     // TODO(proberge): This logic could be simplified if |content_verify_job|
diff --git a/extensions/browser/content_hash_reader.h b/extensions/browser/content_hash_reader.h
index 265fcc66..07daf5e 100644
--- a/extensions/browser/content_hash_reader.h
+++ b/extensions/browser/content_hash_reader.h
@@ -18,6 +18,8 @@
 
 namespace extensions {
 
+class ContentHash;
+
 // This class creates an object that will read expected hashes that may have
 // been fetched/calculated by the ContentHashFetcher, and vends them out for
 // use in ContentVerifyJob's.
@@ -31,11 +33,8 @@
   // instance whose succees/failure can be determined by calling succeeded()
   // method. On failure, this object should likely be discarded.
   static std::unique_ptr<const ContentHashReader> Create(
-      const ExtensionId& extension_id,
-      const base::Version& extension_version,
-      const base::FilePath& extension_root,
       const base::FilePath& relative_path,
-      const ContentVerifierKey& key);
+      const scoped_refptr<const ContentHash>& content_hash);
 
   bool succeeded() const { return status_ == SUCCESS; }
 
diff --git a/extensions/browser/content_verifier.cc b/extensions/browser/content_verifier.cc
index 41defa93..93953458 100644
--- a/extensions/browser/content_verifier.cc
+++ b/extensions/browser/content_verifier.cc
@@ -9,14 +9,17 @@
 #include <vector>
 
 #include "base/files/file_path.h"
+#include "base/memory/weak_ptr.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/threading/thread_restrictions.h"
 #include "content/public/browser/browser_context.h"
-#include "content/public/browser/browser_thread.h"
 #include "content/public/browser/storage_partition.h"
 #include "extensions/browser/content_hash_fetcher.h"
+#include "extensions/browser/content_hash_reader.h"
 #include "extensions/browser/content_verifier_delegate.h"
-#include "extensions/browser/content_verifier_io_data.h"
+#include "extensions/browser/extension_file_task_runner.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/management_policy.h"
 #include "extensions/common/constants.h"
@@ -56,6 +59,221 @@
 
 }  // namespace
 
+// A class to retrieve ContentHash for ContentVerifier.
+//
+// All public calls originate and terminate on IO, making it suitable for
+// ContentVerifier to cache ContentHash instances easily.
+// TODO(lazyboy): Implement caching.
+//
+// This class makes sure we do not have more than one ContentHash request in
+// flight for a particular version of an extension. If a call to retrieve an
+// extensions's ContentHash is made while another retieval for the same
+// version of the extension is in flight, this class will queue up the
+// callback(s) and respond to all of them when ContentHash is available.
+class ContentVerifier::HashHelper {
+ public:
+  explicit HashHelper(ContentVerifier* content_verifier)
+      : content_verifier_(content_verifier), weak_factory_(this) {}
+  ~HashHelper() {
+    DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+    // TODO(lazyboy): Do we need to Cancel() the callacks?
+  }
+
+  // Cancels any ongoing computed_hashes.json disk write for an extension.
+  void Cancel(const ExtensionId& extension_id,
+              const base::Version& extension_version) {
+    DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+    auto callback_key = std::make_pair(extension_id, extension_version);
+    auto iter = callback_infos_.find(callback_key);
+    if (iter == callback_infos_.end())
+      return;
+    iter->second.Cancel();
+    callback_infos_.erase(iter);
+  }
+
+  // Retrieves the ContentHash of an extension and responds via |callback|.
+  //
+  // Must be called on IO thread. The method responds through |callback| on IO
+  // thread.
+  void GetContentHash(const ContentHash::ExtensionKey& extension_key,
+                      const ContentHash::FetchParams& fetch_params,
+                      bool force_missing_computed_hashes_creation,
+                      ContentHashCallback callback) {
+    DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+    auto callback_key = std::make_pair(extension_key.extension_id,
+                                       extension_key.extension_version);
+    auto iter = callback_infos_.find(callback_key);
+    if (iter != callback_infos_.end()) {
+      iter->second.callbacks.push_back(std::move(callback));
+      iter->second.force_missing_computed_hashes_creation |=
+          force_missing_computed_hashes_creation;
+      return;
+    }
+    scoped_refptr<IsCancelledChecker> checker =
+        base::MakeRefCounted<IsCancelledChecker>();
+    auto iter_pair = callback_infos_.emplace(
+        callback_key, CallbackInfo(checker, std::move(callback)));
+    DCHECK(iter_pair.second);
+    iter_pair.first->second.force_missing_computed_hashes_creation |=
+        force_missing_computed_hashes_creation;
+
+    GetExtensionFileTaskRunner()->PostTask(
+        FROM_HERE,
+        base::BindOnce(
+            &HashHelper::ReadHashOnFileTaskRunner, extension_key, fetch_params,
+            base::BindRepeating(&IsCancelledChecker::IsCancelled, checker),
+            base::BindOnce(&HashHelper::DidReadHash, weak_factory_.GetWeakPtr(),
+                           callback_key)));
+  }
+
+ private:
+  using CallbackKey = std::pair<ExtensionId, base::Version>;
+
+  class IsCancelledChecker
+      : public base::RefCountedThreadSafe<IsCancelledChecker> {
+   public:
+    IsCancelledChecker() {}
+
+    // Safe to call from any thread.
+    void Cancel() {
+      base::AutoLock autolock(cancelled_lock_);
+      cancelled_ = true;
+    }
+    // Safe to call from any thread.
+    bool IsCancelled() {
+      base::AutoLock autolock(cancelled_lock_);
+      return cancelled_;
+    }
+
+   private:
+    friend class base::RefCountedThreadSafe<IsCancelledChecker>;
+
+    ~IsCancelledChecker() {}
+
+    // Note: this may be accessed from multiple threads, so all access should
+    // be protected by |cancelled_lock_|.
+    bool cancelled_ = false;
+
+    // A lock for synchronizing access to |cancelled_|.
+    base::Lock cancelled_lock_;
+
+    DISALLOW_COPY_AND_ASSIGN(IsCancelledChecker);
+  };
+
+  // Holds information about each call to HashHelper::GetContentHash(), for a
+  // particular extension (id and version).
+  //
+  // |callbacks| are the callbacks that callers to GetContentHash() passed us.
+  // |cancelled_checker| is used to cancel an extension's task from any thread.
+  // |force_missing_computed_hashes_creation| is true if any callback (from
+  //     ContentVerifyJob) requested to recompute computed_hashes.json file in
+  //     case the file is missing or cannot be read.
+  struct CallbackInfo {
+    CallbackInfo(const scoped_refptr<IsCancelledChecker>& cancelled_checker,
+                 ContentHashCallback callback)
+        : cancelled_checker(cancelled_checker) {
+      callbacks.push_back(std::move(callback));
+    }
+
+    void Cancel() { cancelled_checker->Cancel(); }
+
+    scoped_refptr<IsCancelledChecker> cancelled_checker;
+    // TODO(lazyboy): Use std::list?
+    std::vector<ContentHashCallback> callbacks;
+    bool force_missing_computed_hashes_creation = false;
+  };
+
+  using IsCancelledCallback = base::RepeatingCallback<bool(void)>;
+
+  static void ForwardToIO(ContentHash::CreatedCallback callback,
+                          const scoped_refptr<ContentHash>& content_hash,
+                          bool was_cancelled) {
+    // If the request was cancelled, then we don't have a corresponding entry
+    // for the request in |callback_infos_| anymore.
+    if (was_cancelled)
+      return;
+
+    content::BrowserThread::PostTask(
+        content::BrowserThread::IO, FROM_HERE,
+        base::BindOnce(std::move(callback), content_hash, was_cancelled));
+  }
+
+  static void ReadHashOnFileTaskRunner(
+      const ContentHash::ExtensionKey& extension_key,
+      const ContentHash::FetchParams& fetch_params,
+      const IsCancelledCallback& is_cancelled,
+      ContentHash::CreatedCallback created_callback) {
+    ContentHash::Create(
+        extension_key, fetch_params, is_cancelled,
+        base::BindOnce(&HashHelper::ForwardToIO, std::move(created_callback)));
+  }
+
+  static void ForceBuildComputedHashesOnFileTaskRuner(
+      const scoped_refptr<ContentHash> content_hash,
+      const IsCancelledCallback& is_cancelled,
+      ContentHash::CreatedCallback created_callback) {
+    content_hash->ForceBuildComputedHashes(
+        is_cancelled,
+        base::BindOnce(&HashHelper::ForwardToIO, std::move(created_callback)));
+  }
+
+  void DidReadHash(const CallbackKey& key,
+                   const scoped_refptr<ContentHash>& content_hash,
+                   bool was_cancelled) {
+    auto iter = callback_infos_.find(key);
+    DCHECK(iter != callback_infos_.end());
+    auto& callback_info = iter->second;
+
+    // Force creation of computed_hashes.json if all of the following are true:
+    //   - any caller(s) has explicitly requested it.
+    //   - hash retrieval failed due to invalid computed_hashes.json and
+    //     re-creating the file might make the hash retrieval successful.
+    if (callback_info.force_missing_computed_hashes_creation &&
+        content_hash->might_require_computed_hashes_force_creation()) {
+      GetExtensionFileTaskRunner()->PostTask(
+          FROM_HERE,
+          base::BindOnce(&HashHelper::ForceBuildComputedHashesOnFileTaskRuner,
+                         content_hash,
+                         base::BindRepeating(&IsCancelledChecker::IsCancelled,
+                                             callback_info.cancelled_checker),
+                         base::BindOnce(&HashHelper::CompleteDidReadHash,
+                                        weak_factory_.GetWeakPtr(), key)));
+      return;
+    }
+
+    CompleteDidReadHash(key, std::move(content_hash), was_cancelled);
+  }
+
+  void CompleteDidReadHash(const CallbackKey& key,
+                           const scoped_refptr<ContentHash>& content_hash,
+                           bool was_cancelled) {
+    DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+    DCHECK(!was_cancelled);
+
+    auto iter = callback_infos_.find(key);
+    DCHECK(iter != callback_infos_.end());
+    auto& callback_info = iter->second;
+
+    for (auto& callback : callback_info.callbacks)
+      std::move(callback).Run(content_hash);
+    callback_infos_.erase(iter);
+
+    DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+
+    // OnFetchComplete will check content_hash->hash_mismatch_unix_paths():
+    content_verifier_->OnFetchComplete(content_hash);
+  }
+
+  // List of pending callbacks of GetContentHash().
+  std::map<CallbackKey, CallbackInfo> callback_infos_;
+
+  ContentVerifier* const content_verifier_ = nullptr;
+
+  base::WeakPtrFactory<HashHelper> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(HashHelper);
+};
+
 // static
 bool ContentVerifier::ShouldRepairIfCorrupted(
     const ManagementPolicy* management_policy,
@@ -75,11 +293,9 @@
     : shutdown_(false),
       context_(context),
       delegate_(std::move(delegate)),
-      fetcher_(new ContentHashFetcher(
+      request_context_getter_(
           content::BrowserContext::GetDefaultStoragePartition(context)
-              ->GetURLRequestContext(),
-          delegate_.get(),
-          base::Bind(&ContentVerifier::OnFetchComplete, this))),
+              ->GetURLRequestContext()),
       observer_(this),
       io_data_(new ContentVerifierIOData) {}
 
@@ -99,7 +315,7 @@
       FROM_HERE,
       base::Bind(&ContentVerifierIOData::Clear, io_data_));
   observer_.RemoveAll();
-  fetcher_.reset();
+  hash_helper_.reset();
 }
 
 ContentVerifyJob* ContentVerifier::CreateJobFor(
@@ -124,23 +340,57 @@
   // a cache of ContentHashReader's that we hold onto past the end of each job.
   return new ContentVerifyJob(
       extension_id, data->version, extension_root, normalized_unix_path,
-      delegate_->GetPublicKey(),
       base::BindOnce(&ContentVerifier::VerifyFailed, this, extension_id));
 }
 
-void ContentVerifier::VerifyFailed(const std::string& extension_id,
+void ContentVerifier::GetContentHash(
+    const ExtensionId& extension_id,
+    const base::FilePath& extension_root,
+    const base::Version& extension_version,
+    bool force_missing_computed_hashes_creation,
+    ContentHashCallback callback) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+  if (shutdown_) {
+    // NOTE: Release |callback| asynchronously, so that we don't release ref of
+    // ContentVerifyJob and possibly destroy it synchronously here while
+    // ContentVerifyJob is holding a lock. The lock destroyer would fail DCHECK
+    // in that case.
+    // TODO(lazyboy): Make CreateJobFor return a scoped_refptr instead of raw
+    // pointer to fix this. Also add unit test to exercise this code path
+    // explicitly.
+    content::BrowserThread::PostTask(
+        content::BrowserThread::IO, FROM_HERE,
+        base::BindOnce(base::DoNothing::Once<ContentHashCallback>(),
+                       std::move(callback)));
+    return;
+  }
+
+  ContentHash::ExtensionKey extension_key(extension_id, extension_root,
+                                          extension_version,
+                                          delegate_->GetPublicKey());
+  ContentHash::FetchParams fetch_params =
+      GetFetchParams(extension_id, extension_version);
+  // Since |shutdown_| = false, GetOrCreateHashHelper() must return non-nullptr
+  // instance of HashHelper.
+  GetOrCreateHashHelper()->GetContentHash(
+      extension_key, fetch_params, force_missing_computed_hashes_creation,
+      std::move(callback));
+}
+
+void ContentVerifier::VerifyFailed(const ExtensionId& extension_id,
                                    ContentVerifyJob::FailureReason reason) {
   if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
     content::BrowserThread::PostTask(
-        content::BrowserThread::UI,
-        FROM_HERE,
-        base::Bind(&ContentVerifier::VerifyFailed, this, extension_id, reason));
+        content::BrowserThread::UI, FROM_HERE,
+        base::BindOnce(&ContentVerifier::VerifyFailed, this, extension_id,
+                       reason));
     return;
   }
   if (shutdown_)
     return;
 
   VLOG(1) << "VerifyFailed " << extension_id << " reason:" << reason;
+  DCHECK_NE(ContentVerifyJob::NONE, reason);
 
   ExtensionRegistry* registry = ExtensionRegistry::Get(context_);
   const Extension* extension =
@@ -149,13 +399,15 @@
   if (!extension)
     return;
 
-  if (reason == ContentVerifyJob::MISSING_ALL_HASHES) {
-    // If we failed because there were no hashes yet for this extension, just
-    // request some.
-    fetcher_->DoFetch(extension, true /* force */);
-  } else {
-    delegate_->VerifyFailed(extension_id, reason);
+  ContentVerifierDelegate::Mode mode = delegate_->ShouldBeVerified(*extension);
+  // If the failure was due to hashes missing, only "enforce_strict" would
+  // disable the extension, but not "enforce".
+  if (reason == ContentVerifyJob::MISSING_ALL_HASHES &&
+      mode != ContentVerifierDelegate::ENFORCE_STRICT) {
+    return;
   }
+
+  delegate_->VerifyFailed(extension_id, reason);
 }
 
 void ContentVerifier::OnExtensionLoaded(
@@ -181,16 +433,27 @@
     std::unique_ptr<ContentVerifierIOData::ExtensionData> data(
         new ContentVerifierIOData::ExtensionData(std::move(image_paths),
                                                  extension->version()));
-    content::BrowserThread::PostTask(content::BrowserThread::IO,
-                                     FROM_HERE,
-                                     base::Bind(&ContentVerifierIOData::AddData,
-                                                io_data_,
-                                                extension->id(),
-                                                base::Passed(&data)));
-    fetcher_->ExtensionLoaded(extension);
+
+    content::BrowserThread::PostTask(
+        content::BrowserThread::IO, FROM_HERE,
+        base::BindOnce(&ContentVerifier::OnExtensionLoadedOnIO, this,
+                       extension->id(), extension->path(), extension->version(),
+                       std::move(data)));
   }
 }
 
+void ContentVerifier::OnExtensionLoadedOnIO(
+    const ExtensionId& extension_id,
+    const base::FilePath& extension_root,
+    const base::Version& extension_version,
+    std::unique_ptr<ContentVerifierIOData::ExtensionData> data) {
+  io_data_->AddData(extension_id, std::move(data));
+  GetContentHash(extension_id, extension_root, extension_version,
+                 false /* force_missing_computed_hashes_creation */,
+                 // HashHelper will respond directly to OnFetchComplete().
+                 base::DoNothing());
+}
+
 void ContentVerifier::OnExtensionUnloaded(
     content::BrowserContext* browser_context,
     const Extension* extension,
@@ -198,12 +461,9 @@
   if (shutdown_)
     return;
   content::BrowserThread::PostTask(
-      content::BrowserThread::IO,
-      FROM_HERE,
-      base::Bind(
-          &ContentVerifierIOData::RemoveData, io_data_, extension->id()));
-  if (fetcher_)
-    fetcher_->ExtensionUnloaded(extension);
+      content::BrowserThread::IO, FROM_HERE,
+      base::BindOnce(&ContentVerifier::OnExtensionUnloadedOnIO, this,
+                     extension->id(), extension->version()));
 }
 
 GURL ContentVerifier::GetSignatureFetchUrlForTest(
@@ -212,46 +472,42 @@
   return delegate_->GetSignatureFetchUrl(extension_id, extension_version);
 }
 
-void ContentVerifier::OnFetchCompleteHelper(
-    const std::string& extension_id,
-    bool should_verify_any_paths_result) {
-  if (should_verify_any_paths_result)
-    delegate_->VerifyFailed(extension_id, ContentVerifyJob::MISSING_ALL_HASHES);
+void ContentVerifier::OnExtensionUnloadedOnIO(
+    const ExtensionId& extension_id,
+    const base::Version& extension_version) {
+  io_data_->RemoveData(extension_id);
+  HashHelper* hash_helper = GetOrCreateHashHelper();
+  if (hash_helper)
+    hash_helper->Cancel(extension_id, extension_version);
 }
 
 void ContentVerifier::OnFetchComplete(
-    const std::string& extension_id,
-    bool success,
-    bool was_force_check,
-    const std::set<base::FilePath>& hash_mismatch_unix_paths) {
-  if (g_content_verifier_test_observer)
-    g_content_verifier_test_observer->OnFetchComplete(extension_id, success);
-
-  if (shutdown_)
-    return;
-
-  VLOG(1) << "OnFetchComplete " << extension_id << " success:" << success;
-
-  ExtensionRegistry* registry = ExtensionRegistry::Get(context_);
-  const Extension* extension =
-      registry->GetExtensionById(extension_id, ExtensionRegistry::EVERYTHING);
-  if (!delegate_ || !extension)
-    return;
-
-  ContentVerifierDelegate::Mode mode = delegate_->ShouldBeVerified(*extension);
-  if (was_force_check && !success &&
-      mode == ContentVerifierDelegate::ENFORCE_STRICT) {
-    // We weren't able to get verified_contents.json or weren't able to compute
-    // hashes.
-    delegate_->VerifyFailed(extension_id, ContentVerifyJob::MISSING_ALL_HASHES);
-  } else {
-    content::BrowserThread::PostTaskAndReplyWithResult(
-        content::BrowserThread::IO, FROM_HERE,
-        base::Bind(&ContentVerifier::ShouldVerifyAnyPaths, this, extension_id,
-                   extension->path(), hash_mismatch_unix_paths),
-        base::Bind(&ContentVerifier::OnFetchCompleteHelper, this,
-                   extension_id));
+    const scoped_refptr<const ContentHash>& content_hash) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+  ExtensionId extension_id = content_hash->extension_key().extension_id;
+  if (g_content_verifier_test_observer) {
+    g_content_verifier_test_observer->OnFetchComplete(
+        extension_id, content_hash->has_verified_contents());
   }
+
+  VLOG(1) << "OnFetchComplete " << extension_id
+          << " success:" << content_hash->succeeded();
+
+  const bool did_hash_mismatch = ShouldVerifyAnyPaths(
+      extension_id, content_hash->extension_key().extension_root,
+      content_hash->hash_mismatch_unix_paths());
+  if (!did_hash_mismatch)
+    return;
+
+  VerifyFailed(extension_id, ContentVerifyJob::HASH_MISMATCH);
+}
+
+ContentHash::FetchParams ContentVerifier::GetFetchParams(
+    const ExtensionId& extension_id,
+    const base::Version& extension_version) {
+  return ContentHash::FetchParams(
+      request_context_getter_,
+      delegate_->GetSignatureFetchUrl(extension_id, extension_version));
 }
 
 bool ContentVerifier::ShouldVerifyAnyPaths(
@@ -312,4 +568,18 @@
   return false;
 }
 
+ContentVerifier::HashHelper* ContentVerifier::GetOrCreateHashHelper() {
+  // Just checking |hash_helper_| against nullptr isn't enough because we reset
+  // hash_helper_ in Shutdown(), and we shouldn't be re-creating it in that
+  // case.
+  if (!hash_helper_created_) {
+    DCHECK(!hash_helper_);
+    hash_helper_ =
+        std::unique_ptr<HashHelper, content::BrowserThread::DeleteOnIOThread>(
+            new HashHelper(this));
+    hash_helper_created_ = true;
+  }
+  return hash_helper_.get();
+}
+
 }  // namespace extensions
diff --git a/extensions/browser/content_verifier.h b/extensions/browser/content_verifier.h
index d89c5a9e..7601e6e 100644
--- a/extensions/browser/content_verifier.h
+++ b/extensions/browser/content_verifier.h
@@ -13,7 +13,10 @@
 #include "base/memory/ref_counted.h"
 #include "base/scoped_observer.h"
 #include "base/version.h"
+#include "content/public/browser/browser_thread.h"
+#include "extensions/browser/content_verifier/content_hash.h"
 #include "extensions/browser/content_verifier_delegate.h"
+#include "extensions/browser/content_verifier_io_data.h"
 #include "extensions/browser/content_verify_job.h"
 #include "extensions/browser/extension_registry_observer.h"
 
@@ -25,11 +28,13 @@
 class BrowserContext;
 }
 
+namespace net {
+class URLRequestContextGetter;
+}
+
 namespace extensions {
 
 class Extension;
-class ContentHashFetcher;
-class ContentVerifierIOData;
 class ManagementPolicy;
 
 // Used for managing overall content verification - both fetching content
@@ -64,7 +69,7 @@
 
   // Called (typically by a verification job) to indicate that verification
   // failed while reading some file in |extension_id|.
-  void VerifyFailed(const std::string& extension_id,
+  void VerifyFailed(const ExtensionId& extension_id,
                     ContentVerifyJob::FailureReason reason);
 
   // ExtensionRegistryObserver interface
@@ -74,6 +79,25 @@
                            const Extension* extension,
                            UnloadedExtensionReason reason) override;
 
+  using ContentHashCallback =
+      base::OnceCallback<void(const scoped_refptr<const ContentHash>&)>;
+
+  // Retrieves ContentHash for an extension through |callback|.
+  // Must be called on IO thread.
+  // |callback| is called on IO thread.
+  // |force_missing_computed_hashes_creation| should be true if
+  // computed_hashes.json is required to be created if that file is missing or
+  // unreadable.
+  // TODO(lazyboy): |force_missing_computed_hashes_creation| should always be
+  // true, handing its behavior adds extra complexity in HashHelper and this
+  // param should be removed when we can unify/fix computed_hashes.json
+  // treatment, see https://crbug.com/819832 for details.
+  void GetContentHash(const ExtensionId& extension_id,
+                      const base::FilePath& extension_root,
+                      const base::Version& extension_version,
+                      bool force_missing_computed_hashes_creation,
+                      ContentHashCallback callback);
+
   GURL GetSignatureFetchUrlForTest(const ExtensionId& extension_id,
                                    const base::Version& extension_version);
 
@@ -81,16 +105,25 @@
   DISALLOW_COPY_AND_ASSIGN(ContentVerifier);
 
   friend class base::RefCountedThreadSafe<ContentVerifier>;
+  friend class HashHelper;
   ~ContentVerifier() override;
 
-  void OnFetchComplete(
-      const std::string& extension_id,
-      bool success,
-      bool was_force_check,
-      const std::set<base::FilePath>& hash_mismatch_unix_paths);
+  class HashHelper;
 
-  void OnFetchCompleteHelper(const std::string& extension_id,
-                             bool should_verify_any_paths_result);
+  void OnFetchComplete(const scoped_refptr<const ContentHash>& content_hash);
+  ContentHash::FetchParams GetFetchParams(
+      const ExtensionId& extension_id,
+      const base::Version& extension_version);
+
+  // Performs IO thread operations after extension load.
+  void OnExtensionLoadedOnIO(
+      const ExtensionId& extension_id,
+      const base::FilePath& extension_root,
+      const base::Version& extension_version,
+      std::unique_ptr<ContentVerifierIOData::ExtensionData> data);
+  // Performs IO thread operations after extension unload.
+  void OnExtensionUnloadedOnIO(const ExtensionId& extension_id,
+                               const base::Version& extension_version);
 
   // Returns true if any of the paths in |relative_unix_paths| *should* have
   // their contents verified. (Some files get transcoded during the install
@@ -101,15 +134,26 @@
       const base::FilePath& extension_root,
       const std::set<base::FilePath>& relative_unix_paths);
 
+  // Returns the HashHelper instance, making sure we create it at most once.
+  HashHelper* GetOrCreateHashHelper();
+
   // Set to true once we've begun shutting down.
   bool shutdown_;
 
   content::BrowserContext* context_;
 
+  // Guards creation of |hash_helper_|, limiting number of creation to <= 1.
+  // Accessed only on IO thread.
+  bool hash_helper_created_ = false;
+
+  // Created and used on IO thread.
+  std::unique_ptr<HashHelper, content::BrowserThread::DeleteOnIOThread>
+      hash_helper_;
+
   std::unique_ptr<ContentVerifierDelegate> delegate_;
 
-  // For fetching content hash signatures.
-  std::unique_ptr<ContentHashFetcher> fetcher_;
+  // Used by ContentHashFetcher.
+  net::URLRequestContextGetter* request_context_getter_;
 
   // For observing the ExtensionRegistry.
   ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver> observer_;
diff --git a/extensions/browser/content_verifier/content_hash.cc b/extensions/browser/content_verifier/content_hash.cc
index 9e7b3c0f..31cd1dbf 100644
--- a/extensions/browser/content_verifier/content_hash.cc
+++ b/extensions/browser/content_verifier/content_hash.cc
@@ -6,21 +6,61 @@
 
 #include "base/files/file_enumerator.h"
 #include "base/files/file_util.h"
+#include "base/json/json_reader.h"
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/sequence_checker.h"
+#include "base/task_scheduler/post_task.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/timer/elapsed_timer.h"
+#include "content/public/browser/browser_thread.h"
 #include "crypto/sha2.h"
+#include "extensions/browser/content_hash_fetcher.h"
 #include "extensions/browser/content_hash_tree.h"
+#include "extensions/browser/extension_file_task_runner.h"
 #include "extensions/common/file_util.h"
+#include "net/base/load_flags.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
+
+namespace extensions {
 
 namespace {
 
 using SortedFilePathSet = std::set<base::FilePath>;
 
-}  // namespace
+bool WriteFile(const base::FilePath& destination, const std::string& content) {
+  base::AssertBlockingAllowed();
+  DCHECK(GetExtensionFileTaskRunner()->RunsTasksInCurrentSequence());
+  base::FilePath dir = destination.DirName();
+  if (!base::CreateDirectory(dir))
+    return false;
 
-namespace extensions {
+  int write_result =
+      base::WriteFile(destination, content.data(), content.size());
+  return write_result >= 0 &&
+         base::checked_cast<size_t>(write_result) == content.size();
+}
+
+std::unique_ptr<VerifiedContents> GetVerifiedContents(
+    const ContentHash::ExtensionKey& key,
+    bool delete_invalid_file) {
+  base::AssertBlockingAllowed();
+  DCHECK(GetExtensionFileTaskRunner()->RunsTasksInCurrentSequence());
+  auto verified_contents = std::make_unique<VerifiedContents>(
+      key.verifier_key.data, key.verifier_key.size);
+  base::FilePath verified_contents_path =
+      file_util::GetVerifiedContentsPath(key.extension_root);
+  if (!verified_contents->InitFrom(verified_contents_path)) {
+    if (delete_invalid_file &&
+        !base::DeleteFile(verified_contents_path, false)) {
+      LOG(WARNING) << "Failed to delete " << verified_contents_path.value();
+    }
+    return nullptr;
+  }
+  return verified_contents;
+}
+
+}  // namespace
 
 ContentHash::ExtensionKey::ExtensionKey(const ExtensionId& extension_id,
                                         const base::FilePath& extension_root,
@@ -37,23 +77,51 @@
 ContentHash::ExtensionKey& ContentHash::ExtensionKey::operator=(
     const ContentHash::ExtensionKey& other) = default;
 
-// static
-std::unique_ptr<ContentHash> ContentHash::Create(const ExtensionKey& key) {
-  return ContentHash::CreateImpl(key, 0 /* mode */,
-                                 false /* create_computed_hashes_file */,
-                                 IsCancelledCallback());
-}
+ContentHash::FetchParams::FetchParams(
+    net::URLRequestContextGetter* request_context,
+    const GURL& fetch_url)
+    : request_context(request_context), fetch_url(fetch_url) {}
+
+ContentHash::FetchParams::FetchParams(const FetchParams& other) = default;
+ContentHash::FetchParams& ContentHash::FetchParams::operator=(
+    const FetchParams& other) = default;
 
 // static
-std::unique_ptr<ContentHash> ContentHash::Create(
-    const ExtensionKey& key,
-    int mode,
-    const IsCancelledCallback& is_cancelled) {
-  return ContentHash::CreateImpl(
-      key, mode, true /* create_computed_hashes_file */, is_cancelled);
+void ContentHash::Create(const ExtensionKey& key,
+                         const FetchParams& fetch_params,
+                         const IsCancelledCallback& is_cancelled,
+                         CreatedCallback created_callback) {
+  base::AssertBlockingAllowed();
+  // Step 1/2: verified_contents.json:
+  std::unique_ptr<VerifiedContents> verified_contents = GetVerifiedContents(
+      key,
+      // If verified_contents.json exists on disk but is invalid, we want to
+      // delete it so we can fetch and write the file later if required.
+      true /* delete_invalid_file */);
+
+  if (!verified_contents) {
+    // Fetch verified_contents.json and then respond.
+    FetchVerifiedContents(key, fetch_params, is_cancelled,
+                          std::move(created_callback));
+    return;
+  }
+
+  // Step 2/2: computed_hashes.json:
+  scoped_refptr<ContentHash> hash =
+      new ContentHash(key, std::move(verified_contents), nullptr);
+  const bool did_fetch_verified_contents = false;
+  hash->BuildComputedHashes(did_fetch_verified_contents,
+                            false /* force_build */, is_cancelled);
+  std::move(created_callback).Run(hash, is_cancelled && is_cancelled.Run());
 }
 
-ContentHash::~ContentHash() = default;
+void ContentHash::ForceBuildComputedHashes(
+    const IsCancelledCallback& is_cancelled,
+    CreatedCallback created_callback) {
+  BuildComputedHashes(false /* did_fetch_verified_contents */,
+                      true /* force_build */, is_cancelled);
+  std::move(created_callback).Run(this, is_cancelled && is_cancelled.Run());
+}
 
 const VerifiedContents& ContentHash::verified_contents() const {
   DCHECK(status_ >= Status::kHasVerifiedContents && verified_contents_);
@@ -80,66 +148,99 @@
     status_ = Status::kSucceeded;
 }
 
+ContentHash::~ContentHash() = default;
+
 // static
-std::unique_ptr<ContentHash> ContentHash::CreateImpl(
-    const ExtensionKey& key,
-    int mode,
-    bool create_computed_hashes_file,
-    const IsCancelledCallback& is_cancelled) {
+void ContentHash::FetchVerifiedContents(
+    const ContentHash::ExtensionKey& extension_key,
+    const ContentHash::FetchParams& fetch_params,
+    const ContentHash::IsCancelledCallback& is_cancelled,
+    ContentHash::CreatedCallback created_callback) {
+  // |fetcher| deletes itself when it's done.
+  internals::ContentHashFetcher* fetcher =
+      new internals::ContentHashFetcher(extension_key, fetch_params);
+  fetcher->Start(base::BindOnce(&ContentHash::DidFetchVerifiedContents,
+                                std::move(created_callback), is_cancelled));
+}
+
+// static
+void ContentHash::DidFetchVerifiedContents(
+    ContentHash::CreatedCallback created_callback,
+    const ContentHash::IsCancelledCallback& is_cancelled,
+    const ContentHash::ExtensionKey& key,
+    const ContentHash::FetchParams& fetch_params,
+    std::unique_ptr<std::string> fetched_contents) {
   base::AssertBlockingAllowed();
+  if (!fetched_contents) {
+    ContentHash::DispatchFetchFailure(key, std::move(created_callback),
+                                      is_cancelled);
+    return;
+  }
 
-  // verified_contents.json:
-  base::FilePath verified_contents_path =
+  // Write file and continue reading hash.
+  // Write:
+  // Parse the response to make sure it is valid json (on staging sometimes it
+  // can be a login redirect html, xml file, etc. if you aren't logged in with
+  // the right cookies).  TODO(asargent) - It would be a nice enhancement to
+  // move to parsing this in a sandboxed helper (https://crbug.com/372878).
+  std::unique_ptr<base::Value> parsed =
+      base::JSONReader::Read(*fetched_contents);
+  if (!parsed) {
+    ContentHash::DispatchFetchFailure(key, std::move(created_callback),
+                                      is_cancelled);
+    return;
+  }
+
+  VLOG(1) << "JSON parsed ok for " << key.extension_id;
+  parsed.reset();  // no longer needed
+
+  base::FilePath destination =
       file_util::GetVerifiedContentsPath(key.extension_root);
-  if (!base::PathExists(verified_contents_path)) {
-    // kInvalid.
-    return base::WrapUnique(new ContentHash(key, nullptr, nullptr));
+  if (!WriteFile(destination, *fetched_contents)) {
+    LOG(ERROR) << "Error writing computed_hashes.json at " << destination;
+    ContentHash::DispatchFetchFailure(key, std::move(created_callback),
+                                      is_cancelled);
+    return;
   }
 
-  auto verified_contents = std::make_unique<VerifiedContents>(
-      key.verifier_key.data, key.verifier_key.size);
-  if (!verified_contents->InitFrom(verified_contents_path)) {
-    if (mode & Mode::kDeleteInvalidVerifiedContents) {
-      if (!base::DeleteFile(verified_contents_path, false))
-        LOG(WARNING) << "Failed to delete " << verified_contents_path.value();
-    }
-    // kInvalid.
-    return base::WrapUnique(new ContentHash(key, nullptr, nullptr));
+  // Continue reading hash.
+  std::unique_ptr<VerifiedContents> verified_contents = GetVerifiedContents(
+      key,
+      // We've just fetched verified_contents.json, so treat it as a read-only
+      // file from now on and do not delete the file even if it turns out to be
+      // invalid.
+      false /* delete_invalid_file */);
+
+  if (!verified_contents) {
+    ContentHash::DispatchFetchFailure(key, std::move(created_callback),
+                                      is_cancelled);
+    return;
   }
 
-  // computed_hashes.json: create if necessary.
-  base::FilePath computed_hashes_path =
-      file_util::GetComputedHashesPath(key.extension_root);
+  scoped_refptr<ContentHash> hash =
+      new ContentHash(key, std::move(verified_contents), nullptr);
+  const bool did_fetch_verified_contents = true;
+  hash->BuildComputedHashes(did_fetch_verified_contents,
+                            false /* force_build */, is_cancelled);
+  std::move(created_callback).Run(hash, is_cancelled && is_cancelled.Run());
+}
 
-  std::unique_ptr<ContentHash> hash = base::WrapUnique(
-      new ContentHash(key, std::move(verified_contents), nullptr));
-  if (create_computed_hashes_file) {
-    // If force recreate wasn't requested, existence of computed_hashes.json is
-    // enough, otherwise create computed_hashes.json.
-    bool need_to_create =
-        (mode & Mode::kForceRecreateExistingComputedHashesFile) != 0 ||
-        !base::PathExists(computed_hashes_path);
-    if (need_to_create)
-      hash->CreateHashes(computed_hashes_path, is_cancelled);
-  }
-
-  // computed_hashes.json: read.
-  if (!base::PathExists(computed_hashes_path))
-    return hash;
-
-  auto computed_hashes = std::make_unique<ComputedHashes::Reader>();
-  if (!computed_hashes->InitFromFile(computed_hashes_path))
-    return hash;
-
-  hash->status_ = Status::kSucceeded;
-  hash->computed_hashes_ = std::move(computed_hashes);
-
-  return hash;
+// static
+void ContentHash::DispatchFetchFailure(
+    const ExtensionKey& key,
+    CreatedCallback created_callback,
+    const IsCancelledCallback& is_cancelled) {
+  // NOTE: bare new because ContentHash constructor is private.
+  scoped_refptr<ContentHash> content_hash =
+      new ContentHash(key, nullptr, nullptr);
+  std::move(created_callback)
+      .Run(content_hash, is_cancelled && is_cancelled.Run());
 }
 
 bool ContentHash::CreateHashes(const base::FilePath& hashes_file,
                                const IsCancelledCallback& is_cancelled) {
   base::ElapsedTimer timer;
+  did_attempt_creating_computed_hashes_ = true;
   // Make sure the directory exists.
   if (!base::CreateDirectoryAndGetError(hashes_file.DirName(), nullptr))
     return false;
@@ -203,4 +304,58 @@
   return result;
 }
 
+void ContentHash::BuildComputedHashes(bool attempted_fetching_verified_contents,
+                                      bool force_build,
+                                      const IsCancelledCallback& is_cancelled) {
+  base::FilePath computed_hashes_path =
+      file_util::GetComputedHashesPath(key_.extension_root);
+
+  // Create computed_hashes.json file if any of the following is true:
+  // - We just fetched and wrote a verified_contents.json (i.e.
+  //   |attempted_fetching_verified_contents| = true).
+  // - computed_hashes.json is missing.
+  // - existing computed_hashes.json cannot be initialized correctly (probably
+  //   due to disk corruption).
+  //  bool will_create = attempted_fetching_verified_contents ||
+  //                     !base::PathExists(computed_hashes_path);
+
+  // However, existing behavior is to create computed_hashes.json only when
+  // ContentVerifyJob's request to computed_hashes.json fails.
+  // TODO(lazyboy): Fix this and use |will_create| condition from the comment
+  // above, see https://crbug.com/819832 for details.
+  bool will_create = force_build || !base::PathExists(computed_hashes_path);
+  if (!will_create) {
+    // Note: Tolerate for existing implementation.
+    // Try to read and initialize the file first. On failure, continue creating.
+    auto computed_hashes = std::make_unique<ComputedHashes::Reader>();
+    if (!computed_hashes->InitFromFile(computed_hashes_path)) {
+      // TODO(lazyboy): Also create computed_hashes.json in this case. See the
+      // comment above about |will_create|.
+      // will_create = true;
+    } else {
+      // Read successful.
+      status_ = Status::kSucceeded;
+      computed_hashes_ = std::move(computed_hashes);
+      return;
+    }
+  }
+
+  if (will_create && !CreateHashes(computed_hashes_path, is_cancelled)) {
+    // Failed creating computed_hashes.json.
+    return;
+  }
+
+  // Read computed_hashes.json:
+  if (!base::PathExists(computed_hashes_path))
+    return;
+
+  auto computed_hashes = std::make_unique<ComputedHashes::Reader>();
+  if (!computed_hashes->InitFromFile(computed_hashes_path))
+    return;
+
+  // Read successful.
+  status_ = Status::kSucceeded;
+  computed_hashes_ = std::move(computed_hashes);
+}
+
 }  // namespace extensions
diff --git a/extensions/browser/content_verifier/content_hash.h b/extensions/browser/content_verifier/content_hash.h
index df5f7c9..4e7d8079 100644
--- a/extensions/browser/content_verifier/content_hash.h
+++ b/extensions/browser/content_verifier/content_hash.h
@@ -15,12 +15,17 @@
 #include "extensions/browser/verified_contents.h"
 #include "extensions/common/constants.h"
 #include "extensions/common/extension_id.h"
+#include "url/gurl.h"
+
+namespace net {
+class URLRequestContextGetter;
+}
 
 namespace extensions {
 
 // Represents content verification hashes for an extension.
 //
-// Instances can be created using Create() factory methods on sequences with
+// Instances can be created using Create() factory method on sequences with
 // blocking IO access. If hash retrieval succeeds then ContentHash::succeeded()
 // will return true and
 // a. ContentHash::verified_contents() will return structured representation of
@@ -28,11 +33,23 @@
 // b. ContentHash::computed_hashes() will return structured representation of
 //    computed_hashes.json.
 //
-// Additionally if computed_hashes.json was required to be written to disk and
+// If verified_contents.json was missing on disk (e.g. because of disk
+// corruption or such), this class will fetch the file from network. After
+// fetching the class will parse/validate this data as needed, including
+// calculating expected hashes for each block of each file within an extension.
+// (These unsigned leaf node block level hashes will always be checked at time
+// of use use to make sure they match the signed treehash root hash).
+//
+// computed_hashes.json is computed over the files in an extension's directory.
+// If computed_hashes.json was required to be written to disk and
 // it was successful, ContentHash::hash_mismatch_unix_paths() will return all
 // FilePaths from the extension directory that had content verification
 // mismatch.
-class ContentHash {
+//
+// Clients of this class can cancel the disk write operation of
+// computed_hashes.json while it is ongoing. This is because it can potentially
+// take long time. This cancellation can be performed through |is_cancelled|.
+class ContentHash : public base::RefCountedThreadSafe<ContentHash> {
  public:
   // Key to identify an extension.
   struct ExtensionKey {
@@ -51,30 +68,39 @@
     ExtensionKey& operator=(const ExtensionKey& other);
   };
 
-  // Specifiable modes for ContentHash instantiation.
-  enum Mode {
-    // Deletes verified_contents.json if the file on disk is invalid.
-    kDeleteInvalidVerifiedContents = 1 << 0,
+  // Parameters to fetch verified_contents.json.
+  struct FetchParams {
+    net::URLRequestContextGetter* request_context;
+    GURL fetch_url;
 
-    // Always creates computed_hashes.json (as opposed to only when the file is
-    // non-existent).
-    kForceRecreateExistingComputedHashesFile = 1 << 1,
+    FetchParams(net::URLRequestContextGetter* request_context,
+                const GURL& fetch_url);
+
+    FetchParams(const FetchParams& other);
+    FetchParams& operator=(const FetchParams& other);
   };
 
   using IsCancelledCallback = base::RepeatingCallback<bool(void)>;
 
-  // Factories:
-  // These will never return nullptr, but verified_contents or computed_hashes
-  // may be empty if something fails.
-  // Reads existing hashes from disk.
-  static std::unique_ptr<ContentHash> Create(const ExtensionKey& key);
-  // Reads existing hashes from disk, with specifying flags from |Mode|.
-  static std::unique_ptr<ContentHash> Create(
-      const ExtensionKey& key,
-      int mode,
-      const IsCancelledCallback& is_cancelled);
+  // Factory:
+  // Returns ContentHash through |created_callback|, the returned values are:
+  //   - |hash| The content hash. This will never be nullptr, but
+  //     verified_contents or computed_hashes may be empty if something fails.
+  //   - |was_cancelled| Indicates whether or not the request was cancelled
+  //     through |is_cancelled|, while it was being processed.
+  using CreatedCallback =
+      base::OnceCallback<void(const scoped_refptr<ContentHash>& hash,
+                              bool was_cancelled)>;
+  static void Create(const ExtensionKey& key,
+                     const FetchParams& fetch_params,
+                     const IsCancelledCallback& is_cancelled,
+                     CreatedCallback created_callback);
 
-  ~ContentHash();
+  // Forces creation of computed_hashes.json. Must be called with after
+  // |verified_contents| has been successfully set.
+  // TODO(lazyboy): Remove this once https://crbug.com/819832 is fixed.
+  void ForceBuildComputedHashes(const IsCancelledCallback& is_cancelled,
+                                CreatedCallback created_callback);
 
   const VerifiedContents& verified_contents() const;
   const ComputedHashes::Reader& computed_hashes() const;
@@ -86,11 +112,22 @@
 
   // If ContentHash creation writes computed_hashes.json, then this returns the
   // FilePaths whose content hash didn't match expected hashes.
-  const std::set<base::FilePath>& hash_mismatch_unix_paths() {
+  const std::set<base::FilePath>& hash_mismatch_unix_paths() const {
     return hash_mismatch_unix_paths_;
   }
+  const ExtensionKey extension_key() const { return key_; }
+
+  // Returns whether or not computed_hashes.json re-creation might be required
+  // for |this| to succeed.
+  // TODO(lazyboy): Remove this once https://crbug.com/819832 is fixed.
+  bool might_require_computed_hashes_force_creation() const {
+    return !succeeded() && has_verified_contents() &&
+           !did_attempt_creating_computed_hashes_;
+  }
 
  private:
+  friend class base::RefCountedThreadSafe<ContentHash>;
+
   enum class Status {
     // Retrieving hashes failed.
     kInvalid,
@@ -105,12 +142,22 @@
   ContentHash(const ExtensionKey& key,
               std::unique_ptr<VerifiedContents> verified_contents,
               std::unique_ptr<ComputedHashes::Reader> computed_hashes);
+  ~ContentHash();
 
-  static std::unique_ptr<ContentHash> CreateImpl(
+  static void FetchVerifiedContents(const ExtensionKey& extension_key,
+                                    const FetchParams& fetch_params,
+                                    const IsCancelledCallback& is_cancelled,
+                                    CreatedCallback created_callback);
+  static void DidFetchVerifiedContents(
+      CreatedCallback created_callback,
+      const IsCancelledCallback& is_cancelled,
       const ExtensionKey& key,
-      int mode,
-      bool create_computed_hashes_file,
-      const IsCancelledCallback& is_cancelled);
+      const FetchParams& fetch_params,
+      std::unique_ptr<std::string> fetched_contents);
+
+  static void DispatchFetchFailure(const ExtensionKey& key,
+                                   CreatedCallback created_callback,
+                                   const IsCancelledCallback& is_cancelled);
 
   // Computes hashes for all files in |key_.extension_root|, and uses
   // a ComputedHashes::Writer to write that information into |hashes_file|.
@@ -124,9 +171,17 @@
   bool CreateHashes(const base::FilePath& hashes_file,
                     const IsCancelledCallback& is_cancelled);
 
+  // Builds computed_hashes. Possibly after creating computed_hashes.json file
+  // if necessary.
+  void BuildComputedHashes(bool attempted_fetching_verified_contents,
+                           bool force_build,
+                           const IsCancelledCallback& is_cancelled);
+
   ExtensionKey key_;
 
-  Status status_;
+  Status status_ = Status::kInvalid;
+
+  bool did_attempt_creating_computed_hashes_ = false;
 
   // TODO(lazyboy): Avoid dynamic allocations here, |this| already supports
   // move.
diff --git a/extensions/browser/content_verifier/test_utils.cc b/extensions/browser/content_verifier/test_utils.cc
index 30a5faf..e429c66 100644
--- a/extensions/browser/content_verifier/test_utils.cc
+++ b/extensions/browser/content_verifier/test_utils.cc
@@ -166,6 +166,8 @@
 
 // VerifierObserver -----------------------------------------------------------
 VerifierObserver::VerifierObserver() {
+  EXPECT_TRUE(
+      content::BrowserThread::GetCurrentThreadIdentifier(&creation_thread_));
   ContentVerifier::SetObserverForTests(this);
 }
 
@@ -174,6 +176,7 @@
 }
 
 void VerifierObserver::WaitForFetchComplete(const ExtensionId& extension_id) {
+  EXPECT_TRUE(content::BrowserThread::CurrentlyOn(creation_thread_));
   EXPECT_TRUE(id_to_wait_for_.empty());
   EXPECT_EQ(loop_runner_.get(), nullptr);
   id_to_wait_for_ = extension_id;
@@ -185,6 +188,13 @@
 
 void VerifierObserver::OnFetchComplete(const ExtensionId& extension_id,
                                        bool success) {
+  if (!content::BrowserThread::CurrentlyOn(creation_thread_)) {
+    content::BrowserThread::PostTask(
+        creation_thread_, FROM_HERE,
+        base::BindOnce(&VerifierObserver::OnFetchComplete,
+                       base::Unretained(this), extension_id, success));
+    return;
+  }
   completed_fetches_.insert(extension_id);
   if (extension_id == id_to_wait_for_)
     loop_runner_->Quit();
diff --git a/extensions/browser/content_verifier/test_utils.h b/extensions/browser/content_verifier/test_utils.h
index 1797d3a..9c83d4e 100644
--- a/extensions/browser/content_verifier/test_utils.h
+++ b/extensions/browser/content_verifier/test_utils.h
@@ -145,7 +145,12 @@
  private:
   std::set<ExtensionId> completed_fetches_;
   ExtensionId id_to_wait_for_;
+
+  // Created and accessed on |creation_thread_|.
   scoped_refptr<content::MessageLoopRunner> loop_runner_;
+  content::BrowserThread::ID creation_thread_;
+
+  DISALLOW_COPY_AND_ASSIGN(VerifierObserver);
 };
 
 namespace content_verifier_test_utils {
diff --git a/extensions/browser/content_verify_job.cc b/extensions/browser/content_verify_job.cc
index 67af8a1d..086b2fd 100644
--- a/extensions/browser/content_verify_job.cc
+++ b/extensions/browser/content_verify_job.cc
@@ -10,9 +10,12 @@
 #include "base/stl_util.h"
 #include "base/task_scheduler/post_task.h"
 #include "base/timer/elapsed_timer.h"
+#include "content/public/browser/browser_thread.h"
 #include "crypto/secure_hash.h"
 #include "crypto/sha2.h"
 #include "extensions/browser/content_hash_reader.h"
+#include "extensions/browser/content_verifier.h"
+#include "extensions/browser/content_verifier/content_hash.h"
 
 namespace extensions {
 
@@ -44,7 +47,6 @@
                                    const base::Version& extension_version,
                                    const base::FilePath& extension_root,
                                    const base::FilePath& relative_path,
-                                   const ContentVerifierKey& key,
                                    FailureCallback failure_callback)
     : done_reading_(false),
       hashes_ready_(false),
@@ -55,7 +57,6 @@
       extension_version_(extension_version),
       extension_root_(extension_root),
       relative_path_(relative_path),
-      content_verifier_key_(key),
       failure_callback_(std::move(failure_callback)),
       failed_(false) {}
 
@@ -64,16 +65,26 @@
                        time_spent_.InMicroseconds());
 }
 
-void ContentVerifyJob::Start() {
+void ContentVerifyJob::Start(ContentVerifier* verifier) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+  base::AutoLock auto_lock(lock_);
+  verifier->GetContentHash(
+      extension_id_, extension_root_, extension_version_,
+      true /* force_missing_computed_hashes_creation */,
+      base::BindOnce(&ContentVerifyJob::DidGetContentHashOnIO, this));
+}
+
+void ContentVerifyJob::DidGetContentHashOnIO(
+    const scoped_refptr<const ContentHash>& content_hash) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   base::AutoLock auto_lock(lock_);
   if (g_content_verify_job_test_observer)
     g_content_verify_job_test_observer->JobStarted(extension_id_,
                                                    relative_path_);
+  // Build |hash_reader_|.
   base::PostTaskWithTraitsAndReplyWithResult(
       FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
-      base::BindOnce(&ContentHashReader::Create, extension_id_,
-                     extension_version_, extension_root_, relative_path_,
-                     content_verifier_key_),
+      base::BindOnce(&ContentHashReader::Create, relative_path_, content_hash),
       base::BindOnce(&ContentVerifyJob::OnHashesReady, this));
 }
 
diff --git a/extensions/browser/content_verify_job.h b/extensions/browser/content_verify_job.h
index 64b2de6..9a1be99 100644
--- a/extensions/browser/content_verify_job.h
+++ b/extensions/browser/content_verify_job.h
@@ -29,7 +29,9 @@
 
 namespace extensions {
 
+class ContentHash;
 class ContentHashReader;
+class ContentVerifier;
 
 // Objects of this class are responsible for verifying that the actual content
 // read from an extension file matches an expected set of hashes. This class
@@ -59,12 +61,11 @@
                    const base::Version& extension_version,
                    const base::FilePath& extension_root,
                    const base::FilePath& relative_path,
-                   const ContentVerifierKey& content_verifier_key,
                    FailureCallback failure_callback);
 
   // This begins the process of getting expected hashes, so it should be called
   // as early as possible.
-  void Start();
+  void Start(ContentVerifier* verifier);
 
   // Call this to add more bytes to verify. If at any point the read bytes
   // don't match the expected hashes, this will dispatch the failure
@@ -100,6 +101,8 @@
   virtual ~ContentVerifyJob();
   friend class base::RefCountedThreadSafe<ContentVerifyJob>;
 
+  void DidGetContentHashOnIO(const scoped_refptr<const ContentHash>& hash);
+
   // Same as BytesRead, but is run without acquiring lock.
   void BytesReadImpl(int count, const char* data);
 
@@ -146,8 +149,6 @@
   const base::FilePath extension_root_;
   const base::FilePath relative_path_;
 
-  const ContentVerifierKey content_verifier_key_;
-
   base::TimeDelta time_spent_;
 
   // Called once if verification fails.
diff --git a/extensions/browser/content_verify_job_unittest.cc b/extensions/browser/content_verify_job_unittest.cc
index d43f0fc..e16e5c83 100644
--- a/extensions/browser/content_verify_job_unittest.cc
+++ b/extensions/browser/content_verify_job_unittest.cc
@@ -9,12 +9,18 @@
 #include "base/path_service.h"
 #include "base/version.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/test/mock_resource_context.h"
+#include "content/public/test/test_browser_context.h"
 #include "content/public/test/test_browser_thread_bundle.h"
+#include "extensions/browser/content_verifier.h"
 #include "extensions/browser/content_verifier/test_utils.h"
 #include "extensions/browser/extensions_test.h"
+#include "extensions/browser/info_map.h"
 #include "extensions/common/constants.h"
 #include "extensions/common/extension_paths.h"
 #include "extensions/common/file_util.h"
+#include "net/url_request/url_request_job_factory_impl.h"
+#include "net/url_request/url_request_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/zlib/google/zip.h"
 
@@ -42,8 +48,7 @@
  public:
   ContentVerifyJobUnittest()
       // The TestBrowserThreadBundle is needed for ContentVerifyJob::Start().
-      : ExtensionsTest(std::make_unique<content::TestBrowserThreadBundle>(
-            content::TestBrowserThreadBundle::REAL_IO_THREAD)) {}
+      : resource_context_(&test_url_request_context_) {}
   ~ContentVerifyJobUnittest() override {}
 
   // Helper to get files from our subdirectory in the general extensions test
@@ -55,6 +60,29 @@
         .AppendASCII(relative_path);
   }
 
+  void SetUp() override {
+    ExtensionsTest::SetUp();
+
+    extension_info_map_ = new InfoMap();
+    net::URLRequestContext* request_context =
+        resource_context_.GetRequestContext();
+    old_factory_ = request_context->job_factory();
+    content_verifier_ = new ContentVerifier(
+        &testing_context_, std::make_unique<MockContentVerifierDelegate>());
+    extension_info_map_->SetContentVerifier(content_verifier_.get());
+  }
+
+  void TearDown() override {
+    net::URLRequestContext* request_context =
+        resource_context_.GetRequestContext();
+    request_context->set_job_factory(old_factory_);
+    content_verifier_->Shutdown();
+
+    ExtensionsTest::TearDown();
+  }
+
+  ContentVerifier* content_verifier() { return content_verifier_.get(); }
+
  protected:
   ContentVerifyJob::FailureReason RunContentVerifyJob(
       const Extension& extension,
@@ -64,8 +92,6 @@
     TestContentVerifySingleJobObserver observer(extension.id(), resource_path);
     scoped_refptr<ContentVerifyJob> verify_job = new ContentVerifyJob(
         extension.id(), extension.version(), extension.path(), resource_path,
-        ContentVerifierKey(kWebstoreSignaturesPublicKey,
-                           kWebstoreSignaturesPublicKeySize),
         base::DoNothing());
 
     auto run_content_read_step = [](ContentVerifyJob* verify_job,
@@ -78,15 +104,15 @@
 
     switch (run_mode) {
       case kNone:
-        verify_job->Start();  // Read hashes asynchronously.
+        StartJob(verify_job);  // Read hashes asynchronously.
         run_content_read_step(verify_job.get(), &resource_contents);
         break;
       case kContentReadBeforeHashesReady:
         run_content_read_step(verify_job.get(), &resource_contents);
-        verify_job->Start();  // Read hashes asynchronously.
+        StartJob(verify_job);  // Read hashes asynchronously.
         break;
       case kHashesReadyBeforeContentRead:
-        verify_job->Start();
+        StartJob(verify_job);
         // Wait for hashes to become ready.
         observer.WaitForOnHashesReady();
         run_content_read_step(verify_job.get(), &resource_contents);
@@ -129,6 +155,21 @@
   }
 
  private:
+  void StartJob(scoped_refptr<ContentVerifyJob> job) {
+    content::BrowserThread::PostTask(
+        content::BrowserThread::IO, FROM_HERE,
+        base::BindOnce(&ContentVerifyJob::Start, job,
+                       base::Unretained(content_verifier_.get())));
+  }
+
+  scoped_refptr<InfoMap> extension_info_map_;
+  net::URLRequestJobFactoryImpl job_factory_;
+  const net::URLRequestJobFactory* old_factory_;
+  net::TestURLRequestContext test_url_request_context_;
+  content::MockResourceContext resource_context_;
+  scoped_refptr<ContentVerifier> content_verifier_;
+  content::TestBrowserContext testing_context_;
+
   DISALLOW_COPY_AND_ASSIGN(ContentVerifyJobUnittest);
 };
 
diff --git a/extensions/browser/event_listener_map_unittest.cc b/extensions/browser/event_listener_map_unittest.cc
index 2ab82e23..e4e309b9 100644
--- a/extensions/browser/event_listener_map_unittest.cc
+++ b/extensions/browser/event_listener_map_unittest.cc
@@ -12,6 +12,7 @@
 #include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_browser_context.h"
 #include "extensions/browser/event_router.h"
+#include "extensions/browser/extensions_test.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
@@ -39,14 +40,19 @@
   void OnListenerRemoved(const EventListener* listener) override {}
 };
 
-class EventListenerMapTest : public testing::Test {
+class EventListenerMapTest : public ExtensionsTest {
  public:
   EventListenerMapTest()
       : delegate_(std::make_unique<EmptyDelegate>()),
-        listeners_(std::make_unique<EventListenerMap>(delegate_.get())),
-        browser_context_(std::make_unique<content::TestBrowserContext>()),
-        process_(std::make_unique<content::MockRenderProcessHost>(
-            browser_context_.get())) {}
+        listeners_(std::make_unique<EventListenerMap>(delegate_.get())) {}
+
+  // testing::Test overrides:
+  void SetUp() override {
+    ExtensionsTest::SetUp();
+
+    // |process_| will be destroyed by |browser_context()| when it goes away.
+    process_ = new content::MockRenderProcessHost(browser_context());
+  }
 
   std::unique_ptr<DictionaryValue> CreateHostSuffixFilter(
       const std::string& suffix) {
@@ -85,8 +91,7 @@
 
   std::unique_ptr<EventListenerMap::Delegate> delegate_;
   std::unique_ptr<EventListenerMap> listeners_;
-  std::unique_ptr<content::TestBrowserContext> browser_context_;
-  std::unique_ptr<content::MockRenderProcessHost> process_;
+  content::RenderProcessHost* process_;
 };
 
 std::unique_ptr<EventListener> CreateEventListenerForExtension(
@@ -153,11 +158,8 @@
   listeners_->AddListener(EventListener::ForExtension(
       kEvent1Name, kExt1Id, nullptr, CreateHostSuffixFilter("google.com")));
 
-  listeners_->AddListener(
-      EventListener::ForExtension(kEvent1Name,
-                                  kExt1Id,
-                                  process_.get(),
-                                  CreateHostSuffixFilter("google.com")));
+  listeners_->AddListener(EventListener::ForExtension(
+      kEvent1Name, kExt1Id, process_, CreateHostSuffixFilter("google.com")));
 
   std::unique_ptr<Event> event(CreateNamedEvent(kEvent1Name));
   event->filter_info.url = GURL("http://www.google.com");
@@ -171,9 +173,9 @@
       kEvent1Name, nullptr, CreateHostSuffixFilter("google.com")));
 
   listeners_->AddListener(constructor.Run(
-      kEvent1Name, process_.get(), CreateHostSuffixFilter("google.com")));
+      kEvent1Name, process_, CreateHostSuffixFilter("google.com")));
 
-  listeners_->RemoveListenersForProcess(process_.get());
+  listeners_->RemoveListenersForProcess(process_);
 
   std::unique_ptr<Event> event(CreateNamedEvent(kEvent1Name));
   event->filter_info.url = GURL("http://www.google.com");
@@ -194,10 +196,10 @@
       kEvent1Name, nullptr, CreateHostSuffixFilter("google.com")));
 
   listeners_->AddListener(constructor.Run(
-      kEvent1Name, process_.get(), CreateHostSuffixFilter("google.com")));
+      kEvent1Name, process_, CreateHostSuffixFilter("google.com")));
 
   std::unique_ptr<EventListener> listener(constructor.Run(
-      kEvent1Name, process_.get(), CreateHostSuffixFilter("google.com")));
+      kEvent1Name, process_, CreateHostSuffixFilter("google.com")));
   listeners_->RemoveListener(listener.get());
 
   std::unique_ptr<Event> event(CreateNamedEvent(kEvent1Name));
@@ -296,13 +298,11 @@
 }
 
 TEST_F(EventListenerMapTest, RemovingRouters) {
-  listeners_->AddListener(
-      EventListener::ForExtension(kEvent1Name, kExt1Id, process_.get(),
-                                  std::unique_ptr<DictionaryValue>()));
-  listeners_->AddListener(
-      EventListener::ForURL(kEvent1Name, GURL(kURL), process_.get(),
-                            std::unique_ptr<DictionaryValue>()));
-  listeners_->RemoveListenersForProcess(process_.get());
+  listeners_->AddListener(EventListener::ForExtension(
+      kEvent1Name, kExt1Id, process_, std::unique_ptr<DictionaryValue>()));
+  listeners_->AddListener(EventListener::ForURL(
+      kEvent1Name, GURL(kURL), process_, std::unique_ptr<DictionaryValue>()));
+  listeners_->RemoveListenersForProcess(process_);
   ASSERT_FALSE(listeners_->HasListenerForEvent(kEvent1Name));
 }
 
@@ -311,11 +311,11 @@
   ASSERT_FALSE(listeners_->HasListenerForEvent(kEvent1Name));
 
   listeners_->AddListener(constructor.Run(
-      kEvent1Name, process_.get(), std::make_unique<base::DictionaryValue>()));
+      kEvent1Name, process_, std::make_unique<base::DictionaryValue>()));
 
   ASSERT_FALSE(listeners_->HasListenerForEvent(kEvent2Name));
   ASSERT_TRUE(listeners_->HasListenerForEvent(kEvent1Name));
-  listeners_->RemoveListenersForProcess(process_.get());
+  listeners_->RemoveListenersForProcess(process_);
   ASSERT_FALSE(listeners_->HasListenerForEvent(kEvent1Name));
 }
 
@@ -332,9 +332,8 @@
   ASSERT_FALSE(listeners_->HasListenerForExtension(kExt1Id, kEvent1Name));
 
   // Non-lazy listener.
-  listeners_->AddListener(
-      EventListener::ForExtension(kEvent1Name, kExt1Id, process_.get(),
-                                  std::unique_ptr<DictionaryValue>()));
+  listeners_->AddListener(EventListener::ForExtension(
+      kEvent1Name, kExt1Id, process_, std::unique_ptr<DictionaryValue>()));
   // Lazy listener.
   listeners_->AddListener(EventListener::ForExtension(
       kEvent1Name, kExt1Id, nullptr, std::unique_ptr<DictionaryValue>()));
@@ -342,7 +341,7 @@
   ASSERT_FALSE(listeners_->HasListenerForExtension(kExt1Id, kEvent2Name));
   ASSERT_TRUE(listeners_->HasListenerForExtension(kExt1Id, kEvent1Name));
   ASSERT_FALSE(listeners_->HasListenerForExtension(kExt2Id, kEvent1Name));
-  listeners_->RemoveListenersForProcess(process_.get());
+  listeners_->RemoveListenersForProcess(process_);
   ASSERT_TRUE(listeners_->HasListenerForExtension(kExt1Id, kEvent1Name));
   listeners_->RemoveListenersForExtension(kExt1Id);
   ASSERT_FALSE(listeners_->HasListenerForExtension(kExt1Id, kEvent1Name));
diff --git a/extensions/browser/event_router_unittest.cc b/extensions/browser/event_router_unittest.cc
index 8870eef..ed80fff 100644
--- a/extensions/browser/event_router_unittest.cc
+++ b/extensions/browser/event_router_unittest.cc
@@ -16,7 +16,6 @@
 #include "base/values.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/test/mock_render_process_host.h"
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "extensions/browser/event_listener_map.h"
 #include "extensions/browser/extensions_test.h"
 #include "extensions/common/extension_builder.h"
@@ -127,8 +126,7 @@
 
 class EventRouterTest : public ExtensionsTest {
  public:
-  EventRouterTest()
-      : ExtensionsTest(std::make_unique<content::TestBrowserThreadBundle>()) {}
+  EventRouterTest() = default;
 
  protected:
   // Tests adding and removing observers from EventRouter.
diff --git a/extensions/browser/extension_icon_image_unittest.cc b/extensions/browser/extension_icon_image_unittest.cc
index 68b7e972..19a4911 100644
--- a/extensions/browser/extension_icon_image_unittest.cc
+++ b/extensions/browser/extension_icon_image_unittest.cc
@@ -12,7 +12,6 @@
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "content/public/test/test_browser_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "extensions/browser/extensions_test.h"
 #include "extensions/browser/image_loader.h"
 #include "extensions/browser/test_image_loader.h"
@@ -69,9 +68,7 @@
                                public IconImage::Observer {
  public:
   ExtensionIconImageTest()
-      : ExtensionsTest(std::make_unique<content::TestBrowserThreadBundle>()),
-        image_loaded_count_(0),
-        quit_in_image_loaded_(false) {}
+      : image_loaded_count_(0), quit_in_image_loaded_(false) {}
 
   ~ExtensionIconImageTest() override {}
 
diff --git a/extensions/browser/extension_protocols.cc b/extensions/browser/extension_protocols.cc
index 46b644d..c6cd52d 100644
--- a/extensions/browser/extension_protocols.cc
+++ b/extensions/browser/extension_protocols.cc
@@ -650,7 +650,7 @@
     verify_job =
         verifier->CreateJobFor(extension_id, directory_path, relative_path);
     if (verify_job)
-      verify_job->Start();
+      verify_job->Start(verifier);
   }
 
   return new URLRequestExtensionJob(request,
@@ -964,7 +964,7 @@
                                                   resource.extension_root(),
                                                   resource.relative_path());
       if (verify_job)
-        verify_job->Start();
+        verify_job->Start(content_verifier.get());
     }
 
     content::CreateFileURLLoader(
diff --git a/extensions/browser/extension_registrar_unittest.cc b/extensions/browser/extension_registrar_unittest.cc
index 440a95b..1fac72088 100644
--- a/extensions/browser/extension_registrar_unittest.cc
+++ b/extensions/browser/extension_registrar_unittest.cc
@@ -11,7 +11,6 @@
 #include "base/optional.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "content/public/browser/browser_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_notification_tracker.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extension_registry.h"
@@ -84,8 +83,7 @@
 
 class ExtensionRegistrarTest : public ExtensionsTest {
  public:
-  ExtensionRegistrarTest()
-      : ExtensionsTest(std::make_unique<content::TestBrowserThreadBundle>()) {}
+  ExtensionRegistrarTest() = default;
   ~ExtensionRegistrarTest() override = default;
 
   void SetUp() override {
diff --git a/extensions/browser/extension_user_script_loader.cc b/extensions/browser/extension_user_script_loader.cc
index ca22f21b..0dbc734 100644
--- a/extensions/browser/extension_user_script_loader.cc
+++ b/extensions/browser/extension_user_script_loader.cc
@@ -52,7 +52,7 @@
   scoped_refptr<ContentVerifyJob> job(
       verifier->CreateJobFor(extension_id, extension_root, relative_path));
   if (job.get()) {
-    job->Start();
+    job->Start(verifier.get());
     job->BytesRead(content.size(), content.data());
     job->DoneReading();
   }
diff --git a/extensions/browser/extensions_test.cc b/extensions/browser/extensions_test.cc
index ef10b04a..a6150d1 100644
--- a/extensions/browser/extensions_test.cc
+++ b/extensions/browser/extensions_test.cc
@@ -31,12 +31,12 @@
 namespace extensions {
 
 ExtensionsTest::ExtensionsTest()
-    : rvh_test_enabler_(
-          std::make_unique<content::RenderViewHostTestEnabler>()) {}
+    : ExtensionsTest(content::TestBrowserThreadBundle::Options::DEFAULT) {}
 
 ExtensionsTest::ExtensionsTest(
-    std::unique_ptr<content::TestBrowserThreadBundle> thread_bundle)
-    : thread_bundle_(std::move(thread_bundle)),
+    content::TestBrowserThreadBundle::Options thread_options)
+    : thread_bundle_(
+          std::make_unique<content::TestBrowserThreadBundle>(thread_options)),
       rvh_test_enabler_(
           std::make_unique<content::RenderViewHostTestEnabler>()) {}
 
diff --git a/extensions/browser/extensions_test.h b/extensions/browser/extensions_test.h
index c6cb8b1..bb9caa6 100644
--- a/extensions/browser/extensions_test.h
+++ b/extensions/browser/extensions_test.h
@@ -36,10 +36,8 @@
 class ExtensionsTest : public testing::Test {
  public:
   ExtensionsTest();
-  // If the test uses a TestBrowserThreadBundle, then it must be given to the
-  // constructor here so that this class can use its MessageLoop.
   explicit ExtensionsTest(
-      std::unique_ptr<content::TestBrowserThreadBundle> thread_bundle);
+      content::TestBrowserThreadBundle::Options thread_options);
   ~ExtensionsTest() override;
 
   // Allows setting a custom TestExtensionsBrowserClient. Must only be called
@@ -79,8 +77,6 @@
 
   MockExtensionSystemFactory<MockExtensionSystem> extension_system_factory_;
 
-  // Optional thread bundle for some subclasses. Needs to exist before
-  // the RenderViewHostTestEnabler if it is going to exist.
   std::unique_ptr<content::TestBrowserThreadBundle> thread_bundle_;
 
   // The existence of this object enables tests via
diff --git a/extensions/browser/image_loader_unittest.cc b/extensions/browser/image_loader_unittest.cc
index 66af59e..20e9a59 100644
--- a/extensions/browser/image_loader_unittest.cc
+++ b/extensions/browser/image_loader_unittest.cc
@@ -13,7 +13,6 @@
 #include "base/run_loop.h"
 #include "base/strings/string_util.h"
 #include "content/public/test/test_browser_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extensions_browser_client.h"
 #include "extensions/browser/extensions_test.h"
@@ -35,10 +34,7 @@
 
 class ImageLoaderTest : public ExtensionsTest {
  public:
-  ImageLoaderTest()
-      : ExtensionsTest(std::make_unique<content::TestBrowserThreadBundle>()),
-        image_loaded_count_(0),
-        quit_in_image_loaded_(false) {}
+  ImageLoaderTest() : image_loaded_count_(0), quit_in_image_loaded_(false) {}
 
   void OnImageLoaded(const gfx::Image& image) {
     image_loaded_count_++;
diff --git a/extensions/browser/load_monitoring_extension_host_queue_unittest.cc b/extensions/browser/load_monitoring_extension_host_queue_unittest.cc
index fac5712..11f4e6e1 100644
--- a/extensions/browser/load_monitoring_extension_host_queue_unittest.cc
+++ b/extensions/browser/load_monitoring_extension_host_queue_unittest.cc
@@ -12,7 +12,6 @@
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "extensions/browser/deferred_start_render_host.h"
 #include "extensions/browser/extensions_test.h"
 #include "extensions/browser/serial_extension_host_queue.h"
@@ -50,8 +49,7 @@
 class LoadMonitoringExtensionHostQueueTest : public ExtensionsTest {
  public:
   LoadMonitoringExtensionHostQueueTest()
-      : ExtensionsTest(std::make_unique<content::TestBrowserThreadBundle>()),
-        finished_(false),
+      : finished_(false),
         // Arbitrary choice of an invalid size_t.
         num_queued_(g_invalid_size_t),
         num_loaded_(g_invalid_size_t),
diff --git a/extensions/browser/mojo/keep_alive_impl_unittest.cc b/extensions/browser/mojo/keep_alive_impl_unittest.cc
index 8624540..379e0f2 100644
--- a/extensions/browser/mojo/keep_alive_impl_unittest.cc
+++ b/extensions/browser/mojo/keep_alive_impl_unittest.cc
@@ -8,7 +8,6 @@
 
 #include "base/macros.h"
 #include "base/run_loop.h"
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extensions_test.h"
 #include "extensions/browser/process_manager.h"
@@ -18,8 +17,7 @@
 
 class KeepAliveTest : public ExtensionsTest {
  public:
-  KeepAliveTest()
-      : ExtensionsTest(std::make_unique<content::TestBrowserThreadBundle>()) {}
+  KeepAliveTest() {}
   ~KeepAliveTest() override {}
 
   void SetUp() override {
diff --git a/extensions/browser/requirements_checker_unittest.cc b/extensions/browser/requirements_checker_unittest.cc
index 3bd077f..98bdc07 100644
--- a/extensions/browser/requirements_checker_unittest.cc
+++ b/extensions/browser/requirements_checker_unittest.cc
@@ -13,7 +13,6 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "content/public/browser/gpu_data_manager.h"
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/browser/extensions_test.h"
 #include "extensions/browser/preload_check.h"
@@ -49,8 +48,7 @@
 
 class RequirementsCheckerTest : public ExtensionsTest {
  public:
-  RequirementsCheckerTest()
-      : ExtensionsTest(std::make_unique<content::TestBrowserThreadBundle>()) {
+  RequirementsCheckerTest() {
     manifest_dict_ = std::make_unique<base::DictionaryValue>();
   }
 
diff --git a/extensions/browser/sandboxed_unpacker_unittest.cc b/extensions/browser/sandboxed_unpacker_unittest.cc
index 51ec350a1..1a9f5543 100644
--- a/extensions/browser/sandboxed_unpacker_unittest.cc
+++ b/extensions/browser/sandboxed_unpacker_unittest.cc
@@ -121,8 +121,7 @@
       : SandboxedUnpackerTest(content::TestBrowserThreadBundle::IO_MAINLOOP) {}
 
   SandboxedUnpackerTest(content::TestBrowserThreadBundle::Options options)
-      : ExtensionsTest(
-            std::make_unique<content::TestBrowserThreadBundle>(options)) {}
+      : ExtensionsTest(options) {}
 
   void SetUp() override {
     ExtensionsTest::SetUp();
diff --git a/extensions/browser/updater/extension_installer_unittest.cc b/extensions/browser/updater/extension_installer_unittest.cc
index 347ff04..c009bc5 100644
--- a/extensions/browser/updater/extension_installer_unittest.cc
+++ b/extensions/browser/updater/extension_installer_unittest.cc
@@ -16,7 +16,6 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "components/update_client/update_client.h"
 #include "components/update_client/update_client_errors.h"
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_utils.h"
 #include "extensions/browser/extensions_test.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -58,9 +57,7 @@
 };
 
 ExtensionInstallerTest::ExtensionInstallerTest()
-    : ExtensionsTest(std::make_unique<content::TestBrowserThreadBundle>()),
-      result_(-1),
-      executed_(false) {}
+    : result_(-1), executed_(false) {}
 
 ExtensionInstallerTest::~ExtensionInstallerTest() {}
 
diff --git a/extensions/browser/updater/update_service_unittest.cc b/extensions/browser/updater/update_service_unittest.cc
index 78c248b..da13551 100644
--- a/extensions/browser/updater/update_service_unittest.cc
+++ b/extensions/browser/updater/update_service_unittest.cc
@@ -15,7 +15,6 @@
 #include "base/values.h"
 #include "components/crx_file/id_util.h"
 #include "components/update_client/update_client.h"
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_utils.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extensions_test.h"
@@ -158,8 +157,7 @@
 
 class UpdateServiceTest : public ExtensionsTest {
  public:
-  UpdateServiceTest()
-      : ExtensionsTest(std::make_unique<content::TestBrowserThreadBundle>()) {}
+  UpdateServiceTest() {}
   ~UpdateServiceTest() override {}
 
   void SetUp() override {
diff --git a/extensions/browser/warning_service_unittest.cc b/extensions/browser/warning_service_unittest.cc
index 8ea2002e..bb62e1c 100644
--- a/extensions/browser/warning_service_unittest.cc
+++ b/extensions/browser/warning_service_unittest.cc
@@ -5,7 +5,6 @@
 #include "extensions/browser/warning_service.h"
 
 #include "content/public/test/test_browser_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "extensions/browser/extensions_test.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -34,11 +33,7 @@
   MOCK_METHOD1(ExtensionWarningsChanged, void(const ExtensionIdSet&));
 };
 
-class WarningServiceTest : public ExtensionsTest {
- public:
-  WarningServiceTest()
-      : ExtensionsTest(std::make_unique<content::TestBrowserThreadBundle>()) {}
-};
+using WarningServiceTest = ExtensionsTest;
 
 const char ext1_id[] = "extension1";
 const char ext2_id[] = "extension2";
diff --git a/extensions/renderer/BUILD.gn b/extensions/renderer/BUILD.gn
index a102cf4..3804c48 100644
--- a/extensions/renderer/BUILD.gn
+++ b/extensions/renderer/BUILD.gn
@@ -193,6 +193,7 @@
     "resources/extension.css",
     "resources/extension_custom_bindings.js",
     "resources/extension_fonts.css",
+    "resources/feedback_private_custom_bindings.js",
     "resources/file_entry_binding_util.js",
     "resources/file_system_custom_bindings.js",
     "resources/greasemonkey_api.js",
diff --git a/extensions/renderer/dispatcher.cc b/extensions/renderer/dispatcher.cc
index 8c817cf..12c536c5 100644
--- a/extensions/renderer/dispatcher.cc
+++ b/extensions/renderer/dispatcher.cc
@@ -659,6 +659,7 @@
       {"extensionViewConstants", IDR_EXTENSION_VIEW_CONSTANTS_JS},
       {"extensionViewEvents", IDR_EXTENSION_VIEW_EVENTS_JS},
       {"extensionViewInternal", IDR_EXTENSION_VIEW_INTERNAL_CUSTOM_BINDINGS_JS},
+      {"feedbackPrivate", IDR_FEEDBACK_PRIVATE_CUSTOM_BINDINGS_JS},
       {"fileEntryBindingUtil", IDR_FILE_ENTRY_BINDING_UTIL_JS},
       {"fileSystem", IDR_FILE_SYSTEM_CUSTOM_BINDINGS_JS},
       {"guestView", IDR_GUEST_VIEW_JS},
diff --git a/extensions/renderer/messaging_util.cc b/extensions/renderer/messaging_util.cc
index 4b9f468..e767494 100644
--- a/extensions/renderer/messaging_util.cc
+++ b/extensions/renderer/messaging_util.cc
@@ -196,9 +196,17 @@
                           std::string* target_out,
                           std::string* error_out) {
   DCHECK(!v8_target_id.IsEmpty());
+  // Argument parsing should guarantee this is null or a string before we reach
+  // this point.
+  DCHECK(v8_target_id->IsNull() || v8_target_id->IsString());
 
   std::string target_id;
-  if (v8_target_id->IsNull()) {
+  // If omitted, we use the extension associated with the context.
+  // Note: we deliberately treat the empty string as omitting the id, even
+  // though it's not strictly correct. See https://crbug.com/823577.
+  if (v8_target_id->IsNull() ||
+      (v8_target_id->IsString() &&
+       v8_target_id.As<v8::String>()->Length() == 0)) {
     if (!script_context->extension()) {
       *error_out =
           base::StringPrintf(kExtensionIdRequiredErrorTemplate, method_name);
diff --git a/extensions/renderer/messaging_util_unittest.cc b/extensions/renderer/messaging_util_unittest.cc
index a742059a..89e248bd 100644
--- a/extensions/renderer/messaging_util_unittest.cc
+++ b/extensions/renderer/messaging_util_unittest.cc
@@ -6,9 +6,14 @@
 
 #include <memory>
 
+#include "base/strings/stringprintf.h"
 #include "extensions/common/api/messaging/message.h"
+#include "extensions/common/extension_builder.h"
 #include "extensions/renderer/bindings/api_binding_test.h"
 #include "extensions/renderer/bindings/api_binding_test_util.h"
+#include "extensions/renderer/native_extension_bindings_system_test_base.h"
+#include "extensions/renderer/script_context.h"
+#include "gin/converter.h"
 #include "v8/include/v8.h"
 
 namespace extensions {
@@ -44,4 +49,84 @@
   }
 }
 
+using MessagingUtilWithSystemTest = NativeExtensionBindingsSystemUnittest;
+
+TEST_F(MessagingUtilWithSystemTest, TestGetTargetIdFromExtensionContext) {
+  v8::HandleScope handle_scope(isolate());
+  v8::Local<v8::Context> context = MainContext();
+
+  scoped_refptr<Extension> extension = ExtensionBuilder("foo").Build();
+  RegisterExtension(extension);
+
+  ScriptContext* script_context = CreateScriptContext(
+      context, extension.get(), Feature::BLESSED_EXTENSION_CONTEXT);
+  script_context->set_url(extension->url());
+
+  std::string other_id(32, 'a');
+  struct {
+    v8::Local<v8::Value> passed_id;
+    base::StringPiece expected_id;
+    bool should_pass;
+  } test_cases[] = {
+      // If the extension ID is not provided, the bindings use the calling
+      // extension's.
+      {v8::Null(isolate()), extension->id(), true},
+      // We treat the empty string to be the same as null, even though it's
+      // somewhat unfortunate.
+      // See https://crbug.com/823577.
+      {gin::StringToV8(isolate(), ""), extension->id(), true},
+      {gin::StringToV8(isolate(), extension->id()), extension->id(), true},
+      {gin::StringToV8(isolate(), other_id), other_id, true},
+      {gin::StringToV8(isolate(), "invalid id"), base::StringPiece(), false},
+  };
+
+  for (size_t i = 0; i < arraysize(test_cases); ++i) {
+    SCOPED_TRACE(base::StringPrintf("Test Case: %d", static_cast<int>(i)));
+    const auto& test_case = test_cases[i];
+    std::string target;
+    std::string error;
+    EXPECT_EQ(test_case.should_pass,
+              messaging_util::GetTargetExtensionId(
+                  script_context, test_case.passed_id, "runtime.sendMessage",
+                  &target, &error));
+    EXPECT_EQ(test_case.expected_id, target);
+    EXPECT_EQ(test_case.should_pass, error.empty()) << error;
+  }
+}
+
+TEST_F(MessagingUtilWithSystemTest, TestGetTargetIdFromWebContext) {
+  v8::HandleScope handle_scope(isolate());
+  v8::Local<v8::Context> context = MainContext();
+
+  ScriptContext* script_context =
+      CreateScriptContext(context, nullptr, Feature::WEB_PAGE_CONTEXT);
+  script_context->set_url(GURL("https://example.com"));
+
+  std::string other_id(32, 'a');
+  struct {
+    v8::Local<v8::Value> passed_id;
+    base::StringPiece expected_id;
+    bool should_pass;
+  } test_cases[] = {
+      // A web page should always have to specify the extension id.
+      {gin::StringToV8(isolate(), other_id), other_id, true},
+      {v8::Null(isolate()), base::StringPiece(), false},
+      {gin::StringToV8(isolate(), ""), base::StringPiece(), false},
+      {gin::StringToV8(isolate(), "invalid id"), base::StringPiece(), false},
+  };
+
+  for (size_t i = 0; i < arraysize(test_cases); ++i) {
+    SCOPED_TRACE(base::StringPrintf("Test Case: %d", static_cast<int>(i)));
+    const auto& test_case = test_cases[i];
+    std::string target;
+    std::string error;
+    EXPECT_EQ(test_case.should_pass,
+              messaging_util::GetTargetExtensionId(
+                  script_context, test_case.passed_id, "runtime.sendMessage",
+                  &target, &error));
+    EXPECT_EQ(test_case.expected_id, target);
+    EXPECT_EQ(test_case.should_pass, error.empty()) << error;
+  }
+}
+
 }  // namespace extensions
diff --git a/extensions/renderer/resources/extension_custom_bindings.js b/extensions/renderer/resources/extension_custom_bindings.js
index cb13513..76e2547d 100644
--- a/extensions/renderer/resources/extension_custom_bindings.js
+++ b/extensions/renderer/resources/extension_custom_bindings.js
@@ -14,7 +14,6 @@
 var inIncognitoContext = requireNative('process').InIncognitoContext();
 var sendRequestIsDisabled = requireNative('process').IsSendRequestDisabled();
 var contextType = requireNative('process').GetContextType();
-var manifestVersion = requireNative('process').GetManifestVersion();
 
 // This should match chrome.windows.WINDOW_ID_NONE.
 //
@@ -26,10 +25,6 @@
 
 binding.registerCustomHook(function(bindingsAPI, extensionId) {
   var extension = bindingsAPI.compiledApi;
-  if (manifestVersion < 2) {
-    chrome.self = extension;
-    extension.inIncognitoTab = inIncognitoContext;
-  }
   extension.inIncognitoContext = inIncognitoContext;
 
   var apiFunctions = bindingsAPI.apiFunctions;
diff --git a/extensions/renderer/resources/extensions_renderer_resources.grd b/extensions/renderer/resources/extensions_renderer_resources.grd
index e06a844..d5e72d3f 100644
--- a/extensions/renderer/resources/extensions_renderer_resources.grd
+++ b/extensions/renderer/resources/extensions_renderer_resources.grd
@@ -23,6 +23,7 @@
       <include name="IDR_EXTENSION_VIEW_CONSTANTS_JS" file="guest_view/extension_view/extension_view_constants.js" type="BINDATA" />
       <include name="IDR_EXTENSION_VIEW_EVENTS_JS" file="guest_view/extension_view/extension_view_events.js" type="BINDATA" />
       <include name="IDR_EXTENSION_VIEW_INTERNAL_CUSTOM_BINDINGS_JS" file="guest_view/extension_view/extension_view_internal.js" type="BINDATA" />
+      <include name="IDR_FEEDBACK_PRIVATE_CUSTOM_BINDINGS_JS" file="feedback_private_custom_bindings.js" type="BINDATA" />
       <include name="IDR_GUEST_VIEW_ATTRIBUTES_JS" file="guest_view/guest_view_attributes.js" type="BINDATA" />
       <include name="IDR_GUEST_VIEW_CONTAINER_JS" file="guest_view/guest_view_container.js" type="BINDATA" />
       <include name="IDR_GUEST_VIEW_DENY_JS" file="guest_view/guest_view_deny.js" type="BINDATA" />
diff --git a/chrome/renderer/resources/extensions/feedback_private_custom_bindings.js b/extensions/renderer/resources/feedback_private_custom_bindings.js
similarity index 100%
rename from chrome/renderer/resources/extensions/feedback_private_custom_bindings.js
rename to extensions/renderer/resources/feedback_private_custom_bindings.js
diff --git a/extensions/shell/browser/shell_browser_context.cc b/extensions/shell/browser/shell_browser_context.cc
index 569bf66b..db7a900 100644
--- a/extensions/shell/browser/shell_browser_context.cc
+++ b/extensions/shell/browser/shell_browser_context.cc
@@ -41,6 +41,7 @@
       browser_main_parts_(browser_main_parts) {}
 
 ShellBrowserContext::~ShellBrowserContext() {
+  content::BrowserContext::NotifyWillBeDestroyed(this);
 }
 
 content::BrowserPluginGuestManager* ShellBrowserContext::GetGuestManager() {
diff --git a/extensions/shell/browser/shell_browser_context.h b/extensions/shell/browser/shell_browser_context.h
index 00725c86..3c8febe 100644
--- a/extensions/shell/browser/shell_browser_context.h
+++ b/extensions/shell/browser/shell_browser_context.h
@@ -16,7 +16,7 @@
 
 // The BrowserContext used by the content, apps and extensions systems in
 // app_shell.
-class ShellBrowserContext : public content::ShellBrowserContext {
+class ShellBrowserContext final : public content::ShellBrowserContext {
  public:
   explicit ShellBrowserContext(ShellBrowserMainParts* browser_main_parts);
   ~ShellBrowserContext() override;
diff --git a/extensions/shell/browser/shell_extension_loader_unittest.cc b/extensions/shell/browser/shell_extension_loader_unittest.cc
index 92f1fe1..0d1958e7 100644
--- a/extensions/shell/browser/shell_extension_loader_unittest.cc
+++ b/extensions/shell/browser/shell_extension_loader_unittest.cc
@@ -84,8 +84,7 @@
 
 class ShellExtensionLoaderTest : public ExtensionsTest {
  protected:
-  ShellExtensionLoaderTest()
-      : ExtensionsTest(std::make_unique<content::TestBrowserThreadBundle>()) {}
+  ShellExtensionLoaderTest() = default;
   ~ShellExtensionLoaderTest() override = default;
 
   void SetUp() override {
diff --git a/extensions/shell/browser/shell_nacl_browser_delegate_unittest.cc b/extensions/shell/browser/shell_nacl_browser_delegate_unittest.cc
index 0e1d178..d09bef5 100644
--- a/extensions/shell/browser/shell_nacl_browser_delegate_unittest.cc
+++ b/extensions/shell/browser/shell_nacl_browser_delegate_unittest.cc
@@ -7,14 +7,16 @@
 #include "base/strings/pattern.h"
 #include "base/strings/string_util.h"
 #include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace extensions {
 
-typedef testing::Test ShellNaClBrowserDelegateTest;
+using ShellNaClBrowserDelegateTest = testing::Test;
 
 // Verifies that the returned version string has a valid format.
 TEST_F(ShellNaClBrowserDelegateTest, VersionString) {
+  content::TestBrowserThreadBundle thread_bundle;
   content::TestBrowserContext browser_context;
   ShellNaClBrowserDelegate delegate(&browser_context);
 
diff --git a/extensions/shell/browser/shell_native_app_window_aura_unittest.cc b/extensions/shell/browser/shell_native_app_window_aura_unittest.cc
index 1c8eb185..911ef1f0 100644
--- a/extensions/shell/browser/shell_native_app_window_aura_unittest.cc
+++ b/extensions/shell/browser/shell_native_app_window_aura_unittest.cc
@@ -9,7 +9,6 @@
 #include "base/memory/ptr_util.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "extensions/browser/app_window/app_window.h"
 #include "extensions/browser/app_window/test_app_window_contents.h"
 #include "extensions/browser/extensions_test.h"
@@ -24,10 +23,7 @@
 
 class ShellNativeAppWindowAuraTest : public ExtensionsTest {
  public:
-  ShellNativeAppWindowAuraTest()
-      : ExtensionsTest(std::make_unique<content::TestBrowserThreadBundle>()) {
-    AppWindowClient::Set(&app_window_client_);
-  }
+  ShellNativeAppWindowAuraTest() { AppWindowClient::Set(&app_window_client_); }
 
   ~ShellNativeAppWindowAuraTest() override { AppWindowClient::Set(nullptr); }
 
diff --git a/extensions/shell/browser/shell_oauth2_token_service_unittest.cc b/extensions/shell/browser/shell_oauth2_token_service_unittest.cc
index bf43eeef..861c871d 100644
--- a/extensions/shell/browser/shell_oauth2_token_service_unittest.cc
+++ b/extensions/shell/browser/shell_oauth2_token_service_unittest.cc
@@ -5,15 +5,13 @@
 #include "extensions/shell/browser/shell_oauth2_token_service.h"
 
 #include "base/memory/ptr_util.h"
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "extensions/browser/extensions_test.h"
 
 namespace extensions {
 
 class ShellOAuth2TokenServiceTest : public ExtensionsTest {
  public:
-  ShellOAuth2TokenServiceTest()
-      : ExtensionsTest(std::make_unique<content::TestBrowserThreadBundle>()) {}
+  ShellOAuth2TokenServiceTest() {}
   ~ShellOAuth2TokenServiceTest() override {}
 };
 
diff --git a/extensions/shell/browser/system_logs/shell_system_logs_fetcher_unittest.cc b/extensions/shell/browser/system_logs/shell_system_logs_fetcher_unittest.cc
index 649f01e..fb5b493 100644
--- a/extensions/shell/browser/system_logs/shell_system_logs_fetcher_unittest.cc
+++ b/extensions/shell/browser/system_logs/shell_system_logs_fetcher_unittest.cc
@@ -15,7 +15,6 @@
 #include "components/feedback/system_logs/system_logs_fetcher.h"
 #include "components/feedback/system_logs/system_logs_source.h"
 #include "content/public/browser/browser_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "extensions/browser/extension_function.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extensions_test.h"
@@ -28,8 +27,7 @@
 
 class ShellSystemLogsFetcherTest : public ExtensionsTest {
  public:
-  ShellSystemLogsFetcherTest()
-      : ExtensionsTest(std::make_unique<content::TestBrowserThreadBundle>()) {}
+  ShellSystemLogsFetcherTest() = default;
   ~ShellSystemLogsFetcherTest() override = default;
 
   scoped_refptr<Extension> BuildExtension(const std::string& name,
diff --git a/extensions/shell/common/shell_extensions_client.cc b/extensions/shell/common/shell_extensions_client.cc
index 681dde3..e509c88 100644
--- a/extensions/shell/common/shell_extensions_client.cc
+++ b/extensions/shell/common/shell_extensions_client.cc
@@ -154,7 +154,7 @@
 
 bool ShellExtensionsClient::IsScriptableURL(const GURL& url,
                                             std::string* error) const {
-  NOTIMPLEMENTED();
+  // No restrictions on URLs.
   return true;
 }
 
diff --git a/extensions/shell/renderer/shell_content_renderer_client.cc b/extensions/shell/renderer/shell_content_renderer_client.cc
index 0263724..d19fb96 100644
--- a/extensions/shell/renderer/shell_content_renderer_client.cc
+++ b/extensions/shell/renderer/shell_content_renderer_client.cc
@@ -84,13 +84,15 @@
   return NULL;
 }
 
-bool ShellContentRendererClient::WillSendRequest(
+void ShellContentRendererClient::WillSendRequest(
     blink::WebLocalFrame* frame,
     ui::PageTransition transition_type,
     const blink::WebURL& url,
-    GURL* new_url) {
+    const url::Origin* initiator_origin,
+    GURL* new_url,
+    bool* attach_same_site_cookies) {
+  *attach_same_site_cookies = false;
   // TODO(jamescook): Cause an error for bad extension scheme requests?
-  return false;
 }
 
 bool ShellContentRendererClient::IsExternalPepperPlugin(
diff --git a/extensions/shell/renderer/shell_content_renderer_client.h b/extensions/shell/renderer/shell_content_renderer_client.h
index 21549a9..3b28547 100644
--- a/extensions/shell/renderer/shell_content_renderer_client.h
+++ b/extensions/shell/renderer/shell_content_renderer_client.h
@@ -36,11 +36,12 @@
   blink::WebPlugin* CreatePluginReplacement(
       content::RenderFrame* render_frame,
       const base::FilePath& plugin_path) override;
-  bool WillSendRequest(
-      blink::WebLocalFrame* frame,
-      ui::PageTransition transition_type,
-      const blink::WebURL& url,
-      GURL* new_url) override;
+  void WillSendRequest(blink::WebLocalFrame* frame,
+                       ui::PageTransition transition_type,
+                       const blink::WebURL& url,
+                       const url::Origin* initiator_origin,
+                       GURL* new_url,
+                       bool* attach_same_site_cookies) override;
   bool IsExternalPepperPlugin(const std::string& module_name) override;
   content::BrowserPluginDelegate* CreateBrowserPluginDelegate(
       content::RenderFrame* render_frame,
diff --git a/extensions/shell/test/shell_test_base_aura.cc b/extensions/shell/test/shell_test_base_aura.cc
index 0be0ddc8..20dd49d2 100644
--- a/extensions/shell/test/shell_test_base_aura.cc
+++ b/extensions/shell/test/shell_test_base_aura.cc
@@ -4,14 +4,12 @@
 
 #include "extensions/shell/test/shell_test_base_aura.h"
 
-#include "content/public/test/test_browser_thread_bundle.h"
 #include "extensions/shell/test/shell_test_extensions_browser_client.h"
 #include "extensions/shell/test/shell_test_helper_aura.h"
 
 namespace extensions {
 
-ShellTestBaseAura::ShellTestBaseAura()
-    : ExtensionsTest(std::make_unique<content::TestBrowserThreadBundle>()) {}
+ShellTestBaseAura::ShellTestBaseAura() {}
 
 ShellTestBaseAura::~ShellTestBaseAura() {}
 
diff --git a/gpu/BUILD.gn b/gpu/BUILD.gn
index a93fa0c..cc54a566 100644
--- a/gpu/BUILD.gn
+++ b/gpu/BUILD.gn
@@ -381,6 +381,7 @@
     "config/gpu_test_config_unittest.cc",
     "config/gpu_test_expectations_parser_unittest.cc",
     "config/gpu_util_unittest.cc",
+    "ipc/client/command_buffer_proxy_impl_unittest.cc",
     "ipc/common/gpu_memory_buffer_impl_shared_memory_unittest.cc",
     "ipc/common/gpu_memory_buffer_impl_test_template.h",
     "ipc/common/gpu_preferences_util_unittest.cc",
@@ -437,9 +438,11 @@
     "//gpu/command_buffer/client:raster",
     "//gpu/command_buffer/common:gles2_utils",
     "//gpu/ipc:gl_in_process_context",
+    "//gpu/ipc/client",
     "//gpu/ipc/common:gpu_preferences_util",
     "//gpu/ipc/common:test_interfaces",
     "//gpu/ipc/host",
+    "//ipc:test_support",
     "//mojo/edk",
     "//mojo/public/cpp/bindings",
     "//net:test_support",
diff --git a/gpu/command_buffer/service/BUILD.gn b/gpu/command_buffer/service/BUILD.gn
index 15af2e7..c655bed2 100644
--- a/gpu/command_buffer/service/BUILD.gn
+++ b/gpu/command_buffer/service/BUILD.gn
@@ -86,7 +86,7 @@
     "//gpu/command_buffer/client:client_sources",
     "//gpu/config:config_sources",
     "//gpu/ipc/common:surface_handle_type",
-    "//media:media_features",
+    "//media:media_buildflags",
     "//ui/gfx",
     "//ui/gfx/geometry",
     "//ui/gl",
diff --git a/gpu/command_buffer/service/DEPS b/gpu/command_buffer/service/DEPS
index 0e3904d8..03786f8b 100644
--- a/gpu/command_buffer/service/DEPS
+++ b/gpu/command_buffer/service/DEPS
@@ -1,6 +1,6 @@
 include_rules = [
   "+cc/paint",
-  "+media/media_features.h",
+  "+media/media_buildflags.h",
   "+third_party/skia",
   "+components/viz/common/resources/resource_format.h",
   "+components/viz/common/resources/resource_format_utils.h",
diff --git a/gpu/command_buffer/service/buffer_manager.h b/gpu/command_buffer/service/buffer_manager.h
index 6efb10f3..07224171 100644
--- a/gpu/command_buffer/service/buffer_manager.h
+++ b/gpu/command_buffer/service/buffer_manager.h
@@ -52,6 +52,8 @@
 
   Buffer(BufferManager* manager, GLuint service_id);
 
+  GLenum initial_target() const { return initial_target_; }
+
   GLuint service_id() const {
     return service_id_;
   }
@@ -166,10 +168,6 @@
 
   ~Buffer();
 
-  GLenum initial_target() const {
-    return initial_target_;
-  }
-
   void set_initial_target(GLenum target) {
     DCHECK_EQ(0u, initial_target_);
     initial_target_ = target;
diff --git a/gpu/command_buffer/service/context_state.cc b/gpu/command_buffer/service/context_state.cc
index 5bdbcf02..0e7ce98 100644
--- a/gpu/command_buffer/service/context_state.cc
+++ b/gpu/command_buffer/service/context_state.cc
@@ -712,46 +712,69 @@
 void ContextState::RemoveBoundBuffer(Buffer* buffer) {
   DCHECK(buffer);
   bool do_refcounting = feature_info_->IsWebGL2OrES3Context();
-  vertex_attrib_manager->Unbind(buffer);
   if (bound_array_buffer.get() == buffer) {
     bound_array_buffer = nullptr;
-    if (do_refcounting && buffer)
+    if (do_refcounting)
       buffer->OnUnbind(GL_ARRAY_BUFFER);
+    if (!context_lost_)
+      api()->glBindBufferFn(GL_ARRAY_BUFFER, 0);
   }
+  // Needs to be called after bound_array_buffer handled.
+  vertex_attrib_manager->Unbind(buffer, bound_array_buffer.get());
   if (bound_copy_read_buffer.get() == buffer) {
     bound_copy_read_buffer = nullptr;
-    if (do_refcounting && buffer)
+    if (do_refcounting)
       buffer->OnUnbind(GL_COPY_READ_BUFFER);
+    if (!context_lost_)
+      api()->glBindBufferFn(GL_COPY_READ_BUFFER, 0);
   }
   if (bound_copy_write_buffer.get() == buffer) {
     bound_copy_write_buffer = nullptr;
-    if (do_refcounting && buffer)
+    if (do_refcounting)
       buffer->OnUnbind(GL_COPY_WRITE_BUFFER);
+    if (!context_lost_)
+      api()->glBindBufferFn(GL_COPY_WRITE_BUFFER, 0);
   }
   if (bound_pixel_pack_buffer.get() == buffer) {
     bound_pixel_pack_buffer = nullptr;
-    if (do_refcounting && buffer)
+    if (do_refcounting)
       buffer->OnUnbind(GL_PIXEL_PACK_BUFFER);
+    if (!context_lost_)
+      api()->glBindBufferFn(GL_PIXEL_PACK_BUFFER, 0);
     UpdatePackParameters();
   }
   if (bound_pixel_unpack_buffer.get() == buffer) {
     bound_pixel_unpack_buffer = nullptr;
-    if (do_refcounting && buffer)
+    if (do_refcounting)
       buffer->OnUnbind(GL_PIXEL_UNPACK_BUFFER);
+    if (!context_lost_)
+      api()->glBindBufferFn(GL_PIXEL_UNPACK_BUFFER, 0);
     UpdateUnpackParameters();
   }
   if (bound_transform_feedback_buffer.get() == buffer) {
     bound_transform_feedback_buffer = nullptr;
-    if (do_refcounting && buffer)
+    if (do_refcounting)
       buffer->OnUnbind(GL_TRANSFORM_FEEDBACK_BUFFER);
+    if (!context_lost_)
+      api()->glBindBufferFn(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
   }
+  // Needs to be called after bound_transform_feedback_buffer handled.
   if (bound_transform_feedback.get()) {
-    bound_transform_feedback->RemoveBoundBuffer(buffer);
+    bound_transform_feedback->RemoveBoundBuffer(
+        GL_TRANSFORM_FEEDBACK_BUFFER, buffer,
+        bound_transform_feedback_buffer.get(), !context_lost_);
   }
   if (bound_uniform_buffer.get() == buffer) {
     bound_uniform_buffer = nullptr;
-    if (do_refcounting && buffer)
+    if (do_refcounting)
       buffer->OnUnbind(GL_UNIFORM_BUFFER);
+    if (!context_lost_)
+      api()->glBindBufferFn(GL_UNIFORM_BUFFER, 0);
+  }
+  // Needs to be called after bound_uniform_buffer handled.
+  if (indexed_uniform_buffer_bindings) {
+    indexed_uniform_buffer_bindings->RemoveBoundBuffer(
+        GL_UNIFORM_BUFFER, buffer, bound_uniform_buffer.get(), !context_lost_);
   }
 }
 
diff --git a/gpu/command_buffer/service/context_state.h b/gpu/command_buffer/service/context_state.h
index 6a0712b6..9213758 100644
--- a/gpu/command_buffer/service/context_state.h
+++ b/gpu/command_buffer/service/context_state.h
@@ -203,6 +203,8 @@
 
   void Initialize();
 
+  void MarkContextLost() { context_lost_ = true; }
+
   void SetLineWidthBounds(GLfloat min, GLfloat max);
 
   void SetIgnoreCachedStateForTest(bool ignore) {
@@ -420,6 +422,8 @@
   gl::GLApi* api_ = nullptr;
   FeatureInfo* feature_info_;
   std::unique_ptr<ErrorState> error_state_;
+
+  bool context_lost_ = false;
 };
 
 }  // namespace gles2
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 1d38364..f7ea51d 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -787,6 +787,8 @@
                                       const volatile GLuint* client_ids);
   void DeleteSyncHelper(GLuint sync);
 
+  bool UnmapBufferHelper(Buffer* buffer);
+
   // Workarounds
   void OnFboChanged() const;
   void OnUseFramebuffer() const;
@@ -1244,11 +1246,6 @@
     return buffer;
   }
 
-  // Removes any buffers in the VertexAtrribInfos and BufferInfos. This is used
-  // on glDeleteBuffers so we can make sure the user does not try to render
-  // with deleted buffers.
-  void RemoveBuffer(GLuint client_id);
-
   // Creates a framebuffer info for the given framebuffer.
   void CreateFramebuffer(GLuint client_id, GLuint service_id) {
     return framebuffer_manager()->CreateFramebuffer(client_id, service_id);
@@ -4424,9 +4421,9 @@
     GLuint client_id = client_ids[ii];
     Buffer* buffer = GetBuffer(client_id);
     if (buffer && !buffer->IsDeleted()) {
-      buffer->RemoveMappedRange();
+      UnmapBufferHelper(buffer);
       state_.RemoveBoundBuffer(buffer);
-      RemoveBuffer(client_id);
+      buffer_manager()->RemoveBuffer(client_id);
     }
   }
 }
@@ -5100,6 +5097,7 @@
       group_->texture_manager()->MarkContextLost();
     if (gr_context_)
       gr_context_->abandonContext();
+    state_.MarkContextLost();
   }
   deschedule_until_finished_fences_.clear();
 
@@ -5688,10 +5686,6 @@
   }
 }
 
-void GLES2DecoderImpl::RemoveBuffer(GLuint client_id) {
-  buffer_manager()->RemoveBuffer(client_id);
-}
-
 void GLES2DecoderImpl::DoFinish() {
   api()->glFinishFn();
   ProcessPendingReadPixels(true);
@@ -16507,6 +16501,10 @@
   if (transform_feedback_manager_.get()) {
     transform_feedback_manager_->MarkContextLost();
   }
+  if (vertex_array_manager_.get()) {
+    vertex_array_manager_->MarkContextLost();
+  }
+  state_.MarkContextLost();
 }
 
 bool GLES2DecoderImpl::CheckResetStatus() {
@@ -18995,6 +18993,43 @@
   return error::kNoError;
 }
 
+bool GLES2DecoderImpl::UnmapBufferHelper(Buffer* buffer) {
+  DCHECK(buffer);
+  const Buffer::MappedRange* mapped_range = buffer->GetMappedRange();
+  if (!mapped_range)
+    return true;
+  if (!AllBitsSet(mapped_range->access, GL_MAP_WRITE_BIT) ||
+      AllBitsSet(mapped_range->access, GL_MAP_FLUSH_EXPLICIT_BIT)) {
+    // If we don't need to write back, or explict flush is required, no copying
+    // back is needed.
+  } else if (!WasContextLost()) {
+    void* mem = mapped_range->GetShmPointer();
+    DCHECK(mem);
+    DCHECK(mapped_range->pointer);
+    memcpy(mapped_range->pointer, mem, mapped_range->size);
+    if (buffer->shadowed()) {
+      buffer->SetRange(mapped_range->offset, mapped_range->size, mem);
+    }
+  }
+  buffer->RemoveMappedRange();
+  if (WasContextLost())
+    return true;
+  GLboolean rt = api()->glUnmapBufferFn(buffer->initial_target());
+  if (rt == GL_FALSE) {
+    // At this point, we have already done the necessary validation, so
+    // GL_FALSE indicates data corruption.
+    // TODO(zmo): We could redo the map / copy data / unmap to recover, but
+    // the second unmap could still return GL_FALSE. For now, we simply lose
+    // the contexts in the share group.
+    LOG(ERROR) << "glUnmapBuffer unexpectedly returned GL_FALSE";
+    // Need to lose current context before broadcasting!
+    MarkContextLost(error::kGuilty);
+    group_->LoseContexts(error::kInnocent);
+    return false;
+  }
+  return true;
+}
+
 error::Error GLES2DecoderImpl::HandleUnmapBuffer(
     uint32_t immediate_data_size, const volatile void* cmd_data) {
   if (!feature_info_->IsWebGL2OrES3Context()) {
@@ -19021,33 +19056,8 @@
     LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, func_name, "buffer is unmapped");
     return error::kNoError;
   }
-  if (!AllBitsSet(mapped_range->access, GL_MAP_WRITE_BIT) ||
-      AllBitsSet(mapped_range->access, GL_MAP_FLUSH_EXPLICIT_BIT)) {
-    // If we don't need to write back, or explict flush is required, no copying
-    // back is needed.
-  } else {
-    void* mem = mapped_range->GetShmPointer();
-    DCHECK(mem);
-    DCHECK(mapped_range->pointer);
-    memcpy(mapped_range->pointer, mem, mapped_range->size);
-    if (buffer->shadowed()) {
-      buffer->SetRange(mapped_range->offset, mapped_range->size, mem);
-    }
-  }
-  buffer->RemoveMappedRange();
-  GLboolean rt = api()->glUnmapBufferFn(target);
-  if (rt == GL_FALSE) {
-    // At this point, we have already done the necessary validation, so
-    // GL_FALSE indicates data corruption.
-    // TODO(zmo): We could redo the map / copy data / unmap to recover, but
-    // the second unmap could still return GL_FALSE. For now, we simply lose
-    // the contexts in the share group.
-    LOG(ERROR) << func_name << " unexpectedly returned GL_FALSE";
-    // Need to lose current context before broadcasting!
-    MarkContextLost(error::kGuilty);
-    group_->LoseContexts(error::kInnocent);
+  if (!UnmapBufferHelper(buffer))
     return error::kLostContext;
-  }
   return error::kNoError;
 }
 
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
index 524c070..4c31c04 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
@@ -196,6 +196,9 @@
   EXPECT_FALSE(DoIsBuffer(client_buffer_id_));
   DoBindBuffer(GL_ARRAY_BUFFER, client_buffer_id_, kServiceBufferId);
   EXPECT_TRUE(DoIsBuffer(client_buffer_id_));
+  EXPECT_CALL(*gl_, BindBuffer(GL_ARRAY_BUFFER, 0))
+      .Times(1)
+      .RetiresOnSaturation();
   DoDeleteBuffer(client_buffer_id_, kServiceBufferId);
   EXPECT_FALSE(DoIsBuffer(client_buffer_id_));
 }
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_buffers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_buffers.cc
index 0403e95a..c614726 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_buffers.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_buffers.cc
@@ -657,6 +657,10 @@
   }
 
   {  // DeleteBuffers unmaps the data store.
+    EXPECT_CALL(*gl_, BindBuffer(kTarget, 0)).Times(1).RetiresOnSaturation();
+    EXPECT_CALL(*gl_, UnmapBuffer(kTarget))
+        .WillOnce(Return(GL_TRUE))
+        .RetiresOnSaturation();
     DoDeleteBuffer(client_buffer_id_, kServiceBufferId);
     EXPECT_EQ(GL_NO_ERROR, GetGLError());
   }
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc
index 31272d4..f8fa614 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc
@@ -42,7 +42,6 @@
 using ::testing::SaveArg;
 using ::testing::SetArrayArgument;
 using ::testing::SetArgPointee;
-using ::testing::SetArgPointee;
 using ::testing::StrEq;
 using ::testing::StrictMock;
 
@@ -845,8 +844,26 @@
 }
 
 TEST_P(GLES2DecoderWithShaderTest, DrawArraysDeletedBufferFails) {
+  const GLuint kNewServiceBufferId = 1897u;
   SetupVertexBuffer();
   DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0);
+
+  EXPECT_CALL(*gl_, BindBuffer(GL_ARRAY_BUFFER, 0))
+      .Times(1)
+      .RetiresOnSaturation();
+  EXPECT_CALL(*gl_, GenBuffersARB(1, _))
+      .WillOnce(SetArgPointee<1>(kNewServiceBufferId))
+      .RetiresOnSaturation();
+  EXPECT_CALL(*gl_, BindBuffer(GL_ARRAY_BUFFER, kNewServiceBufferId))
+      .Times(1)
+      .RetiresOnSaturation();
+  EXPECT_CALL(*gl_, VertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0))
+      .Times(1)
+      .RetiresOnSaturation();
+  EXPECT_CALL(*gl_, DeleteBuffersARB(1, _)).Times(1).RetiresOnSaturation();
+  EXPECT_CALL(*gl_, BindBuffer(GL_ARRAY_BUFFER, 0))
+      .Times(1)
+      .RetiresOnSaturation();
   DeleteVertexBuffer();
 
   EXPECT_CALL(*gl_, DrawArrays(_, _, _)).Times(0);
@@ -1305,6 +1322,10 @@
   SetupVertexBuffer();
   SetupIndexBuffer();
   DoVertexAttribPointer(1, 2, GL_FLOAT, 0, 0);
+
+  EXPECT_CALL(*gl_, BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0))
+      .Times(1)
+      .RetiresOnSaturation();
   DeleteIndexBuffer();
 
   EXPECT_CALL(*gl_, DrawElements(_, _, _, _)).Times(0);
diff --git a/gpu/command_buffer/service/gpu_preferences.h b/gpu/command_buffer/service/gpu_preferences.h
index ce22a33..8b82080 100644
--- a/gpu/command_buffer/service/gpu_preferences.h
+++ b/gpu/command_buffer/service/gpu_preferences.h
@@ -12,7 +12,7 @@
 #include "build/build_config.h"
 #include "gpu/command_buffer/common/constants.h"
 #include "gpu/gpu_export.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "ui/gfx/buffer_types.h"
 
 namespace gpu {
diff --git a/gpu/command_buffer/service/indexed_buffer_binding_host.cc b/gpu/command_buffer/service/indexed_buffer_binding_host.cc
index b29ed964b..4b59c9b 100644
--- a/gpu/command_buffer/service/indexed_buffer_binding_host.cc
+++ b/gpu/command_buffer/service/indexed_buffer_binding_host.cc
@@ -175,13 +175,25 @@
   }
 }
 
-void IndexedBufferBindingHost::RemoveBoundBuffer(Buffer* buffer) {
+void IndexedBufferBindingHost::RemoveBoundBuffer(
+    GLenum target,
+    Buffer* buffer,
+    Buffer* target_generic_bound_buffer,
+    bool have_context) {
+  DCHECK(buffer);
+  bool need_to_recover_generic_binding = false;
   for (size_t ii = 0; ii < buffer_bindings_.size(); ++ii) {
     if (buffer_bindings_[ii].buffer.get() == buffer) {
       buffer_bindings_[ii].Reset();
       UpdateMaxNonNullBindingIndex(ii);
+      if (have_context) {
+        glBindBufferBase(target, ii, 0);
+        need_to_recover_generic_binding = true;
+      }
     }
   }
+  if (need_to_recover_generic_binding && target_generic_bound_buffer)
+    glBindBuffer(target, target_generic_bound_buffer->service_id());
 }
 
 void IndexedBufferBindingHost::SetIsBound(bool is_bound) {
diff --git a/gpu/command_buffer/service/indexed_buffer_binding_host.h b/gpu/command_buffer/service/indexed_buffer_binding_host.h
index c7a55391..af2f467 100644
--- a/gpu/command_buffer/service/indexed_buffer_binding_host.h
+++ b/gpu/command_buffer/service/indexed_buffer_binding_host.h
@@ -42,7 +42,10 @@
   // size might change.
   void OnBufferData(Buffer* buffer);
 
-  void RemoveBoundBuffer(Buffer* buffer);
+  void RemoveBoundBuffer(GLenum target,
+                         Buffer* buffer,
+                         Buffer* target_generic_bound_buffer,
+                         bool have_context);
 
   void SetIsBound(bool bound);
 
diff --git a/gpu/command_buffer/service/indexed_buffer_binding_host_unittest.cc b/gpu/command_buffer/service/indexed_buffer_binding_host_unittest.cc
index 7e5237b..3d37f16b 100644
--- a/gpu/command_buffer/service/indexed_buffer_binding_host_unittest.cc
+++ b/gpu/command_buffer/service/indexed_buffer_binding_host_unittest.cc
@@ -39,8 +39,6 @@
   }
 
   void TearDown() override {
-    uniform_host_->RemoveBoundBuffer(buffer_.get());
-    tf_host_->RemoveBoundBuffer(buffer_.get());
     buffer_ = nullptr;
     buffer_manager_->MarkContextLost();
     buffer_manager_->Destroy();
@@ -80,6 +78,8 @@
       EXPECT_EQ(kOffset, tf_host_->GetBufferStart(index));
     }
   }
+
+  tf_host_->RemoveBoundBuffer(kTarget, buffer_.get(), nullptr, false);
 }
 
 TEST_F(IndexedBufferBindingHostTest, DoBindBufferRangeBufferWithoutEnoughSize) {
@@ -118,6 +118,8 @@
 
   SetBufferSize(kTarget, kOffset + kSize);
   tf_host_->OnBufferData(buffer_.get());
+
+  tf_host_->RemoveBoundBuffer(kTarget, buffer_.get(), nullptr, false);
 }
 
 TEST_F(IndexedBufferBindingHostTest, RestoreBindings) {
@@ -138,7 +140,7 @@
   uniform_host_->DoBindBufferBase(kIndex, buffer_.get());
   // Set up the second host
   scoped_refptr<IndexedBufferBindingHost> other =
-      new IndexedBufferBindingHost(kMaxBindings, GL_UNIFORM_BUFFER, true);
+      new IndexedBufferBindingHost(kMaxBindings, kTarget, true);
   EXPECT_CALL(*gl_, BindBufferRange(kTarget, kOtherIndex, kBufferServiceId,
                                     kOffset, clamped_size))
       .Times(1)
@@ -167,9 +169,12 @@
         .RetiresOnSaturation();
     other->RestoreBindings(uniform_host_.get());
   }
+
+  EXPECT_CALL(*gl_, BindBufferBase(kTarget, kIndex, 0))
+      .Times(1)
+      .RetiresOnSaturation();
+  uniform_host_->RemoveBoundBuffer(kTarget, buffer_.get(), nullptr, true);
 }
 
 }  // namespace gles2
 }  // namespace gpu
-
-
diff --git a/gpu/command_buffer/service/raster_decoder.cc b/gpu/command_buffer/service/raster_decoder.cc
index 06eccef6..f217a8f 100644
--- a/gpu/command_buffer/service/raster_decoder.cc
+++ b/gpu/command_buffer/service/raster_decoder.cc
@@ -28,6 +28,7 @@
 #include "gpu/command_buffer/service/decoder_client.h"
 #include "gpu/command_buffer/service/error_state.h"
 #include "gpu/command_buffer/service/feature_info.h"
+#include "gpu/command_buffer/service/framebuffer_manager.h"
 #include "gpu/command_buffer/service/logger.h"
 #include "gpu/command_buffer/service/mailbox_manager.h"
 #include "gpu/command_buffer/service/query_manager.h"
@@ -96,6 +97,94 @@
   const GLenum target_;
 };
 
+// This class prevents any GL errors that occur when it is in scope from
+// being reported to the client.
+class ScopedGLErrorSuppressor {
+ public:
+  ScopedGLErrorSuppressor(const char* function_name, ErrorState* error_state);
+  ~ScopedGLErrorSuppressor();
+
+ private:
+  const char* function_name_;
+  ErrorState* error_state_;
+  DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
+};
+
+ScopedGLErrorSuppressor::ScopedGLErrorSuppressor(const char* function_name,
+                                                 ErrorState* error_state)
+    : function_name_(function_name), error_state_(error_state) {
+  ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_, function_name_);
+}
+
+ScopedGLErrorSuppressor::~ScopedGLErrorSuppressor() {
+  ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
+}
+
+void RestoreCurrentTextureBindings(ContextState* state,
+                                   GLenum target,
+                                   GLuint texture_unit) {
+  DCHECK(!state->texture_units.empty());
+  DCHECK_LT(texture_unit, state->texture_units.size());
+  TextureUnit& info = state->texture_units[texture_unit];
+  GLuint last_id;
+  TextureRef* texture_ref = info.GetInfoForTarget(target);
+  if (texture_ref) {
+    last_id = texture_ref->service_id();
+  } else {
+    last_id = 0;
+  }
+
+  state->api()->glBindTextureFn(target, last_id);
+}
+
+// Temporarily changes a decoder's bound texture and restore it when this
+// object goes out of scope. Also temporarily switches to using active texture
+// unit zero in case the client has changed that to something invalid.
+class ScopedTextureBinder {
+ public:
+  ScopedTextureBinder(ContextState* state,
+                      TextureManager* texture_manager,
+                      TextureRef* texture_ref,
+                      GLenum target);
+  ~ScopedTextureBinder();
+
+ private:
+  ContextState* state_;
+  GLenum target_;
+  TextureUnit old_unit_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder);
+};
+
+ScopedTextureBinder::ScopedTextureBinder(ContextState* state,
+                                         TextureManager* texture_manager,
+                                         TextureRef* texture_ref,
+                                         GLenum target)
+    : state_(state), target_(target), old_unit_(state->texture_units[0]) {
+  auto* api = state->api();
+  api->glActiveTextureFn(GL_TEXTURE0);
+
+  Texture* texture = texture_ref->texture();
+  if (texture->target() == 0) {
+    texture_manager->SetTarget(texture_ref, target);
+  }
+  DCHECK_EQ(texture->target(), target)
+      << "Texture bound to more than 1 target.";
+
+  api->glBindTextureFn(target, texture_ref->service_id());
+
+  TextureUnit& unit = state_->texture_units[0];
+  unit.bind_target = target;
+  unit.SetInfoForTarget(target, texture_ref);
+}
+
+ScopedTextureBinder::~ScopedTextureBinder() {
+  state_->texture_units[0] = old_unit_;
+
+  RestoreCurrentTextureBindings(state_, target_, 0);
+  state_->RestoreActiveTexture();
+}
+
 }  // namespace
 
 class RasterDecoderImpl : public RasterDecoder, public gles2::ErrorStateClient {
@@ -194,10 +283,24 @@
     return feature_info_->feature_flags();
   }
 
+  const GpuDriverBugWorkarounds& workarounds() const {
+    return feature_info_->workarounds();
+  }
+
   const gl::GLVersionInfo& gl_version_info() {
     return feature_info_->gl_version_info();
   }
 
+  MemoryTracker* memory_tracker() { return group_->memory_tracker(); }
+
+  bool EnsureGPUMemoryAvailable(size_t estimated_size) {
+    MemoryTracker* tracker = memory_tracker();
+    if (tracker) {
+      return tracker->EnsureGPUMemoryAvailable(estimated_size);
+    }
+    return true;
+  }
+
   const TextureManager* texture_manager() const {
     return group_->texture_manager();
   }
@@ -275,12 +378,25 @@
   void DoReleaseTexImage2DCHROMIUM(GLuint texture_id, GLint image_id) {
     NOTIMPLEMENTED();
   }
+  void TexStorage2DImage(TextureRef* texture_ref,
+                         const TextureMetadata& texture_metadata,
+                         GLsizei width,
+                         GLsizei height) {
+    NOTIMPLEMENTED();
+  }
+  void TexStorage2D(TextureRef* texture_ref,
+                    const TextureMetadata& texture_metadata,
+                    GLint levels,
+                    GLsizei width,
+                    GLsizei height);
+  void TexImage2D(TextureRef* texture_ref,
+                  const TextureMetadata& texture_metadata,
+                  GLsizei width,
+                  GLsizei height);
   void DoTexStorage2D(GLuint texture_id,
                       GLint levels,
                       GLsizei width,
-                      GLsizei height) {
-    NOTIMPLEMENTED();
-  }
+                      GLsizei height);
   void DoCopySubTexture(GLuint source_id,
                         GLuint dest_id,
                         GLint xoffset,
@@ -411,6 +527,10 @@
 
   GLES2Util util_;
 
+  // States related to each manager.
+  DecoderTextureState texture_state_;
+  DecoderFramebufferState framebuffer_state_;
+
   bool gpu_debug_commands_;
 
   // Log extra info.
@@ -490,6 +610,7 @@
       validators_(new Validators),
       feature_info_(group_->feature_info()),
       state_(group_->feature_info(), this, &logger_),
+      texture_state_(group_->feature_info()->workarounds()),
       service_logging_(
           group_->gpu_preferences().enable_gpu_service_logging_gpu),
       weak_ptr_factory_(this) {}
@@ -612,7 +733,9 @@
       group_->gpu_preferences().texture_target_exception_list;
   caps.texture_format_bgra8888 =
       feature_info_->feature_flags().ext_texture_format_bgra8888;
-
+  caps.texture_storage_image =
+      feature_info_->feature_flags().chromium_texture_storage_image;
+  caps.texture_storage = feature_info_->feature_flags().ext_texture_storage;
   return caps;
 }
 
@@ -1205,15 +1328,21 @@
   }
 }
 
-void RasterDecoderImpl::DoTexParameteri(GLuint texture_id,
+void RasterDecoderImpl::DoTexParameteri(GLuint client_id,
                                         GLenum pname,
                                         GLint param) {
-  TextureRef* texture = texture_manager()->GetTexture(texture_id);
+  TextureRef* texture = texture_manager()->GetTexture(client_id);
   if (!texture) {
     LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
     return;
   }
 
+  TextureMetadata* texture_metadata = GetTextureMetadata(client_id);
+  if (!texture_metadata) {
+    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture");
+    return;
+  }
+
   // TextureManager uses validators from the share group, which may include
   // GLES2. Perform stronger validation here.
   bool valid_param = true;
@@ -1241,6 +1370,9 @@
     return;
   }
 
+  ScopedTextureBinder binder(&state_, texture_manager(), texture,
+                             texture_metadata->target());
+
   texture_manager()->SetParameteri("glTexParameteri", GetErrorState(), texture,
                                    pname, param);
 }
@@ -1283,6 +1415,217 @@
   group_->mailbox_manager()->ProduceTexture(mailbox, produced);
 }
 
+void RasterDecoderImpl::TexStorage2D(TextureRef* texture_ref,
+                                     const TextureMetadata& texture_metadata,
+                                     GLint levels,
+                                     GLsizei width,
+                                     GLsizei height) {
+  TRACE_EVENT2("gpu", "RasterDecoderImpl::TexStorage2D", "width", width,
+               "height", height);
+
+  if (!texture_manager()->ValidForTarget(texture_metadata.target(), 0, width,
+                                         height, 1 /* depth */) ||
+      TextureManager::ComputeMipMapCount(texture_metadata.target(), width,
+                                         height, 1 /* depth */) < levels) {
+    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexStorage2D",
+                       "dimensions out of range");
+    return;
+  }
+
+  ScopedTextureBinder binder(&state_, texture_manager(), texture_ref,
+                             texture_metadata.target());
+
+  unsigned int internal_format =
+      viz::GLInternalFormat(texture_metadata.format());
+  GLenum format =
+      TextureManager::ExtractFormatFromStorageFormat(internal_format);
+  GLenum type = TextureManager::ExtractTypeFromStorageFormat(internal_format);
+
+  // First lookup compatibility format via texture manager for swizzling legacy
+  // LUMINANCE/ALPHA formats.
+  GLenum compatibility_internal_format =
+      texture_manager()->AdjustTexStorageFormat(feature_info_.get(),
+                                                internal_format);
+
+  Texture* texture = texture_ref->texture();
+  if (workarounds().reset_base_mipmap_level_before_texstorage &&
+      texture->base_level() > 0)
+    api()->glTexParameteriFn(texture_metadata.target(), GL_TEXTURE_BASE_LEVEL,
+                             0);
+
+  // TODO(zmo): We might need to emulate TexStorage using TexImage or
+  // CompressedTexImage on Mac OSX where we expose ES3 APIs when the underlying
+  // driver is lower than 4.2 and ARB_texture_storage extension doesn't exist.
+  api()->glTexStorage2DEXTFn(texture_metadata.target(), levels,
+                             compatibility_internal_format, width, height);
+  if (workarounds().reset_base_mipmap_level_before_texstorage &&
+      texture->base_level() > 0)
+    api()->glTexParameteriFn(texture_metadata.target(), GL_TEXTURE_BASE_LEVEL,
+                             texture->base_level());
+
+  {
+    GLsizei level_width = width;
+    GLsizei level_height = height;
+
+    GLenum adjusted_internal_format =
+        feature_info_->IsWebGL1OrES2Context() ? format : internal_format;
+    for (int ii = 0; ii < levels; ++ii) {
+      texture_manager()->SetLevelInfo(texture_ref, texture_metadata.target(),
+                                      ii, adjusted_internal_format, level_width,
+                                      level_height, 1 /* level_depth */, 0,
+                                      format, type, gfx::Rect());
+      level_width = std::max(1, level_width >> 1);
+      level_height = std::max(1, level_height >> 1);
+    }
+    texture->ApplyFormatWorkarounds(feature_info_.get());
+  }
+}
+
+void RasterDecoderImpl::TexImage2D(TextureRef* texture_ref,
+                                   const TextureMetadata& texture_metadata,
+                                   GLsizei width,
+                                   GLsizei height) {
+  TRACE_EVENT2("gpu", "RasterDecoderImpl::TexImage2D", "width", width, "height",
+               height);
+
+  // Set as failed for now, but if it successed, this will be set to not failed.
+  texture_state_.tex_image_failed = true;
+
+  DCHECK(!state_.bound_pixel_unpack_buffer.get());
+
+  ScopedTextureBinder binder(&state_, texture_manager(), texture_ref,
+                             texture_metadata.target());
+
+  TextureManager::DoTexImageArguments args = {
+      texture_metadata.target(),
+      0 /* level */,
+      viz::GLInternalFormat(texture_metadata.format()),
+      width,
+      height,
+      1 /* depth */,
+      0 /* border */,
+      viz::GLDataFormat(texture_metadata.format()),
+      viz::GLDataType(texture_metadata.format()),
+      nullptr /* pixels */,
+      0 /* pixels_size */,
+      0 /* padding */,
+      TextureManager::DoTexImageArguments::kTexImage2D};
+  texture_manager()->ValidateAndDoTexImage(
+      &texture_state_, &state_, &framebuffer_state_, "glTexStorage2D", args);
+
+  // This may be a slow command.  Exit command processing to allow for
+  // context preemption and GPU watchdog checks.
+  ExitCommandProcessingEarly();
+}
+
+void RasterDecoderImpl::DoTexStorage2D(GLuint client_id,
+                                       GLint levels,
+                                       GLsizei width,
+                                       GLsizei height) {
+  TextureRef* texture_ref = GetTexture(client_id);
+  if (!texture_ref) {
+    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexStorage2D", "unknown texture");
+    return;
+  }
+
+  TextureMetadata* texture_metadata = GetTextureMetadata(client_id);
+  if (!texture_metadata) {
+    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexStorage2D", "unknown texture");
+    return;
+  }
+
+  Texture* texture = texture_ref->texture();
+  if (texture->IsImmutable()) {
+    LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glTexStorage2D",
+                       "texture is immutable");
+    return;
+  }
+
+  if (levels == 0) {
+    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexStorage2D", "levels == 0");
+    return;
+  }
+
+  if (width < 1 || height < 1) {
+    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexStorage2D", "dimensions < 1");
+    return;
+  }
+
+  // For testing only. Allows us to stress the ability to respond to OOM errors.
+  if (workarounds().simulate_out_of_memory_on_large_textures &&
+      (width * height >= 4096 * 4096)) {
+    LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glTexStorage2D",
+                       "synthetic out of memory");
+    return;
+  }
+
+  // Check if we have enough memory.
+  unsigned int internal_format =
+      viz::GLInternalFormat(texture_metadata->format());
+  bool is_compressed_format =
+      viz::IsResourceFormatCompressed(texture_metadata->format());
+  GLenum format =
+      TextureManager::ExtractFormatFromStorageFormat(internal_format);
+  GLenum type = TextureManager::ExtractTypeFromStorageFormat(internal_format);
+  GLsizei level_width = width;
+  GLsizei level_height = height;
+  base::CheckedNumeric<uint32_t> estimated_size(0);
+  PixelStoreParams params;
+  params.alignment = 1;
+  for (int ii = 0; ii < levels; ++ii) {
+    uint32_t size;
+    if (is_compressed_format) {
+      DCHECK_EQ(static_cast<unsigned int>(GL_ETC1_RGB8_OES), internal_format);
+      base::CheckedNumeric<uint32_t> bytes_required(0);
+      const int kS3TCBlockWidth = 4;
+      const int kS3TCBlockHeight = 4;
+      const int kS3TCDXT1BlockSize = 8;
+      bytes_required = (width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
+      bytes_required *= (height + kS3TCBlockHeight - 1) / kS3TCBlockHeight;
+      bytes_required *= kS3TCDXT1BlockSize;
+      if (!bytes_required.IsValid()) {
+        LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexStorage2D", "invalid size");
+        return;
+      }
+      size = bytes_required.ValueOrDefault(0);
+    } else {
+      if (!GLES2Util::ComputeImageDataSizesES3(
+              level_width, level_height, 1 /* level_depth */, format, type,
+              params, &size, nullptr, nullptr, nullptr, nullptr)) {
+        LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glTexStorage2D",
+                           "dimensions too large");
+        return;
+      }
+    }
+    estimated_size += size;
+    level_width = std::max(1, level_width >> 1);
+    level_height = std::max(1, level_height >> 1);
+  }
+
+  if (!estimated_size.IsValid() ||
+      !EnsureGPUMemoryAvailable(estimated_size.ValueOrDefault(0))) {
+    LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, "glTexStorage2D", "out of memory");
+    return;
+  }
+
+  if (texture_metadata->use_buffer()) {
+    if (!GetCapabilities().texture_storage_image) {
+      LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexStorage2DImage", "use_buffer");
+      return;
+    }
+    DCHECK(levels == 1);
+    TexStorage2DImage(texture_ref, *texture_metadata, width, height);
+  } else if (GetCapabilities().texture_storage) {
+    TexStorage2D(texture_ref, *texture_metadata, levels, width, height);
+  } else {
+    // TODO(backer): Support more than one texture level.
+    DCHECK(levels == 1);
+    TexImage2D(texture_ref, *texture_metadata, width, height);
+  }
+
+  texture->SetImmutable(true);
+}
+
 // Include the auto-generated part of this file. We split this because it means
 // we can easily edit the non-auto generated parts right here in this file
 // instead of having to edit some template or the code generator.
diff --git a/gpu/command_buffer/service/raster_decoder_unittest.cc b/gpu/command_buffer/service/raster_decoder_unittest.cc
index 0268b21c..54a11bf4 100644
--- a/gpu/command_buffer/service/raster_decoder_unittest.cc
+++ b/gpu/command_buffer/service/raster_decoder_unittest.cc
@@ -9,6 +9,7 @@
 #include "gpu/command_buffer/common/mailbox.h"
 #include "gpu/command_buffer/common/raster_cmd_format.h"
 #include "gpu/command_buffer/service/context_group.h"
+#include "gpu/command_buffer/service/memory_tracking.h"
 #include "gpu/command_buffer/service/program_manager.h"
 #include "gpu/command_buffer/service/query_manager.h"
 #include "gpu/command_buffer/service/raster_decoder_unittest_base.h"
@@ -24,31 +25,73 @@
 namespace gpu {
 namespace raster {
 
+namespace {
+const GLsizei kWidth = 10;
+const GLsizei kHeight = 20;
+
+class MockMemoryTracker : public gles2::MemoryTracker {
+ public:
+  MockMemoryTracker() {}
+
+  // Ensure a certain amount of GPU memory is free. Returns true on success.
+  MOCK_METHOD1(EnsureGPUMemoryAvailable, bool(size_t size_needed));
+
+  void TrackMemoryAllocatedChange(size_t old_size, size_t new_size) override {}
+
+  uint64_t ClientTracingId() const override { return 0; }
+  int ClientId() const override { return 0; }
+  uint64_t ShareGroupTracingGUID() const override { return 0; }
+
+ private:
+  virtual ~MockMemoryTracker() = default;
+};
+
+}  // namespace
+
 class RasterDecoderTest : public RasterDecoderTestBase {
  public:
   RasterDecoderTest() = default;
 };
 
+class RasterDecoderManualInitTest : public RasterDecoderTestBase {
+ public:
+  RasterDecoderManualInitTest() = default;
+
+  // Override default setup so nothing gets setup.
+  void SetUp() override {}
+};
+
 INSTANTIATE_TEST_CASE_P(Service, RasterDecoderTest, ::testing::Bool());
+INSTANTIATE_TEST_CASE_P(Service,
+                        RasterDecoderManualInitTest,
+                        ::testing::Bool());
 
 TEST_P(RasterDecoderTest, TexParameteriValidArgs) {
-  EXPECT_CALL(*gl_, TexParameteri(_, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
+  SetScopedTextureBinderExpectations(GL_TEXTURE_2D);
+  EXPECT_CALL(*gl_,
+              TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
   cmds::TexParameteri cmd;
   cmd.Init(client_texture_id_, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
   EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
   EXPECT_EQ(GL_NO_ERROR, GetGLError());
 
-  EXPECT_CALL(*gl_, TexParameteri(_, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
+  SetScopedTextureBinderExpectations(GL_TEXTURE_2D);
+  EXPECT_CALL(*gl_,
+              TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
   cmd.Init(client_texture_id_, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
   EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
   EXPECT_EQ(GL_NO_ERROR, GetGLError());
 
-  EXPECT_CALL(*gl_, TexParameteri(_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
+  SetScopedTextureBinderExpectations(GL_TEXTURE_2D);
+  EXPECT_CALL(
+      *gl_, TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
   cmd.Init(client_texture_id_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
   EXPECT_EQ(GL_NO_ERROR, GetGLError());
 
-  EXPECT_CALL(*gl_, TexParameteri(_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
+  SetScopedTextureBinderExpectations(GL_TEXTURE_2D);
+  EXPECT_CALL(
+      *gl_, TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
   cmd.Init(client_texture_id_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
   EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
   EXPECT_EQ(GL_NO_ERROR, GetGLError());
@@ -186,19 +229,92 @@
   EXPECT_FALSE(query->IsPending());
 }
 
-TEST_P(RasterDecoderTest, ProduceAndConsumeTexture) {
-  Mailbox mailbox = Mailbox::Generate();
-  GLuint new_texture_id = kNewClientId;
-
-  // TODO(backer): Use TexStorage2D to set some attributes like width and
-  // height.
+TEST_P(RasterDecoderTest, TexStorage2D) {
+  DoTexStorage2D(client_texture_id_, 1 /* levels */, kWidth, kHeight);
 
   gles2::TextureRef* texture_ref =
       group().texture_manager()->GetTexture(client_texture_id_);
   ASSERT_TRUE(texture_ref != nullptr);
   gles2::Texture* texture = texture_ref->texture();
+
   EXPECT_EQ(kServiceTextureId, texture->service_id());
 
+  GLsizei width;
+  GLsizei height;
+  EXPECT_TRUE(
+      texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height, nullptr));
+  EXPECT_EQ(width, kWidth);
+  EXPECT_EQ(height, kHeight);
+}
+
+TEST_P(RasterDecoderManualInitTest, TexStorage2DWithEXTTextureStorage) {
+  InitDecoderWithWorkarounds({"GL_ARB_sync", "GL_EXT_texture_storage"});
+  DoTexStorage2D(client_texture_id_, 2 /* levels */, kWidth, kHeight);
+
+  gles2::TextureRef* texture_ref =
+      group().texture_manager()->GetTexture(client_texture_id_);
+  ASSERT_TRUE(texture_ref != nullptr);
+  gles2::Texture* texture = texture_ref->texture();
+
+  EXPECT_EQ(kServiceTextureId, texture->service_id());
+
+  GLsizei width;
+  GLsizei height;
+  EXPECT_TRUE(
+      texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height, nullptr));
+  EXPECT_EQ(width, kWidth);
+  EXPECT_EQ(height, kHeight);
+
+  EXPECT_TRUE(
+      texture->GetLevelSize(GL_TEXTURE_2D, 1, &width, &height, nullptr));
+  EXPECT_EQ(width, kWidth / 2);
+  EXPECT_EQ(height, kHeight / 2);
+}
+
+TEST_P(RasterDecoderManualInitTest, TexStorage2DOutOfMemory) {
+  scoped_refptr<MockMemoryTracker> memory_tracker = new MockMemoryTracker();
+  set_memory_tracker(memory_tracker.get());
+  InitDecoderWithWorkarounds({"GL_ARB_sync"});
+
+  EXPECT_CALL(*memory_tracker.get(), EnsureGPUMemoryAvailable(_))
+      .WillOnce(Return(false))
+      .RetiresOnSaturation();
+
+  cmds::TexStorage2D cmd;
+  cmd.Init(client_texture_id_, 1 /* levels */, kWidth, kHeight);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+  EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError());
+}
+
+TEST_P(RasterDecoderTest, TexStorage2DInvalid) {
+  // Bad client id
+  cmds::TexStorage2D cmd;
+  cmd.Init(kInvalidClientId, 1 /* levels */, kWidth, kHeight);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+  EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
+
+  // Bad levels
+  cmd.Init(client_texture_id_, 0 /* levels */, kWidth, kHeight);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+  EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
+
+  // Bad width
+  cmd.Init(client_texture_id_, 1 /* levels */, 0, kHeight);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+  EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
+
+  // Bad height
+  cmd.Init(client_texture_id_, 1 /* levels */, kWidth, 0);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+  EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
+}
+
+TEST_P(RasterDecoderTest, ProduceAndConsumeTexture) {
+  Mailbox mailbox = Mailbox::Generate();
+  GLuint new_texture_id = kNewClientId;
+
+  DoTexStorage2D(client_texture_id_, 1 /* levels */, kWidth, kHeight);
+
   ProduceTextureDirectImmediate& produce_cmd =
       *GetImmediateAs<ProduceTextureDirectImmediate>();
   produce_cmd.Init(client_texture_id_, mailbox.name);
@@ -206,10 +322,17 @@
             ExecuteImmediateCmd(produce_cmd, sizeof(mailbox.name)));
   EXPECT_EQ(GL_NO_ERROR, GetGLError());
 
-  // TODO(backer): Check that ProduceTextureDirect did not change attributes
-  // like width and height.
+  // Check that ProduceTextureDirect did not change attributes.
+  gles2::TextureRef* texture_ref =
+      group().texture_manager()->GetTexture(client_texture_id_);
+  ASSERT_TRUE(texture_ref != nullptr);
+  gles2::Texture* texture = texture_ref->texture();
 
-  // Service ID has not changed.
+  GLsizei width, height;
+  EXPECT_TRUE(
+      texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height, nullptr));
+  EXPECT_EQ(width, kWidth);
+  EXPECT_EQ(height, kHeight);
   EXPECT_EQ(kServiceTextureId, texture->service_id());
 
   CreateAndConsumeTextureINTERNALImmediate& consume_cmd =
@@ -221,13 +344,15 @@
             ExecuteImmediateCmd(consume_cmd, sizeof(mailbox.name)));
   EXPECT_EQ(GL_NO_ERROR, GetGLError());
 
-  // TODO(backer): Check that new_texture_id has appropriate attributes like
-  // width and height.
-
-  // Service ID is restored.
+  // Check that new_texture_id has appropriate attributes like width and height.
   texture_ref = group().texture_manager()->GetTexture(new_texture_id);
   ASSERT_NE(texture_ref, nullptr);
-  EXPECT_EQ(kServiceTextureId, texture_ref->service_id());
+  texture = texture_ref->texture();
+  EXPECT_TRUE(
+      texture->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height, nullptr));
+  EXPECT_EQ(width, kWidth);
+  EXPECT_EQ(height, kHeight);
+  EXPECT_EQ(kServiceTextureId, texture->service_id());
 }
 
 }  // namespace raster
diff --git a/gpu/command_buffer/service/raster_decoder_unittest_base.cc b/gpu/command_buffer/service/raster_decoder_unittest_base.cc
index abb6e19..0ed580da 100644
--- a/gpu/command_buffer/service/raster_decoder_unittest_base.cc
+++ b/gpu/command_buffer/service/raster_decoder_unittest_base.cc
@@ -34,7 +34,9 @@
 using ::testing::_;
 using ::testing::AnyNumber;
 using ::testing::AtMost;
+using ::testing::Between;
 using ::testing::InSequence;
+using ::testing::Ne;
 using ::testing::Pointee;
 using ::testing::Return;
 using ::testing::SetArgPointee;
@@ -73,11 +75,15 @@
 void RasterDecoderTestBase::OnRescheduleAfterFinished() {}
 
 void RasterDecoderTestBase::SetUp() {
-  InitDecoderWithWorkarounds();
+  InitDecoderWithWorkarounds({"GL_ARB_sync"});
 }
 
-void RasterDecoderTestBase::InitDecoderWithWorkarounds() {
-  const std::string extensions("GL_ARB_sync ");
+void RasterDecoderTestBase::InitDecoderWithWorkarounds(
+    std::initializer_list<std::string> extensions) {
+  std::string all_extensions;
+  for (const std::string& extension : extensions) {
+    all_extensions += extension + " ";
+  }
   const std::string gl_version("2.1");
   const bool bind_generates_resource(false);
   const bool lose_context_when_out_of_memory(false);
@@ -108,14 +114,14 @@
   // in turn initialize FeatureInfo, which needs a context to determine
   // extension support.
   context_ = new StrictMock<GLContextMock>();
-  context_->SetExtensionsString(extensions.c_str());
+  context_->SetExtensionsString(all_extensions.c_str());
   context_->SetGLVersionString(gl_version.c_str());
 
   context_->GLContextStub::MakeCurrent(surface_.get());
 
   TestHelper::SetupContextGroupInitExpectations(
-      gl_.get(), DisallowedFeatures(), extensions.c_str(), gl_version.c_str(),
-      context_type, bind_generates_resource);
+      gl_.get(), DisallowedFeatures(), all_extensions.c_str(),
+      gl_version.c_str(), context_type, bind_generates_resource);
 
   // We initialize the ContextGroup with a MockRasterDecoder so that
   // we can use the ContextGroup to figure out how the real RasterDecoder
@@ -284,6 +290,44 @@
   }
 }
 
+void RasterDecoderTestBase::SetScopedTextureBinderExpectations(GLenum target) {
+  // ScopedTextureBinder
+  EXPECT_CALL(*gl_, ActiveTexture(_))
+      .Times(Between(1, 2))
+      .RetiresOnSaturation();
+  EXPECT_CALL(*gl_, BindTexture(target, Ne(0U))).Times(1).RetiresOnSaturation();
+  EXPECT_CALL(*gl_, BindTexture(target, 0)).Times(1).RetiresOnSaturation();
+}
+
+void RasterDecoderTestBase::DoTexStorage2D(GLuint client_id,
+                                           GLint levels,
+                                           GLsizei width,
+                                           GLsizei height) {
+  cmds::TexStorage2D tex_storage_cmd;
+  tex_storage_cmd.Init(client_id, levels, width, height);
+
+  SetScopedTextureBinderExpectations(GL_TEXTURE_2D);
+
+  if (decoder_->GetCapabilities().texture_storage) {
+    EXPECT_CALL(*gl_, TexStorage2DEXT(GL_TEXTURE_2D, levels, _, width, height))
+        .Times(1)
+        .RetiresOnSaturation();
+  } else {
+    // Currently only supports levels == 1
+    DCHECK_EQ(levels, 1);
+
+    EXPECT_CALL(*gl_, GetError())
+        .WillOnce(Return(GL_NO_ERROR))
+        .WillOnce(Return(GL_NO_ERROR))
+        .RetiresOnSaturation();
+    EXPECT_CALL(*gl_,
+                TexImage2D(GL_TEXTURE_2D, _, _, width, height, _, _, _, _))
+        .Times(1)
+        .RetiresOnSaturation();
+  }
+  EXPECT_EQ(error::kNoError, ExecuteCmd(tex_storage_cmd));
+  EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
 
 // Include the auto-generated part of this file. We split this because it means
 // we can easily edit the non-auto generated parts right here in this file
diff --git a/gpu/command_buffer/service/raster_decoder_unittest_base.h b/gpu/command_buffer/service/raster_decoder_unittest_base.h
index 44d947bb..23f05ea 100644
--- a/gpu/command_buffer/service/raster_decoder_unittest_base.h
+++ b/gpu/command_buffer/service/raster_decoder_unittest_base.h
@@ -9,7 +9,9 @@
 #include <stdint.h>
 
 #include <array>
+#include <initializer_list>
 #include <memory>
+#include <string>
 
 #include "base/message_loop/message_loop.h"
 #include "gpu/command_buffer/client/client_test_helper.h"
@@ -127,8 +129,12 @@
                            const char** str,
                            GLsizei count_in_header,
                            char str_end);
+  void set_memory_tracker(gles2::MemoryTracker* memory_tracker) {
+    memory_tracker_ = memory_tracker;
+  }
 
-  void InitDecoderWithWorkarounds();
+  void InitDecoderWithWorkarounds(
+      std::initializer_list<std::string> extensions);
 
   void ResetDecoder();
 
@@ -165,6 +171,11 @@
 
   void DoBindTexture(GLenum target, GLuint client_id, GLuint service_id);
   void DoDeleteTexture(GLuint client_id, GLuint service_id);
+  void SetScopedTextureBinderExpectations(GLenum target);
+  void DoTexStorage2D(GLuint client_id,
+                      GLint levels,
+                      GLsizei width,
+                      GLsizei height);
 
   GLvoid* BufferOffset(unsigned i) { return static_cast<int8_t*>(NULL) + (i); }
 
diff --git a/gpu/command_buffer/service/vertex_array_manager.h b/gpu/command_buffer/service/vertex_array_manager.h
index a3ab420f..29cc3d6 100644
--- a/gpu/command_buffer/service/vertex_array_manager.h
+++ b/gpu/command_buffer/service/vertex_array_manager.h
@@ -29,6 +29,8 @@
   // Must call before destruction.
   void Destroy(bool have_context);
 
+  void MarkContextLost() { have_context_ = false; }
+
   // Creates a VertexAttribManager and if client_visible,
   // maps it to the client_id.
   scoped_refptr<VertexAttribManager> CreateVertexAttribManager(
diff --git a/gpu/command_buffer/service/vertex_attrib_manager.cc b/gpu/command_buffer/service/vertex_attrib_manager.cc
index 673f36b3..e8b25e7 100644
--- a/gpu/command_buffer/service/vertex_attrib_manager.cc
+++ b/gpu/command_buffer/service/vertex_attrib_manager.cc
@@ -168,21 +168,47 @@
   return true;
 }
 
-void VertexAttribManager::Unbind(Buffer* buffer) {
-  if (!buffer)
-    return;
+void VertexAttribManager::Unbind(Buffer* buffer, Buffer* bound_array_buffer) {
+  DCHECK(buffer);
+  DCHECK(is_bound_);
   if (element_array_buffer_.get() == buffer) {
-    if (do_buffer_refcounting_ && is_bound_)
+    if (do_buffer_refcounting_)
       buffer->OnUnbind(GL_ELEMENT_ARRAY_BUFFER);
+    if (manager_ && manager_->have_context_)
+      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
     element_array_buffer_ = nullptr;
   }
+  // When a vertex array object is bound, some drivers (AMD Linux,
+  // Qualcomm, etc.) have a bug where it incorrectly generates an
+  // GL_INVALID_OPERATION on glVertexAttribPointer() if pointer is
+  // NULL, no buffer is bound on GL_ARRAY_BUFFER.  Therefore, in order
+  // to clear the buffer bindings, we create a new array buffer,
+  // redirect all bindings to the new buffer, and then delete the
+  // buffer.
+  GLuint new_buffer = 0;
   for (uint32_t vv = 0; vv < vertex_attribs_.size(); ++vv) {
     if (vertex_attribs_[vv].buffer_ == buffer) {
-      if (do_buffer_refcounting_ && is_bound_)
+      if (do_buffer_refcounting_)
         buffer->OnUnbind(GL_ARRAY_BUFFER);
       vertex_attribs_[vv].buffer_ = nullptr;
+      if (manager_ && manager_->have_context_) {
+        if (!new_buffer) {
+          glGenBuffersARB(1, &new_buffer);
+          DCHECK_NE(0u, new_buffer);
+          glBindBuffer(GL_ARRAY_BUFFER, new_buffer);
+          // TODO(zmo): Do we need to also call glBufferData() here?
+        }
+        glVertexAttribPointer(
+            vv, vertex_attribs_[vv].size_, vertex_attribs_[vv].type_,
+            vertex_attribs_[vv].normalized_, vertex_attribs_[vv].gl_stride_, 0);
+      }
     }
   }
+  if (new_buffer) {
+    glDeleteBuffersARB(1, &new_buffer);
+    glBindBuffer(GL_ARRAY_BUFFER,
+                 bound_array_buffer ? bound_array_buffer->service_id() : 0u);
+  }
 }
 
 void VertexAttribManager::SetIsBound(bool is_bound) {
diff --git a/gpu/command_buffer/service/vertex_attrib_manager.h b/gpu/command_buffer/service/vertex_attrib_manager.h
index f60539f..f652798c 100644
--- a/gpu/command_buffer/service/vertex_attrib_manager.h
+++ b/gpu/command_buffer/service/vertex_attrib_manager.h
@@ -278,7 +278,7 @@
     return service_id_;
   }
 
-  void Unbind(Buffer* buffer);
+  void Unbind(Buffer* buffer, Buffer* bound_array_buffer);
 
   bool IsDeleted() const {
     return deleted_;
diff --git a/gpu/command_buffer/service/vertex_attrib_manager_unittest.cc b/gpu/command_buffer/service/vertex_attrib_manager_unittest.cc
index c894c6a..c0eb67c 100644
--- a/gpu/command_buffer/service/vertex_attrib_manager_unittest.cc
+++ b/gpu/command_buffer/service/vertex_attrib_manager_unittest.cc
@@ -40,6 +40,7 @@
 
     manager_ = new VertexAttribManager(false);
     manager_->Initialize(kNumVertexAttribs, true);
+    manager_->SetIsBound(true);
   }
 
   scoped_refptr<VertexAttribManager> manager_;
@@ -204,12 +205,12 @@
   EXPECT_EQ(buffer1, attrib1->buffer());
   EXPECT_EQ(buffer1, attrib3->buffer());
   // Unbind unattached buffer.
-  manager_->Unbind(buffer2);
+  manager_->Unbind(buffer2, nullptr);
   // Should be no-op.
   EXPECT_EQ(buffer1, attrib1->buffer());
   EXPECT_EQ(buffer1, attrib3->buffer());
   // Unbind buffer.
-  manager_->Unbind(buffer1);
+  manager_->Unbind(buffer1, nullptr);
   // Check they were detached
   EXPECT_TRUE(NULL == attrib1->buffer());
   EXPECT_TRUE(NULL == attrib3->buffer());
diff --git a/gpu/command_buffer/tests/gl_virtual_contexts_ext_window_rectangles_unittest.cc b/gpu/command_buffer/tests/gl_virtual_contexts_ext_window_rectangles_unittest.cc
index 9e412b8..99b6286 100644
--- a/gpu/command_buffer/tests/gl_virtual_contexts_ext_window_rectangles_unittest.cc
+++ b/gpu/command_buffer/tests/gl_virtual_contexts_ext_window_rectangles_unittest.cc
@@ -20,14 +20,20 @@
     GLManager::Options options;
     options.context_type = CONTEXT_TYPE_OPENGLES3;
     gl_real_shared_.Initialize(options);
+
+    if (!IsApplicable())
+      return;
+
     options.virtual_manager = &gl_real_shared_;
     gl1_.Initialize(options);
     gl2_.Initialize(options);
   }
 
   void TearDown() override {
-    gl1_.Destroy();
-    gl2_.Destroy();
+    if (IsApplicable()) {
+      gl1_.Destroy();
+      gl2_.Destroy();
+    }
     gl_real_shared_.Destroy();
   }
 
diff --git a/gpu/config/gpu_util.cc b/gpu/config/gpu_util.cc
index 384c4801..e84a91f 100644
--- a/gpu/config/gpu_util.cc
+++ b/gpu/config/gpu_util.cc
@@ -202,7 +202,7 @@
   return gpu_feature_info;
 }
 
-GpuFeatureInfo ComputeGpuFeatureInfoWithNoGpuProcess() {
+GpuFeatureInfo ComputeGpuFeatureInfoWithNoGpu() {
   GpuFeatureInfo gpu_feature_info;
   gpu_feature_info.status_values[GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS] =
       kGpuFeatureStatusSoftware;
diff --git a/gpu/config/gpu_util.h b/gpu/config/gpu_util.h
index dfcc307..b99a1cb 100644
--- a/gpu/config/gpu_util.h
+++ b/gpu/config/gpu_util.h
@@ -21,8 +21,8 @@
 GPU_EXPORT GpuFeatureInfo
 ComputeGpuFeatureInfoWithHardwareAccelerationDisabled();
 
-// Set GPU feature status if GPU process is blocked.
-GPU_EXPORT GpuFeatureInfo ComputeGpuFeatureInfoWithNoGpuProcess();
+// Set GPU feature status if GPU is blocked.
+GPU_EXPORT GpuFeatureInfo ComputeGpuFeatureInfoWithNoGpu();
 
 // Set GPU feature status for SwiftShader.
 GPU_EXPORT GpuFeatureInfo ComputeGpuFeatureInfoForSwiftShader();
diff --git a/gpu/ipc/client/command_buffer_proxy_impl_unittest.cc b/gpu/ipc/client/command_buffer_proxy_impl_unittest.cc
new file mode 100644
index 0000000..14b9f50
--- /dev/null
+++ b/gpu/ipc/client/command_buffer_proxy_impl_unittest.cc
@@ -0,0 +1,159 @@
+// Copyright (c) 2018 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 "gpu/ipc/client/command_buffer_proxy_impl.h"
+
+#include "base/memory/scoped_refptr.h"
+#include "base/test/test_simple_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "gpu/ipc/client/gpu_channel_host.h"
+#include "gpu/ipc/common/gpu_messages.h"
+#include "gpu/ipc/common/surface_handle.h"
+#include "ipc/ipc_test_sink.h"
+#include "mojo/public/cpp/system/message_pipe.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace gpu {
+// GpuChannelHost is expected to be created on the IO thread, and posts tasks to
+// setup its IPC listener, so it must be created after the thread task runner
+// handle is set.  It expects Send to be called on any thread except IO thread,
+// and posts tasks to the IO thread to ensure IPCs are sent in order, which is
+// important for sync IPCs.  But we override Send, so we can't test sync IPC
+// behavior with this setup.
+class TestGpuChannelHost : public GpuChannelHost {
+ public:
+  TestGpuChannelHost(IPC::TestSink* sink)
+      : GpuChannelHost(0 /* channel_id */,
+                       GPUInfo(),
+                       GpuFeatureInfo(),
+                       mojo::ScopedMessagePipeHandle(
+                           mojo::MessagePipeHandle(mojo::kInvalidHandleValue))),
+        sink_(sink) {}
+
+  bool Send(IPC::Message* msg) override { return sink_->Send(msg); }
+
+ protected:
+  ~TestGpuChannelHost() override {}
+
+  IPC::TestSink* sink_;
+};
+
+class CommandBufferProxyImplTest : public testing::Test {
+ public:
+  CommandBufferProxyImplTest()
+      : task_runner_(base::MakeRefCounted<base::TestSimpleTaskRunner>()),
+        thread_task_runner_handle_override_(
+            base::ThreadTaskRunnerHandle::OverrideForTesting(task_runner_)),
+        channel_(base::MakeRefCounted<TestGpuChannelHost>(&sink_)) {}
+
+  ~CommandBufferProxyImplTest() override {
+    // Release channel, and run any cleanup tasks it posts.
+    channel_ = nullptr;
+    task_runner_->RunUntilIdle();
+  }
+
+  std::unique_ptr<CommandBufferProxyImpl> CreateAndInitializeProxy() {
+    auto proxy = std::make_unique<CommandBufferProxyImpl>(
+        channel_, nullptr /* gpu_memory_buffer_manager */, 0 /* stream_id */,
+        task_runner_);
+    proxy->Initialize(kNullSurfaceHandle, nullptr, SchedulingPriority::kNormal,
+                      ContextCreationAttribs(), GURL());
+    // Use an arbitrary valid shm_id. The command buffer doesn't use this
+    // directly, but not setting it triggers DCHECKs.
+    proxy->SetGetBuffer(1 /* shm_id */);
+    sink_.ClearMessages();
+    return proxy;
+  }
+
+ protected:
+  IPC::TestSink sink_;
+  scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
+  base::ScopedClosureRunner thread_task_runner_handle_override_;
+  scoped_refptr<TestGpuChannelHost> channel_;
+};
+
+TEST_F(CommandBufferProxyImplTest, OrderingBarriersAreCoalescedWithFlush) {
+  auto proxy1 = CreateAndInitializeProxy();
+  auto proxy2 = CreateAndInitializeProxy();
+
+  proxy1->OrderingBarrier(10);
+  proxy2->OrderingBarrier(20);
+  proxy1->OrderingBarrier(30);
+  proxy1->OrderingBarrier(40);
+  proxy1->Flush(50);
+
+  EXPECT_EQ(1u, sink_.message_count());
+  const IPC::Message* msg =
+      sink_.GetFirstMessageMatching(GpuChannelMsg_FlushCommandBuffers::ID);
+  ASSERT_TRUE(msg);
+  GpuChannelMsg_FlushCommandBuffers::Param params;
+  ASSERT_TRUE(GpuChannelMsg_FlushCommandBuffers::Read(msg, &params));
+  std::vector<FlushParams> flush_list = std::get<0>(std::move(params));
+  EXPECT_EQ(3u, flush_list.size());
+  EXPECT_EQ(proxy1->route_id(), flush_list[0].route_id);
+  EXPECT_EQ(10, flush_list[0].put_offset);
+  EXPECT_EQ(proxy2->route_id(), flush_list[1].route_id);
+  EXPECT_EQ(20, flush_list[1].put_offset);
+  EXPECT_EQ(proxy1->route_id(), flush_list[2].route_id);
+  EXPECT_EQ(50, flush_list[2].put_offset);
+}
+
+TEST_F(CommandBufferProxyImplTest, FlushPendingWorkFlushesOrderingBarriers) {
+  auto proxy1 = CreateAndInitializeProxy();
+  auto proxy2 = CreateAndInitializeProxy();
+
+  proxy1->OrderingBarrier(10);
+  proxy2->OrderingBarrier(20);
+  proxy1->OrderingBarrier(30);
+  proxy2->FlushPendingWork();
+
+  EXPECT_EQ(1u, sink_.message_count());
+  const IPC::Message* msg =
+      sink_.GetFirstMessageMatching(GpuChannelMsg_FlushCommandBuffers::ID);
+  ASSERT_TRUE(msg);
+  GpuChannelMsg_FlushCommandBuffers::Param params;
+  ASSERT_TRUE(GpuChannelMsg_FlushCommandBuffers::Read(msg, &params));
+  std::vector<FlushParams> flush_list = std::get<0>(std::move(params));
+  EXPECT_EQ(3u, flush_list.size());
+  EXPECT_EQ(proxy1->route_id(), flush_list[0].route_id);
+  EXPECT_EQ(10, flush_list[0].put_offset);
+  EXPECT_EQ(proxy2->route_id(), flush_list[1].route_id);
+  EXPECT_EQ(20, flush_list[1].put_offset);
+  EXPECT_EQ(proxy1->route_id(), flush_list[2].route_id);
+  EXPECT_EQ(30, flush_list[2].put_offset);
+}
+
+TEST_F(CommandBufferProxyImplTest, EnsureWorkVisibleFlushesOrderingBarriers) {
+  auto proxy1 = CreateAndInitializeProxy();
+  auto proxy2 = CreateAndInitializeProxy();
+
+  proxy1->OrderingBarrier(10);
+  proxy2->OrderingBarrier(20);
+  proxy1->OrderingBarrier(30);
+
+  proxy2->EnsureWorkVisible();
+
+  EXPECT_EQ(2u, sink_.message_count());
+  const IPC::Message* msg = sink_.GetMessageAt(0);
+  ASSERT_TRUE(msg);
+  EXPECT_EQ(static_cast<uint32_t>(GpuChannelMsg_FlushCommandBuffers::ID),
+            msg->type());
+
+  GpuChannelMsg_FlushCommandBuffers::Param params;
+  ASSERT_TRUE(GpuChannelMsg_FlushCommandBuffers::Read(msg, &params));
+  std::vector<FlushParams> flush_list = std::get<0>(std::move(params));
+  EXPECT_EQ(3u, flush_list.size());
+  EXPECT_EQ(proxy1->route_id(), flush_list[0].route_id);
+  EXPECT_EQ(10, flush_list[0].put_offset);
+  EXPECT_EQ(proxy2->route_id(), flush_list[1].route_id);
+  EXPECT_EQ(20, flush_list[1].put_offset);
+  EXPECT_EQ(proxy1->route_id(), flush_list[2].route_id);
+  EXPECT_EQ(30, flush_list[2].put_offset);
+
+  msg = sink_.GetMessageAt(1);
+  ASSERT_TRUE(msg);
+  EXPECT_EQ(static_cast<uint32_t>(GpuChannelMsg_Nop::ID), msg->type());
+}
+
+}  // namespace gpu
diff --git a/gpu/ipc/client/gpu_channel_host.h b/gpu/ipc/client/gpu_channel_host.h
index 21b6d54..221fd3e 100644
--- a/gpu/ipc/client/gpu_channel_host.h
+++ b/gpu/ipc/client/gpu_channel_host.h
@@ -128,9 +128,11 @@
   // Generate a route ID guaranteed to be unique for this channel.
   int32_t GenerateRouteID();
 
- private:
+ protected:
   friend class base::RefCountedThreadSafe<GpuChannelHost>;
+  ~GpuChannelHost() override;
 
+ private:
   // A filter used internally to route incoming messages from the IO thread
   // to the correct message loop. It also maintains some shared state between
   // all the contexts.
@@ -190,7 +192,6 @@
     bool lost_ = false;
   };
 
-  ~GpuChannelHost() override;
   void InternalFlush(uint32_t flush_id);
 
   // Threading notes: all fields are constant during the lifetime of |this|
diff --git a/gpu/ipc/common/gpu_preferences.typemap b/gpu/ipc/common/gpu_preferences.typemap
index 0dfa902..7b8f2748a 100644
--- a/gpu/ipc/common/gpu_preferences.typemap
+++ b/gpu/ipc/common/gpu_preferences.typemap
@@ -7,7 +7,7 @@
 traits_headers = [ "//gpu/ipc/common/gpu_preferences_struct_traits.h" ]
 public_deps = [
   "//gpu/command_buffer/service",
-  "//media:media_features",
+  "//media:media_buildflags",
   "//mojo/common:struct_traits",
 ]
 type_mappings = [
diff --git a/gpu/ipc/service/gpu_init.cc b/gpu/ipc/service/gpu_init.cc
index f4cd63ba..88bcec9 100644
--- a/gpu/ipc/service/gpu_init.cc
+++ b/gpu/ipc/service/gpu_init.cc
@@ -120,13 +120,19 @@
         gpu_preferences.log_gpu_control_list_decisions, command_line,
         &needs_more_info);
   }
-  if (gpu::SwitchableGPUsSupported(gpu_info_, *command_line)) {
-    gpu::InitializeSwitchableGPUs(
-        gpu_feature_info_.enabled_gpu_driver_bug_workarounds);
-  }
 #endif  // !OS_ANDROID && !IS_CHROMECAST
   gpu_info_.in_process_gpu = false;
 
+  // GL bindings may have already been initialized, specifically on MacOSX.
+  bool gl_initialized = gl::GetGLImplementation() != gl::kGLImplementationNone;
+  if (!gl_initialized) {
+    // If GL has already been initialized, then it's too late to select GPU.
+    if (gpu::SwitchableGPUsSupported(gpu_info_, *command_line)) {
+      gpu::InitializeSwitchableGPUs(
+          gpu_feature_info_.enabled_gpu_driver_bug_workarounds);
+    }
+  }
+
   bool enable_watchdog = !gpu_preferences.disable_gpu_watchdog &&
                          !command_line->HasSwitch(switches::kHeadless);
 
@@ -189,10 +195,6 @@
 #endif
 
   bool use_swiftshader = ShouldEnableSwiftShader(command_line, needs_more_info);
-  // Load and initialize the GL implementation and locate the GL entry points if
-  // needed. This initialization may have already happened if running in the
-  // browser process, for example.
-  bool gl_initialized = gl::GetGLImplementation() != gl::kGLImplementationNone;
   if (gl_initialized && use_swiftshader) {
     gl::init::ShutdownGL(true);
     gl_initialized = false;
diff --git a/gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.cc b/gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.cc
index 4c1f72e..69d31ad 100644
--- a/gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.cc
+++ b/gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.cc
@@ -6,6 +6,7 @@
 
 #include "ui/gfx/buffer_format_util.h"
 #include "ui/gfx/client_native_pixmap.h"
+#include "ui/gfx/linux/native_pixmap_dmabuf.h"
 #include "ui/gfx/native_pixmap.h"
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_image_native_pixmap.h"
@@ -105,9 +106,9 @@
                  ->CreateNativePixmapFromHandle(surface_handle, size, format,
                                                 handle.native_pixmap_handle);
 #else
-    // TODO(j.isorce): implement this to enable glCreateImageCHROMIUM on Linux.
-    // On going in http://codereview.chromium.org/2705213005, crbug.com/584248.
-    NOTIMPLEMENTED();
+    DCHECK_EQ(surface_handle, gpu::kNullSurfaceHandle);
+    pixmap = base::WrapRefCounted(
+        new gfx::NativePixmapDmaBuf(size, format, handle.native_pixmap_handle));
 #endif
     if (!pixmap.get()) {
       DLOG(ERROR) << "Failed to create pixmap from handle";
diff --git a/gpu/vulkan/BUILD.gn b/gpu/vulkan/BUILD.gn
index 53f06fd..976f68e 100644
--- a/gpu/vulkan/BUILD.gn
+++ b/gpu/vulkan/BUILD.gn
@@ -8,10 +8,11 @@
 import("//testing/test.gni")
 
 # Generate a buildflag header for compile-time checking of Vulkan support.
-buildflag_header("features") {
-  header = "features.h"
+buildflag_header("buildflags") {
+  header = "buildflags.h"
   flags = [ "ENABLE_VULKAN=$enable_vulkan" ]
 }
+
 if (enable_vulkan) {
   vulkan_lib_dir = getenv("VULKAN_SDK") + "/lib"
   component("vulkan") {
diff --git a/headless/BUILD.gn b/headless/BUILD.gn
index 35e5e9d..f360d31 100644
--- a/headless/BUILD.gn
+++ b/headless/BUILD.gn
@@ -731,9 +731,6 @@
     "public/util/testing/test_in_memory_protocol_handler.h",
     "test/headless_browser_test.cc",
     "test/headless_browser_test.h",
-    "test/headless_render_browsertest.cc",
-    "test/headless_render_test.cc",
-    "test/headless_render_test.h",
     "test/headless_test_launcher.cc",
     "test/tab_socket_test.cc",
     "test/tab_socket_test.h",
@@ -788,11 +785,21 @@
     ]
   }
 
-  # Only include this if we built the js_binary
   if (is_linux) {
+    # Only include this if we built the js_binary
     data += [ "$root_out_dir/headless_browser_tests.pak" ]
-    sources += [ "test/headless_js_bindings_browsertest.cc" ]
-    deps += [ ":headless_browser_tests_pak" ]
+    sources += [
+      "test/headless_js_bindings_browsertest.cc",
+      "test/headless_render_browsertest.cc",
+      "test/headless_render_test.cc",
+      "test/headless_render_test.h",
+    ]
+    deps += [
+      ":headless_browser_tests_pak",
+      "//ui/gfx:geometry_skia",
+      "//ui/gfx/codec",
+      "//ui/gfx/geometry",
+    ]
   }
 
   if (enable_basic_printing) {
diff --git a/headless/lib/browser/headless_browser_context_impl.cc b/headless/lib/browser/headless_browser_context_impl.cc
index 47d4a97..d86a0f73 100644
--- a/headless/lib/browser/headless_browser_context_impl.cc
+++ b/headless/lib/browser/headless_browser_context_impl.cc
@@ -91,6 +91,7 @@
 
 HeadlessBrowserContextImpl::~HeadlessBrowserContextImpl() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  NotifyWillBeDestroyed(this);
 
   // Inform observers that we're going away.
   {
diff --git a/headless/lib/browser/headless_browser_context_impl.h b/headless/lib/browser/headless_browser_context_impl.h
index 4204139..7c27e9b 100644
--- a/headless/lib/browser/headless_browser_context_impl.h
+++ b/headless/lib/browser/headless_browser_context_impl.h
@@ -19,14 +19,16 @@
 #include "headless/lib/browser/headless_url_request_context_getter.h"
 #include "headless/public/headless_browser.h"
 #include "headless/public/headless_browser_context.h"
+#include "headless/public/headless_export.h"
 
 namespace headless {
 class HeadlessBrowserImpl;
 class HeadlessResourceContext;
 class HeadlessWebContentsImpl;
 
-class HeadlessBrowserContextImpl : public HeadlessBrowserContext,
-                                   public content::BrowserContext {
+class HEADLESS_EXPORT HeadlessBrowserContextImpl final
+    : public HeadlessBrowserContext,
+      public content::BrowserContext {
  public:
   ~HeadlessBrowserContextImpl() override;
 
diff --git a/headless/test/DEPS b/headless/test/DEPS
new file mode 100644
index 0000000..77c0dd46
--- /dev/null
+++ b/headless/test/DEPS
@@ -0,0 +1,8 @@
+specific_include_rules = {
+  "headless_render_test.cc": [
+    "+cc/base/switches.h",
+    "+components/viz/common/features.h",
+    "+components/viz/common/switches.h",
+    "+third_party/skia/include",
+  ]
+}
diff --git a/headless/test/data/font.ttf b/headless/test/data/font.ttf
new file mode 100644
index 0000000..bbc73711
--- /dev/null
+++ b/headless/test/data/font.ttf
Binary files differ
diff --git a/headless/test/data/golden/custom_font.png b/headless/test/data/golden/custom_font.png
new file mode 100644
index 0000000..4abc477
--- /dev/null
+++ b/headless/test/data/golden/custom_font.png
Binary files differ
diff --git a/headless/test/headless_render_browsertest.cc b/headless/test/headless_render_browsertest.cc
index 5b291f8..60d4e1d 100644
--- a/headless/test/headless_render_browsertest.cc
+++ b/headless/test/headless_render_browsertest.cc
@@ -5,7 +5,9 @@
 #include <functional>
 
 #include "base/message_loop/message_loop.h"
+#include "base/path_service.h"
 #include "base/run_loop.h"
+#include "base/threading/thread_restrictions.h"
 #include "content/public/test/browser_test.h"
 #include "headless/public/devtools/domains/dom_snapshot.h"
 #include "headless/public/devtools/domains/page.h"
@@ -165,6 +167,24 @@
   return TestInMemoryProtocolHandler::Response(html, TEXT_HTML);
 }
 
+TestInMemoryProtocolHandler::Response ResponseFromFile(
+    const std::string& file_name,
+    const std::string& mime_type) {
+  static const base::FilePath kTestDataDirectory(
+      FILE_PATH_LITERAL("headless/test/data"));
+
+  base::ScopedAllowBlockingForTesting allow_blocking;
+
+  base::FilePath src_dir;
+  CHECK(base::PathService::Get(base::DIR_SOURCE_ROOT, &src_dir));
+  base::FilePath file_path =
+      src_dir.Append(kTestDataDirectory).Append(file_name);
+  std::string contents;
+  CHECK(base::ReadFileToString(file_path, &contents));
+
+  return TestInMemoryProtocolHandler::Response(contents, mime_type);
+}
+
 }  // namespace
 
 class HelloWorldTest : public HeadlessRenderTest {
@@ -1328,4 +1348,38 @@
 };
 HEADLESS_RENDER_BROWSERTEST(FrameLoadEvents);
 
+class CustomFont : public HeadlessRenderTest {
+ private:
+  GURL GetPageUrl(HeadlessDevToolsClient* client) override {
+    GetProtocolHandler()->InsertResponse("http://www.example.com/", HttpOk(R"|(
+<html>
+  <head>
+    <style>
+      @font-face {
+        font-family: testfont;
+        src: url("font.ttf");
+      }
+      span.test {
+        font-family: testfont;
+        font-size: 200px;
+      }
+    </style>
+  </head>
+  <body>
+    <span class="test">Hello</span>
+  </body>
+</html>
+)|"));
+    GetProtocolHandler()->InsertResponse(
+        "http://www.example.com/font.ttf",
+        ResponseFromFile("font.ttf", "application/octet-stream"));
+    return GURL("http://www.example.com/");
+  }
+
+  base::Optional<ScreenshotOptions> GetScreenshotOptions() override {
+    return ScreenshotOptions("custom_font.png", 0, 0, 500, 250, 1);
+  }
+};
+HEADLESS_RENDER_BROWSERTEST(CustomFont);
+
 }  // namespace headless
diff --git a/headless/test/headless_render_test.cc b/headless/test/headless_render_test.cc
index df0aa34..978e5881 100644
--- a/headless/test/headless_render_test.cc
+++ b/headless/test/headless_render_test.cc
@@ -4,21 +4,142 @@
 
 #include "headless/test/headless_render_test.h"
 
+#include "base/base_paths.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/path_service.h"
+#include "base/threading/thread_restrictions.h"
+#include "cc/base/switches.h"
+#include "components/viz/common/features.h"
+#include "components/viz/common/switches.h"
+#include "content/public/common/content_switches.h"
 #include "headless/public/devtools/domains/dom_snapshot.h"
 #include "headless/public/headless_devtools_client.h"
+#include "headless/public/util/compositor_controller.h"
 #include "headless/public/util/virtual_time_controller.h"
 #include "net/test/embedded_test_server/http_response.h"
 #include "net/url_request/url_request.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/codec/png_codec.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/skia_util.h"
 
 namespace headless {
 
 namespace {
+
+static constexpr int kAnimationIntervalMs = 100;
+static constexpr bool kUpdateDisplayForAnimations = false;
+static const char kUpdateGoldens[] = "update-goldens";
+
 void SetVirtualTimePolicyDoneCallback(
     base::RunLoop* run_loop,
     std::unique_ptr<emulation::SetVirtualTimePolicyResult>) {
   run_loop->Quit();
 }
+
+bool DecodePNG(const std::string& data, SkBitmap* bitmap) {
+  return gfx::PNGCodec::Decode(
+      reinterpret_cast<unsigned const char*>(data.data()), data.size(), bitmap);
+}
+
+bool ColorsMatchWithinLimit(SkColor color1, SkColor color2, int error_limit) {
+  auto a_diff = static_cast<int>(SkColorGetA(color1)) -
+                static_cast<int>(SkColorGetA(color2));
+  auto r_diff = static_cast<int>(SkColorGetR(color1)) -
+                static_cast<int>(SkColorGetR(color2));
+  auto g_diff = static_cast<int>(SkColorGetG(color1)) -
+                static_cast<int>(SkColorGetG(color2));
+  auto b_diff = static_cast<int>(SkColorGetB(color1)) -
+                static_cast<int>(SkColorGetB(color2));
+  return a_diff * a_diff + r_diff * r_diff + g_diff * g_diff +
+             b_diff * b_diff <=
+         error_limit * error_limit;
+}
+
+bool MatchesBitmap(const SkBitmap& expected_bmp,
+                   const SkBitmap& actual_bmp,
+                   int error_limit) {
+  // Number of pixels with an error
+  int error_pixels_count = 0;
+  gfx::Rect error_bounding_rect = gfx::Rect();
+
+  // Check that bitmaps have identical dimensions.
+  EXPECT_EQ(expected_bmp.width(), actual_bmp.width());
+  EXPECT_EQ(expected_bmp.height(), actual_bmp.height());
+  if (expected_bmp.width() != actual_bmp.width() ||
+      expected_bmp.height() != actual_bmp.height()) {
+    LOG(ERROR) << "To update goldens, use --update-goldens.";
+    return false;
+  }
+
+  for (int y = 0; y < actual_bmp.height(); ++y) {
+    for (int x = 0; x < actual_bmp.width(); ++x) {
+      SkColor actual_color = actual_bmp.getColor(x, y);
+      SkColor expected_color = expected_bmp.getColor(x, y);
+      if (!ColorsMatchWithinLimit(actual_color, expected_color, error_limit)) {
+        if (error_pixels_count < 10) {
+          LOG(ERROR) << "Pixel (" << x << "," << y << "): expected " << std::hex
+                     << expected_color << " actual " << actual_color;
+        }
+        error_pixels_count++;
+        error_bounding_rect.Union(gfx::Rect(x, y, 1, 1));
+      }
+    }
+  }
+
+  if (error_pixels_count != 0) {
+    LOG(ERROR) << "Number of pixel with an error: " << error_pixels_count;
+    LOG(ERROR) << "Error Bounding Box : " << error_bounding_rect.ToString();
+    LOG(ERROR) << "To update goldens, use --update-goldens.";
+    return false;
+  }
+
+  return true;
+}
+
+bool WriteStringToFile(const base::FilePath& file_path,
+                       const std::string& content) {
+  int result = base::WriteFile(file_path, content.data(),
+                               static_cast<int>(content.size()));
+  return content.size() == static_cast<size_t>(result);
+}
+
+bool ScreenshotMatchesGolden(const std::string& screenshot_data,
+                             const std::string& golden_file_name) {
+  static const base::FilePath kGoldenDirectory(
+      FILE_PATH_LITERAL("headless/test/data/golden"));
+
+  SkBitmap actual_bitmap;
+  EXPECT_TRUE(DecodePNG(screenshot_data, &actual_bitmap));
+  if (actual_bitmap.empty())
+    return false;
+
+  base::ScopedAllowBlockingForTesting allow_blocking;
+
+  base::FilePath src_dir;
+  CHECK(base::PathService::Get(base::DIR_SOURCE_ROOT, &src_dir));
+  base::FilePath golden_path =
+      src_dir.Append(kGoldenDirectory).Append(golden_file_name);
+
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(kUpdateGoldens)) {
+    LOG(INFO) << "Updating golden file at " << golden_path;
+    CHECK(WriteStringToFile(golden_path, screenshot_data));
+  }
+
+  std::string golden_data;
+  CHECK(base::ReadFileToString(golden_path, &golden_data));
+
+  SkBitmap expected_bitmap;
+  EXPECT_TRUE(DecodePNG(golden_data, &expected_bitmap));
+  if (expected_bitmap.empty())
+    return false;
+
+  return MatchesBitmap(expected_bitmap, actual_bitmap, 0);
+}
+
 }  // namespace
 
 HeadlessRenderTest::HeadlessRenderTest() : weak_ptr_factory_(this) {}
@@ -79,10 +200,23 @@
 void HeadlessRenderTest::RunDevTooledTest() {
   http_handler_->SetHeadlessBrowserContext(browser_context_);
 
-  // TODO(alexclarke): Use the compositor controller here too.
   virtual_time_controller_ =
       std::make_unique<VirtualTimeController>(devtools_client_.get());
 
+  SetDeviceMetricsOverride(headless::page::Viewport::Builder()
+                               .SetX(0)
+                               .SetY(0)
+                               .SetWidth(1)
+                               .SetHeight(1)
+                               .SetScale(1)
+                               .Build());
+
+  compositor_controller_ = std::make_unique<CompositorController>(
+      browser()->BrowserMainThread(), devtools_client_.get(),
+      virtual_time_controller_.get(),
+      base::TimeDelta::FromMilliseconds(kAnimationIntervalMs),
+      kUpdateDisplayForAnimations);
+
   devtools_client_->GetPage()->GetExperimental()->AddObserver(this);
   devtools_client_->GetPage()->Enable(Sync());
   devtools_client_->GetRuntime()->GetExperimental()->AddObserver(this);
@@ -133,15 +267,56 @@
   // from OnGetDomSnapshotDone() or from HandleTimeout().
 }
 
+void HeadlessRenderTest::SetDeviceMetricsOverride(
+    std::unique_ptr<headless::page::Viewport> viewport) {
+  gfx::Size size = GetEmulatedWindowSize();
+  devtools_client_->GetEmulation()->GetExperimental()->SetDeviceMetricsOverride(
+      headless::emulation::SetDeviceMetricsOverrideParams::Builder()
+          .SetDeviceScaleFactor(0)
+          .SetMobile(false)
+          .SetWidth(size.width())
+          .SetHeight(size.height())
+          .SetScreenWidth(size.width())
+          .SetScreenHeight(size.height())
+          .SetViewport(std::move(viewport))
+          .Build(),
+      Sync());
+}
+
 void HeadlessRenderTest::OnTimeout() {
   ADD_FAILURE() << "Rendering timed out!";
 }
 
+void HeadlessRenderTest::SetUpCommandLine(base::CommandLine* command_line) {
+  HeadlessAsyncDevTooledBrowserTest::SetUpCommandLine(command_line);
+  // See bit.ly/headless-rendering for why we use these flags.
+  command_line->AppendSwitch(switches::kRunAllCompositorStagesBeforeDraw);
+  command_line->AppendSwitch(switches::kDisableNewContentRenderingTimeout);
+  command_line->AppendSwitch(cc::switches::kDisableCheckerImaging);
+  command_line->AppendSwitch(cc::switches::kDisableThreadedAnimation);
+  command_line->AppendSwitch(switches::kDisableImageAnimationResync);
+  command_line->AppendSwitch(switches::kDisableThreadedScrolling);
+
+  scoped_feature_list_.InitAndEnableFeature(
+      features::kEnableSurfaceSynchronization);
+}
+
+void HeadlessRenderTest::SetUp() {
+  EnablePixelOutput();
+  HeadlessAsyncDevTooledBrowserTest::SetUp();
+}
+
 void HeadlessRenderTest::CustomizeHeadlessBrowserContext(
     HeadlessBrowserContext::Builder& builder) {
   builder.SetOverrideWebPreferencesCallback(
       base::Bind(&HeadlessRenderTest::OverrideWebPreferences,
                  weak_ptr_factory_.GetWeakPtr()));
+  // Set an initial time to enable base::Time/TimeTicks overrides.
+  builder.SetInitialVirtualTime(base::Time::FromJsTime(100000.0));
+}
+
+bool HeadlessRenderTest::GetEnableBeginFrameControl() {
+  return true;
 }
 
 ProtocolHandlerMap HeadlessRenderTest::GetProtocolHandlers() {
@@ -159,6 +334,15 @@
   preferences->autoplay_policy = content::AutoplayPolicy::kUserGestureRequired;
 }
 
+base::Optional<HeadlessRenderTest::ScreenshotOptions>
+HeadlessRenderTest::GetScreenshotOptions() {
+  return base::nullopt;
+}
+
+gfx::Size HeadlessRenderTest::GetEmulatedWindowSize() {
+  return gfx::Size(800, 600);
+}
+
 void HeadlessRenderTest::UrlRequestFailed(net::URLRequest* request,
                                           int net_error,
                                           DevToolsStatus devtools_status) {
@@ -279,6 +463,9 @@
   complete_request.Run();
 }
 
+void HeadlessRenderTest::VerifyDom(
+    dom_snapshot::GetSnapshotResult* dom_snapshot) {}
+
 void HeadlessRenderTest::OnPageRenderCompleted() {
   CHECK_GE(state_, LOADING);
   if (state_ >= DONE)
@@ -302,10 +489,45 @@
 void HeadlessRenderTest::OnGetDomSnapshotDone(
     std::unique_ptr<dom_snapshot::GetSnapshotResult> result) {
   CHECK_EQ(DONE, state_);
+  VerifyDom(result.get());
+
+  base::Optional<ScreenshotOptions> screenshot_options = GetScreenshotOptions();
+  if (screenshot_options) {
+    state_ = SCREENSHOT;
+    CaptureScreenshot(*screenshot_options);
+    return;
+  }
+  RenderComplete();
+}
+
+void HeadlessRenderTest::CaptureScreenshot(const ScreenshotOptions& options) {
+  // Set up emulation according to options.
+  auto clip = headless::page::Viewport::Builder()
+                  .SetX(options.x)
+                  .SetY(options.y)
+                  .SetWidth(options.width)
+                  .SetHeight(options.height)
+                  .SetScale(options.scale)
+                  .Build();
+
+  SetDeviceMetricsOverride(std::move(clip));
+
+  compositor_controller_->CaptureScreenshot(
+      CompositorController::ScreenshotParamsFormat::PNG, 100,
+      base::BindRepeating(&HeadlessRenderTest::ScreenshotCaptured,
+                          base::Unretained(this), options));
+}
+
+void HeadlessRenderTest::ScreenshotCaptured(const ScreenshotOptions& options,
+                                            const std::string& data) {
+  EXPECT_TRUE(ScreenshotMatchesGolden(data, options.golden_file_name));
+  RenderComplete();
+}
+
+void HeadlessRenderTest::RenderComplete() {
   state_ = FINISHED;
   CleanUp();
   FinishAsynchronousTest();
-  VerifyDom(result.get());
 }
 
 void HeadlessRenderTest::HandleTimeout() {
@@ -323,4 +545,18 @@
   devtools_client_->GetPage()->GetExperimental()->RemoveObserver(this);
 }
 
+HeadlessRenderTest::ScreenshotOptions::ScreenshotOptions(
+    const std::string& golden_file_name,
+    int x,
+    int y,
+    int width,
+    int height,
+    double scale)
+    : golden_file_name(golden_file_name),
+      x(x),
+      y(y),
+      width(width),
+      height(height),
+      scale(scale) {}
+
 }  // namespace headless
diff --git a/headless/test/headless_render_test.h b/headless/test/headless_render_test.h
index fb4faed6..c64175a 100644
--- a/headless/test/headless_render_test.h
+++ b/headless/test/headless_render_test.h
@@ -9,6 +9,10 @@
 #include <string>
 
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
+#include "base/optional.h"
+#include "base/run_loop.h"
+#include "base/test/scoped_feature_list.h"
 #include "headless/public/devtools/domains/emulation.h"
 #include "headless/public/devtools/domains/page.h"
 #include "headless/public/devtools/domains/runtime.h"
@@ -17,12 +21,11 @@
 #include "headless/public/util/testing/test_in_memory_protocol_handler.h"
 #include "headless/test/headless_browser_test.h"
 #include "net/test/embedded_test_server/http_request.h"
-
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
+#include "ui/gfx/geometry/size.h"
 #include "url/gurl.h"
 
 namespace headless {
+class CompositorController;
 class HeadlessDevToolsClient;
 class VirtualTimeController;
 namespace dom_snapshot {
@@ -57,6 +60,22 @@
     DISALLOW_COPY_AND_ASSIGN(Sync);
   };
 
+  struct ScreenshotOptions {
+    ScreenshotOptions(const std::string& golden_file_name,
+                      int x,
+                      int y,
+                      int width,
+                      int height,
+                      double scale);
+
+    std::string golden_file_name;
+    int x;
+    int y;
+    int width;
+    int height;
+    double scale;
+  };
+
   HeadlessRenderTest();
   ~HeadlessRenderTest() override;
 
@@ -70,7 +89,7 @@
   virtual GURL GetPageUrl(HeadlessDevToolsClient* client) = 0;
 
   // Check if the DOM snapshot is as expected.
-  virtual void VerifyDom(dom_snapshot::GetSnapshotResult* dom_snapshot) = 0;
+  virtual void VerifyDom(dom_snapshot::GetSnapshotResult* dom_snapshot);
 
   // Called when all steps needed to load and present page are done.
   virtual void OnPageRenderCompleted();
@@ -81,9 +100,20 @@
   // Override to set specific options for requests.
   virtual void OverrideWebPreferences(WebPreferences* preferences);
 
+  // Determines whether a screenshot will be taken or not. If one is taken,
+  // ScreenshotOptions specifies the area to capture as well as a golden data
+  // file to compare the result to. By default, no screenshot is taken.
+  virtual base::Optional<ScreenshotOptions> GetScreenshotOptions();
+
+  // Returns the emulated width/height of the window. Defaults to 800x600.
+  virtual gfx::Size GetEmulatedWindowSize();
+
   // Setting up the browsertest.
+  void SetUpCommandLine(base::CommandLine* command_line) override;
+  void SetUp() override;
   void CustomizeHeadlessBrowserContext(
       HeadlessBrowserContext::Builder& builder) override;
+  bool GetEnableBeginFrameControl() override;
   void PostRunAsynchronousTest() override;
   ProtocolHandlerMap GetProtocolHandlers() override;
 
@@ -120,25 +150,35 @@
  private:
   class AdditionalVirtualTimeBudget;
 
+  void SetDeviceMetricsOverride(
+      std::unique_ptr<headless::page::Viewport> viewport);
   void HandleVirtualTimeExhausted();
   void OnGetDomSnapshotDone(
       std::unique_ptr<dom_snapshot::GetSnapshotResult> result);
+  void CaptureScreenshot(const ScreenshotOptions& options);
+  void ScreenshotCaptured(const ScreenshotOptions& options,
+                          const std::string& data);
+  void RenderComplete();
   void HandleTimeout();
   void CleanUp();
 
   enum State {
-    INIT,       // Setting up the client, no navigation performed yet.
-    STARTING,   // Navigation request issued but URL not being loaded yet.
-    LOADING,    // URL was requested but resources are not fully loaded yet.
-    RENDERING,  // Main resources were loaded but page is still being rendered.
-    DONE,       // Page considered to be fully rendered.
-    FINISHED,   // Test has finished.
+    INIT,        // Setting up the client, no navigation performed yet.
+    STARTING,    // Navigation request issued but URL not being loaded yet.
+    LOADING,     // URL was requested but resources are not fully loaded yet.
+    RENDERING,   // Main resources were loaded but page is still being rendered.
+    DONE,        // Page considered to be rendered, DOM snapshot is being taken.
+    SCREENSHOT,  // DOM snapshot has completed, screenshot is being taken.
+    FINISHED,    // Test has finished.
   };
   State state_ = INIT;
 
   std::unique_ptr<VirtualTimeController> virtual_time_controller_;
+  std::unique_ptr<CompositorController> compositor_controller_;
   TestInMemoryProtocolHandler* http_handler_;  // NOT OWNED
 
+  base::test::ScopedFeatureList scoped_feature_list_;
+
   base::WeakPtrFactory<HeadlessRenderTest> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(HeadlessRenderTest);
diff --git a/infra/config/global/cr-buildbucket.cfg b/infra/config/global/cr-buildbucket.cfg
index 35f409c..8e2f8ab 100644
--- a/infra/config/global/cr-buildbucket.cfg
+++ b/infra/config/global/cr-buildbucket.cfg
@@ -504,6 +504,11 @@
     }
 
     builders {
+      name: "Linux Tests (dbg)(1)(32)"
+      mixins: "linux-ci"
+    }
+
+    builders {
       name: "GPU FYI Linux Builder"
       mixins: "linux-gpu-fyi-ci"
     }
@@ -1003,7 +1008,13 @@
     builders { mixins: "win-try" name: "win_chrome_official" }
     builders { mixins: "win-try" name: "win_chromium_compile_dbg_ng" }
     builders { mixins: "win-try" name: "win_chromium_compile_rel_ng" }
-    builders { mixins: "win-try" name: "win_chromium_dbg_ng" }
+    # TODO(crbug/794085): Revisit exceptional extra-long timeout when we speed
+    # up the builder.
+    builders {
+      mixins: "win-try"
+      name: "win_chromium_dbg_ng"
+      execution_timeout_secs: 14400 # 4h
+    }
     builders { mixins: "win-try" name: "win_chromium_syzyasan_rel" }
     builders { mixins: "win-try" name: "win_chromium_variable" }
     builders { mixins: "win-try" name: "win_chromium_variable_archive" }
diff --git a/infra/config/global/luci-milo-dev.cfg b/infra/config/global/luci-milo-dev.cfg
index 5c383790..6f6ff7a 100644
--- a/infra/config/global/luci-milo-dev.cfg
+++ b/infra/config/global/luci-milo-dev.cfg
@@ -407,6 +407,11 @@
     short_name: "tst"
   }
   builders: {
+    name: "buildbot/luci.chromium.ci/linux-gcc-rel"
+    category: "chromium.linux|release"
+    short_name: "gcc"
+  }
+  builders: {
     name: "buildbot/chromium.linux/Linux Builder (dbg)(32)"
     category: "chromium.linux|debug|builder"
     short_name: "32"
@@ -2313,10 +2318,6 @@
     category: "linux"
   }
   builders: {
-    name: "buildbot/chromium.fyi/linux-gcc-rel"
-    category: "linux"
-  }
-  builders: {
     name: "buildbot/chromium.fyi/Headless Linux (dbg)"
     category: "linux"
   }
diff --git a/infra/config/global/luci-milo.cfg b/infra/config/global/luci-milo.cfg
index ec744d67..624da67 100644
--- a/infra/config/global/luci-milo.cfg
+++ b/infra/config/global/luci-milo.cfg
@@ -412,6 +412,11 @@
     short_name: "tst"
   }
   builders: {
+    name: "buildbot/luci.chromium.ci/linux-gcc-rel"
+    category: "chromium.linux|release"
+    short_name: "gcc"
+  }
+  builders: {
     name: "buildbot/chromium.linux/Linux Builder (dbg)(32)"
     name: "buildbucket/luci.chromium.ci/Linux Builder (dbg)(32)"
     category: "chromium.linux|debug|builder"
@@ -424,6 +429,7 @@
   }
   builders: {
     name: "buildbot/chromium.linux/Linux Tests (dbg)(1)(32)"
+    name: "buildbucket/luci.chromium.ci/Linux Tests (dbg)(1)(32)"
     category: "chromium.linux|debug|tester"
     short_name: "32"
   }
@@ -903,6 +909,7 @@
   }
   builders: {
     name: "buildbot/chromium.linux/Deterministic Linux"
+    name: "buildbucket/luci.chromium.ci/Deterministic Linux"
     short_name: "det"
   }
   builders: {
@@ -1617,260 +1624,6 @@
     short_name: "(ಥ_ಥ)"
   }
 
-  # GPU FYI Android bots, prefixed with GPU FYI|Android
-  builders: {
-    name: "buildbucket/luci.chromium.ci/Android FYI Release (Nexus 5)"
-    category: "GPU FYI|Android|L32|N5"
-    short_name: "ci"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/Android FYI Release (Nexus 5)"
-    category: "GPU FYI|Android|L32|N5"
-    short_name: "bb"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/Android FYI Release (Nexus 6)"
-    category: "GPU FYI|Android|L32|N6"
-    short_name: "ci"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/Android FYI Release (Nexus 6)"
-    category: "GPU FYI|Android|L32|N6"
-    short_name: "bb"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/Android FYI Release (Nexus 5X)"
-    category: "GPU FYI|Android|M64|QCOM|N5X"
-    short_name: "ci"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/Android FYI Release (Nexus 5X)"
-    category: "GPU FYI|Android|M64|QCOM|N5X"
-    short_name: "bb"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/Android FYI Release (Nexus 6P)"
-    category: "GPU FYI|Android|M64|QCOM|N6P"
-    short_name: "ci"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/Android FYI Release (Nexus 6P)"
-    category: "GPU FYI|Android|M64|QCOM|N6P"
-    short_name: "bb"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/Android FYI Release (Nexus 9)"
-    category: "GPU FYI|Android|M64|NVDA|N9"
-    short_name: "ci"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/Android FYI Release (Nexus 9)"
-    category: "GPU FYI|Android|M64|NVDA|N9"
-    short_name: "bb"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/Android FYI Release (NVIDIA Shield TV)"
-    category: "GPU FYI|Android|N64|NVDA|STV"
-    short_name: "ci"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/Android FYI Release (NVIDIA Shield TV)"
-    category: "GPU FYI|Android|N64|NVDA|STV"
-    short_name: "bb"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/Android FYI dEQP Release (Nexus 5X)"
-    category: "GPU FYI|Android|dqp|M64|N5X"
-    short_name: "ci"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/Android FYI dEQP Release (Nexus 5X)"
-    category: "GPU FYI|Android|dqp|M64|N5X"
-    short_name: "bb"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/Android FYI 32 Vk Release (Nexus 5X)"
-    category: "GPU FYI|Android|vk|O32|N5X"
-    short_name: "ci"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/Android FYI 32 Vk Release (Nexus 5X)"
-    category: "GPU FYI|Android|vk|O32|N5X"
-    short_name: "bb"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/Android FYI 64 Vk Release (Nexus 5X)"
-    category: "GPU FYI|Android|vk|O64|N5X"
-    short_name: "ci"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/Android FYI 64 Vk Release (Nexus 5X)"
-    category: "GPU FYI|Android|vk|O64|N5X"
-    short_name: "bb"
-  }
-
-  # GPU FYI Mac bots, prefixed with GPU FYI|Mac
-  builders: {
-    name: "buildbucket/luci.chromium.ci/GPU FYI Mac Builder"
-    category: "GPU FYI|Mac|Builder|Release"
-    short_name: "☄️"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/GPU FYI Mac Builder"
-    category: "GPU FYI|Mac|Builder|Release"
-    short_name: "🦖"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/GPU FYI Mac Builder (dbg)"
-    category: "GPU FYI|Mac|Builder|Debug"
-    short_name: "☄️"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/GPU FYI Mac Builder (dbg)"
-    category: "GPU FYI|Mac|Builder|Debug"
-    short_name: "🦖"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/GPU FYI Mac dEQP Builder"
-    category: "GPU FYI|Mac|Builder|dEQP"
-    short_name: "☄️"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/GPU FYI Mac dEQP Builder"
-    category: "GPU FYI|Mac|Builder|dEQP"
-    short_name: "🦖"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/Mac FYI Release (Intel)"
-    category: "GPU FYI|Mac|Intel|Release"
-    short_name: "☄️"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/Mac FYI Release (Intel)"
-    category: "GPU FYI|Mac|Intel|Release"
-    short_name: "🦖"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/Mac FYI Debug (Intel)"
-    category: "GPU FYI|Mac|Intel|Debug"
-    short_name: "☄️"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/Mac FYI Debug (Intel)"
-    category: "GPU FYI|Mac|Intel|Debug"
-    short_name: "🦖"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/Mac Pro FYI Release (AMD)"
-    category: "GPU FYI|Mac|Pro|Release"
-    short_name: "☄️"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/Mac Pro FYI Release (AMD)"
-    category: "GPU FYI|Mac|Pro|Release"
-    short_name: "🦖"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/Mac FYI Retina Release (NVIDIA)"
-    category: "GPU FYI|Mac|Nvidia|Release"
-    short_name: "☄️"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/Mac FYI Retina Release (NVIDIA)"
-    category: "GPU FYI|Mac|Nvidia|Release"
-    short_name: "🦖"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/Mac FYI Retina Debug (NVIDIA)"
-    category: "GPU FYI|Mac|Nvidia|Debug"
-    short_name: "☄️"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/Mac FYI Retina Debug (NVIDIA)"
-    category: "GPU FYI|Mac|Nvidia|Debug"
-    short_name: "🦖"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/Mac FYI Retina Release (AMD)"
-    category: "GPU FYI|Mac|AMD|Release"
-    short_name: "☄️"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/Mac FYI Retina Release (AMD)"
-    category: "GPU FYI|Mac|AMD|Release"
-    short_name: "🦖"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/Mac FYI Retina Debug (AMD)"
-    category: "GPU FYI|Mac|AMD|Debug"
-    short_name: "☄️"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/Mac FYI Retina Debug (AMD)"
-    category: "GPU FYI|Mac|AMD|Debug"
-    short_name: "🦖"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/Mac FYI Experimental Release (Intel)"
-    category: "GPU FYI|Mac|Intel|Exp"
-    short_name: "☄️"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/Mac FYI Experimental Release (Intel)"
-    category: "GPU FYI|Mac|Intel|Exp"
-    short_name: "🦖"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/Mac FYI Experimental Retina Release (AMD)"
-    category: "GPU FYI|Mac|AMD|Exp"
-    short_name: "☄️"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/Mac FYI Experimental Retina Release (AMD)"
-    category: "GPU FYI|Mac|AMD|Exp"
-    short_name: "🦖"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/Mac FYI Experimental Retina Release (NVIDIA)"
-    category: "GPU FYI|Mac|Nvidia|Exp"
-    short_name: "☄️"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/Mac FYI Experimental Retina Release (NVIDIA)"
-    category: "GPU FYI|Mac|Nvidia|Exp"
-    short_name: "🦖"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/Mac FYI GPU ASAN Release"
-    category: "GPU FYI|Mac|ASAN|Release"
-    short_name: "☄️"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/Mac FYI GPU ASAN Release"
-    category: "GPU FYI|Mac|ASAN|Release"
-    short_name: "🦖"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/Mac FYI dEQP Release AMD"
-    category: "GPU FYI|Mac|AMD|dEQP"
-    short_name: "☄️"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/Mac FYI dEQP Release AMD"
-    category: "GPU FYI|Mac|AMD|dEQP"
-    short_name: "🦖"
-  }
-  builders: {
-    name: "buildbucket/luci.chromium.ci/Mac FYI dEQP Release Intel"
-    category: "GPU FYI|Mac|Intel|dEQP"
-    short_name: "☄️"
-  }
-  builders: {
-    name: "buildbot/chromium.gpu.fyi/Mac FYI dEQP Release Intel"
-    category: "GPU FYI|Mac|Intel|dEQP"
-    short_name: "🦖"
-  }
-
   # GPU FYI Window bots, prefixed with GPU FYI|Windows
   builders: {
     name: "buildbucket/luci.chromium.ci/GPU FYI Win Builder"
@@ -2082,6 +1835,27 @@
     category: "chromium.linux|debug|builder"
     short_name: "luci_32"
   }
+
+  builders: {
+    name: "buildbot/chromium.linux/Deterministic Linux"
+    category: "chromium.linux"
+    short_name: "bb"
+  }
+  builders: {
+    name: "buildbucket/luci.chromium.ci/Deterministic Linux"
+    category: "chromium.linux"
+    short_name: "ci"
+  }
+  builders: {
+    name: "buildbot/chromium.linux/Linux Tests (dbg)(1)(32)"
+    category: "chromium.linux|debug|tester"
+    short_name: "buildbot_linux_tests_32"
+  }
+  builders: {
+    name: "buildbucket/luci.chromium.ci/Linux Tests (dbg)(1)(32)"
+    category: "chromium.linux|debug|tester"
+    short_name: "luci_linux_tests_32"
+  }
 }
 
 # Everything below was generated from buildermap.json.
@@ -2909,10 +2683,6 @@
     category: "linux"
   }
   builders: {
-    name: "buildbot/chromium.fyi/linux-gcc-rel"
-    category: "linux"
-  }
-  builders: {
     name: "buildbot/chromium.fyi/linux-annotator-rel"
     category: "linux"
   }
@@ -3261,97 +3031,81 @@
     short_name: "dqp"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/GPU FYI Mac Builder"
     name: "buildbucket/luci.chromium.ci/GPU FYI Mac Builder"
     category: "Mac|Builder"
     short_name: "rel"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/GPU FYI Mac Builder (dbg)"
     name: "buildbucket/luci.chromium.ci/GPU FYI Mac Builder (dbg)"
     category: "Mac|Builder"
     short_name: "dbg"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/GPU FYI Mac dEQP Builder"
     name: "buildbucket/luci.chromium.ci/GPU FYI Mac dEQP Builder"
     category: "Mac|Builder"
     short_name: "dqp"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/Mac FYI Debug (Intel)"
     name: "buildbucket/luci.chromium.ci/Mac FYI Debug (Intel)"
     category: "Mac|Intel"
     short_name: "dbg"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/Mac FYI Experimental Release (Intel)"
     name: "buildbucket/luci.chromium.ci/Mac FYI Experimental Release (Intel)"
     category: "Mac|Intel"
     short_name: "exp"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/Mac FYI dEQP Release Intel"
     name: "buildbucket/luci.chromium.ci/Mac FYI dEQP Release Intel"
     category: "Mac|Intel"
     short_name: "dqp"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/Mac FYI Release (Intel)"
     name: "buildbucket/luci.chromium.ci/Mac FYI Release (Intel)"
     category: "Mac|Intel"
     short_name: "rel"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/Mac Pro FYI Release (AMD)"
     name: "buildbucket/luci.chromium.ci/Mac Pro FYI Release (AMD)"
     category: "Mac|AMD|Pro"
     short_name: "rel"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/Mac FYI dEQP Release AMD"
     name: "buildbucket/luci.chromium.ci/Mac FYI dEQP Release AMD"
     category: "Mac|AMD"
     short_name: "dqp"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/Mac FYI Retina Debug (AMD)"
     name: "buildbucket/luci.chromium.ci/Mac FYI Retina Debug (AMD)"
     category: "Mac|AMD|Retina"
     short_name: "dbg"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/Mac FYI Retina Release (AMD)"
     name: "buildbucket/luci.chromium.ci/Mac FYI Retina Release (AMD)"
     category: "Mac|AMD|Retina"
     short_name: "rel"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/Mac FYI Experimental Retina Release (AMD)"
     name: "buildbucket/luci.chromium.ci/Mac FYI Experimental Retina Release (AMD)"
     category: "Mac|AMD|Retina"
     short_name: "exp"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/Mac FYI Retina Debug (NVIDIA)"
     name: "buildbucket/luci.chromium.ci/Mac FYI Retina Debug (NVIDIA)"
     category: "Mac|Nvidia"
     short_name: "dbg"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/Mac FYI Retina Release (NVIDIA)"
     name: "buildbucket/luci.chromium.ci/Mac FYI Retina Release (NVIDIA)"
     category: "Mac|Nvidia"
     short_name: "rel"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/Mac FYI Experimental Retina Release (NVIDIA)"
     name: "buildbucket/luci.chromium.ci/Mac FYI Experimental Retina Release (NVIDIA)"
     category: "Mac|Nvidia"
     short_name: "exp"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/Mac FYI GPU ASAN Release"
     name: "buildbucket/luci.chromium.ci/Mac FYI GPU ASAN Release"
     category: "Mac"
     short_name: "asn"
@@ -3412,55 +3166,46 @@
     short_name: "tsn"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/Android FYI Release (Nexus 5)"
     name: "buildbucket/luci.chromium.ci/Android FYI Release (Nexus 5)"
     category: "Android|L32"
     short_name: "N5"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/Android FYI Release (Nexus 6)"
     name: "buildbucket/luci.chromium.ci/Android FYI Release (Nexus 6)"
     category: "Android|L32"
     short_name: "N6"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/Android FYI Release (Nexus 5X)"
     name: "buildbucket/luci.chromium.ci/Android FYI Release (Nexus 5X)"
     category: "Android|M64|QCOM"
     short_name: "N5X"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/Android FYI Release (Nexus 6P)"
     name: "buildbucket/luci.chromium.ci/Android FYI Release (Nexus 6P)"
     category: "Android|M64|QCOM"
     short_name: "N6P"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/Android FYI Release (Nexus 9)"
     name: "buildbucket/luci.chromium.ci/Android FYI Release (Nexus 9)"
     category: "Android|M64|NVDA"
     short_name: "N9"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/Android FYI Release (NVIDIA Shield TV)"
     name: "buildbucket/luci.chromium.ci/Android FYI Release (NVIDIA Shield TV)"
     category: "Android|N64|NVDA"
     short_name: "STV"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/Android FYI dEQP Release (Nexus 5X)"
     name: "buildbucket/luci.chromium.ci/Android FYI dEQP Release (Nexus 5X)"
     category: "Android|dqp|M64"
     short_name: "N5X"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/Android FYI 32 Vk Release (Nexus 5X)"
     name: "buildbucket/luci.chromium.ci/Android FYI 32 Vk Release (Nexus 5X)"
     category: "Android|vk|O32"
     short_name: "N5X"
   }
   builders: {
-    name: "buildbot/chromium.gpu.fyi/Android FYI 64 Vk Release (Nexus 5X)"
     name: "buildbucket/luci.chromium.ci/Android FYI 64 Vk Release (Nexus 5X)"
     category: "Android|vk|O64"
     short_name: "N5X"
diff --git a/infra/config/global/luci-scheduler.cfg b/infra/config/global/luci-scheduler.cfg
index a29a534..61e39f9 100644
--- a/infra/config/global/luci-scheduler.cfg
+++ b/infra/config/global/luci-scheduler.cfg
@@ -83,6 +83,7 @@
   triggers: "Linux Builder"
   triggers: "Linux Builder (dbg)"
   triggers: "Linux Builder (dbg)(32)"
+  triggers: "Linux Tests (dbg)(1)(32)"
   triggers: "Linux FYI GPU TSAN Release"
 
   # Mac. Sorted alphabetically.
@@ -575,6 +576,16 @@
 }
 
 job {
+  id: "Linux Tests (dbg)(1)(32)"
+  acl_sets: "default"
+  buildbucket: {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "luci.chromium.ci"
+    builder: "Linux Tests (dbg)(1)(32)"
+  }
+}
+
+job {
   id: "Linux Builder"
   acl_sets: "default"
   buildbucket: {
@@ -1091,22 +1102,24 @@
   id: "Win7 (32) Tests"
   # Triggered by "Win Builder"
   acl_sets: "triggered-by-parent-builders"
-  buildbucket: {
-    server: "cr-buildbucket.appspot.com"
-    bucket: "luci.chromium.ci"
-    builder: "Win7 (32) Tests"
-  }
+  noop: {}
+  # buildbucket: {
+  #   server: "cr-buildbucket.appspot.com"
+  #   bucket: "luci.chromium.ci"
+  #   builder: "Win7 (32) Tests"
+  # }
 }
 
 job {
   id: "Win7 Tests (1)"
   # Triggered by "Win Builder"
   acl_sets: "triggered-by-parent-builders"
-  buildbucket: {
-    server: "cr-buildbucket.appspot.com"
-    bucket: "luci.chromium.ci"
-    builder: "Win7 Tests (1)"
-  }
+  noop: {}
+  # buildbucket: {
+  #   server: "cr-buildbucket.appspot.com"
+  #   bucket: "luci.chromium.ci"
+  #   builder: "Win7 Tests (1)"
+  # }
 }
 
 job {
diff --git a/ios/build/bots/chromium.fyi/ios-webview.json b/ios/build/bots/chromium.fyi/ios-webview.json
index 697f999c..94df752a 100644
--- a/ios/build/bots/chromium.fyi/ios-webview.json
+++ b/ios/build/bots/chromium.fyi/ios-webview.json
@@ -5,6 +5,7 @@
   "xcode build version": "9C40b",
   "gn_args": [
     "goma_dir=\"$(goma_dir)\"",
+    "ios_deployment_target=\"9.0\"",
     "is_component_build=false",
     "is_debug=true",
     "target_cpu=\"x64\"",
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm
index 4b9a008..961d252f 100644
--- a/ios/chrome/app/main_controller.mm
+++ b/ios/chrome/app/main_controller.mm
@@ -1938,8 +1938,11 @@
 
   _dismissingStackView = YES;
   // Prevent wayward touches from wreaking havoc while the stack view is being
-  // dismissed.
-  [[_tabSwitcher viewController].view setUserInteractionEnabled:NO];
+  // dismissed. Don't do this when the tab grid is used.
+  if (!IsUIRefreshPhase1Enabled()) {
+    [[_tabSwitcher viewController].view setUserInteractionEnabled:NO];
+  }
+
   BrowserViewController* targetBVC =
       (tabModel == self.mainTabModel) ? self.mainBVC : self.otrBVC;
   self.currentBVC = targetBVC;
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd
index 2b4a845..247a543 100644
--- a/ios/chrome/app/strings/ios_strings.grd
+++ b/ios/chrome/app/strings/ios_strings.grd
@@ -1587,7 +1587,7 @@
         Recent Tabs
       </message>
       <message name="IDS_IOS_TOOLS_MENU_RELOAD" desc="The title of the button in the menu allowing the user to reload the page.">
-        Reload This Page
+        Reload
       </message>
       <message name="IDS_IOS_TOOLS_MENU_REQUEST_DESKTOP_SITE" desc="The iOS menu item for requesting the desktop site [Length: 15em] [iOS only]">
         Request Desktop Site
@@ -1604,6 +1604,9 @@
       <message name="IDS_IOS_TOOLS_MENU_SITE_INFORMATION" desc="The iOS menu item for getting the site informations.">
         Site Information
       </message>
+      <message name="IDS_IOS_TOOLS_MENU_STOP" desc="The iOS menu item for stoping the loading of the page.">
+        Stop
+      </message>
       <message name="IDS_IOS_TRANSLATE_SETTING" desc="Title for the view and option in Settings for Translate. [Length: 25em] [iOS only]">
         Google Translate
       </message>
diff --git a/ios/chrome/browser/metrics/ukm_egtest.mm b/ios/chrome/browser/metrics/ukm_egtest.mm
index cb65739..ba52ac5 100644
--- a/ios/chrome/browser/metrics/ukm_egtest.mm
+++ b/ios/chrome/browser/metrics/ukm_egtest.mm
@@ -427,14 +427,6 @@
 - (void)testSecondaryPassphrase {
   uint64_t original_client_id = metrics::UkmEGTestHelper::client_id();
 
-  // This test hangs for a while when typing, and eventually causes the suite to
-  // timeout on iOS 11 iPad. crbug.com/811376
-  if (IsIPadIdiom()) {
-    if (@available(iOS 11, *)) {
-      EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11 iPad");
-    }
-  }
-
   [ChromeEarlGreyUI openSettingsMenu];
   // Open accounts settings, then sync settings.
   [[EarlGrey selectElementWithMatcher:SettingsAccountButton()]
@@ -454,13 +446,10 @@
       performAction:grey_tap()];
   // Type and confirm passphrase, then submit.
   [[EarlGrey selectElementWithMatcher:grey_accessibilityValue(@"Passphrase")]
-      performAction:grey_typeText(@"mypassphrase")];
+      performAction:grey_replaceText(@"mypassphrase")];
   [[EarlGrey
       selectElementWithMatcher:grey_accessibilityValue(@"Confirm passphrase")]
-      performAction:grey_typeText(@"mypassphrase")];
-  [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabelId(
-                                          IDS_IOS_SYNC_DECRYPT_BUTTON)]
-      performAction:grey_tap()];
+      performAction:grey_replaceText(@"mypassphrase")];
 
   AssertUKMEnabled(false);
   // Client ID should have been reset.
diff --git a/ios/chrome/browser/passwords/account_select_fill_data.cc b/ios/chrome/browser/passwords/account_select_fill_data.cc
index bf69f32..086a913 100644
--- a/ios/chrome/browser/passwords/account_select_fill_data.cc
+++ b/ios/chrome/browser/passwords/account_select_fill_data.cc
@@ -71,16 +71,12 @@
 
 std::vector<UsernameAndRealm> AccountSelectFillData::RetrieveSuggestions(
     const base::string16& form_name,
-    const base::string16& field_identifier,
-    const base::string16& typed_value) const {
+    const base::string16& field_identifier) const {
   last_requested_form_ = GetFormInfo(form_name, field_identifier);
   DCHECK(last_requested_form_);
   std::vector<UsernameAndRealm> result;
   for (const Credential& credential : credentials_) {
-    if (base::StartsWith(credential.username, typed_value,
-                         base::CompareCase::SENSITIVE)) {
-      result.push_back({credential.username, credential.realm});
-    }
+    result.push_back({credential.username, credential.realm});
   }
   return result;
 }
diff --git a/ios/chrome/browser/passwords/account_select_fill_data.h b/ios/chrome/browser/passwords/account_select_fill_data.h
index 4c3a6346..fab0c7d2 100644
--- a/ios/chrome/browser/passwords/account_select_fill_data.h
+++ b/ios/chrome/browser/passwords/account_select_fill_data.h
@@ -86,8 +86,7 @@
   // with name |form_name|.
   std::vector<UsernameAndRealm> RetrieveSuggestions(
       const base::string16& form_name,
-      const base::string16& field_identifier,
-      const base::string16& typed_value) const;
+      const base::string16& field_identifier) const;
 
   // Returns data for password form filling based on |username| chosen by the
   // user.
diff --git a/ios/chrome/browser/passwords/account_select_fill_data_unittest.cc b/ios/chrome/browser/passwords/account_select_fill_data_unittest.cc
index d5a6c06b..6d1d7dc 100644
--- a/ios/chrome/browser/passwords/account_select_fill_data_unittest.cc
+++ b/ios/chrome/browser/passwords/account_select_fill_data_unittest.cc
@@ -97,8 +97,7 @@
 
   std::vector<UsernameAndRealm> suggestions =
       account_select_fill_data.RetrieveSuggestions(
-          form_data_[0].name, form_data_[0].username_field.id,
-          base::string16());
+          form_data_[0].name, form_data_[0].username_field.id);
   EXPECT_EQ(2u, suggestions.size());
   EXPECT_EQ(base::ASCIIToUTF16(kUsernames[0]), suggestions[0].username);
   EXPECT_EQ(std::string(), suggestions[0].realm);
@@ -118,50 +117,16 @@
 
   std::vector<UsernameAndRealm> suggestions =
       account_select_fill_data.RetrieveSuggestions(
-          form_data_[0].name, form_data_[0].username_field.id,
-          base::string16());
+          form_data_[0].name, form_data_[0].username_field.id);
   EXPECT_EQ(1u, suggestions.size());
   EXPECT_EQ(base::ASCIIToUTF16(kUsernames[1]), suggestions[0].username);
 
   suggestions = account_select_fill_data.RetrieveSuggestions(
-      form_data_[1].name, form_data_[1].username_field.id, base::string16());
+      form_data_[1].name, form_data_[1].username_field.id);
   EXPECT_EQ(1u, suggestions.size());
   EXPECT_EQ(base::ASCIIToUTF16(kUsernames[1]), suggestions[0].username);
 }
 
-TEST_F(AccountSelectFillDataTest, RetrieveSuggestionsPrefix) {
-  // Test that after adding two PasswordFormFillData, suggestions for both forms
-  // are shown, with credentials from the second PasswordFormFillData. That
-  // emulates the case when credentials in the Password Store were changed
-  // between load the first and the second forms.
-  AccountSelectFillData account_select_fill_data;
-  account_select_fill_data.Add(form_data_[0]);
-
-  std::vector<UsernameAndRealm> suggestions =
-      account_select_fill_data.RetrieveSuggestions(
-          form_data_[0].name, form_data_[0].username_field.id,
-          base::ASCIIToUTF16("u"));
-  // u prefix of username and additional username.
-  EXPECT_EQ(2u, suggestions.size());
-  EXPECT_EQ(base::ASCIIToUTF16(kUsernames[0]), suggestions[0].username);
-  EXPECT_EQ(base::ASCIIToUTF16(kAdditionalUsernames[0]),
-            suggestions[1].username);
-
-  suggestions = account_select_fill_data.RetrieveSuggestions(
-      form_data_[0].name, form_data_[0].username_field.id,
-      base::ASCIIToUTF16("u$"));
-  // u$ is prefix of additional username.
-  EXPECT_EQ(1u, suggestions.size());
-  EXPECT_EQ(base::ASCIIToUTF16(kAdditionalUsernames[0]),
-            suggestions[0].username);
-
-  suggestions = account_select_fill_data.RetrieveSuggestions(
-      form_data_[0].name, form_data_[0].username_field.id,
-      base::ASCIIToUTF16("1"));
-  // 1 is prefix of neither usernames.
-  EXPECT_TRUE(suggestions.empty());
-}
-
 TEST_F(AccountSelectFillDataTest, RetrievePSLMatchedSuggestions) {
   AccountSelectFillData account_select_fill_data;
   const char* kRealm = "http://a.example.com/";
@@ -174,8 +139,7 @@
   account_select_fill_data.Add(form_data_[0]);
   std::vector<UsernameAndRealm> suggestions =
       account_select_fill_data.RetrieveSuggestions(
-          form_data_[0].name, form_data_[0].username_field.id,
-          base::string16());
+          form_data_[0].name, form_data_[0].username_field.id);
   EXPECT_EQ(2u, suggestions.size());
   EXPECT_EQ(base::ASCIIToUTF16(kUsernames[0]), suggestions[0].username);
   EXPECT_EQ(kRealm, suggestions[0].realm);
@@ -193,9 +157,8 @@
     const auto& form_data = form_data_[form_i];
     // GetFillData() doesn't have form identifier in arguments, it should be
     // provided in RetrieveSuggestions().
-    account_select_fill_data.RetrieveSuggestions(
-        form_data.name, form_data.username_field.id, base::string16());
-
+    account_select_fill_data.RetrieveSuggestions(form_data.name,
+                                                 form_data.username_field.id);
     std::unique_ptr<FillData> fill_data =
         account_select_fill_data.GetFillData(base::ASCIIToUTF16(kUsernames[1]));
 
@@ -218,8 +181,8 @@
 
   // GetFillData() doesn't have form identifier in arguments, it should be
   // provided in RetrieveSuggestions().
-  account_select_fill_data.RetrieveSuggestions(
-      form_data_[0].name, form_data_[0].username_field.id, base::string16());
+  account_select_fill_data.RetrieveSuggestions(form_data_[0].name,
+                                               form_data_[0].username_field.id);
 
   // AccountSelectFillData should keep only last credentials. Check that in
   // request of old credentials nothing is returned.
diff --git a/ios/chrome/browser/passwords/password_controller.mm b/ios/chrome/browser/passwords/password_controller.mm
index cb461b1..561d92d 100644
--- a/ios/chrome/browser/passwords/password_controller.mm
+++ b/ios/chrome/browser/passwords/password_controller.mm
@@ -77,6 +77,9 @@
 // Script command prefix for form changes. Possible command to be sent from
 // injected JS is 'form.buttonClicked'.
 constexpr char kCommandPrefix[] = "passwordForm";
+
+// The string ' •••' appended to the username in the suggestion.
+NSString* const kSuggestionSuffix = @" ••••••••";
 }
 
 @interface PasswordController ()
@@ -166,31 +169,28 @@
 namespace {
 
 // Constructs an array of FormSuggestions, each corresponding to a username/
-// password pair in |AccountSelectFillData|, such that |typedValue| is a prefix
-// of the username of each suggestion. "Show all" item is appended.
+// password pair in |AccountSelectFillData|. "Show all" item is appended.
 NSArray* BuildSuggestions(const AccountSelectFillData& fillData,
                           NSString* formName,
-                          NSString* fieldIdentifier,
-                          NSString* typedValue) {
+                          NSString* fieldIdentifier) {
   base::string16 form_name = base::SysNSStringToUTF16(formName);
   base::string16 field_identifier = base::SysNSStringToUTF16(fieldIdentifier);
-  base::string16 typed_value = base::SysNSStringToUTF16(typedValue);
 
   NSMutableArray* suggestions = [NSMutableArray array];
   if (fillData.IsSuggestionsAvailable(form_name, field_identifier)) {
     std::vector<password_manager::UsernameAndRealm> username_and_realms_ =
-        fillData.RetrieveSuggestions(form_name, field_identifier, typed_value);
+        fillData.RetrieveSuggestions(form_name, field_identifier);
 
     // Add credentials.
     for (const auto& username_and_realm : username_and_realms_) {
-      NSString* username =
-          base::SysUTF16ToNSString(username_and_realm.username);
+      NSString* value = [base::SysUTF16ToNSString(username_and_realm.username)
+          stringByAppendingString:kSuggestionSuffix];
       NSString* origin =
           username_and_realm.realm.empty()
               ? nil
               : base::SysUTF8ToNSString(username_and_realm.realm);
 
-      [suggestions addObject:[FormSuggestion suggestionWithValue:username
+      [suggestions addObject:[FormSuggestion suggestionWithValue:value
                                               displayDescription:origin
                                                             icon:nil
                                                       identifier:0]];
@@ -744,8 +744,7 @@
                           webState:(web::WebState*)webState
                  completionHandler:(SuggestionsReadyCompletion)completion {
   DCHECK(GetPageURLAndCheckTrustLevel(webState, nullptr));
-  completion(BuildSuggestions(fillData_, formName, fieldIdentifier, typedValue),
-             self);
+  completion(BuildSuggestions(fillData_, formName, fieldIdentifier), self);
 }
 
 - (void)didSelectSuggestion:(FormSuggestion*)suggestion
@@ -759,8 +758,10 @@
     completion();
     return;
   }
-  const base::string16 username = base::SysNSStringToUTF16(suggestion.value);
-  std::unique_ptr<FillData> fillData = fillData_.GetFillData(username);
+  base::string16 value = base::SysNSStringToUTF16(suggestion.value);
+  DCHECK([suggestion.value hasSuffix:kSuggestionSuffix]);
+  value.erase(value.length() - kSuggestionSuffix.length);
+  std::unique_ptr<FillData> fillData = fillData_.GetFillData(value);
 
   if (!fillData)
     completion();
diff --git a/ios/chrome/browser/passwords/password_controller_unittest.mm b/ios/chrome/browser/passwords/password_controller_unittest.mm
index ac09c0f0..3c7827d 100644
--- a/ios/chrome/browser/passwords/password_controller_unittest.mm
+++ b/ios/chrome/browser/passwords/password_controller_unittest.mm
@@ -1179,7 +1179,7 @@
           "evt.initEvent('focus', true, true, window, 1);"
           "username_.dispatchEvent(evt);"),
         @""],
-      @[@"user0", @"abc", showAll],
+      @[@"user0 ••••••••", @"abc ••••••••", showAll],
       @"[]=, onkeyup=false, onchange=false"
     },
     {
@@ -1192,48 +1192,15 @@
       @"[]=, onkeyup=false, onchange=false"
     },
     {
-      "Should filter suggestions when focusing username field with input",
+      "Should not filter suggestions when focusing username field with input",
       @[(@"username_.value='ab';"
           "var evt = document.createEvent('Events');"
           "evt.initEvent('focus', true, true, window, 1);"
           "username_.dispatchEvent(evt);"),
         @""],
-      @[@"abc", showAll],
+      @[@"user0 ••••••••", @"abc ••••••••", showAll],
       @"ab[]=, onkeyup=false, onchange=false"
     },
-    {
-      "Should filter suggestions while typing",
-      @[(@"var evt = document.createEvent('Events');"
-          "evt.initEvent('focus', true, true, window, 1);"
-          "username_.dispatchEvent(evt);"),
-        (@"username_.value='ab';"
-          "evt = document.createEvent('Events');"
-          "evt.initEvent('keyup', true, true, window, 1);"
-          "evt.keyCode = 98;"
-          "username_.dispatchEvent(evt);"),
-        @""],
-      @[@"abc", showAll],
-      @"ab[]=, onkeyup=true, onchange=false"
-    },
-    {
-      "Should unfilter suggestions after backspacing",
-      @[(@"var evt = document.createEvent('Events');"
-          "evt.initEvent('focus', true, true, window, 1);"
-          "username_.dispatchEvent(evt);"),
-        (@"username_.value='ab';"
-          "evt = document.createEvent('Events');"
-          "evt.initEvent('keyup', true, true, window, 1);"
-          "evt.keyCode = 98;"
-          "username_.dispatchEvent(evt);"),
-        (@"username_.value='';"
-          "evt = document.createEvent('Events');"
-          "evt.initEvent('keyup', true, true, window, 1);"
-          "evt.keyCode = 8;"
-          "username_.dispatchEvent(evt);"),
-        @""],
-      @[@"user0", @"abc", showAll],
-      @"[]=, onkeyup=true, onchange=false"
-    },
   };
   // clang-format on
 
@@ -1327,14 +1294,17 @@
                    fieldIdentifier:username_element
                          fieldType:@"text"
                               type:@"focus"
-                        typedValue:@"abc"
+                        typedValue:@""
                           webState:web_state()
                  completionHandler:^(NSArray* suggestions,
                                      id<FormSuggestionProvider> provider) {
                    NSMutableArray* suggestion_values = [NSMutableArray array];
                    for (FormSuggestion* suggestion in suggestions)
                      [suggestion_values addObject:suggestion.value];
-                   EXPECT_NSEQ((@[ @"abc", @"Show All\u2026" ]),
+                   EXPECT_NSEQ((@[
+                                 @"user0 ••••••••", @"abc ••••••••",
+                                 @"Show All\u2026"
+                               ]),
                                suggestion_values);
                    block_was_called = YES;
                  }];
@@ -1342,10 +1312,11 @@
 
     // Tell PasswordController that a suggestion was selected. It should fill
     // out the password form with the corresponding credentials.
-    FormSuggestion* suggestion = [FormSuggestion suggestionWithValue:@"abc"
-                                                  displayDescription:nil
-                                                                icon:nil
-                                                          identifier:0];
+    FormSuggestion* suggestion =
+        [FormSuggestion suggestionWithValue:@"abc ••••••••"
+                         displayDescription:nil
+                                       icon:nil
+                                 identifier:0];
 
     block_was_called = NO;
     SuggestionHandledCompletion completion = ^{
diff --git a/ios/chrome/browser/sync/ios_chrome_sync_client.mm b/ios/chrome/browser/sync/ios_chrome_sync_client.mm
index 935966a..2a5f9c4a 100644
--- a/ios/chrome/browser/sync/ios_chrome_sync_client.mm
+++ b/ios/chrome/browser/sync/ios_chrome_sync_client.mm
@@ -28,7 +28,6 @@
 #include "components/password_manager/sync/browser/password_model_worker.h"
 #include "components/reading_list/core/reading_list_model.h"
 #include "components/search_engines/search_engine_data_type_controller.h"
-#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "components/sync/base/report_unrecoverable_error.h"
 #include "components/sync/driver/sync_api_component_factory.h"
 #include "components/sync/driver/sync_util.h"
@@ -54,7 +53,6 @@
 #include "ios/chrome/browser/passwords/ios_chrome_password_store_factory.h"
 #include "ios/chrome/browser/pref_names.h"
 #include "ios/chrome/browser/reading_list/reading_list_model_factory.h"
-#include "ios/chrome/browser/signin/oauth2_token_service_factory.h"
 #include "ios/chrome/browser/sync/glue/sync_start_util.h"
 #include "ios/chrome/browser/sync/ios_chrome_profile_sync_service_factory.h"
 #include "ios/chrome/browser/sync/ios_user_event_service_factory.h"
@@ -156,22 +154,13 @@
 
   // Component factory may already be set in tests.
   if (!GetSyncApiComponentFactory()) {
-    const GURL sync_service_url = syncer::GetSyncServiceURL(
-        *base::CommandLine::ForCurrentProcess(), ::GetChannel());
-    ProfileOAuth2TokenService* token_service =
-        OAuth2TokenServiceFactory::GetForBrowserState(browser_state_);
-
-    net::URLRequestContextGetter* url_request_context_getter =
-        browser_state_->GetRequestContext();
-
     component_factory_.reset(new browser_sync::ProfileSyncComponentsFactoryImpl(
         this, ::GetChannel(), ::GetVersionString(),
         ui::GetDeviceFormFactor() == ui::DEVICE_FORM_FACTOR_TABLET,
         *base::CommandLine::ForCurrentProcess(),
-        prefs::kSavingBrowserHistoryDisabled, sync_service_url,
+        prefs::kSavingBrowserHistoryDisabled,
         web::WebThread::GetTaskRunnerForThread(web::WebThread::UI), db_thread_,
-        token_service, url_request_context_getter, web_data_service_,
-        password_store_));
+        web_data_service_, password_store_));
   }
 }
 
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm
index 37cada0..fa78d1b 100644
--- a/ios/chrome/browser/ui/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -710,9 +710,7 @@
 @property(nonatomic, strong)
     AdaptiveToolbarCoordinator* secondaryToolbarCoordinator;
 // Interface object with the toolbars.
-@property(nonatomic, strong)
-    id<ToolbarCoordinating, ToolsMenuPresentationStateProvider>
-        toolbarInterface;
+@property(nonatomic, strong) id<ToolbarCoordinating> toolbarInterface;
 
 // Vertical offset for the primary toolbar, used for fullscreen.
 @property(nonatomic, strong) NSLayoutConstraint* primaryToolbarOffsetConstraint;
@@ -1508,10 +1506,12 @@
   [_paymentRequestManager cancelRequest];
   [_printController dismissAnimated:YES];
   _printController = nil;
-  if (base::FeatureList::IsEnabled(kNewToolsMenu)) {
+  if (IsUIRefreshPhase1Enabled()) {
     [self.dispatcher dismissPopupMenu];
   } else {
     [self.dispatcher dismissToolsMenu];
+  }
+  if (!base::FeatureList::IsEnabled(kNewToolsMenu)) {
     [_tabHistoryCoordinator dismissHistoryPopup];
   }
   [_contextMenuCoordinator stop];
@@ -2051,9 +2051,8 @@
     bottomToolbarCoordinator.dispatcher = self.dispatcher;
     [bottomToolbarCoordinator start];
 
-    ToolbarCoordinatorAdaptor* adaptor = [[ToolbarCoordinatorAdaptor alloc]
-        initWithToolsMenuConfigurationProvider:self
-                                    dispatcher:self.dispatcher];
+    ToolbarCoordinatorAdaptor* adaptor =
+        [[ToolbarCoordinatorAdaptor alloc] initWithDispatcher:self.dispatcher];
     self.toolbarInterface = adaptor;
     [adaptor addToolbarCoordinator:topToolbarCoordinator];
     [adaptor addToolbarCoordinator:bottomToolbarCoordinator];
@@ -2243,13 +2242,15 @@
       [self.primaryToolbarCoordinator QRScannerResultLoader];
   _qrScannerCoordinator.presentationProvider = self;
 
-  if (base::FeatureList::IsEnabled(kNewToolsMenu)) {
+  if (IsUIRefreshPhase1Enabled()) {
     self.popupMenuCoordinator = [[PopupMenuCoordinator alloc]
         initWithBaseViewController:self
                       browserState:self.browserState];
     self.popupMenuCoordinator.dispatcher = _dispatcher;
+    self.popupMenuCoordinator.webStateList = [_model webStateList];
     [self.popupMenuCoordinator start];
-  } else {
+  }
+  if (!base::FeatureList::IsEnabled(kNewToolsMenu)) {
     _tabHistoryCoordinator = [[LegacyTabHistoryCoordinator alloc]
         initWithBaseViewController:self
                       browserState:_browserState];
@@ -2338,6 +2339,7 @@
       kToolsMenuGuide,
       kTabSwitcherGuide,
       kSecondaryToolbar,
+      kVoiceSearchButtonGuide,
     ];
     AddNamedGuidesToView(guideNames, self.view);
   }
@@ -2433,7 +2435,7 @@
   Tab* tab = [_model currentTab];
   if (![tab navigationManager])
     return;
-  [self.toolbarInterface updateToolsMenu];
+  [_toolbarCoordinator updateToolsMenu];
 
   if (_insertedTabWasPrerenderedTab &&
       ![self.helper isToolbarLoading:self.currentWebState])
@@ -2472,10 +2474,12 @@
 
 - (void)dismissPopups {
   [self.dispatcher hidePageInfo];
-  if (base::FeatureList::IsEnabled(kNewToolsMenu)) {
+  if (IsUIRefreshPhase1Enabled()) {
     [self.dispatcher dismissPopupMenu];
   } else {
     [self.dispatcher dismissToolsMenu];
+  }
+  if (!base::FeatureList::IsEnabled(kNewToolsMenu)) {
     [_tabHistoryCoordinator dismissHistoryPopup];
   }
   [self.tabTipBubblePresenter dismissAnimated:NO];
@@ -5248,7 +5252,13 @@
 }
 
 - (BOOL)preventSideSwipe {
-  if ([self.toolbarInterface isShowingToolsMenu])
+  BOOL isShowingToolsMenu = NO;
+  if (IsUIRefreshPhase1Enabled()) {
+    isShowingToolsMenu = [self.popupMenuCoordinator isShowingPopupMenu];
+  } else {
+    isShowingToolsMenu = [_toolbarCoordinator isShowingToolsMenu];
+  }
+  if (isShowingToolsMenu)
     return YES;
 
   if (_voiceSearchController && _voiceSearchController->IsVisible())
diff --git a/ios/chrome/browser/ui/content_suggestions/BUILD.gn b/ios/chrome/browser/ui/content_suggestions/BUILD.gn
index e2e5fcbd..286d9c4b 100644
--- a/ios/chrome/browser/ui/content_suggestions/BUILD.gn
+++ b/ios/chrome/browser/ui/content_suggestions/BUILD.gn
@@ -71,6 +71,7 @@
     "//ios/chrome/browser/ui/toolbar/buttons",
     "//ios/chrome/browser/ui/toolbar/clean:toolbar",
     "//ios/chrome/browser/ui/toolbar/public",
+    "//ios/chrome/browser/ui/util",
     "//ios/chrome/browser/web_state_list",
     "//ios/chrome/common/app_group",
     "//ios/public/provider/chrome/browser",
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm
index 38d510d9..2e8f737 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm
@@ -26,6 +26,7 @@
 #import "ios/chrome/browser/ui/uikit_ui_util.h"
 #import "ios/chrome/browser/ui/url_loader.h"
 #import "ios/chrome/browser/ui/util/constraints_ui_util.h"
+#import "ios/chrome/browser/ui/util/named_guide.h"
 #include "ios/chrome/grit/ios_strings.h"
 #include "ios/public/provider/chrome/browser/ui/logo_vendor.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -362,9 +363,11 @@
 
   DCHECK(self.voiceSearchIsEnabled);
   base::RecordAction(UserMetricsAction("MobileNTPMostVisitedVoiceSearch"));
-  UIView* view = base::mac::ObjCCastStrict<UIView>(sender);
+  UIView* voiceSearchButton = base::mac::ObjCCastStrict<UIView>(sender);
+  [NamedGuide guideWithName:kVoiceSearchButtonGuide view:voiceSearchButton]
+      .constrainedView = voiceSearchButton;
   StartVoiceSearchCommand* command =
-      [[StartVoiceSearchCommand alloc] initWithOriginView:view];
+      [[StartVoiceSearchCommand alloc] initWithOriginView:voiceSearchButton];
   [self.dispatcher startVoiceSearch:command];
 }
 
diff --git a/ios/chrome/browser/ui/download/download_manager_coordinator.mm b/ios/chrome/browser/ui/download/download_manager_coordinator.mm
index 10fc99a..8ce2b13 100644
--- a/ios/chrome/browser/ui/download/download_manager_coordinator.mm
+++ b/ios/chrome/browser/ui/download/download_manager_coordinator.mm
@@ -7,6 +7,7 @@
 #include <memory>
 
 #import "base/logging.h"
+#include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
 #include "base/metrics/user_metrics_action.h"
@@ -49,6 +50,10 @@
                                     ? DownloadFileResult::Failure
                                     : DownloadFileResult::Completed,
                                 DownloadFileResult::Count);
+      if (task->GetErrorCode()) {
+        base::UmaHistogramSparse("Download.IOSDownloadedFileNetError",
+                                 -task->GetErrorCode());
+      }
     }
   }
   void OnDownloadDestroyed(web::DownloadTask* task) override {
@@ -107,7 +112,6 @@
   _viewController.delegate = self;
   _mediator.SetDownloadTask(_downloadTask);
   _mediator.SetConsumer(_viewController);
-  _unopenedDownloads.Add(_downloadTask);
 
   self.presenter.baseViewController = self.baseViewController;
   self.presenter.presentedViewController = _viewController;
@@ -120,10 +124,13 @@
 
 - (void)stop {
   if (_viewController) {
-    [self.presenter dismissAnimated:YES];
+    [self.presenter dismissAnimated:self.animatesPresentation];
+    // Prevent delegate callbacks for stopped coordinator.
+    _viewController.delegate = nil;
     _viewController = nil;
   }
-  [_confirmationDialog dismissViewControllerAnimated:YES completion:nil];
+  [_confirmationDialog dismissViewControllerAnimated:self.animatesPresentation
+                                          completion:nil];
   _confirmationDialog = nil;
   _downloadTask = nullptr;
 
@@ -182,7 +189,9 @@
   }
 
   DCHECK_EQ(_downloadTask, download);
+  self.animatesPresentation = NO;
   [self stop];
+  self.animatesPresentation = YES;
 }
 
 - (void)downloadManagerTabHelper:(nonnull DownloadManagerTabHelper*)tabHelper
@@ -191,6 +200,7 @@
   _downloadTask = download;
   self.animatesPresentation = NO;
   [self start];
+  self.animatesPresentation = YES;
 }
 
 #pragma mark - UIDocumentInteractionControllerDelegate
@@ -247,6 +257,8 @@
     (DownloadManagerViewController*)controller {
   if (_downloadTask->GetErrorCode() != net::OK) {
     base::RecordAction(base::UserMetricsAction("MobileDownloadRetryDownload"));
+  } else {
+    _unopenedDownloads.Add(_downloadTask);
   }
   _mediator.StartDowloading();
 }
diff --git a/ios/chrome/browser/ui/download/download_manager_coordinator_unittest.mm b/ios/chrome/browser/ui/download/download_manager_coordinator_unittest.mm
index d0bffa8..cbc619a 100644
--- a/ios/chrome/browser/ui/download/download_manager_coordinator_unittest.mm
+++ b/ios/chrome/browser/ui/download/download_manager_coordinator_unittest.mm
@@ -370,12 +370,11 @@
       base_view_controller_.childViewControllers.firstObject;
   ASSERT_EQ([DownloadManagerViewController class], [viewController class]);
 
-  // Start and complete the download.
+  // Start the download.
   base::FilePath path;
   ASSERT_TRUE(base::GetTempDir(&path));
   task->Start(std::make_unique<net::URLFetcherFileWriter>(
       base::ThreadTaskRunnerHandle::Get(), path));
-  task->SetDone(true);
 
   // Stub UIDocumentInteractionController.
   FakeDocumentInteractionController* document_interaction_controller =
@@ -391,7 +390,9 @@
   [view addLayoutGuide:guide];
   ASSERT_FALSE(document_interaction_controller.presentedOpenInMenu);
   @autoreleasepool {
-    // This call will retain coordinator, which should outlive thread bundle.
+    // These calls will retain coordinator, which should outlive thread bundle.
+    [viewController.delegate
+        downloadManagerViewControllerDidStartDownload:viewController];
     [viewController.delegate downloadManagerViewController:viewController
                           presentOpenInMenuWithLayoutGuide:guide];
   }
@@ -401,8 +402,12 @@
   ASSERT_EQ(view, document_interaction_controller.presentedOpenInMenu.view);
   ASSERT_TRUE(document_interaction_controller.presentedOpenInMenu.animated);
 
+  // Complete the download to log Download.IOSDownloadFileResult.
+  task->SetDone(true);
+
   // Download task is destroyed without opening the file.
   task = nullptr;
+  histogram_tester_.ExpectTotalCount("Download.IOSDownloadedFileNetError", 0);
   histogram_tester_.ExpectUniqueSample(
       "Download.IOSDownloadFileResult",
       static_cast<base::HistogramBase::Sample>(DownloadFileResult::Completed),
@@ -417,6 +422,7 @@
 TEST_F(DownloadManagerCoordinatorTest, DestroyInProgressDownload) {
   auto task = CreateTestTask();
   coordinator_.downloadTask = task.get();
+  web::DownloadTask* task_ptr = task.get();
   [coordinator_ start];
 
   EXPECT_EQ(1U, base_view_controller_.childViewControllers.count);
@@ -425,13 +431,21 @@
   ASSERT_EQ([DownloadManagerViewController class], [viewController class]);
 
   // Start and the download.
-  base::FilePath path;
-  ASSERT_TRUE(base::GetTempDir(&path));
-  task->Start(std::make_unique<net::URLFetcherFileWriter>(
-      base::ThreadTaskRunnerHandle::Get(), path));
+  @autoreleasepool {
+    // This call will retain coordinator, which should outlive thread bundle.
+    [viewController.delegate
+        downloadManagerViewControllerDidStartDownload:viewController];
+  }
+
+  // Starting download is async for model.
+  ASSERT_TRUE(WaitUntilConditionOrTimeout(testing::kWaitForDownloadTimeout, ^{
+    base::RunLoop().RunUntilIdle();
+    return task_ptr->GetState() == web::DownloadTask::State::kInProgress;
+  }));
 
   // Download task is destroyed before the download is complete.
   task = nullptr;
+  histogram_tester_.ExpectTotalCount("Download.IOSDownloadedFileNetError", 0);
   histogram_tester_.ExpectTotalCount("Download.IOSDownloadedFileAction", 0);
   histogram_tester_.ExpectUniqueSample(
       "Download.IOSDownloadFileResult",
@@ -443,6 +457,7 @@
   web::FakeDownloadTask task(GURL(kTestUrl), kTestMimeType);
   task.SetSuggestedFilename(base::SysNSStringToUTF16(kTestSuggestedFileName));
   coordinator_.downloadTask = &task;
+  web::DownloadTask* task_ptr = &task;
   [coordinator_ start];
 
   EXPECT_EQ(1U, base_view_controller_.childViewControllers.count);
@@ -450,12 +465,6 @@
       base_view_controller_.childViewControllers.firstObject;
   ASSERT_EQ([DownloadManagerViewController class], [viewController class]);
 
-  // Start and complete the download.
-  base::FilePath path;
-  ASSERT_TRUE(base::GetTempDir(&path));
-  task.Start(std::make_unique<net::URLFetcherFileWriter>(
-      base::ThreadTaskRunnerHandle::Get(), path));
-
   // Stub UIDocumentInteractionController.
   id document_interaction_controller =
       [[FakeDocumentInteractionController alloc] init];
@@ -463,6 +472,18 @@
               interactionControllerWithURL:[OCMArg any]])
       .andReturn(document_interaction_controller);
 
+  // Start the download.
+  @autoreleasepool {
+    // This call will retain coordinator, which should outlive thread bundle.
+    [viewController.delegate
+        downloadManagerViewControllerDidStartDownload:viewController];
+  }
+  // Starting download is async for model.
+  ASSERT_TRUE(WaitUntilConditionOrTimeout(testing::kWaitForDownloadTimeout, ^{
+    base::RunLoop().RunUntilIdle();
+    return task_ptr->GetState() == web::DownloadTask::State::kInProgress;
+  }));
+
   // Present Open In... menu.
   ASSERT_FALSE([document_interaction_controller presentedOpenInMenu]);
   @autoreleasepool {
@@ -480,6 +501,7 @@
         willBeginSendingToApplication:kGoogleDriveAppBundleID];
   }
 
+  histogram_tester_.ExpectTotalCount("Download.IOSDownloadedFileNetError", 0);
   histogram_tester_.ExpectTotalCount("Download.IOSDownloadFileResult", 0);
   histogram_tester_.ExpectUniqueSample("Download.IOSDownloadedFileAction",
                                        static_cast<base::HistogramBase::Sample>(
@@ -492,6 +514,7 @@
   web::FakeDownloadTask task(GURL(kTestUrl), kTestMimeType);
   task.SetSuggestedFilename(base::SysNSStringToUTF16(kTestSuggestedFileName));
   coordinator_.downloadTask = &task;
+  web::DownloadTask* task_ptr = &task;
   [coordinator_ start];
 
   EXPECT_EQ(1U, base_view_controller_.childViewControllers.count);
@@ -499,12 +522,6 @@
       base_view_controller_.childViewControllers.firstObject;
   ASSERT_EQ([DownloadManagerViewController class], [viewController class]);
 
-  // Start and complete the download.
-  base::FilePath path;
-  ASSERT_TRUE(base::GetTempDir(&path));
-  task.Start(std::make_unique<net::URLFetcherFileWriter>(
-      base::ThreadTaskRunnerHandle::Get(), path));
-
   // Stub UIDocumentInteractionController.
   id document_interaction_controller =
       [[FakeDocumentInteractionController alloc] init];
@@ -512,6 +529,18 @@
               interactionControllerWithURL:[OCMArg any]])
       .andReturn(document_interaction_controller);
 
+  // Start the download.
+  @autoreleasepool {
+    // This call will retain coordinator, which should outlive thread bundle.
+    [viewController.delegate
+        downloadManagerViewControllerDidStartDownload:viewController];
+  }
+  // Starting download is async for model.
+  ASSERT_TRUE(WaitUntilConditionOrTimeout(testing::kWaitForDownloadTimeout, ^{
+    base::RunLoop().RunUntilIdle();
+    return task_ptr->GetState() == web::DownloadTask::State::kInProgress;
+  }));
+
   // Present Open In... menu.
   ASSERT_FALSE([document_interaction_controller presentedOpenInMenu]);
   @autoreleasepool {
@@ -529,6 +558,7 @@
         willBeginSendingToApplication:@"foo-app-id"];
   }
 
+  histogram_tester_.ExpectTotalCount("Download.IOSDownloadedFileNetError", 0);
   histogram_tester_.ExpectTotalCount("Download.IOSDownloadFileResult", 0);
   histogram_tester_.ExpectUniqueSample(
       "Download.IOSDownloadedFileAction",
@@ -693,9 +723,8 @@
   web::DownloadTask* task_ptr = &task;
   coordinator_.downloadTask = &task;
   [coordinator_ start];
-  task.SetErrorCode(net::ERR_INTERNET_DISCONNECTED);
-  task.SetDone(true);
 
+  // First download is a failure.
   DownloadManagerViewController* viewController =
       base_view_controller_.childViewControllers.firstObject;
   ASSERT_EQ([DownloadManagerViewController class], [viewController class]);
@@ -704,6 +733,14 @@
     [viewController.delegate
         downloadManagerViewControllerDidStartDownload:viewController];
   }
+  task.SetErrorCode(net::ERR_INTERNET_DISCONNECTED);
+  task.SetDone(true);
+
+  @autoreleasepool {
+    // This call will retain coordinator, which should outlive thread bundle.
+    [viewController.delegate
+        downloadManagerViewControllerDidStartDownload:viewController];
+  }
 
   // Starting download is async for model.
   ASSERT_TRUE(WaitUntilConditionOrTimeout(testing::kWaitForDownloadTimeout, ^{
@@ -711,6 +748,8 @@
     return task_ptr->GetState() == web::DownloadTask::State::kInProgress;
   }));
 
+  histogram_tester_.ExpectUniqueSample("Download.IOSDownloadedFileNetError",
+                                       -net::ERR_INTERNET_DISCONNECTED, 1);
   histogram_tester_.ExpectUniqueSample(
       "Download.IOSDownloadFileResult",
       static_cast<base::HistogramBase::Sample>(DownloadFileResult::Failure), 1);
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_egtest.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_egtest.mm
index 24ec03c..817be5bc5 100644
--- a/ios/chrome/browser/ui/fullscreen/fullscreen_egtest.mm
+++ b/ios/chrome/browser/ui/fullscreen/fullscreen_egtest.mm
@@ -4,6 +4,7 @@
 
 #import <EarlGrey/EarlGrey.h>
 #import <UIKit/UIKit.h>
+#import <WebKit/WebKit.h>
 #import <XCTest/XCTest.h>
 
 #include "base/ios/ios_util.h"
@@ -247,11 +248,6 @@
 // Test to make sure the header is shown when a Tab opened by the current Tab is
 // closed even if the toolbar was not present previously.
 - (void)testShowHeaderWhenChildTabCloses {
-// TODO(crbug.com/812664): Re-enable this test on devices.
-#if !TARGET_IPHONE_SIMULATOR
-  EARL_GREY_TEST_DISABLED(@"Test disabled on device.");
-#endif
-
   std::map<GURL, std::string> responses;
   const GURL URL = web::test::HttpServer::MakeUrl("http://origin");
   const GURL destinationURL =
@@ -297,22 +293,18 @@
   HideToolbarUsingUI();
   [ChromeEarlGreyUI waitForToolbarVisible:NO];
 
-  // Close the tab.
+  // Close the tab by tapping link2.
   NSError* error = nil;
-  bool success = chrome_test_util::TapWebViewElementWithId("link2", &error);
-
-  if (!web::GetWebClient()->IsSlimNavigationManagerEnabled()) {
-    // The effect of clicking the link, closes the tab and invalidates the web
-    // view. This results in |TapWebViewElementWithId| returning false. This
-    // error is represented by code 3. WKBasedNavigationManager does not trigger
-    // any error.
-    GREYAssertFalse(success, @"Failed to tap \"link2\"");
-    GREYAssert(error.code == 3,
+  if (!chrome_test_util::TapWebViewElementWithId("link2", &error)) {
+    // Sometimes, the tap will be unsuccessful due to the window.close()
+    // operation invalidating the WKWebView.  If this occurs, verify the error.
+    // This results in |TapWebViewElementWithId| returning false.
+    // TODO(crbug.com/824879): Remove conditional once flake is eliminated from
+    // TapWebViewElementWithId() for window.close() links.
+    GREYAssert(error.code == WKErrorWebViewInvalidated,
                @"Failed to receive WKErrorWebViewInvalidated error");
-    GREYAssert([error.domain isEqualToString:@"WKErrorDomain"],
+    GREYAssert([error.domain isEqualToString:WKErrorDomain],
                @"Failed to receive WKErrorDomain error");
-  } else {
-    GREYAssert(success, @"Failed to tap \"link2\"");
   }
 
   [ChromeEarlGrey waitForWebViewContainingText:"link1"];
diff --git a/ios/chrome/browser/ui/key_commands_provider.mm b/ios/chrome/browser/ui/key_commands_provider.mm
index 5246f8f..938413be 100644
--- a/ios/chrome/browser/ui/key_commands_provider.mm
+++ b/ios/chrome/browser/ui/key_commands_provider.mm
@@ -10,6 +10,7 @@
 #include "ios/chrome/browser/ui/commands/start_voice_search_command.h"
 #import "ios/chrome/browser/ui/keyboard/UIKeyCommand+Chrome.h"
 #include "ios/chrome/browser/ui/rtl_geometry.h"
+#import "ios/chrome/browser/ui/util/named_guide.h"
 #include "ios/chrome/grit/ios_strings.h"
 #include "ui/base/l10n/l10n_util_mac.h"
 
@@ -198,6 +199,10 @@
                    modifierFlags:UIKeyModifierCommand | UIKeyModifierShift
                            title:voiceSearchTitle
                           action:^{
+                            UIView* baseView = baseViewController.view;
+                            [[NamedGuide guideWithName:kVoiceSearchButtonGuide
+                                                  view:baseView]
+                                resetConstraints];
                             StartVoiceSearchCommand* command =
                                 [[StartVoiceSearchCommand alloc]
                                     initWithOriginView:nil];
diff --git a/ios/chrome/browser/ui/omnibox/popup/BUILD.gn b/ios/chrome/browser/ui/omnibox/popup/BUILD.gn
index 8f2d933..2fa2ec00 100644
--- a/ios/chrome/browser/ui/omnibox/popup/BUILD.gn
+++ b/ios/chrome/browser/ui/omnibox/popup/BUILD.gn
@@ -17,6 +17,7 @@
     "omnibox_popup_view_ios.h",
     "omnibox_popup_view_ios.mm",
     "omnibox_popup_view_suggestions_delegate.h",
+    "table_view_owning.h",
   ]
   deps = [
     ":popup_internal",
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_presenter.h b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_presenter.h
index af6a9f6..e92792f 100644
--- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_presenter.h
+++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_presenter.h
@@ -8,11 +8,13 @@
 #import <UIKit/UIKit.h>
 
 @protocol OmniboxPopupPositioner;
+@protocol TableViewOwning;
 
 @interface OmniboxPopupPresenter : NSObject
 
 - (instancetype)initWithPopupPositioner:(id<OmniboxPopupPositioner>)positioner
-                    popupViewController:(UITableViewController*)viewController;
+                    popupViewController:
+                        (UIViewController<TableViewOwning>*)viewController;
 
 // Updates appearance depending on the content size of the presented view
 // controller by changing the visible height of the popup. When the popup was
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_presenter.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_presenter.mm
index a3ce596..c9d550e 100644
--- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_presenter.mm
+++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_presenter.mm
@@ -5,6 +5,7 @@
 #import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_presenter.h"
 
 #import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_positioner.h"
+#import "ios/chrome/browser/ui/omnibox/popup/table_view_owning.h"
 #import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_base_feature.h"
 #include "ios/chrome/browser/ui/ui_util.h"
 #import "ios/chrome/browser/ui/uikit_ui_util.h"
@@ -32,7 +33,7 @@
 @property(nonatomic, strong) NSLayoutConstraint* bottomConstraint;
 
 @property(nonatomic, weak) id<OmniboxPopupPositioner> positioner;
-@property(nonatomic, weak) UITableViewController* viewController;
+@property(nonatomic, weak) UIViewController<TableViewOwning>* viewController;
 @property(nonatomic, strong) UIView* popupContainerView;
 @end
 
@@ -44,7 +45,8 @@
 @synthesize bottomConstraint = _bottomConstraint;
 
 - (instancetype)initWithPopupPositioner:(id<OmniboxPopupPositioner>)positioner
-                    popupViewController:(UITableViewController*)viewController {
+                    popupViewController:
+                        (UIViewController<TableViewOwning>*)viewController {
   self = [super init];
   if (self) {
     _positioner = positioner;
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.h b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.h
index a5ab3f68..614f079 100644
--- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.h
+++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.h
@@ -9,6 +9,7 @@
 #import "ios/chrome/browser/ui/commands/omnibox_suggestion_commands.h"
 #import "ios/chrome/browser/ui/omnibox/autocomplete_result_consumer.h"
 #import "ios/chrome/browser/ui/omnibox/image_retriever.h"
+#import "ios/chrome/browser/ui/omnibox/popup/table_view_owning.h"
 
 @protocol ImageRetriever;
 
@@ -20,16 +21,17 @@
 // is the first responder, this view controller cannot receive these events.
 // Hence the delegation.
 @interface OmniboxPopupViewController
-    : UITableViewController<AutocompleteResultConsumer,
-                            OmniboxSuggestionCommands>
+    : UIViewController<AutocompleteResultConsumer,
+                       OmniboxSuggestionCommands,
+                       TableViewOwning>
 
 @property(nonatomic, assign) BOOL incognito;
 @property(nonatomic, weak) id<AutocompleteResultConsumerDelegate> delegate;
 @property(nonatomic, weak) id<ImageRetriever> imageRetriever;
 
 - (instancetype)init NS_DESIGNATED_INITIALIZER;
+
 - (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE;
-- (instancetype)initWithStyle:(UITableViewStyle)style NS_UNAVAILABLE;
 - (instancetype)initWithNibName:(NSString*)nibNameOrNil
                          bundle:(NSBundle*)nibBundleOrNil NS_UNAVAILABLE;
 
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.mm
index c152725d..d7c8ddc9 100644
--- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.mm
+++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.mm
@@ -43,7 +43,8 @@
 }
 }  // namespace
 
-@interface OmniboxPopupViewController () {
+@interface OmniboxPopupViewController ()<UITableViewDelegate,
+                                         UITableViewDataSource> {
   // Alignment of omnibox text. Popup text should match this alignment.
   NSTextAlignment _alignment;
 
@@ -68,12 +69,13 @@
 @synthesize incognito = _incognito;
 @synthesize imageRetriever = _imageRetriever;
 @synthesize highlightedIndexPath = _highlightedIndexPath;
+@synthesize tableView = _tableView;
 
 #pragma mark -
 #pragma mark Initialization
 
 - (instancetype)init {
-  if ((self = [super initWithStyle:UITableViewStylePlain])) {
+  if (self = [super initWithNibName:nil bundle:nil]) {
     if (IsIPadIdiom()) {
       // The iPad keyboard can cover some of the rows of the scroll view. The
       // scroll view's content inset may need to be updated when the keyboard is
@@ -93,6 +95,14 @@
   self.tableView.delegate = nil;
 }
 
+- (void)loadView {
+  self.tableView = [[UITableView alloc] initWithFrame:CGRectZero
+                                                style:UITableViewStylePlain];
+  self.tableView.delegate = self;
+  self.tableView.dataSource = self;
+  self.view = self.tableView;
+}
+
 - (UIScrollView*)scrollView {
   return (UIScrollView*)self.tableView;
 }
diff --git a/ios/chrome/browser/ui/omnibox/popup/table_view_owning.h b/ios/chrome/browser/ui/omnibox/popup/table_view_owning.h
new file mode 100644
index 0000000..f25c4a5
--- /dev/null
+++ b/ios/chrome/browser/ui/omnibox/popup/table_view_owning.h
@@ -0,0 +1,15 @@
+// Copyright 2018 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_OMNIBOX_POPUP_TABLE_VIEW_OWNING_H_
+#define IOS_CHROME_BROWSER_UI_OMNIBOX_POPUP_TABLE_VIEW_OWNING_H_
+
+// A protocol that can be implemented by anything that owns a table view.
+@protocol TableViewOwning<NSObject>
+
+@property(nonatomic, strong) UITableView* tableView;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_OMNIBOX_POPUP_TABLE_VIEW_OWNING_H_
diff --git a/ios/chrome/browser/ui/popup_menu/BUILD.gn b/ios/chrome/browser/ui/popup_menu/BUILD.gn
index 6bd08f2..d2b39b1 100644
--- a/ios/chrome/browser/ui/popup_menu/BUILD.gn
+++ b/ios/chrome/browser/ui/popup_menu/BUILD.gn
@@ -14,10 +14,15 @@
     ":popup_menu_ui",
     "//base",
     "//ios/chrome/app/strings",
+    "//ios/chrome/browser/find_in_page",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/coordinators:chrome_coordinators",
     "//ios/chrome/browser/ui/popup_menu/cells",
     "//ios/chrome/browser/ui/util",
+    "//ios/chrome/browser/web_state_list",
+    "//ios/public/provider/chrome/browser",
+    "//ios/public/provider/chrome/browser/user_feedback",
+    "//ios/web",
     "//ui/base",
   ]
   libs = [ "UIKit.framework" ]
@@ -57,6 +62,32 @@
   ]
 }
 
+source_set("unit_tests") {
+  testonly = true
+
+  sources = [
+    "popup_menu_mediator_unittest.mm",
+  ]
+  deps = [
+    ":popup_menu",
+    ":popup_menu_ui",
+    "//base",
+    "//base/test:test_support",
+    "//ios/chrome/browser/browser_state:test_support",
+    "//ios/chrome/browser/ui/toolbar/test",
+    "//ios/chrome/browser/web_state_list",
+    "//ios/chrome/browser/web_state_list:test_support",
+    "//ios/chrome/test:test_support",
+    "//ios/public/provider/chrome/browser:test_support",
+    "//ios/web",
+    "//ios/web/public/test",
+    "//ios/web/public/test/fakes",
+    "//testing/gtest",
+    "//third_party/ocmock",
+  ]
+  configs += [ "//build/config/compiler:enable_arc" ]
+}
+
 source_set("flags") {
   configs += [ "//build/config/compiler:enable_arc" ]
   sources = [
diff --git a/ios/chrome/browser/ui/popup_menu/cells/popup_menu_item.h b/ios/chrome/browser/ui/popup_menu/cells/popup_menu_item.h
index 338797f..60d9ff3 100644
--- a/ios/chrome/browser/ui/popup_menu/cells/popup_menu_item.h
+++ b/ios/chrome/browser/ui/popup_menu/cells/popup_menu_item.h
@@ -5,7 +5,7 @@
 #ifndef IOS_CHROME_BROWSER_UI_POPUP_MENU_CELLS_POPUP_MENU_ITEM_H_
 #define IOS_CHROME_BROWSER_UI_POPUP_MENU_CELLS_POPUP_MENU_ITEM_H_
 
-#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
 
 // Identifier for the action associated with a popup menu item.
 typedef NS_ENUM(NSInteger, PopupMenuAction) {
@@ -14,6 +14,7 @@
   PopupMenuActionOpenNewTab,
   PopupMenuActionOpenNewIncognitoTab,
   PopupMenuActionReadLater,
+  PopupMenuActionFindInPage,
   PopupMenuActionRequestDesktop,
   PopupMenuActionRequestMobile,
   PopupMenuActionSiteInformation,
@@ -32,6 +33,9 @@
 // Action identifier for the popup item.
 @property(nonatomic, assign) PopupMenuAction actionIdentifier;
 
+// Returns the size needed to display the cell associated with this item.
+- (CGSize)cellSizeForWidth:(CGFloat)width;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_POPUP_MENU_CELLS_POPUP_MENU_ITEM_H_
diff --git a/ios/chrome/browser/ui/popup_menu/cells/popup_menu_navigation_item.mm b/ios/chrome/browser/ui/popup_menu/cells/popup_menu_navigation_item.mm
index 7a45720..4e1daf2f3 100644
--- a/ios/chrome/browser/ui/popup_menu/cells/popup_menu_navigation_item.mm
+++ b/ios/chrome/browser/ui/popup_menu/cells/popup_menu_navigation_item.mm
@@ -4,6 +4,8 @@
 
 #import "ios/chrome/browser/ui/popup_menu/cells/popup_menu_navigation_item.h"
 
+#include "base/logging.h"
+
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
@@ -20,6 +22,14 @@
   return self;
 }
 
+#pragma mark - PopupMenuItem
+
+- (CGSize)cellSizeForWidth:(CGFloat)width {
+  // TODO(crbug.com/804779): implement this.
+  NOTREACHED();
+  return CGSizeZero;
+}
+
 @end
 
 @implementation PopupMenuNavigationCell
diff --git a/ios/chrome/browser/ui/popup_menu/cells/popup_menu_tools_item.h b/ios/chrome/browser/ui/popup_menu/cells/popup_menu_tools_item.h
index 5dd2c30..2653b5c 100644
--- a/ios/chrome/browser/ui/popup_menu/cells/popup_menu_tools_item.h
+++ b/ios/chrome/browser/ui/popup_menu/cells/popup_menu_tools_item.h
@@ -15,6 +15,8 @@
 @property(nonatomic, copy) NSString* title;
 // Image to be displayed on the item.
 @property(nonatomic, strong) UIImage* image;
+// Whether the cell associated with this item should be enabled.
+@property(nonatomic, assign) BOOL enabled;
 
 @end
 
@@ -24,8 +26,12 @@
 // Image view to display the image.
 @property(nonatomic, strong, readonly) UIImageView* imageView;
 
-// Sets the title of the cell.
-- (void)setTitleText:(NSString*)title;
+// Title label for the cell.
+@property(nonatomic, strong, readonly) UILabel* titleLabel;
+
+// Returns the size this cell would use to display its content when it has a
+// |title| and a maximum |width|.
++ (CGSize)sizeForWidth:(CGFloat)width title:(NSString*)title;
 
 @end
 
diff --git a/ios/chrome/browser/ui/popup_menu/cells/popup_menu_tools_item.mm b/ios/chrome/browser/ui/popup_menu/cells/popup_menu_tools_item.mm
index fd0596f..c29ba94b 100644
--- a/ios/chrome/browser/ui/popup_menu/cells/popup_menu_tools_item.mm
+++ b/ios/chrome/browser/ui/popup_menu/cells/popup_menu_tools_item.mm
@@ -4,6 +4,7 @@
 
 #import "ios/chrome/browser/ui/popup_menu/cells/popup_menu_tools_item.h"
 
+#include "base/logging.h"
 #import "ios/chrome/browser/ui/util/constraints_ui_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -12,6 +13,7 @@
 
 namespace {
 const CGFloat kImageLength = 30;
+const CGFloat kMargin = 8;
 }
 
 @implementation PopupMenuToolsItem
@@ -19,11 +21,13 @@
 @synthesize actionIdentifier = _actionIdentifier;
 @synthesize image = _image;
 @synthesize title = _title;
+@synthesize enabled = _enabled;
 
 - (instancetype)initWithType:(NSInteger)type {
   self = [super initWithType:type];
   if (self) {
     self.cellClass = [PopupMenuToolsCell class];
+    _enabled = YES;
   }
   return self;
 }
@@ -31,8 +35,15 @@
 - (void)configureCell:(PopupMenuToolsCell*)cell
            withStyler:(ChromeTableViewStyler*)styler {
   [super configureCell:cell withStyler:styler];
-  [cell setTitleText:self.title];
+  cell.titleLabel.text = self.title;
   cell.imageView.image = self.image;
+  cell.userInteractionEnabled = self.enabled;
+}
+
+#pragma mark - PopupMenuItem
+
+- (CGSize)cellSizeForWidth:(CGFloat)width {
+  return [self.cellClass sizeForWidth:width title:self.title];
 }
 
 @end
@@ -41,8 +52,8 @@
 
 @interface PopupMenuToolsCell ()
 
-// Title label for the cell.
-@property(nonatomic, strong) UILabel* title;
+// Title label for the cell, redefined as readwrite.
+@property(nonatomic, strong, readwrite) UILabel* titleLabel;
 // Image view for the cell, redefined as readwrite.
 @property(nonatomic, strong, readwrite) UIImageView* imageView;
 
@@ -51,14 +62,15 @@
 @implementation PopupMenuToolsCell
 
 @synthesize imageView = _imageView;
-@synthesize title = _title;
+@synthesize titleLabel = _titleLabel;
 
 - (instancetype)initWithStyle:(UITableViewCellStyle)style
               reuseIdentifier:(NSString*)reuseIdentifier {
   self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
   if (self) {
-    _title = [[UILabel alloc] init];
-    _title.translatesAutoresizingMaskIntoConstraints = NO;
+    _titleLabel = [[UILabel alloc] init];
+    _titleLabel.numberOfLines = 0;
+    _titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
 
     _imageView = [[UIImageView alloc] init];
     _imageView.translatesAutoresizingMaskIntoConstraints = NO;
@@ -68,23 +80,83 @@
           constraintGreaterThanOrEqualToConstant:kImageLength],
     ]];
 
-    [self.contentView addSubview:_title];
+    [self.contentView addSubview:_titleLabel];
     [self.contentView addSubview:_imageView];
 
-    AddSameConstraintsToSides(
-        self.contentView, _title,
-        LayoutSides::kTop | LayoutSides::kBottom | LayoutSides::kTrailing);
+    AddSameConstraintsToSides(self.contentView, _titleLabel,
+                              LayoutSides::kTop | LayoutSides::kBottom);
     AddSameConstraintsToSides(
         self.contentView, _imageView,
         LayoutSides::kTop | LayoutSides::kBottom | LayoutSides::kLeading);
-    [_imageView.trailingAnchor constraintEqualToAnchor:_title.leadingAnchor]
+    [_imageView.trailingAnchor
+        constraintEqualToAnchor:_titleLabel.leadingAnchor]
+        .active = YES;
+    [_titleLabel.trailingAnchor
+        constraintEqualToAnchor:self.contentView.trailingAnchor
+                       constant:-kMargin]
         .active = YES;
   }
   return self;
 }
 
-- (void)setTitleText:(NSString*)title {
-  self.title.text = title;
++ (CGSize)sizeForWidth:(CGFloat)width title:(NSString*)title {
+  // This is not using a prototype cell and autolayout for performance reasons.
+  CGFloat nonTitleElementWidth = kImageLength + kMargin;
+  // The width should be enough to contain more than the image.
+  DCHECK(width > nonTitleElementWidth);
+
+  CGSize titleSize = CGSizeMake(width - nonTitleElementWidth,
+                                [UIScreen mainScreen].bounds.size.height);
+  NSDictionary* attributes = @{NSFontAttributeName : [self cellFont]};
+  CGRect rectForString =
+      [title boundingRectWithSize:titleSize
+                          options:NSStringDrawingUsesLineFragmentOrigin
+                       attributes:attributes
+                          context:nil];
+  CGSize size = rectForString.size;
+  size.height = MAX(size.height, kImageLength);
+  size.width += nonTitleElementWidth;
+  return size;
+}
+
+- (void)prepareForReuse {
+  [super prepareForReuse];
+  self.userInteractionEnabled = YES;
+}
+
+- (void)setUserInteractionEnabled:(BOOL)userInteractionEnabled {
+  [super setUserInteractionEnabled:userInteractionEnabled];
+  if (userInteractionEnabled) {
+    self.titleLabel.textColor = self.tintColor;
+  } else {
+    self.titleLabel.textColor = [[self class] disabledColor];
+  }
+}
+
+#pragma mark - Private
+
+// Returns the font used by this cell's label.
++ (UIFont*)cellFont {
+  static UIFont* font;
+  if (!font) {
+    PopupMenuToolsCell* cell =
+        [[PopupMenuToolsCell alloc] initWithStyle:UITableViewCellStyleDefault
+                                  reuseIdentifier:@"fakeID"];
+    font = cell.titleLabel.font;
+  }
+  return font;
+}
+
+// Returns the color of the disabled button's title.
++ (UIColor*)disabledColor {
+  static UIColor* systemTintColorForDisabled = nil;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    UIButton* button = [UIButton buttonWithType:UIButtonTypeSystem];
+    systemTintColorForDisabled =
+        [button titleColorForState:UIControlStateDisabled];
+  });
+  return systemTintColorForDisabled;
 }
 
 @end
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_coordinator.h b/ios/chrome/browser/ui/popup_menu/popup_menu_coordinator.h
index 60ee068..6d08936f 100644
--- a/ios/chrome/browser/ui/popup_menu/popup_menu_coordinator.h
+++ b/ios/chrome/browser/ui/popup_menu/popup_menu_coordinator.h
@@ -10,12 +10,18 @@
 #import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h"
 
 @class CommandDispatcher;
+class WebStateList;
 
 // Coordinator for the popup menu, handling the commands.
 @interface PopupMenuCoordinator : ChromeCoordinator
 
 // Dispatcher used by this coordinator to receive the PopupMenuCommands.
 @property(nonatomic, weak) CommandDispatcher* dispatcher;
+// The WebStateList this coordinator is handling.
+@property(nonatomic, assign) WebStateList* webStateList;
+
+// Returns whether this coordinator is showing a popup menu.
+- (BOOL)isShowingPopupMenu;
 
 @end
 
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_coordinator.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_coordinator.mm
index fc7cd84..986734d 100644
--- a/ios/chrome/browser/ui/popup_menu/popup_menu_coordinator.mm
+++ b/ios/chrome/browser/ui/popup_menu/popup_menu_coordinator.mm
@@ -20,23 +20,40 @@
 
 // Presenter for the popup menu, managing the animations.
 @property(nonatomic, strong) PopupMenuPresenter* presenter;
+// Mediator for the popup menu.
+@property(nonatomic, strong) PopupMenuMediator* mediator;
 
 @end
 
 @implementation PopupMenuCoordinator
 
 @synthesize dispatcher = _dispatcher;
+@synthesize mediator = _mediator;
 @synthesize presenter = _presenter;
+@synthesize webStateList = _webStateList;
 
 #pragma mark - ChromeCoordinator
 
 - (void)start {
   [self.dispatcher startDispatchingToTarget:self
                                 forProtocol:@protocol(PopupMenuCommands)];
+  NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter];
+  [defaultCenter addObserver:self
+                    selector:@selector(applicationDidEnterBackground:)
+                        name:UIApplicationDidEnterBackgroundNotification
+                      object:nil];
 }
 
 - (void)stop {
   [self.dispatcher stopDispatchingToTarget:self];
+  [self.mediator disconnect];
+  self.mediator = nil;
+}
+
+#pragma mark - Public
+
+- (BOOL)isShowingPopupMenu {
+  return self.presenter != nil;
 }
 
 #pragma mark - PopupMenuCommands
@@ -65,11 +82,12 @@
       [[PopupMenuTableViewController alloc] init];
   tableViewController.dispatcher =
       static_cast<id<ApplicationCommands, BrowserCommands>>(self.dispatcher);
+  tableViewController.baseViewController = self.baseViewController;
 
-  PopupMenuMediator* mediator =
+  self.mediator =
       [[PopupMenuMediator alloc] initWithType:PopupMenuTypeToolsMenu];
-  [mediator setUp];
-  [mediator configurePopupMenu:tableViewController];
+  self.mediator.webStateList = self.webStateList;
+  self.mediator.popupMenu = tableViewController;
 
   [self presentPopupForContent:tableViewController
                 fromNamedGuide:kToolsMenuGuide];
@@ -96,6 +114,14 @@
 - (void)dismissPopupMenu {
   [self.presenter dismissAnimated:YES];
   self.presenter = nil;
+  [self.mediator disconnect];
+  self.mediator = nil;
+}
+
+#pragma mark - Notification callback
+
+- (void)applicationDidEnterBackground:(NSNotification*)note {
+  [self dismissPopupMenu];
 }
 
 #pragma mark - Private
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.h b/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.h
index f68983a..a56e11b 100644
--- a/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.h
+++ b/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.h
@@ -8,6 +8,7 @@
 #import <UIKit/UIKit.h>
 
 @class PopupMenuTableViewController;
+class WebStateList;
 
 // Type of popup menus.
 typedef NS_ENUM(NSInteger, PopupMenuType) {
@@ -25,11 +26,14 @@
 - (instancetype)initWithType:(PopupMenuType)type NS_DESIGNATED_INITIALIZER;
 - (instancetype)init NS_UNAVAILABLE;
 
-// Sets this mediator up.
-- (void)setUp;
+// The WebStateList that this mediator listens for any changes on the current
+// WebState.
+@property(nonatomic, assign) WebStateList* webStateList;
+// The TableView to be configured with this mediator.
+@property(nonatomic, strong) PopupMenuTableViewController* popupMenu;
 
-// Configures the items of |popupMenu|.
-- (void)configurePopupMenu:(PopupMenuTableViewController*)popupMenu;
+// Disconnect the mediator.
+- (void)disconnect;
 
 @end
 
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm
index 885f123..23034e3 100644
--- a/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm
+++ b/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm
@@ -4,10 +4,21 @@
 
 #import "ios/chrome/browser/ui/popup_menu/popup_menu_mediator.h"
 
+#import "ios/chrome/browser/find_in_page/find_tab_helper.h"
 #import "ios/chrome/browser/ui/popup_menu/cells/popup_menu_item.h"
 #import "ios/chrome/browser/ui/popup_menu/cells/popup_menu_tools_item.h"
 #import "ios/chrome/browser/ui/popup_menu/popup_menu_table_view_controller.h"
+#import "ios/chrome/browser/web_state_list/web_state_list.h"
+#import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h"
 #include "ios/chrome/grit/ios_strings.h"
+#include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
+#import "ios/public/provider/chrome/browser/user_feedback/user_feedback_provider.h"
+#import "ios/web/public/navigation_item.h"
+#import "ios/web/public/navigation_manager.h"
+#include "ios/web/public/user_agent.h"
+#include "ios/web/public/web_client.h"
+#include "ios/web/public/web_state/web_state.h"
+#import "ios/web/public/web_state/web_state_observer_bridge.h"
 #include "ui/base/l10n/l10n_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -15,8 +26,7 @@
 #endif
 
 namespace {
-TableViewItem<PopupMenuItem>* CreateTableViewItem(int titleID,
-                                                  PopupMenuAction action) {
+PopupMenuToolsItem* CreateTableViewItem(int titleID, PopupMenuAction action) {
   PopupMenuToolsItem* item =
       [[PopupMenuToolsItem alloc] initWithType:kItemTypeEnumZero];
   item.title = l10n_util::GetNSString(titleID);
@@ -25,7 +35,10 @@
 }
 }
 
-@interface PopupMenuMediator ()
+@interface PopupMenuMediator () {
+  std::unique_ptr<web::WebStateObserverBridge> _webStateObserver;
+  std::unique_ptr<WebStateListObserverBridge> _webStateListObserver;
+}
 
 // Items to be displayed in the popup menu.
 @property(nonatomic, strong)
@@ -34,12 +47,32 @@
 // Type of this mediator.
 @property(nonatomic, assign) PopupMenuType type;
 
+// The current web state associated with the toolbar.
+@property(nonatomic, assign) web::WebState* webState;
+
+#pragma mark*** Specific Items ***
+
+@property(nonatomic, strong) PopupMenuToolsItem* reloadStop;
+@property(nonatomic, strong) PopupMenuToolsItem* readLater;
+@property(nonatomic, strong) PopupMenuToolsItem* findInPage;
+@property(nonatomic, strong) PopupMenuToolsItem* siteInformation;
+// Array containing all the nonnull items/
+@property(nonatomic, strong) NSArray<TableViewItem*>* specificItems;
+
 @end
 
 @implementation PopupMenuMediator
 
 @synthesize items = _items;
+@synthesize popupMenu = _popupMenu;
 @synthesize type = _type;
+@synthesize webState = _webState;
+@synthesize webStateList = _webStateList;
+@synthesize reloadStop = _reloadStop;
+@synthesize readLater = _readLater;
+@synthesize findInPage = _findInPage;
+@synthesize siteInformation = _siteInformation;
+@synthesize specificItems = _specificItems;
 
 #pragma mark - Public
 
@@ -47,40 +80,211 @@
   self = [super init];
   if (self) {
     _type = type;
+    _webStateObserver = std::make_unique<web::WebStateObserverBridge>(self);
+    _webStateListObserver = std::make_unique<WebStateListObserverBridge>(self);
   }
   return self;
 }
 
-- (void)setUp {
-  switch (self.type) {
-    case PopupMenuTypeToolsMenu:
-      [self createToolsMenuItem];
-      break;
-    case PopupMenuTypeNavigationForward:
-      break;
-    case PopupMenuTypeNavigationBackward:
-      break;
-    case PopupMenuTypeTabGrid:
-      break;
-    case PopupMenuTypeSearch:
-      break;
+- (void)disconnect {
+  if (_webStateList) {
+    _webStateList->RemoveObserver(_webStateListObserver.get());
+    _webStateListObserver.reset();
+    _webStateList = nullptr;
+  }
+
+  if (_webState) {
+    _webState->RemoveObserver(_webStateObserver.get());
+    _webStateObserver.reset();
+    _webState = nullptr;
   }
 }
 
-- (void)configurePopupMenu:(PopupMenuTableViewController*)popupMenu {
-  [popupMenu setPopupMenuItems:self.items];
+#pragma mark - CRWWebStateObserver
+
+- (void)webState:(web::WebState*)webState didLoadPageWithSuccess:(BOOL)success {
+  DCHECK_EQ(_webState, webState);
+  [self updatePopupMenu];
 }
 
-#pragma mark - Private
+- (void)webState:(web::WebState*)webState
+    didStartNavigation:(web::NavigationContext*)navigation {
+  DCHECK_EQ(_webState, webState);
+  [self updatePopupMenu];
+}
+
+- (void)webState:(web::WebState*)webState
+    didFinishNavigation:(web::NavigationContext*)navigation {
+  DCHECK_EQ(_webState, webState);
+  [self updatePopupMenu];
+}
+
+- (void)webState:(web::WebState*)webState
+    didPruneNavigationItemsWithCount:(size_t)pruned_item_count {
+  DCHECK_EQ(_webState, webState);
+  [self updatePopupMenu];
+}
+
+- (void)webStateDidStartLoading:(web::WebState*)webState {
+  DCHECK_EQ(_webState, webState);
+  [self updatePopupMenu];
+}
+
+- (void)webStateDidStopLoading:(web::WebState*)webState {
+  DCHECK_EQ(_webState, webState);
+  [self updatePopupMenu];
+}
+
+- (void)webState:(web::WebState*)webState
+    didChangeLoadingProgress:(double)progress {
+  DCHECK_EQ(_webState, webState);
+  [self updatePopupMenu];
+}
+
+- (void)webStateDidChangeVisibleSecurityState:(web::WebState*)webState {
+  DCHECK_EQ(_webState, webState);
+  [self updatePopupMenu];
+}
+
+- (void)webStateDestroyed:(web::WebState*)webState {
+  DCHECK_EQ(_webState, webState);
+  self.webState = nullptr;
+}
+
+#pragma mark - WebStateListObserver
+
+- (void)webStateList:(WebStateList*)webStateList
+    didChangeActiveWebState:(web::WebState*)newWebState
+                oldWebState:(web::WebState*)oldWebState
+                    atIndex:(int)atIndex
+                     reason:(int)reason {
+  DCHECK_EQ(_webStateList, webStateList);
+  self.webState = newWebState;
+}
+
+#pragma mark - Properties
+
+- (void)setWebState:(web::WebState*)webState {
+  if (_webState) {
+    _webState->RemoveObserver(_webStateObserver.get());
+  }
+
+  _webState = webState;
+
+  if (_webState) {
+    _webState->AddObserver(_webStateObserver.get());
+
+    if (self.popupMenu) {
+      [self updatePopupMenu];
+    }
+  }
+}
+
+- (void)setWebStateList:(WebStateList*)webStateList {
+  if (_webStateList) {
+    _webStateList->RemoveObserver(_webStateListObserver.get());
+  }
+
+  _webStateList = webStateList;
+  self.webState = nil;
+
+  if (_webStateList) {
+    self.webState = self.webStateList->GetActiveWebState();
+    _webStateList->AddObserver(_webStateListObserver.get());
+  }
+}
+
+- (void)setPopupMenu:(PopupMenuTableViewController*)popupMenu {
+  _popupMenu = popupMenu;
+  [_popupMenu setPopupMenuItems:self.items];
+  if (self.webState) {
+    [self updatePopupMenu];
+  }
+}
+
+- (NSArray<NSArray<TableViewItem<PopupMenuItem>*>*>*)items {
+  if (!_items) {
+    switch (self.type) {
+      case PopupMenuTypeToolsMenu:
+        [self createToolsMenuItem];
+        break;
+      case PopupMenuTypeNavigationForward:
+        break;
+      case PopupMenuTypeNavigationBackward:
+        break;
+      case PopupMenuTypeTabGrid:
+        break;
+      case PopupMenuTypeSearch:
+        break;
+    }
+    NSMutableArray* specificItems = [NSMutableArray array];
+    if (self.reloadStop)
+      [specificItems addObject:self.reloadStop];
+    if (self.readLater)
+      [specificItems addObject:self.readLater];
+    if (self.findInPage)
+      [specificItems addObject:self.findInPage];
+    if (self.siteInformation)
+      [specificItems addObject:self.siteInformation];
+    self.specificItems = specificItems;
+  }
+  return _items;
+}
+
+#pragma mark - Popup updates (Private)
+
+// Updates the popup menu to have its state in sync with the current page
+// status.
+- (void)updatePopupMenu {
+  // TODO(crbug.com/804773): update the items to take into account the state.
+  self.readLater.enabled = [self isWebURL];
+  self.findInPage.enabled = [self isFindInPageEnabled];
+  if ([self isPageLoading]) {
+    self.reloadStop.title = l10n_util::GetNSString(IDS_IOS_TOOLS_MENU_STOP);
+    self.reloadStop.actionIdentifier = PopupMenuActionStop;
+  } else {
+    self.reloadStop.title = l10n_util::GetNSString(IDS_IOS_TOOLS_MENU_RELOAD);
+    self.reloadStop.actionIdentifier = PopupMenuActionReload;
+  }
+
+  // Reload the items.
+  [self.popupMenu reconfigureCellsForItems:self.specificItems];
+}
+
+// Whether the actions associated with the share menu can be enabled.
+- (BOOL)isWebURL {
+  if (!self.webState)
+    return NO;
+  const GURL& URL = self.webState->GetLastCommittedURL();
+  return URL.is_valid() && !web::GetWebClient()->IsAppSpecificURL(URL);
+}
+
+// Whether find in page is enabled.
+- (BOOL)isFindInPageEnabled {
+  if (!self.webState)
+    return NO;
+  auto* helper = FindTabHelper::FromWebState(self.webState);
+  return (helper && helper->CurrentPageSupportsFindInPage() &&
+          !helper->IsFindUIActive());
+}
+
+// Whether the page is currently loading.
+- (BOOL)isPageLoading {
+  if (!self.webState)
+    return NO;
+  return self.webState->IsLoading();
+}
+
+#pragma mark - Item creation (Private)
 
 // Creates the menu items for the tools menu.
 - (void)createToolsMenuItem {
-  // Reload page action.
-  TableViewItem* reload =
+  // Reload or stop page action, created as reload.
+  self.reloadStop =
       CreateTableViewItem(IDS_IOS_TOOLS_MENU_RELOAD, PopupMenuActionReload);
 
-  NSArray* tabActions =
-      [@[ reload ] arrayByAddingObjectsFromArray:[self itemsForNewTab]];
+  NSArray* tabActions = [@[ self.reloadStop ]
+      arrayByAddingObjectsFromArray:[self itemsForNewTab]];
 
   NSArray* browserActions = [self actionItems];
 
@@ -102,34 +306,52 @@
 }
 
 - (NSArray<TableViewItem*>*)actionItems {
+  NSMutableArray* actionsArray = [NSMutableArray array];
   // Read Later.
-  TableViewItem* readLater = CreateTableViewItem(
-      IDS_IOS_CONTENT_CONTEXT_ADDTOREADINGLIST, PopupMenuActionReadLater);
+  self.readLater = CreateTableViewItem(IDS_IOS_CONTENT_CONTEXT_ADDTOREADINGLIST,
+                                       PopupMenuActionReadLater);
+  [actionsArray addObject:self.readLater];
 
-  // Request Desktop Site.
-  TableViewItem* requestDesktopSite = CreateTableViewItem(
-      IDS_IOS_TOOLS_MENU_REQUEST_DESKTOP_SITE, PopupMenuActionRequestDesktop);
+  // Find in Pad.
+  self.findInPage = CreateTableViewItem(IDS_IOS_TOOLS_MENU_FIND_IN_PAGE,
+                                        PopupMenuActionFindInPage);
+  [actionsArray addObject:self.findInPage];
 
-  // Request Mobile Site.
-  TableViewItem* requestMobileSite = CreateTableViewItem(
-      IDS_IOS_TOOLS_MENU_REQUEST_MOBILE_SITE, PopupMenuActionRequestMobile);
+  if ([self userAgentType] != web::UserAgentType::DESKTOP) {
+    // Request Desktop Site.
+    PopupMenuToolsItem* requestDesktopSite = CreateTableViewItem(
+        IDS_IOS_TOOLS_MENU_REQUEST_DESKTOP_SITE, PopupMenuActionRequestDesktop);
+    // Disable the action if the user agent is not mobile.
+    requestDesktopSite.enabled =
+        [self userAgentType] == web::UserAgentType::MOBILE;
+    [actionsArray addObject:requestDesktopSite];
+  } else {
+    // Request Mobile Site.
+    TableViewItem* requestMobileSite = CreateTableViewItem(
+        IDS_IOS_TOOLS_MENU_REQUEST_MOBILE_SITE, PopupMenuActionRequestMobile);
+    [actionsArray addObject:requestMobileSite];
+  }
 
   // Site Information.
-  TableViewItem* siteInformation = CreateTableViewItem(
+  self.siteInformation = CreateTableViewItem(
       IDS_IOS_TOOLS_MENU_SITE_INFORMATION, PopupMenuActionSiteInformation);
+  [actionsArray addObject:self.siteInformation];
 
   // Report an Issue.
-  TableViewItem* reportIssue = CreateTableViewItem(
-      IDS_IOS_OPTIONS_REPORT_AN_ISSUE, PopupMenuActionReportIssue);
+  if (ios::GetChromeBrowserProvider()
+          ->GetUserFeedbackProvider()
+          ->IsUserFeedbackEnabled()) {
+    TableViewItem* reportIssue = CreateTableViewItem(
+        IDS_IOS_OPTIONS_REPORT_AN_ISSUE, PopupMenuActionReportIssue);
+    [actionsArray addObject:reportIssue];
+  }
 
   // Help.
   TableViewItem* help =
       CreateTableViewItem(IDS_IOS_TOOLS_MENU_HELP_MOBILE, PopupMenuActionHelp);
+  [actionsArray addObject:help];
 
-  return @[
-    readLater, requestDesktopSite, requestMobileSite, siteInformation,
-    reportIssue, help
-  ];
+  return actionsArray;
 }
 
 - (NSArray<TableViewItem*>*)collectionItems {
@@ -156,4 +378,16 @@
   return @[ bookmarks, readingList, recentTabs, history, settings ];
 }
 
+// Returns the UserAgentType currently in use.
+- (web::UserAgentType)userAgentType {
+  if (!self.webState)
+    return web::UserAgentType::NONE;
+  web::NavigationItem* visibleItem =
+      self.webState->GetNavigationManager()->GetVisibleItem();
+  if (!visibleItem)
+    return web::UserAgentType::NONE;
+
+  return visibleItem->GetUserAgentType();
+}
+
 @end
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_mediator_unittest.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_mediator_unittest.mm
new file mode 100644
index 0000000..de217f7e
--- /dev/null
+++ b/ios/chrome/browser/ui/popup_menu/popup_menu_mediator_unittest.mm
@@ -0,0 +1,102 @@
+// Copyright 2018 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/popup_menu/popup_menu_mediator.h"
+#import "ios/chrome/browser/ui/popup_menu/popup_menu_table_view_controller.h"
+#import "ios/chrome/browser/ui/toolbar/test/toolbar_test_navigation_manager.h"
+#import "ios/chrome/browser/ui/toolbar/test/toolbar_test_web_state.h"
+#include "ios/chrome/browser/web_state_list/fake_web_state_list_delegate.h"
+#include "ios/chrome/browser/web_state_list/web_state_list.h"
+#import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h"
+#import "ios/chrome/browser/web_state_list/web_state_opener.h"
+#import "ios/web/public/test/fakes/fake_navigation_context.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_bundle.h"
+#import "ios/web/public/web_state/web_state_observer_bridge.h"
+#include "testing/platform_test.h"
+#import "third_party/ocmock/OCMock/OCMock.h"
+#include "third_party/ocmock/gtest_support.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+const int kNumberOfWebStates = 3;
+}  // namespace
+
+@interface TestPopupMenuMediator
+    : PopupMenuMediator<CRWWebStateObserver, WebStateListObserving>
+@end
+
+@implementation TestPopupMenuMediator
+@end
+
+class PopupMenuMediatorTest : public PlatformTest {
+ public:
+  PopupMenuMediatorTest() {
+    mediator_ = [[PopupMenuMediator alloc] initWithType:PopupMenuTypeToolsMenu];
+    popup_menu_ = OCMClassMock([PopupMenuTableViewController class]);
+    popup_menu_strict_ =
+        OCMStrictClassMock([PopupMenuTableViewController class]);
+    OCMExpect([popup_menu_strict_ setPopupMenuItems:[OCMArg any]]);
+    SetUpWebStateList();
+  }
+
+  // Explicitly disconnect the mediator so there won't be any WebStateList
+  // observers when web_state_list_ gets dealloc.
+  ~PopupMenuMediatorTest() override { [mediator_ disconnect]; }
+
+ protected:
+  void SetUpWebStateList() {
+    auto navigation_manager = std::make_unique<ToolbarTestNavigationManager>();
+    navigation_manager_ = navigation_manager.get();
+
+    std::unique_ptr<ToolbarTestWebState> test_web_state =
+        std::make_unique<ToolbarTestWebState>();
+    test_web_state->SetNavigationManager(std::move(navigation_manager));
+    test_web_state->SetLoading(true);
+    web_state_ = test_web_state.get();
+
+    web_state_list_ = std::make_unique<WebStateList>(&web_state_list_delegate_);
+    web_state_list_->InsertWebState(0, std::move(test_web_state),
+                                    WebStateList::INSERT_FORCE_INDEX,
+                                    WebStateOpener());
+    for (int i = 1; i < kNumberOfWebStates; i++) {
+      InsertNewWebState(i);
+    }
+  }
+
+  void InsertNewWebState(int index) {
+    auto web_state = std::make_unique<web::TestWebState>();
+    GURL url("http://test/" + std::to_string(index));
+    web_state->SetCurrentURL(url);
+    web_state_list_->InsertWebState(index, std::move(web_state),
+                                    WebStateList::INSERT_FORCE_INDEX,
+                                    WebStateOpener());
+  }
+
+  void SetUpActiveWebState() { web_state_list_->ActivateWebStateAt(0); }
+
+  PopupMenuMediator* mediator_;
+  ToolbarTestWebState* web_state_;
+  ToolbarTestNavigationManager* navigation_manager_;
+  std::unique_ptr<WebStateList> web_state_list_;
+  FakeWebStateListDelegate web_state_list_delegate_;
+  id popup_menu_;
+  // Mock refusing all calls except -setPopupMenuItems:.
+  id popup_menu_strict_;
+};
+
+// Test no setup is being done on the PopupMenu if there's no Webstate.
+TEST_F(PopupMenuMediatorTest, TestPopupMenuSetupWithNoWebstate) {
+  mediator_.popupMenu = popup_menu_strict_;
+}
+
+// Test no setup is being done on the LocationBar if there's no active Webstate.
+TEST_F(PopupMenuMediatorTest, TestPopupMenuSetupWithNoActiveWebstate) {
+  mediator_.webStateList = web_state_list_.get();
+  mediator_.popupMenu = popup_menu_strict_;
+}
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_presenter.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_presenter.mm
index 1d717d9..e4a1c0f 100644
--- a/ios/chrome/browser/ui/popup_menu/popup_menu_presenter.mm
+++ b/ios/chrome/browser/ui/popup_menu/popup_menu_presenter.mm
@@ -16,6 +16,7 @@
 
 namespace {
 const CGFloat kMinHeight = 200;
+const CGFloat kMinWidth = 200;
 const CGFloat kMaxWidth = 250;
 const CGFloat kMaxHeight = 400;
 const CGFloat kMinMargin = 16;
@@ -46,6 +47,41 @@
   [self.presentedViewController.view
       setContentCompressionResistancePriority:UILayoutPriorityDefaultHigh + 1
                                       forAxis:UILayoutConstraintAxisHorizontal];
+
+  // Set the frame of the table view to the maximum width to have the label
+  // resizing correctly.
+  CGRect frame = self.presentedViewController.view.frame;
+  frame.size.width = kMaxWidth - 2 * kMinMargin;
+  self.presentedViewController.view.frame = frame;
+  // It is necessary to do a first layout pass so the table view can size
+  // itself.
+  [self.presentedViewController.view setNeedsLayout];
+  [self.presentedViewController.view layoutIfNeeded];
+  CGSize fittingSize = [self.presentedViewController.view
+      sizeThatFits:CGSizeMake(kMaxWidth, kMaxHeight)];
+  // Use preferredSize if it is set.
+  CGSize preferredSize = self.presentedViewController.preferredContentSize;
+  CGFloat width = fittingSize.width;
+  if (!CGSizeEqualToSize(preferredSize, CGSizeZero)) {
+    width = preferredSize.width;
+  }
+
+  // Set the sizing constraints, in case the UIViewController is using a
+  // UIScrollView. The priority needs to be non-required to allow downsizing if
+  // needed, and more than UILayoutPriorityDefaultHigh to take precedence on
+  // compression resistance.
+  NSLayoutConstraint* widthConstraint =
+      [self.presentedViewController.view.widthAnchor
+          constraintEqualToConstant:width];
+  widthConstraint.priority = UILayoutPriorityDefaultHigh + 1;
+  widthConstraint.active = YES;
+
+  NSLayoutConstraint* heightConstraint =
+      [self.presentedViewController.view.heightAnchor
+          constraintEqualToConstant:fittingSize.height];
+  heightConstraint.priority = UILayoutPriorityDefaultHigh + 1;
+  heightConstraint.active = YES;
+
   [self.popupViewController addContent:self.presentedViewController];
 
   [self.baseViewController addChildViewController:self.popupViewController];
@@ -63,8 +99,6 @@
 - (void)presentAnimated:(BOOL)animated {
   // TODO(crbug.com/804774): Add animation based on |guideName|.
   self.popupViewController.contentContainer.alpha = 1;
-  self.popupViewController.contentContainer.frame =
-      CGRectMake(170, 300, 230, 400);
 }
 
 - (void)dismissAnimated:(BOOL)animated {
@@ -113,10 +147,12 @@
                                  constant:-kMinMargin],
     [container.heightAnchor constraintLessThanOrEqualToConstant:kMaxHeight],
     [container.widthAnchor constraintLessThanOrEqualToConstant:kMaxWidth],
+    [container.widthAnchor constraintGreaterThanOrEqualToConstant:kMinWidth],
     [container.bottomAnchor
-        constraintLessThanOrEqualToAnchor:safeArea.bottomAnchor],
-    [container.topAnchor
-        constraintGreaterThanOrEqualToAnchor:safeArea.topAnchor],
+        constraintLessThanOrEqualToAnchor:safeArea.bottomAnchor
+                                 constant:-kMinMargin],
+    [container.topAnchor constraintGreaterThanOrEqualToAnchor:safeArea.topAnchor
+                                                     constant:kMinMargin],
   ]];
   NSLayoutConstraint* leading = [container.leadingAnchor
       constraintEqualToAnchor:namedGuide.leadingAnchor];
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_table_view_controller.h b/ios/chrome/browser/ui/popup_menu/popup_menu_table_view_controller.h
index cfd541cb..33cba558 100644
--- a/ios/chrome/browser/ui/popup_menu/popup_menu_table_view_controller.h
+++ b/ios/chrome/browser/ui/popup_menu/popup_menu_table_view_controller.h
@@ -21,6 +21,10 @@
 // Dispatcher.
 @property(nonatomic, weak) id<ApplicationCommands, BrowserCommands> dispatcher;
 
+// Presenting ViewController for the ViewController needing to be presented as
+// result of an interaction with the popup.
+@property(nonatomic, weak) UIViewController* baseViewController;
+
 // Sets the |items| to be displayed by this Table View. Removes all the
 // currently presented items.
 - (void)setPopupMenuItems:
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_table_view_controller.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_table_view_controller.mm
index 10c5b0d5..49b5abd0 100644
--- a/ios/chrome/browser/ui/popup_menu/popup_menu_table_view_controller.mm
+++ b/ios/chrome/browser/ui/popup_menu/popup_menu_table_view_controller.mm
@@ -17,12 +17,10 @@
 
 using base::UserMetricsAction;
 
-@interface PopupMenuTableViewController ()
-@end
-
 @implementation PopupMenuTableViewController
 
 @dynamic tableViewModel;
+@synthesize baseViewController = _baseViewController;
 @synthesize dispatcher = _dispatcher;
 
 #pragma mark - UIViewController
@@ -32,6 +30,7 @@
   self.tableView.rowHeight = UITableViewAutomaticDimension;
   self.tableView.sectionHeaderHeight = 0;
   self.tableView.sectionFooterHeight = 0;
+  self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
 }
 
 - (void)setPopupMenuItems:
@@ -48,6 +47,23 @@
   [self.tableView reloadData];
 }
 
+- (CGSize)preferredContentSize {
+  CGFloat width = 0;
+  CGFloat height = 0;
+  for (NSInteger section = 0; section < [self.tableViewModel numberOfSections];
+       section++) {
+    NSInteger sectionIdentifier =
+        [self.tableViewModel sectionIdentifierForSection:section];
+    for (TableViewItem<PopupMenuItem>* item in
+         [self.tableViewModel itemsInSectionWithIdentifier:sectionIdentifier]) {
+      CGSize sizeForCell = [item cellSizeForWidth:self.view.bounds.size.width];
+      width = MAX(width, ceil(sizeForCell.width));
+      height += ceil(sizeForCell.height);
+    }
+  }
+  return CGSizeMake(width, height);
+}
+
 #pragma mark - UITableViewDelegate
 
 - (void)tableView:(UITableView*)tableView
@@ -89,6 +105,11 @@
     case PopupMenuActionReadLater:
       base::RecordAction(UserMetricsAction("MobileMenuReadLater"));
       // TODO(crbug.com/822703): Add action.
+      [self showNotImplementedAlert];
+      break;
+    case PopupMenuActionFindInPage:
+      base::RecordAction(UserMetricsAction("MobileMenuFindInPage"));
+      [self.dispatcher showFindInPage];
       break;
     case PopupMenuActionRequestDesktop:
       base::RecordAction(UserMetricsAction("MobileMenuRequestDesktopSite"));
@@ -101,10 +122,12 @@
     case PopupMenuActionSiteInformation:
       base::RecordAction(UserMetricsAction("MobileMenuSiteInformation"));
       // TODO(crbug.com/822703): Add action.
+      [self showNotImplementedAlert];
       break;
     case PopupMenuActionReportIssue:
       base::RecordAction(UserMetricsAction("MobileMenuReportAnIssue"));
-      // TODO(crbug.com/822703): Add action.
+      [self.dispatcher
+          showReportAnIssueFromViewController:self.baseViewController];
       break;
     case PopupMenuActionHelp:
       base::RecordAction(UserMetricsAction("MobileMenuHelp"));
@@ -128,7 +151,7 @@
       break;
     case PopupMenuActionSettings:
       base::RecordAction(UserMetricsAction("MobileMenuSettings"));
-      // TODO(crbug.com/822703): Add action.
+      [self.dispatcher showSettingsFromViewController:self.baseViewController];
       break;
   }
 
@@ -136,4 +159,23 @@
   [self.dispatcher dismissPopupMenu];
 }
 
+#pragma mark - Private
+
+// TODO(crbug.com/822703): Remove this.
+- (void)showNotImplementedAlert {
+  UIAlertController* alertController =
+      [UIAlertController alertControllerWithTitle:@"Not implemented yet."
+                                          message:nil
+                                   preferredStyle:UIAlertControllerStyleAlert];
+  UIAlertAction* alertAction =
+      [UIAlertAction actionWithTitle:@"OK"
+                               style:UIAlertActionStyleCancel
+                             handler:nil];
+
+  [alertController addAction:alertAction];
+  [self.baseViewController presentViewController:alertController
+                                        animated:YES
+                                      completion:nil];
+}
+
 @end
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.mm
index 3cea4bb..fd0d8bf 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.mm
@@ -90,6 +90,7 @@
 }
 
 - (void)setOtrTabModel:(TabModel*)otrModel {
+  DCHECK(self.incognitoMediator);
   self.incognitoMediator.tabModel = otrModel;
 }
 
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
index 1057c34..2a4f9d31 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
@@ -12,6 +12,7 @@
 #import "ios/chrome/browser/ui/main/bvc_container_view_controller.h"
 #import "ios/chrome/browser/ui/tab_grid/tab_grid_adaptor.h"
 #import "ios/chrome/browser/ui/tab_grid/tab_grid_mediator.h"
+#import "ios/chrome/browser/ui/tab_grid/tab_grid_paging.h"
 #import "ios/chrome/browser/ui/tab_grid/tab_grid_transition_handler.h"
 #import "ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.h"
 
@@ -72,6 +73,30 @@
   return self.adaptor;
 }
 
+- (TabModel*)regularTabModel {
+  // Ensure tab model actually used by the mediator is returned, as it may have
+  // been updated.
+  return self.regularTabsMediator ? self.regularTabsMediator.tabModel
+                                  : _regularTabModel;
+}
+
+- (void)setRegularTabModel:(TabModel*)regularTabModel {
+  self.regularTabsMediator.tabModel = regularTabModel;
+  _regularTabModel = regularTabModel;
+}
+
+- (TabModel*)incognitoTabModel {
+  // Ensure tab model actually used by the mediator is returned, as it may have
+  // been updated.
+  return self.incognitoTabsMediator ? self.incognitoTabsMediator.tabModel
+                                    : _incognitoTabModel;
+}
+
+- (void)setIncognitoTabModel:(TabModel*)incognitoTabModel {
+  self.incognitoTabsMediator.tabModel = incognitoTabModel;
+  _incognitoTabModel = incognitoTabModel;
+}
+
 #pragma mark - MainCoordinator properties
 
 - (id<ViewControllerSwapping>)viewControllerSwapper {
@@ -99,10 +124,11 @@
 
   self.regularTabsMediator = [[TabGridMediator alloc]
       initWithConsumer:mainViewController.regularTabsConsumer];
-  self.regularTabsMediator.tabModel = self.regularTabModel;
+  self.regularTabsMediator.tabModel = _regularTabModel;
   self.incognitoTabsMediator = [[TabGridMediator alloc]
       initWithConsumer:mainViewController.incognitoTabsConsumer];
-  self.incognitoTabsMediator.tabModel = self.incognitoTabModel;
+  self.incognitoTabsMediator.tabModel = _incognitoTabModel;
+  self.adaptor.incognitoMediator = self.incognitoTabsMediator;
   mainViewController.regularTabsDelegate = self.regularTabsMediator;
   mainViewController.incognitoTabsDelegate = self.incognitoTabsMediator;
   mainViewController.regularTabsImageDataSource = self.regularTabsMediator;
@@ -189,14 +215,21 @@
 
 #pragma mark - TabPresentationDelegate
 
-- (void)showActiveTab {
-  // Figure out which tab model is the active one. If the view controller is
-  // showing the incognito panel, and there's more than one incognito tab, then
-  // the incognito model is active. Otherwise the regular model is active.
-  TabModel* activeTabModel = self.regularTabModel;
-  if (self.mainViewController.currentPage == TabGridPageIncognitoTabs &&
-      self.incognitoTabModel.count > 0) {
-    activeTabModel = self.incognitoTabModel;
+- (void)showActiveTabInPage:(TabGridPage)page {
+  DCHECK(self.regularTabModel && self.incognitoTabModel);
+  TabModel* activeTabModel;
+  switch (page) {
+    case TabGridPageIncognitoTabs:
+      DCHECK_GT(self.incognitoTabModel.count, 0U);
+      activeTabModel = self.incognitoTabModel;
+      break;
+    case TabGridPageRegularTabs:
+      DCHECK_GT(self.regularTabModel.count, 0U);
+      activeTabModel = self.regularTabModel;
+      break;
+    case TabGridPageRemoteTabs:
+      NOTREACHED() << "It is invalid to have an active tab in remote tabs.";
+      break;
   }
   // Trigger the transition through the TabSwitcher delegate. This will in turn
   // call back into this coordinator via the ViewControllerSwapping protocol.
@@ -207,6 +240,7 @@
 #pragma mark - BrowserCommands
 
 - (void)openNewTab:(OpenNewTabCommand*)command {
+  DCHECK(self.regularTabModel && self.incognitoTabModel);
   TabModel* activeTabModel =
       command.incognito ? self.incognitoTabModel : self.regularTabModel;
   // TODO(crbug.com/804587) : It is better to use the mediator to insert a
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_transition_handler.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_transition_handler.mm
index b1b15d9..a523cc52 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_transition_handler.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_transition_handler.mm
@@ -26,7 +26,8 @@
   id<UIViewControllerAnimatedTransitioning> animator;
   if (self.provider.selectedCellVisible) {
     // This will be a GridToVisibleTabAnimator eventually.
-    animator = [[GridToHiddenTabAnimator alloc] init];
+    animator =
+        [[GridToVisibleTabAnimator alloc] initWithStateProvider:self.provider];
   } else {
     animator = [[GridToHiddenTabAnimator alloc] init];
   }
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.h b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.h
index f018f58..8208faa 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.h
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.h
@@ -17,8 +17,8 @@
 // Delegate protocol for an object that can handle presenting ("opening") tabs
 // from the tab grid.
 @protocol TabPresentationDelegate<NSObject>
-// Show the active tab, presented on top of the tab grid.
-- (void)showActiveTab;
+// Show the active tab in |page|, presented on top of the tab grid.
+- (void)showActiveTabInPage:(TabGridPage)page;
 @end
 
 // View controller representing a tab switcher. The tab switcher has an
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
index 03c32fde..fbcbfc4 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
@@ -51,7 +51,9 @@
 @property(nonatomic, weak) TabGridNewTabButton* newTabButton;
 @property(nonatomic, weak) TabGridNewTabButton* floatingButton;
 @property(nonatomic, assign) TabGridConfiguration configuration;
-
+// The page that was shown when entering the tab grid from the tab view.
+// This is used to decide whether the Done button is enabled.
+@property(nonatomic, assign) TabGridPage originalPage;
 @end
 
 @implementation TabGridViewController
@@ -76,6 +78,7 @@
 @synthesize newTabButton = _newTabButton;
 @synthesize floatingButton = _floatingButton;
 @synthesize configuration = _configuration;
+@synthesize originalPage = _originalPage;
 
 - (instancetype)init {
   if (self = [super init]) {
@@ -103,6 +106,7 @@
   // Call the current page setter to sync the scroll view offset to the current
   // page value.
   self.currentPage = _currentPage;
+  self.originalPage = _currentPage;
   [self.topToolbar.pageControl setSelectedPage:self.currentPage animated:YES];
   [self configureViewControllerForCurrentSizeClassesAndPage];
   if (animated && self.transitionCoordinator) {
@@ -111,6 +115,13 @@
   [super viewWillAppear:animated];
 }
 
+- (void)viewWillDisappear:(BOOL)animated {
+  if (animated && self.transitionCoordinator) {
+    [self animateToolbarsForDisappearance];
+  }
+  [super viewWillDisappear:animated];
+}
+
 - (void)viewWillLayoutSubviews {
   [super viewWillLayoutSubviews];
   // The content inset of the tab grids must be modified so that the toolbars
@@ -135,6 +146,7 @@
 - (void)viewWillTransitionToSize:(CGSize)size
        withTransitionCoordinator:
            (id<UIViewControllerTransitionCoordinator>)coordinator {
+  [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
   auto animate = ^(id<UIViewControllerTransitionCoordinatorContext> context) {
     // Call the current page setter to sync the scroll view offset to the
     // current page value.
@@ -164,7 +176,7 @@
     NSUInteger page = lround(fractionalPage);
     if (page != self.currentPage) {
       _currentPage = static_cast<TabGridPage>(page);
-      [self configureButtonsForCurrentPage];
+      [self configureButtonsForOriginalAndCurrentPage];
     }
   }
 }
@@ -551,22 +563,32 @@
   [self.newTabButton addTarget:self
                         action:@selector(newTabButtonTapped:)
               forControlEvents:UIControlEventTouchUpInside];
-  [self configureButtonsForCurrentPage];
+  [self configureButtonsForOriginalAndCurrentPage];
 }
 
-- (void)configureButtonsForCurrentPage {
+- (void)configureButtonsForOriginalAndCurrentPage {
   self.newTabButton.page = self.currentPage;
-  switch (self.currentPage) {
+  switch (self.originalPage) {
     case TabGridPageIncognitoTabs:
       self.doneButton.enabled = !self.incognitoTabsViewController.isGridEmpty;
-      self.closeAllButton.enabled = self.doneButton.enabled;
       break;
     case TabGridPageRegularTabs:
       self.doneButton.enabled = !self.regularTabsViewController.isGridEmpty;
-      self.closeAllButton.enabled = self.doneButton.enabled;
       break;
     case TabGridPageRemoteTabs:
-      self.doneButton.enabled = YES;
+      NOTREACHED() << "It is not possible to have entered tab grid directly "
+                      "into remote tabs.";
+      break;
+  }
+  switch (self.currentPage) {
+    case TabGridPageIncognitoTabs:
+      self.closeAllButton.enabled =
+          !self.incognitoTabsViewController.isGridEmpty;
+      break;
+    case TabGridPageRegularTabs:
+      self.closeAllButton.enabled = !self.regularTabsViewController.isGridEmpty;
+      break;
+    case TabGridPageRemoteTabs:
       self.closeAllButton.enabled = NO;
       break;
   }
@@ -611,6 +633,45 @@
                                               completion:cleanup];
 }
 
+// Translates the toolbar views offscreen using the transition coordinator.
+- (void)animateToolbarsForDisappearance {
+  DCHECK(self.transitionCoordinator);
+  // TODO(crbug.com/820410): Tune the timing of these animations.
+
+  // Capture the current toolbar transforms.
+  CGAffineTransform topToolbarBaseTransform = self.topToolbar.transform;
+  CGAffineTransform bottomToolbarBaseTransform = self.bottomToolbar.transform;
+  // Translate the top toolbar up offscreen by shifting it up by its height.
+  CGAffineTransform topToolbarOffsetTransform = CGAffineTransformTranslate(
+      self.topToolbar.transform, /*tx=*/0,
+      /*ty=*/-(self.topToolbar.bounds.size.height * 0.5));
+  // Translate the bottom toolbar down offscreen by shifting it down by its
+  // height.
+  CGAffineTransform bottomToolbarOffsetTransform = CGAffineTransformTranslate(
+      self.bottomToolbar.transform, /*tx=*/0,
+      /*ty=*/(self.topToolbar.bounds.size.height * 0.5));
+
+  // Block that animates the toolbar transforms, suitable for using with the
+  // transition coordinator.
+  auto animation = ^(id<UIViewControllerTransitionCoordinatorContext> context) {
+    self.topToolbar.transform = topToolbarOffsetTransform;
+    self.bottomToolbar.transform = bottomToolbarOffsetTransform;
+  };
+
+  // Hide the scroll view (and thus the tab grids) until the transition
+  // completes.
+  self.scrollView.hidden = YES;
+  auto cleanup = ^(id<UIViewControllerTransitionCoordinatorContext> context) {
+    self.scrollView.hidden = NO;
+    self.topToolbar.transform = topToolbarBaseTransform;
+    self.bottomToolbar.transform = bottomToolbarBaseTransform;
+  };
+
+  // Animate the toolbars into place alongside the current transition.
+  [self.transitionCoordinator animateAlongsideTransition:animation
+                                              completion:cleanup];
+}
+
 #pragma mark - GridViewControllerDelegate
 
 - (void)gridViewController:(GridViewController*)gridViewController
@@ -620,7 +681,7 @@
   } else if (gridViewController == self.incognitoTabsViewController) {
     [self.incognitoTabsDelegate selectItemAtIndex:index];
   }
-  [self.tabPresentationDelegate showActiveTab];
+  [self.tabPresentationDelegate showActiveTabInPage:self.currentPage];
 }
 
 - (void)gridViewController:(GridViewController*)gridViewController
@@ -634,7 +695,7 @@
 
 - (void)gridViewController:(GridViewController*)gridViewController
         didChangeItemCount:(NSUInteger)count {
-  [self configureButtonsForCurrentPage];
+  [self configureButtonsForOriginalAndCurrentPage];
   if (gridViewController == self.regularTabsViewController) {
     self.topToolbar.pageControl.regularTabCount = count;
   }
@@ -643,7 +704,7 @@
 #pragma mark - Control actions
 
 - (void)doneButtonTapped:(id)sender {
-  [self.tabPresentationDelegate showActiveTab];
+  [self.tabPresentationDelegate showActiveTabInPage:self.originalPage];
 }
 
 - (void)closeAllButtonTapped:(id)sender {
@@ -655,7 +716,7 @@
       [self.regularTabsDelegate closeAllItems];
       break;
     case TabGridPageRemoteTabs:
-      // No-op. It is invalid to call close all tabs on remote tabs.
+      NOTREACHED() << "It is invalid to call close all tabs on remote tabs.";
       break;
   }
 }
@@ -664,16 +725,15 @@
   switch (self.currentPage) {
     case TabGridPageIncognitoTabs:
       [self.incognitoTabsDelegate addNewItem];
-      [self.tabPresentationDelegate showActiveTab];
       break;
     case TabGridPageRegularTabs:
       [self.regularTabsDelegate addNewItem];
-      [self.tabPresentationDelegate showActiveTab];
       break;
     case TabGridPageRemoteTabs:
-      // No-op. It is invalid to call insert new tab on remote tabs.
+      NOTREACHED() << "It is invalid to call insert new tab on remote tabs.";
       break;
   }
+  [self.tabPresentationDelegate showActiveTabInPage:self.currentPage];
 }
 
 - (void)pageControlChanged:(id)sender {
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/grid_to_visible_tab_animator.h b/ios/chrome/browser/ui/tab_grid/transitions/grid_to_visible_tab_animator.h
index 76b285a..ad3cbe9 100644
--- a/ios/chrome/browser/ui/tab_grid/transitions/grid_to_visible_tab_animator.h
+++ b/ios/chrome/browser/ui/tab_grid/transitions/grid_to_visible_tab_animator.h
@@ -7,9 +7,18 @@
 
 #import <UIKit/UIKit.h>
 
+@protocol GridTransitionStateProviding;
+
+// Animator object for transitioning from a collection view of square-ish items
+// (the "grid") into a fullscreen view controller (the "tab").
 @interface GridToVisibleTabAnimator
     : NSObject<UIViewControllerAnimatedTransitioning>
 
+// Initialize an animator object with |stateProvider| to provide state
+// information for the transition.
+- (instancetype)initWithStateProvider:
+    (id<GridTransitionStateProviding>)stateProvider;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_TAB_GRID_TRANSITIONS_GRID_TO_VISIBLE_TAB_ANIMATOR_H_
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/grid_to_visible_tab_animator.mm b/ios/chrome/browser/ui/tab_grid/transitions/grid_to_visible_tab_animator.mm
index bf21f48..e566b8f 100644
--- a/ios/chrome/browser/ui/tab_grid/transitions/grid_to_visible_tab_animator.mm
+++ b/ios/chrome/browser/ui/tab_grid/transitions/grid_to_visible_tab_animator.mm
@@ -4,19 +4,110 @@
 
 #import "ios/chrome/browser/ui/tab_grid/transitions/grid_to_visible_tab_animator.h"
 
+#import "ios/chrome/browser/ui/tab_grid/transitions/grid_transition_animation.h"
+#import "ios/chrome/browser/ui/tab_grid/transitions/grid_transition_state_providing.h"
+
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
 
+@interface GridToVisibleTabAnimator ()<GridTransitionAnimationDelegate>
+@property(nonatomic, weak) id<GridTransitionStateProviding> stateProvider;
+// Animation object for this transition.
+@property(nonatomic, strong) GridTransitionAnimation* animation;
+// Transition context passed into this object when the animation is started.
+@property(nonatomic, weak) id<UIViewControllerContextTransitioning>
+    transitionContext;
+@end
+
 @implementation GridToVisibleTabAnimator
+@synthesize stateProvider = _stateProvider;
+@synthesize animation = _animation;
+@synthesize transitionContext = _transitionContext;
+
+- (instancetype)initWithStateProvider:
+    (id<GridTransitionStateProviding>)stateProvider {
+  if ((self = [super init])) {
+    _stateProvider = stateProvider;
+  }
+  return self;
+}
 
 - (NSTimeInterval)transitionDuration:
     (id<UIViewControllerContextTransitioning>)transitionContext {
-  return 0.25;
+  return 0.4;
 }
 
 - (void)animateTransition:
     (id<UIViewControllerContextTransitioning>)transitionContext {
+  // Keep a pointer to the transition context for use in animation delegate
+  // callbacks.
+  self.transitionContext = transitionContext;
+
+  // Get views and view controllers for this transition.
+  UIView* containerView = [transitionContext containerView];
+  UIViewController* presentedViewController = [transitionContext
+      viewControllerForKey:UITransitionContextToViewControllerKey];
+  UIView* presentedView =
+      [transitionContext viewForKey:UITransitionContextToViewKey];
+
+  // Add the presented view to the container. This isn't just for the
+  // transition; this is how the presented view controller's view is added to
+  // the view hierarchy.
+  [containerView addSubview:presentedView];
+  presentedView.frame =
+      [transitionContext finalFrameForViewController:presentedViewController];
+  presentedView.alpha = 0.0;
+
+  // Get the layout of the grid for the transition.
+  GridTransitionLayout* layout =
+      [self.stateProvider layoutForTransitionContext:transitionContext];
+
+  // Create the animation view and insert it.
+  self.animation = [[GridTransitionAnimation alloc]
+      initWithLayout:layout
+            delegate:self
+           direction:GridAnimationDirectionExpanding];
+
+  //   Ask the state provider for the views to use when inserting the animation.
+  UIView* proxyContainer =
+      [self.stateProvider proxyContainerForTransitionContext:transitionContext];
+  UIView* viewBehindProxies =
+      [self.stateProvider proxyPositionForTransitionContext:transitionContext];
+
+  [proxyContainer insertSubview:self.animation aboveSubview:viewBehindProxies];
+
+  NSTimeInterval duration = [self transitionDuration:transitionContext];
+
+  // Fade in the presented view.
+  [UIView animateWithDuration:duration * 0.3
+                        delay:duration * 0.7
+                      options:UIViewAnimationOptionCurveEaseOut
+                   animations:^{
+                     presentedView.alpha = 1.0;
+                   }
+                   completion:nil];
+
+  // Run the main animation.
+  [self.animation animateWithDuration:duration];
+}
+
+- (void)gridTransitionAnimationDidFinish:(BOOL)finished {
+  // Clean up the animation
+  [self.animation removeFromSuperview];
+  // If the transition was cancelled, remove the presented view.
+  // If not, remove the grid view.
+  UIView* gridView =
+      [self.transitionContext viewForKey:UITransitionContextFromViewKey];
+  UIView* presentedView =
+      [self.transitionContext viewForKey:UITransitionContextToViewKey];
+  if (self.transitionContext.transitionWasCancelled) {
+    [presentedView removeFromSuperview];
+  } else {
+    [gridView removeFromSuperview];
+  }
+  // Mark the transition as completed.
+  [self.transitionContext completeTransition:YES];
 }
 
 @end
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_animation.h b/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_animation.h
index 04d9148d..501f683 100644
--- a/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_animation.h
+++ b/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_animation.h
@@ -9,6 +9,14 @@
 
 @class GridTransitionLayout;
 
+// The directions the animation can take.
+typedef NS_ENUM(NSUInteger, GridAnimationDirection) {
+  // Moving from the expanded grid down into the regular grid.
+  GridAnimationDirectionContracting = 0,
+  // Moving from the regular grid out to the expanded grid.
+  GridAnimationDirectionExpanding = 1,
+};
+
 // Delegate for this animation, to be informed about animation events.
 @protocol GridTransitionAnimationDelegate
 // Tell the delegate thet the animation completed. If |finished| is YES, then
@@ -26,8 +34,12 @@
 // Designated initializer. |layout| is a GridTransitionLayout object defining
 // the layout the animation should animate to. |delegate| is an object that will
 // be informed about events in this object's animation.
+// If |startsExpanded| is YES, the animation will start with the grid cells in
+// the expanded position and zoom down to the regular grid position. Otherwise
+// they will start in the grid position and zoom out to the expanded positions.
 - (instancetype)initWithLayout:(GridTransitionLayout*)layout
                       delegate:(id<GridTransitionAnimationDelegate>)delegate
+                     direction:(GridAnimationDirection)direction
     NS_DESIGNATED_INITIALIZER;
 
 - (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE;
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_animation.mm b/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_animation.mm
index 82801c4..8116b57 100644
--- a/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_animation.mm
+++ b/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_animation.mm
@@ -11,27 +11,40 @@
 #endif
 
 @interface GridTransitionAnimation ()
+// The layout of the grid for this animation.
 @property(nonatomic, strong) GridTransitionLayout* layout;
+// The delegate for this animation.
 @property(nonatomic, weak) id<GridTransitionAnimationDelegate> delegate;
+// The direction this animation is in.
+@property(nonatomic, readonly, assign) GridAnimationDirection direction;
+// The x and y scales of the enlarged grid relative to the selected cell in the
+// regular grid.
 @property(nonatomic, assign) CGFloat xScale;
 @property(nonatomic, assign) CGFloat yScale;
+// Convenience properties for getting the size and center of the selected cell
+// in the grid.
 @property(nonatomic, readonly) CGSize selectedSize;
 @property(nonatomic, readonly) CGPoint selectedCenter;
+// Corner radius that the selected cell will have when it is animated into the
+// regulat grid.
 @property(nonatomic, assign) CGFloat finalSelectedCellCornerRadius;
 @end
 
 @implementation GridTransitionAnimation
-@synthesize delegate = _delegate;
 @synthesize layout = _layout;
+@synthesize delegate = _delegate;
+@synthesize direction = _direction;
 @synthesize xScale = _xScale;
 @synthesize yScale = _yScale;
 @synthesize finalSelectedCellCornerRadius = _finalSelectedCellCornerRadius;
 
 - (instancetype)initWithLayout:(GridTransitionLayout*)layout
-                      delegate:(id<GridTransitionAnimationDelegate>)delegate {
+                      delegate:(id<GridTransitionAnimationDelegate>)delegate
+                     direction:(GridAnimationDirection)direction {
   if (self = [super initWithFrame:CGRectZero]) {
     _layout = layout;
     _delegate = delegate;
+    _direction = direction;
     _finalSelectedCellCornerRadius =
         _layout.selectedItem.cell.contentView.layer.cornerRadius;
   }
@@ -50,8 +63,17 @@
 - (void)didMoveToSuperview {
   // Positioning the animating items depends on converting points to this
   // view's coordinate system, so wait until it's in a view hierarchy.
-  [self positionSelectedItemInExpandedGrid];
-  [self positionUnselectedItemsInExpandedGrid];
+  switch (self.direction) {
+    case GridAnimationDirectionContracting:
+      [self positionSelectedItemInExpandedGrid];
+      [self positionUnselectedItemsInExpandedGrid];
+      break;
+    case GridAnimationDirectionExpanding:
+      [self positionSelectedItemInRegularGrid];
+      self.layout.selectedItem.cell.selected = YES;
+      [self positionUnselectedItemsInRegularGrid];
+      break;
+  }
 }
 
 #pragma mark - Private Properties
@@ -67,6 +89,19 @@
 #pragma mark - Public methods
 
 - (void)animateWithDuration:(NSTimeInterval)duration {
+  switch (self.direction) {
+    case GridAnimationDirectionContracting:
+      [self animateToRegularGridWithDuration:duration];
+      break;
+    case GridAnimationDirectionExpanding:
+      [self animateToExpandedGridWithDuration:duration];
+      break;
+  }
+}
+
+#pragma mark - Private methods
+
+- (void)animateToRegularGridWithDuration:(NSTimeInterval)duration {
   // The transition is structured as two or three separate animations. They are
   // timed based on |staggeredDuration|, which is a configurable fraction
   // of the overall animation duration.
@@ -149,7 +184,88 @@
   }
 }
 
-#pragma mark - Private methods
+- (void)animateToExpandedGridWithDuration:(NSTimeInterval)duration {
+  // The transition is structured as two or three separate animations. They are
+  // timed based on |staggeredDuration|, which is a configurable fraction
+  // of the overall animation duration.
+  CGFloat staggeredDuration = duration * 0.9;
+
+  // If there's only one cell, the animation has two parts:
+  //   (A) Fading out the selected cell highlight indicator.
+  //   (B) Zooming the selected cell out into position.
+  // These parts are timed like this:
+  //
+  //  {0%}----[A]----|#|
+  //  {0%}------------------[B]--------------------{100%}
+  //
+  //  (|#| is 1-<staggeredDuration>%).
+  // Animation B will call the completion handler in this case.
+
+  // If there's more than once cell, the animation has three parts:
+  //   (A) Fading out the selected cell highlight indicator.
+  //   (B) Zooming the selected cell into position.
+  //   (C) Zooming the unselected cells into position.
+  // The timing is as follows:
+  //
+  //  {0%}----[A]----|#|
+  //  {0%}---------- [C]-------------|*|
+  //                 |#|-------------[B]-----------{100%}
+  //  (|*| is <staggeredDuration>%).
+  //  (|#| is 1-<staggeredDuration>%).
+  // Animation C will call the completion handler in this case.
+
+  // TODO(crbug.com/820410): Tune the timing, relative pacing, and curves of
+  // these animations.
+
+  UICollectionViewCell* selectedCell = self.layout.selectedItem.cell;
+
+  // Run animation (A) for |duration - staggeredDuration|.
+  [UIView animateWithDuration:0
+                        delay:duration - staggeredDuration
+                      options:UIViewAnimationOptionCurveEaseOut
+                   animations:^{
+                     selectedCell.selected = NO;
+                   }
+                   completion:nil];
+
+  // Completion block to be run when the transition completes.
+  auto completion = ^(BOOL finished) {
+    // Tell the delegate the animation has completed.
+    [self.delegate gridTransitionAnimationDidFinish:finished];
+  };
+
+  if (self.layout.items.count == 1) {
+    // Single cell case.
+    // Run animation (B) for the whole duration without delay.
+    [UIView animateWithDuration:duration
+                          delay:0
+                        options:UIViewAnimationOptionCurveEaseIn
+                     animations:^{
+                       [self positionSelectedItemInExpandedGrid];
+                     }
+                     completion:completion];
+  } else {
+    // Multiple cell case.
+    // Run animation (C) for |staggeredDuration|.
+    [UIView animateWithDuration:staggeredDuration
+                          delay:0.0
+                        options:UIViewAnimationOptionCurveEaseOut
+                     animations:^{
+                       [self positionUnselectedItemsInExpandedGrid];
+                     }
+                     completion:completion];
+
+    // Run animation (B) for |staggeredDuration| up to the end of the
+    // transition.
+    [UIView animateWithDuration:staggeredDuration
+                          delay:duration - staggeredDuration
+                        options:UIViewAnimationOptionCurveEaseOut
+                     animations:^{
+                       [self positionSelectedItemInExpandedGrid];
+                     }
+                     completion:nil];
+  }
+}
 
 // Perfrom the initial setup for the animation, computing scale based on the
 // superview size and adding the transition cells to the view hierarchy.
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/tab_to_grid_animator.mm b/ios/chrome/browser/ui/tab_grid/transitions/tab_to_grid_animator.mm
index 5c53114..f34e263e 100644
--- a/ios/chrome/browser/ui/tab_grid/transitions/tab_to_grid_animator.mm
+++ b/ios/chrome/browser/ui/tab_grid/transitions/tab_to_grid_animator.mm
@@ -4,8 +4,6 @@
 
 #import "ios/chrome/browser/ui/tab_grid/transitions/tab_to_grid_animator.h"
 
-#import "base/logging.h"
-#import "base/mac/foundation_util.h"
 #import "ios/chrome/browser/ui/tab_grid/transitions/grid_transition_animation.h"
 #import "ios/chrome/browser/ui/tab_grid/transitions/grid_transition_state_providing.h"
 
@@ -67,8 +65,10 @@
       [self.stateProvider layoutForTransitionContext:transitionContext];
 
   // Create the animation view and insert it.
-  self.animation =
-      [[GridTransitionAnimation alloc] initWithLayout:layout delegate:self];
+  self.animation = [[GridTransitionAnimation alloc]
+      initWithLayout:layout
+            delegate:self
+           direction:GridAnimationDirectionContracting];
 
   // Ask the state provider for the views to use when inserting the animation.
   UIView* proxyContainer =
diff --git a/ios/chrome/browser/ui/table_view/chrome_table_view_controller.h b/ios/chrome/browser/ui/table_view/chrome_table_view_controller.h
index 762b09f..3a74b0ac 100644
--- a/ios/chrome/browser/ui/table_view/chrome_table_view_controller.h
+++ b/ios/chrome/browser/ui/table_view/chrome_table_view_controller.h
@@ -34,6 +34,10 @@
 // override this method in order to get a clean tableViewModel.
 - (void)loadModel NS_REQUIRES_SUPER;
 
+// Reconfigures the cells corresponding to the given |items| by calling
+// |configureCell:| on each cell.
+- (void)reconfigureCellsForItems:(NSArray*)items;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_TABLE_VIEW_CHROME_TABLE_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/table_view/chrome_table_view_controller.mm b/ios/chrome/browser/ui/table_view/chrome_table_view_controller.mm
index 1d2a8d4..d7ca07a 100644
--- a/ios/chrome/browser/ui/table_view/chrome_table_view_controller.mm
+++ b/ios/chrome/browser/ui/table_view/chrome_table_view_controller.mm
@@ -30,6 +30,18 @@
   _tableViewModel = [[TableViewModel alloc] init];
 }
 
+- (void)reconfigureCellsForItems:(NSArray*)items {
+  for (TableViewItem* item in items) {
+    NSIndexPath* indexPath = [self.tableViewModel indexPathForItem:item];
+    UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:indexPath];
+
+    // |cell| may be nil if the row is not currently on screen.
+    if (cell) {
+      [item configureCell:cell withStyler:self.styler];
+    }
+  }
+}
+
 #pragma mark - ViewLifeCycle
 
 - (void)viewDidLoad {
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/toolbar_coordinator_adaptor.h b/ios/chrome/browser/ui/toolbar/adaptive/toolbar_coordinator_adaptor.h
index f1e3c8e..0bcc24a 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/toolbar_coordinator_adaptor.h
+++ b/ios/chrome/browser/ui/toolbar/adaptive/toolbar_coordinator_adaptor.h
@@ -10,18 +10,13 @@
 
 @class CommandDispatcher;
 @protocol ToolbarCoordinatee;
-@protocol ToolsMenuConfigurationProvider;
 
 // This object is an interface between multiple toolbars and the objects which
 // want to interact with them without having to know to which one specifically
 // send the call.
-@interface ToolbarCoordinatorAdaptor
-    : NSObject<ToolbarCoordinating, ToolsMenuPresentationStateProvider>
+@interface ToolbarCoordinatorAdaptor : NSObject<ToolbarCoordinating>
 
-- (instancetype)initWithToolsMenuConfigurationProvider:
-                    (id<ToolsMenuConfigurationProvider>)configurationProvider
-                                            dispatcher:
-                                                (CommandDispatcher*)dispatcher;
+- (instancetype)initWithDispatcher:(CommandDispatcher*)dispatcher;
 
 // Adds a |toolbarCoordinator| to the set of coordinators this object is
 // interfacing with.
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/toolbar_coordinator_adaptor.mm b/ios/chrome/browser/ui/toolbar/adaptive/toolbar_coordinator_adaptor.mm
index aa7634f..3276f7a 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/toolbar_coordinator_adaptor.mm
+++ b/ios/chrome/browser/ui/toolbar/adaptive/toolbar_coordinator_adaptor.mm
@@ -8,7 +8,6 @@
 #import "ios/chrome/browser/ui/commands/toolbar_commands.h"
 #import "ios/chrome/browser/ui/history_popup/requirements/tab_history_ui_updater.h"
 #import "ios/chrome/browser/ui/toolbar/adaptive/toolbar_coordinatee.h"
-#import "ios/chrome/browser/ui/tools_menu/tools_menu_coordinator.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -18,27 +17,17 @@
 @property(nonatomic, strong)
     NSMutableArray<id<NewTabPageControllerDelegate, ToolbarCommands>>*
         coordinators;
-// Coordinator for the toolsMenu.
-@property(nonatomic, strong) ToolsMenuCoordinator* toolsMenuCoordinator;
 @end
 
 @implementation ToolbarCoordinatorAdaptor
 
 @synthesize coordinators = _coordinators;
-@synthesize toolsMenuCoordinator = _toolsMenuCoordinator;
 
 #pragma mark - Public
 
-- (instancetype)initWithToolsMenuConfigurationProvider:
-                    (id<ToolsMenuConfigurationProvider>)configurationProvider
-                                            dispatcher:
-                                                (CommandDispatcher*)dispatcher {
+- (instancetype)initWithDispatcher:(CommandDispatcher*)dispatcher {
   self = [super init];
   if (self) {
-    _toolsMenuCoordinator = [[ToolsMenuCoordinator alloc] init];
-    _toolsMenuCoordinator.dispatcher = dispatcher;
-    _toolsMenuCoordinator.configurationProvider = configurationProvider;
-    [_toolsMenuCoordinator start];
     [dispatcher startDispatchingToTarget:self
                              forProtocol:@protocol(ToolbarCommands)];
     _coordinators = [NSMutableArray array];
@@ -73,12 +62,6 @@
   }
 }
 
-#pragma mark - ToolsMenuPresentationStateProvider
-
-- (BOOL)isShowingToolsMenu {
-  return [self.toolsMenuCoordinator isShowingToolsMenu];
-}
-
 #pragma mark - SideSwipeToolbarInteracting
 
 - (BOOL)isInsideToolbar:(CGPoint)point {
@@ -96,10 +79,6 @@
 
 #pragma mark - ToolbarCoordinating
 
-- (void)updateToolsMenu {
-  [self.toolsMenuCoordinator updateConfiguration];
-}
-
 - (id<TabHistoryUIUpdater>)tabHistoryUIUpdater {
   return self;
 }
diff --git a/ios/chrome/browser/ui/toolbar/buttons/toolbar_button_factory.mm b/ios/chrome/browser/ui/toolbar/buttons/toolbar_button_factory.mm
index d995997..b9eecee 100644
--- a/ios/chrome/browser/ui/toolbar/buttons/toolbar_button_factory.mm
+++ b/ios/chrome/browser/ui/toolbar/buttons/toolbar_button_factory.mm
@@ -237,7 +237,7 @@
   } else {
     [self configureButton:toolsMenuButton width:kToolsMenuButtonWidth];
   }
-  if (base::FeatureList::IsEnabled(kNewToolsMenu)) {
+  if (IsUIRefreshPhase1Enabled()) {
     [toolsMenuButton addTarget:self.dispatcher
                         action:@selector(showToolsMenuPopup)
               forControlEvents:UIControlEventTouchUpInside];
diff --git a/ios/chrome/browser/ui/toolbar/clean/toolbar_coordinator.h b/ios/chrome/browser/ui/toolbar/clean/toolbar_coordinator.h
index 8894a8f..380b7a3 100644
--- a/ios/chrome/browser/ui/toolbar/clean/toolbar_coordinator.h
+++ b/ios/chrome/browser/ui/toolbar/clean/toolbar_coordinator.h
@@ -50,6 +50,9 @@
 // Stop this coordinator.
 - (void)stop;
 
+// Updates the tools menu, changing its content to reflect the current page.
+- (void)updateToolsMenu;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_TOOLBAR_CLEAN_TOOLBAR_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/toolbar/clean/toolbar_view_controller.mm b/ios/chrome/browser/ui/toolbar/clean/toolbar_view_controller.mm
index 80f0584..24d1f44 100644
--- a/ios/chrome/browser/ui/toolbar/clean/toolbar_view_controller.mm
+++ b/ios/chrome/browser/ui/toolbar/clean/toolbar_view_controller.mm
@@ -656,6 +656,8 @@
 // Target of the voice search button.
 - (void)startVoiceSearch:(id)sender {
   UIView* view = base::mac::ObjCCastStrict<UIView>(sender);
+  [NamedGuide guideWithName:kVoiceSearchButtonGuide view:view].constrainedView =
+      view;
   StartVoiceSearchCommand* command =
       [[StartVoiceSearchCommand alloc] initWithOriginView:view];
   [self.dispatcher startVoiceSearch:command];
diff --git a/ios/chrome/browser/ui/toolbar/keyboard_assist/BUILD.gn b/ios/chrome/browser/ui/toolbar/keyboard_assist/BUILD.gn
index faba125..5ef1bf1e 100644
--- a/ios/chrome/browser/ui/toolbar/keyboard_assist/BUILD.gn
+++ b/ios/chrome/browser/ui/toolbar/keyboard_assist/BUILD.gn
@@ -31,6 +31,7 @@
     "//ios/chrome/browser/ui/location_bar:constants",
     "//ios/chrome/browser/ui/omnibox:omnibox_internal",
     "//ios/chrome/browser/ui/toolbar/public",
+    "//ios/chrome/browser/ui/util/",
     "//ios/public/provider/chrome/browser",
     "//ios/public/provider/chrome/browser/external_search",
     "//ios/public/provider/chrome/browser/voice",
diff --git a/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_delegate.h b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_delegate.h
index 3084db7..a6068f5 100644
--- a/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_delegate.h
+++ b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_delegate.h
@@ -9,6 +9,7 @@
 
 @protocol ApplicationCommands;
 @protocol BrowserCommands;
+@class NamedGuide;
 @class OmniboxTextFieldIOS;
 
 // Delegate protocol for the KeyboardAccessoryView.
@@ -38,6 +39,7 @@
 
 @property(nonatomic, weak) id<ApplicationCommands, BrowserCommands> dispatcher;
 @property(nonatomic, weak) OmniboxTextFieldIOS* omniboxTextField;
+@property(nonatomic, weak) NamedGuide* voiceSearchButtonGuide;
 
 @end
 
diff --git a/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_delegate.mm b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_delegate.mm
index 32058e7..828d30c 100644
--- a/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_delegate.mm
+++ b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_delegate.mm
@@ -12,6 +12,7 @@
 #import "ios/chrome/browser/ui/commands/start_voice_search_command.h"
 #import "ios/chrome/browser/ui/location_bar/location_bar_constants.h"
 #import "ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.h"
+#import "ios/chrome/browser/ui/util/named_guide.h"
 #import "ios/public/provider/chrome/browser/chrome_browser_provider.h"
 #import "ios/public/provider/chrome/browser/voice/voice_search_provider.h"
 
@@ -23,6 +24,7 @@
 
 @synthesize dispatcher = _dispatcher;
 @synthesize omniboxTextField = _omniboxTextField;
+@synthesize voiceSearchButtonGuide = _voiceSearchButtonGuide;
 
 #pragma mark - Public
 
@@ -39,6 +41,21 @@
           ->GetVoiceSearchProvider()
           ->IsVoiceSearchEnabled()) {
     base::RecordAction(base::UserMetricsAction("MobileCustomRowVoiceSearch"));
+    // Since the keyboard accessory view is in a different window than the main
+    // UIViewController upon which Voice Search will be presented, the guide
+    // must be constrained to a frame instead of the view itself.  The keyboard
+    // and its accessory view will be dismissed at the bottom of the screen
+    // before the presentation animation, so bottom-align the view's frame.
+    if (self.voiceSearchButtonGuide) {
+      self.voiceSearchButtonGuide.autoresizingMask =
+          (UIViewAutoresizingFlexibleTopMargin |
+           UIViewAutoresizingFlexibleRightMargin);
+      CGRect frame = view.frame;
+      frame.origin.y =
+          CGRectGetMaxY(self.voiceSearchButtonGuide.owningView.bounds) -
+          CGRectGetHeight(frame);
+      self.voiceSearchButtonGuide.constrainedFrame = frame;
+    }
     StartVoiceSearchCommand* command =
         [[StartVoiceSearchCommand alloc] initWithOriginView:view];
     [self.dispatcher startVoiceSearch:command];
diff --git a/ios/chrome/browser/ui/toolbar/public/toolbar_coordinating.h b/ios/chrome/browser/ui/toolbar/public/toolbar_coordinating.h
index 62133ba..0dfe11b4 100644
--- a/ios/chrome/browser/ui/toolbar/public/toolbar_coordinating.h
+++ b/ios/chrome/browser/ui/toolbar/public/toolbar_coordinating.h
@@ -16,9 +16,6 @@
 @protocol ToolbarCoordinating<NewTabPageControllerDelegate,
                               SideSwipeToolbarInteracting>
 
-// Updates the tools menu, changing its content to reflect the current page.
-- (void)updateToolsMenu;
-
 - (id<TabHistoryUIUpdater>)tabHistoryUIUpdater;
 
 @end
diff --git a/ios/chrome/browser/ui/uikit_ui_util.mm b/ios/chrome/browser/ui/uikit_ui_util.mm
index 8f90bea..2a89d91 100644
--- a/ios/chrome/browser/ui/uikit_ui_util.mm
+++ b/ios/chrome/browser/ui/uikit_ui_util.mm
@@ -559,7 +559,8 @@
 }
 
 bool IsSplitToolbarMode(id<UITraitEnvironment> environment) {
-  return IsCompactWidth(environment) && !IsCompactHeight(environment);
+  return IsUIRefreshPhase1Enabled() && IsCompactWidth(environment) &&
+         !IsCompactHeight(environment);
 }
 
 // Returns the current first responder.
diff --git a/ios/chrome/browser/ui/util/layout_guide_names.h b/ios/chrome/browser/ui/util/layout_guide_names.h
index 36f80e8..b8a26bbe 100644
--- a/ios/chrome/browser/ui/util/layout_guide_names.h
+++ b/ios/chrome/browser/ui/util/layout_guide_names.h
@@ -28,5 +28,8 @@
 extern GuideName* const kTabSwitcherGuide;
 // A guide that is constrained to match the frame of the ToolsMenu button.
 extern GuideName* const kToolsMenuGuide;
+// A guide that is constrained to match the frame of the last-tapped voice
+// search button.
+extern GuideName* const kVoiceSearchButtonGuide;
 
 #endif  // IOS_CHROME_BROWSER_UI_UTIL_LAYOUT_GUIDE_NAMES_H_
diff --git a/ios/chrome/browser/ui/util/layout_guide_names.mm b/ios/chrome/browser/ui/util/layout_guide_names.mm
index 5f68014..cd0ba7f 100644
--- a/ios/chrome/browser/ui/util/layout_guide_names.mm
+++ b/ios/chrome/browser/ui/util/layout_guide_names.mm
@@ -16,3 +16,4 @@
 GuideName* const kForwardButtonGuide = @"kForwardButtonGuide";
 GuideName* const kTabSwitcherGuide = @"kTabSwitcherGuide";
 GuideName* const kToolsMenuGuide = @"kToolsMenuGuide";
+GuideName* const kVoiceSearchButtonGuide = @"kVoiceSearchButtonGuide";
diff --git a/ios/chrome/browser/ui/util/named_guide.h b/ios/chrome/browser/ui/util/named_guide.h
index 487339b..49da3be 100644
--- a/ios/chrome/browser/ui/util/named_guide.h
+++ b/ios/chrome/browser/ui/util/named_guide.h
@@ -23,14 +23,35 @@
 // or one of |view|'s ancestors.  If no guide is found, returns nil.
 + (instancetype)guideWithName:(GuideName*)name view:(UIView*)view;
 
+// Resets |constrainedView| and |constrainedFrame|, deactivating constraints
+// that were created to support following the view/frame.  Note that calling
+// this function has no effect on constraints that were created outside of this
+// class.
+- (void)resetConstraints;
+
 // The GuideName passed on initialization.
 @property(nonatomic, readonly) GuideName* name;
 
 // The view to which this guide should be constrained.  Setting this property
 // to a new value will update the guide's constraints to match the new view.
-// Setting to nil removes constraints.
+// Setting to nil removes constraints.  Setting this property to a non-nil value
+// will reset |constrainedFrame| to CGRectNull.
 @property(nonatomic, weak) UIView* constrainedView;
 
+// The frame to which this guide should be constrained, in the guide's owning
+// view's coordinate system.  This can be used to specify locations that don't
+// correspond with a particular view, or correspond to views in different
+// windows.  Setting this property to a new value will update the guide's
+// constraints to match the specified frame according to |autoresizingMask|.
+// Setting to CGRectNull removes constraints.  Setting this property to a non-
+// CGRectNull value will reset |constrainedView| to nil.
+@property(nonatomic, assign) CGRect constrainedFrame;
+
+// The autoresizing behavior to use when setting up constraints for
+// |constrainedFrame|.  This property has no effect if |constrainedFrame| is
+// CGRectNull.
+@property(nonatomic, assign) UIViewAutoresizing autoresizingMask;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_UTIL_NAMED_GUIDE_H_
diff --git a/ios/chrome/browser/ui/util/named_guide.mm b/ios/chrome/browser/ui/util/named_guide.mm
index 3c3130f..5efbb07 100644
--- a/ios/chrome/browser/ui/util/named_guide.mm
+++ b/ios/chrome/browser/ui/util/named_guide.mm
@@ -14,25 +14,43 @@
 
 @interface NamedGuide ()
 
-// The constraints used to connect the guide to |constrainedView|.
-@property(nonatomic, strong) NSArray* constrainedViewConstraints;
+// The constraints used to connect the guide to |constrainedView| or
+// |constrainedFrame|.
+@property(nonatomic, strong) NSArray* constraints;
+// A dummy view that is used to support |constrainedFrame|.
+@property(nonatomic, strong) UIView* constrainedFrameView;
+
+// Updates |constraints| to constrain the guide to |view|.
+- (void)updateConstraintsWithView:(UIView*)view;
+
+// Updates |constrainedFrameView| according to |constrainedFrame| and
+// |autoresizingMask|.  This function will lazily instantiate the view if
+// necessary and set up constraints so that this layout guide follows the view.
+- (void)updateConstrainedFrameView;
 
 @end
 
 @implementation NamedGuide
 @synthesize name = _name;
 @synthesize constrainedView = _constrainedView;
-@synthesize constrainedViewConstraints = _constrainedViewConstraints;
+@synthesize constrainedFrame = _constrainedFrame;
+@synthesize autoresizingMask = _autoresizingMask;
+@synthesize constraints = _constraints;
+@synthesize constrainedFrameView = _constrainedFrameView;
 
 - (instancetype)initWithName:(GuideName*)name {
   if (self = [super init]) {
     _name = name;
+    _constrainedFrame = CGRectNull;
   }
   return self;
 }
 
 - (void)dealloc {
-  self.constrainedView = nil;
+  _constrainedView = nil;
+  _constrainedFrame = CGRectNull;
+  if (_constraints.count)
+    [NSLayoutConstraint deactivateConstraints:_constraints];
 }
 
 #pragma mark - Accessors
@@ -40,29 +58,58 @@
 - (void)setConstrainedView:(UIView*)constrainedView {
   if (_constrainedView == constrainedView)
     return;
+
+  // Reset the constrained frame to null if specifying a new constrained view.
+  if (constrainedView)
+    self.constrainedFrame = CGRectNull;
+
   _constrainedView = constrainedView;
-  if (_constrainedView) {
-    self.constrainedViewConstraints = @[
-      [self.leadingAnchor
-          constraintEqualToAnchor:_constrainedView.leadingAnchor],
-      [self.trailingAnchor
-          constraintEqualToAnchor:_constrainedView.trailingAnchor],
-      [self.topAnchor constraintEqualToAnchor:_constrainedView.topAnchor],
-      [self.bottomAnchor constraintEqualToAnchor:_constrainedView.bottomAnchor]
-    ];
-  } else {
-    self.constrainedViewConstraints = nil;
-  }
+  [self updateConstraintsWithView:_constrainedView];
 }
 
-- (void)setConstrainedViewConstraints:(NSArray*)constrainedViewConstraints {
-  if (_constrainedViewConstraints == constrainedViewConstraints)
+- (void)setConstrainedFrame:(CGRect)constrainedFrame {
+  if (CGRectEqualToRect(_constrainedFrame, constrainedFrame))
     return;
-  if (_constrainedViewConstraints.count)
-    [NSLayoutConstraint deactivateConstraints:_constrainedViewConstraints];
-  _constrainedViewConstraints = constrainedViewConstraints;
-  if (_constrainedViewConstraints.count)
-    [NSLayoutConstraint activateConstraints:_constrainedViewConstraints];
+
+  // Reset the constrained view to nil if specifying a new constrained frame.
+  if (!CGRectIsNull(constrainedFrame))
+    self.constrainedView = nil;
+
+  _constrainedFrame = constrainedFrame;
+  [self updateConstrainedFrameView];
+}
+
+- (void)setAutoresizingMask:(UIViewAutoresizing)autoresizingMask {
+  if (_autoresizingMask == autoresizingMask)
+    return;
+  _autoresizingMask = autoresizingMask;
+  [self updateConstrainedFrameView];
+}
+
+- (void)setConstraints:(NSArray*)constraints {
+  if (_constraints == constraints)
+    return;
+  if (_constraints.count)
+    [NSLayoutConstraint deactivateConstraints:_constraints];
+  _constraints = constraints;
+  if (_constraints.count)
+    [NSLayoutConstraint activateConstraints:_constraints];
+}
+
+- (void)setConstrainedFrameView:(UIView*)constrainedFrameView {
+  if (_constrainedFrameView == constrainedFrameView)
+    return;
+
+  if (_constrainedFrameView)
+    [_constrainedFrameView removeFromSuperview];
+  _constrainedFrameView = constrainedFrameView;
+
+  // The constrained frame view is inserted at the bottom of the owning view's
+  // hierarchy in an effort to minimize additional rendering costs.
+  if (_constrainedFrameView)
+    [self.owningView insertSubview:_constrainedFrameView atIndex:0];
+
+  [self updateConstraintsWithView:_constrainedFrameView];
 }
 
 #pragma mark - Public
@@ -79,4 +126,44 @@
   return nil;
 }
 
+- (void)resetConstraints {
+  self.constrainedView = nil;
+  self.constrainedFrame = CGRectNull;
+}
+
+#pragma mark - Private
+
+- (void)updateConstraintsWithView:(UIView*)view {
+  if (view) {
+    self.constraints = @[
+      [self.leadingAnchor constraintEqualToAnchor:view.leadingAnchor],
+      [self.trailingAnchor constraintEqualToAnchor:view.trailingAnchor],
+      [self.topAnchor constraintEqualToAnchor:view.topAnchor],
+      [self.bottomAnchor constraintEqualToAnchor:view.bottomAnchor]
+    ];
+  } else {
+    self.constraints = nil;
+  }
+}
+
+- (void)updateConstrainedFrameView {
+  // Remove the dummy view if |constrainedFrame| is null.
+  if (CGRectIsNull(self.constrainedFrame)) {
+    self.constrainedFrameView = nil;
+    return;
+  }
+
+  // Lazily create the view if necessary and set it up using the specified frame
+  // and autoresizing mask.
+  // NOTE: The view's |translatesAutoresizingMaskIntoConstraints| remains set to
+  // the default value of |YES| in order to leverage UIKit's built in frame =>
+  // constraint conversion.
+  if (!self.constrainedFrameView) {
+    self.constrainedFrameView = [[UIView alloc] init];
+    self.constrainedFrameView.backgroundColor = [UIColor clearColor];
+  }
+  self.constrainedFrameView.frame = self.constrainedFrame;
+  self.constrainedFrameView.autoresizingMask = self.autoresizingMask;
+}
+
 @end
diff --git a/ios/chrome/browser/ui/util/named_guide_unittest.mm b/ios/chrome/browser/ui/util/named_guide_unittest.mm
index 343fafe..7a20a66 100644
--- a/ios/chrome/browser/ui/util/named_guide_unittest.mm
+++ b/ios/chrome/browser/ui/util/named_guide_unittest.mm
@@ -12,6 +12,15 @@
 #error "This file requires ARC support."
 #endif
 
+namespace {
+// Tests that |guide|'s layoutFrame is equal to |frame|.
+void VerifyLayoutFrame(UILayoutGuide* guide, CGRect frame) {
+  [guide.owningView setNeedsLayout];
+  [guide.owningView layoutIfNeeded];
+  EXPECT_TRUE(CGRectEqualToRect(guide.layoutFrame, frame));
+}
+}  // namespace
+
 using NamedGuideTest = PlatformTest;
 
 // Tests that guides are reachable after being added to a view.
@@ -64,7 +73,7 @@
 }
 
 // Tests that resetting the constrained view updates the guide.
-TEST_F(NamedGuideTest, TestConstrainedViewUpdate) {
+TEST_F(NamedGuideTest, TestConstrainedView) {
   GuideName* test_guide = @"NamedGuideTest";
 
   UIWindow* window =
@@ -81,8 +90,62 @@
   // is updated.
   for (UIView* subview in view.subviews) {
     guide.constrainedView = subview;
-    [view setNeedsLayout];
-    [view layoutIfNeeded];
-    EXPECT_TRUE(CGRectEqualToRect(guide.layoutFrame, subview.frame));
+    VerifyLayoutFrame(guide, subview.frame);
   }
 }
+
+// Tests that resetting the constrained frame updates the guide.
+TEST_F(NamedGuideTest, TestConstrainedFrame) {
+  GuideName* test_guide = @"NamedGuideTest";
+
+  UIWindow* window =
+      [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
+  UIView* view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
+  [window addSubview:view];
+
+  NamedGuide* guide = [[NamedGuide alloc] initWithName:test_guide];
+  [view addLayoutGuide:guide];
+
+  // Test updating the guide's |constrainedFrame| to the lower left corner.
+  const CGRect kLowerLeftCorner = CGRectMake(0, 50, 50, 50);
+  guide.constrainedFrame = kLowerLeftCorner;
+  VerifyLayoutFrame(guide, kLowerLeftCorner);
+
+  // Tests that updating the view's size stretches the layout frame such that
+  // it remains the lower left quadrant.
+  guide.autoresizingMask =
+      (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight |
+       UIViewAutoresizingFlexibleTopMargin |
+       UIViewAutoresizingFlexibleRightMargin);
+  view.frame = CGRectMake(0, 0, 200, 200);
+  const CGRect kNewLowerLeftCorner = CGRectMake(0, 100, 100, 100);
+  VerifyLayoutFrame(guide, kNewLowerLeftCorner);
+}
+
+// Tests that setting the |constrainedView| and |contstrainedFrame| correctly
+// nullify other properties.
+TEST_F(NamedGuideTest, TestConstrainedViewFrameMutex) {
+  GuideName* test_guide = @"NamedGuideTest";
+  UIWindow* window =
+      [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
+  UIView* view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
+  [window addSubview:view];
+  UIView* childView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 100)];
+  [view addSubview:childView];
+  NamedGuide* guide = [[NamedGuide alloc] initWithName:test_guide];
+  [view addLayoutGuide:guide];
+  guide.constrainedView = childView;
+
+  // Set the guide's |constrainedFrame| and verify that |constrainedView| is
+  // reset to nil.
+  const CGRect kConstrainedFrame = CGRectMake(0, 0, 50, 50);
+  guide.constrainedFrame = kConstrainedFrame;
+  EXPECT_FALSE(guide.constrainedView);
+  VerifyLayoutFrame(guide, kConstrainedFrame);
+
+  // Set the guide's |constrainedView| and verify that |constrainedFrame| is
+  // reset to CGRectNull.
+  guide.constrainedView = childView;
+  EXPECT_TRUE(CGRectIsNull(guide.constrainedFrame));
+  VerifyLayoutFrame(guide, childView.frame);
+}
diff --git a/ios/chrome/browser/ui/webui/crashes_ui.cc b/ios/chrome/browser/ui/webui/crashes_ui.cc
index 31fc779..6c99a2b 100644
--- a/ios/chrome/browser/ui/webui/crashes_ui.cc
+++ b/ios/chrome/browser/ui/webui/crashes_ui.cc
@@ -97,8 +97,8 @@
                                     base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       crash::kCrashesUIRequestCrashList,
-      base::Bind(&CrashesDOMHandler::HandleRequestCrashes,
-                 base::Unretained(this)));
+      base::BindRepeating(&CrashesDOMHandler::HandleRequestCrashes,
+                          base::Unretained(this)));
 }
 
 void CrashesDOMHandler::HandleRequestCrashes(const base::ListValue* args) {
diff --git a/ios/chrome/browser/ui/webui/flags_ui.cc b/ios/chrome/browser/ui/webui/flags_ui.cc
index 837fc24..c48b6e3 100644
--- a/ios/chrome/browser/ui/webui/flags_ui.cc
+++ b/ios/chrome/browser/ui/webui/flags_ui.cc
@@ -96,20 +96,21 @@
 void FlagsDOMHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       flags_ui::kRequestExperimentalFeatures,
-      base::Bind(&FlagsDOMHandler::HandleRequestExperimentalFeatures,
-                 base::Unretained(this)));
+      base::BindRepeating(&FlagsDOMHandler::HandleRequestExperimentalFeatures,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       flags_ui::kEnableExperimentalFeature,
-      base::Bind(&FlagsDOMHandler::HandleEnableExperimentalFeatureMessage,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &FlagsDOMHandler::HandleEnableExperimentalFeatureMessage,
+          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       flags_ui::kRestartBrowser,
-      base::Bind(&FlagsDOMHandler::HandleRestartBrowser,
-                 base::Unretained(this)));
+      base::BindRepeating(&FlagsDOMHandler::HandleRestartBrowser,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       flags_ui::kResetAllFlags,
-      base::Bind(&FlagsDOMHandler::HandleResetAllFlags,
-                 base::Unretained(this)));
+      base::BindRepeating(&FlagsDOMHandler::HandleResetAllFlags,
+                          base::Unretained(this)));
 }
 
 void FlagsDOMHandler::Init(
diff --git a/ios/chrome/browser/ui/webui/gcm/gcm_internals_ui.cc b/ios/chrome/browser/ui/webui/gcm/gcm_internals_ui.cc
index 1f3b964..439eb82 100644
--- a/ios/chrome/browser/ui/webui/gcm/gcm_internals_ui.cc
+++ b/ios/chrome/browser/ui/webui/gcm/gcm_internals_ui.cc
@@ -144,12 +144,12 @@
 void GcmInternalsUIMessageHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       gcm_driver::kGetGcmInternalsInfo,
-      base::Bind(&GcmInternalsUIMessageHandler::RequestAllInfo,
-                 weak_ptr_factory_.GetWeakPtr()));
+      base::BindRepeating(&GcmInternalsUIMessageHandler::RequestAllInfo,
+                          weak_ptr_factory_.GetWeakPtr()));
   web_ui()->RegisterMessageCallback(
       gcm_driver::kSetGcmInternalsRecording,
-      base::Bind(&GcmInternalsUIMessageHandler::SetRecording,
-                 weak_ptr_factory_.GetWeakPtr()));
+      base::BindRepeating(&GcmInternalsUIMessageHandler::SetRecording,
+                          weak_ptr_factory_.GetWeakPtr()));
 }
 
 }  // namespace
diff --git a/ios/chrome/browser/ui/webui/net_export/net_export_ui.mm b/ios/chrome/browser/ui/webui/net_export/net_export_ui.mm
index 7ab09f00..cb4cc04 100644
--- a/ios/chrome/browser/ui/webui/net_export/net_export_ui.mm
+++ b/ios/chrome/browser/ui/webui/net_export/net_export_ui.mm
@@ -110,20 +110,20 @@
 
   web_ui()->RegisterMessageCallback(
       net_log::kEnableNotifyUIWithStateHandler,
-      base::Bind(&NetExportMessageHandler::OnEnableNotifyUIWithState,
-                 base::Unretained(this)));
+      base::BindRepeating(&NetExportMessageHandler::OnEnableNotifyUIWithState,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       net_log::kStartNetLogHandler,
-      base::Bind(&NetExportMessageHandler::OnStartNetLog,
-                 base::Unretained(this)));
+      base::BindRepeating(&NetExportMessageHandler::OnStartNetLog,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       net_log::kStopNetLogHandler,
-      base::Bind(&NetExportMessageHandler::OnStopNetLog,
-                 base::Unretained(this)));
+      base::BindRepeating(&NetExportMessageHandler::OnStopNetLog,
+                          base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
       net_log::kSendNetLogHandler,
-      base::Bind(&NetExportMessageHandler::OnSendNetLog,
-                 base::Unretained(this)));
+      base::BindRepeating(&NetExportMessageHandler::OnSendNetLog,
+                          base::Unretained(this)));
 }
 
 void NetExportMessageHandler::OnEnableNotifyUIWithState(
diff --git a/ios/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc b/ios/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc
index b2f43c6..896ccd2 100644
--- a/ios/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc
+++ b/ios/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc
@@ -44,7 +44,8 @@
   PrefService* GetPrefs() override;
   void RegisterMessageCallback(
       const std::string& message,
-      const base::Callback<void(const base::ListValue*)>& callback) override;
+      const base::RepeatingCallback<void(const base::ListValue*)>& callback)
+      override;
   void CallJavascriptFunctionVector(
       const std::string& name,
       const std::vector<const base::Value*>& values) override;
@@ -90,7 +91,7 @@
 
 void IOSNTPTilesInternalsMessageHandlerBridge::RegisterMessageCallback(
     const std::string& message,
-    const base::Callback<void(const base::ListValue*)>& callback) {
+    const base::RepeatingCallback<void(const base::ListValue*)>& callback) {
   web_ui()->RegisterMessageCallback(message, callback);
 }
 
diff --git a/ios/chrome/browser/ui/webui/omaha_ui.cc b/ios/chrome/browser/ui/webui/omaha_ui.cc
index 20ecbdd..52d92eb 100644
--- a/ios/chrome/browser/ui/webui/omaha_ui.cc
+++ b/ios/chrome/browser/ui/webui/omaha_ui.cc
@@ -63,8 +63,8 @@
 void OmahaDOMHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "requestOmahaDebugInformation",
-      base::Bind(&OmahaDOMHandler::HandleRequestDebugInformation,
-                 base::Unretained(this)));
+      base::BindRepeating(&OmahaDOMHandler::HandleRequestDebugInformation,
+                          base::Unretained(this)));
 }
 
 void OmahaDOMHandler::HandleRequestDebugInformation(
diff --git a/ios/chrome/browser/ui/webui/sync_internals/sync_internals_message_handler.cc b/ios/chrome/browser/ui/webui/sync_internals/sync_internals_message_handler.cc
index 4829605d..e5fe13d 100644
--- a/ios/chrome/browser/ui/webui/sync_internals/sync_internals_message_handler.cc
+++ b/ios/chrome/browser/ui/webui/sync_internals/sync_internals_message_handler.cc
@@ -53,33 +53,37 @@
 
   web_ui()->RegisterMessageCallback(
       syncer::sync_ui_util::kRegisterForEvents,
-      base::Bind(&SyncInternalsMessageHandler::HandleRegisterForEvents,
-                 base::Unretained(this)));
+      base::BindRepeating(&SyncInternalsMessageHandler::HandleRegisterForEvents,
+                          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       syncer::sync_ui_util::kRegisterForPerTypeCounters,
-      base::Bind(&SyncInternalsMessageHandler::HandleRegisterForPerTypeCounters,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &SyncInternalsMessageHandler::HandleRegisterForPerTypeCounters,
+          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       syncer::sync_ui_util::kRequestUpdatedAboutInfo,
-      base::Bind(&SyncInternalsMessageHandler::HandleRequestUpdatedAboutInfo,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &SyncInternalsMessageHandler::HandleRequestUpdatedAboutInfo,
+          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       syncer::sync_ui_util::kRequestListOfTypes,
-      base::Bind(&SyncInternalsMessageHandler::HandleRequestListOfTypes,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &SyncInternalsMessageHandler::HandleRequestListOfTypes,
+          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       syncer::sync_ui_util::kGetAllNodes,
-      base::Bind(&SyncInternalsMessageHandler::HandleGetAllNodes,
-                 base::Unretained(this)));
+      base::BindRepeating(&SyncInternalsMessageHandler::HandleGetAllNodes,
+                          base::Unretained(this)));
 
   web_ui()->RegisterMessageCallback(
       syncer::sync_ui_util::kSetIncludeSpecifics,
-      base::Bind(&SyncInternalsMessageHandler::HandleSetIncludeSpecifics,
-                 base::Unretained(this)));
+      base::BindRepeating(
+          &SyncInternalsMessageHandler::HandleSetIncludeSpecifics,
+          base::Unretained(this)));
 }
 
 void SyncInternalsMessageHandler::HandleRegisterForEvents(
diff --git a/ios/chrome/browser/ui/webui/version_handler.cc b/ios/chrome/browser/ui/webui/version_handler.cc
index fc2d7e0..34a5daed 100644
--- a/ios/chrome/browser/ui/webui/version_handler.cc
+++ b/ios/chrome/browser/ui/webui/version_handler.cc
@@ -19,8 +19,8 @@
 void VersionHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       version_ui::kRequestVersionInfo,
-      base::Bind(&VersionHandler::HandleRequestVersionInfo,
-                 base::Unretained(this)));
+      base::BindRepeating(&VersionHandler::HandleRequestVersionInfo,
+                          base::Unretained(this)));
 }
 
 void VersionHandler::HandleRequestVersionInfo(const base::ListValue* args) {
diff --git a/ios/chrome/browser/web/browsing_egtest.mm b/ios/chrome/browser/web/browsing_egtest.mm
index d814551..55138fa 100644
--- a/ios/chrome/browser/web/browsing_egtest.mm
+++ b/ios/chrome/browser/web/browsing_egtest.mm
@@ -13,7 +13,6 @@
 #include "ios/chrome/browser/ui/ui_util.h"
 #include "ios/chrome/grit/ios_strings.h"
 #import "ios/chrome/test/app/chrome_test_util.h"
-#include "ios/chrome/test/app/navigation_test_util.h"
 #import "ios/chrome/test/app/web_view_interaction_test_util.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
diff --git a/ios/chrome/browser/web/navigation_egtest.mm b/ios/chrome/browser/web/navigation_egtest.mm
index 7c75f32..08b39aae 100644
--- a/ios/chrome/browser/web/navigation_egtest.mm
+++ b/ios/chrome/browser/web/navigation_egtest.mm
@@ -7,6 +7,7 @@
 #include "base/ios/ios_util.h"
 #include "components/strings/grit/components_strings.h"
 #import "ios/chrome/browser/ui/uikit_ui_util.h"
+#import "ios/chrome/test/app/chrome_test_util.h"
 #import "ios/chrome/test/app/web_view_interaction_test_util.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
@@ -22,6 +23,7 @@
 using chrome_test_util::ContentSuggestionCollectionView;
 using chrome_test_util::BackButton;
 using chrome_test_util::ForwardButton;
+using chrome_test_util::PurgeCachedWebViewPages;
 using chrome_test_util::OmniboxText;
 using chrome_test_util::TapWebViewElementWithId;
 
@@ -594,4 +596,40 @@
       assertWithMatcher:grey_notNil()];
 }
 
+// Tests that navigating forward from a WebUI URL works when resuming from
+// session restore. This is a regression test for https://crbug.com/814790.
+- (void)testRestoreHistoryToWebUIAndNavigateForward {
+  GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
+  const GURL destinationURL = self.testServer->GetURL(kSimpleFileBasedTestURL);
+  [ChromeEarlGrey loadURL:GURL("chrome://version")];
+  [ChromeEarlGrey loadURL:destinationURL];
+  [ChromeEarlGrey goBack];
+
+  GREYAssert(PurgeCachedWebViewPages(), @"History not restored");
+
+  [ChromeEarlGrey waitForWebViewContainingText:"Revision"];
+  [[EarlGrey selectElementWithMatcher:OmniboxText("chrome://version")]
+      assertWithMatcher:grey_notNil()];
+  [ChromeEarlGrey goForward];
+  [ChromeEarlGrey waitForWebViewContainingText:"pony"];
+  [[EarlGrey selectElementWithMatcher:OmniboxText(destinationURL.GetContent())]
+      assertWithMatcher:grey_notNil()];
+}
+
+// Tests that navigating forward from NTP works when resuming from session
+// restore. This is a regression test for https://crbug.com/814790.
+- (void)testRestoreHistoryToNTPAndNavigateForward {
+  GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
+  const GURL destinationURL = self.testServer->GetURL(kSimpleFileBasedTestURL);
+  [ChromeEarlGrey loadURL:destinationURL];
+  [ChromeEarlGrey goBack];
+
+  GREYAssert(PurgeCachedWebViewPages(), @"History not restored");
+
+  [ChromeEarlGrey goForward];
+  [ChromeEarlGrey waitForWebViewContainingText:"pony"];
+  [[EarlGrey selectElementWithMatcher:OmniboxText(destinationURL.GetContent())]
+      assertWithMatcher:grey_notNil()];
+}
+
 @end
diff --git a/ios/chrome/browser/web/visible_url_egtest.mm b/ios/chrome/browser/web/visible_url_egtest.mm
index f1addf1..d6faaff 100644
--- a/ios/chrome/browser/web/visible_url_egtest.mm
+++ b/ios/chrome/browser/web/visible_url_egtest.mm
@@ -31,6 +31,7 @@
 #endif
 
 using chrome_test_util::OmniboxText;
+using chrome_test_util::PurgeCachedWebViewPages;
 
 namespace {
 
@@ -45,19 +46,6 @@
 const char kPage2Link[] = "page-2";
 const char kPage3Link[] = "page-3";
 
-// Purges cached web view page, so the next time back navigation will not use
-// cached page. Browsers don't have to use fresh version for back forward
-// navigation for HTTP pages and may serve version from the cache even if
-// Cache-Control response header says otherwise.
-bool PurgeCachedWebViewPages() WARN_UNUSED_RESULT;
-bool PurgeCachedWebViewPages() {
-  web::WebState* web_state = chrome_test_util::GetCurrentWebState();
-  web_state->SetWebUsageEnabled(false);
-  web_state->SetWebUsageEnabled(true);
-  web_state->GetNavigationManager()->LoadIfNecessary();
-  return chrome_test_util::WaitForPageToFinishLoading();
-}
-
 // Response provider which can be paused. When it is paused it buffers all
 // requests and does not respond to them until |set_paused(false)| is called.
 class PausableResponseProvider : public HtmlResponseProvider {
diff --git a/ios/chrome/test/BUILD.gn b/ios/chrome/test/BUILD.gn
index 82a181c8..901635b 100644
--- a/ios/chrome/test/BUILD.gn
+++ b/ios/chrome/test/BUILD.gn
@@ -210,6 +210,7 @@
     "//ios/chrome/browser/ui/overlays:unit_tests",
     "//ios/chrome/browser/ui/payments:unit_tests",
     "//ios/chrome/browser/ui/payments/cells:unit_tests",
+    "//ios/chrome/browser/ui/popup_menu:unit_tests",
     "//ios/chrome/browser/ui/presenters:unit_tests",
     "//ios/chrome/browser/ui/promos:unit_tests",
     "//ios/chrome/browser/ui/reading_list:unit_tests",
diff --git a/ios/chrome/test/app/chrome_test_util.h b/ios/chrome/test/app/chrome_test_util.h
index 160d7ce..5dd473d 100644
--- a/ios/chrome/test/app/chrome_test_util.h
+++ b/ios/chrome/test/app/chrome_test_util.h
@@ -97,6 +97,12 @@
 // Simulates launching Chrome from another application.
 void OpenChromeFromExternalApp(const GURL& url);
 
+// Purges cached web view page, so the next time back navigation will not use
+// cached page. Browsers don't have to use fresh version for back forward
+// navigation for HTTP pages and may serve version from the cache even if
+// Cache-Control response header says otherwise.
+bool PurgeCachedWebViewPages() WARN_UNUSED_RESULT;
+
 }  // namespace chrome_test_util
 
 #endif  // IOS_CHROME_TEST_APP_CHROME_TEST_UTIL_H_
diff --git a/ios/chrome/test/app/chrome_test_util.mm b/ios/chrome/test/app/chrome_test_util.mm
index 0008ad6b..b31a2c2a 100644
--- a/ios/chrome/test/app/chrome_test_util.mm
+++ b/ios/chrome/test/app/chrome_test_util.mm
@@ -24,7 +24,9 @@
 #import "ios/chrome/browser/ui/main/view_controller_swapping.h"
 #import "ios/chrome/browser/ui/ntp/new_tab_page_controller.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_switcher.h"
+#include "ios/chrome/test/app/navigation_test_util.h"
 #import "ios/chrome/test/app/tab_test_util.h"
+#import "ios/web/public/navigation_manager.h"
 #import "ios/web/public/test/native_controller_test_util.h"
 #import "third_party/breakpad/breakpad/src/client/ios/BreakpadController.h"
 
@@ -231,4 +233,12 @@
       applicationDidBecomeActive:[UIApplication sharedApplication]];
 }
 
+bool PurgeCachedWebViewPages() {
+  web::WebState* web_state = chrome_test_util::GetCurrentWebState();
+  web_state->SetWebUsageEnabled(false);
+  web_state->SetWebUsageEnabled(true);
+  web_state->GetNavigationManager()->LoadIfNecessary();
+  return chrome_test_util::WaitForPageToFinishLoading();
+}
+
 }  // namespace chrome_test_util
diff --git a/ios/net/cookies/system_cookie_store.h b/ios/net/cookies/system_cookie_store.h
index 95806ee..5a63abf 100644
--- a/ios/net/cookies/system_cookie_store.h
+++ b/ios/net/cookies/system_cookie_store.h
@@ -22,6 +22,7 @@
 // type of system store (WKHTTPCookieStore, NSHTTPCookieStorage, ..), its main
 // purpose is to interact with the system cookie store, and let the caller use
 // it directly without caring about the type of the underlying cookie store.
+// The class methods should only be called from IO Thread.
 class SystemCookieStore {
  public:
   // Callback definitions.
@@ -81,6 +82,7 @@
   // Internal cookie stores doesn't store creation time. This object is used
   // to keep track of the creation time of cookies, this is required for
   // conversion between SystemCookie and Chromium CookieMonster.
+  // TODO(crbug.com/825227): Move this to be private.
   std::unique_ptr<CookieCreationTimeManager> creation_time_manager_;
 
   // Weak Ptr factory.
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn
index ba02ae8b..b0829dc 100644
--- a/ios/web/BUILD.gn
+++ b/ios/web/BUILD.gn
@@ -596,9 +596,9 @@
 
   sources = [
     "web_state/js/resources/console.js",
-    "web_state/js/resources/context_menu.js",
     "web_state/js/resources/error.js",
     "web_state/js/resources/legacy.js",
+    "web_state/js/resources/main_frame_context_menu.js",
     "web_state/js/resources/main_frame_web_bundle.js",
     "web_state/js/resources/navigation.js",
     "web_state/js/resources/scroll_workaround.js",
@@ -610,6 +610,7 @@
   closure_entry_point = "__crWeb.allFramesWebBundle"
 
   sources = [
+    "web_state/js/resources/all_frames_context_menu.js",
     "web_state/js/resources/all_frames_web_bundle.js",
     "web_state/js/resources/base.js",
     "web_state/js/resources/common.js",
diff --git a/ios/web/net/cookies/wk_http_system_cookie_store.h b/ios/web/net/cookies/wk_http_system_cookie_store.h
index fb665c06..f1fd974 100644
--- a/ios/web/net/cookies/wk_http_system_cookie_store.h
+++ b/ios/web/net/cookies/wk_http_system_cookie_store.h
@@ -46,8 +46,9 @@
 
  private:
   // Run |callback| on |cookies| after sorting them  as per RFC6265.
-  void RunSystemCookieCallbackForCookies(
+  static void RunSystemCookieCallbackForCookies(
       net::SystemCookieStore::SystemCookieCallbackForCookies callback,
+      base::WeakPtr<net::CookieCreationTimeManager> weak_time_manager,
       NSArray<NSHTTPCookie*>* cookies);
 
   // cookie_store_ must be deleted in the UI thread, So by making it weak
diff --git a/ios/web/net/cookies/wk_http_system_cookie_store.mm b/ios/web/net/cookies/wk_http_system_cookie_store.mm
index a941445b..6f19112 100644
--- a/ios/web/net/cookies/wk_http_system_cookie_store.mm
+++ b/ios/web/net/cookies/wk_http_system_cookie_store.mm
@@ -66,6 +66,8 @@
   // This function shouldn't be called if cookie_store_ is deleted.
   DCHECK(cookie_store_);
   __block SystemCookieCallbackForCookies shared_callback = std::move(callback);
+  base::WeakPtr<net::CookieCreationTimeManager> weak_time_manager =
+      creation_time_manager_->GetWeakPtr();
   GURL block_url = url;
   web::WebThread::PostTask(
       web::WebThread::UI, FROM_HERE, base::BindBlockArc(^{
@@ -76,7 +78,8 @@
               [result addObject:cookie];
             }
           }
-          RunSystemCookieCallbackForCookies(std::move(shared_callback), result);
+          RunSystemCookieCallbackForCookies(std::move(shared_callback),
+                                            weak_time_manager, result);
         }];
       }));
 }
@@ -86,11 +89,13 @@
   // This function shouldn't be called if cookie_store_ is deleted.
   DCHECK(cookie_store_);
   __block SystemCookieCallbackForCookies shared_callback = std::move(callback);
+  base::WeakPtr<net::CookieCreationTimeManager> weak_time_manager =
+      creation_time_manager_->GetWeakPtr();
   web::WebThread::PostTask(
       web::WebThread::UI, FROM_HERE, base::BindBlockArc(^{
         [cookie_store_ getAllCookies:^(NSArray<NSHTTPCookie*>* cookies) {
           RunSystemCookieCallbackForCookies(std::move(shared_callback),
-                                            cookies);
+                                            weak_time_manager, cookies);
         }];
       }));
 }
@@ -100,13 +105,16 @@
   // This function shouldn't be called if cookie_store_ is deleted.
   DCHECK(cookie_store_);
   __block SystemCookieCallback shared_callback = std::move(callback);
+  base::WeakPtr<net::CookieCreationTimeManager> weak_time_manager =
+      creation_time_manager_->GetWeakPtr();
   NSHTTPCookie* block_cookie = cookie;
   web::WebThread::PostTask(
       web::WebThread::UI, FROM_HERE, base::BindBlockArc(^{
         [cookie_store_ deleteCookie:block_cookie
                   completionHandler:^{
                     RunSystemCookieCallbackOnIOThread(base::BindBlockArc(^{
-                      creation_time_manager_->DeleteCreationTime(block_cookie);
+                      if (weak_time_manager)
+                        weak_time_manager->DeleteCreationTime(block_cookie);
                       if (!shared_callback.is_null())
                         std::move(shared_callback).Run();
                     }));
@@ -120,6 +128,8 @@
   // cookies can't be set if cookie_store_ is deleted.
   DCHECK(cookie_store_);
   __block SystemCookieCallback shared_callback = std::move(callback);
+  base::WeakPtr<net::CookieCreationTimeManager> weak_time_manager =
+      creation_time_manager_->GetWeakPtr();
   NSHTTPCookie* block_cookie = cookie;
   base::Time cookie_time = base::Time::Now();
   if (optional_creation_time && !optional_creation_time->is_null())
@@ -127,29 +137,34 @@
 
   web::WebThread::PostTask(
       web::WebThread::UI, FROM_HERE, base::BindBlockArc(^{
-        [cookie_store_ setCookie:block_cookie
-               completionHandler:^{
-                 RunSystemCookieCallbackOnIOThread(base::BindBlockArc(^{
-                   creation_time_manager_->SetCreationTime(
-                       block_cookie,
-                       creation_time_manager_->MakeUniqueCreationTime(
-                           cookie_time));
-                   if (!shared_callback.is_null())
-                     std::move(shared_callback).Run();
-                 }));
-               }];
+        [cookie_store_
+                    setCookie:block_cookie
+            completionHandler:^{
+              RunSystemCookieCallbackOnIOThread(base::BindBlockArc(^{
+                if (weak_time_manager) {
+                  weak_time_manager->SetCreationTime(
+                      block_cookie,
+                      weak_time_manager->MakeUniqueCreationTime(cookie_time));
+                }
+                if (!shared_callback.is_null())
+                  std::move(shared_callback).Run();
+              }));
+            }];
       }));
 }
 
 void WKHTTPSystemCookieStore::ClearStoreAsync(SystemCookieCallback callback) {
   __block SystemCookieCallback shared_callback = std::move(callback);
+  base::WeakPtr<net::CookieCreationTimeManager> weak_time_manager =
+      creation_time_manager_->GetWeakPtr();
   web::WebThread::PostTask(
       web::WebThread::UI, FROM_HERE, base::BindBlockArc(^{
         [cookie_store_ getAllCookies:^(NSArray<NSHTTPCookie*>* cookies) {
           scoped_refptr<CallbackCounter> callback_counter =
               new CallbackCounter(base::BindRepeating(
                   &RunSystemCookieCallbackOnIOThread, base::BindBlockArc(^{
-                    creation_time_manager_->Clear();
+                    if (weak_time_manager)
+                      weak_time_manager->Clear();
                     std::move(shared_callback).Run();
                   })));
           // Add callback for each cookie
@@ -170,22 +185,22 @@
   return [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookieAcceptPolicy];
 }
 
-#pragma mark private methods
-
+// private static
+// Runs |callback| on |cookies| after sorting them as per RFC6265 using
+// |weak_time_manager|.
 void WKHTTPSystemCookieStore::RunSystemCookieCallbackForCookies(
     net::SystemCookieStore::SystemCookieCallbackForCookies callback,
+    base::WeakPtr<net::CookieCreationTimeManager> weak_time_manager,
     NSArray<NSHTTPCookie*>* cookies) {
   if (callback.is_null())
     return;
-  base::WeakPtr<net::CookieCreationTimeManager> weak_time_manager =
-      creation_time_manager_->GetWeakPtr();
-  NSArray<NSHTTPCookie*>* block_cookies = cookies;
+  NSArray* block_cookies = cookies;
   __block net::SystemCookieStore::SystemCookieCallbackForCookies
       shared_callback = std::move(callback);
   RunSystemCookieCallbackOnIOThread(base::BindBlockArc(^{
     if (weak_time_manager) {
-      NSArray* result = [static_cast<NSArray*>(block_cookies)
-          sortedArrayUsingFunction:CompareCookies
+      NSArray* result = [block_cookies
+          sortedArrayUsingFunction:net::SystemCookieStore::CompareCookies
                            context:weak_time_manager.get()];
       std::move(shared_callback).Run(result);
     } else {
diff --git a/ios/web/public/webui/web_ui_ios.h b/ios/web/public/webui/web_ui_ios.h
index e655d4d..cc97807 100644
--- a/ios/web/public/webui/web_ui_ios.h
+++ b/ios/web/public/webui/web_ui_ios.h
@@ -48,7 +48,7 @@
 
   // Used by WebUIIOSMessageHandlers. If the given message is already
   // registered, the call has no effect.
-  typedef base::Callback<void(const base::ListValue*)> MessageCallback;
+  using MessageCallback = base::RepeatingCallback<void(const base::ListValue*)>;
   virtual void RegisterMessageCallback(const std::string& message,
                                        const MessageCallback& callback) = 0;
 
diff --git a/ios/web/web_state/js/resources/all_frames_context_menu.js b/ios/web/web_state/js/resources/all_frames_context_menu.js
new file mode 100644
index 0000000..7dba93b
--- /dev/null
+++ b/ios/web/web_state/js/resources/all_frames_context_menu.js
@@ -0,0 +1,276 @@
+// Copyright 2018 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.
+
+/**
+ * @fileoverview APIs used by CRWContextMenuController.
+ */
+
+goog.provide('__crWeb.allFramesContextMenu');
+
+goog.require('__crWeb.base');
+
+/** Beginning of anonymous object */
+(function() {
+
+/**
+ * Returns an object representing the details of the given element.
+ * @param {number} x Horizontal center of the selected point in page
+ *                 coordinates.
+ * @param {number} y Vertical center of the selected point in page
+ *                 coordinates.
+ * @return {Object} null if no element was found or an object of the form {
+ *     href,  // URL of the link under the point
+ *     innerText,  // innerText of the link, if the selected element is a link
+ *     src,  // src of the image, if the selected element is an image
+ *     title,  // title of the image, if the selected
+ *     referrerPolicy
+ *   }
+ *   where:
+ *     <ul>
+ *     <li>href, innerText are set if the selected element is a link.
+ *     <li>src, title are set if the selected element is an image.
+ *     <li>href is also set if the selected element is an image with a link.
+ *     <li>referrerPolicy is the referrer policy to use for navigations away
+ *         from the current page.
+ *     </ul>
+ */
+__gCrWeb['getElementFromPointInPageCoordinates'] = function(x, y) {
+  var hitCoordinates = spiralCoordinates_(x, y);
+  for (var index = 0; index < hitCoordinates.length; index++) {
+    var coordinates = hitCoordinates[index];
+
+    var coordinateDetails = newCoordinate(coordinates.x, coordinates.y);
+    var element = elementsFromCoordinates(coordinateDetails);
+    if (!element || !element.tagName) {
+      // Nothing under the hit point. Try the next hit point.
+      continue;
+    }
+
+    // Also check element's ancestors. A bound on the level is used here to
+    // avoid large overhead when no links or images are found.
+    var level = 0;
+    while (++level < 8 && element && element != document) {
+      var tagName = element.tagName;
+      if (!tagName) continue;
+      tagName = tagName.toLowerCase();
+
+      if (tagName === 'input' || tagName === 'textarea' ||
+          tagName === 'select' || tagName === 'option') {
+        // If the element is a known input element, stop the spiral search and
+        // return empty results.
+        return {};
+      }
+
+      if (getComputedWebkitTouchCallout_(element) !== 'none') {
+        if (tagName === 'a' && element.href) {
+          // Found a link.
+          return {
+            href: element.href,
+            referrerPolicy: getReferrerPolicy_(element),
+            innerText: element.innerText
+          };
+        }
+
+        if (tagName === 'img' && element.src) {
+          // Found an image.
+          var result = {src: element.src, referrerPolicy: getReferrerPolicy_()};
+          // Copy the title, if any.
+          if (element.title) {
+            result.title = element.title;
+          }
+          // Check if the image is also a link.
+          var parent = element.parentNode;
+          while (parent) {
+            if (parent.tagName && parent.tagName.toLowerCase() === 'a' &&
+                parent.href) {
+              // This regex identifies strings like void(0),
+              // void(0)  ;void(0);, ;;;;
+              // which result in a NOP when executed as JavaScript.
+              var regex = RegExp('^javascript:(?:(?:void\\(0\\)|;)\\s*)+$');
+              if (parent.href.match(regex)) {
+                parent = parent.parentNode;
+                continue;
+              }
+              result.href = parent.href;
+              result.referrerPolicy = getReferrerPolicy_(parent);
+              break;
+            }
+            parent = parent.parentNode;
+          }
+          return result;
+        }
+      }
+      element = element.parentNode;
+    }
+  }
+  return {};
+};
+
+/**
+ * Returns whether or not view port coordinates should be used for the given
+ * window.
+ * @return {boolean} True if the window has been scrolled down or to the right,
+ *                   false otherwise.
+ */
+var elementFromPointIsUsingViewPortCoordinates = function(win) {
+  if (win.pageYOffset > 0) {  // Page scrolled down.
+    return (
+        win.document.elementFromPoint(
+            0, win.pageYOffset + win.innerHeight - 1) === null);
+  }
+  if (win.pageXOffset > 0) {  // Page scrolled to the right.
+    return (
+        win.document.elementFromPoint(
+            win.pageXOffset + win.innerWidth - 1, 0) === null);
+  }
+  return false;  // No scrolling, don't care.
+};
+
+/**
+ * Returns the coordinates of the upper left corner of |obj| in the
+ * coordinates of the window that |obj| is in.
+ * @param {HTMLElement} el The element whose coordinates will be returned.
+ * @return {!Object} coordinates of the given object.
+ */
+var getPositionInWindow = function(el) {
+  var coord = {x: 0, y: 0};
+  while (el.offsetParent) {
+    coord.x += el.offsetLeft;
+    coord.y += el.offsetTop;
+    el = el.offsetParent;
+  }
+  return coord;
+};
+
+/**
+ * Returns details about a given coordinate in {@code window}.
+ * @param {number} x The x component of the coordinate in {@code window}.
+ * @param {number} y The y component of the coordinate in {@code window}.
+ * @return {!Object} Details about the given coordinate and the current window.
+ */
+var newCoordinate = function(x, y) {
+  var coordinates = {
+    x: x,
+    y: y,
+    viewPortX: x - window.pageXOffset,
+    viewPortY: y - window.pageYOffset,
+    useViewPortCoordinates: false,
+    window: window
+  };
+  return coordinates;
+};
+
+/**
+ * Returns the element at the given coordinates.
+ * @param {Object} coordinates Page coordinates in the same format as the result
+ *                             from {@code newCoordinate}.
+ */
+var elementsFromCoordinates = function(coordinates) {
+  coordinates.useViewPortCoordinates = coordinates.useViewPortCoordinates ||
+      elementFromPointIsUsingViewPortCoordinates(coordinates.window);
+
+  var currentElement = null;
+  if (coordinates.useViewPortCoordinates) {
+    currentElement = coordinates.window.document.elementFromPoint(
+        coordinates.viewPortX, coordinates.viewPortY);
+  } else {
+    currentElement = coordinates.window.document.elementFromPoint(
+        coordinates.x, coordinates.y);
+  }
+  // We have to check for tagName, because if a selection is made by the
+  // UIWebView, the element we will get won't have one.
+  if (!currentElement || !currentElement.tagName) {
+    return null;
+  }
+  if (currentElement.tagName.toLowerCase() === 'iframe' ||
+      currentElement.tagName.toLowerCase() === 'frame') {
+    // Check if the frame is in a different domain using only information
+    // visible to the current frame (i.e. currentElement.src) to avoid
+    // triggering a SecurityError in the console.
+    if (!__gCrWeb.common.isSameOrigin(
+        window.location.href, currentElement.src)) {
+      return currentElement;
+    }
+    var framePosition = getPositionInWindow(currentElement);
+    coordinates.viewPortX -= framePosition.x - coordinates.window.pageXOffset;
+    coordinates.viewPortY -= framePosition.y - coordinates.window.pageYOffset;
+    coordinates.window = currentElement.contentWindow;
+    coordinates.x -= framePosition.x + coordinates.window.pageXOffset;
+    coordinates.y -= framePosition.y + coordinates.window.pageYOffset;
+    return elementsFromCoordinates(coordinates);
+  }
+  return currentElement;
+};
+
+/** @private
+ * @param {number} x
+ * @param {number} y
+ * @return {Object}
+ */
+var spiralCoordinates_ = function(x, y) {
+  var MAX_ANGLE = Math.PI * 2.0 * 3.0;
+  var POINT_COUNT = 30;
+  var ANGLE_STEP = MAX_ANGLE / POINT_COUNT;
+  var TOUCH_MARGIN = 25;
+  var SPEED = TOUCH_MARGIN / MAX_ANGLE;
+
+  var coordinates = [];
+  for (var index = 0; index < POINT_COUNT; index++) {
+    var angle = ANGLE_STEP * index;
+    var radius = angle * SPEED;
+
+    coordinates.push({
+      x: x + Math.round(Math.cos(angle) * radius),
+      y: y + Math.round(Math.sin(angle) * radius)
+    });
+  }
+
+  return coordinates;
+};
+
+/** @private
+ * @param {HTMLElement} element
+ * @return {Object}
+ */
+var getComputedWebkitTouchCallout_ = function(element) {
+  return window.getComputedStyle(element, null)['webkitTouchCallout'];
+};
+
+/**
+ * Gets the referrer policy to use for navigations away from the current page.
+ * If a link element is passed, and it includes a rel=noreferrer tag, that
+ * will override the page setting.
+ * @param {HTMLElement=} opt_linkElement The link triggering the navigation.
+ * @return {string} The policy string.
+ * @private
+ */
+var getReferrerPolicy_ = function(opt_linkElement) {
+  if (opt_linkElement) {
+    var rel = opt_linkElement.getAttribute('rel');
+    if (rel && rel.toLowerCase() == 'noreferrer') {
+      return 'never';
+    }
+  }
+
+  // Search for referrer meta tag.  WKWebView only supports a subset of values
+  // for referrer meta tags.  If it parses a referrer meta tag with an
+  // unsupported value, it will default to 'never'.
+  var metaTags = document.getElementsByTagName('meta');
+  for (var i = 0; i < metaTags.length; ++i) {
+    if (metaTags[i].name.toLowerCase() == 'referrer') {
+      var referrerPolicy = metaTags[i].content.toLowerCase();
+      if (referrerPolicy == 'default' || referrerPolicy == 'always' ||
+          referrerPolicy == 'no-referrer' || referrerPolicy == 'origin' ||
+          referrerPolicy == 'no-referrer-when-downgrade' ||
+          referrerPolicy == 'unsafe-url') {
+        return referrerPolicy;
+      } else {
+        return 'never';
+      }
+    }
+  }
+  return 'default';
+};
+
+}());  // End of anonymouse object
diff --git a/ios/web/web_state/js/resources/all_frames_web_bundle.js b/ios/web/web_state/js/resources/all_frames_web_bundle.js
index de81c0a1..704c4dc 100644
--- a/ios/web/web_state/js/resources/all_frames_web_bundle.js
+++ b/ios/web/web_state/js/resources/all_frames_web_bundle.js
@@ -5,6 +5,7 @@
 // Set of scripts required by web layer backed up by WKWebView.
 goog.provide('__crWeb.allFramesWebBundle');
 
+goog.require('__crWeb.allFramesContextMenu');
 goog.require('__crWeb.base');
 goog.require('__crWeb.common');
 goog.require('__crWeb.message');
diff --git a/ios/web/web_state/js/resources/context_menu.js b/ios/web/web_state/js/resources/context_menu.js
deleted file mode 100644
index 8327c38..0000000
--- a/ios/web/web_state/js/resources/context_menu.js
+++ /dev/null
@@ -1,347 +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.
-
-/**
- * @fileoverview APIs used by CRWContextMenuController.
- */
-
-goog.provide('__crWeb.contextMenu');
-
-/** Beginning of anonymous object */
-(function() {
-
-/**
- * Finds the url of the image or link under the selected point. Sends the
- * found element (or an empty object if no links or images are found) back to
- * the application by posting a 'FindElementResultHandler' message.
- * The object returned in the message is an object of the form {
- *     requestID,  // identifier as passed to this function
- *     href,  // URL of the link under the point
- *     innerText,  // innerText of the link, if the selected element is a link
- *     src,  // src of the image, if the selected element is an image
- *     title,  // title of the image, if the selected
- *     referrerPolicy
- *   }
- *   where:
- *     <ul>
- *     <li>requestID is the value of the identifier passed to this function.
- *     <li>href, innerText are set if the selected element is a link.
- *     <li>src, title are set if the selected element is an image.
- *     <li>href is also set if the selected element is an image with a link.
- *     <li>referrerPolicy is the referrer policy to use for navigations away
- *         from the current page.
- *     </ul>
- * @param {string} identifier An identifier which be returned in the result
- *                 dictionary of this request.
- * @param {number} x Horizontal center of the selected point in web view
- *                 coordinates.
- * @param {number} y Vertical center of the selected point in web view
- *                 coordinates.
- * @param {number} webViewWidth the width of web view.
- * @param {number} webViewHeight the height of web view.
- */
-__gCrWeb['findElementAtPoint'] =
-    function(requestID, x, y, webViewWidth, webViewHeight) {
-      var scale = getPageWidth() / webViewWidth;
-      var result = getElementFromPointInPageCoordinates(x * scale, y * scale);
-      result.requestID = requestID;
-      __gCrWeb.common.sendWebKitMessage('FindElementResultHandler', result);
-    };
-
-/**
- * Returns the url of the image or link under the selected point. Returns an
- * empty object if no links or images are found.
- * @param {number} x Horizontal center of the selected point in web view
- *                   coordinates.
- * @param {number} y Vertical center of the selected point in web view
- *                 coordinates.
- * @param {number} webViewWidth the width of web view.
- * @param {number} webViewHeight the height of web view.
- * @return {!Object} An object of the form {
- *     href,  // URL of the link under the point
- *     innerText,  // innerText of the link, if the selected element is a link
- *     src,  // src of the image, if the selected element is an image
- *     title,  // title of the image, if the selected
- *     referrerPolicy
- *   }
- *   where:
- *     <ul>
- *     <li>href, innerText are set if the selected element is a link.
- *     <li>src, title are set if the selected element is an image.
- *     <li>href is also set if the selected element is an image with a link.
- *     <li>referrerPolicy is the referrer policy to use for navigations away
- *         from the current page.
- *     </ul>
- */
-__gCrWeb['getElementFromPoint'] = function(x, y, webViewWidth, webViewHeight) {
-  var scale = getPageWidth() / webViewWidth;
-  return getElementFromPointInPageCoordinates(x * scale, y * scale);
-};
-
-/**
- * Suppresses the next click such that they are not handled by JS click
- * event handlers.
- * @type {void}
- */
-__gCrWeb['suppressNextClick'] = function() {
-  var suppressNextClick = function(evt) {
-    evt.preventDefault();
-    document.removeEventListener('click', suppressNextClick, false);
-  };
-  document.addEventListener('click', suppressNextClick);
-};
-
-/**
- * Returns the url of the image or link under the selected point in page
- * coordinates. Returns an empty object if no links or images are found.
- * @param {number} x Horizontal center of the selected point in page
- *                 coordinates.
- * @param {number} y Vertical center of the selected point in page
- *                 coordinates.
- * @return {!Object} An object in the same form as
- *                   {@code getElementFromPoint} result.
- */
-var getElementFromPointInPageCoordinates = function(x, y) {
-  var hitCoordinates = spiralCoordinates_(x, y);
-  for (var index = 0; index < hitCoordinates.length; index++) {
-    var coordinates = hitCoordinates[index];
-
-    var element = elementFromPoint_(coordinates.x, coordinates.y);
-    if (!element || !element.tagName) {
-      // Nothing under the hit point. Try the next hit point.
-      continue;
-    }
-
-    // Also check element's ancestors. A bound on the level is used here to
-    // avoid large overhead when no links or images are found.
-    var level = 0;
-    while (++level < 8 && element && element != document) {
-      var tagName = element.tagName;
-      if (!tagName) continue;
-      tagName = tagName.toLowerCase();
-
-      if (tagName === 'input' || tagName === 'textarea' ||
-          tagName === 'select' || tagName === 'option') {
-        // If the element is a known input element, stop the spiral search and
-        // return empty results.
-        return {};
-      }
-
-      if (getComputedWebkitTouchCallout_(element) !== 'none') {
-        if (tagName === 'a' && element.href) {
-          // Found a link.
-          return {
-            href: element.href,
-            referrerPolicy: getReferrerPolicy_(element),
-            innerText: element.innerText
-          };
-        }
-
-        if (tagName === 'img' && element.src) {
-          // Found an image.
-          var result = {src: element.src, referrerPolicy: getReferrerPolicy_()};
-          // Copy the title, if any.
-          if (element.title) {
-            result.title = element.title;
-          }
-          // Check if the image is also a link.
-          var parent = element.parentNode;
-          while (parent) {
-            if (parent.tagName && parent.tagName.toLowerCase() === 'a' &&
-                parent.href) {
-              // This regex identifies strings like void(0),
-              // void(0)  ;void(0);, ;;;;
-              // which result in a NOP when executed as JavaScript.
-              var regex = RegExp('^javascript:(?:(?:void\\(0\\)|;)\\s*)+$');
-              if (parent.href.match(regex)) {
-                parent = parent.parentNode;
-                continue;
-              }
-              result.href = parent.href;
-              result.referrerPolicy = getReferrerPolicy_(parent);
-              break;
-            }
-            parent = parent.parentNode;
-          }
-          return result;
-        }
-      }
-      element = element.parentNode;
-    }
-  }
-  return {};
-};
-
-/**
- * Returns the margin in points around touchable elements (e.g. links for
- * custom context menu).
- * @type {number}
- */
-var getPageWidth = function() {
-  var documentElement = document.documentElement;
-  var documentBody = document.body;
-  return Math.max(
-      documentElement.clientWidth, documentElement.scrollWidth,
-      documentElement.offsetWidth, documentBody.scrollWidth,
-      documentBody.offsetWidth);
-};
-
-/**
- * Implementation of document.elementFromPoint that is working for iOS4 and
- * iOS5 and that also goes into frames and iframes.
- * @private
- * @param {number} x
- * @param {number} y
- * @return {HTMLElement | boolean}
- */
-var elementFromPoint_ = function(x, y) {
-  var elementFromPointIsUsingViewPortCoordinates = function(win) {
-    if (win.pageYOffset > 0) {  // Page scrolled down.
-      return (
-          win.document.elementFromPoint(
-              0, win.pageYOffset + win.innerHeight - 1) === null);
-    }
-    if (win.pageXOffset > 0) {  // Page scrolled to the right.
-      return (
-          win.document.elementFromPoint(
-              win.pageXOffset + win.innerWidth - 1, 0) === null);
-    }
-    return false;  // No scrolling, don't care.
-  };
-
-  var newCoordinate = function(x, y) {
-    var coordinates = {
-      x: x,
-      y: y,
-      viewPortX: x - window.pageXOffset,
-      viewPortY: y - window.pageYOffset,
-      useViewPortCoordinates: false,
-      window: window
-    };
-    return coordinates;
-  };
-
-  // Returns the coordinates of the upper left corner of |obj| in the
-  // coordinates of the window that |obj| is in.
-  var getPositionInWindow = function(obj) {
-    var coord = {x: 0, y: 0};
-    while (obj.offsetParent) {
-      coord.x += obj.offsetLeft;
-      coord.y += obj.offsetTop;
-      obj = obj.offsetParent;
-    }
-    return coord;
-  };
-
-  var elementsFromCoordinates = function(coordinates) {
-    coordinates.useViewPortCoordinates = coordinates.useViewPortCoordinates ||
-        elementFromPointIsUsingViewPortCoordinates(coordinates.window);
-
-    var currentElement = null;
-    if (coordinates.useViewPortCoordinates) {
-      currentElement = coordinates.window.document.elementFromPoint(
-          coordinates.viewPortX, coordinates.viewPortY);
-    } else {
-      currentElement = coordinates.window.document.elementFromPoint(
-          coordinates.x, coordinates.y);
-    }
-    // We have to check for tagName, because if a selection is made by the
-    // UIWebView, the element we will get won't have one.
-    if (!currentElement || !currentElement.tagName) {
-      return null;
-    }
-    if (currentElement.tagName.toLowerCase() === 'iframe' ||
-        currentElement.tagName.toLowerCase() === 'frame') {
-      // Check if the frame is in a different domain using only information
-      // visible to the current frame (i.e. currentElement.src) to avoid
-      // triggering a SecurityError in the console.
-      if (!__gCrWeb.common.isSameOrigin(
-              window.location.href, currentElement.src)) {
-        return currentElement;
-      }
-      var framePosition = getPositionInWindow(currentElement);
-      coordinates.viewPortX -= framePosition.x - coordinates.window.pageXOffset;
-      coordinates.viewPortY -= framePosition.y - coordinates.window.pageYOffset;
-      coordinates.window = currentElement.contentWindow;
-      coordinates.x -= framePosition.x + coordinates.window.pageXOffset;
-      coordinates.y -= framePosition.y + coordinates.window.pageYOffset;
-      return elementsFromCoordinates(coordinates);
-    }
-    return currentElement;
-  };
-
-  return elementsFromCoordinates(newCoordinate(x, y));
-};
-
-/** @private
- * @param {number} x
- * @param {number} y
- * @return {Object}
- */
-var spiralCoordinates_ = function(x, y) {
-  var MAX_ANGLE = Math.PI * 2.0 * 3.0;
-  var POINT_COUNT = 30;
-  var ANGLE_STEP = MAX_ANGLE / POINT_COUNT;
-  var TOUCH_MARGIN = 25;
-  var SPEED = TOUCH_MARGIN / MAX_ANGLE;
-
-  var coordinates = [];
-  for (var index = 0; index < POINT_COUNT; index++) {
-    var angle = ANGLE_STEP * index;
-    var radius = angle * SPEED;
-
-    coordinates.push({
-      x: x + Math.round(Math.cos(angle) * radius),
-      y: y + Math.round(Math.sin(angle) * radius)
-    });
-  }
-
-  return coordinates;
-};
-
-/** @private
- * @param {HTMLElement} element
- * @return {Object}
- */
-var getComputedWebkitTouchCallout_ = function(element) {
-  return window.getComputedStyle(element, null)['webkitTouchCallout'];
-};
-
-/**
- * Gets the referrer policy to use for navigations away from the current page.
- * If a link element is passed, and it includes a rel=noreferrer tag, that
- * will override the page setting.
- * @param {HTMLElement=} opt_linkElement The link triggering the navigation.
- * @return {string} The policy string.
- * @private
- */
-var getReferrerPolicy_ = function(opt_linkElement) {
-  if (opt_linkElement) {
-    var rel = opt_linkElement.getAttribute('rel');
-    if (rel && rel.toLowerCase() == 'noreferrer') {
-      return 'never';
-    }
-  }
-
-  // Search for referrer meta tag.  WKWebView only supports a subset of values
-  // for referrer meta tags.  If it parses a referrer meta tag with an
-  // unsupported value, it will default to 'never'.
-  var metaTags = document.getElementsByTagName('meta');
-  for (var i = 0; i < metaTags.length; ++i) {
-    if (metaTags[i].name.toLowerCase() == 'referrer') {
-      var referrerPolicy = metaTags[i].content.toLowerCase();
-      if (referrerPolicy == 'default' || referrerPolicy == 'always' ||
-          referrerPolicy == 'no-referrer' || referrerPolicy == 'origin' ||
-          referrerPolicy == 'no-referrer-when-downgrade' ||
-          referrerPolicy == 'unsafe-url') {
-        return referrerPolicy;
-      } else {
-        return 'never';
-      }
-    }
-  }
-  return 'default';
-};
-
-}());  // End of anonymouse object
diff --git a/ios/web/web_state/js/resources/main_frame_context_menu.js b/ios/web/web_state/js/resources/main_frame_context_menu.js
new file mode 100644
index 0000000..efedf28
--- /dev/null
+++ b/ios/web/web_state/js/resources/main_frame_context_menu.js
@@ -0,0 +1,84 @@
+// 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.
+
+/**
+ * @fileoverview APIs used by CRWContextMenuController.
+ */
+
+goog.provide('__crWeb.mainFrameContextMenu');
+
+// Requires __crWeb.allFramesContextMenu provided by __crWeb.allFramesWebBundle.
+
+/** Beginning of anonymous object */
+(function() {
+
+/**
+ * Finds the url of the image or link under the selected point. Sends the
+ * found element (or an empty object if no links or images are found) back to
+ * the application by posting a 'FindElementResultHandler' message.
+ * The object returned in the message is of the same form as
+ * {@code getElementFromPointInPageCoordinates} result.
+ * @param {string} identifier An identifier which be returned in the result
+ *                 dictionary of this request.
+ * @param {number} x Horizontal center of the selected point in web view
+ *                 coordinates.
+ * @param {number} y Vertical center of the selected point in web view
+ *                 coordinates.
+ * @param {number} webViewWidth the width of web view.
+ * @param {number} webViewHeight the height of web view.
+ */
+__gCrWeb['findElementAtPoint'] =
+    function(requestID, x, y, webViewWidth, webViewHeight) {
+      var scale = getPageWidth() / webViewWidth;
+      var result =
+          __gCrWeb.getElementFromPointInPageCoordinates(x * scale, y * scale);
+      result.requestID = requestID;
+      __gCrWeb.common.sendWebKitMessage('FindElementResultHandler', result);
+    };
+
+/**
+ * Returns the url of the image or link under the selected point. Returns an
+ * empty object if no links or images are found.
+ * @param {number} x Horizontal center of the selected point in web view
+ *                   coordinates.
+ * @param {number} y Vertical center of the selected point in web view
+ *                 coordinates.
+ * @param {number} webViewWidth the width of web view.
+ * @param {number} webViewHeight the height of web view.
+ * @return {!Object} An object in the same form as
+ *                   {@code getElementFromPointInPageCoordinates} result.
+ */
+__gCrWeb['getElementFromPoint'] = function(x, y, webViewWidth, webViewHeight) {
+  var scale = getPageWidth() / webViewWidth;
+  return __gCrWeb.getElementFromPointInPageCoordinates(x * scale, y * scale);
+};
+
+/**
+ * Suppresses the next click such that they are not handled by JS click
+ * event handlers.
+ * @type {void}
+ */
+__gCrWeb['suppressNextClick'] = function() {
+  var suppressNextClick = function(evt) {
+    evt.preventDefault();
+    document.removeEventListener('click', suppressNextClick, false);
+  };
+  document.addEventListener('click', suppressNextClick);
+};
+
+/**
+ * Returns the margin in points around touchable elements (e.g. links for
+ * custom context menu).
+ * @type {number}
+ */
+var getPageWidth = function() {
+  var documentElement = document.documentElement;
+  var documentBody = document.body;
+  return Math.max(
+      documentElement.clientWidth, documentElement.scrollWidth,
+      documentElement.offsetWidth, documentBody.scrollWidth,
+      documentBody.offsetWidth);
+};
+
+}());  // End of anonymouse object
diff --git a/ios/web/web_state/js/resources/main_frame_web_bundle.js b/ios/web/web_state/js/resources/main_frame_web_bundle.js
index e8314e75..1434758 100644
--- a/ios/web/web_state/js/resources/main_frame_web_bundle.js
+++ b/ios/web/web_state/js/resources/main_frame_web_bundle.js
@@ -8,8 +8,8 @@
 // Requires __crWeb.form provided by __crWeb.allFramesWebBundle.
 
 goog.require('__crWeb.console');
-goog.require('__crWeb.contextMenu');
 goog.require('__crWeb.error');
 goog.require('__crWeb.legacy');
+goog.require('__crWeb.mainFrameContextMenu');
 goog.require('__crWeb.navigation');
 goog.require('__crWeb.scrollWorkaround');
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm
index 64bec7d7..557788e 100644
--- a/ios/web/web_state/ui/crw_web_controller.mm
+++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -1912,6 +1912,10 @@
 - (GURL)webURLWithTrustLevel:(web::URLVerificationTrustLevel*)trustLevel {
   DCHECK(trustLevel);
   *trustLevel = web::URLVerificationTrustLevel::kAbsolute;
+  // Placeholder URL is an implementation detail. Don't expose it to users of
+  // web layer.
+  if (IsPlaceholderUrl(_documentURL))
+    return ExtractUrlFromPlaceholderUrl(_documentURL);
   return _documentURL;
 }
 
@@ -4929,11 +4933,28 @@
 }
 
 - (void)webViewLoadingStateDidChange {
-  if ([_webView isLoading] || ![self isCurrentNavigationBackForward]) {
+  if (_webView.loading)
+    return;
+
+  GURL webViewURL = net::GURLWithNSURL([_webView URL]);
+
+  // When traversing history restored from a previous session, WKWebView does
+  // not fire 'pageshow', 'onload', 'popstate' or any of the
+  // WKNavigationDelegate callbacks for back/forward navigation from an
+  // app-specific URL to another entry. Loading state KVO is the only observable
+  // event in this scenario, so force a reload to trigger redirect from
+  // restore_session.html to the restored URL.
+  bool previousURLIsAppSpecific =
+      IsPlaceholderUrl(_documentURL) ||
+      web::GetWebClient()->IsAppSpecificURL(_documentURL);
+  if (web::GetWebClient()->IsSlimNavigationManagerEnabled() &&
+      web::IsRestoreSessionUrl(webViewURL) && previousURLIsAppSpecific) {
+    [_webView reload];
     return;
   }
 
-  GURL webViewURL = net::GURLWithNSURL([_webView URL]);
+  if (![self isCurrentNavigationBackForward])
+    return;
 
   // For failed navigations, WKWebView will sometimes revert to the previous URL
   // before committing the current navigation or resetting the web view's
diff --git a/ipc/BUILD.gn b/ipc/BUILD.gn
index 0d9d726..b8839e3 100644
--- a/ipc/BUILD.gn
+++ b/ipc/BUILD.gn
@@ -10,8 +10,8 @@
 import("//tools/ipc_fuzzer/ipc_fuzzer.gni")
 import("//third_party/protobuf/proto_library.gni")
 
-buildflag_header("ipc_features") {
-  header = "ipc_features.h"
+buildflag_header("ipc_buildflags") {
+  header = "ipc_buildflags.h"
 
   flags = [ "IPC_MESSAGE_LOG_ENABLED=$enable_ipc_logging" ]
 }
@@ -78,7 +78,7 @@
   defines = [ "IS_IPC_IMPL" ]
 
   public_deps = [
-    ":ipc_features",
+    ":ipc_buildflags",
     ":message_support",
     ":mojom",
     ":native_handle_type_converters",
@@ -143,7 +143,7 @@
   defines = [ "IPC_MESSAGE_SUPPORT_IMPL" ]
 
   public_deps = [
-    ":ipc_features",
+    ":ipc_buildflags",
     ":param_traits",
     "//base",
     "//mojo/public/cpp/system",
diff --git a/ipc/ipc_logging.h b/ipc/ipc_logging.h
index 68b8e9ba..eee32f6 100644
--- a/ipc/ipc_logging.h
+++ b/ipc/ipc_logging.h
@@ -5,7 +5,7 @@
 #ifndef IPC_IPC_LOGGING_H_
 #define IPC_IPC_LOGGING_H_
 
-#include "ipc/ipc_features.h"
+#include "ipc/ipc_buildflags.h"
 
 #if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
 
diff --git a/ipc/ipc_message.h b/ipc/ipc_message.h
index d1ea54e..d83e0132 100644
--- a/ipc/ipc_message.h
+++ b/ipc/ipc_message.h
@@ -15,7 +15,7 @@
 #include "base/pickle.h"
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
-#include "ipc/ipc_features.h"
+#include "ipc/ipc_buildflags.h"
 #include "ipc/ipc_message_support_export.h"
 
 namespace mojo {
diff --git a/media/BUILD.gn b/media/BUILD.gn
index 5a22535..a5d98ccd 100644
--- a/media/BUILD.gn
+++ b/media/BUILD.gn
@@ -13,8 +13,8 @@
 import("//testing/test.gni")
 import("//third_party/ffmpeg/ffmpeg_options.gni")
 
-buildflag_header("media_features") {
-  header = "media_features.h"
+buildflag_header("media_buildflags") {
+  header = "media_buildflags.h"
 
   flags = [
     "ALTERNATE_CDM_STORAGE_ID_KEY=$alternate_cdm_storage_id_key",
@@ -103,7 +103,7 @@
   public_configs = [ "//third_party/libwebm:libwebm_config" ]
   public_deps = media_subcomponent_deps
   public_deps += [
-    ":media_features",
+    ":media_buildflags",
     ":shared_memory_support",
     "//ui/gfx:color_space",
   ]
diff --git a/media/audio/audio_manager.cc b/media/audio/audio_manager.cc
index edeff13..0dd9887 100644
--- a/media/audio/audio_manager.cc
+++ b/media/audio/audio_manager.cc
@@ -353,4 +353,22 @@
   return true;
 }
 
+void AudioManager::SetDiverterCallbacks(
+    AddDiverterCallback add_callback,
+    RemoveDiverterCallback remove_callback) {
+  add_diverter_callback_ = std::move(add_callback);
+  remove_diverter_callback_ = std::move(remove_callback);
+}
+
+void AudioManager::AddDiverter(const base::UnguessableToken& group_id,
+                               media::AudioSourceDiverter* diverter) {
+  if (!add_diverter_callback_.is_null())
+    add_diverter_callback_.Run(group_id, diverter);
+}
+
+void AudioManager::RemoveDiverter(media::AudioSourceDiverter* diverter) {
+  if (!remove_diverter_callback_.is_null())
+    remove_diverter_callback_.Run(diverter);
+}
+
 }  // namespace media
diff --git a/media/audio/audio_manager.h b/media/audio/audio_manager.h
index 9b419ea5..12d9e0c 100644
--- a/media/audio/audio_manager.h
+++ b/media/audio/audio_manager.h
@@ -8,7 +8,7 @@
 #include <memory>
 #include <string>
 
-#include "base/callback_forward.h"
+#include "base/callback.h"
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
@@ -21,6 +21,7 @@
 
 namespace base {
 class SingleThreadTaskRunner;
+class UnguessableToken;
 }
 
 namespace media {
@@ -29,6 +30,7 @@
 class AudioInputStream;
 class AudioManager;
 class AudioOutputStream;
+class AudioSourceDiverter;
 
 // Manages all audio resources.  Provides some convenience functions that avoid
 // the need to provide iterators over the existing streams.
@@ -184,6 +186,23 @@
   // Limits the number of streams that can be created for testing purposes.
   virtual void SetMaxStreamCountForTesting(int max_input, int max_output);
 
+  // TODO(crbug/824019): The following are temporary, as a middle-ground step
+  // necessary to resolve a chicken-and-egg problem as we migrate audio
+  // mirroring into the new AudioService. Add/RemoveDiverter() allow
+  // AudioOutputController to (de)register itself as an AudioSourceDiverter,
+  // while SetDiverterCallbacks() allows the entity that is interested in such
+  // notifications to receive them.
+  using AddDiverterCallback =
+      base::RepeatingCallback<void(const base::UnguessableToken&,
+                                   media::AudioSourceDiverter*)>;
+  using RemoveDiverterCallback =
+      base::RepeatingCallback<void(media::AudioSourceDiverter*)>;
+  virtual void SetDiverterCallbacks(AddDiverterCallback add_callback,
+                                    RemoveDiverterCallback remove_callback);
+  virtual void AddDiverter(const base::UnguessableToken& group_id,
+                           media::AudioSourceDiverter* diverter);
+  virtual void RemoveDiverter(media::AudioSourceDiverter* diverter);
+
  protected:
   FRIEND_TEST_ALL_PREFIXES(AudioManagerTest, AudioDebugRecording);
   friend class AudioDeviceInfoAccessorForTests;
@@ -265,6 +284,9 @@
   std::unique_ptr<AudioThread> audio_thread_;
   bool shutdown_ = false;  // True after |this| has been shutdown.
 
+  AddDiverterCallback add_diverter_callback_;
+  RemoveDiverterCallback remove_diverter_callback_;
+
   THREAD_CHECKER(thread_checker_);
   DISALLOW_COPY_AND_ASSIGN(AudioManager);
 };
diff --git a/media/audio/audio_manager_base.cc b/media/audio/audio_manager_base.cc
index 83a1239..04445f2 100644
--- a/media/audio/audio_manager_base.cc
+++ b/media/audio/audio_manager_base.cc
@@ -515,16 +515,27 @@
     const std::string& output_device_id) {
   if (output_device_id == AudioDeviceDescription::kDefaultDeviceId) {
     std::string real_device_id = GetDefaultOutputDeviceID();
-    if (!real_device_id.empty()) {
+    if (!real_device_id.empty())
       return real_device_id;
-    }
+  } else if (output_device_id ==
+             AudioDeviceDescription::kCommunicationsDeviceId) {
+    std::string real_device_id = GetCommunicationsOutputDeviceID();
+    if (!real_device_id.empty())
+      return real_device_id;
   }
   return output_device_id;
 }
 
 std::string AudioManagerBase::GetGroupIDInput(
     const std::string& input_device_id) {
-  std::string output_device_id = GetAssociatedOutputDeviceID(input_device_id);
+  const std::string& real_input_device_id =
+      input_device_id == AudioDeviceDescription::kDefaultDeviceId
+          ? GetDefaultInputDeviceID()
+          : input_device_id == AudioDeviceDescription::kCommunicationsDeviceId
+                ? GetCommunicationsInputDeviceID()
+                : input_device_id;
+  std::string output_device_id =
+      GetAssociatedOutputDeviceID(real_input_device_id);
   if (output_device_id.empty()) {
     // Some characters are added to avoid accidentally
     // giving the input the same group id as an output.
diff --git a/media/audio/audio_manager_unittest.cc b/media/audio/audio_manager_unittest.cc
index 720df56..71db2ec 100644
--- a/media/audio/audio_manager_unittest.cc
+++ b/media/audio/audio_manager_unittest.cc
@@ -180,10 +180,10 @@
                               0);
 #endif  // defined(USE_CRAS)
 
-const char kRealDefaultInputDeviceID[] = "input3";
-const char kRealDefaultOutputDeviceID[] = "output4";
-const char kRealCommunicationsInputDeviceID[] = "input2";
-const char kRealCommunicationsOutputDeviceID[] = "output2";
+const char kRealDefaultInputDeviceID[] = "input2";
+const char kRealDefaultOutputDeviceID[] = "output3";
+const char kRealCommunicationsInputDeviceID[] = "input1";
+const char kRealCommunicationsOutputDeviceID[] = "output1";
 
 void CheckDescriptionLabels(const AudioDeviceDescriptions& descriptions,
                             const std::string& real_default_id,
@@ -632,51 +632,64 @@
       const std::string& input_id) override {
     if (input_id == "input1")
       return "output1";
-    if (input_id == "input2")
+    DCHECK_EQ(std::string(kRealDefaultInputDeviceID), "input2");
+    if (input_id == AudioDeviceDescription::kDefaultDeviceId ||
+        input_id == kRealDefaultInputDeviceID)
       return "output2";
-    if (input_id == "default")
-      return "output1";
-    return "";
+    return std::string();
   }
 
  private:
   void GetAudioInputDeviceNames(AudioDeviceNames* device_names) override {
+    DCHECK(device_names->empty());
+    device_names->emplace_back(AudioDeviceName::CreateDefault());
     device_names->emplace_back("Input 1", "input1");
     device_names->emplace_back("Input 2", "input2");
     device_names->emplace_back("Input 3", "input3");
-    device_names->push_front(AudioDeviceName::CreateDefault());
   }
 
   void GetAudioOutputDeviceNames(AudioDeviceNames* device_names) override {
+    DCHECK(device_names->empty());
+    device_names->emplace_back(AudioDeviceName::CreateDefault());
     device_names->emplace_back("Output 1", "output1");
     device_names->emplace_back("Output 2", "output2");
     device_names->emplace_back("Output 3", "output3");
-    device_names->emplace_back("Output 4", "output4");
-    device_names->push_front(AudioDeviceName::CreateDefault());
   }
 };
 
 TEST_F(AudioManagerTest, GroupId) {
   CreateAudioManagerForTesting<TestAudioManager>();
   // Groups:
-  // input1, output1, default input
-  // input2, output2
-  // input3,
-  // output3
-  // output4, default output
+  // input1, output1
+  // input2, output2, default input
+  // input3
+  // output3, default output
   AudioDeviceDescriptions inputs;
   device_info_accessor_->GetAudioInputDeviceDescriptions(&inputs);
   AudioDeviceDescriptions outputs;
   device_info_accessor_->GetAudioOutputDeviceDescriptions(&outputs);
-  EXPECT_EQ(inputs[0].group_id, outputs[1].group_id);
+  // default input
+  EXPECT_EQ(inputs[0].group_id, outputs[2].group_id);
+  // default input and default output are not associated
+  EXPECT_NE(inputs[0].group_id, outputs[0].group_id);
+
+  // default output
+  EXPECT_EQ(outputs[0].group_id, outputs[3].group_id);
+
+  // real inputs and outputs that are associated
   EXPECT_EQ(inputs[1].group_id, outputs[1].group_id);
   EXPECT_EQ(inputs[2].group_id, outputs[2].group_id);
+
+  // real inputs and outputs that are not associated
   EXPECT_NE(inputs[3].group_id, outputs[3].group_id);
-  EXPECT_EQ(outputs[4].group_id, outputs[0].group_id);
-  EXPECT_NE(inputs[0].group_id, outputs[0].group_id);
-  EXPECT_NE(inputs[1].group_id, outputs[2].group_id);
-  EXPECT_NE(inputs[2].group_id, outputs[3].group_id);
-  EXPECT_NE(inputs[1].group_id, outputs[3].group_id);
+
+  // group IDs of different devices should differ.
+  EXPECT_NE(inputs[1].group_id, inputs[2].group_id);
+  EXPECT_NE(inputs[1].group_id, inputs[3].group_id);
+  EXPECT_NE(inputs[2].group_id, inputs[3].group_id);
+  EXPECT_NE(outputs[1].group_id, outputs[2].group_id);
+  EXPECT_NE(outputs[1].group_id, outputs[3].group_id);
+  EXPECT_NE(outputs[2].group_id, outputs[3].group_id);
 }
 
 TEST_F(AudioManagerTest, DefaultCommunicationsLabelsContainRealLabels) {
diff --git a/media/audio/audio_output_controller.cc b/media/audio/audio_output_controller.cc
index 3b41689b..e017324 100644
--- a/media/audio/audio_output_controller.cc
+++ b/media/audio/audio_output_controller.cc
@@ -126,6 +126,7 @@
     EventHandler* event_handler,
     const AudioParameters& params,
     const std::string& output_device_id,
+    const base::UnguessableToken& group_id,
     SyncReader* sync_reader) {
   CHECK(audio_manager);
   CHECK_EQ(AudioManager::Get(), audio_manager);
@@ -137,12 +138,14 @@
 
   if (controller->task_runner_->BelongsToCurrentThread()) {
     controller->DoCreate(false);
+    audio_manager->AddDiverter(group_id, controller.get());
     return controller;
   }
 
   controller->task_runner_->PostTask(
       FROM_HERE,
       base::BindOnce(&AudioOutputController::DoCreate, controller, false));
+  audio_manager->AddDiverter(group_id, controller.get());
   return controller;
 }
 
@@ -179,13 +182,24 @@
   if (task_runner_->BelongsToCurrentThread()) {
     DCHECK(closed_task.is_null());
     DoClose();
+    audio_manager_->RemoveDiverter(this);
     return;
   }
 
   DCHECK(!closed_task.is_null());
   task_runner_->PostTaskAndReply(
       FROM_HERE, base::BindOnce(&AudioOutputController::DoClose, this),
-      std::move(closed_task));
+      base::BindOnce(
+          [](scoped_refptr<AudioOutputController> controller,
+             base::OnceClosure closed_task) {
+            DCHECK_CALLED_ON_VALID_SEQUENCE(controller->owning_sequence_);
+
+            controller->audio_manager_->RemoveDiverter(controller.get());
+            controller = nullptr;
+
+            std::move(closed_task).Run();
+          },
+          base::WrapRefCounted(this), std::move(closed_task)));
 }
 
 void AudioOutputController::SetVolume(double volume) {
diff --git a/media/audio/audio_output_controller.h b/media/audio/audio_output_controller.h
index d4634e8..8c8afe5 100644
--- a/media/audio/audio_output_controller.h
+++ b/media/audio/audio_output_controller.h
@@ -67,6 +67,10 @@
 // AudioSourceCallback interface. AudioOutputController uses the SyncReader
 // passed to it via construction to synchronously fulfill this read request.
 
+namespace base {
+class UnguessableToken;
+}
+
 namespace media {
 
 class MEDIA_EXPORT AudioOutputController
@@ -122,8 +126,11 @@
   // The |output_device_id| can be either empty (default device) or specify a
   // specific hardware device for audio output.
   static scoped_refptr<AudioOutputController> Create(
-      AudioManager* audio_manager, EventHandler* event_handler,
-      const AudioParameters& params, const std::string& output_device_id,
+      AudioManager* audio_manager,
+      EventHandler* event_handler,
+      const AudioParameters& params,
+      const std::string& output_device_id,
+      const base::UnguessableToken& group_id,
       SyncReader* sync_reader);
 
   // Indicates whether audio power level analysis will be performed.  If false,
diff --git a/media/audio/audio_output_controller_unittest.cc b/media/audio/audio_output_controller_unittest.cc
index f001e599..f654b07 100644
--- a/media/audio/audio_output_controller_unittest.cc
+++ b/media/audio/audio_output_controller_unittest.cc
@@ -22,6 +22,7 @@
 #include "base/test/test_message_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
+#include "base/unguessable_token.h"
 #include "media/audio/audio_device_description.h"
 #include "media/audio/audio_source_diverter.h"
 #include "media/audio/test_audio_thread.h"
@@ -194,7 +195,7 @@
 
     controller_ = AudioOutputController::Create(
         audio_manager_.get(), &mock_event_handler_, AOCTestParams(),
-        std::string(), &mock_sync_reader_);
+        std::string(), base::UnguessableToken(), &mock_sync_reader_);
     EXPECT_NE(nullptr, controller_.get());
     controller_->SetVolume(kTestVolume);
   }
diff --git a/media/base/BUILD.gn b/media/base/BUILD.gn
index ee0def1..4987757 100644
--- a/media/base/BUILD.gn
+++ b/media/base/BUILD.gn
@@ -279,7 +279,7 @@
   defines = []
   public_deps = [
     ":video_facing",
-    "//media:media_features",
+    "//media:media_buildflags",
     "//media:shared_memory_support",
     "//ui/gfx:color_space",
   ]
diff --git a/media/base/cdm_context.h b/media/base/cdm_context.h
index e2d32e1e..c58d6a7 100644
--- a/media/base/cdm_context.h
+++ b/media/base/cdm_context.h
@@ -9,7 +9,7 @@
 #include "base/macros.h"
 #include "build/build_config.h"
 #include "media/base/media_export.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 namespace media {
 
diff --git a/media/base/decode_capabilities.cc b/media/base/decode_capabilities.cc
index 704136b5..94d8292a 100644
--- a/media/base/decode_capabilities.cc
+++ b/media/base/decode_capabilities.cc
@@ -7,7 +7,7 @@
 #include "base/command_line.h"
 #include "base/feature_list.h"
 #include "media/base/media_switches.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "third_party/libaom/av1_features.h"
 #include "ui/display/display_switches.h"
 
diff --git a/media/base/eme_constants.h b/media/base/eme_constants.h
index dbd8736..e4f898d 100644
--- a/media/base/eme_constants.h
+++ b/media/base/eme_constants.h
@@ -7,7 +7,7 @@
 
 #include <stdint.h>
 
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 namespace media {
 
diff --git a/media/base/ipc/media_param_traits_macros.h b/media/base/ipc/media_param_traits_macros.h
index 2ddca2cb..59e2f09 100644
--- a/media/base/ipc/media_param_traits_macros.h
+++ b/media/base/ipc/media_param_traits_macros.h
@@ -34,7 +34,7 @@
 // TODO(crbug.com/676224): When EnabledIf attribute is supported in mojom files,
 // move CdmProxy related code into #if BUILDFLAG(ENABLE_LIBRARY_CDMS).
 #include "media/cdm/cdm_proxy.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "ui/gfx/ipc/color/gfx_param_traits_macros.h"
 
 // Enum traits.
diff --git a/media/base/key_system_properties.cc b/media/base/key_system_properties.cc
index 6f6da95..1e219819 100644
--- a/media/base/key_system_properties.cc
+++ b/media/base/key_system_properties.cc
@@ -5,7 +5,7 @@
 #include "media/base/key_system_properties.h"
 
 #include "base/logging.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 namespace media {
 
diff --git a/media/base/key_systems.cc b/media/base/key_systems.cc
index 6861502..36f5f498 100644
--- a/media/base/key_systems.cc
+++ b/media/base/key_systems.cc
@@ -18,9 +18,9 @@
 #include "media/base/key_system_names.h"
 #include "media/base/key_system_properties.h"
 #include "media/base/media.h"
-#include "media/base/media_switches.h"
 #include "media/base/media_client.h"
-#include "media/media_features.h"
+#include "media/base/media_switches.h"
+#include "media/media_buildflags.h"
 #include "third_party/widevine/cdm/widevine_cdm_common.h"
 
 namespace media {
diff --git a/media/base/key_systems.h b/media/base/key_systems.h
index 242d9d0..6d885336 100644
--- a/media/base/key_systems.h
+++ b/media/base/key_systems.h
@@ -12,7 +12,7 @@
 
 #include "media/base/eme_constants.h"
 #include "media/base/media_export.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 namespace media {
 
diff --git a/media/base/key_systems_unittest.cc b/media/base/key_systems_unittest.cc
index 5c1a2ab..a291c82 100644
--- a/media/base/key_systems_unittest.cc
+++ b/media/base/key_systems_unittest.cc
@@ -17,7 +17,7 @@
 #include "media/base/key_systems.h"
 #include "media/base/media.h"
 #include "media/base/media_client.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/widevine/cdm/widevine_cdm_common.h"
 
diff --git a/media/base/localized_strings.h b/media/base/localized_strings.h
index 81c8123..4a0d36ce 100644
--- a/media/base/localized_strings.h
+++ b/media/base/localized_strings.h
@@ -10,7 +10,7 @@
 #include "base/strings/string16.h"
 #include "build/build_config.h"
 #include "media/base/media_export.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 namespace media {
 
diff --git a/media/base/media.cc b/media/base/media.cc
index bc7e3e1..d820f16 100644
--- a/media/base/media.cc
+++ b/media/base/media.cc
@@ -10,7 +10,7 @@
 #include "base/metrics/field_trial.h"
 #include "base/trace_event/trace_event.h"
 #include "media/base/media_switches.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "third_party/libyuv/include/libyuv.h"
 
 #if defined(OS_ANDROID)
diff --git a/media/base/media_switches.h b/media/base/media_switches.h
index b2ddcf7..ae9ca8e 100644
--- a/media/base/media_switches.h
+++ b/media/base/media_switches.h
@@ -12,7 +12,7 @@
 #include "base/feature_list.h"
 #include "build/build_config.h"
 #include "media/base/media_export.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 namespace base {
 class CommandLine;
diff --git a/media/base/mime_util_internal.cc b/media/base/mime_util_internal.cc
index 206d8a2..722c2ac6 100644
--- a/media/base/mime_util_internal.cc
+++ b/media/base/mime_util_internal.cc
@@ -14,7 +14,7 @@
 #include "media/base/media_switches.h"
 #include "media/base/video_codecs.h"
 #include "media/base/video_color_space.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "third_party/libaom/av1_features.h"
 
 #if defined(OS_ANDROID)
diff --git a/media/base/mime_util_unittest.cc b/media/base/mime_util_unittest.cc
index e541c9c..be4e06b8 100644
--- a/media/base/mime_util_unittest.cc
+++ b/media/base/mime_util_unittest.cc
@@ -16,7 +16,7 @@
 #include "media/base/mime_util_internal.h"
 #include "media/base/video_codecs.h"
 #include "media/base/video_color_space.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 #if defined(OS_ANDROID)
diff --git a/media/base/stream_parser_buffer.cc b/media/base/stream_parser_buffer.cc
index 6ccdd480..c0937f7 100644
--- a/media/base/stream_parser_buffer.cc
+++ b/media/base/stream_parser_buffer.cc
@@ -64,7 +64,7 @@
       config_id_(kInvalidConfigId),
       type_(type),
       track_id_(track_id),
-      is_duration_estimated_(false) {
+      duration_type_(DurationType::kKnownDuration) {
   // TODO(scherkus): Should DataBuffer constructor accept a timestamp and
   // duration to force clients to set them? Today they end up being zero which
   // is both a common and valid value and could lead to bugs.
diff --git a/media/base/stream_parser_buffer.h b/media/base/stream_parser_buffer.h
index 96524d0..186f4a1e 100644
--- a/media/base/stream_parser_buffer.h
+++ b/media/base/stream_parser_buffer.h
@@ -100,6 +100,14 @@
   return DecodeTimestamp::FromPresentationTime(kNoTimestamp);
 }
 
+// Sync with StreamParserBufferDurationType in enums.xml.
+enum class DurationType {
+  kKnownDuration = 0,
+  kConstantEstimate = 1,
+  kRoughEstimate = 2,
+  kDurationTypeMax = kRoughEstimate  // Must point to last.
+};
+
 class MEDIA_EXPORT StreamParserBuffer : public DecoderBuffer {
  public:
   // Value used to signal an invalid decoder config ID.
@@ -158,10 +166,14 @@
 
   void set_timestamp(base::TimeDelta timestamp) override;
 
-  bool is_duration_estimated() const { return is_duration_estimated_; }
+  DurationType duration_type() const { return duration_type_; }
 
-  void set_is_duration_estimated(bool is_estimated) {
-    is_duration_estimated_ = is_estimated;
+  void set_duration_type(DurationType duration_type) {
+    duration_type_ = duration_type;
+  }
+
+  bool is_duration_estimated() const {
+    return duration_type_ != DurationType::kKnownDuration;
   }
 
  private:
@@ -179,7 +191,7 @@
   Type type_;
   TrackId track_id_;
   scoped_refptr<StreamParserBuffer> preroll_buffer_;
-  bool is_duration_estimated_;
+  DurationType duration_type_;
 
   DISALLOW_COPY_AND_ASSIGN(StreamParserBuffer);
 };
diff --git a/media/base/test_helpers.h b/media/base/test_helpers.h
index 99940f4..4a90206f 100644
--- a/media/base/test_helpers.h
+++ b/media/base/test_helpers.h
@@ -330,12 +330,8 @@
 }
 
 MATCHER_P(WebMSimpleBlockDurationEstimated, estimated_duration_ms, "") {
-  return CONTAINS_STRING(arg, "Estimating WebM block duration to be " +
-                                  base::IntToString(estimated_duration_ms) +
-                                  "ms for the last (Simple)Block in the "
-                                  "Cluster for this Track. Use BlockGroups "
-                                  "with BlockDurations at the end of each "
-                                  "Track in a Cluster to avoid estimation.");
+  return CONTAINS_STRING(arg, "Estimating WebM block duration=" +
+                                  base::IntToString(estimated_duration_ms));
 }
 
 MATCHER_P(WebMNegativeTimecodeOffset, timecode_string, "") {
diff --git a/media/base/video_codecs.h b/media/base/video_codecs.h
index 881d4c3..0788788 100644
--- a/media/base/video_codecs.h
+++ b/media/base/video_codecs.h
@@ -8,7 +8,7 @@
 #include <stdint.h>
 #include <string>
 #include "media/base/media_export.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "ui/gfx/color_space.h"
 
 namespace media {
diff --git a/media/blink/webcontentdecryptionmodulesession_impl.cc b/media/blink/webcontentdecryptionmodulesession_impl.cc
index cc4e85ff..0e1c0142 100644
--- a/media/blink/webcontentdecryptionmodulesession_impl.cc
+++ b/media/blink/webcontentdecryptionmodulesession_impl.cc
@@ -24,7 +24,7 @@
 #include "media/blink/cdm_session_adapter.h"
 #include "media/blink/webmediaplayer_util.h"
 #include "media/cdm/json_web_key.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "third_party/WebKit/public/platform/WebData.h"
 #include "third_party/WebKit/public/platform/WebEncryptedMediaKeyInformation.h"
 #include "third_party/WebKit/public/platform/WebString.h"
diff --git a/media/blink/webmediaplayer_delegate.h b/media/blink/webmediaplayer_delegate.h
index 5dc008a..873ffe1 100644
--- a/media/blink/webmediaplayer_delegate.h
+++ b/media/blink/webmediaplayer_delegate.h
@@ -100,6 +100,9 @@
   // Notify that the muted status of the media player has changed.
   virtual void DidPlayerMutedStatusChange(int delegate_id, bool muted) = 0;
 
+  // Notify that the source media player of Picture-in-Picture has changed.
+  virtual void DidPictureInPictureSourceChange(int delegate_id) = 0;
+
   // Notify that playback is stopped. This will drop wake locks and remove any
   // external controls.
   //
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc
index 6a5d7ed..507ee26 100644
--- a/media/blink/webmediaplayer_impl.cc
+++ b/media/blink/webmediaplayer_impl.cc
@@ -53,7 +53,7 @@
 #include "media/blink/webmediasource_impl.h"
 #include "media/filters/chunk_demuxer.h"
 #include "media/filters/ffmpeg_demuxer.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "third_party/WebKit/public/platform/WebEncryptedMediaTypes.h"
 #include "third_party/WebKit/public/platform/WebLocalizedString.h"
 #include "third_party/WebKit/public/platform/WebMediaPlayerClient.h"
@@ -189,13 +189,6 @@
     std::unique_ptr<VideoFrameCompositor> compositor,
     std::unique_ptr<WebMediaPlayerParams> params)
     : frame_(frame),
-      delegate_state_(DelegateState::GONE),
-      delegate_has_audio_(false),
-      network_state_(WebMediaPlayer::kNetworkStateEmpty),
-      ready_state_(WebMediaPlayer::kReadyStateHaveNothing),
-      highest_ready_state_(WebMediaPlayer::kReadyStateHaveNothing),
-      preload_(MultibufferDataSource::METADATA),
-      has_poster_(false),
       main_task_runner_(
           frame->GetTaskRunner(blink::TaskType::kMediaElementEvent)),
       media_task_runner_(params->media_task_runner()),
@@ -212,26 +205,11 @@
           base::Bind(&WebMediaPlayerImpl::OnBeforePipelineResume, AsWeakPtr()),
           base::Bind(&WebMediaPlayerImpl::OnPipelineResumed, AsWeakPtr()),
           base::Bind(&WebMediaPlayerImpl::OnError, AsWeakPtr())),
-      load_type_(kLoadTypeURL),
-      opaque_(false),
-      playback_rate_(0.0),
-      num_playback_rate_logs_(0),
-      paused_(true),
-      paused_when_hidden_(false),
-      seeking_(false),
-      pending_suspend_resume_cycle_(false),
-      ended_(false),
-      should_notify_time_changed_(false),
-      overlay_enabled_(false),
-      decoder_requires_restart_for_overlay_(false),
       client_(client),
       encrypted_client_(encrypted_client),
       delegate_(delegate),
-      delegate_id_(0),
       defer_load_cb_(params->defer_load_cb()),
       adjust_allocated_memory_cb_(params->adjust_allocated_memory_cb()),
-      last_reported_memory_usage_(0),
-      chunk_demuxer_(NULL),
       tick_clock_(base::DefaultTickClock::GetInstance()),
       buffered_data_source_host_(
           base::Bind(&WebMediaPlayerImpl::OnProgress, AsWeakPtr()),
@@ -243,14 +221,8 @@
 #if defined(OS_ANDROID)  // WMPI_CAST
       cast_impl_(this, client_, params->context_provider()),
 #endif
-      volume_(1.0),
-      volume_multiplier_(1.0),
       renderer_factory_selector_(std::move(renderer_factory_selector)),
       surface_manager_(params->surface_manager()),
-      overlay_surface_id_(SurfaceManager::kNoSurfaceID),
-      suppress_destruction_errors_(false),
-      is_encrypted_(false),
-      preroll_attempt_pending_(false),
       observer_(params->media_observer()),
       max_keyframe_distance_to_disable_background_video_(
           params->max_keyframe_distance_to_disable_background_video()),
@@ -346,6 +318,8 @@
   client_->MediaRemotingStopped(
       blink::WebLocalizedString::kMediaRemotingStopNoText);
 
+  client_->PictureInPictureStopped();
+
   if (!surface_layer_for_video_enabled_ && video_weblayer_) {
     static_cast<cc::VideoLayer*>(video_weblayer_->layer())->StopUsingProvider();
   }
@@ -807,6 +781,10 @@
 
   pip_surface_info_cb_.Run(pip_surface_id_);
 
+  // Updates the MediaWebContentsObserver with |delegate_id_| to track which
+  // media player is in Picture-in-Picture mode.
+  delegate_->DidPictureInPictureSourceChange(delegate_id_);
+
   if (client_)
     client_->PictureInPictureStarted();
 }
diff --git a/media/blink/webmediaplayer_impl.h b/media/blink/webmediaplayer_impl.h
index 969dd6f..6eb807d2 100644
--- a/media/blink/webmediaplayer_impl.h
+++ b/media/blink/webmediaplayer_impl.h
@@ -551,43 +551,45 @@
   // of |chunk_demuxer_|, while the EME one is only recorded if |is_encrypted_|.
   void RecordTimingUMA(const std::string& key, base::TimeDelta elapsed);
 
-  blink::WebLocalFrame* frame_;
+  blink::WebLocalFrame* const frame_;
 
   // The playback state last reported to |delegate_|, to avoid setting duplicate
   // states.
   // TODO(sandersd): The delegate should be implementing deduplication.
-  DelegateState delegate_state_;
-  bool delegate_has_audio_;
+  DelegateState delegate_state_ = DelegateState::GONE;
+  bool delegate_has_audio_ = false;
 
-  blink::WebMediaPlayer::NetworkState network_state_;
-  blink::WebMediaPlayer::ReadyState ready_state_;
-  blink::WebMediaPlayer::ReadyState highest_ready_state_;
+  blink::WebMediaPlayer::NetworkState network_state_ =
+      WebMediaPlayer::kNetworkStateEmpty;
+  blink::WebMediaPlayer::ReadyState ready_state_ =
+      WebMediaPlayer::kReadyStateHaveNothing;
+  blink::WebMediaPlayer::ReadyState highest_ready_state_ =
+      WebMediaPlayer::kReadyStateHaveNothing;
 
   // Preload state for when |data_source_| is created after setPreload().
-  MultibufferDataSource::Preload preload_;
+  MultibufferDataSource::Preload preload_ = MultibufferDataSource::METADATA;
 
   // Poster state (for UMA reporting).
-  bool has_poster_;
+  bool has_poster_ = false;
 
   // Task runner for posting tasks on Chrome's main thread. Also used
   // for DCHECKs so methods calls won't execute in the wrong thread.
   const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
-
-  scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_;
-  scoped_refptr<base::TaskRunner> worker_task_runner_;
+  const scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_;
+  const scoped_refptr<base::TaskRunner> worker_task_runner_;
   std::unique_ptr<MediaLog> media_log_;
 
   // |pipeline_controller_| owns an instance of Pipeline.
   PipelineController pipeline_controller_;
 
   // The LoadType passed in the |load_type| parameter of the load() call.
-  LoadType load_type_;
+  LoadType load_type_ = kLoadTypeURL;
 
   // Cache of metadata for answering hasAudio(), hasVideo(), and naturalSize().
   PipelineMetadata pipeline_metadata_;
 
   // Whether the video is known to be opaque or not.
-  bool opaque_;
+  bool opaque_ = false;
 
   // Playback state.
   //
@@ -601,22 +603,22 @@
   // time we pause and then return that value in currentTime().  Otherwise our
   // clock can creep forward a little bit while the asynchronous
   // SetPlaybackRate(0) is being executed.
-  double playback_rate_;
+  double playback_rate_ = 0.0;
 
   // Counter that limits spam to |media_log_| of |playback_rate_| changes.
-  int num_playback_rate_logs_;
+  int num_playback_rate_logs_ = 0;
 
   // Set while paused. |paused_time_| is only valid when |paused_| is true.
-  bool paused_;
+  bool paused_ = true;
   base::TimeDelta paused_time_;
 
   // Set if paused automatically when hidden and need to resume when visible.
   // Reset if paused for any other reason.
-  bool paused_when_hidden_;
+  bool paused_when_hidden_ = false;
 
   // Set when starting, seeking, and resuming (all of which require a Pipeline
   // seek). |seek_time_| is only valid when |seeking_| is true.
-  bool seeking_;
+  bool seeking_ = false;
   base::TimeDelta seek_time_;
 
   // Set when doing a restart (a suspend and resume in sequence) of the pipeline
@@ -624,23 +626,23 @@
   // |pending_resume_| and |pending_suspend_| because they can be elided in
   // certain cases, whereas for a restart they must happen.
   // TODO(sandersd,watk): Create a simpler interface for a pipeline restart.
-  bool pending_suspend_resume_cycle_;
+  bool pending_suspend_resume_cycle_ = false;
 
   // TODO(scherkus): Replace with an explicit ended signal to HTMLMediaElement,
   // see http://crbug.com/409280
-  bool ended_;
+  bool ended_ = false;
 
   // Tracks whether to issue time changed notifications during buffering state
   // changes.
-  bool should_notify_time_changed_;
+  bool should_notify_time_changed_ = false;
 
-  bool overlay_enabled_;
+  bool overlay_enabled_ = false;
 
   // Whether the current decoder requires a restart on overlay transitions.
-  bool decoder_requires_restart_for_overlay_;
+  bool decoder_requires_restart_for_overlay_ = false;
 
-  blink::WebMediaPlayerClient* client_;
-  blink::WebMediaPlayerEncryptedMediaClient* encrypted_client_;
+  blink::WebMediaPlayerClient* const client_;
+  blink::WebMediaPlayerEncryptedMediaClient* const encrypted_client_;
 
   // WebMediaPlayer notifies the |delegate_| of playback state changes using
   // |delegate_id_|; an id provided after registering with the delegate.  The
@@ -652,8 +654,8 @@
   // Document::shutdown() is called before the frame detaches (and before the
   // frame is destroyed). RenderFrameImpl owns |delegate_| and is guaranteed
   // to outlive |this|; thus it is safe to store |delegate_| as a raw pointer.
-  media::WebMediaPlayerDelegate* delegate_;
-  int delegate_id_;
+  media::WebMediaPlayerDelegate* const delegate_;
+  int delegate_id_ = 0;
 
   WebMediaPlayerParams::DeferLoadCB defer_load_cb_;
 
@@ -661,7 +663,7 @@
   // |adjust_allocated_memory_cb_| must only be called on |main_task_runner_|.
   base::RepeatingTimer memory_usage_reporting_timer_;
   WebMediaPlayerParams::AdjustAllocatedMemoryCB adjust_allocated_memory_cb_;
-  int64_t last_reported_memory_usage_;
+  int64_t last_reported_memory_usage_ = 0;
 
   // Routes audio playback to either AudioRendererSink or WebAudio.
   scoped_refptr<WebAudioSourceProviderImpl> audio_source_provider_;
@@ -674,14 +676,14 @@
   // load strategy we're using.
   std::unique_ptr<MultibufferDataSource> data_source_;
   std::unique_ptr<Demuxer> demuxer_;
-  ChunkDemuxer* chunk_demuxer_;
+  ChunkDemuxer* chunk_demuxer_ = nullptr;
 
   std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
 
-  base::TickClock* tick_clock_;
+  base::TickClock* tick_clock_ = nullptr;
 
   BufferedDataSourceHostImpl buffered_data_source_host_;
-  UrlIndex* url_index_;
+  UrlIndex* const url_index_;
   scoped_refptr<viz::ContextProvider> context_provider_;
 
   // Video rendering members.
@@ -715,14 +717,14 @@
   // OnVolumeMultiplierUpdate().  The multiplier is typical 1.0, but may be less
   // if the WebMediaPlayerDelegate has requested a volume reduction (ducking)
   // for a transient sound.  Playout volume is derived by volume * multiplier.
-  double volume_;
-  double volume_multiplier_;
+  double volume_ = 1.0;
+  double volume_multiplier_ = 1.0;
 
   std::unique_ptr<RendererFactorySelector> renderer_factory_selector_;
 
   // For requesting surfaces on behalf of the Android H/W decoder in fullscreen.
   // This will be null everywhere but Android.
-  SurfaceManager* surface_manager_;
+  SurfaceManager* const surface_manager_;
 
   // For canceling ongoing surface creation requests when exiting fullscreen.
   base::CancelableCallback<void(int)> surface_created_cb_;
@@ -730,7 +732,7 @@
   // The current overlay surface id. Populated, possibly with kNoSurfaceID if
   // we're not supposed to use an overlay, unless we have an outstanding surface
   // request to the SurfaceManager.
-  base::Optional<int> overlay_surface_id_;
+  base::Optional<int> overlay_surface_id_ = SurfaceManager::kNoSurfaceID;
 
   // For canceling AndroidOverlay routing token requests.
   base::CancelableCallback<void(const base::UnguessableToken&)>
@@ -746,12 +748,12 @@
   // SurfaceView instead of SurfaceTexture.
 
   // Allow overlays for all video on android.
-  bool always_enable_overlays_;
+  bool always_enable_overlays_ = false;
 
   // Suppresses calls to OnPipelineError() after destruction / shutdown has been
   // started; prevents us from spuriously logging errors that are transient or
   // unimportant.
-  bool suppress_destruction_errors_;
+  bool suppress_destruction_errors_ = false;
 
   // Used for HLS playback and in certain fallback paths (e.g. on older devices
   // that can't support the unified media pipeline).
@@ -771,7 +773,7 @@
 
   // Monitors the watch time of the played content.
   std::unique_ptr<WatchTimeReporter> watch_time_reporter_;
-  bool is_encrypted_;
+  bool is_encrypted_ = false;
   std::string audio_decoder_name_;
   std::string video_decoder_name_;
 
@@ -789,7 +791,7 @@
   // |preroll_attempt_pending_| indicates that the clock has been reset
   // (awaiting a resume to start), while |preroll_attempt_start_time_| tracks
   // when a preroll attempt began.
-  bool preroll_attempt_pending_;
+  bool preroll_attempt_pending_ = false;
   base::TimeTicks preroll_attempt_start_time_;
 
   // Monitors the player events.
diff --git a/media/blink/webmediaplayer_impl_unittest.cc b/media/blink/webmediaplayer_impl_unittest.cc
index d8c0d9c..e48bbeb5 100644
--- a/media/blink/webmediaplayer_impl_unittest.cc
+++ b/media/blink/webmediaplayer_impl_unittest.cc
@@ -178,6 +178,8 @@
     DCHECK_EQ(player_id_, delegate_id);
   }
 
+  MOCK_METHOD1(DidPictureInPictureSourceChange, void(int));
+
   void ClearStaleFlag(int player_id) override {
     DCHECK_EQ(player_id_, player_id);
     is_stale_ = false;
@@ -223,6 +225,8 @@
 
   void SetFrameClosedForTesting(bool is_closed) { is_closed_ = is_closed; }
 
+  int player_id() { return player_id_; }
+
  private:
   Observer* observer_ = nullptr;
   int player_id_ = 1234;
@@ -328,6 +332,7 @@
   ~WebMediaPlayerImplTest() override {
     EXPECT_CALL(client_, SetWebLayer(nullptr));
     EXPECT_CALL(client_, MediaRemotingStopped(_));
+    EXPECT_CALL(client_, PictureInPictureStopped());
     // Destruct WebMediaPlayerImpl and pump the message loop to ensure that
     // objects passed to the message loop for destruction are released.
     //
@@ -401,7 +406,7 @@
   void OnMetadata(PipelineMetadata metadata) {
     if (base::FeatureList::IsEnabled(media::kUseSurfaceLayerForVideo)) {
       EXPECT_CALL(*surface_layer_bridge_ptr_, GetFrameSinkId())
-          .WillOnce(ReturnRef(id_));
+          .WillOnce(ReturnRef(frame_sink_id_));
       EXPECT_CALL(*compositor_, EnableSubmission(_, _));
     }
     wmpi_->OnMetadata(metadata);
@@ -528,7 +533,12 @@
   // The client interface used by |wmpi_|.
   NiceMock<MockWebMediaPlayerClient> client_;
 
-  viz::FrameSinkId id_ = viz::FrameSinkId(1, 1);
+  viz::FrameSinkId frame_sink_id_ = viz::FrameSinkId(1, 1);
+
+  viz::LocalSurfaceId local_surface_id_ =
+      viz::LocalSurfaceId(11, base::UnguessableToken::Deserialize(0x111111, 0));
+  viz::SurfaceId surface_id_ =
+      viz::SurfaceId(frame_sink_id_, local_surface_id_);
 
   NiceMock<MockWebMediaPlayerDelegate> delegate_;
 
@@ -1081,20 +1091,15 @@
 TEST_F(WebMediaPlayerImplTest, PictureInPictureTriggerCallback) {
   InitializeWebMediaPlayerImpl();
 
-  // Set up valid viz::SurfaceId. Values are arbitrary for test purposes.
-  viz::FrameSinkId frame_sink_id = viz::FrameSinkId(1, 1);
-  viz::LocalSurfaceId local_surface_id =
-      viz::LocalSurfaceId(11, base::UnguessableToken::Deserialize(0x111111, 0));
-  const viz::SurfaceId& surface_id =
-      viz::SurfaceId(frame_sink_id, local_surface_id);
-
   // This call should do nothing because there is no SurfaceId set.
   wmpi_->EnterPictureInPicture();
   EXPECT_CALL(client_, IsInPictureInPictureMode());
-  wmpi_->OnSurfaceIdUpdated(surface_id);
+  wmpi_->OnSurfaceIdUpdated(surface_id_);
   testing::Mock::VerifyAndClearExpectations(&client_);
 
-  EXPECT_CALL(pip_surface_info_cb_, Run(surface_id));
+  EXPECT_CALL(delegate_,
+              DidPictureInPictureSourceChange(delegate_.player_id()));
+  EXPECT_CALL(pip_surface_info_cb_, Run(surface_id_));
   // This call should trigger the callback since the SurfaceId is set.
   wmpi_->EnterPictureInPicture();
 }
diff --git a/media/cast/net/udp_socket_client_unittest.cc b/media/cast/net/udp_socket_client_unittest.cc
index f2ae68b..59d59024 100644
--- a/media/cast/net/udp_socket_client_unittest.cc
+++ b/media/cast/net/udp_socket_client_unittest.cc
@@ -154,6 +154,10 @@
       CreateTCPConnectedSocketCallback callback) override {}
 
   MockUdpSocket* udp_socket() const { return udp_socket_.get(); }
+  void CreateWebSocket(network::mojom::WebSocketRequest request,
+                       int process_id,
+                       int render_frame_id,
+                       const url::Origin& origin) override {}
 
  private:
   mojo::Binding<network::mojom::NetworkContext> binding_;
diff --git a/media/cast/sender/h264_vt_encoder_unittest.cc b/media/cast/sender/h264_vt_encoder_unittest.cc
index 9bba4c2..cd4bbca5 100644
--- a/media/cast/sender/h264_vt_encoder_unittest.cc
+++ b/media/cast/sender/h264_vt_encoder_unittest.cc
@@ -31,7 +31,7 @@
 #include "media/ffmpeg/ffmpeg_common.h"
 #include "media/filters/ffmpeg_glue.h"
 #include "media/filters/ffmpeg_video_decoder.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
diff --git a/media/cdm/aes_decryptor.cc b/media/cdm/aes_decryptor.cc
index b1d9a33..4a156af 100644
--- a/media/cdm/aes_decryptor.cc
+++ b/media/cdm/aes_decryptor.cc
@@ -26,7 +26,7 @@
 #include "media/base/video_frame.h"
 #include "media/cdm/cenc_utils.h"
 #include "media/cdm/json_web_key.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 namespace media {
 
diff --git a/media/cdm/aes_decryptor_unittest.cc b/media/cdm/aes_decryptor_unittest.cc
index 1975059..7da8affb 100644
--- a/media/cdm/aes_decryptor_unittest.cc
+++ b/media/cdm/aes_decryptor_unittest.cc
@@ -27,7 +27,7 @@
 #include "media/base/media_switches.h"
 #include "media/base/mock_filters.h"
 #include "media/cdm/cdm_module.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest-param-test.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/media/cdm/cdm_adapter_unittest.cc b/media/cdm/cdm_adapter_unittest.cc
index 37f10382..0ced276 100644
--- a/media/cdm/cdm_adapter_unittest.cc
+++ b/media/cdm/cdm_adapter_unittest.cc
@@ -23,7 +23,7 @@
 #include "media/cdm/external_clear_key_test_helper.h"
 #include "media/cdm/mock_helpers.h"
 #include "media/cdm/simple_cdm_allocator.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/media/cdm/cdm_module.h b/media/cdm/cdm_module.h
index 3c8177d..894c18c 100644
--- a/media/cdm/cdm_module.h
+++ b/media/cdm/cdm_module.h
@@ -13,7 +13,7 @@
 #include "base/scoped_native_library.h"
 #include "media/base/media_export.h"
 #include "media/cdm/api/content_decryption_module.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 #if BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION)
 #include "media/cdm/cdm_host_file.h"
diff --git a/media/cdm/library_cdm/clear_key_cdm/clear_key_cdm.cc b/media/cdm/library_cdm/clear_key_cdm/clear_key_cdm.cc
index a69a9dd..543684b1 100644
--- a/media/cdm/library_cdm/clear_key_cdm/clear_key_cdm.cc
+++ b/media/cdm/library_cdm/clear_key_cdm/clear_key_cdm.cc
@@ -28,7 +28,7 @@
 #include "media/cdm/library_cdm/clear_key_cdm/cdm_host_proxy_impl.h"
 #include "media/cdm/library_cdm/clear_key_cdm/cdm_proxy_test.h"
 #include "media/cdm/library_cdm/clear_key_cdm/cdm_video_decoder.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER)
 #include "base/at_exit.h"
diff --git a/media/ffmpeg/ffmpeg_common.cc b/media/ffmpeg/ffmpeg_common.cc
index a394af20..caa2647c 100644
--- a/media/ffmpeg/ffmpeg_common.cc
+++ b/media/ffmpeg/ffmpeg_common.cc
@@ -16,7 +16,7 @@
 #include "media/base/media_util.h"
 #include "media/base/video_decoder_config.h"
 #include "media/base/video_util.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 namespace media {
 
diff --git a/media/filters/audio_decoder_unittest.cc b/media/filters/audio_decoder_unittest.cc
index 3e6c1606..96fda0f 100644
--- a/media/filters/audio_decoder_unittest.cc
+++ b/media/filters/audio_decoder_unittest.cc
@@ -30,7 +30,7 @@
 #include "media/filters/audio_file_reader.h"
 #include "media/filters/ffmpeg_audio_decoder.h"
 #include "media/filters/in_memory_url_protocol.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 #if defined(OS_ANDROID)
diff --git a/media/filters/audio_file_reader_unittest.cc b/media/filters/audio_file_reader_unittest.cc
index 3ea4146..6b3ce992 100644
--- a/media/filters/audio_file_reader_unittest.cc
+++ b/media/filters/audio_file_reader_unittest.cc
@@ -16,7 +16,7 @@
 #include "media/base/test_data_util.h"
 #include "media/ffmpeg/ffmpeg_common.h"
 #include "media/filters/in_memory_url_protocol.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace media {
diff --git a/media/filters/audio_video_metadata_extractor_unittest.cc b/media/filters/audio_video_metadata_extractor_unittest.cc
index 9446ed3..022efcc 100644
--- a/media/filters/audio_video_metadata_extractor_unittest.cc
+++ b/media/filters/audio_video_metadata_extractor_unittest.cc
@@ -11,7 +11,7 @@
 #include "build/build_config.h"
 #include "media/base/test_data_util.h"
 #include "media/filters/file_data_source.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace media {
diff --git a/media/filters/chunk_demuxer_unittest.cc b/media/filters/chunk_demuxer_unittest.cc
index 85358fb..4f0c5093 100644
--- a/media/filters/chunk_demuxer_unittest.cc
+++ b/media/filters/chunk_demuxer_unittest.cc
@@ -36,7 +36,7 @@
 #include "media/formats/webm/cluster_builder.h"
 #include "media/formats/webm/webm_cluster_parser.h"
 #include "media/formats/webm/webm_constants.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using ::testing::AnyNumber;
diff --git a/media/filters/decoder_stream.cc b/media/filters/decoder_stream.cc
index 837a690..fdfe0adf 100644
--- a/media/filters/decoder_stream.cc
+++ b/media/filters/decoder_stream.cc
@@ -24,8 +24,6 @@
 
 namespace media {
 
-// TODO(rileya): Devise a better way of specifying trace/UMA/etc strings for
-// templated classes such as this.
 template <DemuxerStream::Type StreamType>
 static const char* GetTraceString();
 
@@ -52,17 +50,19 @@
       create_decoders_cb_(std::move(create_decoders_cb)),
       media_log_(media_log),
       state_(STATE_UNINITIALIZED),
-      stream_(NULL),
+      stream_(nullptr),
       cdm_context_(nullptr),
       decoder_produced_a_frame_(false),
       has_fallen_back_once_on_decode_error_(false),
       decoding_eos_(false),
+      preparing_output_(false),
       pending_decode_requests_(0),
       duration_tracker_(8),
       received_config_change_during_reinit_(false),
       pending_demuxer_read_(false),
       weak_factory_(this),
-      fallback_weak_factory_(this) {
+      fallback_weak_factory_(this),
+      prepare_weak_factory_(this) {
   FUNCTION_DVLOG(1);
 }
 
@@ -71,22 +71,20 @@
   FUNCTION_DVLOG(1);
   DCHECK(task_runner_->BelongsToCurrentThread());
 
-  decoder_selector_.reset();
-
-  if (!init_cb_.is_null()) {
-    task_runner_->PostTask(FROM_HERE,
-                           base::Bind(base::ResetAndReturn(&init_cb_), false));
+  if (init_cb_) {
+    task_runner_->PostTask(
+        FROM_HERE, base::BindOnce(base::ResetAndReturn(&init_cb_), false));
   }
-  if (!read_cb_.is_null()) {
-    task_runner_->PostTask(FROM_HERE, base::Bind(
-        base::ResetAndReturn(&read_cb_), ABORTED, scoped_refptr<Output>()));
+  if (read_cb_) {
+    task_runner_->PostTask(
+        FROM_HERE, base::BindOnce(base::ResetAndReturn(&read_cb_), ABORTED,
+                                  scoped_refptr<Output>()));
   }
-  if (!reset_cb_.is_null())
+  if (reset_cb_)
     task_runner_->PostTask(FROM_HERE, base::ResetAndReturn(&reset_cb_));
 
-  stream_ = NULL;
-  decoder_.reset();
-  decrypting_demuxer_stream_.reset();
+  // Don't manually reset anything here; rely on the order of member variables
+  // within the header, which enforces WeakPtrFactory invalidation first.
 }
 
 template <DemuxerStream::Type StreamType>
@@ -104,8 +102,8 @@
   FUNCTION_DVLOG(1);
   DCHECK(task_runner_->BelongsToCurrentThread());
   DCHECK_EQ(state_, STATE_UNINITIALIZED);
-  DCHECK(init_cb_.is_null());
-  DCHECK(!init_cb.is_null());
+  DCHECK(!init_cb_);
+  DCHECK(init_cb);
 
   stream_ = stream;
   init_cb_ = init_cb;
@@ -126,26 +124,29 @@
   DCHECK(state_ != STATE_UNINITIALIZED && state_ != STATE_INITIALIZING)
       << state_;
   // No two reads in the flight at any time.
-  DCHECK(read_cb_.is_null());
+  DCHECK(!read_cb_);
   // No read during resetting or stopping process.
-  DCHECK(reset_cb_.is_null());
+  DCHECK(!reset_cb_);
 
   if (state_ == STATE_ERROR) {
-    task_runner_->PostTask(
-        FROM_HERE, base::Bind(read_cb, DECODE_ERROR, scoped_refptr<Output>()));
+    task_runner_->PostTask(FROM_HERE, base::BindOnce(read_cb, DECODE_ERROR,
+                                                     scoped_refptr<Output>()));
     return;
   }
 
-  if (state_ == STATE_END_OF_STREAM && ready_outputs_.empty()) {
+  if (state_ == STATE_END_OF_STREAM && ready_outputs_.empty() &&
+      unprepared_outputs_.empty()) {
     task_runner_->PostTask(
-        FROM_HERE, base::Bind(read_cb, OK, StreamTraits::CreateEOSOutput()));
+        FROM_HERE,
+        base::BindOnce(read_cb, OK, StreamTraits::CreateEOSOutput()));
     return;
   }
 
   if (!ready_outputs_.empty()) {
     task_runner_->PostTask(FROM_HERE,
-                           base::Bind(read_cb, OK, ready_outputs_.front()));
+                           base::BindOnce(read_cb, OK, ready_outputs_.front()));
     ready_outputs_.pop_front();
+    MaybePrepareAnotherOutput();
   } else {
     read_cb_ = read_cb;
   }
@@ -159,17 +160,17 @@
   FUNCTION_DVLOG(2);
   DCHECK(task_runner_->BelongsToCurrentThread());
   DCHECK_NE(state_, STATE_UNINITIALIZED);
-  DCHECK(reset_cb_.is_null());
+  DCHECK(!reset_cb_);
 
   reset_cb_ = closure;
 
-  if (!read_cb_.is_null()) {
-    task_runner_->PostTask(FROM_HERE,
-                           base::Bind(base::ResetAndReturn(&read_cb_), ABORTED,
-                                      scoped_refptr<Output>()));
+  if (read_cb_) {
+    task_runner_->PostTask(
+        FROM_HERE, base::BindOnce(base::ResetAndReturn(&read_cb_), ABORTED,
+                                  scoped_refptr<Output>()));
   }
 
-  ready_outputs_.clear();
+  ClearOutputs();
   traits_.OnStreamReset(stream_);
 
   // It's possible to have received a DECODE_ERROR and entered STATE_ERROR right
@@ -191,7 +192,7 @@
   // it resets. |reset_cb_| will be fired in OnDecoderReset(), after the
   // decrypting demuxer stream finishes its reset.
   if (decrypting_demuxer_stream_) {
-    decrypting_demuxer_stream_->Reset(base::Bind(
+    decrypting_demuxer_stream_->Reset(base::BindRepeating(
         &DecoderStream<StreamType>::ResetDecoder, weak_factory_.GetWeakPtr()));
     return;
   }
@@ -208,7 +209,7 @@
 template <DemuxerStream::Type StreamType>
 bool DecoderStream<StreamType>::CanReadWithoutStalling() const {
   DCHECK(task_runner_->BelongsToCurrentThread());
-  return !ready_outputs_.empty() ||
+  return !ready_outputs_.empty() || !unprepared_outputs_.empty() ||
          (decoder_ && decoder_->CanReadWithoutStalling());
 }
 
@@ -234,11 +235,10 @@
 
   bool buffers_left = !(fallback_buffers_.empty() && decoding_eos_);
 
-  // Limit total number of outputs stored in |ready_outputs_| and being decoded.
-  // It only makes sense to saturate decoder completely when output queue is
-  // empty.
-  int num_decodes =
-      static_cast<int>(ready_outputs_.size()) + pending_decode_requests_;
+  // Limit total number of outputs stored and being decoded. It only makes sense
+  // to saturate decoder completely when our output queues are empty.
+  int num_decodes = ready_outputs_.size() + unprepared_outputs_.size() +
+                    pending_decode_requests_;
   return buffers_left && num_decodes < GetMaxDecodeRequests();
 }
 
@@ -250,10 +250,16 @@
 }
 
 template <DemuxerStream::Type StreamType>
-void DecoderStream<StreamType>::DropFramesBefore(
+void DecoderStream<StreamType>::SetPrepareCB(PrepareCB prepare_cb) {
+  DCHECK(task_runner_->BelongsToCurrentThread());
+  prepare_cb_ = std::move(prepare_cb);
+}
+
+template <DemuxerStream::Type StreamType>
+void DecoderStream<StreamType>::SkipPrepareUntil(
     base::TimeDelta start_timestamp) {
   DCHECK(task_runner_->BelongsToCurrentThread());
-  start_timestamp_ = start_timestamp;
+  skip_prepare_until_timestamp_ = start_timestamp;
 }
 
 template <DemuxerStream::Type StreamType>
@@ -265,15 +271,15 @@
   CdmContext* cdm_context = decrypting_demuxer_stream_ ? nullptr : cdm_context_;
   std::string blacklisted_decoder = decoder_ ? decoder_->GetDisplayName() : "";
 
-  decoder_selector_.reset(new DecoderSelector<StreamType>(
-      task_runner_, create_decoders_cb_, media_log_));
+  decoder_selector_ = std::make_unique<DecoderSelector<StreamType>>(
+      task_runner_, create_decoders_cb_, media_log_);
 
   decoder_selector_->SelectDecoder(
       &traits_, stream_, cdm_context, blacklisted_decoder,
-      base::Bind(&DecoderStream<StreamType>::OnDecoderSelected,
-                 weak_factory_.GetWeakPtr()),
-      base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady,
-                 fallback_weak_factory_.GetWeakPtr()),
+      base::BindRepeating(&DecoderStream<StreamType>::OnDecoderSelected,
+                          weak_factory_.GetWeakPtr()),
+      base::BindRepeating(&DecoderStream<StreamType>::OnDecodeOutputReady,
+                          fallback_weak_factory_.GetWeakPtr()),
       waiting_for_decryption_key_cb_);
 }
 
@@ -291,9 +297,9 @@
   decoder_selector_.reset();
 
   if (state_ == STATE_INITIALIZING) {
-    DCHECK(!init_cb_.is_null());
-    DCHECK(read_cb_.is_null());
-    DCHECK(reset_cb_.is_null());
+    DCHECK(init_cb_);
+    DCHECK(!read_cb_);
+    DCHECK(!reset_cb_);
   } else if (state_ == STATE_REINITIALIZING_DECODER) {
     DCHECK(decoder_);
   }
@@ -319,8 +325,8 @@
   if (!decoder_) {
     if (state_ == STATE_INITIALIZING) {
       state_ = STATE_UNINITIALIZED;
-      MEDIA_LOG(ERROR, media_log_) << GetStreamTypeString()
-                                   << " decoder initialization failed";
+      MEDIA_LOG(ERROR, media_log_)
+          << GetStreamTypeString() << " decoder initialization failed";
       base::ResetAndReturn(&init_cb_).Run(false);
     } else {
       CompleteDecoderReinitialization(false);
@@ -356,7 +362,7 @@
 void DecoderStream<StreamType>::SatisfyRead(
     Status status,
     const scoped_refptr<Output>& output) {
-  DCHECK(!read_cb_.is_null());
+  DCHECK(read_cb_);
   base::ResetAndReturn(&read_cb_).Run(status, output);
 }
 
@@ -391,8 +397,8 @@
   FUNCTION_DVLOG(3);
   DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER) << state_;
   DCHECK_LT(pending_decode_requests_, GetMaxDecodeRequests());
-  DCHECK(reset_cb_.is_null());
-  DCHECK(buffer.get());
+  DCHECK(!reset_cb_);
+  DCHECK(buffer);
 
   traits_.OnDecode(buffer);
 
@@ -409,9 +415,10 @@
     duration_tracker_.AddSample(buffer->duration());
 
   ++pending_decode_requests_;
-  decoder_->Decode(buffer, base::Bind(&DecoderStream<StreamType>::OnDecodeDone,
-                                      fallback_weak_factory_.GetWeakPtr(),
-                                      buffer_size, buffer->end_of_stream()));
+  decoder_->Decode(buffer,
+                   base::BindRepeating(&DecoderStream<StreamType>::OnDecodeDone,
+                                       fallback_weak_factory_.GetWeakPtr(),
+                                       buffer_size, buffer->end_of_stream()));
 }
 
 template <DemuxerStream::Type StreamType>
@@ -441,13 +448,13 @@
   }
 
   if (state_ == STATE_ERROR) {
-    DCHECK(read_cb_.is_null());
+    DCHECK(!read_cb_);
     return;
   }
 
   // Drop decoding result if Reset() was called during decoding.
   // The resetting process will be handled when the decoder is reset.
-  if (!reset_cb_.is_null())
+  if (reset_cb_)
     return;
 
   switch (status) {
@@ -473,9 +480,9 @@
       FUNCTION_DVLOG(1) << ": Decode error!";
       state_ = STATE_ERROR;
       MEDIA_LOG(ERROR, media_log_) << GetStreamTypeString() << " decode error";
-      ready_outputs_.clear();
-      if (!read_cb_.is_null())
-        SatisfyRead(DECODE_ERROR, NULL);
+      ClearOutputs();
+      if (read_cb_)
+        SatisfyRead(DECODE_ERROR, nullptr);
       return;
 
     case DecodeStatus::ABORTED:
@@ -491,7 +498,7 @@
       if (state_ == STATE_NORMAL) {
         if (end_of_stream) {
           state_ = STATE_END_OF_STREAM;
-          if (ready_outputs_.empty() && !read_cb_.is_null())
+          if (ready_outputs_.empty() && unprepared_outputs_.empty() && read_cb_)
             SatisfyRead(OK, StreamTraits::CreateEOSOutput());
           return;
         }
@@ -511,19 +518,19 @@
 void DecoderStream<StreamType>::OnDecodeOutputReady(
     const scoped_refptr<Output>& output) {
   FUNCTION_DVLOG(3) << ": " << output->timestamp().InMilliseconds() << " ms";
-  DCHECK(output.get());
+  DCHECK(output);
   DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER ||
          state_ == STATE_ERROR)
       << state_;
 
   if (state_ == STATE_ERROR) {
-    DCHECK(read_cb_.is_null());
+    DCHECK(!read_cb_);
     return;
   }
 
   // Drop decoding result if Reset() was called during decoding.
   // The resetting process will be handled when the decoder is reset.
-  if (!reset_cb_.is_null())
+  if (reset_cb_)
     return;
 
   // |decoder_| successfully decoded a frame. No need to keep buffers for a
@@ -537,7 +544,14 @@
   if (traits_.OnDecodeDone(output) == PostDecodeAction::DROP)
     return;
 
-  if (!read_cb_.is_null()) {
+  if (prepare_cb_ && output->timestamp() + AverageDuration() >=
+                         skip_prepare_until_timestamp_) {
+    unprepared_outputs_.push_back(output);
+    MaybePrepareAnotherOutput();
+    return;
+  }
+
+  if (read_cb_) {
     // If |ready_outputs_| was non-empty, the read would have already been
     // satisifed by Read().
     DCHECK(ready_outputs_.empty());
@@ -554,7 +568,7 @@
   FUNCTION_DVLOG(3);
   DCHECK_EQ(state_, STATE_NORMAL);
   DCHECK(CanDecodeMore());
-  DCHECK(reset_cb_.is_null());
+  DCHECK(!reset_cb_);
 
   if (!fallback_buffers_.empty()) {
     scoped_refptr<DecoderBuffer> buffer = fallback_buffers_.front();
@@ -570,8 +584,8 @@
     return;
 
   pending_demuxer_read_ = true;
-  stream_->Read(base::Bind(&DecoderStream<StreamType>::OnBufferReady,
-                           weak_factory_.GetWeakPtr()));
+  stream_->Read(base::BindRepeating(&DecoderStream<StreamType>::OnBufferReady,
+                                    weak_factory_.GetWeakPtr()));
 }
 
 template <DemuxerStream::Type StreamType>
@@ -579,8 +593,7 @@
     DemuxerStream::Status status,
     const scoped_refptr<DecoderBuffer>& buffer) {
   FUNCTION_DVLOG(3) << ": " << status << ", "
-                    << (buffer.get() ? buffer->AsHumanReadableString()
-                                     : "NULL");
+                    << (buffer ? buffer->AsHumanReadableString() : "nullptr");
 
   DCHECK(task_runner_->BelongsToCurrentThread());
   DCHECK(pending_demuxer_read_);
@@ -589,17 +602,9 @@
            state_ == STATE_NORMAL)
         << state_;
   }
-  DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status;
+  DCHECK_EQ(buffer != nullptr, status == DemuxerStream::kOk) << status;
   pending_demuxer_read_ = false;
 
-  if (buffer && !buffer->end_of_stream() &&
-      buffer->timestamp() + buffer->duration() < start_timestamp_) {
-    // Tell decoders that we expect to discard the frame. Some decoders will use
-    // this information to skip expensive decoding operations.
-    buffer->set_discard_padding(
-        std::make_pair(kInfiniteDuration, base::TimeDelta()));
-  }
-
   // If parallel decode requests are supported, multiple read requests might
   // have been sent to the demuxer. The buffers might arrive while the decoder
   // is reinitializing after falling back on first decode error.
@@ -634,16 +639,16 @@
     MEDIA_LOG(ERROR, media_log_)
         << GetStreamTypeString() << " demuxer stream read error!";
     pending_buffers_.clear();
-    ready_outputs_.clear();
-    if (!read_cb_.is_null())
+    ClearOutputs();
+    if (read_cb_)
       SatisfyRead(DECODE_ERROR, nullptr);
   }
 
   // Decoding has been stopped.
   if (state_ == STATE_ERROR) {
-    DCHECK(read_cb_.is_null());
+    DCHECK(!read_cb_);
 
-    if (!reset_cb_.is_null()) {
+    if (reset_cb_) {
       // If we are using DecryptingDemuxerStream, we already called DDS::Reset()
       // which will continue the resetting process in its callback.
       if (!decrypting_demuxer_stream_)
@@ -655,7 +660,7 @@
   state_ = STATE_NORMAL;
 
   if (status == DemuxerStream::kConfigChanged) {
-    FUNCTION_DVLOG(2) << ": " << "ConfigChanged";
+    FUNCTION_DVLOG(2) << ": ConfigChanged";
     DCHECK(stream_->SupportsConfigChanges());
 
     // Pending buffers might not match the reinitialized decoder's new config.
@@ -686,11 +691,11 @@
         << " decoder config changed midstream, new config: "
         << config.AsHumanReadableString();
 
-    if (!config_change_observer_cb_.is_null())
+    if (config_change_observer_cb_)
       config_change_observer_cb_.Run(config);
 
     state_ = STATE_FLUSHING_DECODER;
-    if (!reset_cb_.is_null()) {
+    if (reset_cb_) {
       // If we are using DecryptingDemuxerStream, we already called DDS::Reset()
       // which will continue the resetting process in its callback.
       if (!decrypting_demuxer_stream_)
@@ -702,7 +707,7 @@
     return;
   }
 
-  if (!reset_cb_.is_null()) {
+  if (reset_cb_) {
     // If we are using DecryptingDemuxerStream, we already called DDS::Reset()
     // which will continue the resetting process in its callback.
     if (!decrypting_demuxer_stream_)
@@ -711,8 +716,8 @@
   }
 
   if (status == DemuxerStream::kAborted) {
-    if (!read_cb_.is_null())
-      SatisfyRead(DEMUXER_READ_ABORTED, NULL);
+    if (read_cb_)
+      SatisfyRead(DEMUXER_READ_ABORTED, nullptr);
     return;
   }
 
@@ -736,10 +741,10 @@
   traits_.InitializeDecoder(
       decoder_.get(), StreamTraits::GetDecoderConfig(stream_),
       stream_->liveness() == DemuxerStream::LIVENESS_LIVE, cdm_context_,
-      base::Bind(&DecoderStream<StreamType>::OnDecoderReinitialized,
-                 weak_factory_.GetWeakPtr()),
-      base::Bind(&DecoderStream<StreamType>::OnDecodeOutputReady,
-                 fallback_weak_factory_.GetWeakPtr()),
+      base::BindRepeating(&DecoderStream<StreamType>::OnDecoderReinitialized,
+                          weak_factory_.GetWeakPtr()),
+      base::BindRepeating(&DecoderStream<StreamType>::OnDecodeOutputReady,
+                          fallback_weak_factory_.GetWeakPtr()),
       waiting_for_decryption_key_cb_);
 }
 
@@ -773,18 +778,18 @@
 
   state_ = success ? STATE_NORMAL : STATE_ERROR;
 
-  if (!reset_cb_.is_null()) {
+  if (reset_cb_) {
     base::ResetAndReturn(&reset_cb_).Run();
     return;
   }
 
-  if (read_cb_.is_null())
+  if (!read_cb_)
     return;
 
   if (state_ == STATE_ERROR) {
-    MEDIA_LOG(ERROR, media_log_) << GetStreamTypeString()
-                                 << " decoder reinitialization failed";
-    SatisfyRead(DECODE_ERROR, NULL);
+    MEDIA_LOG(ERROR, media_log_)
+        << GetStreamTypeString() << " decoder reinitialization failed";
+    SatisfyRead(DECODE_ERROR, nullptr);
     return;
   }
 
@@ -796,7 +801,11 @@
   // flushing the decoder during a seek operation.
   decoder_produced_a_frame_ = false;
 
-  ReadFromDemuxerStream();
+  // We may still have too many |ready_outputs_| or |unprepared_outputs_| to
+  // initiate another read to the demuxer stream. If so, the read will be
+  // initiated later once we vended enough outputs to read again.
+  if (CanDecodeMore())
+    ReadFromDemuxerStream();
 }
 
 template <DemuxerStream::Type StreamType>
@@ -804,11 +813,12 @@
   FUNCTION_DVLOG(2);
   DCHECK(task_runner_->BelongsToCurrentThread());
   DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER ||
-         state_ == STATE_ERROR || state_ == STATE_END_OF_STREAM) << state_;
-  DCHECK(!reset_cb_.is_null());
+         state_ == STATE_ERROR || state_ == STATE_END_OF_STREAM)
+      << state_;
+  DCHECK(reset_cb_);
 
-  decoder_->Reset(base::Bind(&DecoderStream<StreamType>::OnDecoderReset,
-                             weak_factory_.GetWeakPtr()));
+  decoder_->Reset(base::BindRepeating(
+      &DecoderStream<StreamType>::OnDecoderReset, weak_factory_.GetWeakPtr()));
 }
 
 template <DemuxerStream::Type StreamType>
@@ -816,11 +826,12 @@
   FUNCTION_DVLOG(2);
   DCHECK(task_runner_->BelongsToCurrentThread());
   DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER ||
-         state_ == STATE_ERROR || state_ == STATE_END_OF_STREAM) << state_;
+         state_ == STATE_ERROR || state_ == STATE_END_OF_STREAM)
+      << state_;
   // If Reset() was called during pending read, read callback should be fired
   // before the reset callback is fired.
-  DCHECK(read_cb_.is_null());
-  DCHECK(!reset_cb_.is_null());
+  DCHECK(!read_cb_);
+  DCHECK(reset_cb_);
 
   // Make sure we read directly from the demuxer after a reset.
   fallback_buffers_.clear();
@@ -829,7 +840,7 @@
   if (state_ != STATE_FLUSHING_DECODER) {
     state_ = STATE_NORMAL;
     // Pending read, on failure, could have fired the reset callback already.
-    if (!reset_cb_.is_null())
+    if (reset_cb_)
       base::ResetAndReturn(&reset_cb_).Run();
     return;
   }
@@ -838,6 +849,69 @@
   ReinitializeDecoder();
 }
 
+template <DemuxerStream::Type StreamType>
+void DecoderStream<StreamType>::ClearOutputs() {
+  preparing_output_ = false;
+  ready_outputs_.clear();
+  unprepared_outputs_.clear();
+  prepare_weak_factory_.InvalidateWeakPtrs();
+}
+
+template <DemuxerStream::Type StreamType>
+void DecoderStream<StreamType>::MaybePrepareAnotherOutput() {
+  FUNCTION_DVLOG(2);
+  DCHECK(task_runner_->BelongsToCurrentThread());
+  DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER ||
+         state_ == STATE_END_OF_STREAM ||
+         state_ == STATE_REINITIALIZING_DECODER)
+      << state_;
+
+  // If there's nothing to prepare or a prepare is underway, we're done.
+  if (!prepare_cb_ || unprepared_outputs_.empty() || preparing_output_)
+    return;
+
+  // If there's too many ready outputs, we're done.
+  if (ready_outputs_.size() >= static_cast<size_t>(GetMaxDecodeRequests()))
+    return;
+
+  preparing_output_ = true;
+  prepare_cb_.Run(
+      unprepared_outputs_.front(),
+      base::BindOnce(&DecoderStream<StreamType>::OnPreparedOutputReady,
+                     prepare_weak_factory_.GetWeakPtr()));
+}
+
+template <DemuxerStream::Type StreamType>
+void DecoderStream<StreamType>::OnPreparedOutputReady(
+    const scoped_refptr<Output>& output) {
+  FUNCTION_DVLOG(2);
+  DCHECK(task_runner_->BelongsToCurrentThread());
+
+  // Errors and reset invalidate the WeakPtr factory for this function, so it
+  // should only be called in normal and flush states.
+  DCHECK(state_ == STATE_NORMAL || state_ == STATE_FLUSHING_DECODER ||
+         state_ == STATE_END_OF_STREAM ||
+         state_ == STATE_REINITIALIZING_DECODER)
+      << state_;
+  DCHECK(!reset_cb_);
+  DCHECK(!unprepared_outputs_.empty());
+  DCHECK(preparing_output_);
+
+  preparing_output_ = false;
+  unprepared_outputs_.pop_front();
+  if (!read_cb_)
+    ready_outputs_.emplace_back(output);
+  else
+    SatisfyRead(OK, output);
+
+  MaybePrepareAnotherOutput();
+
+  // Since decoding may have been stalled by unprepared outputs, we should try
+  // to queue another decode here if one has been returned.
+  if (state_ == STATE_NORMAL && CanDecodeMore())
+    ReadFromDemuxerStream();
+}
+
 template class DecoderStream<DemuxerStream::VIDEO>;
 template class DecoderStream<DemuxerStream::AUDIO>;
 
diff --git a/media/filters/decoder_stream.h b/media/filters/decoder_stream.h
index d8ec237..9d67497 100644
--- a/media/filters/decoder_stream.h
+++ b/media/filters/decoder_stream.h
@@ -36,19 +36,19 @@
 
 // Wraps a DemuxerStream and a list of Decoders and provides decoded
 // output to its client (e.g. Audio/VideoRendererImpl).
-template<DemuxerStream::Type StreamType>
+template <DemuxerStream::Type StreamType>
 class MEDIA_EXPORT DecoderStream {
  public:
-  typedef DecoderStreamTraits<StreamType> StreamTraits;
-  typedef typename StreamTraits::DecoderType Decoder;
-  typedef typename StreamTraits::OutputType Output;
-  typedef typename StreamTraits::DecoderConfigType DecoderConfig;
+  using StreamTraits = DecoderStreamTraits<StreamType>;
+  using Decoder = typename StreamTraits::DecoderType;
+  using Output = typename StreamTraits::OutputType;
+  using DecoderConfig = typename StreamTraits::DecoderConfigType;
 
   enum Status {
-    OK,  // Everything went as planned.
-    ABORTED,  // Read aborted due to Reset() during pending read.
+    OK,                    // Everything went as planned.
+    ABORTED,               // Read aborted due to Reset() during pending read.
     DEMUXER_READ_ABORTED,  // Demuxer returned aborted read.
-    DECODE_ERROR,  // Decoder returned decode error.
+    DECODE_ERROR,          // Decoder returned decode error.
   };
 
   // Callback to create a list of decoders.
@@ -56,10 +56,11 @@
       base::RepeatingCallback<std::vector<std::unique_ptr<Decoder>>()>;
 
   // Indicates completion of a DecoderStream initialization.
-  using InitCB = base::Callback<void(bool success)>;
+  using InitCB = base::RepeatingCallback<void(bool success)>;
 
   // Indicates completion of a DecoderStream read.
-  using ReadCB = base::Callback<void(Status, const scoped_refptr<Output>&)>;
+  using ReadCB =
+      base::RepeatingCallback<void(Status, const scoped_refptr<Output>&)>;
 
   DecoderStream(const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
                 CreateDecodersCB create_decoders_cb,
@@ -96,8 +97,6 @@
 
   // Returns true if the decoder currently has the ability to decode and return
   // an Output.
-  // TODO(rileya): Remove the need for this by refactoring Decoder queueing
-  // behavior.
   bool CanReadWithoutStalling() const;
 
   // Returns maximum concurrent decode requests for the current |decoder_|.
@@ -108,11 +107,26 @@
 
   base::TimeDelta AverageDuration() const;
 
-  // Tells decoders that we won't need frames before |start_timestamp| so they
-  // can be dropped post-decode. Causes outgoing DecoderBuffer packets to be
-  // marked for discard so that decoders may apply further optimizations such as
-  // reduced resolution decoding or filter skipping.
-  void DropFramesBefore(base::TimeDelta start_timestamp);
+  // Indicates that outputs need preparation (e.g., copying into GPU buffers)
+  // before being marked as ready. When an output is given by the decoder it
+  // will be added to |unprepared_outputs_| if a PrepareCB has been specified.
+  // If the size of |ready_outputs_| is less than
+  // Decoder::GetMaxDecodeRequests(), the provided PrepareCB will be called for
+  // the output. Once an output has been prepared by the PrepareCB it must call
+  // the given OutputReadyCB with the prepared output.
+  //
+  // This process is structured such that only a fixed number of outputs are
+  // prepared at any one time; this alleviates resource usage issues incurred by
+  // the preparation process when a decoder has a burst of outputs after on
+  // Decode(). For more context on why, see https://crbug.com/820167.
+  using OutputReadyCB = base::OnceCallback<void(const scoped_refptr<Output>&)>;
+  using PrepareCB = base::RepeatingCallback<void(const scoped_refptr<Output>&,
+                                                 OutputReadyCB)>;
+  void SetPrepareCB(PrepareCB prepare_cb);
+
+  // Indicates that we won't need to prepare outputs before |start_timestamp|,
+  // so that the preparation step (which is generally expensive) can be skipped.
+  void SkipPrepareUntil(base::TimeDelta start_timestamp);
 
   // Allows callers to register for notification of config changes; this is
   // called immediately after receiving the 'kConfigChanged' status from the
@@ -159,8 +173,7 @@
       std::unique_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream);
 
   // Satisfy pending |read_cb_| with |status| and |output|.
-  void SatisfyRead(Status status,
-                   const scoped_refptr<Output>& output);
+  void SatisfyRead(Status status, const scoped_refptr<Output>& output);
 
   // Decodes |buffer| and returns the result via OnDecodeOutputReady().
   // Saves |buffer| into |pending_buffers_| if appropriate.
@@ -196,6 +209,10 @@
   void ResetDecoder();
   void OnDecoderReset();
 
+  void ClearOutputs();
+  void MaybePrepareAnotherOutput();
+  void OnPreparedOutputReady(const scoped_refptr<Output>& frame);
+
   DecoderStreamTraits<StreamType> traits_;
 
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
@@ -215,8 +232,6 @@
 
   CdmContext* cdm_context_;
 
-  std::unique_ptr<DecoderSelector<StreamType>> decoder_selector_;
-
   std::unique_ptr<Decoder> decoder_;
 
   // Whether |decoder_| has produced a frame yet. Reset on fallback.
@@ -234,6 +249,9 @@
 
   std::unique_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream_;
 
+  // Destruct before |decrypting_demuxer_stream_| or |decoder_|.
+  std::unique_ptr<DecoderSelector<StreamType>> decoder_selector_;
+
   ConfigChangeObserverCB config_change_observer_cb_;
   DecoderChangeObserverCB decoder_change_observer_cb_;
 
@@ -242,9 +260,15 @@
   // TODO(sandersd): Turn this into a State. http://crbug.com/408316
   bool decoding_eos_;
 
-  // Decoded buffers that haven't been read yet. Used when the decoder supports
-  // parallel decoding.
-  std::list<scoped_refptr<Output> > ready_outputs_;
+  PrepareCB prepare_cb_;
+  bool preparing_output_;
+
+  // Decoded buffers that haven't been read yet. If |prepare_cb_| has been set
+  // |unprepared_outputs_| will contain buffers which haven't been prepared yet.
+  // Once prepared or if preparation is not required, outputs will be put into
+  // |ready_outputs_|.
+  base::circular_deque<scoped_refptr<Output>> unprepared_outputs_;
+  base::circular_deque<scoped_refptr<Output>> ready_outputs_;
 
   // Number of outstanding decode requests sent to the |decoder_|.
   int pending_decode_requests_;
@@ -269,14 +293,19 @@
   // overwritten in many cases.
   bool pending_demuxer_read_;
 
-  base::TimeDelta start_timestamp_;
+  // Timestamp after which all outputs need to be prepared.
+  base::TimeDelta skip_prepare_until_timestamp_;
 
   // NOTE: Weak pointers must be invalidated before all other member variables.
   base::WeakPtrFactory<DecoderStream<StreamType>> weak_factory_;
 
-  // Used to invalidate pending decode requests and output callbacks when
-  // falling back to a new decoder (on first decode error).
+  // Used to invalidate pending decode requests and output callbacks.
   base::WeakPtrFactory<DecoderStream<StreamType>> fallback_weak_factory_;
+
+  // Used to invalidate outputs awaiting preparation. This can't use either of
+  // the above factories since they are used to bind one time callbacks given
+  // to decoders that may not be reinitialized after Reset().
+  base::WeakPtrFactory<DecoderStream<StreamType>> prepare_weak_factory_;
 };
 
 template <>
@@ -285,8 +314,8 @@
 template <>
 int DecoderStream<DemuxerStream::AUDIO>::GetMaxDecodeRequests() const;
 
-typedef DecoderStream<DemuxerStream::VIDEO> VideoFrameStream;
-typedef DecoderStream<DemuxerStream::AUDIO> AudioBufferStream;
+using VideoFrameStream = DecoderStream<DemuxerStream::VIDEO>;
+using AudioBufferStream = DecoderStream<DemuxerStream::AUDIO>;
 
 }  // namespace media
 
diff --git a/media/filters/demuxer_perftest.cc b/media/filters/demuxer_perftest.cc
index a216a3d..f3fcc00 100644
--- a/media/filters/demuxer_perftest.cc
+++ b/media/filters/demuxer_perftest.cc
@@ -22,7 +22,7 @@
 #include "media/base/timestamp_constants.h"
 #include "media/filters/ffmpeg_demuxer.h"
 #include "media/filters/file_data_source.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/perf/perf_test.h"
 
diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc
index 173afb5..48fe1bc 100644
--- a/media/filters/ffmpeg_demuxer.cc
+++ b/media/filters/ffmpeg_demuxer.cc
@@ -43,7 +43,7 @@
 #include "media/filters/ffmpeg_h264_to_annex_b_bitstream_converter.h"
 #include "media/formats/mpeg/mpeg1_audio_stream_parser.h"
 #include "media/formats/webm/webm_crypto_helpers.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "third_party/ffmpeg/ffmpeg_features.h"
 
 #if BUILDFLAG(ENABLE_HEVC_DEMUXING)
diff --git a/media/filters/ffmpeg_demuxer.h b/media/filters/ffmpeg_demuxer.h
index b7e37e10..a847f6a2 100644
--- a/media/filters/ffmpeg_demuxer.h
+++ b/media/filters/ffmpeg_demuxer.h
@@ -44,7 +44,7 @@
 #include "media/base/video_decoder_config.h"
 #include "media/ffmpeg/ffmpeg_deleters.h"
 #include "media/filters/blocking_url_protocol.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 // FFmpeg forward declarations.
 struct AVFormatContext;
diff --git a/media/filters/ffmpeg_demuxer_unittest.cc b/media/filters/ffmpeg_demuxer_unittest.cc
index 0eb22b6..0df8998e 100644
--- a/media/filters/ffmpeg_demuxer_unittest.cc
+++ b/media/filters/ffmpeg_demuxer_unittest.cc
@@ -33,7 +33,7 @@
 #include "media/filters/ffmpeg_demuxer.h"
 #include "media/filters/file_data_source.h"
 #include "media/formats/mp4/avc.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using ::testing::AnyNumber;
diff --git a/media/filters/ffmpeg_video_decoder.cc b/media/filters/ffmpeg_video_decoder.cc
index 87be73f..03a50b2 100644
--- a/media/filters/ffmpeg_video_decoder.cc
+++ b/media/filters/ffmpeg_video_decoder.cc
@@ -184,9 +184,20 @@
   video_frame->metadata()->SetInteger(VideoFrameMetadata::COLOR_SPACE,
                                       color_space);
 
-  if (codec_context->color_primaries != AVCOL_PRI_UNSPECIFIED ||
-      codec_context->color_trc != AVCOL_TRC_UNSPECIFIED ||
-      codec_context->colorspace != AVCOL_SPC_UNSPECIFIED) {
+  if (codec_context->codec_id == AV_CODEC_ID_VP8 &&
+      codec_context->color_primaries == AVCOL_PRI_UNSPECIFIED &&
+      codec_context->color_trc == AVCOL_TRC_UNSPECIFIED &&
+      codec_context->colorspace == AVCOL_SPC_BT470BG) {
+    // vp8 has no colorspace information, except for the color range.
+    // However, because of a comment in the vp8 spec, ffmpeg sets the
+    // colorspace to BT470BG. We detect this and treat it as unset.
+    // If the color range is set to full range, we use the jpeg color space.
+    if (codec_context->color_range == AVCOL_RANGE_JPEG) {
+      video_frame->set_color_space(gfx::ColorSpace::CreateJpeg());
+    }
+  } else if (codec_context->color_primaries != AVCOL_PRI_UNSPECIFIED ||
+             codec_context->color_trc != AVCOL_TRC_UNSPECIFIED ||
+             codec_context->colorspace != AVCOL_SPC_UNSPECIFIED) {
     media::VideoColorSpace video_color_space = media::VideoColorSpace(
         codec_context->color_primaries, codec_context->color_trc,
         codec_context->colorspace,
diff --git a/media/filters/gpu_video_decoder.cc b/media/filters/gpu_video_decoder.cc
index ae6505e8..a47e3acd 100644
--- a/media/filters/gpu_video_decoder.cc
+++ b/media/filters/gpu_video_decoder.cc
@@ -29,7 +29,7 @@
 #include "media/base/pipeline_status.h"
 #include "media/base/surface_manager.h"
 #include "media/base/video_decoder_config.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "media/video/gpu_video_accelerator_factories.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 
diff --git a/media/filters/media_file_checker_unittest.cc b/media/filters/media_file_checker_unittest.cc
index c04e780..27d47960 100644
--- a/media/filters/media_file_checker_unittest.cc
+++ b/media/filters/media_file_checker_unittest.cc
@@ -10,7 +10,7 @@
 #include "base/logging.h"
 #include "build/build_config.h"
 #include "media/base/test_data_util.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace media {
diff --git a/media/filters/source_buffer_range.cc b/media/filters/source_buffer_range.cc
index fb4bb21..72407b3 100644
--- a/media/filters/source_buffer_range.cc
+++ b/media/filters/source_buffer_range.cc
@@ -82,6 +82,12 @@
     return;
   }
 
+  // Do not adjust estimate for Audio buffers to avoid competing with
+  // SourceBufferStream::TrimSpliceOverlap()
+  if (buffers_.front()->type() == StreamParserBuffer::Type::AUDIO) {
+    return;
+  }
+
   // If the last of the previously appended buffers contains estimated duration,
   // we now refine that estimate by taking the PTS delta from the first new
   // buffer being appended.
diff --git a/media/filters/source_buffer_stream.cc b/media/filters/source_buffer_stream.cc
index b1d73ea..89c85aa 100644
--- a/media/filters/source_buffer_stream.cc
+++ b/media/filters/source_buffer_stream.cc
@@ -12,6 +12,7 @@
 
 #include "base/bind.h"
 #include "base/logging.h"
+#include "base/metrics/histogram_macros.h"
 #include "base/trace_event/trace_event.h"
 #include "media/base/demuxer_memory_limit.h"
 #include "media/base/media_switches.h"
@@ -146,7 +147,7 @@
   for (const auto& buf : buffers) {
     result << "\tdts=" << buf->GetDecodeTimestamp().InMicroseconds() << " "
            << buf->AsHumanReadableString()
-           << ", is_duration_estimated=" << buf->is_duration_estimated()
+           << ", duration_type=" << static_cast<int>(buf->duration_type())
            << "\n";
   }
 
@@ -1289,6 +1290,14 @@
     return;
   }
 
+  // At this point, trimming will go ahead. Log UMAs about the type of duration
+  // in the original overlapped buffer. The hope is that splicing on
+  // rough-estimated durations is rare enough that we can disable it outright.
+  // This would allow more liberal estimates of audio durations.
+  UMA_HISTOGRAM_ENUMERATION(
+      "Media.MSE.AudioSpliceDurationType", overlapped_buffer->duration_type(),
+      static_cast<int>(DurationType::kDurationTypeMax) + 1);
+
   // Trim overlap from the existing buffer.
   DecoderBuffer::DiscardPadding discard_padding =
       overlapped_buffer->discard_padding();
diff --git a/media/filters/source_buffer_stream_unittest.cc b/media/filters/source_buffer_stream_unittest.cc
index bc86746..83ec07e 100644
--- a/media/filters/source_buffer_stream_unittest.cc
+++ b/media/filters/source_buffer_stream_unittest.cc
@@ -523,6 +523,20 @@
   BufferingApi buffering_api_;
 
  private:
+  DemuxerStream::Type GetStreamType() {
+    switch (STREAM_OP(GetType())) {
+      case SourceBufferStreamType::kAudio:
+        return DemuxerStream::AUDIO;
+      case SourceBufferStreamType::kVideo:
+        return DemuxerStream::VIDEO;
+      case SourceBufferStreamType::kText:
+        return DemuxerStream::TEXT;
+      default:
+        NOTREACHED();
+        return DemuxerStream::UNKNOWN;
+    }
+  }
+
   base::TimeDelta ConvertToFrameDuration(int frames_per_second) {
     return base::TimeDelta::FromMicroseconds(
         base::Time::kMicrosecondsPerSecond / frames_per_second);
@@ -548,10 +562,9 @@
     for (int i = 0; i < number_of_buffers; i++) {
       int position = starting_position + i;
       bool is_keyframe = position % keyframe_interval == 0;
-      // Buffer type and track ID are meaningless to these tests.
-      scoped_refptr<StreamParserBuffer> buffer =
-          StreamParserBuffer::CopyFrom(data, size, is_keyframe,
-                                       DemuxerStream::AUDIO, 0);
+      // Track ID is meaningless to these tests.
+      scoped_refptr<StreamParserBuffer> buffer = StreamParserBuffer::CopyFrom(
+          data, size, is_keyframe, GetStreamType(), 0);
       base::TimeDelta timestamp = frame_duration_ * position;
 
       if (i == 0)
@@ -703,12 +716,12 @@
         buffer_timestamps.push_back(base::TimeDelta::FromMicroseconds(us));
       }
 
-      // Create buffer. Buffer type and track ID are meaningless to these tests.
-      scoped_refptr<StreamParserBuffer> buffer =
-          StreamParserBuffer::CopyFrom(&kDataA, kDataSize, is_keyframe,
-                                       DemuxerStream::AUDIO, 0);
+      // Create buffer. Track ID is meaningless to these tests
+      scoped_refptr<StreamParserBuffer> buffer = StreamParserBuffer::CopyFrom(
+          &kDataA, kDataSize, is_keyframe, GetStreamType(), 0);
       buffer->set_timestamp(buffer_timestamps[0]);
-      buffer->set_is_duration_estimated(is_duration_estimated);
+      if (is_duration_estimated)
+        buffer->set_duration_type(DurationType::kRoughEstimate);
 
       if (buffer_timestamps[1] != buffer_timestamps[0]) {
         buffer->SetDecodeTimestamp(
@@ -722,8 +735,8 @@
       // it as the preroll.
       if (has_preroll) {
         scoped_refptr<StreamParserBuffer> preroll_buffer =
-            StreamParserBuffer::CopyFrom(
-                &kDataA, kDataSize, is_keyframe, DemuxerStream::AUDIO, 0);
+            StreamParserBuffer::CopyFrom(&kDataA, kDataSize, is_keyframe,
+                                         GetStreamType(), 0);
         preroll_buffer->set_duration(frame_duration_);
         buffer->SetPrerollBuffer(preroll_buffer);
       }
diff --git a/media/filters/stream_parser_factory.cc b/media/filters/stream_parser_factory.cc
index c958632..687ac620 100644
--- a/media/filters/stream_parser_factory.cc
+++ b/media/filters/stream_parser_factory.cc
@@ -20,7 +20,7 @@
 #include "media/formats/mpeg/adts_stream_parser.h"
 #include "media/formats/mpeg/mpeg1_audio_stream_parser.h"
 #include "media/formats/webm/webm_stream_parser.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "third_party/libaom/av1_features.h"
 
 #if defined(OS_ANDROID)
diff --git a/media/filters/video_frame_stream_unittest.cc b/media/filters/video_frame_stream_unittest.cc
index 7cdf6f3..65a81949 100644
--- a/media/filters/video_frame_stream_unittest.cc
+++ b/media/filters/video_frame_stream_unittest.cc
@@ -50,15 +50,18 @@
 struct VideoFrameStreamTestParams {
   VideoFrameStreamTestParams(bool is_encrypted,
                              bool has_decryptor,
+                             bool has_prepare,
                              int decoding_delay,
                              int parallel_decoding)
       : is_encrypted(is_encrypted),
         has_decryptor(has_decryptor),
+        has_prepare(has_prepare),
         decoding_delay(decoding_delay),
         parallel_decoding(parallel_decoding) {}
 
   bool is_encrypted;
   bool has_decryptor;
+  bool has_prepare;
   int decoding_delay;
   int parallel_decoding;
 };
@@ -86,6 +89,10 @@
         &media_log_));
     video_frame_stream_->set_decoder_change_observer_for_testing(base::Bind(
         &VideoFrameStreamTest::OnDecoderChanged, base::Unretained(this)));
+    if (GetParam().has_prepare) {
+      video_frame_stream_->SetPrepareCB(base::BindRepeating(
+          &VideoFrameStreamTest::PrepareFrame, base::Unretained(this)));
+    }
 
     if (GetParam().is_encrypted && GetParam().has_decryptor) {
       decryptor_.reset(new NiceMock<MockDecryptor>());
@@ -126,6 +133,13 @@
     DCHECK(!pending_stop_);
   }
 
+  void PrepareFrame(const scoped_refptr<VideoFrame>& frame,
+                    VideoFrameStream::OutputReadyCB output_ready_cb) {
+    // Simulate some delay in return of the output.
+    message_loop_.task_runner()->PostTask(
+        FROM_HERE, base::BindOnce(std::move(output_ready_cb), frame));
+  }
+
   void OnBytesDecoded(int count) {
     num_decoded_bytes_unreported_ += count;
   }
@@ -473,25 +487,31 @@
 INSTANTIATE_TEST_CASE_P(
     Clear,
     VideoFrameStreamTest,
-    ::testing::Values(VideoFrameStreamTestParams(false, false, 0, 1),
-                      VideoFrameStreamTestParams(false, false, 3, 1),
-                      VideoFrameStreamTestParams(false, false, 7, 1)));
+    ::testing::Values(VideoFrameStreamTestParams(false, false, false, 0, 1),
+                      VideoFrameStreamTestParams(false, false, false, 3, 1),
+                      VideoFrameStreamTestParams(false, false, false, 7, 1),
+                      VideoFrameStreamTestParams(false, false, true, 0, 1),
+                      VideoFrameStreamTestParams(false, false, true, 3, 1)));
 
 INSTANTIATE_TEST_CASE_P(
     EncryptedWithDecryptor,
     VideoFrameStreamTest,
-    ::testing::Values(VideoFrameStreamTestParams(true, true, 7, 1)));
+    ::testing::Values(VideoFrameStreamTestParams(true, true, false, 7, 1),
+                      VideoFrameStreamTestParams(true, true, true, 7, 1)));
 
 INSTANTIATE_TEST_CASE_P(
     EncryptedWithoutDecryptor,
     VideoFrameStreamTest,
-    ::testing::Values(VideoFrameStreamTestParams(true, false, 7, 1)));
+    ::testing::Values(VideoFrameStreamTestParams(true, false, false, 7, 1),
+                      VideoFrameStreamTestParams(true, false, true, 7, 1)));
 
 INSTANTIATE_TEST_CASE_P(
     Clear_Parallel,
     VideoFrameStreamTest,
-    ::testing::Values(VideoFrameStreamTestParams(false, false, 0, 3),
-                      VideoFrameStreamTestParams(false, false, 2, 3)));
+    ::testing::Values(VideoFrameStreamTestParams(false, false, false, 0, 3),
+                      VideoFrameStreamTestParams(false, false, false, 2, 3),
+                      VideoFrameStreamTestParams(false, false, true, 0, 3),
+                      VideoFrameStreamTestParams(false, false, true, 2, 3)));
 
 TEST_P(VideoFrameStreamTest, CanReadWithoutStallingAtAnyTime) {
   ASSERT_FALSE(video_frame_stream_->CanReadWithoutStalling());
diff --git a/media/formats/mp2t/es_parser_adts.h b/media/formats/mp2t/es_parser_adts.h
index 3b52f6e..61b368ed 100644
--- a/media/formats/mp2t/es_parser_adts.h
+++ b/media/formats/mp2t/es_parser_adts.h
@@ -20,7 +20,7 @@
 #include "media/base/media_export.h"
 #include "media/formats/mp2t/es_parser.h"
 #include "media/formats/mpeg/adts_stream_parser.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 namespace media {
 class AudioTimestampHelper;
diff --git a/media/formats/mp2t/es_parser_h264.h b/media/formats/mp2t/es_parser_h264.h
index 91c74601..5e22635 100644
--- a/media/formats/mp2t/es_parser_h264.h
+++ b/media/formats/mp2t/es_parser_h264.h
@@ -19,7 +19,7 @@
 #include "media/base/video_decoder_config.h"
 #include "media/formats/mp2t/es_adapter_video.h"
 #include "media/formats/mp2t/es_parser.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 namespace media {
 class EncryptionScheme;
diff --git a/media/formats/mp2t/mp2t_stream_parser.h b/media/formats/mp2t/mp2t_stream_parser.h
index 548270be..835fafe 100644
--- a/media/formats/mp2t/mp2t_stream_parser.h
+++ b/media/formats/mp2t/mp2t_stream_parser.h
@@ -21,7 +21,7 @@
 #include "media/base/stream_parser.h"
 #include "media/base/video_decoder_config.h"
 #include "media/formats/mp2t/timestamp_unroller.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 namespace media {
 
diff --git a/media/formats/mp2t/mp2t_stream_parser_unittest.cc b/media/formats/mp2t/mp2t_stream_parser_unittest.cc
index 8702bef..137a742 100644
--- a/media/formats/mp2t/mp2t_stream_parser_unittest.cc
+++ b/media/formats/mp2t/mp2t_stream_parser_unittest.cc
@@ -27,7 +27,7 @@
 #include "media/base/test_data_util.h"
 #include "media/base/text_track_config.h"
 #include "media/base/video_decoder_config.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
diff --git a/media/formats/mp4/avc.h b/media/formats/mp4/avc.h
index 74118565..b9ce1c8 100644
--- a/media/formats/mp4/avc.h
+++ b/media/formats/mp4/avc.h
@@ -14,7 +14,7 @@
 #include "base/macros.h"
 #include "media/base/media_export.h"
 #include "media/formats/mp4/bitstream_converter.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 namespace media {
 
diff --git a/media/formats/mp4/box_definitions.cc b/media/formats/mp4/box_definitions.cc
index 78c6b2d9..307419e7 100644
--- a/media/formats/mp4/box_definitions.cc
+++ b/media/formats/mp4/box_definitions.cc
@@ -16,7 +16,7 @@
 #include "media/base/video_util.h"
 #include "media/formats/mp4/es_descriptor.h"
 #include "media/formats/mp4/rcheck.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "third_party/libaom/av1_features.h"
 
 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
diff --git a/media/formats/mp4/box_definitions.h b/media/formats/mp4/box_definitions.h
index 62ec5eb..c251c8b 100644
--- a/media/formats/mp4/box_definitions.h
+++ b/media/formats/mp4/box_definitions.h
@@ -20,7 +20,7 @@
 #include "media/formats/mp4/avc.h"
 #include "media/formats/mp4/box_reader.h"
 #include "media/formats/mp4/fourccs.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 namespace media {
 namespace mp4 {
diff --git a/media/formats/mp4/fourccs.h b/media/formats/mp4/fourccs.h
index c66c92f..bdf3d5fa 100644
--- a/media/formats/mp4/fourccs.h
+++ b/media/formats/mp4/fourccs.h
@@ -7,7 +7,7 @@
 
 #include <string>
 
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "third_party/libaom/av1_features.h"
 
 namespace media {
diff --git a/media/formats/mp4/mp4_stream_parser_unittest.cc b/media/formats/mp4/mp4_stream_parser_unittest.cc
index e7f0efd..588ebafa 100644
--- a/media/formats/mp4/mp4_stream_parser_unittest.cc
+++ b/media/formats/mp4/mp4_stream_parser_unittest.cc
@@ -31,7 +31,7 @@
 #include "media/base/video_decoder_config.h"
 #include "media/formats/mp4/es_descriptor.h"
 #include "media/formats/mp4/fourccs.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/media/formats/mp4/track_run_iterator.cc b/media/formats/mp4/track_run_iterator.cc
index f5dd6aa2..1e35058e 100644
--- a/media/formats/mp4/track_run_iterator.cc
+++ b/media/formats/mp4/track_run_iterator.cc
@@ -16,7 +16,7 @@
 #include "media/base/timestamp_constants.h"
 #include "media/formats/mp4/rcheck.h"
 #include "media/formats/mp4/sample_to_group_iterator.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 namespace media {
 namespace mp4 {
diff --git a/media/formats/mp4/track_run_iterator.h b/media/formats/mp4/track_run_iterator.h
index b138780..59521c3 100644
--- a/media/formats/mp4/track_run_iterator.h
+++ b/media/formats/mp4/track_run_iterator.h
@@ -17,7 +17,7 @@
 #include "media/base/media_log.h"
 #include "media/base/stream_parser_buffer.h"
 #include "media/formats/mp4/box_definitions.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 namespace media {
 
diff --git a/media/formats/webm/webm_cluster_parser.cc b/media/formats/webm/webm_cluster_parser.cc
index 583f188..88bdabd2 100644
--- a/media/formats/webm/webm_cluster_parser.cc
+++ b/media/formats/webm/webm_cluster_parser.cc
@@ -54,15 +54,22 @@
       audio_codec_(audio_codec),
       parser_(kWebMIdCluster, this),
       cluster_start_time_(kNoTimestamp),
-      audio_(audio_track_num, false, audio_default_duration, media_log),
-      video_(video_track_num, true, video_default_duration, media_log),
+      audio_(audio_track_num,
+             TrackType::AUDIO,
+             audio_default_duration,
+             media_log),
+      video_(video_track_num,
+             TrackType::VIDEO,
+             video_default_duration,
+             media_log),
       ready_buffer_upper_bound_(kNoDecodeTimestamp()),
       media_log_(media_log) {
   for (WebMTracksParser::TextTracks::const_iterator it = text_tracks.begin();
        it != text_tracks.end();
        ++it) {
     text_track_map_.insert(std::make_pair(
-        it->first, Track(it->first, false, kNoTimestamp, media_log_)));
+        it->first,
+        Track(it->first, TrackType::TEXT, kNoTimestamp, media_log_)));
   }
 }
 
@@ -616,13 +623,14 @@
 }
 
 WebMClusterParser::Track::Track(int track_num,
-                                bool is_video,
+                                TrackType track_type,
                                 base::TimeDelta default_duration,
                                 MediaLog* media_log)
     : track_num_(track_num),
-      is_video_(is_video),
+      track_type_(track_type),
       default_duration_(default_duration),
-      estimated_next_frame_duration_(kNoTimestamp),
+      min_frame_duration_(kNoTimestamp),
+      max_frame_duration_(kNoTimestamp),
       media_log_(media_log) {
   DCHECK(default_duration_ == kNoTimestamp ||
          default_duration_ > base::TimeDelta());
@@ -714,24 +722,28 @@
   if (!last_added_buffer_missing_duration_.get())
     return;
 
-  base::TimeDelta estimated_duration = GetDurationEstimate();
-  last_added_buffer_missing_duration_->set_duration(estimated_duration);
+  bool constant_duration_estimate = false;
+  last_added_buffer_missing_duration_->set_duration(
+      GetDurationEstimate(&constant_duration_estimate));
 
-  if (is_video_) {
-    // Exposing estimation so splicing/overlap frame processing can make
-    // informed decisions downstream.
-    // TODO(chcunningham): Set this for audio as well in later change where
-    // audio is switched to max estimation and splicing is disabled.
-    last_added_buffer_missing_duration_->set_is_duration_estimated(true);
+  // Signal to downstream to make informed decisions about buffer adjacency
+  // and splicing.
+  if (constant_duration_estimate) {
+    last_added_buffer_missing_duration_->set_duration_type(
+        DurationType::kConstantEstimate);
+  } else {
+    last_added_buffer_missing_duration_->set_duration_type(
+        DurationType::kRoughEstimate);
   }
 
   LIMITED_MEDIA_LOG(INFO, media_log_, num_duration_estimates_,
                     kMaxDurationEstimateLogs)
-      << "Estimating WebM block duration to be "
-      << estimated_duration.InMilliseconds()
-      << "ms for the last (Simple)Block in the Cluster for this Track. Use "
-         "BlockGroups with BlockDurations at the end of each Track in a "
-         "Cluster to avoid estimation.";
+      << "Estimating WebM block duration="
+      << last_added_buffer_missing_duration_->duration().InMilliseconds()
+      << "ms for the last (Simple)Block in the Cluster for this Track (PTS="
+      << last_added_buffer_missing_duration_->timestamp().InMilliseconds()
+      << "ms). Use BlockGroups with BlockDurations at the end of each Cluster "
+      << "to avoid estimation.";
 
   DVLOG(2) << __func__ << " new dur : ts "
            << last_added_buffer_missing_duration_->timestamp().InSecondsF()
@@ -747,7 +759,7 @@
 }
 
 void WebMClusterParser::Track::ClearReadyBuffers() {
-  // Note that |buffers_| are kept and |estimated_next_frame_duration_| is not
+  // Note that |buffers_| are kept and |{min|max}_frame_duration_| is not
   // reset here.
   ready_buffers_.clear();
 }
@@ -776,33 +788,26 @@
     return false;
   }
 
-  // The estimated frame duration is the minimum (for audio) or the maximum
-  // (for video) non-zero duration since the last initialization segment. The
-  // minimum is used for audio to ensure frame durations aren't overestimated,
-  // triggering unnecessary frame splicing. For video, splicing does not apply,
-  // so maximum is used and overlap is simply resolved by showing the
-  // later of the overlapping frames at its given PTS, effectively trimming down
-  // the over-estimated duration of the previous frame.
-  // TODO(chcunningham): Use max for audio and disable splicing whenever
-  // estimated buffers are encountered.
   if (duration > base::TimeDelta()) {
-    base::TimeDelta orig_duration_estimate = estimated_next_frame_duration_;
-    if (estimated_next_frame_duration_ == kNoTimestamp) {
-      estimated_next_frame_duration_ = duration;
-    } else if (is_video_) {
-      estimated_next_frame_duration_ =
-          std::max(duration, estimated_next_frame_duration_);
+    base::TimeDelta orig_min_duration = min_frame_duration_;
+    base::TimeDelta orig_max_duration = max_frame_duration_;
+
+    if (min_frame_duration_ == kNoTimestamp) {
+      DCHECK_EQ(max_frame_duration_, kNoTimestamp);
+      min_frame_duration_ = max_frame_duration_ = duration;
     } else {
-      estimated_next_frame_duration_ =
-          std::min(duration, estimated_next_frame_duration_);
+      min_frame_duration_ = std::min(min_frame_duration_, duration);
+      max_frame_duration_ = std::max(max_frame_duration_, duration);
     }
 
-    if (orig_duration_estimate != estimated_next_frame_duration_) {
-      DVLOG(3) << "Updated duration estimate:"
-               << orig_duration_estimate
-               << " -> "
-               << estimated_next_frame_duration_
-               << " at timestamp: "
+    if (min_frame_duration_ != orig_min_duration) {
+      DVLOG(3) << "Updated min duration estimate:" << orig_min_duration
+               << " -> " << min_frame_duration_ << " at timestamp: "
+               << buffer->GetDecodeTimestamp().InSecondsF();
+    }
+    if (max_frame_duration_ != orig_max_duration) {
+      DVLOG(3) << "Updated max duration estimate:" << orig_max_duration
+               << " -> " << max_frame_duration_ << " at timestamp: "
                << buffer->GetDecodeTimestamp().InSecondsF();
     }
   }
@@ -811,18 +816,34 @@
   return true;
 }
 
-base::TimeDelta WebMClusterParser::Track::GetDurationEstimate() {
-  base::TimeDelta duration = estimated_next_frame_duration_;
-  if (duration != kNoTimestamp) {
-    DVLOG(3) << __func__ << " : using estimated duration";
-  } else {
+base::TimeDelta WebMClusterParser::Track::GetDurationEstimate(
+    bool* constant_duration_estimate) {
+  *constant_duration_estimate = false;
+  base::TimeDelta duration;
+
+  if (min_frame_duration_ == kNoTimestamp) {
+    DCHECK_EQ(max_frame_duration_, kNoTimestamp);
     DVLOG(3) << __func__ << " : using hardcoded default duration";
-    if (is_video_) {
-      duration = base::TimeDelta::FromMilliseconds(
-          kDefaultVideoBufferDurationInMs);
+    if (track_type_ == TrackType::AUDIO) {
+      duration =
+          base::TimeDelta::FromMilliseconds(kDefaultAudioBufferDurationInMs);
     } else {
-      duration = base::TimeDelta::FromMilliseconds(
-          kDefaultAudioBufferDurationInMs);
+      // Text and video tracks can both use the larger video default duration.
+      duration =
+          base::TimeDelta::FromMilliseconds(kDefaultVideoBufferDurationInMs);
+    }
+  } else {
+    *constant_duration_estimate = min_frame_duration_ == max_frame_duration_;
+
+    if (track_type_ == TrackType::AUDIO) {
+      // Audio uses min to avoid overtriggering splice trimming logic. See
+      // http://crbug.com/396634
+      duration = min_frame_duration_;
+    } else {
+      // Both kText and kVideo types safely use max because these formats don't
+      // undergo trimming analagous to the audio splicing (no risk of over
+      // trimming nor av sync loss).
+      duration = max_frame_duration_;
     }
   }
 
diff --git a/media/formats/webm/webm_cluster_parser.h b/media/formats/webm/webm_cluster_parser.h
index f107d80..f2e35df 100644
--- a/media/formats/webm/webm_cluster_parser.h
+++ b/media/formats/webm/webm_cluster_parser.h
@@ -48,11 +48,13 @@
   static const uint16_t kOpusFrameDurationsMu[];
 
  private:
+  typedef StreamParserBuffer::Type TrackType;
+
   // Helper class that manages per-track state.
   class Track {
    public:
     Track(int track_num,
-          bool is_video,
+          TrackType track_type,
           base::TimeDelta default_duration,
           MediaLog* media_log);
     Track(const Track& other);
@@ -80,8 +82,8 @@
     bool AddBuffer(const scoped_refptr<StreamParserBuffer>& buffer);
 
     // If |last_added_buffer_missing_duration_| is set, updates its duration to
-    // be non-kNoTimestamp value of |estimated_next_frame_duration_| or a
-    // hard-coded default, then adds it to |buffers_| and unsets
+    // be non-kNoTimestamp value of |{min|max}_frame_duration_| or a hard-coded
+    // default, then adds it to |buffers_| and unsets
     // |last_added_buffer_missing_duration_|. (This method helps stream parser
     // emit all buffers in a media segment before signaling end of segment.)
     void ApplyDurationEstimateIfNeeded();
@@ -100,21 +102,22 @@
 
    private:
     // Helper that sanity-checks |buffer| duration, updates
-    // |estimated_next_frame_duration_|, and adds |buffer| to |buffers_|.
-    // Returns false if |buffer| failed sanity check and therefore was not added
-    // to |buffers_|. Returns true otherwise.
+    // |{min|max}_frame_duration_|, and adds |buffer| to |buffers_|. Returns
+    // false if |buffer| failed sanity check and therefore was not added to
+    // |buffers_|. Returns true otherwise.
     bool QueueBuffer(const scoped_refptr<StreamParserBuffer>& buffer);
 
     // Helper that calculates the buffer duration to use in
-    // ApplyDurationEstimateIfNeeded().
-    base::TimeDelta GetDurationEstimate();
+    // ApplyDurationEstimateIfNeeded(). |constant_duration| will be set true
+    // when track is so far comprised of all same-duration packets.
+    base::TimeDelta GetDurationEstimate(bool* constant_duration);
 
     // Counts the number of estimated durations used in this track. Used to
     // prevent log spam for MEDIA_LOG()s about estimated duration.
     int num_duration_estimates_ = 0;
 
     int track_num_;
-    bool is_video_;
+    TrackType track_type_;
 
     // Parsed track buffers, each with duration and in (decode) timestamp order,
     // that have not yet been extracted into |ready_buffers_|. Note that up to
@@ -131,15 +134,18 @@
     // timestamp).
     BufferQueue ready_buffers_;
 
-    // If kNoTimestamp, then |estimated_next_frame_duration_| will be used.
+    // If kNoTimestamp, then |{min|max}_frame_duration_| will be used.
     base::TimeDelta default_duration_;
 
-    // If kNoTimestamp, then a default value will be used. This estimate is
-    // the maximum (for video), or minimum (for audio) duration seen so far for
-    // this track, and is used only if |default_duration_| is kNoTimestamp.
-    // TODO(chcunningham): Use maximum for audio too, adding checks to disable
-    // splicing when these estimates are observed in SourceBufferStream.
-    base::TimeDelta estimated_next_frame_duration_;
+    // Tracks the min/max durations seen for this track. Used to estimate block
+    // durations at the end of clusters. Video uses maximum to minimize chance
+    // of introudcing discontinuities. Audio uses minimum to minimize chance of
+    // overtriggering splice logic, which may lead to AV sync loss. Keeping both
+    // min and max allows us to detect cases where min==max, which gives high
+    // enough confidence in estimate to potentially allow splicing. Research
+    // is ongoing. See http://crbug.com/396634.
+    base::TimeDelta min_frame_duration_;
+    base::TimeDelta max_frame_duration_;
 
     MediaLog* media_log_;
   };
diff --git a/media/formats/webm/webm_cluster_parser_unittest.cc b/media/formats/webm/webm_cluster_parser_unittest.cc
index 7b7e9f4..b5d0b8c 100644
--- a/media/formats/webm/webm_cluster_parser_unittest.cc
+++ b/media/formats/webm/webm_cluster_parser_unittest.cc
@@ -20,6 +20,7 @@
 #include "media/base/audio_decoder_config.h"
 #include "media/base/decrypt_config.h"
 #include "media/base/mock_media_log.h"
+#include "media/base/test_helpers.h"
 #include "media/base/timestamp_constants.h"
 #include "media/formats/webm/cluster_builder.h"
 #include "media/formats/webm/opus_packet_builder.h"
@@ -46,15 +47,6 @@
                "ms. Should be no greater than 120ms.");
 }
 
-MATCHER_P(WebMSimpleBlockDurationEstimated, estimated_duration_ms, "") {
-  return CONTAINS_STRING(arg, "Estimating WebM block duration to be " +
-                                  base::IntToString(estimated_duration_ms) +
-                                  "ms for the last (Simple)Block in the "
-                                  "Cluster for this Track. Use BlockGroups "
-                                  "with BlockDurations at the end of each "
-                                  "Track in a Cluster to avoid estimation.");
-}
-
 MATCHER_P2(WebMBlockDurationMismatchesOpusDuration,
            block_duration_ms,
            opus_duration_ms,
diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn
index ba89d7c..35cff6b 100644
--- a/media/gpu/BUILD.gn
+++ b/media/gpu/BUILD.gn
@@ -9,8 +9,8 @@
 import("//media/media_options.gni")
 import("//testing/test.gni")
 
-buildflag_header("features") {
-  header = "features.h"
+buildflag_header("buildflags") {
+  header = "buildflags.h"
 
   flags = [
     "USE_VAAPI=$use_vaapi",
@@ -106,8 +106,8 @@
   ]
 
   public_deps = [
+    ":buildflags",
     ":common",
-    ":features",
     "//base",
     "//gpu",
     "//media",
@@ -166,6 +166,9 @@
       "android/codec_image_group.h",
       "android/codec_wrapper.cc",
       "android/codec_wrapper.h",
+      "android/command_buffer_stub_wrapper.h",
+      "android/command_buffer_stub_wrapper_impl.cc",
+      "android/command_buffer_stub_wrapper_impl.h",
       "android/content_video_view_overlay.cc",
       "android/content_video_view_overlay.h",
       "android/content_video_view_overlay_allocator.cc",
@@ -181,13 +184,17 @@
       "android/surface_chooser_helper.h",
       "android/surface_texture_gl_owner.cc",
       "android/surface_texture_gl_owner.h",
+      "android/texture_pool.cc",
+      "android/texture_pool.h",
+      "android/texture_wrapper.cc",
+      "android/texture_wrapper.h",
       "android/video_frame_factory.h",
       "android/video_frame_factory_impl.cc",
       "android/video_frame_factory_impl.h",
     ]
     deps += [
       # TODO(crbug.com/789435): This can be removed once CdmManager is removed.
-      "//media/mojo:features",
+      "//media/mojo:buildflags",
       "//services/service_manager/public/cpp:cpp",
     ]
     if (enable_webrtc) {
@@ -331,7 +338,7 @@
   }
 
   deps = [
-    ":features",
+    ":buildflags",
     "//base",
     "//media",
     "//ui/gfx:buffer_types",
@@ -427,6 +434,8 @@
       "android/media_codec_video_decoder_unittest.cc",
       "android/mock_android_video_surface_chooser.cc",
       "android/mock_android_video_surface_chooser.h",
+      "android/mock_command_buffer_stub_wrapper.cc",
+      "android/mock_command_buffer_stub_wrapper.h",
       "android/mock_device_info.cc",
       "android/mock_device_info.h",
       "android/mock_promotion_hint_aggregator.cc",
@@ -436,6 +445,7 @@
       "android/promotion_hint_aggregator_impl_unittest.cc",
       "android/surface_chooser_helper_unittest.cc",
       "android/surface_texture_gl_owner_unittest.cc",
+      "android/texture_pool_unittest.cc",
       "android/video_frame_factory_impl_unittest.cc",
     ]
     deps = [
diff --git a/media/gpu/android/android_video_decode_accelerator.cc b/media/gpu/android/android_video_decode_accelerator.cc
index d8c8f841..e912e765 100644
--- a/media/gpu/android/android_video_decode_accelerator.cc
+++ b/media/gpu/android/android_video_decode_accelerator.cc
@@ -42,7 +42,7 @@
 #include "media/gpu/android/device_info.h"
 #include "media/gpu/android/promotion_hint_aggregator_impl.h"
 #include "media/gpu/shared_memory_region.h"
-#include "media/mojo/features.h"
+#include "media/mojo/buildflags.h"
 #include "media/video/picture.h"
 #include "services/service_manager/public/cpp/service_context_ref.h"
 #include "ui/gl/android/scoped_java_surface.h"
diff --git a/media/gpu/android/command_buffer_stub_wrapper.h b/media/gpu/android/command_buffer_stub_wrapper.h
new file mode 100644
index 0000000..38bed44
--- /dev/null
+++ b/media/gpu/android/command_buffer_stub_wrapper.h
@@ -0,0 +1,39 @@
+// Copyright 2018 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 MEDIA_GPU_ANDROID_COMMAND_BUFFER_STUB_WRAPPER_H_
+#define MEDIA_GPU_ANDROID_COMMAND_BUFFER_STUB_WRAPPER_H_
+
+#include "gpu/ipc/service/command_buffer_stub.h"
+
+namespace media {
+
+// Helpful class to wrap a CommandBufferStub that we can mock out more easily.
+// Mocking out a CommandBufferStub + DecoderContext is quite annoying, since we
+// really need very little.
+// TODO(liberato): consider making this refcounted, so that one injected mock
+// can be re-used as its passed from class to class.  In that case, it likely
+// has to keep its own DestructionObserver list, and register itself as a
+// DestructionObserver on the stub.
+// TODO(liberato): once this interface is stable, move this to media/gpu and
+// use it on non-android platforms.
+class CommandBufferStubWrapper {
+ public:
+  virtual ~CommandBufferStubWrapper() = default;
+
+  // Make the stub's context current.  Return true on success.
+  virtual bool MakeCurrent() = 0;
+
+  // Add or remove a destruction observer on the underlying stub.
+  virtual void AddDestructionObserver(
+      gpu::CommandBufferStub::DestructionObserver* observer) = 0;
+  virtual void RemoveDestructionObserver(
+      gpu::CommandBufferStub::DestructionObserver* observer) = 0;
+
+  // To support VideoFrameFactoryImpl, we need at least GetTextureManager().
+};
+
+}  // namespace media
+
+#endif  // MEDIA_GPU_ANDROID_COMMAND_BUFFER_STUB_WRAPPER_H_
diff --git a/media/gpu/android/command_buffer_stub_wrapper_impl.cc b/media/gpu/android/command_buffer_stub_wrapper_impl.cc
new file mode 100644
index 0000000..88c439145
--- /dev/null
+++ b/media/gpu/android/command_buffer_stub_wrapper_impl.cc
@@ -0,0 +1,30 @@
+// Copyright 2018 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 "command_buffer_stub_wrapper_impl.h"
+
+#include "gpu/ipc/service/command_buffer_stub.h"
+
+namespace media {
+
+CommandBufferStubWrapperImpl::CommandBufferStubWrapperImpl(
+    gpu::CommandBufferStub* stub)
+    : stub_(stub) {}
+
+bool CommandBufferStubWrapperImpl::MakeCurrent() {
+  // Support |!stub_| as a convenience.
+  return stub_ && stub_->decoder_context()->MakeCurrent();
+}
+
+void CommandBufferStubWrapperImpl::AddDestructionObserver(
+    gpu::CommandBufferStub::DestructionObserver* observer) {
+  stub_->AddDestructionObserver(observer);
+}
+
+void CommandBufferStubWrapperImpl::RemoveDestructionObserver(
+    gpu::CommandBufferStub::DestructionObserver* observer) {
+  stub_->RemoveDestructionObserver(observer);
+}
+
+}  // namespace media
diff --git a/media/gpu/android/command_buffer_stub_wrapper_impl.h b/media/gpu/android/command_buffer_stub_wrapper_impl.h
new file mode 100644
index 0000000..cd209ea0
--- /dev/null
+++ b/media/gpu/android/command_buffer_stub_wrapper_impl.h
@@ -0,0 +1,31 @@
+// Copyright 2018 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 MEDIA_GPU_ANDROID_COMMAND_BUFFER_STUB_WRAPPER_IMPL_H_
+#define MEDIA_GPU_ANDROID_COMMAND_BUFFER_STUB_WRAPPER_IMPL_H_
+
+#include "media/gpu/android/command_buffer_stub_wrapper.h"
+
+namespace media {
+
+// Implementation that actually talks to a CommandBufferStub
+class CommandBufferStubWrapperImpl : public CommandBufferStubWrapper {
+ public:
+  explicit CommandBufferStubWrapperImpl(gpu::CommandBufferStub* stub);
+  ~CommandBufferStubWrapperImpl() override = default;
+
+  // CommandBufferStubWrapper
+  bool MakeCurrent() override;
+  void AddDestructionObserver(
+      gpu::CommandBufferStub::DestructionObserver* observer) override;
+  void RemoveDestructionObserver(
+      gpu::CommandBufferStub::DestructionObserver* observer) override;
+
+ private:
+  gpu::CommandBufferStub* stub_;
+};
+
+}  // namespace media
+
+#endif  // MEDIA_GPU_ANDROID_MEDIA_COMMAND_BUFFER_STUB_WRAPPER_IMPL_H_
diff --git a/media/gpu/android/mock_command_buffer_stub_wrapper.cc b/media/gpu/android/mock_command_buffer_stub_wrapper.cc
new file mode 100644
index 0000000..319e3f3c
--- /dev/null
+++ b/media/gpu/android/mock_command_buffer_stub_wrapper.cc
@@ -0,0 +1,30 @@
+// Copyright 2018 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 "media/gpu/android/mock_command_buffer_stub_wrapper.h"
+
+namespace media {
+
+MockCommandBufferStubWrapper::MockCommandBufferStubWrapper() = default;
+MockCommandBufferStubWrapper::~MockCommandBufferStubWrapper() = default;
+
+void MockCommandBufferStubWrapper::AddDestructionObserver(
+    gpu::CommandBufferStub::DestructionObserver* observer) {
+  ASSERT_FALSE(observer_);
+  ASSERT_TRUE(observer);
+  observer_ = observer;
+}
+
+void MockCommandBufferStubWrapper::RemoveDestructionObserver(
+    gpu::CommandBufferStub::DestructionObserver* observer) {
+  ASSERT_EQ(observer_, observer);
+  observer_ = nullptr;
+}
+
+void MockCommandBufferStubWrapper::NotifyDestruction() {
+  if (observer_)
+    observer_->OnWillDestroyStub();
+}
+
+}  // namespace media
diff --git a/media/gpu/android/mock_command_buffer_stub_wrapper.h b/media/gpu/android/mock_command_buffer_stub_wrapper.h
new file mode 100644
index 0000000..a2eef3b
--- /dev/null
+++ b/media/gpu/android/mock_command_buffer_stub_wrapper.h
@@ -0,0 +1,37 @@
+// Copyright 2018 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 MEDIA_GPU_ANDROID_MOCK_COMMAND_BUFFER_STUB_WRAPPER_H_
+#define MEDIA_GPU_ANDROID_MOCK_COMMAND_BUFFER_STUB_WRAPPER_H_
+
+#include "media/gpu/android/command_buffer_stub_wrapper.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace media {
+
+class MockCommandBufferStubWrapper
+    : public ::testing::NiceMock<CommandBufferStubWrapper> {
+ public:
+  MockCommandBufferStubWrapper();
+  virtual ~MockCommandBufferStubWrapper();
+
+  // CommandBufferStubWrapper
+  MOCK_METHOD0(MakeCurrent, bool());
+
+  void AddDestructionObserver(
+      gpu::CommandBufferStub::DestructionObserver* observer);
+  void RemoveDestructionObserver(
+      gpu::CommandBufferStub::DestructionObserver* observer);
+
+  // Notify the observer that we will be destroyed.
+  void NotifyDestruction();
+
+ private:
+  gpu::CommandBufferStub::DestructionObserver* observer_ = nullptr;
+};
+
+}  // namespace media
+
+#endif  // MEDIA_GPU_ANDROID_MOCK_COMMAND_BUFFER_STUB_WRAPPER_H_
diff --git a/media/gpu/android/texture_pool.cc b/media/gpu/android/texture_pool.cc
new file mode 100644
index 0000000..ba124bae
--- /dev/null
+++ b/media/gpu/android/texture_pool.cc
@@ -0,0 +1,86 @@
+// Copyright 2018 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 "media/gpu/android/texture_pool.h"
+
+#include "gpu/command_buffer/service/texture_manager.h"
+#include "media/gpu/android/command_buffer_stub_wrapper.h"
+#include "media/gpu/android/texture_wrapper.h"
+
+namespace media {
+
+TexturePool::TexturePool(std::unique_ptr<CommandBufferStubWrapper> stub)
+    : stub_(std::move(stub)) {
+  if (stub_)
+    stub_->AddDestructionObserver(this);
+}
+
+TexturePool::~TexturePool() {
+  DestroyAllPlatformTextures();
+
+  if (stub_)
+    stub_->RemoveDestructionObserver(this);
+}
+
+void TexturePool::AddTexture(std::unique_ptr<TextureWrapper> texture) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  DCHECK(pool_.find(texture.get()) == pool_.end());
+  // Don't permit additions after we've lost the stub.
+  // TODO(liberato): consider making this fail gracefully.  However, nobody
+  // should be doing this, so for now it's a DCHECK.
+  DCHECK(stub_);
+  TextureWrapper* texture_raw = texture.get();
+  pool_[texture_raw] = std::move(texture);
+}
+
+void TexturePool::ReleaseTexture(TextureWrapper* texture) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  auto iter = pool_.find(texture);
+  DCHECK(iter != pool_.end());
+
+  // If we can't make the context current, then notify the texture.  Note that
+  // the wrapper might already have been destroyed, which is fine.
+  if (iter->second && (!stub_ || !stub_->MakeCurrent()))
+    texture->ForceContextLost();
+
+  pool_.erase(iter);
+}
+
+void TexturePool::DestroyAllPlatformTextures() {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+  // Don't bother to make the context current if we have no textures.
+  if (!pool_.size())
+    return;
+
+  // If we can't make the context current, then notify all the textures that
+  // they can't delete the underlying platform textures.
+  const bool have_context = stub_ && stub_->MakeCurrent();
+
+  // Destroy the wrapper, but keep the entry around in the map.  We do this so
+  // that ReleaseTexture can still check that at least the texture was, at some
+  // point, in the map.  Hopefully, since nobody should be adding textures to
+  // the pool after we've lost the stub, there's no issue with aliasing if the
+  // ptr is re-used; it won't be given to us, so it's okay.
+  for (auto& it : pool_) {
+    std::unique_ptr<TextureWrapper> texture = std::move(it.second);
+    if (!texture)
+      continue;
+
+    if (!have_context)
+      texture->ForceContextLost();
+
+    // |texture| will be destroyed.
+  }
+}
+
+void TexturePool::OnWillDestroyStub() {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  DCHECK(stub_);
+  // Since the stub is going away, clean up while we can.
+  DestroyAllPlatformTextures();
+  stub_ = nullptr;
+}
+
+}  // namespace media
diff --git a/media/gpu/android/texture_pool.h b/media/gpu/android/texture_pool.h
new file mode 100644
index 0000000..cc42f516
--- /dev/null
+++ b/media/gpu/android/texture_pool.h
@@ -0,0 +1,71 @@
+// Copyright 2018 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 MEDIA_GPU_ANDROID_TEXTURE_POOL_H_
+#define MEDIA_GPU_ANDROID_TEXTURE_POOL_H_
+
+#include <map>
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/threading/thread_checker.h"
+#include "gpu/ipc/service/command_buffer_stub.h"
+#include "media/gpu/media_gpu_export.h"
+
+namespace media {
+
+class CommandBufferStubWrapper;
+class TextureWrapper;
+
+// Owns Textures that are used to hold decoded video frames.  Allows them to
+// outlive the decoder that created them, since decoders are torn down when the
+// pipeline is suspended, but decoded frames can be on-screen indefinitely.
+// TODO(tmathmeyer): Convert this into a pool.  Right now, we just constantly
+// add new textures and remove them.
+class MEDIA_GPU_EXPORT TexturePool
+    : public base::RefCounted<TexturePool>,
+      public gpu::CommandBufferStub::DestructionObserver {
+ public:
+  TexturePool(std::unique_ptr<CommandBufferStubWrapper> stub);
+
+  // Add a new texture into the pool.  This may only be done before |stub_| is
+  // destroyed.  When |stub_| is destroyed, we will destroy any textures that
+  // are in the pool.
+  //
+  // Note that if we were really a pool this would mean "add |texture| into the
+  // pool of available textures".  There would be some other call to allocate
+  // a texture from the pool.
+  void AddTexture(std::unique_ptr<TextureWrapper> texture);
+
+  // Release a texture back into the pool.  |texture| must have been added to
+  // the pool previously, and not released.  Otherwise, this is undefined.
+  // Note: since we don't actually pool things, this just forgets |texture|.
+  // It's okay if this is called after we've lost |stub_|.
+  void ReleaseTexture(TextureWrapper* texture);
+
+ protected:
+  ~TexturePool() override;
+
+  // DestructionObserver
+  void OnWillDestroyStub() override;
+
+  // When called, we will destroy any platform textures if we have a context,
+  // or mark them as "lost context" if we don't.  This will not actually remove
+  // entries in |pool_|, but will instead clear the unique_ptr to delete the
+  // texture.  Assuming that nobody adds textures after our stub is destroyed,
+  // this is still alias-free.
+  void DestroyAllPlatformTextures();
+
+ private:
+  friend class base::RefCounted<TexturePool>;
+  THREAD_CHECKER(thread_checker_);
+
+  std::unique_ptr<CommandBufferStubWrapper> stub_;
+
+  std::map<TextureWrapper*, std::unique_ptr<TextureWrapper>> pool_;
+};
+
+}  // namespace media
+
+#endif  // MEDIA_GPU_ANDROID_TEXTURE_POOL_H_
diff --git a/media/gpu/android/texture_pool_unittest.cc b/media/gpu/android/texture_pool_unittest.cc
new file mode 100644
index 0000000..d1c9ed7a
--- /dev/null
+++ b/media/gpu/android/texture_pool_unittest.cc
@@ -0,0 +1,154 @@
+// Copyright 2018 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 "media/gpu/android/texture_pool.h"
+
+#include <memory>
+
+#include "base/memory/weak_ptr.h"
+#include "gpu/command_buffer/service/sequence_id.h"
+#include "gpu/ipc/common/gpu_messages.h"
+#include "media/gpu/android/mock_command_buffer_stub_wrapper.h"
+#include "media/gpu/android/texture_wrapper.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace media {
+
+using testing::NiceMock;
+using testing::Return;
+
+// SupportsWeakPtr so it's easy to tell when it has been destroyed.
+class MockTextureWrapper : public NiceMock<TextureWrapper>,
+                           public base::SupportsWeakPtr<MockTextureWrapper> {
+ public:
+  MockTextureWrapper() {}
+  ~MockTextureWrapper() override {}
+
+  MOCK_METHOD0(ForceContextLost, void());
+};
+
+class TexturePoolTest : public testing::Test {
+ public:
+  TexturePoolTest() = default;
+
+  void SetUp() override {
+    std::unique_ptr<MockCommandBufferStubWrapper> stub =
+        std::make_unique<MockCommandBufferStubWrapper>();
+    stub_ = stub.get();
+    SetContextCanBeCurrent(true);
+    texture_pool_ = new TexturePool(std::move(stub));
+  }
+
+  using WeakTexture = base::WeakPtr<MockTextureWrapper>;
+
+  // Set whether or not |stub_| will report that MakeCurrent worked.
+  void SetContextCanBeCurrent(bool allow) {
+    ON_CALL(*stub_, MakeCurrent()).WillByDefault(Return(allow));
+  }
+
+  WeakTexture CreateAndAddTexture() {
+    std::unique_ptr<MockTextureWrapper> texture =
+        std::make_unique<MockTextureWrapper>();
+    WeakTexture texture_weak = texture->AsWeakPtr();
+
+    texture_pool_->AddTexture(std::move(texture));
+
+    return texture_weak;
+  }
+
+  scoped_refptr<TexturePool> texture_pool_;
+  MockCommandBufferStubWrapper* stub_ = nullptr;
+};
+
+TEST_F(TexturePoolTest, AddAndReleaseTexturesWithContext) {
+  // Test that adding then deleting a texture destroys it.
+  WeakTexture texture = CreateAndAddTexture();
+  // The texture should not be notified that the context was lost.
+  EXPECT_CALL(*texture.get(), ForceContextLost()).Times(0);
+  EXPECT_CALL(*stub_, MakeCurrent()).Times(1);
+  texture_pool_->ReleaseTexture(texture.get());
+  ASSERT_FALSE(texture);
+}
+
+TEST_F(TexturePoolTest, AddAndReleaseTexturesWithoutContext) {
+  // Test that adding then deleting a texture destroys it, and marks that the
+  // context is lost.
+  WeakTexture texture = CreateAndAddTexture();
+  SetContextCanBeCurrent(false);
+  EXPECT_CALL(*texture, ForceContextLost()).Times(1);
+  EXPECT_CALL(*stub_, MakeCurrent()).Times(1);
+  texture_pool_->ReleaseTexture(texture.get());
+  ASSERT_FALSE(texture);
+}
+
+TEST_F(TexturePoolTest, TexturesAreReleasedOnStubDestructionWithContext) {
+  // Add multiple textures, and test that they're all destroyed when the stub
+  // says that it's destroyed.
+  std::vector<TextureWrapper*> raw_textures;
+  std::vector<WeakTexture> textures;
+
+  for (int i = 0; i < 3; i++) {
+    textures.push_back(CreateAndAddTexture());
+    raw_textures.push_back(textures.back().get());
+    // The context should not be lost.
+    EXPECT_CALL(*textures.back(), ForceContextLost()).Times(0);
+  }
+
+  EXPECT_CALL(*stub_, MakeCurrent()).Times(1);
+
+  stub_->NotifyDestruction();
+
+  // TextureWrappers should be destroyed.
+  for (auto& texture : textures)
+    ASSERT_FALSE(texture);
+
+  // It should be okay to release the textures after they're destroyed, and
+  // nothing should crash.
+  for (auto* raw_texture : raw_textures)
+    texture_pool_->ReleaseTexture(raw_texture);
+}
+
+TEST_F(TexturePoolTest, TexturesAreReleasedOnStubDestructionWithoutContext) {
+  std::vector<TextureWrapper*> raw_textures;
+  std::vector<WeakTexture> textures;
+
+  for (int i = 0; i < 3; i++) {
+    textures.push_back(CreateAndAddTexture());
+    raw_textures.push_back(textures.back().get());
+    EXPECT_CALL(*textures.back(), ForceContextLost()).Times(1);
+  }
+
+  SetContextCanBeCurrent(false);
+  EXPECT_CALL(*stub_, MakeCurrent()).Times(1);
+
+  stub_->NotifyDestruction();
+
+  for (auto& texture : textures)
+    ASSERT_FALSE(texture);
+
+  // It should be okay to release the textures after they're destroyed, and
+  // nothing should crash.
+  for (auto* raw_texture : raw_textures)
+    texture_pool_->ReleaseTexture(raw_texture);
+}
+
+TEST_F(TexturePoolTest, NonEmptyPoolAfterStubDestructionDoesntCrash) {
+  // Make sure that we can delete the stub, and verify that pool teardown still
+  // works (doesn't crash) even though the pool is not empty.
+  CreateAndAddTexture();
+
+  stub_->NotifyDestruction();
+}
+
+TEST_F(TexturePoolTest,
+       NonEmptyPoolAfterStubWithoutContextDestructionDoesntCrash) {
+  // Make sure that we can delete the stub, and verify that pool teardown still
+  // works (doesn't crash) even though the pool is not empty.
+  CreateAndAddTexture();
+
+  SetContextCanBeCurrent(false);
+  stub_->NotifyDestruction();
+}
+
+}  // namespace media
diff --git a/media/gpu/android/texture_wrapper.cc b/media/gpu/android/texture_wrapper.cc
new file mode 100644
index 0000000..cb7ce99f
--- /dev/null
+++ b/media/gpu/android/texture_wrapper.cc
@@ -0,0 +1,22 @@
+// Copyright 2018 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 "media/gpu/android/texture_wrapper.h"
+
+#include "gpu/command_buffer/service/texture_manager.h"
+
+namespace media {
+
+TextureWrapperImpl::TextureWrapperImpl(
+    scoped_refptr<gpu::gles2::TextureRef> texture_ref)
+    : texture_ref_(std::move(texture_ref)) {}
+
+TextureWrapperImpl::~TextureWrapperImpl() {}
+
+void TextureWrapperImpl::ForceContextLost() {
+  if (texture_ref_)
+    texture_ref_->ForceContextLost();
+}
+
+}  // namespace media
diff --git a/media/gpu/android/texture_wrapper.h b/media/gpu/android/texture_wrapper.h
new file mode 100644
index 0000000..eeb77f0
--- /dev/null
+++ b/media/gpu/android/texture_wrapper.h
@@ -0,0 +1,43 @@
+// Copyright 2018 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 MEDIA_GPU_ANDROID_TEXTURE_WRAPPER_H_
+#define MEDIA_GPU_ANDROID_TEXTURE_WRAPPER_H_
+
+#include "base/memory/scoped_refptr.h"
+
+namespace gpu {
+namespace gles2 {
+class TextureRef;
+}  // namespace gles2
+}  // namespace gpu
+
+namespace media {
+
+// Temporary class to allow mocking a TextureRef, which has no virtual methods.
+// It is expected that this will be replaced by gpu::gles2::AbstractTexture in
+// the near future, will will support mocks directly.
+class TextureWrapper {
+ public:
+  virtual ~TextureWrapper() = default;
+  virtual void ForceContextLost() = 0;
+};
+
+// Since these are temporary classes, the impl might as well go in the same
+// file for easier cleanup later.
+class TextureWrapperImpl : public TextureWrapper {
+ public:
+  TextureWrapperImpl(scoped_refptr<gpu::gles2::TextureRef> texture_ref);
+  ~TextureWrapperImpl() override;
+
+  // TextureWrapper
+  void ForceContextLost() override;
+
+ private:
+  scoped_refptr<gpu::gles2::TextureRef> texture_ref_;
+};
+
+}  // namespace media
+
+#endif  // MEDIA_GPU_ANDROID_TEXTURE_WRAPPER_H_
diff --git a/media/gpu/android/video_frame_factory_impl.cc b/media/gpu/android/video_frame_factory_impl.cc
index 6c839c6..2bf885f 100644
--- a/media/gpu/android/video_frame_factory_impl.cc
+++ b/media/gpu/android/video_frame_factory_impl.cc
@@ -18,9 +18,12 @@
 #include "gpu/ipc/service/gpu_channel.h"
 #include "media/base/bind_to_current_loop.h"
 #include "media/base/video_frame.h"
-#include "media/gpu//android/codec_image.h"
-#include "media/gpu//android/codec_image_group.h"
+#include "media/gpu/android/codec_image.h"
+#include "media/gpu/android/codec_image_group.h"
 #include "media/gpu/android/codec_wrapper.h"
+#include "media/gpu/android/command_buffer_stub_wrapper_impl.h"
+#include "media/gpu/android/texture_pool.h"
+#include "media/gpu/android/texture_wrapper.h"
 #include "mojo/public/cpp/bindings/callback_helpers.h"
 #include "ui/gl/android/surface_texture.h"
 #include "ui/gl/gl_bindings.h"
@@ -121,7 +124,6 @@
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   if (stub_)
     stub_->RemoveDestructionObserver(this);
-  ClearTextureRefs();
 }
 
 scoped_refptr<SurfaceTextureGLOwner> GpuVideoFrameFactory::Initialize(
@@ -133,6 +135,10 @@
   if (!MakeContextCurrent(stub_))
     return nullptr;
   stub_->AddDestructionObserver(this);
+
+  texture_pool_ =
+      new TexturePool(std::make_unique<CommandBufferStubWrapperImpl>(stub_));
+
   decoder_helper_ = GLES2DecoderHelper::Create(stub_->decoder_context());
   return SurfaceTextureGLOwnerImpl::Create();
 }
@@ -157,16 +163,15 @@
   // Try to render this frame if possible.
   internal::MaybeRenderEarly(&images_);
 
-  // TODO(sandersd, watk): The VideoFrame release callback will not be called
-  // after MojoVideoDecoderService is destructed, so we have to release all
-  // our TextureRefs when |this| is destructed. This can unback outstanding
-  // VideoFrames (e.g., the current frame when the player is suspended). The
-  // release callback lifetime should be separate from MCVD or
-  // MojoVideoDecoderService (http://crbug.com/737220).
-  texture_refs_[texture_ref.get()] = texture_ref;
-  auto drop_texture_ref = base::BindOnce(&GpuVideoFrameFactory::DropTextureRef,
-                                         weak_factory_.GetWeakPtr(),
-                                         base::Unretained(texture_ref.get()));
+  std::unique_ptr<TextureWrapper> texture_wrapper =
+      std::make_unique<TextureWrapperImpl>(std::move(texture_ref));
+  auto drop_texture_ref = base::BindOnce(
+      [](scoped_refptr<TexturePool> texture_pool,
+         TextureWrapper* texture_wrapper, const gpu::SyncToken& sync_token) {
+        texture_pool->ReleaseTexture(texture_wrapper);
+      },
+      texture_pool_, base::Unretained(texture_wrapper.get()));
+  texture_pool_->AddTexture(std::move(texture_wrapper));
 
   // Guarantee that the TextureRef is released even if the VideoFrame is
   // dropped. Otherwise we could keep TextureRefs we don't need alive.
@@ -271,36 +276,10 @@
 void GpuVideoFrameFactory::OnWillDestroyStub() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   DCHECK(stub_);
-  ClearTextureRefs();
   stub_ = nullptr;
   decoder_helper_ = nullptr;
 }
 
-void GpuVideoFrameFactory::ClearTextureRefs() {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  DCHECK(stub_ || texture_refs_.empty());
-  // If we fail to make the context current, we have to notify the TextureRefs
-  // so they don't try to delete textures without a context.
-  if (!MakeContextCurrent(stub_)) {
-    for (const auto& kv : texture_refs_)
-      kv.first->ForceContextLost();
-  }
-  texture_refs_.clear();
-}
-
-void GpuVideoFrameFactory::DropTextureRef(gpu::gles2::TextureRef* ref,
-                                          const gpu::SyncToken& token) {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  auto it = texture_refs_.find(ref);
-  if (it == texture_refs_.end())
-    return;
-  // If we fail to make the context current, we have to notify the TextureRef
-  // so it doesn't try to delete a texture without a context.
-  if (!MakeContextCurrent(stub_))
-    ref->ForceContextLost();
-  texture_refs_.erase(it);
-}
-
 void GpuVideoFrameFactory::OnImageDestructed(CodecImage* image) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   base::Erase(images_, image);
diff --git a/media/gpu/android/video_frame_factory_impl.h b/media/gpu/android/video_frame_factory_impl.h
index 7eadf50..0e78a032 100644
--- a/media/gpu/android/video_frame_factory_impl.h
+++ b/media/gpu/android/video_frame_factory_impl.h
@@ -21,6 +21,7 @@
 namespace media {
 class CodecImageGroup;
 class GpuVideoFrameFactory;
+class TexturePool;
 
 // VideoFrameFactoryImpl creates CodecOutputBuffer backed VideoFrames and tries
 // to eagerly render them to their surface to release the buffers back to the
@@ -98,25 +99,12 @@
 
   void OnWillDestroyStub() override;
 
-  // Clears |texture_refs_|. Makes the gl context current.
-  void ClearTextureRefs();
-
-  // Removes |ref| from texture_refs_. Makes the gl context current.
-  // |token| is ignored because MojoVideoDecoderService guarantees that it has
-  // already passed by the time we get the callback.
-  void DropTextureRef(gpu::gles2::TextureRef* ref, const gpu::SyncToken& token);
-
   // Removes |image| from |images_|.
   void OnImageDestructed(CodecImage* image);
 
   // Outstanding images that should be considered for early rendering.
   std::vector<CodecImage*> images_;
 
-  // Outstanding TextureRefs that are still referenced by a mailbox VideoFrame.
-  // They're kept alive until their mailboxes are released (or |this| is
-  // destructed).
-  std::map<gpu::gles2::TextureRef*, scoped_refptr<gpu::gles2::TextureRef>>
-      texture_refs_;
   gpu::CommandBufferStub* stub_;
 
   // Callback to notify us that an image has been destroyed.
@@ -132,6 +120,9 @@
   // replace this when SetImageGroup() is called.
   scoped_refptr<CodecImageGroup> image_group_;
 
+  // Pool which owns all the textures that we create.
+  scoped_refptr<TexturePool> texture_pool_;
+
   THREAD_CHECKER(thread_checker_);
   base::WeakPtrFactory<GpuVideoFrameFactory> weak_factory_;
   DISALLOW_COPY_AND_ASSIGN(GpuVideoFrameFactory);
diff --git a/media/gpu/gpu_jpeg_decode_accelerator_factory.cc b/media/gpu/gpu_jpeg_decode_accelerator_factory.cc
index 55265ac..b3fe539 100644
--- a/media/gpu/gpu_jpeg_decode_accelerator_factory.cc
+++ b/media/gpu/gpu_jpeg_decode_accelerator_factory.cc
@@ -9,8 +9,8 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "media/base/media_switches.h"
+#include "media/gpu/buildflags.h"
 #include "media/gpu/fake_jpeg_decode_accelerator.h"
-#include "media/gpu/features.h"
 
 #if BUILDFLAG(USE_V4L2_CODEC) && defined(ARCH_CPU_ARM_FAMILY)
 #define USE_V4L2_JDA
diff --git a/media/gpu/gpu_jpeg_encode_accelerator_factory.cc b/media/gpu/gpu_jpeg_encode_accelerator_factory.cc
index 57bf628..c4e6114 100644
--- a/media/gpu/gpu_jpeg_encode_accelerator_factory.cc
+++ b/media/gpu/gpu_jpeg_encode_accelerator_factory.cc
@@ -8,7 +8,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
 #include "media/base/media_switches.h"
-#include "media/gpu/features.h"
+#include "media/gpu/buildflags.h"
 
 #if BUILDFLAG(USE_V4L2_CODEC) && defined(ARCH_CPU_ARM_FAMILY)
 #define USE_V4L2_JEA
diff --git a/media/gpu/gpu_video_decode_accelerator_factory.cc b/media/gpu/gpu_video_decode_accelerator_factory.cc
index 5962749..1f488bb 100644
--- a/media/gpu/gpu_video_decode_accelerator_factory.cc
+++ b/media/gpu/gpu_video_decode_accelerator_factory.cc
@@ -11,7 +11,7 @@
 #include "build/build_config.h"
 #include "gpu/command_buffer/service/gpu_preferences.h"
 #include "media/base/media_switches.h"
-#include "media/gpu/features.h"
+#include "media/gpu/buildflags.h"
 #include "media/gpu/gpu_video_accelerator_util.h"
 #include "media/gpu/media_gpu_export.h"
 
@@ -228,8 +228,7 @@
     const gpu::GpuDriverBugWorkarounds& workarounds,
     const gpu::GpuPreferences& gpu_preferences) const {
   std::unique_ptr<VideoDecodeAccelerator> decoder;
-  decoder.reset(
-      new VTVideoDecodeAccelerator(make_context_current_cb_, bind_image_cb_));
+  decoder.reset(new VTVideoDecodeAccelerator(bind_image_cb_));
   return decoder;
 }
 #endif
diff --git a/media/gpu/gpu_video_decode_accelerator_factory.h b/media/gpu/gpu_video_decode_accelerator_factory.h
index 56a0d7f..3244daa 100644
--- a/media/gpu/gpu_video_decode_accelerator_factory.h
+++ b/media/gpu/gpu_video_decode_accelerator_factory.h
@@ -13,7 +13,7 @@
 #include "gpu/config/gpu_driver_bug_workarounds.h"
 #include "gpu/config/gpu_info.h"
 #include "media/base/android_overlay_mojo_factory.h"
-#include "media/gpu/features.h"
+#include "media/gpu/buildflags.h"
 #include "media/gpu/media_gpu_export.h"
 #include "media/video/video_decode_accelerator.h"
 
diff --git a/media/gpu/gpu_video_encode_accelerator_factory.cc b/media/gpu/gpu_video_encode_accelerator_factory.cc
index 9d9d575..d770f10 100644
--- a/media/gpu/gpu_video_encode_accelerator_factory.cc
+++ b/media/gpu/gpu_video_encode_accelerator_factory.cc
@@ -7,7 +7,7 @@
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
 #include "build/build_config.h"
-#include "media/gpu/features.h"
+#include "media/gpu/buildflags.h"
 #include "media/gpu/gpu_video_accelerator_util.h"
 
 #if BUILDFLAG(USE_V4L2_CODEC)
diff --git a/media/gpu/ipc/client/BUILD.gn b/media/gpu/ipc/client/BUILD.gn
index 427c8d3..4344e7d 100644
--- a/media/gpu/ipc/client/BUILD.gn
+++ b/media/gpu/ipc/client/BUILD.gn
@@ -15,7 +15,7 @@
     "//gpu/ipc/common",
     "//ipc",
     "//media",
-    "//media:media_features",
+    "//media:media_buildflags",
     "//media/gpu",
     "//media/gpu/ipc/common",
     "//ui/gfx:memory_buffer",
diff --git a/media/gpu/ipc/service/BUILD.gn b/media/gpu/ipc/service/BUILD.gn
index 812d291..a8ab246 100644
--- a/media/gpu/ipc/service/BUILD.gn
+++ b/media/gpu/ipc/service/BUILD.gn
@@ -36,8 +36,8 @@
   deps = [
     "//gpu/command_buffer/service:gles2",
     "//gpu/ipc/service",
-    "//media:media_features",
-    "//media/gpu:features",
+    "//media:media_buildflags",
+    "//media/gpu:buildflags",
     "//media/gpu/ipc/common",
     "//third_party/mesa:mesa_headers",
     "//ui/gfx/ipc/color",
diff --git a/media/gpu/jpeg_decode_accelerator_unittest.cc b/media/gpu/jpeg_decode_accelerator_unittest.cc
index d50e610..93750e1 100644
--- a/media/gpu/jpeg_decode_accelerator_unittest.cc
+++ b/media/gpu/jpeg_decode_accelerator_unittest.cc
@@ -26,7 +26,7 @@
 #include "build/build_config.h"
 #include "media/base/test_data_util.h"
 #include "media/filters/jpeg_parser.h"
-#include "media/gpu/features.h"
+#include "media/gpu/buildflags.h"
 #include "media/gpu/gpu_jpeg_decode_accelerator_factory.h"
 #include "media/gpu/video_accelerator_unittest_helpers.h"
 #include "media/video/jpeg_decode_accelerator.h"
diff --git a/media/gpu/jpeg_encode_accelerator_unittest.cc b/media/gpu/jpeg_encode_accelerator_unittest.cc
index b58ee8a7..c0cc3ca 100644
--- a/media/gpu/jpeg_encode_accelerator_unittest.cc
+++ b/media/gpu/jpeg_encode_accelerator_unittest.cc
@@ -29,7 +29,7 @@
 #include "build/build_config.h"
 #include "media/base/test_data_util.h"
 #include "media/filters/jpeg_parser.h"
-#include "media/gpu/features.h"
+#include "media/gpu/buildflags.h"
 #include "media/gpu/vaapi/vaapi_jpeg_encode_accelerator.h"
 #include "media/gpu/video_accelerator_unittest_helpers.h"
 #include "media/video/jpeg_encode_accelerator.h"
diff --git a/media/gpu/v4l2/generic_v4l2_device.cc b/media/gpu/v4l2/generic_v4l2_device.cc
index 241598c..45220eb0 100644
--- a/media/gpu/v4l2/generic_v4l2_device.cc
+++ b/media/gpu/v4l2/generic_v4l2_device.cc
@@ -24,7 +24,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
-#include "media/gpu/features.h"
+#include "media/gpu/buildflags.h"
 #include "media/gpu/v4l2/generic_v4l2_device.h"
 #include "ui/gfx/native_pixmap.h"
 #include "ui/gl/egl_util.h"
diff --git a/media/gpu/v4l2/generic_v4l2_device.h b/media/gpu/v4l2/generic_v4l2_device.h
index 49e2d663..6df6eed43 100644
--- a/media/gpu/v4l2/generic_v4l2_device.h
+++ b/media/gpu/v4l2/generic_v4l2_device.h
@@ -15,7 +15,7 @@
 
 #include "base/files/scoped_file.h"
 #include "base/macros.h"
-#include "media/gpu/features.h"
+#include "media/gpu/buildflags.h"
 #include "media/gpu/v4l2/v4l2_device.h"
 
 namespace media {
diff --git a/media/gpu/v4l2/v4l2_video_encode_accelerator.cc b/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
index 387ce352..46f4c01d 100644
--- a/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
+++ b/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
@@ -102,12 +102,15 @@
 
 V4L2VideoEncodeAccelerator::OutputRecord::~OutputRecord() {}
 
-V4L2VideoEncodeAccelerator::ImageProcessorInputRecord::
-    ImageProcessorInputRecord()
-    : force_keyframe(false) {}
+V4L2VideoEncodeAccelerator::InputFrameInfo::InputFrameInfo()
+    : InputFrameInfo(nullptr, false) {}
 
-V4L2VideoEncodeAccelerator::ImageProcessorInputRecord::
-    ~ImageProcessorInputRecord() {}
+V4L2VideoEncodeAccelerator::InputFrameInfo::InputFrameInfo(
+    scoped_refptr<VideoFrame> frame,
+    bool force_keyframe)
+    : frame(frame), force_keyframe(force_keyframe) {}
+
+V4L2VideoEncodeAccelerator::InputFrameInfo::~InputFrameInfo() {}
 
 V4L2VideoEncodeAccelerator::V4L2VideoEncodeAccelerator(
     const scoped_refptr<V4L2Device>& device)
@@ -286,10 +289,7 @@
         NOTIFY_ERROR(kPlatformFailureError);
       }
     } else {
-      ImageProcessorInputRecord record;
-      record.frame = frame;
-      record.force_keyframe = force_keyframe;
-      image_processor_input_queue_.push(record);
+      image_processor_input_queue_.emplace(frame, force_keyframe);
     }
   } else {
     encoder_thread_.task_runner()->PostTask(
@@ -442,9 +442,9 @@
   DVLOGF(4) << "output_buffer_index=" << output_buffer_index;
   free_image_processor_output_buffers_.push_back(output_buffer_index);
   if (!image_processor_input_queue_.empty()) {
-    ImageProcessorInputRecord record = image_processor_input_queue_.front();
+    InputFrameInfo frame_info = image_processor_input_queue_.front();
     image_processor_input_queue_.pop();
-    Encode(record.frame, record.force_keyframe);
+    Encode(frame_info.frame, frame_info.force_keyframe);
   }
 }
 
@@ -530,26 +530,8 @@
     return;
   }
 
-  encoder_input_queue_.push(frame);
+  encoder_input_queue_.emplace(frame, force_keyframe);
   Enqueue();
-
-  if (force_keyframe) {
-    // TODO(posciak): this presently makes for slightly imprecise encoding
-    // parameters updates.  To precisely align the parameter updates with the
-    // incoming input frame, we should queue the parameters together with the
-    // frame onto encoder_input_queue_ and apply them when the input is about
-    // to be queued to the codec.
-    std::vector<struct v4l2_ext_control> ctrls;
-    struct v4l2_ext_control ctrl;
-    memset(&ctrl, 0, sizeof(ctrl));
-    ctrl.id = V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME;
-    ctrls.push_back(ctrl);
-    if (!SetExtCtrls(ctrls)) {
-      VLOGF(1) << "Failed requesting keyframe";
-      NOTIFY_ERROR(kPlatformFailureError);
-      return;
-    }
-  }
 }
 
 void V4L2VideoEncodeAccelerator::UseOutputBitstreamBufferTask(
@@ -637,7 +619,7 @@
   const int old_inputs_queued = input_buffer_queued_count_;
   while (!encoder_input_queue_.empty() && !free_input_buffers_.empty()) {
     // A null frame indicates a flush.
-    if (encoder_input_queue_.front() == nullptr) {
+    if (encoder_input_queue_.front().frame == nullptr) {
       DVLOGF(3) << "All input frames needed to be flushed are enqueued.";
       encoder_input_queue_.pop();
 
@@ -748,24 +730,39 @@
     DCHECK(output_record.at_device);
     DCHECK(output_record.buffer_ref);
 
-    int32_t bitstream_buffer_id = output_record.buffer_ref->id;
-    size_t output_data_size = CopyIntoOutputBuffer(
-        static_cast<uint8_t*>(output_record.address),
-        base::checked_cast<size_t>(dqbuf.m.planes[0].bytesused),
-        std::move(output_record.buffer_ref));
+    bool flush_done =
+        (encoder_state_ == kFlushing) && (dqbuf.flags & V4L2_BUF_FLAG_LAST);
+    if (flush_done && (dqbuf.m.planes[0].bytesused == 0)) {
+      // Empty buffer for indicating Flush has finished. Recycle the buffer
+      // directly instead of sending to the client.
+      VLOGF(4) << "Recycle the empty buffer directly.";
+      encoder_thread_.task_runner()->PostTask(
+          FROM_HERE,
+          base::Bind(&V4L2VideoEncodeAccelerator::UseOutputBitstreamBufferTask,
+                     base::Unretained(this),
+                     base::Passed(&output_record.buffer_ref)));
+    } else {
+      int32_t bitstream_buffer_id = output_record.buffer_ref->id;
+      size_t output_data_size = CopyIntoOutputBuffer(
+          static_cast<uint8_t*>(output_record.address),
+          base::checked_cast<size_t>(dqbuf.m.planes[0].bytesused),
+          std::move(output_record.buffer_ref));
 
-    DVLOGF(4) << "returning "
-              << "bitstream_buffer_id=" << bitstream_buffer_id
-              << ", size=" << output_data_size << ", key_frame=" << key_frame;
+      DVLOGF(4) << "returning "
+                << "bitstream_buffer_id=" << bitstream_buffer_id
+                << ", size=" << output_data_size << ", key_frame=" << key_frame;
 
-    child_task_runner_->PostTask(
-        FROM_HERE, base::Bind(&Client::BitstreamBufferReady, client_,
-                              bitstream_buffer_id, output_data_size, key_frame,
-                              base::TimeDelta::FromMicroseconds(
-                                  dqbuf.timestamp.tv_usec +
-                                  dqbuf.timestamp.tv_sec *
-                                      base::Time::kMicrosecondsPerSecond)));
-    if ((encoder_state_ == kFlushing) && (dqbuf.flags & V4L2_BUF_FLAG_LAST)) {
+      child_task_runner_->PostTask(
+          FROM_HERE,
+          base::Bind(&Client::BitstreamBufferReady, client_,
+                     bitstream_buffer_id, output_data_size, key_frame,
+                     base::TimeDelta::FromMicroseconds(
+                         dqbuf.timestamp.tv_usec +
+                         dqbuf.timestamp.tv_sec *
+                             base::Time::kMicrosecondsPerSecond)));
+    }
+
+    if (flush_done) {
       // Notify client that flush has finished successfully. The flush callback
       // should be called after notifying the last buffer is ready.
       DVLOGF(3) << "Flush completed. Start the encoder again.";
@@ -791,7 +788,21 @@
   DCHECK(!encoder_input_queue_.empty());
 
   // Enqueue an input (VIDEO_OUTPUT) buffer.
-  scoped_refptr<VideoFrame> frame = encoder_input_queue_.front();
+  InputFrameInfo frame_info = encoder_input_queue_.front();
+  if (frame_info.force_keyframe) {
+    std::vector<struct v4l2_ext_control> ctrls;
+    struct v4l2_ext_control ctrl;
+    memset(&ctrl, 0, sizeof(ctrl));
+    ctrl.id = V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME;
+    ctrls.push_back(ctrl);
+    if (!SetExtCtrls(ctrls)) {
+      VLOGF(1) << "Failed requesting keyframe";
+      NOTIFY_ERROR(kPlatformFailureError);
+      return false;
+    }
+  }
+
+  scoped_refptr<VideoFrame> frame = frame_info.frame;
   const int index = free_input_buffers_.back();
   InputRecord& input_record = input_buffer_map_[index];
   DCHECK(!input_record.at_device);
diff --git a/media/gpu/v4l2/v4l2_video_encode_accelerator.h b/media/gpu/v4l2/v4l2_video_encode_accelerator.h
index 1499bd8..5a64e65b 100644
--- a/media/gpu/v4l2/v4l2_video_encode_accelerator.h
+++ b/media/gpu/v4l2/v4l2_video_encode_accelerator.h
@@ -83,9 +83,11 @@
     size_t length;
   };
 
-  struct ImageProcessorInputRecord {
-    ImageProcessorInputRecord();
-    ~ImageProcessorInputRecord();
+  // Store all the information of input frame passed to Encode().
+  struct InputFrameInfo {
+    InputFrameInfo();
+    InputFrameInfo(scoped_refptr<VideoFrame> frame, bool force_keyframe);
+    ~InputFrameInfo();
     scoped_refptr<VideoFrame> frame;
     bool force_keyframe;
   };
@@ -258,7 +260,7 @@
   size_t cached_h264_header_size_ = 0;
 
   // Video frames ready to be encoded.
-  base::queue<scoped_refptr<VideoFrame>> encoder_input_queue_;
+  base::queue<InputFrameInfo> encoder_input_queue_;
 
   // Encoder device.
   scoped_refptr<V4L2Device> device_;
@@ -295,7 +297,7 @@
   // thread.
   std::vector<int> free_image_processor_output_buffers_;
   // Video frames ready to be processed. Only accessed on child thread.
-  base::queue<ImageProcessorInputRecord> image_processor_input_queue_;
+  base::queue<InputFrameInfo> image_processor_input_queue_;
   // Mapping of int index to fds of image processor output buffer.
   std::vector<std::vector<base::ScopedFD>> image_processor_output_buffer_map_;
 
diff --git a/media/gpu/video_decode_accelerator_unittest.cc b/media/gpu/video_decode_accelerator_unittest.cc
index 0c4ebc96..8ef6db71 100644
--- a/media/gpu/video_decode_accelerator_unittest.cc
+++ b/media/gpu/video_decode_accelerator_unittest.cc
@@ -59,8 +59,8 @@
 #include "gpu/command_buffer/service/gpu_preferences.h"
 #include "gpu/config/gpu_driver_bug_workarounds.h"
 #include "media/base/test_data_util.h"
+#include "media/gpu/buildflags.h"
 #include "media/gpu/fake_video_decode_accelerator.h"
-#include "media/gpu/features.h"
 #include "media/gpu/format_utils.h"
 #include "media/gpu/gpu_video_decode_accelerator_factory.h"
 #include "media/gpu/rendering_helper.h"
diff --git a/media/gpu/video_encode_accelerator_unittest.cc b/media/gpu/video_encode_accelerator_unittest.cc
index 369e7e7..06d5b708 100644
--- a/media/gpu/video_encode_accelerator_unittest.cc
+++ b/media/gpu/video_encode_accelerator_unittest.cc
@@ -45,7 +45,7 @@
 #include "media/base/video_frame.h"
 #include "media/filters/ffmpeg_video_decoder.h"
 #include "media/filters/ivf_parser.h"
-#include "media/gpu/features.h"
+#include "media/gpu/buildflags.h"
 #include "media/gpu/gpu_video_encode_accelerator_factory.h"
 #include "media/gpu/video_accelerator_unittest_helpers.h"
 #include "media/video/fake_video_encode_accelerator.h"
diff --git a/media/gpu/vt_video_decode_accelerator_mac.cc b/media/gpu/vt_video_decode_accelerator_mac.cc
index 15317c98..229b4f1 100644
--- a/media/gpu/vt_video_decode_accelerator_mac.cc
+++ b/media/gpu/vt_video_decode_accelerator_mac.cc
@@ -420,10 +420,8 @@
 }
 
 VTVideoDecodeAccelerator::VTVideoDecodeAccelerator(
-    const MakeGLContextCurrentCallback& make_context_current_cb,
     const BindGLImageCallback& bind_image_cb)
-    : make_context_current_cb_(make_context_current_cb),
-      bind_image_cb_(bind_image_cb),
+    : bind_image_cb_(bind_image_cb),
       gpu_task_runner_(base::ThreadTaskRunnerHandle::Get()),
       decoder_thread_("VTDecoderThread"),
       weak_this_factory_(this) {
@@ -465,7 +463,7 @@
   DVLOG(1) << __func__;
   DCHECK(gpu_task_runner_->BelongsToCurrentThread());
 
-  if (make_context_current_cb_.is_null() || bind_image_cb_.is_null()) {
+  if (bind_image_cb_.is_null()) {
     NOTREACHED() << "GL callbacks are required for this VDA";
     return false;
   }
@@ -1239,12 +1237,6 @@
   DCHECK(!picture_info->cv_image);
   DCHECK(!picture_info->gl_image);
 
-  if (!make_context_current_cb_.Run()) {
-    DLOG(ERROR) << "Failed to make GL context current";
-    NotifyError(PLATFORM_FAILURE, SFT_PLATFORM_ERROR);
-    return false;
-  }
-
   scoped_refptr<gl::GLImageIOSurface> gl_image(
       gl::GLImageIOSurface::Create(frame.image_size, GL_BGRA_EXT));
   if (!gl_image->InitializeWithCVPixelBuffer(
@@ -1330,8 +1322,6 @@
 
   // For a graceful shutdown, return assigned buffers and flush before
   // destructing |this|.
-  // TODO(sandersd): Prevent the decoder from reading buffers before discarding
-  // them.
   for (int32_t bitstream_id : assigned_bitstream_ids_)
     client_->NotifyEndOfBitstreamBuffer(bitstream_id);
   assigned_bitstream_ids_.clear();
diff --git a/media/gpu/vt_video_decode_accelerator_mac.h b/media/gpu/vt_video_decode_accelerator_mac.h
index 65fe809..d363468 100644
--- a/media/gpu/vt_video_decode_accelerator_mac.h
+++ b/media/gpu/vt_video_decode_accelerator_mac.h
@@ -27,7 +27,6 @@
 #include "media/video/h264_poc.h"
 #include "media/video/video_decode_accelerator.h"
 #include "ui/gfx/geometry/size.h"
-#include "ui/gl/gl_context_cgl.h"
 #include "ui/gl/gl_image_io_surface.h"
 
 namespace media {
@@ -40,9 +39,7 @@
 class VTVideoDecodeAccelerator : public VideoDecodeAccelerator,
                                  public base::trace_event::MemoryDumpProvider {
  public:
-  explicit VTVideoDecodeAccelerator(
-      const MakeGLContextCurrentCallback& make_context_current_cb,
-      const BindGLImageCallback& bind_image_cb);
+  explicit VTVideoDecodeAccelerator(const BindGLImageCallback& bind_image_cb);
 
   ~VTVideoDecodeAccelerator() override;
 
@@ -194,7 +191,6 @@
   //
   // GPU thread state.
   //
-  MakeGLContextCurrentCallback make_context_current_cb_;
   BindGLImageCallback bind_image_cb_;
 
   VideoDecodeAccelerator::Client* client_ = nullptr;
diff --git a/media/mojo/BUILD.gn b/media/mojo/BUILD.gn
index 30e843c1..2fc42466 100644
--- a/media/mojo/BUILD.gn
+++ b/media/mojo/BUILD.gn
@@ -6,8 +6,8 @@
 import("//media/media_options.gni")
 import("//testing/test.gni")
 
-buildflag_header("features") {
-  header = "features.h"
+buildflag_header("buildflags") {
+  header = "buildflags.h"
 
   enable_mojo_renderer = false
   enable_mojo_cdm = false
diff --git a/media/mojo/clients/BUILD.gn b/media/mojo/clients/BUILD.gn
index a41cf28c..92cdfd0 100644
--- a/media/mojo/clients/BUILD.gn
+++ b/media/mojo/clients/BUILD.gn
@@ -56,7 +56,7 @@
   public_deps = [
     "//base",
     "//media",
-    "//media/mojo:features",
+    "//media/mojo:buildflags",
     "//media/mojo/interfaces",
     "//mojo/public/cpp/bindings",
     "//mojo/public/cpp/system",
diff --git a/media/mojo/clients/mojo_cdm_factory.cc b/media/mojo/clients/mojo_cdm_factory.cc
index 58144f70..9811c94 100644
--- a/media/mojo/clients/mojo_cdm_factory.cc
+++ b/media/mojo/clients/mojo_cdm_factory.cc
@@ -11,8 +11,8 @@
 #include "media/base/content_decryption_module.h"
 #include "media/base/key_systems.h"
 #include "media/cdm/aes_decryptor.h"
+#include "media/mojo/buildflags.h"
 #include "media/mojo/clients/mojo_cdm.h"
-#include "media/mojo/features.h"
 #include "media/mojo/interfaces/interface_factory.mojom.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 #include "url/origin.h"
diff --git a/media/mojo/clients/mojo_decoder_factory.cc b/media/mojo/clients/mojo_decoder_factory.cc
index ae70798..db90344e 100644
--- a/media/mojo/clients/mojo_decoder_factory.cc
+++ b/media/mojo/clients/mojo_decoder_factory.cc
@@ -10,9 +10,9 @@
 #include "base/single_thread_task_runner.h"
 #include "build/build_config.h"
 #include "media/base/media_switches.h"
+#include "media/mojo/buildflags.h"
 #include "media/mojo/clients/mojo_audio_decoder.h"
 #include "media/mojo/clients/mojo_video_decoder.h"
-#include "media/mojo/features.h"
 #include "media/mojo/interfaces/audio_decoder.mojom.h"
 #include "media/mojo/interfaces/interface_factory.mojom.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
diff --git a/media/mojo/interfaces/android_overlay.mojom b/media/mojo/interfaces/android_overlay.mojom
index f6917336..eab18c9 100644
--- a/media/mojo/interfaces/android_overlay.mojom
+++ b/media/mojo/interfaces/android_overlay.mojom
@@ -5,7 +5,7 @@
 module media.mojom;
 
 import "media/mojo/interfaces/media_types.mojom";
-import "mojo/common/unguessable_token.mojom";
+import "mojo/public/mojom/base/unguessable_token.mojom";
 import "ui/gfx/geometry/mojo/geometry.mojom";
 
 // Provides mojo clients with AndroidOverlay instances.  This will live in the
@@ -58,7 +58,7 @@
   // will be the parent of the overlay.  For legacy reasons, we need this token
   // to be sent via IPC, so using the message pipe, or other mojo construct, as
   // the identifier won't work yet.
-  mojo.common.mojom.UnguessableToken routing_token;
+  mojo_base.mojom.UnguessableToken routing_token;
 
   // Initial rectangle.
   gfx.mojom.Rect rect;
diff --git a/media/mojo/interfaces/media_drm_storage.mojom b/media/mojo/interfaces/media_drm_storage.mojom
index c6e2b2a..a67493c 100644
--- a/media/mojo/interfaces/media_drm_storage.mojom
+++ b/media/mojo/interfaces/media_drm_storage.mojom
@@ -4,7 +4,7 @@
 
 module media.mojom;
 
-import "mojo/common/unguessable_token.mojom";
+import "mojo/public/mojom/base/unguessable_token.mojom";
 
 struct SessionData {
   array<uint8> key_set_id;
@@ -18,7 +18,7 @@
   // current origin. The origin ID should be randomly generated if it doesn't
   // exist. |origin_id| must be valid.
   // This should not modify anything in the storage.
-  Initialize() => (mojo.common.mojom.UnguessableToken origin_id);
+  Initialize() => (mojo_base.mojom.UnguessableToken origin_id);
 
   // Saves origin information (e.g. origin ID, provision time) in the storage
   // after MediaDrm is provisioned for current origin.
diff --git a/media/mojo/interfaces/renderer.mojom b/media/mojo/interfaces/renderer.mojom
index f8c04b1..9f17e04 100644
--- a/media/mojo/interfaces/renderer.mojom
+++ b/media/mojo/interfaces/renderer.mojom
@@ -7,7 +7,7 @@
 import "media/mojo/interfaces/demuxer_stream.mojom";
 import "media/mojo/interfaces/media_types.mojom";
 import "mojo/public/mojom/base/time.mojom";
-import "mojo/common/unguessable_token.mojom";
+import "mojo/public/mojom/base/unguessable_token.mojom";
 import "ui/gfx/geometry/mojo/geometry.mojom";
 import "url/mojom/url.mojom";
 
@@ -46,7 +46,7 @@
   // content::MediaPlayerRenderer.
   // Unexpected calls to this method will close the connection.
   InitiateScopedSurfaceRequest()
-      => (mojo.common.mojom.UnguessableToken request_token);
+      => (mojo_base.mojom.UnguessableToken request_token);
 };
 
 interface RendererClient {
diff --git a/media/mojo/interfaces/video_decoder.mojom b/media/mojo/interfaces/video_decoder.mojom
index f64fd8e..07bf9a1 100644
--- a/media/mojo/interfaces/video_decoder.mojom
+++ b/media/mojo/interfaces/video_decoder.mojom
@@ -7,12 +7,12 @@
 import "gpu/ipc/common/sync_token.mojom";
 import "media/mojo/interfaces/media_log.mojom";
 import "media/mojo/interfaces/media_types.mojom";
-import "mojo/common/unguessable_token.mojom";
+import "mojo/public/mojom/base/unguessable_token.mojom";
 
 // Identifies a CommandBufferStub. MediaGpuChannelManager is responsible
 // for minting |channel_token| values.
 struct CommandBufferId {
-  mojo.common.mojom.UnguessableToken channel_token;
+  mojo_base.mojom.UnguessableToken channel_token;
   int32 route_id;
 };
 
@@ -23,7 +23,7 @@
   //
   // TODO(sandersd): Do we need release notification for non-texture
   // VideoFrames? If so, |release_sync_token| should be optional.
-  ReleaseVideoFrame(mojo.common.mojom.UnguessableToken release_token,
+  ReleaseVideoFrame(mojo_base.mojom.UnguessableToken release_token,
                     gpu.mojom.SyncToken release_sync_token);
 };
 
@@ -117,7 +117,7 @@
   // VideoFrameHandleReleaser::Release() when it is finished using |frame|.
   OnVideoFrameDecoded(VideoFrame frame,
                       bool can_read_without_stalling,
-                      mojo.common.mojom.UnguessableToken? release_token);
+                      mojo_base.mojom.UnguessableToken? release_token);
 
   // Request to be notified when the current OverlayInfo changes. This results
   // in at least one call to OnOverlayInfoChanged() for the initial OverlayInfo.
diff --git a/media/mojo/services/BUILD.gn b/media/mojo/services/BUILD.gn
index c4ce9f7f..441082e 100644
--- a/media/mojo/services/BUILD.gn
+++ b/media/mojo/services/BUILD.gn
@@ -83,7 +83,7 @@
     "//media",
     "//media/gpu",
     "//media/gpu/ipc/common",
-    "//media/mojo:features",
+    "//media/mojo:buildflags",
     "//media/mojo/interfaces",
     "//mojo/public/cpp/bindings",
     "//mojo/public/cpp/system",
@@ -96,7 +96,7 @@
     "//media:shared_memory_support",
     "//media/cdm:cdm_manager",
     "//media/gpu",
-    "//media/gpu:features",
+    "//media/gpu:buildflags",
     "//media/gpu/ipc/service",
     "//media/mojo/common",
     "//media/mojo/common:mojo_shared_buffer_video_frame",
diff --git a/media/mojo/services/cdm_service.cc b/media/mojo/services/cdm_service.cc
index 7a5cdba..1a46b545 100644
--- a/media/mojo/services/cdm_service.cc
+++ b/media/mojo/services/cdm_service.cc
@@ -7,7 +7,7 @@
 #include "base/logging.h"
 #include "media/base/cdm_factory.h"
 #include "media/cdm/cdm_module.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "media/mojo/services/mojo_cdm_service.h"
 #include "media/mojo/services/mojo_cdm_service_context.h"
 #include "services/service_manager/public/cpp/connector.h"
diff --git a/media/mojo/services/cdm_service.h b/media/mojo/services/cdm_service.h
index 0d34f970..d309aab 100644
--- a/media/mojo/services/cdm_service.h
+++ b/media/mojo/services/cdm_service.h
@@ -8,7 +8,7 @@
 #include <memory>
 
 #include "build/build_config.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "media/mojo/interfaces/cdm_service.mojom.h"
 #include "media/mojo/interfaces/content_decryption_module.mojom.h"
 #include "media/mojo/services/media_mojo_export.h"
diff --git a/media/mojo/services/gpu_mojo_media_client.cc b/media/mojo/services/gpu_mojo_media_client.cc
index 7f78e61c..fb112f2 100644
--- a/media/mojo/services/gpu_mojo_media_client.cc
+++ b/media/mojo/services/gpu_mojo_media_client.cc
@@ -12,7 +12,7 @@
 #include "media/base/audio_decoder.h"
 #include "media/base/cdm_factory.h"
 #include "media/base/video_decoder.h"
-#include "media/gpu/features.h"
+#include "media/gpu/buildflags.h"
 #include "media/gpu/ipc/service/media_gpu_channel_manager.h"
 
 #if defined(OS_ANDROID)
diff --git a/media/mojo/services/interface_factory_impl.h b/media/mojo/services/interface_factory_impl.h
index d441eb01..7797ca1 100644
--- a/media/mojo/services/interface_factory_impl.h
+++ b/media/mojo/services/interface_factory_impl.h
@@ -8,7 +8,7 @@
 #include <memory>
 
 #include "base/macros.h"
-#include "media/mojo/features.h"
+#include "media/mojo/buildflags.h"
 #include "media/mojo/interfaces/interface_factory.mojom.h"
 #include "media/mojo/services/mojo_cdm_service_context.h"
 #include "mojo/public/cpp/bindings/strong_binding_set.h"
diff --git a/media/mojo/services/media_service.cc b/media/mojo/services/media_service.cc
index 2f69e43..d27889d5 100644
--- a/media/mojo/services/media_service.cc
+++ b/media/mojo/services/media_service.cc
@@ -5,7 +5,7 @@
 #include "media/mojo/services/media_service.h"
 
 #include "base/logging.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "media/mojo/services/interface_factory_impl.h"
 #include "media/mojo/services/mojo_media_client.h"
 #include "services/service_manager/public/cpp/connector.h"
diff --git a/media/mojo/services/media_service_unittest.cc b/media/mojo/services/media_service_unittest.cc
index 87860f8d..76bcbfb 100644
--- a/media/mojo/services/media_service_unittest.cc
+++ b/media/mojo/services/media_service_unittest.cc
@@ -15,9 +15,9 @@
 #include "media/base/cdm_config.h"
 #include "media/base/mock_filters.h"
 #include "media/base/test_helpers.h"
+#include "media/mojo/buildflags.h"
 #include "media/mojo/clients/mojo_demuxer_stream_impl.h"
 #include "media/mojo/common/media_type_converters.h"
-#include "media/mojo/features.h"
 #include "media/mojo/interfaces/constants.mojom.h"
 #include "media/mojo/interfaces/content_decryption_module.mojom.h"
 #include "media/mojo/interfaces/decryptor.mojom.h"
diff --git a/media/mojo/services/mojo_cdm_service_context.h b/media/mojo/services/mojo_cdm_service_context.h
index 439c780d..28961f6 100644
--- a/media/mojo/services/mojo_cdm_service_context.h
+++ b/media/mojo/services/mojo_cdm_service_context.h
@@ -11,7 +11,7 @@
 #include <memory>
 
 #include "base/macros.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "media/mojo/services/media_mojo_export.h"
 
 namespace media {
diff --git a/media/mojo/services/mojo_media_client.h b/media/mojo/services/mojo_media_client.h
index 52d0cd6e..9e84464 100644
--- a/media/mojo/services/mojo_media_client.h
+++ b/media/mojo/services/mojo_media_client.h
@@ -12,7 +12,7 @@
 #include "base/callback_forward.h"
 #include "base/memory/ref_counted.h"
 #include "media/base/overlay_info.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "media/mojo/interfaces/video_decoder.mojom.h"
 #include "media/mojo/services/media_mojo_export.h"
 
diff --git a/media/remoting/courier_renderer_factory.cc b/media/remoting/courier_renderer_factory.cc
index 1091c41e..b957afa 100644
--- a/media/remoting/courier_renderer_factory.cc
+++ b/media/remoting/courier_renderer_factory.cc
@@ -9,7 +9,7 @@
 #include "base/logging.h"
 #include "build/buildflag.h"
 #include "media/base/overlay_info.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 #if BUILDFLAG(ENABLE_MEDIA_REMOTING_RPC)
 #include "media/remoting/courier_renderer.h"  // nogncheck
diff --git a/media/remoting/fake_remoter.cc b/media/remoting/fake_remoter.cc
index fcbfe21..5e35242 100644
--- a/media/remoting/fake_remoter.cc
+++ b/media/remoting/fake_remoter.cc
@@ -11,7 +11,7 @@
 #include "base/callback.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/buildflag.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "media/remoting/renderer_controller.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/media/remoting/renderer_controller.cc b/media/remoting/renderer_controller.cc
index 79e82aca..ee60173 100644
--- a/media/remoting/renderer_controller.cc
+++ b/media/remoting/renderer_controller.cc
@@ -12,7 +12,7 @@
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "build/buildflag.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 #if defined(OS_ANDROID)
 #include "media/base/android/media_codec_util.h"
diff --git a/media/remoting/renderer_controller.h b/media/remoting/renderer_controller.h
index ea1c6868..75a1c73 100644
--- a/media/remoting/renderer_controller.h
+++ b/media/remoting/renderer_controller.h
@@ -14,7 +14,7 @@
 #include "base/timer/timer.h"
 #include "build/buildflag.h"
 #include "media/base/media_observer.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "media/mojo/interfaces/remoting.mojom.h"
 #include "media/remoting/metrics.h"
 #include "mojo/public/cpp/bindings/binding.h"
diff --git a/media/renderers/default_renderer_factory.cc b/media/renderers/default_renderer_factory.cc
index a740d11c..dc286ce 100644
--- a/media/renderers/default_renderer_factory.cc
+++ b/media/renderers/default_renderer_factory.cc
@@ -17,7 +17,7 @@
 #include "media/base/media_switches.h"
 #include "media/filters/gpu_memory_buffer_decoder_wrapper.h"
 #include "media/filters/gpu_video_decoder.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "media/renderers/audio_renderer_impl.h"
 #include "media/renderers/renderer_impl.h"
 #include "media/renderers/video_renderer_impl.h"
diff --git a/media/renderers/video_renderer_impl.cc b/media/renderers/video_renderer_impl.cc
index 5403edbe..b6d78ce 100644
--- a/media/renderers/video_renderer_impl.cc
+++ b/media/renderers/video_renderer_impl.cc
@@ -211,6 +211,7 @@
   painted_first_frame_ = false;
   has_playback_met_watch_time_duration_requirement_ = false;
   last_render_time_ = last_frame_ready_time_ = base::TimeTicks();
+  video_frame_stream_->SkipPrepareUntil(start_timestamp_);
   AttemptRead_Locked();
 }
 
@@ -234,6 +235,12 @@
       task_runner_, create_video_decoders_cb_, media_log_));
   video_frame_stream_->set_config_change_observer(base::Bind(
       &VideoRendererImpl::OnConfigChange, weak_factory_.GetWeakPtr()));
+  if (gpu_memory_buffer_pool_) {
+    video_frame_stream_->SetPrepareCB(base::BindRepeating(
+        &GpuMemoryBufferVideoFramePool::MaybeCreateHardwareFrame,
+        // Safe since VideoFrameStream won't issue calls after destruction.
+        base::Unretained(gpu_memory_buffer_pool_.get())));
+  }
 
   low_delay_ = ShouldUseLowDelayMode(stream);
 
@@ -450,22 +457,6 @@
   }
 }
 
-void VideoRendererImpl::FrameReadyForCopyingToGpuMemoryBuffers(
-    base::TimeTicks read_time,
-    VideoFrameStream::Status status,
-    const scoped_refptr<VideoFrame>& frame) {
-  if (status != VideoFrameStream::OK || IsBeforeStartTime(frame->timestamp())) {
-    VideoRendererImpl::FrameReady(read_time, status, frame);
-    return;
-  }
-
-  DCHECK(frame);
-  gpu_memory_buffer_pool_->MaybeCreateHardwareFrame(
-      frame, base::BindOnce(&VideoRendererImpl::FrameReady,
-                            frame_callback_weak_factory_.GetWeakPtr(),
-                            read_time, status));
-}
-
 void VideoRendererImpl::FrameReady(base::TimeTicks read_time,
                                    VideoFrameStream::Status status,
                                    const scoped_refptr<VideoFrame>& frame) {
@@ -668,19 +659,9 @@
   switch (state_) {
     case kPlaying:
       pending_read_ = true;
-      if (gpu_memory_buffer_pool_) {
-        // TODO(dalecurtis): Move this functionality into DecoderStream via the
-        // concept of "prepared" buffers.
-        video_frame_stream_->Read(base::BindRepeating(
-            &VideoRendererImpl::FrameReadyForCopyingToGpuMemoryBuffers,
-            frame_callback_weak_factory_.GetWeakPtr(),
-            tick_clock_->NowTicks()));
-      } else {
-        video_frame_stream_->Read(
-            base::BindRepeating(&VideoRendererImpl::FrameReady,
-                                frame_callback_weak_factory_.GetWeakPtr(),
-                                tick_clock_->NowTicks()));
-      }
+      video_frame_stream_->Read(base::BindRepeating(
+          &VideoRendererImpl::FrameReady,
+          frame_callback_weak_factory_.GetWeakPtr(), tick_clock_->NowTicks()));
       return;
     case kUninitialized:
     case kInitializing:
diff --git a/media/renderers/video_renderer_impl.h b/media/renderers/video_renderer_impl.h
index cb11c29..af6fab3e 100644
--- a/media/renderers/video_renderer_impl.h
+++ b/media/renderers/video_renderer_impl.h
@@ -107,15 +107,6 @@
   void OnConfigChange(const VideoDecoderConfig& config);
 
   // Callback for |video_frame_stream_| to deliver decoded video frames and
-  // report video decoding status. If a frame is available the planes will be
-  // copied asynchronously and FrameReady will be called once finished copying.
-  // |read_time| is the time at which this read was started.
-  void FrameReadyForCopyingToGpuMemoryBuffers(
-      base::TimeTicks read_time,
-      VideoFrameStream::Status status,
-      const scoped_refptr<VideoFrame>& frame);
-
-  // Callback for |video_frame_stream_| to deliver decoded video frames and
   // report video decoding status. |read_time| is the time at which this read
   // was started.
   void FrameReady(base::TimeTicks read_time,
@@ -220,14 +211,15 @@
 
   RendererClient* client_;
 
-  // Provides video frames to VideoRendererImpl.
-  std::unique_ptr<VideoFrameStream> video_frame_stream_;
-
   // Pool of GpuMemoryBuffers and resources used to create hardware frames.
   // Ensure this is destructed after |algorithm_| for optimal memory release
-  // when a frames are still held by the compositor.
+  // when a frames are still held by the compositor. Must be destructed after
+  // |video_frame_stream_| since it holds a callback to the pool.
   std::unique_ptr<GpuMemoryBufferVideoFramePool> gpu_memory_buffer_pool_;
 
+  // Provides video frames to VideoRendererImpl.
+  std::unique_ptr<VideoFrameStream> video_frame_stream_;
+
   MediaLog* media_log_;
 
   // Flag indicating low-delay mode.
diff --git a/media/test/pipeline_integration_perftest.cc b/media/test/pipeline_integration_perftest.cc
index 648d2517..0bc66d9 100644
--- a/media/test/pipeline_integration_perftest.cc
+++ b/media/test/pipeline_integration_perftest.cc
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 #include "media/base/test_data_util.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "media/test/pipeline_integration_test_base.h"
 #include "testing/perf/perf_test.h"
 
diff --git a/media/test/pipeline_integration_test.cc b/media/test/pipeline_integration_test.cc
index cc24e55..ca838381 100644
--- a/media/test/pipeline_integration_test.cc
+++ b/media/test/pipeline_integration_test.cc
@@ -28,7 +28,7 @@
 #include "media/base/timestamp_constants.h"
 #include "media/cdm/aes_decryptor.h"
 #include "media/cdm/json_web_key.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "media/renderers/renderer_impl.h"
 #include "media/test/fake_encrypted_media.h"
 #include "media/test/mock_media_source.h"
diff --git a/media/test/pipeline_integration_test_base.cc b/media/test/pipeline_integration_test_base.cc
index f5ee7173..334e7d4 100644
--- a/media/test/pipeline_integration_test_base.cc
+++ b/media/test/pipeline_integration_test_base.cc
@@ -18,7 +18,7 @@
 #include "media/base/test_data_util.h"
 #include "media/filters/file_data_source.h"
 #include "media/filters/memory_data_source.h"
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 #include "media/renderers/audio_renderer_impl.h"
 #include "media/renderers/renderer_impl.h"
 #include "media/test/fake_encrypted_media.h"
diff --git a/media/video/gpu_memory_buffer_video_frame_pool.cc b/media/video/gpu_memory_buffer_video_frame_pool.cc
index 12933d1..4efa4b5 100644
--- a/media/video/gpu_memory_buffer_video_frame_pool.cc
+++ b/media/video/gpu_memory_buffer_video_frame_pool.cc
@@ -124,15 +124,20 @@
   // Struct to keep track of requested videoframe copies.
   struct VideoFrameCopyRequest {
     VideoFrameCopyRequest(scoped_refptr<VideoFrame> video_frame,
-                          FrameReadyCB frame_ready_cb)
-        : video_frame(video_frame), frame_ready_cb(std::move(frame_ready_cb)) {}
+                          FrameReadyCB frame_ready_cb,
+                          bool passthrough)
+        : video_frame(video_frame),
+          frame_ready_cb(std::move(frame_ready_cb)),
+          passthrough(passthrough) {}
     scoped_refptr<VideoFrame> video_frame;
     FrameReadyCB frame_ready_cb;
+    bool passthrough;
   };
 
   // Start the copy of a video_frame on the worker_task_runner_.
-  // It assumes there are currently no in-flight copies.
-  void StartCopy(const scoped_refptr<VideoFrame>& video_frame);
+  // It assumes there are currently no in-flight copies and works on the request
+  // in the front of |frame_copy_requests_| queue.
+  void StartCopy();
 
   // Copy |video_frame| data into |frame_resources| and calls |frame_ready_cb|
   // when done.
@@ -165,6 +170,13 @@
       const gfx::Size& size,
       GpuVideoAcceleratorFactories::OutputFormat format);
 
+  // Calls the FrameReadyCB of the first entry in |frame_copy_requests_|, with
+  // the provided |video_frame|, then deletes the entry from
+  // |frame_copy_requests_| and attempts to start another copy if there are
+  // other |frame_copy_requests_| elements.
+  void CompleteCopyRequestAndMaybeStartNextCopy(
+      const scoped_refptr<VideoFrame>& video_frame);
+
   // Callback called when a VideoFrame generated with GetFrameResources is no
   // longer referenced.
   // This must be called on the thread where |media_task_runner_| is current.
@@ -542,10 +554,9 @@
         gpu_factories_->VideoFrameOutputFormat(video_frame->BitDepth());
   }
 
-  if (output_format_ == GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED) {
-    std::move(frame_ready_cb).Run(video_frame);
-    return;
-  }
+  bool passthrough = false;
+  if (output_format_ == GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED)
+    passthrough = true;
   switch (video_frame->format()) {
     // Supported cases.
     case PIXEL_FORMAT_YV12:
@@ -576,10 +587,8 @@
     case PIXEL_FORMAT_YUV444P12:
     case PIXEL_FORMAT_Y16:
     case PIXEL_FORMAT_UNKNOWN:
-      std::move(frame_ready_cb).Run(video_frame);
-      return;
+      passthrough = true;
   }
-
   // TODO(dcastagna): Handle odd positioned video frame input, see
   // https://crbug.com/638906.
   // TODO(emircan): Eliminate odd size video frame input cases as they are not
@@ -588,13 +597,13 @@
       (video_frame->visible_rect().y() & 1) ||
       (video_frame->coded_size().width() & 1) ||
       (video_frame->coded_size().height() & 1)) {
-    std::move(frame_ready_cb).Run(video_frame);
-    return;
+    passthrough = true;
   }
 
-  frame_copy_requests_.emplace_back(video_frame, std::move(frame_ready_cb));
+  frame_copy_requests_.emplace_back(video_frame, std::move(frame_ready_cb),
+                                    passthrough);
   if (frame_copy_requests_.size() == 1u)
-    StartCopy(video_frame);
+    StartCopy();
 }
 
 bool GpuMemoryBufferVideoFramePool::PoolImpl::OnMemoryDump(
@@ -670,24 +679,30 @@
                      this, video_frame, frame_resources));
 }
 
-void GpuMemoryBufferVideoFramePool::PoolImpl::StartCopy(
-    const scoped_refptr<VideoFrame>& video_frame) {
+void GpuMemoryBufferVideoFramePool::PoolImpl::StartCopy() {
   DCHECK(media_task_runner_->BelongsToCurrentThread());
   DCHECK(!frame_copy_requests_.empty());
 
-  const gfx::Size coded_size = CodedSize(video_frame, output_format_);
-  // Acquire resources. Incompatible ones will be dropped from the pool.
-  FrameResources* frame_resources =
-      GetOrCreateFrameResources(coded_size, output_format_);
-  if (!frame_resources) {
-    std::move(frame_copy_requests_.front().frame_ready_cb).Run(video_frame);
-    frame_copy_requests_.pop_front();
-    return;
-  }
+  while (!frame_copy_requests_.empty()) {
+    VideoFrameCopyRequest& request = frame_copy_requests_.front();
+    // Acquire resources. Incompatible ones will be dropped from the pool.
+    FrameResources* frame_resources =
+        request.passthrough
+            ? nullptr
+            : GetOrCreateFrameResources(
+                  CodedSize(request.video_frame, output_format_),
+                  output_format_);
+    if (!frame_resources) {
+      std::move(request.frame_ready_cb).Run(request.video_frame);
+      frame_copy_requests_.pop_front();
+      continue;
+    }
 
-  worker_task_runner_->PostTask(
-      FROM_HERE, base::BindOnce(&PoolImpl::CopyVideoFrameToGpuMemoryBuffers,
-                                this, video_frame, frame_resources));
+    worker_task_runner_->PostTask(
+        FROM_HERE, base::BindOnce(&PoolImpl::CopyVideoFrameToGpuMemoryBuffers,
+                                  this, request.video_frame, frame_resources));
+    break;
+  }
 }
 
 // Copies |video_frame| into |frame_resources| asynchronously, posting n tasks
@@ -811,8 +826,7 @@
   gpu::gles2::GLES2Interface* gles2 = gpu_factories_->ContextGL();
   if (!gles2) {
     frame_resources->MarkUnused(tick_clock_->NowTicks());
-    std::move(frame_copy_requests_.front().frame_ready_cb).Run(video_frame);
-    frame_copy_requests_.pop_front();
+    CompleteCopyRequestAndMaybeStartNextCopy(video_frame);
     return;
   }
 
@@ -863,8 +877,7 @@
   if (!frame) {
     frame_resources->MarkUnused(tick_clock_->NowTicks());
     MailboxHoldersReleased(frame_resources, gpu::SyncToken());
-    std::move(frame_copy_requests_.front().frame_ready_cb).Run(video_frame);
-    frame_copy_requests_.pop_front();
+    CompleteCopyRequestAndMaybeStartNextCopy(video_frame);
     return;
   }
   frame->SetReleaseMailboxCB(
@@ -906,14 +919,7 @@
   frame->metadata()->SetBoolean(VideoFrameMetadata::READ_LOCK_FENCES_ENABLED,
                                 true);
 
-  DCHECK(!frame_copy_requests_.empty());
-  std::move(frame_copy_requests_.front().frame_ready_cb).Run(frame);
-  frame_copy_requests_.pop_front();
-
-  if (!frame_copy_requests_.empty()) {
-    VideoFrameCopyRequest& copy_request = frame_copy_requests_.front();
-    StartCopy(copy_request.video_frame);
-  }
+  CompleteCopyRequestAndMaybeStartNextCopy(frame);
 }
 
 // Destroy all the resources posting one task per FrameResources
@@ -1006,6 +1012,17 @@
   return frame_resources;
 }
 
+void GpuMemoryBufferVideoFramePool::PoolImpl::
+    CompleteCopyRequestAndMaybeStartNextCopy(
+        const scoped_refptr<VideoFrame>& video_frame) {
+  DCHECK(!frame_copy_requests_.empty());
+
+  std::move(frame_copy_requests_.front().frame_ready_cb).Run(video_frame);
+  frame_copy_requests_.pop_front();
+  if (!frame_copy_requests_.empty())
+    StartCopy();
+}
+
 // static
 void GpuMemoryBufferVideoFramePool::PoolImpl::DeleteFrameResources(
     GpuVideoAcceleratorFactories* const gpu_factories,
diff --git a/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc b/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc
index dbe085e..d269235 100644
--- a/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc
+++ b/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/test/simple_test_tick_clock.h"
 #include "base/test/test_simple_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
 #include "gpu/command_buffer/client/gles2_interface_stub.h"
 #include "media/base/video_frame.h"
 #include "media/video/gpu_memory_buffer_video_frame_pool.h"
@@ -145,6 +146,14 @@
   *video_frame_output = video_frame;
 }
 
+void MaybeCreateHardwareFrameCallbackAndTrackTime(
+    scoped_refptr<VideoFrame>* video_frame_output,
+    base::TimeTicks* output_time,
+    const scoped_refptr<VideoFrame>& video_frame) {
+  *video_frame_output = video_frame;
+  *output_time = base::TimeTicks::Now();
+}
+
 TEST_F(GpuMemoryBufferVideoFramePoolTest, VideoFrameOutputFormatUnknown) {
   scoped_refptr<VideoFrame> software_frame = CreateTestYUVVideoFrame(10);
   mock_gpu_factories_->SetVideoFrameOutputFormat(
@@ -456,6 +465,55 @@
   RunUntilIdle();
 }
 
+// Tests that adding a frame that the pool doesn't handle does not break the
+// FIFO order in tasks.
+TEST_F(GpuMemoryBufferVideoFramePoolTest, PreservesOrder) {
+  std::vector<scoped_refptr<VideoFrame>> frame_outputs;
+
+  scoped_refptr<VideoFrame> software_frame_1 = CreateTestYUVVideoFrame(10);
+  scoped_refptr<VideoFrame> frame_1 = nullptr;
+  gpu_memory_buffer_pool_->MaybeCreateHardwareFrame(
+      software_frame_1,
+      base::BindOnce(MaybeCreateHardwareFrameCallback, &frame_1));
+
+  scoped_refptr<VideoFrame> software_frame_2 = CreateTestYUVVideoFrame(10);
+  scoped_refptr<VideoFrame> frame_2 = nullptr;
+  base::TimeTicks time_2;
+  gpu_memory_buffer_pool_->MaybeCreateHardwareFrame(
+      software_frame_2,
+      base::BindOnce(MaybeCreateHardwareFrameCallbackAndTrackTime, &frame_2,
+                     &time_2));
+
+  scoped_refptr<VideoFrame> software_frame_3 = VideoFrame::CreateEOSFrame();
+  scoped_refptr<VideoFrame> frame_3 = nullptr;
+  base::TimeTicks time_3;
+  gpu_memory_buffer_pool_->MaybeCreateHardwareFrame(
+      software_frame_3,
+      base::BindOnce(MaybeCreateHardwareFrameCallbackAndTrackTime, &frame_3,
+                     &time_3));
+
+  // Queue all the tasks |media_task_runner_|. Make sure that none is early
+  // returned.
+  media_task_runner_->RunUntilIdle();
+  EXPECT_FALSE(frame_1.get());
+  EXPECT_FALSE(frame_2.get());
+  EXPECT_FALSE(frame_3.get());
+  EXPECT_EQ(1u, copy_task_runner_->NumPendingTasks());
+
+  RunUntilIdle();
+  EXPECT_TRUE(frame_1.get());
+  EXPECT_NE(software_frame_1.get(), frame_1.get());
+  EXPECT_FALSE(frame_2.get());
+  EXPECT_FALSE(frame_3.get());
+
+  RunUntilIdle();
+  EXPECT_TRUE(frame_2.get());
+  EXPECT_TRUE(frame_3.get());
+  EXPECT_NE(software_frame_2.get(), frame_2.get());
+  EXPECT_EQ(software_frame_3.get(), frame_3.get());
+  EXPECT_LE(time_2, time_3);
+}
+
 // Test that Abort() stops any pending copies.
 TEST_F(GpuMemoryBufferVideoFramePoolTest, AbortCopies) {
   scoped_refptr<VideoFrame> software_frame_1 = CreateTestYUVVideoFrame(10);
diff --git a/mojo/common/BUILD.gn b/mojo/common/BUILD.gn
index 612de0da..d000202c 100644
--- a/mojo/common/BUILD.gn
+++ b/mojo/common/BUILD.gn
@@ -16,8 +16,6 @@
   sources = [
     "memory_allocator_dump_cross_process_uid.mojom",
     "process_id.mojom",
-    "thread_priority.mojom",
-    "unguessable_token.mojom",
     "values.mojom",
   ]
 
diff --git a/mojo/common/common_custom_types_struct_traits.cc b/mojo/common/common_custom_types_struct_traits.cc
index 7a2ea17e..d626b5ef 100644
--- a/mojo/common/common_custom_types_struct_traits.cc
+++ b/mojo/common/common_custom_types_struct_traits.cc
@@ -8,61 +8,6 @@
 namespace mojo {
 
 // static
-bool StructTraits<
-    common::mojom::UnguessableTokenDataView,
-    base::UnguessableToken>::Read(common::mojom::UnguessableTokenDataView data,
-                                  base::UnguessableToken* out) {
-  uint64_t high = data.high();
-  uint64_t low = data.low();
-
-  // Receiving a zeroed UnguessableToken is a security issue.
-  if (high == 0 && low == 0)
-    return false;
-
-  *out = base::UnguessableToken::Deserialize(high, low);
-  return true;
-}
-
-// static
-common::mojom::ThreadPriority
-EnumTraits<common::mojom::ThreadPriority, base::ThreadPriority>::ToMojom(
-    base::ThreadPriority thread_priority) {
-  switch (thread_priority) {
-    case base::ThreadPriority::BACKGROUND:
-      return common::mojom::ThreadPriority::BACKGROUND;
-    case base::ThreadPriority::NORMAL:
-      return common::mojom::ThreadPriority::NORMAL;
-    case base::ThreadPriority::DISPLAY:
-      return common::mojom::ThreadPriority::DISPLAY;
-    case base::ThreadPriority::REALTIME_AUDIO:
-      return common::mojom::ThreadPriority::REALTIME_AUDIO;
-  }
-  NOTREACHED();
-  return common::mojom::ThreadPriority::BACKGROUND;
-}
-
-// static
-bool EnumTraits<common::mojom::ThreadPriority, base::ThreadPriority>::FromMojom(
-    common::mojom::ThreadPriority input,
-    base::ThreadPriority* out) {
-  switch (input) {
-    case common::mojom::ThreadPriority::BACKGROUND:
-      *out = base::ThreadPriority::BACKGROUND;
-      return true;
-    case common::mojom::ThreadPriority::NORMAL:
-      *out = base::ThreadPriority::NORMAL;
-      return true;
-    case common::mojom::ThreadPriority::DISPLAY:
-      *out = base::ThreadPriority::DISPLAY;
-      return true;
-    case common::mojom::ThreadPriority::REALTIME_AUDIO:
-      *out = base::ThreadPriority::REALTIME_AUDIO;
-      return true;
-  }
-  return false;
-}
-
-// static
 bool StructTraits<common::mojom::MemoryAllocatorDumpCrossProcessUidDataView,
                   base::trace_event::MemoryAllocatorDumpGuid>::
     Read(common::mojom::MemoryAllocatorDumpCrossProcessUidDataView data,
diff --git a/mojo/common/common_custom_types_struct_traits.h b/mojo/common/common_custom_types_struct_traits.h
index 09c877e..367d8f60 100644
--- a/mojo/common/common_custom_types_struct_traits.h
+++ b/mojo/common/common_custom_types_struct_traits.h
@@ -8,35 +8,12 @@
 #include "base/process/process_handle.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/trace_event/memory_allocator_dump_guid.h"
-#include "base/unguessable_token.h"
 #include "mojo/common/memory_allocator_dump_cross_process_uid.mojom-shared.h"
 #include "mojo/common/mojo_common_export.h"
 #include "mojo/common/process_id.mojom-shared.h"
-#include "mojo/common/thread_priority.mojom-shared.h"
-#include "mojo/common/unguessable_token.mojom-shared.h"
 
 namespace mojo {
 
-// If base::UnguessableToken is no longer 128 bits, the logic below and the
-// mojom::UnguessableToken type should be updated.
-static_assert(sizeof(base::UnguessableToken) == 2 * sizeof(uint64_t),
-              "base::UnguessableToken should be of size 2 * sizeof(uint64_t).");
-
-template <>
-struct StructTraits<common::mojom::UnguessableTokenDataView,
-                    base::UnguessableToken> {
-  static uint64_t high(const base::UnguessableToken& token) {
-    return token.GetHighForSerialization();
-  }
-
-  static uint64_t low(const base::UnguessableToken& token) {
-    return token.GetLowForSerialization();
-  }
-
-  static bool Read(common::mojom::UnguessableTokenDataView data,
-                   base::UnguessableToken* out);
-};
-
 template <>
 struct StructTraits<common::mojom::ProcessIdDataView, base::ProcessId> {
   static uint32_t pid(const base::ProcessId& process_id) {
@@ -51,14 +28,6 @@
 };
 
 template <>
-struct EnumTraits<common::mojom::ThreadPriority, base::ThreadPriority> {
-  static common::mojom::ThreadPriority ToMojom(
-      base::ThreadPriority thread_priority);
-  static bool FromMojom(common::mojom::ThreadPriority input,
-                        base::ThreadPriority* out);
-};
-
-template <>
 struct StructTraits<common::mojom::MemoryAllocatorDumpCrossProcessUidDataView,
                     base::trace_event::MemoryAllocatorDumpGuid> {
   static uint64_t value(const base::trace_event::MemoryAllocatorDumpGuid& id) {
diff --git a/mojo/common/common_custom_types_unittest.cc b/mojo/common/common_custom_types_unittest.cc
index 14b60be..3ccad0f 100644
--- a/mojo/common/common_custom_types_unittest.cc
+++ b/mojo/common/common_custom_types_unittest.cc
@@ -61,21 +61,6 @@
   return base::Bind(&DoExpectResponse<T>, expected_value, closure);
 }
 
-class TestUnguessableTokenImpl : public TestUnguessableToken {
- public:
-  explicit TestUnguessableTokenImpl(TestUnguessableTokenRequest request)
-      : binding_(this, std::move(request)) {}
-
-  // TestUnguessableToken implementation:
-  void BounceNonce(const base::UnguessableToken& in,
-                   BounceNonceCallback callback) override {
-    std::move(callback).Run(in);
-  }
-
- private:
-  mojo::Binding<TestUnguessableToken> binding_;
-};
-
 class TestValueImpl : public TestValue {
  public:
   explicit TestValueImpl(TestValueRequest request)
@@ -114,19 +99,6 @@
 
 }  // namespace
 
-TEST_F(CommonCustomTypesTest, UnguessableToken) {
-  base::RunLoop run_loop;
-
-  TestUnguessableTokenPtr ptr;
-  TestUnguessableTokenImpl impl(MakeRequest(&ptr));
-
-  base::UnguessableToken token = base::UnguessableToken::Create();
-
-  ptr->BounceNonce(token, ExpectResponse(&token, run_loop.QuitClosure()));
-
-  run_loop.Run();
-}
-
 TEST_F(CommonCustomTypesTest, ProcessId) {
   base::ProcessId pid = base::GetCurrentProcId();
   base::ProcessId out_pid = base::kNullProcessId;
diff --git a/mojo/common/test_common_custom_types.mojom b/mojo/common/test_common_custom_types.mojom
index 69520da..e23a94ae 100644
--- a/mojo/common/test_common_custom_types.mojom
+++ b/mojo/common/test_common_custom_types.mojom
@@ -4,14 +4,8 @@
 
 module mojo.common.test;
 
-import "mojo/common/unguessable_token.mojom";
 import "mojo/common/values.mojom";
 
-interface TestUnguessableToken {
-  BounceNonce(mojo.common.mojom.UnguessableToken in)
-      => (mojo.common.mojom.UnguessableToken out);
-};
-
 interface TestValue {
   [Sync]
   BounceDictionaryValue(mojo.common.mojom.DictionaryValue in)
diff --git a/mojo/common/thread_priority.mojom b/mojo/common/thread_priority.mojom
deleted file mode 100644
index c3ebb468..0000000
--- a/mojo/common/thread_priority.mojom
+++ /dev/null
@@ -1,17 +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.
-
-module mojo.common.mojom;
-
-// Corresponds to |base::ThreadPriority|
-enum ThreadPriority {
-  // Suitable for threads that shouldn't disrupt high priority work.
-  BACKGROUND,
-  // Default priority level.
-  NORMAL,
-  // Suitable for threads which generate data for the display (at ~60Hz).
-  DISPLAY,
-  // Suitable for low-latency, glitch-resistant audio.
-  REALTIME_AUDIO,
-};
diff --git a/mojo/common/thread_priority.typemap b/mojo/common/thread_priority.typemap
deleted file mode 100644
index d3f9be1..0000000
--- a/mojo/common/thread_priority.typemap
+++ /dev/null
@@ -1,12 +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.
-
-mojom = "//mojo/common/thread_priority.mojom"
-public_headers = [ "//base/threading/platform_thread.h" ]
-traits_headers = [ "//mojo/common/common_custom_types_struct_traits.h" ]
-public_deps = [
-  "//base",
-  "//mojo/common:struct_traits",
-]
-type_mappings = [ "mojo.common.mojom.ThreadPriority=base::ThreadPriority" ]
diff --git a/mojo/common/typemaps.gni b/mojo/common/typemaps.gni
index acf6dea..eadf9925 100644
--- a/mojo/common/typemaps.gni
+++ b/mojo/common/typemaps.gni
@@ -6,7 +6,5 @@
   "//mojo/common/memory_allocator_dump_cross_process_uid.typemap",
   "//mojo/common/process_id.typemap",
   "//mojo/common/read_only_buffer.typemap",
-  "//mojo/common/thread_priority.typemap",
-  "//mojo/common/unguessable_token.typemap",
   "//mojo/common/values.typemap",
 ]
diff --git a/mojo/common/unguessable_token.mojom b/mojo/common/unguessable_token.mojom
deleted file mode 100644
index 3279717..0000000
--- a/mojo/common/unguessable_token.mojom
+++ /dev/null
@@ -1,11 +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 mojo.common.mojom;
-
-// Corresponds to |base::UnguessableToken| in base/unguessable_token.h
-struct UnguessableToken {
-  uint64 high;
-  uint64 low;
-};
diff --git a/mojo/common/unguessable_token.typemap b/mojo/common/unguessable_token.typemap
deleted file mode 100644
index ec7b194..0000000
--- a/mojo/common/unguessable_token.typemap
+++ /dev/null
@@ -1,12 +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.
-
-mojom = "//mojo/common/unguessable_token.mojom"
-public_headers = [ "//base/unguessable_token.h" ]
-traits_headers = [ "//mojo/common/common_custom_types_struct_traits.h" ]
-public_deps = [
-  "//mojo/common:struct_traits",
-]
-
-type_mappings = [ "mojo.common.mojom.UnguessableToken=base::UnguessableToken" ]
diff --git a/mojo/edk/BUILD.gn b/mojo/edk/BUILD.gn
index a5a2102..c6d5275 100644
--- a/mojo/edk/BUILD.gn
+++ b/mojo/edk/BUILD.gn
@@ -3,6 +3,8 @@
 # found in the LICENSE file.
 
 import("//build/config/nacl/config.gni")
+import("//mojo/edk/mojo_core_library.gni")
+import("//testing/test.gni")
 
 # Targets should depend on this if directly referencing the |mojo::edk|
 # namespace.
@@ -31,7 +33,7 @@
   }
 
   public_deps = [
-    ":core",
+    ":impl_for_edk",
     "//mojo/public/cpp/system",
   ]
 }
@@ -39,75 +41,203 @@
 # Bits of the EDK library which do not depend on public API linkage. It is
 # not allowed for this target or any of its transitive dependencies to depend
 # on anything under //mojo/public beyond strict C type definitions.
-source_set("core") {
-  visibility = [ ":edk" ]
+#
+# This is templated because it's consumed by both the ":edk" component library
+# as well as the ":mojo_core" shared library. In the former case we want to
+# export symbols, but in the latter case we don't. The template stamps out two
+# nearly identical targets which differ only in what symbols they export.
+template("core_impl_source_set") {
+  source_set(target_name) {
+    if (invoker.for_mojo_core) {
+      visibility = [ ":mojo_core" ]
+    } else {
+      visibility = [ ":edk" ]
+    }
 
-  public = [
-    "embedder/configuration.h",
-    "embedder/connection_params.h",
-    "embedder/embedder_internal.h",
-    "embedder/entrypoints.h",
-    "embedder/named_platform_channel_pair.h",
-    "embedder/named_platform_handle.h",
-    "embedder/named_platform_handle_utils.h",
-    "embedder/platform_channel_pair.h",
-    "embedder/platform_handle.h",
-    "embedder/platform_handle_utils.h",
-    "embedder/process_error_callback.h",
-    "embedder/scoped_ipc_support.h",
-    "embedder/scoped_platform_handle.h",
-    "embedder/transport_protocol.h",
-  ]
-
-  sources = [
-    "embedder/connection_params.cc",
-    "embedder/entrypoints.cc",
-    "embedder/named_platform_channel_pair_win.cc",
-    "embedder/named_platform_handle_utils_win.cc",
-    "embedder/platform_channel_pair.cc",
-    "embedder/platform_channel_pair_win.cc",
-    "embedder/platform_handle.cc",
-    "embedder/platform_handle_utils_win.cc",
-    "embedder/platform_shared_buffer.cc",
-    "embedder/scoped_ipc_support.cc",
-  ]
-
-  if (is_fuchsia) {
-    sources += [
-      "embedder/named_platform_handle_utils_fuchsia.cc",
-      "embedder/platform_channel_pair_fuchsia.cc",
-      "embedder/platform_handle_utils_fuchsia.cc",
-    ]
-  } else if (is_posix) {
-    public += [ "embedder/platform_channel_utils_posix.h" ]
-
-    sources += [
-      "embedder/platform_channel_pair_posix.cc",
-      "embedder/platform_channel_utils_posix.cc",
-      "embedder/platform_handle_utils_posix.cc",
+    public = [
+      "embedder/configuration.h",
+      "embedder/connection_params.h",
+      "embedder/entrypoints.h",
+      "embedder/named_platform_channel_pair.h",
+      "embedder/named_platform_handle.h",
+      "embedder/named_platform_handle_utils.h",
+      "embedder/platform_channel_pair.h",
+      "embedder/platform_handle.h",
+      "embedder/platform_handle_utils.h",
+      "embedder/process_error_callback.h",
+      "embedder/scoped_ipc_support.h",
+      "embedder/scoped_platform_handle.h",
+      "embedder/transport_protocol.h",
+      "system/channel.h",
+      "system/configuration.h",
+      "system/core.h",
+      "system/data_pipe_consumer_dispatcher.h",
+      "system/data_pipe_control_message.h",
+      "system/data_pipe_producer_dispatcher.h",
+      "system/dispatcher.h",
+      "system/handle_signals_state.h",
+      "system/handle_table.h",
+      "system/message_pipe_dispatcher.h",
+      "system/node_controller.h",
+      "system/options_validation.h",
+      "system/platform_handle_dispatcher.h",
+      "system/request_context.h",
+      "system/shared_buffer_dispatcher.h",
+      "system/user_message_impl.h",
     ]
 
+    sources = [
+      "embedder/connection_params.cc",
+      "embedder/entrypoints.cc",
+      "embedder/named_platform_channel_pair_win.cc",
+      "embedder/named_platform_handle_utils_win.cc",
+      "embedder/platform_channel_pair.cc",
+      "embedder/platform_channel_pair_win.cc",
+      "embedder/platform_handle.cc",
+      "embedder/platform_handle_utils_win.cc",
+      "embedder/platform_shared_buffer.cc",
+      "embedder/scoped_ipc_support.cc",
+      "system/atomic_flag.h",
+      "system/broker.h",
+      "system/broker_host.cc",
+      "system/broker_host.h",
+      "system/broker_win.cc",
+      "system/channel.cc",
+      "system/channel_win.cc",
+      "system/configuration.cc",
+      "system/core.cc",
+      "system/data_pipe_consumer_dispatcher.cc",
+      "system/data_pipe_control_message.cc",
+      "system/data_pipe_producer_dispatcher.cc",
+      "system/dispatcher.cc",
+      "system/handle_table.cc",
+      "system/mapping_table.cc",
+      "system/mapping_table.h",
+      "system/message_pipe_dispatcher.cc",
+      "system/node_channel.cc",
+      "system/node_channel.h",
+      "system/node_controller.cc",
+      "system/platform_handle_dispatcher.cc",
+      "system/request_context.cc",
+      "system/shared_buffer_dispatcher.cc",
+      "system/user_message_impl.cc",
+      "system/watch.cc",
+      "system/watch.h",
+      "system/watcher_dispatcher.cc",
+      "system/watcher_dispatcher.h",
+      "system/watcher_set.cc",
+      "system/watcher_set.h",
+    ]
+
+    if (is_fuchsia) {
+      sources += [
+        "embedder/named_platform_handle_utils_fuchsia.cc",
+        "embedder/platform_channel_pair_fuchsia.cc",
+        "embedder/platform_handle_utils_fuchsia.cc",
+        "system/channel_fuchsia.cc",
+      ]
+    } else if (is_posix) {
+      public += [ "embedder/platform_channel_utils_posix.h" ]
+
+      sources += [
+        "embedder/platform_channel_pair_posix.cc",
+        "embedder/platform_channel_utils_posix.cc",
+        "embedder/platform_handle_utils_posix.cc",
+      ]
+
+      if (!is_nacl || is_nacl_nonsfi) {
+        sources += [
+          "system/broker_posix.cc",
+          "system/channel_posix.cc",
+        ]
+      }
+
+      if (!is_nacl) {
+        sources += [ "embedder/named_platform_handle_utils_posix.cc" ]
+      }
+    }
+
+    if (is_mac && !is_ios) {
+      sources += [
+        "system/mach_port_relay.cc",
+        "system/mach_port_relay.h",
+      ]
+    }
+
+    if (is_nacl && !is_nacl_nonsfi) {
+      sources -= [
+        "embedder/platform_channel_utils_posix.cc",
+        "system/broker_host.cc",
+      ]
+    }
+
+    defines = []
+    if (!invoker.for_mojo_core) {
+      defines += [ "MOJO_SYSTEM_IMPL_IMPLEMENTATION" ]
+    }
+
+    public_deps = [
+      "//base",
+      "//mojo/edk/system/ports",
+      "//mojo/public/c/system:headers",
+    ]
+
+    deps = []
+    if (is_android) {
+      deps += [ "//third_party/ashmem" ]
+    }
     if (!is_nacl) {
-      sources += [ "embedder/named_platform_handle_utils_posix.cc" ]
+      deps += [ "//crypto" ]
+    }
+
+    if (is_win) {
+      cflags = [ "/wd4324" ]  # Structure was padded due to __declspec(align()),
+                              # which is uninteresting.
+    }
+
+    # Use target_os == "chromeos" instead of is_chromeos because we need to
+    # build NaCl targets (i.e. IRT) for ChromeOS the same as the rest of ChromeOS.
+    if (is_android || target_os == "chromeos") {
+      defines += [ "MOJO_EDK_LEGACY_PROTOCOL" ]
+    }
+  }
+}
+
+core_impl_source_set("impl_for_edk") {
+  for_mojo_core = false
+}
+
+if (enable_mojo_core_library) {
+  core_impl_source_set("impl_for_mojo_core") {
+    for_mojo_core = true
+  }
+
+  shared_library("mojo_core") {
+    sources = [
+      "mojo_core.cc",
+    ]
+    deps = [
+      ":impl_for_mojo_core",
+      "//build/config:exe_and_shlib_deps",
+      "//mojo/public/c/system:headers",
+    ]
+    if (!is_component_build) {
+      public_configs = [ "//build/config/gcc:rpath_for_built_shared_libraries" ]
     }
   }
 
-  if (is_nacl && !is_nacl_nonsfi) {
-    sources -= [ "embedder/platform_channel_utils_posix.cc" ]
+  test("mojo_core_unittests") {
+    sources = [
+      "mojo_core_unittest.cc",
+      "run_all_core_unittests.cc",
+    ]
+
+    deps = [
+      ":mojo_core",
+      "//base",
+      "//base/test:test_support",
+      "//mojo/public/c/system",
+      "//testing/gtest",
+    ]
   }
-
-  defines = [ "MOJO_SYSTEM_IMPL_IMPLEMENTATION" ]
-
-  public_deps = [
-    "//base",
-    "//mojo/edk/system",
-    "//mojo/public/c/system:headers",
-  ]
-
-  deps = []
-  if (is_android) {
-    deps += [ "//third_party/ashmem" ]
-  }
-
-  allow_circular_includes_from = [ "//mojo/edk/system" ]
 }
diff --git a/mojo/edk/embedder/embedder.cc b/mojo/edk/embedder/embedder.cc
index 7cf5fb6..1148ac3 100644
--- a/mojo/edk/embedder/embedder.cc
+++ b/mojo/edk/embedder/embedder.cc
@@ -13,11 +13,11 @@
 #include "base/rand_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/task_runner.h"
-#include "mojo/edk/embedder/embedder_internal.h"
 #include "mojo/edk/embedder/entrypoints.h"
 #include "mojo/edk/system/configuration.h"
 #include "mojo/edk/system/core.h"
 #include "mojo/edk/system/node_controller.h"
+#include "mojo/public/c/system/thunks.h"
 
 #if !defined(OS_NACL)
 #include "crypto/random.h"
@@ -26,24 +26,10 @@
 namespace mojo {
 namespace edk {
 
-class Core;
-class PlatformSupport;
-
-namespace internal {
-
-Core* g_core;
-
-Core* GetCore() { return g_core; }
-
-}  // namespace internal
-
 void Init(const Configuration& configuration) {
-  MojoSystemThunks thunks = MakeSystemThunks();
-  size_t expected_size = MojoEmbedderSetSystemThunks(&thunks);
-  DCHECK_EQ(expected_size, sizeof(thunks));
-
   internal::g_configuration = configuration;
-  internal::g_core = new Core;
+  InitializeCore();
+  MojoEmbedderSetSystemThunks(&GetSystemThunks());
 }
 
 void Init() {
@@ -51,7 +37,7 @@
 }
 
 void SetDefaultProcessErrorCallback(const ProcessErrorCallback& callback) {
-  internal::g_core->SetDefaultProcessErrorCallback(callback);
+  Core::Get()->SetDefaultProcessErrorCallback(callback);
 }
 
 std::string GenerateRandomToken() {
@@ -68,14 +54,14 @@
 MojoResult CreatePlatformHandleWrapper(
     ScopedPlatformHandle platform_handle,
     MojoHandle* platform_handle_wrapper_handle) {
-  return internal::g_core->CreatePlatformHandleWrapper(
+  return Core::Get()->CreatePlatformHandleWrapper(
       std::move(platform_handle), platform_handle_wrapper_handle);
 }
 
 MojoResult PassWrappedPlatformHandle(MojoHandle platform_handle_wrapper_handle,
                                      ScopedPlatformHandle* platform_handle) {
-  return internal::g_core->PassWrappedPlatformHandle(
-      platform_handle_wrapper_handle, platform_handle);
+  return Core::Get()->PassWrappedPlatformHandle(platform_handle_wrapper_handle,
+                                                platform_handle);
 }
 
 MojoResult CreateSharedBufferWrapper(
@@ -83,8 +69,8 @@
     size_t num_bytes,
     bool read_only,
     MojoHandle* mojo_wrapper_handle) {
-  return internal::g_core->CreateSharedBufferWrapper(
-      shared_memory_handle, num_bytes, read_only, mojo_wrapper_handle);
+  return Core::Get()->CreateSharedBufferWrapper(shared_memory_handle, num_bytes,
+                                                read_only, mojo_wrapper_handle);
 }
 
 MojoResult PassSharedMemoryHandle(
@@ -92,23 +78,22 @@
     base::SharedMemoryHandle* shared_memory_handle,
     size_t* num_bytes,
     bool* read_only) {
-  return internal::g_core->PassSharedMemoryHandle(
-      mojo_handle, shared_memory_handle, num_bytes, read_only);
+  return Core::Get()->PassSharedMemoryHandle(mojo_handle, shared_memory_handle,
+                                             num_bytes, read_only);
 }
 
 MojoResult SetProperty(MojoPropertyType type, const void* value) {
-  CHECK(internal::g_core);
-  return internal::g_core->SetProperty(type, value);
+  return Core::Get()->SetProperty(type, value);
 }
 
 scoped_refptr<base::TaskRunner> GetIOTaskRunner() {
-  return internal::g_core->GetNodeController()->io_task_runner();
+  return Core::Get()->GetNodeController()->io_task_runner();
 }
 
 #if defined(OS_MACOSX) && !defined(OS_IOS)
 void SetMachPortProvider(base::PortProvider* port_provider) {
   DCHECK(port_provider);
-  internal::g_core->SetMachPortProvider(port_provider);
+  Core::Get()->SetMachPortProvider(port_provider);
 }
 #endif
 
diff --git a/mojo/edk/embedder/embedder_internal.h b/mojo/edk/embedder/embedder_internal.h
deleted file mode 100644
index 7deeca1..0000000
--- a/mojo/edk/embedder/embedder_internal.h
+++ /dev/null
@@ -1,44 +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.
-
-// This header contains internal details for the *implementation* of the
-// embedder API. It should not be included by any public header (nor by users of
-// the embedder API).
-
-#ifndef MOJO_EDK_EMBEDDER_EMBEDDER_INTERNAL_H_
-#define MOJO_EDK_EMBEDDER_EMBEDDER_INTERNAL_H_
-
-#include <stdint.h>
-
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace base {
-class TaskRunner;
-}
-
-namespace mojo {
-
-namespace edk {
-
-class Broker;
-class Core;
-class ProcessDelegate;
-
-namespace internal {
-
-// Instance of |Broker| to use.
-extern Broker* g_broker;
-
-// Instance of |Core| used by the system functions (|Mojo...()|).
-extern MOJO_SYSTEM_IMPL_EXPORT Core* g_core;
-extern base::TaskRunner* g_delegate_thread_task_runner;
-extern ProcessDelegate* g_process_delegate;
-
-}  // namespace internal
-
-}  // namepace edk
-
-}  // namespace mojo
-
-#endif  // MOJO_EDK_EMBEDDER_EMBEDDER_INTERNAL_H_
diff --git a/mojo/edk/embedder/embedder_unittest.cc b/mojo/edk/embedder/embedder_unittest.cc
index 6cfdc82..6f91de2 100644
--- a/mojo/edk/embedder/embedder_unittest.cc
+++ b/mojo/edk/embedder/embedder_unittest.cc
@@ -31,7 +31,6 @@
 #include "mojo/edk/embedder/outgoing_broker_client_invitation.h"
 #include "mojo/edk/embedder/peer_connection.h"
 #include "mojo/edk/embedder/platform_channel_pair.h"
-#include "mojo/edk/embedder/test_embedder.h"
 #include "mojo/edk/system/test_utils.h"
 #include "mojo/edk/test/mojo_test_base.h"
 #include "mojo/public/c/system/core.h"
diff --git a/mojo/edk/embedder/entrypoints.cc b/mojo/edk/embedder/entrypoints.cc
index a2aba1b..d079178 100644
--- a/mojo/edk/embedder/entrypoints.cc
+++ b/mojo/edk/embedder/entrypoints.cc
@@ -6,7 +6,6 @@
 
 #include <stdint.h>
 
-#include "mojo/edk/embedder/embedder_internal.h"
 #include "mojo/edk/system/core.h"
 #include "mojo/public/c/system/buffer.h"
 #include "mojo/public/c/system/data_pipe.h"
@@ -14,11 +13,17 @@
 #include "mojo/public/c/system/message_pipe.h"
 #include "mojo/public/c/system/platform_handle.h"
 
-using mojo::edk::internal::g_core;
+namespace {
 
-// Definitions of the system functions.
+mojo::edk::Core* g_core;
+
 extern "C" {
 
+MojoResult MojoInitializeImpl(const struct MojoInitializeOptions* options) {
+  NOTREACHED() << "Do not call MojoInitialize() as an EDK embedder!";
+  return MOJO_RESULT_OK;
+}
+
 MojoTimeTicks MojoGetTimeTicksNowImpl() {
   return g_core->GetTimeTicksNow();
 }
@@ -193,7 +198,7 @@
 }
 
 MojoResult MojoCreateSharedBufferImpl(
-    const struct MojoCreateSharedBufferOptions* options,
+    const MojoCreateSharedBufferOptions* options,
     uint64_t num_bytes,
     MojoHandle* shared_buffer_handle) {
   return g_core->CreateSharedBuffer(options, num_bytes, shared_buffer_handle);
@@ -201,7 +206,7 @@
 
 MojoResult MojoDuplicateBufferHandleImpl(
     MojoHandle buffer_handle,
-    const struct MojoDuplicateBufferHandleOptions* options,
+    const MojoDuplicateBufferHandleOptions* options,
     MojoHandle* new_buffer_handle) {
   return g_core->DuplicateBufferHandle(buffer_handle, options,
                                        new_buffer_handle);
@@ -219,6 +224,12 @@
   return g_core->UnmapBuffer(buffer);
 }
 
+MojoResult MojoGetBufferInfoImpl(MojoHandle buffer_handle,
+                                 const MojoSharedBufferOptions* options,
+                                 MojoSharedBufferInfo* info) {
+  return g_core->GetBufferInfo(buffer_handle, options, info);
+}
+
 MojoResult MojoWrapPlatformHandleImpl(const MojoPlatformHandle* platform_handle,
                                       MojoHandle* mojo_handle) {
   return g_core->WrapPlatformHandle(platform_handle, mojo_handle);
@@ -261,47 +272,61 @@
 
 }  // extern "C"
 
+MojoSystemThunks g_thunks = {sizeof(MojoSystemThunks),
+                             MojoInitializeImpl,
+                             MojoGetTimeTicksNowImpl,
+                             MojoCloseImpl,
+                             MojoQueryHandleSignalsStateImpl,
+                             MojoCreateMessagePipeImpl,
+                             MojoWriteMessageImpl,
+                             MojoReadMessageImpl,
+                             MojoCreateDataPipeImpl,
+                             MojoWriteDataImpl,
+                             MojoBeginWriteDataImpl,
+                             MojoEndWriteDataImpl,
+                             MojoReadDataImpl,
+                             MojoBeginReadDataImpl,
+                             MojoEndReadDataImpl,
+                             MojoCreateSharedBufferImpl,
+                             MojoDuplicateBufferHandleImpl,
+                             MojoMapBufferImpl,
+                             MojoUnmapBufferImpl,
+                             MojoGetBufferInfoImpl,
+                             MojoCreateTrapImpl,
+                             MojoAddTriggerImpl,
+                             MojoRemoveTriggerImpl,
+                             MojoArmTrapImpl,
+                             MojoFuseMessagePipesImpl,
+                             MojoCreateMessageImpl,
+                             MojoDestroyMessageImpl,
+                             MojoSerializeMessageImpl,
+                             MojoAppendMessageDataImpl,
+                             MojoGetMessageDataImpl,
+                             MojoSetMessageContextImpl,
+                             MojoGetMessageContextImpl,
+                             MojoWrapPlatformHandleImpl,
+                             MojoUnwrapPlatformHandleImpl,
+                             MojoWrapPlatformSharedBufferHandleImpl,
+                             MojoUnwrapPlatformSharedBufferHandleImpl,
+                             MojoNotifyBadMessageImpl,
+                             MojoGetPropertyImpl};
+
+}  // namespace
+
 namespace mojo {
 namespace edk {
 
-MojoSystemThunks MakeSystemThunks() {
-  MojoSystemThunks system_thunks = {sizeof(MojoSystemThunks),
-                                    MojoGetTimeTicksNowImpl,
-                                    MojoCloseImpl,
-                                    MojoQueryHandleSignalsStateImpl,
-                                    MojoCreateMessagePipeImpl,
-                                    MojoWriteMessageImpl,
-                                    MojoReadMessageImpl,
-                                    MojoCreateDataPipeImpl,
-                                    MojoWriteDataImpl,
-                                    MojoBeginWriteDataImpl,
-                                    MojoEndWriteDataImpl,
-                                    MojoReadDataImpl,
-                                    MojoBeginReadDataImpl,
-                                    MojoEndReadDataImpl,
-                                    MojoCreateSharedBufferImpl,
-                                    MojoDuplicateBufferHandleImpl,
-                                    MojoMapBufferImpl,
-                                    MojoUnmapBufferImpl,
-                                    MojoCreateTrapImpl,
-                                    MojoAddTriggerImpl,
-                                    MojoRemoveTriggerImpl,
-                                    MojoArmTrapImpl,
-                                    MojoFuseMessagePipesImpl,
-                                    MojoCreateMessageImpl,
-                                    MojoDestroyMessageImpl,
-                                    MojoSerializeMessageImpl,
-                                    MojoAppendMessageDataImpl,
-                                    MojoGetMessageDataImpl,
-                                    MojoSetMessageContextImpl,
-                                    MojoGetMessageContextImpl,
-                                    MojoWrapPlatformHandleImpl,
-                                    MojoUnwrapPlatformHandleImpl,
-                                    MojoWrapPlatformSharedBufferHandleImpl,
-                                    MojoUnwrapPlatformSharedBufferHandleImpl,
-                                    MojoNotifyBadMessageImpl,
-                                    MojoGetPropertyImpl};
-  return system_thunks;
+// static
+Core* Core::Get() {
+  return g_core;
+}
+
+void InitializeCore() {
+  g_core = new Core;
+}
+
+const MojoSystemThunks& GetSystemThunks() {
+  return g_thunks;
 }
 
 }  // namespace edk
diff --git a/mojo/edk/embedder/entrypoints.h b/mojo/edk/embedder/entrypoints.h
index 8e448c1..63299a6 100644
--- a/mojo/edk/embedder/entrypoints.h
+++ b/mojo/edk/embedder/entrypoints.h
@@ -11,10 +11,13 @@
 namespace mojo {
 namespace edk {
 
-// Creates a MojoSystemThunks struct populated with the EDK's implementation of
+// Initializes the global Core object.
+MOJO_SYSTEM_IMPL_EXPORT void InitializeCore();
+
+// Returns a MojoSystemThunks struct populated with the EDK's implementation of
 // each function. This may be used by embedders to populate thunks for
 // application loading.
-MOJO_SYSTEM_IMPL_EXPORT MojoSystemThunks MakeSystemThunks();
+MOJO_SYSTEM_IMPL_EXPORT const MojoSystemThunks& GetSystemThunks();
 
 }  // namespace edk
 }  // namespace mojo
diff --git a/mojo/edk/embedder/incoming_broker_client_invitation.cc b/mojo/edk/embedder/incoming_broker_client_invitation.cc
index 4bb7374..8c0b693 100644
--- a/mojo/edk/embedder/incoming_broker_client_invitation.cc
+++ b/mojo/edk/embedder/incoming_broker_client_invitation.cc
@@ -7,7 +7,6 @@
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
-#include "mojo/edk/embedder/embedder_internal.h"
 #include "mojo/edk/embedder/platform_channel_pair.h"
 #include "mojo/edk/embedder/scoped_platform_handle.h"
 #include "mojo/edk/system/core.h"
@@ -38,14 +37,13 @@
 
 ScopedMessagePipeHandle IncomingBrokerClientInvitation::ExtractMessagePipe(
     const std::string& name) {
-  return ScopedMessagePipeHandle(MessagePipeHandle(
-      internal::g_core->ExtractMessagePipeFromInvitation(name)));
+  return ScopedMessagePipeHandle(
+      MessagePipeHandle(Core::Get()->ExtractMessagePipeFromInvitation(name)));
 }
 
 IncomingBrokerClientInvitation::IncomingBrokerClientInvitation(
     ConnectionParams params) {
-  DCHECK(internal::g_core);
-  internal::g_core->AcceptBrokerClientInvitation(std::move(params));
+  Core::Get()->AcceptBrokerClientInvitation(std::move(params));
 }
 
 }  // namespace edk
diff --git a/mojo/edk/embedder/outgoing_broker_client_invitation.cc b/mojo/edk/embedder/outgoing_broker_client_invitation.cc
index f66a33e..6c9ae1e 100644
--- a/mojo/edk/embedder/outgoing_broker_client_invitation.cc
+++ b/mojo/edk/embedder/outgoing_broker_client_invitation.cc
@@ -5,7 +5,6 @@
 #include "mojo/edk/embedder/outgoing_broker_client_invitation.h"
 
 #include "base/logging.h"
-#include "mojo/edk/embedder/embedder_internal.h"
 #include "mojo/edk/system/core.h"
 #include "mojo/edk/system/node_controller.h"
 #include "mojo/edk/system/ports/port_ref.h"
@@ -14,14 +13,12 @@
 namespace mojo {
 namespace edk {
 
-OutgoingBrokerClientInvitation::OutgoingBrokerClientInvitation() {
-  DCHECK(internal::g_core);
-}
+OutgoingBrokerClientInvitation::OutgoingBrokerClientInvitation() = default;
 
 OutgoingBrokerClientInvitation::~OutgoingBrokerClientInvitation() {
   RequestContext request_context;
   for (auto& entry : attached_ports_)
-    internal::g_core->GetNodeController()->ClosePort(entry.second);
+    Core::Get()->GetNodeController()->ClosePort(entry.second);
 }
 
 ScopedMessagePipeHandle OutgoingBrokerClientInvitation::AttachMessagePipe(
@@ -29,7 +26,7 @@
   DCHECK(!sent_);
   ports::PortRef port;
   ScopedMessagePipeHandle pipe = ScopedMessagePipeHandle(
-      MessagePipeHandle(internal::g_core->CreatePartialMessagePipe(&port)));
+      MessagePipeHandle(Core::Get()->CreatePartialMessagePipe(&port)));
   attached_ports_.emplace_back(name, port);
   return pipe;
 }
@@ -42,8 +39,8 @@
   // a single entry.
   for (auto it = attached_ports_.begin(); it != attached_ports_.end(); ++it) {
     if (it->first == name) {
-      ScopedMessagePipeHandle pipe = ScopedMessagePipeHandle(MessagePipeHandle(
-          internal::g_core->CreatePartialMessagePipe(it->second)));
+      ScopedMessagePipeHandle pipe = ScopedMessagePipeHandle(
+          MessagePipeHandle(Core::Get()->CreatePartialMessagePipe(it->second)));
       attached_ports_.erase(it);
       return pipe;
     }
@@ -59,8 +56,8 @@
     const ProcessErrorCallback& error_callback) {
   DCHECK(!sent_);
   sent_ = true;
-  internal::g_core->SendBrokerClientInvitation(
-      target_process, std::move(params), attached_ports_, error_callback);
+  Core::Get()->SendBrokerClientInvitation(target_process, std::move(params),
+                                          attached_ports_, error_callback);
   attached_ports_.clear();
 }
 
diff --git a/mojo/edk/embedder/peer_connection.cc b/mojo/edk/embedder/peer_connection.cc
index a4139b5..8534411 100644
--- a/mojo/edk/embedder/peer_connection.cc
+++ b/mojo/edk/embedder/peer_connection.cc
@@ -4,7 +4,6 @@
 
 #include "mojo/edk/embedder/peer_connection.h"
 
-#include "mojo/edk/embedder/embedder_internal.h"
 #include "mojo/edk/system/core.h"
 
 namespace mojo {
@@ -14,7 +13,7 @@
 
 PeerConnection::~PeerConnection() {
   if (is_connected_)
-    internal::g_core->ClosePeerConnection(connection_id_);
+    Core::Get()->ClosePeerConnection(connection_id_);
 }
 
 ScopedMessagePipeHandle PeerConnection::Connect(ConnectionParams params) {
@@ -22,10 +21,9 @@
   is_connected_ = true;
 
   ports::PortRef peer_port;
-  auto pipe = ScopedMessagePipeHandle(MessagePipeHandle(
-      internal::g_core->CreatePartialMessagePipe(&peer_port)));
-  connection_id_ =
-      internal::g_core->ConnectToPeer(std::move(params), peer_port);
+  auto pipe = ScopedMessagePipeHandle(
+      MessagePipeHandle(Core::Get()->CreatePartialMessagePipe(&peer_port)));
+  connection_id_ = Core::Get()->ConnectToPeer(std::move(params), peer_port);
   return pipe;
 }
 
diff --git a/mojo/edk/embedder/scoped_ipc_support.cc b/mojo/edk/embedder/scoped_ipc_support.cc
index 7d05f55..a023172 100644
--- a/mojo/edk/embedder/scoped_ipc_support.cc
+++ b/mojo/edk/embedder/scoped_ipc_support.cc
@@ -8,7 +8,6 @@
 #include "base/bind_helpers.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/threading/thread_restrictions.h"
-#include "mojo/edk/embedder/embedder_internal.h"
 #include "mojo/edk/system/core.h"
 
 namespace mojo {
@@ -17,8 +16,7 @@
 namespace {
 
 void ShutdownIPCSupport(const base::Closure& callback) {
-  DCHECK(internal::g_core);
-  internal::g_core->RequestShutdown(callback);
+  Core::Get()->RequestShutdown(callback);
 }
 
 }  // namespace
@@ -26,8 +24,7 @@
 ScopedIPCSupport::ScopedIPCSupport(
     scoped_refptr<base::TaskRunner> io_thread_task_runner,
     ShutdownPolicy shutdown_policy) : shutdown_policy_(shutdown_policy) {
-  DCHECK(internal::g_core);
-  internal::g_core->SetIOTaskRunner(io_thread_task_runner);
+  Core::Get()->SetIOTaskRunner(io_thread_task_runner);
 }
 
 ScopedIPCSupport::~ScopedIPCSupport() {
diff --git a/mojo/edk/embedder/test_embedder.cc b/mojo/edk/embedder/test_embedder.cc
deleted file mode 100644
index 9658010..0000000
--- a/mojo/edk/embedder/test_embedder.cc
+++ /dev/null
@@ -1,46 +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.
-
-#include "mojo/edk/embedder/test_embedder.h"
-
-#include <memory>
-
-#include "base/logging.h"
-#include "mojo/edk/embedder/embedder.h"
-#include "mojo/edk/embedder/embedder_internal.h"
-#include "mojo/edk/system/core.h"
-#include "mojo/edk/system/handle_table.h"
-
-namespace mojo {
-
-namespace edk {
-namespace internal {
-
-bool ShutdownCheckNoLeaks(Core* core) {
-  std::vector<MojoHandle> leaked_handles;
-  core->GetActiveHandlesForTest(&leaked_handles);
-  if (leaked_handles.empty())
-    return true;
-  for (auto handle : leaked_handles)
-    LOG(ERROR) << "Mojo embedder shutdown: Leaking handle " << handle;
-  return false;
-}
-
-}  // namespace internal
-
-namespace test {
-
-bool Shutdown() {
-  CHECK(internal::g_core);
-  bool rv = internal::ShutdownCheckNoLeaks(internal::g_core);
-  delete internal::g_core;
-  internal::g_core = nullptr;
-
-  return rv;
-}
-
-}  // namespace test
-}  // namespace edk
-
-}  // namespace mojo
diff --git a/mojo/edk/embedder/test_embedder.h b/mojo/edk/embedder/test_embedder.h
deleted file mode 100644
index c64ba17..0000000
--- a/mojo/edk/embedder/test_embedder.h
+++ /dev/null
@@ -1,28 +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.
-
-#ifndef MOJO_EDK_EMBEDDER_TEST_EMBEDDER_H_
-#define MOJO_EDK_EMBEDDER_TEST_EMBEDDER_H_
-
-#include "mojo/edk/system/system_impl_export.h"
-
-namespace mojo {
-namespace edk {
-namespace test {
-
-// This shuts down the global, singleton instance. (Note: "Real" embedders are
-// not expected to ever shut down this instance. This |Shutdown()| function will
-// do more work to ensure that tests don't leak, etc.) Returns true if there
-// were no problems, false if there were leaks -- i.e., handles still open -- or
-// any other problems.
-//
-// Note: It is up to the caller to ensure that there are not outstanding
-// callbacks from |CreateChannel()| before calling this.
-MOJO_SYSTEM_IMPL_EXPORT bool Shutdown();
-
-}  // namespace test
-}  // namespace edk
-}  // namespace mojo
-
-#endif  // MOJO_EDK_EMBEDDER_TEST_EMBEDDER_H_
diff --git a/mojo/edk/mojo_core.cc b/mojo/edk/mojo_core.cc
new file mode 100644
index 0000000..b0c6527
--- /dev/null
+++ b/mojo/edk/mojo_core.cc
@@ -0,0 +1,42 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/time/time.h"
+#include "mojo/edk/embedder/entrypoints.h"
+#include "mojo/edk/system/core.h"
+#include "mojo/public/c/system/core.h"
+#include "mojo/public/c/system/thunks.h"
+
+extern "C" {
+
+namespace {
+
+MojoResult InitializeImpl(const struct MojoInitializeOptions* options) {
+  mojo::edk::InitializeCore();
+  return MOJO_RESULT_OK;
+}
+
+MojoSystemThunks g_thunks = {0};
+
+}  // namespace
+
+#if defined(WIN32)
+#define EXPORT_FROM_MOJO_CORE __declspec(dllexport)
+#else
+#define EXPORT_FROM_MOJO_CORE __attribute__((visibility("default")))
+#endif
+
+EXPORT_FROM_MOJO_CORE void MojoGetSystemThunks(MojoSystemThunks* thunks) {
+  if (!g_thunks.size) {
+    g_thunks = mojo::edk::GetSystemThunks();
+    g_thunks.Initialize = InitializeImpl;
+  }
+
+  // Since this is the first version of the library, no valid system API
+  // implementation can request fewer thunks than we have available.
+  CHECK_GE(thunks->size, g_thunks.size);
+  memcpy(thunks, &g_thunks, g_thunks.size);
+}
+
+}  // extern "C"
diff --git a/mojo/edk/mojo_core_library.gni b/mojo/edk/mojo_core_library.gni
new file mode 100644
index 0000000..bfd5885
--- /dev/null
+++ b/mojo/edk/mojo_core_library.gni
@@ -0,0 +1,9 @@
+# Copyright 2018 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.
+
+declare_args() {
+  # TODO(https://crbug.com/822034): Enable this by default on Chrome OS and
+  # Linux.
+  enable_mojo_core_library = false
+}
diff --git a/mojo/edk/mojo_core_unittest.cc b/mojo/edk/mojo_core_unittest.cc
new file mode 100644
index 0000000..ddd24d23
--- /dev/null
+++ b/mojo/edk/mojo_core_unittest.cc
@@ -0,0 +1,41 @@
+// Copyright 2018 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 "mojo/public/c/system/core.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+TEST(MojoCoreTest, SanityCheck) {
+  // Exercises some APIs against the mojo_core library and expects them to work
+  // as intended.
+
+  MojoHandle a, b;
+  EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &a, &b));
+
+  MojoMessageHandle m;
+  EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessage(nullptr, &m));
+  EXPECT_EQ(MOJO_RESULT_OK,
+            MojoSetMessageContext(m, 42, nullptr, nullptr, nullptr));
+  EXPECT_EQ(MOJO_RESULT_OK,
+            MojoWriteMessage(a, m, MOJO_WRITE_MESSAGE_FLAG_NONE));
+  m = MOJO_MESSAGE_HANDLE_INVALID;
+
+  MojoHandleSignalsState state;
+  EXPECT_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(b, &state));
+  EXPECT_TRUE(state.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE);
+
+  EXPECT_EQ(MOJO_RESULT_OK,
+            MojoReadMessage(b, &m, MOJO_READ_MESSAGE_FLAG_NONE));
+
+  uintptr_t context = 0;
+  EXPECT_EQ(MOJO_RESULT_OK, MojoGetMessageContext(m, nullptr, &context));
+  EXPECT_EQ(42u, context);
+
+  EXPECT_EQ(MOJO_RESULT_OK, MojoDestroyMessage(m));
+  EXPECT_EQ(MOJO_RESULT_OK, MojoClose(b));
+  EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a));
+}
+
+}  // namespace
diff --git a/mojo/edk/run_all_core_unittests.cc b/mojo/edk/run_all_core_unittests.cc
new file mode 100644
index 0000000..92dcafc9
--- /dev/null
+++ b/mojo/edk/run_all_core_unittests.cc
@@ -0,0 +1,18 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/bind.h"
+#include "base/test/launcher/unit_test_launcher.h"
+#include "base/test/test_suite.h"
+#include "build/build_config.h"
+#include "mojo/public/c/system/core.h"
+
+int main(int argc, char** argv) {
+  base::TestSuite test_suite(argc, argv);
+
+  CHECK_EQ(MOJO_RESULT_OK, MojoInitialize(nullptr));
+  return base::LaunchUnitTests(
+      argc, argv,
+      base::BindOnce(&base::TestSuite::Run, base::Unretained(&test_suite)));
+}
diff --git a/mojo/edk/system/BUILD.gn b/mojo/edk/system/BUILD.gn
index ad03c3ad..6387dcd 100644
--- a/mojo/edk/system/BUILD.gn
+++ b/mojo/edk/system/BUILD.gn
@@ -10,111 +10,6 @@
   import("//build/config/android/rules.gni")
 }
 
-source_set("system") {
-  # All sources in this target should really just be private sources in
-  # "//mojo/edk:core". Make sure that's the only target than can see this one.
-  visibility = [ "//mojo/edk:core" ]
-
-  sources = [
-    "atomic_flag.h",
-    "broker.h",
-    "broker_host.cc",
-    "broker_host.h",
-    "broker_win.cc",
-    "channel.cc",
-    "channel.h",
-    "channel_win.cc",
-    "configuration.cc",
-    "configuration.h",
-    "core.cc",
-    "core.h",
-    "data_pipe_consumer_dispatcher.cc",
-    "data_pipe_consumer_dispatcher.h",
-    "data_pipe_control_message.cc",
-    "data_pipe_control_message.h",
-    "data_pipe_producer_dispatcher.cc",
-    "data_pipe_producer_dispatcher.h",
-    "dispatcher.cc",
-    "dispatcher.h",
-    "handle_signals_state.h",
-    "handle_table.cc",
-    "handle_table.h",
-    "mapping_table.cc",
-    "mapping_table.h",
-    "message_pipe_dispatcher.cc",
-    "message_pipe_dispatcher.h",
-    "node_channel.cc",
-    "node_channel.h",
-    "node_controller.cc",
-    "node_controller.h",
-    "options_validation.h",
-    "platform_handle_dispatcher.cc",
-    "platform_handle_dispatcher.h",
-    "request_context.cc",
-    "request_context.h",
-    "shared_buffer_dispatcher.cc",
-    "shared_buffer_dispatcher.h",
-    "user_message_impl.cc",
-    "user_message_impl.h",
-    "watch.cc",
-    "watch.h",
-    "watcher_dispatcher.cc",
-    "watcher_dispatcher.h",
-    "watcher_set.cc",
-    "watcher_set.h",
-  ]
-
-  if (is_mac && !is_ios) {
-    sources += [
-      "mach_port_relay.cc",
-      "mach_port_relay.h",
-    ]
-  }
-
-  if (is_fuchsia) {
-    sources += [ "channel_fuchsia.cc" ]
-  } else if (is_posix) {
-    sources += [
-      "broker_posix.cc",
-      "channel_posix.cc",
-    ]
-  }
-
-  if (is_nacl && !is_nacl_nonsfi) {
-    sources -= [
-      "broker_host.cc",
-      "broker_posix.cc",
-      "channel_posix.cc",
-    ]
-  }
-
-  defines = [ "MOJO_SYSTEM_IMPL_IMPLEMENTATION" ]
-
-  public_deps = [
-    "//mojo/edk/system/ports",
-    "//mojo/public/c/system:headers",
-  ]
-
-  deps = [
-    "//base",
-  ]
-
-  if (!is_nacl) {
-    deps += [ "//crypto" ]
-  }
-
-  if (is_win) {
-    cflags = [ "/wd4324" ]  # Structure was padded due to __declspec(align()),
-                            # which is uninteresting.
-  }
-
-  # Use target_os == "chromeos" instead of is_chromeos because we need to
-  # build NaCl targets (i.e. IRT) for ChromeOS the same as the rest of ChromeOS.
-  if (is_android || target_os == "chromeos") {
-    defines += [ "MOJO_EDK_LEGACY_PROTOCOL" ]
-  }
-}
-
 source_set("test_utils") {
   testonly = true
 
diff --git a/mojo/edk/system/broker_posix.cc b/mojo/edk/system/broker_posix.cc
index fcca490..88695e9 100644
--- a/mojo/edk/system/broker_posix.cc
+++ b/mojo/edk/system/broker_posix.cc
@@ -10,7 +10,6 @@
 #include <utility>
 
 #include "base/logging.h"
-#include "mojo/edk/embedder/embedder_internal.h"
 #include "mojo/edk/embedder/platform_channel_utils_posix.h"
 #include "mojo/edk/embedder/platform_handle_utils.h"
 #include "mojo/edk/embedder/platform_shared_buffer.h"
diff --git a/mojo/edk/system/channel.cc b/mojo/edk/system/channel.cc
index eacdf5c..41ff3ee 100644
--- a/mojo/edk/system/channel.cc
+++ b/mojo/edk/system/channel.cc
@@ -16,7 +16,6 @@
 #include "base/numerics/safe_math.h"
 #include "base/process/process_handle.h"
 #include "build/build_config.h"
-#include "mojo/edk/embedder/embedder_internal.h"
 #include "mojo/edk/embedder/platform_handle.h"
 #include "mojo/edk/system/configuration.h"
 #include "mojo/edk/system/core.h"
diff --git a/mojo/edk/system/core.cc b/mojo/edk/system/core.cc
index f5bcbcc..bf2f95c 100644
--- a/mojo/edk/system/core.cc
+++ b/mojo/edk/system/core.cc
@@ -20,7 +20,6 @@
 #include "base/time/time.h"
 #include "base/trace_event/memory_dump_manager.h"
 #include "build/build_config.h"
-#include "mojo/edk/embedder/embedder_internal.h"
 #include "mojo/edk/embedder/platform_shared_buffer.h"
 #include "mojo/edk/embedder/process_error_callback.h"
 #include "mojo/edk/system/channel.h"
@@ -1009,6 +1008,21 @@
   return result;
 }
 
+MojoResult Core::GetBufferInfo(MojoHandle buffer_handle,
+                               const MojoSharedBufferOptions* options,
+                               MojoSharedBufferInfo* info) {
+  if (options && options->struct_size != sizeof(MojoSharedBufferOptions))
+    return MOJO_RESULT_INVALID_ARGUMENT;
+  if (!info || info->struct_size != sizeof(MojoSharedBufferInfo))
+    return MOJO_RESULT_INVALID_ARGUMENT;
+
+  scoped_refptr<Dispatcher> dispatcher(GetDispatcher(buffer_handle));
+  if (!dispatcher)
+    return MOJO_RESULT_INVALID_ARGUMENT;
+
+  return dispatcher->GetBufferInfo(info);
+}
+
 MojoResult Core::WrapPlatformHandle(const MojoPlatformHandle* platform_handle,
                                     MojoHandle* mojo_handle) {
   ScopedPlatformHandle handle;
diff --git a/mojo/edk/system/core.h b/mojo/edk/system/core.h
index 6ac8cf6b..478971e2 100644
--- a/mojo/edk/system/core.h
+++ b/mojo/edk/system/core.h
@@ -43,6 +43,8 @@
   Core();
   virtual ~Core();
 
+  static Core* Get();
+
   // Called exactly once, shortly after construction, and before any other
   // methods are called on this object.
   void SetIOTaskRunner(scoped_refptr<base::TaskRunner> io_task_runner);
@@ -280,6 +282,9 @@
                        void** buffer,
                        MojoMapBufferFlags flags);
   MojoResult UnmapBuffer(void* buffer);
+  MojoResult GetBufferInfo(MojoHandle buffer_handle,
+                           const MojoSharedBufferOptions* options,
+                           MojoSharedBufferInfo* info);
 
   // These methods correspond to the API functions defined in
   // "mojo/public/c/system/platform_handle.h".
diff --git a/mojo/edk/system/core_test_base.cc b/mojo/edk/system/core_test_base.cc
index 9f8637c4..ff7b7c3a 100644
--- a/mojo/edk/system/core_test_base.cc
+++ b/mojo/edk/system/core_test_base.cc
@@ -12,7 +12,6 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "mojo/edk/embedder/embedder_internal.h"
 #include "mojo/edk/system/configuration.h"
 #include "mojo/edk/system/core.h"
 #include "mojo/edk/system/dispatcher.h"
@@ -121,7 +120,7 @@
 }
 
 Core* CoreTestBase::core() {
-  return mojo::edk::internal::g_core;
+  return Core::Get();
 }
 
 // CoreTestBase_MockHandleInfo -------------------------------------------------
diff --git a/mojo/edk/system/core_test_base.h b/mojo/edk/system/core_test_base.h
index 3d156e32..84718be 100644
--- a/mojo/edk/system/core_test_base.h
+++ b/mojo/edk/system/core_test_base.h
@@ -9,7 +9,6 @@
 
 #include "base/macros.h"
 #include "base/synchronization/lock.h"
-#include "mojo/edk/embedder/embedder_internal.h"
 #include "mojo/edk/system/test_utils.h"
 #include "mojo/public/c/system/types.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/mojo/edk/system/core_unittest.cc b/mojo/edk/system/core_unittest.cc
index 013a427..7fe7ba0 100644
--- a/mojo/edk/system/core_unittest.cc
+++ b/mojo/edk/system/core_unittest.cc
@@ -9,7 +9,6 @@
 #include <limits>
 
 #include "base/bind.h"
-#include "mojo/edk/embedder/embedder_internal.h"
 #include "mojo/edk/system/core_test_base.h"
 #include "mojo/edk/system/test_utils.h"
 #include "mojo/public/cpp/system/wait.h"
diff --git a/mojo/edk/system/data_pipe_consumer_dispatcher.cc b/mojo/edk/system/data_pipe_consumer_dispatcher.cc
index e1ecc85..f5c0c7e 100644
--- a/mojo/edk/system/data_pipe_consumer_dispatcher.cc
+++ b/mojo/edk/system/data_pipe_consumer_dispatcher.cc
@@ -15,7 +15,6 @@
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
 #include "base/message_loop/message_loop.h"
-#include "mojo/edk/embedder/embedder_internal.h"
 #include "mojo/edk/embedder/platform_shared_buffer.h"
 #include "mojo/edk/system/core.h"
 #include "mojo/edk/system/data_pipe_control_message.h"
@@ -374,7 +373,7 @@
     return nullptr;
   }
 
-  NodeController* node_controller = internal::g_core->GetNodeController();
+  NodeController* node_controller = Core::Get()->GetNodeController();
   ports::PortRef port;
   if (node_controller->node()->GetPort(ports[0], &port) != ports::OK)
     return nullptr;
diff --git a/mojo/edk/system/data_pipe_producer_dispatcher.cc b/mojo/edk/system/data_pipe_producer_dispatcher.cc
index de0b768..987e4d61 100644
--- a/mojo/edk/system/data_pipe_producer_dispatcher.cc
+++ b/mojo/edk/system/data_pipe_producer_dispatcher.cc
@@ -13,7 +13,6 @@
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
 #include "base/message_loop/message_loop.h"
-#include "mojo/edk/embedder/embedder_internal.h"
 #include "mojo/edk/embedder/platform_shared_buffer.h"
 #include "mojo/edk/system/configuration.h"
 #include "mojo/edk/system/core.h"
@@ -337,7 +336,7 @@
     return nullptr;
   }
 
-  NodeController* node_controller = internal::g_core->GetNodeController();
+  NodeController* node_controller = Core::Get()->GetNodeController();
   ports::PortRef port;
   if (node_controller->node()->GetPort(ports[0], &port) != ports::OK)
     return nullptr;
diff --git a/mojo/edk/system/dispatcher.cc b/mojo/edk/system/dispatcher.cc
index 43959288..e736276 100644
--- a/mojo/edk/system/dispatcher.cc
+++ b/mojo/edk/system/dispatcher.cc
@@ -66,6 +66,10 @@
   return MOJO_RESULT_INVALID_ARGUMENT;
 }
 
+MojoResult Dispatcher::GetBufferInfo(MojoSharedBufferInfo* info) {
+  return MOJO_RESULT_INVALID_ARGUMENT;
+}
+
 MojoResult Dispatcher::ReadData(void* elements,
                                 uint32_t* num_bytes,
                                 MojoReadDataFlags flags) {
diff --git a/mojo/edk/system/dispatcher.h b/mojo/edk/system/dispatcher.h
index ec3d019..3e13c1b 100644
--- a/mojo/edk/system/dispatcher.h
+++ b/mojo/edk/system/dispatcher.h
@@ -106,6 +106,8 @@
       MojoMapBufferFlags flags,
       std::unique_ptr<PlatformSharedBufferMapping>* mapping);
 
+  virtual MojoResult GetBufferInfo(MojoSharedBufferInfo* info);
+
   ///////////// Data pipe consumer API /////////////
 
   virtual MojoResult ReadData(void* elements,
diff --git a/mojo/edk/system/mapping_table.h b/mojo/edk/system/mapping_table.h
index 81cc56bb..a9498201 100644
--- a/mojo/edk/system/mapping_table.h
+++ b/mojo/edk/system/mapping_table.h
@@ -21,12 +21,6 @@
 class Core;
 class PlatformSharedBufferMapping;
 
-// Test-only function (defined/used in embedder/test_embedder.cc). Declared here
-// so it can be friended.
-namespace internal {
-bool ShutdownCheckNoLeaks(Core*);
-}
-
 // This class provides the (global) table of memory mappings (owned by |Core|),
 // which maps mapping base addresses to |PlatformSharedBufferMapping|s.
 //
@@ -44,8 +38,6 @@
       std::unique_ptr<PlatformSharedBufferMapping>* mapping);
 
  private:
-  friend bool internal::ShutdownCheckNoLeaks(Core*);
-
   using AddressToMappingMap =
       base::hash_map<void*, PlatformSharedBufferMapping*>;
   AddressToMappingMap address_to_mapping_map_;
diff --git a/mojo/edk/system/message_pipe_dispatcher.cc b/mojo/edk/system/message_pipe_dispatcher.cc
index eb15227..a095ab4 100644
--- a/mojo/edk/system/message_pipe_dispatcher.cc
+++ b/mojo/edk/system/message_pipe_dispatcher.cc
@@ -10,7 +10,6 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "mojo/edk/embedder/embedder_internal.h"
 #include "mojo/edk/system/core.h"
 #include "mojo/edk/system/node_controller.h"
 #include "mojo/edk/system/ports/event.h"
@@ -274,7 +273,7 @@
 
   const SerializedState* state = static_cast<const SerializedState*>(data);
 
-  ports::Node* node = internal::g_core->GetNodeController()->node();
+  ports::Node* node = Core::Get()->GetNodeController()->node();
   ports::PortRef port;
   if (node->GetPort(ports[0], &port) != ports::OK)
     return nullptr;
@@ -283,7 +282,7 @@
   if (node->GetStatus(port, &status) != ports::OK)
     return nullptr;
 
-  return new MessagePipeDispatcher(internal::g_core->GetNodeController(), port,
+  return new MessagePipeDispatcher(Core::Get()->GetNodeController(), port,
                                    state->pipe_id, state->endpoint);
 }
 
diff --git a/mojo/edk/system/multiprocess_message_pipe_unittest.cc b/mojo/edk/system/multiprocess_message_pipe_unittest.cc
index 8a6a3c3..c9a00de 100644
--- a/mojo/edk/system/multiprocess_message_pipe_unittest.cc
+++ b/mojo/edk/system/multiprocess_message_pipe_unittest.cc
@@ -338,6 +338,11 @@
     MojoHandle shared_buffer;
     ASSERT_EQ(MOJO_RESULT_OK,
               MojoCreateSharedBuffer(&options, 100, &shared_buffer));
+    MojoSharedBufferInfo buffer_info;
+    buffer_info.struct_size = sizeof(buffer_info);
+    ASSERT_EQ(MOJO_RESULT_OK,
+              MojoGetBufferInfo(shared_buffer, nullptr, &buffer_info));
+    EXPECT_EQ(100U, buffer_info.size);
 
     // Send the shared buffer.
     const std::string go1("go 1");
@@ -346,6 +351,10 @@
     ASSERT_EQ(MOJO_RESULT_OK,
               MojoDuplicateBufferHandle(shared_buffer, nullptr,
                                         &duplicated_shared_buffer));
+    buffer_info.size = 0;
+    ASSERT_EQ(MOJO_RESULT_OK,
+              MojoGetBufferInfo(shared_buffer, nullptr, &buffer_info));
+    EXPECT_EQ(100U, buffer_info.size);
     MojoHandle handles[1];
     handles[0] = duplicated_shared_buffer;
     ASSERT_EQ(MOJO_RESULT_OK,
diff --git a/mojo/edk/system/node_controller.cc b/mojo/edk/system/node_controller.cc
index b014703..b8638a5 100644
--- a/mojo/edk/system/node_controller.cc
+++ b/mojo/edk/system/node_controller.cc
@@ -19,7 +19,6 @@
 #include "base/rand_util.h"
 #include "base/time/time.h"
 #include "base/timer/elapsed_timer.h"
-#include "mojo/edk/embedder/embedder_internal.h"
 #include "mojo/edk/embedder/named_platform_channel_pair.h"
 #include "mojo/edk/embedder/named_platform_handle.h"
 #include "mojo/edk/embedder/platform_channel_pair.h"
diff --git a/mojo/edk/system/shared_buffer_dispatcher.cc b/mojo/edk/system/shared_buffer_dispatcher.cc
index f65fd88..ca9a1a8 100644
--- a/mojo/edk/system/shared_buffer_dispatcher.cc
+++ b/mojo/edk/system/shared_buffer_dispatcher.cc
@@ -12,7 +12,6 @@
 #include <utility>
 
 #include "base/logging.h"
-#include "mojo/edk/embedder/embedder_internal.h"
 #include "mojo/edk/system/configuration.h"
 #include "mojo/edk/system/node_controller.h"
 #include "mojo/edk/system/options_validation.h"
@@ -240,6 +239,15 @@
   return MOJO_RESULT_OK;
 }
 
+MojoResult SharedBufferDispatcher::GetBufferInfo(MojoSharedBufferInfo* info) {
+  if (!info)
+    return MOJO_RESULT_INVALID_ARGUMENT;
+
+  base::AutoLock lock(lock_);
+  info->size = shared_buffer_->GetNumBytes();
+  return MOJO_RESULT_OK;
+}
+
 void SharedBufferDispatcher::StartSerialize(uint32_t* num_bytes,
                                             uint32_t* num_ports,
                                             uint32_t* num_platform_handles) {
diff --git a/mojo/edk/system/shared_buffer_dispatcher.h b/mojo/edk/system/shared_buffer_dispatcher.h
index 351a7d1..fcaf5c1 100644
--- a/mojo/edk/system/shared_buffer_dispatcher.h
+++ b/mojo/edk/system/shared_buffer_dispatcher.h
@@ -76,6 +76,7 @@
       uint64_t num_bytes,
       MojoMapBufferFlags flags,
       std::unique_ptr<PlatformSharedBufferMapping>* mapping) override;
+  MojoResult GetBufferInfo(MojoSharedBufferInfo* info) override;
   void StartSerialize(uint32_t* num_bytes,
                       uint32_t* num_ports,
                       uint32_t* num_platform_handles) override;
diff --git a/mojo/edk/system/user_message_impl.cc b/mojo/edk/system/user_message_impl.cc
index da361229..c80ed7a2 100644
--- a/mojo/edk/system/user_message_impl.cc
+++ b/mojo/edk/system/user_message_impl.cc
@@ -11,7 +11,6 @@
 #include "base/metrics/histogram_macros_local.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/numerics/safe_math.h"
-#include "mojo/edk/embedder/embedder_internal.h"
 #include "mojo/edk/system/core.h"
 #include "mojo/edk/system/node_channel.h"
 #include "mojo/edk/system/node_controller.h"
@@ -273,15 +272,15 @@
     if (result == MOJO_RESULT_OK) {
       for (auto handle : handles) {
         if (handle != MOJO_HANDLE_INVALID)
-          internal::g_core->Close(handle);
+          Core::Get()->Close(handle);
       }
     }
 
     if (!pending_handle_attachments_.empty()) {
-      internal::g_core->ReleaseDispatchersForTransit(
-          pending_handle_attachments_, false);
+      Core::Get()->ReleaseDispatchersForTransit(pending_handle_attachments_,
+                                                false);
       for (const auto& dispatcher : pending_handle_attachments_)
-        internal::g_core->Close(dispatcher.local_handle);
+        Core::Get()->Close(dispatcher.local_handle);
     }
   }
 }
@@ -405,7 +404,7 @@
 
   std::vector<Dispatcher::DispatcherInTransit> dispatchers;
   if (num_handles > 0) {
-    MojoResult acquire_result = internal::g_core->AcquireDispatchersForTransit(
+    MojoResult acquire_result = Core::Get()->AcquireDispatchersForTransit(
         handles, num_handles, &dispatchers);
     if (acquire_result != MOJO_RESULT_OK)
       return acquire_result;
@@ -420,8 +419,8 @@
         dispatchers.data(), num_handles, &channel_message, &header_,
         &header_size_, &user_payload_);
     if (num_handles > 0) {
-      internal::g_core->ReleaseDispatchersForTransit(dispatchers,
-                                                     rv == MOJO_RESULT_OK);
+      Core::Get()->ReleaseDispatchersForTransit(dispatchers,
+                                                rv == MOJO_RESULT_OK);
     }
     if (rv != MOJO_RESULT_OK)
       return MOJO_RESULT_ABORTED;
@@ -471,8 +470,8 @@
         message_event_, user_payload_size_, user_payload_size_,
         pending_handle_attachments_.data(), pending_handle_attachments_.size(),
         &channel_message_, &header_, &header_size_, &user_payload_);
-    internal::g_core->ReleaseDispatchersForTransit(pending_handle_attachments_,
-                                                   true);
+    Core::Get()->ReleaseDispatchersForTransit(pending_handle_attachments_,
+                                              true);
     pending_handle_attachments_.clear();
   }
 
@@ -580,7 +579,7 @@
     platform_handle_index = next_platform_handle_index.ValueOrDie();
   }
 
-  if (!internal::g_core->AddDispatchersFromTransit(dispatchers, handles))
+  if (!Core::Get()->AddDispatchersFromTransit(dispatchers, handles))
     return MOJO_RESULT_ABORTED;
 
   return MOJO_RESULT_OK;
diff --git a/mojo/public/c/system/BUILD.gn b/mojo/public/c/system/BUILD.gn
index 4d8605b1..f684dd193 100644
--- a/mojo/public/c/system/BUILD.gn
+++ b/mojo/public/c/system/BUILD.gn
@@ -2,6 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//mojo/edk/mojo_core_library.gni")
+
 component("system") {
   output_name = "mojo_public_system"
 
@@ -14,6 +16,15 @@
   public_deps = [
     ":headers",
   ]
+
+  deps = [
+    "//base",
+  ]
+
+  if (enable_mojo_core_library) {
+    defines += [ "ENABLE_MOJO_CORE_LIBRARY" ]
+    public_deps += [ "//mojo/edk:mojo_core" ]
+  }
 }
 
 source_set("headers") {
diff --git a/mojo/public/c/system/buffer.h b/mojo/public/c/system/buffer.h
index 09f6d285..0e086fc 100644
--- a/mojo/public/c/system/buffer.h
+++ b/mojo/public/c/system/buffer.h
@@ -43,6 +43,35 @@
 MOJO_STATIC_ASSERT(sizeof(MojoCreateSharedBufferOptions) == 8,
                    "MojoCreateSharedBufferOptions has wrong size");
 
+// Flags passed to |MojoGetBufferInfo()| via |MojoSharedBufferOptions|.
+typedef uint32_t MojoSharedBufferOptionsFlags;
+
+#ifdef __cplusplus
+const MojoSharedBufferOptionsFlags MOJO_SHARED_BUFFER_OPTIONS_FLAG_NONE = 0;
+#else
+#define MOJO_SHARED_BUFFER_OPTIONS_FLAG_NONE ((MojoSharedBufferOptionsFlags)0)
+#endif
+
+struct MOJO_ALIGNAS(8) MojoSharedBufferOptions {
+  // The size of this structure, used for versioning.
+  uint32_t struct_size;
+
+  // See |MojoSharedBufferOptionsFlags|.
+  MojoSharedBufferOptionsFlags flags;
+};
+MOJO_STATIC_ASSERT(sizeof(MojoSharedBufferOptions) == 8,
+                   "MojoSharedBufferOptions has wrong size");
+
+struct MOJO_ALIGNAS(8) MojoSharedBufferInfo {
+  // The size of this structure, used for versioning.
+  uint32_t struct_size;
+
+  // The size of the shared buffer.
+  uint64_t size;
+};
+MOJO_STATIC_ASSERT(sizeof(MojoSharedBufferInfo) == 16,
+                   "MojoSharedBufferInfo has wrong size");
+
 // |MojoDuplicateBufferHandleOptions|: Used to specify parameters in duplicating
 // access to a shared buffer to |MojoDuplicateBufferHandle()|.
 //
@@ -181,6 +210,21 @@
 //       result of |MojoMapBuffer()| or has already been unmapped).
 MOJO_SYSTEM_EXPORT MojoResult MojoUnmapBuffer(void* buffer);  // In.
 
+// Retrieve information about |buffer_handle| into |info|. |options| is optional
+// and reserved for future use.
+//
+// Returns:
+//   |MOJO_RESULT_OK| on success.
+//   |MOJO_RESULT_INVALID_ARGUMENT| if |buffer_handle| is invalid or if |info|
+//       is NULL.
+//
+// On success, |info->size| will be set to the size of the buffer. On failure it
+// is not modified.
+MOJO_SYSTEM_EXPORT MojoResult
+MojoGetBufferInfo(MojoHandle buffer_handle,
+                  const struct MojoSharedBufferOptions* options,  // Optional.
+                  struct MojoSharedBufferInfo* info);             // Out.
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif
diff --git a/mojo/public/c/system/functions.h b/mojo/public/c/system/functions.h
index 5ce0dab..30bfb3a 100644
--- a/mojo/public/c/system/functions.h
+++ b/mojo/public/c/system/functions.h
@@ -26,6 +26,22 @@
 // operation's success/failure. E.g., a separate |flags| parameter may control
 // whether a given "in/out" parameter is used for input, output, or both.)
 
+// Initializes Mojo in the calling application.
+//
+// With the exception of EDK embedders, applications using Mojo APIs must call
+// this function before any others.
+//
+// |options| may be null.
+//
+// Returns:
+//   |MOJO_RESULT_OK| if Mojo intiailization was successful.
+//   |MOJO_RESULT_INVALID_ARGUMENT| if |options| was null or invalid.
+//   |MOJO_RESULT_FAILED_PRECONDITION| if |MojoInitialize()| was already called
+//       once or if the application already explicitly initialized a Mojo EDK
+//       environment.
+MOJO_SYSTEM_EXPORT MojoResult
+MojoInitialize(const struct MojoInitializeOptions* options);
+
 // Returns the time, in microseconds, since some undefined point in the past.
 // The values are only meaningful relative to other values that were obtained
 // from the same device without an intervening system restart. Such values are
diff --git a/mojo/public/c/system/set_thunks_for_app.cc b/mojo/public/c/system/set_thunks_for_app.cc
deleted file mode 100644
index 335cc02..0000000
--- a/mojo/public/c/system/set_thunks_for_app.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "mojo/public/c/system/thunks.h"
-
-extern "C" {
-
-#if defined(WIN32)
-#define THUNKS_EXPORT __declspec(dllexport)
-#else
-#define THUNKS_EXPORT __attribute__((visibility("default")))
-#endif
-
-THUNKS_EXPORT size_t MojoSetSystemThunks(
-    const MojoSystemThunks* system_thunks) {
-  return MojoEmbedderSetSystemThunks(system_thunks);
-}
-
-}  // extern "C"
diff --git a/mojo/public/c/system/tests/core_api_unittest.cc b/mojo/public/c/system/tests/core_api_unittest.cc
index ff24b5d..10c049d 100644
--- a/mojo/public/c/system/tests/core_api_unittest.cc
+++ b/mojo/public/c/system/tests/core_api_unittest.cc
@@ -264,23 +264,30 @@
 }
 
 TEST(CoreAPITest, BasicSharedBuffer) {
-  MojoHandle h0, h1;
-  void* pointer;
+  MojoSharedBufferInfo buffer_info;
+  buffer_info.struct_size = sizeof(buffer_info);
+  MojoHandle h0 = MOJO_HANDLE_INVALID;
+  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+            MojoGetBufferInfo(h0, nullptr, &buffer_info));
 
   // Create a shared buffer (|h0|).
-  h0 = MOJO_HANDLE_INVALID;
   EXPECT_EQ(MOJO_RESULT_OK, MojoCreateSharedBuffer(nullptr, 100, &h0));
   EXPECT_NE(h0, MOJO_HANDLE_INVALID);
 
+  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+            MojoGetBufferInfo(h0, nullptr, nullptr));
+  ASSERT_EQ(MOJO_RESULT_OK, MojoGetBufferInfo(h0, nullptr, &buffer_info));
+  EXPECT_EQ(100U, buffer_info.size);
+
   // Map everything.
-  pointer = nullptr;
+  void* pointer = nullptr;
   EXPECT_EQ(MOJO_RESULT_OK,
             MojoMapBuffer(h0, 0, 100, &pointer, MOJO_MAP_BUFFER_FLAG_NONE));
   ASSERT_TRUE(pointer);
   static_cast<char*>(pointer)[50] = 'x';
 
   // Duplicate |h0| to |h1|.
-  h1 = MOJO_HANDLE_INVALID;
+  MojoHandle h1 = MOJO_HANDLE_INVALID;
   EXPECT_EQ(MOJO_RESULT_OK, MojoDuplicateBufferHandle(h0, nullptr, &h1));
   EXPECT_NE(h1, MOJO_HANDLE_INVALID);
 
@@ -306,6 +313,10 @@
   // Unmap it.
   EXPECT_EQ(MOJO_RESULT_OK, MojoUnmapBuffer(pointer));
 
+  buffer_info.size = 0;
+  ASSERT_EQ(MOJO_RESULT_OK, MojoGetBufferInfo(h1, nullptr, &buffer_info));
+  EXPECT_EQ(100U, buffer_info.size);
+
   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h1));
 }
 
diff --git a/mojo/public/c/system/thunks.cc b/mojo/public/c/system/thunks.cc
index b3a0564..7abad1d1 100644
--- a/mojo/public/c/system/thunks.cc
+++ b/mojo/public/c/system/thunks.cc
@@ -4,35 +4,65 @@
 
 #include "mojo/public/c/system/thunks.h"
 
-#include <assert.h>
-#include <stddef.h>
-#include <stdint.h>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+
+#include "base/logging.h"
+#include "mojo/public/c/system/core.h"
+
+namespace {
+
+MojoSystemThunks g_thunks = {0};
+
+}  // namespace
 
 extern "C" {
 
-static MojoSystemThunks g_thunks = {0};
+#if defined(ENABLE_MOJO_CORE_LIBRARY)
+
+// If the system API sources are built with ENABLE_MOJO_CORE_LIBRARY, we assume
+// that an imported |MojoGetSystemThunks()| definition is available. This is
+// exported to us by the mojo_core shared library.
+#if defined(WIN32)
+#define IMPORT_FROM_MOJO_CORE __declspec(dllimport)
+#else
+#define IMPORT_FROM_MOJO_CORE
+#endif
+
+IMPORT_FROM_MOJO_CORE void MojoGetSystemThunks(MojoSystemThunks* thunks);
+
+#endif  // defined(ENABLE_MOJO_CORE_LIBRARY)
+
+MojoResult MojoInitialize(const struct MojoInitializeOptions* options) {
+#if defined(ENABLE_MOJO_CORE_LIBRARY)
+  g_thunks.size = sizeof(g_thunks);
+  MojoGetSystemThunks(&g_thunks);
+#else
+  CHECK(g_thunks.size) << "You must either build with ENABLE_MOJO_CORE_LIBRARY "
+                       << "or manually initialize the EDK before you can use "
+                       << "the Mojo system API.";
+#endif
+  return g_thunks.Initialize(options);
+}
 
 MojoTimeTicks MojoGetTimeTicksNow() {
-  assert(g_thunks.GetTimeTicksNow);
   return g_thunks.GetTimeTicksNow();
 }
 
 MojoResult MojoClose(MojoHandle handle) {
-  assert(g_thunks.Close);
   return g_thunks.Close(handle);
 }
 
 MojoResult MojoQueryHandleSignalsState(
     MojoHandle handle,
     struct MojoHandleSignalsState* signals_state) {
-  assert(g_thunks.QueryHandleSignalsState);
   return g_thunks.QueryHandleSignalsState(handle, signals_state);
 }
 
 MojoResult MojoCreateMessagePipe(const MojoCreateMessagePipeOptions* options,
                                  MojoHandle* message_pipe_handle0,
                                  MojoHandle* message_pipe_handle1) {
-  assert(g_thunks.CreateMessagePipe);
   return g_thunks.CreateMessagePipe(options, message_pipe_handle0,
                                     message_pipe_handle1);
 }
@@ -40,7 +70,6 @@
 MojoResult MojoWriteMessage(MojoHandle message_pipe_handle,
                             MojoMessageHandle message_handle,
                             MojoWriteMessageFlags flags) {
-  assert(g_thunks.WriteMessage);
   return g_thunks.WriteMessage(message_pipe_handle, message_handle, flags);
 }
 
@@ -54,7 +83,6 @@
 MojoResult MojoCreateDataPipe(const MojoCreateDataPipeOptions* options,
                               MojoHandle* data_pipe_producer_handle,
                               MojoHandle* data_pipe_consumer_handle) {
-  assert(g_thunks.CreateDataPipe);
   return g_thunks.CreateDataPipe(options, data_pipe_producer_handle,
                                  data_pipe_consumer_handle);
 }
@@ -63,7 +91,6 @@
                          const void* elements,
                          uint32_t* num_elements,
                          MojoWriteDataFlags flags) {
-  assert(g_thunks.WriteData);
   return g_thunks.WriteData(data_pipe_producer_handle, elements, num_elements,
                             flags);
 }
@@ -72,14 +99,12 @@
                               void** buffer,
                               uint32_t* buffer_num_elements,
                               MojoWriteDataFlags flags) {
-  assert(g_thunks.BeginWriteData);
   return g_thunks.BeginWriteData(data_pipe_producer_handle, buffer,
                                  buffer_num_elements, flags);
 }
 
 MojoResult MojoEndWriteData(MojoHandle data_pipe_producer_handle,
                             uint32_t num_elements_written) {
-  assert(g_thunks.EndWriteData);
   return g_thunks.EndWriteData(data_pipe_producer_handle, num_elements_written);
 }
 
@@ -87,7 +112,6 @@
                         void* elements,
                         uint32_t* num_elements,
                         MojoReadDataFlags flags) {
-  assert(g_thunks.ReadData);
   return g_thunks.ReadData(data_pipe_consumer_handle, elements, num_elements,
                            flags);
 }
@@ -96,14 +120,12 @@
                              const void** buffer,
                              uint32_t* buffer_num_elements,
                              MojoReadDataFlags flags) {
-  assert(g_thunks.BeginReadData);
   return g_thunks.BeginReadData(data_pipe_consumer_handle, buffer,
                                 buffer_num_elements, flags);
 }
 
 MojoResult MojoEndReadData(MojoHandle data_pipe_consumer_handle,
                            uint32_t num_elements_read) {
-  assert(g_thunks.EndReadData);
   return g_thunks.EndReadData(data_pipe_consumer_handle, num_elements_read);
 }
 
@@ -111,7 +133,6 @@
     const struct MojoCreateSharedBufferOptions* options,
     uint64_t num_bytes,
     MojoHandle* shared_buffer_handle) {
-  assert(g_thunks.CreateSharedBuffer);
   return g_thunks.CreateSharedBuffer(options, num_bytes, shared_buffer_handle);
 }
 
@@ -119,7 +140,6 @@
     MojoHandle buffer_handle,
     const struct MojoDuplicateBufferHandleOptions* options,
     MojoHandle* new_buffer_handle) {
-  assert(g_thunks.DuplicateBufferHandle);
   return g_thunks.DuplicateBufferHandle(buffer_handle, options,
                                         new_buffer_handle);
 }
@@ -129,19 +149,23 @@
                          uint64_t num_bytes,
                          void** buffer,
                          MojoMapBufferFlags flags) {
-  assert(g_thunks.MapBuffer);
   return g_thunks.MapBuffer(buffer_handle, offset, num_bytes, buffer, flags);
 }
 
 MojoResult MojoUnmapBuffer(void* buffer) {
-  assert(g_thunks.UnmapBuffer);
   return g_thunks.UnmapBuffer(buffer);
 }
 
+MojoResult MojoGetBufferInfo(MojoHandle buffer_handle,
+                             const struct MojoSharedBufferOptions* options,
+                             struct MojoSharedBufferInfo* info) {
+  assert(g_thunks.GetBufferInfo);
+  return g_thunks.GetBufferInfo(buffer_handle, options, info);
+}
+
 MojoResult MojoCreateTrap(MojoTrapEventHandler handler,
                           const MojoCreateTrapOptions* options,
                           MojoHandle* trap_handle) {
-  assert(g_thunks.CreateTrap);
   return g_thunks.CreateTrap(handler, options, trap_handle);
 }
 
@@ -151,7 +175,6 @@
                           MojoTriggerCondition condition,
                           uintptr_t context,
                           const MojoAddTriggerOptions* options) {
-  assert(g_thunks.AddTrigger);
   return g_thunks.AddTrigger(trap_handle, handle, signals, condition, context,
                              options);
 }
@@ -159,7 +182,6 @@
 MojoResult MojoRemoveTrigger(MojoHandle trap_handle,
                              uintptr_t context,
                              const MojoRemoveTriggerOptions* options) {
-  assert(g_thunks.RemoveTrigger);
   return g_thunks.RemoveTrigger(trap_handle, context, options);
 }
 
@@ -169,30 +191,25 @@
                        uintptr_t* ready_triggers,
                        MojoResult* ready_results,
                        MojoHandleSignalsState* ready_signals_states) {
-  assert(g_thunks.ArmTrap);
   return g_thunks.ArmTrap(trap_handle, options, num_ready_triggers,
                           ready_triggers, ready_results, ready_signals_states);
 }
 
 MojoResult MojoFuseMessagePipes(MojoHandle handle0, MojoHandle handle1) {
-  assert(g_thunks.FuseMessagePipes);
   return g_thunks.FuseMessagePipes(handle0, handle1);
 }
 
 MojoResult MojoCreateMessage(const MojoCreateMessageOptions* options,
                              MojoMessageHandle* message) {
-  assert(g_thunks.CreateMessage);
   return g_thunks.CreateMessage(options, message);
 }
 
 MojoResult MojoDestroyMessage(MojoMessageHandle message) {
-  assert(g_thunks.DestroyMessage);
   return g_thunks.DestroyMessage(message);
 }
 
 MojoResult MojoSerializeMessage(MojoMessageHandle message,
                                 const MojoSerializeMessageOptions* options) {
-  assert(g_thunks.SerializeMessage);
   return g_thunks.SerializeMessage(message, options);
 }
 
@@ -203,7 +220,6 @@
                                  const MojoAppendMessageDataOptions* options,
                                  void** buffer,
                                  uint32_t* buffer_size) {
-  assert(g_thunks.AppendMessageData);
   return g_thunks.AppendMessageData(message, payload_size, handles, num_handles,
                                     options, buffer, buffer_size);
 }
@@ -214,7 +230,6 @@
                               uint32_t* num_bytes,
                               MojoHandle* handles,
                               uint32_t* num_handles) {
-  assert(g_thunks.GetMessageData);
   return g_thunks.GetMessageData(message, options, buffer, num_bytes, handles,
                                  num_handles);
 }
@@ -224,7 +239,6 @@
                                  MojoMessageContextSerializer serializer,
                                  MojoMessageContextDestructor destructor,
                                  const MojoSetMessageContextOptions* options) {
-  assert(g_thunks.SetMessageContext);
   return g_thunks.SetMessageContext(message, context, serializer, destructor,
                                     options);
 }
@@ -232,21 +246,18 @@
 MojoResult MojoGetMessageContext(MojoMessageHandle message,
                                  const MojoGetMessageContextOptions* options,
                                  uintptr_t* context) {
-  assert(g_thunks.GetMessageContext);
   return g_thunks.GetMessageContext(message, options, context);
 }
 
 MojoResult MojoWrapPlatformHandle(
     const struct MojoPlatformHandle* platform_handle,
     MojoHandle* mojo_handle) {
-  assert(g_thunks.WrapPlatformHandle);
   return g_thunks.WrapPlatformHandle(platform_handle, mojo_handle);
 }
 
 MojoResult MojoUnwrapPlatformHandle(
     MojoHandle mojo_handle,
     struct MojoPlatformHandle* platform_handle) {
-  assert(g_thunks.UnwrapPlatformHandle);
   return g_thunks.UnwrapPlatformHandle(mojo_handle, platform_handle);
 }
 
@@ -256,7 +267,6 @@
     const struct MojoSharedBufferGuid* guid,
     MojoPlatformSharedBufferHandleFlags flags,
     MojoHandle* mojo_handle) {
-  assert(g_thunks.WrapPlatformSharedBufferHandle);
   return g_thunks.WrapPlatformSharedBufferHandle(platform_handle, num_bytes,
                                                  guid, flags, mojo_handle);
 }
@@ -267,7 +277,6 @@
     size_t* num_bytes,
     struct MojoSharedBufferGuid* guid,
     MojoPlatformSharedBufferHandleFlags* flags) {
-  assert(g_thunks.UnwrapPlatformSharedBufferHandle);
   return g_thunks.UnwrapPlatformSharedBufferHandle(mojo_handle, platform_handle,
                                                    num_bytes, guid, flags);
 }
@@ -275,19 +284,25 @@
 MojoResult MojoNotifyBadMessage(MojoMessageHandle message,
                                 const char* error,
                                 size_t error_num_bytes) {
-  assert(g_thunks.NotifyBadMessage);
   return g_thunks.NotifyBadMessage(message, error, error_num_bytes);
 }
 
 MojoResult MojoGetProperty(MojoPropertyType type, void* value) {
-  assert(g_thunks.GetProperty);
   return g_thunks.GetProperty(type, value);
 }
 
 }  // extern "C"
 
-size_t MojoEmbedderSetSystemThunks(const MojoSystemThunks* system_thunks) {
-  if (system_thunks->size >= sizeof(g_thunks))
-    g_thunks = *system_thunks;
-  return sizeof(g_thunks);
+void MojoEmbedderSetSystemThunks(const MojoSystemThunks* thunks) {
+  // Assume embedders will always use matching versions of the EDK and public
+  // APIs.
+  DCHECK_EQ(thunks->size, sizeof(g_thunks));
+
+  // This should only have to check that the |g_thunks.size| is zero, but we
+  // have multiple EDK initializations in some test suites still. For now we
+  // allow double calls as long as they're the same thunks as before.
+  DCHECK(g_thunks.size == 0 || !memcmp(&g_thunks, thunks, sizeof(g_thunks)))
+      << "Cannot set embedder thunks after Mojo API calls have been made.";
+
+  g_thunks = *thunks;
 }
diff --git a/mojo/public/c/system/thunks.h b/mojo/public/c/system/thunks.h
index 0564ea60..968e1c1 100644
--- a/mojo/public/c/system/thunks.h
+++ b/mojo/public/c/system/thunks.h
@@ -20,6 +20,7 @@
 #pragma pack(push, 8)
 struct MojoSystemThunks {
   size_t size;  // Should be set to sizeof(MojoSystemThunks).
+  MojoResult (*Initialize)(const struct MojoInitializeOptions* options);
   MojoTimeTicks (*GetTimeTicksNow)();
   MojoResult (*Close)(MojoHandle handle);
   MojoResult (*QueryHandleSignalsState)(
@@ -72,6 +73,9 @@
                           void** buffer,
                           MojoMapBufferFlags flags);
   MojoResult (*UnmapBuffer)(void* buffer);
+  MojoResult (*GetBufferInfo)(MojoHandle buffer_handle,
+                              const struct MojoSharedBufferOptions* options,
+                              struct MojoSharedBufferInfo* info);
   MojoResult (*CreateTrap)(MojoTrapEventHandler handler,
                            const struct MojoCreateTrapOptions* options,
                            MojoHandle* trap_handle);
@@ -146,19 +150,9 @@
 };
 #pragma pack(pop)
 
-// Use this type for the function found by dynamically discovering it in
-// a DSO linked with mojo_system. For example:
-// MojoSetSystemThunksFn mojo_set_system_thunks_fn =
-//     reinterpret_cast<MojoSetSystemThunksFn>(app_library.GetFunctionPointer(
-//         "MojoSetSystemThunks"));
-// The expected size of |system_thunks| is returned.
-// The contents of |system_thunks| are copied.
-typedef size_t (*MojoSetSystemThunksFn)(
-    const struct MojoSystemThunks* system_thunks);
-
 // A function for setting up the embedder's own system thunks. This should only
 // be called by Mojo embedder code.
-MOJO_SYSTEM_EXPORT size_t
-MojoEmbedderSetSystemThunks(const struct MojoSystemThunks* system_thunks);
+MOJO_SYSTEM_EXPORT void MojoEmbedderSetSystemThunks(
+    const struct MojoSystemThunks* system_thunks);
 
 #endif  // MOJO_PUBLIC_C_SYSTEM_THUNKS_H_
diff --git a/mojo/public/c/system/types.h b/mojo/public/c/system/types.h
index 220f90f1..2a6cdbc 100644
--- a/mojo/public/c/system/types.h
+++ b/mojo/public/c/system/types.h
@@ -136,6 +136,21 @@
 #define MOJO_DEADLINE_INDEFINITE ((MojoDeadline)-1)
 #endif
 
+// Flags passed to |MojoInitialize()| via |MojoInitializeOptions|.
+typedef uint32_t MojoInitializeFlags;
+
+// No flags.
+#define MOJO_INITIALIZE_FLAG_NONE ((MojoInitializeFlags)0)
+
+// Options passed to |MojoInitialize()|.
+struct MOJO_ALIGNAS(8) MojoInitializeOptions {
+  // The size of this structure, used for versioning.
+  uint32_t struct_size;
+
+  // See |MojoInitializeFlags|.
+  MojoInitializeFlags flags;
+};
+
 // |MojoHandleSignals|: Used to specify signals that can be watched for on a
 // handle (and which can be triggered), e.g., the ability to read or write to
 // the handle.
diff --git a/mojo/public/cpp/base/BUILD.gn b/mojo/public/cpp/base/BUILD.gn
index 07daf07..8a41d23 100644
--- a/mojo/public/cpp/base/BUILD.gn
+++ b/mojo/public/cpp/base/BUILD.gn
@@ -54,7 +54,9 @@
     "ref_counted_memory_unittest.cc",
     "string16_unittest.cc",
     "text_direction_unittest.cc",
+    "thread_priority_unittest.cc",
     "time_unittest.cc",
+    "unguessable_token_unittest.cc",
     "values_unittest.cc",
   ]
 
diff --git a/mojo/public/cpp/base/text_direction_unittest.cc b/mojo/public/cpp/base/text_direction_unittest.cc
index 696beb0..02085fc 100644
--- a/mojo/public/cpp/base/text_direction_unittest.cc
+++ b/mojo/public/cpp/base/text_direction_unittest.cc
@@ -9,9 +9,9 @@
 namespace text_direction_unittest {
 
 TEST(TextDirectionTest, TextDirection) {
-  base::i18n::TextDirection kTestDirections[] = {base::i18n::LEFT_TO_RIGHT,
-                                                 base::i18n::RIGHT_TO_LEFT,
-                                                 base::i18n::UNKNOWN_DIRECTION};
+  static constexpr base::i18n::TextDirection kTestDirections[] = {
+      base::i18n::LEFT_TO_RIGHT, base::i18n::RIGHT_TO_LEFT,
+      base::i18n::UNKNOWN_DIRECTION};
 
   for (auto direction_in : kTestDirections) {
     base::i18n::TextDirection direction_out;
diff --git a/mojo/public/cpp/base/thread_priority.typemap b/mojo/public/cpp/base/thread_priority.typemap
new file mode 100644
index 0000000..319818f
--- /dev/null
+++ b/mojo/public/cpp/base/thread_priority.typemap
@@ -0,0 +1,13 @@
+# 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.
+
+mojom = "//mojo/public/mojom/base/thread_priority.mojom"
+public_headers = [ "//base/threading/platform_thread.h" ]
+traits_headers = [ "//mojo/public/cpp/base/thread_priority_mojom_traits.h" ]
+sources = [
+  "//mojo/public/cpp/base/thread_priority_mojom_traits.cc",
+  "//mojo/public/cpp/base/thread_priority_mojom_traits.h",
+]
+
+type_mappings = [ "mojo_base.mojom.ThreadPriority=base::ThreadPriority" ]
diff --git a/mojo/public/cpp/base/thread_priority_mojom_traits.cc b/mojo/public/cpp/base/thread_priority_mojom_traits.cc
new file mode 100644
index 0000000..f8b88cd
--- /dev/null
+++ b/mojo/public/cpp/base/thread_priority_mojom_traits.cc
@@ -0,0 +1,48 @@
+// Copyright 2018 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 "mojo/public/cpp/base/thread_priority_mojom_traits.h"
+
+namespace mojo {
+
+// static
+mojo_base::mojom::ThreadPriority
+EnumTraits<mojo_base::mojom::ThreadPriority, base::ThreadPriority>::ToMojom(
+    base::ThreadPriority thread_priority) {
+  switch (thread_priority) {
+    case base::ThreadPriority::BACKGROUND:
+      return mojo_base::mojom::ThreadPriority::BACKGROUND;
+    case base::ThreadPriority::NORMAL:
+      return mojo_base::mojom::ThreadPriority::NORMAL;
+    case base::ThreadPriority::DISPLAY:
+      return mojo_base::mojom::ThreadPriority::DISPLAY;
+    case base::ThreadPriority::REALTIME_AUDIO:
+      return mojo_base::mojom::ThreadPriority::REALTIME_AUDIO;
+  }
+  NOTREACHED();
+  return mojo_base::mojom::ThreadPriority::BACKGROUND;
+}
+
+// static
+bool EnumTraits<mojo_base::mojom::ThreadPriority, base::ThreadPriority>::
+    FromMojom(mojo_base::mojom::ThreadPriority input,
+              base::ThreadPriority* out) {
+  switch (input) {
+    case mojo_base::mojom::ThreadPriority::BACKGROUND:
+      *out = base::ThreadPriority::BACKGROUND;
+      return true;
+    case mojo_base::mojom::ThreadPriority::NORMAL:
+      *out = base::ThreadPriority::NORMAL;
+      return true;
+    case mojo_base::mojom::ThreadPriority::DISPLAY:
+      *out = base::ThreadPriority::DISPLAY;
+      return true;
+    case mojo_base::mojom::ThreadPriority::REALTIME_AUDIO:
+      *out = base::ThreadPriority::REALTIME_AUDIO;
+      return true;
+  }
+  return false;
+}
+
+}  // namespace mojo
\ No newline at end of file
diff --git a/mojo/public/cpp/base/thread_priority_mojom_traits.h b/mojo/public/cpp/base/thread_priority_mojom_traits.h
new file mode 100644
index 0000000..7f58e03
--- /dev/null
+++ b/mojo/public/cpp/base/thread_priority_mojom_traits.h
@@ -0,0 +1,24 @@
+// Copyright 2018 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 MOJO_PUBLIC_CPP_BASE_THREAD_PRIORITY_MOJOM_TRAITS_H_
+#define MOJO_PUBLIC_CPP_BASE_THREAD_PRIORITY_MOJOM_TRAITS_H_
+
+#include "base/component_export.h"
+#include "mojo/public/mojom/base/thread_priority.mojom-shared.h"
+
+namespace mojo {
+
+template <>
+struct COMPONENT_EXPORT(MOJO_BASE_MOJOM)
+    EnumTraits<mojo_base::mojom::ThreadPriority, base::ThreadPriority> {
+  static mojo_base::mojom::ThreadPriority ToMojom(
+      base::ThreadPriority thread_priority);
+  static bool FromMojom(mojo_base::mojom::ThreadPriority input,
+                        base::ThreadPriority* out);
+};
+
+}  // namespace mojo
+
+#endif  // MOJO_PUBLIC_CPP_BASE_THREAD_PRIORITY_MOJOM_TRAITS_H_
\ No newline at end of file
diff --git a/mojo/public/cpp/base/thread_priority_unittest.cc b/mojo/public/cpp/base/thread_priority_unittest.cc
new file mode 100644
index 0000000..115d757
--- /dev/null
+++ b/mojo/public/cpp/base/thread_priority_unittest.cc
@@ -0,0 +1,31 @@
+// Copyright 2018 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 "mojo/public/cpp/base/thread_priority_mojom_traits.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo_base {
+namespace thread_priority_unittest {
+
+TEST(ThreadPriorityTest, ThreadPriority) {
+  static constexpr base::ThreadPriority kTestPriorities[] = {
+      base::ThreadPriority::BACKGROUND, base::ThreadPriority::NORMAL,
+      base::ThreadPriority::DISPLAY, base::ThreadPriority::REALTIME_AUDIO};
+
+  for (auto priority_in : kTestPriorities) {
+    base::ThreadPriority priority_out;
+
+    mojo_base::mojom::ThreadPriority serialized_priority =
+        mojo::EnumTraits<mojo_base::mojom::ThreadPriority,
+                         base::ThreadPriority>::ToMojom(priority_in);
+    ASSERT_TRUE(
+        (mojo::EnumTraits<mojo_base::mojom::ThreadPriority,
+                          base::ThreadPriority>::FromMojom(serialized_priority,
+                                                           &priority_out)));
+    EXPECT_EQ(priority_in, priority_out);
+  }
+}
+
+}  // namespace thread_priority_unittest
+}  // namespace mojo_base
\ No newline at end of file
diff --git a/mojo/public/cpp/base/typemaps.gni b/mojo/public/cpp/base/typemaps.gni
index 87127baa..f1d3adc 100644
--- a/mojo/public/cpp/base/typemaps.gni
+++ b/mojo/public/cpp/base/typemaps.gni
@@ -13,6 +13,8 @@
   "//mojo/public/cpp/base/string16.typemap",
   "//mojo/public/cpp/base/logfont_win.typemap",
   "//mojo/public/cpp/base/text_direction.typemap",
+  "//mojo/public/cpp/base/thread_priority.typemap",
   "//mojo/public/cpp/base/time.typemap",
+  "//mojo/public/cpp/base/unguessable_token.typemap",
   "//mojo/public/cpp/base/values.typemap",
 ]
diff --git a/mojo/public/cpp/base/unguessable_token.typemap b/mojo/public/cpp/base/unguessable_token.typemap
new file mode 100644
index 0000000..056f146
--- /dev/null
+++ b/mojo/public/cpp/base/unguessable_token.typemap
@@ -0,0 +1,13 @@
+# 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.
+
+mojom = "//mojo/public/mojom/base/unguessable_token.mojom"
+public_headers = [ "//base/unguessable_token.h" ]
+traits_headers = [ "//mojo/public/cpp/base/unguessable_token_mojom_traits.h" ]
+sources = [
+  "//mojo/public/cpp/base/unguessable_token_mojom_traits.cc",
+  "//mojo/public/cpp/base/unguessable_token_mojom_traits.h",
+]
+
+type_mappings = [ "mojo_base.mojom.UnguessableToken=base::UnguessableToken" ]
diff --git a/mojo/public/cpp/base/unguessable_token_mojom_traits.cc b/mojo/public/cpp/base/unguessable_token_mojom_traits.cc
new file mode 100644
index 0000000..153d0a4
--- /dev/null
+++ b/mojo/public/cpp/base/unguessable_token_mojom_traits.cc
@@ -0,0 +1,25 @@
+// Copyright 2018 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 "mojo/public/cpp/base/unguessable_token_mojom_traits.h"
+
+namespace mojo {
+
+// static
+bool StructTraits<mojo_base::mojom::UnguessableTokenDataView,
+                  base::UnguessableToken>::
+    Read(mojo_base::mojom::UnguessableTokenDataView data,
+         base::UnguessableToken* out) {
+  uint64_t high = data.high();
+  uint64_t low = data.low();
+
+  // Receiving a zeroed UnguessableToken is a security issue.
+  if (high == 0 && low == 0)
+    return false;
+
+  *out = base::UnguessableToken::Deserialize(high, low);
+  return true;
+}
+
+}  // namespace mojo
\ No newline at end of file
diff --git a/mojo/public/cpp/base/unguessable_token_mojom_traits.h b/mojo/public/cpp/base/unguessable_token_mojom_traits.h
new file mode 100644
index 0000000..b23bd70cc
--- /dev/null
+++ b/mojo/public/cpp/base/unguessable_token_mojom_traits.h
@@ -0,0 +1,37 @@
+// Copyright 2018 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 MOJO_PUBLIC_CPP_BASE_UNGUESSABLE_TOKEN_MOJOM_TRAITS_H_
+#define MOJO_PUBLIC_CPP_BASE_UNGUESSABLE_TOKEN_MOJOM_TRAITS_H_
+
+#include "base/component_export.h"
+#include "base/unguessable_token.h"
+#include "mojo/public/mojom/base/unguessable_token.mojom-shared.h"
+
+namespace mojo {
+
+// If base::UnguessableToken is no longer 128 bits, the logic below and the
+// mojom::UnguessableToken type should be updated.
+static_assert(sizeof(base::UnguessableToken) == 2 * sizeof(uint64_t),
+              "base::UnguessableToken should be of size 2 * sizeof(uint64_t).");
+
+template <>
+struct COMPONENT_EXPORT(MOJO_BASE_MOJOM)
+    StructTraits<mojo_base::mojom::UnguessableTokenDataView,
+                 base::UnguessableToken> {
+  static uint64_t high(const base::UnguessableToken& token) {
+    return token.GetHighForSerialization();
+  }
+
+  static uint64_t low(const base::UnguessableToken& token) {
+    return token.GetLowForSerialization();
+  }
+
+  static bool Read(mojo_base::mojom::UnguessableTokenDataView data,
+                   base::UnguessableToken* out);
+};
+
+}  // namespace mojo
+
+#endif  // MOJO_PUBLIC_CPP_BASE_UNGUESSABLE_TOKEN_MOJOM_TRAITS_H_
\ No newline at end of file
diff --git a/mojo/public/cpp/base/unguessable_token_unittest.cc b/mojo/public/cpp/base/unguessable_token_unittest.cc
new file mode 100644
index 0000000..c752178
--- /dev/null
+++ b/mojo/public/cpp/base/unguessable_token_unittest.cc
@@ -0,0 +1,23 @@
+// Copyright 2018 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 "mojo/public/cpp/base/unguessable_token_mojom_traits.h"
+#include "mojo/public/cpp/test_support/test_utils.h"
+#include "mojo/public/mojom/base/unguessable_token.mojom.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo_base {
+namespace unguessable_token_unittest {
+
+TEST(UnguessableTokenTest, UnguessableToken) {
+  base::UnguessableToken in = base::UnguessableToken::Create();
+  base::UnguessableToken out;
+
+  ASSERT_TRUE(
+      mojo::test::SerializeAndDeserialize<mojom::UnguessableToken>(&in, &out));
+  EXPECT_EQ(in, out);
+}
+
+}  // namespace unguessable_token_unittest
+}  // namespace mojo_base
\ No newline at end of file
diff --git a/mojo/public/cpp/bindings/BUILD.gn b/mojo/public/cpp/bindings/BUILD.gn
index cefb31d..d1eaece 100644
--- a/mojo/public/cpp/bindings/BUILD.gn
+++ b/mojo/public/cpp/bindings/BUILD.gn
@@ -7,8 +7,8 @@
   enable_mojo_tracing = false
 }
 
-buildflag_header("mojo_features") {
-  header = "mojo_features.h"
+buildflag_header("mojo_buildflags") {
+  header = "mojo_buildflags.h"
 
   flags = [ "MOJO_TRACE_ENABLED=$enable_mojo_tracing" ]
 }
@@ -86,7 +86,7 @@
   defines = [ "IS_MOJO_CPP_BINDINGS_BASE_IMPL" ]
 
   public_deps = [
-    ":mojo_features",
+    ":mojo_buildflags",
     "//base",
     "//mojo/public/cpp/system",
   ]
diff --git a/mojo/public/cpp/bindings/lib/connector.cc b/mojo/public/cpp/bindings/lib/connector.cc
index 94b6b4a..5cc30b1 100644
--- a/mojo/public/cpp/bindings/lib/connector.cc
+++ b/mojo/public/cpp/bindings/lib/connector.cc
@@ -18,7 +18,7 @@
 #include "base/threading/thread_local.h"
 #include "base/trace_event/trace_event.h"
 #include "mojo/public/cpp/bindings/lib/may_auto_lock.h"
-#include "mojo/public/cpp/bindings/mojo_features.h"
+#include "mojo/public/cpp/bindings/mojo_buildflags.h"
 #include "mojo/public/cpp/bindings/sync_handle_watcher.h"
 #include "mojo/public/cpp/system/wait.h"
 
diff --git a/mojo/public/cpp/system/buffer.cc b/mojo/public/cpp/system/buffer.cc
index 49f45d8..13f20263 100644
--- a/mojo/public/cpp/system/buffer.cc
+++ b/mojo/public/cpp/system/buffer.cc
@@ -43,4 +43,12 @@
   return ScopedSharedBufferMapping(buffer);
 }
 
+uint64_t SharedBufferHandle::GetSize() const {
+  MojoSharedBufferInfo buffer_info;
+  buffer_info.struct_size = sizeof(buffer_info);
+  return MojoGetBufferInfo(value(), nullptr, &buffer_info) == MOJO_RESULT_OK
+             ? buffer_info.size
+             : 0;
+}
+
 }  // namespace mojo
diff --git a/mojo/public/cpp/system/buffer.h b/mojo/public/cpp/system/buffer.h
index 660b750..d72d1976 100644
--- a/mojo/public/cpp/system/buffer.h
+++ b/mojo/public/cpp/system/buffer.h
@@ -69,6 +69,9 @@
   // Maps |size| bytes of this shared buffer, starting |offset| bytes into the
   // buffer. On failure, this will return a null mapping.
   ScopedSharedBufferMapping MapAtOffset(uint64_t size, uint64_t offset) const;
+
+  // Get the size of this shared buffer.
+  uint64_t GetSize() const;
 };
 
 static_assert(sizeof(SharedBufferHandle) == sizeof(Handle),
diff --git a/mojo/public/cpp/system/tests/core_unittest.cc b/mojo/public/cpp/system/tests/core_unittest.cc
index b134e9b..d727431f 100644
--- a/mojo/public/cpp/system/tests/core_unittest.cc
+++ b/mojo/public/cpp/system/tests/core_unittest.cc
@@ -386,6 +386,7 @@
 TEST(CoreCppTest, BasicSharedBuffer) {
   ScopedSharedBufferHandle h0 = SharedBufferHandle::Create(100);
   ASSERT_TRUE(h0.is_valid());
+  EXPECT_EQ(100U, h0->GetSize());
 
   // Map everything.
   ScopedSharedBufferMapping mapping = h0->Map(100);
diff --git a/mojo/public/mojom/base/BUILD.gn b/mojo/public/mojom/base/BUILD.gn
index 6aa5f4e..1c36b1d 100644
--- a/mojo/public/mojom/base/BUILD.gn
+++ b/mojo/public/mojom/base/BUILD.gn
@@ -15,7 +15,9 @@
     "ref_counted_memory.mojom",
     "string16.mojom",
     "text_direction.mojom",
+    "thread_priority.mojom",
     "time.mojom",
+    "unguessable_token.mojom",
     "values.mojom",
   ]
 
diff --git a/mojo/public/mojom/base/thread_priority.mojom b/mojo/public/mojom/base/thread_priority.mojom
new file mode 100644
index 0000000..21d7f34
--- /dev/null
+++ b/mojo/public/mojom/base/thread_priority.mojom
@@ -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.
+
+module mojo_base.mojom;
+
+// Corresponds to |base::ThreadPriority|
+enum ThreadPriority {
+  // Suitable for threads that shouldn't disrupt high priority work.
+  BACKGROUND,
+  // Default priority level.
+  NORMAL,
+  // Suitable for threads which generate data for the display (at ~60Hz).
+  DISPLAY,
+  // Suitable for low-latency, glitch-resistant audio.
+  REALTIME_AUDIO,
+};
diff --git a/mojo/public/mojom/base/unguessable_token.mojom b/mojo/public/mojom/base/unguessable_token.mojom
new file mode 100644
index 0000000..42aa7e2
--- /dev/null
+++ b/mojo/public/mojom/base/unguessable_token.mojom
@@ -0,0 +1,11 @@
+// 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 mojo_base.mojom;
+
+// Corresponds to |base::UnguessableToken| in base/unguessable_token.h
+struct UnguessableToken {
+  uint64 high;
+  uint64 low;
+};
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl
index 3d14795..c055687 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl
@@ -43,7 +43,7 @@
 #include "base/macros.h"
 #include "base/optional.h"
 
-#include "mojo/public/cpp/bindings/mojo_features.h"
+#include "mojo/public/cpp/bindings/mojo_buildflags.h"
 #if BUILDFLAG(MOJO_TRACE_ENABLED)
 #include "base/trace_event/trace_event.h"
 #endif
diff --git a/mojo/public/tools/fuzzers/BUILD.gn b/mojo/public/tools/fuzzers/BUILD.gn
index 2c8a68a..00d09f1 100644
--- a/mojo/public/tools/fuzzers/BUILD.gn
+++ b/mojo/public/tools/fuzzers/BUILD.gn
@@ -7,6 +7,7 @@
 import("//build/config/features.gni")
 import("//mojo/public/tools/bindings/mojom.gni")
 import("//testing/libfuzzer/fuzzer_test.gni")
+import("//third_party/protobuf/proto_library.gni")
 
 # mojo/public BUILD depends on this target. Needed for package discovery
 group("fuzzers") {
@@ -45,3 +46,23 @@
     ]
   }
 }
+
+fuzzer_test("mojo_parse_message_proto_fuzzer") {
+  sources = [
+    "fuzz_impl.cc",
+    "mojo_parse_message_proto_fuzzer.cc",
+  ]
+  deps = [
+    ":fuzz_mojom",
+    ":mojo_fuzzer_proto",
+    "//mojo/edk",
+    "//third_party/libprotobuf-mutator",
+  ]
+  seed_corpus = "//mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus"
+}
+
+proto_library("mojo_fuzzer_proto") {
+  sources = [
+    "mojo_fuzzer.proto",
+  ]
+}
diff --git a/mojo/public/tools/fuzzers/mojo_fuzzer.proto b/mojo/public/tools/fuzzers/mojo_fuzzer.proto
new file mode 100644
index 0000000..fb178711
--- /dev/null
+++ b/mojo/public/tools/fuzzers/mojo_fuzzer.proto
@@ -0,0 +1,7 @@
+syntax = "proto2";
+
+package mojo_proto_fuzzer;
+
+message MojoFuzzerMessages {
+  repeated bytes messages = 1;
+}
\ No newline at end of file
diff --git a/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/07775ad8fdb79599024caefbe7889501dfee9e06 b/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/07775ad8fdb79599024caefbe7889501dfee9e06
new file mode 100644
index 0000000..f1932a6
--- /dev/null
+++ b/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/07775ad8fdb79599024caefbe7889501dfee9e06
@@ -0,0 +1 @@
+messages: "\060\000\000\000\002\000\000\000\000\000\000\000\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\014\000\000\000\001\000\000\000\001\000\000\200\000\000\000\000"
diff --git a/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/2ce2f91669a46921ebf4e47679c86dd2bf5b1496 b/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/2ce2f91669a46921ebf4e47679c86dd2bf5b1496
new file mode 100644
index 0000000..52bae3d
--- /dev/null
+++ b/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/2ce2f91669a46921ebf4e47679c86dd2bf5b1496
@@ -0,0 +1 @@
+messages: "\030\000\000\000\000\000\000\000\001\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000"
diff --git a/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/32a65dcd84debde03d51f8b8ace2cdcc87461d34 b/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/32a65dcd84debde03d51f8b8ace2cdcc87461d34
new file mode 100644
index 0000000..9cbd562
--- /dev/null
+++ b/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/32a65dcd84debde03d51f8b8ace2cdcc87461d34
@@ -0,0 +1 @@
+messages: "\030\000\000\000\000\000\000\000\000\000\000\000\003\000\000\000\000\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\040\001\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\150\000\000\000\000\000\000\000\210\000\000\000\000\000\000\000\250\000\000\000\000\000\000\000\250\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\001\377\001\000\000\377\000\001\000\000\377\377\000\000\001\000\000\000\000\000\377\377\377\377\000\000\000\000\001\000\000\000\000\000\200\077\000\000\000\000\000\000\000\000\000\000\360\077\110\000\000\000\000\000\000\000\120\000\000\000\000\000\000\000\130\000\000\000\000\000\000\000\230\000\000\000\000\000\000\000\020\001\000\000\000\000\000\000\240\001\000\000\000\000\000\000\110\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\140\003\000\000\000\000\000\000\014\000\000\000\004\000\000\000\146\165\172\172\000\000\000\000\014\000\000\000\004\000\000\000\146\165\172\172\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\050\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\014\000\000\000\004\000\000\000\146\165\172\172\000\000\000\000\011\000\000\000\001\000\000\000\172\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\050\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\014\000\000\000\004\000\000\000\146\165\172\172\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\002\000\000\000\020\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\015\000\000\000\005\000\000\000\146\165\172\172\061\000\000\000\015\000\000\000\005\000\000\000\146\165\172\172\062\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\014\000\000\000\001\000\000\000\001\000\000\000\000\000\000\000\030\000\000\000\001\000\000\000\020\000\000\000\020\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\050\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\014\000\000\000\004\000\000\000\146\165\172\172\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\030\000\000\000\001\000\000\000\020\000\000\000\022\000\000\000\010\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\014\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\011\000\000\000\001\000\000\000\172\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\001\000\000\000\020\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\150\000\000\000\000\000\000\000\210\000\000\000\000\000\000\000\250\000\000\000\000\000\000\000\250\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\014\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\011\000\000\000\001\000\000\000\172\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\150\000\000\000\000\000\000\000\210\000\000\000\000\000\000\000\250\000\000\000\000\000\000\000\250\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000"
diff --git a/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/7cbf9144ec3980eb121eedc679ebc56a3ddd22a6 b/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/7cbf9144ec3980eb121eedc679ebc56a3ddd22a6
new file mode 100644
index 0000000..fb4a52b1
--- /dev/null
+++ b/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/7cbf9144ec3980eb121eedc679ebc56a3ddd22a6
@@ -0,0 +1 @@
+messages: "\040\000\000\000\001\000\000\000\000\000\000\000\005\000\000\000\001\000\000\000\000\000\000\000\006\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\040\001\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\150\000\000\000\000\000\000\000\210\000\000\000\000\000\000\000\250\000\000\000\000\000\000\000\250\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\001\377\001\000\000\377\000\001\000\000\377\377\000\000\001\000\000\000\000\000\377\377\377\377\000\000\000\000\001\000\000\000\000\000\200\077\000\000\000\000\000\000\000\000\000\000\360\077\110\000\000\000\000\000\000\000\120\000\000\000\000\000\000\000\130\000\000\000\000\000\000\000\230\000\000\000\000\000\000\000\020\001\000\000\000\000\000\000\240\001\000\000\000\000\000\000\110\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\140\003\000\000\000\000\000\000\014\000\000\000\004\000\000\000\146\165\172\172\000\000\000\000\014\000\000\000\004\000\000\000\146\165\172\172\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\050\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\014\000\000\000\004\000\000\000\146\165\172\172\000\000\000\000\011\000\000\000\001\000\000\000\172\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\050\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\014\000\000\000\004\000\000\000\146\165\172\172\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\002\000\000\000\020\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\015\000\000\000\005\000\000\000\146\165\172\172\061\000\000\000\015\000\000\000\005\000\000\000\146\165\172\172\062\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\014\000\000\000\001\000\000\000\001\000\000\000\000\000\000\000\030\000\000\000\001\000\000\000\020\000\000\000\020\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\050\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\014\000\000\000\004\000\000\000\146\165\172\172\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\030\000\000\000\001\000\000\000\020\000\000\000\022\000\000\000\010\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\014\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\011\000\000\000\001\000\000\000\172\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\001\000\000\000\020\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\150\000\000\000\000\000\000\000\210\000\000\000\000\000\000\000\250\000\000\000\000\000\000\000\250\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\014\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\011\000\000\000\001\000\000\000\172\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\020\000\000\000\001\000\000\000\010\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\150\000\000\000\000\000\000\000\210\000\000\000\000\000\000\000\250\000\000\000\000\000\000\000\250\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000"
diff --git a/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/9ccc6b5c0a61672816dc252194c3d722c18107bc b/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/9ccc6b5c0a61672816dc252194c3d722c18107bc
new file mode 100644
index 0000000..d5fa611
--- /dev/null
+++ b/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/9ccc6b5c0a61672816dc252194c3d722c18107bc
@@ -0,0 +1 @@
+messages: "\040\000\000\000\001\000\000\000\000\000\000\000\002\000\000\000\005\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000"
diff --git a/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/9e0a62bdd4b08cb777bee9449a22b3ad6702b106 b/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/9e0a62bdd4b08cb777bee9449a22b3ad6702b106
new file mode 100644
index 0000000..c5567f2
--- /dev/null
+++ b/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/9e0a62bdd4b08cb777bee9449a22b3ad6702b106
@@ -0,0 +1 @@
+messages: "\030\000\000\000\000\000\000\000\000\000\000\000\003\000\000\000\000\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\110\000\000\000\000\000\000\000\150\000\000\000\000\000\000\000\210\000\000\000\000\000\000\000\250\000\000\000\000\000\000\000\250\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000"
diff --git a/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/a74241101f97704b96c9ba11b4781651e236ad8f b/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/a74241101f97704b96c9ba11b4781651e236ad8f
new file mode 100644
index 0000000..619a2bb
--- /dev/null
+++ b/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/a74241101f97704b96c9ba11b4781651e236ad8f
@@ -0,0 +1 @@
+messages: "\030\000\000\000\000\000\000\000\377\377\377\377\376\377\377\377\000\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\030\000\000\000\000\000\000\000\001\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000"
diff --git a/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/be66c5d078fbf574388b7b1d25a29ff2d16df67e b/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/be66c5d078fbf574388b7b1d25a29ff2d16df67e
new file mode 100644
index 0000000..dcd7e6e
--- /dev/null
+++ b/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/be66c5d078fbf574388b7b1d25a29ff2d16df67e
@@ -0,0 +1 @@
+messages: "\040\000\000\000\001\000\000\000\000\000\000\000\001\000\000\000\001\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000"
diff --git a/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/e4be6bde72d04c5cda7d4939a80e5890c5c01374 b/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/e4be6bde72d04c5cda7d4939a80e5890c5c01374
new file mode 100644
index 0000000..186f82d8
--- /dev/null
+++ b/mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus/e4be6bde72d04c5cda7d4939a80e5890c5c01374
@@ -0,0 +1 @@
+messages: "\030\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000"
diff --git a/mojo/public/tools/fuzzers/mojo_parse_message_proto_fuzzer.cc b/mojo/public/tools/fuzzers/mojo_parse_message_proto_fuzzer.cc
new file mode 100644
index 0000000..6772541d
--- /dev/null
+++ b/mojo/public/tools/fuzzers/mojo_parse_message_proto_fuzzer.cc
@@ -0,0 +1,70 @@
+// Copyright 2018 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.
+
+// Implementation of a proto version of mojo_parse_message_fuzzer that sends
+// multiple messages per run.
+
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/task_scheduler/task_scheduler.h"
+#include "mojo/edk/embedder/embedder.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/tools/fuzzers/fuzz_impl.h"
+#include "mojo/public/tools/fuzzers/mojo_fuzzer.pb.h"
+#include "testing/libfuzzer/proto/lpm_interface.h"
+
+namespace mojo_proto_fuzzer {
+
+void FuzzMessage(const MojoFuzzerMessages& mojo_fuzzer_messages,
+                 base::RunLoop* run) {
+  fuzz::mojom::FuzzInterfacePtr fuzz;
+  auto impl = std::make_unique<FuzzImpl>(MakeRequest(&fuzz));
+  auto router = impl->binding_.RouterForTesting();
+
+  for (auto& message_str : mojo_fuzzer_messages.messages()) {
+    // Create a mojo message with the appropriate payload size.
+    mojo::Message message(0, 0, message_str.size(), 0, nullptr);
+    if (message.data_num_bytes() < message_str.size()) {
+      message.payload_buffer()->Allocate(message_str.size() -
+                                         message.data_num_bytes());
+    }
+
+    // Set the raw message data.
+    memcpy(message.mutable_data(), message_str.data(), message_str.size());
+
+    // Run the message through header validation, payload validation, and
+    // dispatch to the impl.
+    router->SimulateReceivingMessageForTesting(&message);
+  }
+
+  // Allow the harness function to return now.
+  run->Quit();
+}
+
+// Environment for the fuzzer. Initializes the mojo EDK and sets up a
+// TaskScheduler, because Mojo messages must be sent and processed from
+// TaskRunners.
+struct Environment {
+  Environment() : message_loop(base::MessageLoop::TYPE_UI) {
+    base::TaskScheduler::CreateAndStartWithDefaultParams(
+        "MojoParseMessageFuzzerProcess");
+    mojo::edk::Init();
+  }
+
+  // Message loop to send and handle messages on.
+  base::MessageLoop message_loop;
+
+  // Suppress mojo validation failure logs.
+  mojo::internal::ScopedSuppressValidationErrorLoggingForTests log_suppression;
+};
+
+DEFINE_PROTO_FUZZER(const MojoFuzzerMessages& mojo_fuzzer_messages) {
+  static Environment* env = new Environment();
+  // Pass the data along to run on a MessageLoop, and wait for it to finish.
+  base::RunLoop run;
+  env->message_loop.task_runner()->PostTask(
+      FROM_HERE, base::BindOnce(&FuzzMessage, mojo_fuzzer_messages, &run));
+  run.Run();
+}
+}  // namespace mojo_proto_fuzzer
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 5432ce5..695c1343 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -47,8 +47,8 @@
 # Python works only on Linux, MacOS and Windows.
 enable_python_utils = !is_android && !is_fuchsia && !is_ios
 
-buildflag_header("features") {
-  header = "net_features.h"
+buildflag_header("buildflags") {
+  header = "net_buildflags.h"
   flags = [
     "POSIX_AVOID_MMAP=$posix_avoid_mmap",
     "DISABLE_FILE_SUPPORT=$disable_file_support",
@@ -109,6 +109,8 @@
     "base/auth.h",
     "base/completion_callback.h",
     "base/completion_once_callback.h",
+    "base/datagram_buffer.cc",
+    "base/datagram_buffer.h",
     "base/escape.cc",
     "base/escape.h",
     "base/hash_value.cc",
@@ -2067,7 +2069,7 @@
   configs += net_configs
 
   public_deps += [
-    ":features",
+    ":buildflags",
     "//url",
   ]
 
@@ -4679,6 +4681,7 @@
     "base/backoff_entry_unittest.cc",
     "base/chunked_upload_data_stream_unittest.cc",
     "base/data_url_unittest.cc",
+    "base/datagram_buffer_unittest.cc",
     "base/directory_lister_unittest.cc",
     "base/directory_listing_unittest.cc",
     "base/elements_upload_data_stream_unittest.cc",
diff --git a/net/base/datagram_buffer.cc b/net/base/datagram_buffer.cc
new file mode 100644
index 0000000..c4f3eaa
--- /dev/null
+++ b/net/base/datagram_buffer.cc
@@ -0,0 +1,56 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/base/datagram_buffer.h"
+#include "net/quic/platform/api/quic_ptr_util.h"
+
+namespace net {
+
+DatagramBufferPool::DatagramBufferPool(size_t max_buffer_size)
+    : max_buffer_size_(max_buffer_size) {}
+
+DatagramBufferPool::~DatagramBufferPool() {}
+
+void DatagramBufferPool::Enqueue(const char* buffer,
+                                 size_t buf_len,
+                                 DatagramBuffers* buffers) {
+  DCHECK_LE(buf_len, max_buffer_size_);
+  std::unique_ptr<DatagramBuffer> datagram_buffer;
+  if (free_list_.empty()) {
+    datagram_buffer =
+        QuicWrapUnique<DatagramBuffer>(new DatagramBuffer(max_buffer_size_));
+  } else {
+    datagram_buffer = std::move(free_list_.front());
+    free_list_.pop_front();
+  }
+  datagram_buffer->Set(buffer, buf_len);
+  buffers->emplace_back(std::move(datagram_buffer));
+}
+
+void DatagramBufferPool::Dequeue(DatagramBuffers* buffers) {
+  if (buffers->size() == 0)
+    return;
+
+  free_list_.splice(free_list_.cend(), *buffers);
+}
+
+DatagramBuffer::DatagramBuffer(size_t max_buffer_size)
+    : data_(new char[max_buffer_size]), length_(0) {}
+
+DatagramBuffer::~DatagramBuffer() {}
+
+void DatagramBuffer::Set(const char* buffer, size_t buf_len) {
+  length_ = buf_len;
+  std::memcpy(data_.get(), buffer, buf_len);
+}
+
+char* DatagramBuffer::data() const {
+  return data_.get();
+}
+
+size_t DatagramBuffer::length() const {
+  return length_;
+}
+
+}  // namespace net
diff --git a/net/base/datagram_buffer.h b/net/base/datagram_buffer.h
new file mode 100644
index 0000000..a7622b8
--- /dev/null
+++ b/net/base/datagram_buffer.h
@@ -0,0 +1,102 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_BASE_DATAGRAM_BUFFER_H_
+#define NET_BASE_DATAGRAM_BUFFER_H_
+
+#include <list>
+
+#include "base/memory/weak_ptr.h"
+#include "net/base/net_export.h"
+
+namespace net {
+
+// An IO buffer, (at least initially) specifically for use with the
+// new DatagramClientSocket::WriteAsync method, with the following key
+// features:
+//
+//   1) Meant to be easily batched when that improves efficiency. The
+//      primary goal of WriteAsync is to enable enlisting an
+//      additional cpu core for the kernel part of socket write.
+//   2) Uses unique_ptr (with std::move) rather than reference
+//      counting as in IOBuffers.  The benefit is safer cancellation
+//      semantics, IOBuffer used reference count to enforce unique
+//      ownership in an idiomatic fashion.  unique_ptr is ligher weight
+//      as it doesn't use thread safe primitives as
+//      RefCountedThreadSafe does.
+//   3) Provides a pooling allocator, which for datagram buffers is
+//      much cheaper than using fully general allocator (e.g. malloc
+//      etc.).  The implementation takes advantage of
+//      std::list::splice so that costs associated with allocations
+//      and copies of pool metadata quickly amortize to zero, and all
+//      common operations are O(1).
+
+class DatagramBuffer;
+
+// Batches of DatagramBuffers are treated as a FIFO queue, implemented
+// by |std::list|.  Note that |std::list::splice()| is attractive for
+// this use case because it keeps most operations to O(1) and
+// minimizes allocations/frees and copies.
+typedef std::list<std::unique_ptr<DatagramBuffer>> DatagramBuffers;
+
+class NET_EXPORT_PRIVATE DatagramBufferPool {
+ public:
+  // |max_buffer_size| must be >= largest |buf_len| provided to
+  // ||New()|.
+  DatagramBufferPool(size_t max_buffer_size);
+  DatagramBufferPool(const DatagramBufferPool&) = delete;
+  DatagramBufferPool& operator=(const DatagramBufferPool&) = delete;
+  virtual ~DatagramBufferPool();
+  // Insert a new element (drawn from the pool) containing a copy of
+  // |buffer| to |buffers|. Caller retains owenership of |buffers| and |buffer|.
+  void Enqueue(const char* buffer, size_t buf_len, DatagramBuffers* buffers);
+  // Return all elements of |buffers| to the pool.  Caller retains
+  // ownership of |buffers|.
+  void Dequeue(DatagramBuffers* buffers);
+
+  size_t max_buffer_size() { return max_buffer_size_; }
+
+ private:
+  const size_t max_buffer_size_;
+  DatagramBuffers free_list_;
+};
+
+// |DatagramBuffer|s can only be created via
+// |DatagramBufferPool::Enqueue()|.
+//
+
+// |DatagramBuffer|s should be recycled via
+// |DatagramBufferPool::Dequeue|.  Care must be taken when a
+// |DatagramBuffer| is moved to another thread via
+// |PostTask|. |Dequeue| is not expected to be thread-safe, so it
+// is preferred to move the |DatagramBuffer|s back to the thread where
+// the pool lives (e.g. using |PostTaskAndReturnWithResult|) and
+// dequeuing them from there.  In the exception of pathalogical
+// cancellation (e.g. due to thread tear-down), the destructor will
+// release its memory permanently rather than returning to the pool.
+class NET_EXPORT_PRIVATE DatagramBuffer {
+ public:
+  DatagramBuffer() = delete;
+  DatagramBuffer(const DatagramBuffer&) = delete;
+  DatagramBuffer& operator=(const DatagramBuffer&) = delete;
+  ~DatagramBuffer();
+
+  char* data() const;
+  size_t length() const;
+
+ protected:
+  DatagramBuffer(size_t max_packet_size);
+
+ private:
+  friend class DatagramBufferPool;
+
+  void Set(const char* buffer, size_t buf_len);
+
+  std::unique_ptr<char[]> data_;
+  size_t length_;
+};
+
+}  // namespace net
+
+#endif  // NET_BASE_DATAGRAM_BUFFER_H_
diff --git a/net/base/datagram_buffer_unittest.cc b/net/base/datagram_buffer_unittest.cc
new file mode 100644
index 0000000..0f65ffd
--- /dev/null
+++ b/net/base/datagram_buffer_unittest.cc
@@ -0,0 +1,54 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/base/datagram_buffer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+namespace test {
+
+const size_t kMaxBufferSize = 1024;
+
+class DatagramBufferTest : public testing::Test {
+ public:
+  DatagramBufferTest() : pool_(kMaxBufferSize) {}
+
+  DatagramBufferPool pool_;
+};
+
+TEST_F(DatagramBufferTest, EnqueueCopiesData) {
+  DatagramBuffers buffers;
+  const char data[] = "foo";
+  pool_.Enqueue(data, sizeof(data), &buffers);
+  EXPECT_EQ(sizeof(data), buffers.front()->length());
+  EXPECT_NE(data, buffers.front()->data());
+  EXPECT_EQ(0, memcmp(data, buffers.front()->data(), sizeof(data)));
+}
+
+TEST_F(DatagramBufferTest, DatgramBufferPoolRecycles) {
+  DatagramBuffers buffers;
+  const char data1[] = "foo";
+  pool_.Enqueue(data1, sizeof(data1), &buffers);
+  DatagramBuffer* buffer1_ptr = buffers.back().get();
+  EXPECT_EQ(1u, buffers.size());
+  const char data2[] = "bar";
+  pool_.Enqueue(data2, sizeof(data2), &buffers);
+  DatagramBuffer* buffer2_ptr = buffers.back().get();
+  EXPECT_EQ(2u, buffers.size());
+  pool_.Dequeue(&buffers);
+  EXPECT_EQ(0u, buffers.size());
+  const char data3[] = "baz";
+  pool_.Enqueue(data3, sizeof(data3), &buffers);
+  EXPECT_EQ(1u, buffers.size());
+  EXPECT_EQ(buffer1_ptr, buffers.back().get());
+  const char data4[] = "bag";
+  pool_.Enqueue(data4, sizeof(data4), &buffers);
+  EXPECT_EQ(2u, buffers.size());
+  EXPECT_EQ(buffer2_ptr, buffers.back().get());
+}
+
+}  // namespace test
+
+}  // namespace net
diff --git a/net/base/load_flags_list.h b/net/base/load_flags_list.h
index 9b58859..9abb9b9 100644
--- a/net/base/load_flags_list.h
+++ b/net/base/load_flags_list.h
@@ -16,10 +16,13 @@
 
 LOAD_FLAG(NORMAL, 0)
 
-// This is "normal reload", meaning an if-none-match/if-modified-since query
+// This is "normal reload", meaning an if-none-match/if-modified-since query. It
+// has no effect on the host cache.
 LOAD_FLAG(VALIDATE_CACHE, 1 << 0)
 
-// This is "shift-reload", meaning a "pragma: no-cache" end-to-end fetch
+// This is "shift-reload", meaning a "pragma: no-cache" end-to-end fetch. It
+// also disables use of the host cache for resolutions that go through the
+// socket pools.
 LOAD_FLAG(BYPASS_CACHE, 1 << 1)
 
 // This is a back/forward style navigation where the cached content should
@@ -31,7 +34,7 @@
 LOAD_FLAG(ONLY_FROM_CACHE, 1 << 3)
 
 // This is a navigation that will not use the cache at all.  It does not
-// impact the HTTP request headers.
+// impact the HTTP request headers or use of the host cache.
 LOAD_FLAG(DISABLE_CACHE, 1 << 4)
 
 // If present, causes certificate revocation checks to be skipped on secure
diff --git a/net/base/load_timing_info.h b/net/base/load_timing_info.h
index d397e07..af743523 100644
--- a/net/base/load_timing_info.h
+++ b/net/base/load_timing_info.h
@@ -73,6 +73,9 @@
     // established, which results in unexpected event ordering.
     // TODO(mmenke):  The SOCKS4 event ordering could be refactored to allow
     //                these times to be non-null.
+    // Corresponds to |domainLookupStart| and |domainLookupEnd| in
+    // ResourceTiming (http://www.w3.org/TR/resource-timing/) for Web-surfacing
+    // requests.
     base::TimeTicks dns_start;
     base::TimeTicks dns_end;
 
@@ -87,12 +90,16 @@
     //                handled at different levels, this may not be worth
     //                worrying about - backup jobs, reused socket failure,
     //                multiple round authentication.
+    // Corresponds to |connectStart| and |connectEnd| in ResourceTiming
+    // (http://www.w3.org/TR/resource-timing/) for Web-surfacing requests.
     base::TimeTicks connect_start;
     base::TimeTicks connect_end;
 
     // The time when the SSL handshake started / completed. For non-HTTPS
     // requests these are null.  These times are only for the SSL connection to
     // the final destination server, not an SSL/SPDY proxy.
+    // |ssl_start| corresponds to |secureConnectionStart| in ResourceTiming
+    // (http://www.w3.org/TR/resource-timing/) for Web-surfacing requests.
     base::TimeTicks ssl_start;
     base::TimeTicks ssl_end;
   };
@@ -127,6 +134,8 @@
   // changes.
   base::Time request_start_time;
 
+  // Corresponds to |fetchStart| in ResourceTiming
+  // (http://www.w3.org/TR/resource-timing/) for Web-surfacing requests.
   base::TimeTicks request_start;
 
   // The time spent determing which proxy to use.  Null when there is no PAC.
@@ -136,10 +145,14 @@
   ConnectTiming connect_timing;
 
   // The time that sending HTTP request started / ended.
+  // |send_start| corresponds to |requestStart| in ResourceTiming
+  // (http://www.w3.org/TR/resource-timing/) for Web-surfacing requests.
   base::TimeTicks send_start;
   base::TimeTicks send_end;
 
   // The time at which the end of the HTTP headers were received.
+  // Corresponds to |responseStart| in ResourceTiming
+  // (http://www.w3.org/TR/resource-timing/) for Web-surfacing requests.
   base::TimeTicks receive_headers_end;
 
   // In case the resource was proactively pushed by the server, these are
diff --git a/net/base/unescape_url_component_fuzzer.cc b/net/base/unescape_url_component_fuzzer.cc
index 0053011c..cd93f99d 100644
--- a/net/base/unescape_url_component_fuzzer.cc
+++ b/net/base/unescape_url_component_fuzzer.cc
@@ -13,10 +13,23 @@
 
 // Entry point for LibFuzzer.
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  std::string path(reinterpret_cast<const char*>(data), size);
+  base::StringPiece path(reinterpret_cast<const char*>(data), size);
   for (int i = 0; i <= kMaxUnescapeRule; i++) {
-    (void)net::UnescapeURLComponent(path,
-                                    static_cast<net::UnescapeRule::Type>(i));
+    net::UnescapeURLComponent(path, static_cast<net::UnescapeRule::Type>(i));
   }
+
+  // When non-empty, align |data| to sizeof(char16).
+  if ((size > 0) && ((size % 2) == 1)) {
+    data++;
+    size--;
+  }
+
+  // Test for StringPiece16.
+  base::StringPiece16 path16(reinterpret_cast<const base::char16*>(data),
+                             size / 2);
+  for (int i = 0; i <= kMaxUnescapeRule; i++) {
+    net::UnescapeURLComponent(path16, static_cast<net::UnescapeRule::Type>(i));
+  }
+
   return 0;
 }
diff --git a/net/base/upload_data_stream.h b/net/base/upload_data_stream.h
index 1c6e554b..b9645ec 100644
--- a/net/base/upload_data_stream.h
+++ b/net/base/upload_data_stream.h
@@ -124,7 +124,7 @@
   virtual int ReadInternal(IOBuffer* buf, int buf_len) = 0;
 
   // Resets state and cancels any pending callbacks. Guaranteed to be called
-  // before all but the first call to InitInternal.
+  // at least once before every call to InitInternal.
   virtual void ResetInternal() = 0;
 
   uint64_t total_size_;
diff --git a/net/cert/x509_util_win.cc b/net/cert/x509_util_win.cc
index 9def51f9..827ab4d8 100644
--- a/net/cert/x509_util_win.cc
+++ b/net/cert/x509_util_win.cc
@@ -7,7 +7,7 @@
 #include "crypto/scoped_capi_types.h"
 #include "crypto/sha2.h"
 #include "net/cert/x509_certificate.h"
-#include "net/net_features.h"
+#include "net/net_buildflags.h"
 #include "third_party/boringssl/src/include/openssl/pool.h"
 
 namespace net {
diff --git a/net/disk_cache/blockfile/mapped_file.h b/net/disk_cache/blockfile/mapped_file.h
index 21dd0c7..3e36c79 100644
--- a/net/disk_cache/blockfile/mapped_file.h
+++ b/net/disk_cache/blockfile/mapped_file.h
@@ -13,7 +13,7 @@
 #include "net/base/net_export.h"
 #include "net/disk_cache/blockfile/file.h"
 #include "net/disk_cache/blockfile/file_block.h"
-#include "net/net_features.h"
+#include "net/net_buildflags.h"
 
 namespace base {
 class FilePath;
diff --git a/net/disk_cache/simple/simple_backend_impl.cc b/net/disk_cache/simple/simple_backend_impl.cc
index 3fbb29f..bbf9773 100644
--- a/net/disk_cache/simple/simple_backend_impl.cc
+++ b/net/disk_cache/simple/simple_backend_impl.cc
@@ -32,7 +32,6 @@
 #include "base/time/time.h"
 #include "base/trace_event/memory_usage_estimator.h"
 #include "base/trace_event/process_memory_dump.h"
-#include "build/build_config.h"
 #include "net/base/net_errors.h"
 #include "net/disk_cache/backend_cleanup_tracker.h"
 #include "net/disk_cache/cache_util.h"
@@ -74,6 +73,11 @@
 // Maximum fraction of the cache that one entry can consume.
 const int kMaxFileRatio = 8;
 
+#if defined(OS_POSIX) && !defined(OS_ANDROID)
+// Period to check the maximum count of files available
+constexpr int kUpdateIntervalInSeconds = 10 * 60;  // 10 min
+#endif
+
 bool g_fd_limit_histogram_has_been_populated = false;
 
 void MaybeHistogramFdLimit() {
@@ -640,6 +644,18 @@
                                         const DiskStatResult& result) {
   if (result.net_error == net::OK) {
     index_->SetMaxSize(result.max_size);
+#if defined(OS_POSIX) && !defined(OS_ANDROID)
+    int64_t available = base::SysInfo::AmountOfAvailableDiskInode(path_);
+    int64_t total = base::SysInfo::AmountOfMaxDiskInode(path_);
+    if (available != -1 && total != -1) {
+      index_->UpdateMaxFiles(available, total);
+      if (!update_timer_.IsRunning())
+        update_timer_.Start(
+            FROM_HERE, base::TimeDelta::FromSeconds(kUpdateIntervalInSeconds),
+            base::BindRepeating(&SimpleBackendImpl::OnUpdateMaxFiles,
+                                AsWeakPtr()));
+    }
+#endif
     index_->Initialize(result.cache_dir_mtime);
   }
   callback.Run(result.net_error);
@@ -851,4 +867,13 @@
   base::TaskScheduler::GetInstance()->FlushForTesting();
 }
 
+#if defined(OS_POSIX) && !defined(OS_ANDROID)
+void SimpleBackendImpl::OnUpdateMaxFiles() {
+  int64_t available = base::SysInfo::AmountOfAvailableDiskInode(path_);
+  int64_t total = base::SysInfo::AmountOfMaxDiskInode(path_);
+  if (available != -1 && total != -1)
+    index_->UpdateMaxFiles(available, total);
+}
+#endif
+
 }  // namespace disk_cache
diff --git a/net/disk_cache/simple/simple_backend_impl.h b/net/disk_cache/simple/simple_backend_impl.h
index 370969b0..1190461 100644
--- a/net/disk_cache/simple/simple_backend_impl.h
+++ b/net/disk_cache/simple/simple_backend_impl.h
@@ -21,6 +21,7 @@
 #include "base/strings/string_split.h"
 #include "base/task_runner.h"
 #include "base/time/time.h"
+#include "build/build_config.h"
 #include "net/base/cache_type.h"
 #include "net/base/net_export.h"
 #include "net/disk_cache/disk_cache.h"
@@ -28,6 +29,10 @@
 #include "net/disk_cache/simple/simple_experiment.h"
 #include "net/disk_cache/simple/simple_index_delegate.h"
 
+#if defined(OS_POSIX) && !defined(OS_ANDROID)
+#include "base/timer/timer.h"
+#endif
+
 namespace base {
 class SequencedTaskRunner;
 class TaskRunner;
@@ -237,6 +242,11 @@
                            const CompletionCallback& callback,
                            int result);
 
+#if defined(OS_POSIX) && !defined(OS_ANDROID)
+  // update limit of max files to be created
+  void OnUpdateMaxFiles();
+#endif
+
   // We want this destroyed after every other field.
   scoped_refptr<BackendCleanupTracker> cleanup_tracker_;
 
@@ -266,6 +276,10 @@
       entries_pending_doom_;
 
   net::NetLog* const net_log_;
+
+#if defined(OS_POSIX) && !defined(OS_ANDROID)
+  base::RepeatingTimer update_timer_;
+#endif
 };
 
 }  // namespace disk_cache
diff --git a/net/disk_cache/simple/simple_index.cc b/net/disk_cache/simple/simple_index.cc
index a891458..3d4b702 100644
--- a/net/disk_cache/simple/simple_index.cc
+++ b/net/disk_cache/simple/simple_index.cc
@@ -155,6 +155,9 @@
       max_size_(0),
       high_watermark_(0),
       low_watermark_(0),
+      max_files_(0),
+      files_high_watermark_(0),
+      files_low_watermark_(0),
       eviction_in_progress_(false),
       initialized_(false),
       init_method_(INITIALIZE_METHOD_MAX),
@@ -347,7 +350,10 @@
 
 void SimpleIndex::StartEvictionIfNeeded() {
   DCHECK(io_thread_checker_.CalledOnValidThread());
-  if (eviction_in_progress_ || cache_size_ <= high_watermark_)
+  uint64_t cache_files = entries_set_.size();
+  if (eviction_in_progress_ ||
+      (cache_size_ <= high_watermark_ &&
+       (files_high_watermark_ == 0 || cache_files <= files_high_watermark_)))
     return;
   // Take all live key hashes from the index and sort them by time.
   eviction_in_progress_ = true;
@@ -378,13 +384,21 @@
   }
 
   uint64_t evicted_so_far_size = 0;
-  const uint64_t amount_to_evict = cache_size_ - low_watermark_;
+  const uint64_t amount_to_evict =
+      (cache_size_ > low_watermark_) ? cache_size_ - low_watermark_ : 0;
+  uint64_t evicted_files_count = 0;
+  const uint64_t file_amount_to_evict =
+      (files_low_watermark_ > 0 && cache_files > files_low_watermark_)
+          ? cache_files - files_low_watermark_
+          : 0;
   std::vector<uint64_t> entry_hashes;
   std::sort(entries.begin(), entries.end());
   for (const auto& score_metadata_pair : entries) {
-    if (evicted_so_far_size >= amount_to_evict)
+    if (evicted_so_far_size >= amount_to_evict &&
+        evicted_files_count >= file_amount_to_evict)
       break;
     evicted_so_far_size += score_metadata_pair.second->second.GetEntrySize();
+    evicted_files_count++;
     entry_hashes.push_back(score_metadata_pair.second->first);
   }
 
@@ -529,6 +543,10 @@
     io_thread_->PostTask(FROM_HERE, base::Bind((*it), net::OK));
   }
   to_run_when_initialized_.clear();
+  if (!update_max_files_cb_.is_null()) {
+    std::move(update_max_files_cb_).Run();
+    CHECK(update_max_files_cb_.is_null());
+  }
 }
 
 #if defined(OS_ANDROID)
@@ -581,4 +599,23 @@
                            app_on_background_, after_write);
 }
 
+void SimpleIndex::UpdateMaxFiles(uint64_t available, uint64_t total) {
+  DCHECK(io_thread_checker_.CalledOnValidThread());
+  if (!initialized_) {
+    update_max_files_cb_ = base::BindOnce(&SimpleIndex::UpdateMaxFiles,
+                                          AsWeakPtr(), available, total);
+    return;
+  }
+
+  auto cache_files = entries_set_.size();
+  uint64_t max_files = static_cast<uint64_t>((cache_files + available) * 0.3);
+  if (max_files_ == max_files)
+    return;
+
+  max_files_ = max_files;
+  files_high_watermark_ = max_files_ - max_files_ / kEvictionMarginDivisor;
+  files_low_watermark_ = max_files_ - 2 * (max_files_ / kEvictionMarginDivisor);
+  StartEvictionIfNeeded();
+}
+
 }  // namespace disk_cache
diff --git a/net/disk_cache/simple/simple_index.h b/net/disk_cache/simple/simple_index.h
index 0da8cd9..68c1024 100644
--- a/net/disk_cache/simple/simple_index.h
+++ b/net/disk_cache/simple/simple_index.h
@@ -194,6 +194,8 @@
 
   void SetLastUsedTimeForTest(uint64_t entry_hash, const base::Time last_used);
 
+  void UpdateMaxFiles(uint64_t available, uint64_t total);
+
  private:
   friend class SimpleIndexTest;
   FRIEND_TEST_ALL_PREFIXES(SimpleIndexTest, IndexSizeCorrectOnMerge);
@@ -231,6 +233,10 @@
   uint64_t max_size_;
   uint64_t high_watermark_;
   uint64_t low_watermark_;
+  uint64_t max_files_;  // Maximum number of files allowed (0 if unlimited).
+  // High and low thresholds for allowed number of files (0 if unlimited).
+  uint64_t files_high_watermark_;
+  uint64_t files_low_watermark_;
   bool eviction_in_progress_;
   base::TimeTicks eviction_start_time_;
 
@@ -255,6 +261,7 @@
 
   base::OneShotTimer write_to_disk_timer_;
   base::Closure write_to_disk_cb_;
+  base::OnceClosure update_max_files_cb_;
 
   typedef std::list<net::CompletionCallback> CallbackList;
   CallbackList to_run_when_initialized_;
diff --git a/net/disk_cache/simple/simple_index_unittest.cc b/net/disk_cache/simple/simple_index_unittest.cc
index 03a6bedc..7463c09 100644
--- a/net/disk_cache/simple/simple_index_unittest.cc
+++ b/net/disk_cache/simple/simple_index_unittest.cc
@@ -176,7 +176,7 @@
   }
   int doom_entries_calls() const { return doom_entries_calls_; }
 
-  const simple_util::ImmutableArray<uint64_t, 16> hashes_;
+  const simple_util::ImmutableArray<uint64_t, 20> hashes_;
   std::unique_ptr<SimpleIndex> index_;
   base::WeakPtr<MockSimpleIndexFile> index_file_;
 
@@ -697,6 +697,66 @@
   ASSERT_EQ(2u, last_doom_entry_hashes().size());
 }
 
+TEST_F(SimpleIndexTest, EvictByFileCount) {
+  base::Time now(base::Time::Now());
+  index()->SetMaxSize(50000);
+  InsertIntoIndexFileReturn(hashes_.at<0>(),
+                            now - base::TimeDelta::FromDays(21), 10u);
+  InsertIntoIndexFileReturn(hashes_.at<1>(),
+                            now - base::TimeDelta::FromDays(20), 10u);
+  InsertIntoIndexFileReturn(hashes_.at<2>(),
+                            now - base::TimeDelta::FromDays(19), 10u);
+  InsertIntoIndexFileReturn(hashes_.at<3>(),
+                            now - base::TimeDelta::FromDays(18), 10u);
+  InsertIntoIndexFileReturn(hashes_.at<4>(),
+                            now - base::TimeDelta::FromDays(17), 10u);
+  InsertIntoIndexFileReturn(hashes_.at<5>(),
+                            now - base::TimeDelta::FromDays(16), 10u);
+  InsertIntoIndexFileReturn(hashes_.at<6>(),
+                            now - base::TimeDelta::FromDays(15), 10u);
+  InsertIntoIndexFileReturn(hashes_.at<7>(),
+                            now - base::TimeDelta::FromDays(14), 10u);
+  InsertIntoIndexFileReturn(hashes_.at<8>(),
+                            now - base::TimeDelta::FromDays(13), 10u);
+  InsertIntoIndexFileReturn(hashes_.at<9>(),
+                            now - base::TimeDelta::FromDays(12), 10u);
+  InsertIntoIndexFileReturn(hashes_.at<10>(),
+                            now - base::TimeDelta::FromDays(11), 10u);
+  InsertIntoIndexFileReturn(hashes_.at<11>(),
+                            now - base::TimeDelta::FromDays(10), 10u);
+  InsertIntoIndexFileReturn(hashes_.at<12>(),
+                            now - base::TimeDelta::FromDays(9), 10u);
+  InsertIntoIndexFileReturn(hashes_.at<13>(),
+                            now - base::TimeDelta::FromDays(8), 10u);
+  InsertIntoIndexFileReturn(hashes_.at<14>(),
+                            now - base::TimeDelta::FromDays(7), 10u);
+  InsertIntoIndexFileReturn(hashes_.at<15>(),
+                            now - base::TimeDelta::FromDays(6), 10u);
+  InsertIntoIndexFileReturn(hashes_.at<16>(),
+                            now - base::TimeDelta::FromDays(5), 10u);
+  InsertIntoIndexFileReturn(hashes_.at<17>(),
+                            now - base::TimeDelta::FromDays(4), 10u);
+  index()->UpdateMaxFiles(50, 200);
+  // This should set the max files limit to 20, so the high watermark is 19 and
+  // the lower watermark is 18.
+  ReturnIndexFile();
+  WaitForTimeChange();
+
+  // No eviction should have happened yet.
+  EXPECT_EQ(18, index()->GetEntryCount());
+
+  index()->Insert(hashes_.at<18>());
+  index()->UpdateEntrySize(hashes_.at<18>(), 10u);
+  index()->Insert(hashes_.at<19>());
+  index()->UpdateEntrySize(hashes_.at<19>(), 10u);
+
+  // Eviction has happened, we get back to 18 elements
+  EXPECT_EQ(18, index()->GetEntryCount());
+  EXPECT_EQ(1, doom_entries_calls());
+  EXPECT_TRUE(index()->Has(hashes_.at<2>()));
+  EXPECT_FALSE(index()->Has(hashes_.at<1>()));
+}
+
 // Confirm all the operations queue a disk write at some point in the
 // future.
 TEST_F(SimpleIndexTest, DiskWriteQueued) {
diff --git a/net/dns/OWNERS b/net/dns/OWNERS
index 4be0e48..52b51f2 100644
--- a/net/dns/OWNERS
+++ b/net/dns/OWNERS
@@ -1,5 +1,3 @@
-mgersh@chromium.org
-
 per-file *_struct_traits*.*=set noparent
 per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
 
diff --git a/net/dns/dns_client.cc b/net/dns/dns_client.cc
index c1c9e419..6158b0a 100644
--- a/net/dns/dns_client.cc
+++ b/net/dns/dns_client.cc
@@ -15,10 +15,6 @@
 #include "net/dns/dns_transaction.h"
 #include "net/socket/client_socket_factory.h"
 
-namespace base {
-class Value;
-}
-
 namespace net {
 
 namespace {
@@ -58,18 +54,6 @@
 
   AddressSorter* GetAddressSorter() override { return address_sorter_.get(); }
 
-  std::unique_ptr<const base::Value> GetPersistentData() const override {
-    if (!session_)
-      return std::unique_ptr<const base::Value>();
-    return session_->GetPersistentData();
-  }
-
-  void ApplyPersistentData(const base::Value& data) override {
-    if (!session_)
-      return;
-    session_->ApplyPersistentData(data);
-  }
-
  private:
   scoped_refptr<DnsSession> session_;
   std::unique_ptr<DnsTransactionFactory> factory_;
diff --git a/net/dns/dns_client.h b/net/dns/dns_client.h
index 7809a910..57f823e 100644
--- a/net/dns/dns_client.h
+++ b/net/dns/dns_client.h
@@ -7,7 +7,6 @@
 
 #include <memory>
 
-#include "base/values.h"
 #include "net/base/net_export.h"
 #include "net/base/rand_callback.h"
 
@@ -39,13 +38,6 @@
   // Returns NULL if the current config is not valid.
   virtual AddressSorter* GetAddressSorter() = 0;
 
-  // Does nothing if the current config is not valid.
-  virtual void ApplyPersistentData(const base::Value& data) = 0;
-
-  // Returns std::unique_ptr<const Value>(NULL) if the current config is not
-  // valid.
-  virtual std::unique_ptr<const base::Value> GetPersistentData() const = 0;
-
   // Creates default client.
   static std::unique_ptr<DnsClient> CreateClient(NetLog* net_log);
 
diff --git a/net/dns/dns_session.cc b/net/dns/dns_session.cc
index 3e6efc1..85c7b09f 100644
--- a/net/dns/dns_session.cc
+++ b/net/dns/dns_session.cc
@@ -18,7 +18,6 @@
 #include "base/rand_util.h"
 #include "base/stl_util.h"
 #include "base/time/time.h"
-#include "base/values.h"
 #include "net/base/ip_endpoint.h"
 #include "net/base/net_errors.h"
 #include "net/dns/dns_config_service.h"
@@ -330,12 +329,6 @@
   return socket_pool_->CreateTCPSocket(server_index, source);
 }
 
-void DnsSession::ApplyPersistentData(const base::Value& data) {}
-
-std::unique_ptr<const base::Value> DnsSession::GetPersistentData() const {
-  return std::unique_ptr<const base::Value>();
-}
-
 // Release a socket.
 void DnsSession::FreeSocket(unsigned server_index,
                             std::unique_ptr<DatagramClientSocket> socket) {
diff --git a/net/dns/dns_session.h b/net/dns/dns_session.h
index 3a09d33..803a64d 100644
--- a/net/dns/dns_session.h
+++ b/net/dns/dns_session.h
@@ -114,9 +114,6 @@
   std::unique_ptr<StreamSocket> CreateTCPSocket(unsigned server_index,
                                                 const NetLogSource& source);
 
-  void ApplyPersistentData(const base::Value& data);
-  std::unique_ptr<const base::Value> GetPersistentData() const;
-
  private:
   friend class base::RefCounted<DnsSession>;
   ~DnsSession() override;
diff --git a/net/dns/dns_test_util.cc b/net/dns/dns_test_util.cc
index 8418d3b..186a7ef 100644
--- a/net/dns/dns_test_util.cc
+++ b/net/dns/dns_test_util.cc
@@ -232,12 +232,6 @@
   return address_sorter_.get();
 }
 
-void MockDnsClient::ApplyPersistentData(const base::Value& data) {}
-
-std::unique_ptr<const base::Value> MockDnsClient::GetPersistentData() const {
-  return std::unique_ptr<const base::Value>();
-}
-
 void MockDnsClient::CompleteDelayedTransactions() {
   factory_->CompleteDelayedTransactions();
 }
diff --git a/net/dns/dns_test_util.h b/net/dns/dns_test_util.h
index 133c33f..a991c33 100644
--- a/net/dns/dns_test_util.h
+++ b/net/dns/dns_test_util.h
@@ -204,8 +204,6 @@
   const DnsConfig* GetConfig() const override;
   DnsTransactionFactory* GetTransactionFactory() override;
   AddressSorter* GetAddressSorter() override;
-  void ApplyPersistentData(const base::Value& data) override;
-  std::unique_ptr<const base::Value> GetPersistentData() const override;
 
   // Completes all DnsTransactions that were delayed by a rule.
   void CompleteDelayedTransactions();
diff --git a/net/dns/host_cache.cc b/net/dns/host_cache.cc
index 41cab7cd..b900828 100644
--- a/net/dns/host_cache.cc
+++ b/net/dns/host_cache.cc
@@ -438,8 +438,6 @@
     }
   }
 
-  if (!eviction_callback_.is_null())
-    eviction_callback_.Run(oldest_it->first, oldest_it->second);
   RecordErase(ERASE_EVICT, now, oldest_it->second);
   entries_.erase(oldest_it);
 }
diff --git a/net/dns/host_cache.h b/net/dns/host_cache.h
index cb9c6ea..816c038 100644
--- a/net/dns/host_cache.h
+++ b/net/dns/host_cache.h
@@ -154,7 +154,6 @@
   };
 
   using EntryMap = std::map<Key, Entry>;
-  using EvictionCallback = base::Callback<void(const Key&, const Entry&)>;
 
   // Constructs a HostCache that stores up to |max_entries|.
   explicit HostCache(size_t max_entries);
@@ -193,10 +192,6 @@
   // Marks all entries as stale on account of a network change.
   void OnNetworkChange();
 
-  void set_eviction_callback(const EvictionCallback& callback) {
-    eviction_callback_ = callback;
-  }
-
   void set_persistence_delegate(PersistenceDelegate* delegate);
 
   // Empties the cache.
@@ -264,7 +259,6 @@
   EntryMap entries_;
   size_t max_entries_;
   int network_changes_;
-  EvictionCallback eviction_callback_;
   // Number of cache entries that were restored in the last call to
   // RestoreFromListValue(). Used in histograms.
   size_t restore_size_;
diff --git a/net/dns/host_cache_unittest.cc b/net/dns/host_cache_unittest.cc
index e95717d8..7f6e569 100644
--- a/net/dns/host_cache_unittest.cc
+++ b/net/dns/host_cache_unittest.cc
@@ -392,58 +392,6 @@
   EXPECT_TRUE(cache.Lookup(key3, now));
 }
 
-void TestEvictionCallback(int* evict_count,
-                          HostCache::Key* key_out,
-                          const HostCache::Key& key,
-                          const HostCache::Entry& entry) {
-  ++*evict_count;
-  *key_out = key;
-}
-
-// Try to add too many entries to cache; it should evict the one with the oldest
-// expiration time.
-TEST(HostCacheTest, EvictWithCallback) {
-  HostCache cache(2);
-
-  int evict_count = 0;
-  HostCache::Key evicted_key = Key("nothingevicted.com");
-  cache.set_eviction_callback(
-      base::Bind(&TestEvictionCallback, &evict_count, &evicted_key));
-
-  base::TimeTicks now;
-
-  HostCache::Key key1 = Key("foobar.com");
-  HostCache::Key key2 = Key("foobar2.com");
-  HostCache::Key key3 = Key("foobar3.com");
-  HostCache::Entry entry =
-      HostCache::Entry(OK, AddressList(), HostCache::Entry::SOURCE_UNKNOWN);
-
-  EXPECT_EQ(0u, cache.size());
-  EXPECT_FALSE(cache.Lookup(key1, now));
-  EXPECT_FALSE(cache.Lookup(key2, now));
-  EXPECT_FALSE(cache.Lookup(key3, now));
-
-  // |key1| expires in 10 seconds, but |key2| in just 5.
-  cache.Set(key1, entry, now, base::TimeDelta::FromSeconds(10));
-  cache.Set(key2, entry, now, base::TimeDelta::FromSeconds(5));
-  EXPECT_EQ(2u, cache.size());
-  EXPECT_TRUE(cache.Lookup(key1, now));
-  EXPECT_TRUE(cache.Lookup(key2, now));
-  EXPECT_FALSE(cache.Lookup(key3, now));
-
-  EXPECT_EQ(0, evict_count);
-
-  // |key2| should be chosen for eviction, since it expires sooner.
-  cache.Set(key3, entry, now, base::TimeDelta::FromSeconds(10));
-  EXPECT_EQ(2u, cache.size());
-  EXPECT_TRUE(cache.Lookup(key1, now));
-  EXPECT_FALSE(cache.Lookup(key2, now));
-  EXPECT_TRUE(cache.Lookup(key3, now));
-
-  EXPECT_EQ(1, evict_count);
-  EXPECT_EQ(key2.hostname, evicted_key.hostname);
-}
-
 // Try to retrieve stale entries from the cache. They should be returned by
 // |LookupStale()| but not |Lookup()|, with correct |EntryStaleness| data.
 TEST(HostCacheTest, Stale) {
diff --git a/net/dns/host_resolver.cc b/net/dns/host_resolver.cc
index 165fb00..3986b87 100644
--- a/net/dns/host_resolver.cc
+++ b/net/dns/host_resolver.cc
@@ -120,10 +120,6 @@
   return nullptr;
 }
 
-void HostResolver::InitializePersistence(
-    const PersistCallback& persist_callback,
-    std::unique_ptr<const base::Value> old_data) {}
-
 void HostResolver::SetNoIPv6OnWifi(bool no_ipv6_on_wifi) {
   NOTREACHED();
 }
diff --git a/net/dns/host_resolver.h b/net/dns/host_resolver.h
index 7876d87..43d251c1 100644
--- a/net/dns/host_resolver.h
+++ b/net/dns/host_resolver.h
@@ -208,16 +208,6 @@
   // nullptr if it's configured to always use the system host resolver.
   virtual std::unique_ptr<base::Value> GetDnsConfigAsValue() const;
 
-  typedef base::Callback<void(std::unique_ptr<const base::Value>)>
-      PersistCallback;
-  // Configures the HostResolver to be able to persist data (e.g. observed
-  // performance) between sessions. |persist_callback| is a callback that will
-  // be called when the HostResolver wants to persist data; |old_data| is the
-  // data last persisted by the resolver on the previous session.
-  virtual void InitializePersistence(
-      const PersistCallback& persist_callback,
-      std::unique_ptr<const base::Value> old_data);
-
   // Sets the HostResolver to assume that IPv6 is unreachable when on a wifi
   // connection. See https://crbug.com/696569 for further context.
   virtual void SetNoIPv6OnWifi(bool no_ipv6_on_wifi);
diff --git a/net/dns/host_resolver_impl.cc b/net/dns/host_resolver_impl.cc
index 039fc9c1..3a279aa 100644
--- a/net/dns/host_resolver_impl.cc
+++ b/net/dns/host_resolver_impl.cc
@@ -562,9 +562,6 @@
   stale_info->stale_hits = 0;
 }
 
-// Persist data every five minutes (potentially, cache and learned RTT).
-const int64_t kPersistDelaySec = 300;
-
 }  // namespace
 
 //-----------------------------------------------------------------------------
@@ -670,6 +667,9 @@
 
 // Calls HostResolverProc in TaskScheduler. Performs retries if necessary.
 //
+// In non-test code, the HostResolverProc is always SystemHostResolverProc,
+// which calls a platform API that implements host resolution.
+//
 // Whenever we try to resolve the host, we post a delayed task to check if host
 // resolution (OnLookupComplete) is completed or not. If the original attempt
 // hasn't completed, then we start another attempt for host resolution. We take
@@ -966,7 +966,11 @@
 
 //-----------------------------------------------------------------------------
 
-// Resolves the hostname using DnsTransaction.
+// Resolves the hostname using DnsTransaction, which is a full implementation of
+// a DNS stub resolver. One DnsTransaction is created for each resolution
+// needed, which for AF_UNSPEC resolutions includes both A and AAAA. The
+// transactions are scheduled separately and started separately.
+//
 // TODO(szym): This could be moved to separate source file as well.
 class HostResolverImpl::DnsTask : public base::SupportsWeakPtr<DnsTask> {
  public:
@@ -1769,8 +1773,6 @@
     net_log_.EndEventWithNetErrorCode(NetLogEventType::HOST_RESOLVER_IMPL_JOB,
                                       entry.error());
 
-    resolver_->SchedulePersist();
-
     DCHECK(!requests_.empty());
 
     if (entry.error() == OK || entry.error() == ERR_ICANN_NAME_COLLISION) {
@@ -1977,7 +1979,6 @@
       last_ipv6_probe_result_(true),
       additional_resolver_flags_(0),
       fallback_to_proctask_(true),
-      persist_initialized_(false),
       weak_ptr_factory_(this),
       probe_weak_ptr_factory_(this) {
   if (options.enable_caching)
@@ -2645,36 +2646,6 @@
   AbortDnsTasks();
 }
 
-void HostResolverImpl::InitializePersistence(
-    const PersistCallback& persist_callback,
-    std::unique_ptr<const base::Value> old_data) {
-  DCHECK(!persist_initialized_);
-  persist_callback_ = persist_callback;
-  persist_initialized_ = true;
-  if (old_data)
-    ApplyPersistentData(std::move(old_data));
-}
-
-void HostResolverImpl::ApplyPersistentData(
-    std::unique_ptr<const base::Value> data) {}
-
-std::unique_ptr<const base::Value> HostResolverImpl::GetPersistentData() {
-  return std::unique_ptr<const base::Value>();
-}
-
-void HostResolverImpl::SchedulePersist() {
-  if (!persist_initialized_ || persist_timer_.IsRunning())
-    return;
-  persist_timer_.Start(
-      FROM_HERE, base::TimeDelta::FromSeconds(kPersistDelaySec),
-      base::Bind(&HostResolverImpl::DoPersist, weak_ptr_factory_.GetWeakPtr()));
-}
-
-void HostResolverImpl::DoPersist() {
-  DCHECK(persist_initialized_);
-  persist_callback_.Run(GetPersistentData());
-}
-
 HostResolverImpl::RequestImpl::~RequestImpl() {
   if (job_)
     job_->CancelRequest(this);
diff --git a/net/dns/host_resolver_impl.h b/net/dns/host_resolver_impl.h
index 0eada32f2..c98b12a 100644
--- a/net/dns/host_resolver_impl.h
+++ b/net/dns/host_resolver_impl.h
@@ -31,11 +31,11 @@
 class NetLogWithSource;
 
 // For each hostname that is requested, HostResolver creates a
-// HostResolverImpl::Job. When this job gets dispatched it creates a ProcTask
-// which runs the given HostResolverProc in TaskScheduler. If requests for that
-// same host are made during the job's lifetime, they are attached to the
-// existing job rather than creating a new one. This avoids doing parallel
-// resolves for the same host.
+// HostResolverImpl::Job. When this job gets dispatched it creates a task
+// (ProcTask for the system resolver or DnsTask for the async resolver) which
+// resolves the hostname. If requests for that same host are made during the
+// job's lifetime, they are attached to the existing job rather than creating a
+// new one. This avoids doing parallel resolves for the same host.
 //
 // The way these classes fit together is illustrated by:
 //
@@ -159,10 +159,6 @@
   // Returns the number of entries in the host cache, or 0 if there is no cache.
   size_t CacheSize() const;
 
-  void InitializePersistence(
-      const PersistCallback& persist_callback,
-      std::unique_ptr<const base::Value> old_data) override;
-
   void SetNoIPv6OnWifi(bool no_ipv6_on_wifi) override;
   bool GetNoIPv6OnWifi() override;
 
@@ -316,12 +312,6 @@
   // and resulted in |net_error|.
   void OnDnsTaskResolve(int net_error);
 
-  void ApplyPersistentData(std::unique_ptr<const base::Value>);
-  std::unique_ptr<const base::Value> GetPersistentData();
-
-  void SchedulePersist();
-  void DoPersist();
-
   // Allows the tests to catch slots leaking out of the dispatcher.  One
   // HostResolverImpl::Job could occupy multiple PrioritizedDispatcher job
   // slots.
@@ -377,10 +367,6 @@
   // TaskScheduler task runner, but can be overridden for tests.
   scoped_refptr<base::TaskRunner> proc_task_runner_;
 
-  bool persist_initialized_;
-  PersistCallback persist_callback_;
-  base::OneShotTimer persist_timer_;
-
   URLRequestContext* url_request_context_;
   std::vector<DnsConfig::DnsOverHttpsServerConfig> dns_over_https_servers_;
 
diff --git a/net/dns/host_resolver_impl_unittest.cc b/net/dns/host_resolver_impl_unittest.cc
index cbf1dec0..f9d485a9 100644
--- a/net/dns/host_resolver_impl_unittest.cc
+++ b/net/dns/host_resolver_impl_unittest.cc
@@ -25,6 +25,7 @@
 #include "base/threading/thread_restrictions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
+#include "base/values.h"
 #include "net/base/address_list.h"
 #include "net/base/ip_address.h"
 #include "net/base/mock_network_change_notifier.h"
diff --git a/net/docs/host-resolver.md b/net/docs/host-resolver.md
new file mode 100644
index 0000000..263b8d0f
--- /dev/null
+++ b/net/docs/host-resolver.md
@@ -0,0 +1,102 @@
+# Host Resolution
+
+This document is a brief overview of how host resolution works in the Chrome
+network stack.
+
+The stack includes two different implementations: the "system" or "platform"
+resolver, and the "async" or "built-in" resolver. The higher layers are shared
+between the implementations, and the lower layers are implemented separately.
+
+## Shared layers
+
+### Host resolver
+
+The HostResolverImpl is the main interface between DNS and the rest of the
+network stack. It checks the HostCache, checks if there is an already running
+Job, and schedules a new Job if there isn't one in progress.
+
+Data collected at this layer:
+* "Net.DNS.TotalTime" (recommended for DNS experiments)
+* "Net.DNS.TotalTimeNotCached"
+
+### Job
+
+The HostResolverImpl::Job represents a single DNS resolution from the network
+(or in some cases the OS's DNS cache, which Chrome doesn't know about). It
+starts a task depending on which implementation should be used. If a DnsTask
+fails, it retries using a ProcTask.
+
+Data collected at this layer:
+* "Net.DNS.ResolveSuccessTime" (also by address family)
+* "Net.DNS.ResolveFailureTime" (also by address family)
+* "Net.DNS.ResolveCategory"
+* "Net.DNS.ResolveError.Fast"
+* "Net.DNS.ResolveError.Slow"
+
+## System resolver
+
+### Task
+
+The entry point for the system resolver is HostResolverImpl::ProcTask. The task
+runs almost entirely on TaskScheduler. Its main implementation is in
+SystemHostResolverProc. Other implementations of HostResolverProc can be swapped
+in for testing.
+
+Data collected at this layer:
+* "Net.DNS.ProcTask.SuccessTime"
+* "Net.DNS.ProcTask.FailureTime"
+* "Net.OSErrorsForGetaddrinfo*"
+
+### Attempt
+
+Attempts in the system resolver are not a separate class. They're implemented as
+separate tasks posted to TaskScheduler.
+
+Data collected at this layer:
+* "DNS.AttemptFirstSuccess"
+* "DNS.AttemptFirstFailure"
+* "DNS.AttemptSuccess"
+* "DNS.AttemptFailure"
+* "DNS.AttemptDiscarded"
+* "DNS.AttemptCancelled"
+* "DNS.AttemptSuccessDuration"
+* "DNS.AttemptFailDuration"
+
+## Async resolver
+
+### Task
+
+The entry point for the async resolver is HostResolverImpl::DnsTask. DnsTask
+starts one DnsTransaction for each lookup needed, which can be one for a single
+address family or two when both A and AAAA are needed.
+
+Data collected at this layer:
+* "Net.DNS.DnsTask.SuccessTime"
+* "Net.DNS.DnsTask.FailureTime"
+* "Net.DNS.DnsTask.ErrorBeforeFallback.Fast"
+* "Net.DNS.DnsTask.ErrorBeforeFallback.Slow"
+* "Net.DNS.DnsTask.Errors"
+
+### Transaction
+
+The main implementation of the async resolver is in the DnsTransaction. Each
+transaction represents a single query, which might be tried multiple times or in
+different ways.
+
+Data collected at this layer:
+* "AsyncDNS.TransactionFailure"
+* "AsyncDNS.TransactionSuccess" (and by query type)
+
+### Attempt
+
+Attempts in the async resolver are an explicit layer, implemented by subclasses
+of DnsAttempt. In most cases, DnsUDPAttempt is used. DnsTCPAttempt is used
+instead when the server requests it. DnsHTTPAttempt is experimental.
+
+Data collected at this layer:
+* "AsyncDNS.UDPAttemptSuccess"
+* "AsyncDNS.UDPAttemptFail"
+* "AsyncDNS.TCPAttemptSuccess"
+* "AsyncDNS.TCPAttemptFail"
+* "AsyncDNS.AttemptCountSuccess"
+* "AsyncDNS.AttemptCountFail"
diff --git a/net/extras/sqlite/sqlite_persistent_cookie_store.cc b/net/extras/sqlite/sqlite_persistent_cookie_store.cc
index 4c46ce71..37b56ded 100644
--- a/net/extras/sqlite/sqlite_persistent_cookie_store.cc
+++ b/net/extras/sqlite/sqlite_persistent_cookie_store.cc
@@ -48,6 +48,16 @@
   COOKIE_LOAD_PROBLEM_LAST_ENTRY
 };
 
+// Used to report a histogram on status of cookie commit to disk.
+//
+// Please do not reorder or remove entries. New entries must be added to the
+// end of the list, just before BACKING_STORE_RESULTS_LAST_ENTRY.
+enum BackingStoreResults {
+  BACKING_STORE_RESULTS_SUCCESS = 0,
+  BACKING_STORE_RESULTS_FAILURE = 1,
+  BACKING_STORE_RESULTS_LAST_ENTRY
+};
+
 void RecordCookieLoadProblem(CookieLoadProblem event) {
   UMA_HISTOGRAM_ENUMERATION("Cookie.LoadProblem", event,
                             COOKIE_LOAD_PROBLEM_LAST_ENTRY);
@@ -1323,8 +1333,10 @@
     }
   }
   bool succeeded = transaction.Commit();
-  UMA_HISTOGRAM_ENUMERATION("Cookie.BackingStoreUpdateResults",
-                            succeeded ? 0 : 1, 2);
+  UMA_HISTOGRAM_ENUMERATION(
+      "Cookie.BackingStoreUpdateResults",
+      succeeded ? BACKING_STORE_RESULTS_SUCCESS : BACKING_STORE_RESULTS_FAILURE,
+      BACKING_STORE_RESULTS_LAST_ENTRY);
 }
 
 void SQLitePersistentCookieStore::Backend::SetBeforeFlushCallback(
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc
index 45a38a88..10eafcf 100644
--- a/net/http/http_cache_transaction.cc
+++ b/net/http/http_cache_transaction.cc
@@ -2510,8 +2510,9 @@
 int HttpCache::Transaction::ValidateEntryHeadersAndContinue() {
   DCHECK_EQ(mode_, READ_WRITE);
 
-  if (!partial_->UpdateFromStoredHeaders(
-          response_.headers.get(), entry_->disk_entry, truncated_)) {
+  if (!partial_->UpdateFromStoredHeaders(response_.headers.get(),
+                                         entry_->disk_entry, truncated_,
+                                         cache_->IsWritingInProgress(entry_))) {
     return DoRestartPartialRequest();
   }
 
diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc
index 690f67a..0d122b2 100644
--- a/net/http/http_cache_unittest.cc
+++ b/net/http/http_cache_unittest.cc
@@ -19,6 +19,7 @@
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/stl_util.h"
+#include "base/strings/strcat.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
@@ -2062,6 +2063,89 @@
   }
 }
 
+// Tests a 200 request and a simultaneous range request where conditionalization
+// is possible.
+TEST(HttpCache, RangeGET_ParallelValidationCouldConditionalize) {
+  MockHttpCache cache;
+
+  MockTransaction mock_transaction(kSimpleGET_Transaction);
+  mock_transaction.url = kRangeGET_TransactionOK.url;
+  mock_transaction.data = kFullRangeData;
+  std::string response_headers_str = base::StrCat(
+      {"ETag: StrongOne\n",
+       "Content-Length:", base::IntToString(strlen(kFullRangeData)), "\n"});
+  mock_transaction.response_headers = response_headers_str.c_str();
+
+  ScopedMockTransaction transaction(mock_transaction);
+
+  std::vector<std::unique_ptr<Context>> context_list;
+  const int kNumTransactions = 2;
+
+  for (int i = 0; i < kNumTransactions; ++i) {
+    context_list.push_back(std::make_unique<Context>());
+  }
+
+  // Let 1st transaction complete headers phase for no range and read some part
+  // of the response and write in the cache.
+  std::string first_read;
+  MockHttpRequest request1(transaction);
+  {
+    request1.url = GURL(kRangeGET_TransactionOK.url);
+    auto& c = context_list[0];
+    c->result = cache.CreateTransaction(&c->trans);
+    ASSERT_THAT(c->result, IsOk());
+    EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
+
+    c->result =
+        c->trans->Start(&request1, c->callback.callback(), NetLogWithSource());
+    base::RunLoop().RunUntilIdle();
+
+    const int kBufferSize = 5;
+    scoped_refptr<IOBuffer> buffer(new IOBuffer(kBufferSize));
+    ReleaseBufferCompletionCallback cb(buffer.get());
+    c->result = c->trans->Read(buffer.get(), kBufferSize, cb.callback());
+    EXPECT_EQ(kBufferSize, cb.GetResult(c->result));
+
+    std::string data_read(buffer->data(), kBufferSize);
+    first_read = data_read;
+
+    EXPECT_EQ(LOAD_STATE_READING_RESPONSE, c->trans->GetLoadState());
+  }
+
+  // 2nd transaction requests a range.
+  ScopedMockTransaction range_transaction(kRangeGET_TransactionOK);
+  range_transaction.request_headers = "Range: bytes = 0-29\r\n" EXTRA_HEADER;
+  MockHttpRequest request2(range_transaction);
+  {
+    auto& c = context_list[1];
+    c->result = cache.CreateTransaction(&c->trans);
+    ASSERT_THAT(c->result, IsOk());
+    EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
+
+    c->result =
+        c->trans->Start(&request2, c->callback.callback(), NetLogWithSource());
+    base::RunLoop().RunUntilIdle();
+
+    EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState());
+  }
+
+  EXPECT_EQ(2, cache.network_layer()->transaction_count());
+  EXPECT_EQ(0, cache.disk_cache()->open_count());
+  EXPECT_EQ(1, cache.disk_cache()->create_count());
+
+  // Finish and verify the first request.
+  auto& c0 = context_list[0];
+  c0->result = c0->callback.WaitForResult();
+  ReadRemainingAndVerifyTransaction(c0->trans.get(), first_read, transaction);
+
+  // And the second.
+  auto& c1 = context_list[1];
+  c1->result = c1->callback.WaitForResult();
+
+  range_transaction.data = "rg: 00-09 rg: 10-19 rg: 20-29 ";
+  ReadAndVerifyTransaction(c1->trans.get(), range_transaction);
+}
+
 // Tests parallel validation on range requests with overlapping ranges.
 TEST(HttpCache, RangeGET_ParallelValidationOverlappingRanges) {
   MockHttpCache cache;
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index 03acaca8..e1bb8dcf 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -576,8 +576,6 @@
 
   void ConnectStatusHelper(const MockRead& status);
 
-  void BypassHostCacheOnRefreshHelper(int load_flags);
-
   void CheckErrorIsPassedBack(int error, IoMode mode);
 
   SpdyTestUtil spdy_util_;
@@ -10404,14 +10402,12 @@
   EXPECT_THAT(rv, IsError(ERR_PROXY_CONNECTION_FAILED));
 }
 
-// Base test to make sure that when the load flags for a request specify to
-// bypass the cache, the DNS cache is not used.
-void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
-    int load_flags) {
+// LOAD_BYPASS_CACHE should trigger the host cache bypass.
+TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh) {
   // Issue a request, asking to bypass the cache(s).
   HttpRequestInfo request_info;
   request_info.method = "GET";
-  request_info.load_flags = load_flags;
+  request_info.load_flags = LOAD_BYPASS_CACHE;
   request_info.url = GURL("http://www.example.org/");
   request_info.traffic_annotation =
       net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
@@ -10464,20 +10460,6 @@
   EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
 }
 
-// There are multiple load flags that should trigger the host cache bypass.
-// Test each in isolation:
-TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
-  BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
-}
-
-TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
-  BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
-}
-
-TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
-  BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
-}
-
 // Make sure we can handle an error when writing the request.
 TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
   HttpRequestInfo request;
diff --git a/net/http/http_stream_factory_impl_job.cc b/net/http/http_stream_factory_impl_job.cc
index 9e8571b6..c90a039 100644
--- a/net/http/http_stream_factory_impl_job.cc
+++ b/net/http/http_stream_factory_impl_job.cc
@@ -1051,8 +1051,14 @@
         net_log_.AddEvent(
             NetLogEventType::HTTP_STREAM_REQUEST_PROTO,
             base::Bind(&NetLogHttpStreamProtoCallback, negotiated_protocol_));
-        if (negotiated_protocol_ == kProtoHTTP2)
+        if (negotiated_protocol_ == kProtoHTTP2) {
+          // If request is WebSocket, HTTP/2 must not have been advertised in
+          // the TLS handshake.  The TLS layer must not have accepted the
+          // server choosing HTTP/2.
+          // TODO(bnc): Change to DCHECK once https://crbug.com/819101 is fixed.
+          CHECK(!is_websocket_);
           using_spdy_ = true;
+        }
       }
     }
   } else if (proxy_info_.is_https() && connection_->socket() &&
@@ -1078,7 +1084,7 @@
     // complete the auth (or read the response body).  The tunnel restart code
     // is careful to remove it before returning control to the rest of this
     // class.
-    connection_.reset(connection_->release_pending_http_proxy_connection());
+    connection_ = connection_->release_pending_http_proxy_connection();
     return result;
   }
 
@@ -1213,6 +1219,10 @@
 
   CHECK(!stream_.get());
 
+  // WebSocket over HTTP/2 is only allowed to use existing connections.
+  // TODO(bnc): Change to DCHECK once https://crbug.com/819101 is fixed.
+  CHECK(!is_websocket_ || existing_spdy_session_);
+
   // It is possible that a pushed stream has been opened by a server since last
   // time Job checked above.
   if (!existing_spdy_session_) {
diff --git a/net/http/partial_data.cc b/net/http/partial_data.cc
index 4f92b18..5a71e198 100644
--- a/net/http/partial_data.cc
+++ b/net/http/partial_data.cc
@@ -181,7 +181,8 @@
 
 bool PartialData::UpdateFromStoredHeaders(const HttpResponseHeaders* headers,
                                           disk_cache::Entry* entry,
-                                          bool truncated) {
+                                          bool truncated,
+                                          bool writing_in_progress) {
   resource_size_ = 0;
   if (truncated) {
     DCHECK_EQ(headers->response_code(), 200);
@@ -224,25 +225,39 @@
     return true;
   }
 
-  if (headers->response_code() != 206) {
-    DCHECK(byte_range_.IsValid());
-    sparse_entry_ = false;
+  sparse_entry_ = (headers->response_code() == 206);
+
+  if (writing_in_progress || sparse_entry_) {
+    // |writing_in_progress| means another Transaction is still fetching the
+    // body, so the only way we can see the length is if the server sent it
+    // in Content-Length -- GetDataSize would just return what got written
+    // thus far.
+    //
+    // |sparse_entry_| means a 206, and for those FixContentLength arranges it
+    // so that Content-Length written to the cache has the full length (on wire
+    // it's for a particular range only); while GetDataSize would be unusable
+    // since the data is stored using WriteSparseData, and not in the usual data
+    // stream.
+    resource_size_ = headers->GetContentLength();
+    if (resource_size_ <= 0)
+      return false;
+  } else {
+    // If we can safely use GetDataSize, it's preferrable since it's usable for
+    // things w/o Content-Length, such as chunked content.
     resource_size_ = entry->GetDataSize(kDataStream);
-    DVLOG(2) << "UpdateFromStoredHeaders size: " << resource_size_;
-    return true;
   }
 
-  if (!headers->HasStrongValidators())
-    return false;
+  DVLOG(2) << "UpdateFromStoredHeaders size: " << resource_size_;
 
-  int64_t length_value = headers->GetContentLength();
-  if (length_value <= 0)
-    return false;  // We must have stored the resource length.
-
-  resource_size_ = length_value;
-
-  // Make sure that this is really a sparse entry.
-  return entry->CouldBeSparse();
+  if (sparse_entry_) {
+    // If our previous is a 206, we need strong validators as we may be
+    // stiching the cached data and network data together.
+    if (!headers->HasStrongValidators())
+      return false;
+    // Make sure that this is really a sparse entry.
+    return entry->CouldBeSparse();
+  }
+  return true;
 }
 
 void PartialData::SetRangeToStartDownload() {
diff --git a/net/http/partial_data.h b/net/http/partial_data.h
index a20d87a..68dd500f 100644
--- a/net/http/partial_data.h
+++ b/net/http/partial_data.h
@@ -73,9 +73,13 @@
 
   // Extracts info from headers already stored in the cache. Returns false if
   // there is any problem with the headers. |truncated| should be true if we
-  // have an incomplete 200 entry.
+  // have an incomplete 200 entry due to a transfer having been interrupted.
+  // |writing_in_progress| should be set to true if a transfer for this entry's
+  // payload is still in progress.
   bool UpdateFromStoredHeaders(const HttpResponseHeaders* headers,
-                               disk_cache::Entry* entry, bool truncated);
+                               disk_cache::Entry* entry,
+                               bool truncated,
+                               bool writing_in_progress);
 
   // Sets the byte current range to start again at zero (for a truncated entry).
   void SetRangeToStartDownload();
diff --git a/net/http/transport_security_state.cc b/net/http/transport_security_state.cc
index cd4e9c7..8a0d7968 100644
--- a/net/http/transport_security_state.cc
+++ b/net/http/transport_security_state.cc
@@ -33,7 +33,7 @@
 #include "net/cert/x509_certificate.h"
 #include "net/dns/dns_util.h"
 #include "net/http/http_security_headers.h"
-#include "net/net_features.h"
+#include "net/net_buildflags.h"
 #include "net/ssl/ssl_info.h"
 
 namespace net {
diff --git a/net/http/transport_security_state_unittest.cc b/net/http/transport_security_state_unittest.cc
index 67aebbb..a09caf6 100644
--- a/net/http/transport_security_state_unittest.cc
+++ b/net/http/transport_security_state_unittest.cc
@@ -35,7 +35,7 @@
 #include "net/cert/x509_certificate.h"
 #include "net/http/http_status_code.h"
 #include "net/http/http_util.h"
-#include "net/net_features.h"
+#include "net/net_buildflags.h"
 #include "net/ssl/ssl_info.h"
 #include "net/test/cert_test_util.h"
 #include "net/test/test_data_directory.h"
diff --git a/net/network_error_logging/network_error_logging_service.cc b/net/network_error_logging/network_error_logging_service.cc
index df848b64..b838000 100644
--- a/net/network_error_logging/network_error_logging_service.cc
+++ b/net/network_error_logging/network_error_logging_service.cc
@@ -11,6 +11,7 @@
 #include "base/json/json_reader.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_macros.h"
 #include "base/rand_util.h"
 #include "base/time/default_tick_clock.h"
 #include "base/time/tick_clock.h"
@@ -122,6 +123,54 @@
   return request.type == OK && !IsHttpError(request);
 }
 
+enum class HeaderOutcome {
+  DISCARDED_NO_NETWORK_ERROR_LOGGING_SERVICE = 0,
+  DISCARDED_INVALID_SSL_INFO = 1,
+  DISCARDED_CERT_STATUS_ERROR = 2,
+
+  DISCARDED_INSECURE_ORIGIN = 3,
+
+  DISCARDED_JSON_TOO_BIG = 4,
+  DISCARDED_JSON_INVALID = 5,
+  DISCARDED_NOT_DICTIONARY = 6,
+  DISCARDED_TTL_MISSING = 7,
+  DISCARDED_TTL_NOT_INTEGER = 8,
+  DISCARDED_TTL_NEGATIVE = 9,
+  DISCARDED_REPORT_TO_MISSING = 10,
+  DISCARDED_REPORT_TO_NOT_STRING = 11,
+
+  REMOVED = 12,
+  SET = 13,
+
+  MAX
+};
+
+void RecordHeaderOutcome(HeaderOutcome outcome) {
+  UMA_HISTOGRAM_ENUMERATION("Net.NetworkErrorLogging.HeaderOutcome", outcome,
+                            HeaderOutcome::MAX);
+}
+
+enum class RequestOutcome {
+  DISCARDED_NO_NETWORK_ERROR_LOGGING_SERVICE = 0,
+
+  DISCARDED_NO_REPORTING_SERVICE = 1,
+  DISCARDED_INSECURE_ORIGIN = 2,
+  DISCARDED_NO_ORIGIN_POLICY = 3,
+  DISCARDED_UNMAPPED_ERROR = 4,
+  DISCARDED_REPORTING_UPLOAD = 5,
+  DISCARDED_UNSAMPLED_SUCCESS = 6,
+  DISCARDED_UNSAMPLED_FAILURE = 7,
+
+  QUEUED = 8,
+
+  MAX
+};
+
+void RecordRequestOutcome(RequestOutcome outcome) {
+  UMA_HISTOGRAM_ENUMERATION("Net.NetworkErrorLogging.RequestOutcome", outcome,
+                            RequestOutcome::MAX);
+}
+
 class NetworkErrorLoggingServiceImpl : public NetworkErrorLoggingService {
  public:
   explicit NetworkErrorLoggingServiceImpl(
@@ -130,18 +179,23 @@
     DCHECK(delegate_);
   }
 
-  // NetworkErrorLoggingService implementation:
-
   ~NetworkErrorLoggingServiceImpl() override = default;
 
+  // NetworkErrorLoggingService implementation:
+
   void OnHeader(const url::Origin& origin, const std::string& value) override {
     // NEL is only available to secure origins, so don't permit insecure origins
     // to set policies.
-    if (!origin.GetURL().SchemeIsCryptographic())
+    if (!origin.GetURL().SchemeIsCryptographic()) {
+      RecordHeaderOutcome(HeaderOutcome::DISCARDED_INSECURE_ORIGIN);
       return;
+    }
 
     OriginPolicy policy;
-    if (!ParseHeader(value, tick_clock_->NowTicks(), &policy))
+    HeaderOutcome outcome =
+        ParseHeader(value, tick_clock_->NowTicks(), &policy);
+    RecordHeaderOutcome(outcome);
+    if (outcome != HeaderOutcome::SET && outcome != HeaderOutcome::REMOVED)
       return;
 
     PolicyMap::iterator it = policies_.find(origin);
@@ -159,43 +213,62 @@
   }
 
   void OnRequest(const RequestDetails& details) override {
-    if (!reporting_service_)
+    if (!reporting_service_) {
+      RecordRequestOutcome(RequestOutcome::DISCARDED_NO_REPORTING_SERVICE);
       return;
-
-    // It is expected for Reporting uploads to terminate with ERR_ABORTED, since
-    // the ReportingUploader cancels them after receiving the response code and
-    // headers.
-    if (details.is_reporting_upload && details.type == ERR_ABORTED)
-      return;
+    }
 
     // NEL is only available to secure origins, so ignore network errors from
     // insecure origins. (The check in OnHeader prevents insecure origins from
     // setting policies, but this check is needed to ensure that insecure
     // origins can't match wildcard policies from secure origins.)
-    if (!details.uri.SchemeIsCryptographic())
+    if (!details.uri.SchemeIsCryptographic()) {
+      RecordRequestOutcome(RequestOutcome::DISCARDED_INSECURE_ORIGIN);
       return;
+    }
 
     const OriginPolicy* policy =
         FindPolicyForOrigin(url::Origin::Create(details.uri));
-    if (!policy)
+    if (!policy) {
+      RecordRequestOutcome(RequestOutcome::DISCARDED_NO_ORIGIN_POLICY);
       return;
+    }
 
     std::string type_string;
-    if (!GetTypeFromNetError(details.type, &type_string))
+    if (!GetTypeFromNetError(details.type, &type_string)) {
+      RecordRequestOutcome(RequestOutcome::DISCARDED_UNMAPPED_ERROR);
       return;
+    }
+
+    // It is expected for Reporting uploads to terminate with ERR_ABORTED, since
+    // the ReportingUploader cancels them after receiving the response code and
+    // headers.
+    //
+    // (This check would go earlier, but the histogram bucket will be more
+    // meaningful if it only includes reports that otherwise could have been
+    // uploaded.)
+    if (details.is_reporting_upload && details.type == ERR_ABORTED) {
+      RecordRequestOutcome(RequestOutcome::DISCARDED_REPORTING_UPLOAD);
+      return;
+    }
 
     if (IsHttpError(details))
       type_string = kHttpErrorType;
 
-    double sampling_fraction = RequestWasSuccessful(details)
-                                   ? policy->success_fraction
-                                   : policy->failure_fraction;
-    if (base::RandDouble() >= sampling_fraction)
+    bool success = RequestWasSuccessful(details);
+    double sampling_fraction =
+        success ? policy->success_fraction : policy->failure_fraction;
+    if (base::RandDouble() >= sampling_fraction) {
+      RecordRequestOutcome(success
+                               ? RequestOutcome::DISCARDED_UNSAMPLED_SUCCESS
+                               : RequestOutcome::DISCARDED_UNSAMPLED_FAILURE);
       return;
+    }
 
     reporting_service_->QueueReport(
         details.uri, policy->report_to, kReportType,
         CreateReportBody(type_string, sampling_fraction, details));
+    RecordRequestOutcome(RequestOutcome::QUEUED);
   }
 
   void RemoveBrowsingData(const base::RepeatingCallback<bool(const GURL&)>&
@@ -255,30 +328,38 @@
   PolicyMap policies_;
   WildcardPolicyMap wildcard_policies_;
 
-  bool ParseHeader(const std::string& json_value,
-                   base::TimeTicks now_ticks,
-                   OriginPolicy* policy_out) const {
+  HeaderOutcome ParseHeader(const std::string& json_value,
+                            base::TimeTicks now_ticks,
+                            OriginPolicy* policy_out) const {
     DCHECK(policy_out);
 
     if (json_value.size() > kMaxJsonSize)
-      return false;
+      return HeaderOutcome::DISCARDED_JSON_TOO_BIG;
 
     std::unique_ptr<base::Value> value =
         base::JSONReader::Read(json_value, base::JSON_PARSE_RFC, kMaxJsonDepth);
     if (!value)
-      return false;
+      return HeaderOutcome::DISCARDED_JSON_INVALID;
 
     const base::DictionaryValue* dict = nullptr;
     if (!value->GetAsDictionary(&dict))
-      return false;
+      return HeaderOutcome::DISCARDED_NOT_DICTIONARY;
 
+    if (!dict->HasKey(kMaxAgeKey))
+      return HeaderOutcome::DISCARDED_TTL_MISSING;
     int max_age_sec;
-    if (!dict->GetInteger(kMaxAgeKey, &max_age_sec) || max_age_sec < 0)
-      return false;
+    if (!dict->GetInteger(kMaxAgeKey, &max_age_sec))
+      return HeaderOutcome::DISCARDED_TTL_NOT_INTEGER;
+    if (max_age_sec < 0)
+      return HeaderOutcome::DISCARDED_TTL_NEGATIVE;
 
     std::string report_to;
-    if (!dict->GetString(kReportToKey, &report_to) && max_age_sec > 0)
-      return false;
+    if (max_age_sec > 0) {
+      if (!dict->HasKey(kReportToKey))
+        return HeaderOutcome::DISCARDED_REPORT_TO_MISSING;
+      if (!dict->GetString(kReportToKey, &report_to))
+        return HeaderOutcome::DISCARDED_REPORT_TO_NOT_STRING;
+    }
 
     bool include_subdomains = false;
     // includeSubdomains is optional and defaults to false, so it's okay if
@@ -296,17 +377,17 @@
     dict->GetDouble(kFailureFractionKey, &failure_fraction);
 
     policy_out->report_to = report_to;
-    if (max_age_sec > 0) {
-      policy_out->expires =
-          now_ticks + base::TimeDelta::FromSeconds(max_age_sec);
-    } else {
-      policy_out->expires = base::TimeTicks();
-    }
     policy_out->include_subdomains = include_subdomains;
     policy_out->success_fraction = success_fraction;
     policy_out->failure_fraction = failure_fraction;
-
-    return true;
+    if (max_age_sec > 0) {
+      policy_out->expires =
+          now_ticks + base::TimeDelta::FromSeconds(max_age_sec);
+      return HeaderOutcome::SET;
+    } else {
+      policy_out->expires = base::TimeTicks();
+      return HeaderOutcome::REMOVED;
+    }
   }
 
   const OriginPolicy* FindPolicyForOrigin(const url::Origin& origin) const {
@@ -413,6 +494,9 @@
     const RequestDetails& other) = default;
 
 NetworkErrorLoggingService::RequestDetails::~RequestDetails() = default;
+
+// static:
+
 const char NetworkErrorLoggingService::kHeaderName[] = "NEL";
 
 const char NetworkErrorLoggingService::kReportType[] = "network-error";
@@ -427,6 +511,30 @@
 const char NetworkErrorLoggingService::kTypeKey[] = "type";
 
 // static
+void NetworkErrorLoggingService::
+    RecordHeaderDiscardedForNoNetworkErrorLoggingService() {
+  RecordHeaderOutcome(
+      HeaderOutcome::DISCARDED_NO_NETWORK_ERROR_LOGGING_SERVICE);
+}
+
+// static
+void NetworkErrorLoggingService::RecordHeaderDiscardedForInvalidSSLInfo() {
+  RecordHeaderOutcome(HeaderOutcome::DISCARDED_INVALID_SSL_INFO);
+}
+
+// static
+void NetworkErrorLoggingService::RecordHeaderDiscardedForCertStatusError() {
+  RecordHeaderOutcome(HeaderOutcome::DISCARDED_CERT_STATUS_ERROR);
+}
+
+// static
+void NetworkErrorLoggingService::
+    RecordRequestDiscardedForNoNetworkErrorLoggingService() {
+  RecordRequestOutcome(
+      RequestOutcome::DISCARDED_NO_NETWORK_ERROR_LOGGING_SERVICE);
+}
+
+// static
 std::unique_ptr<NetworkErrorLoggingService> NetworkErrorLoggingService::Create(
     std::unique_ptr<NetworkErrorLoggingDelegate> delegate) {
   return std::make_unique<NetworkErrorLoggingServiceImpl>(std::move(delegate));
diff --git a/net/network_error_logging/network_error_logging_service.h b/net/network_error_logging/network_error_logging_service.h
index 3a7613f..c41ae83 100644
--- a/net/network_error_logging/network_error_logging_service.h
+++ b/net/network_error_logging/network_error_logging_service.h
@@ -74,6 +74,12 @@
   static const char kElapsedTimeKey[];
   static const char kTypeKey[];
 
+  static void RecordHeaderDiscardedForNoNetworkErrorLoggingService();
+  static void RecordHeaderDiscardedForInvalidSSLInfo();
+  static void RecordHeaderDiscardedForCertStatusError();
+
+  static void RecordRequestDiscardedForNoNetworkErrorLoggingService();
+
   static std::unique_ptr<NetworkErrorLoggingService> Create(
       std::unique_ptr<NetworkErrorLoggingDelegate> delegate);
 
diff --git a/net/nqe/network_quality_estimator.cc b/net/nqe/network_quality_estimator.cc
index f6437e8..2b54408 100644
--- a/net/nqe/network_quality_estimator.cc
+++ b/net/nqe/network_quality_estimator.cc
@@ -596,8 +596,7 @@
   DCHECK(thread_checker_.CalledOnValidThread());
 
   bool private_network_request = nqe::internal::IsPrivateHost(
-      request.context()->host_resolver(),
-      HostPortPair(request.url().host(), request.url().EffectiveIntPort()));
+      request.context()->host_resolver(), HostPortPair::FromURL(request.url()));
 
   return (use_localhost_requests_ || !private_network_request) &&
          // Verify that response headers are received, so it can be ensured that
diff --git a/net/nqe/throughput_analyzer.cc b/net/nqe/throughput_analyzer.cc
index 376e9d6..d8f84cc 100644
--- a/net/nqe/throughput_analyzer.cc
+++ b/net/nqe/throughput_analyzer.cc
@@ -349,8 +349,7 @@
   DCHECK(thread_checker_.CalledOnValidThread());
 
   bool private_network_request = nqe::internal::IsPrivateHost(
-      request.context()->host_resolver(),
-      HostPortPair(request.url().host(), request.url().EffectiveIntPort()));
+      request.context()->host_resolver(), HostPortPair::FromURL(request.url()));
 
   return !(use_localhost_requests_for_tests_ || !private_network_request) ||
          request.creation_time() < last_connection_change_;
diff --git a/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc b/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc
index 205ffe2c..6acd2b6 100644
--- a/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc
+++ b/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc
@@ -32,7 +32,7 @@
 #include "net/http/http_server_properties_impl.h"
 #include "net/http/http_transaction_factory.h"
 #include "net/http/transport_security_state.h"
-#include "net/net_features.h"
+#include "net/net_buildflags.h"
 #include "net/socket/client_socket_pool_manager.h"
 #include "net/socket/transport_client_socket_pool.h"
 #include "net/ssl/ssl_config_service_defaults.h"
diff --git a/net/proxy_resolution/proxy_config_service_linux.h b/net/proxy_resolution/proxy_config_service_linux.h
index 8022a92..c853d1a 100644
--- a/net/proxy_resolution/proxy_config_service_linux.h
+++ b/net/proxy_resolution/proxy_config_service_linux.h
@@ -299,9 +299,9 @@
 
   void SetupAndFetchInitialConfig(
       const scoped_refptr<base::SingleThreadTaskRunner>& glib_task_runner,
-      const scoped_refptr<base::SequencedTaskRunner>& io_task_runner,
+      const scoped_refptr<base::SequencedTaskRunner>& main_task_runner,
       const NetworkTrafficAnnotationTag& traffic_annotation) {
-    delegate_->SetUpAndFetchInitialConfig(glib_task_runner, io_task_runner,
+    delegate_->SetUpAndFetchInitialConfig(glib_task_runner, main_task_runner,
                                           traffic_annotation);
   }
   void OnCheckProxyConfigSettings() {
diff --git a/net/proxy_resolution/proxy_resolution_service.cc b/net/proxy_resolution/proxy_resolution_service.cc
index 9f4143d..241dd4b 100644
--- a/net/proxy_resolution/proxy_resolution_service.cc
+++ b/net/proxy_resolution/proxy_resolution_service.cc
@@ -1483,7 +1483,7 @@
 // static
 std::unique_ptr<ProxyConfigService>
 ProxyResolutionService::CreateSystemProxyConfigService(
-    const scoped_refptr<base::SequencedTaskRunner>& io_task_runner) {
+    const scoped_refptr<base::SequencedTaskRunner>& main_task_runner) {
 #if defined(OS_WIN)
   return std::make_unique<ProxyConfigServiceWin>(
       kSystemProxyConfigTrafficAnnotation);
@@ -1492,7 +1492,7 @@
       kSystemProxyConfigTrafficAnnotation);
 #elif defined(OS_MACOSX)
   return std::make_unique<ProxyConfigServiceMac>(
-      io_task_runner, kSystemProxyConfigTrafficAnnotation);
+      main_task_runner, kSystemProxyConfigTrafficAnnotation);
 #elif defined(OS_CHROMEOS)
   LOG(ERROR) << "ProxyConfigService for ChromeOS should be created in "
              << "profile_io_data.cc::CreateProxyConfigService and this should "
@@ -1513,13 +1513,13 @@
   // either |glib_default_loop| or an internal sequenced task runner) to
   // keep us updated when the proxy config changes.
   linux_config_service->SetupAndFetchInitialConfig(
-      glib_thread_task_runner, io_task_runner,
+      glib_thread_task_runner, main_task_runner,
       kSystemProxyConfigTrafficAnnotation);
 
   return std::move(linux_config_service);
 #elif defined(OS_ANDROID)
   return std::make_unique<ProxyConfigServiceAndroid>(
-      io_task_runner, base::ThreadTaskRunnerHandle::Get());
+      main_task_runner, base::ThreadTaskRunnerHandle::Get());
 #else
   LOG(WARNING) << "Failed to choose a system proxy settings fetcher "
                   "for this platform.";
diff --git a/net/proxy_resolution/proxy_resolution_service.h b/net/proxy_resolution/proxy_resolution_service.h
index 1996deb9..e438c6a 100644
--- a/net/proxy_resolution/proxy_resolution_service.h
+++ b/net/proxy_resolution/proxy_resolution_service.h
@@ -272,9 +272,14 @@
       const NetworkTrafficAnnotationTag& traffic_annotation);
 
   // Creates a config service appropriate for this platform that fetches the
-  // system proxy settings.
+  // system proxy settings. |main_task_runner| is the thread where the consumer
+  // of the ProxyConfigService will live.
+  //
+  // TODO(mmenke): Should this be a member of ProxyConfigService?
+  // The ProxyResolutionService may not even be in the same process as the
+  // system ProxyConfigService.
   static std::unique_ptr<ProxyConfigService> CreateSystemProxyConfigService(
-      const scoped_refptr<base::SequencedTaskRunner>& io_task_runner);
+      const scoped_refptr<base::SequencedTaskRunner>& main_task_runner);
 
   // This method should only be used by unit tests.
   void set_stall_proxy_auto_config_delay(base::TimeDelta delay) {
diff --git a/net/socket/client_socket_handle.h b/net/socket/client_socket_handle.h
index 1a0afb9..3926bcc 100644
--- a/net/socket/client_socket_handle.h
+++ b/net/socket/client_socket_handle.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 #include <string>
+#include <utility>
 
 #include "base/logging.h"
 #include "base/macros.h"
@@ -151,8 +152,9 @@
   void set_ssl_error_response_info(const HttpResponseInfo& ssl_error_state) {
     ssl_error_response_info_ = ssl_error_state;
   }
-  void set_pending_http_proxy_connection(ClientSocketHandle* connection) {
-    pending_http_proxy_connection_.reset(connection);
+  void set_pending_http_proxy_connection(
+      std::unique_ptr<ClientSocketHandle> connection) {
+    pending_http_proxy_connection_ = std::move(connection);
   }
   void set_connection_attempts(const ConnectionAttempts& attempts) {
     connection_attempts_ = attempts;
@@ -169,8 +171,8 @@
   const HttpResponseInfo& ssl_error_response_info() const {
     return ssl_error_response_info_;
   }
-  ClientSocketHandle* release_pending_http_proxy_connection() {
-    return pending_http_proxy_connection_.release();
+  std::unique_ptr<ClientSocketHandle> release_pending_http_proxy_connection() {
+    return std::move(pending_http_proxy_connection_);
   }
   // If the connection failed, returns the connection attempts made. (If it
   // succeeded, they will be returned through the socket instead; see
diff --git a/net/socket/client_socket_pool_manager.cc b/net/socket/client_socket_pool_manager.cc
index e818616..b25448e 100644
--- a/net/socket/client_socket_pool_manager.cc
+++ b/net/socket/client_socket_pool_manager.cc
@@ -96,10 +96,9 @@
     origin_host_port.set_port(session->params().testing_fixed_https_port);
   }
 
-  bool disable_resolver_cache =
-      request_load_flags & LOAD_BYPASS_CACHE ||
-      request_load_flags & LOAD_VALIDATE_CACHE ||
-      request_load_flags & LOAD_DISABLE_CACHE;
+  // LOAD_BYPASS_CACHE should bypass the host cache as well as the HTTP cache.
+  // Other cache-related load flags should not have this effect.
+  bool disable_resolver_cache = request_load_flags & LOAD_BYPASS_CACHE;
 
   int load_flags = request_load_flags;
   if (session->params().ignore_certificate_errors)
diff --git a/net/socket/ssl_client_socket_pool.cc b/net/socket/ssl_client_socket_pool.cc
index 918fa659..69a00ca 100644
--- a/net/socket/ssl_client_socket_pool.cc
+++ b/net/socket/ssl_client_socket_pool.cc
@@ -166,7 +166,7 @@
   // problem. See DoTunnelConnectComplete.
   if (error_response_info_.headers.get()) {
     handle->set_pending_http_proxy_connection(
-        transport_socket_handle_.release());
+        std::move(transport_socket_handle_));
   }
   handle->set_ssl_error_response_info(error_response_info_);
   if (!connect_timing_.ssl_start.is_null())
diff --git a/net/socket/ssl_client_socket_pool_unittest.cc b/net/socket/ssl_client_socket_pool_unittest.cc
index 141f7956..b29f728 100644
--- a/net/socket/ssl_client_socket_pool_unittest.cc
+++ b/net/socket/ssl_client_socket_pool_unittest.cc
@@ -735,8 +735,8 @@
   EXPECT_FALSE(handle.is_ssl_error());
   const HttpResponseInfo& tunnel_info = handle.ssl_error_response_info();
   EXPECT_EQ(tunnel_info.headers->response_code(), 407);
-  std::unique_ptr<ClientSocketHandle> tunnel_handle(
-      handle.release_pending_http_proxy_connection());
+  std::unique_ptr<ClientSocketHandle> tunnel_handle =
+      handle.release_pending_http_proxy_connection();
   EXPECT_TRUE(tunnel_handle->socket());
   EXPECT_FALSE(tunnel_handle->socket()->IsConnected());
 }
diff --git a/net/test/embedded_test_server/default_handlers.cc b/net/test/embedded_test_server/default_handlers.cc
index bc89ab8..6d7375ded 100644
--- a/net/test/embedded_test_server/default_handlers.cc
+++ b/net/test/embedded_test_server/default_handlers.cc
@@ -232,7 +232,7 @@
   if (request.headers.find("Cookie") != request.headers.end()) {
     received_cookies =
         base::SplitString(request.headers.at("Cookie"), ";",
-                          base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
+                          base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
   }
 
   bool got_all_expected = true;
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc
index 323d0db..8e18063 100644
--- a/net/url_request/url_request.cc
+++ b/net/url_request/url_request.cc
@@ -557,6 +557,7 @@
       net_log_(NetLogWithSource::Make(context->net_log(),
                                       NetLogSourceType::URL_REQUEST)),
       url_chain_(1, url),
+      attach_same_site_cookies_(false),
       method_("GET"),
       referrer_policy_(CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE),
       first_party_url_policy_(NEVER_CHANGE_FIRST_PARTY_URL),
@@ -1166,8 +1167,11 @@
 void URLRequest::MaybeGenerateNetworkErrorLoggingReport() {
   NetworkErrorLoggingService* service =
       context()->network_error_logging_service();
-  if (!service)
+  if (!service) {
+    NetworkErrorLoggingService::
+        RecordRequestDiscardedForNoNetworkErrorLoggingService();
     return;
+  }
 
   // TODO(juliatuttle): Figure out whether we should be ignoring errors from
   // non-HTTPS origins.
diff --git a/net/url_request/url_request.h b/net/url_request/url_request.h
index c0fc8aee..5727310 100644
--- a/net/url_request/url_request.h
+++ b/net/url_request/url_request.h
@@ -35,7 +35,7 @@
 #include "net/http/http_response_headers.h"
 #include "net/http/http_response_info.h"
 #include "net/log/net_log_with_source.h"
-#include "net/net_features.h"
+#include "net/net_buildflags.h"
 #include "net/socket/connection_attempts.h"
 #include "net/socket/socket_tag.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
@@ -285,6 +285,13 @@
   // This method may only be called before Start().
   void set_site_for_cookies(const GURL& site_for_cookies);
 
+  // Indicate whether SameSite cookies should be attached even though the
+  // request is cross-site.
+  bool attach_same_site_cookies() const { return attach_same_site_cookies_; }
+  void set_attach_same_site_cookies(bool attach) {
+    attach_same_site_cookies_ = attach;
+  }
+
   // The first-party URL policy to apply when updating the first party URL
   // during redirects. The first-party URL policy may only be changed before
   // Start() is called.
@@ -815,6 +822,7 @@
 
   std::vector<GURL> url_chain_;
   GURL site_for_cookies_;
+  bool attach_same_site_cookies_;
   base::Optional<url::Origin> initiator_;
   GURL delegate_redirect_url_;
   std::string method_;  // "GET", "POST", etc. Should be all uppercase.
diff --git a/net/url_request/url_request_context.h b/net/url_request/url_request_context.h
index e26a3f0..f7b559d 100644
--- a/net/url_request/url_request_context.h
+++ b/net/url_request/url_request_context.h
@@ -22,7 +22,7 @@
 #include "net/http/http_network_session.h"
 #include "net/http/http_server_properties.h"
 #include "net/http/transport_security_state.h"
-#include "net/net_features.h"
+#include "net/net_buildflags.h"
 #include "net/ssl/ssl_config_service.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "net/url_request/url_request.h"
diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/url_request_context_builder.cc
index 2f10f419..c86c7fe 100644
--- a/net/url_request/url_request_context_builder.cc
+++ b/net/url_request/url_request_context_builder.cc
@@ -34,7 +34,7 @@
 #include "net/http/transport_security_persister.h"
 #include "net/http/transport_security_state.h"
 #include "net/log/net_log.h"
-#include "net/net_features.h"
+#include "net/net_buildflags.h"
 #include "net/nqe/network_quality_estimator.h"
 #include "net/quic/chromium/quic_stream_factory.h"
 #include "net/ssl/channel_id_service.h"
diff --git a/net/url_request/url_request_context_builder.h b/net/url_request/url_request_context_builder.h
index 775476f..690a9edd 100644
--- a/net/url_request/url_request_context_builder.h
+++ b/net/url_request/url_request_context_builder.h
@@ -35,7 +35,7 @@
 #include "net/base/proxy_delegate.h"
 #include "net/dns/host_resolver.h"
 #include "net/http/http_network_session.h"
-#include "net/net_features.h"
+#include "net/net_buildflags.h"
 #include "net/proxy_resolution/proxy_config_service.h"
 #include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/quic/core/quic_packets.h"
diff --git a/net/url_request/url_request_context_storage.h b/net/url_request/url_request_context_storage.h
index b44a060..9975977 100644
--- a/net/url_request/url_request_context_storage.h
+++ b/net/url_request/url_request_context_storage.h
@@ -11,7 +11,7 @@
 #include "base/memory/ref_counted.h"
 #include "build/buildflag.h"
 #include "net/base/net_export.h"
-#include "net/net_features.h"
+#include "net/net_buildflags.h"
 
 namespace net {
 
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc
index 7ed0c12..f63b544e 100644
--- a/net/url_request/url_request_http_job.cc
+++ b/net/url_request/url_request_http_job.cc
@@ -54,7 +54,7 @@
 #include "net/log/net_log.h"
 #include "net/log/net_log_event_type.h"
 #include "net/log/net_log_with_source.h"
-#include "net/net_features.h"
+#include "net/net_buildflags.h"
 #include "net/nqe/network_quality_estimator.h"
 #include "net/proxy_resolution/proxy_info.h"
 #include "net/proxy_resolution/proxy_resolution_service.h"
@@ -663,6 +663,12 @@
     //   Note that this will generally be the case only for cross-site requests
     //   which target a top-level browsing context.
     //
+    // * Include both "strict" and "lax" same-site cookies if the request is
+    //   tagged with a flag allowing it.
+    //   Note that this can be the case for requests initiated by extensions,
+    //   which need to behave as though they are made by the document itself,
+    //   but appear like cross-site ones.
+    //
     // * Otherwise, do not include same-site cookies.
     if (registry_controlled_domains::SameDomainOrHost(
             request_->url(), request_->site_for_cookies(),
@@ -670,7 +676,8 @@
       if (!request_->initiator() ||
           registry_controlled_domains::SameDomainOrHost(
               request_->url(), request_->initiator().value().GetURL(),
-              registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) {
+              registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES) ||
+          request_->attach_same_site_cookies()) {
         options.set_same_site_cookie_mode(
             CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
       } else if (HttpUtil::IsMethodSafe(request_->method())) {
@@ -872,14 +879,23 @@
 
   NetworkErrorLoggingService* service =
       request_->context()->network_error_logging_service();
-  if (!service)
+  if (!service) {
+    NetworkErrorLoggingService::
+        RecordHeaderDiscardedForNoNetworkErrorLoggingService();
     return;
+  }
 
-  // Only accept Report-To headers on HTTPS connections that have no
-  // certificate errors.
+  // Only accept NEL headers on HTTPS connections that have no certificate
+  // errors.
   const SSLInfo& ssl_info = response_info_->ssl_info;
-  if (!ssl_info.is_valid() || IsCertStatusError(ssl_info.cert_status))
+  if (!ssl_info.is_valid()) {
+    NetworkErrorLoggingService::RecordHeaderDiscardedForInvalidSSLInfo();
     return;
+  }
+  if (IsCertStatusError(ssl_info.cert_status)) {
+    NetworkErrorLoggingService::RecordHeaderDiscardedForCertStatusError();
+    return;
+  }
 
   service->OnHeader(url::Origin::Create(request_info_.url), value);
 }
diff --git a/net/url_request/url_request_http_job.h b/net/url_request/url_request_http_job.h
index 1f050c2c..f5f84b7d 100644
--- a/net/url_request/url_request_http_job.h
+++ b/net/url_request/url_request_http_job.h
@@ -21,7 +21,7 @@
 #include "net/base/net_export.h"
 #include "net/cookies/cookie_store.h"
 #include "net/http/http_request_info.h"
-#include "net/net_features.h"
+#include "net/net_buildflags.h"
 #include "net/socket/connection_attempts.h"
 #include "net/url_request/url_request_job.h"
 #include "net/url_request/url_request_throttler_entry_interface.h"
diff --git a/net/url_request/url_request_http_job_unittest.cc b/net/url_request/url_request_http_job_unittest.cc
index 377fb3b8..3ce02ad 100644
--- a/net/url_request/url_request_http_job_unittest.cc
+++ b/net/url_request/url_request_http_job_unittest.cc
@@ -29,7 +29,7 @@
 #include "net/log/test_net_log.h"
 #include "net/log/test_net_log_entry.h"
 #include "net/log/test_net_log_util.h"
-#include "net/net_features.h"
+#include "net/net_buildflags.h"
 #include "net/socket/socket_test_util.h"
 #include "net/test/cert_test_util.h"
 #include "net/test/gtest_util.h"
diff --git a/net/url_request/url_request_job_manager.cc b/net/url_request/url_request_job_manager.cc
index 0817a12..ab244be 100644
--- a/net/url_request/url_request_job_manager.cc
+++ b/net/url_request/url_request_job_manager.cc
@@ -7,12 +7,12 @@
 #include <algorithm>
 
 #include "base/memory/singleton.h"
-#include "build/build_config.h"
 #include "base/strings/string_util.h"
+#include "build/build_config.h"
 #include "net/base/load_flags.h"
 #include "net/base/net_errors.h"
 #include "net/base/network_delegate.h"
-#include "net/net_features.h"
+#include "net/net_buildflags.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_error_job.h"
 #include "net/url_request/url_request_http_job.h"
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index 222829a3e..87231c0 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -88,7 +88,7 @@
 #include "net/log/test_net_log.h"
 #include "net/log/test_net_log_entry.h"
 #include "net/log/test_net_log_util.h"
-#include "net/net_features.h"
+#include "net/net_buildflags.h"
 #include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/quic/chromium/mock_crypto_client_stream_factory.h"
 #include "net/quic/chromium/quic_server_info.h"
diff --git a/pdf/BUILD.gn b/pdf/BUILD.gn
index 4d7e4c0..c5afc08 100644
--- a/pdf/BUILD.gn
+++ b/pdf/BUILD.gn
@@ -10,8 +10,8 @@
 import("//third_party/pdfium/pdfium.gni")
 
 # Generate a buildflag header for compile-time checking of PDF support.
-buildflag_header("features") {
-  header = "features.h"
+buildflag_header("buildflags") {
+  header = "buildflags.h"
   flags = [ "ENABLE_PDF=$enable_pdf" ]
 }
 
diff --git a/pdf/pdfium/pdfium_engine.cc b/pdf/pdfium/pdfium_engine.cc
index 5ce0f64..0019b8a 100644
--- a/pdf/pdfium/pdfium_engine.cc
+++ b/pdf/pdfium/pdfium_engine.cc
@@ -4586,14 +4586,14 @@
                                             int page_number,
                                             const RenderingSettings& settings,
                                             HDC dc) {
-  FPDF_DOCUMENT doc = FPDF_LoadMemDocument(pdf_buffer, buffer_size, nullptr);
+  std::unique_ptr<void, FPDFDocumentDeleter> doc(
+      FPDF_LoadMemDocument(pdf_buffer, buffer_size, nullptr));
   if (!doc)
     return false;
-  FPDF_PAGE page = FPDF_LoadPage(doc, page_number);
-  if (!page) {
-    FPDF_CloseDocument(doc);
+  FPDF_PAGE page = FPDF_LoadPage(doc.get(), page_number);
+  if (!page)
     return false;
-  }
+
   RenderingSettings new_settings = settings;
   // calculate the page size
   if (new_settings.dpi_x == -1)
@@ -4646,7 +4646,6 @@
   }
   RestoreDC(dc, save_state);
   FPDF_ClosePage(page);
-  FPDF_CloseDocument(doc);
   return true;
 }
 
@@ -4671,15 +4670,13 @@
     int page_number,
     const RenderingSettings& settings,
     void* bitmap_buffer) {
-  FPDF_DOCUMENT doc =
-      FPDF_LoadMemDocument(pdf_buffer, pdf_buffer_size, nullptr);
+  std::unique_ptr<void, FPDFDocumentDeleter> doc(
+      FPDF_LoadMemDocument(pdf_buffer, pdf_buffer_size, nullptr));
   if (!doc)
     return false;
-  FPDF_PAGE page = FPDF_LoadPage(doc, page_number);
-  if (!page) {
-    FPDF_CloseDocument(doc);
+  FPDF_PAGE page = FPDF_LoadPage(doc.get(), page_number);
+  if (!page)
     return false;
-  }
 
   pp::Rect dest;
   int rotate = CalculatePosition(page, settings, &dest);
@@ -4697,7 +4694,6 @@
                         FPDF_ANNOT | FPDF_PRINTING | FPDF_NO_CATCH);
   FPDFBitmap_Destroy(bitmap);
   FPDF_ClosePage(page);
-  FPDF_CloseDocument(doc);
   return true;
 }
 
@@ -4705,25 +4701,30 @@
                                         int buffer_size,
                                         int* page_count,
                                         double* max_page_width) {
-  FPDF_DOCUMENT doc = FPDF_LoadMemDocument(pdf_buffer, buffer_size, nullptr);
+  std::unique_ptr<void, FPDFDocumentDeleter> doc(
+      FPDF_LoadMemDocument(pdf_buffer, buffer_size, nullptr));
   if (!doc)
     return false;
-  int page_count_local = FPDF_GetPageCount(doc);
-  if (page_count) {
+
+  if (!page_count && !max_page_width)
+    return true;
+
+  int page_count_local = FPDF_GetPageCount(doc.get());
+  if (page_count)
     *page_count = page_count_local;
-  }
+
   if (max_page_width) {
     *max_page_width = 0;
     for (int page_number = 0; page_number < page_count_local; page_number++) {
       double page_width = 0;
       double page_height = 0;
-      FPDF_GetPageSizeByIndex(doc, page_number, &page_width, &page_height);
+      FPDF_GetPageSizeByIndex(doc.get(), page_number, &page_width,
+                              &page_height);
       if (page_width > *max_page_width) {
         *max_page_width = page_width;
       }
     }
   }
-  FPDF_CloseDocument(doc);
   return true;
 }
 
@@ -4732,13 +4733,11 @@
                                                 int page_number,
                                                 double* width,
                                                 double* height) {
-  FPDF_DOCUMENT doc =
-      FPDF_LoadMemDocument(pdf_buffer, pdf_buffer_size, nullptr);
+  std::unique_ptr<void, FPDFDocumentDeleter> doc(
+      FPDF_LoadMemDocument(pdf_buffer, pdf_buffer_size, nullptr));
   if (!doc)
     return false;
-  bool success = FPDF_GetPageSizeByIndex(doc, page_number, width, height) != 0;
-  FPDF_CloseDocument(doc);
-  return success;
+  return FPDF_GetPageSizeByIndex(doc.get(), page_number, width, height) != 0;
 }
 
 }  // namespace chrome_pdf
diff --git a/rlz/BUILD.gn b/rlz/BUILD.gn
index 9beeeec..d1c59e2 100644
--- a/rlz/BUILD.gn
+++ b/rlz/BUILD.gn
@@ -85,6 +85,10 @@
       "//url",
     ]
 
+    if (is_chromeos) {
+      deps += [ "//chromeos" ]
+    }
+
     if (is_mac) {
       libs = [
         "Foundation.framework",
@@ -115,6 +119,9 @@
       "//base/test:test_support",
       "//testing/gtest",
     ]
+    if (is_chromeos) {
+      deps += [ "//chromeos" ]
+    }
   }
 
   test("rlz_unittests") {
diff --git a/rlz/DEPS b/rlz/DEPS
index aba5be2..9cab8e58 100644
--- a/rlz/DEPS
+++ b/rlz/DEPS
@@ -56,6 +56,7 @@
 
 include_rules = [
   "+build",
+  "+chromeos/system",
   "+net",  # This is only used when force_rlz_use_chrome_net=1 is passed to gyp.
   "+third_party/zlib",
 ]
diff --git a/rlz/chromeos/lib/rlz_value_store_chromeos.cc b/rlz/chromeos/lib/rlz_value_store_chromeos.cc
index 6a92164..e7b0f9a 100644
--- a/rlz/chromeos/lib/rlz_value_store_chromeos.cc
+++ b/rlz/chromeos/lib/rlz_value_store_chromeos.cc
@@ -16,6 +16,8 @@
 #include "base/sequenced_task_runner.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/values.h"
+#include "chromeos/system/statistics_provider.h"
+#include "rlz/lib/financial_ping.h"
 #include "rlz/lib/lib_values.h"
 #include "rlz/lib/recursive_cross_process_lock_posix.h"
 #include "rlz/lib/rlz_lib.h"
@@ -46,9 +48,6 @@
     LAZY_INSTANCE_INITIALIZER;
 
 base::FilePath GetRlzStorePathCommon() {
-  // TODO(wzang): Replace base::DIR_HOME with something that is shared by all
-  // profiles on the device.  This location must be somewhere that is wiped
-  // when the device is factory reset or powerwashed.
   base::FilePath homedir;
   PathService::Get(base::DIR_HOME, &homedir);
   return g_testing_rlz_store_path.Get().empty()
@@ -82,8 +81,43 @@
   return key + "." + GetProductName(product) + "." + brand;
 }
 
+// Returns true if the |rlz_embargo_end_date| present in VPD has passed
+// compared to the current time.
+bool HasRlzEmbargoEndDatePassed() {
+  chromeos::system::StatisticsProvider* stats =
+      chromeos::system::StatisticsProvider::GetInstance();
+
+  std::string rlz_embargo_end_date;
+  if (!stats->GetMachineStatistic(chromeos::system::kRlzEmbargoEndDateKey,
+                                  &rlz_embargo_end_date)) {
+    // |rlz_embargo_end_date| only exists on new devices that have not yet
+    // launched. When the field doesn't exist, returns true so it's a no-op.
+    return true;
+  }
+  base::Time parsed_time;
+  if (!base::Time::FromUTCString(rlz_embargo_end_date.c_str(), &parsed_time)) {
+    LOG(ERROR) << "|rlz_embargo_end_date| exists but cannot be parsed.";
+    return true;
+  }
+
+  if (parsed_time - base::Time::Now() >=
+      base::TimeDelta::FromDays(
+          RlzValueStoreChromeOS::kRlzEmbargoEndDateGarbageDateThresholdDays)) {
+    // If |rlz_embargo_end_date| is more than this many days in the future,
+    // ignore it. Because it indicates that the device is not connected to an
+    // ntp server in the factory, and its internal clock could be off when the
+    // date is written.
+    return true;
+  }
+
+  return base::Time::Now() > parsed_time;
+}
+
 }  // namespace
 
+const int RlzValueStoreChromeOS::kRlzEmbargoEndDateGarbageDateThresholdDays =
+    14;
+
 RlzValueStoreChromeOS::RlzValueStoreChromeOS(const base::FilePath& store_path)
     : rlz_store_(new base::DictionaryValue),
       store_path_(store_path),
@@ -111,12 +145,12 @@
 bool RlzValueStoreChromeOS::ReadPingTime(Product product, int64_t* time) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-#if defined(OS_CHROMEOS)
   // TODO(wzang): make sure time is correct (check that npupdate has updated
   // successfully).
-  // TODO(wzang): if the current time is within 7 days of the
-  // factory_production_date value in the RW_VPD, then return the current time.
-#endif
+  if (!HasRlzEmbargoEndDatePassed()) {
+    *time = FinancialPing::GetSystemTimeAsInt64();
+    return true;
+  }
 
   std::string ping_time;
   return rlz_store_->GetString(GetKeyName(kPingTimeKey, product), &ping_time) &&
@@ -131,7 +165,6 @@
 
 bool RlzValueStoreChromeOS::WriteAccessPointRlz(AccessPoint access_point,
                                                 const char* new_rlz) {
-#if defined(OS_CHROMEOS)
   // If an access point already exists, don't overwrite it.  This is to prevent
   // writing cohort data for first search which is not needed in Chrome OS.
   //
@@ -147,7 +180,6 @@
       dummy[0] != 0) {
     return true;
   }
-#endif
 
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   rlz_store_->SetString(
@@ -217,12 +249,9 @@
                                              const char* event_rlz) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-#if defined(OS_CHROMEOS)
   if (strcmp(event_rlz, "CAF") == 0) {
     // TODO(wzang): Set rlz_first_use_ping_not_sent to 0 in RW_VPD.
   }
-#endif
-
   return AddValueToList(GetKeyName(kStatefulEventKey, product),
                         std::make_unique<base::Value>(event_rlz));
 }
@@ -231,24 +260,36 @@
                                             const char* event_rlz) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-#if defined(OS_CHROMEOS)
-  if (strcmp(event_rlz, "CAF") == 0) {
-    // TODO(wzang): If rlz_first_use_ping_not_sent exists in RW_VPD with
-    // value 0, then return true.
-    // TODO(wzang): if the current time is within 7 days of the
-    // factory_production_date value in the RW_VPD, then return true.
-    // TODO(wzang): if rlz_first_use_ping_not_sent exists in RW_VPD with
-    // value 1 but below the code finds |event_value| in the list, try to
-    // set rlz_first_use_ping_not_sent to zero in the RW_VPD.  This is to try
-    // and fix the RW_VPD if there was an error writing to it earlier.
-  }
-#endif
-
   base::Value event_value(event_rlz);
   base::ListValue* events_list = NULL;
-  return rlz_store_->GetList(GetKeyName(kStatefulEventKey, product),
-                             &events_list) &&
+  const bool event_exists =
+      rlz_store_->GetList(GetKeyName(kStatefulEventKey, product),
+                          &events_list) &&
       events_list->Find(event_value) != events_list->end();
+
+  if (strcmp(event_rlz, "CAF") == 0) {
+    chromeos::system::StatisticsProvider* stats =
+        chromeos::system::StatisticsProvider::GetInstance();
+    std::string should_send_rlz_ping_value;
+    if (stats->GetMachineStatistic(chromeos::system::kShouldSendRlzPingKey,
+                                   &should_send_rlz_ping_value)) {
+      if (should_send_rlz_ping_value ==
+          chromeos::system::kShouldSendRlzPingValueFalse) {
+        return true;
+      }
+      if (!HasRlzEmbargoEndDatePassed())
+        return true;
+      DCHECK_EQ(should_send_rlz_ping_value,
+                chromeos::system::kShouldSendRlzPingValueTrue);
+      if (event_exists) {
+        // TODO(wzang): If we reach here, it means there was an error writing to
+        // RW_VPD earlier. We should log the error and try writing to RW_VPD
+        // again. Also, capture UMA stat on persistent failure to write VPD.
+      }
+    }
+  }
+
+  return event_exists;
 }
 
 bool RlzValueStoreChromeOS::ClearAllStatefulEvents(Product product) {
diff --git a/rlz/chromeos/lib/rlz_value_store_chromeos.h b/rlz/chromeos/lib/rlz_value_store_chromeos.h
index 7222a78..0b0940f 100644
--- a/rlz/chromeos/lib/rlz_value_store_chromeos.h
+++ b/rlz/chromeos/lib/rlz_value_store_chromeos.h
@@ -25,6 +25,10 @@
 // An implementation of RlzValueStore for ChromeOS.
 class RlzValueStoreChromeOS : public RlzValueStore {
  public:
+  // Ignore |kRlzEmbargoEndDateKey| if it's more than this many days in the
+  // future.
+  static const int kRlzEmbargoEndDateGarbageDateThresholdDays;
+
   // Creates new instance and synchronously reads data from file.
   explicit RlzValueStoreChromeOS(const base::FilePath& store_path);
   ~RlzValueStoreChromeOS() override;
diff --git a/rlz/lib/financial_ping.cc b/rlz/lib/financial_ping.cc
index 503a2c25..bf4ed584 100644
--- a/rlz/lib/financial_ping.cc
+++ b/rlz/lib/financial_ping.cc
@@ -70,31 +70,6 @@
 
 #endif
 
-namespace {
-
-// Returns the time relative to a fixed point in the past in multiples of
-// 100 ns stepts. The point in the past is arbitrary but can't change, as the
-// result of this value is stored on disk.
-int64_t GetSystemTimeAsInt64() {
-#if defined(OS_WIN)
-  FILETIME now_as_file_time;
-  // Relative to Jan 1, 1601 (UTC).
-  GetSystemTimeAsFileTime(&now_as_file_time);
-
-  LARGE_INTEGER integer;
-  integer.HighPart = now_as_file_time.dwHighDateTime;
-  integer.LowPart = now_as_file_time.dwLowDateTime;
-  return integer.QuadPart;
-#else
-  // Seconds since epoch (Jan 1, 1970).
-  double now_seconds = base::Time::Now().ToDoubleT();
-  return static_cast<int64_t>(now_seconds * 1000 * 1000 * 10);
-#endif
-}
-
-}  // namespace
-
-
 namespace rlz_lib {
 
 using base::subtle::AtomicWord;
@@ -503,6 +478,23 @@
   return store->ClearPingTime(product);
 }
 
+int64_t FinancialPing::GetSystemTimeAsInt64() {
+#if defined(OS_WIN)
+  FILETIME now_as_file_time;
+  // Relative to Jan 1, 1601 (UTC).
+  GetSystemTimeAsFileTime(&now_as_file_time);
+
+  LARGE_INTEGER integer;
+  integer.HighPart = now_as_file_time.dwHighDateTime;
+  integer.LowPart = now_as_file_time.dwLowDateTime;
+  return integer.QuadPart;
+#else
+  // Seconds since epoch (Jan 1, 1970).
+  double now_seconds = base::Time::Now().ToDoubleT();
+  return static_cast<int64_t>(now_seconds * 1000 * 1000 * 10);
+#endif
+}
+
 #if defined(RLZ_NETWORK_IMPLEMENTATION_CHROME_NET)
 namespace test {
 
diff --git a/rlz/lib/financial_ping.h b/rlz/lib/financial_ping.h
index 63c20a1f..35148d8 100644
--- a/rlz/lib/financial_ping.h
+++ b/rlz/lib/financial_ping.h
@@ -49,6 +49,11 @@
   // Ping the financial server with request. Writes to RlzValueStore.
   static bool PingServer(const char* request, std::string* response);
 
+  // Returns the time relative to a fixed point in the past in multiples of
+  // 100 ns stepts. The point in the past is arbitrary but can't change, as the
+  // result of this value is stored on disk.
+  static int64_t GetSystemTimeAsInt64();
+
 #if defined(RLZ_NETWORK_IMPLEMENTATION_CHROME_NET)
   static bool SetURLRequestContext(net::URLRequestContextGetter* context);
 #endif
diff --git a/rlz/lib/financial_ping_test.cc b/rlz/lib/financial_ping_test.cc
index 5b66140..3d2edbb 100644
--- a/rlz/lib/financial_ping_test.cc
+++ b/rlz/lib/financial_ping_test.cc
@@ -38,22 +38,11 @@
 #include "base/time/time.h"
 #endif
 
-namespace {
-
-// Must match the implementation in file_time.cc.
-int64_t GetSystemTimeAsInt64() {
-#if defined(OS_WIN)
-  FILETIME now_as_file_time;
-  GetSystemTimeAsFileTime(&now_as_file_time);
-  LARGE_INTEGER integer;
-  integer.HighPart = now_as_file_time.dwHighDateTime;
-  integer.LowPart = now_as_file_time.dwLowDateTime;
-  return integer.QuadPart;
-#else
-  double now_seconds = base::Time::Now().ToDoubleT();
-  return static_cast<int64_t>(now_seconds * 1000 * 1000 * 10);
+#if defined(OS_CHROMEOS)
+#include "rlz/chromeos/lib/rlz_value_store_chromeos.h"
 #endif
-}
+
+namespace {
 
 #if defined(OS_CHROMEOS)
 void RemoveMachineIdFromUrl(std::string* url) {
@@ -61,6 +50,22 @@
   EXPECT_NE(std::string::npos, id_offset);
   url->resize(id_offset);
 }
+
+// Utility function to convert a |base::Time::Exploded| to "yyyy-mm-dd" format.
+std::string ConvertExplodedToRlzEmbargoDate(
+    const base::Time::Exploded& exploded) {
+  std::string rlz_embargo_date = std::to_string(exploded.year);
+  rlz_embargo_date += '-';
+  if (exploded.month < 10)
+    rlz_embargo_date += '0';
+  rlz_embargo_date += std::to_string(exploded.month);
+  rlz_embargo_date += '-';
+  if (exploded.day_of_month < 10)
+    rlz_embargo_date += '0';
+  rlz_embargo_date += std::to_string(exploded.day_of_month);
+
+  return rlz_embargo_date;
+}
 #endif
 
 // Ping times in 100-nanosecond intervals.
@@ -218,7 +223,7 @@
 }
 
 TEST_F(FinancialPingTest, IsPingTime) {
-  int64_t now = GetSystemTimeAsInt64();
+  int64_t now = rlz_lib::FinancialPing::GetSystemTimeAsInt64();
   int64_t last_ping = now - rlz_lib::kEventsPingInterval - k1MinuteInterval;
   SetLastPingTime(last_ping, rlz_lib::TOOLBAR_NOTIFIER);
 
@@ -270,7 +275,7 @@
   if (!rlz_lib::SupplementaryBranding::GetBrand().empty())
     return;
 
-  int64_t now = GetSystemTimeAsInt64();
+  int64_t now = rlz_lib::FinancialPing::GetSystemTimeAsInt64();
   int64_t last_ping = now - rlz_lib::kEventsPingInterval - k1MinuteInterval;
   SetLastPingTime(last_ping, rlz_lib::TOOLBAR_NOTIFIER);
 
@@ -305,7 +310,7 @@
 }
 
 TEST_F(FinancialPingTest, ClearLastPingTime) {
-  int64_t now = GetSystemTimeAsInt64();
+  int64_t now = rlz_lib::FinancialPing::GetSystemTimeAsInt64();
   int64_t last_ping = now - rlz_lib::kEventsPingInterval + k1MinuteInterval;
   SetLastPingTime(last_ping, rlz_lib::TOOLBAR_NOTIFIER);
 
@@ -321,3 +326,58 @@
   EXPECT_TRUE(rlz_lib::FinancialPing::IsPingTime(rlz_lib::TOOLBAR_NOTIFIER,
                                                  false));
 }
+
+#if defined(OS_CHROMEOS)
+TEST_F(FinancialPingTest, RlzEmbargoEndDate) {
+  // Do not set last ping time, verify that |IsPingTime| returns true.
+  EXPECT_TRUE(
+      rlz_lib::FinancialPing::IsPingTime(rlz_lib::TOOLBAR_NOTIFIER, false));
+
+  // Simulate writing a past embargo date to VPD, verify that |IsPingTime|
+  // returns true when the embargo date has already passed.
+  base::Time::Exploded exploded;
+  base::Time past_rlz_embargo_date =
+      base::Time::NowFromSystemTime() - base::TimeDelta::FromDays(1);
+  past_rlz_embargo_date.LocalExplode(&exploded);
+  std::string past_rlz_embargo_date_value =
+      ConvertExplodedToRlzEmbargoDate(exploded);
+  statistics_provider_->SetMachineStatistic(
+      chromeos::system::kRlzEmbargoEndDateKey, past_rlz_embargo_date_value);
+
+  EXPECT_TRUE(
+      rlz_lib::FinancialPing::IsPingTime(rlz_lib::TOOLBAR_NOTIFIER, false));
+
+  // Simulate writing a future embargo date (less than
+  // |kRlzEmbargoEndDateGarbageDateThresholdDays|) to VPD, verify that
+  // |IsPingTime| is false.
+  base::Time future_rlz_embargo_date =
+      base::Time::NowFromSystemTime() +
+      base::TimeDelta::FromDays(rlz_lib::RlzValueStoreChromeOS::
+                                    kRlzEmbargoEndDateGarbageDateThresholdDays -
+                                1);
+  future_rlz_embargo_date.LocalExplode(&exploded);
+  std::string future_rlz_embargo_date_value =
+      ConvertExplodedToRlzEmbargoDate(exploded);
+  statistics_provider_->SetMachineStatistic(
+      chromeos::system::kRlzEmbargoEndDateKey, future_rlz_embargo_date_value);
+
+  EXPECT_FALSE(
+      rlz_lib::FinancialPing::IsPingTime(rlz_lib::TOOLBAR_NOTIFIER, false));
+
+  // Simulate writing a future embargo date (more than
+  // |kRlzEmbargoEndDateGarbageDateThresholdDays|) to VPD, verify that
+  // |IsPingTime| is true.
+  future_rlz_embargo_date =
+      base::Time::NowFromSystemTime() +
+      base::TimeDelta::FromDays(rlz_lib::RlzValueStoreChromeOS::
+                                    kRlzEmbargoEndDateGarbageDateThresholdDays +
+                                1);
+  future_rlz_embargo_date.LocalExplode(&exploded);
+  future_rlz_embargo_date_value = ConvertExplodedToRlzEmbargoDate(exploded);
+  statistics_provider_->SetMachineStatistic(
+      chromeos::system::kRlzEmbargoEndDateKey, future_rlz_embargo_date_value);
+
+  EXPECT_TRUE(
+      rlz_lib::FinancialPing::IsPingTime(rlz_lib::TOOLBAR_NOTIFIER, false));
+}
+#endif
diff --git a/rlz/test/rlz_test_helpers.cc b/rlz/test/rlz_test_helpers.cc
index de18427..24695e6d 100644
--- a/rlz/test/rlz_test_helpers.cc
+++ b/rlz/test/rlz_test_helpers.cc
@@ -162,6 +162,10 @@
   m_rlz_test_helper_.TearDown();
 }
 
+RlzLibTestBase::RlzLibTestBase() = default;
+
+RlzLibTestBase::~RlzLibTestBase() = default;
+
 void RlzLibTestBase::SetUp() {
   RlzLibTestNoMachineState::SetUp();
 #if defined(OS_WIN)
@@ -173,5 +177,18 @@
   // out not set, since on Chrome OS RLZ string can only be set once.
   EXPECT_TRUE(rlz_lib::SetAccessPointRlz(rlz_lib::IETB_SEARCH_BOX, ""));
   EXPECT_TRUE(rlz_lib::SetAccessPointRlz(rlz_lib::IE_HOME_PAGE, ""));
+#endif  // defined(OS_POSIX)
+
+#if defined(OS_CHROMEOS)
+  statistics_provider_ =
+      std::make_unique<chromeos::system::FakeStatisticsProvider>();
+  chromeos::system::StatisticsProvider::SetTestProvider(
+      statistics_provider_.get());
+#endif  // defined(OS_CHROMEOS)
+}
+
+void RlzLibTestBase::TearDown() {
+#if defined(OS_CHROMEOS)
+  chromeos::system::StatisticsProvider::SetTestProvider(nullptr);
 #endif  // defined(OS_CHROMEOS)
 }
diff --git a/rlz/test/rlz_test_helpers.h b/rlz/test/rlz_test_helpers.h
index 5a8f1177..87c3600 100644
--- a/rlz/test/rlz_test_helpers.h
+++ b/rlz/test/rlz_test_helpers.h
@@ -19,6 +19,10 @@
 #include "base/test/test_reg_util_win.h"
 #endif
 
+#if defined(OS_CHROMEOS)
+#include "chromeos/system/fake_statistics_provider.h"
+#endif
+
 // A test helper class that constructs and destructs platform dependent machine
 // state. It's used by src/components/rlz/rlz_tracker_unittest.cc and
 // src/rlz/lib/rlz_lib_test.cc
@@ -46,8 +50,18 @@
 };
 
 class RlzLibTestBase : public RlzLibTestNoMachineState {
+ public:
+  RlzLibTestBase();
+  ~RlzLibTestBase() override;
+
  protected:
   void SetUp() override;
+  void TearDown() override;
+
+#if defined(OS_CHROMEOS)
+  std::unique_ptr<chromeos::system::FakeStatisticsProvider>
+      statistics_provider_;
+#endif
 };
 
 #endif  // RLZ_TEST_RLZ_TEST_HELPERS_H
diff --git a/services/audio/output_stream.cc b/services/audio/output_stream.cc
index e4b2477..8f54ff6a 100644
--- a/services/audio/output_stream.cc
+++ b/services/audio/output_stream.cc
@@ -27,7 +27,8 @@
     media::mojom::AudioLogPtr log,
     media::AudioManager* audio_manager,
     const std::string& output_device_id,
-    const media::AudioParameters& params)
+    const media::AudioParameters& params,
+    const base::UnguessableToken& group_id)
     : foreign_socket_(),
       created_callback_(std::move(created_callback)),
       delete_callback_(std::move(delete_callback)),
@@ -68,7 +69,7 @@
   }
 
   controller_ = media::AudioOutputController::Create(
-      audio_manager, this, params, output_device_id, reader_.get());
+      audio_manager, this, params, output_device_id, group_id, reader_.get());
 }
 
 OutputStream::~OutputStream() {
diff --git a/services/audio/output_stream.h b/services/audio/output_stream.h
index a1416a3..4068786 100644
--- a/services/audio/output_stream.h
+++ b/services/audio/output_stream.h
@@ -24,6 +24,10 @@
 #include "mojo/public/cpp/system/handle.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 
+namespace base {
+class UnguessableToken;
+}  // namespace base
+
 namespace media {
 class AudioManager;
 class AudioParameters;
@@ -47,7 +51,8 @@
                media::mojom::AudioLogPtr log,
                media::AudioManager* audio_manager,
                const std::string& output_device_id,
-               const media::AudioParameters& params);
+               const media::AudioParameters& params,
+               const base::UnguessableToken& group_id);
 
   ~OutputStream() final;
 
diff --git a/services/audio/public/mojom/stream_factory.mojom b/services/audio/public/mojom/stream_factory.mojom
index cabdc24..dd64dfb 100644
--- a/services/audio/public/mojom/stream_factory.mojom
+++ b/services/audio/public/mojom/stream_factory.mojom
@@ -4,7 +4,7 @@
 import "media/mojo/interfaces/audio_logging.mojom";
 import "media/mojo/interfaces/audio_output_stream.mojom";
 import "media/mojo/interfaces/audio_parameters.mojom";
-import "mojo/common/unguessable_token.mojom";
+import "mojo/public/mojom/base/unguessable_token.mojom";
 
 // This interface is exposed by the audio service to allow trusted clients
 // (like the browser process) to create streams. Note that while the factory
@@ -24,6 +24,6 @@
     associated media.mojom.AudioOutputStreamObserver observer,
     media.mojom.AudioLog log,
     string device_id, media.mojom.AudioParameters params,
-    mojo.common.mojom.UnguessableToken stream_group_id)
+    mojo_base.mojom.UnguessableToken stream_group_id)
     => (media.mojom.AudioDataPipe? data_pipe);
 };
diff --git a/services/audio/stream_factory.cc b/services/audio/stream_factory.cc
index 67e235c..62afd90 100644
--- a/services/audio/stream_factory.cc
+++ b/services/audio/stream_factory.cc
@@ -43,7 +43,7 @@
   output_streams_.insert(std::make_unique<OutputStream>(
       std::move(created_callback), std::move(deleter_callback),
       std::move(stream_request), std::move(client), std::move(observer),
-      std::move(log), audio_manager_, output_device_id, params));
+      std::move(log), audio_manager_, output_device_id, params, group_id));
 }
 
 void StreamFactory::RemoveOutputStream(OutputStream* stream) {
diff --git a/services/network/BUILD.gn b/services/network/BUILD.gn
index a7cf45ba..81fe393 100644
--- a/services/network/BUILD.gn
+++ b/services/network/BUILD.gn
@@ -84,6 +84,17 @@
     "url_request_context_owner.h",
   ]
 
+  if (!is_ios) {
+    sources += [
+      "websocket.cc",
+      "websocket.h",
+      "websocket_factory.cc",
+      "websocket_factory.h",
+      "websocket_throttler.cc",
+      "websocket_throttler.h",
+    ]
+  }
+
   deps = [
     "//base",
     "//components/cookie_config",
@@ -154,7 +165,10 @@
   ]
 
   if (!is_ios) {
-    sources += [ "proxy_resolver_factory_mojo_unittest.cc" ]
+    sources += [
+      "proxy_resolver_factory_mojo_unittest.cc",
+      "websocket_throttler_unittest.cc",
+    ]
   }
 
   deps = [
diff --git a/services/network/network_context.cc b/services/network/network_context.cc
index 2cefc6f..0f83023b 100644
--- a/services/network/network_context.cc
+++ b/services/network/network_context.cc
@@ -14,7 +14,6 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/task_scheduler/post_task.h"
 #include "base/task_scheduler/task_traits.h"
-#include "build/build_config.h"
 #include "components/cookie_config/cookie_store_util.h"
 #include "components/network_session_configurator/browser/network_session_configurator.h"
 #include "components/network_session_configurator/common/network_switches.h"
@@ -55,6 +54,10 @@
 #include "services/network/url_loader_factory.h"
 #include "services/network/url_request_context_builder_mojo.h"
 
+#if !defined(OS_IOS)
+#include "services/network/websocket_factory.h"
+#endif  // !defined(OS_IOS)
+
 namespace network {
 
 namespace {
@@ -121,7 +124,8 @@
       socket_factory_(network_service_->net_log()) {
   url_request_context_owner_ = ApplyContextParamsToBuilder(
       builder.get(), params_.get(), network_service->quic_disabled(),
-      network_service->net_log(), &user_agent_settings_);
+      network_service->net_log(), network_service->network_quality_estimator(),
+      &user_agent_settings_);
   url_request_context_getter_ =
       url_request_context_owner_.url_request_context_getter;
   network_service_->RegisterNetworkContext(this);
@@ -321,6 +325,8 @@
       &builder, network_context_params,
       network_service_ ? network_service_->quic_disabled() : false,
       network_service_ ? network_service_->net_log() : nullptr,
+      network_service_ ? network_service_->network_quality_estimator()
+                       : nullptr,
       &user_agent_settings_);
 }
 
@@ -329,10 +335,14 @@
     mojom::NetworkContextParams* network_context_params,
     bool quic_disabled,
     net::NetLog* net_log,
+    net::NetworkQualityEstimator* network_quality_estimator,
     net::StaticHttpUserAgentSettings** out_http_user_agent_settings) {
   if (net_log)
     builder->set_net_log(net_log);
 
+  if (network_quality_estimator)
+    builder->set_network_quality_estimator(network_quality_estimator);
+
   std::string accept_language = network_context_params->accept_language
                                     ? *network_context_params->accept_language
                                     : "en-us,en";
@@ -539,6 +549,18 @@
       std::move(request), std::move(observer), std::move(callback));
 }
 
+void NetworkContext::CreateWebSocket(mojom::WebSocketRequest request,
+                                     int32_t process_id,
+                                     int32_t render_frame_id,
+                                     const url::Origin& origin) {
+#if !defined(OS_IOS)
+  if (!websocket_factory_)
+    websocket_factory_ = std::make_unique<WebSocketFactory>(this);
+  websocket_factory_->CreateWebSocket(std::move(request), process_id,
+                                      render_frame_id, origin);
+#endif  // !defined(OS_IOS)
+}
+
 void NetworkContext::AddHSTSForTesting(const std::string& host,
                                        base::Time expiry,
                                        bool include_subdomains,
diff --git a/services/network/network_context.h b/services/network/network_context.h
index ad382155..2fc1b8ec 100644
--- a/services/network/network_context.h
+++ b/services/network/network_context.h
@@ -15,6 +15,7 @@
 #include "base/component_export.h"
 #include "base/macros.h"
 #include "base/time/time.h"
+#include "build/build_config.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/bindings/strong_binding_set.h"
 #include "services/network/cookie_manager.h"
@@ -23,11 +24,13 @@
 #include "services/network/public/mojom/tcp_socket.mojom.h"
 #include "services/network/public/mojom/udp_socket.mojom.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "services/network/public/mojom/websocket.mojom.h"
 #include "services/network/socket_factory.h"
 #include "services/network/url_request_context_owner.h"
 
 namespace net {
 class CertVerifier;
+class NetworkQualityEstimator;
 class StaticHttpUserAgentSettings;
 class URLRequestContext;
 }  // namespace net
@@ -37,6 +40,7 @@
 class ResourceScheduler;
 class ResourceSchedulerClient;
 class URLRequestContextBuilderMojo;
+class WebSocketFactory;
 
 // A NetworkContext creates and manages access to a URLRequestContext.
 //
@@ -128,6 +132,10 @@
       mojom::TCPConnectedSocketRequest request,
       mojom::TCPConnectedSocketObserverPtr observer,
       CreateTCPConnectedSocketCallback callback) override;
+  void CreateWebSocket(mojom::WebSocketRequest request,
+                       int32_t process_id,
+                       int32_t render_frame_id,
+                       const url::Origin& origin) override;
   void AddHSTSForTesting(const std::string& host,
                          base::Time expiry,
                          bool include_subdomains,
@@ -151,6 +159,7 @@
       mojom::NetworkContextParams* network_context_params,
       bool quic_disabled,
       net::NetLog* net_log,
+      net::NetworkQualityEstimator* network_quality_estimator,
       net::StaticHttpUserAgentSettings** out_http_user_agent_settings);
 
  private:
@@ -190,6 +199,10 @@
 
   SocketFactory socket_factory_;
 
+#if !defined(OS_IOS)
+  std::unique_ptr<WebSocketFactory> websocket_factory_;
+#endif  // !defined(OS_IOS)
+
   std::vector<std::unique_ptr<HttpCacheDataRemover>> http_cache_data_removers_;
 
   int current_resource_scheduler_client_id_ = 0;
diff --git a/services/network/network_service.cc b/services/network/network_service.cc
index 58324f4..56a94ef4 100644
--- a/services/network/network_service.cc
+++ b/services/network/network_service.cc
@@ -4,11 +4,13 @@
 
 #include "services/network/network_service.h"
 
+#include <map>
 #include <utility>
 
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
+#include "base/metrics/field_trial_params.h"
 #include "base/values.h"
 #include "build/build_config.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
@@ -17,6 +19,8 @@
 #include "net/log/file_net_log_observer.h"
 #include "net/log/net_log.h"
 #include "net/log/net_log_util.h"
+#include "net/nqe/network_quality_estimator.h"
+#include "net/nqe/network_quality_estimator_params.h"
 #include "net/url_request/url_request_context_builder.h"
 #include "services/network/network_context.h"
 #include "services/network/public/cpp/network_switches.h"
@@ -26,6 +30,11 @@
 
 namespace {
 
+// Field trial for network quality estimator. Seeds RTT and downstream
+// throughput observations with values that correspond to the connection type
+// determined by the operating system.
+const char kNetworkQualityEstimatorFieldTrialName[] = "NetworkQualityEstimator";
+
 std::unique_ptr<net::NetworkChangeNotifier>
 CreateNetworkChangeNotifierIfNeeded() {
   // There is a global singleton net::NetworkChangeNotifier if NetworkService
@@ -102,6 +111,7 @@
   network_change_manager_ = std::make_unique<NetworkChangeManager>(
       CreateNetworkChangeNotifierIfNeeded());
 
+  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
   if (net_log) {
     net_log_ = net_log;
   } else {
@@ -109,7 +119,7 @@
     // Note: The command line switches are only checked when not using the
     // embedder's NetLog, as it may already be writing to the destination log
     // file.
-    owned_net_log_->ProcessCommandLine(*base::CommandLine::ForCurrentProcess());
+    owned_net_log_->ProcessCommandLine(*command_line);
     net_log_ = owned_net_log_.get();
   }
 
@@ -118,6 +128,28 @@
   // logging the network change before other IO thread consumers respond to it.
   network_change_observer_.reset(
       new net::LoggingNetworkChangeObserver(net_log_));
+
+  std::map<std::string, std::string> network_quality_estimator_params;
+  base::GetFieldTrialParams(kNetworkQualityEstimatorFieldTrialName,
+                            &network_quality_estimator_params);
+
+  if (command_line->HasSwitch(switches::kForceEffectiveConnectionType)) {
+    const std::string force_ect_value = command_line->GetSwitchValueASCII(
+        switches::kForceEffectiveConnectionType);
+
+    if (!force_ect_value.empty()) {
+      // If the effective connection type is forced using command line switch,
+      // it overrides the one set by field trial.
+      network_quality_estimator_params[net::kForceEffectiveConnectionType] =
+          force_ect_value;
+    }
+  }
+
+  // Pass ownership.
+  network_quality_estimator_ = std::make_unique<net::NetworkQualityEstimator>(
+      std::make_unique<net::NetworkQualityEstimatorParams>(
+          network_quality_estimator_params),
+      net_log_);
 }
 
 NetworkService::~NetworkService() {
diff --git a/services/network/network_service.h b/services/network/network_service.h
index 51922c3..0885926 100644
--- a/services/network/network_service.h
+++ b/services/network/network_service.h
@@ -21,8 +21,9 @@
 #include "services/service_manager/public/cpp/service.h"
 
 namespace net {
-class NetLog;
 class LoggingNetworkChangeObserver;
+class NetLog;
+class NetworkQualityEstimator;
 class URLRequestContext;
 }  // namespace net
 
@@ -96,6 +97,9 @@
   bool HasRawHeadersAccess(uint32_t process_id) const;
 
   mojom::NetworkServiceClient* client() { return client_.get(); }
+  net::NetworkQualityEstimator* network_quality_estimator() {
+    return network_quality_estimator_.get();
+  }
   net::NetLog* net_log() const;
   KeepaliveStatisticsRecorder* keepalive_statistics_recorder() {
     return &keepalive_statistics_recorder_;
@@ -129,6 +133,8 @@
 
   mojo::Binding<mojom::NetworkService> binding_;
 
+  std::unique_ptr<net::NetworkQualityEstimator> network_quality_estimator_;
+
   // NetworkContexts register themselves with the NetworkService so that they
   // can be cleaned up when the NetworkService goes away. This is needed as
   // NetworkContexts share global state with the NetworkService, so must be
diff --git a/services/network/proxy_resolving_client_socket.cc b/services/network/proxy_resolving_client_socket.cc
index b6d30af..b1c779be 100644
--- a/services/network/proxy_resolving_client_socket.cc
+++ b/services/network/proxy_resolving_client_socket.cc
@@ -312,8 +312,7 @@
       // code expects an SSLClientSocket. The tunnel restart code is careful to
       // put it back to the socket pool before returning control to the rest of
       // this class.
-      socket_handle_.reset(
-          socket_handle_->release_pending_http_proxy_connection());
+      socket_handle_ = socket_handle_->release_pending_http_proxy_connection();
     }
     next_state_ = STATE_RESTART_TUNNEL_AUTH;
     return result;
diff --git a/services/network/public/cpp/network_param_ipc_traits.h b/services/network/public/cpp/network_param_ipc_traits.h
index a52c22f..1f8ed90e 100644
--- a/services/network/public/cpp/network_param_ipc_traits.h
+++ b/services/network/public/cpp/network_param_ipc_traits.h
@@ -309,6 +309,7 @@
   IPC_STRUCT_TRAITS_MEMBER(method)
   IPC_STRUCT_TRAITS_MEMBER(url)
   IPC_STRUCT_TRAITS_MEMBER(site_for_cookies)
+  IPC_STRUCT_TRAITS_MEMBER(attach_same_site_cookies)
   IPC_STRUCT_TRAITS_MEMBER(update_first_party_url_on_redirect)
   IPC_STRUCT_TRAITS_MEMBER(request_initiator)
   IPC_STRUCT_TRAITS_MEMBER(referrer)
diff --git a/services/network/public/cpp/network_switches.cc b/services/network/public/cpp/network_switches.cc
index efed4b7..7790a6f 100644
--- a/services/network/public/cpp/network_switches.cc
+++ b/services/network/public/cpp/network_switches.cc
@@ -8,6 +8,10 @@
 
 namespace switches {
 
+// Forces Network Quality Estimator (NQE) to return a specific effective
+// connection type.
+const char kForceEffectiveConnectionType[] = "force-effective-connection-type";
+
 // These mappings only apply to the host resolver.
 const char kHostResolverRules[] = "host-resolver-rules";
 
diff --git a/services/network/public/cpp/network_switches.h b/services/network/public/cpp/network_switches.h
index 411e455b..3829a2d 100644
--- a/services/network/public/cpp/network_switches.h
+++ b/services/network/public/cpp/network_switches.h
@@ -11,6 +11,7 @@
 
 namespace switches {
 
+COMPONENT_EXPORT(NETWORK_CPP) extern const char kForceEffectiveConnectionType[];
 COMPONENT_EXPORT(NETWORK_CPP)
 extern const char kHostResolverRules[];
 COMPONENT_EXPORT(NETWORK_CPP)
diff --git a/services/network/public/cpp/resource_request.h b/services/network/public/cpp/resource_request.h
index e5a532c9..085ab85c 100644
--- a/services/network/public/cpp/resource_request.h
+++ b/services/network/public/cpp/resource_request.h
@@ -42,6 +42,11 @@
   // done if there really is no way to determine the correct value.
   GURL site_for_cookies;
 
+  // Boolean indicating whether SameSite cookies are allowed to be attached
+  // to the request. It should be used as additional input to network side
+  // checks.
+  bool attach_same_site_cookies = false;
+
   // First-party URL redirect policy: During server redirects, the first-party
   // URL for cookies normally doesn't change. However, if this is true, the
   // the first-party URL should be updated to the URL on every redirect.
diff --git a/services/network/public/mojom/BUILD.gn b/services/network/public/mojom/BUILD.gn
index 595ad7f..8f45c93 100644
--- a/services/network/public/mojom/BUILD.gn
+++ b/services/network/public/mojom/BUILD.gn
@@ -51,6 +51,25 @@
   ]
 }
 
+# This target is split from "mojom" target as the lazy serialization may
+# cause problems. See https://crbug.com/822732.
+mojom("websocket_mojom") {
+  sources = [
+    "websocket.mojom",
+  ]
+
+  public_deps = [
+    "//url/mojom:url_mojom_gurl",
+    "//url/mojom:url_mojom_origin",
+  ]
+
+  if (!is_ios) {
+    export_class_attribute_blink = "BLINK_PLATFORM_EXPORT"
+    export_define_blink = "BLINK_PLATFORM_IMPLEMENTATION=1"
+    export_header_blink = "third_party/WebKit/public/platform/WebCommon.h"
+  }
+}
+
 mojom("mojom") {
   # URLLoader & URLLoaderFactory are used in-process in the browser when
   # navigation uses URLLoader (NavigationMojoResponse) and in the renderer
@@ -80,6 +99,7 @@
     ":data_pipe_interfaces",
     ":mutable_network_traffic_annotation_interface",
     ":udp_socket_interface",
+    ":websocket_mojom",
     "//mojo/public/mojom/base",
     "//net/interfaces",
     "//services/proxy_resolver/public/mojom",
diff --git a/services/network/public/mojom/network_service.mojom b/services/network/public/mojom/network_service.mojom
index d4f44f8..b737757 100644
--- a/services/network/public/mojom/network_service.mojom
+++ b/services/network/public/mojom/network_service.mojom
@@ -18,6 +18,7 @@
 import "services/network/public/mojom/url_loader.mojom";
 import "services/network/public/mojom/network_param.mojom";
 import "services/network/public/mojom/url_loader_factory.mojom";
+import "services/network/public/mojom/websocket.mojom";
 import "services/proxy_resolver/public/mojom/proxy_resolver.mojom";
 import "services/network/public/mojom/restricted_cookie_manager.mojom";
 import "url/mojom/origin.mojom";
@@ -233,6 +234,12 @@
          handle<data_pipe_consumer>? receive_stream,
          handle<data_pipe_producer>? send_stream);
 
+  // Creates a WebSocket connection.
+  CreateWebSocket(WebSocket& request,
+                  int32 process_id,
+                  int32 render_frame_id,
+                  url.mojom.Origin origin);
+
   [Sync]
   // Adds explicitly-specified data as if it was processed from an
   // HSTS header.
diff --git a/services/network/public/mojom/websocket.mojom b/services/network/public/mojom/websocket.mojom
new file mode 100644
index 0000000..d6cb515
--- /dev/null
+++ b/services/network/public/mojom/websocket.mojom
@@ -0,0 +1,140 @@
+// 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 network.mojom;
+
+import "url/mojom/url.mojom";
+
+enum WebSocketMessageType {
+  CONTINUATION,
+  TEXT,
+  BINARY,
+  LAST = BINARY
+};
+
+// TODO(darin): Move to a more general location.
+struct HttpHeader {
+  string name;
+  string value;
+};
+
+// TODO(darin): Remove redundancy b/w |headers| and |headers_text|.
+
+struct WebSocketHandshakeRequest {
+  url.mojom.Url url;
+  array<HttpHeader> headers;
+  string headers_text;
+};
+
+struct WebSocketHandshakeResponse {
+  url.mojom.Url url;
+  int32 status_code;
+  string status_text;
+  array<HttpHeader> headers;
+  string headers_text;
+};
+
+interface WebSocketClient {
+  OnFailChannel(string reason);
+
+  // Notify the renderer that the browser has started an opening handshake.
+  // This message is for showing the request in the inspector and
+  // can be omitted if the inspector is not active.
+  OnStartOpeningHandshake(WebSocketHandshakeRequest request);
+
+  // Notify the renderer that the browser has finished an opening handshake.
+  // This message precedes AddChannelResponse.
+  // This message is for showing the response in the inspector and
+  // can be omitted if the inspector is not active.
+  OnFinishOpeningHandshake(WebSocketHandshakeResponse response);
+
+  // Response to an AddChannelRequest. |selected_protocol| is the sub-protocol
+  // the server selected, or empty if no sub-protocol was selected.
+  // |extensions| is the list of extensions negotiated for the connection.
+  OnAddChannelResponse(string selected_protocol, string extensions);
+
+  // Receive a non-control frame from the remote server.
+  // - |fin| indicates that this frame is the last in the current message.
+  // - |type| is the type of the message. On the first frame of a message, it
+  //   must be set to either WebSocketMessageType.TEXT or
+  //   WebSocketMessageType.BINARY. On subsequent frames, it must be set to
+  //   WebSocketMessageType.CONTINUATION, and the type is the same as that of
+  //   the first message. If |type| is WebSocketMessageType.TEXT, then the
+  //   concatenation of the |data| from every frame in the message must be valid
+  //   UTF-8. If |fin| is not set, |data| must be non-empty.
+  OnDataFrame(bool fin, WebSocketMessageType type, array<uint8> data);
+
+  // Add |quota| tokens of send quota for the channel. |quota| must be a
+  // positive integer. Both the browser and the renderer set send quota for the
+  // other side, and check that quota has not been exceeded when receiving
+  // messages.  Both sides start a new channel with a quota of 0, and must wait
+  // for a FlowControl message before calling SendFrame. The total available
+  // quota on one side must never exceed 0x7FFFFFFFFFFFFFFF tokens.
+  OnFlowControl(int64 quota);
+
+  // Drop the channel.
+  //
+  // When sent by the renderer, this will cause a Close message will be sent and
+  // the TCP/IP connection will be closed.
+  //
+  // When sent by the browser, this indicates that a Close has been received,
+  // the connection was closed, or a network or protocol error occurred.
+  //
+  // - |code| is one of the reason codes specified in RFC6455.
+  // - |reason|, if non-empty, is a UTF-8 encoded string which may be useful
+  //   for debugging but is not necessarily human-readable, as supplied by the
+  //   server in the Close message.
+  // - If |was_clean| is false, then the WebSocket connection was not closed
+  //   cleanly.
+  OnDropChannel(bool was_clean, uint16 code, string reason);
+
+  // Notify the renderer that a closing handshake has been initiated by the
+  // server, so that it can set the Javascript readyState to CLOSING.
+  OnClosingHandshake();
+};
+
+interface WebSocket {
+  // The client side may observe the following disconnection reason from the
+  // service side:
+  const uint32 kInsufficientResources = 1;
+
+  // Open new WebSocket connection to |socket_url|. |requested_protocols| is a
+  // list of tokens identifying sub-protocols the renderer would like to use,
+  // as described in RFC6455 "Subprotocols Using the WebSocket Protocol".
+  AddChannelRequest(url.mojom.Url url,
+                    array<string> requested_protocols,
+                    url.mojom.Url first_party_for_cookies,
+                    string user_agent_override,
+                    WebSocketClient client);
+
+  // Send a non-control frame to the remote server.
+  // - |fin| indicates that this frame is the last in the current message.
+  // - |type| is the type of the message. On the first frame of a message, it
+  //   must be set to either WebSocketMessageType.TEXT or
+  //   WebSocketMessageType.BINARY. On subsequent frames, it must be set to
+  //   WebSocketMessageType.CONTINUATION, and the type is the same as that of
+  //   the first message. If |type| is WebSocketMessageType.TEXT, then the
+  //   concatenation of the |data| from every frame in the message must be valid
+  //   UTF-8. If |fin| is not set, |data| must be non-empty.
+  SendFrame(bool fin, WebSocketMessageType type, array<uint8> data);
+
+  // Add |quota| tokens of send quota for the channel. |quota| must be a
+  // positive integer. Both the browser and the renderer set send quota for the
+  // other side, and check that quota has not been exceeded when receiving
+  // messages.  Both sides start a new channel with a quota of 0, and must wait
+  // for a FlowControl message before calling SendFrame. The total available
+  // quota on one side must never exceed 0x7FFFFFFFFFFFFFFF tokens.
+  SendFlowControl(int64 quota);
+
+  // Close the channel gracefully.
+  //
+  // When sent by the renderer, this will cause a Close message will be sent and
+  // the TCP/IP connection will be closed.
+  //
+  // - |code| is one of the reason codes specified in RFC6455.
+  // - |reason|, if non-empty, is a UTF-8 encoded string which may be useful for
+  //   debugging but is not necessarily human-readable, as supplied by the
+  //   server in the Close message.
+  StartClosingHandshake(uint16 code, string reason);
+};
diff --git a/services/network/resource_scheduler.cc b/services/network/resource_scheduler.cc
index 467a282..a05765a 100644
--- a/services/network/resource_scheduler.cc
+++ b/services/network/resource_scheduler.cc
@@ -72,7 +72,7 @@
 // may also throttle delayable requests based on the number of non-delayable
 // requests in-flight times a weighting factor.
 const base::Feature kThrottleDelayable{"ThrottleDelayable",
-                                       base::FEATURE_DISABLED_BY_DEFAULT};
+                                       base::FEATURE_ENABLED_BY_DEFAULT};
 
 enum StartMode { START_SYNC, START_ASYNC };
 
diff --git a/services/network/resource_scheduler_unittest.cc b/services/network/resource_scheduler_unittest.cc
index a22bd06b..a336ad70 100644
--- a/services/network/resource_scheduler_unittest.cc
+++ b/services/network/resource_scheduler_unittest.cc
@@ -383,12 +383,13 @@
 
     std::unique_ptr<base::FeatureList> feature_list(
         std::make_unique<base::FeatureList>());
-    feature_list->RegisterFieldTrialOverride(
-        "ThrottleDelayable",
-        experiment_enabled ? base::FeatureList::OVERRIDE_ENABLE_FEATURE
-                           : base::FeatureList::OVERRIDE_DISABLE_FEATURE,
-        field_trial);
-    scoped_feature_list->InitWithFeatureList(std::move(feature_list));
+
+    if (experiment_enabled) {
+      feature_list->RegisterFieldTrialOverride(
+          "ThrottleDelayable", base::FeatureList::OVERRIDE_ENABLE_FEATURE,
+          field_trial);
+      scoped_feature_list->InitWithFeatureList(std::move(feature_list));
+    }
 
     ResourceScheduler::ParamsForNetworkQualityContainer
         params_network_quality_container =
@@ -1830,6 +1831,67 @@
   EXPECT_EQ(3.0, params_network_quality_container[1].non_delayable_weight);
 }
 
+TEST_F(ResourceSchedulerTest, ThrottleDelayableDisabled) {
+  base::FieldTrialParamAssociator::GetInstance()->ClearAllParamsForTesting();
+
+  const char kTrialName[] = "TrialName";
+  const char kGroupName[] = "GroupName";
+
+  base::FieldTrial* field_trial =
+      base::FieldTrialList::CreateFieldTrial(kTrialName, kGroupName);
+
+  base::test::ScopedFeatureList scoped_feature_list;
+
+  std::unique_ptr<base::FeatureList> feature_list(
+      std::make_unique<base::FeatureList>());
+
+  feature_list->RegisterFieldTrialOverride(
+      "ThrottleDelayable", base::FeatureList::OVERRIDE_DISABLE_FEATURE,
+      field_trial);
+  scoped_feature_list.InitWithFeatureList(std::move(feature_list));
+
+  ResourceScheduler::ParamsForNetworkQualityContainer
+      params_network_quality_container =
+          ResourceScheduler::GetParamsForNetworkQualityContainerForTests();
+
+  EXPECT_EQ(2u, params_network_quality_container.size());
+  EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G,
+            params_network_quality_container[0].effective_connection_type);
+  EXPECT_EQ(8u, params_network_quality_container[0].max_delayable_requests);
+  EXPECT_EQ(3.0, params_network_quality_container[0].non_delayable_weight);
+
+  EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_2G,
+            params_network_quality_container[1].effective_connection_type);
+  EXPECT_EQ(8u, params_network_quality_container[1].max_delayable_requests);
+  EXPECT_EQ(3.0, params_network_quality_container[1].non_delayable_weight);
+
+  InitializeScheduler();
+  network_quality_estimator_.set_effective_connection_type(
+      net::EFFECTIVE_CONNECTION_TYPE_2G);
+  scheduler()->DeprecatedOnNavigate(kChildId, kRouteId);
+  scheduler()->DeprecatedOnWillInsertBody(kChildId, kRouteId);
+  // Insert one non-delayable request. This should not affect the number of
+  // delayable requests started.
+  std::unique_ptr<TestRequest> medium(
+      NewRequest("http://host/medium", net::MEDIUM));
+  ASSERT_TRUE(medium->started());
+  // Start |kDefaultMaxNumDelayableRequestsPerClient| delayable requests and
+  // verify that they all started.
+  // When one high priority request is in flight, the number of low priority
+  // requests allowed in flight are |max_delayable_requests| -
+  // |non_delayable_weight|  = 8 - 3 = 5.
+  std::vector<std::unique_ptr<TestRequest>> delayable_requests;
+  for (int i = 0; i < 5; ++i) {
+    delayable_requests.push_back(NewRequest(
+        base::StringPrintf("http://host%d/low", i).c_str(), net::LOWEST));
+    EXPECT_TRUE(delayable_requests.back()->started());
+  }
+
+  delayable_requests.push_back(
+      NewRequest("http://host/low-blocked", net::LOWEST));
+  EXPECT_FALSE(delayable_requests.back()->started());
+}
+
 // Test that the default limit is used for delayable requests when the
 // experiment is enabled, but the current effective connection type is higher
 // than the maximum effective connection type set in the experiment
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc
index aa31009..fc858937 100644
--- a/services/network/url_loader.cc
+++ b/services/network/url_loader.cc
@@ -308,6 +308,7 @@
           GURL(request.url), request.priority, this, traffic_annotation);
   url_request_->set_method(request.method);
   url_request_->set_site_for_cookies(request.site_for_cookies);
+  url_request_->set_attach_same_site_cookies(request.attach_same_site_cookies);
   url_request_->SetReferrer(ComputeReferrer(request.referrer));
   url_request_->set_referrer_policy(request.referrer_policy);
   url_request_->SetExtraRequestHeaders(request.headers);
diff --git a/services/network/url_request_context_builder_mojo.cc b/services/network/url_request_context_builder_mojo.cc
index adfbc90..c9ba9f2 100644
--- a/services/network/url_request_context_builder_mojo.cc
+++ b/services/network/url_request_context_builder_mojo.cc
@@ -35,9 +35,10 @@
 URLRequestContextOwner URLRequestContextBuilderMojo::Create(
     mojom::NetworkContextParams* params,
     bool quic_disabled,
-    net::NetLog* net_log) {
+    net::NetLog* net_log,
+    net::NetworkQualityEstimator* network_quality_estimator) {
   return NetworkContext::ApplyContextParamsToBuilder(
-      this, params, quic_disabled, net_log,
+      this, params, quic_disabled, net_log, network_quality_estimator,
       nullptr /* out_static_user_agent_settings */);
 }
 
diff --git a/services/network/url_request_context_builder_mojo.h b/services/network/url_request_context_builder_mojo.h
index 4fd04b5..499d7e9 100644
--- a/services/network/url_request_context_builder_mojo.h
+++ b/services/network/url_request_context_builder_mojo.h
@@ -55,9 +55,11 @@
   //
   // This method is intended to ease the transition to an out-of-process
   // NetworkService, and will be removed once that ships.
-  URLRequestContextOwner Create(mojom::NetworkContextParams* params,
-                                bool quic_disabled,
-                                net::NetLog* net_log);
+  URLRequestContextOwner Create(
+      mojom::NetworkContextParams* params,
+      bool quic_disabled,
+      net::NetLog* net_log,
+      net::NetworkQualityEstimator* network_quality_estimator);
 
  private:
   std::unique_ptr<net::ProxyResolutionService> CreateProxyService(
diff --git a/services/network/websocket.cc b/services/network/websocket.cc
new file mode 100644
index 0000000..dd28c00
--- /dev/null
+++ b/services/network/websocket.cc
@@ -0,0 +1,455 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/network/websocket.h"
+
+#include <inttypes.h>
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/single_thread_task_runner.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/http/http_request_headers.h"
+#include "net/http/http_response_headers.h"
+#include "net/http/http_util.h"
+#include "net/ssl/ssl_info.h"
+#include "net/websockets/websocket_channel.h"
+#include "net/websockets/websocket_errors.h"
+#include "net/websockets/websocket_frame.h"  // for WebSocketFrameHeader::OpCode
+#include "net/websockets/websocket_handshake_request_info.h"
+#include "net/websockets/websocket_handshake_response_info.h"
+
+namespace network {
+namespace {
+
+typedef net::WebSocketEventInterface::ChannelState ChannelState;
+
+// Convert a mojom::WebSocketMessageType to a
+// net::WebSocketFrameHeader::OpCode
+net::WebSocketFrameHeader::OpCode MessageTypeToOpCode(
+    mojom::WebSocketMessageType type) {
+  DCHECK(type == mojom::WebSocketMessageType::CONTINUATION ||
+         type == mojom::WebSocketMessageType::TEXT ||
+         type == mojom::WebSocketMessageType::BINARY);
+  typedef net::WebSocketFrameHeader::OpCode OpCode;
+  // These compile asserts verify that the same underlying values are used for
+  // both types, so we can simply cast between them.
+  static_assert(
+      static_cast<OpCode>(mojom::WebSocketMessageType::CONTINUATION) ==
+          net::WebSocketFrameHeader::kOpCodeContinuation,
+      "enum values must match for opcode continuation");
+  static_assert(static_cast<OpCode>(mojom::WebSocketMessageType::TEXT) ==
+                    net::WebSocketFrameHeader::kOpCodeText,
+                "enum values must match for opcode text");
+  static_assert(static_cast<OpCode>(mojom::WebSocketMessageType::BINARY) ==
+                    net::WebSocketFrameHeader::kOpCodeBinary,
+                "enum values must match for opcode binary");
+  return static_cast<OpCode>(type);
+}
+
+mojom::WebSocketMessageType OpCodeToMessageType(
+    net::WebSocketFrameHeader::OpCode opCode) {
+  DCHECK(opCode == net::WebSocketFrameHeader::kOpCodeContinuation ||
+         opCode == net::WebSocketFrameHeader::kOpCodeText ||
+         opCode == net::WebSocketFrameHeader::kOpCodeBinary);
+  // This cast is guaranteed valid by the static_assert() statements above.
+  return static_cast<mojom::WebSocketMessageType>(opCode);
+}
+
+}  // namespace
+
+// Implementation of net::WebSocketEventInterface. Receives events from our
+// WebSocketChannel object.
+class WebSocket::WebSocketEventHandler final
+    : public net::WebSocketEventInterface {
+ public:
+  explicit WebSocketEventHandler(WebSocket* impl);
+  ~WebSocketEventHandler() override;
+
+  // net::WebSocketEventInterface implementation
+
+  void OnCreateURLRequest(net::URLRequest* url_request) override;
+  ChannelState OnAddChannelResponse(const std::string& selected_subprotocol,
+                                    const std::string& extensions) override;
+  ChannelState OnDataFrame(bool fin,
+                           WebSocketMessageType type,
+                           scoped_refptr<net::IOBuffer> buffer,
+                           size_t buffer_size) override;
+  ChannelState OnClosingHandshake() override;
+  ChannelState OnFlowControl(int64_t quota) override;
+  ChannelState OnDropChannel(bool was_clean,
+                             uint16_t code,
+                             const std::string& reason) override;
+  ChannelState OnFailChannel(const std::string& message) override;
+  ChannelState OnStartOpeningHandshake(
+      std::unique_ptr<net::WebSocketHandshakeRequestInfo> request) override;
+  ChannelState OnFinishOpeningHandshake(
+      std::unique_ptr<net::WebSocketHandshakeResponseInfo> response) override;
+  ChannelState OnSSLCertificateError(
+      std::unique_ptr<net::WebSocketEventInterface::SSLErrorCallbacks>
+          callbacks,
+      const GURL& url,
+      const net::SSLInfo& ssl_info,
+      bool fatal) override;
+
+ private:
+  WebSocket* const impl_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebSocketEventHandler);
+};
+
+WebSocket::WebSocketEventHandler::WebSocketEventHandler(WebSocket* impl)
+    : impl_(impl) {
+  DVLOG(1) << "WebSocketEventHandler created @"
+           << reinterpret_cast<void*>(this);
+}
+
+WebSocket::WebSocketEventHandler::~WebSocketEventHandler() {
+  DVLOG(1) << "WebSocketEventHandler destroyed @"
+           << reinterpret_cast<void*>(this);
+}
+
+void WebSocket::WebSocketEventHandler::OnCreateURLRequest(
+    net::URLRequest* url_request) {
+  impl_->delegate_->OnCreateURLRequest(impl_->child_id_, impl_->frame_id_,
+                                       url_request);
+}
+
+ChannelState WebSocket::WebSocketEventHandler::OnAddChannelResponse(
+    const std::string& selected_protocol,
+    const std::string& extensions) {
+  DVLOG(3) << "WebSocketEventHandler::OnAddChannelResponse @"
+           << reinterpret_cast<void*>(this) << " selected_protocol=\""
+           << selected_protocol << "\""
+           << " extensions=\"" << extensions << "\"";
+
+  impl_->handshake_succeeded_ = true;
+  impl_->pending_connection_tracker_.OnCompleteHandshake();
+
+  impl_->client_->OnAddChannelResponse(selected_protocol, extensions);
+
+  return net::WebSocketEventInterface::CHANNEL_ALIVE;
+}
+
+ChannelState WebSocket::WebSocketEventHandler::OnDataFrame(
+    bool fin,
+    net::WebSocketFrameHeader::OpCode type,
+    scoped_refptr<net::IOBuffer> buffer,
+    size_t buffer_size) {
+  DVLOG(3) << "WebSocketEventHandler::OnDataFrame @"
+           << reinterpret_cast<void*>(this) << " fin=" << fin
+           << " type=" << type << " data is " << buffer_size << " bytes";
+
+  // TODO(darin): Avoid this copy.
+  std::vector<uint8_t> data_to_pass(buffer_size);
+  if (buffer_size > 0) {
+    std::copy(buffer->data(), buffer->data() + buffer_size,
+              data_to_pass.begin());
+  }
+
+  impl_->client_->OnDataFrame(fin, OpCodeToMessageType(type), data_to_pass);
+
+  return net::WebSocketEventInterface::CHANNEL_ALIVE;
+}
+
+ChannelState WebSocket::WebSocketEventHandler::OnClosingHandshake() {
+  DVLOG(3) << "WebSocketEventHandler::OnClosingHandshake @"
+           << reinterpret_cast<void*>(this);
+
+  impl_->client_->OnClosingHandshake();
+
+  return net::WebSocketEventInterface::CHANNEL_ALIVE;
+}
+
+ChannelState WebSocket::WebSocketEventHandler::OnFlowControl(int64_t quota) {
+  DVLOG(3) << "WebSocketEventHandler::OnFlowControl @"
+           << reinterpret_cast<void*>(this) << " quota=" << quota;
+
+  impl_->client_->OnFlowControl(quota);
+
+  return net::WebSocketEventInterface::CHANNEL_ALIVE;
+}
+
+ChannelState WebSocket::WebSocketEventHandler::OnDropChannel(
+    bool was_clean,
+    uint16_t code,
+    const std::string& reason) {
+  DVLOG(3) << "WebSocketEventHandler::OnDropChannel @"
+           << reinterpret_cast<void*>(this) << " was_clean=" << was_clean
+           << " code=" << code << " reason=\"" << reason << "\"";
+
+  impl_->client_->OnDropChannel(was_clean, code, reason);
+
+  // net::WebSocketChannel requires that we delete it at this point.
+  impl_->channel_.reset();
+
+  return net::WebSocketEventInterface::CHANNEL_DELETED;
+}
+
+ChannelState WebSocket::WebSocketEventHandler::OnFailChannel(
+    const std::string& message) {
+  DVLOG(3) << "WebSocketEventHandler::OnFailChannel @"
+           << reinterpret_cast<void*>(this) << " message=\"" << message << "\"";
+
+  impl_->client_->OnFailChannel(message);
+
+  // net::WebSocketChannel requires that we delete it at this point.
+  impl_->channel_.reset();
+
+  return net::WebSocketEventInterface::CHANNEL_DELETED;
+}
+
+ChannelState WebSocket::WebSocketEventHandler::OnStartOpeningHandshake(
+    std::unique_ptr<net::WebSocketHandshakeRequestInfo> request) {
+  bool should_send = impl_->delegate_->CanReadRawCookies();
+
+  DVLOG(3) << "WebSocketEventHandler::OnStartOpeningHandshake @"
+           << reinterpret_cast<void*>(this) << " should_send=" << should_send;
+
+  if (!should_send)
+    return WebSocketEventInterface::CHANNEL_ALIVE;
+
+  mojom::WebSocketHandshakeRequestPtr request_to_pass(
+      mojom::WebSocketHandshakeRequest::New());
+  request_to_pass->url.Swap(&request->url);
+  net::HttpRequestHeaders::Iterator it(request->headers);
+  while (it.GetNext()) {
+    mojom::HttpHeaderPtr header(mojom::HttpHeader::New());
+    header->name = it.name();
+    header->value = it.value();
+    request_to_pass->headers.push_back(std::move(header));
+  }
+  request_to_pass->headers_text =
+      base::StringPrintf("GET %s HTTP/1.1\r\n",
+                         request_to_pass->url.spec().c_str()) +
+      request->headers.ToString();
+
+  impl_->client_->OnStartOpeningHandshake(std::move(request_to_pass));
+
+  return WebSocketEventInterface::CHANNEL_ALIVE;
+}
+
+ChannelState WebSocket::WebSocketEventHandler::OnFinishOpeningHandshake(
+    std::unique_ptr<net::WebSocketHandshakeResponseInfo> response) {
+  bool should_send = impl_->delegate_->CanReadRawCookies();
+
+  DVLOG(3) << "WebSocketEventHandler::OnFinishOpeningHandshake "
+           << reinterpret_cast<void*>(this) << " should_send=" << should_send;
+
+  if (!should_send)
+    return WebSocketEventInterface::CHANNEL_ALIVE;
+
+  mojom::WebSocketHandshakeResponsePtr response_to_pass(
+      mojom::WebSocketHandshakeResponse::New());
+  response_to_pass->url.Swap(&response->url);
+  response_to_pass->status_code = response->status_code;
+  response_to_pass->status_text = response->status_text;
+  size_t iter = 0;
+  std::string name, value;
+  while (response->headers->EnumerateHeaderLines(&iter, &name, &value)) {
+    mojom::HttpHeaderPtr header(mojom::HttpHeader::New());
+    header->name = name;
+    header->value = value;
+    response_to_pass->headers.push_back(std::move(header));
+  }
+  response_to_pass->headers_text =
+      net::HttpUtil::ConvertHeadersBackToHTTPResponse(
+          response->headers->raw_headers());
+
+  impl_->client_->OnFinishOpeningHandshake(std::move(response_to_pass));
+
+  return WebSocketEventInterface::CHANNEL_ALIVE;
+}
+
+ChannelState WebSocket::WebSocketEventHandler::OnSSLCertificateError(
+    std::unique_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks,
+    const GURL& url,
+    const net::SSLInfo& ssl_info,
+    bool fatal) {
+  DVLOG(3) << "WebSocketEventHandler::OnSSLCertificateError"
+           << reinterpret_cast<void*>(this) << " url=" << url.spec()
+           << " cert_status=" << ssl_info.cert_status << " fatal=" << fatal;
+  impl_->delegate_->OnSSLCertificateError(std::move(callbacks), url,
+                                          impl_->child_id_, impl_->frame_id_,
+                                          ssl_info, fatal);
+  // The above method is always asynchronous.
+  return WebSocketEventInterface::CHANNEL_ALIVE;
+}
+
+WebSocket::WebSocket(
+    std::unique_ptr<Delegate> delegate,
+    mojom::WebSocketRequest request,
+    WebSocketThrottler::PendingConnection pending_connection_tracker,
+    int child_id,
+    int frame_id,
+    url::Origin origin,
+    base::TimeDelta delay)
+    : delegate_(std::move(delegate)),
+      binding_(this, std::move(request)),
+      pending_connection_tracker_(std::move(pending_connection_tracker)),
+      delay_(delay),
+      pending_flow_control_quota_(0),
+      child_id_(child_id),
+      frame_id_(frame_id),
+      origin_(std::move(origin)),
+      handshake_succeeded_(false),
+      weak_ptr_factory_(this) {
+  binding_.set_connection_error_handler(
+      base::BindOnce(&WebSocket::OnConnectionError, base::Unretained(this)));
+}
+
+WebSocket::~WebSocket() {}
+
+void WebSocket::GoAway() {
+  StartClosingHandshake(static_cast<uint16_t>(net::kWebSocketErrorGoingAway),
+                        "");
+}
+
+void WebSocket::AddChannelRequest(
+    const GURL& socket_url,
+    const std::vector<std::string>& requested_protocols,
+    const GURL& site_for_cookies,
+    const std::string& user_agent_override,
+    mojom::WebSocketClientPtr client) {
+  DVLOG(3) << "WebSocket::AddChannelRequest @" << reinterpret_cast<void*>(this)
+           << " socket_url=\"" << socket_url << "\" requested_protocols=\""
+           << base::JoinString(requested_protocols, ", ") << "\" origin=\""
+           << origin_ << "\" site_for_cookies=\"" << site_for_cookies
+           << "\" user_agent_override=\"" << user_agent_override << "\"";
+
+  if (client_ || !client) {
+    delegate_->ReportBadMessage(
+        Delegate::BadMessageReason::kUnexpectedAddChannelRequest, this);
+    return;
+  }
+
+  client_ = std::move(client);
+
+  DCHECK(!channel_);
+  if (delay_ > base::TimeDelta()) {
+    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+        FROM_HERE,
+        base::BindOnce(&WebSocket::AddChannel, weak_ptr_factory_.GetWeakPtr(),
+                       socket_url, requested_protocols, site_for_cookies,
+                       user_agent_override),
+        delay_);
+  } else {
+    AddChannel(socket_url, requested_protocols, site_for_cookies,
+               user_agent_override);
+  }
+}
+
+void WebSocket::SendFrame(bool fin,
+                          mojom::WebSocketMessageType type,
+                          const std::vector<uint8_t>& data) {
+  DVLOG(3) << "WebSocket::SendFrame @" << reinterpret_cast<void*>(this)
+           << " fin=" << fin << " type=" << type << " data is " << data.size()
+           << " bytes";
+
+  if (!channel_) {
+    // The client should not be sending us frames until after we've informed
+    // it that the channel has been opened (OnAddChannelResponse).
+    if (handshake_succeeded_) {
+      DVLOG(1) << "Dropping frame sent to closed websocket";
+    } else {
+      delegate_->ReportBadMessage(
+          Delegate::BadMessageReason::kUnexpectedSendFrame, this);
+    }
+    return;
+  }
+
+  // TODO(darin): Avoid this copy.
+  scoped_refptr<net::IOBuffer> data_to_pass(new net::IOBuffer(data.size()));
+  std::copy(data.begin(), data.end(), data_to_pass->data());
+
+  channel_->SendFrame(fin, MessageTypeToOpCode(type), std::move(data_to_pass),
+                      data.size());
+}
+
+void WebSocket::SendFlowControl(int64_t quota) {
+  DVLOG(3) << "WebSocket::OnFlowControl @" << reinterpret_cast<void*>(this)
+           << " quota=" << quota;
+
+  if (!channel_) {
+    // WebSocketChannel is not yet created due to the delay introduced by
+    // per-renderer WebSocket throttling.
+    // SendFlowControl() is called after WebSocketChannel is created.
+    pending_flow_control_quota_ += quota;
+    return;
+  }
+
+  ignore_result(channel_->SendFlowControl(quota));
+}
+
+void WebSocket::StartClosingHandshake(uint16_t code,
+                                      const std::string& reason) {
+  DVLOG(3) << "WebSocket::StartClosingHandshake @"
+           << reinterpret_cast<void*>(this) << " code=" << code << " reason=\""
+           << reason << "\"";
+
+  if (!channel_) {
+    // WebSocketChannel is not yet created due to the delay introduced by
+    // per-renderer WebSocket throttling.
+    if (client_)
+      client_->OnDropChannel(false, net::kWebSocketErrorAbnormalClosure, "");
+    return;
+  }
+
+  ignore_result(channel_->StartClosingHandshake(code, reason));
+}
+
+void WebSocket::OnConnectionError() {
+  DVLOG(3) << "WebSocket::OnConnectionError @" << reinterpret_cast<void*>(this);
+
+  delegate_->OnLostConnectionToClient(this);
+}
+
+void WebSocket::AddChannel(const GURL& socket_url,
+                           const std::vector<std::string>& requested_protocols,
+                           const GURL& site_for_cookies,
+                           const std::string& user_agent_override) {
+  DVLOG(3) << "WebSocket::AddChannel @" << reinterpret_cast<void*>(this)
+           << " socket_url=\"" << socket_url << "\" requested_protocols=\""
+           << base::JoinString(requested_protocols, ", ") << "\" origin=\""
+           << origin_ << "\" site_for_cookies=\"" << site_for_cookies
+           << "\" user_agent_override=\"" << user_agent_override << "\"";
+
+  DCHECK(!channel_);
+
+  std::unique_ptr<net::WebSocketEventInterface> event_interface(
+      new WebSocketEventHandler(this));
+  channel_.reset(new net::WebSocketChannel(std::move(event_interface),
+                                           delegate_->GetURLRequestContext()));
+
+  int64_t quota = pending_flow_control_quota_;
+  pending_flow_control_quota_ = 0;
+
+  std::string additional_headers;
+  if (!user_agent_override.empty()) {
+    if (!net::HttpUtil::IsValidHeaderValue(user_agent_override)) {
+      delegate_->ReportBadMessage(
+          Delegate::BadMessageReason::kInvalidHeaderValue, this);
+      return;
+    }
+    additional_headers =
+        base::StringPrintf("%s:%s", net::HttpRequestHeaders::kUserAgent,
+                           user_agent_override.c_str());
+  }
+  channel_->SendAddChannelRequest(socket_url, requested_protocols, origin_,
+                                  site_for_cookies, additional_headers);
+  if (quota > 0)
+    SendFlowControl(quota);
+}
+
+}  // namespace network
diff --git a/services/network/websocket.h b/services/network/websocket.h
new file mode 100644
index 0000000..141a881f
--- /dev/null
+++ b/services/network/websocket.h
@@ -0,0 +1,137 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_NETWORK_WEBSOCKET_H_
+#define SERVICES_NETWORK_WEBSOCKET_H_
+
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/component_export.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "net/websockets/websocket_event_interface.h"
+#include "services/network/public/mojom/websocket.mojom.h"
+#include "services/network/websocket_throttler.h"
+#include "url/origin.h"
+
+class GURL;
+
+namespace net {
+class URLRequestContext;
+class WebSocketChannel;
+class SSLInfo;
+}  // namespace net
+
+namespace network {
+
+// Host of net::WebSocketChannel.
+class COMPONENT_EXPORT(NETWORK_SERVICE) WebSocket
+    : public network::mojom::WebSocket {
+ public:
+  class Delegate {
+   public:
+    enum class BadMessageReason {
+      kInvalidHeaderValue,
+      kUnexpectedAddChannelRequest,
+      kUnexpectedSendFrame,
+    };
+    virtual ~Delegate() {}
+
+    virtual net::URLRequestContext* GetURLRequestContext() = 0;
+    // This function may delete |impl|.
+    virtual void OnLostConnectionToClient(WebSocket* impl) = 0;
+    virtual void OnSSLCertificateError(
+        std::unique_ptr<net::WebSocketEventInterface::SSLErrorCallbacks>
+            callbacks,
+        const GURL& url,
+        int child_id,
+        int frame_id,
+        const net::SSLInfo& ssl_info,
+        bool fatal) = 0;
+    // This function may delete |impl|.
+    virtual void ReportBadMessage(BadMessageReason reason, WebSocket* impl) = 0;
+    virtual bool CanReadRawCookies() = 0;
+    virtual void OnCreateURLRequest(int child_id,
+                                    int frame_id,
+                                    net::URLRequest* request) = 0;
+  };
+
+  WebSocket(std::unique_ptr<Delegate> delegate,
+            mojom::WebSocketRequest request,
+            WebSocketThrottler::PendingConnection pending_connection_tracker,
+            int child_id,
+            int frame_id,
+            url::Origin origin,
+            base::TimeDelta delay);
+  ~WebSocket() override;
+
+  // The renderer process is going away.
+  // This function is virtual for testing.
+  virtual void GoAway();
+
+  // mojom::WebSocket methods:
+  void AddChannelRequest(const GURL& url,
+                         const std::vector<std::string>& requested_protocols,
+                         const GURL& site_for_cookies,
+                         const std::string& user_agent_override,
+                         mojom::WebSocketClientPtr client) override;
+  void SendFrame(bool fin,
+                 mojom::WebSocketMessageType type,
+                 const std::vector<uint8_t>& data) override;
+  void SendFlowControl(int64_t quota) override;
+  void StartClosingHandshake(uint16_t code, const std::string& reason) override;
+
+  bool handshake_succeeded() const { return handshake_succeeded_; }
+
+ protected:
+  class WebSocketEventHandler;
+
+  void OnConnectionError();
+  void AddChannel(const GURL& socket_url,
+                  const std::vector<std::string>& requested_protocols,
+                  const GURL& site_for_cookies,
+                  const std::string& user_agent_override);
+
+  std::unique_ptr<Delegate> delegate_;
+  mojo::Binding<mojom::WebSocket> binding_;
+
+  mojom::WebSocketClientPtr client_;
+
+  WebSocketThrottler::PendingConnection pending_connection_tracker_;
+
+  // The channel we use to send events to the network.
+  std::unique_ptr<net::WebSocketChannel> channel_;
+
+  // Delay used for per-renderer WebSocket throttling.
+  base::TimeDelta delay_;
+
+  // SendFlowControl() is delayed when OnFlowControl() is called before
+  // AddChannel() is called.
+  // Zero indicates there is no pending SendFlowControl().
+  int64_t pending_flow_control_quota_;
+
+  int child_id_;
+  int frame_id_;
+
+  // The web origin to use for the WebSocket.
+  const url::Origin origin_;
+
+  // handshake_succeeded_ is set and used by WebSocketManager to manage
+  // counters for per-renderer WebSocket throttling.
+  bool handshake_succeeded_;
+
+  base::WeakPtrFactory<WebSocket> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebSocket);
+};
+
+}  // namespace network
+
+#endif  // SERVICES_NETWORK_WEBSOCKET_H_
diff --git a/services/network/websocket_factory.cc b/services/network/websocket_factory.cc
new file mode 100644
index 0000000..cc7c51a
--- /dev/null
+++ b/services/network/websocket_factory.cc
@@ -0,0 +1,121 @@
+// Copyright 2018 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 "services/network/websocket_factory.h"
+
+#include "base/memory/weak_ptr.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "services/network/network_context.h"
+#include "services/network/network_service.h"
+#include "services/network/public/mojom/network_service.mojom.h"
+#include "services/network/websocket.h"
+#include "url/origin.h"
+
+namespace network {
+
+class WebSocketFactory::Delegate final
+    : public WebSocket::Delegate,
+      public base::SupportsWeakPtr<Delegate> {
+ public:
+  Delegate(WebSocketFactory* factory, int32_t process_id)
+      : factory_(factory), process_id_(process_id) {}
+  ~Delegate() override {}
+
+  net::URLRequestContext* GetURLRequestContext() override {
+    return factory_->context_->GetURLRequestContext();
+  }
+
+  void OnLostConnectionToClient(WebSocket* impl) override {
+    factory_->OnLostConnectionToClient(impl);
+  }
+
+  void OnSSLCertificateError(
+      std::unique_ptr<net::WebSocketEventInterface::SSLErrorCallbacks>
+          callbacks,
+      const GURL& url,
+      int process_id,
+      int render_frame_id,
+      const net::SSLInfo& ssl_info,
+      bool fatal) override {
+    DCHECK(!callbacks_);
+    callbacks_ = std::move(callbacks);
+
+    NetworkService* network_service = factory_->context_->network_service();
+    // See content::ResourceType defined in
+    // content/public/common/resource_type.h. This is
+    // RESOURCE_TYPE_SUB_RESOURCE.
+    constexpr int resource_type = 6;
+    // We need to provide a request ID which we don't have. Provide an
+    // invalid ID.
+    constexpr uint32_t request_id = static_cast<uint32_t>(-1);
+
+    network_service->client()->OnSSLCertificateError(
+        process_id, render_frame_id, request_id, resource_type, url, ssl_info,
+        fatal,
+        base::BindRepeating(&Delegate::OnSSLCertificateErrorResponse,
+                            AsWeakPtr(), ssl_info));
+  }
+
+  void ReportBadMessage(BadMessageReason reason, WebSocket* impl) override {
+    OnLostConnectionToClient(impl);
+  }
+
+  bool CanReadRawCookies() override {
+    return factory_->context_->network_service()->HasRawHeadersAccess(
+        process_id_);
+  }
+
+  void OnCreateURLRequest(int child_id,
+                          int frame_id,
+                          net::URLRequest* request) override {}
+
+ private:
+  void OnSSLCertificateErrorResponse(const net::SSLInfo& ssl_info,
+                                     int net_error) {
+    if (net_error == net::OK) {
+      callbacks_->ContinueSSLRequest();
+      return;
+    }
+
+    callbacks_->CancelSSLRequest(net_error, &ssl_info);
+  }
+
+  // |factory_| outlives this object.
+  WebSocketFactory* const factory_;
+  const int process_id_;
+  std::unique_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks_;
+
+  DISALLOW_COPY_AND_ASSIGN(Delegate);
+};
+
+WebSocketFactory::WebSocketFactory(NetworkContext* context)
+    : context_(context) {}
+
+WebSocketFactory::~WebSocketFactory() {}
+
+void WebSocketFactory::CreateWebSocket(mojom::WebSocketRequest request,
+                                       int32_t process_id,
+                                       int32_t render_frame_id,
+                                       const url::Origin& origin) {
+  if (throttler_.HasTooManyPendingConnections(process_id)) {
+    // Too many websockets!
+    request.ResetWithReason(
+        mojom::WebSocket::kInsufficientResources,
+        "Error in connection establishment: net::ERR_INSUFFICIENT_RESOURCES");
+    return;
+  }
+  connections_.insert(std::make_unique<WebSocket>(
+      std::make_unique<Delegate>(this, process_id), std::move(request),
+      throttler_.IssuePendingConnectionTracker(process_id), process_id,
+      render_frame_id, origin, throttler_.CalculateDelay(process_id)));
+}
+
+void WebSocketFactory::OnLostConnectionToClient(WebSocket* impl) {
+  auto it = connections_.find(impl);
+  DCHECK(it != connections_.end());
+  impl->GoAway();
+  connections_.erase(it);
+}
+
+}  // namespace network
diff --git a/services/network/websocket_factory.h b/services/network/websocket_factory.h
new file mode 100644
index 0000000..d40b8ab
--- /dev/null
+++ b/services/network/websocket_factory.h
@@ -0,0 +1,54 @@
+// Copyright 2018 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 SERVICES_NETWORK_WEBSOCKET_FACTORY_H_
+#define SERVICES_NETWORK_WEBSOCKET_FACTORY_H_
+
+#include <vector>
+
+#include "base/containers/unique_ptr_adapters.h"
+#include "base/memory/weak_ptr.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "services/network/public/mojom/websocket.mojom.h"
+#include "services/network/websocket.h"
+#include "services/network/websocket_throttler.h"
+
+namespace url {
+class Origin;
+}  // namespace url
+
+namespace network {
+
+class NetworkContext;
+
+// TODO(yhirano): Implement throttling.
+class WebSocketFactory final : public base::SupportsWeakPtr<WebSocketFactory> {
+ public:
+  explicit WebSocketFactory(NetworkContext* context);
+  ~WebSocketFactory();
+
+  void CreateWebSocket(mojom::WebSocketRequest request,
+                       int32_t process_id,
+                       int32_t render_frame_id,
+                       const url::Origin& origin);
+
+ private:
+  class Delegate;
+
+  void OnLostConnectionToClient(WebSocket* impl);
+
+  // The connections held by this factory.
+  std::set<std::unique_ptr<WebSocket>, base::UniquePtrComparator> connections_;
+
+  WebSocketThrottler throttler_;
+
+  // |context_| outlives this object.
+  NetworkContext* const context_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebSocketFactory);
+};
+
+}  // namespace network
+
+#endif  // SERVICES_NETWORK_WEBSOCKET_FACTORY_H_
diff --git a/services/network/websocket_throttler.cc b/services/network/websocket_throttler.cc
new file mode 100644
index 0000000..8cb8ee2
--- /dev/null
+++ b/services/network/websocket_throttler.cc
@@ -0,0 +1,129 @@
+// Copyright 2018 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 "services/network/websocket_throttler.h"
+
+#include <algorithm>
+
+#include "base/rand_util.h"
+
+namespace network {
+
+constexpr int WebSocketPerProcessThrottler::kMaxPendingWebSocketConnections;
+
+WebSocketPerProcessThrottler::PendingConnection::PendingConnection(
+    base::WeakPtr<WebSocketPerProcessThrottler> throttler)
+    : throttler_(std::move(throttler)) {
+  DCHECK(throttler_);
+  ++throttler_->num_pending_connections_;
+}
+WebSocketPerProcessThrottler::PendingConnection::PendingConnection(
+    PendingConnection&& other)
+    : throttler_(std::move(other.throttler_)) {
+  other.throttler_ = nullptr;
+}
+WebSocketPerProcessThrottler::PendingConnection::~PendingConnection() {
+  if (!throttler_)
+    return;
+
+  --throttler_->num_pending_connections_;
+  ++throttler_->num_current_failed_connections_;
+}
+
+void WebSocketPerProcessThrottler::PendingConnection::OnCompleteHandshake() {
+  DCHECK(throttler_);
+
+  --throttler_->num_pending_connections_;
+  ++throttler_->num_current_succeeded_connections_;
+  throttler_ = nullptr;
+}
+
+WebSocketPerProcessThrottler::WebSocketPerProcessThrottler() {}
+WebSocketPerProcessThrottler::~WebSocketPerProcessThrottler() {}
+
+base::TimeDelta WebSocketPerProcessThrottler::CalculateDelay() const {
+  int64_t f =
+      num_previous_failed_connections_ + num_current_failed_connections_;
+  int64_t s =
+      num_previous_succeeded_connections_ + num_current_succeeded_connections_;
+  int p = num_pending_connections_;
+  return base::TimeDelta::FromMilliseconds(
+      base::RandInt(1000, 5000) *
+      (1 << std::min(p + f / (s + 1), INT64_C(16))) / 65536);
+  return base::TimeDelta();
+}
+
+WebSocketPerProcessThrottler::PendingConnection
+WebSocketPerProcessThrottler::IssuePendingConnectionTracker() {
+  return PendingConnection(AsWeakPtr());
+}
+
+bool WebSocketPerProcessThrottler::IsClean() const {
+  return num_pending_connections_ == 0 &&
+         num_current_succeeded_connections_ == 0 &&
+         num_previous_succeeded_connections_ == 0 &&
+         num_current_failed_connections_ == 0 &&
+         num_previous_succeeded_connections_ == 0;
+}
+
+void WebSocketPerProcessThrottler::Roll() {
+  num_previous_succeeded_connections_ = num_current_succeeded_connections_;
+  num_previous_failed_connections_ = num_current_failed_connections_;
+
+  num_current_succeeded_connections_ = 0;
+  num_current_failed_connections_ = 0;
+}
+
+WebSocketThrottler::WebSocketThrottler() {}
+WebSocketThrottler::~WebSocketThrottler() {}
+
+bool WebSocketThrottler::HasTooManyPendingConnections(int process_id) const {
+  auto it = per_process_throttlers_.find(process_id);
+  if (it == per_process_throttlers_.end())
+    return false;
+
+  return it->second->HasTooManyPendingConnections();
+}
+
+base::TimeDelta WebSocketThrottler::CalculateDelay(int process_id) const {
+  auto it = per_process_throttlers_.find(process_id);
+  if (it == per_process_throttlers_.end())
+    return base::TimeDelta();
+
+  return it->second->CalculateDelay();
+}
+
+WebSocketThrottler::PendingConnection
+WebSocketThrottler::IssuePendingConnectionTracker(int process_id) {
+  auto it = per_process_throttlers_.find(process_id);
+  if (it == per_process_throttlers_.end()) {
+    it = per_process_throttlers_
+             .insert(std::make_pair(
+                 process_id, std::make_unique<WebSocketPerProcessThrottler>()))
+             .first;
+  }
+
+  if (!throttling_period_timer_.IsRunning()) {
+    throttling_period_timer_.Start(FROM_HERE, base::TimeDelta::FromMinutes(2),
+                                   this, &WebSocketThrottler::OnTimer);
+  }
+  return it->second->IssuePendingConnectionTracker();
+}
+
+void WebSocketThrottler::OnTimer() {
+  auto it = per_process_throttlers_.begin();
+  while (it != per_process_throttlers_.end()) {
+    it->second->Roll();
+    if (it->second->IsClean()) {
+      // We don't need the entry. Erase it.
+      it = per_process_throttlers_.erase(it);
+    } else {
+      ++it;
+    }
+  }
+  if (per_process_throttlers_.empty())
+    throttling_period_timer_.Stop();
+}
+
+}  // namespace network
diff --git a/services/network/websocket_throttler.h b/services/network/websocket_throttler.h
new file mode 100644
index 0000000..282649c2f
--- /dev/null
+++ b/services/network/websocket_throttler.h
@@ -0,0 +1,138 @@
+// Copyright 2018 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 SERVICES_NETWORK_WEBSOCKET_THROTTLER_H_
+#define SERVICES_NETWORK_WEBSOCKET_THROTTLER_H_
+
+#include <stdint.h>
+#include <map>
+#include <memory>
+
+#include "base/component_export.h"
+#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
+
+namespace network {
+
+// WebSocketPerProcessThrottler provies a throttling functionality per
+// renderer process. See https://goo.gl/tldFNn.
+class COMPONENT_EXPORT(NETWORK_SERVICE) WebSocketPerProcessThrottler final
+    : public base::SupportsWeakPtr<WebSocketPerProcessThrottler> {
+ public:
+  // A PendingConnection represents a connection that has not finished a
+  // handshake.
+  //
+  // Destroying a PendingConnection whose OnCompleteHandshake has not been
+  // called represents a handshake failure (including going away during
+  // handshake).
+  class COMPONENT_EXPORT(NETWORK_SERVICE) PendingConnection final {
+   public:
+    // |throttler| cannot be null.
+    explicit PendingConnection(
+        base::WeakPtr<WebSocketPerProcessThrottler> throttler);
+    PendingConnection(PendingConnection&& other);
+    ~PendingConnection();
+
+    // Called when the hansdhake finishes sucessfully.
+    void OnCompleteHandshake();
+
+   private:
+    base::WeakPtr<WebSocketPerProcessThrottler> throttler_;
+
+    DISALLOW_COPY_AND_ASSIGN(PendingConnection);
+  };
+
+  WebSocketPerProcessThrottler();
+  ~WebSocketPerProcessThrottler();
+
+  // Returns if there are too many pending connections.
+  bool HasTooManyPendingConnections() const {
+    return num_pending_connections_ >= kMaxPendingWebSocketConnections;
+  }
+
+  // Returns the delay which should be used to throttle opening websocket
+  // connections.
+  base::TimeDelta CalculateDelay() const;
+
+  // Issues an object which represents a pending connection.
+  PendingConnection IssuePendingConnectionTracker();
+
+  // Returns true if this throttler is clean, i.e., we can restore the internal
+  // state by simply creating a new object.
+  bool IsClean() const;
+
+  // Copies the succeeded / failed counters for the current period to the
+  // ones for the previous period, and zeroes them.
+  void Roll();
+
+  int64_t num_pending_connections() const { return num_pending_connections_; }
+  int64_t num_current_succeeded_connections() const {
+    return num_current_succeeded_connections_;
+  }
+  int64_t num_previous_succeeded_connections() const {
+    return num_previous_succeeded_connections_;
+  }
+  int64_t num_current_failed_connections() const {
+    return num_current_failed_connections_;
+  }
+  int64_t num_previous_failed_connections() const {
+    return num_previous_failed_connections_;
+  }
+
+ private:
+  // The current number of pending connections.
+  int num_pending_connections_ = 0;
+
+  // The number of handshakes that failed in the clurrent and previous time
+  // period.
+  int64_t num_current_succeeded_connections_ = 0;
+  int64_t num_previous_succeeded_connections_ = 0;
+
+  // The number of handshakes that succeeded in the current and previous time
+  // period.
+  int64_t num_current_failed_connections_ = 0;
+  int64_t num_previous_failed_connections_ = 0;
+
+  static constexpr int kMaxPendingWebSocketConnections = 255;
+
+  DISALLOW_COPY_AND_ASSIGN(WebSocketPerProcessThrottler);
+};
+
+// This class is for throttling WebSocket connections. WebSocketThrottler is
+// a set of per-renderer throttlers.
+// This class is only used in the network service. content::WebSocketManager
+// uses WebSocketPerProcessThrottler directly.
+class COMPONENT_EXPORT(NETWORK_SERVICE) WebSocketThrottler final {
+ public:
+  using PendingConnection = WebSocketPerProcessThrottler::PendingConnection;
+
+  WebSocketThrottler();
+  ~WebSocketThrottler();
+
+  // Returns true if there are too many pending connections for |process_id|.
+  bool HasTooManyPendingConnections(int process_id) const;
+
+  // Calculates connection delay for |process_id|.
+  base::TimeDelta CalculateDelay(int process_id) const;
+
+  // Returns a pending connection for |process_id|. This function can be called
+  // only when |HasTooManyPendingConnections(process_id)| is false.
+  PendingConnection IssuePendingConnectionTracker(int process_id);
+
+  size_t GetSizeForTesting() const { return per_process_throttlers_.size(); }
+
+ private:
+  void OnTimer();
+
+  std::map<int, std::unique_ptr<WebSocketPerProcessThrottler>>
+      per_process_throttlers_;
+  base::RepeatingTimer throttling_period_timer_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebSocketThrottler);
+};
+
+}  // namespace network
+
+#endif  // SERVICES_NETWORK_WEBSOCKET_THROTTLER_H_
diff --git a/services/network/websocket_throttler_unittest.cc b/services/network/websocket_throttler_unittest.cc
new file mode 100644
index 0000000..c0ffce1
--- /dev/null
+++ b/services/network/websocket_throttler_unittest.cc
@@ -0,0 +1,344 @@
+// Copyright 2018 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 "services/network/websocket_throttler.h"
+
+#include <vector>
+
+#include "base/message_loop/message_loop.h"
+#include "base/optional.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace network {
+
+namespace {
+
+class WebSocketThrottlerTest : public ::testing::Test {
+ private:
+  base::MessageLoop message_loop_;
+};
+
+TEST(WebSocketPerProcessThrottlerTest, InitialState) {
+  WebSocketPerProcessThrottler throttler;
+
+  EXPECT_FALSE(throttler.HasTooManyPendingConnections());
+  EXPECT_EQ(0, throttler.num_pending_connections());
+  EXPECT_EQ(0, throttler.num_current_succeeded_connections());
+  EXPECT_EQ(0, throttler.num_previous_succeeded_connections());
+  EXPECT_EQ(0, throttler.num_current_failed_connections());
+  EXPECT_EQ(0, throttler.num_previous_failed_connections());
+  EXPECT_EQ(base::TimeDelta(), throttler.CalculateDelay());
+}
+
+TEST(WebSocketPerProcessThrottlerTest, Pending) {
+  WebSocketPerProcessThrottler throttler;
+
+  auto tracker = throttler.IssuePendingConnectionTracker();
+
+  EXPECT_FALSE(throttler.HasTooManyPendingConnections());
+  EXPECT_EQ(1, throttler.num_pending_connections());
+  EXPECT_EQ(0, throttler.num_current_succeeded_connections());
+  EXPECT_EQ(0, throttler.num_previous_succeeded_connections());
+  EXPECT_EQ(0, throttler.num_current_failed_connections());
+  EXPECT_EQ(0, throttler.num_previous_failed_connections());
+  EXPECT_EQ(base::TimeDelta(), throttler.CalculateDelay());
+}
+
+TEST(WebSocketPerProcessThrottlerTest, Complete) {
+  WebSocketPerProcessThrottler throttler;
+
+  {
+    auto tracker = throttler.IssuePendingConnectionTracker();
+
+    EXPECT_FALSE(throttler.HasTooManyPendingConnections());
+    EXPECT_EQ(1, throttler.num_pending_connections());
+    EXPECT_EQ(0, throttler.num_current_succeeded_connections());
+    EXPECT_EQ(0, throttler.num_previous_succeeded_connections());
+    EXPECT_EQ(0, throttler.num_current_failed_connections());
+    EXPECT_EQ(0, throttler.num_previous_failed_connections());
+    EXPECT_EQ(base::TimeDelta(), throttler.CalculateDelay());
+
+    tracker.OnCompleteHandshake();
+
+    EXPECT_FALSE(throttler.HasTooManyPendingConnections());
+    EXPECT_EQ(0, throttler.num_pending_connections());
+    EXPECT_EQ(1, throttler.num_current_succeeded_connections());
+    EXPECT_EQ(0, throttler.num_previous_succeeded_connections());
+    EXPECT_EQ(0, throttler.num_current_failed_connections());
+    EXPECT_EQ(0, throttler.num_previous_failed_connections());
+    EXPECT_EQ(base::TimeDelta(), throttler.CalculateDelay());
+
+    // Destruct |tracker|.
+  }
+
+  EXPECT_FALSE(throttler.HasTooManyPendingConnections());
+  EXPECT_EQ(0, throttler.num_pending_connections());
+  EXPECT_EQ(1, throttler.num_current_succeeded_connections());
+  EXPECT_EQ(0, throttler.num_previous_succeeded_connections());
+  EXPECT_EQ(0, throttler.num_current_failed_connections());
+  EXPECT_EQ(0, throttler.num_previous_failed_connections());
+  EXPECT_EQ(base::TimeDelta(), throttler.CalculateDelay());
+}
+
+TEST(WebSocketPerProcessThrottlerTest, Failed) {
+  WebSocketPerProcessThrottler throttler;
+
+  {
+    auto tracker = throttler.IssuePendingConnectionTracker();
+
+    EXPECT_FALSE(throttler.HasTooManyPendingConnections());
+    EXPECT_EQ(1, throttler.num_pending_connections());
+    EXPECT_EQ(0, throttler.num_current_succeeded_connections());
+    EXPECT_EQ(0, throttler.num_previous_succeeded_connections());
+    EXPECT_EQ(0, throttler.num_current_failed_connections());
+    EXPECT_EQ(0, throttler.num_previous_failed_connections());
+    EXPECT_EQ(base::TimeDelta(), throttler.CalculateDelay());
+
+    // Destruct |tracker|.
+  }
+
+  EXPECT_FALSE(throttler.HasTooManyPendingConnections());
+  EXPECT_EQ(0, throttler.num_pending_connections());
+  EXPECT_EQ(0, throttler.num_current_succeeded_connections());
+  EXPECT_EQ(0, throttler.num_previous_succeeded_connections());
+  EXPECT_EQ(1, throttler.num_current_failed_connections());
+  EXPECT_EQ(0, throttler.num_previous_failed_connections());
+  EXPECT_EQ(base::TimeDelta(), throttler.CalculateDelay());
+}
+
+TEST(WebSocketPerProcessThrottlerTest, TooManyPendingConnections) {
+  constexpr int limit = 255;
+  WebSocketPerProcessThrottler throttler;
+
+  std::vector<WebSocketPerProcessThrottler::PendingConnection> trackers;
+  for (int i = 0; i < limit - 1; ++i) {
+    ASSERT_FALSE(throttler.HasTooManyPendingConnections());
+    trackers.push_back(throttler.IssuePendingConnectionTracker());
+  }
+
+  ASSERT_FALSE(throttler.HasTooManyPendingConnections());
+  trackers.push_back(throttler.IssuePendingConnectionTracker());
+  EXPECT_TRUE(throttler.HasTooManyPendingConnections());
+}
+
+TEST(WebSocketPerProcessThrottlerTest, CompletedConnectionsDontCount) {
+  constexpr int limit = 255;
+  WebSocketPerProcessThrottler throttler;
+
+  for (int i = 0; i < limit * 3; ++i) {
+    ASSERT_FALSE(throttler.HasTooManyPendingConnections());
+    auto tracker = throttler.IssuePendingConnectionTracker();
+    tracker.OnCompleteHandshake();
+  }
+  EXPECT_FALSE(throttler.HasTooManyPendingConnections());
+}
+
+TEST(WebSocketPerProcessThrottlerTest, FailedConnectionsDontCount) {
+  constexpr int limit = 255;
+  WebSocketPerProcessThrottler throttler;
+
+  for (int i = 0; i < limit * 3; ++i) {
+    ASSERT_FALSE(throttler.HasTooManyPendingConnections());
+    auto tracker = throttler.IssuePendingConnectionTracker();
+  }
+  EXPECT_FALSE(throttler.HasTooManyPendingConnections());
+}
+
+TEST(WebSocketPerProcessThrottlerTest, Roll) {
+  WebSocketPerProcessThrottler throttler;
+  for (int i = 0; i < 2; ++i)
+    throttler.IssuePendingConnectionTracker().OnCompleteHandshake();
+  for (int i = 0; i < 3; ++i)
+    throttler.IssuePendingConnectionTracker();
+
+  EXPECT_EQ(0, throttler.num_pending_connections());
+  EXPECT_EQ(2, throttler.num_current_succeeded_connections());
+  EXPECT_EQ(0, throttler.num_previous_succeeded_connections());
+  EXPECT_EQ(3, throttler.num_current_failed_connections());
+  EXPECT_EQ(0, throttler.num_previous_failed_connections());
+
+  throttler.Roll();
+  EXPECT_EQ(0, throttler.num_pending_connections());
+  EXPECT_EQ(0, throttler.num_current_succeeded_connections());
+  EXPECT_EQ(2, throttler.num_previous_succeeded_connections());
+  EXPECT_EQ(0, throttler.num_current_failed_connections());
+  EXPECT_EQ(3, throttler.num_previous_failed_connections());
+
+  throttler.Roll();
+  EXPECT_EQ(0, throttler.num_pending_connections());
+  EXPECT_EQ(0, throttler.num_current_succeeded_connections());
+  EXPECT_EQ(0, throttler.num_previous_succeeded_connections());
+  EXPECT_EQ(0, throttler.num_current_failed_connections());
+  EXPECT_EQ(0, throttler.num_previous_failed_connections());
+}
+
+TEST(WebSocketPerProcessThrottlerTest, CalculateDelay_4Pending) {
+  WebSocketPerProcessThrottler throttler;
+  std::vector<WebSocketPerProcessThrottler::PendingConnection> trackers;
+  for (int i = 0; i < 4; ++i)
+    trackers.push_back(throttler.IssuePendingConnectionTracker());
+
+  EXPECT_EQ(4, throttler.num_pending_connections());
+  EXPECT_EQ(0, throttler.num_current_succeeded_connections());
+  EXPECT_EQ(0, throttler.num_previous_succeeded_connections());
+  EXPECT_EQ(0, throttler.num_current_failed_connections());
+  EXPECT_EQ(0, throttler.num_previous_failed_connections());
+  EXPECT_EQ(base::TimeDelta(), throttler.CalculateDelay());
+}
+
+TEST(WebSocketPerProcessThrottlerTest, CalculateDelay_8Pending) {
+  WebSocketPerProcessThrottler throttler;
+  std::vector<WebSocketPerProcessThrottler::PendingConnection> trackers;
+  for (int i = 0; i < 8; ++i)
+    trackers.push_back(throttler.IssuePendingConnectionTracker());
+
+  EXPECT_EQ(8, throttler.num_pending_connections());
+  EXPECT_EQ(0, throttler.num_current_succeeded_connections());
+  EXPECT_EQ(0, throttler.num_previous_succeeded_connections());
+  EXPECT_EQ(0, throttler.num_current_failed_connections());
+  EXPECT_EQ(0, throttler.num_previous_failed_connections());
+  EXPECT_LT(base::TimeDelta(), throttler.CalculateDelay());
+}
+
+TEST(WebSocketPerProcessThrottlerTest, CalculateDelay_17Pending) {
+  WebSocketPerProcessThrottler throttler;
+  std::vector<WebSocketPerProcessThrottler::PendingConnection> trackers;
+  for (int i = 0; i < 17; ++i)
+    trackers.push_back(throttler.IssuePendingConnectionTracker());
+
+  EXPECT_EQ(17, throttler.num_pending_connections());
+  EXPECT_EQ(0, throttler.num_current_succeeded_connections());
+  EXPECT_EQ(0, throttler.num_previous_succeeded_connections());
+  EXPECT_EQ(0, throttler.num_current_failed_connections());
+  EXPECT_EQ(0, throttler.num_previous_failed_connections());
+  EXPECT_LE(base::TimeDelta::FromMilliseconds(1000),
+            throttler.CalculateDelay());
+  EXPECT_LE(throttler.CalculateDelay(),
+            base::TimeDelta::FromMilliseconds(5000));
+}
+
+TEST(WebSocketPerProcessThrottlerTest, CalculateDelay_3Failure) {
+  WebSocketPerProcessThrottler throttler;
+  for (int i = 0; i < 3; ++i)
+    throttler.IssuePendingConnectionTracker();
+
+  EXPECT_EQ(0, throttler.num_pending_connections());
+  EXPECT_EQ(0, throttler.num_current_succeeded_connections());
+  EXPECT_EQ(0, throttler.num_previous_succeeded_connections());
+  EXPECT_EQ(3, throttler.num_current_failed_connections());
+  EXPECT_EQ(0, throttler.num_previous_failed_connections());
+  EXPECT_EQ(base::TimeDelta(), throttler.CalculateDelay());
+}
+
+TEST(WebSocketPerProcessThrottlerTest, CalculateDelay_7Failure) {
+  WebSocketPerProcessThrottler throttler;
+  for (int i = 0; i < 7; ++i)
+    throttler.IssuePendingConnectionTracker();
+
+  EXPECT_EQ(0, throttler.num_pending_connections());
+  EXPECT_EQ(0, throttler.num_current_succeeded_connections());
+  EXPECT_EQ(0, throttler.num_previous_succeeded_connections());
+  EXPECT_EQ(7, throttler.num_current_failed_connections());
+  EXPECT_EQ(0, throttler.num_previous_failed_connections());
+  EXPECT_LT(base::TimeDelta(), throttler.CalculateDelay());
+}
+
+TEST(WebSocketPerProcessThrottlerTest, CalculateDelay_16Failure) {
+  WebSocketPerProcessThrottler throttler;
+  for (int i = 0; i < 16; ++i)
+    throttler.IssuePendingConnectionTracker();
+
+  EXPECT_EQ(0, throttler.num_pending_connections());
+  EXPECT_EQ(0, throttler.num_current_succeeded_connections());
+  EXPECT_EQ(0, throttler.num_previous_succeeded_connections());
+  EXPECT_EQ(16, throttler.num_current_failed_connections());
+  EXPECT_EQ(0, throttler.num_previous_failed_connections());
+  EXPECT_LE(base::TimeDelta::FromMilliseconds(1000),
+            throttler.CalculateDelay());
+  EXPECT_LE(throttler.CalculateDelay(),
+            base::TimeDelta::FromMilliseconds(5000));
+}
+
+TEST(WebSocketPerProcessThrottlerTest, MoveTracker) {
+  WebSocketPerProcessThrottler throttler;
+
+  base::Optional<WebSocketThrottler::PendingConnection> tracker_holder;
+  {
+    WebSocketThrottler::PendingConnection tracker =
+        throttler.IssuePendingConnectionTracker();
+
+    EXPECT_EQ(1, throttler.num_pending_connections());
+    EXPECT_EQ(0, throttler.num_current_succeeded_connections());
+    EXPECT_EQ(0, throttler.num_previous_succeeded_connections());
+    EXPECT_EQ(0, throttler.num_current_failed_connections());
+    EXPECT_EQ(0, throttler.num_previous_failed_connections());
+
+    WebSocketThrottler::PendingConnection tracker2 = std::move(tracker);
+    WebSocketThrottler::PendingConnection tracker3 = std::move(tracker2);
+
+    EXPECT_EQ(1, throttler.num_pending_connections());
+    EXPECT_EQ(0, throttler.num_current_succeeded_connections());
+    EXPECT_EQ(0, throttler.num_previous_succeeded_connections());
+    EXPECT_EQ(0, throttler.num_current_failed_connections());
+    EXPECT_EQ(0, throttler.num_previous_failed_connections());
+
+    tracker_holder.emplace(std::move(tracker3));
+
+    EXPECT_EQ(1, throttler.num_pending_connections());
+    EXPECT_EQ(0, throttler.num_current_succeeded_connections());
+    EXPECT_EQ(0, throttler.num_previous_succeeded_connections());
+    EXPECT_EQ(0, throttler.num_current_failed_connections());
+    EXPECT_EQ(0, throttler.num_previous_failed_connections());
+  }
+
+  EXPECT_EQ(1, throttler.num_pending_connections());
+  EXPECT_EQ(0, throttler.num_current_succeeded_connections());
+  EXPECT_EQ(0, throttler.num_previous_succeeded_connections());
+  EXPECT_EQ(0, throttler.num_current_failed_connections());
+  EXPECT_EQ(0, throttler.num_previous_failed_connections());
+
+  tracker_holder = base::nullopt;
+
+  EXPECT_EQ(0, throttler.num_pending_connections());
+  EXPECT_EQ(0, throttler.num_current_succeeded_connections());
+  EXPECT_EQ(0, throttler.num_previous_succeeded_connections());
+  EXPECT_EQ(1, throttler.num_current_failed_connections());
+  EXPECT_EQ(0, throttler.num_previous_failed_connections());
+}
+
+TEST_F(WebSocketThrottlerTest, InitialState) {
+  WebSocketThrottler throttler;
+  EXPECT_EQ(0u, throttler.GetSizeForTesting());
+}
+
+TEST_F(WebSocketThrottlerTest, TooManyPendingConnections) {
+  constexpr int process1 = 1;
+  constexpr int process2 = 2;
+  constexpr int limit = 255;
+  WebSocketThrottler throttler;
+
+  std::vector<WebSocketThrottler::PendingConnection> trackers;
+  for (int i = 0; i < limit - 1; ++i) {
+    ASSERT_FALSE(throttler.HasTooManyPendingConnections(process1));
+    ASSERT_FALSE(throttler.HasTooManyPendingConnections(process2));
+    trackers.push_back(throttler.IssuePendingConnectionTracker(process1));
+    trackers.push_back(throttler.IssuePendingConnectionTracker(process2));
+  }
+
+  EXPECT_EQ(2u, throttler.GetSizeForTesting());
+  ASSERT_FALSE(throttler.HasTooManyPendingConnections(process1));
+  ASSERT_FALSE(throttler.HasTooManyPendingConnections(process2));
+  trackers.push_back(throttler.IssuePendingConnectionTracker(process1));
+
+  ASSERT_TRUE(throttler.HasTooManyPendingConnections(process1));
+  ASSERT_FALSE(throttler.HasTooManyPendingConnections(process2));
+  trackers.push_back(throttler.IssuePendingConnectionTracker(process2));
+
+  ASSERT_TRUE(throttler.HasTooManyPendingConnections(process1));
+  ASSERT_TRUE(throttler.HasTooManyPendingConnections(process2));
+}
+
+}  // namespace
+
+}  // namespace network
diff --git a/services/resource_coordinator/coordination_unit/coordination_unit_manager.h b/services/resource_coordinator/coordination_unit/coordination_unit_manager.h
index c9a3b8a..d84e28c 100644
--- a/services/resource_coordinator/coordination_unit/coordination_unit_manager.h
+++ b/services/resource_coordinator/coordination_unit/coordination_unit_manager.h
@@ -30,7 +30,7 @@
 // The CoordinationUnitManager is a singleton that encapsulates all
 // aspects of Coordination Units within the resource_coordinator service.
 // All functionality for dealing with CoordinationUnits should be contained
-// within this class or classes that are owned by it
+// within this class or classes that are owned by it.
 class CoordinationUnitManager {
  public:
   CoordinationUnitManager();
diff --git a/services/resource_coordinator/coordination_unit/mock_coordination_unit_graphs.h b/services/resource_coordinator/coordination_unit/mock_coordination_unit_graphs.h
index 3de64a55..04861bc 100644
--- a/services/resource_coordinator/coordination_unit/mock_coordination_unit_graphs.h
+++ b/services/resource_coordinator/coordination_unit/mock_coordination_unit_graphs.h
@@ -14,7 +14,7 @@
 class ProcessCoordinationUnitImpl;
 
 // The following coordination unit graph topology is created to emulate a
-// scenario when a single page are executes in a single process:
+// scenario when a single page executes in a single process:
 //
 // P'  P
 //  \ /
@@ -54,7 +54,7 @@
 };
 
 // The following coordination unit graph topology is created to emulate a
-// scenario where a single page that has frames executing in different
+// scenario where a single page that has frames is executing in different
 // processes (e.g. out-of-process iFrames):
 //
 // P'  P
diff --git a/services/resource_coordinator/coordination_unit/page_coordination_unit_impl.cc b/services/resource_coordinator/coordination_unit/page_coordination_unit_impl.cc
index bb3036c..94a92383 100644
--- a/services/resource_coordinator/coordination_unit/page_coordination_unit_impl.cc
+++ b/services/resource_coordinator/coordination_unit/page_coordination_unit_impl.cc
@@ -25,8 +25,9 @@
 
 void PageCoordinationUnitImpl::AddFrame(const CoordinationUnitID& cu_id) {
   DCHECK(cu_id.type == CoordinationUnitType::kFrame);
-  FrameCoordinationUnitImpl* frame_cu = static_cast<FrameCoordinationUnitImpl*>(
-      CoordinationUnitBase::GetCoordinationUnitByID(cu_id));
+  FrameCoordinationUnitImpl* frame_cu =
+      FrameCoordinationUnitImpl::FromCoordinationUnitBase(
+          CoordinationUnitBase::GetCoordinationUnitByID(cu_id));
   if (!frame_cu)
     return;
   if (AddFrame(frame_cu))
diff --git a/services/resource_coordinator/coordination_unit/process_coordination_unit_impl.cc b/services/resource_coordinator/coordination_unit/process_coordination_unit_impl.cc
index 8691a4d..3844f2712 100644
--- a/services/resource_coordinator/coordination_unit/process_coordination_unit_impl.cc
+++ b/services/resource_coordinator/coordination_unit/process_coordination_unit_impl.cc
@@ -18,7 +18,7 @@
   std::vector<ProcessCoordinationUnitImpl*> process_cus;
   for (auto* process_cu : cus) {
     process_cus.push_back(
-        static_cast<ProcessCoordinationUnitImpl*>(process_cu));
+        ProcessCoordinationUnitImpl::FromCoordinationUnitBase(process_cu));
   }
   return process_cus;
 }
diff --git a/services/resource_coordinator/memory_instrumentation/coordinator_impl_unittest.cc b/services/resource_coordinator/memory_instrumentation/coordinator_impl_unittest.cc
index ef7eb6f..365417e 100644
--- a/services/resource_coordinator/memory_instrumentation/coordinator_impl_unittest.cc
+++ b/services/resource_coordinator/memory_instrumentation/coordinator_impl_unittest.cc
@@ -624,24 +624,9 @@
             renderer_dump = std::move(dump);
           }
         }
-        // For malloc we only count the root "malloc" not children "malloc/*".
-        EXPECT_EQ(1u, browser_dump->chrome_dump->malloc_total_kb);
-
-        // For blink_gc we only count the root "blink_gc" not children
-        // "blink_gc/*".
-        EXPECT_EQ(2u, browser_dump->chrome_dump->blink_gc_total_kb);
-
-        // For v8 we count the children ("v8/*") as the root total is not given.
-        EXPECT_EQ(3u, browser_dump->chrome_dump->v8_total_kb);
-
-        // partition_alloc has partition_alloc/allocated_objects/* which is a
-        // subset of partition_alloc/partitions/* so we only count the latter.
-        EXPECT_EQ(4u, browser_dump->chrome_dump->partition_alloc_total_kb);
 
         EXPECT_EQ(browser_dump->os_dump->resident_set_kb, 1u);
         EXPECT_EQ(renderer_dump->os_dump->resident_set_kb, 2u);
-        EXPECT_EQ(browser_dump->chrome_dump->malloc_total_kb, 1u);
-        EXPECT_EQ(renderer_dump->chrome_dump->malloc_total_kb, 2u);
         run_loop.Quit();
       }));
 
diff --git a/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.cc b/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.cc
index 3fdd926..9fc11d7 100644
--- a/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.cc
+++ b/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.cc
@@ -81,38 +81,6 @@
   return os_dump;
 }
 
-uint32_t GetDumpsSumKb(const std::string& pattern,
-                       const base::trace_event::ProcessMemoryDump& pmd) {
-  uint64_t sum = 0;
-  for (const auto& kv : pmd.allocator_dumps()) {
-    if (base::MatchPattern(kv.first /* name */, pattern))
-      sum += kv.second->GetSizeInternal();
-  }
-  return sum / 1024;
-}
-
-mojom::ChromeMemDumpPtr CreateDumpSummary(
-    const base::trace_event::ProcessMemoryDump& process_memory_dump) {
-  mojom::ChromeMemDumpPtr result = mojom::ChromeMemDump::New();
-  result->malloc_total_kb = GetDumpsSumKb("malloc", process_memory_dump);
-  result->v8_total_kb = GetDumpsSumKb("v8/*", process_memory_dump);
-  result->command_buffer_total_kb =
-      GetDumpsSumKb("gpu/gl/textures/*", process_memory_dump);
-  result->command_buffer_total_kb +=
-      GetDumpsSumKb("gpu/gl/buffers/*", process_memory_dump);
-  result->command_buffer_total_kb +=
-      GetDumpsSumKb("gpu/gl/renderbuffers/*", process_memory_dump);
-
-  // partition_alloc reports sizes for both allocated_objects and
-  // partitions. The memory allocated_objects uses is a subset of
-  // the partitions memory so to avoid double counting we only
-  // count partitions memory.
-  result->partition_alloc_total_kb =
-      GetDumpsSumKb("partition_alloc/partitions/*", process_memory_dump);
-  result->blink_gc_total_kb = GetDumpsSumKb("blink_gc", process_memory_dump);
-  return result;
-}
-
 void NodeAsValueIntoRecursively(const GlobalDumpGraph::Node& node,
                                 TracedValue* value,
                                 std::vector<base::StringPiece>* path) {
@@ -466,24 +434,6 @@
   std::map<base::ProcessId, uint64_t> shared_footprints =
       GraphProcessor::ComputeSharedFootprintFromGraph(*global_graph);
 
-  // On non-macOS platforms, the entries in pid_to_shared_resident_kb will be
-  // default constructed when they are first accessed in the call to
-  // CreatePublicOSDump(). This has a small amount of overhead, but seems
-  // cleaner than plumbing through platform-specific if-defs.
-  std::map<base::ProcessId, uint32_t>* pid_to_shared_resident_kb = nullptr;
-#if defined(OS_MACOSX)
-  // The resident, anonymous shared memory for each process is only relevant on
-  // macOS.
-  std::map<base::ProcessId, uint32_t> pid_to_shared_resident_kb_actual;
-  for (const auto& pair : pid_to_pmd) {
-    if (pair.second) {
-      pid_to_shared_resident_kb_actual[pair.first] =
-          GetDumpsSumKb("shared_memory/*", *pair.second);
-    }
-  }
-  pid_to_shared_resident_kb = &pid_to_shared_resident_kb_actual;
-#endif
-
   // Perform the rest of the computation on the graph.
   GraphProcessor::AddOverheadsAndPropogateEntries(global_graph.get());
   GraphProcessor::CalculateSizesForGraph(global_graph.get());
@@ -509,9 +459,24 @@
     // If the raw dump exists, create a summarised version of it.
     mojom::OSMemDumpPtr os_dump = nullptr;
     if (raw_os_dump) {
-      os_dump = CreatePublicOSDump(
-          *raw_os_dump,
-          pid_to_shared_resident_kb ? (*pid_to_shared_resident_kb)[pid] : 0);
+      uint64_t shared_resident_kb = 0;
+#if defined(OS_MACOSX)
+      // The resident, anonymous shared memory for each process is only relevant
+      // on macOS.
+      const auto process_graph_it =
+          global_graph->process_dump_graphs().find(pid);
+      if (process_graph_it != global_graph->process_dump_graphs().end()) {
+        const auto& process_graph = process_graph_it->second;
+        auto* node = process_graph->FindNode("shared_memory");
+        if (node) {
+          const auto& entry =
+              node->entries()->find(MemoryAllocatorDump::kNameSize);
+          if (entry != node->entries()->end())
+            shared_resident_kb = entry->second.value_uint64 / 1024;
+        }
+      }
+#endif
+      os_dump = CreatePublicOSDump(*raw_os_dump, shared_resident_kb);
       os_dump->shared_footprint_kb = shared_footprints[pid] / 1024;
     }
 
@@ -543,11 +508,10 @@
     if (!valid)
       continue;
 
-    // TODO(hjd): not sure we need an empty instance for the !SUMMARY_ONLY
-    // requests. Check and make the else branch a nullptr otherwise.
-    mojom::ChromeMemDumpPtr chrome_dump =
-        request->should_return_summaries() ? CreateDumpSummary(*raw_chrome_dump)
-                                           : mojom::ChromeMemDump::New();
+    mojom::ProcessMemoryDumpPtr pmd = mojom::ProcessMemoryDump::New();
+    pmd->pid = pid;
+    pmd->process_type = pid_to_process_type[pid];
+    pmd->os_dump = std::move(os_dump);
 
     // If we have to return a summary, add all entries for the requested
     // allocator dumps.
@@ -564,16 +528,11 @@
           if (entry.second.type == Node::Entry::Type::kUInt64)
             numeric_entries.emplace(entry.first, entry.second.value_uint64);
         }
-        chrome_dump->entries_for_allocator_dumps.emplace(
+        pmd->chrome_allocator_dumps.emplace(
             name, mojom::AllocatorMemDump::New(std::move(numeric_entries)));
       }
     }
 
-    mojom::ProcessMemoryDumpPtr pmd = mojom::ProcessMemoryDump::New();
-    pmd->pid = pid;
-    pmd->process_type = pid_to_process_type[pid];
-    pmd->os_dump = std::move(os_dump);
-    pmd->chrome_dump = std::move(chrome_dump);
     global_dump->process_dumps.push_back(std::move(pmd));
   }
 
diff --git a/services/resource_coordinator/observers/metrics_collector.cc b/services/resource_coordinator/observers/metrics_collector.cc
index adb7546..e80db9e 100644
--- a/services/resource_coordinator/observers/metrics_collector.cc
+++ b/services/resource_coordinator/observers/metrics_collector.cc
@@ -117,7 +117,7 @@
   const auto page_cu_id = page_cu->id();
   if (property_type == mojom::PropertyType::kVisible) {
     if (value) {
-      // The page becomes visible again, clear all record in order to
+      // The page becomes visible again, clear all records in order to
       // report metrics when page becomes invisible next time.
       ResetMetricsReportRecord(page_cu_id);
       return;
diff --git a/services/resource_coordinator/observers/page_signal_generator_impl.cc b/services/resource_coordinator/observers/page_signal_generator_impl.cc
index 6dd4cc7..f3f7997 100644
--- a/services/resource_coordinator/observers/page_signal_generator_impl.cc
+++ b/services/resource_coordinator/observers/page_signal_generator_impl.cc
@@ -69,7 +69,7 @@
     return;
 
   // Create page data exists for this Page CU.
-  auto* page_cu = static_cast<const PageCoordinationUnitImpl*>(cu);
+  auto* page_cu = PageCoordinationUnitImpl::FromCoordinationUnitBase(cu);
   DCHECK(!base::ContainsKey(page_data_, page_cu)); // No data should exist yet.
   page_data_[page_cu].load_idle_state = kLoadingNotStarted;
 }
@@ -83,7 +83,7 @@
   if (!resource_coordinator::IsPageAlmostIdleSignalEnabled())
     return;
 
-  auto* page_cu = static_cast<const PageCoordinationUnitImpl*>(cu);
+  auto* page_cu = PageCoordinationUnitImpl::FromCoordinationUnitBase(cu);
   size_t count = page_data_.erase(page_cu);
   DCHECK_EQ(1u, count);  // This should always erase exactly one CU.
 }
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.cc
index 9c11149f..c56e2fe 100644
--- a/services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.cc
+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.cc
@@ -30,9 +30,8 @@
 base::Optional<uint64_t> GlobalMemoryDump::ProcessDump::GetMetric(
     const std::string& dump_name,
     const std::string& metric_name) const {
-  auto dump_it =
-      raw_dump_->chrome_dump->entries_for_allocator_dumps.find(dump_name);
-  if (dump_it == raw_dump_->chrome_dump->entries_for_allocator_dumps.cend())
+  auto dump_it = raw_dump_->chrome_allocator_dumps.find(dump_name);
+  if (dump_it == raw_dump_->chrome_allocator_dumps.cend())
     return base::nullopt;
 
   auto metric_it = dump_it->second->numeric_entries.find(metric_name);
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.h b/services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.h
index 1aa7204..ad996fd1 100644
--- a/services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.h
+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.h
@@ -29,11 +29,6 @@
     base::ProcessId pid() const { return raw_dump_->pid; }
     mojom::ProcessType process_type() const { return raw_dump_->process_type; }
 
-    // TODO(lalitm): remove this when all consumers have migrated to using
-    // GetMetric.
-    const mojom::ChromeMemDump& chrome_dump() const {
-      return *raw_dump_->chrome_dump;
-    }
     const mojom::OSMemDump& os_dump() const { return *raw_dump_->os_dump; }
 
    private:
diff --git a/services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom b/services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom
index 1b4b2d1..2a2345e 100644
--- a/services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom
+++ b/services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom
@@ -152,18 +152,6 @@
   uint32 private_footprint_swap_kb = 0;
 };
 
-struct ChromeMemDump {
-  uint32 malloc_total_kb = 0;
-  uint32 command_buffer_total_kb = 0;
-  uint32 partition_alloc_total_kb = 0;
-  uint32 blink_gc_total_kb = 0;
-  uint32 v8_total_kb = 0;
-
-  // The allocator dumps specified by the input args.
-  // (See GlobalRequestArgs.allocator_dump_names).
-  map<string, AllocatorMemDump> entries_for_allocator_dumps;
-};
-
 // This struct contains information about a particular allocator dump
 // (e.g. cc/resource_memory).
 struct AllocatorMemDump {
@@ -177,7 +165,10 @@
 struct ProcessMemoryDump {
   ProcessType process_type;
   OSMemDump os_dump;
-  ChromeMemDump chrome_dump;
+
+  // The chrome allocator dumps specified by the input args.
+  // (See GlobalRequestArgs.allocator_dump_names).
+  map<string, AllocatorMemDump> chrome_allocator_dumps;
 
   // |pid| is necessary to correlate a ProcessMemoryDump with the URLs for the
   // process, which is obtained from the ResourceCoordinator service. In a
@@ -210,7 +201,8 @@
 
   // Requests an OSMemDump for each pid in |pids|.
   // The Memory-infra service deals with two kinds of information:
-  // 1) Chrome's view of its own memory use (recorded as ChromeMemDumps)
+  // 1) Chrome's view of its own memory use (recorded as
+  //    |chrome_allocator_dumps|)
   // 2) The OS's view of Chrome's memory use (recorded as OSMemDumps)
   // Both of these are collected per process. On most platforms each process
   // can make the system calls to collect its own OSMemDump however on some
diff --git a/services/shape_detection/BUILD.gn b/services/shape_detection/BUILD.gn
index ec6e5148..6debb796 100644
--- a/services/shape_detection/BUILD.gn
+++ b/services/shape_detection/BUILD.gn
@@ -141,5 +141,6 @@
   data = [
     "//services/test/data/mona_lisa.jpg",
     "//services/test/data/text_detection.png",
+    "//services/test/data/the_beatles.jpg",
   ]
 }
diff --git a/services/shape_detection/detection_utils_win.h b/services/shape_detection/detection_utils_win.h
index c64c6a8ae..3e0f4fc 100644
--- a/services/shape_detection/detection_utils_win.h
+++ b/services/shape_detection/detection_utils_win.h
@@ -9,17 +9,12 @@
 #include <wrl/client.h>
 #include <wrl/event.h>
 #include <wrl/implements.h>
-#include <memory>
 #include <utility>
 
 #include "base/bind.h"
 #include "base/callback.h"
-#include "base/location.h"
 #include "base/logging.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
 #include "base/sequenced_task_runner.h"
 
 class SkBitmap;
@@ -35,10 +30,8 @@
 using ABI::Windows::Graphics::Imaging::BitmapPixelFormat;
 
 // This template represents an asynchronous operation which returns a result
-// upon completion, internal async callback will be not called if the instance
-// is deleted. RuntimeType is Windows Runtime APIs that has a result.
-// TODO(junwei.fu): https://crbug.com/791371 consider moving the implementation
-// of AsyncOperation to .cc file.
+// upon completion, |callback_| will not be run if its object has been already
+// destroyed.
 template <typename RuntimeType>
 class AsyncOperation {
  public:
@@ -52,14 +45,11 @@
 
   // Creates an AsyncOperation instance which sets |callback| to be called when
   // the asynchronous action completes.
-  static std::unique_ptr<AsyncOperation<RuntimeType>> Create(
-      Callback callback,
-      IAsyncOperationPtr async_op_ptr) {
-    auto instance = base::WrapUnique(
-        new AsyncOperation<RuntimeType>(std::move(callback), async_op_ptr));
+  static HRESULT BeginAsyncOperation(Callback callback,
+                                     IAsyncOperationPtr async_op_ptr) {
+    auto instance =
+        new AsyncOperation<RuntimeType>(std::move(callback), async_op_ptr);
 
-    base::WeakPtr<AsyncOperation> weak_ptr =
-        instance->weak_factory_.GetWeakPtr();
     scoped_refptr<base::SequencedTaskRunner> task_runner =
         base::SequencedTaskRunnerHandle::Get();
 
@@ -68,33 +58,25 @@
                             WRL::FtmBase>
         AsyncCallback;
     auto async_callback = WRL::Callback<AsyncCallback>(
-        [weak_ptr, task_runner](IAsyncOperation<RuntimeType*>* async_op,
+        [instance, task_runner](IAsyncOperation<RuntimeType*>* async_op,
                                 AsyncStatus status) {
           // A reference to |async_op| is kept in |async_op_ptr_|, safe to pass
           // outside.  This is happening on an OS thread.
           task_runner->PostTask(
               FROM_HERE, base::BindOnce(&AsyncOperation::AsyncCallbackInternal,
-                                        std::move(weak_ptr),
+                                        base::Owned(instance),
                                         base::Unretained(async_op), status));
 
           return S_OK;
         });
 
-    const HRESULT hr = async_op_ptr->put_Completed(async_callback.Get());
-    if (FAILED(hr)) {
-      DLOG(ERROR) << "Async put completed failed: "
-                  << logging::SystemErrorCodeToString(hr);
-      return nullptr;
-    }
-
-    return instance;
+    return async_op_ptr->put_Completed(async_callback.Get());
   }
 
  private:
   AsyncOperation(Callback callback, IAsyncOperationPtr async_op_ptr)
       : async_op_ptr_(std::move(async_op_ptr)),
-        callback_(std::move(callback)),
-        weak_factory_(this) {}
+        callback_(std::move(callback)) {}
 
   void AsyncCallbackInternal(IAsyncOperation<RuntimeType*>* async_op,
                              AsyncStatus status) {
@@ -107,9 +89,6 @@
 
   IAsyncOperationPtr async_op_ptr_;
   Callback callback_;
-  // TODO(junwei.fu): https://crbug.com/790843 guarantee |callback_| will be
-  // called instead of canceling the callback if this object is freed.
-  base::WeakPtrFactory<AsyncOperation<RuntimeType>> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(AsyncOperation);
 };
diff --git a/services/shape_detection/face_detection_impl_mac.mm b/services/shape_detection/face_detection_impl_mac.mm
index 58e5f20..b822045 100644
--- a/services/shape_detection/face_detection_impl_mac.mm
+++ b/services/shape_detection/face_detection_impl_mac.mm
@@ -12,7 +12,9 @@
 FaceDetectionImplMac::FaceDetectionImplMac(
     shape_detection::mojom::FaceDetectorOptionsPtr options) {
   NSString* const accuracy =
-      options->fast_mode ? CIDetectorAccuracyHigh : CIDetectorAccuracyLow;
+      options->fast_mode ? CIDetectorAccuracyLow : CIDetectorAccuracyHigh;
+  // The CIDetectorMaxFeatureCount option introduced in Mac OS SDK 10.12 can
+  // only be used with Rectangle Detectors.
   NSDictionary* const detector_options = @{CIDetectorAccuracy : accuracy};
   detector_.reset([[CIDetector detectorOfType:CIDetectorTypeFace
                                       context:nil
diff --git a/services/shape_detection/face_detection_impl_mac_unittest.mm b/services/shape_detection/face_detection_impl_mac_unittest.mm
index 6c90810b..c45ce8af 100644
--- a/services/shape_detection/face_detection_impl_mac_unittest.mm
+++ b/services/shape_detection/face_detection_impl_mac_unittest.mm
@@ -28,22 +28,34 @@
   closure.Run();
 }
 
-const int kJpegImageWidth = 120;
-const int kJpegImageHeight = 120;
-const char kJpegImagePath[] = "services/test/data/mona_lisa.jpg";
-
 }  // anonymous namespace
 
-class FaceDetectionImplMacTest : public TestWithParam<bool> {
+struct TestParams {
+  bool fast_mode;
+  int image_width;
+  int image_height;
+  const char* image_path;
+  uint32_t num_faces;
+} kTestParams[] = {
+    {false, 120, 120, "services/test/data/mona_lisa.jpg", 1},
+    {true, 120, 120, "services/test/data/mona_lisa.jpg", 1},
+    {false, 240, 240, "services/test/data/the_beatles.jpg", 3},
+    {true, 240, 240, "services/test/data/the_beatles.jpg", 3},
+};
+
+class FaceDetectionImplMacTest : public TestWithParam<struct TestParams> {
  public:
   ~FaceDetectionImplMacTest() override {}
 
-  void DetectCallback(std::vector<mojom::FaceDetectionResultPtr> results) {
-    ASSERT_EQ(1u, results.size());
-    ASSERT_EQ(3u, results[0]->landmarks.size());
-    EXPECT_EQ(mojom::LandmarkType::EYE, results[0]->landmarks[0]->type);
-    EXPECT_EQ(mojom::LandmarkType::EYE, results[0]->landmarks[1]->type);
-    EXPECT_EQ(mojom::LandmarkType::MOUTH, results[0]->landmarks[2]->type);
+  void DetectCallback(uint32_t num_faces,
+                      std::vector<mojom::FaceDetectionResultPtr> results) {
+    ASSERT_EQ(num_faces, results.size());
+    for (const auto& face : results) {
+      ASSERT_EQ(3u, face->landmarks.size());
+      EXPECT_EQ(mojom::LandmarkType::EYE, face->landmarks[0]->type);
+      EXPECT_EQ(mojom::LandmarkType::EYE, face->landmarks[1]->type);
+      EXPECT_EQ(mojom::LandmarkType::MOUTH, face->landmarks[2]->type);
+    }
     Detection();
   }
   MOCK_METHOD0(Detection, void(void));
@@ -65,13 +77,13 @@
   }
 
   auto options = shape_detection::mojom::FaceDetectorOptions::New();
-  options->fast_mode = GetParam();
+  options->fast_mode = GetParam().fast_mode;
   impl_ = std::make_unique<FaceDetectionImplMac>(std::move(options));
 
   // Load image data from test directory.
   base::FilePath image_path;
   ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &image_path));
-  image_path = image_path.AppendASCII(kJpegImagePath);
+  image_path = image_path.AppendASCII(GetParam().image_path);
   ASSERT_TRUE(base::PathExists(image_path));
   std::string image_data;
   ASSERT_TRUE(base::ReadFileToString(image_path, &image_data));
@@ -79,8 +91,8 @@
   std::unique_ptr<SkBitmap> image = gfx::JPEGCodec::Decode(
       reinterpret_cast<const uint8_t*>(image_data.data()), image_data.size());
   ASSERT_TRUE(image);
-  ASSERT_EQ(kJpegImageWidth, image->width());
-  ASSERT_EQ(kJpegImageHeight, image->height());
+  ASSERT_EQ(GetParam().image_width, image->width());
+  ASSERT_EQ(GetParam().image_height, image->height());
 
   const gfx::Size size(image->width(), image->height());
   const size_t num_bytes = size.GetArea() * 4 /* bytes per pixel */;
@@ -91,12 +103,13 @@
   base::Closure quit_closure = run_loop.QuitClosure();
   // Send the image to Detect() and expect the response in callback.
   EXPECT_CALL(*this, Detection()).WillOnce(RunClosure(quit_closure));
-  impl_->Detect(*image, base::Bind(&FaceDetectionImplMacTest::DetectCallback,
-                                   base::Unretained(this)));
+  impl_->Detect(*image,
+                base::BindOnce(&FaceDetectionImplMacTest::DetectCallback,
+                               base::Unretained(this), GetParam().num_faces));
 
   run_loop.Run();
 }
 
-INSTANTIATE_TEST_CASE_P(, FaceDetectionImplMacTest, ValuesIn({true, false}));
+INSTANTIATE_TEST_CASE_P(, FaceDetectionImplMacTest, ValuesIn(kTestParams));
 
 }  // shape_detection namespace
diff --git a/services/shape_detection/face_detection_impl_win.cc b/services/shape_detection/face_detection_impl_win.cc
index 935c2e38..3bd14b6 100644
--- a/services/shape_detection/face_detection_impl_win.cc
+++ b/services/shape_detection/face_detection_impl_win.cc
@@ -23,7 +23,8 @@
     BitmapPixelFormat pixel_format)
     : face_detector_(std::move(face_detector)),
       bitmap_factory_(std::move(bitmap_factory)),
-      pixel_format_(pixel_format) {
+      pixel_format_(pixel_format),
+      weak_factory_(this) {
   DCHECK(face_detector_);
   DCHECK(bitmap_factory_);
 }
@@ -31,25 +32,24 @@
 
 void FaceDetectionImplWin::Detect(const SkBitmap& bitmap,
                                   DetectCallback callback) {
-  if ((async_detect_face_ops_ = BeginDetect(bitmap))) {
-    // Hold on the callback until AsyncOperation completes.
-    detected_face_callback_ = std::move(callback);
-    // This prevents the Detect function from being called before the
-    // AsyncOperation completes.
-    binding_->PauseIncomingMethodCallProcessing();
-  } else {
+  if (FAILED(BeginDetect(bitmap))) {
     // No detection taking place; run |callback| with an empty array of results.
     std::move(callback).Run(std::vector<mojom::FaceDetectionResultPtr>());
+    return;
   }
+  // Hold on the callback until AsyncOperation completes.
+  detected_face_callback_ = std::move(callback);
+  // This prevents the Detect function from being called before the
+  // AsyncOperation completes.
+  binding_->PauseIncomingMethodCallProcessing();
 }
 
-std::unique_ptr<AsyncOperation<IVector<DetectedFace*>>>
-FaceDetectionImplWin::BeginDetect(const SkBitmap& bitmap) {
+HRESULT FaceDetectionImplWin::BeginDetect(const SkBitmap& bitmap) {
   Microsoft::WRL::ComPtr<ISoftwareBitmap> win_bitmap =
       CreateWinBitmapWithPixelFormat(bitmap, bitmap_factory_.Get(),
                                      pixel_format_);
   if (!win_bitmap)
-    return nullptr;
+    return E_FAIL;
 
   // Detect faces asynchronously.
   AsyncOperation<IVector<DetectedFace*>>::IAsyncOperationPtr async_op;
@@ -58,15 +58,15 @@
   if (FAILED(hr)) {
     DLOG(ERROR) << "Detect faces asynchronously failed: "
                 << logging::SystemErrorCodeToString(hr);
-    return nullptr;
+    return hr;
   }
 
-  // The once callback will not be called if this object is deleted, so it's
-  // fine to use Unretained to bind the callback. |win_bitmap| needs to be kept
+  // Use WeakPtr to bind the callback so that the once callback will not be run
+  // if this object has been already destroyed. |win_bitmap| needs to be kept
   // alive until OnFaceDetected().
-  return AsyncOperation<IVector<DetectedFace*>>::Create(
+  return AsyncOperation<IVector<DetectedFace*>>::BeginAsyncOperation(
       base::BindOnce(&FaceDetectionImplWin::OnFaceDetected,
-                     base::Unretained(this), std::move(win_bitmap)),
+                     weak_factory_.GetWeakPtr(), std::move(win_bitmap)),
       std::move(async_op));
 }
 
@@ -117,7 +117,6 @@
     AsyncOperation<IVector<DetectedFace*>>::IAsyncOperationPtr async_op) {
   std::move(detected_face_callback_)
       .Run(BuildFaceDetectionResult(std::move(async_op)));
-  async_detect_face_ops_.reset();
   binding_->ResumeIncomingMethodCallProcessing();
 }
 
diff --git a/services/shape_detection/face_detection_impl_win.h b/services/shape_detection/face_detection_impl_win.h
index d99235f..8267c47 100644
--- a/services/shape_detection/face_detection_impl_win.h
+++ b/services/shape_detection/face_detection_impl_win.h
@@ -14,6 +14,7 @@
 #include <vector>
 
 #include "base/macros.h"
+#include "base/memory/weak_ptr.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "services/shape_detection/detection_utils_win.h"
 #include "services/shape_detection/public/mojom/facedetection.mojom.h"
@@ -49,8 +50,7 @@
               mojom::FaceDetection::DetectCallback callback) override;
 
  private:
-  std::unique_ptr<AsyncOperation<IVector<DetectedFace*>>> BeginDetect(
-      const SkBitmap& bitmap);
+  HRESULT BeginDetect(const SkBitmap& bitmap);
   std::vector<mojom::FaceDetectionResultPtr> BuildFaceDetectionResult(
       AsyncOperation<IVector<DetectedFace*>>::IAsyncOperationPtr async_op);
   void OnFaceDetected(
@@ -62,11 +62,11 @@
   Microsoft::WRL::ComPtr<ISoftwareBitmapStatics> bitmap_factory_;
   BitmapPixelFormat pixel_format_;
 
-  std::unique_ptr<AsyncOperation<IVector<DetectedFace*>>>
-      async_detect_face_ops_;
   DetectCallback detected_face_callback_;
   mojo::StrongBindingPtr<mojom::FaceDetection> binding_;
 
+  base::WeakPtrFactory<FaceDetectionImplWin> weak_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(FaceDetectionImplWin);
 };
 
diff --git a/services/shape_detection/face_detection_provider_win.cc b/services/shape_detection/face_detection_provider_win.cc
index 9150b63..a4c1fbc 100644
--- a/services/shape_detection/face_detection_provider_win.cc
+++ b/services/shape_detection/face_detection_provider_win.cc
@@ -41,13 +41,6 @@
 void FaceDetectionProviderWin::CreateFaceDetection(
     shape_detection::mojom::FaceDetectionRequest request,
     shape_detection::mojom::FaceDetectorOptionsPtr options) {
-  if (async_create_detector_ops_) {
-    mojo::ReportBadMessage(
-        "FaceDetectionProvider client may only create one FaceDetection at a "
-        "time.");
-    return;
-  }
-
   // FaceDetector class is only available in Win 10 onwards (v10.0.10240.0).
   if (base::win::GetVersion() < base::win::VERSION_WIN10) {
     DVLOG(1) << "FaceDetector not supported before Windows 10";
@@ -93,24 +86,28 @@
     return;
   }
 
-  // The once callback will not be called if this object is deleted, so it's
-  // fine to use Unretained to bind the callback.
-  auto async_operation = AsyncOperation<FaceDetector>::Create(
+  // Use WeakPtr to bind the callback so that the once callback will not be run
+  // if this object has been already destroyed.
+  hr = AsyncOperation<FaceDetector>::BeginAsyncOperation(
       base::BindOnce(&FaceDetectionProviderWin::OnFaceDetectorCreated,
-                     base::Unretained(this), std::move(request), pixel_format),
+                     weak_factory_.GetWeakPtr(), std::move(request),
+                     pixel_format),
       std::move(async_op));
-  if (!async_operation)
+  if (FAILED(hr)) {
+    DLOG(ERROR) << "Begin async operation failed: "
+                << logging::SystemErrorCodeToString(hr);
     return;
+  }
 
-  async_create_detector_ops_ = std::move(async_operation);
-  // When |provider| goes out of scope it will immediately closes its end of
-  // the message pipe, then |async_create_detector_ops_| will be deleted and the
-  // callback OnFaceDetectorCreated will be not called. This prevents this
-  // object from being destroyed before the AsyncOperation completes.
+  // When |provider| goes out of scope it will immediately close its end of
+  // the message pipe, then the callback OnFaceDetectorCreated will be not
+  // called. This prevents this object from being destroyed before the
+  // AsyncOperation completes.
   binding_->PauseIncomingMethodCallProcessing();
 }
 
-FaceDetectionProviderWin::FaceDetectionProviderWin() = default;
+FaceDetectionProviderWin::FaceDetectionProviderWin() : weak_factory_(this) {}
+
 FaceDetectionProviderWin::~FaceDetectionProviderWin() = default;
 
 void FaceDetectionProviderWin::OnFaceDetectorCreated(
@@ -118,7 +115,6 @@
     BitmapPixelFormat pixel_format,
     AsyncOperation<FaceDetector>::IAsyncOperationPtr async_op) {
   binding_->ResumeIncomingMethodCallProcessing();
-  async_create_detector_ops_.reset();
 
   Microsoft::WRL::ComPtr<IFaceDetector> face_detector;
   HRESULT hr =
diff --git a/services/shape_detection/face_detection_provider_win.h b/services/shape_detection/face_detection_provider_win.h
index c73032d2..f7e789c 100644
--- a/services/shape_detection/face_detection_provider_win.h
+++ b/services/shape_detection/face_detection_provider_win.h
@@ -11,6 +11,7 @@
 #include <utility>
 
 #include "base/macros.h"
+#include "base/memory/weak_ptr.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "services/shape_detection/detection_utils_win.h"
 #include "services/shape_detection/face_detection_impl_win.h"
@@ -48,7 +49,7 @@
 
   FRIEND_TEST_ALL_PREFIXES(FaceDetectionImplWinTest, ScanOneFace);
   mojo::StrongBindingPtr<mojom::FaceDetectionProvider> binding_;
-  std::unique_ptr<AsyncOperation<FaceDetector>> async_create_detector_ops_;
+  base::WeakPtrFactory<FaceDetectionProviderWin> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(FaceDetectionProviderWin);
 };
diff --git a/services/shape_detection/text_detection_impl_win.cc b/services/shape_detection/text_detection_impl_win.cc
index 9b74f04..051022f 100644
--- a/services/shape_detection/text_detection_impl_win.cc
+++ b/services/shape_detection/text_detection_impl_win.cc
@@ -115,7 +115,8 @@
     Microsoft::WRL::ComPtr<IOcrEngine> ocr_engine,
     Microsoft::WRL::ComPtr<ISoftwareBitmapStatics> bitmap_factory)
     : ocr_engine_(std::move(ocr_engine)),
-      bitmap_factory_(std::move(bitmap_factory)) {
+      bitmap_factory_(std::move(bitmap_factory)),
+      weak_factory_(this) {
   DCHECK(ocr_engine_);
   DCHECK(bitmap_factory_);
 }
@@ -124,24 +125,23 @@
 
 void TextDetectionImplWin::Detect(const SkBitmap& bitmap,
                                   DetectCallback callback) {
-  if ((async_recognize_ops_ = BeginDetect(bitmap))) {
-    // Hold on the callback until AsyncOperation completes.
-    recognize_text_callback_ = std::move(callback);
-    // This prevents the Detect function from being called before the
-    // AsyncOperation completes.
-    binding_->PauseIncomingMethodCallProcessing();
-  } else {
+  if (FAILED(BeginDetect(bitmap))) {
     // No detection taking place; run |callback| with an empty array of results.
     std::move(callback).Run(std::vector<mojom::TextDetectionResultPtr>());
+    return;
   }
+  // Hold on the callback until AsyncOperation completes.
+  recognize_text_callback_ = std::move(callback);
+  // This prevents the Detect function from being called before the
+  // AsyncOperation completes.
+  binding_->PauseIncomingMethodCallProcessing();
 }
 
-std::unique_ptr<AsyncOperation<OcrResult>> TextDetectionImplWin::BeginDetect(
-    const SkBitmap& bitmap) {
+HRESULT TextDetectionImplWin::BeginDetect(const SkBitmap& bitmap) {
   Microsoft::WRL::ComPtr<ISoftwareBitmap> win_bitmap =
       CreateWinBitmapFromSkBitmap(bitmap, bitmap_factory_.Get());
   if (!win_bitmap)
-    return nullptr;
+    return E_FAIL;
 
   // Recognize text asynchronously.
   AsyncOperation<OcrResult>::IAsyncOperationPtr async_op;
@@ -149,15 +149,15 @@
   if (FAILED(hr)) {
     DLOG(ERROR) << "Recognize text asynchronously failed: "
                 << logging::SystemErrorCodeToString(hr);
-    return nullptr;
+    return hr;
   }
 
-  // The once callback will not be called if this object is deleted, so it's
-  // fine to use Unretained to bind the callback.
-  // |win_bitmap| needs to be kept alive until OnTextDetected().
-  return AsyncOperation<OcrResult>::Create(
+  // Use WeakPtr to bind the callback so that the once callback will not be run
+  // if this object has been already destroyed. |win_bitmap| needs to be kept
+  // alive until OnTextDetected().
+  return AsyncOperation<OcrResult>::BeginAsyncOperation(
       base::BindOnce(&TextDetectionImplWin::OnTextDetected,
-                     base::Unretained(this), std::move(win_bitmap)),
+                     weak_factory_.GetWeakPtr(), std::move(win_bitmap)),
       std::move(async_op));
 }
 
@@ -214,7 +214,6 @@
     AsyncOperation<OcrResult>::IAsyncOperationPtr async_op) {
   std::move(recognize_text_callback_)
       .Run(BuildTextDetectionResult(std::move(async_op)));
-  async_recognize_ops_.reset();
   binding_->ResumeIncomingMethodCallProcessing();
 }
 
diff --git a/services/shape_detection/text_detection_impl_win.h b/services/shape_detection/text_detection_impl_win.h
index 79ffe9d..65337e2 100644
--- a/services/shape_detection/text_detection_impl_win.h
+++ b/services/shape_detection/text_detection_impl_win.h
@@ -13,6 +13,7 @@
 #include <vector>
 
 #include "base/macros.h"
+#include "base/memory/weak_ptr.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "services/shape_detection/detection_utils_win.h"
 #include "services/shape_detection/public/mojom/textdetection.mojom.h"
@@ -44,17 +45,17 @@
  private:
   Microsoft::WRL::ComPtr<IOcrEngine> ocr_engine_;
   Microsoft::WRL::ComPtr<ISoftwareBitmapStatics> bitmap_factory_;
-  std::unique_ptr<AsyncOperation<OcrResult>> async_recognize_ops_;
   DetectCallback recognize_text_callback_;
   mojo::StrongBindingPtr<mojom::TextDetection> binding_;
 
-  std::unique_ptr<AsyncOperation<OcrResult>> BeginDetect(
-      const SkBitmap& bitmap);
+  HRESULT BeginDetect(const SkBitmap& bitmap);
   std::vector<mojom::TextDetectionResultPtr> BuildTextDetectionResult(
       AsyncOperation<OcrResult>::IAsyncOperationPtr async_op);
   void OnTextDetected(Microsoft::WRL::ComPtr<ISoftwareBitmap> win_bitmap,
                       AsyncOperation<OcrResult>::IAsyncOperationPtr async_op);
 
+  base::WeakPtrFactory<TextDetectionImplWin> weak_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(TextDetectionImplWin);
 };
 
diff --git a/services/test/data/the_beatles.jpg b/services/test/data/the_beatles.jpg
new file mode 100644
index 0000000..fcd4985
--- /dev/null
+++ b/services/test/data/the_beatles.jpg
Binary files differ
diff --git a/services/ui/manifest.json b/services/ui/manifest.json
index b9311b6..a1be7b72 100644
--- a/services/ui/manifest.json
+++ b/services/ui/manifest.json
@@ -30,7 +30,7 @@
           "ui::ozone::mojom::DrmDevice"
         ],
         "test": [
-          "ui::mojom::RemoteEventDispatcher",
+          "ui::mojom::EventInjector",
           "ui::mojom::WindowServerTest"
         ],
         "discardable_memory": [
@@ -56,7 +56,7 @@
         ],
         "privileged": [
           // Injecting events is security-sensitive.
-          "ui::mojom::RemoteEventDispatcher"
+          "ui::mojom::EventInjector"
         ],
         "window_manager": [
           "discardable_memory::mojom::DiscardableSharedMemoryManager",
@@ -65,11 +65,11 @@
           "ui::mojom::AccessibilityManager",
           "ui::mojom::Clipboard",
           "ui::mojom::DisplayManager",
+          "ui::mojom::EventInjector",
           "ui::mojom::Gpu",
           "ui::mojom::IMEDriver",
           "ui::mojom::InputDeviceController",
           "ui::mojom::InputDeviceServer",
-          "ui::mojom::RemoteEventDispatcher",
           "ui::mojom::TouchDeviceServer",
           "ui::mojom::UserActivityMonitor",
           "ui::mojom::WindowManagerWindowTreeFactory"
diff --git a/services/ui/public/interfaces/BUILD.gn b/services/ui/public/interfaces/BUILD.gn
index eac70afb..a59fd14 100644
--- a/services/ui/public/interfaces/BUILD.gn
+++ b/services/ui/public/interfaces/BUILD.gn
@@ -18,10 +18,10 @@
     "accessibility_manager.mojom",
     "clipboard.mojom",
     "display_manager.mojom",
+    "event_injector.mojom",
     "event_matcher.mojom",
     "gpu.mojom",
     "mus_constants.mojom",
-    "remote_event_dispatcher.mojom",
     "user_activity_monitor.mojom",
     "video_detector.mojom",
     "window_manager.mojom",
@@ -43,7 +43,7 @@
     ":constants",
     "//gpu/ipc/common:interfaces",
     "//media/mojo/interfaces",
-    "//mojo/common:common_custom_types",
+    "//mojo/public/mojom/base",
     "//services/ui/public/interfaces/cursor",
     "//services/ui/public/interfaces/display",
     "//services/ui/public/interfaces/ime",
diff --git a/services/ui/public/interfaces/event_injector.mojom b/services/ui/public/interfaces/event_injector.mojom
new file mode 100644
index 0000000..7ba6e70
--- /dev/null
+++ b/services/ui/public/interfaces/event_injector.mojom
@@ -0,0 +1,21 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module ui.mojom;
+
+import "ui/events/mojo/event.mojom";
+
+// An interface offered by the window server which allows clients to inject
+// events which are dispatched as if they came from the system. Used for things
+// like remoting, where the window manager is receiving input from a remote
+// process, along with testing.
+interface EventInjector {
+  // Takes an event and dispatches it as if it came from the native platform.
+  // Returns false on bad |display_id| or bad |event|; returns true once the
+  // target client has completed processing the event.
+  //
+  // If |event| is a LocatedEvent, then the coordinates must be in pixels, and
+  // relative to the origin of the display identified by |display_id|.
+  InjectEvent(int64 display_id, ui.mojom.Event event) => (bool result);
+};
diff --git a/services/ui/public/interfaces/ime/ime_struct_traits_unittest.cc b/services/ui/public/interfaces/ime/ime_struct_traits_unittest.cc
index c1a57db..48beb25 100644
--- a/services/ui/public/interfaces/ime/ime_struct_traits_unittest.cc
+++ b/services/ui/public/interfaces/ime/ime_struct_traits_unittest.cc
@@ -111,11 +111,13 @@
 TEST_F(IMEStructTraitsTest, CompositionText) {
   CompositionText input;
   input.text = base::UTF8ToUTF16("abcdefghij");
-  input.ime_text_spans.push_back(
-      ImeTextSpan(0, 2, SK_ColorGRAY, ImeTextSpan::Thickness::kThin));
-  input.ime_text_spans.push_back(
-      ImeTextSpan(ImeTextSpan::Type::kComposition, 3, 6, SK_ColorRED,
-                  ImeTextSpan::Thickness::kThick, SK_ColorGREEN));
+  ImeTextSpan ime_text_span_1(0, 2, ImeTextSpan::Thickness::kThin);
+  ime_text_span_1.underline_color = SK_ColorGRAY;
+  input.ime_text_spans.push_back(ime_text_span_1);
+  ImeTextSpan ime_text_span_2(ImeTextSpan::Type::kComposition, 3, 6,
+                              ImeTextSpan::Thickness::kThick, SK_ColorGREEN);
+  ime_text_span_2.underline_color = SK_ColorRED;
+  input.ime_text_spans.push_back(ime_text_span_2);
   input.selection = gfx::Range(1, 7);
 
   CompositionText output;
diff --git a/services/ui/public/interfaces/remote_event_dispatcher.mojom b/services/ui/public/interfaces/remote_event_dispatcher.mojom
deleted file mode 100644
index 345aa88..0000000
--- a/services/ui/public/interfaces/remote_event_dispatcher.mojom
+++ /dev/null
@@ -1,19 +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.
-
-module ui.mojom;
-
-import "ui/events/mojo/event.mojom";
-
-// An interface offered by the window server which allows clients to submit
-// events which are dispatched as if they came from the system. Used for things
-// like remoting, where the window manager is receiving input from a remote
-// process, along with testing.
-interface RemoteEventDispatcher {
-  // Takes an event and dispatches it as if it came from the native platform.
-  // Returns false on bad |display_id| or bad |event|; returns true once the
-  // target client has completed processing the event.
-  DispatchEvent(int64 display_id, ui.mojom.Event event)
-      => (bool result);
-};
diff --git a/services/ui/public/interfaces/window_tree.mojom b/services/ui/public/interfaces/window_tree.mojom
index d2af92a..b5be0eb 100644
--- a/services/ui/public/interfaces/window_tree.mojom
+++ b/services/ui/public/interfaces/window_tree.mojom
@@ -4,7 +4,7 @@
 
 module ui.mojom;
 
-import "mojo/common/unguessable_token.mojom";
+import "mojo/public/mojom/base/unguessable_token.mojom";
 import "services/ui/public/interfaces/cursor/cursor.mojom";
 import "services/ui/public/interfaces/event_matcher.mojom";
 import "services/ui/public/interfaces/mus_constants.mojom";
@@ -262,7 +262,7 @@
   // token returned from ScheduleEmbed() to client B (using a separate pipe) so
   // that client B may call EmbedUsingToken().
   ScheduleEmbed(WindowTreeClient client)
-      => (mojo.common.mojom.UnguessableToken token);
+      => (mojo_base.mojom.UnguessableToken token);
 
   // Creates an UnguessableToken for use in a future call, by another client, to
   // EmbedUsingToken().
@@ -277,12 +277,12 @@
   //
   // |window_id| is the id used for the window once EmbedUsingToken() is called.
   ScheduleEmbedForExistingClient(uint32 window_id) => (
-      mojo.common.mojom.UnguessableToken token);
+      mojo_base.mojom.UnguessableToken token);
 
   // Pair with ScheduleEmbed() or ScheduleEmbedForExistingClient() to complete
   // an embedding, see them for details.
   EmbedUsingToken(uint64 window_id,
-                  mojo.common.mojom.UnguessableToken token,
+                  mojo_base.mojom.UnguessableToken token,
                   uint32 embed_flags)
       => (bool success);
 
@@ -393,7 +393,7 @@
 
   // See description in ScheduleEmbedForExistingClient() for details on this.
   // Supplied arguments match that of OnEmbed().
-  OnEmbedFromToken(mojo.common.mojom.UnguessableToken token,
+  OnEmbedFromToken(mojo_base.mojom.UnguessableToken token,
                    WindowData root,
                    int64 display_id,
                    viz.mojom.LocalSurfaceId? local_surface_id);
diff --git a/services/ui/service.cc b/services/ui/service.cc
index c69ea7d..54ffb80 100644
--- a/services/ui/service.cc
+++ b/services/ui/service.cc
@@ -30,8 +30,8 @@
 #include "services/ui/ws/display_binding.h"
 #include "services/ui/ws/display_creation_config.h"
 #include "services/ui/ws/display_manager.h"
+#include "services/ui/ws/event_injector.h"
 #include "services/ui/ws/gpu_host.h"
-#include "services/ui/ws/remote_event_dispatcher.h"
 #include "services/ui/ws/threaded_image_cursors.h"
 #include "services/ui/ws/threaded_image_cursors_factory.h"
 #include "services/ui/ws/user_activity_monitor.h"
@@ -312,8 +312,8 @@
     registry_.AddInterface<WindowServerTest>(base::BindRepeating(
         &Service::BindWindowServerTestRequest, base::Unretained(this)));
   }
-  registry_.AddInterface<mojom::RemoteEventDispatcher>(base::BindRepeating(
-      &Service::BindRemoteEventDispatcherRequest, base::Unretained(this)));
+  registry_.AddInterface<mojom::EventInjector>(base::BindRepeating(
+      &Service::BindEventInjectorRequest, base::Unretained(this)));
 
   // On non-Linux platforms there will be no DeviceDataManager instance and no
   // purpose in adding the Mojo interface to connect to.
@@ -508,10 +508,9 @@
       std::move(request));
 }
 
-void Service::BindRemoteEventDispatcherRequest(
-    mojom::RemoteEventDispatcherRequest request) {
+void Service::BindEventInjectorRequest(mojom::EventInjectorRequest request) {
   mojo::MakeStrongBinding(
-      std::make_unique<ws::RemoteEventDispatcherImpl>(window_server_.get()),
+      std::make_unique<ws::EventInjector>(window_server_.get()),
       std::move(request));
 }
 
diff --git a/services/ui/service.h b/services/ui/service.h
index b772807..caf037f 100644
--- a/services/ui/service.h
+++ b/services/ui/service.h
@@ -26,9 +26,9 @@
 #include "services/ui/public/interfaces/accessibility_manager.mojom.h"
 #include "services/ui/public/interfaces/clipboard.mojom.h"
 #include "services/ui/public/interfaces/display_manager.mojom.h"
+#include "services/ui/public/interfaces/event_injector.mojom.h"
 #include "services/ui/public/interfaces/gpu.mojom.h"
 #include "services/ui/public/interfaces/ime/ime.mojom.h"
-#include "services/ui/public/interfaces/remote_event_dispatcher.mojom.h"
 #include "services/ui/public/interfaces/user_activity_monitor.mojom.h"
 #include "services/ui/public/interfaces/video_detector.mojom.h"
 #include "services/ui/public/interfaces/window_manager_window_tree_factory.mojom.h"
@@ -167,8 +167,7 @@
 
   void BindWindowServerTestRequest(mojom::WindowServerTestRequest request);
 
-  void BindRemoteEventDispatcherRequest(
-      mojom::RemoteEventDispatcherRequest request);
+  void BindEventInjectorRequest(mojom::EventInjectorRequest request);
 
   void BindVideoDetectorRequest(mojom::VideoDetectorRequest request);
 
diff --git a/services/ui/ws/BUILD.gn b/services/ui/ws/BUILD.gn
index 18e4cf28..4a5416f1 100644
--- a/services/ui/ws/BUILD.gn
+++ b/services/ui/ws/BUILD.gn
@@ -21,6 +21,8 @@
     "access_policy_delegate.h",
     "accessibility_manager.cc",
     "accessibility_manager.h",
+    "async_event_dispatcher.h",
+    "async_event_dispatcher_lookup.h",
     "compositor_frame_sink_client_binding.cc",
     "compositor_frame_sink_client_binding.h",
     "cursor_location_manager.cc",
@@ -45,6 +47,11 @@
     "drag_source.h",
     "drag_target_connection.h",
     "event_dispatcher.h",
+    "event_dispatcher_delegate.h",
+    "event_dispatcher_impl.cc",
+    "event_dispatcher_impl.h",
+    "event_injector.cc",
+    "event_injector.h",
     "event_location.h",
     "event_matcher.cc",
     "event_matcher.h",
@@ -74,8 +81,8 @@
     "platform_display_default.h",
     "platform_display_delegate.h",
     "platform_display_factory.h",
-    "remote_event_dispatcher.cc",
-    "remote_event_dispatcher.h",
+    "platform_display_mirror.cc",
+    "platform_display_mirror.h",
     "server_window.cc",
     "server_window.h",
     "server_window_delegate.h",
@@ -251,6 +258,8 @@
     "cursor_unittest.cc",
     "display_unittest.cc",
     "drag_controller_unittest.cc",
+    "event_dispatcher_impl_test_api.cc",
+    "event_dispatcher_impl_test_api.h",
     "event_matcher_unittest.cc",
     "event_processor_unittest.cc",
     "focus_controller_unittest.cc",
diff --git a/services/ui/ws/README.md b/services/ui/ws/README.md
index 3b25467..35688fe5 100644
--- a/services/ui/ws/README.md
+++ b/services/ui/ws/README.md
@@ -85,3 +85,29 @@
 
 FrameSinkId is derived from the embedded client, where as LocalSurfaceId
 comes from the embedder.
+
+### Event Processing
+
+One of the key operations of the Window Service is event processing. This
+includes maintaining state associated with the current input devices (such
+as the location of the mouse cursor) as well dispatching to the appropriate
+client. Event processing includes the following classes, see each for more
+details:
+. EventDispatcherImpl: events received from the platform are sent here first.
+  If not already processing an event EventDispatcherImpl forwards the event to
+  EventProcessor. If EventDispatcherImpl is processing an event it queues the
+  event for later processing.
+. EventProcessor: maintains state related to event processing, passing the
+  appropriate events and targets to EventDispatcher for dispatch.
+. AsyncEventDispatcher: dispatches an event to the client, notifying a callback
+  when done. This interface is largely for testing with WindowTree providing
+  the implementation.
+. EventTargeter: used by EventProcessor to determine the ServerWindow to send an
+  event to. Targetting is potentially asynchronous.
+
+EventDispatcherImpl and EventProcessor both have delegates that can impact
+targetting, as well as being notified during the lifecycle of processing.
+
+EventInjector is not a core part of event processing. It allows remote clients
+to inject events for testing, remoting and similar use cases. Events injected
+via EventInjector end up going to EventProcessor.
diff --git a/services/ui/ws/async_event_dispatcher.h b/services/ui/ws/async_event_dispatcher.h
new file mode 100644
index 0000000..95cb7ec
--- /dev/null
+++ b/services/ui/ws/async_event_dispatcher.h
@@ -0,0 +1,66 @@
+// Copyright 2018 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 SERVICES_UI_WS_ASYNC_EVENT_DISPATCHER_H_
+#define SERVICES_UI_WS_ASYNC_EVENT_DISPATCHER_H_
+
+#include <stdint.h>
+
+#include <string>
+#include <unordered_map>
+
+#include "base/callback_forward.h"
+
+namespace ui {
+class Event;
+}
+
+namespace ui {
+namespace mojom {
+enum class EventReslut;
+}
+namespace ws {
+
+class ServerWindow;
+
+struct EventLocation;
+
+// AsyncEventDispatchers dispatch events asynchronously. A callback is run once
+// the accelerator or event is dispatched. This class allows the event
+// dispatching code to be independent of WindowTree (for testing and
+// modularity).
+//
+// If an AsyncEventDispatcher does not run the callback in a reasonable amount
+// of time, Dispatch* may be called again.
+class AsyncEventDispatcher {
+ public:
+  using DispatchEventCallback = base::OnceCallback<void(mojom::EventResult)>;
+  // Dispatches |event| to |target|, running |callback| with the result.
+  // |event_location| is only useful for located events.
+  virtual void DispatchEvent(ServerWindow* target,
+                             const Event& event,
+                             const EventLocation& event_location,
+                             DispatchEventCallback callback) = 0;
+
+  // In addition to the result of the accelerator, AcceleratorCallback is
+  // supplied arbitrary key-value pairs that are added to the event if
+  // further processing is necessary (EventResult::UNHANDLED is supplied to the
+  // callback). The intepretation of the key-value pairs is left to clients (see
+  // ash/public/interfaces/event_properties.mojom for examples).
+  using AcceleratorCallback = base::OnceCallback<void(
+      mojom::EventResult,
+      const std::unordered_map<std::string, std::vector<uint8_t>>&)>;
+
+  // Dispatches an accelerator that matches |event|, running the callback with
+  // the result and key-value pairs. |accelerator_id| identifies the
+  // accelerator.
+  virtual void DispatchAccelerator(uint32_t accelerator_id,
+                                   const Event& event,
+                                   AcceleratorCallback callback) = 0;
+};
+
+}  // namespace ws
+}  // namespace ui
+
+#endif  // SERVICES_UI_WS_ASYNC_EVENT_DISPATCHER_H_
diff --git a/services/ui/ws/async_event_dispatcher_lookup.h b/services/ui/ws/async_event_dispatcher_lookup.h
new file mode 100644
index 0000000..e4ee1eab
--- /dev/null
+++ b/services/ui/ws/async_event_dispatcher_lookup.h
@@ -0,0 +1,26 @@
+// Copyright 2018 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 SERVICES_UI_WS_ASYNC_EVENT_DISPATCHER_LOOKUP_H_
+#define SERVICES_UI_WS_ASYNC_EVENT_DISPATCHER_LOOKUP_H_
+
+#include "services/ui/common/types.h"
+
+namespace ui {
+namespace ws {
+
+class AsyncEventDispatcher;
+
+// Looks up an AsyncEventDispatcher by id. This is used so that event processing
+// related code does not have a dependency on WindowTree or WindowService.
+class AsyncEventDispatcherLookup {
+ public:
+  virtual AsyncEventDispatcher* GetAsyncEventDispatcherById(
+      ClientSpecificId id) = 0;
+};
+
+}  // namespace ws
+}  // namespace ui
+
+#endif  // SERVICES_UI_WS_ASYNC_EVENT_DISPATCHER_LOOKUP_H_
diff --git a/services/ui/ws/display.cc b/services/ui/ws/display.cc
index 4294814..09ac461 100644
--- a/services/ui/ws/display.cc
+++ b/services/ui/ws/display.cc
@@ -30,10 +30,6 @@
 #include "ui/base/cursor/cursor.h"
 #include "ui/display/screen.h"
 
-#if defined(USE_OZONE)
-#include "ui/ozone/public/ozone_platform.h"
-#endif
-
 namespace ui {
 namespace ws {
 
@@ -137,7 +133,7 @@
   ServerWindow* old_focused_window = focus_controller_->GetFocusedWindow();
   if (old_focused_window == new_focused_window)
     return true;
-  DCHECK(!new_focused_window || root_window()->Contains(new_focused_window));
+  DCHECK(!new_focused_window || root_->Contains(new_focused_window));
   return focus_controller_->SetFocusedWindow(new_focused_window);
 }
 
@@ -255,14 +251,6 @@
   }
 }
 
-OzonePlatform* Display::GetOzonePlatform() {
-#if defined(USE_OZONE)
-  return OzonePlatform::GetInstance();
-#else
-  return nullptr;
-#endif
-}
-
 bool Display::IsHostingViz() const {
   return window_server_->is_hosting_viz();
 }
diff --git a/services/ui/ws/display.h b/services/ui/ws/display.h
index 228537ac..fb4eb6a 100644
--- a/services/ui/ws/display.h
+++ b/services/ui/ws/display.h
@@ -174,7 +174,6 @@
   EventSink* GetEventSink() override;
   void OnAcceleratedWidgetAvailable() override;
   void OnNativeCaptureLost() override;
-  OzonePlatform* GetOzonePlatform() override;
   bool IsHostingViz() const override;
 
   // FocusControllerObserver:
diff --git a/services/ui/ws/display_manager.cc b/services/ui/ws/display_manager.cc
index e580213..655f2f7 100644
--- a/services/ui/ws/display_manager.cc
+++ b/services/ui/ws/display_manager.cc
@@ -6,8 +6,8 @@
 
 #include <vector>
 
+#include "base/containers/flat_set.h"
 #include "base/memory/ptr_util.h"
-#include "base/stl_util.h"
 #include "base/trace_event/trace_event.h"
 #include "services/ui/display/screen_manager.h"
 #include "services/ui/display/viewport_metrics.h"
@@ -17,6 +17,7 @@
 #include "services/ui/ws/display_creation_config.h"
 #include "services/ui/ws/event_processor.h"
 #include "services/ui/ws/frame_generator.h"
+#include "services/ui/ws/platform_display_mirror.h"
 #include "services/ui/ws/server_window.h"
 #include "services/ui/ws/user_display_manager.h"
 #include "services/ui/ws/user_display_manager_delegate.h"
@@ -85,13 +86,11 @@
     return false;
   }
 
-  std::set<int64_t> display_ids;
   size_t primary_display_index = std::numeric_limits<size_t>::max();
   bool found_internal_display = false;
 
   // Check the mirrors before potentially passing them to a unified display.
-  DCHECK(window_server_->is_hosting_viz() || mirrors.empty())
-      << "The window server only handles mirrors specially when hosting viz.";
+  base::flat_set<int64_t> mirror_ids;
   for (const auto& mirror : mirrors) {
     if (mirror.id() == display::kInvalidDisplayId) {
       LOG(ERROR) << "SetDisplayConfiguration passed invalid display id";
@@ -101,7 +100,7 @@
       LOG(ERROR) << "SetDisplayConfiguration passed unified display in mirrors";
       return false;
     }
-    if (!display_ids.insert(mirror.id()).second) {
+    if (!mirror_ids.insert(mirror.id()).second) {
       LOG(ERROR) << "SetDisplayConfiguration passed duplicate display id";
       return false;
     }
@@ -111,6 +110,8 @@
     }
     found_internal_display |= mirror.id() == internal_display_id;
   }
+
+  base::flat_set<int64_t> display_ids;
   for (size_t i = 0; i < displays.size(); ++i) {
     const display::Display& display = displays[i];
     if (display.id() == display::kInvalidDisplayId) {
@@ -150,8 +151,36 @@
 
   display::DisplayList& display_list =
       display::ScreenManager::GetInstance()->GetScreen()->display_list();
+  // Update the primary display first, in case the old primary has been removed.
   display_list.AddOrUpdateDisplay(displays[primary_display_index],
                                   display::DisplayList::Type::PRIMARY);
+
+  // Remove any existing displays that are not included in the configuration.
+  for (int i = display_list.displays().size() - 1; i >= 0; --i) {
+    const int64_t id = display_list.displays()[i].id();
+    if (display_ids.count(id) == 0) {
+      // The display list also contains mirrors, which do not have ws::Displays.
+      // If the destroyed display still has a root window, it is orphaned here.
+      // Root windows are destroyed by explicit window manager instruction.
+      if (Display* ws_display = GetDisplayById(id))
+        DestroyDisplay(ws_display);
+      // Do not remove display::Display entries for mirroring displays.
+      if (mirror_ids.count(id) == 0)
+        display_list.RemoveDisplay(id);
+    }
+  }
+
+  // Remove any existing mirrors that are not included in the configuration.
+  for (int i = mirrors_.size() - 1; i >= 0; --i) {
+    if (mirror_ids.count(mirrors_[i]->display().id()) == 0) {
+      // Do not remove display::Display entries for extended displays.
+      if (display_ids.count(mirrors_[i]->display().id()) == 0)
+        display_list.RemoveDisplay(mirrors_[i]->display().id());
+      mirrors_.erase(mirrors_.begin() + i);
+    }
+  }
+
+  // Add or update any displays that are included in the configuration.
   for (size_t i = 0; i < displays.size(); ++i) {
     Display* ws_display = GetDisplayById(displays[i].id());
     DCHECK(ws_display);
@@ -162,19 +191,26 @@
                                       display::DisplayList::Type::NOT_PRIMARY);
     }
   }
+
+  // Add or update any mirrors that are included in the configuration.
   for (size_t i = 0; i < mirrors.size(); ++i) {
-    NOTIMPLEMENTED() << "TODO(crbug.com/806318): Mus+Viz mirroring/unified";
-    Display* ws_mirror = GetDisplayById(mirrors[i].id());
+    DCHECK(!GetDisplayById(mirrors[i].id()));
+    Display* ws_display_to_mirror = GetDisplayById(displays[0].id());
+
     const auto& metrics = viewport_metrics[displays.size() + i];
-    if (!ws_mirror) {
-      // Create a mirror destination display on startup or on display connected.
-      CreateDisplay(mirrors[i], metrics);
+    PlatformDisplayMirror* mirror = nullptr;
+    for (size_t i = 0; i < mirrors_.size(); ++i) {
+      if (mirrors_[i]->display().id() == mirrors[i].id()) {
+        mirror = mirrors_[i].get();
+        break;
+      }
+    }
+    if (mirror) {
+      mirror->set_display(mirrors[i]);
+      mirror->UpdateViewportMetrics(metrics);
     } else {
-      // Reuse an existing display for mirroring that was previously extended.
-      ws_mirror->SetDisplay(mirrors[i]);
-      ws_mirror->OnViewportMetricsChanged(metrics);
-      display_list.AddOrUpdateDisplay(mirrors[i],
-                                      display::DisplayList::Type::NOT_PRIMARY);
+      mirrors_.push_back(std::make_unique<PlatformDisplayMirror>(
+          mirrors[i], metrics, window_server_, ws_display_to_mirror));
     }
   }
 
@@ -224,8 +260,10 @@
   const display::DisplayList::Type display_type =
       is_primary_display ? display::DisplayList::Type::PRIMARY
                          : display::DisplayList::Type::NOT_PRIMARY;
-  display::ScreenManager::GetInstance()->GetScreen()->display_list().AddDisplay(
-      display, display_type);
+  display::DisplayList& display_list =
+      display::ScreenManager::GetInstance()->GetScreen()->display_list();
+  // The display may already be listed as a mirror destination display.
+  display_list.AddOrUpdateDisplay(display, display_type);
   OnDisplayAdded(display, metrics);
   return GetDisplayById(display.id());
 }
@@ -337,6 +375,18 @@
   window_server_->OnDisplayReady(display, is_first_display);
 }
 
+void DisplayManager::OnWindowManagerSurfaceActivation(
+    Display* display,
+    const viz::SurfaceInfo& surface_info) {
+  display->platform_display()->GetFrameGenerator()->SetEmbeddedSurface(
+      surface_info);
+  // Also pass the surface info to any displays mirroring the given display.
+  for (const auto& mirror : mirrors_) {
+    if (mirror->display_to_mirror() == display)
+      mirror->GetFrameGenerator()->SetEmbeddedSurface(surface_info);
+  }
+}
+
 void DisplayManager::SetHighContrastMode(bool enabled) {
   for (Display* display : displays_) {
     display->platform_display()->GetFrameGenerator()->SetHighContrastMode(
diff --git a/services/ui/ws/display_manager.h b/services/ui/ws/display_manager.h
index 00b48484..df84b1f 100644
--- a/services/ui/ws/display_manager.h
+++ b/services/ui/ws/display_manager.h
@@ -10,6 +10,7 @@
 #include <set>
 
 #include "base/macros.h"
+#include "components/viz/common/surfaces/surface_info.h"
 #include "services/ui/display/screen_manager_delegate.h"
 #include "services/ui/public/interfaces/window_manager_constants.mojom.h"
 #include "services/ui/ws/ids.h"
@@ -24,6 +25,7 @@
 
 class CursorLocationManager;
 class Display;
+class PlatformDisplayMirror;
 class ServerWindow;
 class UserDisplayManager;
 class WindowManagerDisplayRoot;
@@ -114,6 +116,10 @@
   // Called when the AcceleratedWidget is available for |display|.
   void OnDisplayAcceleratedWidgetAvailable(Display* display);
 
+  // Called when a new surface for a WindowManager root has been created.
+  void OnWindowManagerSurfaceActivation(Display* display,
+                                        const viz::SurfaceInfo& surface_info);
+
   // Switch the high contrast mode of all Displays to |enabled|.
   void SetHighContrastMode(bool enabled);
 
@@ -144,6 +150,9 @@
   std::set<Display*> pending_displays_;
   std::set<Display*> displays_;
 
+  // Displays that mirror the contents of another display in |displays_|.
+  std::vector<std::unique_ptr<PlatformDisplayMirror>> mirrors_;
+
   std::unique_ptr<UserDisplayManager> user_display_manager_;
 
   std::unique_ptr<CursorLocationManager> cursor_location_manager_;
diff --git a/services/ui/ws/event_dispatcher_delegate.h b/services/ui/ws/event_dispatcher_delegate.h
new file mode 100644
index 0000000..2eea409
--- /dev/null
+++ b/services/ui/ws/event_dispatcher_delegate.h
@@ -0,0 +1,57 @@
+// Copyright 2018 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 SERVICES_UI_WS_EVENT_DISPATCHER_DELEGATE_H_
+#define SERVICES_UI_WS_EVENT_DISPATCHER_DELEGATE_H_
+
+#include <stdint.h>
+
+#include "services/ui/ws/ids.h"
+
+namespace ui {
+
+class Event;
+
+namespace ws {
+
+class AsyncEventDispatcher;
+class ServerWindow;
+
+struct EventLocation;
+
+// Called at interesting stages during event dispatch.
+class EventDispatcherDelegate {
+ public:
+  // Called immediately before |event| is handed to EventProcessor for
+  // processing
+  virtual void OnWillProcessEvent(const ui::Event& event,
+                                  const EventLocation& event_location) = 0;
+
+  // Called before dispatching an event to an AsyncEventDispatcher. The delegate
+  // may return a different ServerWindow to send the event to. Typically the
+  // delegate will return |target|.
+  virtual ServerWindow* OnWillDispatchInputEvent(
+      ServerWindow* target,
+      ClientSpecificId client_id,
+      const EventLocation& event_location,
+      const Event& event) = 0;
+
+  // Called when |async_event_dispatcher| did not complete processing in a
+  // reasonable amount of time.
+  virtual void OnEventDispatchTimedOut(
+      AsyncEventDispatcher* async_event_dispatcher) = 0;
+
+  // Called when an AsyncEventDispatcher handles an event that mapped to an
+  // accelerator.
+  virtual void OnAsyncEventDispatcherHandledAccelerator(const Event& event,
+                                                        int64_t display_id) = 0;
+
+ protected:
+  virtual ~EventDispatcherDelegate() {}
+};
+
+}  // namespace ws
+}  // namespace ui
+
+#endif  // SERVICES_UI_WS_EVENT_DISPATCHER_DELEGATE_H_
diff --git a/services/ui/ws/event_dispatcher_impl.cc b/services/ui/ws/event_dispatcher_impl.cc
new file mode 100644
index 0000000..782a149d1
--- /dev/null
+++ b/services/ui/ws/event_dispatcher_impl.cc
@@ -0,0 +1,411 @@
+// Copyright 2018 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 "services/ui/ws/event_dispatcher_impl.h"
+
+#include "base/debug/debugger.h"
+#include "services/ui/public/interfaces/window_tree_constants.mojom.h"
+#include "services/ui/ws/accelerator.h"
+#include "services/ui/ws/async_event_dispatcher.h"
+#include "services/ui/ws/async_event_dispatcher_lookup.h"
+#include "services/ui/ws/event_dispatcher_delegate.h"
+#include "services/ui/ws/event_location.h"
+#include "services/ui/ws/event_processor.h"
+#include "services/ui/ws/server_window.h"
+#include "services/ui/ws/server_window_tracker.h"
+#include "ui/events/event.h"
+
+namespace ui {
+namespace ws {
+namespace {
+
+bool CanEventsBeCoalesced(const ui::Event& one, const ui::Event& two) {
+  if (one.type() != two.type() || one.flags() != two.flags())
+    return false;
+
+  // TODO(sad): wheel events can also be merged.
+  if (one.type() != ui::ET_POINTER_MOVED)
+    return false;
+
+  return one.AsPointerEvent()->pointer_details().id ==
+         two.AsPointerEvent()->pointer_details().id;
+}
+
+std::unique_ptr<ui::Event> CoalesceEvents(std::unique_ptr<ui::Event> first,
+                                          std::unique_ptr<ui::Event> second) {
+  DCHECK(first->type() == ui::ET_POINTER_MOVED)
+      << " Non-move events cannot be merged yet.";
+  // For mouse moves, the new event just replaces the old event, but we need to
+  // use the latency from the old event.
+  second->set_latency(*first->latency());
+  second->latency()->set_coalesced();
+  return second;
+}
+
+base::TimeDelta GetDefaultAckTimerDelay() {
+#if defined(NDEBUG)
+  return base::TimeDelta::FromMilliseconds(100);
+#else
+  return base::TimeDelta::FromMilliseconds(1000);
+#endif
+}
+
+}  // namespace
+
+// See EventDispatcherImpl::EventTask::Type::kProcessedEvent for details on
+// this.
+class EventDispatcherImpl::ProcessedEventTarget {
+ public:
+  ProcessedEventTarget(
+      AsyncEventDispatcherLookup* async_event_dispatcher_lookup,
+      ServerWindow* window,
+      ClientSpecificId client_id,
+      Accelerator* accelerator)
+      : async_event_dispatcher_lookup_(async_event_dispatcher_lookup),
+        client_id_(client_id) {
+    DCHECK(async_event_dispatcher_lookup_);
+    DCHECK(window);
+    tracker_.Add(window);
+    if (accelerator)
+      accelerator_ = accelerator->GetWeakPtr();
+  }
+
+  ~ProcessedEventTarget() {}
+
+  // Return true if the event is still valid. The event becomes invalid if
+  // the window is destroyed while waiting to dispatch.
+  bool IsValid() {
+    return window() &&
+           async_event_dispatcher_lookup_->GetAsyncEventDispatcherById(
+               client_id_);
+  }
+
+  ServerWindow* window() {
+    return tracker_.windows().empty() ? nullptr : tracker_.windows().front();
+  }
+
+  ClientSpecificId client_id() const { return client_id_; }
+
+  base::WeakPtr<Accelerator> accelerator() { return accelerator_; }
+
+ private:
+  AsyncEventDispatcherLookup* async_event_dispatcher_lookup_;
+  ServerWindowTracker tracker_;
+  const ClientSpecificId client_id_;
+  base::WeakPtr<Accelerator> accelerator_;
+
+  DISALLOW_COPY_AND_ASSIGN(ProcessedEventTarget);
+};
+
+EventDispatcherImpl::InFlightEventDispatchDetails::InFlightEventDispatchDetails(
+    EventDispatcherImpl* event_dispatcher,
+    AsyncEventDispatcher* async_event_dispatcher,
+    int64_t display_id,
+    const Event& event,
+    EventDispatchPhase phase)
+    : async_event_dispatcher(async_event_dispatcher),
+      display_id(display_id),
+      event(Event::Clone(event)),
+      phase(phase),
+      weak_factory_(event_dispatcher) {}
+
+EventDispatcherImpl::InFlightEventDispatchDetails::
+    ~InFlightEventDispatchDetails() {}
+
+// Contains data used for event processing that needs to happen. See enum for
+// details.
+struct EventDispatcherImpl::EventTask {
+  enum class Type {
+    // ProcessEvent() was called while waiting on a client or EventProcessor
+    // to complete processing. |event| is non-null and |processed_target| is
+    // null.
+    kEvent,
+
+    // In certain situations EventProcessor::ProcessEvent() generates more than
+    // one event. When that happens, |kProcessedEvent| is used for all events
+    // after the first. For example, a move may result in an exit for one
+    // Window and and an enter for another Window. The event generated for the
+    // enter results in an EventTask of type |kProcessedEvent|. In this case
+    // both |event| and |processed_target| are valid.
+    kProcessedEvent,
+
+    // ScheduleCallbackWhenDoneProcessingEvents() is called while waiting on
+    // a client or EventProcessor. |event| and |processed_target| are null.
+    kClosure
+  };
+
+  EventTask() = default;
+  ~EventTask() = default;
+
+  Type type() const {
+    if (done_closure)
+      return Type::kClosure;
+    if (processed_target) {
+      DCHECK(event);
+      return Type::kProcessedEvent;
+    }
+    DCHECK(event);
+    return Type::kEvent;
+  }
+
+  std::unique_ptr<Event> event;
+  std::unique_ptr<ProcessedEventTarget> processed_target;
+  EventLocation event_location;
+  base::OnceClosure done_closure;
+};
+
+EventDispatcherImpl::EventDispatcherImpl(
+    AsyncEventDispatcherLookup* async_event_dispatcher_lookup,
+    AsyncEventDispatcher* accelerator_dispatcher,
+    EventDispatcherDelegate* delegate)
+    : async_event_dispatcher_lookup_(async_event_dispatcher_lookup),
+      accelerator_dispatcher_(accelerator_dispatcher),
+      delegate_(delegate) {
+  DCHECK(async_event_dispatcher_lookup_);
+}
+
+EventDispatcherImpl::~EventDispatcherImpl() = default;
+
+void EventDispatcherImpl::Init(EventProcessor* event_processor) {
+  DCHECK(event_processor);
+  DCHECK(!event_processor_);
+  event_processor_ = event_processor;
+}
+
+void EventDispatcherImpl::ProcessEvent(ui::Event* event,
+                                       const EventLocation& event_location) {
+  // If this is still waiting for an ack from a previously sent event, then
+  // queue the event so it's dispatched once the ack is received.
+  if (IsProcessingEvent()) {
+    if (!event_tasks_.empty() &&
+        event_tasks_.back()->type() == EventTask::Type::kEvent &&
+        CanEventsBeCoalesced(*event_tasks_.back()->event, *event)) {
+      event_tasks_.back()->event = CoalesceEvents(
+          std::move(event_tasks_.back()->event), ui::Event::Clone(*event));
+      event_tasks_.back()->event_location = event_location;
+      return;
+    }
+    QueueEvent(*event, nullptr, event_location);
+    return;
+  }
+
+  QueueEvent(*event, nullptr, event_location);
+  ProcessEventTasks();
+}
+
+bool EventDispatcherImpl::IsProcessingEvent() const {
+  return in_flight_event_dispatch_details_ ||
+         event_processor_->IsProcessingEvent();
+}
+
+const ui::Event* EventDispatcherImpl::GetInFlightEvent() const {
+  return in_flight_event_dispatch_details_
+             ? in_flight_event_dispatch_details_->event.get()
+             : nullptr;
+}
+
+void EventDispatcherImpl::ScheduleCallbackWhenDoneProcessingEvents(
+    base::OnceClosure closure) {
+  DCHECK(closure);
+  if (!IsProcessingEvent()) {
+    std::move(closure).Run();
+    return;
+  }
+
+  // TODO(sky): use make_unique (presubmit check fails on make_unique).
+  std::unique_ptr<EventTask> event_task(new EventTask());
+  event_task->done_closure = std::move(closure);
+  event_tasks_.push(std::move(event_task));
+}
+
+void EventDispatcherImpl::OnWillDestroyAsyncEventDispatcher(
+    AsyncEventDispatcher* target) {
+  if (!in_flight_event_dispatch_details_ ||
+      in_flight_event_dispatch_details_->async_event_dispatcher != target) {
+    return;
+  }
+
+  // The target is going to be deleted and won't ack the event, simulate an ack
+  // so we don't wait for the timer to fire.
+  OnDispatchInputEventDone(mojom::EventResult::UNHANDLED);
+}
+
+void EventDispatcherImpl::ScheduleInputEventTimeout(
+    AsyncEventDispatcher* async_event_dispatcher,
+    int64_t display_id,
+    const Event& event,
+    EventDispatchPhase phase) {
+  DCHECK(!in_flight_event_dispatch_details_);
+  std::unique_ptr<InFlightEventDispatchDetails> details =
+      std::make_unique<InFlightEventDispatchDetails>(
+          this, async_event_dispatcher, display_id, event, phase);
+
+  // TODO(sad): Adjust this delay, possibly make this dynamic.
+  const base::TimeDelta max_delay = base::debug::BeingDebugged()
+                                        ? base::TimeDelta::FromDays(1)
+                                        : GetDefaultAckTimerDelay();
+  details->timer.Start(
+      FROM_HERE, max_delay,
+      base::Bind(&EventDispatcherImpl::OnDispatchInputEventTimeout,
+                 details->weak_factory_.GetWeakPtr()));
+  in_flight_event_dispatch_details_ = std::move(details);
+}
+
+void EventDispatcherImpl::ProcessEventTasks() {
+  // Loop through |event_tasks_| stopping after dispatching the first valid
+  // event.
+  while (!event_tasks_.empty() && !IsProcessingEvent()) {
+    std::unique_ptr<EventTask> task = std::move(event_tasks_.front());
+    event_tasks_.pop();
+
+    switch (task->type()) {
+      case EventTask::Type::kClosure:
+        std::move(task->done_closure).Run();
+        break;
+      case EventTask::Type::kEvent:
+        delegate_->OnWillProcessEvent(*task->event, task->event_location);
+        event_processor_->ProcessEvent(
+            *task->event, task->event_location,
+            EventProcessor::AcceleratorMatchPhase::ANY);
+        break;
+      case EventTask::Type::kProcessedEvent:
+        if (task->processed_target->IsValid()) {
+          DispatchInputEventToWindowImpl(task->processed_target->window(),
+                                         task->processed_target->client_id(),
+                                         task->event_location, *task->event,
+                                         task->processed_target->accelerator());
+        }
+        break;
+    }
+  }
+}
+
+// TODO(riajiang): We might want to do event targeting for the next event while
+// waiting for the current event to be dispatched. https://crbug.com/724521
+void EventDispatcherImpl::DispatchInputEventToWindowImpl(
+    ServerWindow* target,
+    ClientSpecificId client_id,
+    const EventLocation& event_location,
+    const ui::Event& event,
+    base::WeakPtr<Accelerator> accelerator) {
+  DCHECK(!in_flight_event_dispatch_details_);
+  DCHECK(target);
+  target = delegate_->OnWillDispatchInputEvent(target, client_id,
+                                               event_location, event);
+  AsyncEventDispatcher* async_event_dispatcher =
+      async_event_dispatcher_lookup_->GetAsyncEventDispatcherById(client_id);
+  DCHECK(async_event_dispatcher);
+  ScheduleInputEventTimeout(async_event_dispatcher, event_location.display_id,
+                            event, EventDispatchPhase::TARGET);
+  in_flight_event_dispatch_details_->post_target_accelerator = accelerator;
+
+  async_event_dispatcher->DispatchEvent(
+      target, event, event_location,
+      base::BindOnce(
+          &EventDispatcherImpl::OnDispatchInputEventDone,
+          in_flight_event_dispatch_details_->weak_factory_.GetWeakPtr()));
+}
+
+void EventDispatcherImpl::OnDispatchInputEventTimeout() {
+  DCHECK(in_flight_event_dispatch_details_);
+  delegate_->OnEventDispatchTimedOut(
+      in_flight_event_dispatch_details_->async_event_dispatcher);
+  if (in_flight_event_dispatch_details_->phase ==
+      EventDispatchPhase::PRE_TARGET_ACCELERATOR) {
+    OnAcceleratorDone(mojom::EventResult::UNHANDLED, KeyEvent::Properties());
+  } else {
+    OnDispatchInputEventDone(mojom::EventResult::UNHANDLED);
+  }
+}
+
+void EventDispatcherImpl::OnDispatchInputEventDone(mojom::EventResult result) {
+  DCHECK(in_flight_event_dispatch_details_);
+  std::unique_ptr<InFlightEventDispatchDetails> details =
+      std::move(in_flight_event_dispatch_details_);
+
+  if (result == mojom::EventResult::UNHANDLED &&
+      details->post_target_accelerator) {
+    OnAccelerator(details->post_target_accelerator->id(), details->display_id,
+                  *details->event, AcceleratorPhase::kPost);
+  }
+
+  ProcessEventTasks();
+}
+
+void EventDispatcherImpl::OnAcceleratorDone(
+    mojom::EventResult result,
+    const std::unordered_map<std::string, std::vector<uint8_t>>& properties) {
+  DCHECK(in_flight_event_dispatch_details_);
+  DCHECK_EQ(EventDispatchPhase::PRE_TARGET_ACCELERATOR,
+            in_flight_event_dispatch_details_->phase);
+
+  std::unique_ptr<InFlightEventDispatchDetails> details =
+      std::move(in_flight_event_dispatch_details_);
+
+  if (result == mojom::EventResult::UNHANDLED) {
+    DCHECK(details->event->IsKeyEvent());
+    if (!properties.empty())
+      details->event->AsKeyEvent()->SetProperties(properties);
+    event_processor_->ProcessEvent(
+        *details->event, EventLocation(details->display_id),
+        EventProcessor::AcceleratorMatchPhase::POST_ONLY);
+  } else {
+    // We're not going to process the event any further, notify the delegate.
+    delegate_->OnAsyncEventDispatcherHandledAccelerator(*details->event,
+                                                        details->display_id);
+    ProcessEventTasks();
+  }
+}
+
+void EventDispatcherImpl::QueueEvent(
+    const ui::Event& event,
+    std::unique_ptr<ProcessedEventTarget> processed_event_target,
+    const EventLocation& event_location) {
+  std::unique_ptr<EventTask> queued_event(new EventTask);
+  queued_event->event = ui::Event::Clone(event);
+  queued_event->processed_target = std::move(processed_event_target);
+  queued_event->event_location = event_location;
+  event_tasks_.push(std::move(queued_event));
+}
+
+void EventDispatcherImpl::DispatchInputEventToWindow(
+    ServerWindow* target,
+    ClientSpecificId client_id,
+    const EventLocation& event_location,
+    const Event& event,
+    Accelerator* accelerator) {
+  if (in_flight_event_dispatch_details_) {
+    std::unique_ptr<ProcessedEventTarget> processed_event_target =
+        std::make_unique<ProcessedEventTarget>(async_event_dispatcher_lookup_,
+                                               target, client_id, accelerator);
+    QueueEvent(event, std::move(processed_event_target), event_location);
+    return;
+  }
+
+  base::WeakPtr<Accelerator> weak_accelerator;
+  if (accelerator)
+    weak_accelerator = accelerator->GetWeakPtr();
+  DispatchInputEventToWindowImpl(target, client_id, event_location, event,
+                                 weak_accelerator);
+}
+
+void EventDispatcherImpl::OnAccelerator(uint32_t accelerator_id,
+                                        int64_t display_id,
+                                        const ui::Event& event,
+                                        AcceleratorPhase phase) {
+  const bool needs_ack = phase == AcceleratorPhase::kPre;
+  AsyncEventDispatcher::AcceleratorCallback ack_callback;
+  if (needs_ack) {
+    ScheduleInputEventTimeout(accelerator_dispatcher_, display_id, event,
+                              EventDispatchPhase::PRE_TARGET_ACCELERATOR);
+    ack_callback = base::BindOnce(
+        &EventDispatcherImpl::OnAcceleratorDone,
+        in_flight_event_dispatch_details_->weak_factory_.GetWeakPtr());
+  }
+  accelerator_dispatcher_->DispatchAccelerator(accelerator_id, event,
+                                               std::move(ack_callback));
+}
+
+}  // namespace ws
+}  // namespace ui
diff --git a/services/ui/ws/event_dispatcher_impl.h b/services/ui/ws/event_dispatcher_impl.h
new file mode 100644
index 0000000..46d00cd
--- /dev/null
+++ b/services/ui/ws/event_dispatcher_impl.h
@@ -0,0 +1,195 @@
+// Copyright 2018 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 SERVICES_UI_WS_EVENT_DISPATCHER_IMPL_H_
+#define SERVICES_UI_WS_EVENT_DISPATCHER_IMPL_H_
+
+#include <stdint.h>
+
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "base/containers/queue.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/timer/timer.h"
+#include "services/ui/ws/event_dispatcher.h"
+#include "services/ui/ws/event_processor_delegate.h"
+
+namespace ui {
+
+class Event;
+
+namespace mojom {
+enum class EventResult;
+}
+
+namespace ws {
+
+class EventDispatcherDelegate;
+class EventProcessor;
+class AsyncEventDispatcher;
+class AsyncEventDispatcherLookup;
+
+struct EventLocation;
+
+// EventDispatcherImpl is the entry point for event related processing done by
+// the Window Service. Events received from the platform are forwarded to
+// ProcessEvent(). ProcessEvent() may queue the event for later processing (if
+// waiting for an event to be dispatched, or waiting on EventProcessor to
+// complete processing). EventDispatcherImpl ultimately calls to EventProcessor
+// for processing. EventDispatcherImpl uses AsyncEventDispatcher for dispatch
+// to clients.
+class EventDispatcherImpl : public EventDispatcher {
+ public:
+  // |accelerator_dispatcher| must outlive this class.
+  EventDispatcherImpl(AsyncEventDispatcherLookup* async_event_dispatcher_lookup,
+                      AsyncEventDispatcher* accelerator_dispatcher,
+                      EventDispatcherDelegate* delegate);
+  ~EventDispatcherImpl() override;
+
+  void Init(EventProcessor* processor);
+
+  // Processes an event. If IsProcessingEvent() is true, this queues up the
+  // event for later processing. This doesn't take ownership of |event|, but it
+  // may modify it.
+  void ProcessEvent(ui::Event* event, const EventLocation& event_location);
+
+  // Returns true if actively processing an event. This includes waiting for an
+  // AsyncEventDispatcher to respond to an event.
+  bool IsProcessingEvent() const;
+
+  // Returns the event this EventDispatcherImpl is waiting on a response for, or
+  // null if not waiting on an AsyncEventDispatcher.
+  const ui::Event* GetInFlightEvent() const;
+
+  // Notifies |closure| once done processing currently queued events. This
+  // notifies |closure| immediately if IsProcessingEvent() returns false.
+  void ScheduleCallbackWhenDoneProcessingEvents(base::OnceClosure closure);
+
+  // Called when an AsyncEventDispatcher is destroyed.
+  // TODO(sky): AsyncEventDispatcher should support observers.
+  void OnWillDestroyAsyncEventDispatcher(AsyncEventDispatcher* target);
+
+ private:
+  friend class EventDispatcherImplTestApi;
+  class ProcessedEventTarget;
+  struct EventTask;
+
+  enum class EventDispatchPhase {
+    // Not actively dispatching.
+    NONE,
+
+    // A PRE_TARGET accelerator has been encountered and we're awaiting the ack.
+    PRE_TARGET_ACCELERATOR,
+
+    // Dispatching to the target, awaiting the ack.
+    TARGET,
+  };
+
+  // Tracks state associated with an event being dispatched to an
+  // AsyncEventDispatcher.
+  struct InFlightEventDispatchDetails {
+    InFlightEventDispatchDetails(EventDispatcherImpl* dispatcher,
+                                 AsyncEventDispatcher* async_event_dispatcher,
+                                 int64_t display_id,
+                                 const Event& event,
+                                 EventDispatchPhase phase);
+    ~InFlightEventDispatchDetails();
+
+    // Timer used to know when the AsyncEventDispatcher has taken too long.
+    base::OneShotTimer timer;
+    AsyncEventDispatcher* async_event_dispatcher;
+    int64_t display_id;
+    std::unique_ptr<Event> event;
+    EventDispatchPhase phase;
+    base::WeakPtr<Accelerator> post_target_accelerator;
+
+    // Used for callbacks associated with the processing (such as |timer|). This
+    // is used rather than a WeakPtrFactory on EventDispatcherImpl itself so
+    // that it's scoped to the life of waiting for the AsyncEventDispatcher to
+    // respond.
+    base::WeakPtrFactory<EventDispatcherImpl> weak_factory_;
+  };
+
+  // Creates an InFlightEventDispatchDetails and schedules a timer that calls
+  // OnDispatchInputEventTimeout() when done. This is used prior to asking
+  // an AsyncEventDispatcher to dispatch an event or accelerator.
+  void ScheduleInputEventTimeout(AsyncEventDispatcher* async_event_dispatcher,
+                                 int64_t display_id,
+                                 const Event& event,
+                                 EventDispatchPhase phase);
+
+  // Processes all pending events until there are no more, or this class is
+  // waiting on on a result from either EventProcessor of AsyncEventDispatcher.
+  void ProcessEventTasks();
+
+  // Actual implementation of DispatchInputEventToWindow(). Schedules a timeout
+  // and calls DispatchEvent() on the appropriate AsyncEventDispatcher.
+  void DispatchInputEventToWindowImpl(ServerWindow* target,
+                                      ClientSpecificId client_id,
+                                      const EventLocation& event_location,
+                                      const ui::Event& event,
+                                      base::WeakPtr<Accelerator> accelerator);
+
+  // The AsyncEventDispatcher has not completed processing in an appropriate
+  // amount of time.
+  void OnDispatchInputEventTimeout();
+
+  // The AsyncEventDispatcher has completed processing the current event.
+  void OnDispatchInputEventDone(mojom::EventResult result);
+
+  // Called when |accelerator_dispatcher_| has completed processing the
+  // accelerator.
+  void OnAcceleratorDone(
+      mojom::EventResult result,
+      const std::unordered_map<std::string, std::vector<uint8_t>>& properties);
+
+  // Schedules an event to be processed later.
+  void QueueEvent(const Event& event,
+                  std::unique_ptr<ProcessedEventTarget> processed_event_target,
+                  const EventLocation& event_location);
+
+  // EventDispatcher:
+  void DispatchInputEventToWindow(ServerWindow* target,
+                                  ClientSpecificId client_id,
+                                  const EventLocation& event_location,
+                                  const Event& event,
+                                  Accelerator* accelerator) override;
+  void OnAccelerator(uint32_t accelerator_id,
+                     int64_t display_id,
+                     const ui::Event& event,
+                     AcceleratorPhase phase) override;
+
+  EventProcessor* event_processor_ = nullptr;
+
+  // Used to map a ClientId to an AsyncEventDispatcher.
+  AsyncEventDispatcherLookup* const async_event_dispatcher_lookup_;
+
+  // Processes accelerators. This AsyncEventDispatcher corresponds to the
+  // AsyncEventDispatcher accelerators originate from, which is typically the
+  // WindowManager.
+  AsyncEventDispatcher* const accelerator_dispatcher_;
+
+  EventDispatcherDelegate* delegate_;
+
+  // Used for any event related tasks that need to be processed. Tasks are added
+  // to the queue anytime work comes in while waiting for an
+  // AsyncEventDispatcher to respond, or waiting for async hit-testing
+  // processing to complete.
+  base::queue<std::unique_ptr<EventTask>> event_tasks_;
+
+  // If non-null we're actively waiting for a response from an
+  // AsyncEventDispatcher.
+  std::unique_ptr<InFlightEventDispatchDetails>
+      in_flight_event_dispatch_details_;
+
+  DISALLOW_COPY_AND_ASSIGN(EventDispatcherImpl);
+};
+
+}  // namespace ws
+}  // namespace ui
+
+#endif  // SERVICES_UI_WS_EVENT_DISPATCHER_IMPL_H_
diff --git a/services/ui/ws/event_dispatcher_impl_test_api.cc b/services/ui/ws/event_dispatcher_impl_test_api.cc
new file mode 100644
index 0000000..8f64e70
--- /dev/null
+++ b/services/ui/ws/event_dispatcher_impl_test_api.cc
@@ -0,0 +1,55 @@
+// Copyright 2018 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 "services/ui/ws/event_dispatcher_impl_test_api.h"
+
+#include "services/ui/ws/event_dispatcher_impl.h"
+#include "services/ui/ws/window_tree.h"
+
+namespace ui {
+namespace ws {
+
+EventDispatcherImplTestApi::EventDispatcherImplTestApi(
+    EventDispatcherImpl* event_dispatcher)
+    : event_dispatcher_(event_dispatcher) {}
+
+EventDispatcherImplTestApi::~EventDispatcherImplTestApi() = default;
+
+void EventDispatcherImplTestApi::DispatchInputEventToWindow(
+    ServerWindow* target,
+    ClientSpecificId client_id,
+    const EventLocation& event_location,
+    const Event& event,
+    Accelerator* accelerator) {
+  event_dispatcher_->DispatchInputEventToWindow(
+      target, client_id, event_location, event, accelerator);
+}
+
+WindowTree* EventDispatcherImplTestApi::GetTreeThatWillAckEvent() {
+  return event_dispatcher_->in_flight_event_dispatch_details_
+             ? static_cast<WindowTree*>(
+                   event_dispatcher_->in_flight_event_dispatch_details_
+                       ->async_event_dispatcher)
+             : nullptr;
+}
+
+bool EventDispatcherImplTestApi::is_event_tasks_empty() {
+  return event_dispatcher_->event_tasks_.empty();
+}
+
+bool EventDispatcherImplTestApi::OnDispatchInputEventDone(
+    mojom::EventResult result) {
+  if (!event_dispatcher_->GetInFlightEvent())
+    return false;
+  event_dispatcher_->OnDispatchInputEventDone(result);
+  return true;
+}
+
+void EventDispatcherImplTestApi::OnDispatchInputEventTimeout() {
+  if (event_dispatcher_->GetInFlightEvent())
+    event_dispatcher_->OnDispatchInputEventTimeout();
+}
+
+}  // namespace ws
+}  // namespace ui
diff --git a/services/ui/ws/event_dispatcher_impl_test_api.h b/services/ui/ws/event_dispatcher_impl_test_api.h
new file mode 100644
index 0000000..bdd0b4fc
--- /dev/null
+++ b/services/ui/ws/event_dispatcher_impl_test_api.h
@@ -0,0 +1,62 @@
+// Copyright 2018 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 SERVICES_UI_WS_EVENT_DISPATCHER_IMPL_TEST_API_H_
+#define SERVICES_UI_WS_EVENT_DISPATCHER_IMPL_TEST_API_H_
+
+#include "base/macros.h"
+#include "services/ui/common/types.h"
+
+namespace ui {
+
+class Event;
+
+namespace mojom {
+enum class EventResult;
+}
+
+namespace ws {
+
+class Accelerator;
+class EventDispatcherImpl;
+class ServerWindow;
+class WindowTree;
+
+struct EventLocation;
+
+// Allows accessing internal functions of EventDispatcherImpl for testing. Most
+// functions call through to a function of the same name on EventDispatcherImpl,
+// see EventDispatcherImpl for details.
+class EventDispatcherImplTestApi {
+ public:
+  explicit EventDispatcherImplTestApi(EventDispatcherImpl* event_dispatcher);
+  ~EventDispatcherImplTestApi();
+
+  void DispatchInputEventToWindow(ServerWindow* target,
+                                  ClientSpecificId client_id,
+                                  const EventLocation& event_location,
+                                  const Event& event,
+                                  Accelerator* accelerator);
+
+  // Convenience for returning
+  // |in_flight_event_dispatch_details_->async_event_dispatcher_| as a
+  // WindowTree.
+  WindowTree* GetTreeThatWillAckEvent();
+
+  bool is_event_tasks_empty();
+
+  bool OnDispatchInputEventDone(mojom::EventResult result);
+
+  void OnDispatchInputEventTimeout();
+
+ private:
+  EventDispatcherImpl* event_dispatcher_;
+
+  DISALLOW_COPY_AND_ASSIGN(EventDispatcherImplTestApi);
+};
+
+}  // namespace ws
+}  // namespace ui
+
+#endif  // SERVICES_UI_WS_EVENT_DISPATCHER_IMPL_TEST_API_H_
diff --git a/services/ui/ws/event_injector.cc b/services/ui/ws/event_injector.cc
new file mode 100644
index 0000000..faad73cc
--- /dev/null
+++ b/services/ui/ws/event_injector.cc
@@ -0,0 +1,88 @@
+// 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 "services/ui/ws/event_injector.h"
+
+#include "services/ui/ws/display.h"
+#include "services/ui/ws/display_manager.h"
+#include "services/ui/ws/platform_display.h"
+#include "services/ui/ws/window_manager_state.h"
+#include "services/ui/ws/window_server.h"
+
+namespace ui {
+namespace ws {
+
+EventInjector::EventInjector(WindowServer* server) : window_server_(server) {}
+
+EventInjector::~EventInjector() {}
+
+void EventInjector::AdjustEventLocationForPixelLayout(Display* display,
+                                                      ui::LocatedEvent* event) {
+  WindowManagerState* window_manager_state =
+      window_server_->GetWindowManagerState();
+  if (!window_manager_state)
+    return;
+
+  // Only need to adjust the location of events when there is capture.
+  PlatformDisplay* platform_display_with_capture =
+      window_manager_state->platform_display_with_capture();
+  if (!platform_display_with_capture ||
+      display->platform_display() == platform_display_with_capture) {
+    return;
+  }
+
+  // The event is from a display other than the display with capture. On device
+  // events originate from the display with capture and are in terms of the
+  // pixel layout (see comments in EventLocation). Convert the location to be
+  // relative to the display with capture in terms of the pixel layout to match
+  // what happens on device.
+  gfx::PointF capture_relative_location = event->location_f();
+  capture_relative_location += display->GetViewportMetrics()
+                                   .bounds_in_pixels.origin()
+                                   .OffsetFromOrigin();
+  capture_relative_location -=
+      platform_display_with_capture->GetViewportMetrics()
+          .bounds_in_pixels.origin()
+          .OffsetFromOrigin();
+  event->set_location_f(capture_relative_location);
+  event->set_root_location_f(capture_relative_location);
+}
+
+void EventInjector::InjectEvent(int64_t display_id,
+                                std::unique_ptr<ui::Event> event,
+                                InjectEventCallback cb) {
+  DisplayManager* manager = window_server_->display_manager();
+  if (!manager) {
+    DVLOG(1) << "No display manager in InjectEvent.";
+    std::move(cb).Run(false);
+    return;
+  }
+
+  Display* display = manager->GetDisplayById(display_id);
+  if (!display) {
+    DVLOG(1) << "Invalid display_id in InjectEvent.";
+    std::move(cb).Run(false);
+    return;
+  }
+
+  if (event->IsLocatedEvent()) {
+    LocatedEvent* located_event = event->AsLocatedEvent();
+    if (located_event->root_location_f() != located_event->location_f()) {
+      DVLOG(1) << "EventInjector::InjectEvent locations must match";
+      std::move(cb).Run(false);
+      return;
+    }
+
+    AdjustEventLocationForPixelLayout(display, located_event);
+
+    // If this is a mouse pointer event, then we have to also update the
+    // location of the cursor on the screen.
+    if (event->IsMousePointerEvent())
+      display->platform_display()->MoveCursorTo(located_event->location());
+  }
+  display->ProcessEvent(event.get(), base::BindOnce(std::move(cb), true));
+}
+
+}  // namespace ws
+}  // namespace ui
diff --git a/services/ui/ws/event_injector.h b/services/ui/ws/event_injector.h
new file mode 100644
index 0000000..f8108db9
--- /dev/null
+++ b/services/ui/ws/event_injector.h
@@ -0,0 +1,41 @@
+// 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 SERVICES_UI_WS_EVENT_INJECTOR_H_
+#define SERVICES_UI_WS_EVENT_INJECTOR_H_
+
+#include "services/ui/public/interfaces/event_injector.mojom.h"
+
+namespace ui {
+namespace ws {
+
+class Display;
+class WindowServer;
+
+// See description in mojom for details on this.
+class EventInjector : public mojom::EventInjector {
+ public:
+  explicit EventInjector(WindowServer* server);
+  ~EventInjector() override;
+
+ private:
+  // Adjusts the location as necessary of |event|. |display| is the display
+  // the event is targetted at.
+  void AdjustEventLocationForPixelLayout(Display* display,
+                                         ui::LocatedEvent* event);
+
+  // mojom::EventInjector:
+  void InjectEvent(int64_t display_id,
+                   std::unique_ptr<ui::Event> event,
+                   InjectEventCallback cb) override;
+
+  WindowServer* window_server_;
+
+  DISALLOW_COPY_AND_ASSIGN(EventInjector);
+};
+
+}  // namespace ws
+}  // namespace ui
+
+#endif  // SERVICES_UI_WS_EVENT_INJECTOR_H_
diff --git a/services/ui/ws/event_processor.h b/services/ui/ws/event_processor.h
index 31df067..4d2c5208 100644
--- a/services/ui/ws/event_processor.h
+++ b/services/ui/ws/event_processor.h
@@ -51,10 +51,14 @@
 class EventProcessorTestApi;
 }
 
-// Processes events sent to the Window Service from the native platform. Updates
-// internal state associated with events (such as mouse, keyboard state,
-// capture, focus...). EventProcessorDelegate handles dispatching to the
-// appropriate client.
+// EventProcessor is responsible for processing events and maintaining event
+// related state: capture, cursor, last mouse location... EventProcessor informs
+// EventProcessorDelegate of interesting state changes and uses an
+// EventDispatcher for the actual dispatch. EventProcessor uses EventTargeter
+// to determine the actual target. EventProcessor handles a single event at a
+// time, and it may asynchronously process the event (EventTargeter may work
+// asynchronously). A single event may result in multiple calls to
+// EventDispatcher::DispatchEvent().
 class EventProcessor : public ServerWindowDrawnTrackerObserver,
                        public DragCursorUpdater,
                        public EventTargeterDelegate {
diff --git a/services/ui/ws/event_processor_delegate.h b/services/ui/ws/event_processor_delegate.h
index 9c916bd..f0408f7 100644
--- a/services/ui/ws/event_processor_delegate.h
+++ b/services/ui/ws/event_processor_delegate.h
@@ -14,6 +14,7 @@
 }
 
 namespace viz {
+class FrameSinkId;
 class HitTestQuery;
 }
 
@@ -25,8 +26,9 @@
 
 class ServerWindow;
 
-// Used by EventProcessor for dispatching of events, as well as to inform the
-// delegate of various state changes.
+// Notified of various state changes to EventProcessor. This is also used to
+// obtain ServerWindows matching certain criteria (such as the ServerWindow for
+// a display).
 class EventProcessorDelegate {
  public:
   virtual void SetFocusedWindowFromEventProcessor(ServerWindow* window) = 0;
diff --git a/services/ui/ws/frame_generator.cc b/services/ui/ws/frame_generator.cc
index f58676e..676d204 100644
--- a/services/ui/ws/frame_generator.cc
+++ b/services/ui/ws/frame_generator.cc
@@ -12,9 +12,9 @@
 #include "components/viz/common/quads/render_pass_draw_quad.h"
 #include "components/viz/common/quads/shared_quad_state.h"
 #include "components/viz/common/quads/surface_draw_quad.h"
+#include "ui/gfx/geometry/size_f.h"
 
 namespace ui {
-
 namespace ws {
 
 FrameGenerator::FrameGenerator() = default;
@@ -36,8 +36,7 @@
   SetNeedsBeginFrame(true);
 }
 
-void FrameGenerator::OnFirstSurfaceActivation(
-    const viz::SurfaceInfo& surface_info) {
+void FrameGenerator::SetEmbeddedSurface(const viz::SurfaceInfo& surface_info) {
   DCHECK(surface_info.is_valid());
 
   // Only handle embedded surfaces changing here. The display root surface
@@ -195,8 +194,29 @@
       window_manager_surface_info_.size_in_pixels());
 
   gfx::Transform quad_to_target_transform;
-  quad_to_target_transform.Translate(bounds_at_origin.x(),
-                                     bounds_at_origin.y());
+
+  if (scale_and_center_) {
+    // Determine the scaling to fit the source within the target.
+    gfx::SizeF source(window_manager_surface_info_.size_in_pixels());
+    const gfx::SizeF target(pixel_size_);
+    const float scale = std::min(target.width() / source.width(),
+                                 target.height() / source.height());
+
+    // Apply the transform to center the source within the output.
+    source.Scale(scale);
+    DCHECK(source.width() <= target.width() ||
+           source.height() <= target.height());
+    if (source.width() < target.width()) {
+      quad_to_target_transform.Translate(
+          (target.width() - source.width()) / 2.0f, 0);
+    } else if (source.height() < target.height()) {
+      quad_to_target_transform.Translate(
+          0, (target.height() - source.height()) / 2.0f);
+    }
+
+    // Apply the scaling after the transform.
+    quad_to_target_transform.Scale(scale, scale);
+  }
 
   viz::SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState();
 
@@ -228,5 +248,4 @@
 }
 
 }  // namespace ws
-
 }  // namespace ui
diff --git a/services/ui/ws/frame_generator.h b/services/ui/ws/frame_generator.h
index 589ac19..5b387e5 100644
--- a/services/ui/ws/frame_generator.h
+++ b/services/ui/ws/frame_generator.h
@@ -34,7 +34,7 @@
   void SetHighContrastMode(bool enabled);
 
   // Updates the WindowManager's SurfaceInfo.
-  void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info);
+  void SetEmbeddedSurface(const viz::SurfaceInfo& surface_info);
 
   // Swaps the |window_manager_surface_info_| with that of |other|.
   void SwapSurfaceWith(FrameGenerator* other);
@@ -44,6 +44,12 @@
   void Bind(
       std::unique_ptr<viz::mojom::CompositorFrameSink> compositor_frame_sink);
 
+  const viz::SurfaceInfo& window_manager_surface_info() const {
+    return window_manager_surface_info_;
+  }
+
+  void set_scale_and_center(bool value) { scale_and_center_ = value; }
+
  private:
   // viz::mojom::CompositorFrameSinkClient implementation:
   void DidReceiveCompositorFrameAck(
@@ -82,11 +88,13 @@
 
   viz::SurfaceInfo window_manager_surface_info_;
 
+  // Whether the window manager surface should be scaled and centered.
+  bool scale_and_center_ = false;
+
   DISALLOW_COPY_AND_ASSIGN(FrameGenerator);
 };
 
 }  // namespace ws
-
 }  // namespace ui
 
 #endif  // SERVICES_UI_WS_FRAME_GENERATOR_H_
diff --git a/services/ui/ws/frame_generator_unittest.cc b/services/ui/ws/frame_generator_unittest.cc
index 32202bcc2..b1d0c69 100644
--- a/services/ui/ws/frame_generator_unittest.cc
+++ b/services/ui/ws/frame_generator_unittest.cc
@@ -145,7 +145,7 @@
   // |frame_generator_|. After InitWithSurfaceInfo finishes, |frame_generator_|
   // has a valid SurfaceInfo and does not request BeginFrames.
   void InitWithSurfaceInfo() {
-    frame_generator_->OnFirstSurfaceActivation(kArbitrarySurfaceInfo);
+    frame_generator_->SetEmbeddedSurface(kArbitrarySurfaceInfo);
 
     // Issue a BeginFrame so that frame_generator_ stops requesting BeginFrames
     // after submitting a CompositorFrame.
diff --git a/services/ui/ws/platform_display.cc b/services/ui/ws/platform_display.cc
index 35f2664..3414a81 100644
--- a/services/ui/ws/platform_display.cc
+++ b/services/ui/ws/platform_display.cc
@@ -5,11 +5,24 @@
 #include "services/ui/ws/platform_display.h"
 
 #include "base/memory/ptr_util.h"
+#include "build/build_config.h"
 #include "services/ui/ws/platform_display_default.h"
 #include "services/ui/ws/platform_display_factory.h"
 #include "services/ui/ws/server_window.h"
 #include "services/ui/ws/threaded_image_cursors.h"
 #include "services/ui/ws/threaded_image_cursors_factory.h"
+#include "ui/platform_window/platform_window.h"
+
+#if defined(OS_WIN)
+#include "ui/platform_window/win/win_window.h"
+#elif defined(USE_X11)
+#include "ui/platform_window/x11/x11_window.h"
+#elif defined(OS_ANDROID)
+#include "ui/platform_window/android/platform_window_android.h"
+#elif defined(USE_OZONE)
+#include "ui/ozone/public/ozone_platform.h"
+#include "ui/platform_window/platform_window_delegate.h"
+#endif
 
 namespace ui {
 namespace ws {
@@ -34,5 +47,27 @@
 #endif
 }
 
+// static
+std::unique_ptr<PlatformWindow> PlatformDisplay::CreatePlatformWindow(
+    PlatformWindowDelegate* delegate,
+    const gfx::Rect& bounds) {
+  DCHECK(!bounds.size().IsEmpty());
+  std::unique_ptr<PlatformWindow> platform_window;
+#if defined(OS_WIN)
+  platform_window = std::make_unique<ui::WinWindow>(delegate, bounds);
+#elif defined(USE_X11)
+  platform_window = std::make_unique<ui::X11Window>(delegate, bounds);
+#elif defined(OS_ANDROID)
+  platform_window = std::make_unique<ui::PlatformWindowAndroid>(delegate);
+  platform_window->SetBounds(bounds);
+#elif defined(USE_OZONE)
+  platform_window =
+      OzonePlatform::GetInstance()->CreatePlatformWindow(delegate, bounds);
+#else
+  NOTREACHED() << "Unsupported platform";
+#endif
+  return platform_window;
+}
+
 }  // namespace ws
 }  // namespace ui
diff --git a/services/ui/ws/platform_display.h b/services/ui/ws/platform_display.h
index 62a2536..b9c1210 100644
--- a/services/ui/ws/platform_display.h
+++ b/services/ui/ws/platform_display.h
@@ -20,6 +20,8 @@
 namespace ui {
 
 enum class CursorSize;
+class PlatformWindow;
+class PlatformWindowDelegate;
 struct TextInputState;
 
 namespace ws {
@@ -82,6 +84,12 @@
     PlatformDisplay::factory_ = factory;
   }
 
+ protected:
+  // Create a platform window with the given delegate and bounds.
+  static std::unique_ptr<PlatformWindow> CreatePlatformWindow(
+      PlatformWindowDelegate* delegate,
+      const gfx::Rect& bounds);
+
  private:
   // Static factory instance (always NULL for non-test).
   static PlatformDisplayFactory* factory_;
diff --git a/services/ui/ws/platform_display_default.cc b/services/ui/ws/platform_display_default.cc
index 00cd7df..bede0fb2 100644
--- a/services/ui/ws/platform_display_default.cc
+++ b/services/ui/ws/platform_display_default.cc
@@ -21,15 +21,8 @@
 #include "ui/platform_window/platform_window.h"
 #include "ui/platform_window/stub/stub_window.h"
 
-#if defined(OS_WIN)
-#include "ui/platform_window/win/win_window.h"
-#elif defined(USE_X11)
-#include "ui/platform_window/x11/x11_window.h"
-#elif defined(OS_ANDROID)
-#include "ui/platform_window/android/platform_window_android.h"
-#elif defined(USE_OZONE)
+#if defined(USE_OZONE)
 #include "ui/events/ozone/chromeos/cursor_controller.h"
-#include "ui/ozone/public/ozone_platform.h"
 #endif
 
 namespace ui {
@@ -73,26 +66,18 @@
   const gfx::Rect& bounds = metrics_.bounds_in_pixels;
   DCHECK(!bounds.size().IsEmpty());
 
-  // Use StubWindow for virtual unified displays, like AshWindowTreeHostUnified.
   if (delegate_->GetDisplay().id() == display::kUnifiedDisplayId) {
+    // Virtual unified displays use a StubWindow; see AshWindowTreeHostUnified.
     platform_window_ = std::make_unique<ui::StubWindow>(this, true, bounds);
+  } else if (delegate_->GetDisplay().id() == display::kInvalidDisplayId) {
+    // Unit tests may use kInvalidDisplayId to request a StubWindow for testing.
+    platform_window_ = std::make_unique<ui::StubWindow>(this, false);
   } else {
-#if defined(OS_WIN)
-    platform_window_ = std::make_unique<ui::WinWindow>(this, bounds);
-#elif defined(USE_X11)
-    platform_window_ = std::make_unique<ui::X11Window>(this, bounds);
-#elif defined(OS_ANDROID)
-    platform_window_ = std::make_unique<ui::PlatformWindowAndroid>(this);
-    platform_window_->SetBounds(bounds);
-#elif defined(USE_OZONE)
-    platform_window_ =
-        delegate_->GetOzonePlatform()->CreatePlatformWindow(this, bounds);
-#else
-    NOTREACHED() << "Unsupported platform";
-#endif
+    platform_window_ = CreatePlatformWindow(this, metrics_.bounds_in_pixels);
   }
 
   platform_window_->Show();
+
   if (image_cursors_) {
     image_cursors_->SetDisplay(delegate_->GetDisplay(),
                                metrics_.device_scale_factor);
diff --git a/services/ui/ws/platform_display_default_unittest.cc b/services/ui/ws/platform_display_default_unittest.cc
index e34b8d0..04bac1c 100644
--- a/services/ui/ws/platform_display_default_unittest.cc
+++ b/services/ui/ws/platform_display_default_unittest.cc
@@ -14,6 +14,7 @@
 #include "ui/events/event_sink.h"
 #include "ui/events/system_input_injector.h"
 #include "ui/gfx/geometry/point.h"
+#include "ui/ozone/public/cursor_factory_ozone.h"
 #include "ui/ozone/public/ozone_platform.h"
 #include "ui/platform_window/platform_window.h"
 #include "ui/platform_window/stub/stub_window.h"
@@ -47,70 +48,27 @@
 // A PlatformDisplayDelegate to connect the PlatformDisplay to a TestEventSink.
 class TestPlatformDisplayDelegate : public PlatformDisplayDelegate {
  public:
-  TestPlatformDisplayDelegate(TestEventSink* sink, OzonePlatform* platform)
-      : event_sink_(sink), ozone_platform_(platform) {}
+  explicit TestPlatformDisplayDelegate(TestEventSink* sink) : sink_(sink) {}
   ~TestPlatformDisplayDelegate() override = default;
 
   // PlatformDisplayDelegate:
   const display::Display& GetDisplay() override { return stub_display_; }
   ServerWindow* GetRootWindow() override { return nullptr; }
-  EventSink* GetEventSink() override { return event_sink_; }
+  EventSink* GetEventSink() override { return sink_; }
   void OnAcceleratedWidgetAvailable() override {}
   void OnNativeCaptureLost() override {}
-  OzonePlatform* GetOzonePlatform() override { return ozone_platform_; }
   bool IsHostingViz() const override { return true; }
 
  private:
-  TestEventSink* event_sink_;
-  OzonePlatform* ozone_platform_;
+  TestEventSink* sink_;
   display::Display stub_display_;
 
   DISALLOW_COPY_AND_ASSIGN(TestPlatformDisplayDelegate);
 };
 
-// An OzonePlatform that creates StubWindows.
-class TestOzonePlatform : public OzonePlatform {
- public:
-  TestOzonePlatform() = default;
-  ~TestOzonePlatform() override = default;
-
-  // OzonePlatform:
-  ui::SurfaceFactoryOzone* GetSurfaceFactoryOzone() override { return nullptr; }
-  ui::OverlayManagerOzone* GetOverlayManager() override { return nullptr; }
-  ui::CursorFactoryOzone* GetCursorFactoryOzone() override { return nullptr; }
-  ui::InputController* GetInputController() override { return nullptr; }
-  ui::GpuPlatformSupportHost* GetGpuPlatformSupportHost() override {
-    return nullptr;
-  }
-  std::unique_ptr<SystemInputInjector> CreateSystemInputInjector() override {
-    return nullptr;
-  }
-  std::unique_ptr<PlatformWindow> CreatePlatformWindow(
-      PlatformWindowDelegate* delegate,
-      const gfx::Rect& bounds) override {
-    return std::make_unique<StubWindow>(
-        delegate, false /* use_default_accelerated_widget */);
-  }
-  std::unique_ptr<display::NativeDisplayDelegate> CreateNativeDisplayDelegate()
-      override {
-    return nullptr;
-  }
-  void InitializeUI(const InitParams& params) override {}
-  void InitializeGPU(const InitParams& params) override {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(TestOzonePlatform);
-};
-
-// Test fails in part because services_unittests appears to have its own ozone
-// platform that it initializes. For some reason, this only started failing
-// locally and on the trybots on 06/13/2017, while passing when run on the CQ
-// and the builders. crbug.com/732987
-TEST(PlatformDisplayDefaultTest, DISABLED_EventDispatch) {
+TEST(PlatformDisplayDefaultTest, EventDispatch) {
   // ThreadTaskRunnerHandle needed required by ThreadedImageCursors.
   base::MessageLoop loop;
-  // Setup ozone so the display can be initialized.
-  TestOzonePlatform platform;
 
   // Create the display.
   display::ViewportMetrics metrics;
@@ -120,6 +78,7 @@
   scoped_refptr<base::SingleThreadTaskRunner> task_runner =
       base::ThreadTaskRunnerHandle::Get();
   ImageCursorsSet image_cursors_set;
+  CursorFactoryOzone cursor_factory_ozone;
   std::unique_ptr<ThreadedImageCursors> threaded_image_cursors =
       std::make_unique<ThreadedImageCursors>(task_runner,
                                              image_cursors_set.GetWeakPtr());
@@ -128,7 +87,9 @@
 
   // Initialize the display with a test EventSink so we can sense events.
   TestEventSink event_sink;
-  TestPlatformDisplayDelegate delegate(&event_sink, &platform);
+  TestPlatformDisplayDelegate delegate(&event_sink);
+  // kInvalidDisplayId causes the display to be initialized with a StubWindow.
+  EXPECT_EQ(display::kInvalidDisplayId, delegate.GetDisplay().id());
   display.Init(&delegate);
 
   // Event dispatch is handled at the PlatformWindowDelegate level.
diff --git a/services/ui/ws/platform_display_delegate.h b/services/ui/ws/platform_display_delegate.h
index 2e64d00..41bbb95 100644
--- a/services/ui/ws/platform_display_delegate.h
+++ b/services/ui/ws/platform_display_delegate.h
@@ -12,7 +12,6 @@
 namespace ui {
 
 class EventSink;
-class OzonePlatform;
 
 namespace ws {
 
@@ -38,10 +37,6 @@
   // Called when the Display loses capture.
   virtual void OnNativeCaptureLost() = 0;
 
-  // Allows the OzonePlatform to be overridden, e.g. for tests. Returns null
-  // for non-Ozone platforms.
-  virtual OzonePlatform* GetOzonePlatform() = 0;
-
   virtual bool IsHostingViz() const = 0;
 
  protected:
diff --git a/services/ui/ws/platform_display_mirror.cc b/services/ui/ws/platform_display_mirror.cc
new file mode 100644
index 0000000..914f1ff
--- /dev/null
+++ b/services/ui/ws/platform_display_mirror.cc
@@ -0,0 +1,167 @@
+// 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 "services/ui/ws/platform_display_mirror.h"
+
+#include "components/viz/common/surfaces/surface_id.h"
+#include "components/viz/common/surfaces/surface_info.h"
+#include "components/viz/host/renderer_settings_creation.h"
+#include "services/ui/ws/display.h"
+#include "services/ui/ws/display_manager.h"
+#include "services/ui/ws/frame_generator.h"
+#include "services/ui/ws/window_server.h"
+#include "ui/platform_window/platform_window.h"
+
+namespace ui {
+namespace ws {
+
+PlatformDisplayMirror::PlatformDisplayMirror(
+    const display::Display& display,
+    const display::ViewportMetrics& metrics,
+    WindowServer* window_server,
+    Display* display_to_mirror)
+    : display_(display),
+      metrics_(metrics),
+      window_server_(window_server),
+      display_to_mirror_(display_to_mirror) {
+  DCHECK(display_to_mirror_);
+  frame_sink_id_ = window_server->display_manager()->GetAndAdvanceNextRootId();
+
+  // Create a new platform window to display the mirror destination content.
+  platform_window_ = CreatePlatformWindow(this, metrics_.bounds_in_pixels);
+  platform_window_->Show();
+}
+
+PlatformDisplayMirror::~PlatformDisplayMirror() = default;
+
+void PlatformDisplayMirror::Init(PlatformDisplayDelegate* delegate) {}
+
+void PlatformDisplayMirror::SetViewportSize(const gfx::Size& size) {}
+
+void PlatformDisplayMirror::SetTitle(const base::string16& title) {}
+
+void PlatformDisplayMirror::SetCapture() {}
+
+void PlatformDisplayMirror::ReleaseCapture() {}
+
+void PlatformDisplayMirror::SetCursor(const ui::CursorData& cursor) {}
+
+void PlatformDisplayMirror::MoveCursorTo(
+    const gfx::Point& window_pixel_location) {}
+
+void PlatformDisplayMirror::SetCursorSize(const ui::CursorSize& cursor_size) {}
+
+void PlatformDisplayMirror::ConfineCursorToBounds(
+    const gfx::Rect& pixel_bounds) {}
+
+void PlatformDisplayMirror::UpdateTextInputState(
+    const ui::TextInputState& state) {}
+
+void PlatformDisplayMirror::SetImeVisibility(bool visible) {}
+
+void PlatformDisplayMirror::UpdateViewportMetrics(
+    const display::ViewportMetrics& metrics) {
+  metrics_ = metrics;
+}
+
+const display::ViewportMetrics& PlatformDisplayMirror::GetViewportMetrics() {
+  return metrics_;
+}
+
+gfx::AcceleratedWidget PlatformDisplayMirror::GetAcceleratedWidget() const {
+  return widget_;
+}
+
+FrameGenerator* PlatformDisplayMirror::GetFrameGenerator() {
+  return frame_generator_.get();
+}
+
+EventSink* PlatformDisplayMirror::GetEventSink() {
+  return nullptr;
+}
+
+void PlatformDisplayMirror::SetCursorConfig(display::Display::Rotation rotation,
+                                            float scale) {}
+
+void PlatformDisplayMirror::OnBoundsChanged(const gfx::Rect& new_bounds) {}
+
+void PlatformDisplayMirror::OnDamageRect(const gfx::Rect& damaged_region) {}
+
+void PlatformDisplayMirror::DispatchEvent(ui::Event* event) {}
+
+void PlatformDisplayMirror::OnCloseRequest() {}
+
+void PlatformDisplayMirror::OnClosed() {}
+
+void PlatformDisplayMirror::OnWindowStateChanged(
+    ui::PlatformWindowState new_state) {}
+
+void PlatformDisplayMirror::OnLostCapture() {}
+
+void PlatformDisplayMirror::OnAcceleratedWidgetAvailable(
+    gfx::AcceleratedWidget widget,
+    float device_scale_factor) {
+  DCHECK_EQ(gfx::kNullAcceleratedWidget, widget_);
+  widget_ = widget;
+
+  // Create a CompositorFrameSink for this display, using the widget's surface.
+  viz::mojom::CompositorFrameSinkAssociatedPtr compositor_frame_sink;
+  viz::mojom::CompositorFrameSinkClientPtr compositor_frame_sink_client;
+  viz::mojom::CompositorFrameSinkClientRequest
+      compositor_frame_sink_client_request =
+          mojo::MakeRequest(&compositor_frame_sink_client);
+  window_server_->GetVizHostProxy()->RegisterFrameSinkId(frame_sink_id_, this);
+
+  // TODO(ccameron): Bind |display_client| to support macOS? (maybe not needed)
+  viz::mojom::DisplayPrivateAssociatedPtr display_private;
+  viz::mojom::DisplayClientPtr display_client;
+  viz::mojom::DisplayClientRequest display_client_request =
+      mojo::MakeRequest(&display_client);
+
+  auto params = viz::mojom::RootCompositorFrameSinkParams::New();
+  params->frame_sink_id = frame_sink_id_;
+  params->widget = widget_;
+  params->renderer_settings = viz::CreateRendererSettings();
+  params->compositor_frame_sink = mojo::MakeRequest(&compositor_frame_sink);
+  params->compositor_frame_sink_client =
+      compositor_frame_sink_client.PassInterface();
+  params->display_private = mojo::MakeRequest(&display_private);
+  params->display_client = display_client.PassInterface();
+  window_server_->GetVizHostProxy()->CreateRootCompositorFrameSink(
+      std::move(params));
+
+  // Make a FrameGenerator that references |display_to_mirror_|'s surface id.
+  display_private->SetDisplayVisible(true);
+  frame_generator_ = std::make_unique<FrameGenerator>();
+  auto frame_sink_client_binding =
+      std::make_unique<CompositorFrameSinkClientBinding>(
+          frame_generator_.get(),
+          std::move(compositor_frame_sink_client_request),
+          std::move(compositor_frame_sink), std::move(display_private));
+  frame_generator_->Bind(std::move(frame_sink_client_binding));
+
+  frame_generator_->OnWindowSizeChanged(metrics_.bounds_in_pixels.size());
+  frame_generator_->SetDeviceScaleFactor(metrics_.device_scale_factor);
+  frame_generator_->set_scale_and_center(true);
+
+  // Pass the surface info for the mirror source display to the frame generator,
+  // the id is not available if the source display init is not yet complete.
+  const viz::SurfaceInfo& info = display_to_mirror_->platform_display()
+                                     ->GetFrameGenerator()
+                                     ->window_manager_surface_info();
+  if (info.id().is_valid())
+    frame_generator_->SetEmbeddedSurface(info);
+}
+
+void PlatformDisplayMirror::OnAcceleratedWidgetDestroyed() {}
+
+void PlatformDisplayMirror::OnActivationChanged(bool active) {}
+
+void PlatformDisplayMirror::OnFirstSurfaceActivation(
+    const viz::SurfaceInfo& surface_info) {}
+
+void PlatformDisplayMirror::OnFrameTokenChanged(uint32_t frame_token) {}
+
+}  // namespace ws
+}  // namespace ui
diff --git a/services/ui/ws/platform_display_mirror.h b/services/ui/ws/platform_display_mirror.h
new file mode 100644
index 0000000..0e7d3c7
--- /dev/null
+++ b/services/ui/ws/platform_display_mirror.h
@@ -0,0 +1,107 @@
+// 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 SERVICES_UI_WS_PLATFORM_DISPLAY_MIRROR_H_
+#define SERVICES_UI_WS_PLATFORM_DISPLAY_MIRROR_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "components/viz/common/surfaces/frame_sink_id.h"
+#include "components/viz/host/host_frame_sink_client.h"
+#include "services/ui/ws/platform_display.h"
+#include "ui/display/display.h"
+#include "ui/platform_window/platform_window.h"
+#include "ui/platform_window/platform_window_delegate.h"
+
+namespace ui {
+namespace ws {
+
+class Display;
+class WindowServer;
+
+// PlatformDisplay implementation that mirrors another display.
+class PlatformDisplayMirror : public PlatformDisplay,
+                              public ui::PlatformWindowDelegate,
+                              public viz::HostFrameSinkClient {
+ public:
+  PlatformDisplayMirror(const display::Display& display,
+                        const display::ViewportMetrics& metrics,
+                        WindowServer* window_server,
+                        Display* display_to_mirror);
+  ~PlatformDisplayMirror() override;
+
+  const display::Display& display() const { return display_; }
+  void set_display(const display::Display& display) { display_ = display; }
+
+  Display* display_to_mirror() const { return display_to_mirror_; }
+
+  // PlatformDisplay:
+  void Init(PlatformDisplayDelegate* delegate) override;
+  void SetViewportSize(const gfx::Size& size) override;
+  void SetTitle(const base::string16& title) override;
+  void SetCapture() override;
+  void ReleaseCapture() override;
+  void SetCursor(const ui::CursorData& cursor) override;
+  void MoveCursorTo(const gfx::Point& window_pixel_location) override;
+  void SetCursorSize(const ui::CursorSize& cursor_size) override;
+  void ConfineCursorToBounds(const gfx::Rect& pixel_bounds) override;
+  void UpdateTextInputState(const ui::TextInputState& state) override;
+  void SetImeVisibility(bool visible) override;
+  void UpdateViewportMetrics(const display::ViewportMetrics& metrics) override;
+  const display::ViewportMetrics& GetViewportMetrics() override;
+  gfx::AcceleratedWidget GetAcceleratedWidget() const override;
+  FrameGenerator* GetFrameGenerator() override;
+  EventSink* GetEventSink() override;
+  void SetCursorConfig(display::Display::Rotation rotation,
+                       float scale) override;
+
+  // ui::PlatformWindowDelegate:
+  void OnBoundsChanged(const gfx::Rect& new_bounds) override;
+  void OnDamageRect(const gfx::Rect& damaged_region) override;
+  void DispatchEvent(ui::Event* event) override;
+  void OnCloseRequest() override;
+  void OnClosed() override;
+  void OnWindowStateChanged(ui::PlatformWindowState new_state) override;
+  void OnLostCapture() override;
+  void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget,
+                                    float device_scale_factor) override;
+  void OnAcceleratedWidgetDestroyed() override;
+  void OnActivationChanged(bool active) override;
+
+  // viz::HostFrameSinkClient:
+  void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override;
+  void OnFrameTokenChanged(uint32_t frame_token) override;
+
+ private:
+  // The basic info and metrics about this mirroring destination display.
+  display::Display display_;
+  display::ViewportMetrics metrics_;
+
+  // The WindowServer that owns this object, via DisplayManager.
+  WindowServer* window_server_;
+
+  // The source ws::Display that this display mirrors.
+  Display* display_to_mirror_;
+
+  // The frame sink id assigned to this display.
+  viz::FrameSinkId frame_sink_id_;
+
+  // The window in the underlying platform windowing system (i.e. Wayland/X11).
+  std::unique_ptr<ui::PlatformWindow> platform_window_;
+
+  // The accelerated widget that provides a surface to paint pixels.
+  gfx::AcceleratedWidget widget_ = gfx::kNullAcceleratedWidget;
+
+  // The generator that submits frames copied from the source display's surface
+  // to this destination display's frame sink.
+  std::unique_ptr<FrameGenerator> frame_generator_;
+
+  DISALLOW_COPY_AND_ASSIGN(PlatformDisplayMirror);
+};
+
+}  // namespace ws
+}  // namespace ui
+
+#endif  // SERVICES_UI_WS_PLATFORM_DISPLAY_MIRROR_H_
diff --git a/services/ui/ws/remote_event_dispatcher.cc b/services/ui/ws/remote_event_dispatcher.cc
deleted file mode 100644
index a951ecf..0000000
--- a/services/ui/ws/remote_event_dispatcher.cc
+++ /dev/null
@@ -1,90 +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 "services/ui/ws/remote_event_dispatcher.h"
-
-#include "services/ui/ws/display.h"
-#include "services/ui/ws/display_manager.h"
-#include "services/ui/ws/platform_display.h"
-#include "services/ui/ws/window_manager_state.h"
-#include "services/ui/ws/window_server.h"
-
-namespace ui {
-namespace ws {
-
-RemoteEventDispatcherImpl::RemoteEventDispatcherImpl(WindowServer* server)
-    : window_server_(server) {}
-
-RemoteEventDispatcherImpl::~RemoteEventDispatcherImpl() {}
-
-void RemoteEventDispatcherImpl::AdjustEventLocationForPixelLayout(
-    Display* display,
-    ui::LocatedEvent* event) {
-  WindowManagerState* window_manager_state =
-      window_server_->GetWindowManagerState();
-  if (!window_manager_state)
-    return;
-
-  // Only need to adjust the location of events when there is capture.
-  PlatformDisplay* platform_display_with_capture =
-      window_manager_state->platform_display_with_capture();
-  if (!platform_display_with_capture ||
-      display->platform_display() == platform_display_with_capture) {
-    return;
-  }
-
-  // The event is from a display other than the display with capture. On device
-  // events originate from the display with capture and are in terms of the
-  // pixel layout (see comments in EventLocation). Convert the location to be
-  // relative to the display with capture in terms of the pixel layout to match
-  // what happens on device.
-  gfx::PointF capture_relative_location = event->location_f();
-  capture_relative_location += display->GetViewportMetrics()
-                                   .bounds_in_pixels.origin()
-                                   .OffsetFromOrigin();
-  capture_relative_location -=
-      platform_display_with_capture->GetViewportMetrics()
-          .bounds_in_pixels.origin()
-          .OffsetFromOrigin();
-  event->set_location_f(capture_relative_location);
-  event->set_root_location_f(capture_relative_location);
-}
-
-void RemoteEventDispatcherImpl::DispatchEvent(int64_t display_id,
-                                              std::unique_ptr<ui::Event> event,
-                                              DispatchEventCallback cb) {
-  DisplayManager* manager = window_server_->display_manager();
-  if (!manager) {
-    DVLOG(1) << "No display manager in DispatchEvent.";
-    std::move(cb).Run(false);
-    return;
-  }
-
-  Display* display = manager->GetDisplayById(display_id);
-  if (!display) {
-    DVLOG(1) << "Invalid display_id in DispatchEvent.";
-    std::move(cb).Run(false);
-    return;
-  }
-
-  if (event->IsLocatedEvent()) {
-    LocatedEvent* located_event = event->AsLocatedEvent();
-    if (located_event->root_location_f() != located_event->location_f()) {
-      DVLOG(1) << "RemoteEventDispatcher::DispatchEvent locations must match";
-      std::move(cb).Run(false);
-      return;
-    }
-
-    AdjustEventLocationForPixelLayout(display, located_event);
-
-    // If this is a mouse pointer event, then we have to also update the
-    // location of the cursor on the screen.
-    if (event->IsMousePointerEvent())
-      display->platform_display()->MoveCursorTo(located_event->location());
-  }
-  display->ProcessEvent(event.get(), base::BindOnce(std::move(cb), true));
-}
-
-}  // namespace ws
-}  // namespace ui
diff --git a/services/ui/ws/remote_event_dispatcher.h b/services/ui/ws/remote_event_dispatcher.h
deleted file mode 100644
index adf408f..0000000
--- a/services/ui/ws/remote_event_dispatcher.h
+++ /dev/null
@@ -1,40 +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 SERVICES_UI_WS_REMOTE_EVENT_DISPATCHER_H_
-#define SERVICES_UI_WS_REMOTE_EVENT_DISPATCHER_H_
-
-#include "services/ui/public/interfaces/remote_event_dispatcher.mojom.h"
-
-namespace ui {
-namespace ws {
-
-class Display;
-class WindowServer;
-
-class RemoteEventDispatcherImpl : public mojom::RemoteEventDispatcher {
- public:
-  explicit RemoteEventDispatcherImpl(WindowServer* server);
-  ~RemoteEventDispatcherImpl() override;
-
- private:
-  // Adjusts the location as necessary of |event|. |display| is the display
-  // the event is targetted at.
-  void AdjustEventLocationForPixelLayout(Display* display,
-                                         ui::LocatedEvent* event);
-
-  // mojom::RemoteEventDispatcher:
-  void DispatchEvent(int64_t display_id,
-                     std::unique_ptr<ui::Event> event,
-                     DispatchEventCallback cb) override;
-
-  WindowServer* window_server_;
-
-  DISALLOW_COPY_AND_ASSIGN(RemoteEventDispatcherImpl);
-};
-
-}  // namespace ws
-}  // namespace ui
-
-#endif  // SERVICES_UI_WS_REMOTE_EVENT_DISPATCHER_H_
diff --git a/services/ui/ws/test_utils.h b/services/ui/ws/test_utils.h
index b25d3136..4caef109 100644
--- a/services/ui/ws/test_utils.h
+++ b/services/ui/ws/test_utils.h
@@ -24,6 +24,7 @@
 #include "services/ui/ws/display.h"
 #include "services/ui/ws/display_binding.h"
 #include "services/ui/ws/drag_controller.h"
+#include "services/ui/ws/event_dispatcher_impl_test_api.h"
 #include "services/ui/ws/event_processor.h"
 #include "services/ui/ws/event_targeter.h"
 #include "services/ui/ws/gpu_host.h"
@@ -232,15 +233,6 @@
   explicit WindowManagerStateTestApi(WindowManagerState* wms) : wms_(wms) {}
   ~WindowManagerStateTestApi() {}
 
-  void DispatchInputEventToWindow(ServerWindow* target,
-                                  ClientSpecificId client_id,
-                                  const EventLocation& event_location,
-                                  const ui::Event& event,
-                                  Accelerator* accelerator) {
-    wms_->DispatchInputEventToWindow(target, client_id, event_location, event,
-                                     accelerator);
-  }
-
   ClientSpecificId GetEventTargetClientId(ServerWindow* window,
                                           bool in_nonclient_area) {
     return wms_->GetEventTargetClientId(window, in_nonclient_area);
@@ -250,33 +242,42 @@
     wms_->ProcessEvent(event, display_id);
   }
 
-  void OnEventAckTimeout(ClientSpecificId client_id) {
-    wms_->OnEventAckTimeout(client_id);
-  }
-
   ClientSpecificId GetEventTargetClientId(const ServerWindow* window,
                                           bool in_nonclient_area) {
     return wms_->GetEventTargetClientId(window, in_nonclient_area);
   }
 
-  WindowTree* tree_awaiting_input_ack() {
-    return wms_->in_flight_event_dispatch_details_
-               ? wms_->in_flight_event_dispatch_details_->tree
-               : nullptr;
+  void OnEventAckTimeout(ClientSpecificId client_id) {
+    EventDispatcherImplTestApi(&wms_->event_dispatcher_)
+        .OnDispatchInputEventTimeout();
   }
 
-  bool is_event_tasks_empty() const { return wms_->event_tasks_.empty(); }
-
   const std::vector<std::unique_ptr<WindowManagerDisplayRoot>>&
   window_manager_display_roots() const {
     return wms_->window_manager_display_roots_;
   }
 
+  // TODO(sky): convert calling code to use EventDispatcherImplTestApi directly.
+  void DispatchInputEventToWindow(ServerWindow* target,
+                                  ClientSpecificId client_id,
+                                  const EventLocation& event_location,
+                                  const ui::Event& event,
+                                  Accelerator* accelerator) {
+    EventDispatcherImplTestApi(&wms_->event_dispatcher_)
+        .DispatchInputEventToWindow(target, client_id, event_location, event,
+                                    accelerator);
+  }
+  WindowTree* tree_awaiting_input_ack() {
+    return EventDispatcherImplTestApi(&wms_->event_dispatcher_)
+        .GetTreeThatWillAckEvent();
+  }
+  bool is_event_tasks_empty() const {
+    return EventDispatcherImplTestApi(&wms_->event_dispatcher_)
+        .is_event_tasks_empty();
+  }
   bool AckInFlightEvent(mojom::EventResult result) {
-    if (!wms_->in_flight_event_dispatch_details_)
-      return false;
-    wms_->OnEventAck(wms_->in_flight_event_dispatch_details_->tree, result);
-    return true;
+    return EventDispatcherImplTestApi(&wms_->event_dispatcher_)
+        .OnDispatchInputEventDone(result);
   }
 
  private:
diff --git a/services/ui/ws/window_manager_state.cc b/services/ui/ws/window_manager_state.cc
index 252e3af..4b4a2361 100644
--- a/services/ui/ws/window_manager_state.cc
+++ b/services/ui/ws/window_manager_state.cc
@@ -39,37 +39,6 @@
 const int kAcceleratorEventFlags =
     EF_SHIFT_DOWN | EF_CONTROL_DOWN | EF_ALT_DOWN | EF_COMMAND_DOWN;
 
-base::TimeDelta GetDefaultAckTimerDelay() {
-#if defined(NDEBUG)
-  return base::TimeDelta::FromMilliseconds(100);
-#else
-  return base::TimeDelta::FromMilliseconds(1000);
-#endif
-}
-
-bool CanEventsBeCoalesced(const ui::Event& one, const ui::Event& two) {
-  if (one.type() != two.type() || one.flags() != two.flags())
-    return false;
-
-  // TODO(sad): wheel events can also be merged.
-  if (one.type() != ui::ET_POINTER_MOVED)
-    return false;
-
-  return one.AsPointerEvent()->pointer_details().id ==
-         two.AsPointerEvent()->pointer_details().id;
-}
-
-std::unique_ptr<ui::Event> CoalesceEvents(std::unique_ptr<ui::Event> first,
-                                          std::unique_ptr<ui::Event> second) {
-  DCHECK(first->type() == ui::ET_POINTER_MOVED)
-      << " Non-move events cannot be merged yet.";
-  // For mouse moves, the new event just replaces the old event, but we need to
-  // use the latency from the old event.
-  second->set_latency(*first->latency());
-  second->latency()->set_coalesced();
-  return second;
-}
-
 const ServerWindow* GetEmbedRoot(const ServerWindow* window) {
   DCHECK(window);
   const ServerWindow* embed_root = window->parent();
@@ -100,59 +69,6 @@
 
 }  // namespace
 
-WindowManagerState::InFlightEventDispatchDetails::InFlightEventDispatchDetails(
-    WindowManagerState* window_manager_state,
-    WindowTree* tree,
-    int64_t display_id,
-    const Event& event,
-    EventDispatchPhase phase)
-    : tree(tree),
-      display_id(display_id),
-      event(Event::Clone(event)),
-      phase(phase),
-      weak_factory(window_manager_state) {}
-
-WindowManagerState::InFlightEventDispatchDetails::
-    ~InFlightEventDispatchDetails() {}
-
-class WindowManagerState::ProcessedEventTarget {
- public:
-  ProcessedEventTarget(WindowServer* window_server,
-                       ServerWindow* window,
-                       ClientSpecificId client_id,
-                       Accelerator* accelerator)
-      : window_server_(window_server), client_id_(client_id) {
-    DCHECK(window_server_);
-    tracker_.Add(window);
-    if (accelerator)
-      accelerator_ = accelerator->GetWeakPtr();
-  }
-
-  ~ProcessedEventTarget() {}
-
-  // Return true if the event is still valid. The event becomes invalid if
-  // the window is destroyed while waiting to dispatch.
-  bool IsValid() {
-    return window() && window_server_->GetTreeWithId(client_id_);
-  }
-
-  ServerWindow* window() {
-    return tracker_.windows().empty() ? nullptr : tracker_.windows().front();
-  }
-
-  ClientSpecificId client_id() const { return client_id_; }
-
-  base::WeakPtr<Accelerator> accelerator() { return accelerator_; }
-
- private:
-  WindowServer* window_server_;
-  ServerWindowTracker tracker_;
-  const ClientSpecificId client_id_;
-  base::WeakPtr<Accelerator> accelerator_;
-
-  DISALLOW_COPY_AND_ASSIGN(ProcessedEventTarget);
-};
-
 bool WindowManagerState::DebugAccelerator::Matches(
     const ui::KeyEvent& event) const {
   return key_code == event.key_code() &&
@@ -160,52 +76,12 @@
          !event.is_char();
 }
 
-// Contains data used for event processing that needs to happen. See enum for
-// details.
-struct WindowManagerState::EventTask {
-  enum class Type {
-    // ProcessEvent() was called while waiting on a client or EventProcessor
-    // to complete processing. |event| is non-null and |processed_target| is
-    // null.
-    kEvent,
-
-    // In certain situations EventProcessor::ProcessEvent() generates more than
-    // one event. When that happens, |kProcessedEvent| is used for all events
-    // after the first. For example, a move may result in an exit for one
-    // Window and and an enter for another Window. The event generated for the
-    // enter results in an EventTask of type |kProcessedEvent|. In this case
-    // both |event| and |processed_target| are valid.
-    kProcessedEvent,
-
-    // ScheduleCallbackWhenDoneProcessingEvents() is called while waiting on
-    // a client or EventProcessor. |event| and |processed_target| are null.
-    kClosure
-  };
-
-  EventTask() = default;
-  ~EventTask() = default;
-
-  Type type() const {
-    if (done_closure)
-      return Type::kClosure;
-    if (processed_target) {
-      DCHECK(event);
-      return Type::kProcessedEvent;
-    }
-    DCHECK(event);
-    return Type::kEvent;
-  }
-
-  std::unique_ptr<Event> event;
-  std::unique_ptr<ProcessedEventTarget> processed_target;
-  EventLocation event_location;
-  base::OnceClosure done_closure;
-};
-
 WindowManagerState::WindowManagerState(WindowTree* window_tree)
     : window_tree_(window_tree),
-      event_processor_(this, this),
+      event_dispatcher_(window_server(), window_tree_, this),
+      event_processor_(this, &event_dispatcher_),
       cursor_state_(window_tree_->display_manager(), this) {
+  event_dispatcher_.Init(&event_processor_);
   frame_decoration_values_ = mojom::FrameDecorationValues::New();
   frame_decoration_values_->max_title_bar_button_width = 0u;
 
@@ -284,12 +160,10 @@
     DragTargetConnection* source_connection,
     const std::unordered_map<std::string, std::vector<uint8_t>>& drag_data,
     uint32_t drag_operation) {
-  int32_t drag_pointer = MouseEvent::kMousePointerId;
-  if (in_flight_event_dispatch_details_ &&
-      in_flight_event_dispatch_details_->event->IsPointerEvent()) {
-    drag_pointer = in_flight_event_dispatch_details_->event->AsPointerEvent()
-                       ->pointer_details()
-                       .id;
+  PointerId drag_pointer = MouseEvent::kMousePointerId;
+  const ui::Event* in_flight_event = event_dispatcher_.GetInFlightEvent();
+  if (in_flight_event && in_flight_event->IsPointerEvent()) {
+    drag_pointer = in_flight_event->AsPointerEvent()->pointer_details().id;
   } else {
     NOTIMPLEMENTED() << "Set drag drop set up during something other than a "
                      << "pointer event; rejecting drag.";
@@ -338,16 +212,7 @@
 void WindowManagerState::OnWillDestroyTree(WindowTree* tree) {
   event_processor_.OnWillDestroyDragTargetConnection(tree);
 
-  if (!in_flight_event_dispatch_details_ ||
-      in_flight_event_dispatch_details_->tree != tree)
-    return;
-
-  // The WindowTree is dying. So it's not going to ack the event.
-  // If the dying tree matches the root |tree_| mark as handled so we don't
-  // notify it of accelerators.
-  OnEventAck(in_flight_event_dispatch_details_->tree,
-             tree == window_tree_ ? mojom::EventResult::HANDLED
-                                  : mojom::EventResult::UNHANDLED);
+  event_dispatcher_.OnWillDestroyAsyncEventDispatcher(tree);
 }
 
 void WindowManagerState::ProcessEvent(ui::Event* event, int64_t display_id) {
@@ -357,69 +222,13 @@
     AdjustEventLocation(display_id, event->AsLocatedEvent());
     event_location.location = event->AsLocatedEvent()->root_location_f();
   }
-
-  // If this is still waiting for an ack from a previously sent event, then
-  // queue the event so it's dispatched once the ack is received.
-  if (IsProcessingEvent()) {
-    if (!event_tasks_.empty() &&
-        event_tasks_.back()->type() == EventTask::Type::kEvent &&
-        CanEventsBeCoalesced(*event_tasks_.back()->event, *event)) {
-      event_tasks_.back()->event = CoalesceEvents(
-          std::move(event_tasks_.back()->event), ui::Event::Clone(*event));
-      event_tasks_.back()->event_location = event_location;
-      return;
-    }
-    QueueEvent(*event, nullptr, event_location);
-    return;
-  }
-
-  QueueEvent(*event, nullptr, event_location);
-  ProcessEventTasks();
-}
-
-bool WindowManagerState::IsProcessingEvent() const {
-  return in_flight_event_dispatch_details_ ||
-         event_processor_.IsProcessingEvent();
+  event_dispatcher_.ProcessEvent(event, event_location);
 }
 
 void WindowManagerState::ScheduleCallbackWhenDoneProcessingEvents(
     base::OnceClosure closure) {
-  DCHECK(closure);
-  if (!IsProcessingEvent()) {
-    std::move(closure).Run();
-    return;
-  }
-
-  // TODO(sky): use make_unique (presubmit check fails on make_unique).
-  std::unique_ptr<EventTask> event_task(new EventTask());
-  event_task->done_closure = std::move(closure);
-  event_tasks_.push(std::move(event_task));
-}
-
-void WindowManagerState::OnAcceleratorAck(
-    mojom::EventResult result,
-    const std::unordered_map<std::string, std::vector<uint8_t>>& properties) {
-  DCHECK(in_flight_event_dispatch_details_);
-  DCHECK_EQ(EventDispatchPhase::PRE_TARGET_ACCELERATOR,
-            in_flight_event_dispatch_details_->phase);
-
-  std::unique_ptr<InFlightEventDispatchDetails> details =
-      std::move(in_flight_event_dispatch_details_);
-
-  if (result == mojom::EventResult::UNHANDLED) {
-    DCHECK(details->event->IsKeyEvent());
-    if (!properties.empty())
-      details->event->AsKeyEvent()->SetProperties(properties);
-    event_processor_.ProcessEvent(
-        *details->event, EventLocation(details->display_id),
-        EventProcessor::AcceleratorMatchPhase::POST_ONLY);
-  } else {
-    // We're not going to process the event any further, notify event observers.
-    // We don't do this first to ensure we don't send an event twice to clients.
-    window_server()->SendToPointerWatchers(*details->event, nullptr, nullptr,
-                                           details->display_id);
-    ProcessEventTasks();
-  }
+  event_dispatcher_.ScheduleCallbackWhenDoneProcessingEvents(
+      std::move(closure));
 }
 
 const WindowServer* WindowManagerState::window_server() const {
@@ -471,88 +280,6 @@
   return nullptr;
 }
 
-void WindowManagerState::OnEventAck(mojom::WindowTree* tree,
-                                    mojom::EventResult result) {
-  DCHECK(in_flight_event_dispatch_details_);
-  std::unique_ptr<InFlightEventDispatchDetails> details =
-      std::move(in_flight_event_dispatch_details_);
-
-  if (result == mojom::EventResult::UNHANDLED &&
-      details->post_target_accelerator) {
-    OnAccelerator(details->post_target_accelerator->id(), details->display_id,
-                  *details->event, AcceleratorPhase::kPost);
-  }
-
-  ProcessEventTasks();
-}
-
-void WindowManagerState::OnEventAckTimeout(ClientSpecificId client_id) {
-  WindowTree* hung_tree = window_server()->GetTreeWithId(client_id);
-  if (hung_tree && !hung_tree->janky())
-    window_tree_->ClientJankinessChanged(hung_tree);
-  if (in_flight_event_dispatch_details_->phase ==
-      EventDispatchPhase::PRE_TARGET_ACCELERATOR) {
-    OnAcceleratorAck(mojom::EventResult::UNHANDLED, KeyEvent::Properties());
-  } else {
-    OnEventAck(in_flight_event_dispatch_details_->tree,
-               mojom::EventResult::UNHANDLED);
-  }
-}
-
-void WindowManagerState::ProcessEventImpl(const ui::Event& event,
-                                          const EventLocation& event_location) {
-  DCHECK(!in_flight_event_dispatch_details_ &&
-         !event_processor_.IsProcessingEvent());
-  // Debug accelerators are always checked and don't interfere with processing.
-  ProcessDebugAccelerator(event, event_location.display_id);
-  event_processor_.ProcessEvent(event, event_location,
-                                EventProcessor::AcceleratorMatchPhase::ANY);
-}
-
-void WindowManagerState::QueueEvent(
-    const ui::Event& event,
-    std::unique_ptr<ProcessedEventTarget> processed_event_target,
-    const EventLocation& event_location) {
-  std::unique_ptr<EventTask> queued_event(new EventTask);
-  queued_event->event = ui::Event::Clone(event);
-  queued_event->processed_target = std::move(processed_event_target);
-  queued_event->event_location = event_location;
-  event_tasks_.push(std::move(queued_event));
-}
-
-// TODO(riajiang): We might want to do event targeting for the next event while
-// waiting for the current event to be dispatched. crbug.com/724521
-void WindowManagerState::DispatchInputEventToWindowImpl(
-    ServerWindow* target,
-    ClientSpecificId client_id,
-    const EventLocation& event_location,
-    const ui::Event& event,
-    base::WeakPtr<Accelerator> accelerator) {
-  DCHECK(!in_flight_event_dispatch_details_);
-  DCHECK(target);
-  if (target->parent() == nullptr)
-    target = GetWindowManagerRootForDisplayRoot(target);
-
-  if (event.IsMousePointerEvent())
-    UpdateNativeCursorFromEventProcessor();
-
-  WindowTree* tree = window_server()->GetTreeWithId(client_id);
-  DCHECK(tree);
-  ScheduleInputEventTimeout(tree, target, event_location.display_id, event,
-                            EventDispatchPhase::TARGET);
-  in_flight_event_dispatch_details_->post_target_accelerator = accelerator;
-
-  // Ignore |tree| because it will receive the event via normal dispatch.
-  window_server()->SendToPointerWatchers(event, target, tree,
-                                         event_location.display_id);
-
-  tree->DispatchInputEvent(
-      target, event, event_location,
-      base::BindOnce(
-          &WindowManagerState::OnEventAck,
-          in_flight_event_dispatch_details_->weak_factory.GetWeakPtr(), tree));
-}
-
 void WindowManagerState::AddDebugAccelerators() {
   const DebugAccelerator accelerator = {
       DebugAcceleratorType::PRINT_WINDOWS, ui::VKEY_S,
@@ -593,26 +320,6 @@
 #endif
 }
 
-void WindowManagerState::ScheduleInputEventTimeout(WindowTree* tree,
-                                                   ServerWindow* target,
-                                                   int64_t display_id,
-                                                   const Event& event,
-                                                   EventDispatchPhase phase) {
-  std::unique_ptr<InFlightEventDispatchDetails> details =
-      std::make_unique<InFlightEventDispatchDetails>(this, tree, display_id,
-                                                     event, phase);
-
-  // TODO(sad): Adjust this delay, possibly make this dynamic.
-  const base::TimeDelta max_delay = base::debug::BeingDebugged()
-                                        ? base::TimeDelta::FromDays(1)
-                                        : GetDefaultAckTimerDelay();
-  details->timer.Start(
-      FROM_HERE, max_delay,
-      base::Bind(&WindowManagerState::OnEventAckTimeout,
-                 details->weak_factory.GetWeakPtr(), tree->id()));
-  in_flight_event_dispatch_details_ = std::move(details);
-}
-
 bool WindowManagerState::ConvertPointToScreen(int64_t display_id,
                                               gfx::Point* point) {
   Display* display = display_manager()->GetDisplayById(display_id);
@@ -662,9 +369,8 @@
 
   const gfx::Rect& display_bounds_in_pixels = GetDisplayBoundsInPixels(display);
   // Typical case is the display contains the location.
-  if (gfx::Rect(display_bounds_in_pixels.size()).Contains(event->location())) {
+  if (gfx::Rect(display_bounds_in_pixels.size()).Contains(event->location()))
     return;
-  }
 
   // The location is outside the bounds of the specified display. This generally
   // happens when there is a grab and the mouse is moved to another display.
@@ -699,23 +405,6 @@
 ////////////////////////////////////////////////////////////////////////////////
 // EventProcessorDelegate:
 
-void WindowManagerState::OnAccelerator(uint32_t accelerator_id,
-                                       int64_t display_id,
-                                       const ui::Event& event,
-                                       AcceleratorPhase phase) {
-  const bool needs_ack = phase == AcceleratorPhase::kPre;
-  WindowTree::AcceleratorCallback ack_callback;
-  if (needs_ack) {
-    DCHECK(!in_flight_event_dispatch_details_);
-    ScheduleInputEventTimeout(window_tree_, nullptr, display_id, event,
-                              EventDispatchPhase::PRE_TARGET_ACCELERATOR);
-    ack_callback = base::BindOnce(
-        &WindowManagerState::OnAcceleratorAck,
-        in_flight_event_dispatch_details_->weak_factory.GetWeakPtr());
-  }
-  window_tree_->OnAccelerator(accelerator_id, event, std::move(ack_callback));
-}
-
 void WindowManagerState::SetFocusedWindowFromEventProcessor(
     ServerWindow* new_focused_window) {
   window_server()->SetFocusedWindow(new_focused_window);
@@ -809,53 +498,6 @@
   cursor_state_.SetCursorTouchVisible(visible);
 }
 
-void WindowManagerState::DispatchInputEventToWindow(
-    ServerWindow* target,
-    ClientSpecificId client_id,
-    const EventLocation& event_location,
-    const ui::Event& event,
-    Accelerator* accelerator) {
-  if (in_flight_event_dispatch_details_) {
-    std::unique_ptr<ProcessedEventTarget> processed_event_target =
-        std::make_unique<ProcessedEventTarget>(window_server(), target,
-                                               client_id, accelerator);
-    QueueEvent(event, std::move(processed_event_target), event_location);
-    return;
-  }
-
-  base::WeakPtr<Accelerator> weak_accelerator;
-  if (accelerator)
-    weak_accelerator = accelerator->GetWeakPtr();
-  DispatchInputEventToWindowImpl(target, client_id, event_location, event,
-                                 weak_accelerator);
-}
-
-void WindowManagerState::ProcessEventTasks() {
-  // Loop through |event_tasks_| stopping after dispatching the first valid
-  // event.
-  while (!event_tasks_.empty() && !IsProcessingEvent()) {
-    std::unique_ptr<EventTask> task = std::move(event_tasks_.front());
-    event_tasks_.pop();
-
-    switch (task->type()) {
-      case EventTask::Type::kClosure:
-        std::move(task->done_closure).Run();
-        break;
-      case EventTask::Type::kEvent:
-        ProcessEventImpl(*task->event, task->event_location);
-        break;
-      case EventTask::Type::kProcessedEvent:
-        if (task->processed_target->IsValid()) {
-          DispatchInputEventToWindowImpl(task->processed_target->window(),
-                                         task->processed_target->client_id(),
-                                         task->event_location, *task->event,
-                                         task->processed_target->accelerator());
-        }
-        break;
-    }
-  }
-}
-
 ClientSpecificId WindowManagerState::GetEventTargetClientId(
     const ServerWindow* window,
     bool in_nonclient_area) {
@@ -955,5 +597,46 @@
   window_tree_->OnCursorTouchVisibleChanged(enabled);
 }
 
+ServerWindow* WindowManagerState::OnWillDispatchInputEvent(
+    ServerWindow* target,
+    ClientSpecificId client_id,
+    const EventLocation& event_location,
+    const Event& event) {
+  if (target->parent() == nullptr) {
+    // The target is a display root, redirect to the WindowManager's root so
+    // that the WindowManager is passed a window it knows.
+    target = GetWindowManagerRootForDisplayRoot(target);
+  }
+  if (event.IsMousePointerEvent())
+    UpdateNativeCursorFromEventProcessor();
+  WindowTree* tree = window_server()->GetTreeWithId(client_id);
+  DCHECK(tree);
+  // Ignore |tree| because it will receive the event via normal dispatch.
+  window_server()->SendToPointerWatchers(event, target, tree,
+                                         event_location.display_id);
+  return target;
+}
+
+void WindowManagerState::OnEventDispatchTimedOut(
+    AsyncEventDispatcher* async_event_dispatcher) {
+  DCHECK(async_event_dispatcher);
+  WindowTree* hung_tree = static_cast<WindowTree*>(async_event_dispatcher);
+  if (!hung_tree->janky())
+    window_tree_->ClientJankinessChanged(hung_tree);
+}
+
+void WindowManagerState::OnAsyncEventDispatcherHandledAccelerator(
+    const Event& event,
+    int64_t display_id) {
+  window_server()->SendToPointerWatchers(event, nullptr, nullptr, display_id);
+}
+
+void WindowManagerState::OnWillProcessEvent(
+    const ui::Event& event,
+    const EventLocation& event_location) {
+  // Debug accelerators are always checked and don't interfere with processing.
+  ProcessDebugAccelerator(event, event_location.display_id);
+}
+
 }  // namespace ws
 }  // namespace ui
diff --git a/services/ui/ws/window_manager_state.h b/services/ui/ws/window_manager_state.h
index 8c7210b..7ef2ffbe 100644
--- a/services/ui/ws/window_manager_state.h
+++ b/services/ui/ws/window_manager_state.h
@@ -12,13 +12,13 @@
 #include <unordered_map>
 #include <vector>
 
-#include "base/containers/queue.h"
 #include "base/memory/weak_ptr.h"
 #include "base/timer/timer.h"
 #include "services/ui/public/interfaces/display_manager.mojom.h"
 #include "services/ui/ws/cursor_state.h"
 #include "services/ui/ws/cursor_state_delegate.h"
-#include "services/ui/ws/event_dispatcher.h"
+#include "services/ui/ws/event_dispatcher_delegate.h"
+#include "services/ui/ws/event_dispatcher_impl.h"
 #include "services/ui/ws/event_processor.h"
 #include "services/ui/ws/event_processor_delegate.h"
 #include "services/ui/ws/server_window_observer.h"
@@ -32,6 +32,7 @@
 namespace ws {
 
 class DisplayManager;
+class EventDispatcherImpl;
 class PlatformDisplay;
 class WindowManagerDisplayRoot;
 class WindowTree;
@@ -46,7 +47,7 @@
 class WindowManagerState : public EventProcessorDelegate,
                            public ServerWindowObserver,
                            public CursorStateDelegate,
-                           public EventDispatcher {
+                           public EventDispatcherDelegate {
  public:
   explicit WindowManagerState(WindowTree* window_tree);
   ~WindowManagerState() override;
@@ -104,10 +105,6 @@
   // |event|, but it may modify it.
   void ProcessEvent(ui::Event* event, int64_t display_id);
 
-  // Returns true if actively processing an event. This includes waiting for a
-  // client to ack an event.
-  bool IsProcessingEvent() const;
-
   // Notifies |closure| once done processing currently queued events. This
   // notifies |closure| immediately if IsProcessingEvent() returns false.
   void ScheduleCallbackWhenDoneProcessingEvents(base::OnceClosure closure);
@@ -117,7 +114,6 @@
   }
 
  private:
-  class ProcessedEventTarget;
   friend class Display;
   friend class test::WindowManagerStateTestApi;
 
@@ -138,38 +134,6 @@
     int event_flags;
   };
 
-  enum class EventDispatchPhase {
-    // Not actively dispatching.
-    NONE,
-
-    // A PRE_TARGET accelerator has been encountered and we're awaiting the ack.
-    PRE_TARGET_ACCELERATOR,
-
-    // Dispatching to the target, awaiting the ack.
-    TARGET,
-  };
-
-  struct EventTask;
-
-  // Tracks state associated with an event being dispatched to a client.
-  struct InFlightEventDispatchDetails {
-    InFlightEventDispatchDetails(WindowManagerState* window_manager_state,
-                                 WindowTree* tree,
-                                 int64_t display_id,
-                                 const Event& event,
-                                 EventDispatchPhase phase);
-    ~InFlightEventDispatchDetails();
-
-    base::OneShotTimer timer;
-    WindowTree* tree;
-    int64_t display_id;
-    std::unique_ptr<Event> event;
-    EventDispatchPhase phase;
-    base::WeakPtr<Accelerator> post_target_accelerator;
-    // Used for callbacks/timer specific to processing |event|.
-    base::WeakPtrFactory<WindowManagerState> weak_factory;
-  };
-
   const WindowServer* window_server() const;
   WindowServer* window_server();
 
@@ -188,14 +152,6 @@
   // |window|. |window| corresponds to the root of a Display.
   ServerWindow* GetWindowManagerRootForDisplayRoot(ServerWindow* window);
 
-  // Called from the callback supplied to WindowTree::OnAccelerator().
-  void OnAcceleratorAck(
-      mojom::EventResult result,
-      const std::unordered_map<std::string, std::vector<uint8_t>>& properties);
-
-  // Called from the callback supplied to WindowTree::DispatchInputEvent().
-  void OnEventAck(mojom::WindowTree* tree, mojom::EventResult result);
-
   // Called if the client doesn't ack an event in the appropriate amount of
   // time.
   void OnEventAckTimeout(ClientSpecificId client_id);
@@ -205,11 +161,6 @@
   void ProcessEventImpl(const Event& event,
                         const EventLocation& event_location);
 
-  // Schedules an event to be processed later.
-  void QueueEvent(const Event& event,
-                  std::unique_ptr<ProcessedEventTarget> processed_event_target,
-                  const EventLocation& event_location);
-
   // Dispatches the event to the appropriate client and starts the ack timer.
   void DispatchInputEventToWindowImpl(ServerWindow* target,
                                       ClientSpecificId client_id,
@@ -227,13 +178,6 @@
   // Runs the specified debug accelerator.
   void HandleDebugAccelerator(DebugAcceleratorType type, int64_t display_id);
 
-  // Called when waiting for an event or accelerator to be processed by |tree|.
-  void ScheduleInputEventTimeout(WindowTree* tree,
-                                 ServerWindow* target,
-                                 int64_t display_id,
-                                 const Event& event,
-                                 EventDispatchPhase phase);
-
   // Processes queued event tasks until there are no more, or we're waiting on
   // a client or the EventDisptacher to complete processing.
   void ProcessEventTasks();
@@ -274,23 +218,24 @@
   ServerWindow* GetWindowFromFrameSinkId(
       const viz::FrameSinkId& frame_sink_id) override;
 
-  // EventDispatcher:
-  void DispatchInputEventToWindow(ServerWindow* target,
-                                  ClientSpecificId client_id,
-                                  const EventLocation& event_location,
-                                  const Event& event,
-                                  Accelerator* accelerator) override;
-  void OnAccelerator(uint32_t accelerator_id,
-                     int64_t display_id,
-                     const Event& event,
-                     AcceleratorPhase phase) override;
-
   // ServerWindowObserver:
   void OnWindowEmbeddedAppDisconnected(ServerWindow* window) override;
 
   // CursorStateDelegate:
   void OnCursorTouchVisibleChanged(bool enabled) override;
 
+  // EventDispatcherDelegate:
+  ServerWindow* OnWillDispatchInputEvent(ServerWindow* target,
+                                         ClientSpecificId client_id,
+                                         const EventLocation& event_location,
+                                         const Event& event) override;
+  void OnEventDispatchTimedOut(
+      AsyncEventDispatcher* async_event_dipsatcher) override;
+  void OnAsyncEventDispatcherHandledAccelerator(const Event& event,
+                                                int64_t display_id) override;
+  void OnWillProcessEvent(const ui::Event& event,
+                          const EventLocation& event_location) override;
+
   // The single WindowTree this WindowManagerState is associated with.
   // |window_tree_| owns this.
   WindowTree* window_tree_;
@@ -299,17 +244,9 @@
   bool got_frame_decoration_values_ = false;
   mojom::FrameDecorationValuesPtr frame_decoration_values_;
 
-  // Used for any event related tasks that need to be processed. Tasks are added
-  // to the queue anytime work comes in while waiting for a client to respond,
-  // or waiting for async hit-testing processing to complete.
-  base::queue<std::unique_ptr<EventTask>> event_tasks_;
-
   std::vector<DebugAccelerator> debug_accelerators_;
 
-  // If non-null we're actively waiting for a response from a client for an
-  // event.
-  std::unique_ptr<InFlightEventDispatchDetails>
-      in_flight_event_dispatch_details_;
+  EventDispatcherImpl event_dispatcher_;
 
   EventProcessor event_processor_;
 
diff --git a/services/ui/ws/window_server.cc b/services/ui/ws/window_server.cc
index bf92ce8d..db2d40b 100644
--- a/services/ui/ws/window_server.cc
+++ b/services/ui/ws/window_server.cc
@@ -702,8 +702,7 @@
     // special case because ServerWindows created by the WindowServer are not
     // part of a WindowTree. Send the SurfaceId directly to FrameGenerator and
     // claim the temporary reference for the display root.
-    display->platform_display()->GetFrameGenerator()->OnFirstSurfaceActivation(
-        surface_info);
+    display_manager_->OnWindowManagerSurfaceActivation(display, surface_info);
     host_frame_sink_manager_->AssignTemporaryReference(
         surface_info.id(), display->root_window()->frame_sink_id());
     return;
@@ -845,6 +844,11 @@
       std::move(frame_sink_manager));
 }
 
+AsyncEventDispatcher* WindowServer::GetAsyncEventDispatcherById(
+    ClientSpecificId id) {
+  return GetTreeWithId(id);
+}
+
 ServerWindow* WindowServer::GetRootWindowForDrawn(const ServerWindow* window) {
   Display* display = display_manager_->GetDisplayContaining(window);
   return display ? display->root_window() : nullptr;
diff --git a/services/ui/ws/window_server.h b/services/ui/ws/window_server.h
index 6be9d2d..d9d2dc1 100644
--- a/services/ui/ws/window_server.h
+++ b/services/ui/ws/window_server.h
@@ -21,6 +21,7 @@
 #include "mojo/public/cpp/bindings/binding.h"
 #include "services/ui/public/interfaces/window_manager_window_tree_factory.mojom.h"
 #include "services/ui/public/interfaces/window_tree.mojom.h"
+#include "services/ui/ws/async_event_dispatcher_lookup.h"
 #include "services/ui/ws/gpu_host_delegate.h"
 #include "services/ui/ws/ids.h"
 #include "services/ui/ws/operation.h"
@@ -59,7 +60,8 @@
 class WindowServer : public ServerWindowDelegate,
                      public ServerWindowObserver,
                      public GpuHostDelegate,
-                     public UserDisplayManagerDelegate {
+                     public UserDisplayManagerDelegate,
+                     public AsyncEventDispatcherLookup {
  public:
   WindowServer(WindowServerDelegate* delegate, bool should_host_viz);
   ~WindowServer() override;
@@ -326,6 +328,10 @@
 
   void CreateFrameSinkManager();
 
+  // AsyncEventDispatcherLookup:
+  AsyncEventDispatcher* GetAsyncEventDispatcherById(
+      ClientSpecificId id) override;
+
   // Overridden from ServerWindowDelegate:
   ServerWindow* GetRootWindowForDrawn(const ServerWindow* window) override;
 
diff --git a/services/ui/ws/window_tree.cc b/services/ui/ws/window_tree.cc
index 1c6c3131..c397bc3 100644
--- a/services/ui/ws/window_tree.cc
+++ b/services/ui/ws/window_tree.cc
@@ -476,6 +476,41 @@
                                                           kInvalidClientId);
 }
 
+void WindowTree::DispatchEvent(ServerWindow* target,
+                               const ui::Event& event,
+                               const EventLocation& event_location,
+                               DispatchEventCallback callback) {
+  if (event_ack_id_ || !event_queue_.empty()) {
+    // Either awaiting an ack, or there are events in the queue. Store the event
+    // for processing when the ack is received.
+    event_queue_.push(std::make_unique<TargetedEvent>(
+        target, event, event_location, std::move(callback)));
+    // TODO(sad): If the |event_queue_| grows too large, then this should notify
+    // Display, so that it can stop sending events.
+    return;
+  }
+
+  DispatchEventImpl(target, event, event_location, std::move(callback));
+}
+
+void WindowTree::DispatchAccelerator(uint32_t accelerator_id,
+                                     const ui::Event& event,
+                                     AcceleratorCallback callback) {
+  DVLOG(3) << "OnAccelerator client=" << id_;
+  DCHECK(window_manager_internal_);  // Only valid for the window manager.
+  if (callback) {
+    GenerateEventAckId();
+    accelerator_ack_callback_ = std::move(callback);
+  } else {
+    DCHECK_EQ(0u, event_ack_id_);
+    DCHECK(!accelerator_ack_callback_);
+  }
+  // TODO: https://crbug.com/617167. Don't clone event once we map mojom::Event
+  // directly to ui::Event.
+  window_manager_internal_->OnAccelerator(event_ack_id_, accelerator_id,
+                                          ui::Event::Clone(event));
+}
+
 bool WindowTree::NewWindow(
     const ClientWindowId& client_window_id,
     const std::map<std::string, std::vector<uint8_t>>& properties) {
@@ -730,31 +765,6 @@
   return true;
 }
 
-void WindowTree::DispatchInputEvent(ServerWindow* target,
-                                    const ui::Event& event,
-                                    const EventLocation& event_location,
-                                    DispatchEventCallback callback) {
-  if (event_ack_id_) {
-    // This is currently waiting for an event ack. Add it to the queue.
-    event_queue_.push(std::make_unique<TargetedEvent>(
-        target, event, event_location, std::move(callback)));
-    // TODO(sad): If the |event_queue_| grows too large, then this should notify
-    // Display, so that it can stop sending events.
-    return;
-  }
-
-  // If there are events in the queue, then store this new event in the queue,
-  // and dispatch the latest event from the queue instead that still has a live
-  // target.
-  if (!event_queue_.empty()) {
-    event_queue_.push(std::make_unique<TargetedEvent>(
-        target, event, event_location, std::move(callback)));
-    return;
-  }
-
-  DispatchInputEventImpl(target, event, event_location, std::move(callback));
-}
-
 bool WindowTree::IsWaitingForNewTopLevelWindow(uint32_t wm_change_id) {
   return waiting_for_top_level_window_info_ &&
          waiting_for_top_level_window_info_->wm_change_id == wm_change_id;
@@ -799,24 +809,6 @@
   client()->OnChangeCompleted(change_id, success);
 }
 
-void WindowTree::OnAccelerator(uint32_t accelerator_id,
-                               const ui::Event& event,
-                               AcceleratorCallback callback) {
-  DVLOG(3) << "OnAccelerator client=" << id_;
-  DCHECK(window_manager_internal_);  // Only valid for the window manager.
-  if (callback) {
-    GenerateEventAckId();
-    accelerator_ack_callback_ = std::move(callback);
-  } else {
-    DCHECK_EQ(0u, event_ack_id_);
-    DCHECK(!accelerator_ack_callback_);
-  }
-  // TODO(moshayedi): crbug.com/617167. Don't clone even once we map
-  // mojom::Event directly to ui::Event.
-  window_manager_internal_->OnAccelerator(event_ack_id_, accelerator_id,
-                                          ui::Event::Clone(event));
-}
-
 void WindowTree::OnEventOccurredOutsideOfModalWindow(
     const ServerWindow* modal_window) {
   DCHECK(window_manager_internal_);
@@ -1515,12 +1507,12 @@
   return event_ack_id_;
 }
 
-void WindowTree::DispatchInputEventImpl(ServerWindow* target,
-                                        const ui::Event& event,
-                                        const EventLocation& event_location,
-                                        DispatchEventCallback callback) {
-  // DispatchInputEventImpl() is called so often that log level 4 is used.
-  DVLOG(4) << "DispatchInputEventImpl client=" << id_;
+void WindowTree::DispatchEventImpl(ServerWindow* target,
+                                   const ui::Event& event,
+                                   const EventLocation& event_location,
+                                   DispatchEventCallback callback) {
+  // DispatchEventImpl() is called so often that log level 4 is used.
+  DVLOG(4) << "DispatchEventImpl client=" << id_;
   GenerateEventAckId();
   event_ack_callback_ = std::move(callback);
   WindowManagerDisplayRoot* display_root = GetWindowManagerDisplayRoot(target);
@@ -1922,7 +1914,7 @@
 
 void WindowTree::OnWindowInputEventAck(uint32_t event_id,
                                        mojom::EventResult result) {
-  // DispatchInputEventImpl() is called so often that log level 4 is used.
+  // DispatchEventImpl() is called so often that log level 4 is used.
   DVLOG(4) << "OnWindowInputEventAck client=" << id_;
   if (event_ack_id_ == 0 || event_id != event_ack_id_ || !event_ack_callback_) {
     // TODO(sad): Something bad happened. Kill the client?
@@ -1956,8 +1948,7 @@
       callback = targeted_event->TakeCallback();
     } while (!event_queue_.empty() && !GetDisplay(target));
     if (GetDisplay(target)) {
-      DispatchInputEventImpl(target, *event, event_location,
-                             std::move(callback));
+      DispatchEventImpl(target, *event, event_location, std::move(callback));
     } else {
       // If the window is no longer valid (or not in a display), then there is
       // no point in dispatching to the client, but we need to run the callback
diff --git a/services/ui/ws/window_tree.h b/services/ui/ws/window_tree.h
index 85e76ff..20fd79a9 100644
--- a/services/ui/ws/window_tree.h
+++ b/services/ui/ws/window_tree.h
@@ -22,6 +22,7 @@
 #include "mojo/public/cpp/bindings/associated_binding.h"
 #include "services/ui/public/interfaces/window_tree.mojom.h"
 #include "services/ui/ws/access_policy_delegate.h"
+#include "services/ui/ws/async_event_dispatcher.h"
 #include "services/ui/ws/drag_source.h"
 #include "services/ui/ws/drag_target_connection.h"
 #include "services/ui/ws/ids.h"
@@ -74,7 +75,8 @@
                    public AccessPolicyDelegate,
                    public mojom::WindowManagerClient,
                    public DragSource,
-                   public DragTargetConnection {
+                   public DragTargetConnection,
+                   public AsyncEventDispatcher {
  public:
   WindowTree(WindowServer* window_server,
              bool is_for_embedding,
@@ -206,14 +208,6 @@
                          const WindowTreeAndWindowId& tree_and_window_id,
                          const base::UnguessableToken& token);
 
-  // Dispatches an event to the client. |callback| is run with the result from
-  // the client.
-  using DispatchEventCallback = base::OnceCallback<void(mojom::EventResult)>;
-  void DispatchInputEvent(ServerWindow* target,
-                          const ui::Event& event,
-                          const EventLocation& event_location,
-                          DispatchEventCallback callback);
-
   bool IsWaitingForNewTopLevelWindow(uint32_t wm_change_id);
   viz::FrameSinkId OnWindowManagerCreatedTopLevelWindow(
       uint32_t wm_change_id,
@@ -229,9 +223,6 @@
   using AcceleratorCallback = base::OnceCallback<void(
       mojom::EventResult,
       const std::unordered_map<std::string, std::vector<uint8_t>>&)>;
-  void OnAccelerator(uint32_t accelerator_id,
-                     const ui::Event& event,
-                     AcceleratorCallback callback);
   void OnEventOccurredOutsideOfModalWindow(const ServerWindow* modal_window);
 
   // Called when the cursor touch visibility bit changes. This is only called
@@ -422,10 +413,10 @@
   // |event_ack_id_| and returns it.
   uint32_t GenerateEventAckId();
 
-  void DispatchInputEventImpl(ServerWindow* target,
-                              const ui::Event& event,
-                              const EventLocation& event_location,
-                              DispatchEventCallback callback);
+  void DispatchEventImpl(ServerWindow* target,
+                         const ui::Event& event,
+                         const EventLocation& event_location,
+                         DispatchEventCallback callback);
 
   // Returns true if the client has a pointer watcher and this event matches.
   bool EventMatchesPointerWatcher(const ui::Event& event) const;
@@ -465,6 +456,15 @@
   mojom::WindowTreeClientPtr GetAndRemoveScheduledEmbedWindowTreeClient(
       const base::UnguessableToken& token);
 
+  // AsyncEventDispatcher:
+  void DispatchEvent(ServerWindow* target,
+                     const ui::Event& event,
+                     const EventLocation& event_location,
+                     DispatchEventCallback callback) override;
+  void DispatchAccelerator(uint32_t accelerator_id,
+                           const ui::Event& event,
+                           AcceleratorCallback callback) override;
+
   // WindowTree:
   void NewWindow(uint32_t change_id,
                  Id transport_window_id,
diff --git a/services/viz/public/cpp/compositing/copy_output_request_struct_traits.h b/services/viz/public/cpp/compositing/copy_output_request_struct_traits.h
index 9ddac49..20a4dfc6 100644
--- a/services/viz/public/cpp/compositing/copy_output_request_struct_traits.h
+++ b/services/viz/public/cpp/compositing/copy_output_request_struct_traits.h
@@ -6,7 +6,7 @@
 #define SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_COPY_OUTPUT_REQUEST_STRUCT_TRAITS_H_
 
 #include "components/viz/common/frame_sinks/copy_output_request.h"
-#include "mojo/common/common_custom_types_struct_traits.h"
+#include "mojo/public/cpp/base/unguessable_token_mojom_traits.h"
 #include "services/viz/public/cpp/compositing/copy_output_result_struct_traits.h"
 #include "services/viz/public/interfaces/compositing/copy_output_request.mojom.h"
 #include "ui/gfx/geometry/mojo/geometry_struct_traits.h"
diff --git a/services/viz/public/cpp/compositing/local_surface_id_struct_traits.h b/services/viz/public/cpp/compositing/local_surface_id_struct_traits.h
index 6c0aba8..0d16236 100644
--- a/services/viz/public/cpp/compositing/local_surface_id_struct_traits.h
+++ b/services/viz/public/cpp/compositing/local_surface_id_struct_traits.h
@@ -6,7 +6,7 @@
 #define SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_LOCAL_SURFACE_ID_STRUCT_TRAITS_H_
 
 #include "components/viz/common/surfaces/local_surface_id.h"
-#include "mojo/common/common_custom_types_struct_traits.h"
+#include "mojo/public/cpp/base/unguessable_token_mojom_traits.h"
 #include "services/viz/public/interfaces/compositing/local_surface_id.mojom-shared.h"
 
 namespace mojo {
diff --git a/services/viz/public/interfaces/compositing/copy_output_request.mojom b/services/viz/public/interfaces/compositing/copy_output_request.mojom
index a292ac7..220c2e4 100644
--- a/services/viz/public/interfaces/compositing/copy_output_request.mojom
+++ b/services/viz/public/interfaces/compositing/copy_output_request.mojom
@@ -7,7 +7,7 @@
 import "gpu/ipc/common/mailbox.mojom";
 import "gpu/ipc/common/sync_token.mojom";
 import "services/viz/public/interfaces/compositing/copy_output_result.mojom";
-import "mojo/common/unguessable_token.mojom";
+import "mojo/public/mojom/base/unguessable_token.mojom";
 import "ui/gfx/geometry/mojo/geometry.mojom";
 
 // See components/viz/common/frame_sinks/copy_output_request.h.
@@ -18,7 +18,7 @@
   gfx.mojom.Vector2d scale_from;
   gfx.mojom.Vector2d scale_to;
 
-  mojo.common.mojom.UnguessableToken? source;
+  mojo_base.mojom.UnguessableToken? source;
   gfx.mojom.Rect? area;
   gfx.mojom.Rect? result_selection;
 
diff --git a/services/viz/public/interfaces/compositing/local_surface_id.mojom b/services/viz/public/interfaces/compositing/local_surface_id.mojom
index 295b186..6cd09eed 100644
--- a/services/viz/public/interfaces/compositing/local_surface_id.mojom
+++ b/services/viz/public/interfaces/compositing/local_surface_id.mojom
@@ -4,7 +4,7 @@
 
 module viz.mojom;
 
-import "mojo/common/unguessable_token.mojom";
+import "mojo/public/mojom/base/unguessable_token.mojom";
 
 struct LocalSurfaceId {
   // An identifier to uniquely identify a surface.
@@ -16,6 +16,6 @@
   // its own surface.
   uint32 child_sequence_number;
 
-  mojo.common.mojom.UnguessableToken embed_token;
+  mojo_base.mojom.UnguessableToken embed_token;
 };
 
diff --git a/storage/browser/fileapi/async_file_util.h b/storage/browser/fileapi/async_file_util.h
index 8ae710f..ed64283 100644
--- a/storage/browser/fileapi/async_file_util.h
+++ b/storage/browser/fileapi/async_file_util.h
@@ -49,39 +49,36 @@
 //
 class AsyncFileUtil {
  public:
-  typedef base::Callback<void(base::File::Error result)> StatusCallback;
+  using StatusCallback = base::Callback<void(base::File::Error result)>;
 
   // |on_close_callback| will be called after the |file| is closed in the
   // child process. |on_close_callback|.is_null() can be true, if no operation
   // is needed on closing the file.
-  typedef base::Callback<void(base::File file,
-                              base::OnceClosure on_close_callback)>
-      CreateOrOpenCallback;
+  using CreateOrOpenCallback =
+      base::Callback<void(base::File file,
+                          base::OnceClosure on_close_callback)>;
 
-  typedef base::Callback<
-      void(base::File::Error result,
-           bool created)> EnsureFileExistsCallback;
+  using EnsureFileExistsCallback =
+      base::Callback<void(base::File::Error result, bool created)>;
 
-  typedef base::Callback<
-      void(base::File::Error result,
-           const base::File::Info& file_info)> GetFileInfoCallback;
+  using GetFileInfoCallback =
+      base::Callback<void(base::File::Error result,
+                          const base::File::Info& file_info)>;
 
-  typedef std::vector<DirectoryEntry> EntryList;
-  typedef base::RepeatingCallback<
-      void(base::File::Error result, EntryList file_list, bool has_more)>
-      ReadDirectoryCallback;
+  using EntryList = std::vector<DirectoryEntry>;
+  using ReadDirectoryCallback = base::RepeatingCallback<
+      void(base::File::Error result, EntryList file_list, bool has_more)>;
 
-  typedef base::Callback<void(
+  using CreateSnapshotFileCallback = base::Callback<void(
       base::File::Error result,
       const base::File::Info& file_info,
       const base::FilePath& platform_path,
-      scoped_refptr<storage::ShareableFileReference> file_ref)>
-      CreateSnapshotFileCallback;
+      scoped_refptr<storage::ShareableFileReference> file_ref)>;
 
-  typedef base::Callback<void(int64_t size)> CopyFileProgressCallback;
+  using CopyFileProgressCallback = base::RepeatingCallback<void(int64_t size)>;
 
-  typedef FileSystemOperation::CopyOrMoveOption CopyOrMoveOption;
-  typedef FileSystemOperation::GetMetadataField GetMetadataField;
+  using CopyOrMoveOption = FileSystemOperation::CopyOrMoveOption;
+  using GetMetadataField = FileSystemOperation::GetMetadataField;
 
   // Creates an AsyncFileUtil instance which performs file operations on
   // local native file system. The created instance assumes
@@ -103,7 +100,7 @@
   virtual void CreateOrOpen(std::unique_ptr<FileSystemOperationContext> context,
                             const FileSystemURL& url,
                             int file_flags,
-                            const CreateOrOpenCallback& callback) = 0;
+                            CreateOrOpenCallback callback) = 0;
 
   // Ensures that the given |url| exist.  This creates a empty new file
   // at |url| if the |url| does not exist.
@@ -120,7 +117,7 @@
   virtual void EnsureFileExists(
       std::unique_ptr<FileSystemOperationContext> context,
       const FileSystemURL& url,
-      const EnsureFileExistsCallback& callback) = 0;
+      EnsureFileExistsCallback callback) = 0;
 
   // Creates directory at given url.
   //
@@ -140,7 +137,7 @@
       const FileSystemURL& url,
       bool exclusive,
       bool recursive,
-      const StatusCallback& callback) = 0;
+      StatusCallback callback) = 0;
 
   // Retrieves the information about a file.
   //
@@ -153,7 +150,7 @@
   virtual void GetFileInfo(std::unique_ptr<FileSystemOperationContext> context,
                            const FileSystemURL& url,
                            int fields,
-                           const GetFileInfoCallback& callback) = 0;
+                           GetFileInfoCallback callback) = 0;
 
   // Reads contents of a directory at |path|.
   //
@@ -176,7 +173,7 @@
   virtual void ReadDirectory(
       std::unique_ptr<FileSystemOperationContext> context,
       const FileSystemURL& url,
-      const ReadDirectoryCallback& callback) = 0;
+      ReadDirectoryCallback callback) = 0;
 
   // Modifies timestamps of a file or directory at |url| with
   // |last_access_time| and |last_modified_time|. The function DOES NOT
@@ -189,7 +186,7 @@
                      const FileSystemURL& url,
                      const base::Time& last_access_time,
                      const base::Time& last_modified_time,
-                     const StatusCallback& callback) = 0;
+                     StatusCallback callback) = 0;
 
   // Truncates a file at |path| to |length|. If |length| is larger than
   // the original file size, the file will be extended, and the extended
@@ -203,7 +200,7 @@
   virtual void Truncate(std::unique_ptr<FileSystemOperationContext> context,
                         const FileSystemURL& url,
                         int64_t length,
-                        const StatusCallback& callback) = 0;
+                        StatusCallback callback) = 0;
 
   // Copies a file from |src_url| to |dest_url|.
   // This must be called for files that belong to the same filesystem
@@ -231,8 +228,8 @@
       const FileSystemURL& src_url,
       const FileSystemURL& dest_url,
       CopyOrMoveOption option,
-      const CopyFileProgressCallback& progress_callback,
-      const StatusCallback& callback) = 0;
+      CopyFileProgressCallback progress_callback,
+      StatusCallback callback) = 0;
 
   // Moves a local file from |src_url| to |dest_url|.
   // This must be called for files that belong to the same filesystem
@@ -254,7 +251,7 @@
       const FileSystemURL& src_url,
       const FileSystemURL& dest_url,
       CopyOrMoveOption option,
-      const StatusCallback& callback) = 0;
+      StatusCallback callback) = 0;
 
   // Copies in a single file from a different filesystem.
   //
@@ -273,7 +270,7 @@
       std::unique_ptr<FileSystemOperationContext> context,
       const base::FilePath& src_file_path,
       const FileSystemURL& dest_url,
-      const StatusCallback& callback) = 0;
+      StatusCallback callback) = 0;
 
   // Deletes a single file.
   //
@@ -285,7 +282,7 @@
   //
   virtual void DeleteFile(std::unique_ptr<FileSystemOperationContext> context,
                           const FileSystemURL& url,
-                          const StatusCallback& callback) = 0;
+                          StatusCallback callback) = 0;
 
   // Removes a single empty directory.
   //
@@ -299,7 +296,7 @@
   virtual void DeleteDirectory(
       std::unique_ptr<FileSystemOperationContext> context,
       const FileSystemURL& url,
-      const StatusCallback& callback) = 0;
+      StatusCallback callback) = 0;
 
   // Removes a single file or a single directory with its contents
   // (i.e. files/subdirectories under the directory).
@@ -317,7 +314,7 @@
   virtual void DeleteRecursively(
       std::unique_ptr<FileSystemOperationContext> context,
       const FileSystemURL& url,
-      const StatusCallback& callback) = 0;
+      StatusCallback callback) = 0;
 
   // Creates a local snapshot file for a given |url| and returns the
   // metadata and platform path of the snapshot file via |callback|.
@@ -353,7 +350,7 @@
   virtual void CreateSnapshotFile(
       std::unique_ptr<FileSystemOperationContext> context,
       const FileSystemURL& url,
-      const CreateSnapshotFileCallback& callback) = 0;
+      CreateSnapshotFileCallback callback) = 0;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(AsyncFileUtil);
diff --git a/storage/browser/fileapi/async_file_util_adapter.cc b/storage/browser/fileapi/async_file_util_adapter.cc
index 8859e8d..962662a 100644
--- a/storage/browser/fileapi/async_file_util_adapter.cc
+++ b/storage/browser/fileapi/async_file_util_adapter.cc
@@ -43,8 +43,8 @@
     error_ = file_util->EnsureFileExists(context, url, &created_);
   }
 
-  void Reply(const AsyncFileUtil::EnsureFileExistsCallback& callback) {
-    callback.Run(error_, created_);
+  void Reply(AsyncFileUtil::EnsureFileExistsCallback callback) {
+    std::move(callback).Run(error_, created_);
   }
 
  private:
@@ -71,14 +71,14 @@
         context, url, &error_, &file_info_, &platform_path_);
   }
 
-  void ReplyFileInfo(const AsyncFileUtil::GetFileInfoCallback& callback) {
-    callback.Run(error_, file_info_);
+  void ReplyFileInfo(AsyncFileUtil::GetFileInfoCallback callback) {
+    std::move(callback).Run(error_, file_info_);
   }
 
-  void ReplySnapshotFile(
-      const AsyncFileUtil::CreateSnapshotFileCallback& callback) {
-    callback.Run(error_, file_info_, platform_path_,
-                 ShareableFileReference::GetOrCreate(std::move(scoped_file_)));
+  void ReplySnapshotFile(AsyncFileUtil::CreateSnapshotFileCallback callback) {
+    std::move(callback).Run(
+        error_, file_info_, platform_path_,
+        ShareableFileReference::GetOrCreate(std::move(scoped_file_)));
   }
 
  private:
@@ -93,7 +93,7 @@
                          FileSystemOperationContext* context,
                          const FileSystemURL& url,
                          base::SingleThreadTaskRunner* origin_runner,
-                         const AsyncFileUtil::ReadDirectoryCallback& callback) {
+                         AsyncFileUtil::ReadDirectoryCallback callback) {
   base::File::Info file_info;
   base::FilePath platform_path;
   base::File::Error error = file_util->GetFileInfo(
@@ -136,10 +136,9 @@
                                          false /* has_more */));
 }
 
-void RunCreateOrOpenCallback(
-    FileSystemOperationContext* context,
-    const AsyncFileUtil::CreateOrOpenCallback& callback,
-    base::File file) {
+void RunCreateOrOpenCallback(FileSystemOperationContext* context,
+                             AsyncFileUtil::CreateOrOpenCallback callback,
+                             base::File file) {
   if (callback.IsCancelled()) {
     // If |callback| been cancelled, free |file| on the correct task runner.
     context->task_runner()->PostTask(
@@ -148,7 +147,7 @@
     return;
   }
 
-  callback.Run(std::move(file), base::Closure());
+  std::move(callback).Run(std::move(file), base::Closure());
 }
 
 }  // namespace
@@ -165,27 +164,28 @@
     std::unique_ptr<FileSystemOperationContext> context,
     const FileSystemURL& url,
     int file_flags,
-    const CreateOrOpenCallback& callback) {
+    CreateOrOpenCallback callback) {
   FileSystemOperationContext* context_ptr = context.release();
   base::PostTaskAndReplyWithResult(
-      context_ptr->task_runner(),
-      FROM_HERE,
-      Bind(&FileSystemFileUtil::CreateOrOpen, Unretained(sync_file_util_.get()),
-           context_ptr, url, file_flags),
-      Bind(&RunCreateOrOpenCallback, base::Owned(context_ptr), callback));
+      context_ptr->task_runner(), FROM_HERE,
+      BindOnce(&FileSystemFileUtil::CreateOrOpen,
+               Unretained(sync_file_util_.get()), context_ptr, url, file_flags),
+      BindOnce(&RunCreateOrOpenCallback, base::Owned(context_ptr),
+               std::move(callback)));
 }
 
 void AsyncFileUtilAdapter::EnsureFileExists(
     std::unique_ptr<FileSystemOperationContext> context,
     const FileSystemURL& url,
-    const EnsureFileExistsCallback& callback) {
+    EnsureFileExistsCallback callback) {
   EnsureFileExistsHelper* helper = new EnsureFileExistsHelper;
   FileSystemOperationContext* context_ptr = context.release();
   const bool success = context_ptr->task_runner()->PostTaskAndReply(
       FROM_HERE,
       BindOnce(&EnsureFileExistsHelper::RunWork, Unretained(helper),
                sync_file_util_.get(), base::Owned(context_ptr), url),
-      BindOnce(&EnsureFileExistsHelper::Reply, Owned(helper), callback));
+      BindOnce(&EnsureFileExistsHelper::Reply, Owned(helper),
+               std::move(callback)));
   DCHECK(success);
 }
 
@@ -194,14 +194,14 @@
     const FileSystemURL& url,
     bool exclusive,
     bool recursive,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   FileSystemOperationContext* context_ptr = context.release();
   const bool success = base::PostTaskAndReplyWithResult(
       context_ptr->task_runner(), FROM_HERE,
       Bind(&FileSystemFileUtil::CreateDirectory,
-           Unretained(sync_file_util_.get()),
-           base::Owned(context_ptr), url, exclusive, recursive),
-      callback);
+           Unretained(sync_file_util_.get()), base::Owned(context_ptr), url,
+           exclusive, recursive),
+      std::move(callback));
   DCHECK(success);
 }
 
@@ -209,21 +209,22 @@
     std::unique_ptr<FileSystemOperationContext> context,
     const FileSystemURL& url,
     int /* fields */,
-    const GetFileInfoCallback& callback) {
+    GetFileInfoCallback callback) {
   FileSystemOperationContext* context_ptr = context.release();
   GetFileInfoHelper* helper = new GetFileInfoHelper;
   const bool success = context_ptr->task_runner()->PostTaskAndReply(
       FROM_HERE,
       BindOnce(&GetFileInfoHelper::GetFileInfo, Unretained(helper),
                sync_file_util_.get(), base::Owned(context_ptr), url),
-      BindOnce(&GetFileInfoHelper::ReplyFileInfo, Owned(helper), callback));
+      BindOnce(&GetFileInfoHelper::ReplyFileInfo, Owned(helper),
+               std::move(callback)));
   DCHECK(success);
 }
 
 void AsyncFileUtilAdapter::ReadDirectory(
     std::unique_ptr<FileSystemOperationContext> context,
     const FileSystemURL& url,
-    const ReadDirectoryCallback& callback) {
+    ReadDirectoryCallback callback) {
   FileSystemOperationContext* context_ptr = context.release();
   const bool success = context_ptr->task_runner()->PostTask(
       FROM_HERE,
@@ -239,14 +240,13 @@
     const FileSystemURL& url,
     const base::Time& last_access_time,
     const base::Time& last_modified_time,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   FileSystemOperationContext* context_ptr = context.release();
   const bool success = base::PostTaskAndReplyWithResult(
       context_ptr->task_runner(), FROM_HERE,
       Bind(&FileSystemFileUtil::Touch, Unretained(sync_file_util_.get()),
-           base::Owned(context_ptr), url,
-           last_access_time, last_modified_time),
-      callback);
+           base::Owned(context_ptr), url, last_access_time, last_modified_time),
+      std::move(callback));
   DCHECK(success);
 }
 
@@ -254,13 +254,13 @@
     std::unique_ptr<FileSystemOperationContext> context,
     const FileSystemURL& url,
     int64_t length,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   FileSystemOperationContext* context_ptr = context.release();
   const bool success = base::PostTaskAndReplyWithResult(
       context_ptr->task_runner(), FROM_HERE,
       Bind(&FileSystemFileUtil::Truncate, Unretained(sync_file_util_.get()),
            base::Owned(context_ptr), url, length),
-      callback);
+      std::move(callback));
   DCHECK(success);
 }
 
@@ -269,16 +269,16 @@
     const FileSystemURL& src_url,
     const FileSystemURL& dest_url,
     CopyOrMoveOption option,
-    const CopyFileProgressCallback& progress_callback,
-    const StatusCallback& callback) {
+    CopyFileProgressCallback progress_callback,
+    StatusCallback callback) {
   // TODO(hidehiko): Support progress_callback.
   FileSystemOperationContext* context_ptr = context.release();
   const bool success = base::PostTaskAndReplyWithResult(
       context_ptr->task_runner(), FROM_HERE,
       Bind(&FileSystemFileUtil::CopyOrMoveFile,
-           Unretained(sync_file_util_.get()), base::Owned(context_ptr),
-           src_url, dest_url, option, true /* copy */),
-      callback);
+           Unretained(sync_file_util_.get()), base::Owned(context_ptr), src_url,
+           dest_url, option, true /* copy */),
+      std::move(callback));
   DCHECK(success);
 }
 
@@ -287,14 +287,14 @@
     const FileSystemURL& src_url,
     const FileSystemURL& dest_url,
     CopyOrMoveOption option,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   FileSystemOperationContext* context_ptr = context.release();
   const bool success = base::PostTaskAndReplyWithResult(
       context_ptr->task_runner(), FROM_HERE,
       Bind(&FileSystemFileUtil::CopyOrMoveFile,
-           Unretained(sync_file_util_.get()), base::Owned(context_ptr),
-           src_url, dest_url, option, false /* copy */),
-      callback);
+           Unretained(sync_file_util_.get()), base::Owned(context_ptr), src_url,
+           dest_url, option, false /* copy */),
+      std::move(callback));
   DCHECK(success);
 }
 
@@ -302,63 +302,62 @@
     std::unique_ptr<FileSystemOperationContext> context,
     const base::FilePath& src_file_path,
     const FileSystemURL& dest_url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   FileSystemOperationContext* context_ptr = context.release();
   const bool success = base::PostTaskAndReplyWithResult(
       context_ptr->task_runner(), FROM_HERE,
       Bind(&FileSystemFileUtil::CopyInForeignFile,
-           Unretained(sync_file_util_.get()),
-           base::Owned(context_ptr), src_file_path, dest_url),
-      callback);
+           Unretained(sync_file_util_.get()), base::Owned(context_ptr),
+           src_file_path, dest_url),
+      std::move(callback));
   DCHECK(success);
 }
 
 void AsyncFileUtilAdapter::DeleteFile(
     std::unique_ptr<FileSystemOperationContext> context,
     const FileSystemURL& url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   FileSystemOperationContext* context_ptr = context.release();
   const bool success = base::PostTaskAndReplyWithResult(
       context_ptr->task_runner(), FROM_HERE,
-      Bind(&FileSystemFileUtil::DeleteFile,
-           Unretained(sync_file_util_.get()),
+      Bind(&FileSystemFileUtil::DeleteFile, Unretained(sync_file_util_.get()),
            base::Owned(context_ptr), url),
-      callback);
+      std::move(callback));
   DCHECK(success);
 }
 
 void AsyncFileUtilAdapter::DeleteDirectory(
     std::unique_ptr<FileSystemOperationContext> context,
     const FileSystemURL& url,
-    const StatusCallback& callback) {
+    StatusCallback callback) {
   FileSystemOperationContext* context_ptr = context.release();
   const bool success = base::PostTaskAndReplyWithResult(
       context_ptr->task_runner(), FROM_HERE,
       Bind(&FileSystemFileUtil::DeleteDirectory,
-           Unretained(sync_file_util_.get()),
-           base::Owned(context_ptr), url),
-      callback);
+           Unretained(sync_file_util_.get()), base::Owned(context_ptr), url),
+      std::move(callback));
   DCHECK(success);
 }
 
 void AsyncFileUtilAdapter::DeleteRecursively(
     std::unique_ptr<FileSystemOperationContext> context,
     const FileSystemURL& url,
-    const StatusCallback& callback) {
-  callback.Run(base::File::FILE_ERROR_INVALID_OPERATION);
+    StatusCallback callback) {
+  std::move(callback).Run(base::File::FILE_ERROR_INVALID_OPERATION);
 }
 
 void AsyncFileUtilAdapter::CreateSnapshotFile(
     std::unique_ptr<FileSystemOperationContext> context,
     const FileSystemURL& url,
-    const CreateSnapshotFileCallback& callback) {
+    CreateSnapshotFileCallback callback) {
   FileSystemOperationContext* context_ptr = context.release();
   GetFileInfoHelper* helper = new GetFileInfoHelper;
   const bool success = context_ptr->task_runner()->PostTaskAndReply(
       FROM_HERE,
       BindOnce(&GetFileInfoHelper::CreateSnapshotFile, Unretained(helper),
                sync_file_util_.get(), base::Owned(context_ptr), url),
-      BindOnce(&GetFileInfoHelper::ReplySnapshotFile, Owned(helper), callback));
+      BindOnce(&GetFileInfoHelper::ReplySnapshotFile, Owned(helper),
+               std::move(callback)));
   DCHECK(success);
 }
 
diff --git a/storage/browser/fileapi/async_file_util_adapter.h b/storage/browser/fileapi/async_file_util_adapter.h
index 4a3649f..76231644a 100644
--- a/storage/browser/fileapi/async_file_util_adapter.h
+++ b/storage/browser/fileapi/async_file_util_adapter.h
@@ -45,58 +45,58 @@
   void CreateOrOpen(std::unique_ptr<FileSystemOperationContext> context,
                     const FileSystemURL& url,
                     int file_flags,
-                    const CreateOrOpenCallback& callback) override;
+                    CreateOrOpenCallback callback) override;
   void EnsureFileExists(std::unique_ptr<FileSystemOperationContext> context,
                         const FileSystemURL& url,
-                        const EnsureFileExistsCallback& callback) override;
+                        EnsureFileExistsCallback callback) override;
   void CreateDirectory(std::unique_ptr<FileSystemOperationContext> context,
                        const FileSystemURL& url,
                        bool exclusive,
                        bool recursive,
-                       const StatusCallback& callback) override;
+                       StatusCallback callback) override;
   void GetFileInfo(std::unique_ptr<FileSystemOperationContext> context,
                    const FileSystemURL& url,
                    int /* fields */,
-                   const GetFileInfoCallback& callback) override;
+                   GetFileInfoCallback callback) override;
   void ReadDirectory(std::unique_ptr<FileSystemOperationContext> context,
                      const FileSystemURL& url,
-                     const ReadDirectoryCallback& callback) override;
+                     ReadDirectoryCallback callback) override;
   void Touch(std::unique_ptr<FileSystemOperationContext> context,
              const FileSystemURL& url,
              const base::Time& last_access_time,
              const base::Time& last_modified_time,
-             const StatusCallback& callback) override;
+             StatusCallback callback) override;
   void Truncate(std::unique_ptr<FileSystemOperationContext> context,
                 const FileSystemURL& url,
                 int64_t length,
-                const StatusCallback& callback) override;
+                StatusCallback callback) override;
   void CopyFileLocal(std::unique_ptr<FileSystemOperationContext> context,
                      const FileSystemURL& src_url,
                      const FileSystemURL& dest_url,
                      CopyOrMoveOption option,
-                     const CopyFileProgressCallback& progress_callback,
-                     const StatusCallback& callback) override;
+                     CopyFileProgressCallback progress_callback,
+                     StatusCallback callback) override;
   void MoveFileLocal(std::unique_ptr<FileSystemOperationContext> context,
                      const FileSystemURL& src_url,
                      const FileSystemURL& dest_url,
                      CopyOrMoveOption option,
-                     const StatusCallback& callback) override;
+                     StatusCallback callback) override;
   void CopyInForeignFile(std::unique_ptr<FileSystemOperationContext> context,
                          const base::FilePath& src_file_path,
                          const FileSystemURL& dest_url,
-                         const StatusCallback& callback) override;
+                         StatusCallback callback) override;
   void DeleteFile(std::unique_ptr<FileSystemOperationContext> context,
                   const FileSystemURL& url,
-                  const StatusCallback& callback) override;
+                  StatusCallback callback) override;
   void DeleteDirectory(std::unique_ptr<FileSystemOperationContext> context,
                        const FileSystemURL& url,
-                       const StatusCallback& callback) override;
+                       StatusCallback callback) override;
   void DeleteRecursively(std::unique_ptr<FileSystemOperationContext> context,
                          const FileSystemURL& url,
-                         const StatusCallback& callback) override;
+                         StatusCallback callback) override;
   void CreateSnapshotFile(std::unique_ptr<FileSystemOperationContext> context,
                           const FileSystemURL& url,
-                          const CreateSnapshotFileCallback& callback) override;
+                          CreateSnapshotFileCallback callback) override;
 
  private:
   std::unique_ptr<FileSystemFileUtil> sync_file_util_;
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index 60c62dd..89e1ab8 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -651,12 +651,6 @@
         "swarming": {
           "can_use_on_swarming_builders": false
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
         "test": "components_unittests"
       },
       {
@@ -840,12 +834,6 @@
         "swarming": {
           "can_use_on_swarming_builders": false
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
         "test": "components_unittests"
       },
       {
@@ -1230,32 +1218,6 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "components_perftests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_os": "LMY47W",
-              "device_type": "sprout"
-            }
-          ],
-          "expiration": 14400
-        },
-        "test": "components_perftests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
             "components_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -2273,50 +2235,6 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "components_perftests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NRD91N",
-              "device_type": "bullhead"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "components_perftests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
             "components_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -3496,12 +3414,6 @@
         "swarming": {
           "can_use_on_swarming_builders": false
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
         "test": "components_unittests"
       },
       {
@@ -3696,12 +3608,6 @@
         "swarming": {
           "can_use_on_swarming_builders": false
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
         "test": "components_unittests"
       },
       {
@@ -4127,30 +4033,6 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "components_perftests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
-        "test": "components_perftests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
             "components_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -5214,30 +5096,6 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "components_perftests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "gce_x86"
-            }
-          ]
-        },
-        "test": "components_perftests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
             "components_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index a454c8fe..0d87789 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -987,48 +987,6 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "components_perftests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "KTU84P",
-              "device_type": "hammerhead"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "components_perftests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
             "components_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -2670,48 +2628,6 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "components_perftests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "KTU84P",
-              "device_type": "hammerhead"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "components_perftests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
             "components_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -4206,49 +4122,6 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "components_perftests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "KTU84Z",
-              "device_type": "flo"
-            }
-          ],
-          "expiration": 10800,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "components_perftests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
             "components_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -5757,50 +5630,6 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "components_perftests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "LMY48I",
-              "device_type": "hammerhead"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "components_perftests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
             "components_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -7352,50 +7181,6 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "components_perftests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "LMY49B",
-              "device_type": "flo"
-            }
-          ],
-          "expiration": 10800,
-          "hard_timeout": 120,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "components_perftests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
             "components_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -8983,49 +8768,6 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "components_perftests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "hard_timeout": 960,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "components_perftests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
             "components_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -10543,48 +10285,6 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "components_perftests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "components_perftests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
             "components_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -11862,6 +11562,19 @@
     ],
     "isolated_scripts": [
       {
+        "isolate_name": "components_perftests",
+        "name": "components_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ]
+        }
+      },
+      {
         "isolate_name": "monochrome_apk_checker",
         "name": "monochrome_apk_checker",
         "swarming": {
@@ -12261,49 +11974,6 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "components_perftests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "MRA58Z",
-              "device_type": "flo"
-            }
-          ],
-          "expiration": 10800,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "components_perftests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
             "components_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index eea3b35..4564297 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -103,12 +103,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -507,12 +501,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -977,12 +965,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json
index 831b3f3..c83e54f 100644
--- a/testing/buildbot/chromium.clang.json
+++ b/testing/buildbot/chromium.clang.json
@@ -92,12 +92,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -481,12 +475,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -828,12 +816,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -1100,12 +1082,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -1365,12 +1341,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -1637,12 +1607,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -1945,12 +1909,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -2253,12 +2211,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -2561,12 +2513,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -2869,12 +2815,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -3177,12 +3117,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -3485,12 +3419,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -3793,12 +3721,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -4101,12 +4023,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -4403,12 +4319,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -5215,48 +5125,6 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "components_perftests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "KTU84P",
-              "device_type": "hammerhead"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "components_perftests"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
             "components_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -7363,18 +7231,6 @@
             }
           ]
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ]
-        },
         "test": "components_unittests"
       },
       {
@@ -7925,12 +7781,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -8274,12 +8124,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -8545,12 +8389,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -8894,12 +8732,6 @@
         "swarming": {
           "can_use_on_swarming_builders": false
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
         "test": "components_unittests"
       },
       {
@@ -9243,12 +9075,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "compositor_unittests"
       },
       {
@@ -9580,12 +9406,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -9817,6 +9637,13 @@
         }
       },
       {
+        "isolate_name": "components_perftests",
+        "name": "components_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        }
+      },
+      {
         "isolate_name": "telemetry_gpu_unittests",
         "name": "telemetry_gpu_unittests",
         "swarming": {
@@ -9938,12 +9765,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -10213,12 +10034,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -10533,12 +10348,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -10841,12 +10650,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -11149,12 +10952,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -11457,12 +11254,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -11765,12 +11556,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -12073,12 +11858,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -12381,12 +12160,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -12707,12 +12480,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -13033,12 +12800,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -13358,12 +13119,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "compositor_unittests"
       },
       {
@@ -13752,17 +13507,6 @@
             }
           ]
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Windows-10"
-            }
-          ]
-        },
         "test": "components_unittests"
       },
       {
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 280b5a6..c4943bed 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -405,12 +405,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -794,12 +788,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -1185,12 +1173,6 @@
         "swarming": {
           "can_use_on_swarming_builders": false
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
         "test": "components_unittests"
       },
       {
@@ -1454,6 +1436,13 @@
         }
       },
       {
+        "isolate_name": "components_perftests",
+        "name": "components_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": false
+        }
+      },
+      {
         "isolate_name": "telemetry_gpu_unittests",
         "name": "telemetry_gpu_unittests",
         "swarming": {
@@ -1586,12 +1575,6 @@
         "swarming": {
           "can_use_on_swarming_builders": false
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
         "test": "components_unittests"
       },
       {
@@ -1934,12 +1917,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -2206,6 +2183,13 @@
         }
       },
       {
+        "isolate_name": "components_perftests",
+        "name": "components_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        }
+      },
+      {
         "isolate_name": "telemetry_gpu_unittests",
         "name": "telemetry_gpu_unittests",
         "swarming": {
@@ -2384,12 +2368,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -2794,12 +2772,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -3066,12 +3038,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -3331,12 +3297,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -3758,7 +3718,8 @@
       },
       {
         "args": [
-          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.ui_base_unittests.filter"
+          "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.ui_base_unittests.filter",
+          "--use-new-test-runner"
         ],
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -4488,17 +4449,6 @@
             }
           ]
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-16.04"
-            }
-          ]
-        },
         "test": "components_unittests"
       },
       {
@@ -4875,8 +4825,7 @@
       },
       {
         "args": [
-          "--enable-features=NetworkService",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_interactive_ui_tests.filter"
+          "--enable-features=NetworkService"
         ],
         "name": "network_service_interactive_ui_tests",
         "swarming": {
@@ -6033,8 +5982,7 @@
       },
       {
         "args": [
-          "--enable-features=NetworkService",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_interactive_ui_tests.filter"
+          "--enable-features=NetworkService"
         ],
         "name": "network_service_interactive_ui_tests",
         "swarming": {
@@ -6277,17 +6225,6 @@
             }
           ]
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "coho"
-            }
-          ]
-        },
         "test": "components_unittests"
       },
       {
@@ -6755,12 +6692,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -7126,12 +7057,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -7397,6 +7322,13 @@
         }
       },
       {
+        "isolate_name": "components_perftests",
+        "name": "components_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        }
+      },
+      {
         "isolate_name": "telemetry_gpu_unittests",
         "name": "telemetry_gpu_unittests",
         "swarming": {
@@ -7500,12 +7432,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -8068,12 +7994,6 @@
         "swarming": {
           "can_use_on_swarming_builders": false
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
         "test": "components_unittests"
       },
       {
@@ -8502,12 +8422,6 @@
         "swarming": {
           "can_use_on_swarming_builders": false
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
         "test": "components_unittests"
       },
       {
@@ -8935,12 +8849,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -9082,11 +8990,6 @@
       }
     ]
   },
-  "linux-gcc-rel": {
-    "additional_compile_targets": [
-      "empty_main"
-    ]
-  },
   "mac-views-rel": {
     "gtest_tests": [
       {
@@ -9183,12 +9086,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json
index 5890556d0..620e4b4f 100644
--- a/testing/buildbot/chromium.gpu.fyi.json
+++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -167,6 +167,25 @@
     "isolated_scripts": [
       {
         "args": [
+          "-v",
+          "--one-frame-only"
+        ],
+        "isolate_name": "angle_perftests",
+        "name": "angle_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "O",
+              "device_type": "bullhead",
+              "os": "Android",
+              "pool": "Chrome-GPU"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
           "context_lost",
           "--show-stdout",
           "--browser=android-chromium",
@@ -622,6 +641,25 @@
     "isolated_scripts": [
       {
         "args": [
+          "-v",
+          "--one-frame-only"
+        ],
+        "isolate_name": "angle_perftests",
+        "name": "angle_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "O",
+              "device_type": "bullhead",
+              "os": "Android",
+              "pool": "Chrome-GPU"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
           "context_lost",
           "--show-stdout",
           "--browser=android-chromium",
@@ -1077,6 +1115,25 @@
     "isolated_scripts": [
       {
         "args": [
+          "-v",
+          "--one-frame-only"
+        ],
+        "isolate_name": "angle_perftests",
+        "name": "angle_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "N",
+              "device_type": "foster",
+              "os": "Android",
+              "pool": "Chrome-GPU"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
           "context_lost",
           "--show-stdout",
           "--browser=android-chromium",
@@ -1500,6 +1557,25 @@
     "isolated_scripts": [
       {
         "args": [
+          "-v",
+          "--one-frame-only"
+        ],
+        "isolate_name": "angle_perftests",
+        "name": "angle_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "L",
+              "device_type": "hammerhead",
+              "os": "Android",
+              "pool": "Chrome-GPU"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
           "context_lost",
           "--show-stdout",
           "--browser=android-chromium",
@@ -2319,6 +2395,25 @@
     "isolated_scripts": [
       {
         "args": [
+          "-v",
+          "--one-frame-only"
+        ],
+        "isolate_name": "angle_perftests",
+        "name": "angle_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "L",
+              "device_type": "shamu",
+              "os": "Android",
+              "pool": "Chrome-GPU"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
           "context_lost",
           "--show-stdout",
           "--browser=android-chromium",
@@ -3216,6 +3311,25 @@
     "isolated_scripts": [
       {
         "args": [
+          "-v",
+          "--one-frame-only"
+        ],
+        "isolate_name": "angle_perftests",
+        "name": "angle_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "M",
+              "device_type": "flounder",
+              "os": "Android",
+              "pool": "Chrome-GPU"
+            }
+          ]
+        }
+      },
+      {
+        "args": [
           "context_lost",
           "--show-stdout",
           "--browser=android-chromium",
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json
index 32d2a65..f6d85ee 100644
--- a/testing/buildbot/chromium.linux.json
+++ b/testing/buildbot/chromium.linux.json
@@ -86,12 +86,6 @@
         "test": "cast_shell_unittests"
       },
       {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_perftests"
-      },
-      {
         "args": [
           "--test-launcher-filter-file=src/testing/buildbot/filters/cast-linux.content_browsertests.filter"
         ],
@@ -307,12 +301,6 @@
         "test": "cast_shell_unittests"
       },
       {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_perftests"
-      },
-      {
         "args": [
           "--test-launcher-filter-file=src/testing/buildbot/filters/cast-linux.content_browsertests.filter"
         ],
@@ -795,12 +783,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -1026,8 +1008,7 @@
       },
       {
         "args": [
-          "--enable-features=NetworkService",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_interactive_ui_tests.filter"
+          "--enable-features=NetworkService"
         ],
         "name": "network_service_interactive_ui_tests",
         "swarming": {
@@ -1601,12 +1582,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -1833,8 +1808,7 @@
       },
       {
         "args": [
-          "--enable-features=NetworkService",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_interactive_ui_tests.filter"
+          "--enable-features=NetworkService"
         ],
         "name": "network_service_interactive_ui_tests",
         "swarming": {
@@ -2284,12 +2258,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -2429,8 +2397,7 @@
       },
       {
         "args": [
-          "--enable-features=NetworkService",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_interactive_ui_tests.filter"
+          "--enable-features=NetworkService"
         ],
         "name": "network_service_interactive_ui_tests",
         "swarming": {
@@ -2682,5 +2649,10 @@
         "test": "services_unittests"
       }
     ]
+  },
+  "linux-gcc-rel": {
+    "additional_compile_targets": [
+      "empty_main"
+    ]
   }
 }
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json
index d3ed639..afaa17a0 100644
--- a/testing/buildbot/chromium.mac.json
+++ b/testing/buildbot/chromium.mac.json
@@ -109,12 +109,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -406,6 +400,13 @@
         }
       },
       {
+        "isolate_name": "components_perftests",
+        "name": "components_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        }
+      },
+      {
         "isolate_name": "telemetry_gpu_unittests",
         "name": "telemetry_gpu_unittests",
         "swarming": {
@@ -575,12 +576,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -860,6 +855,13 @@
         }
       },
       {
+        "isolate_name": "components_perftests",
+        "name": "components_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        }
+      },
+      {
         "isolate_name": "telemetry_gpu_unittests",
         "name": "telemetry_gpu_unittests",
         "swarming": {
@@ -1017,12 +1019,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -1314,6 +1310,13 @@
         }
       },
       {
+        "isolate_name": "components_perftests",
+        "name": "components_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        }
+      },
+      {
         "isolate_name": "telemetry_gpu_unittests",
         "name": "telemetry_gpu_unittests",
         "swarming": {
@@ -1484,12 +1487,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -1782,6 +1779,13 @@
         }
       },
       {
+        "isolate_name": "components_perftests",
+        "name": "components_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        }
+      },
+      {
         "experiment_percentage": 100,
         "isolate_name": "content_shell_crash_test",
         "name": "content_shell_crash_test",
@@ -1939,12 +1943,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index 3e60dd76..0ae0624 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -133,18 +133,6 @@
             }
           ]
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_os": "MMB29Q",
-              "device_type": "bullhead"
-            }
-          ]
-        },
         "test": "components_unittests"
       },
       {
@@ -720,16 +708,6 @@
           "--test-launcher-print-test-stdio=always"
         ],
         "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_perftests"
-      },
-      {
-        "args": [
-          "--test-launcher-batch-limit=1",
-          "--test-launcher-print-test-stdio=always"
-        ],
-        "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 5
         },
@@ -1217,12 +1195,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -1626,12 +1598,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -1992,12 +1958,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -2310,12 +2270,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -2638,12 +2592,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -2940,12 +2888,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json
index 890baed..82bb391 100644
--- a/testing/buildbot/chromium.perf.json
+++ b/testing/buildbot/chromium.perf.json
@@ -32020,27 +32020,6 @@
         }
       },
       {
-        "args": [],
-        "isolate_name": "views_perftests",
-        "name": "views_perftests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "10de:1cb3",
-              "id": "build31-a9",
-              "os": "Ubuntu-14.04",
-              "pool": "Chrome-perf"
-            }
-          ],
-          "expiration": 36000,
-          "hard_timeout": 10800,
-          "ignore_task_failure": false,
-          "io_timeout": 1200,
-          "upload_test_results": true
-        }
-      },
-      {
         "args": [
           "wasm",
           "-v",
diff --git a/testing/buildbot/chromium.webrtc.json b/testing/buildbot/chromium.webrtc.json
index 0e6536b..6c289163 100644
--- a/testing/buildbot/chromium.webrtc.json
+++ b/testing/buildbot/chromium.webrtc.json
@@ -12,11 +12,6 @@
       "remoting_unittests"
     ]
   },
-  "Linux Builder (Chromium w/o WebRTC)": {
-    "additional_compile_targets": [
-      "chrome"
-    ]
-  },
   "Mac Builder": {
     "additional_compile_targets": [
       "browser_tests",
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json
index 97cc92da..a8145a02 100644
--- a/testing/buildbot/chromium.win.json
+++ b/testing/buildbot/chromium.win.json
@@ -122,12 +122,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -542,6 +536,13 @@
         }
       },
       {
+        "isolate_name": "components_perftests",
+        "name": "components_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        }
+      },
+      {
         "isolate_name": "metrics_python_tests",
         "name": "metrics_python_tests",
         "swarming": {
@@ -723,12 +724,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -1253,12 +1248,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -1925,12 +1914,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
@@ -2357,6 +2340,13 @@
         }
       },
       {
+        "isolate_name": "components_perftests",
+        "name": "components_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        }
+      },
+      {
         "isolate_name": "content_shell_crash_test",
         "name": "content_shell_crash_test",
         "swarming": {
@@ -2534,12 +2524,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "components_perftests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "components_unittests"
       },
       {
diff --git a/testing/buildbot/filters/BUILD.gn b/testing/buildbot/filters/BUILD.gn
index 9940bb6..e7abb4d64 100644
--- a/testing/buildbot/filters/BUILD.gn
+++ b/testing/buildbot/filters/BUILD.gn
@@ -59,7 +59,6 @@
   testonly = true
 
   data = [
-    "//testing/buildbot/filters/mojo.fyi.network_interactive_ui_tests.filter",
     "//testing/buildbot/filters/site-per-process.interactive_ui_tests.filter",
   ]
 }
diff --git a/testing/buildbot/filters/fuchsia.content_unittests.filter b/testing/buildbot/filters/fuchsia.content_unittests.filter
index 1427860..67db632 100644
--- a/testing/buildbot/filters/fuchsia.content_unittests.filter
+++ b/testing/buildbot/filters/fuchsia.content_unittests.filter
@@ -30,9 +30,6 @@
 -MediaStreamManagerTest.MakeMediaAccessRequest
 -MediaStreamManagerTest.MakeMultipleRequests
 
-# Flaky: http://crbug.com/819924.
--WebMediaPlayerMSTest.*HardwareFrames*
-
 # Failing: https://crbug.com/771701.
 -IndexedDBFactoryTest.DataFormatVersion
 
diff --git a/testing/buildbot/filters/mash.browser_tests.filter b/testing/buildbot/filters/mash.browser_tests.filter
index 2811cb0b..30cb13c 100644
--- a/testing/buildbot/filters/mash.browser_tests.filter
+++ b/testing/buildbot/filters/mash.browser_tests.filter
@@ -286,3 +286,7 @@
 # Segfaults after massive recursion setting ash::kWindowStateTypeKey:
 # crbug.com/824458
 -PresentationReceiverWindowViewBrowserTest.ChromeOSHardwareFullscreenButton
+
+# RenderFrameMetadata observation not supported: https://crbug.com/820974
+-WebViewGuestScrollLatchingTest.ScrollLatchingPreservedInGuests
+-WebViewScrollGuestContent/WebViewScrollGuestContentTest.OverscrollControllerSeesConsumedScrollsInGuest/0
diff --git a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
index c64d148..5a8638d 100644
--- a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
+++ b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
@@ -14,12 +14,7 @@
 -ExtensionApiTest.Debugger
 -ExtensionApiTestWithSwitch.ExtensionDebugger
 -ExtensionUnloadBrowserTest.UnloadWithContentScripts
--InstantThemeTest.ThemeBackgroundAccess
--LocalNTPJavascriptTest.SimpleJavascriptTests
--LocalNTPVoiceJavascriptTest.MicrophoneTests
--LocalNTPVoiceJavascriptTest.SpeechTests
 -LocalNTPVoiceJavascriptTest.TextTests
--LocalNTPVoiceJavascriptTest.ViewTests
 -MediaGalleriesPlatformAppBrowserTest.ToURL
 -NetInternalsTest.netInternalsSessionBandwidthSucceed
 -NewlibPackagedAppTest.SuccessfulLoad
@@ -140,9 +135,6 @@
 # crbug.com/778860 SecurityStyleExplanations::info_explanations is empty.
 -BrowserTestNonsecureURLRequest.DidChangeVisibleSecurityStateObserverObsoleteTLSSettings
 
-# crbug.com/779217 The NetworkContext is not created when the network service is enabled.
--SpellingMenuObserverTest.SuggestionsForceTopSeparator
-
 # http://crbug.com/783990
 # Add support for http auth.
 -DownloadExtensionTest.DownloadExtensionTest_Download_AuthBasic_Fail
@@ -183,6 +175,13 @@
 -ExtensionWebRequestApiTest.WebRequestDiceHeaderProtection
 -ExtensionWebRequestApiTest.WebRequestTypes
 
+# https://crbug.com/721400
+# WebSocket with the network service
+-DeclarativeNetRequestResourceTypeBrowserTest.Test2/1
+-DeclarativeNetRequestResourceTypeBrowserTest.Test2/0
+-ExtensionWebRequestApiTest.WebSocketRequestAuthRequired
+-ExtensionWebRequestApiTest.WebSocketRequest
+
 # http://crbug.com/705114
 # Remove streams concept from code and replace with data pipe passing.
 -MimeHandlerViewTests/MimeHandlerViewTest.Abort/0
@@ -327,3 +326,10 @@
 # Flaky in linux tests.
 # https://crbug.com/820995
 -PlatformAppBrowserTest.Restrictions
+
+# Tests check state of NQE in the browser process, but need to be updated to
+# watch NQE in the renderer process.
+# https://crbug.com/819244
+-IOThreadEctCommandLineBrowserTest.ForceECTFromCommandLine
+-IOThreadEctFieldTrialAndCommandLineBrowserTest.ECTFromCommandLineOverridesFieldTrial
+-IOThreadEctFieldTrialBrowserTest.ForceECTUsingFieldTrial
diff --git a/testing/buildbot/filters/mojo.fyi.network_interactive_ui_tests.filter b/testing/buildbot/filters/mojo.fyi.network_interactive_ui_tests.filter
deleted file mode 100644
index 4b26a13..0000000
--- a/testing/buildbot/filters/mojo.fyi.network_interactive_ui_tests.filter
+++ /dev/null
@@ -1,4 +0,0 @@
-# These tests currently fail when run with enablefeatures=NetworkService

-# See https://crbug.com/819249

-

--LocalNTPUITest.FakeboxRedirectsToOmnibox

diff --git a/testing/buildbot/filters/viz.browser_tests.filter b/testing/buildbot/filters/viz.browser_tests.filter
index 8214df9e..80f8938 100644
--- a/testing/buildbot/filters/viz.browser_tests.filter
+++ b/testing/buildbot/filters/viz.browser_tests.filter
@@ -30,12 +30,6 @@
 -WebViewTests/WebViewTest.InterstitialPageFocusedWidget/1
 -WebViewTests/WebViewTest.ReloadAfterCrash/1
 
-# WebViewBrowserTest::ScrollWaiter Doesn't Work in Viz crbug.com/796336
--WebViewScrollBubbling/WebViewGuestScrollTouchTest.TestGuestGestureScrollsBubble/0
--WebViewScrollBubbling/WebViewGuestScrollTouchTest.TestGuestGestureScrollsBubble/1
--WebViewScrollBubbling/WebViewGuestScrollTouchTest.TestGuestGestureScrollsBubble/2
--WebViewScrollBubbling/WebViewGuestScrollTouchTest.TestGuestGestureScrollsBubble/3
-
 #### FrameSinkManager Crashes
 # FrameSinkManagerImpl::RegisterFrameSinkHierarchy Crash crbug.com/796344
 # Linux and Windows failures
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index a3cbb7e2..c427a11 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -387,7 +387,12 @@
   },
   "components_perftests": {
     "label": "//components:components_perftests",
-    "type": "windowed_test_launcher",
+    "type": "script",
+    "script": "//testing/scripts/run_gtest_perf_test.py",
+    "args": [
+      "--xvfb",
+      "components_perftests",
+    ],
   },
   "components_variations_junit_tests": {
     "label": "//components/variations/android:components_variations_junit_tests",
@@ -774,6 +779,17 @@
     "label": "//media/blink:media_blink_unittests",
     "type": "windowed_test_launcher",
   },
+  "media_router_e2e_tests": {
+    "label": "//chrome/test/media_router:media_router_e2e_tests",
+    "type": "script",
+    "script": "//chrome/test/media_router/internal/media_router_tests.py",
+    "args": [
+      "--extension",
+      "mr_extension/",
+      "--test_binary",
+      "./browser_tests",
+    ],
+  },
   "media_router_perf_tests": {
     "label": "//chrome/test/media_router:media_router_perf_tests",
     "type": "script",
@@ -787,17 +803,6 @@
       "--output-dir=${ISOLATED_OUTDIR}",
     ],
   },
-  "media_router_tests": {
-    "label": "//chrome/test/media_router:media_router_e2e_tests",
-    "type": "script",
-    "script": "//chrome/test/media_router/internal/media_router_tests.py",
-    "args": [
-      "--extension",
-      "mr_extension/",
-      "--test_binary",
-      "./browser_tests",
-    ],
-  },
   "microdump_stackwalk" : {
     "label": "//third_party/breakpad:microdump_stackwalk",
     "type": "additional_compile_target",
diff --git a/testing/buildbot/manage.py b/testing/buildbot/manage.py
index b8fc3e6..8bdc541f 100755
--- a/testing/buildbot/manage.py
+++ b/testing/buildbot/manage.py
@@ -126,8 +126,8 @@
   'content_junit_tests',
   'device_junit_tests',
   'junit_unit_tests',
+  'media_router_e2e_tests',
   'media_router_perf_tests',
-  'media_router_tests',
   'motopho_latency_test',
   'net_junit_tests',
   'net_junit_tests',
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index 9ff52d2..88d63f48 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -3349,6 +3349,12 @@
           'hard_timeout': 120,
         },
       },
+      # chromium.fyi
+      'Fuchsia': {
+        'args': [
+          '--use-new-test-runner',
+        ],
+      },
     },
   },
   'ui_touch_selection_unittests': {
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 0eb31e0a..547e0ef2 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -404,7 +404,6 @@
         'shards': 2,
       },
     },
-    'components_perftests': {},
     'content_browsertests': {
       'android_swarming': {
         'hard_timeout': 1500,
@@ -1197,8 +1196,7 @@
     },
     'network_service_interactive_ui_tests': {
       'args': [
-        '--enable-features=NetworkService',
-        '--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_interactive_ui_tests.filter',
+        '--enable-features=NetworkService'
       ],
       'test': 'interactive_ui_tests',
     },
@@ -1649,6 +1647,10 @@
     },
   },
 
+  'components_perftests_isolated_scripts' : {
+    'components_perftests': {},
+  },
+
   'telemetry_perf_unittests_scripts': {
     'telemetry_perf_unittests': {
       'script': 'telemetry_perf_unittests.py',
@@ -1867,6 +1869,7 @@
 
   'chromium_rel_isolated_scripts': [
     'chromedriver_py_tests_isolated_scripts',
+    'components_perftests_isolated_scripts',
     'desktop_chromium_isolated_scripts',
     'telemetry_perf_unittests_isolated_scripts',
   ],
@@ -2301,6 +2304,7 @@
   ],
 
   'marshmallow_isolated_scripts': [
+    'components_perftests_isolated_scripts',
     'monochrome_apk_checker_isolated_script',
     'telemetry_perf_unittests_isolated_scripts',
   ],
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index 26a8272d..fd025a8 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -933,11 +933,6 @@
           'gtest_tests': 'chromium_linux_clang_and_gl_gtests',
         },
       },
-      'linux-gcc-rel': {
-        'additional_compile_targets': [
-          'empty_main',
-        ],
-      },
       'linux-annotator-rel': {
         'test_suites': {
           'scripts': 'check_network_annotation_auditor_script',
@@ -1511,6 +1506,11 @@
           'gtest_tests': 'ozone_linux_gtests',
         },
       },
+      'linux-gcc-rel': {
+        'additional_compile_targets': [
+          'empty_main',
+        ],
+      },
     },
   },
   {
@@ -1920,11 +1920,6 @@
           'remoting_unittests',
         ],
       },
-      'Linux Builder (Chromium w/o WebRTC)': {
-        'additional_compile_targets': [
-          'chrome',
-        ],
-      },
       'Mac Builder': {
         'additional_compile_targets': [
           'browser_tests',
diff --git a/testing/libfuzzer/fuzzers/BUILD.gn b/testing/libfuzzer/fuzzers/BUILD.gn
index c56d538b..61f6006 100644
--- a/testing/libfuzzer/fuzzers/BUILD.gn
+++ b/testing/libfuzzer/fuzzers/BUILD.gn
@@ -62,18 +62,6 @@
   libfuzzer_options = [ "max_len=4096" ]
 }
 
-fuzzer_test("url_parse_fuzzer") {
-  sources = [
-    "url_parse_fuzzer.cc",
-  ]
-  deps = [
-    "//base",
-    "//base:i18n",
-    "//url:url",
-  ]
-  dict = "dicts/generated/url_parse_fuzzer.dict"
-}
-
 fuzzer_test("url_parse_proto_fuzzer") {
   sources = [
     "url_parse_proto_fuzzer.cc",
diff --git a/testing/libfuzzer/fuzzers/url_parse_fuzzer.cc b/testing/libfuzzer/fuzzers/url_parse_fuzzer.cc
deleted file mode 100644
index e2e814da6..0000000
--- a/testing/libfuzzer/fuzzers/url_parse_fuzzer.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "base/at_exit.h"
-#include "base/i18n/icu_util.h"
-#include "url/gurl.h"
-
-struct TestCase {
-  TestCase() {
-    CHECK(base::i18n::InitializeICU());
-  }
-
-  // used by ICU integration.
-  base::AtExitManager at_exit_manager;
-};
-
-TestCase* test_case = new TestCase();
-
-// Entry point for LibFuzzer.
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  GURL url(std::string(reinterpret_cast<const char*>(data), size));
-  return 0;
-}
diff --git a/testing/libfuzzer/proto/lpm_interface.h b/testing/libfuzzer/proto/lpm_interface.h
new file mode 100644
index 0000000..22f2ea11
--- /dev/null
+++ b/testing/libfuzzer/proto/lpm_interface.h
@@ -0,0 +1,16 @@
+// Copyright 2018 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.
+
+// Header file that includes libfuzzer_macro.h from libprotobuf-mutator. Useful
+// for inclusion in fuzz targets that can't include headers from third_party/.
+
+#ifndef TESTING_LIBFUZZER_PROTO_LPM_INTERFACE_H_
+#define TESTING_LIBFUZZER_PROTO_LPM_INTERFACE_H_
+
+#include "third_party/libprotobuf-mutator/src/src/libfuzzer/libfuzzer_macro.h"
+
+// Silence logging from the protobuf library.
+protobuf_mutator::protobuf::LogSilencer log_silencer;
+
+#endif  // TESTING_LIBFUZZER_PROTO_LPM_INTERFACE_H_
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index c2acffa8..501cee25 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -92,30 +92,6 @@
             ]
         }
     ],
-    "AndroidInProductHelpChromeHomeMenuHeader": [
-        {
-            "platforms": [
-                "android"
-            ],
-            "experiments": [
-                {
-                    "name": "Tracking",
-                    "params": {
-                        "availability": "any",
-                        "event_1": "name:bottom_sheet_expanded;comparator:<50;window:680;storage:680",
-                        "event_3": "name:chrome_home_non_home_content_shown;comparator:<20;window:680;storage:680",
-                        "event_trigger": "name:chrome_home_menu_header_iph_trigger;comparator:<100;window:680;storage:680",
-                        "event_used": "name:chrome_home_menu_header_clicked;comparator:<20;window:680;storage:680",
-                        "session_rate": "any",
-                        "session_rate_impact": "none"
-                    },
-                    "enable_features": [
-                        "IPH_ChromeHomeMenuHeader"
-                    ]
-                }
-            ]
-        }
-    ],
     "AndroidInProductHelpChromeHomePullToRefresh": [
         {
             "platforms": [
@@ -386,6 +362,26 @@
             ]
         }
     ],
+    "AutofillCreditCardBankNameDisplay": [
+        {
+            "platforms": [
+                "android",
+                "chromeos",
+                "ios",
+                "linux",
+                "mac",
+                "win"
+            ],
+            "experiments": [
+                {
+                    "name": "BankName_Experiment",
+                    "enable_features": [
+                        "AutofillCreditCardBankNameDisplay"
+                    ]
+                }
+            ]
+        }
+    ],
     "AutofillCreditCardSigninPromo": [
         {
             "platforms": [
@@ -2209,6 +2205,21 @@
             ]
         }
     ],
+    "OfflinePagesDescriptivePendingStatus": [
+        {
+            "platforms": [
+                "android"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "OfflinePagesDescriptivePendingStatus"
+                    ]
+                }
+            ]
+        }
+    ],
     "OfflinePagesPrefetchingSuggestions": [
         {
             "platforms": [
diff --git a/third_party/BUILD.gn b/third_party/BUILD.gn
index 7fccf382..f0a8651 100644
--- a/third_party/BUILD.gn
+++ b/third_party/BUILD.gn
@@ -4,18 +4,10 @@
 
 import("//build/config/freetype/freetype.gni")
 import("//third_party/harfbuzz-ng/harfbuzz.gni")
+import("//third_party/libjpeg.gni")
 
 assert(!is_ios, "This is not used on iOS, don't drag it in unintentionally")
 
-declare_args() {
-  # Uses system libjpeg. If true, overrides use_libjpeg_turbo.
-  use_system_libjpeg = false
-
-  # Uses libjpeg_turbo as the jpeg implementation. Has no effect if
-  # use_system_libjpeg is set.
-  use_libjpeg_turbo = true
-}
-
 config("system_libjpeg_config") {
   libs = [ "jpeg" ]
   defines = [ "USE_SYSTEM_LIBJPEG" ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/disable-blink-features=RootLayerScrolling b/third_party/WebKit/LayoutTests/FlagExpectations/disable-blink-features=RootLayerScrolling
index 741db51..4cfb0a0 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/disable-blink-features=RootLayerScrolling
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/disable-blink-features=RootLayerScrolling
@@ -1042,14 +1042,6 @@
 crbug.com/492664 external/wpt/css/css-writing-modes/line-box-height-vlr-023.xht [ Failure ]
 crbug.com/492664 external/wpt/css/css-writing-modes/ortho-htb-alongside-vrl-floats-006.xht [ Failure ]
 crbug.com/492664 external/wpt/css/css-writing-modes/ortho-htb-alongside-vrl-floats-014.xht [ Failure ]
-crbug.com/492664 external/wpt/css/css-writing-modes/table-column-order-002.xht [ Failure ]
-crbug.com/492664 external/wpt/css/css-writing-modes/table-column-order-003.xht [ Failure ]
-crbug.com/492664 external/wpt/css/css-writing-modes/table-column-order-004.xht [ Failure ]
-crbug.com/492664 external/wpt/css/css-writing-modes/table-column-order-005.xht [ Failure ]
-crbug.com/492664 external/wpt/css/css-writing-modes/table-progression-vlr-003.html [ Failure ]
-crbug.com/492664 external/wpt/css/css-writing-modes/table-progression-vlr-004.html [ Failure ]
-crbug.com/492664 external/wpt/css/css-writing-modes/table-progression-vrl-003.html [ Failure ]
-crbug.com/492664 external/wpt/css/css-writing-modes/table-progression-vrl-004.html [ Failure ]
 
 crbug.com/637055 fast/css/outline-offset-large.html [ Skip ]
 
@@ -1641,7 +1633,6 @@
 crbug.com/626703 external/wpt/css/css-writing-modes/sizing-orthog-vrl-in-htb-004.xht [ Failure ]
 crbug.com/626703 external/wpt/css/css-writing-modes/sizing-orthog-vrl-in-htb-008.xht [ Failure ]
 crbug.com/626703 external/wpt/css/css-writing-modes/sizing-orthog-vrl-in-htb-020.xht [ Failure ]
-crbug.com/626703 external/wpt/css/css-writing-modes/wm-propagation-body-008.xht [ Failure ]
 
 crbug.com/655458 crbug.com/721814 external/wpt/mediacapture-image/idlharness.html [ Skip ]
 crbug.com/626703 external/wpt/web-nfc/idlharness.https.html [ Skip ]
@@ -1679,19 +1670,7 @@
 crbug.com/805463 external/wpt/acid/acid3/numbered-tests.html [ Skip ]
 
 # ====== New tests from wpt-importer added here ======
-crbug.com/626703 external/wpt/css/css-writing-modes/logical-props-001.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-writing-modes/ch-units-vrl-004.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-writing-modes/ch-units-vrl-006.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-writing-modes/ch-units-vrl-001.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-writing-modes/logical-props-004.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-writing-modes/logical-props-003.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-writing-modes/ch-units-vrl-008.html [ Failure ]
 crbug.com/626703 [ Android ] virtual/media-gpu-accelerated/external/wpt/media-source/mediasource-play.html [ Crash ]
-crbug.com/626703 external/wpt/css/css-writing-modes/ch-units-vrl-005.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-writing-modes/ch-units-vrl-007.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-writing-modes/logical-props-002.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-writing-modes/ch-units-vrl-003.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-writing-modes/ch-units-vrl-002.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-writing-modes/available-size-002.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-writing-modes/available-size-006.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-writing-modes/available-size-007.html [ Failure ]
@@ -1745,8 +1724,6 @@
 crbug.com/626703 external/wpt/css/css-grid/alignment/grid-gutters-005.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-grid/alignment/grid-gutters-007.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-grid/alignment/grid-gutters-009.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-writing-modes/table-cell-001.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-writing-modes/table-cell-002.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-fonts/font-synthesis-01.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-fonts/font-synthesis-02.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-fonts/font-synthesis-03.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
index 68b0288..cca773c 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -18,9 +18,6 @@
 # Slow when run with LayoutNG
 crbug.com/591099 external/wpt/css/css-color/color-resolving-hsl.html [ Timeout ]
 
-# Assert in ng_box_fragment_painter.cc(327)
-crbug.com/626703 fast/multicol/multicol-becomes-paged-auto-height.html [ Crash ]
-
 # TODO(skobes): rebaseline
 crbug.com/811429 fast/text/font-format-support-cbdt-sbix-cff2-vertical.html [ Failure ]
 crbug.com/811429 inspector-protocol/layout-fonts/cross-platform-cbdt-sbix-cff2.js [ Failure ]
@@ -117,7 +114,6 @@
 crbug.com/591099 compositing/iframes/floating-self-painting-frame.html [ Failure ]
 crbug.com/591099 compositing/layer-creation/rotate3d-overlap.html [ Failure ]
 crbug.com/591099 compositing/overflow/border-radius-above-composited-subframe.html [ Failure ]
-crbug.com/591099 compositing/overflow/get-transform-from-non-box-container.html [ Failure ]
 crbug.com/591099 compositing/overflow/nested-border-radius-clipping.html [ Failure ]
 crbug.com/591099 compositing/overflow/overflow-scroll-with-local-image-background.html [ Failure ]
 crbug.com/591099 compositing/overflow/scrolling-content-clip-to-viewport.html [ Failure ]
@@ -135,7 +131,7 @@
 crbug.com/591099 css1/box_properties/float_on_text_elements.html [ Failure ]
 crbug.com/591099 css1/classification/list_style.html [ Failure ]
 crbug.com/591099 css1/classification/list_style_image.html [ Failure ]
-crbug.com/591099 css1/font_properties/font_variant.html [ Failure ]
+crbug.com/591099 css1/font_properties/font_variant.html [ Failure Pass ]
 crbug.com/591099 css2.1/20110323/margin-applies-to-008.htm [ Failure ]
 crbug.com/714962 css2.1/20110323/overflow-applies-to-012.htm [ Failure ]
 crbug.com/591099 css2.1/20110323/table-caption-margins-001.htm [ Failure ]
@@ -299,6 +295,8 @@
 crbug.com/714962 external/wpt/css/css-backgrounds/background-attachment-local/attachment-local-clipping-color-5.html [ Failure ]
 crbug.com/714962 external/wpt/css/css-backgrounds/background-attachment-local/attachment-local-clipping-image-5.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-backgrounds/box-shadow-syntax-001.xht [ Failure ]
+crbug.com/591099 external/wpt/css/css-color/t32-opacity-offscreen-b.xht [ Pass ]
+crbug.com/591099 external/wpt/css/css-color/t32-opacity-offscreen-with-alpha-c.xht [ Pass ]
 crbug.com/591099 external/wpt/css/css-display/display-contents-details.html [ Crash ]
 crbug.com/591099 external/wpt/css/css-display/display-contents-dynamic-list-001-inline.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-display/display-contents-dynamic-list-001-none.html [ Failure ]
@@ -328,127 +326,7 @@
 crbug.com/591099 external/wpt/css/css-grid/grid-items/grid-item-containing-block-002.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-grid/grid-items/grid-item-containing-block-003.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-grid/grid-items/grid-item-containing-block-004.html [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-basic-001.html [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-basic-002.html [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-basic-003.html [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-basic-004.html [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-basic-007.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-basic-008.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-br-inside-avoidcolumn-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-breaking-000.html [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-breaking-001.html [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-breaking-002.html [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-breaking-003.html [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-breaking-nobackground-000.html [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-breaking-nobackground-001.html [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-breaking-nobackground-002.html [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-breaking-nobackground-003.html [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-clip-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-clip-002.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-collapsing-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-columns-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-columns-002.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-columns-003.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-columns-004.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-columns-005.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-columns-006.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-columns-007.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-columns-invalid-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-columns-invalid-002.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-columns-toolong-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-containing-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-containing-002.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-count-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-count-002.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-count-negative-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-count-negative-002.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-count-non-integer-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-count-non-integer-002.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-count-non-integer-003.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-fill-000.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-fill-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-fill-auto-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-fill-auto-002.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-fill-auto-003.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-fill-auto-block-children-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-fill-auto-block-children-002.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-fill-balance-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-gap-000.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-gap-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-gap-002.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-gap-003.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-gap-fraction-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-gap-fraction-002.html [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-gap-large-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-gap-large-002.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-gap-negative-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-height-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-height-block-child-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-inherit-002.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-inherit-003.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-list-item-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-margin-002.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-nested-002.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-nested-005.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-nested-margin-002.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-nested-margin-003.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-nested-margin-004.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-nested-margin-005.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-overflow-000.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-overflowing-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-reduce-000.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-rule-000.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-rule-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-rule-002.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-rule-003.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-rule-color-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-rule-color-inherit-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-rule-color-inherit-002.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-rule-dashed-000.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-rule-dotted-000.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-rule-double-000.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-rule-fraction-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-rule-fraction-002.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-rule-fraction-003.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-rule-groove-000.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-rule-large-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-rule-percent-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-rule-px-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-rule-ridge-000.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-rule-samelength-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-rule-shorthand-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-rule-shorthand-2.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-rule-solid-000.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-rule-stacking-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-rule-style-groove-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-rule-style-ridge-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-shorthand-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-span-000.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-span-all-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-span-all-002.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-span-all-003.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-span-all-block-sibling-003.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-span-all-child-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-span-all-margin-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-span-all-margin-002.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-span-all-margin-bottom-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-span-all-margin-nested-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-span-all-margin-nested-003.xht [ Crash ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-span-all-margin-nested-firstchild-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-span-none-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-table-cell-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-table-cell-height-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-table-cell-height-002.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-table-cell-vertical-align-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-width-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-width-002.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-width-003.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-width-ch-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-width-count-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-width-count-002.xht [ Failure ]
-crbug.com/714962 external/wpt/css/css-multicol/multicol-width-large-001.xht [ Failure ]
-crbug.com/714962 external/wpt/css/css-multicol/multicol-width-large-002.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-width-small-001.xht [ Failure ]
+crbug.com/824918 external/wpt/css/css-multicol/multicol-rule-dotted-000.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-position/position-sticky-overflow-padding.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-position/position-sticky-writing-modes.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-pseudo/first-letter-003.html [ Pass ]
@@ -573,7 +451,9 @@
 crbug.com/591099 external/wpt/css/css-shapes/spec-examples/shape-outside-018.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-shapes/spec-examples/shape-outside-019.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-tables/height-distribution/percentage-sizing-of-table-cell-children.html [ Failure ]
+crbug.com/591099 external/wpt/css/css-tables/height-distribution/td-different-subpixel-padding-in-same-row.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-tables/table-model-fixup-2.html [ Failure ]
+crbug.com/591099 external/wpt/css/css-tables/width-distribution/td-with-subpixel-padding-vertical-rl.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-text-decor/text-emphasis-color-001.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-text-decor/text-emphasis-position-above-left-001.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-text-decor/text-emphasis-position-above-left-002.xht [ Failure ]
@@ -621,6 +501,9 @@
 crbug.com/714962 external/wpt/css/css-transforms/transform-origin-006.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-transforms/transform-transformed-tr-percent-height-child.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-transforms/transform3d-perspective-008.html [ Pass ]
+crbug.com/591099 external/wpt/css/css-transitions/properties-value-001.html [ Timeout ]
+crbug.com/591099 external/wpt/css/css-transitions/properties-value-inherit-001.html [ Timeout ]
+crbug.com/591099 external/wpt/css/css-transitions/properties-value-inherit-002.html [ Timeout ]
 crbug.com/591099 external/wpt/css/css-ui/box-sizing-007.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-ui/box-sizing-008.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-ui/box-sizing-009.html [ Failure ]
@@ -771,10 +654,6 @@
 crbug.com/714962 external/wpt/css/css-writing-modes/sizing-orthog-prct-htb-in-vrl-007.xht [ Failure ]
 crbug.com/714962 external/wpt/css/css-writing-modes/sizing-orthog-prct-htb-in-vrl-008.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes/sizing-orthog-vrl-in-htb-013.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-writing-modes/table-column-order-002.xht [ Pass ]
-crbug.com/591099 external/wpt/css/css-writing-modes/table-column-order-003.xht [ Pass ]
-crbug.com/591099 external/wpt/css/css-writing-modes/table-column-order-004.xht [ Pass ]
-crbug.com/591099 external/wpt/css/css-writing-modes/table-column-order-005.xht [ Pass ]
 crbug.com/591099 external/wpt/css/css-writing-modes/text-baseline-vlr-007.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes/text-baseline-vrl-006.xht [ Failure ]
 crbug.com/591099 external/wpt/css/css-writing-modes/text-combine-upright-decorations-001.html [ Failure ]
@@ -817,14 +696,13 @@
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-baseline-multi-item-vert-001b.html [ Pass ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-003v.html [ Pass ]
 crbug.com/714962 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-items-as-stacking-contexts-002.html [ Failure ]
-crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-010.html [ Pass ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-011.html [ Failure ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-012.html [ Failure ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-014.html [ Failure ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-015.html [ Failure ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-break-inside-001.html [ Failure ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-007.html [ Failure ]
-crbug.com/591099 external/wpt/dom/interfaces.html [ Timeout ]
+crbug.com/591099 external/wpt/dom/interfaces.html [ Pass Timeout ]
 crbug.com/591099 external/wpt/dom/nodes/Element-classlist.html [ Timeout ]
 crbug.com/591099 external/wpt/dom/nodes/Element-matches.html [ Timeout ]
 crbug.com/591099 external/wpt/dom/nodes/Element-webkitMatchesSelector.html [ Timeout ]
@@ -962,7 +840,7 @@
 crbug.com/591099 external/wpt/encoding/legacy-mb-tchinese/big5/big5-encode-href-errors-misc.html [ Timeout ]
 crbug.com/591099 external/wpt/encoding/legacy-mb-tchinese/big5/big5-encode-href.html [ Timeout ]
 crbug.com/591099 external/wpt/encoding/textdecoder-fatal-single-byte.html [ Timeout ]
-crbug.com/591099 external/wpt/geolocation-API/PositionOptions.https.html [ Failure ]
+crbug.com/591099 external/wpt/geolocation-API/PositionOptions.https.html [ Failure Pass ]
 crbug.com/591099 external/wpt/html-media-capture/capture_audio_cancel-manual.html [ Failure ]
 crbug.com/591099 external/wpt/html-media-capture/capture_image_cancel-manual.html [ Failure ]
 crbug.com/591099 external/wpt/html-media-capture/capture_video_cancel-manual.html [ Failure ]
@@ -1001,7 +879,6 @@
 crbug.com/591099 external/wpt/pointerevents/pointerevent_click_during_capture-manual.html [ Crash Timeout ]
 crbug.com/591099 external/wpt/pointerevents/pointerevent_pointerleave_pen-manual.html [ Failure ]
 crbug.com/714962 external/wpt/pointerevents/pointerevent_touch-action-mouse-manual.html [ Pass Timeout ]
-crbug.com/714962 external/wpt/pointerevents/pointerevent_touch-action-pan-left-css_touch-manual.html [ Pass ]
 crbug.com/591099 external/wpt/pointerevents/pointerevent_touch-action-span-test_touch-manual.html [ Failure ]
 crbug.com/591099 external/wpt/quirks/line-height-calculation.html [ Failure ]
 crbug.com/591099 external/wpt/quirks/table-cell-width-calculation.html [ Pass ]
@@ -1027,16 +904,16 @@
 crbug.com/591099 external/wpt/selection/extend-00.html [ Timeout ]
 crbug.com/591099 external/wpt/selection/extend-20.html [ Timeout ]
 crbug.com/591099 external/wpt/selection/selectAllChildren.html [ Timeout ]
-crbug.com/591099 external/wpt/service-workers/service-worker/navigation-preload/resource-timing.https.html [ Pass ]
 crbug.com/591099 external/wpt/shadow-dom/DocumentOrShadowRoot-prototype-elementFromPoint.html [ Failure ]
 crbug.com/591099 external/wpt/svg/interfaces.html [ Timeout ]
 crbug.com/591099 external/wpt/svg/linking/reftests/href-filter-element.html [ Failure ]
 crbug.com/591099 external/wpt/url/url-setters.html [ Pass Timeout ]
 crbug.com/591099 external/wpt/wasm/wasm_local_iframe_test.html [ Failure ]
-crbug.com/591099 external/wpt/webaudio/idlharness.https.html [ Timeout ]
+crbug.com/591099 external/wpt/webaudio/idlharness.https.html [ Pass Timeout ]
 crbug.com/591099 external/wpt/webmessaging/broadcastchannel/sandbox.html [ Failure ]
+crbug.com/591099 external/wpt/webrtc/RTCPeerConnection-setLocalDescription-answer.html [ Pass ]
 crbug.com/591099 external/wpt/webrtc/interfaces.html [ Pass Timeout ]
-crbug.com/591099 external/wpt/webrtc/interfaces.https.html [ Timeout ]
+crbug.com/591099 external/wpt/webrtc/interfaces.https.html [ Pass Timeout ]
 crbug.com/591099 external/wpt/webstorage/storage_setitem.html [ Pass Timeout ]
 crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_completely_move_up.html [ Failure ]
 crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_up.html [ Failure ]
@@ -1088,8 +965,7 @@
 crbug.com/810370 fast/block/float/overhanging-float-remove-from-fixed-position-block2.html [ Failure ]
 crbug.com/591099 fast/block/float/overlapping-floats-paint-hittest-order-1.html [ Failure ]
 crbug.com/591099 fast/block/line-layout/floats-do-not-fit-on-line.html [ Failure ]
-crbug.com/591099 fast/block/line-layout/line-break-removal-near-textarea-crash.html [ Failure ]
-crbug.com/591099 fast/block/margin-collapse/103.html [ Failure ]
+crbug.com/591099 fast/block/margin-collapse/103.html [ Failure Pass ]
 crbug.com/591099 fast/block/margin-collapse/webkit-margin-collapse-container.html [ Failure ]
 crbug.com/591099 fast/block/margin-collapse/webkit-margin-collapse-separate-position.html [ Failure ]
 crbug.com/591099 fast/block/margin-collapse/webkit-margin-collapse-siblings.html [ Failure ]
@@ -1099,13 +975,11 @@
 crbug.com/591099 fast/block/positioning/complex-positioned-movement-inline-ancestor.html [ Failure ]
 crbug.com/591099 fast/block/positioning/differing-writing-modes-replaced.html [ Failure ]
 crbug.com/591099 fast/block/positioning/fixed-in-abs-height-change.html [ Crash ]
-crbug.com/714962 fast/block/positioning/offsetLeft-offsetTop-multicolumn.html [ Failure ]
 crbug.com/591099 fast/block/positioning/positioned-child-inside-relative-positioned-anonymous-block.html [ Failure ]
 crbug.com/591099 fast/block/positioning/relative-overflow-replaced.html [ Failure ]
 crbug.com/591099 fast/block/positioning/vertical-rl/002.html [ Failure ]
 crbug.com/591099 fast/borders/bidi-002.html [ Failure ]
 crbug.com/591099 fast/borders/bidi-012.html [ Failure ]
-crbug.com/591099 fast/borders/border-antialiasing.html [ Failure ]
 crbug.com/591099 fast/borders/border-image-border-radius.html [ Failure ]
 crbug.com/714962 fast/borders/border-image-outset-split-inline.html [ Failure ]
 crbug.com/714962 fast/borders/border-inner-bleed.html [ Failure ]
@@ -1253,7 +1127,7 @@
 crbug.com/591099 fast/css-grid-layout/minmax-min-content-column-resolution-rows.html [ Failure ]
 crbug.com/591099 fast/css-grid-layout/minmax-spanning-resolution-columns.html [ Failure ]
 crbug.com/591099 fast/css-grid-layout/minmax-spanning-resolution-rows.html [ Failure ]
-crbug.com/591099 fast/css-grid-layout/named-grid-line-get-set.html [ Pass Timeout ]
+crbug.com/591099 fast/css-grid-layout/named-grid-line-get-set.html [ Timeout ]
 crbug.com/591099 fast/css-grid-layout/named-grid-lines-with-named-grid-areas-dynamic-get-set.html [ Failure ]
 crbug.com/591099 fast/css-grid-layout/named-grid-lines-with-named-grid-areas-resolution.html [ Failure ]
 crbug.com/591099 fast/css-grid-layout/percent-grid-item-in-percent-grid-track-in-percent-grid.html [ Failure ]
@@ -1276,7 +1150,6 @@
 crbug.com/591099 fast/css-intrinsic-dimensions/height-positioned-replaced.html [ Crash ]
 crbug.com/591099 fast/css-intrinsic-dimensions/height-positioned.html [ Crash ]
 crbug.com/591099 fast/css-intrinsic-dimensions/indefinite-percent-minmax-content-inlinesize-contribution-nonreplaced-blocks.html [ Failure ]
-crbug.com/591099 fast/css-intrinsic-dimensions/multicol.html [ Failure ]
 crbug.com/591099 fast/css-intrinsic-dimensions/resize-inside-percent-width-overflow-hidden.html [ Failure ]
 crbug.com/807708 fast/css-intrinsic-dimensions/width-avoid-floats.html [ Failure ]
 crbug.com/591099 fast/css/007.html [ Failure ]
@@ -1296,7 +1169,6 @@
 crbug.com/714962 fast/css/first-letter-before-hit-test.html [ Failure ]
 crbug.com/714962 fast/css/first-letter-hit-test.html [ Failure ]
 crbug.com/714962 fast/css/first-letter-hover-hit-test.html [ Failure ]
-crbug.com/714962 fast/css/first-letter-range-insert.html [ Failure ]
 crbug.com/714962 fast/css/first-line-change-color-direct.html [ Failure ]
 crbug.com/714962 fast/css/first-line-change-color.html [ Failure ]
 crbug.com/714962 fast/css/first-line-hover-001.html [ Failure ]
@@ -1310,7 +1182,6 @@
 crbug.com/591099 fast/css/getComputedStyle/getComputedStyle-margin-auto.html [ Failure ]
 crbug.com/591099 fast/css/getComputedStyle/getComputedStyle-margin-percentage.html [ Failure ]
 crbug.com/591099 fast/css/getComputedStyle/getComputedStyle-resolved-values.html [ Timeout ]
-crbug.com/714962 fast/css/getComputedStyle/getComputedStyle-zoom-and-background-size.html [ Failure ]
 crbug.com/714962 fast/css/hover-pseudo-element-quirks.html [ Failure ]
 crbug.com/591099 fast/css/ignore-empty-focus-ring-rects.html [ Failure ]
 crbug.com/591099 fast/css/import_with_baseurl.html [ Failure Pass ]
@@ -1401,7 +1272,6 @@
 crbug.com/591099 fast/dynamic/text-combine.html [ Failure ]
 crbug.com/591099 fast/encoding/utf-16-big-endian.html [ Failure ]
 crbug.com/591099 fast/encoding/utf-16-little-endian.html [ Failure ]
-crbug.com/714962 fast/events/document-elementFromPoint.html [ Failure ]
 crbug.com/714962 fast/events/drag-in-frames.html [ Failure ]
 crbug.com/714962 fast/events/event-on-culled_inline.html [ Failure ]
 crbug.com/591099 fast/events/keyboardevent-getModifierState.html [ Timeout ]
@@ -1411,7 +1281,6 @@
 crbug.com/591099 fast/events/mouse-event-buttons-attribute.html [ Timeout ]
 crbug.com/591099 fast/events/mouse-relative-position.html [ Failure ]
 crbug.com/591099 fast/events/mouseevent-getModifierState.html [ Timeout ]
-crbug.com/714962 fast/events/offsetX-offsetY.html [ Failure ]
 crbug.com/591099 fast/events/onclick-list-marker.html [ Failure ]
 crbug.com/591099 fast/events/pointer-events-2.html [ Failure ]
 crbug.com/591099 fast/events/pointerevents/mouse-pointer-capture-transition-events.html [ Timeout ]
@@ -1426,7 +1295,6 @@
 crbug.com/591099 fast/events/touch/compositor-touch-hit-rects-scroll.html [ Failure ]
 crbug.com/591099 fast/events/touch/compositor-touch-hit-rects.html [ Failure ]
 crbug.com/591099 fast/events/wheel/mainthread-touchpad-fling-latching.html [ Pass ]
-crbug.com/591099 fast/events/wheel/mouse-wheel-scroll-latching.html [ Pass ]
 crbug.com/591099 fast/events/wheel/wheel-scroll-latching-on-scrollbar.html [ Pass ]
 crbug.com/591099 fast/forms/calendar-picker/calendar-picker-key-operations.html [ Timeout ]
 crbug.com/714962 fast/forms/calendar-picker/calendar-picker-mouse-operations.html [ Failure ]
@@ -1440,11 +1308,8 @@
 crbug.com/714962 fast/forms/label/continous-click-on-label.html [ Failure ]
 crbug.com/591099 fast/forms/label/label-selection-by-textSelection-and-click.html [ Failure Pass ]
 crbug.com/591099 fast/forms/long-text-in-input.html [ Crash Failure ]
-crbug.com/591099 fast/forms/number/number-spinbutton-in-multi-column.html [ Failure ]
 crbug.com/591099 fast/forms/placeholder-position.html [ Failure ]
-crbug.com/591099 fast/forms/range/slider-in-multi-column.html [ Failure ]
-crbug.com/591099 fast/forms/select-popup/popup-menu-appearance-transform.html [ Failure ]
-crbug.com/591099 fast/forms/select/listbox-in-multi-column.html [ Failure ]
+crbug.com/591099 fast/forms/select-popup/popup-menu-appearance-transform.html [ Failure Pass ]
 crbug.com/591099 fast/forms/select/select-initial-position.html [ Failure ]
 crbug.com/591099 fast/forms/select/select-style.html [ Failure ]
 crbug.com/591099 fast/forms/selection-direction.html [ Timeout ]
@@ -1454,7 +1319,7 @@
 crbug.com/591099 fast/forms/textarea/textarea-align.html [ Failure ]
 crbug.com/591099 fast/forms/textarea/textarea-metrics.html [ Timeout ]
 crbug.com/591099 fast/forms/time-multiple-fields/time-multiple-fields-stepup-stepdown-from-renderer.html [ Timeout ]
-crbug.com/591099 fast/forms/validation-bubble-appearance-rtl-ui.html [ Failure ]
+crbug.com/591099 fast/forms/validation-bubble-appearance-rtl-ui.html [ Failure Pass ]
 crbug.com/591099 fast/frames/iframe-with-frameborder.html [ Failure ]
 crbug.com/591099 fast/gradients/list-item-gradient.html [ Failure ]
 crbug.com/591099 fast/gradients/radial-centered.html [ Failure ]
@@ -1503,360 +1368,38 @@
 crbug.com/591099 fast/lists/drag-into-marker.html [ Failure ]
 crbug.com/591099 fast/lists/inline-before-content-after-list-marker.html [ Failure ]
 crbug.com/591099 fast/lists/list-color-change-no-layout.html [ Failure ]
-crbug.com/591099 fast/lists/list-inside-columns-crash.html [ Crash ]
 crbug.com/591099 fast/lists/list-item-line-height.html [ Failure ]
 crbug.com/591099 fast/lists/list-marker-before-content-table.html [ Failure ]
 crbug.com/591099 fast/lists/marker-before-empty-inline.html [ Failure ]
 crbug.com/591099 fast/lists/markers-in-selection.html [ Failure ]
 crbug.com/591099 fast/masking/clip-path-selection.html [ Failure ]
 crbug.com/591099 fast/media/mq-display-mode-fullscreen.html [ Crash ]
-crbug.com/591099 fast/multicol/abspos-after-break-after.html [ Failure ]
-crbug.com/591099 fast/multicol/abspos-new-width-rebalance.html [ Failure ]
-crbug.com/591099 fast/multicol/balance-float-after-forced-break.html [ Failure ]
-crbug.com/591099 fast/multicol/balance-float-in-inline.html [ Failure ]
-crbug.com/591099 fast/multicol/balance-float-with-margin-top-and-line-after-break-2.html [ Failure ]
-crbug.com/591099 fast/multicol/balance-float-with-margin-top-and-line-after-break-3.html [ Failure ]
-crbug.com/591099 fast/multicol/balance-float-with-margin-top-and-line-after-break.html [ Failure ]
-crbug.com/591099 fast/multicol/balance-float-with-margin-top-and-line-before-break.html [ Failure ]
-crbug.com/591099 fast/multicol/balance-floats.html [ Failure ]
-crbug.com/591099 fast/multicol/balance-line-overflow.html [ Failure ]
-crbug.com/591099 fast/multicol/balance-line-underflow-2.html [ Failure ]
-crbug.com/591099 fast/multicol/balance-repeating-table-headers.html [ Failure ]
-crbug.com/591099 fast/multicol/balance-table-with-border-spacing.html [ Failure ]
-crbug.com/591099 fast/multicol/basic-rtl.html [ Failure ]
-crbug.com/591099 fast/multicol/border-radius-clipped-layer-second-column.html [ Failure ]
-crbug.com/591099 fast/multicol/border-radius-clipped-layer.html [ Failure ]
-crbug.com/591099 fast/multicol/break-before-first-line-in-first-child.html [ Failure ]
-crbug.com/591099 fast/multicol/break-in-scrollable.html [ Failure ]
-crbug.com/591099 fast/multicol/caret-range-anonymous-block-rtl.html [ Failure ]
-crbug.com/591099 fast/multicol/caret-range-anonymous-block.html [ Failure ]
-crbug.com/591099 fast/multicol/caret-range-outside-columns-rtl.html [ Failure ]
-crbug.com/591099 fast/multicol/caret-range-outside-columns.html [ Failure ]
-crbug.com/714962 fast/multicol/change-height.html [ Failure ]
-crbug.com/591099 fast/multicol/client-rect-after-spanner.html [ Failure ]
-crbug.com/591099 fast/multicol/client-rect-nested.html [ Failure ]
-crbug.com/591099 fast/multicol/client-rects-crossing-boundaries-nested.html [ Failure ]
-crbug.com/591099 fast/multicol/client-rects-crossing-boundaries.html [ Failure ]
-crbug.com/591099 fast/multicol/client-rects-rtl.html [ Failure ]
-crbug.com/591099 fast/multicol/client-rects.html [ Failure ]
-crbug.com/591099 fast/multicol/column-count-with-rules.html [ Failure ]
-crbug.com/591099 fast/multicol/column-rules.html [ Failure ]
-crbug.com/591099 fast/multicol/columns-shorthand-parsing.html [ Failure ]
-crbug.com/591099 fast/multicol/composited-inner-multicol.html [ Failure ]
-crbug.com/591099 fast/multicol/composited-opacity-2nd-and-3rd-column.html [ Failure ]
-crbug.com/591099 fast/multicol/composited-relpos-clipped.html [ Failure ]
-crbug.com/591099 fast/multicol/composited-relpos-in-clipped.html [ Failure ]
-crbug.com/591099 fast/multicol/composited-relpos-overlapping-will-change.html [ Failure ]
-crbug.com/591099 fast/multicol/composited-relpos-resize.html [ Failure ]
-crbug.com/591099 fast/multicol/composited-relpos.html [ Failure ]
-crbug.com/591099 fast/multicol/composited-with-child-layer-in-next-column.html [ Failure ]
-crbug.com/591099 fast/multicol/composited-with-overflow-in-next-column.html [ Failure ]
-crbug.com/714962 fast/multicol/content-change-same-height.html [ Failure ]
-crbug.com/591099 fast/multicol/doubly-nested-with-top-padding-crossing-row-boundaries.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/abspos-becomes-spanner.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/abspos-multicol-with-spanner-becomes-spanner.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/block-becomes-spanner.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/change-second-row-height.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/change-spanner-display.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/change-spanner-parent-display.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/float-becomes-spanner.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/insert-block-among-text-in-anonymous-wrapper.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/insert-block-before-spanner-before-content.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/insert-block-before-spanner.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/insert-block-between-spanners.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/insert-block-into-content.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/insert-block-into-spanner.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/insert-float-after-content-in-spanner.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/insert-float-before-content-in-spanner.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/insert-spanner-after-content.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/insert-spanner-after-spanner-before-content.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/insert-spanner-before-content.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/insert-spanner-between-out-of-flow.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/insert-spanner-into-content.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/insert-spanner-into-stf-constrained-width.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/insert-spanner-into-stf-unconstrained-width.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/insert-spanner-pseudo-after-then-content.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/insert-spanner-pseudo-after.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/insert-spanner-pseudo-before-after-in-content.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/insert-spanner-pseudo-before-after.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/insert-spanner-pseudo-before-following-content.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/insert-spanner-pseudo-before.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/invalid-spanner-container-becomes-valid.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/relpos-becomes-static-has-abspos.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/remove-abspos-next-to-spanner.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/remove-and-insert-block-after-spanner.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/remove-and-insert-block-before-spanner.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/remove-and-insert-block-between-spanners.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/remove-block-after-spanner.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/remove-block-before-spanner.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/remove-block-between-spanners.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/remove-block-from-content-after-spanner.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/remove-block-from-content-before-spanner.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/remove-block-from-content-between-spanners.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/remove-column-content-next-to-abspos-between-spanners.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/remove-spanner-after-content.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/remove-spanner-before-content.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/remove-spanner-in-content.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/spanner-after-content-becomes-regular-block.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/spanner-ancestor-becomes-spanner.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/spanner-becomes-regular-block.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/spanner-before-content-becomes-regular-block.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/spanner-in-content-becomes-regular-block.html [ Failure ]
-crbug.com/591099 fast/multicol/dynamic/static-becomes-relpos-has-abspos.html [ Failure ]
-crbug.com/714962 fast/multicol/event-offset-complex-tree.html [ Failure ]
-crbug.com/591099 fast/multicol/event-offset-in-nested.html [ Failure ]
-crbug.com/714962 fast/multicol/event-offset.html [ Failure ]
-crbug.com/591099 fast/multicol/first-line-in-float-below-next-column-top.html [ Failure ]
-crbug.com/591099 fast/multicol/first-line-in-float-with-margin.html [ Failure ]
-crbug.com/591099 fast/multicol/fixedpos-child-becomes-static.html [ Failure ]
-crbug.com/591099 fast/multicol/flexbox-starts-at-column-boundary-with-block.html [ Failure ]
-crbug.com/591099 fast/multicol/flexbox-starts-at-column-boundary.html [ Failure ]
-crbug.com/591099 fast/multicol/flexbox-with-overflow-auto-child-crash.html [ Crash ]
-crbug.com/591099 fast/multicol/flexbox.html [ Failure ]
-crbug.com/591099 fast/multicol/flipped-blocks-border-after.html [ Failure ]
-crbug.com/591099 fast/multicol/flipped-blocks-hit-test.html [ Failure ]
-crbug.com/591099 fast/multicol/float-after-break-after.html [ Failure ]
-crbug.com/591099 fast/multicol/float-avoidance.html [ Failure ]
-crbug.com/591099 fast/multicol/float-big-line.html [ Failure ]
-crbug.com/591099 fast/multicol/float-break.html [ Failure ]
-crbug.com/591099 fast/multicol/float-content-break.html [ Failure ]
-crbug.com/591099 fast/multicol/float-edge.html [ Failure ]
-crbug.com/591099 fast/multicol/float-margin-at-row-boundary-fixed-multicol-height.html [ Failure ]
-crbug.com/591099 fast/multicol/float-margin-at-row-boundary.html [ Failure ]
-crbug.com/591099 fast/multicol/float-moved-by-child-line-and-unbreakable.html [ Failure ]
-crbug.com/591099 fast/multicol/float-paginate-empty-lines.html [ Failure ]
-crbug.com/591099 fast/multicol/float-paginate.html [ Failure ]
-crbug.com/714962 fast/multicol/float-truncation.html [ Failure ]
-crbug.com/591099 fast/multicol/float-with-margin-moved-by-child-block-and-unbreakable.html [ Failure ]
-crbug.com/591099 fast/multicol/float-with-margin-moved-by-child-block.html [ Failure ]
-crbug.com/591099 fast/multicol/float-with-margin-moved-by-child-line-and-unbreakable.html [ Failure ]
-crbug.com/591099 fast/multicol/float-with-margin-moved-by-child-line.html [ Failure ]
-crbug.com/591099 fast/multicol/float-with-margin-moved-unbreakable.html [ Failure ]
-crbug.com/591099 fast/multicol/forced-break-after-block-with-spanner.html [ Failure ]
-crbug.com/591099 fast/multicol/forced-break-after-empty-block-after-spanner.html [ Failure ]
-crbug.com/591099 fast/multicol/forced-break-after-last-block-before-spanner.html [ Failure ]
-crbug.com/591099 fast/multicol/forced-break-in-nested-columns.html [ Failure ]
-crbug.com/591099 fast/multicol/forced-break-too-short-column.html [ Failure ]
-crbug.com/591099 fast/multicol/hit-test-above-or-below.html [ Failure ]
-crbug.com/591099 fast/multicol/hit-test-end-of-column-with-line-height.html [ Failure ]
-crbug.com/591099 fast/multicol/hit-test-end-of-column.html [ Failure ]
-crbug.com/591099 fast/multicol/hit-test-gap-between-pages-flipped.html [ Failure ]
-crbug.com/812457 fast/multicol/huge-column-count.html [ Failure ]
-crbug.com/714962 fast/multicol/huge-column-gap-crash.html [ Failure ]
-crbug.com/591099 fast/multicol/image-inside-nested-blocks-with-border.html [ Failure ]
-crbug.com/591099 fast/multicol/inline-block-baseline.html [ Failure ]
-crbug.com/591099 fast/multicol/inline-getclientrects.html [ Failure ]
-crbug.com/591099 fast/multicol/inner-multicol-in-second-column.html [ Failure ]
-crbug.com/714962 fast/multicol/input-type-number.html [ Failure ]
-crbug.com/591099 fast/multicol/input-with-overflow-second-column.html [ Failure ]
-crbug.com/591099 fast/multicol/insane-column-gap.html [ Failure ]
-crbug.com/591099 fast/multicol/layers-in-multicol.html [ Failure ]
-crbug.com/714962 fast/multicol/layers-split-across-columns.html [ Failure ]
-crbug.com/591099 fast/multicol/line-in-next-row-in-fourth-inner-multicol.html [ Failure ]
-crbug.com/591099 fast/multicol/line-pushed-down-by-float.html [ Failure ]
-crbug.com/591099 fast/multicol/line-too-tall-for-second-outer-row.html [ Failure ]
-crbug.com/591099 fast/multicol/many-lines-overflow-in-single-row-inner.html [ Failure ]
-crbug.com/591099 fast/multicol/mixed-opacity-test.html [ Failure ]
-crbug.com/591099 fast/multicol/mixed-positioning-stacking-order.html [ Failure ]
-crbug.com/714962 fast/multicol/multicol-becomes-abspos-crash.html [ Failure ]
-crbug.com/591099 fast/multicol/multicol-svg.html [ Failure ]
-crbug.com/591099 fast/multicol/multicol-with-child-renderLayer-for-input.html [ Failure ]
-crbug.com/591099 fast/multicol/nested-3-multicols-fixed-height.html [ Failure ]
-crbug.com/591099 fast/multicol/nested-auto-height-extra-block-inbetween.html [ Failure ]
-crbug.com/591099 fast/multicol/nested-auto-height-short-first-row.html [ Failure ]
-crbug.com/591099 fast/multicol/nested-auto-height.html [ Failure ]
-crbug.com/591099 fast/multicol/nested-balanced-inner-column-count-1-with-forced-break.html [ Failure ]
-crbug.com/591099 fast/multicol/nested-balanced-inner-with-many-breaks-2.html [ Failure ]
-crbug.com/591099 fast/multicol/nested-balanced-inner-with-many-breaks.html [ Failure ]
-crbug.com/591099 fast/multicol/nested-balanced-with-strut-before-first-line.html [ Failure ]
-crbug.com/591099 fast/multicol/nested-balancing-with-line-at-exact-top.html [ Failure ]
-crbug.com/591099 fast/multicol/nested-balancing-with-lines-and-space-left-in-previous-row.html [ Failure ]
-crbug.com/591099 fast/multicol/nested-columns.html [ Failure ]
-crbug.com/591099 fast/multicol/nested-fixed-height-with-struts.html [ Failure ]
-crbug.com/591099 fast/multicol/nested-one-line-in-inner.html [ Failure ]
-crbug.com/591099 fast/multicol/nested-outer-fixed-height.html [ Failure ]
-crbug.com/591099 fast/multicol/nested-short-first-row-extra-tall-line.html [ Failure ]
-crbug.com/591099 fast/multicol/nested-short-first-row-unsplittable-block.html [ Failure ]
-crbug.com/591099 fast/multicol/nested-uneven-inner-column-height.html [ Failure ]
-crbug.com/591099 fast/multicol/nested-with-clipped-first-column.html [ Failure ]
-crbug.com/591099 fast/multicol/nested-with-forced-breaks-in-eariler-rows.html [ Failure ]
-crbug.com/591099 fast/multicol/nested-with-padding.html [ Failure ]
-crbug.com/591099 fast/multicol/nested-with-single-empty-block.html [ Failure ]
-crbug.com/591099 fast/multicol/nested-with-single-tall-line.html [ Failure ]
-crbug.com/591099 fast/multicol/nested-with-tall-block.html [ Failure ]
-crbug.com/591099 fast/multicol/newmulticol/avoid-column-break-inside.html [ Failure ]
-crbug.com/591099 fast/multicol/newmulticol/balance-images.html [ Failure ]
-crbug.com/714962 fast/multicol/newmulticol/balance-maxheight1.html [ Failure ]
-crbug.com/714962 fast/multicol/newmulticol/balance1.html [ Failure ]
-crbug.com/591099 fast/multicol/newmulticol/balance10.html [ Failure ]
-crbug.com/591099 fast/multicol/newmulticol/balance2.html [ Failure ]
-crbug.com/591099 fast/multicol/newmulticol/balance3.html [ Failure ]
-crbug.com/591099 fast/multicol/newmulticol/balance4.html [ Failure ]
-crbug.com/714962 fast/multicol/newmulticol/balance5.html [ Failure ]
-crbug.com/591099 fast/multicol/newmulticol/break-before.html [ Failure ]
-crbug.com/591099 fast/multicol/newmulticol/breaks-2-columns-3-no-balancing.html [ Failure ]
-crbug.com/591099 fast/multicol/newmulticol/breaks-3-columns-3.html [ Failure ]
-crbug.com/591099 fast/multicol/newmulticol/fixed-height-fill-balance-2.html [ Failure ]
-crbug.com/591099 fast/multicol/newmulticol/hide-box-vertical-lr.html [ Failure ]
-crbug.com/591099 fast/multicol/newmulticol/hide-box-vertical-rl.html [ Failure ]
-crbug.com/591099 fast/multicol/newmulticol/list-item.html [ Failure ]
-crbug.com/591099 fast/multicol/newmulticol/orphans-and-widows-balance.html [ Failure ]
-crbug.com/591099 fast/multicol/newmulticol/table-cell.html [ Failure ]
-crbug.com/591099 fast/multicol/out-of-flow/abspos-auto-position-on-line-at-boundary.html [ Failure ]
-crbug.com/591099 fast/multicol/out-of-flow/abspos-auto-position-on-line-rtl.html [ Failure ]
-crbug.com/591099 fast/multicol/out-of-flow/abspos-auto-position-on-line.html [ Failure ]
-crbug.com/591099 fast/multicol/out-of-flow/abspos-auto-position-small-on-line-at-boundary.html [ Failure ]
-crbug.com/591099 fast/multicol/out-of-flow/abspos-auto-position.html [ Failure ]
-crbug.com/591099 fast/multicol/out-of-flow/nested-multicol.html [ Failure ]
-crbug.com/591099 fast/multicol/outlines-at-column-boundaries.html [ Failure ]
-crbug.com/591099 fast/multicol/overflow-across-columns.html [ Failure ]
-crbug.com/591099 fast/multicol/overflow-content.html [ Failure ]
-crbug.com/591099 fast/multicol/overflow-unsplittable.html [ Failure ]
-crbug.com/591099 fast/multicol/pageLogicalOffset-vertical.html [ Failure ]
-crbug.com/591099 fast/multicol/paginate-block-replaced.html [ Failure ]
-crbug.com/591099 fast/multicol/positioned-outside-of-columns.html [ Failure ]
-crbug.com/591099 fast/multicol/positioned-split.html [ Failure ]
-crbug.com/591099 fast/multicol/positioned-with-constrained-height.html [ Failure ]
-crbug.com/591099 fast/multicol/pushed-line-affected-by-float.html [ Failure ]
-crbug.com/591099 fast/multicol/relayout-and-push-float.html [ Failure ]
-crbug.com/591099 fast/multicol/renderer-positioned-assert-crash.html [ Failure ]
-crbug.com/591099 fast/multicol/rule-in-nested-with-too-tall-line.html [ Failure ]
-crbug.com/714962 fast/multicol/scale-transform-text.html [ Failure ]
-crbug.com/591099 fast/multicol/scrolling-overflow.html [ Failure ]
-crbug.com/591099 fast/multicol/shadow-breaking.html [ Failure ]
-crbug.com/591099 fast/multicol/single-line.html [ Failure ]
-crbug.com/591099 fast/multicol/span/abspos-containing-block-outside-spanner.html [ Failure ]
-crbug.com/591099 fast/multicol/span/adjacent-spanners-with-margin.html [ Failure ]
-crbug.com/591099 fast/multicol/span/adjacent-spanners.html [ Failure ]
-crbug.com/591099 fast/multicol/span/after-row-with-uneven-height-nested-multicol.html [ Failure ]
-crbug.com/591099 fast/multicol/span/as-inner-multicol.html [ Failure ]
-crbug.com/591099 fast/multicol/span/autofill-after-spanner.html [ Failure ]
-crbug.com/591099 fast/multicol/span/balance-after-spanner-exact-fit.html [ Failure ]
-crbug.com/591099 fast/multicol/span/balance-after-spanner-extra-height.html [ Failure ]
-crbug.com/591099 fast/multicol/span/balance-after-spanner-some-extra-height.html [ Failure ]
-crbug.com/591099 fast/multicol/span/balance-before-and-after-spanner.html [ Failure ]
-crbug.com/591099 fast/multicol/span/balance-before-spanner-extra-height.html [ Failure ]
-crbug.com/591099 fast/multicol/span/becomes-spanner-with-new-width.html [ Failure ]
-crbug.com/591099 fast/multicol/span/block-with-top-border-and-margin-around-spanner-exact-fit.html [ Failure ]
-crbug.com/591099 fast/multicol/span/block-with-top-border-and-margin-around-spanner-extra-space.html [ Failure ]
-crbug.com/591099 fast/multicol/span/break-in-columns-before-spanner.html [ Failure ]
-crbug.com/591099 fast/multicol/span/change-multicol-writing-mode.html [ Failure ]
-crbug.com/591099 fast/multicol/span/change-spanner-margins.html [ Failure ]
-crbug.com/591099 fast/multicol/span/empty-block-between-spanners-with-margins.html [ Failure ]
-crbug.com/591099 fast/multicol/span/empty-spanner-between-spanners-with-margins.html [ Failure ]
-crbug.com/591099 fast/multicol/span/fill-after-spanner-exact-fit.html [ Failure ]
-crbug.com/591099 fast/multicol/span/fill-after-spanner-extra-height.html [ Failure ]
-crbug.com/591099 fast/multicol/span/float.html [ Failure ]
-crbug.com/591099 fast/multicol/span/height-decrease.html [ Failure ]
-crbug.com/591099 fast/multicol/span/height-increase.html [ Failure ]
-crbug.com/591099 fast/multicol/span/in-nested-multicol-with-hard-breaks.html [ Failure ]
-crbug.com/591099 fast/multicol/span/in-nested-multicol-with-soft-breaks-inside.html [ Failure ]
-crbug.com/591099 fast/multicol/span/inside-block-with-fixed-height.html [ Failure ]
-crbug.com/591099 fast/multicol/span/invalid-spanner-in-abspos.html [ Failure ]
-crbug.com/591099 fast/multicol/span/invalid-spanner-in-transform.html [ Failure ]
-crbug.com/591099 fast/multicol/span/margin-on-multicol.html [ Failure ]
-crbug.com/591099 fast/multicol/span/multicol-with-padding.html [ Failure ]
-crbug.com/591099 fast/multicol/span/nested-multicol.html [ Failure ]
-crbug.com/591099 fast/multicol/span/offset-properties-empty-content.html [ Failure ]
-crbug.com/591099 fast/multicol/span/offset-properties.html [ Failure ]
-crbug.com/591099 fast/multicol/span/outer-column-break-after-inner-spanner-2.html [ Failure ]
-crbug.com/591099 fast/multicol/span/outer-column-break-after-inner-spanner-and-float.html [ Failure ]
-crbug.com/591099 fast/multicol/span/outer-column-break-after-inner-spanner.html [ Failure ]
-crbug.com/591099 fast/multicol/span/outline.html [ Failure ]
-crbug.com/591099 fast/multicol/span/overflow-on-multicol.html [ Failure ]
-crbug.com/591099 fast/multicol/span/overflow-on-viewport.html [ Failure ]
-crbug.com/591099 fast/multicol/span/percent-margins.html [ Failure ]
-crbug.com/591099 fast/multicol/span/preferred-widths-with-column-content.html [ Failure ]
-crbug.com/591099 fast/multicol/span/pseudo-after-then-content.html [ Failure ]
-crbug.com/591099 fast/multicol/span/pseudo-after.html [ Failure ]
-crbug.com/591099 fast/multicol/span/pseudo-before-after-in-content.html [ Failure ]
-crbug.com/591099 fast/multicol/span/pseudo-before-after.html [ Failure ]
-crbug.com/591099 fast/multicol/span/pseudo-before-following-content.html [ Failure ]
-crbug.com/591099 fast/multicol/span/pseudo-before.html [ Failure ]
-crbug.com/591099 fast/multicol/span/relpos-in-block.html [ Failure ]
-crbug.com/591099 fast/multicol/span/relpos-spanner-with-abspos-child.html [ Failure ]
-crbug.com/591099 fast/multicol/span/remaining-space-in-last-column.html [ Failure ]
-crbug.com/591099 fast/multicol/span/simple-margins.html [ Failure ]
-crbug.com/591099 fast/multicol/span/sole-spanner-inside-div.html [ Failure ]
-crbug.com/591099 fast/multicol/span/sole-spanner.html [ Failure ]
-crbug.com/591099 fast/multicol/span/span-between-text.html [ Failure ]
-crbug.com/591099 fast/multicol/span/spanner-first.html [ Failure ]
-crbug.com/591099 fast/multicol/span/spanner-img.html [ Failure ]
-crbug.com/591099 fast/multicol/span/spanner-last.html [ Failure ]
-crbug.com/591099 fast/multicol/span/spanner-table.html [ Failure ]
-crbug.com/591099 fast/multicol/span/spanner-with-margin.html [ Failure ]
-crbug.com/591099 fast/multicol/span/spanner-with-margins-between-margins.html [ Failure ]
-crbug.com/591099 fast/multicol/span/spanner-with-relpos-child.html [ Failure ]
-crbug.com/591099 fast/multicol/span/summary-split.html [ Failure ]
-crbug.com/591099 fast/multicol/span/trailing-margin-before-spanner.html [ Failure ]
-crbug.com/591099 fast/multicol/span/two-rows-then-spanner-then-two-rows.html [ Failure ]
-crbug.com/591099 fast/multicol/span/underflow-after-spanner.html [ Failure ]
-crbug.com/591099 fast/multicol/span/vertical-lr.html [ Failure ]
-crbug.com/591099 fast/multicol/span/vertical-rl.html [ Failure ]
-crbug.com/591099 fast/multicol/span/with-border.html [ Failure ]
-crbug.com/591099 fast/multicol/static-child-becomes-fixedpos.html [ Failure ]
-crbug.com/591099 fast/multicol/svg-change-column-crash.html [ Failure ]
-crbug.com/591099 fast/multicol/table-caption-and-cells-fixed-width.html [ Failure ]
-crbug.com/591099 fast/multicol/table-caption-and-cells.html [ Failure ]
-crbug.com/591099 fast/multicol/table-caption-with-block.html [ Failure ]
-crbug.com/591099 fast/multicol/table-cell-content-change-with-decorations.html [ Failure ]
-crbug.com/591099 fast/multicol/table-cell-content-change.html [ Failure ]
-crbug.com/591099 fast/multicol/table-margin-collapse.html [ Failure ]
-crbug.com/591099 fast/multicol/tall-content-in-inner-with-fixed-height.html [ Failure ]
-crbug.com/591099 fast/multicol/tall-float2.html [ Failure ]
-crbug.com/591099 fast/multicol/three-inner-rows.html [ Failure ]
-crbug.com/714962 fast/multicol/unbreakable-content-taller-than-height-crash.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-lr/abspos-auto-position-on-line.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-lr/break-properties.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-lr/caret-range-anonymous-block-rtl.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-lr/caret-range-anonymous-block.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-lr/caret-range-outside-columns-rtl.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-lr/caret-range-outside-columns.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-lr/client-rect-after-spanner.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-lr/client-rects-crossing-boundaries-nested.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-lr/column-break-with-balancing.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-lr/column-count-with-rules.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-lr/column-rules.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-lr/composited-relpos-overlapping-will-change.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-lr/float-avoidance.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-lr/float-big-line.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-lr/float-break.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-lr/float-content-break.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-lr/float-edge.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-lr/float-paginate.html [ Failure ]
-crbug.com/714962 fast/multicol/vertical-lr/float-truncation.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-lr/image-inside-nested-blocks-with-border.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-lr/nested-columns.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-lr/offset-top-and-left-at-boundaries-nested.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-lr/offset-top-and-left-at-boundaries.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-lr/offset-top-and-left-nested.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-lr/unsplittable-inline-block.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-rl/abspos-auto-position-on-line.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-rl/break-properties.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-rl/caret-range-anonymous-block-rtl.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-rl/caret-range-anonymous-block.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-rl/caret-range-outside-columns-rtl.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-rl/caret-range-outside-columns.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-rl/client-rect-after-spanner.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-rl/client-rects-crossing-boundaries-nested.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-rl/column-break-with-balancing.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-rl/column-count-with-rules.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-rl/column-rules.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-rl/composited-relpos-overlapping-will-change.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-rl/float-avoidance.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-rl/float-big-line.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-rl/float-break.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-rl/float-content-break.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-rl/float-edge.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-rl/float-paginate.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-rl/float-truncation.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-rl/image-inside-nested-blocks-with-border.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-rl/offset-top-and-left-at-boundaries-nested.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-rl/offset-top-and-left-at-boundaries.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-rl/offset-top-and-left-nested.html [ Failure ]
-crbug.com/591099 fast/multicol/vertical-rl/unsplittable-inline-block.html [ Failure ]
-crbug.com/591099 fast/multicol/widows-and-orphans.html [ Failure ]
-crbug.com/591099 fast/multicol/widows.html [ Failure ]
+crbug.com/824918 fast/multicol/balance-floats.html [ Failure ]
+crbug.com/824918 fast/multicol/break-before-first-line-in-first-child.html [ Failure ]
+crbug.com/824918 fast/multicol/caret-range-anonymous-block-rtl.html [ Failure ]
+crbug.com/824918 fast/multicol/caret-range-anonymous-block.html [ Failure ]
+crbug.com/824918 fast/multicol/dynamic/change-spanner-display.html [ Failure ]
+crbug.com/824918 fast/multicol/flipped-blocks-hit-test.html [ Failure ]
+crbug.com/824918 fast/multicol/hit-test-above-or-below.html [ Failure ]
+crbug.com/824918 fast/multicol/inline-block-baseline.html [ Failure ]
+crbug.com/824918 fast/multicol/nested-one-line-in-inner.html [ Failure ]
+crbug.com/824918 fast/multicol/newmulticol/list-item.html [ Failure ]
+crbug.com/591099 fast/multicol/positive-leading.html [ Failure ]
+crbug.com/824918 fast/multicol/span/overflow-on-multicol.html [ Failure ]
+crbug.com/824918 fast/multicol/span/summary-split.html [ Failure ]
+crbug.com/824918 fast/multicol/span/vertical-rl.html [ Failure ]
+crbug.com/824918 fast/multicol/vertical-lr/caret-range-anonymous-block.html [ Failure ]
+crbug.com/824918 fast/multicol/vertical-rl/caret-range-anonymous-block-rtl.html [ Failure ]
+crbug.com/824918 fast/multicol/vertical-rl/caret-range-anonymous-block.html [ Failure ]
+crbug.com/824918 fast/multicol/vertical-rl/column-break-with-balancing.html [ Failure ]
+crbug.com/824918 fast/multicol/vertical-rl/column-count-with-rules.html [ Failure ]
+crbug.com/824918 fast/multicol/vertical-rl/float-avoidance.html [ Failure ]
+crbug.com/824918 fast/multicol/vertical-rl/float-big-line.html [ Failure ]
+crbug.com/824918 fast/multicol/vertical-rl/float-break.html [ Failure ]
+crbug.com/824918 fast/multicol/vertical-rl/float-content-break.html [ Failure ]
+crbug.com/824918 fast/multicol/vertical-rl/float-edge.html [ Failure ]
+crbug.com/824918 fast/multicol/vertical-rl/float-paginate.html [ Failure ]
+crbug.com/824918 fast/multicol/vertical-rl/unsplittable-inline-block.html [ Failure ]
 crbug.com/591099 fast/overflow/007.html [ Failure ]
 crbug.com/591099 fast/overflow/height-during-simplified-layout.html [ Failure ]
 crbug.com/591099 fast/overflow/image-selection-highlight.html [ Failure ]
@@ -1868,39 +1411,15 @@
 crbug.com/591099 fast/overflow/overflow-update-transform.html [ Failure ]
 crbug.com/591099 fast/overflow/overflow-with-local-background-attachment.html [ Failure ]
 crbug.com/591099 fast/overflow/recompute-overflow-of-layout-root-container.html [ Failure ]
-crbug.com/591099 fast/pagination/auto-height-with-break.html [ Failure ]
-crbug.com/591099 fast/pagination/auto-height.html [ Crash ]
-crbug.com/591099 fast/pagination/break-in-paged-overflow.html [ Failure ]
-crbug.com/591099 fast/pagination/caret-range-outside-paged-x-rtl-vertical-rl.html [ Crash ]
-crbug.com/591099 fast/pagination/caret-range-outside-paged-x-rtl.html [ Failure ]
-crbug.com/591099 fast/pagination/caret-range-outside-paged-x-vertical-rl.html [ Crash ]
-crbug.com/591099 fast/pagination/caret-range-outside-paged-x.html [ Failure ]
-crbug.com/591099 fast/pagination/caret-range-outside-paged-y-rtl-vertical-rl.html [ Failure ]
-crbug.com/714962 fast/pagination/caret-range-outside-paged-y-rtl.html [ Failure ]
-crbug.com/714962 fast/pagination/caret-range-outside-paged-y.html [ Failure ]
-crbug.com/591099 fast/pagination/div-x-horizontal-tb-rtl.html [ Failure ]
-crbug.com/591099 fast/pagination/div-x-vertical-lr-ltr.html [ Failure ]
-crbug.com/591099 fast/pagination/div-x-vertical-lr-rtl.html [ Failure ]
-crbug.com/591099 fast/pagination/div-x-vertical-rl-ltr.html [ Failure ]
-crbug.com/591099 fast/pagination/div-x-vertical-rl-rtl.html [ Failure ]
-crbug.com/591099 fast/pagination/div-y-horizontal-tb-ltr.html [ Failure ]
-crbug.com/591099 fast/pagination/div-y-horizontal-tb-rtl.html [ Failure ]
-crbug.com/591099 fast/pagination/div-y-vertical-lr-ltr.html [ Failure ]
-crbug.com/591099 fast/pagination/div-y-vertical-lr-rtl.html [ Failure ]
-crbug.com/591099 fast/pagination/div-y-vertical-rl-ltr.html [ Failure ]
-crbug.com/591099 fast/pagination/div-y-vertical-rl-rtl.html [ Failure ]
-crbug.com/591099 fast/pagination/first-letter-inherit-all-crash.html [ Crash ]
-crbug.com/591099 fast/pagination/modal-dialog-crash.html [ Crash ]
-crbug.com/591099 fast/pagination/multicol.html [ Failure ]
-crbug.com/591099 fast/pagination/paged-x-column-gap.html [ Failure ]
-crbug.com/714962 fast/pagination/paged-y-to-paged-x.html [ Failure ]
-crbug.com/591099 fast/pagination/repeating-thead-tfoot-paged-x.html [ Failure ]
-crbug.com/591099 fast/pagination/repeating-thead-tfoot-paged-y.html [ Failure ]
-crbug.com/591099 fast/pagination/short-pages-tall-content.html [ Timeout ]
-crbug.com/591099 fast/pagination/viewport-x-vertical-rl-ltr.html [ Failure ]
-crbug.com/591099 fast/pagination/viewport-x-vertical-rl-rtl.html [ Failure ]
-crbug.com/591099 fast/pagination/viewport-y-vertical-rl-ltr.html [ Failure ]
-crbug.com/591099 fast/pagination/viewport-y-vertical-rl-rtl.html [ Failure ]
+crbug.com/824918 fast/pagination/div-y-vertical-rl-ltr.html [ Failure ]
+crbug.com/824918 fast/pagination/div-y-vertical-rl-rtl.html [ Failure ]
+crbug.com/591099 fast/pagination/modal-dialog.html [ Failure ]
+crbug.com/824918 fast/pagination/paged-x-column-gap.html [ Failure ]
+crbug.com/824918 fast/pagination/paged-y-to-paged-x.html [ Failure ]
+crbug.com/824918 fast/pagination/viewport-x-vertical-rl-ltr.html [ Failure ]
+crbug.com/824918 fast/pagination/viewport-x-vertical-rl-rtl.html [ Failure ]
+crbug.com/824918 fast/pagination/viewport-y-vertical-rl-ltr.html [ Failure ]
+crbug.com/824918 fast/pagination/viewport-y-vertical-rl-rtl.html [ Failure ]
 crbug.com/591099 fast/parser/001.html [ Failure ]
 crbug.com/591099 fast/parser/entities-in-html.html [ Failure ]
 crbug.com/591099 fast/parser/entities-in-xhtml.xhtml [ Failure ]
@@ -2116,7 +1635,6 @@
 crbug.com/591099 fast/text-autosizing/clusters-sufficient-text-except-in-root.html [ Failure ]
 crbug.com/591099 fast/text-autosizing/clusters-sufficient-width.html [ Failure ]
 crbug.com/591099 fast/text-autosizing/constrained-and-overflow-auto-ancestor.html [ Failure ]
-crbug.com/591099 fast/text-autosizing/constrained-and-overflow-paged-x-ancestor.html [ Failure ]
 crbug.com/591099 fast/text-autosizing/constrained-and-overflow-scroll-ancestor.html [ Failure ]
 crbug.com/591099 fast/text-autosizing/constrained-floats.html [ Failure ]
 crbug.com/591099 fast/text-autosizing/constrained-height-body.html [ Failure ]
@@ -2198,7 +1716,6 @@
 crbug.com/591099 fast/text/justify-ideograph-simple.html [ Failure ]
 crbug.com/591099 fast/text/justify-ideograph-vertical.html [ Failure ]
 crbug.com/591099 fast/text/large-text-composed-char.html [ Timeout ]
-crbug.com/591099 fast/text/letter-spacing-leading-and-trailing.html [ Failure ]
 crbug.com/714962 fast/text/line-break-after-inline-latin1.html [ Failure ]
 crbug.com/714962 fast/text/multiglyph-characters.html [ Failure ]
 crbug.com/591099 fast/text/orientation-sideways.html [ Failure ]
@@ -2283,95 +1800,7 @@
 crbug.com/591099 fonts/monospace.html [ Failure ]
 crbug.com/591099 fonts/sans-serif.html [ Failure ]
 crbug.com/591099 fonts/serif.html [ Failure ]
-crbug.com/591099 fragmentation/abspos-after-forced-break.html [ Failure ]
-crbug.com/591099 fragmentation/auto-scrollbar-shrink-to-fit.html [ Failure ]
-crbug.com/591099 fragmentation/avoid-break-inside-first-child-nested.html [ Failure ]
-crbug.com/591099 fragmentation/avoid-break-inside-first-child.html [ Failure ]
-crbug.com/591099 fragmentation/block-after-float-first-child.html [ Failure ]
-crbug.com/591099 fragmentation/border-spacing-break-before-unbreakable-row.html [ Failure ]
-crbug.com/591099 fragmentation/break-in-first-table-row-only.html [ Failure ]
-crbug.com/591099 fragmentation/break-in-second-table-section.html [ Failure ]
-crbug.com/591099 fragmentation/break-in-tbody-after-caption.html [ Failure ]
-crbug.com/591099 fragmentation/break-inside-avoid-with-forced-break.html [ Failure ]
-crbug.com/591099 fragmentation/cells-dont-fit-on-page-paginated.html [ Failure ]
-crbug.com/591099 fragmentation/change-fragmentainer-height-block-float-2.html [ Failure ]
-crbug.com/591099 fragmentation/change-fragmentainer-height-block-float.html [ Failure ]
-crbug.com/591099 fragmentation/change-fragmentainer-height-inline-float.html [ Failure ]
-crbug.com/591099 fragmentation/change-fragmentainer-height-line-float.html [ Failure ]
-crbug.com/591099 fragmentation/column-fill-auto-child.html [ Failure ]
-crbug.com/591099 fragmentation/float-after-forced-break.html [ Failure ]
-crbug.com/591099 fragmentation/float-margin-top.html [ Failure ]
-crbug.com/591099 fragmentation/float-pushed-to-next-fragmentainer-by-floats.html [ Failure ]
-crbug.com/591099 fragmentation/forced-break-clearance-unsplittable-content.html [ Failure ]
-crbug.com/591099 fragmentation/fragmented-rowspan-alignment.html [ Failure ]
-crbug.com/591099 fragmentation/fragmented-rowspan.html [ Failure ]
-crbug.com/591099 fragmentation/fragmented-table-cell.html [ Failure ]
-crbug.com/591099 fragmentation/fragmented-table-with-fixed-height.html [ Failure ]
-crbug.com/591099 fragmentation/image-block-as-first-child.html [ Failure ]
-crbug.com/591099 fragmentation/multi-line-cells-paginated.html [ Failure ]
-crbug.com/591099 fragmentation/multi-line-cells.html [ Failure ]
-crbug.com/591099 fragmentation/nested-repeating-thead-2.html [ Failure ]
-crbug.com/591099 fragmentation/nested-repeating-thead-3.html [ Failure ]
-crbug.com/591099 fragmentation/nested-repeating-thead-4.html [ Failure ]
-crbug.com/591099 fragmentation/nested-repeating-thead-tfoot-4.html [ Failure ]
-crbug.com/591099 fragmentation/nested-repeating-thead-tfoot.html [ Failure ]
-crbug.com/591099 fragmentation/overflow-crossing-boundary.html [ Failure ]
-crbug.com/591099 fragmentation/relayout-abspos.html [ Failure ]
-crbug.com/591099 fragmentation/remove-unbreakable-block-in-line-float.html [ Failure ]
-crbug.com/591099 fragmentation/repeating-thead-exceeds-page-size.html [ Failure ]
-crbug.com/591099 fragmentation/repeating-thead-multiple-tables-page-border.html [ Failure ]
-crbug.com/591099 fragmentation/repeating-thead-multiple-tables.html [ Failure ]
-crbug.com/591099 fragmentation/repeating-thead-no-room-for-content-row-on-first-page.html [ Failure ]
-crbug.com/591099 fragmentation/repeating-thead-tfoot-different-fragment-height.html [ Failure ]
-crbug.com/591099 fragmentation/single-cell-repeating-thead-break-inside-avoid-content.html [ Failure ]
-crbug.com/591099 fragmentation/single-cell-repeating-thead-break-inside-content-first-line.html [ Failure ]
-crbug.com/591099 fragmentation/single-cell-repeating-thead-break-inside-content.html [ Failure ]
-crbug.com/591099 fragmentation/single-cells-multiple-tables-no-repeating-thead.html [ Failure ]
-crbug.com/591099 fragmentation/single-large-cell-with-header.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-in-multiple-table-sections.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-multiple-tables-caption-repeating-thead-tfoot-with-border-spacing-at-top-of-row-2.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-multiple-tables-caption-repeating-thead-tfoot-with-border-spacing-at-top-of-row-3.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-multiple-tables-caption-repeating-thead-tfoot-with-border-spacing-at-top-of-row-4.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-multiple-tables-caption-repeating-thead-tfoot-with-border-spacing-at-top-of-row.html [ Failure ]
-crbug.com/714962 fragmentation/single-line-cells-multiple-tables-repeating-thead-with-border-spacing-at-top-of-row.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-nested-repeating-thead-2.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-nested-repeating-thead-3.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-nested-repeating-thead-4.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-nested-repeating-thead-nested-repeating-tfoot.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-nested-repeating-thead-tfoot-2.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-nested-repeating-thead-tfoot-3.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-nested-repeating-thead-tfoot-4.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-nested-repeating-thead-tfoot.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-nested-repeating-thead.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-paginated-with-text.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-paginated.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-repeating-tfoot-rows-allowing-break.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-repeating-thead-cell-straddles-page-unsplittable-div.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-repeating-thead-cell-straddles-page.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-repeating-thead-starts-middle-of-page-break-after-avoid-2.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-repeating-thead-starts-middle-of-page-break-after-avoid-3.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-repeating-thead-starts-middle-of-page-break-after-avoid.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-repeating-thead-starts-middle-of-page.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-repeating-thead-tfoot-starts-middle-of-page-break-after-avoid-2.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-repeating-thead-tfoot-starts-middle-of-page-break-after-avoid-3.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-repeating-thead-tfoot-starts-middle-of-page-break-after-avoid.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-repeating-thead-tfoot-starts-middle-of-page.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-repeating-thead-tfoot-with-border-spacing-at-top-of-row.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-repeating-thead-tfoot-with-caption.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-repeating-thead-tfoot-with-two-captions.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-repeating-thead-tfoot.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-repeating-thead-with-border-spacing-at-top-of-row.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-repeating-thead-with-caption.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-repeating-thead-with-two-captions.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells-repeating-thead.html [ Failure ]
-crbug.com/591099 fragmentation/single-line-cells.html [ Failure ]
-crbug.com/591099 fragmentation/table-in-subpixel-fragmentainer.html [ Failure ]
-crbug.com/591099 fragmentation/table-overlapping-rowspan.html [ Failure ]
-crbug.com/591099 fragmentation/table-row-dimensions-break-freely.html [ Failure ]
-crbug.com/591099 fragmentation/table-row-dimensions-with-thead.html [ Failure ]
-crbug.com/591099 fragmentation/table-row-dimensions.html [ Failure ]
-crbug.com/591099 fragmentation/unbreakable-tall-float-before-block.html [ Failure ]
-crbug.com/591099 fragmentation/unbreakable-tall-float-before-line.html [ Failure ]
+crbug.com/591099 fragmentation/transformed-clip-before-second-column.html [ Failure ]
 crbug.com/591099 fullscreen/enter-exit-full-screen-hover.html [ Crash ]
 crbug.com/591099 fullscreen/full-screen-css.html [ Crash ]
 crbug.com/591099 fullscreen/full-screen-element-stack.html [ Crash ]
@@ -2423,12 +1852,10 @@
 crbug.com/591099 http/tests/devtools/elements/highlight/highlight-css-shapes-outside-scroll.js [ Failure ]
 crbug.com/591099 http/tests/devtools/elements/highlight/highlight-css-shapes-outside.js [ Failure ]
 crbug.com/714962 http/tests/devtools/elements/inspect-pseudo-element.js [ Timeout ]
-crbug.com/591099 http/tests/devtools/elements/styles-3/style-rule-from-imported-stylesheet.js [ Pass ]
-crbug.com/591099 http/tests/devtools/elements/styles-3/styles-change-node-while-editing.js [ Pass ]
 crbug.com/591099 http/tests/devtools/elements/styles-3/styles-disable-inherited.js [ Failure ]
 crbug.com/714962 http/tests/devtools/jump-to-previous-editing-location.js [ Failure ]
 crbug.com/591099 http/tests/devtools/network/network-datareceived.js [ Failure ]
-crbug.com/714962 http/tests/devtools/service-workers/service-workers-view.js [ Failure ]
+crbug.com/714962 http/tests/devtools/service-workers/service-workers-view.js [ Failure Pass Timeout ]
 crbug.com/591099 http/tests/devtools/text-autosizing-override.js [ Failure ]
 crbug.com/591099 http/tests/devtools/tracing/scroll-invalidations.js [ Failure ]
 crbug.com/591099 http/tests/devtools/tracing/timeline-misc/timeline-bound-function.js [ Failure ]
@@ -2470,18 +1897,7 @@
 crbug.com/591099 ietestcenter/css3/bordersbackgrounds/border-radius-applies-to-001.htm [ Failure ]
 crbug.com/591099 ietestcenter/css3/bordersbackgrounds/border-radius-applies-to-003.htm [ Failure ]
 crbug.com/591099 ietestcenter/css3/bordersbackgrounds/border-radius-clip-001.htm [ Failure ]
-crbug.com/591099 ietestcenter/css3/multicolumn/column-block-formatting-context-001.htm [ Failure ]
-crbug.com/591099 ietestcenter/css3/multicolumn/column-containing-block-003.htm [ Failure ]
-crbug.com/714962 ietestcenter/css3/multicolumn/column-width-applies-to-001.htm [ Failure ]
-crbug.com/714962 ietestcenter/css3/multicolumn/column-width-applies-to-002.htm [ Failure ]
-crbug.com/714962 ietestcenter/css3/multicolumn/column-width-applies-to-003.htm [ Failure ]
-crbug.com/714962 ietestcenter/css3/multicolumn/column-width-applies-to-004.htm [ Failure ]
-crbug.com/591099 ietestcenter/css3/multicolumn/column-width-applies-to-007.htm [ Failure ]
-crbug.com/591099 ietestcenter/css3/multicolumn/column-width-applies-to-009.htm [ Failure ]
-crbug.com/591099 ietestcenter/css3/multicolumn/column-width-applies-to-010.htm [ Failure ]
-crbug.com/591099 ietestcenter/css3/multicolumn/column-width-applies-to-012.htm [ Failure ]
-crbug.com/714962 ietestcenter/css3/multicolumn/column-width-applies-to-013.htm [ Failure ]
-crbug.com/591099 ietestcenter/css3/multicolumn/column-width-applies-to-014.htm [ Failure ]
+crbug.com/824918 ietestcenter/css3/multicolumn/column-width-applies-to-010.htm [ Failure ]
 crbug.com/591099 images/55.html [ Failure ]
 crbug.com/714962 images/color-profile-background-clip-text.html [ Failure ]
 crbug.com/591099 images/color-profile-image-filter-all.html [ Failure ]
@@ -2489,13 +1905,7 @@
 crbug.com/591099 images/color-profile-munsell-adobe-to-srgb.html [ Failure ]
 crbug.com/591099 images/percent-height-image.html [ Failure ]
 crbug.com/591099 images/png-suite/test.html [ Failure ]
-crbug.com/591099 images/rendering-broken-0px-images-quirk.html [ Failure ]
-crbug.com/591099 images/rendering-broken-0px-images.html [ Failure ]
-crbug.com/591099 images/rendering-broken-10px-images.html [ Failure ]
-crbug.com/591099 images/rendering-broken-16px-images.html [ Failure ]
-crbug.com/591099 images/rendering-broken-1px-images.html [ Failure ]
 crbug.com/591099 images/rendering-broken-block-flow-images.html [ Failure ]
-crbug.com/591099 images/rendering-broken-images-empty-alt.html [ Failure ]
 crbug.com/591099 images/rendering-broken-images.html [ Failure ]
 crbug.com/591099 inspector-protocol/accessibility/accessibility-ignoredNodes.js [ Timeout ]
 crbug.com/714962 inspector-protocol/accessibility/accessibility-ignoredNodesModal.js [ Failure ]
@@ -2632,18 +2042,10 @@
 crbug.com/591099 paint/invalidation/make-children-non-inline.html [ Failure ]
 crbug.com/591099 paint/invalidation/media-audio-no-spurious-repaints.html [ Failure ]
 crbug.com/591099 paint/invalidation/mix-blend-mode-separate-stacking-context.html [ Failure ]
-crbug.com/591099 paint/invalidation/multicol/column-rules-fixed-height.html [ Failure ]
-crbug.com/591099 paint/invalidation/multicol/multicol-as-paint-container.html [ Failure ]
-crbug.com/591099 paint/invalidation/multicol/multicol-nested.html [ Failure ]
-crbug.com/591099 paint/invalidation/multicol/multicol-relpos-with-abspos.html [ Failure ]
-crbug.com/591099 paint/invalidation/multicol/multicol-repaint.html [ Failure ]
-crbug.com/591099 paint/invalidation/multicol/multicol-rule-actual-columns-change.html [ Crash ]
-crbug.com/591099 paint/invalidation/multicol/multicol-with-abspos-in-relpos.html [ Failure ]
-crbug.com/591099 paint/invalidation/multicol/multicol-with-abspos.html [ Failure ]
-crbug.com/591099 paint/invalidation/multicol/multicol-with-block.html [ Failure ]
-crbug.com/591099 paint/invalidation/multicol/multicol-with-inline.html [ Failure ]
-crbug.com/591099 paint/invalidation/multicol/multicol-with-overflowing-block-rl.html [ Failure ]
-crbug.com/591099 paint/invalidation/multicol/multicol-with-text.html [ Failure ]
+crbug.com/824918 paint/invalidation/multicol/column-rules-fixed-height.html [ Failure ]
+crbug.com/824918 paint/invalidation/multicol/multicol-repaint.html [ Failure ]
+crbug.com/591099 paint/invalidation/multicol/multicol-resize-with-rule.html [ Failure ]
+crbug.com/824918 paint/invalidation/multicol/multicol-with-text.html [ Failure ]
 crbug.com/591099 paint/invalidation/non-text-link-invalidation-optimization.html [ Failure ]
 crbug.com/591099 paint/invalidation/offset-change-wrong-invalidation-with-float.html [ Failure ]
 crbug.com/591099 paint/invalidation/outline/focus-continuations.html [ Failure ]
@@ -2673,7 +2075,6 @@
 crbug.com/591099 paint/invalidation/overflow/justify-self-overflow-change.html [ Failure ]
 crbug.com/591099 paint/invalidation/overflow/line-overflow.html [ Failure ]
 crbug.com/591099 paint/invalidation/overflow/negative-text-indent-with-overflow-hidden.html [ Failure ]
-crbug.com/591099 paint/invalidation/overflow/paged-with-overflowing-block-rl.html [ Failure ]
 crbug.com/591099 paint/invalidation/overflow/repaint-resized-overflow.html [ Failure ]
 crbug.com/591099 paint/invalidation/overflow/vertical-overflow-parent.html [ Failure ]
 crbug.com/591099 paint/invalidation/overflow/vertical-overflow-same.html [ Failure ]
@@ -2848,7 +2249,6 @@
 crbug.com/591099 paint/overflow/background-mask-should-be-recorded-full.html [ Failure ]
 crbug.com/591099 paint/overflow/composited-scroll-vertical-rl.html [ Failure ]
 crbug.com/591099 paint/overflow/transformed-iframe-clipping.html [ Failure ]
-crbug.com/591099 paint/pagination/composited-paginated-inline.html [ Failure ]
 crbug.com/591099 paint/pagination/pagination-change-clip-crash.html [ Failure ]
 crbug.com/591099 paint/selection/text-selection-drag-in-frame-scrolled.html [ Failure ]
 crbug.com/591099 paint/selection/text-selection-drag-in-frame.html [ Failure ]
@@ -2872,49 +2272,12 @@
 crbug.com/714962 paint/text/text-match-highlights-big-line-height.html [ Failure ]
 crbug.com/591099 payments/payment-request-in-iframe-nested-not-allowed.html [ Failure ]
 crbug.com/591099 payments/payment-request-in-iframe.html [ Failure ]
-crbug.com/591099 plugins/mouse-click-plugin-clears-selection.html [ Failure ]
-crbug.com/591099 printing/absolute-position-headers-and-footers.html [ Failure ]
-crbug.com/591099 printing/absolute-positioned.html [ Failure ]
-crbug.com/591099 printing/allowed-page-breaks.html [ Failure ]
-crbug.com/591099 printing/css2.1/page-break-after-000.html [ Failure ]
-crbug.com/591099 printing/css2.1/page-break-after-002.html [ Failure ]
-crbug.com/591099 printing/css2.1/page-break-after-003.html [ Failure ]
-crbug.com/591099 printing/css2.1/page-break-after-004.html [ Failure ]
-crbug.com/591099 printing/css2.1/page-break-before-000.html [ Failure ]
-crbug.com/591099 printing/fixed-positioned-but-static-headers-and-footers.html [ Failure ]
-crbug.com/591099 printing/fixed-positioned-child-repeats-even-when-html-and-body-are-zero-height.html [ Crash ]
-crbug.com/591099 printing/fixed-positioned-child-shouldnt-print.html [ Crash ]
-crbug.com/591099 printing/fixed-positioned-headers-and-footers-clipped.html [ Failure ]
-crbug.com/591099 printing/fixed-positioned-headers-and-footers-inside-transform.html [ Crash ]
-crbug.com/591099 printing/fixed-positioned-headers-and-footers-larger-than-page.html [ Failure ]
-crbug.com/591099 printing/fixed-positioned-headers-and-footers.html [ Failure ]
-crbug.com/591099 printing/fixed-positioned.html [ Failure ]
-crbug.com/591099 printing/forced-break-tree-dump-only.html [ Failure ]
-crbug.com/591099 printing/iframe-print.html [ Failure ]
-crbug.com/591099 printing/list-item-with-empty-first-line.html [ Failure ]
-crbug.com/591099 printing/multicol-2-pages.html [ Failure ]
-crbug.com/591099 printing/multicol.html [ Failure ]
-crbug.com/591099 printing/no-content-empty-pages.html [ Failure ]
-crbug.com/591099 printing/page-break-after-avoid.html [ Failure ]
-crbug.com/591099 printing/page-break-always.html [ Failure ]
-crbug.com/591099 printing/page-break-avoid.html [ Failure ]
-crbug.com/591099 printing/page-break-before-avoid.html [ Failure ]
-crbug.com/591099 printing/page-break-display-none.html [ Failure ]
-crbug.com/591099 printing/page-break-inside-avoid.html [ Failure ]
-crbug.com/591099 printing/page-break-margin-collapsed.html [ Failure ]
-crbug.com/591099 printing/page-break-orphans-and-widows.html [ Failure ]
-crbug.com/591099 printing/page-break-orphans.html [ Failure ]
-crbug.com/591099 printing/page-break-widows.html [ Failure ]
-crbug.com/591099 printing/page-count-relayout-shrink.html [ Failure ]
-crbug.com/591099 printing/respect-layout-overflow-from-pagination.html [ Failure ]
-crbug.com/591099 printing/single-line-must-not-be-split-into-two-pages.html [ Timeout ]
-crbug.com/591099 printing/tfoot-repeats-at-bottom-of-each-page-multiple-tables.html [ Failure ]
-crbug.com/591099 printing/thead-repeats-at-top-of-each-page-multiple-tables.html [ Failure ]
-crbug.com/591099 printing/thead-repeats-at-top-of-each-page.html [ Failure ]
-crbug.com/591099 printing/thead-under-multicol.html [ Failure ]
+crbug.com/824918 printing/absolute-position-headers-and-footers.html [ Failure ]
+crbug.com/824918 printing/single-line-must-not-be-split-into-two-pages.html [ Timeout ]
+crbug.com/591099 printing/webgl-repeated-printing-preservedrawingbuffer.html [ Failure ]
+crbug.com/591099 printing/webgl-repeated-printing.html [ Failure ]
 crbug.com/591099 scrollbars/auto-scrollbar-fit-content.html [ Failure ]
 crbug.com/591099 scrollbars/scrollbar-miss-mousemove-disabled.html [ Failure ]
-crbug.com/714962 scrollbars/scrollbar-position-crash.html [ Crash ]
 crbug.com/591099 shadow-dom/focus-navigation-with-delegatesFocus.html [ Timeout ]
 crbug.com/591099 shapedetection/detection-HTMLVideoElement.html [ Pass ]
 crbug.com/591099 storage/indexeddb/cursor-advance.html [ Pass Timeout ]
@@ -2953,7 +2316,6 @@
 crbug.com/591099 svg/custom/use-font-face-crash.svg [ Failure ]
 crbug.com/591099 svg/dom/svgangle-units.html [ Pass Timeout ]
 crbug.com/591099 svg/filters/feTurbulence-bad-seeds.html [ Failure ]
-crbug.com/591099 svg/foreign-object-under-shadow-root-under-hidden.html [ Failure ]
 crbug.com/591099 svg/hixie/error/012.xml [ Failure ]
 crbug.com/591099 svg/hixie/error/dumpAsText/004.xml [ Failure ]
 crbug.com/591099 svg/hixie/error/dumpAsText/005.xml [ Failure ]
@@ -2965,9 +2327,7 @@
 crbug.com/591099 svg/parser/whitespace-length-invalid-3.html [ Pass Timeout ]
 crbug.com/591099 svg/parser/whitespace-length-invalid-4.html [ Pass Timeout ]
 crbug.com/591099 svg/parser/whitespace-number.html [ Timeout ]
-crbug.com/714962 svg/text/columns-do-not-apply.html [ Failure ]
 crbug.com/591099 svg/text/foreignObject-text-clipping-bug.xml [ Failure ]
-crbug.com/714962 svg/text/layout-inline-children-assert.html [ Failure ]
 crbug.com/591099 svg/text/text-repaint-rects.xhtml [ Failure ]
 crbug.com/714962 svg/text/tspan-multiple-outline.svg [ Failure ]
 crbug.com/591099 svg/transforms/text-with-pattern-inside-transformed-html.xhtml [ Failure ]
@@ -2975,6 +2335,10 @@
 crbug.com/591099 svg/wicd/test-scalable-background-image1.xhtml [ Failure ]
 crbug.com/591099 svg/wicd/test-scalable-background-image2.xhtml [ Failure ]
 crbug.com/591099 svg/zoom/page/zoom-foreignObject.svg [ Failure ]
+crbug.com/591099 svg/zoom/page/zoom-img-preserveAspectRatio-support-1.html [ Failure ]
+crbug.com/591099 svg/zoom/page/zoom-svg-through-object-with-absolute-size-2.xhtml [ Failure ]
+crbug.com/591099 svg/zoom/page/zoom-svg-through-object-with-absolute-size.xhtml [ Failure ]
+crbug.com/591099 svg/zoom/page/zoom-svg-through-object-with-percentage-size.xhtml [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug101674.html [ Failure ]
 crbug.com/591099 tables/mozilla/bugs/bug110566.html [ Failure ]
 crbug.com/714962 tables/mozilla/bugs/bug11384q.html [ Failure ]
@@ -3056,7 +2420,6 @@
 crbug.com/591099 transforms/3d/general/perspective-non-layer.html [ Failure ]
 crbug.com/591099 transforms/3d/hit-testing/backface-hit-test.html [ Failure ]
 crbug.com/591099 transforms/3d/hit-testing/backface-no-transform-hit-test.html [ Failure ]
-crbug.com/714962 transforms/inline-in-transformed-multicol.html [ Failure ]
 crbug.com/714962 transforms/selection-bounds-in-transformed-view.html [ Failure ]
 crbug.com/591099 transforms/shadows.html [ Failure ]
 crbug.com/591099 virtual/android/ [ Skip ]
@@ -3074,13 +2437,7 @@
 crbug.com/591099 virtual/gpu-rasterization/images/color-profile-reflection.html [ Failure ]
 crbug.com/591099 virtual/gpu-rasterization/images/percent-height-image.html [ Failure ]
 crbug.com/591099 virtual/gpu-rasterization/images/png-suite/test.html [ Failure ]
-crbug.com/591099 virtual/gpu-rasterization/images/rendering-broken-0px-images-quirk.html [ Failure ]
-crbug.com/591099 virtual/gpu-rasterization/images/rendering-broken-0px-images.html [ Failure ]
-crbug.com/591099 virtual/gpu-rasterization/images/rendering-broken-10px-images.html [ Failure ]
-crbug.com/591099 virtual/gpu-rasterization/images/rendering-broken-16px-images.html [ Failure ]
-crbug.com/591099 virtual/gpu-rasterization/images/rendering-broken-1px-images.html [ Failure ]
 crbug.com/591099 virtual/gpu-rasterization/images/rendering-broken-block-flow-images.html [ Failure ]
-crbug.com/591099 virtual/gpu-rasterization/images/rendering-broken-images-empty-alt.html [ Failure ]
 crbug.com/591099 virtual/gpu-rasterization/images/rendering-broken-images.html [ Failure ]
 crbug.com/591099 virtual/gpu/fast/canvas/OffscreenCanvas-2d-pattern-in-worker.html [ Pass ]
 crbug.com/714962 virtual/gpu/fast/canvas/canvas-css-clip-path.html [ Failure ]
@@ -3095,7 +2452,6 @@
 crbug.com/591099 virtual/incremental-shadow-dom/html/details_summary/details-writing-mode.html [ Failure ]
 crbug.com/714962 virtual/incremental-shadow-dom/shadow-dom/focus-navigation-with-delegatesFocus.html [ Timeout ]
 crbug.com/591099 virtual/layout_ng/ [ Skip ]
-crbug.com/714962 virtual/mouseevent_fractional/fast/events/document-elementFromPoint.html [ Failure ]
 crbug.com/714962 virtual/mouseevent_fractional/fast/events/drag-in-frames.html [ Failure ]
 crbug.com/714962 virtual/mouseevent_fractional/fast/events/event-on-culled_inline.html [ Failure ]
 crbug.com/591099 virtual/mouseevent_fractional/fast/events/keyboardevent-getModifierState.html [ Timeout ]
@@ -3105,11 +2461,10 @@
 crbug.com/591099 virtual/mouseevent_fractional/fast/events/mouse-event-buttons-attribute.html [ Timeout ]
 crbug.com/591099 virtual/mouseevent_fractional/fast/events/mouse-relative-position.html [ Failure ]
 crbug.com/591099 virtual/mouseevent_fractional/fast/events/mouseevent-getModifierState.html [ Timeout ]
-crbug.com/714962 virtual/mouseevent_fractional/fast/events/offsetX-offsetY.html [ Failure ]
 crbug.com/591099 virtual/mouseevent_fractional/fast/events/onclick-list-marker.html [ Failure ]
 crbug.com/591099 virtual/mouseevent_fractional/fast/events/pointer-events-2.html [ Failure ]
 crbug.com/591099 virtual/mouseevent_fractional/fast/events/pointerevents/mouse-pointer-capture-transition-events.html [ Timeout ]
-crbug.com/591099 virtual/mouseevent_fractional/fast/events/pointerevents/mouse-pointer-capture.html [ Pass Timeout ]
+crbug.com/591099 virtual/mouseevent_fractional/fast/events/pointerevents/mouse-pointer-capture.html [ Timeout ]
 crbug.com/591099 virtual/mouseevent_fractional/fast/events/pointerevents/mouse-pointer-preventdefault.html [ Timeout ]
 crbug.com/591099 virtual/mouseevent_fractional/fast/events/pointerevents/multi-pointer-preventdefault.html [ Pass Timeout ]
 crbug.com/591099 virtual/mouseevent_fractional/fast/events/pointerevents/touch-capture-in-iframe.html [ Timeout ]
@@ -3119,7 +2474,6 @@
 crbug.com/591099 virtual/mouseevent_fractional/fast/events/touch/compositor-touch-hit-rects-scroll.html [ Failure ]
 crbug.com/591099 virtual/mouseevent_fractional/fast/events/touch/compositor-touch-hit-rects.html [ Failure ]
 crbug.com/591099 virtual/mouseevent_fractional/fast/events/wheel/mainthread-touchpad-fling-latching.html [ Pass ]
-crbug.com/591099 virtual/mouseevent_fractional/fast/events/wheel/mouse-wheel-scroll-latching.html [ Pass ]
 crbug.com/591099 virtual/mouseevent_fractional/fast/events/wheel/wheel-scroll-latching-on-scrollbar.html [ Pass ]
 crbug.com/714962 virtual/mouseevent_fractional/fast/events/wheel/wheelevent-basic.html [ Failure Pass ]
 crbug.com/591099 virtual/navigation-mojo-response/external/wpt/service-workers/service-worker/ServiceWorkerGlobalScope/registration-attribute.https.html [ Failure Pass ]
@@ -3128,7 +2482,7 @@
 crbug.com/591099 virtual/outofblink-cors/ [ Skip ]
 crbug.com/591099 virtual/paint-timing/external/wpt/paint-timing/sibling-painting-first-image.html [ Failure ]
 crbug.com/591099 virtual/prefer_compositing_to_lcd_text/ [ Skip ]
-crbug.com/714962 virtual/pwa-full-code-cache/http/tests/devtools/service-workers/service-workers-view.js [ Failure ]
+crbug.com/714962 virtual/pwa-full-code-cache/http/tests/devtools/service-workers/service-workers-view.js [ Failure Pass ]
 crbug.com/591099 virtual/reporting-api/external/wpt/content-security-policy/reporting-api/reporting-api-doesnt-send-reports-without-violation.https.sub.html [ Pass ]
 crbug.com/591099 virtual/scalefactor150/fast/hidpi/static/popup-menu-with-scrollbar-appearance.html [ Failure ]
 crbug.com/591099 virtual/scalefactor200/fast/hidpi/static/popup-menu-with-scrollbar-appearance.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
index 225f6150..156594c 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
@@ -59,6 +59,9 @@
 Bug(none) http/tests/security/cookies/third-party-cookie-blocking-user-action.html [ Failure ]
 Bug(none) http/tests/security/cookies/third-party-cookie-blocking-worker.html [ Failure ]
 Bug(none) http/tests/security/cookies/third-party-cookie-blocking-xslt.xml [ Failure ]
+Bug(none) http/tests/security/cookies/websocket/third-party-cookie-blocked-on-cross-origin-websocket.html [ Failure ]
+Bug(none) http/tests/security/cookies/websocket/third-party-cookie-blocked-on-same-origin-websocket.html [ Failure ]
+Bug(none) http/tests/security/cookies/websocket/third-party-cookie-blocked.html [ Failure ]
 Bug(none) http/tests/security/cors-rfc1918 [ Crash Timeout ]
 Bug(none) http/tests/security/media-element-audio-source-node-cross-origin.html [ Failure Pass Timeout ]
 Bug(none) http/tests/security/media-element-audio-source-node-same-origin.html [ Failure Pass ]
@@ -84,20 +87,6 @@
 # Started failing @ r529490
 Bug(none) virtual/layout_ng/fast/inline/positioned-object-between-replaced-elements.html [ Failure ]
 
-# http://crbug.com/721400 get WebSockets working with network service.
-# http://crbug.com/803958: Tests failing on bot but not in local checkout.
-crbug.com/803958 external/wpt/websockets/cookies/001.html?wss [ Failure ]
-crbug.com/803958 external/wpt/websockets/cookies/002.html?wss [ Failure ]
-crbug.com/803958 external/wpt/websockets/cookies/003.html?wss [ Failure ]
-crbug.com/803958 external/wpt/websockets/cookies/007.html [ Failure ]
-crbug.com/803958 external/wpt/websockets/cookies/007.html?wss [ Failure ]
-crbug.com/721400 external/wpt/websockets/cookies/001.html [ Failure ]
-crbug.com/721400 external/wpt/websockets/cookies/002.html [ Failure ]
-crbug.com/721400 external/wpt/websockets/cookies/003.html [ Failure ]
-crbug.com/721400 external/wpt/websockets/cookies/006.html?wss [ Crash ]
-crbug.com/721400 external/wpt/websockets/opening-handshake/003.html?wss [ Pass Timeout ]
-crbug.com/721400 http/tests/websocket/cookie-document-to-ws.html [ Failure ]
-crbug.com/721400 http/tests/websocket/cookie-http-to-ws.pl [ Failure ]
-crbug.com/721400 http/tests/websocket/httponly-cookie.pl [ Failure ]
+crbug.com/825687 http/tests/devtools/websocket/websocket-handshake.js [ Failure ]
 
 crbug.com/816556 external/wpt/html/semantics/text-level-semantics/the-a-element/a-download-click-404.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
index fcc8e24..c3eefef 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
@@ -552,6 +552,7 @@
 Bug(none) fast/selectors/166.html [ Failure ]
 Bug(none) fast/sub-pixel/repaint-subpixel-layer-in-subpixel-composited-layer.html [ Failure ]
 Bug(none) fast/sub-pixel/should-not-repaint-subpixel-composited-layer.html [ Failure ]
+Bug(none) fast/sub-pixel/sub-pixel-transparency-layer.html [ Failure ]
 Bug(none) fast/sub-pixel/transformed-iframe-copy-on-scroll.html [ Failure ]
 Bug(none) fast/table/023.html [ Failure ]
 Bug(none) fast/table/027-vertical.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/NeverFixTests b/third_party/WebKit/LayoutTests/NeverFixTests
index f11e56b..a35d4c8 100644
--- a/third_party/WebKit/LayoutTests/NeverFixTests
+++ b/third_party/WebKit/LayoutTests/NeverFixTests
@@ -237,7 +237,7 @@
 
 # We could fix this test for us and upstream it if the test shell user agent
 # would let us differentiate test_shell and WebKit DumpTreeNode.
-crbug.com/7482 [ Win Mac ] http/tests/misc/timer-vs-loading.html [ WontFix ]
+crbug.com/7482 [ Linux Win Mac ] http/tests/misc/timer-vs-loading.html [ WontFix ]
 
 # On Linux bold emoji are already supported.
 crbug.com/551843 [ Linux ] fast/text/fallback-traits-fixup.html [ WontFix ]
@@ -750,8 +750,6 @@
 external/wpt/css/css-writing-modes/first-page-vrl-002.xht [ WontFix ]
 external/wpt/css/css-writing-modes/page-flow-direction-002.xht [ WontFix ]
 external/wpt/css/css-writing-modes/page-flow-direction-003.xht [ WontFix ]
-external/wpt/css/css-writing-modes/page-flow-direction-slr-005.xht [ WontFix ]
-external/wpt/css/css-writing-modes/page-flow-direction-srl-004.xht [ WontFix ]
 external/wpt/css/selectors/hover-001-manual.html [ WontFix ]
 external/wpt/entries-api/errors-manual.html [ WontFix ]
 external/wpt/entries-api/filesystemdirectoryentry-attributes-manual.html [ WontFix ]
diff --git a/third_party/WebKit/LayoutTests/SlowTests b/third_party/WebKit/LayoutTests/SlowTests
index 4147c66..78e2ccb 100644
--- a/third_party/WebKit/LayoutTests/SlowTests
+++ b/third_party/WebKit/LayoutTests/SlowTests
@@ -504,3 +504,13 @@
 # This test is very CPU intensive, as it parses a lot of IDL in JS. It's slow
 # even on a normal bot, and takes over a minute with MSAN.
 crbug.com/810963 external/wpt/dom/interfaces.html [ Slow ]
+
+# css-transitions test imported from wpt which sometimes time out according to
+# the flakiness dashboard. They are slow because of many tests and/or long
+# transition durations.
+crbug.com/825170 external/wpt/css/css-transitions/properties-value-001.html [ Slow ]
+crbug.com/825170 external/wpt/css/css-transitions/properties-value-003.html [ Slow ]
+crbug.com/825170 external/wpt/css/css-transitions/properties-value-implicit-001.html [ Slow ]
+crbug.com/825170 external/wpt/css/css-transitions/properties-value-inherit-001.html [ Slow ]
+crbug.com/825170 external/wpt/css/css-transitions/properties-value-inherit-002.html [ Slow ]
+crbug.com/825170 external/wpt/css/css-transitions/transitioncancel-001.html [ Slow ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index c842eaca..7f77e3b 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -68,7 +68,7 @@
 crbug.com/771643 compositing/overflow/nested-border-radius-clipping.html [ Failure ]
 crbug.com/771643 virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-border-radius-clipping.html [ Failure ]
 
-crbug.com/771643 [ Mac ] virtual/gpu-rasterization/images/color-profile-filter.html [ Timeout Pass Failure ]
+crbug.com/771643 [ Mac Win ] virtual/gpu-rasterization/images/color-profile-filter.html [ Timeout Pass Failure ]
 crbug.com/805134 http/tests/devtools/tracing/scroll-invalidations.js [ Failure ]
 crbug.com/805134 virtual/threaded/http/tests/devtools/tracing/scroll-invalidations.js [ Failure ]
 
@@ -1026,14 +1026,6 @@
 crbug.com/492664 external/wpt/css/css-writing-modes/line-box-height-vlr-023.xht [ Failure ]
 crbug.com/492664 external/wpt/css/css-writing-modes/ortho-htb-alongside-vrl-floats-006.xht [ Failure ]
 crbug.com/492664 external/wpt/css/css-writing-modes/ortho-htb-alongside-vrl-floats-014.xht [ Failure ]
-crbug.com/492664 external/wpt/css/css-writing-modes/table-column-order-002.xht [ Failure ]
-crbug.com/492664 external/wpt/css/css-writing-modes/table-column-order-003.xht [ Failure ]
-crbug.com/492664 external/wpt/css/css-writing-modes/table-column-order-004.xht [ Failure ]
-crbug.com/492664 external/wpt/css/css-writing-modes/table-column-order-005.xht [ Failure ]
-crbug.com/492664 external/wpt/css/css-writing-modes/table-progression-vlr-003.html [ Failure ]
-crbug.com/492664 external/wpt/css/css-writing-modes/table-progression-vlr-004.html [ Failure ]
-crbug.com/492664 external/wpt/css/css-writing-modes/table-progression-vrl-003.html [ Failure ]
-crbug.com/492664 external/wpt/css/css-writing-modes/table-progression-vrl-004.html [ Failure ]
 
 crbug.com/637055 fast/css/outline-offset-large.html [ Skip ]
 
@@ -1057,8 +1049,6 @@
 crbug.com/492664 external/wpt/css/css-writing-modes/clip-rect-vrl-008.xht [ Failure ]
 crbug.com/492664 external/wpt/css/css-writing-modes/line-box-direction-vrl-009.xht [ Failure ]
 
-crbug.com/813545 [ Debug ] media/video-transformed.html [ Skip ]
-
 # These tests pass but images do not match because tests are stricter than the spec.
 crbug.com/492664 external/wpt/css/css-writing-modes/text-combine-upright-value-all-001.html [ Failure ]
 crbug.com/492664 external/wpt/css/css-writing-modes/text-combine-upright-value-all-002.html [ Failure ]
@@ -1071,7 +1061,6 @@
 crbug.com/492664 [ Mac ] external/wpt/css/css-writing-modes/sizing-orthog-htb-in-vlr-020.xht [ Failure ]
 crbug.com/492664 [ Mac ] external/wpt/css/css-writing-modes/sizing-orthog-htb-in-vrl-008.xht [ Failure ]
 crbug.com/492664 [ Mac ] external/wpt/css/css-writing-modes/sizing-orthog-htb-in-vrl-020.xht [ Failure ]
-crbug.com/626703 external/wpt/css/css-writing-modes/wm-propagation-body-008.xht [ Failure ]
 
 crbug.com/498845 [ Win ] fast/multicol/vertical-rl/float-content-break.html [ Failure ]
 crbug.com/443615 [ Linux Win ] external/wpt/css/css-shapes/shape-outside/supported-shapes/circle/shape-outside-circle-027.html [ Failure ]
@@ -1342,6 +1331,8 @@
 crbug.com/736319 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-006.html [ Failure ]
 crbug.com/736319 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-006a.html [ Failure ]
 
+crbug.com/825349 http/tests/devtools/console/command-line-api.js [ Skip ]
+
 crbug.com/752449 [ Mac10.12 Mac10.13 Retina ] external/wpt/css/css-fonts/matching/fixed-stretch-style-over-weight.html [ Failure ]
 crbug.com/752449 [ Mac10.12 Retina ] external/wpt/css/css-fonts/matching/stretch-distance-over-weight-distance.html [ Failure ]
 crbug.com/752449 [ Mac10.12 Retina ] external/wpt/css/css-fonts/matching/style-ranges-over-weight-direction.html [ Failure ]
@@ -1677,6 +1668,68 @@
 crbug.com/805463 external/wpt/acid/acid3/numbered-tests.html [ Skip ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-017.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-030.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-015.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-021.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-039.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-timing-function-008.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-timing-function-002.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-012.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-014.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-016.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-timing-function-007.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-009.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-029.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-023.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-027.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-timing-function-010.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-003.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-011.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-008.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-timing-function-011.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-020.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-timing-function-013.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-timing-function-012.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-031.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-delay-000.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-041.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-026.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-duration-003.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-delay-002.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-timing-function-005.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-004.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-006.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-018.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-022.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transitions-animatable-properties-01.html [ Timeout Failure ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-duration-002.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-024.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-timing-function-009.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-037.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-007.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-005.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-042.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-036.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-038.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-delay-003.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-010.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-028.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-timing-function-004.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-043.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-040.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-019.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-034.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-045.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-035.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-033.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-timing-function-003.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-044.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-timing-function-006.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-duration-004.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-032.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-025.html [ Skip ]
+crbug.com/626703 external/wpt/css/css-transitions/transition-property-013.html [ Skip ]
 crbug.com/626703 [ Mac10.11 ] external/wpt/payment-request/show-method-postmessage-manual.https.html [ Skip ]
 crbug.com/626703 [ Linux Mac10.10 Mac10.12 Mac10.13 Retina Win ] external/wpt/payment-request/show-method-postmessage-manual.https.html [ Skip ]
 crbug.com/626703 virtual/incremental-shadow-dom/external/wpt/css/css-scoping/shadow-fallback-dynamic-001.html [ Failure ]
@@ -1812,19 +1865,7 @@
 crbug.com/626703 external/wpt/css/css-text/astral-bidi/adlam-anti-ref.html [ Pass Failure ]
 crbug.com/626703 external/wpt/css/css-text/astral-bidi/cypriot-anti-ref.html [ Pass Failure ]
 crbug.com/626703 external/wpt/css/css-fill-stroke/paint-order-001.tentative.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-writing-modes/logical-props-001.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-writing-modes/ch-units-vrl-004.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-writing-modes/ch-units-vrl-006.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-writing-modes/ch-units-vrl-001.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-writing-modes/logical-props-004.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-writing-modes/logical-props-003.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-writing-modes/ch-units-vrl-008.html [ Failure ]
 crbug.com/626703 [ Android ] virtual/media-gpu-accelerated/external/wpt/media-source/mediasource-play.html [ Crash ]
-crbug.com/626703 external/wpt/css/css-writing-modes/ch-units-vrl-005.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-writing-modes/ch-units-vrl-007.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-writing-modes/logical-props-002.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-writing-modes/ch-units-vrl-003.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-writing-modes/ch-units-vrl-002.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-writing-modes/available-size-002.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-writing-modes/available-size-006.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-writing-modes/available-size-007.html [ Failure ]
@@ -1865,8 +1906,6 @@
 crbug.com/626703 external/wpt/html/rendering/non-replaced-elements/the-page/body-margin-2l.html [ Failure ]
 crbug.com/626703 external/wpt/webaudio/the-audio-api/the-analysernode-interface/test-analyser-minimum.html [ Timeout ]
 crbug.com/626703 external/wpt/webaudio/the-audio-api/the-analysernode-interface/test-analyser-output.html [ Timeout ]
-crbug.com/626703 external/wpt/css/css-writing-modes/table-cell-001.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-writing-modes/table-cell-002.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-fonts/font-synthesis-01.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-fonts/font-synthesis-02.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-fonts/font-synthesis-03.html [ Failure ]
@@ -2969,7 +3008,6 @@
 
 # Tests occasionaly timing out (flaky) on WebKit Win7 dbg builder
 crbug.com/757955 [ Win7 Debug ] http/tests/devtools/sources/debugger-pause/pause-on-elements-panel.js [ Pass Timeout ]
-crbug.com/757955 [ Win7 ] media/color-profile-video-seek-filter.html [ Pass Timeout ]
 crbug.com/757955 [ Win7 Debug ] storage/indexeddb/mozilla/cursors.html [ Pass Timeout ]
 crbug.com/757955 [ Win7 Debug ] storage/indexeddb/objectstore-cursor.html [ Pass Timeout ]
 crbug.com/757955 http/tests/devtools/tracing/timeline-paint/layer-tree.js [ Pass Failure Timeout ]
@@ -3356,3 +3394,22 @@
 
 # Sheriff 2018-03-22
 crbug.com/824775 [ Win Mac ] virtual/new-remote-playback-pipeline/media/controls/video-controls-with-cast-rendering.html [ Pass Failure ]
+crbug.com/824775 [ Win Mac ] media/controls/video-controls-with-cast-rendering.html [ Pass Failure ]
+crbug.com/824830 [ Win ] fast/peerconnection/RTCPeerConnection-many.html [ Timeout Crash Failure Pass ]
+crbug.com/824848 [ Linux Win ] external/wpt/html/semantics/links/following-hyperlinks/activation-behavior.window.html [ Pass Failure ]
+crbug.com/824904 inspector-protocol/heap-profiler/heap-objects-tracking.js [ Pass Failure ]
+crbug.com/824930 svg/animations/getCurrentTime-pause-unpause.html [ Pass Failure ]
+crbug.com/824955 external/wpt/css/css-font-loading/idlharness.https.html [ Pass Failure ]
+crbug.com/825046 virtual/mouseevent_fractional/fast/events/mouse-event-buttons-attribute.html [ Pass Failure ]
+
+# Sheriff 2018-03-23
+crbug.com/825209 [ Win10 ] editing/composition-underline-color.html [ Failure ]
+crbug.com/825262 [ Win Mac Linux ] external/wpt/css/css-transitions/properties-value-001.html [ Pass Failure ]
+crbug.com/825262 [ Win Mac Linux ] external/wpt/css/css-transitions/properties-value-inherit-001.html [ Pass Failure ]
+crbug.com/825262 [ Win Mac Linux ] external/wpt/css/css-transitions/properties-value-inherit-002.html [ Pass Failure ]
+crbug.com/825262 [ Win ] external/wpt/css/css-transitions/properties-value-003.html [ Pass Failure ]
+crbug.com/825262 [ Win7 ] external/wpt/css/css-transitions/properties-value-implicit-001.html [ Pass Failure ]
+
+# Sheriff 2018-03-26
+crbug.com/825733 [ Win7 ] media/color-profile-video-seek-filter.html [ Pass Timeout Failure ]
+crbug.com/754986 media/video-transformed.html [ Pass Failure ]
diff --git a/third_party/WebKit/LayoutTests/animations/web-animations/KeyframeEffect-animation.html b/third_party/WebKit/LayoutTests/animations/web-animations/KeyframeEffect-animation.html
new file mode 100644
index 0000000..f46dc7c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/animations/web-animations/KeyframeEffect-animation.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Animating with KeyframeEffect objects</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../../external/wpt/web-animations/testcommon.js"></script>
+<body>
+<script>
+"use strict";
+
+test(function(t) {
+  var target = createDiv(t);
+  var effect = new KeyframeEffect(target, null);
+  var anim = target.animate(null);
+  anim.effect = effect;
+  assert_class_string(anim.effect, "KeyframeEffect");
+  assert_class_string(anim.effect.timing, "AnimationEffectTiming");
+}, "An animation can be created with a KeyframeEffect, and the effect"
+   + " is of the expected type");
+
+test(function(t) {
+  var target = createDiv(t);
+  var effect = new KeyframeEffect(target, { opacity: [0, 0.9] }, 1000);
+  var anim = target.animate(null);
+  anim.pause();
+  anim.effect = effect;
+  anim.currentTime = 500;
+  assert_equals(getComputedStyle(target).opacity, '0.45',
+      'opacity at mid-point');
+}, "An animation based on a KeyframeEffect applies an effect");
+
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/animations/web-animations/KeyframeEffect-getKeyframes-correct-context.html b/third_party/WebKit/LayoutTests/animations/web-animations/KeyframeEffect-getKeyframes-correct-context.html
new file mode 100644
index 0000000..3afdf2a7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/animations/web-animations/KeyframeEffect-getKeyframes-correct-context.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>KeyframeEffect::getKeyframes should use correct context</title>
+
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../../external/wpt/web-animations/testcommon.js"></script>
+
+<div id="elem"></div>
+<iframe id="iframe"></iframe>
+
+<script>
+"use strict";
+
+// This test checks a particularly nasty corner-case of getKeyframes(). Because
+// getKeyframes() manually constructs a JavaScript object to pass back, care
+// must be taken to ensure that the resultant object is in the same context as
+// the KeyframeEffect object it is being applied to.
+test(function(t) {
+  const effect = new KeyframeEffect(elem, [
+      { left: "0px" },
+      { left: "20px" }
+  ], 1000);
+  const iframe = document.getElementById("iframe");
+  const keyframes = iframe.contentWindow.KeyframeEffect.prototype
+      .getKeyframes.apply(effect);
+
+  assert_equals(Object.getPrototypeOf(keyframes[0]), Object.prototype);
+}, "Applying getKeyframes to a KeyframeEffect object from another "
+   + " frame should produce keyframes in the same frame as the object.");
+
+</script>
+
diff --git a/third_party/WebKit/LayoutTests/animations/web-animations/KeyframeEffectReadOnly-animation.html b/third_party/WebKit/LayoutTests/animations/web-animations/KeyframeEffectReadOnly-animation.html
deleted file mode 100644
index b9f20510..0000000
--- a/third_party/WebKit/LayoutTests/animations/web-animations/KeyframeEffectReadOnly-animation.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>Animating with KeyframeEffectReadOnly objects</title>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../external/wpt/web-animations/testcommon.js"></script>
-<body>
-<script>
-"use strict";
-
-test(function(t) {
-  var target = createDiv(t);
-  var effect = new KeyframeEffectReadOnly(target, null);
-  var anim = target.animate(null);
-  anim.effect = effect;
-  assert_class_string(anim.effect, "KeyframeEffectReadOnly");
-  assert_class_string(anim.effect.timing, "AnimationEffectTimingReadOnly");
-}, "An animation can be created with a KeyframeEffectReadOnly, and the effect"
-   + " is of the expected type");
-
-test(function(t) {
-  var target = createDiv(t);
-  var effect = new KeyframeEffectReadOnly(target, { opacity: [0, 0.9] }, 1000);
-  var anim = target.animate(null);
-  anim.pause();
-  anim.effect = effect;
-  anim.currentTime = 500;
-  assert_equals(getComputedStyle(target).opacity, '0.45',
-      'opacity at mid-point');
-}, "An animation based on a KeyframeEffectReadOnly applies an effect");
-
-</script>
-</body>
diff --git a/third_party/WebKit/LayoutTests/animations/web-animations/KeyframeEffectReadOnly-getKeyframes-correct-context.html b/third_party/WebKit/LayoutTests/animations/web-animations/KeyframeEffectReadOnly-getKeyframes-correct-context.html
deleted file mode 100644
index 8e0ee1c..0000000
--- a/third_party/WebKit/LayoutTests/animations/web-animations/KeyframeEffectReadOnly-getKeyframes-correct-context.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>KeyframeEffectReadOnly::getKeyframes should use correct context</title>
-
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../external/wpt/web-animations/testcommon.js"></script>
-
-<div id="elem"></div>
-<iframe id="iframe"></iframe>
-
-<script>
-"use strict";
-
-// This test checks a particularly nasty corner-case of getKeyframes(). Because
-// getKeyframes() manually constructs a JavaScript object to pass back, care
-// must be taken to ensure that the resultant object is in the same context as
-// the KeyframeEffectReadOnly object it is being applied to.
-test(function(t) {
-  const effect = new KeyframeEffectReadOnly(elem, [
-      { left: "0px" },
-      { left: "20px" }
-  ], 1000);
-  const iframe = document.getElementById("iframe");
-  const keyframes = iframe.contentWindow.KeyframeEffectReadOnly.prototype
-      .getKeyframes.apply(effect);
-
-  assert_equals(Object.getPrototypeOf(keyframes[0]), Object.prototype);
-}, "Applying getKeyframes to a KeyframeEffectReadOnly object from another "
-   + " frame should produce keyframes in the same frame as the object.");
-
-</script>
-
diff --git a/third_party/WebKit/LayoutTests/animations/web-animations/api-readonly-object-types.html b/third_party/WebKit/LayoutTests/animations/web-animations/api-readonly-object-types.html
index 7e1ef50..6a7b47ee 100644
--- a/third_party/WebKit/LayoutTests/animations/web-animations/api-readonly-object-types.html
+++ b/third_party/WebKit/LayoutTests/animations/web-animations/api-readonly-object-types.html
@@ -16,13 +16,5 @@
   assert_class_string(effect.timing, "AnimationEffectTiming");
 }, "KeyframeEffect constructor creates and exposes an AnimationEffectTiming"
    + " object");
-
-test(function(t) {
-  var target = createDiv(t);
-  var effect = new KeyframeEffectReadOnly(target, null);
-  assert_class_string(effect, "KeyframeEffectReadOnly");
-  assert_class_string(effect.timing, "AnimationEffectTimingReadOnly");
-}, "KeyframeEffectReadOnly constructor creates and exposes an"
-   + " AnimationEffectTimingReadOnly object");
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-descriptor-is-removed.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-descriptor-is-removed.html
index e8699eb..f6dee88 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-descriptor-is-removed.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-descriptor-is-removed.html
@@ -7,28 +7,20 @@
 <script src="../../../external/wpt/bluetooth/resources/bluetooth-helpers.js"></script>
 <script>
 'use strict';
-bluetooth_test(() => {
-  let val = new Uint8Array([1]);
-  return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter')
-      .then(
-          () => requestDeviceWithTrustedClick(
-              {filters: [{services: ['health_thermometer']}]}))
-      .then(device => device.gatt.connect())
-      .then(gattServer => gattServer.getPrimaryService('health_thermometer'))
-      .then(service => service.getCharacteristic('measurement_interval'))
-      .then(
-          characteristic => characteristic.getDescriptor(user_description.name))
-      .then(descriptor => {
-        return setBluetoothFakeAdapter(
-                   'MissingDescriptorsDisconnectingHealthThermometerAdapter')
-            .then(
-                () => assert_promise_rejects_with_message(
-                    descriptor.readValue(),
-                    new DOMException(
-                        'GATT Descriptor no longer exists.',
-                        'InvalidStateError'),
-                    'Descriptor got removed.'));
-      });
-}, 'Descriptor gets removed. Reject with InvalidStateError.');
+const test_desc = 'Descriptor gets removed. Reject with InvalidStateError.';
+const expected = new DOMException('GATT Descriptor no longer exists.',
+    'InvalidStateError');
+let descriptor, fake_descriptor, fake_characteristic, fake_peripheral;
+
+bluetooth_test(() => getUserDescriptionDescriptor()
+    .then(_ =>
+      ({descriptor, fake_descriptor, fake_characteristic, fake_peripheral} = _))
+    .then(() => fake_descriptor.remove())
+    .then(() => fake_peripheral.simulateGATTServicesChanged())
+    .then(() => assert_promise_rejects_with_message(
+        descriptor.readValue(),
+        expected,
+        'Descriptor got removed')),
+    test_desc);
 
 </script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-descriptor-is-removed.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-descriptor-is-removed.html
index d4d6032a..0927698 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-descriptor-is-removed.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-descriptor-is-removed.html
@@ -7,28 +7,20 @@
 <script src="../../../external/wpt/bluetooth/resources/bluetooth-helpers.js"></script>
 <script>
 'use strict';
-bluetooth_test(() => {
-  let val = new Uint8Array([1]);
-  return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter')
-      .then(
-          () => requestDeviceWithTrustedClick(
-              {filters: [{services: ['health_thermometer']}]}))
-      .then(device => device.gatt.connect())
-      .then(gattServer => gattServer.getPrimaryService('health_thermometer'))
-      .then(service => service.getCharacteristic('measurement_interval'))
-      .then(
-          characteristic => characteristic.getDescriptor(user_description.name))
-      .then(descriptor => {
-        return setBluetoothFakeAdapter(
-                   'MissingDescriptorsDisconnectingHealthThermometerAdapter')
-            .then(
-                () => assert_promise_rejects_with_message(
-                    descriptor.writeValue(val),
-                    new DOMException(
-                        'GATT Descriptor no longer exists.',
-                        'InvalidStateError'),
-                    'Descriptor got removed.'));
-      });
-}, 'Descriptor gets removed. Reject with InvalidStateError.');
+const test_desc = 'Descriptor gets removed. Reject with InvalidStateError.';
+const expected = new DOMException('GATT Descriptor no longer exists.',
+    'InvalidStateError');
+let descriptor, fake_descriptor, fake_characteristic, fake_peripheral;
+
+bluetooth_test(() => getUserDescriptionDescriptor()
+    .then(_ =>
+      ({descriptor, fake_descriptor, fake_characteristic, fake_peripheral} = _))
+    .then(() => fake_descriptor.remove())
+    .then(() => fake_peripheral.simulateGATTServicesChanged())
+    .then(() => assert_promise_rejects_with_message(
+        descriptor.writeValue(new Uint8Array(1 /* length */)),
+        expected,
+        'Descriptor got removed')),
+    test_desc);
 
 </script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/write-succeeds.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/write-succeeds.html
index 6ce8e3b..ff6fa163 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/write-succeeds.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/write-succeeds.html
@@ -6,19 +6,36 @@
 <script src="../../../external/wpt/bluetooth/resources/bluetooth-helpers.js"></script>
 <script>
 'use strict';
-bluetooth_test(() => {
-  let length = 1;
-  let descriptor;
-  return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter')
-    .then(() => requestDeviceWithTrustedClick({
-      filters: [{services: ['health_thermometer']}]}))
-    .then(device => device.gatt.connect())
-    .then(gattServer => gattServer.getPrimaryService('health_thermometer'))
-    .then(service => service.getCharacteristic('measurement_interval'))
-    .then(characteristic => characteristic.getDescriptor(user_description.name))
-    .then(d => descriptor = d)
-    .then(() => descriptor.writeValue(new Uint8Array(length)))
-    .then(() => descriptor.writeValue(new ArrayBuffer(length)))
-    .then(() => descriptor.writeValue(new DataView(new ArrayBuffer(length))));
-    }, 'A regular write request to a writable descriptor should succeed.');
+const test_desc = 'A regular write request to a writable descriptor ' +
+    'should succeed.';
+let typed_array = Uint8Array.of(1, 2);
+let array_buffer = Uint8Array.of(3, 4).buffer;
+let data_view = new DataView(new ArrayBuffer(2));
+let descriptor, fake_descriptor;
+
+bluetooth_test(() => getUserDescriptionDescriptor()
+    .then(_ => ({descriptor, fake_descriptor} = _))
+    .then(() => new Promise(resolve => {
+        data_view.setUint8(0, 5);
+        data_view.setUint8(1, 6);
+        resolve();
+    }))
+    .then(() => fake_descriptor.getLastWrittenValue())
+    .then(last_value => assert_true(last_value === null))
+
+    .then(() => fake_descriptor.setNextWriteResponse(GATT_SUCCESS))
+    .then(() => descriptor.writeValue(typed_array))
+    .then(() => fake_descriptor.getLastWrittenValue())
+    .then(last_value => assert_array_equals(last_value, [1, 2]))
+
+    .then(() => fake_descriptor.setNextWriteResponse(GATT_SUCCESS))
+    .then(() => descriptor.writeValue(array_buffer))
+    .then(() => fake_descriptor.getLastWrittenValue())
+    .then(last_value => assert_array_equals(last_value, [3, 4]))
+
+    .then(() => fake_descriptor.setNextWriteResponse(GATT_SUCCESS))
+    .then(() => descriptor.writeValue(data_view))
+    .then(() => fake_descriptor.getLastWrittenValue())
+    .then(last_value => assert_array_equals(last_value, [5, 6])),
+    test_desc);
 </script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/write-updates-value.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/write-updates-value.html
index dba3dd1..56aef5a 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/write-updates-value.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/write-updates-value.html
@@ -6,23 +6,18 @@
 <script src="../../../external/wpt/bluetooth/resources/bluetooth-helpers.js"></script>
 <script>
 'use strict';
-bluetooth_test(() => {
-  return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter')
-    .then(() => requestDeviceWithTrustedClick({
-      filters: [{services: ['health_thermometer']}]}))
-    .then(device => device.gatt.connect())
-    .then(gattServer => gattServer.getPrimaryService('health_thermometer'))
-    .then(service => service.getCharacteristic('measurement_interval'))
-    .then(characteristic => characteristic.getDescriptor(user_description.name))
-    .then(descriptor => {
-      assert_equals(descriptor.value, null);
-      let textEncoder = new TextEncoder();
-      let newValue = textEncoder.encode('foo');
-      assert_true(newValue instanceof Uint8Array, 'newValue is Uint8Array');
-      return descriptor.writeValue(newValue).then(() => {
-        assert_true(descriptor.value instanceof DataView, 'descriptor.value is DataView');
-        assert_array_equals(Array.from(descriptor.value.getUint8()), Array.from(newValue.buffer));
-      })
-    })
-}, 'Succesful read should update descriptor\'s value.');
+const test_desc = 'Successful write should update descriptor\'s value.';
+const newValue = new TextEncoder().encode('foo');
+let descriptor, fake_descriptor;
+
+bluetooth_test(() => getUserDescriptionDescriptor()
+    .then(_ => ({descriptor, fake_descriptor} = _))
+    .then(() => assert_equals(descriptor.value, null))
+    .then(() => fake_descriptor.setNextWriteResponse(GATT_SUCCESS))
+    .then(() => descriptor.writeValue(newValue))
+    .then(() => assert_array_equals(
+        new Uint8Array(descriptor.value.buffer), newValue))
+    .then(() => fake_descriptor.getLastWrittenValue())
+    .then(lastValue => assert_array_equals(lastValue, newValue)),
+    test_desc);
 </script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/descriptor-is-removed.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/descriptor-is-removed.js
index 8a1d00c1..f3c73e1 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/descriptor-is-removed.js
+++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/descriptor/descriptor-is-removed.js
@@ -1,24 +1,19 @@
 'use strict';
-bluetooth_test(() => {
-  let val = new Uint8Array([1]);
-  return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter')
-      .then(
-          () => requestDeviceWithTrustedClick(
-              {filters: [{services: ['health_thermometer']}]}))
-      .then(device => device.gatt.connect())
-      .then(gattServer => gattServer.getPrimaryService('health_thermometer'))
-      .then(service => service.getCharacteristic('measurement_interval'))
-      .then(
-          characteristic => characteristic.getDescriptor(user_description.name))
-      .then(descriptor => {
-        return setBluetoothFakeAdapter(
-                   'MissingDescriptorsDisconnectingHealthThermometerAdapter')
-            .then(
-                () => assert_promise_rejects_with_message(
-                    descriptor.CALLS([readValue()|writeValue(val)]),
-                    new DOMException(
-                        'GATT Descriptor no longer exists.',
-                        'InvalidStateError'),
-                    'Descriptor got removed.'));
-      });
-}, 'Descriptor gets removed. Reject with InvalidStateError.');
+const test_desc = 'Descriptor gets removed. Reject with InvalidStateError.';
+const expected = new DOMException('GATT Descriptor no longer exists.',
+    'InvalidStateError');
+let descriptor, fake_descriptor, fake_characteristic, fake_peripheral;
+
+bluetooth_test(() => getUserDescriptionDescriptor()
+    .then(_ =>
+      ({descriptor, fake_descriptor, fake_characteristic, fake_peripheral} = _))
+    .then(() => fake_descriptor.remove())
+    .then(() => fake_peripheral.simulateGATTServicesChanged())
+    .then(() => assert_promise_rejects_with_message(
+        descriptor.CALLS([
+          readValue()|
+          writeValue(new Uint8Array(1 /* length */))
+        ]),
+        expected,
+        'Descriptor got removed')),
+    test_desc);
diff --git a/third_party/WebKit/LayoutTests/compositing/video/video-reflection-expected.png b/third_party/WebKit/LayoutTests/compositing/video/video-reflection-expected.png
deleted file mode 100644
index 635d07ac..0000000
--- a/third_party/WebKit/LayoutTests/compositing/video/video-reflection-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/editing/composition-underline-color.html b/third_party/WebKit/LayoutTests/editing/composition-underline-color.html
new file mode 100644
index 0000000..7bbd579c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/editing/composition-underline-color.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<meta charset="UTF-8">
+<style>
+#test {
+  outline: none;
+  color: lime;
+  padding: 50px;
+  background: black;
+}
+</style>
+<p id="text">
+This test checks that composition underline color uses the color of the text and is not always black.
+The test passes if you see the word "foobar" in green with a composition underline in the same color.
+</p>
+
+<div contenteditable id="test"></div>
+<script>
+var test = document.getElementById("test");
+test.focus();
+if (window.textInputController)
+  textInputController.setComposition("foobar");
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
index ffa2948..0dfef3f9 100644
--- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
+++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -1663,6 +1663,372 @@
      {}
     ]
    ],
+   "css/css-transitions/transition-delay-000.html": [
+    [
+     "/css/css-transitions/transition-delay-000.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-delay-002.html": [
+    [
+     "/css/css-transitions/transition-delay-002.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-delay-003.html": [
+    [
+     "/css/css-transitions/transition-delay-003.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-duration-002.html": [
+    [
+     "/css/css-transitions/transition-duration-002.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-duration-003.html": [
+    [
+     "/css/css-transitions/transition-duration-003.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-duration-004.html": [
+    [
+     "/css/css-transitions/transition-duration-004.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-003.html": [
+    [
+     "/css/css-transitions/transition-property-003.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-004.html": [
+    [
+     "/css/css-transitions/transition-property-004.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-005.html": [
+    [
+     "/css/css-transitions/transition-property-005.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-006.html": [
+    [
+     "/css/css-transitions/transition-property-006.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-007.html": [
+    [
+     "/css/css-transitions/transition-property-007.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-008.html": [
+    [
+     "/css/css-transitions/transition-property-008.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-009.html": [
+    [
+     "/css/css-transitions/transition-property-009.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-010.html": [
+    [
+     "/css/css-transitions/transition-property-010.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-011.html": [
+    [
+     "/css/css-transitions/transition-property-011.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-012.html": [
+    [
+     "/css/css-transitions/transition-property-012.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-013.html": [
+    [
+     "/css/css-transitions/transition-property-013.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-014.html": [
+    [
+     "/css/css-transitions/transition-property-014.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-015.html": [
+    [
+     "/css/css-transitions/transition-property-015.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-016.html": [
+    [
+     "/css/css-transitions/transition-property-016.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-017.html": [
+    [
+     "/css/css-transitions/transition-property-017.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-018.html": [
+    [
+     "/css/css-transitions/transition-property-018.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-019.html": [
+    [
+     "/css/css-transitions/transition-property-019.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-020.html": [
+    [
+     "/css/css-transitions/transition-property-020.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-021.html": [
+    [
+     "/css/css-transitions/transition-property-021.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-022.html": [
+    [
+     "/css/css-transitions/transition-property-022.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-023.html": [
+    [
+     "/css/css-transitions/transition-property-023.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-024.html": [
+    [
+     "/css/css-transitions/transition-property-024.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-025.html": [
+    [
+     "/css/css-transitions/transition-property-025.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-026.html": [
+    [
+     "/css/css-transitions/transition-property-026.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-027.html": [
+    [
+     "/css/css-transitions/transition-property-027.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-028.html": [
+    [
+     "/css/css-transitions/transition-property-028.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-029.html": [
+    [
+     "/css/css-transitions/transition-property-029.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-030.html": [
+    [
+     "/css/css-transitions/transition-property-030.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-031.html": [
+    [
+     "/css/css-transitions/transition-property-031.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-032.html": [
+    [
+     "/css/css-transitions/transition-property-032.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-033.html": [
+    [
+     "/css/css-transitions/transition-property-033.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-034.html": [
+    [
+     "/css/css-transitions/transition-property-034.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-035.html": [
+    [
+     "/css/css-transitions/transition-property-035.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-036.html": [
+    [
+     "/css/css-transitions/transition-property-036.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-037.html": [
+    [
+     "/css/css-transitions/transition-property-037.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-038.html": [
+    [
+     "/css/css-transitions/transition-property-038.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-039.html": [
+    [
+     "/css/css-transitions/transition-property-039.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-040.html": [
+    [
+     "/css/css-transitions/transition-property-040.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-041.html": [
+    [
+     "/css/css-transitions/transition-property-041.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-042.html": [
+    [
+     "/css/css-transitions/transition-property-042.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-043.html": [
+    [
+     "/css/css-transitions/transition-property-043.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-044.html": [
+    [
+     "/css/css-transitions/transition-property-044.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-045.html": [
+    [
+     "/css/css-transitions/transition-property-045.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-timing-function-002.html": [
+    [
+     "/css/css-transitions/transition-timing-function-002.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-timing-function-003.html": [
+    [
+     "/css/css-transitions/transition-timing-function-003.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-timing-function-004.html": [
+    [
+     "/css/css-transitions/transition-timing-function-004.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-timing-function-005.html": [
+    [
+     "/css/css-transitions/transition-timing-function-005.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-timing-function-006.html": [
+    [
+     "/css/css-transitions/transition-timing-function-006.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-timing-function-007.html": [
+    [
+     "/css/css-transitions/transition-timing-function-007.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-timing-function-008.html": [
+    [
+     "/css/css-transitions/transition-timing-function-008.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-timing-function-009.html": [
+    [
+     "/css/css-transitions/transition-timing-function-009.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-timing-function-010.html": [
+    [
+     "/css/css-transitions/transition-timing-function-010.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-timing-function-011.html": [
+    [
+     "/css/css-transitions/transition-timing-function-011.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-timing-function-012.html": [
+    [
+     "/css/css-transitions/transition-timing-function-012.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-timing-function-013.html": [
+    [
+     "/css/css-transitions/transition-timing-function-013.html",
+     {}
+    ]
+   ],
    "css/css-ui/canvas-cursor-001.html": [
     [
      "/css/css-ui/canvas-cursor-001.html",
@@ -3169,18 +3535,6 @@
      {}
     ]
    ],
-   "css/css-writing-modes/page-flow-direction-slr-005.xht": [
-    [
-     "/css/css-writing-modes/page-flow-direction-slr-005.xht",
-     {}
-    ]
-   ],
-   "css/css-writing-modes/page-flow-direction-srl-004.xht": [
-    [
-     "/css/css-writing-modes/page-flow-direction-srl-004.xht",
-     {}
-    ]
-   ],
    "css/cssom-view/overscrollBehavior-manual.html": [
     [
      "/css/cssom-view/overscrollBehavior-manual.html",
@@ -49327,6 +49681,30 @@
      {}
     ]
    ],
+   "css/css-tables/height-distribution/td-different-subpixel-padding-in-same-row-vertical-rl.html": [
+    [
+     "/css/css-tables/height-distribution/td-different-subpixel-padding-in-same-row-vertical-rl.html",
+     [
+      [
+       "/css/css-tables/height-distribution/td-different-subpixel-padding-in-same-row-vertical-rl-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-tables/height-distribution/td-different-subpixel-padding-in-same-row.html": [
+    [
+     "/css/css-tables/height-distribution/td-different-subpixel-padding-in-same-row.html",
+     [
+      [
+       "/css/css-tables/height-distribution/td-different-subpixel-padding-in-same-row-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-tables/internal-containing-block-001.html": [
     [
      "/css/css-tables/internal-containing-block-001.html",
@@ -69887,6 +70265,18 @@
      {}
     ]
    ],
+   "css/css-transitions/transition-test.html": [
+    [
+     "/css/css-transitions/transition-test.html",
+     [
+      [
+       "/css/css-transitions/reference/transition-test-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-ui/box-sizing-001.html": [
     [
      "/css/css-ui/box-sizing-001.html",
@@ -76559,102 +76949,6 @@
      {}
     ]
    ],
-   "css/css-writing-modes/ch-units-vrl-001.html": [
-    [
-     "/css/css-writing-modes/ch-units-vrl-001.html",
-     [
-      [
-       "/css/css-writing-modes/reference/ch-units-vrl-001-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-writing-modes/ch-units-vrl-002.html": [
-    [
-     "/css/css-writing-modes/ch-units-vrl-002.html",
-     [
-      [
-       "/css/css-writing-modes/reference/ch-units-vrl-001-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-writing-modes/ch-units-vrl-003.html": [
-    [
-     "/css/css-writing-modes/ch-units-vrl-003.html",
-     [
-      [
-       "/css/css-writing-modes/reference/ch-units-vrl-001-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-writing-modes/ch-units-vrl-004.html": [
-    [
-     "/css/css-writing-modes/ch-units-vrl-004.html",
-     [
-      [
-       "/css/css-writing-modes/reference/ch-units-vrl-001-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-writing-modes/ch-units-vrl-005.html": [
-    [
-     "/css/css-writing-modes/ch-units-vrl-005.html",
-     [
-      [
-       "/css/css-writing-modes/reference/ch-units-vrl-005-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-writing-modes/ch-units-vrl-006.html": [
-    [
-     "/css/css-writing-modes/ch-units-vrl-006.html",
-     [
-      [
-       "/css/css-writing-modes/reference/ch-units-vrl-005-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-writing-modes/ch-units-vrl-007.html": [
-    [
-     "/css/css-writing-modes/ch-units-vrl-007.html",
-     [
-      [
-       "/css/css-writing-modes/reference/ch-units-vrl-005-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-writing-modes/ch-units-vrl-008.html": [
-    [
-     "/css/css-writing-modes/ch-units-vrl-008.html",
-     [
-      [
-       "/css/css-writing-modes/reference/ch-units-vrl-005-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
    "css/css-writing-modes/clearance-calculations-vrl-002.xht": [
     [
      "/css/css-writing-modes/clearance-calculations-vrl-002.xht",
@@ -78323,54 +78617,6 @@
      {}
     ]
    ],
-   "css/css-writing-modes/logical-props-001.html": [
-    [
-     "/css/css-writing-modes/logical-props-001.html",
-     [
-      [
-       "/css/css-writing-modes/reference/logical-props-001-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-writing-modes/logical-props-002.html": [
-    [
-     "/css/css-writing-modes/logical-props-002.html",
-     [
-      [
-       "/css/css-writing-modes/reference/logical-props-001-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-writing-modes/logical-props-003.html": [
-    [
-     "/css/css-writing-modes/logical-props-003.html",
-     [
-      [
-       "/css/css-writing-modes/reference/logical-props-001-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-writing-modes/logical-props-004.html": [
-    [
-     "/css/css-writing-modes/logical-props-004.html",
-     [
-      [
-       "/css/css-writing-modes/reference/logical-props-001-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
    "css/css-writing-modes/margin-collapse-vlr-003.xht": [
     [
      "/css/css-writing-modes/margin-collapse-vlr-003.xht",
@@ -80603,174 +80849,6 @@
      {}
     ]
    ],
-   "css/css-writing-modes/table-cell-001.html": [
-    [
-     "/css/css-writing-modes/table-cell-001.html",
-     [
-      [
-       "/css/css-writing-modes/reference/table-cell-001-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-writing-modes/table-cell-002.html": [
-    [
-     "/css/css-writing-modes/table-cell-002.html",
-     [
-      [
-       "/css/css-writing-modes/reference/table-cell-002-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-writing-modes/table-column-order-002.xht": [
-    [
-     "/css/css-writing-modes/table-column-order-002.xht",
-     [
-      [
-       "/css/css-writing-modes/block-flow-direction-001-ref.xht",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-writing-modes/table-column-order-003.xht": [
-    [
-     "/css/css-writing-modes/table-column-order-003.xht",
-     [
-      [
-       "/css/css-writing-modes/block-flow-direction-001-ref.xht",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-writing-modes/table-column-order-004.xht": [
-    [
-     "/css/css-writing-modes/table-column-order-004.xht",
-     [
-      [
-       "/css/css-writing-modes/block-flow-direction-001-ref.xht",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-writing-modes/table-column-order-005.xht": [
-    [
-     "/css/css-writing-modes/table-column-order-005.xht",
-     [
-      [
-       "/css/css-writing-modes/block-flow-direction-001-ref.xht",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-writing-modes/table-progression-vlr-001.html": [
-    [
-     "/css/css-writing-modes/table-progression-vlr-001.html",
-     [
-      [
-       "/css/css-writing-modes/table-progression-001-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-writing-modes/table-progression-vlr-002.html": [
-    [
-     "/css/css-writing-modes/table-progression-vlr-002.html",
-     [
-      [
-       "/css/css-writing-modes/table-progression-002-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-writing-modes/table-progression-vlr-003.html": [
-    [
-     "/css/css-writing-modes/table-progression-vlr-003.html",
-     [
-      [
-       "/css/css-writing-modes/table-progression-001-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-writing-modes/table-progression-vlr-004.html": [
-    [
-     "/css/css-writing-modes/table-progression-vlr-004.html",
-     [
-      [
-       "/css/css-writing-modes/table-progression-002-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-writing-modes/table-progression-vrl-001.html": [
-    [
-     "/css/css-writing-modes/table-progression-vrl-001.html",
-     [
-      [
-       "/css/css-writing-modes/table-progression-001-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-writing-modes/table-progression-vrl-002.html": [
-    [
-     "/css/css-writing-modes/table-progression-vrl-002.html",
-     [
-      [
-       "/css/css-writing-modes/table-progression-002-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-writing-modes/table-progression-vrl-003.html": [
-    [
-     "/css/css-writing-modes/table-progression-vrl-003.html",
-     [
-      [
-       "/css/css-writing-modes/table-progression-001-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-writing-modes/table-progression-vrl-004.html": [
-    [
-     "/css/css-writing-modes/table-progression-vrl-004.html",
-     [
-      [
-       "/css/css-writing-modes/table-progression-002-ref.html",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
    "css/css-writing-modes/text-align-vlr-003.xht": [
     [
      "/css/css-writing-modes/text-align-vlr-003.xht",
@@ -81635,18 +81713,6 @@
      {}
     ]
    ],
-   "css/css-writing-modes/wm-propagation-body-008.xht": [
-    [
-     "/css/css-writing-modes/wm-propagation-body-008.xht",
-     [
-      [
-       "/css/css-writing-modes/block-flow-direction-025-ref.xht",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
    "css/css-writing-modes/wm-propagation-body-010.xht": [
     [
      "/css/css-writing-modes/wm-propagation-body-010.xht",
@@ -97110,6 +97176,16 @@
      {}
     ]
    ],
+   "IndexedDB/interfaces.any-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "IndexedDB/interfaces.any.worker-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "IndexedDB/interleaved-cursors-common.js": [
     [
      {}
@@ -100240,6 +100316,11 @@
      {}
     ]
    ],
+   "cookie-store/idlharness.tentative-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "cookie-store/idlharness_serviceworker.js": [
     [
      {}
@@ -119280,6 +119361,16 @@
      {}
     ]
    ],
+   "css/css-tables/height-distribution/td-different-subpixel-padding-in-same-row-ref.html": [
+    [
+     {}
+    ]
+   ],
+   "css/css-tables/height-distribution/td-different-subpixel-padding-in-same-row-vertical-rl-ref.html": [
+    [
+     {}
+    ]
+   ],
    "css/css-tables/html-to-css-mapping-1-expected.txt": [
     [
      {}
@@ -124290,6 +124381,336 @@
      {}
     ]
    ],
+   "css/css-transitions/README.md": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/before-DOMContentLoaded-001-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/before-load-001-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/events-004-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/properties-value-001-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/properties-value-002-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/properties-value-003-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/properties-value-implicit-001-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/properties-value-inherit-001-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/properties-value-inherit-002-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/reference/transition-test-ref.html": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/1x1-green.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/1x1-lime.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/1x1-maroon.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/1x1-navy.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/1x1-red.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/1x1-white.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/60x60-gg-rr.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/60x60-green.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/60x60-red.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/README": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/a-green.css": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/b-green.css": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/c-red.css": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/cat.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/generalParallelTest.js": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/helper.js": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/import-green.css": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/import-red.css": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/one.gif": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/pattern-grg-rgr-grg.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/pattern-grg-rrg-rgg.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/pattern-rgr-grg-rgr.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/pattern-tr.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/properties.js": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/ruler-h-50%.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/ruler-h-50px.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/ruler-v-100px.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/ruler-v-50px.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/runParallelAsyncHarness.js": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/square-purple.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/square-teal.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/square-white.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/support/README": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/support/swatch-green.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/support/swatch-red.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/swatch-blue.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/swatch-green.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/swatch-lime.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/swatch-orange.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/swatch-red.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/swatch-teal.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/swatch-white.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/swatch-yellow.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/test-bl.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/test-br.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/test-inner-half-size.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/test-outer.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/test-tl.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/test-tr.png": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/two.gif": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/support/vendorPrefix.js": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-001-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-002-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-timing-function-001-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transitions/transitioncancel-001-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "css/css-typed-om/CSSMatrixComponent-DOMMatrix-mutable-expected.txt": [
     [
      {}
@@ -126510,11 +126931,6 @@
      {}
     ]
    ],
-   "css/css-writing-modes/inline-block-alignment-slr-009-ref.xht": [
-    [
-     {}
-    ]
-   ],
    "css/css-writing-modes/inline-replaced-vrl-002-ref.xht": [
     [
      {}
@@ -128515,21 +128931,6 @@
      {}
     ]
    ],
-   "css/css-writing-modes/table-progression-001-ref.html": [
-    [
-     {}
-    ]
-   ],
-   "css/css-writing-modes/table-progression-002-ref.html": [
-    [
-     {}
-    ]
-   ],
-   "css/css-writing-modes/table-progression-slr-001-ref.html": [
-    [
-     {}
-    ]
-   ],
    "css/css-writing-modes/test-plan/img/figure-over_and_under-fail.svg": [
     [
      {}
@@ -128620,11 +129021,6 @@
      {}
     ]
    ],
-   "css/css-writing-modes/text-baseline-slr-009-ref.xht": [
-    [
-     {}
-    ]
-   ],
    "css/css-writing-modes/text-baseline-vrl-002-ref.xht": [
     [
      {}
@@ -128690,11 +129086,6 @@
      {}
     ]
    ],
-   "css/css-writing-modes/text-orientation-mixed-srl-016-ref.xht": [
-    [
-     {}
-    ]
-   ],
    "css/css-writing-modes/text-orientation-mixed-vlr-100-ref.html": [
     [
      {}
@@ -128805,11 +129196,6 @@
      {}
     ]
    ],
-   "css/css-writing-modes/vertical-alignment-slr-049-ref.xht": [
-    [
-     {}
-    ]
-   ],
    "css/css-writing-modes/vertical-alignment-vrl-022-ref.xht": [
     [
      {}
@@ -133250,11 +133636,6 @@
      {}
     ]
    ],
-   "dom/nodes/Element-classlist-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "dom/nodes/Element-closest-expected.txt": [
     [
      {}
@@ -136975,6 +137356,11 @@
      {}
     ]
    ],
+   "hr-time/idlharness-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "hr-time/resources/now_frame.html": [
     [
      {}
@@ -150450,6 +150836,11 @@
      {}
     ]
    ],
+   "interfaces/keyboard-lock.idl": [
+    [
+     {}
+    ]
+   ],
    "interfaces/magnetometer.idl": [
     [
      {}
@@ -150620,12 +151011,7 @@
      {}
     ]
    ],
-   "keyboard-lock/idlharness.https-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "keyboard-lock/navigator-keyboardLock-two-parallel-requests.https-expected.txt": [
+   "keyboard-lock/navigator-keyboard-lock-two-parallel-requests.https-expected.txt": [
     [
      {}
     ]
@@ -152410,6 +152796,11 @@
      {}
     ]
    ],
+   "payment-request/PaymentItem/type_member.https-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "payment-request/allowpaymentrequest/common.sub.js": [
     [
      {}
@@ -152445,6 +152836,11 @@
      {}
     ]
    ],
+   "payment-request/payment-request-insecure.http-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "payment-request/payment-response/helpers.js": [
     [
      {}
@@ -159020,31 +159416,11 @@
      {}
     ]
    ],
-   "streams/transform-streams/errors-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "streams/transform-streams/errors.dedicatedworker-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "streams/transform-streams/errors.js": [
     [
      {}
     ]
    ],
-   "streams/transform-streams/errors.serviceworker.https-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "streams/transform-streams/errors.sharedworker-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "streams/transform-streams/flush.js": [
     [
      {}
@@ -159065,56 +159441,16 @@
      {}
     ]
    ],
-   "streams/transform-streams/properties-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "streams/transform-streams/properties.dedicatedworker-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "streams/transform-streams/properties.js": [
     [
      {}
     ]
    ],
-   "streams/transform-streams/properties.serviceworker.https-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "streams/transform-streams/properties.sharedworker-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "streams/transform-streams/reentrant-strategies-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "streams/transform-streams/reentrant-strategies.dedicatedworker-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "streams/transform-streams/reentrant-strategies.js": [
     [
      {}
     ]
    ],
-   "streams/transform-streams/reentrant-strategies.serviceworker.https-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "streams/transform-streams/reentrant-strategies.sharedworker-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "streams/transform-streams/strategies.js": [
     [
      {}
@@ -164335,6 +164671,21 @@
      {}
     ]
    ],
+   "workers/modules/resources/nested-static-import-worker.js": [
+    [
+     {}
+    ]
+   ],
+   "workers/modules/resources/post-message-on-load-worker.js": [
+    [
+     {}
+    ]
+   ],
+   "workers/modules/resources/static-import-worker.js": [
+    [
+     {}
+    ]
+   ],
    "workers/name-property-expected.txt": [
     [
      {}
@@ -180311,6 +180662,12 @@
      {}
     ]
    ],
+   "css/css-grid/grid-definition/grid-inline-auto-repeat-001.html": [
+    [
+     "/css/css-grid/grid-definition/grid-inline-auto-repeat-001.html",
+     {}
+    ]
+   ],
    "css/css-grid/grid-definition/grid-inline-support-flexible-lengths-001.html": [
     [
      "/css/css-grid/grid-definition/grid-inline-support-flexible-lengths-001.html",
@@ -182009,6 +182366,12 @@
      {}
     ]
    ],
+   "css/css-tables/width-distribution/td-with-subpixel-padding-vertical-rl.html": [
+    [
+     "/css/css-tables/width-distribution/td-with-subpixel-padding-vertical-rl.html",
+     {}
+    ]
+   ],
    "css/css-tables/width-distribution/td-with-subpixel-padding.html": [
     [
      "/css/css-tables/width-distribution/td-with-subpixel-padding.html",
@@ -183005,6 +183368,186 @@
      {}
     ]
    ],
+   "css/css-transitions/before-DOMContentLoaded-001.html": [
+    [
+     "/css/css-transitions/before-DOMContentLoaded-001.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/before-load-001.html": [
+    [
+     "/css/css-transitions/before-load-001.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/changing-while-transition.html": [
+    [
+     "/css/css-transitions/changing-while-transition.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/currentcolor-animation-001.html": [
+    [
+     "/css/css-transitions/currentcolor-animation-001.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/detached-container-001.html": [
+    [
+     "/css/css-transitions/detached-container-001.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/events-001.html": [
+    [
+     "/css/css-transitions/events-001.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/events-002.html": [
+    [
+     "/css/css-transitions/events-002.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/events-003.html": [
+    [
+     "/css/css-transitions/events-003.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/events-004.html": [
+    [
+     "/css/css-transitions/events-004.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/events-005.html": [
+    [
+     "/css/css-transitions/events-005.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/events-006.html": [
+    [
+     "/css/css-transitions/events-006.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/events-007.html": [
+    [
+     "/css/css-transitions/events-007.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/hidden-container-001.html": [
+    [
+     "/css/css-transitions/hidden-container-001.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/properties-value-001.html": [
+    [
+     "/css/css-transitions/properties-value-001.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/properties-value-002.html": [
+    [
+     "/css/css-transitions/properties-value-002.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/properties-value-003.html": [
+    [
+     "/css/css-transitions/properties-value-003.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/properties-value-auto-001.html": [
+    [
+     "/css/css-transitions/properties-value-auto-001.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/properties-value-implicit-001.html": [
+    [
+     "/css/css-transitions/properties-value-implicit-001.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/properties-value-inherit-001.html": [
+    [
+     "/css/css-transitions/properties-value-inherit-001.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/properties-value-inherit-002.html": [
+    [
+     "/css/css-transitions/properties-value-inherit-002.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/properties-value-inherit-003.html": [
+    [
+     "/css/css-transitions/properties-value-inherit-003.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/pseudo-elements-001.html": [
+    [
+     "/css/css-transitions/pseudo-elements-001.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-001.html": [
+    [
+     "/css/css-transitions/transition-001.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-delay-001.html": [
+    [
+     "/css/css-transitions/transition-delay-001.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-duration-001.html": [
+    [
+     "/css/css-transitions/transition-duration-001.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-001.html": [
+    [
+     "/css/css-transitions/transition-property-001.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-property-002.html": [
+    [
+     "/css/css-transitions/transition-property-002.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transition-timing-function-001.html": [
+    [
+     "/css/css-transitions/transition-timing-function-001.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transitioncancel-001.html": [
+    [
+     "/css/css-transitions/transitioncancel-001.html",
+     {}
+    ]
+   ],
+   "css/css-transitions/transitions-animatable-properties-01.html": [
+    [
+     "/css/css-transitions/transitions-animatable-properties-01.html",
+     {}
+    ]
+   ],
    "css/css-typed-om/CSSMatrixComponent-DOMMatrix-mutable.html": [
     [
      "/css/css-typed-om/CSSMatrixComponent-DOMMatrix-mutable.html",
@@ -191221,6 +191764,16 @@
      {}
     ]
    ],
+   "fetch/api/cors/cors-cookies-redirect.any.js": [
+    [
+     "/fetch/api/cors/cors-cookies-redirect.any.html",
+     {}
+    ],
+    [
+     "/fetch/api/cors/cors-cookies-redirect.any.worker.html",
+     {}
+    ]
+   ],
    "fetch/api/cors/cors-cookies.any.js": [
     [
      "/fetch/api/cors/cors-cookies.any.html",
@@ -204585,27 +205138,27 @@
      {}
     ]
    ],
-   "keyboard-lock/navigator-keyboardLock-two-parallel-requests.https.html": [
+   "keyboard-lock/navigator-keyboard-lock-two-parallel-requests.https.html": [
     [
-     "/keyboard-lock/navigator-keyboardLock-two-parallel-requests.https.html",
+     "/keyboard-lock/navigator-keyboard-lock-two-parallel-requests.https.html",
      {}
     ]
    ],
-   "keyboard-lock/navigator-keyboardLock-two-sequential-requests.https.html": [
+   "keyboard-lock/navigator-keyboard-lock-two-sequential-requests.https.html": [
     [
-     "/keyboard-lock/navigator-keyboardLock-two-sequential-requests.https.html",
+     "/keyboard-lock/navigator-keyboard-lock-two-sequential-requests.https.html",
      {}
     ]
    ],
-   "keyboard-lock/navigator-keyboardLock.https.html": [
+   "keyboard-lock/navigator-keyboard-lock.https.html": [
     [
-     "/keyboard-lock/navigator-keyboardLock.https.html",
+     "/keyboard-lock/navigator-keyboard-lock.https.html",
      {}
     ]
    ],
-   "keyboard-lock/navigator-keyboardUnlock.https.html": [
+   "keyboard-lock/navigator-keyboard-unlock.https.html": [
     [
-     "/keyboard-lock/navigator-keyboardUnlock.https.html",
+     "/keyboard-lock/navigator-keyboard-unlock.https.html",
      {}
     ]
    ],
@@ -216207,6 +216760,12 @@
      {}
     ]
    ],
+   "payment-request/PaymentItem/type_member.https.html": [
+    [
+     "/payment-request/PaymentItem/type_member.https.html",
+     {}
+    ]
+   ],
    "payment-request/PaymentRequestUpdateEvent/constructor.http.html": [
     [
      "/payment-request/PaymentRequestUpdateEvent/constructor.http.html",
@@ -216329,6 +216888,12 @@
      {}
     ]
    ],
+   "payment-request/payment-request-insecure.http.html": [
+    [
+     "/payment-request/payment-request-insecure.http.html",
+     {}
+    ]
+   ],
    "payment-request/payment-request-not-exposed.https.worker.js": [
     [
      "/payment-request/payment-request-not-exposed.https.worker.html",
@@ -226971,6 +227536,12 @@
      {}
     ]
    ],
+   "shadow-dom/Element-interface-attachShadow-custom-element.html": [
+    [
+     "/shadow-dom/Element-interface-attachShadow-custom-element.html",
+     {}
+    ]
+   ],
    "shadow-dom/Element-interface-attachShadow.html": [
     [
      "/shadow-dom/Element-interface-attachShadow.html",
@@ -235481,6 +236052,18 @@
      {}
     ]
    ],
+   "workers/modules/dedicated-worker-options-type.html": [
+    [
+     "/workers/modules/dedicated-worker-options-type.html",
+     {}
+    ]
+   ],
+   "workers/modules/dedicated-worker-static-import.html": [
+    [
+     "/workers/modules/dedicated-worker-static-import.html",
+     {}
+    ]
+   ],
    "workers/name-property.html": [
     [
      "/workers/name-property.html",
@@ -242753,30 +243336,6 @@
      {}
     ]
    ],
-   "css/css-writing-modes/form-controls-slr-004.xht": [
-    [
-     "/css/css-writing-modes/form-controls-slr-004.xht",
-     {}
-    ]
-   ],
-   "css/css-writing-modes/form-controls-slr-005.xht": [
-    [
-     "/css/css-writing-modes/form-controls-slr-005.xht",
-     {}
-    ]
-   ],
-   "css/css-writing-modes/form-controls-srl-004.xht": [
-    [
-     "/css/css-writing-modes/form-controls-srl-004.xht",
-     {}
-    ]
-   ],
-   "css/css-writing-modes/form-controls-srl-005.xht": [
-    [
-     "/css/css-writing-modes/form-controls-srl-005.xht",
-     {}
-    ]
-   ],
    "css/css-writing-modes/form-controls-vlr-004.xht": [
     [
      "/css/css-writing-modes/form-controls-vlr-004.xht",
@@ -242813,18 +243372,6 @@
      {}
     ]
    ],
-   "css/css-writing-modes/outline-inline-slr-005.xht": [
-    [
-     "/css/css-writing-modes/outline-inline-slr-005.xht",
-     {}
-    ]
-   ],
-   "css/css-writing-modes/outline-inline-srl-004.xht": [
-    [
-     "/css/css-writing-modes/outline-inline-srl-004.xht",
-     {}
-    ]
-   ],
    "css/css-writing-modes/outline-inline-vlr-003.xht": [
     [
      "/css/css-writing-modes/outline-inline-vlr-003.xht",
@@ -242951,12 +243498,6 @@
      {}
     ]
    ],
-   "css/css-writing-modes/text-orientation-mixed-slr-015.xht": [
-    [
-     "/css/css-writing-modes/text-orientation-mixed-slr-015.xht",
-     {}
-    ]
-   ],
    "css/css-writing-modes/text-orientation-mixed-vrl-002.xht": [
     [
      "/css/css-writing-modes/text-orientation-mixed-vrl-002.xht",
@@ -242969,18 +243510,6 @@
      {}
     ]
    ],
-   "css/css-writing-modes/text-orientation-sideways-slr-019.xht": [
-    [
-     "/css/css-writing-modes/text-orientation-sideways-slr-019.xht",
-     {}
-    ]
-   ],
-   "css/css-writing-modes/text-orientation-upright-slr-017.xht": [
-    [
-     "/css/css-writing-modes/text-orientation-upright-slr-017.xht",
-     {}
-    ]
-   ],
    "css/css-writing-modes/text-orientation-upright-vrl-002.xht": [
     [
      "/css/css-writing-modes/text-orientation-upright-vrl-002.xht",
@@ -243065,30 +243594,6 @@
      {}
     ]
    ],
-   "css/css-writing-modes/vertical-alignment-slr-037.xht": [
-    [
-     "/css/css-writing-modes/vertical-alignment-slr-037.xht",
-     {}
-    ]
-   ],
-   "css/css-writing-modes/vertical-alignment-slr-039.xht": [
-    [
-     "/css/css-writing-modes/vertical-alignment-slr-039.xht",
-     {}
-    ]
-   ],
-   "css/css-writing-modes/vertical-alignment-srl-036.xht": [
-    [
-     "/css/css-writing-modes/vertical-alignment-srl-036.xht",
-     {}
-    ]
-   ],
-   "css/css-writing-modes/vertical-alignment-srl-038.xht": [
-    [
-     "/css/css-writing-modes/vertical-alignment-srl-038.xht",
-     {}
-    ]
-   ],
    "css/css-writing-modes/vertical-alignment-vlr-011.xht": [
     [
      "/css/css-writing-modes/vertical-alignment-vlr-011.xht",
@@ -248910,10 +249415,18 @@
    "251a828d333bdd3face9d20a2a28ddf0c0ffeb49",
    "testharness"
   ],
+  "IndexedDB/interfaces.any-expected.txt": [
+   "2606ec37ce4ca007703f69f75e9fb74c97c8b3e2",
+   "support"
+  ],
   "IndexedDB/interfaces.any.js": [
    "df07f5da63c34969a24fe43bc4268418ab0a5132",
    "testharness"
   ],
+  "IndexedDB/interfaces.any.worker-expected.txt": [
+   "2606ec37ce4ca007703f69f75e9fb74c97c8b3e2",
+   "support"
+  ],
   "IndexedDB/interleaved-cursors-common.js": [
    "6744105fe1a15a91058e3e5993f8a1f88548e3a3",
    "support"
@@ -254750,6 +255263,10 @@
    "11c763dd1b7b3a1bff14b9f65538fb33ca97b81b",
    "testharness"
   ],
+  "cookie-store/idlharness.tentative-expected.txt": [
+   "59204fdf907e3d3d5e230dd9a4d808f09ae31ab8",
+   "support"
+  ],
   "cookie-store/idlharness.tentative.html": [
    "24a4e59e8d3c0a481c4b448bd3fb677f30d0208f",
    "testharness"
@@ -277615,7 +278132,7 @@
    "testharness"
   ],
   "css/css-font-loading/idlharness.https-expected.txt": [
-   "2711c37911c9d0547173d0ebb4215745017d43fb",
+   "21ed4233306822c468b0bf0ff1be8681450854c3",
    "support"
   ],
   "css/css-font-loading/idlharness.https.html": [
@@ -286190,6 +286707,10 @@
    "d00e8651be933262d7f64d22f6e8ce68d23d44eb",
    "testharness"
   ],
+  "css/css-grid/grid-definition/grid-inline-auto-repeat-001.html": [
+   "dd057e3ae1332c813ae60dc0bf29b948b24e7f47",
+   "testharness"
+  ],
   "css/css-grid/grid-definition/grid-inline-support-flexible-lengths-001.html": [
    "99215a797996322c89105b8ca5cb426628ec7563",
    "testharness"
@@ -291610,6 +292131,22 @@
    "55a759d84f38e6adf0f091c9c0ecaa69060cb51a",
    "testharness"
   ],
+  "css/css-tables/height-distribution/td-different-subpixel-padding-in-same-row-ref.html": [
+   "2bb8a26451a23ebcf548ad147d301ea5d9603c25",
+   "support"
+  ],
+  "css/css-tables/height-distribution/td-different-subpixel-padding-in-same-row-vertical-rl-ref.html": [
+   "bfb2b402c1887841f89fc7954a2cccacd3babab6",
+   "support"
+  ],
+  "css/css-tables/height-distribution/td-different-subpixel-padding-in-same-row-vertical-rl.html": [
+   "67b7a983d1fed1a754356ba3a3359c60d9575d38",
+   "reftest"
+  ],
+  "css/css-tables/height-distribution/td-different-subpixel-padding-in-same-row.html": [
+   "da90cdb16cb229c4856df7c4ad14bf49d51b900d",
+   "reftest"
+  ],
   "css/css-tables/html-to-css-mapping-1-expected.txt": [
    "6f172cc7f8307e421ee147e8a9489b3275d2ea33",
    "support"
@@ -291862,6 +292399,10 @@
    "9eeb49d2d78c3f81825de0d9e24de2a097275175",
    "testharness"
   ],
+  "css/css-tables/width-distribution/td-with-subpixel-padding-vertical-rl.html": [
+   "cf3f3ffb0dba2dc13f753f9a584084c9f070a48c",
+   "testharness"
+  ],
   "css/css-tables/width-distribution/td-with-subpixel-padding.html": [
    "b93845c332e5153c8a28085303b165d3c96f984e",
    "testharness"
@@ -303446,6 +303987,638 @@
    "7a9cc02dc9cddb5888ffe57ff57693689a510594",
    "reftest"
   ],
+  "css/css-transitions/README.md": [
+   "82376e55f41c00c65d2f9420572fb0361d60b9e6",
+   "support"
+  ],
+  "css/css-transitions/before-DOMContentLoaded-001-expected.txt": [
+   "6e8a1b21a02f10cb6e237e1f5ad0ba9e398ef959",
+   "support"
+  ],
+  "css/css-transitions/before-DOMContentLoaded-001.html": [
+   "d9a08984058da3dbedada7d0dff2d4743e3dd15b",
+   "testharness"
+  ],
+  "css/css-transitions/before-load-001-expected.txt": [
+   "4fe4c48c46d445c26cb877be8602aaa1c7f942cf",
+   "support"
+  ],
+  "css/css-transitions/before-load-001.html": [
+   "7f5f54505f119b0b491df50fcf23d60909f41126",
+   "testharness"
+  ],
+  "css/css-transitions/changing-while-transition.html": [
+   "49ca30de94a41c9228189c44267bdf36a6e8bde2",
+   "testharness"
+  ],
+  "css/css-transitions/currentcolor-animation-001.html": [
+   "aee4e4f0e0154f9390333e4db21904a2cda67b52",
+   "testharness"
+  ],
+  "css/css-transitions/detached-container-001.html": [
+   "45f59afdc4636ed26417999abf206382a2913968",
+   "testharness"
+  ],
+  "css/css-transitions/events-001.html": [
+   "30eb9732ba5c1d5325cb95a1d21e34f06251c613",
+   "testharness"
+  ],
+  "css/css-transitions/events-002.html": [
+   "5fb98d8366418a6d6c72e1885bf0ea0f428e42be",
+   "testharness"
+  ],
+  "css/css-transitions/events-003.html": [
+   "cb4147b4b9e43b3ec6fc70c7887621790e00c0ea",
+   "testharness"
+  ],
+  "css/css-transitions/events-004-expected.txt": [
+   "87a3b6e1055d0c2ca002409f099721ea8aa57a0f",
+   "support"
+  ],
+  "css/css-transitions/events-004.html": [
+   "ba0027ef26edfde941ab3c2f0072e10f0c6248a4",
+   "testharness"
+  ],
+  "css/css-transitions/events-005.html": [
+   "fb8c4dd32adcb9b264f2990ab4e962986561f5ed",
+   "testharness"
+  ],
+  "css/css-transitions/events-006.html": [
+   "2e957a34c69ca94037f4b8af9c3e87fc94a63a46",
+   "testharness"
+  ],
+  "css/css-transitions/events-007.html": [
+   "f92ae90b2f7a88f32f141b3136ff833fb7ba6a2b",
+   "testharness"
+  ],
+  "css/css-transitions/hidden-container-001.html": [
+   "971be3c362daabff565737c0d98be96e2356adb8",
+   "testharness"
+  ],
+  "css/css-transitions/properties-value-001-expected.txt": [
+   "0e2c13ff5054e8c3b2608ed158686a291c876634",
+   "support"
+  ],
+  "css/css-transitions/properties-value-001.html": [
+   "66853fd915a18b3a8eb78e5d551fc7eb529b72cf",
+   "testharness"
+  ],
+  "css/css-transitions/properties-value-002-expected.txt": [
+   "dcf60f53318bafb4e549d7a74aad5a8a63ed08fe",
+   "support"
+  ],
+  "css/css-transitions/properties-value-002.html": [
+   "e2b14b1a6a08e6453f5b040e7be1212b13aa92e2",
+   "testharness"
+  ],
+  "css/css-transitions/properties-value-003-expected.txt": [
+   "5b4400ea761fc161f765959bd13725248b1dd1c3",
+   "support"
+  ],
+  "css/css-transitions/properties-value-003.html": [
+   "71274e78c1c5fc7ced69e9d9bb2fcf076c3806dd",
+   "testharness"
+  ],
+  "css/css-transitions/properties-value-auto-001.html": [
+   "4e1c0fa89888d91e1b5085cb19624eba843a5905",
+   "testharness"
+  ],
+  "css/css-transitions/properties-value-implicit-001-expected.txt": [
+   "4c01b3d5d878aaa1fc9cf8279a4c44dcaf91e3d0",
+   "support"
+  ],
+  "css/css-transitions/properties-value-implicit-001.html": [
+   "30fdd86871362bfdca019a5c339f80ebff49d2b2",
+   "testharness"
+  ],
+  "css/css-transitions/properties-value-inherit-001-expected.txt": [
+   "a4f3d26eb145300a794abfdcfc0250a65c31964e",
+   "support"
+  ],
+  "css/css-transitions/properties-value-inherit-001.html": [
+   "63ddc6510fa07988df7f11d6d0070563ded61887",
+   "testharness"
+  ],
+  "css/css-transitions/properties-value-inherit-002-expected.txt": [
+   "0e2c13ff5054e8c3b2608ed158686a291c876634",
+   "support"
+  ],
+  "css/css-transitions/properties-value-inherit-002.html": [
+   "da354ecb506958e9b0d8c1224b05e19f551cb072",
+   "testharness"
+  ],
+  "css/css-transitions/properties-value-inherit-003.html": [
+   "85156d3741f742f7d621b27354d941d72bc949f1",
+   "testharness"
+  ],
+  "css/css-transitions/pseudo-elements-001.html": [
+   "43108935a5bf1e23ed8a61688843c7246b77b752",
+   "testharness"
+  ],
+  "css/css-transitions/reference/transition-test-ref.html": [
+   "f5d0b5da2bdbd69ef306aa8c0b2a27d553a74c77",
+   "support"
+  ],
+  "css/css-transitions/support/1x1-green.png": [
+   "51e7b6974a09eda6cb31337717c5eaeb9c44b443",
+   "support"
+  ],
+  "css/css-transitions/support/1x1-lime.png": [
+   "b040eb633a35c0648ad72a2902361faf25bc419d",
+   "support"
+  ],
+  "css/css-transitions/support/1x1-maroon.png": [
+   "f78757e5ebe897bd618d100718385c84e00f2369",
+   "support"
+  ],
+  "css/css-transitions/support/1x1-navy.png": [
+   "a3fd80b2c79866fd343e18eef5a51ed6e835e53e",
+   "support"
+  ],
+  "css/css-transitions/support/1x1-red.png": [
+   "b8da86921d04ba42f42b0a60b03c5c2172f58c2b",
+   "support"
+  ],
+  "css/css-transitions/support/1x1-white.png": [
+   "71b246439f915ad21c7d39414d9f85c8ed73b4ca",
+   "support"
+  ],
+  "css/css-transitions/support/60x60-gg-rr.png": [
+   "e4843d42a26189132e1bdd53e8618521330baeca",
+   "support"
+  ],
+  "css/css-transitions/support/60x60-green.png": [
+   "2f8eb2409b0a18e0bff90725ec7eedc16e7be448",
+   "support"
+  ],
+  "css/css-transitions/support/60x60-red.png": [
+   "415b835abaaab822aab11880354296e7356bbb0a",
+   "support"
+  ],
+  "css/css-transitions/support/README": [
+   "c46bfcee920aef0b9167764ec78c699ed217c8f2",
+   "support"
+  ],
+  "css/css-transitions/support/a-green.css": [
+   "a9716c222274ba868bfd06c05e28cb7762d93245",
+   "support"
+  ],
+  "css/css-transitions/support/b-green.css": [
+   "eb78a4d12f35b4249051826ea000c53d04df80b7",
+   "support"
+  ],
+  "css/css-transitions/support/c-red.css": [
+   "dc288b7aa49b57e0abf803741e78582ba5ceffdb",
+   "support"
+  ],
+  "css/css-transitions/support/cat.png": [
+   "461fd17b274662b88500cdf42bab7f3b79e6019d",
+   "support"
+  ],
+  "css/css-transitions/support/generalParallelTest.js": [
+   "1b9c80e2cc423958d70eb24a1b8349ed512d6099",
+   "support"
+  ],
+  "css/css-transitions/support/helper.js": [
+   "73bb1ba1862facb0d8a3e3dcd78611a79f458025",
+   "support"
+  ],
+  "css/css-transitions/support/import-green.css": [
+   "db4f420efdb292d6520be1a3bf052ed3f6f9e7e3",
+   "support"
+  ],
+  "css/css-transitions/support/import-red.css": [
+   "0f2b9133fcfa22d5506a5cee307bd1a4d50e87e9",
+   "support"
+  ],
+  "css/css-transitions/support/one.gif": [
+   "1c33d873bb179fae7111d7f15602605308dbbccd",
+   "support"
+  ],
+  "css/css-transitions/support/pattern-grg-rgr-grg.png": [
+   "cfb6ecc271c296c69b133a81f350a777b608bea4",
+   "support"
+  ],
+  "css/css-transitions/support/pattern-grg-rrg-rgg.png": [
+   "27080d4df556f59d4b501e03f2847bd9da5756a9",
+   "support"
+  ],
+  "css/css-transitions/support/pattern-rgr-grg-rgr.png": [
+   "c100a35c361205932c506f1b3399753b91e4c45e",
+   "support"
+  ],
+  "css/css-transitions/support/pattern-tr.png": [
+   "c1e687deee7b79ae091f2b42c4f6cff430076444",
+   "support"
+  ],
+  "css/css-transitions/support/properties.js": [
+   "c789935bb1a3077f539d20363e6dbeeda1d8cc6e",
+   "support"
+  ],
+  "css/css-transitions/support/ruler-h-50%.png": [
+   "9364be82a07500d6684a275174bcf5185444cb52",
+   "support"
+  ],
+  "css/css-transitions/support/ruler-h-50px.png": [
+   "b3d7cc680b20a5fc44ea93f7df6d33894bc7b09b",
+   "support"
+  ],
+  "css/css-transitions/support/ruler-v-100px.png": [
+   "d8b49696edb2bd614e9c00f96e7862798b6e621f",
+   "support"
+  ],
+  "css/css-transitions/support/ruler-v-50px.png": [
+   "eb299dc261ec04c8f2c11afb6f7a1c2ec147587b",
+   "support"
+  ],
+  "css/css-transitions/support/runParallelAsyncHarness.js": [
+   "8f223b3acf4e828d8bdec349ffa1bb5fd995d03d",
+   "support"
+  ],
+  "css/css-transitions/support/square-purple.png": [
+   "ef0619128f22e05920930420b7d96f91f860d904",
+   "support"
+  ],
+  "css/css-transitions/support/square-teal.png": [
+   "92efae44b710cf1ddd9ba96e593dae03fb2519c4",
+   "support"
+  ],
+  "css/css-transitions/support/square-white.png": [
+   "2f93fcc1462ba32b9b7899e5e78c869e529e68ee",
+   "support"
+  ],
+  "css/css-transitions/support/support/README": [
+   "18698bf71d328054eba0b473486058bc9286c1a4",
+   "support"
+  ],
+  "css/css-transitions/support/support/swatch-green.png": [
+   "eedea3e9a99c18f5fc2de3796be2c6f9da2ea07d",
+   "support"
+  ],
+  "css/css-transitions/support/support/swatch-red.png": [
+   "c51a03a807743f59e3027371ccfbd8e80235a485",
+   "support"
+  ],
+  "css/css-transitions/support/swatch-blue.png": [
+   "e79958e10feeeed3db88dee9bae9ea80055593c5",
+   "support"
+  ],
+  "css/css-transitions/support/swatch-green.png": [
+   "c51a03a807743f59e3027371ccfbd8e80235a485",
+   "support"
+  ],
+  "css/css-transitions/support/swatch-lime.png": [
+   "ee2cc3dcd6d8dda7c0e4ef3bbc7e63c74118211d",
+   "support"
+  ],
+  "css/css-transitions/support/swatch-orange.png": [
+   "10768a5177b772013e628c7397ae64725057295d",
+   "support"
+  ],
+  "css/css-transitions/support/swatch-red.png": [
+   "eedea3e9a99c18f5fc2de3796be2c6f9da2ea07d",
+   "support"
+  ],
+  "css/css-transitions/support/swatch-teal.png": [
+   "994cd98028aff20822f2dca5a6058fb616bf5ce4",
+   "support"
+  ],
+  "css/css-transitions/support/swatch-white.png": [
+   "5bccb1922de065e551d7d106e6493bb91040f3da",
+   "support"
+  ],
+  "css/css-transitions/support/swatch-yellow.png": [
+   "9cc73897c2e1fc45f5224d81d02a6b87bf72b1fa",
+   "support"
+  ],
+  "css/css-transitions/support/test-bl.png": [
+   "16e4eaa4864c10e72433e575f59c9b67763fe06a",
+   "support"
+  ],
+  "css/css-transitions/support/test-br.png": [
+   "37f65e7a21d9b9b2daa508f193b8f665c58a1ce9",
+   "support"
+  ],
+  "css/css-transitions/support/test-inner-half-size.png": [
+   "4ed63dd2bb54a8efc166719e00e1e27406b0ee59",
+   "support"
+  ],
+  "css/css-transitions/support/test-outer.png": [
+   "a0b8dfa40065b27f1d939ce0aab39ada3933c574",
+   "support"
+  ],
+  "css/css-transitions/support/test-tl.png": [
+   "956e5156fd8c0e75b1c0f3b8b3b900b653663f74",
+   "support"
+  ],
+  "css/css-transitions/support/test-tr.png": [
+   "078e1dd6dd61d36cec239ed75d02051f61fe60a5",
+   "support"
+  ],
+  "css/css-transitions/support/two.gif": [
+   "e33e9e6b2935352c87c18ad42bb6df2d95c3164f",
+   "support"
+  ],
+  "css/css-transitions/support/vendorPrefix.js": [
+   "2bbfe4ce7d8ca16f3438fccadfa2996136ddf813",
+   "support"
+  ],
+  "css/css-transitions/transition-001-expected.txt": [
+   "5604564c306335a5e55ab9e7f81d21459ab8d36f",
+   "support"
+  ],
+  "css/css-transitions/transition-001.html": [
+   "2068fe442683e6242633527409c89940d4e04bda",
+   "testharness"
+  ],
+  "css/css-transitions/transition-delay-000.html": [
+   "ad61ec6800863b60d7d392fc0666332673319209",
+   "manual"
+  ],
+  "css/css-transitions/transition-delay-001.html": [
+   "8da706562352ef5aa455be87a1a35246513976d5",
+   "testharness"
+  ],
+  "css/css-transitions/transition-delay-002.html": [
+   "036f62285e360b3c410a16434a7d8095edaebfbf",
+   "manual"
+  ],
+  "css/css-transitions/transition-delay-003.html": [
+   "c59f8c0b6a59fc3b59ec081d800c741f9443d5d1",
+   "manual"
+  ],
+  "css/css-transitions/transition-duration-001.html": [
+   "9d8ed6ae2885604c7358936ac3890085e4cd9943",
+   "testharness"
+  ],
+  "css/css-transitions/transition-duration-002.html": [
+   "e6c958aef084dd9ebddfca09fe7ad90377f6611e",
+   "manual"
+  ],
+  "css/css-transitions/transition-duration-003.html": [
+   "abbde87050dbeda4ca6b3151e54280d5677cca3a",
+   "manual"
+  ],
+  "css/css-transitions/transition-duration-004.html": [
+   "608f6ec7d080fe46522c68bf1f5df2300128d67c",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-001.html": [
+   "8977177635cae901a9f7540c94c6cc74f0ca8d6f",
+   "testharness"
+  ],
+  "css/css-transitions/transition-property-002-expected.txt": [
+   "f81ae298ca1f841935afb1ce50e47c22cede6394",
+   "support"
+  ],
+  "css/css-transitions/transition-property-002.html": [
+   "e4019e8e5ec748cdf5c1112ab87fcfb8478c6410",
+   "testharness"
+  ],
+  "css/css-transitions/transition-property-003.html": [
+   "5bb94a8508de6d547652118618253aad621b1220",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-004.html": [
+   "b6402e2b325709c2e3132b0e2f2fa4f9f4b4a7c2",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-005.html": [
+   "f730beb3cc63e185d1dfae1cf43fdf1cba72c00d",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-006.html": [
+   "dd4e7c387a165059c9a3a45af8e6ca23a54280fd",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-007.html": [
+   "4590cc8f1a8622d82c4215ad4a4722755d67c958",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-008.html": [
+   "d03813ac6dd27345c15c69a64c0ba5bdb4d7c35d",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-009.html": [
+   "60deee8b61c1a30ad92f4e2b2d2f4a1f130eeb77",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-010.html": [
+   "c17a2ca2c84c780c1890dd4b8284c23117f9c0b9",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-011.html": [
+   "6e58ae4c7f97cb552933e401c1e0833e8070d50f",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-012.html": [
+   "71d7f02a1da76fb2b2e4412eb14ae63d889af847",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-013.html": [
+   "e4e62a6102a442d84846a67e1a961fc60bbc8325",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-014.html": [
+   "0cd158660cad2a9423b8a1b02c7977d02299d9f4",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-015.html": [
+   "978b515765f1126bb42a143227dccb86f5cae12f",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-016.html": [
+   "82c2a0b9a8e7c83aae2c0fa65a6df581dfecf3d5",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-017.html": [
+   "5bada192e2db69f6d552a9b45951fe1c56c3bbfc",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-018.html": [
+   "c4bf20548fd54b07f32b7a29698cffda24fd0e59",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-019.html": [
+   "8e242f75ba848b075d809f6c15e190ed10a18698",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-020.html": [
+   "f9483574adf0b0451758e673408807533352d100",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-021.html": [
+   "c462a350bbec767ace812310a988fc2735a4081f",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-022.html": [
+   "99fd8e6fb69ba6401cd689a64045190cf56ec69e",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-023.html": [
+   "14c7dccae14dcd49a980586e2433551532ae91e6",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-024.html": [
+   "3332eca7b6c713a6d6deab3571a8007328867217",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-025.html": [
+   "fc5338f6ade783cfa0e6d59070c0f87d043e4bb4",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-026.html": [
+   "4146e5a7980ba1929393aad73d0a38e30f594f5e",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-027.html": [
+   "a216c5495aa1ec0c48639d021857780d51028a9f",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-028.html": [
+   "eb5ef17ef91e50f007620002c37778b2d57f446d",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-029.html": [
+   "700a07512ee0c9d5ffe6d8a776bf78effc0eadd3",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-030.html": [
+   "04b43a158f39adc75df90d91b6b2077f125ef003",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-031.html": [
+   "9e2bf0f24b6292bddb5a344edf29829e46387fe3",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-032.html": [
+   "34377d2550481dfe8e24fb33c29a627c6c417843",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-033.html": [
+   "cea28fc7b4cc0a8ab98d3e91d686075ee354f53b",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-034.html": [
+   "02ffd8c032ac6d23c0ad5e240b20e3f7f231a8b4",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-035.html": [
+   "04b6a7d9a56b0f7bf3b56af0ae8bc5c52ba18ee2",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-036.html": [
+   "e347950bcd14e28049cf7dd45d3368527b1a664a",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-037.html": [
+   "ec85bdff4c9c6ab4845b3310bf21f709f97bcf94",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-038.html": [
+   "5d085ff1a0b9c058646bd10f09b8cba8d6467a18",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-039.html": [
+   "8ea36428c6aceda04f07398ff8657c1265889a2d",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-040.html": [
+   "916ee4ea9a7e31347de3b712e285c128cd2f68e0",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-041.html": [
+   "4ed891d8de390a305eb7ec78432471ec0309254a",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-042.html": [
+   "106da07cb43c887a748b72fcec419c82a1a287bc",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-043.html": [
+   "529bd87e185b3987aecef014a06dd7628e64889f",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-044.html": [
+   "db29d4cdc85aac7566ac306597d011819a1db4b8",
+   "manual"
+  ],
+  "css/css-transitions/transition-property-045.html": [
+   "4b6dbbc692aeeb610eb186ae2e619321975af1f8",
+   "manual"
+  ],
+  "css/css-transitions/transition-test.html": [
+   "498818597889fae22b79d920d81712bbf77ae3e9",
+   "reftest"
+  ],
+  "css/css-transitions/transition-timing-function-001-expected.txt": [
+   "305fa8536974acd4a3aeefb11c97a72a7212450f",
+   "support"
+  ],
+  "css/css-transitions/transition-timing-function-001.html": [
+   "4b2e7ebb296da03f72f509e3cbc8d647c162c449",
+   "testharness"
+  ],
+  "css/css-transitions/transition-timing-function-002.html": [
+   "ad20165d3fc2c0fc2c0da50be7cd482f09e7bdb1",
+   "manual"
+  ],
+  "css/css-transitions/transition-timing-function-003.html": [
+   "21e0a6fc8b0c5c5503b72f04a85d6cc04cf10845",
+   "manual"
+  ],
+  "css/css-transitions/transition-timing-function-004.html": [
+   "b10107e60257ee4738811bee9f74b6878715d911",
+   "manual"
+  ],
+  "css/css-transitions/transition-timing-function-005.html": [
+   "9a2a1868aeab721574a0c72a8e9ef2a586d6ab64",
+   "manual"
+  ],
+  "css/css-transitions/transition-timing-function-006.html": [
+   "f85ea02dccbbfc49116e0f74a2039e18f6c83fab",
+   "manual"
+  ],
+  "css/css-transitions/transition-timing-function-007.html": [
+   "5d3b7f988c9ce7973cee42c5ff7635d6ea6b8ce4",
+   "manual"
+  ],
+  "css/css-transitions/transition-timing-function-008.html": [
+   "0cf235d15244432c5d03e270adfab65f2d4639b9",
+   "manual"
+  ],
+  "css/css-transitions/transition-timing-function-009.html": [
+   "27e7f6316d05680d3cda832ad65d201931a6f563",
+   "manual"
+  ],
+  "css/css-transitions/transition-timing-function-010.html": [
+   "e84f252786bdb42ad85586a1f1a8911ee722c959",
+   "manual"
+  ],
+  "css/css-transitions/transition-timing-function-011.html": [
+   "d81165943aff65a08f15cc4e3e2f1b2e46ff056f",
+   "manual"
+  ],
+  "css/css-transitions/transition-timing-function-012.html": [
+   "5728ba28f1eab1eca5767200c0178b76e10bfa5c",
+   "manual"
+  ],
+  "css/css-transitions/transition-timing-function-013.html": [
+   "ebcdec6b0ce54cb61c7f8a4abc6675783f06a109",
+   "manual"
+  ],
+  "css/css-transitions/transitioncancel-001-expected.txt": [
+   "884315f100592b9d2a1beabaa234b83eae5eaa79",
+   "support"
+  ],
+  "css/css-transitions/transitioncancel-001.html": [
+   "4db1d84665ccf75d993d877eb08574b1fa7d0203",
+   "testharness"
+  ],
+  "css/css-transitions/transitions-animatable-properties-01.html": [
+   "538b95863c061da60e95c1a61ef9dc93da007aa4",
+   "testharness"
+  ],
   "css/css-typed-om/CSSMatrixComponent-DOMMatrix-mutable-expected.txt": [
    "b382ae164d95402e1b19a9199e647316cb41ba4c",
    "support"
@@ -309254,38 +310427,6 @@
    "220814b621001b3ac2d0b1437d84d2078321e0b9",
    "reftest"
   ],
-  "css/css-writing-modes/ch-units-vrl-001.html": [
-   "1495c8627e20c07ac6ab888925d92f86d1f7aa29",
-   "reftest"
-  ],
-  "css/css-writing-modes/ch-units-vrl-002.html": [
-   "534a0cb579d21d3991abbd6be99560c8ffe06120",
-   "reftest"
-  ],
-  "css/css-writing-modes/ch-units-vrl-003.html": [
-   "fb04787ed593f053f57d5940ebed3dd7812f9e3d",
-   "reftest"
-  ],
-  "css/css-writing-modes/ch-units-vrl-004.html": [
-   "e0957395e97e8aa8f40008531dbec6588edaef6c",
-   "reftest"
-  ],
-  "css/css-writing-modes/ch-units-vrl-005.html": [
-   "4e950c9e21d61ec9aca9ca13a90ed02b6dd00d20",
-   "reftest"
-  ],
-  "css/css-writing-modes/ch-units-vrl-006.html": [
-   "4141f62654e7c58756abba0c51a414eff199a6bf",
-   "reftest"
-  ],
-  "css/css-writing-modes/ch-units-vrl-007.html": [
-   "d686d9af9cffbcf5ff97ee99174723da549d1150",
-   "reftest"
-  ],
-  "css/css-writing-modes/ch-units-vrl-008.html": [
-   "9e0bcf67c5678aeee8845dfb53413ff3b6268ad1",
-   "reftest"
-  ],
   "css/css-writing-modes/clearance-calculations-vrl-002-ref.xht": [
    "a81fc46fd680c66f2a4ff2d5b69ae7c85ff7802b",
    "support"
@@ -309762,22 +310903,6 @@
    "5827ead83a365ea8cb43412d2de239837f826f1b",
    "reftest"
   ],
-  "css/css-writing-modes/form-controls-slr-004.xht": [
-   "5913b5c624e76dd88b60c4483a7508d9ee1acdfd",
-   "visual"
-  ],
-  "css/css-writing-modes/form-controls-slr-005.xht": [
-   "f8580b2937e0723953124a5d3ad5211d193b98a8",
-   "visual"
-  ],
-  "css/css-writing-modes/form-controls-srl-004.xht": [
-   "4add739342cfad21e3c8181f4879b0ef81969823",
-   "visual"
-  ],
-  "css/css-writing-modes/form-controls-srl-005.xht": [
-   "610192f804eaf3e8aa8ec6ffe32e373f5121182f",
-   "visual"
-  ],
   "css/css-writing-modes/form-controls-vlr-004.xht": [
    "6914d51d54ecb957151ec4b28c78e36aafa39d91",
    "visual"
@@ -309886,10 +311011,6 @@
    "53f2dd3e1a6f17755d46ea7a20096b98367fb210",
    "reftest"
   ],
-  "css/css-writing-modes/inline-block-alignment-slr-009-ref.xht": [
-   "95122c4f48d4d8d84854d469de3b3039ce92fc57",
-   "support"
-  ],
   "css/css-writing-modes/inline-replaced-vlr-003.xht": [
    "9b9c4467b7f28b260b17ac4369a77a3f3a3e817d",
    "reftest"
@@ -310094,22 +311215,6 @@
    "af9a1409c41728f261794835cdedbfa2078aa141",
    "reftest"
   ],
-  "css/css-writing-modes/logical-props-001.html": [
-   "748107b578909bb444c7d6cad0a4e59881f69b82",
-   "reftest"
-  ],
-  "css/css-writing-modes/logical-props-002.html": [
-   "6ee88b30d660a43e7cc47d0d610472ca403335e6",
-   "reftest"
-  ],
-  "css/css-writing-modes/logical-props-003.html": [
-   "d1efd40838b83f293108935a755f7f3487700db4",
-   "reftest"
-  ],
-  "css/css-writing-modes/logical-props-004.html": [
-   "96ad70537c9ed9e207ac656a1756e10fec90811a",
-   "reftest"
-  ],
   "css/css-writing-modes/margin-collapse-vlr-003.xht": [
    "4d12a8cd3ec4cb21a30ae1c66facce5abd0a17b3",
    "reftest"
@@ -310366,14 +311471,6 @@
    "fdeb6bfb8b811005fb8a69172f75da465ba18421",
    "reftest"
   ],
-  "css/css-writing-modes/outline-inline-slr-005.xht": [
-   "16186c35b27f203ebc933dd709616485ee9d9c20",
-   "visual"
-  ],
-  "css/css-writing-modes/outline-inline-srl-004.xht": [
-   "133ce7d9f80f6348c3b31371bca5411e059da107",
-   "visual"
-  ],
   "css/css-writing-modes/outline-inline-vlr-003.xht": [
    "247d03ce6bb770c2212e71442319a9401a5d0efd",
    "visual"
@@ -310478,14 +311575,6 @@
    "6dfa1c5e24ea58513813792cfa7c7091a28c3a23",
    "manual"
   ],
-  "css/css-writing-modes/page-flow-direction-slr-005.xht": [
-   "8201313e778d8e5131309e0c9754a62bb7bcf894",
-   "manual"
-  ],
-  "css/css-writing-modes/page-flow-direction-srl-004.xht": [
-   "b7079a0dd1cc46e8252deff8a3b08e0915ea5a31",
-   "manual"
-  ],
   "css/css-writing-modes/percent-margin-vlr-003.xht": [
    "4dc2d772b9fedfc4f498ed488cd8d31c00c50c71",
    "reftest"
@@ -312562,74 +313651,6 @@
    "229401305c755d8e8f8faa22b5bd9114f1037810",
    "reftest"
   ],
-  "css/css-writing-modes/table-cell-001.html": [
-   "16d67b389404d9686f871a3664b37529ad585345",
-   "reftest"
-  ],
-  "css/css-writing-modes/table-cell-002.html": [
-   "cd6d48b254ef9232792834b78c7ebf6ce328edf8",
-   "reftest"
-  ],
-  "css/css-writing-modes/table-column-order-002.xht": [
-   "a9a2515df95c987a974786217cd78ffe9d71d22d",
-   "reftest"
-  ],
-  "css/css-writing-modes/table-column-order-003.xht": [
-   "278403502133ef49f4a0846ea37b57c06baf7cdb",
-   "reftest"
-  ],
-  "css/css-writing-modes/table-column-order-004.xht": [
-   "32989c0e49333dbfe79ab49b37dd97ee6f5da328",
-   "reftest"
-  ],
-  "css/css-writing-modes/table-column-order-005.xht": [
-   "52f8927a08607f7f59283dd4530ea3e4d30aaefa",
-   "reftest"
-  ],
-  "css/css-writing-modes/table-progression-001-ref.html": [
-   "f735a788aa1e51b185f7a72e5746af235c3464b8",
-   "support"
-  ],
-  "css/css-writing-modes/table-progression-002-ref.html": [
-   "c3a28573b64e810b798c1cb262ac3994ba974c32",
-   "support"
-  ],
-  "css/css-writing-modes/table-progression-slr-001-ref.html": [
-   "8125c1f137c1c1d946fd014f676156829716affa",
-   "support"
-  ],
-  "css/css-writing-modes/table-progression-vlr-001.html": [
-   "1b25005d5cfcca9f63c0ac7832f80b09e15ac00f",
-   "reftest"
-  ],
-  "css/css-writing-modes/table-progression-vlr-002.html": [
-   "f12c37a1bbed9e72b0b000b15cefd563441a7c3b",
-   "reftest"
-  ],
-  "css/css-writing-modes/table-progression-vlr-003.html": [
-   "361aa7f02654b7f6e18586e75e6365e13c8a3e87",
-   "reftest"
-  ],
-  "css/css-writing-modes/table-progression-vlr-004.html": [
-   "a5862eac108e3739e074240511df363b5e58f690",
-   "reftest"
-  ],
-  "css/css-writing-modes/table-progression-vrl-001.html": [
-   "c38d6172a27b0090f5972497095f0620a48faf3f",
-   "reftest"
-  ],
-  "css/css-writing-modes/table-progression-vrl-002.html": [
-   "8e09ef23f82f3ecbdf6d8d44a1a8ba9280a417af",
-   "reftest"
-  ],
-  "css/css-writing-modes/table-progression-vrl-003.html": [
-   "b5a016cd06ce5471ba76ada67c079ba5f1334027",
-   "reftest"
-  ],
-  "css/css-writing-modes/table-progression-vrl-004.html": [
-   "06da3d0196df6aae3ad342ec81cacd967423326d",
-   "reftest"
-  ],
   "css/css-writing-modes/test-plan/img/figure-over_and_under-fail.svg": [
    "e51cf0c5422eeeccb490e60dc4f30d675d2f28f4",
    "support"
@@ -312774,10 +313795,6 @@
    "f45c7c0be7c848c68052a0d18fccdd14c64ef53c",
    "reftest"
   ],
-  "css/css-writing-modes/text-baseline-slr-009-ref.xht": [
-   "7ec0350f6daedb8794cdfeec373626062d3006df",
-   "support"
-  ],
   "css/css-writing-modes/text-baseline-vlr-003.xht": [
    "d0aaa0eadcaefc6e5fd5de67f8e138f8e9a08f14",
    "reftest"
@@ -313030,14 +314047,6 @@
    "1afa90604eb4b0ebaf323f9455d8527d29bb7c50",
    "reftest"
   ],
-  "css/css-writing-modes/text-orientation-mixed-slr-015.xht": [
-   "5b03427b13a9586f7891acc84b4481e7be5d9ab4",
-   "visual"
-  ],
-  "css/css-writing-modes/text-orientation-mixed-srl-016-ref.xht": [
-   "5465539d4c5f2e7555da70a25e232fff37d26f8d",
-   "support"
-  ],
   "css/css-writing-modes/text-orientation-mixed-vlr-100-ref.html": [
    "97138c005328b42014b4e84bb21b5cef75ca8fa5",
    "support"
@@ -313142,10 +314151,6 @@
    "c6f9160ba49cf870c8a929d2e165c9a455dd6ef5",
    "visual"
   ],
-  "css/css-writing-modes/text-orientation-sideways-slr-019.xht": [
-   "6402e262986377f75a9734b2ad39c89462f1e4be",
-   "visual"
-  ],
   "css/css-writing-modes/text-orientation-sideways-vlr-100-ref.html": [
    "1f7adad5136675056df6ea741c5b614500b1b4bb",
    "support"
@@ -313162,10 +314167,6 @@
    "28677aafa451764e6b4f31944420be77a85e1ae8",
    "reftest"
   ],
-  "css/css-writing-modes/text-orientation-upright-slr-017.xht": [
-   "37048959d42607f908d704950860a82c605eae29",
-   "visual"
-  ],
   "css/css-writing-modes/text-orientation-upright-vlr-100-ref.html": [
    "3e8ac533cb5dac2bdd1fbffee57ba7c6f9485efd",
    "support"
@@ -313342,26 +314343,6 @@
    "b31f165623768cc252b294ae7a906677ec0efc38",
    "reftest"
   ],
-  "css/css-writing-modes/vertical-alignment-slr-037.xht": [
-   "a47e91d8d292ab9521b3d2319b3032fb090778f8",
-   "visual"
-  ],
-  "css/css-writing-modes/vertical-alignment-slr-039.xht": [
-   "355c4cf541617219a6afdcfd0ec35df37e8f9faa",
-   "visual"
-  ],
-  "css/css-writing-modes/vertical-alignment-slr-049-ref.xht": [
-   "29e78198de36c6357293406b20db81c81c737bf3",
-   "support"
-  ],
-  "css/css-writing-modes/vertical-alignment-srl-036.xht": [
-   "accf5217f77f550153cf3943f53884064f5c68b6",
-   "visual"
-  ],
-  "css/css-writing-modes/vertical-alignment-srl-038.xht": [
-   "c6ccd92ac36fc7981d06ec2ab44449051bc8ad79",
-   "visual"
-  ],
   "css/css-writing-modes/vertical-alignment-vlr-011.xht": [
    "4172d2d209fa5b20c186a37c615a9040fc4f3660",
    "visual"
@@ -313450,10 +314431,6 @@
    "d484c650f4c7f1beeb32d0f179fc29becfdca5b4",
    "reftest"
   ],
-  "css/css-writing-modes/wm-propagation-body-008.xht": [
-   "a58999e55ac7968974cca7ad14d0a218ec140458",
-   "reftest"
-  ],
   "css/css-writing-modes/wm-propagation-body-010.xht": [
    "afdd6ccde5781dec93a01596e28d09f9e0530501",
    "reftest"
@@ -320175,7 +321152,7 @@
    "testharness"
   ],
   "dom/interfaces-expected.txt": [
-   "3cacec14f027e5864ea398db96eb2960d28f30d4",
+   "2606ec37ce4ca007703f69f75e9fb74c97c8b3e2",
    "support"
   ],
   "dom/interfaces.html": [
@@ -320754,10 +321731,6 @@
    "e3fe31ea198922fe64fbf985ae99d1cd4512567a",
    "testharness"
   ],
-  "dom/nodes/Element-classlist-expected.txt": [
-   "d4176f04efee5475cb228397c498878b1e5454bf",
-   "support"
-  ],
   "dom/nodes/Element-classlist.html": [
    "e0a3126453af3e138c322ae0074d7ee73d604a8d",
    "testharness"
@@ -324986,6 +325959,10 @@
    "e6326b75fe6449f211ad19b98a9c1d7ed8c7c27f",
    "testharness"
   ],
+  "fetch/api/cors/cors-cookies-redirect.any.js": [
+   "700c33865dbb6d6dfe63fc08f646d120e7966484",
+   "testharness"
+  ],
   "fetch/api/cors/cors-cookies.any.js": [
    "246a6e661ef1179330f9109131cfcb2fa9f5bf64",
    "testharness"
@@ -325635,7 +326612,7 @@
    "support"
   ],
   "fetch/api/resources/inspect-headers.py": [
-   "c9ac2870a45253664da7de1aaf82626fdd1482bb",
+   "c062c905d538cfa96156fd38d98f586b2c4fb3b5",
    "support"
   ],
   "fetch/api/resources/keepalive-iframe.html": [
@@ -325655,7 +326632,7 @@
    "support"
   ],
   "fetch/api/resources/redirect.py": [
-   "79c8b1bcad05e05a7b628edb22fdaedbdf2c3bc5",
+   "37307bdb30853c2e824cce1fd9a190741e4975ce",
    "support"
   ],
   "fetch/api/resources/script-with-header.py": [
@@ -327058,6 +328035,10 @@
    "5c727eed4efd84b4b280b2584b7338217971a9e7",
    "testharness"
   ],
+  "hr-time/idlharness-expected.txt": [
+   "2606ec37ce4ca007703f69f75e9fb74c97c8b3e2",
+   "support"
+  ],
   "hr-time/idlharness.html": [
    "f2cdcba041df089206cc9c811167c41a771905df",
    "testharness"
@@ -331671,7 +332652,7 @@
    "support"
   ],
   "html/dom/interfaces-expected.txt": [
-   "09a178873b8b79cbfdf05cb8bdca5d90d3e4d3d0",
+   "5199c193d81b05bcccb06b31f023389650484b1f",
    "support"
   ],
   "html/dom/interfaces.html": [
@@ -341619,7 +342600,7 @@
    "testharness"
   ],
   "html/semantics/forms/the-select-element/selected-index.html": [
-   "3dbf338e9065f7f4ad2abfbaa55cf50329768cc2",
+   "98b59224f658d97a782623a054e5c3c5611945a2",
    "testharness"
   ],
   "html/semantics/forms/the-textarea-element/.gitkeep": [
@@ -346959,7 +347940,11 @@
    "support"
   ],
   "interfaces/html.idl": [
-   "b2b35732b54cbe3406493a6c121363eccceb4f5c",
+   "7b9b8b054ad2848e7c5983e46222fbdf8b3b8da8",
+   "support"
+  ],
+  "interfaces/keyboard-lock.idl": [
+   "7188a9233db3acc741650d46156e16e9e7a132fa",
    "support"
   ],
   "interfaces/magnetometer.idl": [
@@ -347190,32 +348175,28 @@
    "6374a5c8d059bb62d557b9d1b20bd855eaab90fa",
    "support"
   ],
-  "keyboard-lock/idlharness.https-expected.txt": [
-   "fe0401f9eb0efc3040b5518f712b2dc86b424a3a",
-   "support"
-  ],
   "keyboard-lock/idlharness.https.html": [
-   "4b41c1c46a8f7d2374d0ff9d796f3f938c1f74d8",
+   "010771094a9dc58e03a2c1ca2d8416866284fc2b",
    "testharness"
   ],
-  "keyboard-lock/navigator-keyboardLock-two-parallel-requests.https-expected.txt": [
-   "d0fa9fa282fc3b89819acba5d858de61c61ec4ce",
+  "keyboard-lock/navigator-keyboard-lock-two-parallel-requests.https-expected.txt": [
+   "3d01a926b0752a2677ae8d888489b1b27433ffc1",
    "support"
   ],
-  "keyboard-lock/navigator-keyboardLock-two-parallel-requests.https.html": [
-   "ee6fe59233abea9325bf7f5e14c1472a72e45a11",
+  "keyboard-lock/navigator-keyboard-lock-two-parallel-requests.https.html": [
+   "b594f75f5b0c89c2a5f2b934d170b8ff81ad9839",
    "testharness"
   ],
-  "keyboard-lock/navigator-keyboardLock-two-sequential-requests.https.html": [
-   "02ad8f54b7cebed96553bd96bbd7e8fc0227d3b1",
+  "keyboard-lock/navigator-keyboard-lock-two-sequential-requests.https.html": [
+   "8990cc5772cdba1281c0a05c6a3c2a80b08b810e",
    "testharness"
   ],
-  "keyboard-lock/navigator-keyboardLock.https.html": [
-   "572f4e827bc3807f4c71641e102d7bac9df3e391",
+  "keyboard-lock/navigator-keyboard-lock.https.html": [
+   "f95f8408986d73501ec7cce09106a8536bd891b4",
    "testharness"
   ],
-  "keyboard-lock/navigator-keyboardUnlock.https.html": [
-   "c4de12456714a34fb791b070304da31c99da080f",
+  "keyboard-lock/navigator-keyboard-unlock.https.html": [
+   "f5cc2141ea7c74964d308784901d6d2c242f4369",
    "testharness"
   ],
   "longtask-timing/OWNERS": [
@@ -348071,7 +349052,7 @@
    "testharness"
   ],
   "mediacapture-streams/MediaDevices-IDL-enumerateDevices-expected.txt": [
-   "9fe53c110fb03d6dadff00577d5082f221666d4b",
+   "67c20a2d57949e965b2680db32d10b287f44b393",
    "support"
   ],
   "mediacapture-streams/MediaDevices-IDL-enumerateDevices.html": [
@@ -356506,6 +357487,14 @@
    "7bfce9810c1afdc53a99fa0036c472f6cfbe5deb",
    "testharness"
   ],
+  "payment-request/PaymentItem/type_member.https-expected.txt": [
+   "976c888831fa4a498fb1e5d5aaa4578c8f6617f0",
+   "support"
+  ],
+  "payment-request/PaymentItem/type_member.https.html": [
+   "5568f96eac7b0ebf1d91d468bb30b9eaa8b1a9f0",
+   "testharness"
+  ],
   "payment-request/PaymentRequestUpdateEvent/constructor.http.html": [
    "017f1f1aca43171083833ddb27ff66e39902e85d",
    "testharness"
@@ -356650,6 +357639,14 @@
    "34dd889e8bc906eb9a99c192e547fab831099f7c",
    "testharness"
   ],
+  "payment-request/payment-request-insecure.http-expected.txt": [
+   "b97d187511f905c5a7573693c53e13f3475534ed",
+   "support"
+  ],
+  "payment-request/payment-request-insecure.http.html": [
+   "34452230c20571ef161fa237130faea57240f532",
+   "testharness"
+  ],
   "payment-request/payment-request-not-exposed.https.worker.js": [
    "b1c3cdc182cb967ec11b1cad826b333511203d77",
    "testharness"
@@ -369138,6 +370135,10 @@
    "e33e48a3eb754e961f07b7850caff67eee38fe69",
    "testharness"
   ],
+  "shadow-dom/Element-interface-attachShadow-custom-element.html": [
+   "4628a8a6e145713c7e0e9df0960d51e34df2fc53",
+   "testharness"
+  ],
   "shadow-dom/Element-interface-attachShadow.html": [
    "e5b4dedaf8f78a6ce771af4509da8acb3aca3441",
    "testharness"
@@ -370466,14 +371467,6 @@
    "6f3911baf77e26af2d7e7d7472caae4df6d5a27e",
    "testharness"
   ],
-  "streams/transform-streams/errors-expected.txt": [
-   "2ba9233fbbde4f44203326fdfd7909125814bf8f",
-   "support"
-  ],
-  "streams/transform-streams/errors.dedicatedworker-expected.txt": [
-   "2ba9233fbbde4f44203326fdfd7909125814bf8f",
-   "support"
-  ],
   "streams/transform-streams/errors.dedicatedworker.html": [
    "ea56c89e303ed85d5f6acd423600b1d4ad73ac13",
    "testharness"
@@ -370486,18 +371479,10 @@
    "607bf12f225025a006e3b898776553fa23d38597",
    "support"
   ],
-  "streams/transform-streams/errors.serviceworker.https-expected.txt": [
-   "8f5bac390f21f8b729d3741b936c7d365e5c7f84",
-   "support"
-  ],
   "streams/transform-streams/errors.serviceworker.https.html": [
    "85dc0c4639761359a19c1eed51692688c0a5fb7c",
    "testharness"
   ],
-  "streams/transform-streams/errors.sharedworker-expected.txt": [
-   "2ba9233fbbde4f44203326fdfd7909125814bf8f",
-   "support"
-  ],
   "streams/transform-streams/errors.sharedworker.html": [
    "479366dd2a194281aba6138aa10fd2bc788ea44c",
    "testharness"
@@ -370582,14 +371567,6 @@
    "477cc1ed4cc94ff6ee29dcd6f96c16768a2c7567",
    "testharness"
   ],
-  "streams/transform-streams/properties-expected.txt": [
-   "d39fe78f78dade58a39adcaf4675b752916d065f",
-   "support"
-  ],
-  "streams/transform-streams/properties.dedicatedworker-expected.txt": [
-   "d39fe78f78dade58a39adcaf4675b752916d065f",
-   "support"
-  ],
   "streams/transform-streams/properties.dedicatedworker.html": [
    "0d766237560b16ddb1bfcd02e701089132f1b3ec",
    "testharness"
@@ -370602,30 +371579,14 @@
    "8bf21998fc6b9d26e79e1fdf541a2efb8f566d36",
    "support"
   ],
-  "streams/transform-streams/properties.serviceworker.https-expected.txt": [
-   "24700fb59915a38d25453af0669829efd5f51542",
-   "support"
-  ],
   "streams/transform-streams/properties.serviceworker.https.html": [
    "2ef8fc878249c429a89e0748e6a98fac47c1a99a",
    "testharness"
   ],
-  "streams/transform-streams/properties.sharedworker-expected.txt": [
-   "d39fe78f78dade58a39adcaf4675b752916d065f",
-   "support"
-  ],
   "streams/transform-streams/properties.sharedworker.html": [
    "5c855e897d1143092ecc10b58268e6a576882184",
    "testharness"
   ],
-  "streams/transform-streams/reentrant-strategies-expected.txt": [
-   "9db3b8540b4bc30489eb73208c4cec67f8b52347",
-   "support"
-  ],
-  "streams/transform-streams/reentrant-strategies.dedicatedworker-expected.txt": [
-   "9db3b8540b4bc30489eb73208c4cec67f8b52347",
-   "support"
-  ],
   "streams/transform-streams/reentrant-strategies.dedicatedworker.html": [
    "6f9350ce1caf4fa9e6239693ec91b2249c2adab5",
    "testharness"
@@ -370638,18 +371599,10 @@
    "1ddadc53f6b69bda7cf015ca44e6c78f74f11111",
    "support"
   ],
-  "streams/transform-streams/reentrant-strategies.serviceworker.https-expected.txt": [
-   "fb43ed0f406693e285c61f9752c1b25bef98b4fb",
-   "support"
-  ],
   "streams/transform-streams/reentrant-strategies.serviceworker.https.html": [
    "f3000f522b6e1b7f1db839b85ff71aed36c29b8d",
    "testharness"
   ],
-  "streams/transform-streams/reentrant-strategies.sharedworker-expected.txt": [
-   "9db3b8540b4bc30489eb73208c4cec67f8b52347",
-   "support"
-  ],
   "streams/transform-streams/reentrant-strategies.sharedworker.html": [
    "cdbd3f2cfc307cf007eabfb324dc107d5baa86a0",
    "testharness"
@@ -373091,7 +374044,7 @@
    "testharness"
   ],
   "web-animations/interfaces/KeyframeEffect/idlharness-expected.txt": [
-   "072161b953aa02ede9a6a37dc0e8c8b506eb3652",
+   "7a3fcbe2552c1778b73aa834d92dd91422ee063e",
    "support"
   ],
   "web-animations/interfaces/KeyframeEffect/idlharness.html": [
@@ -373519,7 +374472,7 @@
    "testharness"
   ],
   "webaudio/idlharness.https-expected.txt": [
-   "fb80b7f73175870f1424df7fdfefb32053029983",
+   "2606ec37ce4ca007703f69f75e9fb74c97c8b3e2",
    "support"
   ],
   "webaudio/idlharness.https.html": [
@@ -374967,7 +375920,7 @@
    "testharness"
   ],
   "webrtc/RTCPeerConnection-setLocalDescription-answer-expected.txt": [
-   "f082fa414eaf77ae0e510cfe5ea17e03d518e56c",
+   "4b15eb005f8d0825ba66bd018d8597a2d2ff779a",
    "support"
   ],
   "webrtc/RTCPeerConnection-setLocalDescription-answer.html": [
@@ -374979,15 +375932,15 @@
    "support"
   ],
   "webrtc/RTCPeerConnection-setLocalDescription-offer-expected.txt": [
-   "f9d35643d0931d5062e8f632f4d57d09f0bff58c",
+   "456d511a8a15fe312d14333464b95080ef2171a8",
    "support"
   ],
   "webrtc/RTCPeerConnection-setLocalDescription-offer.html": [
-   "9f30ee4801fbcd574d90c3f15a733c448f148649",
+   "117fc91599d11b63f2d232a63bace8e367dbb72a",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-setLocalDescription-pranswer-expected.txt": [
-   "ff21fde36d76b73bf976beec719c306ef1190c01",
+   "4a74b3588c4ca20f33af96b8dff3e8b9e672829f",
    "support"
   ],
   "webrtc/RTCPeerConnection-setLocalDescription-pranswer.html": [
@@ -375291,7 +376244,7 @@
    "support"
   ],
   "webrtc/interfaces.https-expected.txt": [
-   "c6d434a1c1082cd0046814f115b45535265068a4",
+   "215189f2052cb1f913baf31c5d319969fd6a8a58",
    "support"
   ],
   "webrtc/interfaces.https.html": [
@@ -380338,6 +381291,26 @@
    "6bffa3be83d81e2faa93119e710e4fee93fb855e",
    "testharness"
   ],
+  "workers/modules/dedicated-worker-options-type.html": [
+   "9f6f1be759beb885e2baa746e36ace83685f649b",
+   "testharness"
+  ],
+  "workers/modules/dedicated-worker-static-import.html": [
+   "d0d3dc37a8c061a1dc5213f8fe79e7f985c48b81",
+   "testharness"
+  ],
+  "workers/modules/resources/nested-static-import-worker.js": [
+   "eb76ec7e8a0f9df6de7114e3aa9100f8374fea8f",
+   "support"
+  ],
+  "workers/modules/resources/post-message-on-load-worker.js": [
+   "c67a79ade775435a67e5999d17e7cdda450c8e50",
+   "support"
+  ],
+  "workers/modules/resources/static-import-worker.js": [
+   "f3020118d7e499e0e910abc7a733e0b9c3cf1e5a",
+   "support"
+  ],
   "workers/name-property-expected.txt": [
    "a5bef9fb78bb5b11e9659f1daf50951fa93de700",
    "support"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/interfaces.any.js b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/interfaces.any.js
index f142db45..f1b2a993 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/interfaces.any.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/interfaces.any.js
@@ -9,8 +9,7 @@
   ].map(url => fetch(url).then(response => response.text())));
 
   const idl_array = new IdlArray();
-  idl_array.add_untested_idls('interface LinkStyle {};');  // Needed by html
-  idl_array.add_untested_idls(html);
+  idl_array.add_untested_idls(html, { only: ['WindowOrWorkerGlobalScope'] });
   idl_array.add_untested_idls(dom);
   idl_array.add_idls(indexeddb);
   idl_array.add_objects({
diff --git a/third_party/WebKit/LayoutTests/external/wpt/cookie-store/idlharness.tentative.html b/third_party/WebKit/LayoutTests/external/wpt/cookie-store/idlharness.tentative.html
index 648d567..e9ffab37 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/cookie-store/idlharness.tentative.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/cookie-store/idlharness.tentative.html
@@ -19,6 +19,7 @@
   // Dependencies of HTML
   idl_array.add_untested_idls('interface Document {};');
   idl_array.add_untested_idls('interface LinkStyle {};');
+  idl_array.add_untested_idls('interface SVGElement {};');
   idl_array.add_untested_idls(html);
 
   idl_array.add_untested_idls('interface Event {};');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-font-loading/idlharness.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-font-loading/idlharness.https-expected.txt
index 61a0d30..64d6523b 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-font-loading/idlharness.https-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-font-loading/idlharness.https-expected.txt
@@ -1,9 +1,3 @@
-frame (anonymous) - didStartProvisionalLoadForFrame
-frame (anonymous) - didCommitLoadForFrame
-main frame - didReceiveTitle: Font Loading API IDL tests
-main frame - didFinishDocumentLoadForFrame
-main frame - didHandleOnloadEventsForFrame
-main frame - didFinishLoadForFrame
 This is a testharness.js-based test.
 PASS Test IDL implementation of CSS Font Loading
 PASS Document interface: attribute fonts
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-definition/grid-inline-auto-repeat-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-definition/grid-inline-auto-repeat-001.html
new file mode 100644
index 0000000..b06ffe5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-definition/grid-inline-auto-repeat-001.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html lang=en>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: auto repeat tracks in indefinite containers with minimum size</title>
+<link rel="author" title="Sergio Villar Senin" href="mailto:svillar@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#repeat-syntax">
+<meta name="assert" content="This test checks that we properly compute the number of required auto repeat tracks in indefinite sized containers with minimum sizes.">
+<link rel="stylesheet" href="support/grid.css">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/testing-utils.js"></script>
+<style>
+.grid {
+    display: inline-grid;
+    grid: 20px / 20px;
+    min-width: 20px;
+    min-height: 20px;
+    justify-content: start;
+    align-content: start;
+}
+</style>
+<div id="log"></div>
+
+<div id="autoFillColumns" class="grid"></div>
+<div id="autoFitColumns" class="grid"></div>
+
+<div id="autoFillRows" class="grid"></div>
+<div id="autoFitRows" class="grid"></div>
+
+<script>
+// Exact fit
+TestingUtils.testGridTemplateColumnsRows("autoFillColumns", "repeat(auto-fill, 10px)", "20px", ["repeat(2, 10px)", "10px 10px"], "20px");
+TestingUtils.testGridTemplateColumnsRows("autoFitColumns", "repeat(auto-fit, 10px)", "20px", ["repeat(2, 0px)", "0px 0px"], "20px");
+TestingUtils.testGridTemplateColumnsRows("autoFillRows", "20px", "repeat(auto-fill, 10px)", "20px", ["repeat(2, 10px)", "10px 10px"]);
+TestingUtils.testGridTemplateColumnsRows("autoFitRows", "20px", "repeat(auto-fit, 10px)", "20px", ["repeat(2, 0px)", "0px 0px"]);
+
+// Require an extra track
+TestingUtils.testGridTemplateColumnsRows("autoFillColumns", "repeat(auto-fill, 9px)", "20px", ["repeat(3, 9px)", "9px 9px 9px"], "20px");
+TestingUtils.testGridTemplateColumnsRows("autoFitColumns", "repeat(auto-fit, 9px)", "20px", ["repeat(2, 0px)", "0px 0px"], "20px");
+TestingUtils.testGridTemplateColumnsRows("autoFillRows", "20px", "repeat(auto-fill, 9px)", "20px", ["repeat(3, 9px)", "9px 9px 9px"]);
+TestingUtils.testGridTemplateColumnsRows("autoFitRows", "20px", "repeat(auto-fit, 9px)", "20px", ["repeat(3, 0px)", "0px 0px 0px"]);
+
+// A single repetition is enough to fill in all the available space
+TestingUtils.testGridTemplateColumnsRows("autoFillColumns", "repeat(auto-fill, 30px)", "20px", "30px", "20px");
+TestingUtils.testGridTemplateColumnsRows("autoFitColumns", "repeat(auto-fit, 30px)", "20px", "0px", "20px");
+TestingUtils.testGridTemplateColumnsRows("autoFillRows", "20px", "repeat(auto-fill, 30px)", "20px", "30px");
+TestingUtils.testGridTemplateColumnsRows("autoFitRows", "20px", "repeat(auto-fit, 30px)", "20px", "0px");
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-tables/height-distribution/td-different-subpixel-padding-in-same-row-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-tables/height-distribution/td-different-subpixel-padding-in-same-row-ref.html
new file mode 100644
index 0000000..02f0f54c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-tables/height-distribution/td-different-subpixel-padding-in-same-row-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+Passes if there is an unbroken rectangular border.
+<style>td { width: 20px; height: 20px; padding: 2px }</style>
+<table style="position: absolute; top: 30.3px; border: 2px solid black; border-collapse: collapse">
+  <tr>
+    <td></td>
+    <td></td>
+    <td></td>
+    <td></td>
+    <td></td>
+  </tr>
+</table>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-tables/height-distribution/td-different-subpixel-padding-in-same-row-vertical-rl-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-tables/height-distribution/td-different-subpixel-padding-in-same-row-vertical-rl-ref.html
new file mode 100644
index 0000000..9784962
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-tables/height-distribution/td-different-subpixel-padding-in-same-row-vertical-rl-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+Passes if there is an unbroken rectangular border.
+<style>td { width: 20px; height: 20px; padding: 2px }</style>
+<table style="position: absolute; top: 30.3px; border: 2px solid black;
+              border-collapse: collapse; writing-mode: vertical-rl">
+  <tr>
+    <td></td>
+    <td></td>
+    <td></td>
+    <td></td>
+    <td></td>
+  </tr>
+</table>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-tables/height-distribution/td-different-subpixel-padding-in-same-row-vertical-rl.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-tables/height-distribution/td-different-subpixel-padding-in-same-row-vertical-rl.html
new file mode 100644
index 0000000..48edbde
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-tables/height-distribution/td-different-subpixel-padding-in-same-row-vertical-rl.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.csswg.org/css-tables-3/#height-distribution-algorithm">
+<link rel="match" href="td-different-subpixel-padding-in-same-row-vertical-rl-ref.html">
+Passes if there is an unbroken rectangular border.
+<style>td { width: 20px; height: 20px }</style>
+<table style="position: absolute; top: 30.3px; border: 2px solid black;
+              border-collapse: collapse; writing-mode: vertical-rl">
+  <tr>
+    <td style="padding: 2px 1px"></td>
+    <td style="padding: 2px 1.2px"></td>
+    <td style="padding: 2px 1.5px"></td>
+    <td style="padding: 2px 1.7px"></td>
+    <td style="padding: 2px"></td>
+  </tr>
+</table>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-tables/height-distribution/td-different-subpixel-padding-in-same-row.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-tables/height-distribution/td-different-subpixel-padding-in-same-row.html
new file mode 100644
index 0000000..a7fe908
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-tables/height-distribution/td-different-subpixel-padding-in-same-row.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.csswg.org/css-tables-3/#height-distribution-algorithm">
+<link rel="match" href="td-different-subpixel-padding-in-same-row-ref.html">
+Passes if there is an unbroken rectangular border.
+<style>td { width: 20px; height: 20px }</style>
+<table style="position: absolute; top: 30.3px; border: 2px solid black; border-collapse: collapse">
+  <tr>
+    <td style="padding: 1px 2px"></td>
+    <td style="padding: 1.2px 2px"></td>
+    <td style="padding: 1.5px 2px"></td>
+    <td style="padding: 1.7px 2px"></td>
+    <td style="padding: 2px"></td>
+  </tr>
+</table>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-tables/width-distribution/td-with-subpixel-padding-vertical-rl.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-tables/width-distribution/td-with-subpixel-padding-vertical-rl.html
new file mode 100644
index 0000000..18ed2ddd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-tables/width-distribution/td-with-subpixel-padding-vertical-rl.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/css-tables/#width-distribution" />
+<style>
+td div {
+  display: inline-block;
+  width: 20px;
+  height: 20px;
+  background: blue;
+}
+</style>
+Passes if each column (logical row) has two blue squares.
+<div style="writing-mode: vertical-rl">
+<table>
+  <tr>
+    <td class='target' style="padding: 0.8px 0"><div></div> <div></div></td>
+    <td style="padding: 0.8px 0; width: 30px"></td>
+  </tr>
+</table>
+<table>
+  <tr>
+    <td class='target' style="padding: 1px 0"><div></div> <div></div></td>
+    <td style="padding: 1px 0; width: 30px"></td>
+  </tr>
+</table>
+<table>
+  <tr>
+    <td class='target' style="padding: 1.3px 0"><div></div> <div></div></td>
+    <td style="padding: 1.3px 0; width: 30px"></td>
+  </tr>
+</table>
+<table>
+  <tr>
+    <td class='target' style="padding: 1.5px 0"><div></div> <div></div></td>
+    <td style="padding: 1.5px 0; width: 30px"></td>
+  </tr>
+</table>
+<table>
+  <tr>
+    <td class='target' style="padding: 1.7px 0"><div></div> <div></div></td>
+    <td style="padding: 1.7px 0; width: 30px"></td>
+  </tr>
+</table>
+</div>
+<script>
+test(() => {
+  var targets = document.getElementsByClassName('target');
+  for (var i = 0; i < targets.length; ++i) {
+    var divs = targets[i].getElementsByTagName('div');
+    assert_equals(divs.length, 2);
+    assert_equals(divs[0].offsetLeft, divs[1].offsetLeft, 'Contents of td.target[' + i + '] should not wrap');
+  }
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/README.md b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/README.md
new file mode 100644
index 0000000..e44decf
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/README.md
@@ -0,0 +1,76 @@
+# CSSWG Compatible Tests #
+
+## Hints ##
+
+* en/disable vendor-prefixing in `./support/helper.js` see `addVendorPrefixes`
+* remove extra `<length>` values to reduce test cases (and thus execution duration) in `./support.properties.js`, see `values.length`
+
+
+## General Properties Test Concept ##
+
+Using `support/property.js` test suites compile a list of animatable properties. `getPropertyTests()` (and the like) will expand the specification's `width: length, percentage` to `width: 1em, 1ex, 1px, … 1%` in order to test all possible value types. The propertyTests returned by `support/property.js` have the following general structure:
+
+```javascript
+{
+  // name of the test
+  "name": "background-color color(rgba)",
+  // property that is being tested
+  "property": "background-color",
+  // styles to set on the parent container (usually #container)
+  "parentStyle": {},
+  // initial styles to set on the transition element (usually #transition)
+  // may contain additional properties such as position: absolute; as required
+  "from": {
+    "background-color": "rgba(100,100,100,1)"
+  },
+  // styles to transition to
+  "to": {
+    "background-color": "rgba(10,10,10,0.4)"
+  },
+  // flags classifying property types,
+  // currently only {discrete:true} for visbility
+  "flags": {}
+}
+```
+
+For each compiled test case the test runner identifies computed initial and target values. If they match, no transition will take place, because the property couldn't be parsed. If after starting the transition the computed style matches the target value, the browser applied that value immedately and no transition will take place. During the transition the computed style may match neither initial nor target value (unless it's a discrete transition), or there was no transition.
+
+Besides value-assertions, the suites compare received TransitionEnd events. While the values are only matched against computed initial and target values, expected TransitionEnd events are declared explicitly. This can (and will) lead to some test failures that are arguably not a failure (mainly because the specification didn't cover the specific case). Transitioning `color` *may* (or not, depending on browser) also run a transition for `background-color`, as the latter's default value is `currentColor`. This suite considers those implicit transitions a failure. If it truly is a failure or not, should be decided in the specification (and tests updated accordingly).
+
+Browsers supporting requestAnimationFrame can run a test in 100ms. Browsers that don't need a wider time frame to allow the not very dead-on-target setTimeout() to be triggered between TransitionStart and TransitionEnd. Low-end CPU devices also benefit from slower transitions. Since a 300 hundred tests, each lasting 500ms would require 2.5 minutes to run, tests are run concurrently, as they cannot affect each other. For low-end devices (e.g. iPad) too many parallel tests lead to global failure, because a single `requestAnimationFrame()` would have to iterate too many nodes, which is why the suite shards into slices of 50 parallel tests. Tests are run in an off-viewport container, to prevent you from having seizures.
+
+To make individual tests a bit more readable, a lot of the test-functionality has been moved to external JavaScript files. All assertions reside within the test file itsel, though. Although they are mostly exact duplicates of other tests, it should help understanding what a test does (while abstracting away *how* it does it.)
+
+### Debugging ###
+
+1. reduce to the tests you want to take a closer look at - see `filterPropertyTests()` in `support/properties.js`
+2. disable final cleanup by commenting out `done` and `teardown` callbacks
+3. possibly increase the `duration` and disable the `#offscreen` (by simply naming it `#off-screen`)
+
+
+## Unspecified Behavior ##
+
+the following suites test behavior that is not covered in CSS3 Transitions (as of today):
+
+* `properties-value-002.html` - verify value types transitionable but not specified for properties
+* `properties-value-003.html` - verify transitionable properties thus far not specified at all
+* `properties-value-implicit-001.html` - verify behavior for `em` based `<length>` properties when `font-size` is changed
+* `events-006.html` - expect `TransitionEnd` event to be triggered and `event.pseudoElement` to be set properly
+* `before-DOMContentLoaded-001.html` - expect transitions to be performed before DOM is ready
+* `before-load-001.html` - expect transitions to be performed before document is fully loaded
+* `hidden-container-001.html` - expect transitions to NOT be performed if they happen within hidden elements
+* `detached-container-001.html` - expect transitions to NOT be performed if they happen outside of the document
+
+
+## Yet To Be Tested ##
+
+These are topics I have identifed in need of testing, but haven gotten around to testing them.
+
+* Anything involving `<svg>`
+  * well, maybe some day...
+* proper execution of timing-functions - are the right property values set at a given time?
+  * how exactly do I pinpoint a specific time to verify a property's value at time `t`?
+  * need to implement cubic-bezier to actually calculate a property's value at time `t`?
+* `selector:hover:before {}`
+  * I have no clue how to trigger that from script
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/before-DOMContentLoaded-001-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/before-DOMContentLoaded-001-expected.txt
new file mode 100644
index 0000000..74659d0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/before-DOMContentLoaded-001-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+PASS transition height from 10px to 100px / values
+FAIL transition height from 10px to 100px / events assert_false: DOMContentLoaded may not have happened yet expected false got true
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/before-DOMContentLoaded-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/before-DOMContentLoaded-001.html
new file mode 100644
index 0000000..152f777
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/before-DOMContentLoaded-001.html
@@ -0,0 +1,150 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>CSS Transitions Test: Transitioning before DOMContentLoaded event</title>
+        <meta name="assert" content="Test checks that transitions are run even before the document has left parsing mode">
+        <link rel="help" title="5. Transition Events" href="http://www.w3.org/TR/css3-transitions/#transition-events">
+        <link rel="author" title="Rodney Rehm" href="http://rodneyrehm.de/en/">
+        <meta name="flags" content="dom">
+
+        <script src="/resources/testharness.js" type="text/javascript"></script>
+        <script src="/resources/testharnessreport.js" type="text/javascript"></script>
+
+        <script src="./support/vendorPrefix.js" type="text/javascript"></script>
+        <script src="./support/helper.js" type="text/javascript"></script>
+        <script src="./support/runParallelAsyncHarness.js" type="text/javascript"></script>
+        <script src="./support/generalParallelTest.js" type="text/javascript"></script>
+        <script src="./support/properties.js" type="text/javascript"></script>
+
+        <style type="text/css">
+            #offscreen {
+                position: absolute;
+                top: -100000px;
+                left: -100000px;
+                width: 100000px;
+                height: 100000px;
+            }
+        </style>
+    </head>
+    <body>
+        <!-- required by testharnessreport.js -->
+        <div id="log"></div>
+        <!-- elements used for testing -->
+        <div id="fixture" class="fixture">
+            <div class="container">
+                <div class="transition">Text sample</div>
+            </div>
+        </div>
+        <div id="offs-creen"></div>
+
+        <!--
+            SEE ./support/README.md for an abstract explanation of the test procedure
+            http://test.csswg.org/source/contributors/rodneyrehm/submitted/css3-transitions/README.md
+        -->
+
+        <script>
+            // make sure a transition is run between DOMContentLoaded and load
+
+            var isDOMContentLoaded = false;
+            window.addEventListener('DOMContentLoaded', function() {
+                isDOMContentLoaded = true;
+            }, false);
+
+            // this test takes its time, give it a minute to run
+            var timeout = 60000;
+            setup({timeout: timeout});
+
+            var tests = [
+                {
+                    name: "transition height from 10px to 100px",
+                    property: 'height',
+                    flags: {},
+                    from: {'height': '10px'},
+                    to: {'height': '100px'}
+                }
+            ];
+
+            // general transition-duration
+            var duration = '0.5s';
+
+            runParallelAsyncHarness({
+                // array of test data
+                tests: tests,
+                // the number of tests to run in parallel
+                testsPerSlice: 1,
+                // milliseconds to wait before calling teardown and ending test
+                duration: parseFloat(duration) * 1000,
+                // the global suite timeout
+                timeout: timeout,
+                // prepare individual test
+                setup: function(data, options) {
+                    var styles = {
+                        '.fixture': {},
+
+                        '.container': data.parentStyle,
+                        '.container.to': {},
+                        '.container.how': {},
+
+                        '.transition': data.from,
+                        '.transition.to' : data.to,
+                        '.transition.how' : {transition: 'all ' + duration + ' linear 0s'}
+                    };
+
+                    generalParallelTest.setup(data, options);
+                    generalParallelTest.addStyles(data, options, styles);
+                },
+                // cleanup after individual test
+                teardown: generalParallelTest.teardown,
+                // invoked prior to running a slice of tests
+                sliceStart: function(options, tests) {
+                    // inject styles into document
+                    setStyle(options.styles);
+                },
+                // invoked after running a slice of tests
+                sliceDone: generalParallelTest.sliceDone,
+                // test cases, make them as granular as possible
+                cases: {
+                    // test property values while transitioning
+                    // values.start kicks off a transition
+                    'values': {
+                        // run actual test, assertions can be used here!
+                        start: function(test, data, options) {
+                            // identify initial and target values
+                            generalParallelTest.getStyle(data);
+                            // make sure values differ, if they don't, the property could most likely not be parsed
+                            assert_not_equals(data.transition.from, data.transition.to, "initial and target values may not match");
+                            // kick off the transition
+                            generalParallelTest.startTransition(data);
+
+                            // make sure we didn't get the target value immediately.
+                            // If we did, there wouldn't be a transition!
+                            var current = data.transition.computedStyle(data.property);
+                            assert_not_equals(current, data.transition.to, "must not be target value after start");
+                        },
+                        done: function(test, data, options) {
+                            // make sure the property's value were neither initial nor target while transitioning
+                            test.step(generalParallelTest.assertIntermediateValuesFunc(data, 'transition'));
+                        }
+                    },
+                    // test TransitionEnd events
+                    'events': {
+                        done: function(test, data, options) {
+                            // make sure there were no events on parent
+                            test.step(generalParallelTest.assertExpectedEventsFunc(data, 'container', ""));
+                            // make sure we got the event for the tested property only
+                            test.step(generalParallelTest.assertExpectedEventsFunc(data, 'transition', addVendorPrefix(data.property) + ":" + duration));
+
+                            test.step(function() {
+                                assert_false(isDOMContentLoaded, "DOMContentLoaded may not have happened yet")
+                            });
+                        }
+                    }
+                },
+                // called once all tests are done
+                done: generalParallelTest.done
+            });
+        </script>
+        <script src="/delay/?type=js&amp;delay=3000"></script>
+    </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/before-load-001-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/before-load-001-expected.txt
new file mode 100644
index 0000000..d88c12b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/before-load-001-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+PASS transition height from 10px to 100px / values
+FAIL transition height from 10px to 100px / events assert_false: load may not have happened yet expected false got true
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/before-load-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/before-load-001.html
new file mode 100644
index 0000000..ee633cf
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/before-load-001.html
@@ -0,0 +1,152 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>CSS Transitions Test: Transitioning before load event</title>
+        <meta name="assert" content="Test checks that transitions are run even before all assets are loaded">
+        <link rel="help" title="5. Transition Events" href="http://www.w3.org/TR/css3-transitions/#transition-events">
+        <link rel="author" title="Rodney Rehm" href="http://rodneyrehm.de/en/">
+        <meta name="flags" content="dom">
+
+        <script src="/resources/testharness.js" type="text/javascript"></script>
+        <script src="/resources/testharnessreport.js" type="text/javascript"></script>
+
+        <script src="./support/vendorPrefix.js" type="text/javascript"></script>
+        <script src="./support/helper.js" type="text/javascript"></script>
+        <script src="./support/runParallelAsyncHarness.js" type="text/javascript"></script>
+        <script src="./support/generalParallelTest.js" type="text/javascript"></script>
+        <script src="./support/properties.js" type="text/javascript"></script>
+
+        <style type="text/css">
+            #offscreen {
+                position: absolute;
+                top: -100000px;
+                left: -100000px;
+                width: 100000px;
+                height: 100000px;
+            }
+        </style>
+    </head>
+    <body>
+        <!-- required by testharnessreport.js -->
+        <div id="log"></div>
+        <!-- elements used for testing -->
+        <div id="fixture" class="fixture">
+            <div class="container">
+                <div class="transition">Text sample</div>
+            </div>
+        </div>
+        <div id="offs-creen"></div>
+
+        <!--
+            SEE ./support/README.md for an abstract explanation of the test procedure
+            http://test.csswg.org/source/contributors/rodneyrehm/submitted/css3-transitions/README.md
+        -->
+
+        <script>
+            // make sure a transition is run between DOMContentLoaded and load
+
+            // this test takes its time, give it a minute to run
+            var timeout = 60000;
+            setup({timeout: timeout});
+
+            var isLoad = false;
+            window.addEventListener('load', function() {
+                isLoad = true;
+            }, false);
+
+            window.addEventListener('DOMContentLoaded', function() {
+                var tests = [
+                    {
+                        name: "transition height from 10px to 100px",
+                        property: 'height',
+                        flags: {},
+                        from: {'height': '10px'},
+                        to: {'height': '100px'}
+                    }
+                ];
+
+                // general transition-duration
+                var duration = '0.5s';
+
+                runParallelAsyncHarness({
+                    // array of test data
+                    tests: tests,
+                    // the number of tests to run in parallel
+                    testsPerSlice: 1,
+                    // milliseconds to wait before calling teardown and ending test
+                    duration: parseFloat(duration) * 1000,
+                    // the global suite timeout
+                    timeout: timeout,
+                    // prepare individual test
+                    setup: function(data, options) {
+                        var styles = {
+                            '.fixture': {},
+
+                            '.container': data.parentStyle,
+                            '.container.to': {},
+                            '.container.how': {},
+
+                            '.transition': data.from,
+                            '.transition.to' : data.to,
+                            '.transition.how' : {transition: 'all ' + duration + ' linear 0s'}
+                        };
+
+                        generalParallelTest.setup(data, options);
+                        generalParallelTest.addStyles(data, options, styles);
+                    },
+                    // cleanup after individual test
+                    teardown: generalParallelTest.teardown,
+                    // invoked prior to running a slice of tests
+                    sliceStart: function(options, tests) {
+                        // inject styles into document
+                        setStyle(options.styles);
+                    },
+                    // invoked after running a slice of tests
+                    sliceDone: generalParallelTest.sliceDone,
+                    // test cases, make them as granular as possible
+                    cases: {
+                        // test property values while transitioning
+                        // values.start kicks off a transition
+                        'values': {
+                            // run actual test, assertions can be used here!
+                            start: function(test, data, options) {
+                                // identify initial and target values
+                                generalParallelTest.getStyle(data);
+                                // make sure values differ, if they don't, the property could most likely not be parsed
+                                assert_not_equals(data.transition.from, data.transition.to, "initial and target values may not match");
+                                // kick off the transition
+                                generalParallelTest.startTransition(data);
+
+                                // make sure we didn't get the target value immediately.
+                                // If we did, there wouldn't be a transition!
+                                var current = data.transition.computedStyle(data.property);
+                                assert_not_equals(current, data.transition.to, "must not be target value after start");
+                            },
+                            done: function(test, data, options) {
+                                // make sure the property's value were neither initial nor target while transitioning
+                                test.step(generalParallelTest.assertIntermediateValuesFunc(data, 'transition'));
+                            }
+                        },
+                        // test TransitionEnd events
+                        'events': {
+                            done: function(test, data, options) {
+                                // make sure there were no events on parent
+                                test.step(generalParallelTest.assertExpectedEventsFunc(data, 'container', ""));
+                                // make sure we got the event for the tested property only
+                                test.step(generalParallelTest.assertExpectedEventsFunc(data, 'transition', addVendorPrefix(data.property) + ":" + duration));
+
+                                test.step(function() {
+                                    assert_false(isLoad, "load may not have happened yet")
+                                });
+                            }
+                        }
+                    },
+                    // called once all tests are done
+                    done: generalParallelTest.done
+                });
+            }, false);
+        </script>
+        <img src="/delay/?type=gif&amp;delay=3000" alt="dummy image">
+    </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/changing-while-transition.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/changing-while-transition.html
new file mode 100644
index 0000000..2e7d0bb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/changing-while-transition.html
@@ -0,0 +1,148 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>CSS Transitions Test: behavior when transition parameters change while transitioning</title>
+        <meta name="assert" content="Test checks that all transitions run properly when property or duration is changed mid-run">
+        <link rel="help" title="3. Starting of transitions" href="http://www.w3.org/TR/css3-transitions/#starting">
+        <link rel="author" title="Rodney Rehm" href="http://rodneyrehm.de/en/">
+        <meta name="flags" content="dom">
+
+        <script src="/resources/testharness.js" type="text/javascript"></script>
+        <script src="/resources/testharnessreport.js" type="text/javascript"></script>
+
+        <script src="./support/vendorPrefix.js" type="text/javascript"></script>
+        <script src="./support/helper.js" type="text/javascript"></script>
+        <script src="./support/runParallelAsyncHarness.js" type="text/javascript"></script>
+        <script src="./support/generalParallelTest.js" type="text/javascript"></script>
+
+        <style type="text/css">
+            #offscreen {
+                position: absolute;
+                top: -100000px;
+                left: -100000px;
+                width: 100000px;
+                height: 100000px;
+            }
+        </style>
+    </head>
+    <body>
+        <!-- required by testharnessreport.js -->
+        <div id="log"></div>
+        <!-- elements used for testing -->
+        <div id="fixture" class="fixture">
+            <div class="container">
+                <div class="transition">Text sample</div>
+            </div>
+        </div>
+        <div id="offscreen"></div>
+
+        <!--
+            SEE ./support/README.md for an abstract explanation of the test procedure
+            http://test.csswg.org/source/contributors/rodneyrehm/submitted/css3-transitions/README.md
+        -->
+
+        <script>
+            // this test takes its time, give it a minute to run
+            var timeout = 60000;
+            setup({timeout: timeout});
+
+            var tests = [
+                {
+                    name: "changing transition-duration",
+                    property: 'padding-left',
+                    transitions: 'padding-left .5s linear 0s',
+                    from: {'padding-left': '1px'},
+                    to: {'padding-left': '10px'},
+                    then: {
+                        'transition-duration': '0.1s'
+                    },
+                    expect: [
+                        'padding-left:0.5s'
+                    ]
+                },
+                {
+                    name: "changing transition-property",
+                    property: 'padding-left',
+                    transitions: 'padding-left .5s linear 0s',
+                    from: {'padding-left': '1px'},
+                    to: {'padding-left': '10px'},
+                    then: {
+                        'transition-property': 'margin-left'
+                    },
+                    expect: [
+                        ''
+                    ]
+                }
+            ];
+
+            // general transition-duration
+            var duration = '0.5s';
+
+            runParallelAsyncHarness({
+                // array of test data
+                tests: tests,
+                // the number of tests to run in parallel
+                testsPerSlice: 50,
+                // milliseconds to wait before calling teardown and ending test
+                duration: parseFloat(duration) * 1000,
+                // the global suite timeout
+                timeout: timeout,
+                // prepare individual test
+                setup: function(data, options) {
+                    var styles = {
+                        '.fixture': {},
+
+                        '.container': {},
+                        '.container.to': {},
+                        '.container.how': {},
+
+                        '.transition': data.from,
+                        '.transition.to' : data.to,
+                        '.transition.how' : {transition: data.transitions},
+                        '.transition.then' : data.then
+                    };
+
+                    generalParallelTest.setup(data, options);
+                    generalParallelTest.addStyles(data, options, styles);
+                },
+                // cleanup after individual test
+                teardown: generalParallelTest.teardown,
+                // invoked prior to running a slice of tests
+                sliceStart: generalParallelTest.sliceStart,
+                // invoked after running a slice of tests
+                sliceDone: generalParallelTest.sliceDone,
+                // test cases, make them as granular as possible
+                cases: {
+                    // test property values while transitioning
+                    // values.start kicks off a transition
+                    'values': {
+                        // run actual test, assertions can be used here!
+                        start: function(test, data, options) {
+                            // identify initial and target values
+                            generalParallelTest.getStyle(data);
+                            // kick off the transition
+                            generalParallelTest.startTransition(data);
+
+                            setTimeout(function() {
+                                data.transition.node.classList.add('then');
+
+                                for (var property in data.then) {
+                                    var current = data.transition.computedStyle(property);
+                                    assert_equals(current, data.then[property], 'value of ' + property + ' changed');
+                                }
+
+                            }, 50);
+                        },
+                        done: function(test, data, options) {
+                            // make sure we got the event for the tested property only
+                            test.step(generalParallelTest.assertExpectedEventsFunc(data, 'transition', data.expect));
+                        }
+                    }
+                },
+                // called once all tests are done
+                done: generalParallelTest.done
+            });
+        </script>
+    </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/currentcolor-animation-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/currentcolor-animation-001.html
new file mode 100644
index 0000000..e36e748
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/currentcolor-animation-001.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>CSS Variables Allowed Syntax</title>
+  <link rel="author" title="L. David Baron" href="https://dbaron.org/">
+  <link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+  <link rel="help" href="http://www.w3.org/TR/css3-transitions/#animatable-types">
+  <!-- also see https://www.w3.org/Bugs/Public/show_bug.cgi?id=14605 -->
+  <script src="/resources/testharness.js"></script>
+  <script src="/resources/testharnessreport.js"></script>
+<style id="style"></style>
+</head>
+<body onload="run()">
+<div id=log></div>
+<div id="test"></div>
+<script>
+
+test(function() {
+       var div = document.getElementById("test");
+       var cs = getComputedStyle(div, "");
+       div.style.color = "red";
+       div.style.backgroundColor = "currentcolor";
+       var force_flush = cs.backgroundColor;
+       div.style.transition = "background-color linear 50s -10s";
+       div.style.color = "blue";
+       var quarter_interpolated = cs.backgroundColor;
+       div.style.transition = "";
+       div.style.backgroundColor = "rgb(204, 0, 51)";
+       var quarter_reference = cs.backgroundColor;
+       div.style.backgroundColor = "blue";
+       var final_reference = cs.backgroundColor;
+       assert_true(quarter_interpolated != quarter_reference &&
+                   quarter_interpolated == final_reference);
+     },
+     "currentcolortransition",
+     { assert: "Transition does not occur when the value is currentColor and color changes" });
+
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/detached-container-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/detached-container-001.html
new file mode 100644
index 0000000..efbc34f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/detached-container-001.html
@@ -0,0 +1,133 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>CSS Transitions Test: Not Transitioning within detached element</title>
+        <meta name="assert" content="Test checks that transitions are NOT run within detached elements">
+        <link rel="help" title="2. Transitions" href="http://www.w3.org/TR/css3-transitions/#transitions">
+        <link rel="author" title="Rodney Rehm" href="http://rodneyrehm.de/en/">
+        <meta name="flags" content="dom">
+
+        <script src="/resources/testharness.js" type="text/javascript"></script>
+        <script src="/resources/testharnessreport.js" type="text/javascript"></script>
+
+        <script src="./support/vendorPrefix.js" type="text/javascript"></script>
+        <script src="./support/helper.js" type="text/javascript"></script>
+        <script src="./support/runParallelAsyncHarness.js" type="text/javascript"></script>
+        <script src="./support/generalParallelTest.js" type="text/javascript"></script>
+        <script src="./support/properties.js" type="text/javascript"></script>
+
+        <style type="text/css">
+            #offscreen {
+                position: absolute;
+                top: -100000px;
+                left: -100000px;
+                width: 100000px;
+                height: 100000px;
+            }
+        </style>
+    </head>
+    <body>
+        <!-- required by testharnessreport.js -->
+        <div id="log"></div>
+        <!-- elements used for testing -->
+        <div id="fixture" class="fixture">
+            <div class="container">
+                <div class="transition">Text sample</div>
+            </div>
+        </div>
+        <div id="off-screen"></div>
+
+        <!--
+            SEE ./support/README.md for an abstract explanation of the test procedure
+            http://test.csswg.org/source/contributors/rodneyrehm/submitted/css3-transitions/README.md
+        -->
+
+        <script>
+
+            // this test takes its time, give it a minute to run
+            var timeout = 60000;
+            setup({timeout: timeout});
+
+            var tests = [
+                {
+                    name: "transition within detached container",
+                    property: 'background-color',
+                    flags: {},
+                    from: {'background-color': 'red'},
+                    to: {'background-color': 'green'}
+                }
+            ];
+
+            // general transition-duration
+            var duration = '0.5s';
+
+            runParallelAsyncHarness({
+                // array of test data
+                tests: tests,
+                // the number of tests to run in parallel
+                testsPerSlice: 1,
+                // milliseconds to wait before calling teardown and ending test
+                duration: parseFloat(duration) * 1000,
+                // the global suite timeout
+                timeout: timeout,
+                // prepare individual test
+                setup: function(data, options) {
+                    var styles = {
+                        '.fixture': {},
+
+                        '.container': data.parentStyle,
+                        '.container.to': {},
+                        '.container.how': {},
+
+                        '.transition': data.from,
+                        '.transition.to' : data.to,
+                        '.transition.how' : {transition: 'all ' + duration + ' linear 0s'}
+                    };
+
+                    generalParallelTest.setup(data, options);
+                    generalParallelTest.addStyles(data, options, styles);
+                },
+                // cleanup after individual test
+                teardown: generalParallelTest.teardown,
+                // invoked prior to running a slice of tests
+                sliceStart: generalParallelTest.sliceStart,
+                // invoked after running a slice of tests
+                sliceDone: generalParallelTest.sliceDone,
+                // test cases, make them as granular as possible
+                cases: {
+                    // test property values while transitioning
+                    // values.start kicks off a transition
+                    'values': {
+                        // run actual test, assertions can be used here!
+                        start: function(test, data, options) {
+                            // identify initial and target values
+                            generalParallelTest.getStyle(data);
+                            // make sure values differ, if they don't, the property could most likely not be parsed
+                            assert_not_equals(data.transition.from, data.transition.to, "initial and target values may not match");
+                            // detach transitioning elements
+                            data.fixture.parentNode.removeChild(data.fixture);
+                            // kick off the transition
+                            generalParallelTest.startTransition(data);
+                        },
+                        done: function(test, data, options) {
+                            // make sure there were no intermediate values
+                            assert_equals(data.transition.values.length, 2, "no intermediate values");
+                        }
+                    },
+                    // test TransitionEnd events
+                    'events': {
+                        done: function(test, data, options) {
+                            // make sure there were no events on parent
+                            test.step(generalParallelTest.assertExpectedEventsFunc(data, 'container', ""));
+                            // make sure we got the event for the tested property only
+                            test.step(generalParallelTest.assertExpectedEventsFunc(data, 'transition', ""));
+                        }
+                    }
+                },
+                // called once all tests are done
+                done: generalParallelTest.done
+            });
+        </script>
+    </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/events-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/events-001.html
new file mode 100644
index 0000000..59d2011
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/events-001.html
@@ -0,0 +1,150 @@
+<!doctype html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>CSS Transitions Test: transitionend event for shorthand property</title>
+<meta name="assert" content="This test checks that all transitionend events are triggered for shorthand property">
+<link rel="help" href="http://www.w3.org/TR/css3-transitions/#transition-property-property">
+<link rel="help" href="http://www.w3.org/TR/css3-transitions/#transition-events">
+<link rel="author" title="Rodney Rehm" href="http://rodneyrehm.de/en/">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="./support/helper.js"></script>
+
+</head>
+<body>
+
+<script>
+promise_test(t => {
+  const div = addDiv(t, { style: 'transition: all .01s linear; ' +
+                                 'padding-left: 1px' });
+  getComputedStyle(div).paddingLeft;
+  div.style.paddingLeft = '10px';
+
+  const watcher = new EventWatcher(t, div, [ 'transitionend' ]);
+  return watcher.wait_for('transitionend').then(evt => {
+    assert_end_events_equal(evt, 'padding-left', 0.01);
+  });
+}, 'transition:all changing padding-left');
+
+promise_test(t => {
+  const div = addDiv(t, { style: 'transition: all .01s linear; ' +
+                                 'padding: 1px' });
+  getComputedStyle(div).paddingLeft;
+  div.style.padding = '10px';
+
+  const watcher = new EventWatcher(t, div, [ 'transitionend' ]);
+  return watcher.wait_for(Array(4).fill('transitionend'),
+                          { record: 'all' }).then(evts => {
+    assert_end_event_batch_equal(evts,
+                                 [ 'padding-bottom',
+                                   'padding-left',
+                                   'padding-right',
+                                   'padding-top' ],
+                                 0.01);
+  });
+}, 'transition:all changing padding');
+
+promise_test(t => {
+  const div = addDiv(t, { style: 'transition: all .01s linear; ' +
+                                 'padding: 1px' });
+  getComputedStyle(div).paddingLeft;
+  div.style.padding = '10px 10px 1px 10px';
+
+  const watcher = new EventWatcher(t, div, [ 'transitionend' ]);
+  return watcher.wait_for(Array(3).fill('transitionend'),
+                          { record: 'all' }).then(evts => {
+    assert_end_event_batch_equal(evts,
+                                 [ 'padding-left',
+                                   'padding-right',
+                                   'padding-top' ],
+                                 0.01);
+  });
+}, 'transition:all changing padding but not padding-bottom');
+
+promise_test(t => {
+  const div = addDiv(t, { style: 'transition: padding .01s linear; ' +
+                                 'padding-left: 1px' });
+  getComputedStyle(div).paddingLeft;
+  div.style.paddingLeft = '10px';
+
+  const watcher = new EventWatcher(t, div, [ 'transitionend' ]);
+  return watcher.wait_for('transitionend').then(evt => {
+    assert_end_events_equal(evt, 'padding-left', 0.01);
+  });
+}, 'transition:padding changing padding-left');
+
+promise_test(t => {
+  const div = addDiv(t, { style: 'transition: padding .01s linear; ' +
+                                 'padding: 1px' });
+  getComputedStyle(div).paddingLeft;
+  div.style.padding = '10px';
+
+  const watcher = new EventWatcher(t, div, [ 'transitionend' ]);
+  return watcher.wait_for(Array(4).fill('transitionend'),
+                          { record: 'all' }).then(evts => {
+    assert_end_event_batch_equal(evts,
+                                 [ 'padding-bottom',
+                                   'padding-left',
+                                   'padding-right',
+                                   'padding-top' ],
+                                 0.01);
+  });
+}, 'transition:padding changing padding');
+
+promise_test(t => {
+  const div = addDiv(t, { style: 'transition: padding .01s linear; ' +
+                                 'padding: 1px' });
+  getComputedStyle(div).paddingLeft;
+  div.style.padding = '10px 10px 1px 10px';
+
+  const watcher = new EventWatcher(t, div, [ 'transitionend' ]);
+  return watcher.wait_for(Array(3).fill('transitionend'),
+                          { record: 'all' }).then(evts => {
+    assert_end_event_batch_equal(evts,
+                                 [ 'padding-left',
+                                   'padding-right',
+                                   'padding-top' ],
+                                 0.01);
+  });
+}, 'transition:padding changing padding but not padding-bottom');
+
+promise_test(t => {
+  const div = addDiv(t, { style: 'transition: padding-left .01s linear; ' +
+                                 'padding-left: 1px' });
+  getComputedStyle(div).paddingLeft;
+  div.style.paddingLeft = '10px';
+
+  const watcher = new EventWatcher(t, div, [ 'transitionend' ]);
+  return watcher.wait_for('transitionend').then(evt => {
+    assert_end_events_equal(evt, 'padding-left', 0.01);
+  });
+}, 'transition:padding-left changing padding-left');
+
+promise_test(t => {
+  const div = addDiv(t, { style: 'transition: padding-left .01s linear; ' +
+                                 'padding: 1px' });
+  getComputedStyle(div).paddingLeft;
+  div.style.padding = '10px';
+
+  const watcher = new EventWatcher(t, div, [ 'transitionend' ]);
+  return watcher.wait_for('transitionend').then(evt => {
+    assert_end_events_equal(evt, 'padding-left', 0.01);
+  });
+}, 'transition:padding-left changing padding');
+
+promise_test(t => {
+  const div = addDiv(t, { style: 'transition: padding-left .01s linear; ' +
+                                 'padding: 1px' });
+  getComputedStyle(div).paddingLeft;
+  div.style.padding = '10px 10px 1px 10px';
+
+  const watcher = new EventWatcher(t, div, [ 'transitionend' ]);
+  return watcher.wait_for('transitionend').then(evt => {
+    assert_end_events_equal(evt, 'padding-left', 0.01);
+  });
+}, 'transition:padding-left changing padding but not padding-bottom');
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/events-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/events-002.html
new file mode 100644
index 0000000..3ec2cc3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/events-002.html
@@ -0,0 +1,49 @@
+<!doctype html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>CSS Transitions Test: transitionend event for implied property value</title>
+<meta name="assert" content="Test checks that all transitionend events are triggered for implied property value">
+<link rel="help" title="5. Transition Events" href="http://www.w3.org/TR/css3-transitions/#transition-events">
+<link rel="author" title="Rodney Rehm" href="http://rodneyrehm.de/en/">
+
+<script src="/resources/testharness.js" type="text/javascript"></script>
+<script src="/resources/testharnessreport.js" type="text/javascript"></script>
+<script src="./support/helper.js" type="text/javascript"></script>
+
+</head>
+<body>
+
+<div id="log"></div>
+
+<script>
+promise_test(t => {
+  const div = addDiv(t, { style: 'transition: all .01s linear' });
+  getComputedStyle(div).paddingLeft;
+  div.style.paddingLeft = '10px';
+
+  const watcher = new EventWatcher(t, div, [ 'transitionend' ]);
+  return watcher.wait_for('transitionend').then(evt => {
+    assert_end_events_equal(evt, 'padding-left', 0.01);
+  });
+}, 'transition:all changing padding-left from nothing');
+
+promise_test(t => {
+  const div = addDiv(t, { style: 'transition: all .01s linear' });
+  getComputedStyle(div).paddingLeft;
+  div.style.padding = '10px';
+
+  const watcher = new EventWatcher(t, div, [ 'transitionend' ]);
+  return watcher.wait_for(Array(4).fill('transitionend'),
+                          { record: 'all' }).then(evts => {
+    assert_end_event_batch_equal(evts,
+                                 [ 'padding-bottom',
+                                   'padding-left',
+                                   'padding-right',
+                                   'padding-top' ],
+                                 0.01);
+  });
+}, 'transition:all changing padding from nothing');
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/events-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/events-003.html
new file mode 100644
index 0000000..2f8ac7f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/events-003.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>CSS Transitions Test: transitionend event with negative delay</title>
+<meta name="assert" content="Test checks that transitionend event is triggered for duration time being canceled out by negative delay">
+<link rel="help" title="2.4. The 'transition-delay' Property" href="http://www.w3.org/TR/css3-transitions/#transition-delay-property">
+<link rel="help" title="5. Transition Events" href="http://www.w3.org/TR/css3-transitions/#transition-events">
+<link rel="author" title="Rodney Rehm" href="http://rodneyrehm.de/en/">
+
+<script src="/resources/testharness.js" type="text/javascript"></script>
+<script src="/resources/testharnessreport.js" type="text/javascript"></script>
+<script src="./support/helper.js" type="text/javascript"></script>
+
+</head>
+<body>
+
+<div id="log"></div>
+
+<script>
+promise_test(t => {
+  const div = addDiv(t, { style: 'transition: all .02s -.01s; ' +
+                                 'padding-left: 1px' });
+  getComputedStyle(div).paddingLeft;
+  div.style.paddingLeft = '10px';
+
+  const watcher = new EventWatcher(t, div, [ 'transitionend' ]);
+  return watcher.wait_for('transitionend').then(evt => {
+    assert_end_events_equal(evt, 'padding-left', 0.02);
+  });
+}, 'duration: 0.02s, delay: -0.01s');
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/events-004-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/events-004-expected.txt
new file mode 100644
index 0000000..48c7fc8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/events-004-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+FAIL repeating lists assert_approx_equals: expected 0.02 +/- 0.0005 but got 0.03
+FAIL truncating lists assert_approx_equals: expected 0.02 +/- 0.0005 but got 0.03
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/events-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/events-004.html
new file mode 100644
index 0000000..17195f4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/events-004.html
@@ -0,0 +1,61 @@
+<!doctype html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>CSS Transitions Test: transitionend event with non matching lists</title>
+<meta name="assert" content="Test checks that non-matching lists are properly resolved">
+<link rel="help" title="2. Transitions - Example 3" href="http://www.w3.org/TR/css3-transitions/#list-matching">
+<link rel="help" title="5. Transition Events" href="http://www.w3.org/TR/css3-transitions/#transition-events">
+<link rel="author" title="Rodney Rehm" href="http://rodneyrehm.de/en/">
+
+<script src="/resources/testharness.js" type="text/javascript"></script>
+<script src="/resources/testharnessreport.js" type="text/javascript"></script>
+<script src="./support/helper.js" type="text/javascript"></script>
+
+</head>
+<body>
+
+<div id="log"></div>
+
+<script>
+promise_test(t => {
+  const div = addDiv(t, { style: 'padding: 1px' });
+  getComputedStyle(div).paddingLeft;
+
+  div.style.transitionProperty =
+    'padding-top, padding-right, padding-bottom, padding-left';
+  div.style.transitionDuration = '0.02s, 0.01s';
+  div.style.transitionTimingFunction = 'linear, ease-in';
+  div.style.transitionDelay = '0.01s, 0.02s';
+  div.style.padding = '10px';
+
+  const watcher = new EventWatcher(t, div, ['transitionend']);
+  return watcher
+    .wait_for(Array(4).fill('transitionend'), { record: 'all' })
+    .then(evts => {
+      assert_end_event_batch_equal(
+        evts,
+        [ 'padding-top', 'padding-right', 'padding-bottom', 'padding-left' ],
+        [ 0.02, 0.01, 0.02, 0.01 ]
+      );
+    });
+}, 'repeating lists');
+
+promise_test(t => {
+  const div = addDiv(t, { style: 'padding: 1px' });
+  getComputedStyle(div).paddingLeft;
+
+  div.style.transitionProperty = 'padding-top';
+  div.style.transitionDuration = '0.02s, 0.01s';
+  div.style.transitionTimingFunction = 'linear, ease-in';
+  div.style.transitionDelay = '0.01s, 0.02s';
+  div.style.padding = '10px';
+
+  const watcher = new EventWatcher(t, div, [ 'transitionend' ]);
+  return watcher.wait_for('transitionend').then(evt => {
+    assert_end_events_equal(evt, 'padding-top', 0.02);
+  });
+}, 'truncating lists');
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/events-005.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/events-005.html
new file mode 100644
index 0000000..48ba63a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/events-005.html
@@ -0,0 +1,67 @@
+<!doctype html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>CSS Transitions Test: transitionend event with property specificity</title>
+<meta name="assert" content="Test checks that property specificity is properly resolved">
+<link rel="help" title="2.1. The 'transition-property' Property" href="http://www.w3.org/TR/css3-transitions/#transition-property-property">
+<link rel="help" title="5. Transition Events" href="http://www.w3.org/TR/css3-transitions/#transition-events">
+<link rel="author" title="Rodney Rehm" href="http://rodneyrehm.de/en/">
+
+<script src="/resources/testharness.js" type="text/javascript"></script>
+<script src="/resources/testharnessreport.js" type="text/javascript"></script>
+<script src="./support/helper.js" type="text/javascript"></script>
+
+</head>
+<body>
+
+<div id="log"></div>
+
+<script>
+promise_test(t => {
+  const div = addDiv(t, {
+    style:
+      'transition: padding-left .01s, padding-left .02s;' +
+      'padding-left: 1px'
+  });
+  getComputedStyle(div).paddingLeft;
+  div.style.paddingLeft = '10px';
+
+  const watcher = new EventWatcher(t, div, [ 'transitionend' ]);
+  return watcher.wait_for('transitionend').then(evt => {
+    assert_end_events_equal(evt, 'padding-left', 0.02);
+  });
+}, 'property repetition');
+
+promise_test(t => {
+  const div = addDiv(t, {
+    style:
+      'transition: padding .01s, padding-left .02s;' +
+      'padding-left: 1px'
+  });
+  getComputedStyle(div).paddingLeft;
+  div.style.paddingLeft = '10px';
+
+  const watcher = new EventWatcher(t, div, [ 'transitionend' ]);
+  return watcher.wait_for('transitionend').then(evt => {
+    assert_end_events_equal(evt, 'padding-left', 0.02);
+  });
+}, 'padding, padding-left');
+
+promise_test(t => {
+  const div = addDiv(t, {
+    style:
+      'transition: padding-left .01s, padding .02s;' +
+      'padding-left: 1px'
+  });
+  getComputedStyle(div).paddingLeft;
+  div.style.paddingLeft = '10px';
+
+  const watcher = new EventWatcher(t, div, [ 'transitionend' ]);
+  return watcher.wait_for('transitionend').then(evt => {
+    assert_end_events_equal(evt, 'padding-left', 0.02);
+  });
+}, 'padding-left, padding');
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/events-006.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/events-006.html
new file mode 100644
index 0000000..36412bc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/events-006.html
@@ -0,0 +1,58 @@
+<!doctype html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>CSS Transitions Test: transitionend event for pseudo elements</title>
+<meta name="assert" content="Test checks that TransitionEnd events are fired for pseudo-elements">
+<link rel="help" title="5. Transition Events" href="http://www.w3.org/TR/css3-transitions/#transition-events">
+<link rel="help" title="CSS21 - 12.1 The :before and :after pseudo-elements" href="http://www.w3.org/TR/CSS21/generate.html#before-after-content">
+<link rel="help" title="CSS3 Generated and Replaced Content Module" href="http://www.w3.org/TR/css3-content/">
+<link rel="author" title="Rodney Rehm" href="http://rodneyrehm.de/en/">
+
+<script src="/resources/testharness.js" type="text/javascript"></script>
+<script src="/resources/testharnessreport.js" type="text/javascript"></script>
+<script src="./support/helper.js" type="text/javascript"></script>
+
+<style>
+.before::before,
+.after:after {
+  content: '';
+  transition: padding-left .01s;
+  padding-left: 1px;
+}
+.before.active::before,
+.after.active:after {
+  padding-left: 10px;
+}
+</style>
+
+</head>
+<body>
+
+<div id="log"></div>
+
+<script>
+promise_test(t => {
+  const div = addDiv(t, { 'class': 'before' });
+  getComputedStyle(div).paddingLeft;
+  div.classList.add('active');
+
+  const watcher = new EventWatcher(t, div, [ 'transitionend' ]);
+  return watcher.wait_for('transitionend').then(evt => {
+    assert_end_events_equal(evt, 'padding-left', 0.01, '::before');
+  });
+}, 'transition padding-left on ::before');
+
+promise_test(t => {
+  const div = addDiv(t, { 'class': 'after' });
+  getComputedStyle(div).paddingLeft;
+  div.classList.add('active');
+
+  const watcher = new EventWatcher(t, div, [ 'transitionend' ]);
+  return watcher.wait_for('transitionend').then(evt => {
+    assert_end_events_equal(evt, 'padding-left', 0.01, '::after');
+  });
+}, 'transition padding-left on ::after');
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/events-007.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/events-007.html
new file mode 100644
index 0000000..610df6e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/events-007.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Transitions Test: no transitionend event after display:none</title>
+<link rel="author" title="Chris Rebert" href="http://chrisrebert.com">
+<link rel="help" href="http://www.w3.org/TR/css3-transitions/#transition-events">
+<link rel="help" href="https://lists.w3.org/Archives/Public/www-style/2015Apr/0405.html" title="[CSSWG] Minutes Telecon 2015-04-29" data-section-title="AnimationEnd events and display: none">
+<meta name="assert" content="Making an element display:none; while it has a transition in progress should prevent a transitionend event from getting fired.">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="./support/helper.js" type="text/javascript"></script>
+
+</head>
+<body>
+
+<div id="log"></div>
+
+<script>
+async_test(t => {
+  window.addEventListener('load', function () {
+    const div = addDiv(t, { 'style': 'transition: background-color 0.4s;' +
+                                     'background-color: red' });
+    getComputedStyle(div).backgroundColor;
+    div.style.backgroundColor = 'blue';
+
+    // Wait until the transition has started before registering the event
+    // listener. That way, if the transition finishes before the
+    // requestAnimationFrame callback is called and the element is made
+    // display:none, we won't report an error if transitionend is dispatched.
+    //
+    // In that case, there will be no indication that the test didn't test
+    // anything. However, that's preferable to having this test fail
+    // intermittently on slower automation hardware and end up being disabled
+    // as a result.
+    requestAnimationFrame(t.step_func(() => {
+      div.addEventListener('transitionend', t.step_func(() => {
+        assert_unreached('transitionend event didn\'t fire');
+      }), false);
+
+      div.style.display = 'none';
+
+      setTimeout(t.done.bind(t), 500);
+    }));
+  }, false);
+}, 'transitionend should not be fired if the element is made display:none during the transition');
+</script>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/hidden-container-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/hidden-container-001.html
new file mode 100644
index 0000000..4d17d4a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/hidden-container-001.html
@@ -0,0 +1,127 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>CSS Transitions Test: Not Transitioning within hidden element</title>
+        <meta name="assert" content="Test checks that transitions are NOT run within hidden elements">
+        <link rel="help" title="2. Transitions" href="http://www.w3.org/TR/css3-transitions/#transitions">
+        <link rel="author" title="Rodney Rehm" href="http://rodneyrehm.de/en/">
+        <meta name="flags" content="dom">
+
+        <script src="/resources/testharness.js" type="text/javascript"></script>
+        <script src="/resources/testharnessreport.js" type="text/javascript"></script>
+
+        <script src="./support/vendorPrefix.js" type="text/javascript"></script>
+        <script src="./support/helper.js" type="text/javascript"></script>
+        <script src="./support/runParallelAsyncHarness.js" type="text/javascript"></script>
+        <script src="./support/generalParallelTest.js" type="text/javascript"></script>
+        <script src="./support/properties.js" type="text/javascript"></script>
+
+        <style type="text/css">
+            #offscreen {
+                display: none;
+            }
+        </style>
+    </head>
+    <body>
+        <!-- required by testharnessreport.js -->
+        <div id="log"></div>
+        <!-- elements used for testing -->
+        <div id="fixture" class="fixture">
+            <div class="container">
+                <div class="transition">Text sample</div>
+            </div>
+        </div>
+        <div id="offscreen"></div>
+
+        <!--
+            SEE ./support/README.md for an abstract explanation of the test procedure
+            http://test.csswg.org/source/contributors/rodneyrehm/submitted/css3-transitions/README.md
+        -->
+
+        <script>
+
+            // this test takes its time, give it a minute to run
+            var timeout = 60000;
+            setup({timeout: timeout});
+
+            var tests = [
+                {
+                    name: "transition within display:none",
+                    property: 'background-color',
+                    flags: {},
+                    from: {'background-color': 'red'},
+                    to: {'background-color': 'green'}
+                }
+            ];
+
+            // general transition-duration
+            var duration = '0.5s';
+
+            runParallelAsyncHarness({
+                // array of test data
+                tests: tests,
+                // the number of tests to run in parallel
+                testsPerSlice: 1,
+                // milliseconds to wait before calling teardown and ending test
+                duration: parseFloat(duration) * 1000,
+                // the global suite timeout
+                timeout: timeout,
+                // prepare individual test
+                setup: function(data, options) {
+                    var styles = {
+                        '.fixture': {},
+
+                        '.container': data.parentStyle,
+                        '.container.to': {},
+                        '.container.how': {},
+
+                        '.transition': data.from,
+                        '.transition.to' : data.to,
+                        '.transition.how' : {transition: 'all ' + duration + ' linear 0s'}
+                    };
+
+                    generalParallelTest.setup(data, options);
+                    generalParallelTest.addStyles(data, options, styles);
+                },
+                // cleanup after individual test
+                teardown: generalParallelTest.teardown,
+                // invoked prior to running a slice of tests
+                sliceStart: generalParallelTest.sliceStart,
+                // invoked after running a slice of tests
+                sliceDone: generalParallelTest.sliceDone,
+                // test cases, make them as granular as possible
+                cases: {
+                    // test property values while transitioning
+                    // values.start kicks off a transition
+                    'values': {
+                        // run actual test, assertions can be used here!
+                        start: function(test, data, options) {
+                            // identify initial and target values
+                            generalParallelTest.getStyle(data);
+                            // make sure values differ, if they don't, the property could most likely not be parsed
+                            assert_not_equals(data.transition.from, data.transition.to, "initial and target values may not match");
+                            // kick off the transition
+                            generalParallelTest.startTransition(data);
+                        },
+                        done: function(test, data, options) {
+                            // make sure there were no intermediate values
+                            assert_equals(data.transition.values.length, 2, "no intermediate values");
+                        }
+                    },
+                    // test TransitionEnd events
+                    'events': {
+                        done: function(test, data, options) {
+                            // make sure there were no events on parent
+                            test.step(generalParallelTest.assertExpectedEventsFunc(data, 'container', ""));
+                            // make sure we got the event for the tested property only
+                            test.step(generalParallelTest.assertExpectedEventsFunc(data, 'transition', ""));
+                        }
+                    }
+                },
+                // called once all tests are done
+                done: generalParallelTest.done
+            });
+        </script>
+    </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-001-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-001-expected.txt
new file mode 100644
index 0000000..e7f8cfe
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-001-expected.txt
@@ -0,0 +1,566 @@
+This is a testharness.js-based test.
+Found 562 tests; 549 PASS, 13 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS background-color color(rgba) / values
+PASS background-color color(rgba) / events
+PASS background-position length(pt) / values
+FAIL background-position length(pt) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "background-position:0.5s" but got "background-position-x:0.5s"
+PASS background-position length(pc) / values
+FAIL background-position length(pc) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "background-position:0.5s" but got "background-position-x:0.5s"
+PASS background-position length(px) / values
+FAIL background-position length(px) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "background-position:0.5s" but got "background-position-x:0.5s"
+PASS background-position length(em) / values
+FAIL background-position length(em) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "background-position:0.5s" but got "background-position-x:0.5s"
+PASS background-position length(ex) / values
+FAIL background-position length(ex) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "background-position:0.5s" but got "background-position-x:0.5s"
+PASS background-position length(mm) / values
+FAIL background-position length(mm) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "background-position:0.5s" but got "background-position-x:0.5s"
+PASS background-position length(cm) / values
+FAIL background-position length(cm) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "background-position:0.5s" but got "background-position-x:0.5s"
+PASS background-position length(in) / values
+FAIL background-position length(in) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "background-position:0.5s" but got "background-position-x:0.5s"
+PASS background-position percentage(%) / values
+FAIL background-position percentage(%) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "background-position:0.5s" but got "background-position-x:0.5s"
+PASS border-top-width length(pt) / values
+PASS border-top-width length(pt) / events
+PASS border-top-width length(pc) / values
+PASS border-top-width length(pc) / events
+PASS border-top-width length(px) / values
+PASS border-top-width length(px) / events
+PASS border-top-width length(em) / values
+PASS border-top-width length(em) / events
+PASS border-top-width length(ex) / values
+PASS border-top-width length(ex) / events
+PASS border-top-width length(mm) / values
+PASS border-top-width length(mm) / events
+PASS border-top-width length(cm) / values
+PASS border-top-width length(cm) / events
+PASS border-top-width length(in) / values
+PASS border-top-width length(in) / events
+PASS border-right-width length(pt) / values
+PASS border-right-width length(pt) / events
+PASS border-right-width length(pc) / values
+PASS border-right-width length(pc) / events
+PASS border-right-width length(px) / values
+PASS border-right-width length(px) / events
+PASS border-right-width length(em) / values
+PASS border-right-width length(em) / events
+PASS border-right-width length(ex) / values
+PASS border-right-width length(ex) / events
+PASS border-right-width length(mm) / values
+PASS border-right-width length(mm) / events
+PASS border-right-width length(cm) / values
+PASS border-right-width length(cm) / events
+PASS border-right-width length(in) / values
+PASS border-right-width length(in) / events
+PASS border-bottom-width length(pt) / values
+PASS border-bottom-width length(pt) / events
+PASS border-bottom-width length(pc) / values
+PASS border-bottom-width length(pc) / events
+PASS border-bottom-width length(px) / values
+PASS border-bottom-width length(px) / events
+PASS border-bottom-width length(em) / values
+PASS border-bottom-width length(em) / events
+PASS border-bottom-width length(ex) / values
+PASS border-bottom-width length(ex) / events
+PASS border-bottom-width length(mm) / values
+PASS border-bottom-width length(mm) / events
+PASS border-bottom-width length(cm) / values
+PASS border-bottom-width length(cm) / events
+PASS border-bottom-width length(in) / values
+PASS border-bottom-width length(in) / events
+PASS border-left-width length(pt) / values
+PASS border-left-width length(pt) / events
+PASS border-left-width length(pc) / values
+PASS border-left-width length(pc) / events
+PASS border-left-width length(px) / values
+PASS border-left-width length(px) / events
+PASS border-left-width length(em) / values
+PASS border-left-width length(em) / events
+PASS border-left-width length(ex) / values
+PASS border-left-width length(ex) / events
+PASS border-left-width length(mm) / values
+PASS border-left-width length(mm) / events
+PASS border-left-width length(cm) / values
+PASS border-left-width length(cm) / events
+PASS border-left-width length(in) / values
+PASS border-left-width length(in) / events
+PASS border-top-color color(rgba) / values
+PASS border-top-color color(rgba) / events
+PASS border-right-color color(rgba) / values
+PASS border-right-color color(rgba) / events
+PASS border-bottom-color color(rgba) / values
+PASS border-bottom-color color(rgba) / events
+PASS border-left-color color(rgba) / values
+PASS border-left-color color(rgba) / events
+PASS padding-bottom length(pt) / values
+PASS padding-bottom length(pt) / events
+PASS padding-bottom length(pc) / values
+PASS padding-bottom length(pc) / events
+PASS padding-bottom length(px) / values
+PASS padding-bottom length(px) / events
+PASS padding-bottom length(em) / values
+PASS padding-bottom length(em) / events
+PASS padding-bottom length(ex) / values
+PASS padding-bottom length(ex) / events
+PASS padding-bottom length(mm) / values
+PASS padding-bottom length(mm) / events
+PASS padding-bottom length(cm) / values
+PASS padding-bottom length(cm) / events
+PASS padding-bottom length(in) / values
+PASS padding-bottom length(in) / events
+PASS padding-left length(pt) / values
+PASS padding-left length(pt) / events
+PASS padding-left length(pc) / values
+PASS padding-left length(pc) / events
+PASS padding-left length(px) / values
+PASS padding-left length(px) / events
+PASS padding-left length(em) / values
+PASS padding-left length(em) / events
+PASS padding-left length(ex) / values
+PASS padding-left length(ex) / events
+PASS padding-left length(mm) / values
+PASS padding-left length(mm) / events
+PASS padding-left length(cm) / values
+PASS padding-left length(cm) / events
+PASS padding-left length(in) / values
+PASS padding-left length(in) / events
+PASS padding-right length(pt) / values
+PASS padding-right length(pt) / events
+PASS padding-right length(pc) / values
+PASS padding-right length(pc) / events
+PASS padding-right length(px) / values
+PASS padding-right length(px) / events
+PASS padding-right length(em) / values
+PASS padding-right length(em) / events
+PASS padding-right length(ex) / values
+PASS padding-right length(ex) / events
+PASS padding-right length(mm) / values
+PASS padding-right length(mm) / events
+PASS padding-right length(cm) / values
+PASS padding-right length(cm) / events
+PASS padding-right length(in) / values
+PASS padding-right length(in) / events
+PASS padding-top length(pt) / values
+PASS padding-top length(pt) / events
+PASS padding-top length(pc) / values
+PASS padding-top length(pc) / events
+PASS padding-top length(px) / values
+PASS padding-top length(px) / events
+PASS padding-top length(em) / values
+PASS padding-top length(em) / events
+PASS padding-top length(ex) / values
+PASS padding-top length(ex) / events
+PASS padding-top length(mm) / values
+PASS padding-top length(mm) / events
+PASS padding-top length(cm) / values
+PASS padding-top length(cm) / events
+PASS padding-top length(in) / values
+PASS padding-top length(in) / events
+PASS margin-bottom length(pt) / values
+PASS margin-bottom length(pt) / events
+PASS margin-bottom length(pc) / values
+PASS margin-bottom length(pc) / events
+PASS margin-bottom length(px) / values
+PASS margin-bottom length(px) / events
+PASS margin-bottom length(em) / values
+PASS margin-bottom length(em) / events
+PASS margin-bottom length(ex) / values
+PASS margin-bottom length(ex) / events
+PASS margin-bottom length(mm) / values
+PASS margin-bottom length(mm) / events
+PASS margin-bottom length(cm) / values
+PASS margin-bottom length(cm) / events
+PASS margin-bottom length(in) / values
+PASS margin-bottom length(in) / events
+PASS margin-left length(pt) / values
+PASS margin-left length(pt) / events
+PASS margin-left length(pc) / values
+PASS margin-left length(pc) / events
+PASS margin-left length(px) / values
+PASS margin-left length(px) / events
+PASS margin-left length(em) / values
+PASS margin-left length(em) / events
+PASS margin-left length(ex) / values
+PASS margin-left length(ex) / events
+PASS margin-left length(mm) / values
+PASS margin-left length(mm) / events
+PASS margin-left length(cm) / values
+PASS margin-left length(cm) / events
+PASS margin-left length(in) / values
+PASS margin-left length(in) / events
+PASS margin-right length(pt) / values
+PASS margin-right length(pt) / events
+PASS margin-right length(pc) / values
+PASS margin-right length(pc) / events
+PASS margin-right length(px) / values
+PASS margin-right length(px) / events
+PASS margin-right length(em) / values
+PASS margin-right length(em) / events
+PASS margin-right length(ex) / values
+PASS margin-right length(ex) / events
+PASS margin-right length(mm) / values
+PASS margin-right length(mm) / events
+PASS margin-right length(cm) / values
+PASS margin-right length(cm) / events
+PASS margin-right length(in) / values
+PASS margin-right length(in) / events
+PASS margin-top length(pt) / values
+PASS margin-top length(pt) / events
+PASS margin-top length(pc) / values
+PASS margin-top length(pc) / events
+PASS margin-top length(px) / values
+PASS margin-top length(px) / events
+PASS margin-top length(em) / values
+PASS margin-top length(em) / events
+PASS margin-top length(ex) / values
+PASS margin-top length(ex) / events
+PASS margin-top length(mm) / values
+PASS margin-top length(mm) / events
+PASS margin-top length(cm) / values
+PASS margin-top length(cm) / events
+PASS margin-top length(in) / values
+PASS margin-top length(in) / events
+PASS height length(pt) / values
+PASS height length(pt) / events
+PASS height length(pc) / values
+PASS height length(pc) / events
+PASS height length(px) / values
+PASS height length(px) / events
+PASS height length(em) / values
+PASS height length(em) / events
+PASS height length(ex) / values
+PASS height length(ex) / events
+PASS height length(mm) / values
+PASS height length(mm) / events
+PASS height length(cm) / values
+PASS height length(cm) / events
+PASS height length(in) / values
+PASS height length(in) / events
+PASS height percentage(%) / values
+PASS height percentage(%) / events
+PASS width length(pt) / values
+PASS width length(pt) / events
+PASS width length(pc) / values
+PASS width length(pc) / events
+PASS width length(px) / values
+PASS width length(px) / events
+PASS width length(em) / values
+PASS width length(em) / events
+PASS width length(ex) / values
+PASS width length(ex) / events
+PASS width length(mm) / values
+PASS width length(mm) / events
+PASS width length(cm) / values
+PASS width length(cm) / events
+PASS width length(in) / values
+PASS width length(in) / events
+PASS width percentage(%) / values
+PASS width percentage(%) / events
+PASS min-height length(pt) / values
+PASS min-height length(pt) / events
+PASS min-height length(pc) / values
+PASS min-height length(pc) / events
+PASS min-height length(px) / values
+PASS min-height length(px) / events
+PASS min-height length(em) / values
+PASS min-height length(em) / events
+PASS min-height length(ex) / values
+PASS min-height length(ex) / events
+PASS min-height length(mm) / values
+PASS min-height length(mm) / events
+PASS min-height length(cm) / values
+PASS min-height length(cm) / events
+PASS min-height length(in) / values
+PASS min-height length(in) / events
+PASS min-height percentage(%) / values
+PASS min-height percentage(%) / events
+PASS min-width length(pt) / values
+PASS min-width length(pt) / events
+PASS min-width length(pc) / values
+PASS min-width length(pc) / events
+PASS min-width length(px) / values
+PASS min-width length(px) / events
+PASS min-width length(em) / values
+PASS min-width length(em) / events
+PASS min-width length(ex) / values
+PASS min-width length(ex) / events
+PASS min-width length(mm) / values
+PASS min-width length(mm) / events
+PASS min-width length(cm) / values
+PASS min-width length(cm) / events
+PASS min-width length(in) / values
+PASS min-width length(in) / events
+PASS min-width percentage(%) / values
+PASS min-width percentage(%) / events
+PASS max-height length(pt) / values
+PASS max-height length(pt) / events
+PASS max-height length(pc) / values
+PASS max-height length(pc) / events
+PASS max-height length(px) / values
+PASS max-height length(px) / events
+PASS max-height length(em) / values
+PASS max-height length(em) / events
+PASS max-height length(ex) / values
+PASS max-height length(ex) / events
+PASS max-height length(mm) / values
+PASS max-height length(mm) / events
+PASS max-height length(cm) / values
+PASS max-height length(cm) / events
+PASS max-height length(in) / values
+PASS max-height length(in) / events
+PASS max-height percentage(%) / values
+PASS max-height percentage(%) / events
+PASS max-width length(pt) / values
+PASS max-width length(pt) / events
+PASS max-width length(pc) / values
+PASS max-width length(pc) / events
+PASS max-width length(px) / values
+PASS max-width length(px) / events
+PASS max-width length(em) / values
+PASS max-width length(em) / events
+PASS max-width length(ex) / values
+PASS max-width length(ex) / events
+PASS max-width length(mm) / values
+PASS max-width length(mm) / events
+PASS max-width length(cm) / values
+PASS max-width length(cm) / events
+PASS max-width length(in) / values
+PASS max-width length(in) / events
+PASS max-width percentage(%) / values
+PASS max-width percentage(%) / events
+PASS top length(pt) / values
+PASS top length(pt) / events
+PASS top length(pc) / values
+PASS top length(pc) / events
+PASS top length(px) / values
+PASS top length(px) / events
+PASS top length(em) / values
+PASS top length(em) / events
+PASS top length(ex) / values
+PASS top length(ex) / events
+PASS top length(mm) / values
+PASS top length(mm) / events
+PASS top length(cm) / values
+PASS top length(cm) / events
+PASS top length(in) / values
+PASS top length(in) / events
+PASS top percentage(%) / values
+PASS top percentage(%) / events
+PASS right length(pt) / values
+PASS right length(pt) / events
+PASS right length(pc) / values
+PASS right length(pc) / events
+PASS right length(px) / values
+PASS right length(px) / events
+PASS right length(em) / values
+PASS right length(em) / events
+PASS right length(ex) / values
+PASS right length(ex) / events
+PASS right length(mm) / values
+PASS right length(mm) / events
+PASS right length(cm) / values
+PASS right length(cm) / events
+PASS right length(in) / values
+PASS right length(in) / events
+PASS right percentage(%) / values
+PASS right percentage(%) / events
+PASS bottom length(pt) / values
+PASS bottom length(pt) / events
+PASS bottom length(pc) / values
+PASS bottom length(pc) / events
+PASS bottom length(px) / values
+PASS bottom length(px) / events
+PASS bottom length(em) / values
+PASS bottom length(em) / events
+PASS bottom length(ex) / values
+PASS bottom length(ex) / events
+PASS bottom length(mm) / values
+PASS bottom length(mm) / events
+PASS bottom length(cm) / values
+PASS bottom length(cm) / events
+PASS bottom length(in) / values
+PASS bottom length(in) / events
+PASS bottom percentage(%) / values
+PASS bottom percentage(%) / events
+PASS left length(pt) / values
+PASS left length(pt) / events
+PASS left length(pc) / values
+PASS left length(pc) / events
+PASS left length(px) / values
+PASS left length(px) / events
+PASS left length(em) / values
+PASS left length(em) / events
+PASS left length(ex) / values
+PASS left length(ex) / events
+PASS left length(mm) / values
+PASS left length(mm) / events
+PASS left length(cm) / values
+PASS left length(cm) / events
+PASS left length(in) / values
+PASS left length(in) / events
+PASS left percentage(%) / values
+PASS left percentage(%) / events
+PASS color color(rgba) / values
+PASS color color(rgba) / events
+PASS font-size length(pt) / values
+PASS font-size length(pt) / events
+PASS font-size length(pc) / values
+PASS font-size length(pc) / events
+PASS font-size length(px) / values
+PASS font-size length(px) / events
+PASS font-size length(em) / values
+PASS font-size length(em) / events
+PASS font-size length(ex) / values
+PASS font-size length(ex) / events
+PASS font-size length(mm) / values
+PASS font-size length(mm) / events
+PASS font-size length(cm) / values
+PASS font-size length(cm) / events
+PASS font-size length(in) / values
+PASS font-size length(in) / events
+PASS font-size percentage(%) / values
+PASS font-size percentage(%) / events
+PASS font-weight font-weight(keyword) / values
+PASS font-weight font-weight(keyword) / events
+PASS font-weight font-weight(numeric) / values
+PASS font-weight font-weight(numeric) / events
+PASS line-height number(integer) / values
+PASS line-height number(integer) / events
+PASS line-height number(decimal) / values
+PASS line-height number(decimal) / events
+PASS line-height length(pt) / values
+PASS line-height length(pt) / events
+PASS line-height length(pc) / values
+PASS line-height length(pc) / events
+PASS line-height length(px) / values
+PASS line-height length(px) / events
+PASS line-height length(em) / values
+PASS line-height length(em) / events
+PASS line-height length(ex) / values
+PASS line-height length(ex) / events
+PASS line-height length(mm) / values
+PASS line-height length(mm) / events
+PASS line-height length(cm) / values
+PASS line-height length(cm) / events
+PASS line-height length(in) / values
+PASS line-height length(in) / events
+PASS line-height percentage(%) / values
+PASS line-height percentage(%) / events
+PASS letter-spacing length(pt) / values
+PASS letter-spacing length(pt) / events
+PASS letter-spacing length(pc) / values
+PASS letter-spacing length(pc) / events
+PASS letter-spacing length(px) / values
+PASS letter-spacing length(px) / events
+PASS letter-spacing length(em) / values
+PASS letter-spacing length(em) / events
+PASS letter-spacing length(ex) / values
+PASS letter-spacing length(ex) / events
+PASS letter-spacing length(mm) / values
+PASS letter-spacing length(mm) / events
+PASS letter-spacing length(cm) / values
+PASS letter-spacing length(cm) / events
+PASS letter-spacing length(in) / values
+PASS letter-spacing length(in) / events
+PASS word-spacing length(pt) / values
+PASS word-spacing length(pt) / events
+PASS word-spacing length(pc) / values
+PASS word-spacing length(pc) / events
+PASS word-spacing length(px) / values
+PASS word-spacing length(px) / events
+PASS word-spacing length(em) / values
+PASS word-spacing length(em) / events
+PASS word-spacing length(ex) / values
+PASS word-spacing length(ex) / events
+PASS word-spacing length(mm) / values
+PASS word-spacing length(mm) / events
+PASS word-spacing length(cm) / values
+PASS word-spacing length(cm) / events
+PASS word-spacing length(in) / values
+PASS word-spacing length(in) / events
+FAIL word-spacing percentage(%) / values assert_not_equals: initial and target values may not match got disallowed value "0px"
+FAIL word-spacing percentage(%) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "word-spacing:0.5s" but got ""
+PASS text-indent length(pt) / values
+PASS text-indent length(pt) / events
+PASS text-indent length(pc) / values
+PASS text-indent length(pc) / events
+PASS text-indent length(px) / values
+PASS text-indent length(px) / events
+PASS text-indent length(em) / values
+PASS text-indent length(em) / events
+PASS text-indent length(ex) / values
+PASS text-indent length(ex) / events
+PASS text-indent length(mm) / values
+PASS text-indent length(mm) / events
+PASS text-indent length(cm) / values
+PASS text-indent length(cm) / events
+PASS text-indent length(in) / values
+PASS text-indent length(in) / events
+PASS text-indent percentage(%) / values
+PASS text-indent percentage(%) / events
+PASS text-shadow shadow(shadow) / values
+PASS text-shadow shadow(shadow) / events
+PASS outline-color color(rgba) / values
+PASS outline-color color(rgba) / events
+PASS outline-offset length(pt) / values
+PASS outline-offset length(pt) / events
+PASS outline-offset length(pc) / values
+PASS outline-offset length(pc) / events
+PASS outline-offset length(px) / values
+PASS outline-offset length(px) / events
+PASS outline-offset length(em) / values
+PASS outline-offset length(em) / events
+PASS outline-offset length(ex) / values
+PASS outline-offset length(ex) / events
+PASS outline-offset length(mm) / values
+PASS outline-offset length(mm) / events
+PASS outline-offset length(cm) / values
+PASS outline-offset length(cm) / events
+PASS outline-offset length(in) / values
+PASS outline-offset length(in) / events
+PASS outline-width length(pt) / values
+PASS outline-width length(pt) / events
+PASS outline-width length(pc) / values
+PASS outline-width length(pc) / events
+PASS outline-width length(px) / values
+PASS outline-width length(px) / events
+PASS outline-width length(em) / values
+PASS outline-width length(em) / events
+PASS outline-width length(ex) / values
+PASS outline-width length(ex) / events
+PASS outline-width length(mm) / values
+PASS outline-width length(mm) / events
+PASS outline-width length(cm) / values
+PASS outline-width length(cm) / events
+PASS outline-width length(in) / values
+PASS outline-width length(in) / events
+PASS clip rectangle(rectangle) / values
+PASS clip rectangle(rectangle) / events
+FAIL crop rectangle(rectangle) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL crop rectangle(rectangle) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "crop:0.5s" but got ""
+PASS vertical-align length(pt) / values
+PASS vertical-align length(pt) / events
+PASS vertical-align length(pc) / values
+PASS vertical-align length(pc) / events
+PASS vertical-align length(px) / values
+PASS vertical-align length(px) / events
+PASS vertical-align length(em) / values
+PASS vertical-align length(em) / events
+PASS vertical-align length(ex) / values
+PASS vertical-align length(ex) / events
+PASS vertical-align length(mm) / values
+PASS vertical-align length(mm) / events
+PASS vertical-align length(cm) / values
+PASS vertical-align length(cm) / events
+PASS vertical-align length(in) / values
+PASS vertical-align length(in) / events
+PASS vertical-align percentage(%) / values
+PASS vertical-align percentage(%) / events
+PASS opacity number[0,1](zero-to-one) / values
+PASS opacity number[0,1](zero-to-one) / events
+PASS visibility visibility(keyword) / values
+PASS visibility visibility(keyword) / events
+PASS z-index integer(integer) / values
+PASS z-index integer(integer) / events
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-001.html
new file mode 100644
index 0000000..9182930e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-001.html
@@ -0,0 +1,134 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>CSS Transitions Test: Intermediate Property Values</title>
+        <meta name="assert" content="Test checks that value ranges between start and end while transitioning">
+        <link rel="help" title="2. Transitions" href="http://www.w3.org/TR/css3-transitions/#transitions">
+        <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+        <link rel="author" title="Rodney Rehm" href="http://rodneyrehm.de/en/">
+        <meta name="flags" content="dom">
+
+        <script src="/resources/testharness.js" type="text/javascript"></script>
+        <script src="/resources/testharnessreport.js" type="text/javascript"></script>
+
+        <script src="./support/vendorPrefix.js" type="text/javascript"></script>
+        <script src="./support/helper.js" type="text/javascript"></script>
+        <script src="./support/runParallelAsyncHarness.js" type="text/javascript"></script>
+        <script src="./support/generalParallelTest.js" type="text/javascript"></script>
+        <script src="./support/properties.js" type="text/javascript"></script>
+
+        <style type="text/css">
+            #offscreen {
+                position: absolute;
+                top: -100000px;
+                left: -100000px;
+                width: 100000px;
+                height: 100000px;
+            }
+        </style>
+    </head>
+    <body>
+        <!-- required by testharnessreport.js -->
+        <div id="log"></div>
+        <!-- elements used for testing -->
+        <div id="fixture" class="fixture">
+            <div class="container">
+                <div class="transition">Text sample</div>
+            </div>
+        </div>
+        <div id="offscreen"></div>
+
+        <!--
+            SEE ./support/README.md for an abstract explanation of the test procedure
+            http://test.csswg.org/source/contributors/rodneyrehm/submitted/css3-transitions/README.md
+        -->
+
+        <script>
+            // this test takes its time, give it a minute to run
+            var timeout = 60000;
+            setup({timeout: timeout});
+
+            var tests = getPropertyTests();
+            // for testing, limit to a couple of iterations
+            // tests = tests.slice(10, 30);
+            // or filter using one of:
+            // tests = filterPropertyTests(tests, "background-color color(rgba)");
+            // tests = filterPropertyTests(tests, ["background-color color(rgba)", ...]);
+            // tests = filterPropertyTests(tests, /^background-color/);
+
+            // general transition-duration
+            var duration = '0.5s';
+
+            runParallelAsyncHarness({
+                // array of test data
+                tests: tests,
+                // the number of tests to run in parallel
+                testsPerSlice: 50,
+                // milliseconds to wait before calling teardown and ending test
+                duration: parseFloat(duration) * 1000,
+                // the global suite timeout
+                timeout: timeout,
+                // prepare individual test
+                setup: function(data, options) {
+                    var styles = {
+                        '.fixture': {},
+
+                        '.container': data.parentStyle,
+                        '.container.to': {},
+                        '.container.how': {},
+
+                        '.transition': data.from,
+                        '.transition.to' : data.to,
+                        '.transition.how' : {transition: 'all ' + duration + ' linear 0s'}
+                    };
+
+                    generalParallelTest.setup(data, options);
+                    generalParallelTest.addStyles(data, options, styles);
+                },
+                // cleanup after individual test
+                teardown: generalParallelTest.teardown,
+                // invoked prior to running a slice of tests
+                sliceStart: generalParallelTest.sliceStart,
+                // invoked after running a slice of tests
+                sliceDone: generalParallelTest.sliceDone,
+                // test cases, make them as granular as possible
+                cases: {
+                    // test property values while transitioning
+                    // values.start kicks off a transition
+                    'values': {
+                        // run actual test, assertions can be used here!
+                        start: function(test, data, options) {
+                            // identify initial and target values
+                            generalParallelTest.getStyle(data);
+                            // make sure values differ, if they don't, the property could most likely not be parsed
+                            assert_not_equals(data.transition.from, data.transition.to, "initial and target values may not match");
+                            // kick off the transition
+                            generalParallelTest.startTransition(data);
+
+                            // make sure we didn't get the target value immediately.
+                            // If we did, there wouldn't be a transition!
+                            var current = data.transition.computedStyle(data.property);
+                            assert_not_equals(current, data.transition.to, "must not be target value after start");
+                        },
+                        done: function(test, data, options) {
+                            // make sure the property's value were neither initial nor target while transitioning
+                            test.step(generalParallelTest.assertIntermediateValuesFunc(data, 'transition'));
+                        }
+                    },
+                    // test TransitionEnd events
+                    'events': {
+                        done: function(test, data, options) {
+                            // make sure there were no events on parent
+                            test.step(generalParallelTest.assertExpectedEventsFunc(data, 'container', ""));
+                            // make sure we got the event for the tested property only
+                            test.step(generalParallelTest.assertExpectedEventsFunc(data, 'transition', addVendorPrefix(data.property) + ":" + duration));
+                        }
+                    }
+                },
+                // called once all tests are done
+                done: generalParallelTest.done
+            });
+        </script>
+    </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-002-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-002-expected.txt
new file mode 100644
index 0000000..a7c6fc6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-002-expected.txt
@@ -0,0 +1,21 @@
+This is a testharness.js-based test.
+PASS margin-bottom percentage(%) / values
+PASS margin-bottom percentage(%) / events
+PASS margin-left percentage(%) / values
+PASS margin-left percentage(%) / events
+PASS margin-right percentage(%) / values
+PASS margin-right percentage(%) / events
+PASS margin-top percentage(%) / values
+PASS margin-top percentage(%) / events
+PASS padding-bottom percentage(%) / values
+PASS padding-bottom percentage(%) / events
+PASS padding-left percentage(%) / values
+PASS padding-left percentage(%) / events
+PASS padding-right percentage(%) / values
+PASS padding-right percentage(%) / events
+PASS padding-top percentage(%) / values
+PASS padding-top percentage(%) / events
+FAIL vertical-align vertical(keyword) / values assert_not_equals: must not be target value after start got disallowed value "bottom"
+FAIL vertical-align vertical(keyword) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "vertical-align:0.5s" but got ""
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-002.html
new file mode 100644
index 0000000..7298070
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-002.html
@@ -0,0 +1,137 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>CSS Transitions Test: Intermediate Property Values of missing value types</title>
+        <meta name="assert" content="Test checks that expected value types that haven't been specified are transitionable">
+        <link rel="help" title="2. Transitions" href="http://www.w3.org/TR/css3-transitions/#transitions">
+        <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+        <link rel="author" title="Rodney Rehm" href="http://rodneyrehm.de/en/">
+        <meta name="flags" content="dom">
+
+        <script src="/resources/testharness.js" type="text/javascript"></script>
+        <script src="/resources/testharnessreport.js" type="text/javascript"></script>
+
+        <script src="./support/vendorPrefix.js" type="text/javascript"></script>
+        <script src="./support/helper.js" type="text/javascript"></script>
+        <script src="./support/runParallelAsyncHarness.js" type="text/javascript"></script>
+        <script src="./support/generalParallelTest.js" type="text/javascript"></script>
+        <script src="./support/properties.js" type="text/javascript"></script>
+
+        <style type="text/css">
+            #offscreen {
+                position: absolute;
+                top: -100000px;
+                left: -100000px;
+                width: 100000px;
+                height: 100000px;
+            }
+        </style>
+    </head>
+    <body>
+        <!-- required by testharnessreport.js -->
+        <div id="log"></div>
+        <!-- elements used for testing -->
+        <div id="fixture" class="fixture">
+            <div class="container">
+                <div class="transition">Text sample</div>
+            </div>
+        </div>
+        <div id="offscreen"></div>
+
+        <!--
+            SEE ./support/README.md for an abstract explanation of the test procedure
+            http://test.csswg.org/source/contributors/rodneyrehm/submitted/css3-transitions/README.md
+        -->
+
+        <script>
+            // this suite tests property value types that haven't been specified
+            // (like <percentage> for margin-bottom)
+
+            // this test takes its time, give it a minute to run
+            var timeout = 60000;
+            setup({timeout: timeout});
+
+            var tests = getMissingPropertyTests();
+            // for testing, limit to a couple of iterations
+            // tests = tests.slice(10, 30);
+            // or filter using one of:
+            // tests = filterPropertyTests(tests, "background-color color(rgba)");
+            // tests = filterPropertyTests(tests, ["background-color color(rgba)", ...]);
+            // tests = filterPropertyTests(tests, /^background-color/);
+
+            // general transition-duration
+            var duration = '0.5s';
+
+            runParallelAsyncHarness({
+                // array of test data
+                tests: tests,
+                // the number of tests to run in parallel
+                testsPerSlice: 50,
+                // milliseconds to wait before calling teardown and ending test
+                duration: parseFloat(duration) * 1000,
+                // the global suite timeout
+                timeout: timeout,
+                // prepare individual test
+                setup: function(data, options) {
+                    var styles = {
+                        '.fixture': {},
+
+                        '.container': data.parentStyle,
+                        '.container.to': {},
+                        '.container.how': {},
+
+                        '.transition': data.from,
+                        '.transition.to' : data.to,
+                        '.transition.how' : {transition: 'all ' + duration + ' linear 0s'}
+                    };
+
+                    generalParallelTest.setup(data, options);
+                    generalParallelTest.addStyles(data, options, styles);
+                },
+                // cleanup after individual test
+                teardown: generalParallelTest.teardown,
+                // invoked prior to running a slice of tests
+                sliceStart: generalParallelTest.sliceStart,
+                // invoked after running a slice of tests
+                sliceDone: generalParallelTest.sliceDone,
+                // test cases, make them as granular as possible
+                cases: {
+                    // test property values while transitioning
+                    // values.start kicks off a transition
+                    'values': {
+                        // run actual test, assertions can be used here!
+                        start: function(test, data, options) {
+                            // identify initial and target values
+                            generalParallelTest.getStyle(data);
+                            // make sure values differ, if they don't, the property could most likely not be parsed
+                            assert_not_equals(data.transition.from, data.transition.to, "initial and target values may not match");
+                            // kick off the transition
+                            generalParallelTest.startTransition(data);
+
+                            // make sure we didn't get the target value immediately.
+                            // If we did, there wouldn't be a transition!
+                            var current = data.transition.computedStyle(data.property);
+                            assert_not_equals(current, data.transition.to, "must not be target value after start");
+                        },
+                        done: function(test, data, options) {
+                            // make sure the property's value were neither initial nor target while transitioning
+                            test.step(generalParallelTest.assertIntermediateValuesFunc(data, 'transition'));
+                        }
+                    },
+                    // test TransitionEnd events
+                    'events': {
+                        done: function(test, data, options) {
+                            // make sure there were no events on parent
+                            test.step(generalParallelTest.assertExpectedEventsFunc(data, 'container', ""));
+                            // make sure we got the event for the tested property only
+                            test.step(generalParallelTest.assertExpectedEventsFunc(data, 'transition', addVendorPrefix(data.property) + ":" + duration));
+                        }
+                    }
+                },
+                // called once all tests are done
+                done: generalParallelTest.done
+            });
+        </script>
+    </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-003-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-003-expected.txt
new file mode 100644
index 0000000..290eb66
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-003-expected.txt
@@ -0,0 +1,196 @@
+This is a testharness.js-based test.
+Found 192 tests; 84 PASS, 108 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS border-top-left-radius border-radius(px) / values
+PASS border-top-left-radius border-radius(px) / events
+PASS border-top-left-radius border-radius(px-px) / values
+PASS border-top-left-radius border-radius(px-px) / events
+PASS border-top-right-radius border-radius(px) / values
+PASS border-top-right-radius border-radius(px) / events
+PASS border-top-right-radius border-radius(px-px) / values
+PASS border-top-right-radius border-radius(px-px) / events
+PASS border-bottom-left-radius border-radius(px) / values
+PASS border-bottom-left-radius border-radius(px) / events
+PASS border-bottom-left-radius border-radius(px-px) / values
+PASS border-bottom-left-radius border-radius(px-px) / events
+PASS border-bottom-right-radius border-radius(px) / values
+PASS border-bottom-right-radius border-radius(px) / events
+PASS border-bottom-right-radius border-radius(px-px) / values
+PASS border-bottom-right-radius border-radius(px-px) / events
+PASS background-image image(url) / values
+PASS background-image image(url) / events
+PASS background-image image(data) / values
+PASS background-image image(data) / events
+FAIL background-image image(gradient) / values assert_not_equals: must not be target value after start got disallowed value "-webkit-linear-gradient(top, rgb(186, 218, 85), rgb(240, 117, 117))"
+FAIL background-image image(gradient) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "background-image:0.5s" but got ""
+FAIL background-size background-size(keyword) / values assert_not_equals: must not be target value after start got disallowed value "contain"
+FAIL background-size background-size(keyword) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "background-size:0.5s" but got ""
+PASS box-shadow box-shadow(shadow) / values
+PASS box-shadow box-shadow(shadow) / events
+PASS font-size-adjust number(integer) / values
+PASS font-size-adjust number(integer) / events
+PASS font-size-adjust number(decimal) / values
+PASS font-size-adjust number(decimal) / events
+FAIL font-stretch font-stretch(keyword) / values assert_not_equals: must not be target value after start got disallowed value "125%"
+FAIL font-stretch font-stretch(keyword) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "font-stretch:0.5s" but got ""
+FAIL marker-offset length(pt) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL marker-offset length(pt) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "marker-offset:0.5s" but got ""
+FAIL marker-offset length(pc) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL marker-offset length(pc) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "marker-offset:0.5s" but got ""
+FAIL marker-offset length(px) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL marker-offset length(px) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "marker-offset:0.5s" but got ""
+FAIL marker-offset length(em) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL marker-offset length(em) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "marker-offset:0.5s" but got ""
+FAIL marker-offset length(ex) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL marker-offset length(ex) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "marker-offset:0.5s" but got ""
+FAIL marker-offset length(mm) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL marker-offset length(mm) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "marker-offset:0.5s" but got ""
+FAIL marker-offset length(cm) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL marker-offset length(cm) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "marker-offset:0.5s" but got ""
+FAIL marker-offset length(in) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL marker-offset length(in) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "marker-offset:0.5s" but got ""
+PASS text-decoration-color color(rgba) / values
+PASS text-decoration-color color(rgba) / events
+PASS column-count integer(integer) / values
+PASS column-count integer(integer) / events
+PASS column-gap length(pt) / values
+PASS column-gap length(pt) / events
+PASS column-gap length(pc) / values
+PASS column-gap length(pc) / events
+PASS column-gap length(px) / values
+PASS column-gap length(px) / events
+PASS column-gap length(em) / values
+PASS column-gap length(em) / events
+PASS column-gap length(ex) / values
+PASS column-gap length(ex) / events
+PASS column-gap length(mm) / values
+PASS column-gap length(mm) / events
+PASS column-gap length(cm) / values
+PASS column-gap length(cm) / events
+PASS column-gap length(in) / values
+PASS column-gap length(in) / events
+PASS column-rule-color color(rgba) / values
+PASS column-rule-color color(rgba) / events
+PASS column-rule-width length(pt) / values
+PASS column-rule-width length(pt) / events
+PASS column-rule-width length(pc) / values
+PASS column-rule-width length(pc) / events
+PASS column-rule-width length(px) / values
+PASS column-rule-width length(px) / events
+PASS column-rule-width length(em) / values
+PASS column-rule-width length(em) / events
+PASS column-rule-width length(ex) / values
+PASS column-rule-width length(ex) / events
+PASS column-rule-width length(mm) / values
+PASS column-rule-width length(mm) / events
+PASS column-rule-width length(cm) / values
+PASS column-rule-width length(cm) / events
+PASS column-rule-width length(in) / values
+PASS column-rule-width length(in) / events
+PASS column-width length(pt) / values
+PASS column-width length(pt) / events
+PASS column-width length(pc) / values
+PASS column-width length(pc) / events
+PASS column-width length(px) / values
+PASS column-width length(px) / events
+PASS column-width length(em) / values
+PASS column-width length(em) / events
+PASS column-width length(ex) / values
+PASS column-width length(ex) / events
+PASS column-width length(mm) / values
+PASS column-width length(mm) / events
+PASS column-width length(cm) / values
+PASS column-width length(cm) / events
+PASS column-width length(in) / values
+PASS column-width length(in) / events
+PASS transform transform(rotate) / values
+PASS transform transform(rotate) / events
+PASS transform-origin horizontal(keyword) / values
+PASS transform-origin horizontal(keyword) / events
+FAIL zoom number(integer) / values assert_not_equals: must not be target value after start got disallowed value "10"
+FAIL zoom number(integer) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "zoom:0.5s" but got ""
+FAIL zoom number(decimal) / values assert_not_equals: must not be target value after start got disallowed value "9.55"
+FAIL zoom number(decimal) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "zoom:0.5s" but got ""
+FAIL outline-radius-topleft length(pt) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-topleft length(pt) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-topleft:0.5s" but got ""
+FAIL outline-radius-topleft length(pc) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-topleft length(pc) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-topleft:0.5s" but got ""
+FAIL outline-radius-topleft length(px) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-topleft length(px) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-topleft:0.5s" but got ""
+FAIL outline-radius-topleft length(em) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-topleft length(em) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-topleft:0.5s" but got ""
+FAIL outline-radius-topleft length(ex) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-topleft length(ex) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-topleft:0.5s" but got ""
+FAIL outline-radius-topleft length(mm) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-topleft length(mm) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-topleft:0.5s" but got ""
+FAIL outline-radius-topleft length(cm) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-topleft length(cm) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-topleft:0.5s" but got ""
+FAIL outline-radius-topleft length(in) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-topleft length(in) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-topleft:0.5s" but got ""
+FAIL outline-radius-topleft percentage(%) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-topleft percentage(%) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-topleft:0.5s" but got ""
+FAIL outline-radius-topright length(pt) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-topright length(pt) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-topright:0.5s" but got ""
+FAIL outline-radius-topright length(pc) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-topright length(pc) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-topright:0.5s" but got ""
+FAIL outline-radius-topright length(px) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-topright length(px) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-topright:0.5s" but got ""
+FAIL outline-radius-topright length(em) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-topright length(em) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-topright:0.5s" but got ""
+FAIL outline-radius-topright length(ex) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-topright length(ex) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-topright:0.5s" but got ""
+FAIL outline-radius-topright length(mm) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-topright length(mm) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-topright:0.5s" but got ""
+FAIL outline-radius-topright length(cm) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-topright length(cm) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-topright:0.5s" but got ""
+FAIL outline-radius-topright length(in) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-topright length(in) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-topright:0.5s" but got ""
+FAIL outline-radius-topright percentage(%) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-topright percentage(%) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-topright:0.5s" but got ""
+FAIL outline-radius-bottomright length(pt) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-bottomright length(pt) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-bottomright:0.5s" but got ""
+FAIL outline-radius-bottomright length(pc) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-bottomright length(pc) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-bottomright:0.5s" but got ""
+FAIL outline-radius-bottomright length(px) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-bottomright length(px) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-bottomright:0.5s" but got ""
+FAIL outline-radius-bottomright length(em) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-bottomright length(em) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-bottomright:0.5s" but got ""
+FAIL outline-radius-bottomright length(ex) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-bottomright length(ex) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-bottomright:0.5s" but got ""
+FAIL outline-radius-bottomright length(mm) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-bottomright length(mm) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-bottomright:0.5s" but got ""
+FAIL outline-radius-bottomright length(cm) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-bottomright length(cm) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-bottomright:0.5s" but got ""
+FAIL outline-radius-bottomright length(in) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-bottomright length(in) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-bottomright:0.5s" but got ""
+FAIL outline-radius-bottomright percentage(%) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-bottomright percentage(%) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-bottomright:0.5s" but got ""
+FAIL outline-radius-bottomleft length(pt) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-bottomleft length(pt) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-bottomleft:0.5s" but got ""
+FAIL outline-radius-bottomleft length(pc) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-bottomleft length(pc) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-bottomleft:0.5s" but got ""
+FAIL outline-radius-bottomleft length(px) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-bottomleft length(px) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-bottomleft:0.5s" but got ""
+FAIL outline-radius-bottomleft length(em) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-bottomleft length(em) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-bottomleft:0.5s" but got ""
+FAIL outline-radius-bottomleft length(ex) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-bottomleft length(ex) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-bottomleft:0.5s" but got ""
+FAIL outline-radius-bottomleft length(mm) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-bottomleft length(mm) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-bottomleft:0.5s" but got ""
+FAIL outline-radius-bottomleft length(cm) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-bottomleft length(cm) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-bottomleft:0.5s" but got ""
+FAIL outline-radius-bottomleft length(in) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-bottomleft length(in) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-bottomleft:0.5s" but got ""
+FAIL outline-radius-bottomleft percentage(%) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL outline-radius-bottomleft percentage(%) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "outline-radius-bottomleft:0.5s" but got ""
+FAIL display display(static to absolute) / values assert_not_equals: must not be target value after start got disallowed value "block"
+FAIL display display(static to absolute) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "display:0.5s" but got ""
+FAIL display display(block to inline-block) / values assert_not_equals: must not be target value after start got disallowed value "inline-block"
+FAIL display display(block to inline-block) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "display:0.5s" but got ""
+FAIL position position(static to absolute) / values assert_not_equals: must not be target value after start got disallowed value "absolute"
+FAIL position position(static to absolute) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "position:0.5s" but got ""
+FAIL position position(relative to absolute) / values assert_not_equals: must not be target value after start got disallowed value "absolute"
+FAIL position position(relative to absolute) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "position:0.5s" but got ""
+FAIL position position(absolute to fixed) / values assert_not_equals: must not be target value after start got disallowed value "fixed"
+FAIL position position(absolute to fixed) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "position:0.5s" but got ""
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-003.html
new file mode 100644
index 0000000..23385d1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-003.html
@@ -0,0 +1,138 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>CSS Transitions Test: Intermediate Property Values of unspecified properties</title>
+        <meta name="assert" content="Test checks that properties are transitionable that haven't been specified">
+        <link rel="help" title="2. Transitions" href="http://www.w3.org/TR/css3-transitions/#transitions">
+        <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+        <link rel="author" title="Rodney Rehm" href="http://rodneyrehm.de/en/">
+        <meta name="flags" content="dom">
+
+        <script src="/resources/testharness.js" type="text/javascript"></script>
+        <script src="/resources/testharnessreport.js" type="text/javascript"></script>
+
+        <script src="./support/vendorPrefix.js" type="text/javascript"></script>
+        <script src="./support/helper.js" type="text/javascript"></script>
+        <script src="./support/runParallelAsyncHarness.js" type="text/javascript"></script>
+        <script src="./support/generalParallelTest.js" type="text/javascript"></script>
+        <script src="./support/properties.js" type="text/javascript"></script>
+
+        <style type="text/css">
+            #offscreen {
+                position: absolute;
+                top: -100000px;
+                left: -100000px;
+                width: 100000px;
+                height: 100000px;
+            }
+        </style>
+    </head>
+    <body>
+        <!-- required by testharnessreport.js -->
+        <div id="log"></div>
+        <!-- elements used for testing -->
+        <div id="fixture" class="fixture">
+            <div class="container">
+                <div class="transition">Text sample</div>
+            </div>
+        </div>
+        <div id="offscreen"></div>
+
+        <!--
+            SEE ./support/README.md for an abstract explanation of the test procedure
+            http://test.csswg.org/source/contributors/rodneyrehm/submitted/css3-transitions/README.md
+        -->
+
+        <script>
+            // see README.md for an explanation of how this test suite works
+            // this suite tests properties that haven't been specified at all
+            // (like background-image and column-rule-width)
+
+            // this test takes its time, give it a minute to run
+            var timeout = 60000;
+            setup({timeout: timeout});
+
+            var tests = getUnspecifiedPropertyTests();
+            // for testing, limit to a couple of iterations
+            // tests = tests.slice(10, 30);
+            // or filter using one of:
+            // tests = filterPropertyTests(tests, "background-color color(rgba)");
+            // tests = filterPropertyTests(tests, ["background-color color(rgba)", ...]);
+            // tests = filterPropertyTests(tests, /^background-color/);
+
+            // general transition-duration
+            var duration = '0.5s';
+
+            runParallelAsyncHarness({
+                // array of test data
+                tests: tests,
+                // the number of tests to run in parallel
+                testsPerSlice: 50,
+                // milliseconds to wait before calling teardown and ending test
+                duration: parseFloat(duration) * 1000,
+                // the global suite timeout
+                timeout: timeout,
+                // prepare individual test
+                setup: function(data, options) {
+                    var styles = {
+                        '.fixture': {},
+
+                        '.container': data.parentStyle,
+                        '.container.to': {},
+                        '.container.how': {},
+
+                        '.transition': data.from,
+                        '.transition.to' : data.to,
+                        '.transition.how' : {transition: 'all ' + duration + ' linear 0s'}
+                    };
+
+                    generalParallelTest.setup(data, options);
+                    generalParallelTest.addStyles(data, options, styles);
+                },
+                // cleanup after individual test
+                teardown: generalParallelTest.teardown,
+                // invoked prior to running a slice of tests
+                sliceStart: generalParallelTest.sliceStart,
+                // invoked after running a slice of tests
+                sliceDone: generalParallelTest.sliceDone,
+                // test cases, make them as granular as possible
+                cases: {
+                    // test property values while transitioning
+                    // values.start kicks off a transition
+                    'values': {
+                        // run actual test, assertions can be used here!
+                        start: function(test, data, options) {
+                            // identify initial and target values
+                            generalParallelTest.getStyle(data);
+                            // make sure values differ, if they don't, the property could most likely not be parsed
+                            assert_not_equals(data.transition.from, data.transition.to, "initial and target values may not match");
+                            // kick off the transition
+                            generalParallelTest.startTransition(data);
+
+                            // make sure we didn't get the target value immediately.
+                            // If we did, there wouldn't be a transition!
+                            var current = data.transition.computedStyle(data.property);
+                            assert_not_equals(current, data.transition.to, "must not be target value after start");
+                        },
+                        done: function(test, data, options) {
+                            // make sure the property's value were neither initial nor target while transitioning
+                            test.step(generalParallelTest.assertIntermediateValuesFunc(data, 'transition'));
+                        }
+                    },
+                    // test TransitionEnd events
+                    'events': {
+                        done: function(test, data, options) {
+                            // make sure there were no events on parent
+                            test.step(generalParallelTest.assertExpectedEventsFunc(data, 'container', ""));
+                            // make sure we got the event for the tested property only
+                            test.step(generalParallelTest.assertExpectedEventsFunc(data, 'transition', addVendorPrefix(data.property) + ":" + duration));
+                        }
+                    }
+                },
+                // called once all tests are done
+                done: generalParallelTest.done
+            });
+        </script>
+    </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-auto-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-auto-001.html
new file mode 100644
index 0000000..087f6bbb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-auto-001.html
@@ -0,0 +1,137 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>CSS Transitions Test: transitioning property value "auto"</title>
+        <meta name="assert" content="Test checks that properties are transitioned from an to auto-value">
+        <link rel="help" title="2. Transitions" href="http://www.w3.org/TR/css3-transitions/#transitions">
+        <link rel="author" title="Rodney Rehm" href="http://rodneyrehm.de/en/">
+        <meta name="flags" content="dom ">
+
+        <script src="/resources/testharness.js" type="text/javascript"></script>
+        <script src="/resources/testharnessreport.js" type="text/javascript"></script>
+
+        <script src="./support/vendorPrefix.js" type="text/javascript"></script>
+        <script src="./support/helper.js" type="text/javascript"></script>
+        <script src="./support/runParallelAsyncHarness.js" type="text/javascript"></script>
+        <script src="./support/generalParallelTest.js" type="text/javascript"></script>
+        <script src="./support/properties.js" type="text/javascript"></script>
+
+        <style type="text/css">
+            #offscreen {
+                position: absolute;
+                top: -100000px;
+                left: -100000px;
+                width: 100000px;
+                height: 100000px;
+            }
+        </style>
+    </head>
+    <body>
+        <!-- required by testharnessreport.js -->
+        <div id="log"></div>
+        <!-- elements used for testing -->
+        <div id="fixture" class="fixture">
+            <div class="container">
+                <div class="transition">Text sample</div>
+            </div>
+        </div>
+        <div id="offscreen"></div>
+
+        <!--
+            SEE ./support/README.md for an abstract explanation of the test procedure
+            http://test.csswg.org/source/contributors/rodneyrehm/submitted/css3-transitions/README.md
+        -->
+
+        <script>
+            // see README.md for an explanation of how this test suite works
+            // this suite tests properties that haven't been specified at all
+            // (like background-image and column-rule-width)
+
+            // this test takes its time, give it a minute to run
+            var timeout = 60000;
+            setup({timeout: timeout});
+
+            var tests = getAutoPropertyTests();
+            // for testing, limit to a couple of iterations
+            // tests = tests.slice(10, 30);
+            // or filter using one of:
+            // tests = filterPropertyTests(tests, "background-color color(rgba)");
+            // tests = filterPropertyTests(tests, ["background-color color(rgba)", ...]);
+            // tests = filterPropertyTests(tests, /^background-color/);
+
+            // general transition-duration
+            var duration = '0.5s';
+
+            runParallelAsyncHarness({
+                // array of test data
+                tests: tests,
+                // the number of tests to run in parallel
+                testsPerSlice: 50,
+                // milliseconds to wait before calling teardown and ending test
+                duration: parseFloat(duration) * 1000,
+                // the global suite timeout
+                timeout: timeout,
+                // prepare individual test
+                setup: function(data, options) {
+                    var styles = {
+                        '.fixture': {},
+
+                        '.container': data.parentStyle,
+                        '.container.to': {},
+                        '.container.how': {},
+
+                        '.transition': data.from,
+                        '.transition.to' : data.to,
+                        '.transition.how' : {transition: 'all ' + duration + ' linear 0s'}
+                    };
+
+                    generalParallelTest.setup(data, options);
+                    generalParallelTest.addStyles(data, options, styles);
+                },
+                // cleanup after individual test
+                teardown: generalParallelTest.teardown,
+                // invoked prior to running a slice of tests
+                sliceStart: generalParallelTest.sliceStart,
+                // invoked after running a slice of tests
+                sliceDone: generalParallelTest.sliceDone,
+                // test cases, make them as granular as possible
+                cases: {
+                    // test property values while transitioning
+                    // values.start kicks off a transition
+                    'values': {
+                        // run actual test, assertions can be used here!
+                        start: function(test, data, options) {
+                            // identify initial and target values
+                            generalParallelTest.getStyle(data);
+                            // make sure values differ, if they don't, the property could most likely not be parsed
+                            assert_not_equals(data.transition.from, data.transition.to, "initial and target values may not match");
+                            // kick off the transition
+                            generalParallelTest.startTransition(data);
+
+                            // make sure we didn't get the target value immediately.
+                            // If we did, there wouldn't be a transition!
+                            var current = data.transition.computedStyle(data.property);
+                            assert_not_equals(current, data.transition.to, "must not be target value after start");
+                        },
+                        done: function(test, data, options) {
+                            // make sure the property's value were neither initial nor target while transitioning
+                            test.step(generalParallelTest.assertIntermediateValuesFunc(data, 'transition'));
+                        }
+                    },
+                    // test TransitionEnd events
+                    'events': {
+                        done: function(test, data, options) {
+                            // make sure there were no events on parent
+                            test.step(generalParallelTest.assertExpectedEventsFunc(data, 'container', ""));
+                            // make sure we got the event for the tested property only
+                            test.step(generalParallelTest.assertExpectedEventsFunc(data, 'transition', addVendorPrefix(data.property) + ":" + duration));
+                        }
+                    }
+                },
+                // called once all tests are done
+                done: generalParallelTest.done
+            });
+        </script>
+    </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-implicit-001-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-implicit-001-expected.txt
new file mode 100644
index 0000000..595ad3b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-implicit-001-expected.txt
@@ -0,0 +1,64 @@
+This is a testharness.js-based test.
+Found 60 tests; 59 PASS, 1 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS background-position length-em(em) / values
+FAIL background-position length-em(em) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "background-position:0.5s" but got "background-position-x:0.5s"
+PASS border-top-width length-em(em) / values
+PASS border-top-width length-em(em) / events
+PASS border-right-width length-em(em) / values
+PASS border-right-width length-em(em) / events
+PASS border-bottom-width length-em(em) / values
+PASS border-bottom-width length-em(em) / events
+PASS border-left-width length-em(em) / values
+PASS border-left-width length-em(em) / events
+PASS padding-bottom length-em(em) / values
+PASS padding-bottom length-em(em) / events
+PASS padding-left length-em(em) / values
+PASS padding-left length-em(em) / events
+PASS padding-right length-em(em) / values
+PASS padding-right length-em(em) / events
+PASS padding-top length-em(em) / values
+PASS padding-top length-em(em) / events
+PASS margin-bottom length-em(em) / values
+PASS margin-bottom length-em(em) / events
+PASS margin-left length-em(em) / values
+PASS margin-left length-em(em) / events
+PASS margin-right length-em(em) / values
+PASS margin-right length-em(em) / events
+PASS margin-top length-em(em) / values
+PASS margin-top length-em(em) / events
+PASS height length-em(em) / values
+PASS height length-em(em) / events
+PASS width length-em(em) / values
+PASS width length-em(em) / events
+PASS min-height length-em(em) / values
+PASS min-height length-em(em) / events
+PASS min-width length-em(em) / values
+PASS min-width length-em(em) / events
+PASS max-height length-em(em) / values
+PASS max-height length-em(em) / events
+PASS max-width length-em(em) / values
+PASS max-width length-em(em) / events
+PASS top length-em(em) / values
+PASS top length-em(em) / events
+PASS right length-em(em) / values
+PASS right length-em(em) / events
+PASS bottom length-em(em) / values
+PASS bottom length-em(em) / events
+PASS left length-em(em) / values
+PASS left length-em(em) / events
+PASS line-height length-em(em) / values
+PASS line-height length-em(em) / events
+PASS letter-spacing length-em(em) / values
+PASS letter-spacing length-em(em) / events
+PASS word-spacing length-em(em) / values
+PASS word-spacing length-em(em) / events
+PASS text-indent length-em(em) / values
+PASS text-indent length-em(em) / events
+PASS outline-offset length-em(em) / values
+PASS outline-offset length-em(em) / events
+PASS outline-width length-em(em) / values
+PASS outline-width length-em(em) / events
+PASS vertical-align length-em(em) / values
+PASS vertical-align length-em(em) / events
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-implicit-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-implicit-001.html
new file mode 100644
index 0000000..4d93083
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-implicit-001.html
@@ -0,0 +1,143 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>CSS Transitions Test: font-size-relative properties transition by implicit value change</title>
+        <meta name="assert" content="Test checks that font-size-relative properties (all em-lengths) run a transition when font-size is changed">
+        <link rel="help" title="2. Transitions" href="http://www.w3.org/TR/css3-transitions/#transitions">
+        <link rel="author" title="Rodney Rehm" href="http://rodneyrehm.de/en/">
+        <meta name="flags" content="dom ">
+
+        <script src="/resources/testharness.js" type="text/javascript"></script>
+        <script src="/resources/testharnessreport.js" type="text/javascript"></script>
+
+        <script src="./support/vendorPrefix.js" type="text/javascript"></script>
+        <script src="./support/helper.js" type="text/javascript"></script>
+        <script src="./support/runParallelAsyncHarness.js" type="text/javascript"></script>
+        <script src="./support/generalParallelTest.js" type="text/javascript"></script>
+        <script src="./support/properties.js" type="text/javascript"></script>
+
+        <style type="text/css">
+            #offscreen {
+                position: absolute;
+                top: -100000px;
+                left: -100000px;
+                width: 100000px;
+                height: 100000px;
+            }
+        </style>
+    </head>
+    <body>
+        <!-- required by testharnessreport.js -->
+        <div id="log"></div>
+        <!-- elements used for testing -->
+        <div id="fixture" class="fixture">
+            <div class="container">
+                <div class="transition">Text sample</div>
+            </div>
+        </div>
+        <div id="offscreen"></div>
+
+        <!--
+            SEE ./support/README.md for an abstract explanation of the test procedure
+            http://test.csswg.org/source/contributors/rodneyrehm/submitted/css3-transitions/README.md
+        -->
+
+        <script>
+            // see README.md for an explanation of how this test suite works
+            // this suite tests properties that haven't been specified at all
+            // (like background-image and column-rule-width)
+
+            // this test takes its time, give it a minute to run
+            var timeout = 60000;
+            setup({timeout: timeout});
+
+            var tests = getFontSizeRelativePropertyTests();
+            // for testing, limit to a couple of iterations
+            // tests = tests.slice(10, 30);
+            // or filter using one of:
+            // tests = filterPropertyTests(tests, "background-color color(rgba)");
+            // tests = filterPropertyTests(tests, ["background-color color(rgba)", ...]);
+            // tests = filterPropertyTests(tests, /^background-color/);
+
+            // general transition-duration
+            var duration = '0.5s';
+
+            runParallelAsyncHarness({
+                // array of test data
+                tests: tests,
+                // the number of tests to run in parallel
+                testsPerSlice: 50,
+                // milliseconds to wait before calling teardown and ending test
+                duration: parseFloat(duration) * 1000,
+                // the global suite timeout
+                timeout: timeout,
+                // prepare individual test
+                setup: function(data, options) {
+                    // as we're dealing with em-based lengths, we need to define a font-size
+                    data.from['font-size'] = '20px';
+                    data.to['font-size'] = '30px';
+                    // remove property from target style so it won't transition on its own
+                    delete data.to[data.property];
+
+                    var styles = {
+                        '.fixture': {},
+
+                        '.container': data.parentStyle,
+                        '.container.to': {},
+                        '.container.how': {},
+
+                        '.transition': data.from,
+                        '.transition.to' : data.to,
+                        '.transition.how' : {transition: addVendorPrefix(data.property) + ' ' + duration + ' linear 0s'}
+                    };
+
+                    generalParallelTest.setup(data, options);
+                    generalParallelTest.addStyles(data, options, styles);
+                },
+                // cleanup after individual test
+                teardown: generalParallelTest.teardown,
+                // invoked prior to running a slice of tests
+                sliceStart: generalParallelTest.sliceStart,
+                // invoked after running a slice of tests
+                sliceDone: generalParallelTest.sliceDone,
+                // test cases, make them as granular as possible
+                cases: {
+                    // test property values while transitioning
+                    // values.start kicks off a transition
+                    'values': {
+                        // run actual test, assertions can be used here!
+                        start: function(test, data, options) {
+                            // identify initial and target values
+                            generalParallelTest.getStyle(data);
+                            // make sure values differ, if they don't, the property could most likely not be parsed
+                            assert_not_equals(data.transition.from, data.transition.to, "initial and target values may not match");
+                            // kick off the transition
+                            generalParallelTest.startTransition(data);
+
+                            // make sure we didn't get the target value immediately.
+                            // If we did, there wouldn't be a transition!
+                            var current = data.transition.computedStyle(data.property);
+                            assert_not_equals(current, data.transition.to, "must not be target value after start");
+                        },
+                        done: function(test, data, options) {
+                            // make sure the property's value were neither initial nor target while transitioning
+                            test.step(generalParallelTest.assertIntermediateValuesFunc(data, 'transition'));
+                        }
+                    },
+                    // test TransitionEnd events
+                    'events': {
+                        done: function(test, data, options) {
+                            // make sure there were no events on parent
+                            test.step(generalParallelTest.assertExpectedEventsFunc(data, 'container', ""));
+                            // make sure we got the event for the tested property only
+                            test.step(generalParallelTest.assertExpectedEventsFunc(data, 'transition', addVendorPrefix(data.property) + ":" + duration));
+                        }
+                    }
+                },
+                // called once all tests are done
+                done: generalParallelTest.done
+            });
+        </script>
+    </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-inherit-001-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-inherit-001-expected.txt
new file mode 100644
index 0000000..4b2acfc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-inherit-001-expected.txt
@@ -0,0 +1,566 @@
+This is a testharness.js-based test.
+Found 562 tests; 548 PASS, 14 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS background-color color(rgba) / values
+PASS background-color color(rgba) / events
+PASS background-position length(pt) / values
+FAIL background-position length(pt) / events assert_equals: Expected TransitionEnd events triggered on .container expected "background-position:0.5s" but got "background-position-x:0.5s"
+PASS background-position length(pc) / values
+FAIL background-position length(pc) / events assert_equals: Expected TransitionEnd events triggered on .container expected "background-position:0.5s" but got "background-position-x:0.5s"
+PASS background-position length(px) / values
+FAIL background-position length(px) / events assert_equals: Expected TransitionEnd events triggered on .container expected "background-position:0.5s" but got "background-position-x:0.5s"
+PASS background-position length(em) / values
+FAIL background-position length(em) / events assert_equals: Expected TransitionEnd events triggered on .container expected "background-position:0.5s" but got "background-position-x:0.5s"
+PASS background-position length(ex) / values
+FAIL background-position length(ex) / events assert_equals: Expected TransitionEnd events triggered on .container expected "background-position:0.5s" but got "background-position-x:0.5s"
+PASS background-position length(mm) / values
+FAIL background-position length(mm) / events assert_equals: Expected TransitionEnd events triggered on .container expected "background-position:0.5s" but got "background-position-x:0.5s"
+PASS background-position length(cm) / values
+FAIL background-position length(cm) / events assert_equals: Expected TransitionEnd events triggered on .container expected "background-position:0.5s" but got "background-position-x:0.5s"
+PASS background-position length(in) / values
+FAIL background-position length(in) / events assert_equals: Expected TransitionEnd events triggered on .container expected "background-position:0.5s" but got "background-position-x:0.5s"
+PASS background-position percentage(%) / values
+FAIL background-position percentage(%) / events assert_equals: Expected TransitionEnd events triggered on .container expected "background-position:0.5s" but got "background-position-x:0.5s"
+PASS border-top-width length(pt) / values
+PASS border-top-width length(pt) / events
+PASS border-top-width length(pc) / values
+PASS border-top-width length(pc) / events
+PASS border-top-width length(px) / values
+PASS border-top-width length(px) / events
+PASS border-top-width length(em) / values
+PASS border-top-width length(em) / events
+PASS border-top-width length(ex) / values
+PASS border-top-width length(ex) / events
+PASS border-top-width length(mm) / values
+PASS border-top-width length(mm) / events
+PASS border-top-width length(cm) / values
+PASS border-top-width length(cm) / events
+PASS border-top-width length(in) / values
+PASS border-top-width length(in) / events
+PASS border-right-width length(pt) / values
+PASS border-right-width length(pt) / events
+PASS border-right-width length(pc) / values
+PASS border-right-width length(pc) / events
+PASS border-right-width length(px) / values
+PASS border-right-width length(px) / events
+PASS border-right-width length(em) / values
+PASS border-right-width length(em) / events
+PASS border-right-width length(ex) / values
+PASS border-right-width length(ex) / events
+PASS border-right-width length(mm) / values
+PASS border-right-width length(mm) / events
+PASS border-right-width length(cm) / values
+PASS border-right-width length(cm) / events
+PASS border-right-width length(in) / values
+PASS border-right-width length(in) / events
+PASS border-bottom-width length(pt) / values
+PASS border-bottom-width length(pt) / events
+PASS border-bottom-width length(pc) / values
+PASS border-bottom-width length(pc) / events
+PASS border-bottom-width length(px) / values
+PASS border-bottom-width length(px) / events
+PASS border-bottom-width length(em) / values
+PASS border-bottom-width length(em) / events
+PASS border-bottom-width length(ex) / values
+PASS border-bottom-width length(ex) / events
+PASS border-bottom-width length(mm) / values
+PASS border-bottom-width length(mm) / events
+PASS border-bottom-width length(cm) / values
+PASS border-bottom-width length(cm) / events
+PASS border-bottom-width length(in) / values
+PASS border-bottom-width length(in) / events
+PASS border-left-width length(pt) / values
+PASS border-left-width length(pt) / events
+PASS border-left-width length(pc) / values
+PASS border-left-width length(pc) / events
+PASS border-left-width length(px) / values
+PASS border-left-width length(px) / events
+PASS border-left-width length(em) / values
+PASS border-left-width length(em) / events
+PASS border-left-width length(ex) / values
+PASS border-left-width length(ex) / events
+PASS border-left-width length(mm) / values
+PASS border-left-width length(mm) / events
+PASS border-left-width length(cm) / values
+PASS border-left-width length(cm) / events
+PASS border-left-width length(in) / values
+PASS border-left-width length(in) / events
+PASS border-top-color color(rgba) / values
+PASS border-top-color color(rgba) / events
+PASS border-right-color color(rgba) / values
+PASS border-right-color color(rgba) / events
+PASS border-bottom-color color(rgba) / values
+PASS border-bottom-color color(rgba) / events
+PASS border-left-color color(rgba) / values
+PASS border-left-color color(rgba) / events
+PASS padding-bottom length(pt) / values
+PASS padding-bottom length(pt) / events
+PASS padding-bottom length(pc) / values
+PASS padding-bottom length(pc) / events
+PASS padding-bottom length(px) / values
+PASS padding-bottom length(px) / events
+PASS padding-bottom length(em) / values
+PASS padding-bottom length(em) / events
+PASS padding-bottom length(ex) / values
+PASS padding-bottom length(ex) / events
+PASS padding-bottom length(mm) / values
+PASS padding-bottom length(mm) / events
+PASS padding-bottom length(cm) / values
+PASS padding-bottom length(cm) / events
+PASS padding-bottom length(in) / values
+PASS padding-bottom length(in) / events
+PASS padding-left length(pt) / values
+PASS padding-left length(pt) / events
+PASS padding-left length(pc) / values
+PASS padding-left length(pc) / events
+PASS padding-left length(px) / values
+PASS padding-left length(px) / events
+PASS padding-left length(em) / values
+PASS padding-left length(em) / events
+PASS padding-left length(ex) / values
+PASS padding-left length(ex) / events
+PASS padding-left length(mm) / values
+PASS padding-left length(mm) / events
+PASS padding-left length(cm) / values
+PASS padding-left length(cm) / events
+PASS padding-left length(in) / values
+PASS padding-left length(in) / events
+PASS padding-right length(pt) / values
+PASS padding-right length(pt) / events
+PASS padding-right length(pc) / values
+PASS padding-right length(pc) / events
+PASS padding-right length(px) / values
+PASS padding-right length(px) / events
+PASS padding-right length(em) / values
+PASS padding-right length(em) / events
+PASS padding-right length(ex) / values
+PASS padding-right length(ex) / events
+PASS padding-right length(mm) / values
+PASS padding-right length(mm) / events
+PASS padding-right length(cm) / values
+PASS padding-right length(cm) / events
+PASS padding-right length(in) / values
+PASS padding-right length(in) / events
+PASS padding-top length(pt) / values
+PASS padding-top length(pt) / events
+PASS padding-top length(pc) / values
+PASS padding-top length(pc) / events
+PASS padding-top length(px) / values
+PASS padding-top length(px) / events
+PASS padding-top length(em) / values
+PASS padding-top length(em) / events
+PASS padding-top length(ex) / values
+PASS padding-top length(ex) / events
+PASS padding-top length(mm) / values
+PASS padding-top length(mm) / events
+PASS padding-top length(cm) / values
+PASS padding-top length(cm) / events
+PASS padding-top length(in) / values
+PASS padding-top length(in) / events
+PASS margin-bottom length(pt) / values
+PASS margin-bottom length(pt) / events
+PASS margin-bottom length(pc) / values
+PASS margin-bottom length(pc) / events
+PASS margin-bottom length(px) / values
+PASS margin-bottom length(px) / events
+PASS margin-bottom length(em) / values
+PASS margin-bottom length(em) / events
+PASS margin-bottom length(ex) / values
+PASS margin-bottom length(ex) / events
+PASS margin-bottom length(mm) / values
+PASS margin-bottom length(mm) / events
+PASS margin-bottom length(cm) / values
+PASS margin-bottom length(cm) / events
+PASS margin-bottom length(in) / values
+PASS margin-bottom length(in) / events
+PASS margin-left length(pt) / values
+PASS margin-left length(pt) / events
+PASS margin-left length(pc) / values
+PASS margin-left length(pc) / events
+PASS margin-left length(px) / values
+PASS margin-left length(px) / events
+PASS margin-left length(em) / values
+PASS margin-left length(em) / events
+PASS margin-left length(ex) / values
+PASS margin-left length(ex) / events
+PASS margin-left length(mm) / values
+PASS margin-left length(mm) / events
+PASS margin-left length(cm) / values
+PASS margin-left length(cm) / events
+PASS margin-left length(in) / values
+PASS margin-left length(in) / events
+PASS margin-right length(pt) / values
+PASS margin-right length(pt) / events
+PASS margin-right length(pc) / values
+PASS margin-right length(pc) / events
+PASS margin-right length(px) / values
+PASS margin-right length(px) / events
+PASS margin-right length(em) / values
+PASS margin-right length(em) / events
+PASS margin-right length(ex) / values
+PASS margin-right length(ex) / events
+PASS margin-right length(mm) / values
+PASS margin-right length(mm) / events
+PASS margin-right length(cm) / values
+PASS margin-right length(cm) / events
+PASS margin-right length(in) / values
+PASS margin-right length(in) / events
+PASS margin-top length(pt) / values
+PASS margin-top length(pt) / events
+PASS margin-top length(pc) / values
+PASS margin-top length(pc) / events
+PASS margin-top length(px) / values
+PASS margin-top length(px) / events
+PASS margin-top length(em) / values
+PASS margin-top length(em) / events
+PASS margin-top length(ex) / values
+PASS margin-top length(ex) / events
+PASS margin-top length(mm) / values
+PASS margin-top length(mm) / events
+PASS margin-top length(cm) / values
+PASS margin-top length(cm) / events
+PASS margin-top length(in) / values
+PASS margin-top length(in) / events
+PASS height length(pt) / values
+PASS height length(pt) / events
+PASS height length(pc) / values
+PASS height length(pc) / events
+PASS height length(px) / values
+PASS height length(px) / events
+PASS height length(em) / values
+PASS height length(em) / events
+PASS height length(ex) / values
+PASS height length(ex) / events
+PASS height length(mm) / values
+PASS height length(mm) / events
+PASS height length(cm) / values
+PASS height length(cm) / events
+PASS height length(in) / values
+PASS height length(in) / events
+PASS height percentage(%) / values
+PASS height percentage(%) / events
+PASS width length(pt) / values
+PASS width length(pt) / events
+PASS width length(pc) / values
+PASS width length(pc) / events
+PASS width length(px) / values
+PASS width length(px) / events
+PASS width length(em) / values
+PASS width length(em) / events
+PASS width length(ex) / values
+PASS width length(ex) / events
+PASS width length(mm) / values
+PASS width length(mm) / events
+PASS width length(cm) / values
+PASS width length(cm) / events
+PASS width length(in) / values
+PASS width length(in) / events
+PASS width percentage(%) / values
+PASS width percentage(%) / events
+PASS min-height length(pt) / values
+PASS min-height length(pt) / events
+PASS min-height length(pc) / values
+PASS min-height length(pc) / events
+PASS min-height length(px) / values
+PASS min-height length(px) / events
+PASS min-height length(em) / values
+PASS min-height length(em) / events
+PASS min-height length(ex) / values
+PASS min-height length(ex) / events
+PASS min-height length(mm) / values
+PASS min-height length(mm) / events
+PASS min-height length(cm) / values
+PASS min-height length(cm) / events
+PASS min-height length(in) / values
+PASS min-height length(in) / events
+PASS min-height percentage(%) / values
+PASS min-height percentage(%) / events
+PASS min-width length(pt) / values
+PASS min-width length(pt) / events
+PASS min-width length(pc) / values
+PASS min-width length(pc) / events
+PASS min-width length(px) / values
+PASS min-width length(px) / events
+PASS min-width length(em) / values
+PASS min-width length(em) / events
+PASS min-width length(ex) / values
+PASS min-width length(ex) / events
+PASS min-width length(mm) / values
+PASS min-width length(mm) / events
+PASS min-width length(cm) / values
+PASS min-width length(cm) / events
+PASS min-width length(in) / values
+PASS min-width length(in) / events
+PASS min-width percentage(%) / values
+PASS min-width percentage(%) / events
+PASS max-height length(pt) / values
+PASS max-height length(pt) / events
+PASS max-height length(pc) / values
+PASS max-height length(pc) / events
+PASS max-height length(px) / values
+PASS max-height length(px) / events
+PASS max-height length(em) / values
+PASS max-height length(em) / events
+PASS max-height length(ex) / values
+PASS max-height length(ex) / events
+PASS max-height length(mm) / values
+PASS max-height length(mm) / events
+PASS max-height length(cm) / values
+PASS max-height length(cm) / events
+PASS max-height length(in) / values
+PASS max-height length(in) / events
+PASS max-height percentage(%) / values
+PASS max-height percentage(%) / events
+PASS max-width length(pt) / values
+PASS max-width length(pt) / events
+PASS max-width length(pc) / values
+PASS max-width length(pc) / events
+PASS max-width length(px) / values
+PASS max-width length(px) / events
+PASS max-width length(em) / values
+PASS max-width length(em) / events
+PASS max-width length(ex) / values
+PASS max-width length(ex) / events
+PASS max-width length(mm) / values
+PASS max-width length(mm) / events
+PASS max-width length(cm) / values
+PASS max-width length(cm) / events
+PASS max-width length(in) / values
+PASS max-width length(in) / events
+PASS max-width percentage(%) / values
+PASS max-width percentage(%) / events
+PASS top length(pt) / values
+PASS top length(pt) / events
+PASS top length(pc) / values
+PASS top length(pc) / events
+PASS top length(px) / values
+PASS top length(px) / events
+PASS top length(em) / values
+PASS top length(em) / events
+PASS top length(ex) / values
+PASS top length(ex) / events
+PASS top length(mm) / values
+PASS top length(mm) / events
+PASS top length(cm) / values
+PASS top length(cm) / events
+PASS top length(in) / values
+PASS top length(in) / events
+PASS top percentage(%) / values
+PASS top percentage(%) / events
+PASS right length(pt) / values
+PASS right length(pt) / events
+PASS right length(pc) / values
+PASS right length(pc) / events
+PASS right length(px) / values
+PASS right length(px) / events
+PASS right length(em) / values
+PASS right length(em) / events
+PASS right length(ex) / values
+PASS right length(ex) / events
+PASS right length(mm) / values
+PASS right length(mm) / events
+PASS right length(cm) / values
+PASS right length(cm) / events
+PASS right length(in) / values
+PASS right length(in) / events
+PASS right percentage(%) / values
+PASS right percentage(%) / events
+PASS bottom length(pt) / values
+PASS bottom length(pt) / events
+PASS bottom length(pc) / values
+PASS bottom length(pc) / events
+PASS bottom length(px) / values
+PASS bottom length(px) / events
+PASS bottom length(em) / values
+PASS bottom length(em) / events
+PASS bottom length(ex) / values
+PASS bottom length(ex) / events
+PASS bottom length(mm) / values
+PASS bottom length(mm) / events
+PASS bottom length(cm) / values
+PASS bottom length(cm) / events
+PASS bottom length(in) / values
+PASS bottom length(in) / events
+PASS bottom percentage(%) / values
+PASS bottom percentage(%) / events
+PASS left length(pt) / values
+PASS left length(pt) / events
+PASS left length(pc) / values
+PASS left length(pc) / events
+PASS left length(px) / values
+PASS left length(px) / events
+PASS left length(em) / values
+PASS left length(em) / events
+PASS left length(ex) / values
+PASS left length(ex) / events
+PASS left length(mm) / values
+PASS left length(mm) / events
+PASS left length(cm) / values
+PASS left length(cm) / events
+PASS left length(in) / values
+PASS left length(in) / events
+PASS left percentage(%) / values
+PASS left percentage(%) / events
+PASS color color(rgba) / values
+PASS color color(rgba) / events
+PASS font-size length(pt) / values
+PASS font-size length(pt) / events
+PASS font-size length(pc) / values
+PASS font-size length(pc) / events
+PASS font-size length(px) / values
+PASS font-size length(px) / events
+PASS font-size length(em) / values
+PASS font-size length(em) / events
+PASS font-size length(ex) / values
+PASS font-size length(ex) / events
+PASS font-size length(mm) / values
+PASS font-size length(mm) / events
+PASS font-size length(cm) / values
+PASS font-size length(cm) / events
+PASS font-size length(in) / values
+PASS font-size length(in) / events
+PASS font-size percentage(%) / values
+PASS font-size percentage(%) / events
+PASS font-weight font-weight(keyword) / values
+PASS font-weight font-weight(keyword) / events
+PASS font-weight font-weight(numeric) / values
+PASS font-weight font-weight(numeric) / events
+PASS line-height number(integer) / values
+PASS line-height number(integer) / events
+PASS line-height number(decimal) / values
+PASS line-height number(decimal) / events
+PASS line-height length(pt) / values
+PASS line-height length(pt) / events
+PASS line-height length(pc) / values
+PASS line-height length(pc) / events
+PASS line-height length(px) / values
+PASS line-height length(px) / events
+PASS line-height length(em) / values
+PASS line-height length(em) / events
+PASS line-height length(ex) / values
+PASS line-height length(ex) / events
+PASS line-height length(mm) / values
+PASS line-height length(mm) / events
+PASS line-height length(cm) / values
+PASS line-height length(cm) / events
+PASS line-height length(in) / values
+PASS line-height length(in) / events
+PASS line-height percentage(%) / values
+PASS line-height percentage(%) / events
+PASS letter-spacing length(pt) / values
+PASS letter-spacing length(pt) / events
+PASS letter-spacing length(pc) / values
+PASS letter-spacing length(pc) / events
+PASS letter-spacing length(px) / values
+PASS letter-spacing length(px) / events
+PASS letter-spacing length(em) / values
+PASS letter-spacing length(em) / events
+PASS letter-spacing length(ex) / values
+PASS letter-spacing length(ex) / events
+PASS letter-spacing length(mm) / values
+PASS letter-spacing length(mm) / events
+PASS letter-spacing length(cm) / values
+PASS letter-spacing length(cm) / events
+PASS letter-spacing length(in) / values
+PASS letter-spacing length(in) / events
+PASS word-spacing length(pt) / values
+PASS word-spacing length(pt) / events
+PASS word-spacing length(pc) / values
+PASS word-spacing length(pc) / events
+PASS word-spacing length(px) / values
+PASS word-spacing length(px) / events
+PASS word-spacing length(em) / values
+PASS word-spacing length(em) / events
+PASS word-spacing length(ex) / values
+PASS word-spacing length(ex) / events
+PASS word-spacing length(mm) / values
+PASS word-spacing length(mm) / events
+PASS word-spacing length(cm) / values
+PASS word-spacing length(cm) / events
+PASS word-spacing length(in) / values
+PASS word-spacing length(in) / events
+FAIL word-spacing percentage(%) / values assert_not_equals: initial and target values may not match got disallowed value "0px"
+FAIL word-spacing percentage(%) / events assert_equals: Expected TransitionEnd events triggered on .container expected "word-spacing:0.5s" but got ""
+PASS text-indent length(pt) / values
+PASS text-indent length(pt) / events
+PASS text-indent length(pc) / values
+PASS text-indent length(pc) / events
+PASS text-indent length(px) / values
+PASS text-indent length(px) / events
+PASS text-indent length(em) / values
+PASS text-indent length(em) / events
+PASS text-indent length(ex) / values
+PASS text-indent length(ex) / events
+PASS text-indent length(mm) / values
+PASS text-indent length(mm) / events
+PASS text-indent length(cm) / values
+PASS text-indent length(cm) / events
+PASS text-indent length(in) / values
+PASS text-indent length(in) / events
+PASS text-indent percentage(%) / values
+PASS text-indent percentage(%) / events
+PASS text-shadow shadow(shadow) / values
+PASS text-shadow shadow(shadow) / events
+PASS outline-color color(rgba) / values
+PASS outline-color color(rgba) / events
+PASS outline-offset length(pt) / values
+PASS outline-offset length(pt) / events
+PASS outline-offset length(pc) / values
+PASS outline-offset length(pc) / events
+PASS outline-offset length(px) / values
+PASS outline-offset length(px) / events
+PASS outline-offset length(em) / values
+PASS outline-offset length(em) / events
+PASS outline-offset length(ex) / values
+PASS outline-offset length(ex) / events
+PASS outline-offset length(mm) / values
+PASS outline-offset length(mm) / events
+PASS outline-offset length(cm) / values
+PASS outline-offset length(cm) / events
+PASS outline-offset length(in) / values
+PASS outline-offset length(in) / events
+PASS outline-width length(pt) / values
+PASS outline-width length(pt) / events
+PASS outline-width length(pc) / values
+PASS outline-width length(pc) / events
+PASS outline-width length(px) / values
+PASS outline-width length(px) / events
+PASS outline-width length(em) / values
+PASS outline-width length(em) / events
+PASS outline-width length(ex) / values
+PASS outline-width length(ex) / events
+PASS outline-width length(mm) / values
+PASS outline-width length(mm) / events
+PASS outline-width length(cm) / values
+PASS outline-width length(cm) / events
+PASS outline-width length(in) / values
+PASS outline-width length(in) / events
+PASS clip rectangle(rectangle) / values
+PASS clip rectangle(rectangle) / events
+FAIL crop rectangle(rectangle) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL crop rectangle(rectangle) / events assert_equals: Expected TransitionEnd events triggered on .container expected "crop:0.5s" but got ""
+PASS vertical-align length(pt) / values
+PASS vertical-align length(pt) / events
+PASS vertical-align length(pc) / values
+PASS vertical-align length(pc) / events
+PASS vertical-align length(px) / values
+PASS vertical-align length(px) / events
+PASS vertical-align length(em) / values
+PASS vertical-align length(em) / events
+PASS vertical-align length(ex) / values
+PASS vertical-align length(ex) / events
+PASS vertical-align length(mm) / values
+PASS vertical-align length(mm) / events
+PASS vertical-align length(cm) / values
+PASS vertical-align length(cm) / events
+PASS vertical-align length(in) / values
+PASS vertical-align length(in) / events
+PASS vertical-align percentage(%) / values
+PASS vertical-align percentage(%) / events
+PASS opacity number[0,1](zero-to-one) / values
+PASS opacity number[0,1](zero-to-one) / events
+FAIL visibility visibility(keyword) / values assert_equals: must be target value after transitioning on .transition expected (string) "hidden" but got (undefined) undefined
+PASS visibility visibility(keyword) / events
+PASS z-index integer(integer) / values
+PASS z-index integer(integer) / events
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-inherit-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-inherit-001.html
new file mode 100644
index 0000000..2de40b4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-inherit-001.html
@@ -0,0 +1,144 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>CSS Transitions Test: transitioning inherited property values</title>
+        <meta name="assert" content="Test checks that inherited property values that are transitioned on a parent element don't start a transition">
+        <link rel="help" title="3. Starting of transitions" href="http://www.w3.org/TR/css3-transitions/#starting">
+        <link rel="author" title="Rodney Rehm" href="http://rodneyrehm.de/en/">
+        <meta name="flags" content="dom ">
+
+        <script src="/resources/testharness.js" type="text/javascript"></script>
+        <script src="/resources/testharnessreport.js" type="text/javascript"></script>
+
+        <script src="./support/vendorPrefix.js" type="text/javascript"></script>
+        <script src="./support/helper.js" type="text/javascript"></script>
+        <script src="./support/runParallelAsyncHarness.js" type="text/javascript"></script>
+        <script src="./support/generalParallelTest.js" type="text/javascript"></script>
+        <script src="./support/properties.js" type="text/javascript"></script>
+
+        <style type="text/css">
+            #offscreen {
+                position: absolute;
+                top: -100000px;
+                left: -100000px;
+                width: 100000px;
+                height: 100000px;
+            }
+        </style>
+    </head>
+    <body>
+        <!-- required by testharnessreport.js -->
+        <div id="log"></div>
+        <!-- elements used for testing -->
+        <div id="fixture" class="fixture">
+            <div class="container">
+                <div class="transition">Text sample</div>
+            </div>
+        </div>
+        <div id="offscreen"></div>
+
+        <!--
+            SEE ./support/README.md for an abstract explanation of the test procedure
+            http://test.csswg.org/source/contributors/rodneyrehm/submitted/css3-transitions/README.md
+        -->
+
+        <script>
+            // http://www.w3.org/TR/css3-transitions/#starting
+            // Implementations also must not start a transition when the computed value changes because
+            // it is inherited (directly or indirectly) from another element that is transitioning the same property.
+
+            // this test takes its time, give it a minute to run
+            var timeout = 60000;
+            setup({timeout: timeout});
+
+            var tests = getPropertyTests();
+            // for testing, limit to a couple of iterations
+            // tests = tests.slice(10, 30);
+            // or filter using one of:
+            // tests = filterPropertyTests(tests, "background-color color(rgba)");
+            // tests = filterPropertyTests(tests, ["background-color color(rgba)", ...]);
+            // tests = filterPropertyTests(tests, /^background-color/);
+
+            // general transition-duration
+            var duration = '0.5s';
+
+            runParallelAsyncHarness({
+                // array of test data
+                tests: tests,
+                // the number of tests to run in parallel
+                testsPerSlice: 50,
+                // milliseconds to wait before calling teardown and ending test
+                duration: parseFloat(duration) * 1000,
+                // the global suite timeout
+                timeout: timeout,
+                // prepare individual test
+                setup: function(data, options) {
+                    // clone and overwrite initial styles to be
+                    // applied to #transition
+                    var inherited = extend({}, data.from);
+                    inherited[data.property] = 'inherit';
+
+                    var styles = {
+                        // as we're testing inheritance, #fixture is our new parent
+                        '.fixture': data.parentStyle,
+                        // all styles including transition apply to to #container so they
+                        // can inherit down to #transition
+                        '.container': extend({}, data.parentStyle, data.from),
+                        '.container.to': data.to,
+                        '.container.how': {transition: addVendorPrefix(data.property) + ' ' + duration + ' linear 0s'},
+                        // #transition only inherits and listens for transition events
+                        '.transition': inherited,
+                        '.transition.to' : {},
+                        '.transition.how' : {transition: addVendorPrefix(data.property) + ' ' + duration + ' linear 0s'}
+                    };
+
+                    generalParallelTest.setup(data, options);
+                    generalParallelTest.addStyles(data, options, styles);
+                },
+                // cleanup after individual test
+                teardown: generalParallelTest.teardown,
+                // invoked prior to running a slice of tests
+                sliceStart: generalParallelTest.sliceStart,
+                // invoked after running a slice of tests
+                sliceDone: generalParallelTest.sliceDone,
+                // test cases, make them as granular as possible
+                cases: {
+                    // test property values while transitioning
+                    // values.start kicks off a transition
+                    'values': {
+                        // run actual test, assertions can be used here!
+                        start: function(test, data, options) {
+                            // identify initial and target values
+                            generalParallelTest.getStyle(data);
+                            // make sure values differ, if they don't, the property could most likely not be parsed
+                            assert_not_equals(data.transition.from, data.transition.to, "initial and target values may not match");
+                            // kick off the transition
+                            generalParallelTest.startTransition(data);
+
+                            // make sure we didn't get the target value immediately.
+                            // If we did, there wouldn't be a transition!
+                            var current = data.transition.computedStyle(data.property);
+                            assert_not_equals(current, data.transition.to, "must not be target value after start");
+                        },
+                        done: function(test, data, options) {
+                            // make sure the property's value were neither initial nor target while transitioning
+                            test.step(generalParallelTest.assertIntermediateValuesFunc(data, 'transition'));
+                        }
+                    },
+                    // test TransitionEnd events
+                    'events': {
+                        done: function(test, data, options) {
+                            // make sure there were no events on parent
+                            test.step(generalParallelTest.assertExpectedEventsFunc(data, 'container', addVendorPrefix(data.property) + ":" + duration));
+                            // make sure we got the event for the tested property only
+                            test.step(generalParallelTest.assertExpectedEventsFunc(data, 'transition', ""));
+                        }
+                    }
+                },
+                // called once all tests are done
+                done: generalParallelTest.done
+            });
+        </script>
+    </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-inherit-002-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-inherit-002-expected.txt
new file mode 100644
index 0000000..e7f8cfe
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-inherit-002-expected.txt
@@ -0,0 +1,566 @@
+This is a testharness.js-based test.
+Found 562 tests; 549 PASS, 13 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS background-color color(rgba) / values
+PASS background-color color(rgba) / events
+PASS background-position length(pt) / values
+FAIL background-position length(pt) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "background-position:0.5s" but got "background-position-x:0.5s"
+PASS background-position length(pc) / values
+FAIL background-position length(pc) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "background-position:0.5s" but got "background-position-x:0.5s"
+PASS background-position length(px) / values
+FAIL background-position length(px) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "background-position:0.5s" but got "background-position-x:0.5s"
+PASS background-position length(em) / values
+FAIL background-position length(em) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "background-position:0.5s" but got "background-position-x:0.5s"
+PASS background-position length(ex) / values
+FAIL background-position length(ex) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "background-position:0.5s" but got "background-position-x:0.5s"
+PASS background-position length(mm) / values
+FAIL background-position length(mm) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "background-position:0.5s" but got "background-position-x:0.5s"
+PASS background-position length(cm) / values
+FAIL background-position length(cm) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "background-position:0.5s" but got "background-position-x:0.5s"
+PASS background-position length(in) / values
+FAIL background-position length(in) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "background-position:0.5s" but got "background-position-x:0.5s"
+PASS background-position percentage(%) / values
+FAIL background-position percentage(%) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "background-position:0.5s" but got "background-position-x:0.5s"
+PASS border-top-width length(pt) / values
+PASS border-top-width length(pt) / events
+PASS border-top-width length(pc) / values
+PASS border-top-width length(pc) / events
+PASS border-top-width length(px) / values
+PASS border-top-width length(px) / events
+PASS border-top-width length(em) / values
+PASS border-top-width length(em) / events
+PASS border-top-width length(ex) / values
+PASS border-top-width length(ex) / events
+PASS border-top-width length(mm) / values
+PASS border-top-width length(mm) / events
+PASS border-top-width length(cm) / values
+PASS border-top-width length(cm) / events
+PASS border-top-width length(in) / values
+PASS border-top-width length(in) / events
+PASS border-right-width length(pt) / values
+PASS border-right-width length(pt) / events
+PASS border-right-width length(pc) / values
+PASS border-right-width length(pc) / events
+PASS border-right-width length(px) / values
+PASS border-right-width length(px) / events
+PASS border-right-width length(em) / values
+PASS border-right-width length(em) / events
+PASS border-right-width length(ex) / values
+PASS border-right-width length(ex) / events
+PASS border-right-width length(mm) / values
+PASS border-right-width length(mm) / events
+PASS border-right-width length(cm) / values
+PASS border-right-width length(cm) / events
+PASS border-right-width length(in) / values
+PASS border-right-width length(in) / events
+PASS border-bottom-width length(pt) / values
+PASS border-bottom-width length(pt) / events
+PASS border-bottom-width length(pc) / values
+PASS border-bottom-width length(pc) / events
+PASS border-bottom-width length(px) / values
+PASS border-bottom-width length(px) / events
+PASS border-bottom-width length(em) / values
+PASS border-bottom-width length(em) / events
+PASS border-bottom-width length(ex) / values
+PASS border-bottom-width length(ex) / events
+PASS border-bottom-width length(mm) / values
+PASS border-bottom-width length(mm) / events
+PASS border-bottom-width length(cm) / values
+PASS border-bottom-width length(cm) / events
+PASS border-bottom-width length(in) / values
+PASS border-bottom-width length(in) / events
+PASS border-left-width length(pt) / values
+PASS border-left-width length(pt) / events
+PASS border-left-width length(pc) / values
+PASS border-left-width length(pc) / events
+PASS border-left-width length(px) / values
+PASS border-left-width length(px) / events
+PASS border-left-width length(em) / values
+PASS border-left-width length(em) / events
+PASS border-left-width length(ex) / values
+PASS border-left-width length(ex) / events
+PASS border-left-width length(mm) / values
+PASS border-left-width length(mm) / events
+PASS border-left-width length(cm) / values
+PASS border-left-width length(cm) / events
+PASS border-left-width length(in) / values
+PASS border-left-width length(in) / events
+PASS border-top-color color(rgba) / values
+PASS border-top-color color(rgba) / events
+PASS border-right-color color(rgba) / values
+PASS border-right-color color(rgba) / events
+PASS border-bottom-color color(rgba) / values
+PASS border-bottom-color color(rgba) / events
+PASS border-left-color color(rgba) / values
+PASS border-left-color color(rgba) / events
+PASS padding-bottom length(pt) / values
+PASS padding-bottom length(pt) / events
+PASS padding-bottom length(pc) / values
+PASS padding-bottom length(pc) / events
+PASS padding-bottom length(px) / values
+PASS padding-bottom length(px) / events
+PASS padding-bottom length(em) / values
+PASS padding-bottom length(em) / events
+PASS padding-bottom length(ex) / values
+PASS padding-bottom length(ex) / events
+PASS padding-bottom length(mm) / values
+PASS padding-bottom length(mm) / events
+PASS padding-bottom length(cm) / values
+PASS padding-bottom length(cm) / events
+PASS padding-bottom length(in) / values
+PASS padding-bottom length(in) / events
+PASS padding-left length(pt) / values
+PASS padding-left length(pt) / events
+PASS padding-left length(pc) / values
+PASS padding-left length(pc) / events
+PASS padding-left length(px) / values
+PASS padding-left length(px) / events
+PASS padding-left length(em) / values
+PASS padding-left length(em) / events
+PASS padding-left length(ex) / values
+PASS padding-left length(ex) / events
+PASS padding-left length(mm) / values
+PASS padding-left length(mm) / events
+PASS padding-left length(cm) / values
+PASS padding-left length(cm) / events
+PASS padding-left length(in) / values
+PASS padding-left length(in) / events
+PASS padding-right length(pt) / values
+PASS padding-right length(pt) / events
+PASS padding-right length(pc) / values
+PASS padding-right length(pc) / events
+PASS padding-right length(px) / values
+PASS padding-right length(px) / events
+PASS padding-right length(em) / values
+PASS padding-right length(em) / events
+PASS padding-right length(ex) / values
+PASS padding-right length(ex) / events
+PASS padding-right length(mm) / values
+PASS padding-right length(mm) / events
+PASS padding-right length(cm) / values
+PASS padding-right length(cm) / events
+PASS padding-right length(in) / values
+PASS padding-right length(in) / events
+PASS padding-top length(pt) / values
+PASS padding-top length(pt) / events
+PASS padding-top length(pc) / values
+PASS padding-top length(pc) / events
+PASS padding-top length(px) / values
+PASS padding-top length(px) / events
+PASS padding-top length(em) / values
+PASS padding-top length(em) / events
+PASS padding-top length(ex) / values
+PASS padding-top length(ex) / events
+PASS padding-top length(mm) / values
+PASS padding-top length(mm) / events
+PASS padding-top length(cm) / values
+PASS padding-top length(cm) / events
+PASS padding-top length(in) / values
+PASS padding-top length(in) / events
+PASS margin-bottom length(pt) / values
+PASS margin-bottom length(pt) / events
+PASS margin-bottom length(pc) / values
+PASS margin-bottom length(pc) / events
+PASS margin-bottom length(px) / values
+PASS margin-bottom length(px) / events
+PASS margin-bottom length(em) / values
+PASS margin-bottom length(em) / events
+PASS margin-bottom length(ex) / values
+PASS margin-bottom length(ex) / events
+PASS margin-bottom length(mm) / values
+PASS margin-bottom length(mm) / events
+PASS margin-bottom length(cm) / values
+PASS margin-bottom length(cm) / events
+PASS margin-bottom length(in) / values
+PASS margin-bottom length(in) / events
+PASS margin-left length(pt) / values
+PASS margin-left length(pt) / events
+PASS margin-left length(pc) / values
+PASS margin-left length(pc) / events
+PASS margin-left length(px) / values
+PASS margin-left length(px) / events
+PASS margin-left length(em) / values
+PASS margin-left length(em) / events
+PASS margin-left length(ex) / values
+PASS margin-left length(ex) / events
+PASS margin-left length(mm) / values
+PASS margin-left length(mm) / events
+PASS margin-left length(cm) / values
+PASS margin-left length(cm) / events
+PASS margin-left length(in) / values
+PASS margin-left length(in) / events
+PASS margin-right length(pt) / values
+PASS margin-right length(pt) / events
+PASS margin-right length(pc) / values
+PASS margin-right length(pc) / events
+PASS margin-right length(px) / values
+PASS margin-right length(px) / events
+PASS margin-right length(em) / values
+PASS margin-right length(em) / events
+PASS margin-right length(ex) / values
+PASS margin-right length(ex) / events
+PASS margin-right length(mm) / values
+PASS margin-right length(mm) / events
+PASS margin-right length(cm) / values
+PASS margin-right length(cm) / events
+PASS margin-right length(in) / values
+PASS margin-right length(in) / events
+PASS margin-top length(pt) / values
+PASS margin-top length(pt) / events
+PASS margin-top length(pc) / values
+PASS margin-top length(pc) / events
+PASS margin-top length(px) / values
+PASS margin-top length(px) / events
+PASS margin-top length(em) / values
+PASS margin-top length(em) / events
+PASS margin-top length(ex) / values
+PASS margin-top length(ex) / events
+PASS margin-top length(mm) / values
+PASS margin-top length(mm) / events
+PASS margin-top length(cm) / values
+PASS margin-top length(cm) / events
+PASS margin-top length(in) / values
+PASS margin-top length(in) / events
+PASS height length(pt) / values
+PASS height length(pt) / events
+PASS height length(pc) / values
+PASS height length(pc) / events
+PASS height length(px) / values
+PASS height length(px) / events
+PASS height length(em) / values
+PASS height length(em) / events
+PASS height length(ex) / values
+PASS height length(ex) / events
+PASS height length(mm) / values
+PASS height length(mm) / events
+PASS height length(cm) / values
+PASS height length(cm) / events
+PASS height length(in) / values
+PASS height length(in) / events
+PASS height percentage(%) / values
+PASS height percentage(%) / events
+PASS width length(pt) / values
+PASS width length(pt) / events
+PASS width length(pc) / values
+PASS width length(pc) / events
+PASS width length(px) / values
+PASS width length(px) / events
+PASS width length(em) / values
+PASS width length(em) / events
+PASS width length(ex) / values
+PASS width length(ex) / events
+PASS width length(mm) / values
+PASS width length(mm) / events
+PASS width length(cm) / values
+PASS width length(cm) / events
+PASS width length(in) / values
+PASS width length(in) / events
+PASS width percentage(%) / values
+PASS width percentage(%) / events
+PASS min-height length(pt) / values
+PASS min-height length(pt) / events
+PASS min-height length(pc) / values
+PASS min-height length(pc) / events
+PASS min-height length(px) / values
+PASS min-height length(px) / events
+PASS min-height length(em) / values
+PASS min-height length(em) / events
+PASS min-height length(ex) / values
+PASS min-height length(ex) / events
+PASS min-height length(mm) / values
+PASS min-height length(mm) / events
+PASS min-height length(cm) / values
+PASS min-height length(cm) / events
+PASS min-height length(in) / values
+PASS min-height length(in) / events
+PASS min-height percentage(%) / values
+PASS min-height percentage(%) / events
+PASS min-width length(pt) / values
+PASS min-width length(pt) / events
+PASS min-width length(pc) / values
+PASS min-width length(pc) / events
+PASS min-width length(px) / values
+PASS min-width length(px) / events
+PASS min-width length(em) / values
+PASS min-width length(em) / events
+PASS min-width length(ex) / values
+PASS min-width length(ex) / events
+PASS min-width length(mm) / values
+PASS min-width length(mm) / events
+PASS min-width length(cm) / values
+PASS min-width length(cm) / events
+PASS min-width length(in) / values
+PASS min-width length(in) / events
+PASS min-width percentage(%) / values
+PASS min-width percentage(%) / events
+PASS max-height length(pt) / values
+PASS max-height length(pt) / events
+PASS max-height length(pc) / values
+PASS max-height length(pc) / events
+PASS max-height length(px) / values
+PASS max-height length(px) / events
+PASS max-height length(em) / values
+PASS max-height length(em) / events
+PASS max-height length(ex) / values
+PASS max-height length(ex) / events
+PASS max-height length(mm) / values
+PASS max-height length(mm) / events
+PASS max-height length(cm) / values
+PASS max-height length(cm) / events
+PASS max-height length(in) / values
+PASS max-height length(in) / events
+PASS max-height percentage(%) / values
+PASS max-height percentage(%) / events
+PASS max-width length(pt) / values
+PASS max-width length(pt) / events
+PASS max-width length(pc) / values
+PASS max-width length(pc) / events
+PASS max-width length(px) / values
+PASS max-width length(px) / events
+PASS max-width length(em) / values
+PASS max-width length(em) / events
+PASS max-width length(ex) / values
+PASS max-width length(ex) / events
+PASS max-width length(mm) / values
+PASS max-width length(mm) / events
+PASS max-width length(cm) / values
+PASS max-width length(cm) / events
+PASS max-width length(in) / values
+PASS max-width length(in) / events
+PASS max-width percentage(%) / values
+PASS max-width percentage(%) / events
+PASS top length(pt) / values
+PASS top length(pt) / events
+PASS top length(pc) / values
+PASS top length(pc) / events
+PASS top length(px) / values
+PASS top length(px) / events
+PASS top length(em) / values
+PASS top length(em) / events
+PASS top length(ex) / values
+PASS top length(ex) / events
+PASS top length(mm) / values
+PASS top length(mm) / events
+PASS top length(cm) / values
+PASS top length(cm) / events
+PASS top length(in) / values
+PASS top length(in) / events
+PASS top percentage(%) / values
+PASS top percentage(%) / events
+PASS right length(pt) / values
+PASS right length(pt) / events
+PASS right length(pc) / values
+PASS right length(pc) / events
+PASS right length(px) / values
+PASS right length(px) / events
+PASS right length(em) / values
+PASS right length(em) / events
+PASS right length(ex) / values
+PASS right length(ex) / events
+PASS right length(mm) / values
+PASS right length(mm) / events
+PASS right length(cm) / values
+PASS right length(cm) / events
+PASS right length(in) / values
+PASS right length(in) / events
+PASS right percentage(%) / values
+PASS right percentage(%) / events
+PASS bottom length(pt) / values
+PASS bottom length(pt) / events
+PASS bottom length(pc) / values
+PASS bottom length(pc) / events
+PASS bottom length(px) / values
+PASS bottom length(px) / events
+PASS bottom length(em) / values
+PASS bottom length(em) / events
+PASS bottom length(ex) / values
+PASS bottom length(ex) / events
+PASS bottom length(mm) / values
+PASS bottom length(mm) / events
+PASS bottom length(cm) / values
+PASS bottom length(cm) / events
+PASS bottom length(in) / values
+PASS bottom length(in) / events
+PASS bottom percentage(%) / values
+PASS bottom percentage(%) / events
+PASS left length(pt) / values
+PASS left length(pt) / events
+PASS left length(pc) / values
+PASS left length(pc) / events
+PASS left length(px) / values
+PASS left length(px) / events
+PASS left length(em) / values
+PASS left length(em) / events
+PASS left length(ex) / values
+PASS left length(ex) / events
+PASS left length(mm) / values
+PASS left length(mm) / events
+PASS left length(cm) / values
+PASS left length(cm) / events
+PASS left length(in) / values
+PASS left length(in) / events
+PASS left percentage(%) / values
+PASS left percentage(%) / events
+PASS color color(rgba) / values
+PASS color color(rgba) / events
+PASS font-size length(pt) / values
+PASS font-size length(pt) / events
+PASS font-size length(pc) / values
+PASS font-size length(pc) / events
+PASS font-size length(px) / values
+PASS font-size length(px) / events
+PASS font-size length(em) / values
+PASS font-size length(em) / events
+PASS font-size length(ex) / values
+PASS font-size length(ex) / events
+PASS font-size length(mm) / values
+PASS font-size length(mm) / events
+PASS font-size length(cm) / values
+PASS font-size length(cm) / events
+PASS font-size length(in) / values
+PASS font-size length(in) / events
+PASS font-size percentage(%) / values
+PASS font-size percentage(%) / events
+PASS font-weight font-weight(keyword) / values
+PASS font-weight font-weight(keyword) / events
+PASS font-weight font-weight(numeric) / values
+PASS font-weight font-weight(numeric) / events
+PASS line-height number(integer) / values
+PASS line-height number(integer) / events
+PASS line-height number(decimal) / values
+PASS line-height number(decimal) / events
+PASS line-height length(pt) / values
+PASS line-height length(pt) / events
+PASS line-height length(pc) / values
+PASS line-height length(pc) / events
+PASS line-height length(px) / values
+PASS line-height length(px) / events
+PASS line-height length(em) / values
+PASS line-height length(em) / events
+PASS line-height length(ex) / values
+PASS line-height length(ex) / events
+PASS line-height length(mm) / values
+PASS line-height length(mm) / events
+PASS line-height length(cm) / values
+PASS line-height length(cm) / events
+PASS line-height length(in) / values
+PASS line-height length(in) / events
+PASS line-height percentage(%) / values
+PASS line-height percentage(%) / events
+PASS letter-spacing length(pt) / values
+PASS letter-spacing length(pt) / events
+PASS letter-spacing length(pc) / values
+PASS letter-spacing length(pc) / events
+PASS letter-spacing length(px) / values
+PASS letter-spacing length(px) / events
+PASS letter-spacing length(em) / values
+PASS letter-spacing length(em) / events
+PASS letter-spacing length(ex) / values
+PASS letter-spacing length(ex) / events
+PASS letter-spacing length(mm) / values
+PASS letter-spacing length(mm) / events
+PASS letter-spacing length(cm) / values
+PASS letter-spacing length(cm) / events
+PASS letter-spacing length(in) / values
+PASS letter-spacing length(in) / events
+PASS word-spacing length(pt) / values
+PASS word-spacing length(pt) / events
+PASS word-spacing length(pc) / values
+PASS word-spacing length(pc) / events
+PASS word-spacing length(px) / values
+PASS word-spacing length(px) / events
+PASS word-spacing length(em) / values
+PASS word-spacing length(em) / events
+PASS word-spacing length(ex) / values
+PASS word-spacing length(ex) / events
+PASS word-spacing length(mm) / values
+PASS word-spacing length(mm) / events
+PASS word-spacing length(cm) / values
+PASS word-spacing length(cm) / events
+PASS word-spacing length(in) / values
+PASS word-spacing length(in) / events
+FAIL word-spacing percentage(%) / values assert_not_equals: initial and target values may not match got disallowed value "0px"
+FAIL word-spacing percentage(%) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "word-spacing:0.5s" but got ""
+PASS text-indent length(pt) / values
+PASS text-indent length(pt) / events
+PASS text-indent length(pc) / values
+PASS text-indent length(pc) / events
+PASS text-indent length(px) / values
+PASS text-indent length(px) / events
+PASS text-indent length(em) / values
+PASS text-indent length(em) / events
+PASS text-indent length(ex) / values
+PASS text-indent length(ex) / events
+PASS text-indent length(mm) / values
+PASS text-indent length(mm) / events
+PASS text-indent length(cm) / values
+PASS text-indent length(cm) / events
+PASS text-indent length(in) / values
+PASS text-indent length(in) / events
+PASS text-indent percentage(%) / values
+PASS text-indent percentage(%) / events
+PASS text-shadow shadow(shadow) / values
+PASS text-shadow shadow(shadow) / events
+PASS outline-color color(rgba) / values
+PASS outline-color color(rgba) / events
+PASS outline-offset length(pt) / values
+PASS outline-offset length(pt) / events
+PASS outline-offset length(pc) / values
+PASS outline-offset length(pc) / events
+PASS outline-offset length(px) / values
+PASS outline-offset length(px) / events
+PASS outline-offset length(em) / values
+PASS outline-offset length(em) / events
+PASS outline-offset length(ex) / values
+PASS outline-offset length(ex) / events
+PASS outline-offset length(mm) / values
+PASS outline-offset length(mm) / events
+PASS outline-offset length(cm) / values
+PASS outline-offset length(cm) / events
+PASS outline-offset length(in) / values
+PASS outline-offset length(in) / events
+PASS outline-width length(pt) / values
+PASS outline-width length(pt) / events
+PASS outline-width length(pc) / values
+PASS outline-width length(pc) / events
+PASS outline-width length(px) / values
+PASS outline-width length(px) / events
+PASS outline-width length(em) / values
+PASS outline-width length(em) / events
+PASS outline-width length(ex) / values
+PASS outline-width length(ex) / events
+PASS outline-width length(mm) / values
+PASS outline-width length(mm) / events
+PASS outline-width length(cm) / values
+PASS outline-width length(cm) / events
+PASS outline-width length(in) / values
+PASS outline-width length(in) / events
+PASS clip rectangle(rectangle) / values
+PASS clip rectangle(rectangle) / events
+FAIL crop rectangle(rectangle) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL crop rectangle(rectangle) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "crop:0.5s" but got ""
+PASS vertical-align length(pt) / values
+PASS vertical-align length(pt) / events
+PASS vertical-align length(pc) / values
+PASS vertical-align length(pc) / events
+PASS vertical-align length(px) / values
+PASS vertical-align length(px) / events
+PASS vertical-align length(em) / values
+PASS vertical-align length(em) / events
+PASS vertical-align length(ex) / values
+PASS vertical-align length(ex) / events
+PASS vertical-align length(mm) / values
+PASS vertical-align length(mm) / events
+PASS vertical-align length(cm) / values
+PASS vertical-align length(cm) / events
+PASS vertical-align length(in) / values
+PASS vertical-align length(in) / events
+PASS vertical-align percentage(%) / values
+PASS vertical-align percentage(%) / events
+PASS opacity number[0,1](zero-to-one) / values
+PASS opacity number[0,1](zero-to-one) / events
+PASS visibility visibility(keyword) / values
+PASS visibility visibility(keyword) / events
+PASS z-index integer(integer) / values
+PASS z-index integer(integer) / events
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-inherit-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-inherit-002.html
new file mode 100644
index 0000000..f2741bd1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-inherit-002.html
@@ -0,0 +1,145 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>CSS Transitions Test: transitioning inherited property values</title>
+        <meta name="assert" content="Test checks that inherited property values that are not transitioned on a parent element start a transition">
+        <link rel="help" title="3. Starting of transitions" href="http://www.w3.org/TR/css3-transitions/#starting">
+        <link rel="author" title="Rodney Rehm" href="http://rodneyrehm.de/en/">
+        <meta name="flags" content="dom ">
+
+        <script src="/resources/testharness.js" type="text/javascript"></script>
+        <script src="/resources/testharnessreport.js" type="text/javascript"></script>
+
+        <script src="./support/vendorPrefix.js" type="text/javascript"></script>
+        <script src="./support/helper.js" type="text/javascript"></script>
+        <script src="./support/runParallelAsyncHarness.js" type="text/javascript"></script>
+        <script src="./support/generalParallelTest.js" type="text/javascript"></script>
+        <script src="./support/properties.js" type="text/javascript"></script>
+
+        <style type="text/css">
+            #offscreen {
+                position: absolute;
+                top: -100000px;
+                left: -100000px;
+                width: 100000px;
+                height: 100000px;
+            }
+        </style>
+    </head>
+    <body>
+        <!-- required by testharnessreport.js -->
+        <div id="log"></div>
+        <!-- elements used for testing -->
+        <div id="fixture" class="fixture">
+            <div class="container">
+                <div class="transition">Text sample</div>
+            </div>
+        </div>
+        <div id="offscreen"></div>
+
+        <!--
+            SEE ./support/README.md for an abstract explanation of the test procedure
+            http://test.csswg.org/source/contributors/rodneyrehm/submitted/css3-transitions/README.md
+        -->
+
+        <script>
+            // http://www.w3.org/TR/css3-transitions/#starting
+            // Implementations also must not start a transition when the computed value changes because
+            // it is inherited (directly or indirectly) from another element that is transitioning the same property.
+            // Note: Parent element doesn't transition, so above quote doesn't apply!
+
+            // this test takes its time, give it a minute to run
+            var timeout = 60000;
+            setup({timeout: timeout});
+
+            var tests = getPropertyTests();
+            // for testing, limit to a couple of iterations
+            // tests = tests.slice(10, 30);
+            // or filter using one of:
+            // tests = filterPropertyTests(tests, "background-color color(rgba)");
+            // tests = filterPropertyTests(tests, ["background-color color(rgba)", ...]);
+            // tests = filterPropertyTests(tests, /^background-color/);
+
+            // general transition-duration
+            var duration = '0.5s';
+
+            runParallelAsyncHarness({
+                // array of test data
+                tests: tests,
+                // the number of tests to run in parallel
+                testsPerSlice: 50,
+                // milliseconds to wait before calling teardown and ending test
+                duration: parseFloat(duration) * 1000,
+                // the global suite timeout
+                timeout: timeout,
+                // prepare individual test
+                setup: function(data, options) {
+                    // clone and overwrite initial styles to be
+                    // applied to #transition
+                    var inherited = extend({}, data.from);
+                    inherited[data.property] = 'inherit';
+
+                    var styles = {
+                        // as we're testing inheritance, #fixture is our new parent
+                        '.fixture': data.parentStyle,
+                        // all styles including transition apply to to #container so they
+                        // can inherit down to #transition
+                        '.container': extend({}, data.parentStyle, data.from),
+                        '.container.to': data.to,
+                        '.container.how': {},
+                        // #transition only inherits and listens for transition events
+                        '.transition': inherited,
+                        '.transition.to' : {},
+                        '.transition.how' : {transition: addVendorPrefix(data.property) + ' ' + duration + ' linear 0s'}
+                    };
+
+                    generalParallelTest.setup(data, options);
+                    generalParallelTest.addStyles(data, options, styles);
+                },
+                // cleanup after individual test
+                teardown: generalParallelTest.teardown,
+                // invoked prior to running a slice of tests
+                sliceStart: generalParallelTest.sliceStart,
+                // invoked after running a slice of tests
+                sliceDone: generalParallelTest.sliceDone,
+                // test cases, make them as granular as possible
+                cases: {
+                    // test property values while transitioning
+                    // values.start kicks off a transition
+                    'values': {
+                        // run actual test, assertions can be used here!
+                        start: function(test, data, options) {
+                            // identify initial and target values
+                            generalParallelTest.getStyle(data);
+                            // make sure values differ, if they don't, the property could most likely not be parsed
+                            assert_not_equals(data.transition.from, data.transition.to, "initial and target values may not match");
+                            // kick off the transition
+                            generalParallelTest.startTransition(data);
+
+                            // make sure we didn't get the target value immediately.
+                            // If we did, there wouldn't be a transition!
+                            var current = data.transition.computedStyle(data.property);
+                            assert_not_equals(current, data.transition.to, "must not be target value after start");
+                        },
+                        done: function(test, data, options) {
+                            // make sure the property's value were neither initial nor target while transitioning
+                            test.step(generalParallelTest.assertIntermediateValuesFunc(data, 'transition'));
+                        }
+                    },
+                    // test TransitionEnd events
+                    'events': {
+                        done: function(test, data, options) {
+                            // make sure there were no events on parent
+                            test.step(generalParallelTest.assertExpectedEventsFunc(data, 'container', ""));
+                            // make sure we got the event for the tested property only
+                            test.step(generalParallelTest.assertExpectedEventsFunc(data, 'transition', addVendorPrefix(data.property) + ":" + duration));
+                        }
+                    }
+                },
+                // called once all tests are done
+                done: generalParallelTest.done
+            });
+        </script>
+    </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-inherit-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-inherit-003.html
new file mode 100644
index 0000000..43d02296
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/properties-value-inherit-003.html
@@ -0,0 +1,145 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>CSS Transitions Test: transitioning implicitly inherited property values</title>
+        <meta name="assert" content="Test checks that implicitly inherited property values that are transitioned on a parent element don't start a transition">
+        <link rel="help" title="3. Starting of transitions" href="http://www.w3.org/TR/css3-transitions/#starting">
+        <link rel="author" title="Rodney Rehm" href="http://rodneyrehm.de/en/">
+        <meta name="flags" content="dom ">
+
+        <script src="/resources/testharness.js" type="text/javascript"></script>
+        <script src="/resources/testharnessreport.js" type="text/javascript"></script>
+
+        <script src="./support/vendorPrefix.js" type="text/javascript"></script>
+        <script src="./support/helper.js" type="text/javascript"></script>
+        <script src="./support/runParallelAsyncHarness.js" type="text/javascript"></script>
+        <script src="./support/generalParallelTest.js" type="text/javascript"></script>
+        <script src="./support/properties.js" type="text/javascript"></script>
+
+        <style type="text/css">
+            #offscreen {
+                position: absolute;
+                top: -100000px;
+                left: -100000px;
+                width: 100000px;
+                height: 100000px;
+            }
+        </style>
+    </head>
+    <body>
+        <!-- required by testharnessreport.js -->
+        <div id="log"></div>
+        <!-- elements used for testing -->
+        <div id="fixture" class="fixture">
+            <div class="container">
+                <div class="transition">Text sample</div>
+            </div>
+        </div>
+        <div id="offscreen"></div>
+
+        <!--
+            SEE ./support/README.md for an abstract explanation of the test procedure
+            http://test.csswg.org/source/contributors/rodneyrehm/submitted/css3-transitions/README.md
+        -->
+
+        <script>
+            // http://www.w3.org/TR/css3-transitions/#starting
+            // Implementations also must not start a transition when the computed value changes because
+            // it is inherited (directly or indirectly) from another element that is transitioning the same property.
+            // Note: "indirectly" could mean "font-size" on parent, "em-based" on element
+
+            // this test takes its time, give it a minute to run
+            var timeout = 60000;
+            setup({timeout: timeout});
+
+            var tests = getFontSizeRelativePropertyTests();
+            // for testing, limit to a couple of iterations
+            // tests = tests.slice(10, 30);
+            // or filter using one of:
+            // tests = filterPropertyTests(tests, "background-color color(rgba)");
+            // tests = filterPropertyTests(tests, ["background-color color(rgba)", ...]);
+            // tests = filterPropertyTests(tests, /^background-color/);
+
+            // general transition-duration
+            var duration = '0.5s';
+
+            runParallelAsyncHarness({
+                // array of test data
+                tests: tests,
+                // the number of tests to run in parallel
+                testsPerSlice: 50,
+                // milliseconds to wait before calling teardown and ending test
+                duration: parseFloat(duration) * 1000,
+                // the global suite timeout
+                timeout: timeout,
+                // prepare individual test
+                setup: function(data, options) {
+                    // have parent transition the font-size only
+                    var from = extend({}, data.from, {'font-size': '20px'});
+                    delete from[data.property];
+
+                    var styles = {
+                        // as we're testing inheritance, #fixture is our new parent
+                        '.fixture': data.parentStyle,
+
+                        '.container': from,
+                        '.container.to': {'font-size': '30px'},
+                        // transition font-size on parent
+                        '.container.how': {transition: 'font-size ' + duration + ' linear 0s'},
+
+                        '.transition': data.from,
+                        '.transition.to' : {},
+                        // transition font-size dependent property on child
+                        '.transition.how' : {transition: addVendorPrefix(data.property) + ' ' + duration + ' linear 0s'}
+                    };
+
+                    generalParallelTest.setup(data, options);
+                    generalParallelTest.addStyles(data, options, styles);
+                },
+                // cleanup after individual test
+                teardown: generalParallelTest.teardown,
+                // invoked prior to running a slice of tests
+                sliceStart: generalParallelTest.sliceStart,
+                // invoked after running a slice of tests
+                sliceDone: generalParallelTest.sliceDone,
+                // test cases, make them as granular as possible
+                cases: {
+                    // test property values while transitioning
+                    // values.start kicks off a transition
+                    'values': {
+                        // run actual test, assertions can be used here!
+                        start: function(test, data, options) {
+                            // identify initial and target values
+                            generalParallelTest.getStyle(data);
+                            // make sure values differ, if they don't, the property could most likely not be parsed
+                            assert_not_equals(data.transition.from, data.transition.to, "initial and target values may not match");
+                            // kick off the transition
+                            generalParallelTest.startTransition(data);
+
+                            // make sure we didn't get the target value immediately.
+                            // If we did, there wouldn't be a transition!
+                            var current = data.transition.computedStyle(data.property);
+                            assert_not_equals(current, data.transition.to, "must not be target value after start");
+                        },
+                        done: function(test, data, options) {
+                            // make sure the property's value were neither initial nor target while transitioning
+                            test.step(generalParallelTest.assertIntermediateValuesFunc(data, 'transition'));
+                        }
+                    },
+                    // test TransitionEnd events
+                    'events': {
+                        done: function(test, data, options) {
+                            // make sure there were no events on parent
+                            test.step(generalParallelTest.assertExpectedEventsFunc(data, 'container', "font-size:" + duration));
+                            // make sure we got the event for the tested property only
+                            test.step(generalParallelTest.assertExpectedEventsFunc(data, 'transition', ""));
+                        }
+                    }
+                },
+                // called once all tests are done
+                done: generalParallelTest.done
+            });
+        </script>
+    </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/pseudo-elements-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/pseudo-elements-001.html
new file mode 100644
index 0000000..cf1d254
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/pseudo-elements-001.html
@@ -0,0 +1,150 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>CSS Transitions Test: Transitioning Pseudo Elements</title>
+        <meta name="assert" content="Test checks that transitions are run on pseudo elements">
+        <link rel="help" title="2.1. The 'transition-property' Property" href="http://www.w3.org/TR/css3-transitions/#transition-property-property">
+        <link rel="help" title="CSS21 - 12.1 The :before and :after pseudo-elements" href="http://www.w3.org/TR/CSS21/generate.html#before-after-content">
+        <link rel="help" title="CSS3 Generated and Replaced Content Module" href="http://www.w3.org/TR/css3-content/">
+        <link rel="author" title="Rodney Rehm" href="http://rodneyrehm.de/en/">
+        <meta name="flags" content="dom">
+
+        <script src="/resources/testharness.js" type="text/javascript"></script>
+        <script src="/resources/testharnessreport.js" type="text/javascript"></script>
+
+        <script src="./support/vendorPrefix.js" type="text/javascript"></script>
+        <script src="./support/helper.js" type="text/javascript"></script>
+        <script src="./support/runParallelAsyncHarness.js" type="text/javascript"></script>
+        <script src="./support/generalParallelTest.js" type="text/javascript"></script>
+        <script src="./support/properties.js" type="text/javascript"></script>
+
+        <style type="text/css">
+            #offscreen {
+                position: absolute;
+                top: -100000px;
+                left: -100000px;
+                width: 100000px;
+                height: 100000px;
+            }
+        </style>
+    </head>
+    <body>
+        <!-- required by testharnessreport.js -->
+        <div id="log"></div>
+        <!-- elements used for testing -->
+        <div id="fixture" class="fixture">
+            <div class="container">
+                <div class="transition">Text sample</div>
+            </div>
+        </div>
+        <div id="offscreen"></div>
+
+        <!--
+            SEE ./support/README.md for an abstract explanation of the test procedure
+            http://test.csswg.org/source/contributors/rodneyrehm/submitted/css3-transitions/README.md
+        -->
+
+        <script>
+
+            // this test takes its time, give it a minute to run
+            var timeout = 60000;
+            setup({timeout: timeout});
+
+            var tests = [
+                {
+                    name: "transition padding-left on :before",
+                    pseudo: 'before',
+                    property: 'padding-left',
+                    flags: {},
+                    from: {'padding-left': '1px', 'content': '""'},
+                    to: {'padding-left': '10px'}
+                }, {
+                    name: "transition padding-left on :after",
+                    pseudo: 'after',
+                    property: 'padding-left',
+                    flags: {},
+                    from: {'padding-left': '1px', 'content': '""'},
+                    to: {'padding-left': '10px'}
+                }, {
+                    name: "transition padding-left on :before, changing content",
+                    pseudo: 'before',
+                    property: 'padding-left',
+                    flags: {},
+                    from: {'padding-left': '1px', 'content': '"1"'},
+                    to: {'padding-left': '10px', 'content': '"2"'}
+                }, {
+                    name: "transition padding-left on :after, changing content",
+                    pseudo: 'after',
+                    property: 'padding-left',
+                    flags: {},
+                    from: {'padding-left': '1px', 'content': '"1"'},
+                    to: {'padding-left': '10px', 'content': '"2"'}
+                }
+            ];
+
+            // general transition-duration
+            var duration = '0.5s';
+
+            runParallelAsyncHarness({
+                // array of test data
+                tests: tests,
+                // the number of tests to run in parallel
+                testsPerSlice: 50,
+                // milliseconds to wait before calling teardown and ending test
+                duration: parseFloat(duration) * 1000,
+                // the global suite timeout
+                timeout: timeout,
+                // prepare individual test
+                setup: function(data, options) {
+                    generalParallelTest.setup(data, options);
+
+                    var styles = {};
+                    styles['.fixture'] = {};
+                    styles['.container'] = data.parentStyle;
+                    styles['.container.to'] = {};
+                    styles['.container.how'] = {};
+                    styles['.transition'] = {};
+                    styles['.transition:' + data.pseudo.name] = data.from;
+                    styles['.transition.how:' + data.pseudo.name] = {transition: 'all ' + duration + ' linear 0s'};
+                    styles['.transition.to:' + data.pseudo.name] = data.to;
+
+                    generalParallelTest.addStyles(data, options, styles);
+                },
+                // cleanup after individual test
+                teardown: generalParallelTest.teardown,
+                // invoked prior to running a slice of tests
+                sliceStart: generalParallelTest.sliceStart,
+                // invoked after running a slice of tests
+                sliceDone: generalParallelTest.sliceDone,
+                // test cases, make them as granular as possible
+                cases: {
+                    // test property values while transitioning
+                    // values.start kicks off a transition
+                    'values': {
+                        // run actual test, assertions can be used here!
+                        start: function(test, data, options) {
+                            // identify initial and target values
+                            generalParallelTest.getStyle(data);
+                            // make sure values differ, if they don't, the property could most likely not be parsed
+                            assert_not_equals(data.pseudo.from, data.pseudo.to, "initial and target values may not match");
+                            // kick off the transition
+                            generalParallelTest.startTransition(data);
+
+                            // make sure we didn't get the target value immediately.
+                            // If we did, there wouldn't be a transition!
+                            var current = data.pseudo.computedStyle(data.property);
+                            assert_not_equals(current, data.pseudo.to, "must not be target value after start");
+                        },
+                        done: function(test, data, options) {
+                            // make sure the property's value were neither initial nor target while transitioning
+                            test.step(generalParallelTest.assertIntermediateValuesFunc(data, 'pseudo'));
+                        }
+                    }
+                },
+                // called once all tests are done
+                done: generalParallelTest.done
+            });
+        </script>
+    </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/reference/transition-test-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/reference/transition-test-ref.html
new file mode 100644
index 0000000..d9d91ec
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/reference/transition-test-ref.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>CSS Transition Reference File</title>
+    <link rel="author" title="Oleg Janeiko" href="mailto:oleg@the-incredible.me">
+    <style type="text/css">
+        .container {
+            background-color: red;
+            height: 200px;
+            width: 200px;
+        }
+        .box {
+            width: 100px;
+            height: 100px;
+            background-color: green;
+
+            transition-property: width;
+            transition-duration: 0;
+        }
+        .box.transition {
+            width: 200px;
+            height: 200px;
+        }
+    </style>
+    <script type="text/javascript" charset="utf-8">
+        function ready(){
+            var box = document.querySelector('.box');
+            box.className = 'box transition';
+        }
+    </script>
+</head>
+<body onload="ready();">
+    <div>
+        <p>You should not see a red background during the transition. Note: if the test passes transition is instant.</p>
+    </div>
+    <div class="container">
+        <div class="box"></div>
+    </div>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/1x1-green.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/1x1-green.png
new file mode 100644
index 0000000..b98ca0ba
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/1x1-green.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/1x1-lime.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/1x1-lime.png
new file mode 100644
index 0000000..cb397fb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/1x1-lime.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/1x1-maroon.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/1x1-maroon.png
new file mode 100644
index 0000000..3f86b07
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/1x1-maroon.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/1x1-navy.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/1x1-navy.png
new file mode 100644
index 0000000..9b9a0395
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/1x1-navy.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/1x1-red.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/1x1-red.png
new file mode 100644
index 0000000..6bd73ac
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/1x1-red.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/1x1-white.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/1x1-white.png
new file mode 100644
index 0000000..dd43fae
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/1x1-white.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/60x60-gg-rr.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/60x60-gg-rr.png
new file mode 100644
index 0000000..84f5b2a4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/60x60-gg-rr.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/60x60-green.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/60x60-green.png
new file mode 100644
index 0000000..b3c8cf3eb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/60x60-green.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/60x60-red.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/60x60-red.png
new file mode 100644
index 0000000..823f125
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/60x60-red.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/README b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/README
new file mode 100644
index 0000000..2e5f2ad
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/README
@@ -0,0 +1,28 @@
+CSS Global Support Directory
+============================
+
+This directory contains common support files (such as images and external
+style sheets). These are sync'ed into the support directories of all our
+test suites. If you have test-suite-specific support files, please add
+them to the appropriate test-suite-specific support/ directory.
+
+If you add to a support/ directory, please run the tools/supportprop.py
+script from the top of the repository to cascade support files into the
+lower-level support directories.
+
+Description of the Common Support File Collection
+-------------------------------------------------
+
+The 1x1-* images are all exactly one pixel.
+
+The swatch-* images all use 15x15 cells.
+
+The square-* images all use 15x15 cells with one pixel borders.
+
+The pattern-* images use cells of various sizes:
+
+   pattern-grg-rgr-grg.png   20x20
+   pattern-rgr-grg-rgr.png   20x20
+   pattern-tr.png            15x15
+   pattern-grg-rrg-rgg.png   15x15
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/a-green.css b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/a-green.css
new file mode 100644
index 0000000..b0dbb07
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/a-green.css
@@ -0,0 +1 @@
+.a { color: green; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/b-green.css b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/b-green.css
new file mode 100644
index 0000000..a0473f5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/b-green.css
@@ -0,0 +1 @@
+.b { color: green; }
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/c-red.css b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/c-red.css
new file mode 100644
index 0000000..d4ba5c6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/c-red.css
@@ -0,0 +1 @@
+.c { color: red; }
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/cat.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/cat.png
new file mode 100644
index 0000000..85dd732
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/cat.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/generalParallelTest.js b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/generalParallelTest.js
new file mode 100644
index 0000000..f6e1412
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/generalParallelTest.js
@@ -0,0 +1,231 @@
+(function(root) {
+'use strict';
+//
+var index = 0;
+var suite = root.generalParallelTest = {
+    // prepare individual test
+    setup: function(data, options) {
+        suite._setupDom(data, options);
+        suite._setupEvents(data, options);
+    },
+    // clone fixture and prepare data containers
+    _setupDom: function(data, options) {
+        // clone fixture into off-viewport test-canvas
+        data.fixture = document.getElementById('fixture').cloneNode(true);
+        data.fixture.id = 'test-' + (index++);
+        (document.getElementById('offscreen') || document.body).appendChild(data.fixture);
+
+        // data container for #fixture > .container > .transition
+        data.transition = {
+            node: data.fixture.querySelector('.transition'),
+            values: [],
+            events: [],
+            computedStyle: function(property) {
+                return computedStyle(data.transition.node, property);
+            }
+        };
+
+        // data container for #fixture > .container
+        data.container = {
+            node: data.transition.node.parentNode,
+            values: [],
+            events: [],
+            computedStyle: function(property) {
+                return computedStyle(data.container.node, property);
+            }
+        };
+
+        // data container for #fixture > .container > .transition[:before | :after]
+        if (data.pseudo) {
+            data.pseudo = {
+                name: data.pseudo,
+                values: [],
+                computedStyle: function(property) {
+                    return computedStyle(data.transition.node, property, ':' + data.pseudo.name);
+                }
+            };
+        }
+    },
+    // bind TransitionEnd event listeners
+    _setupEvents: function(data, options) {
+        ['transition', 'container'].forEach(function(elem) {
+            var handler = function(event) {
+                event.stopPropagation();
+                var name = event.propertyName;
+                var time = Math.round(event.elapsedTime * 1000) / 1000;
+                var pseudo = event.pseudoElement ? (':' + event.pseudoElement) : '';
+                data[elem].events.push(name + pseudo + ":" + time + "s");
+            };
+            data[elem].node.addEventListener('transitionend', handler, false);
+            data[elem]._events = {'transitionend': handler};
+        });
+    },
+    // cleanup after individual test
+    teardown: function(data, options) {
+        // data.fixture.remove();
+        if (data.fixture.parentNode) {
+            data.fixture.parentNode.removeChild(data.fixture);
+        }
+    },
+    // invoked prior to running a slice of tests
+    sliceStart: function(options, tests) {
+        // inject styles into document
+        setStyle(options.styles);
+        // kick off value collection loop
+        generalParallelTest.startValueCollection(options);
+    },
+    // invoked after running a slice of tests
+    sliceDone: function(options, tests) {
+        // stop value collection loop
+        generalParallelTest.stopValueCollection(options);
+        // reset styles cache
+        options.styles = {};
+    },
+    // called once all tests are done
+    done: function(options) {
+        // reset document styles
+        setStyle();
+        reflow();
+    },
+    // add styles of individual test to slice cache
+    addStyles: function(data, options, styles) {
+        if (!options.styles) {
+            options.styles = {};
+        }
+
+        Object.keys(styles).forEach(function(key) {
+            var selector = '#' + data.fixture.id
+                // fixture must become #fixture.fixture rather than a child selector
+                + (key.substring(0, 8) === '.fixture' ? '' : ' ')
+                + key;
+
+            options.styles[selector] = styles[key];
+        });
+    },
+    // set style and compute values for container and transition
+    getStyle: function(data) {
+        reflow();
+        // grab current styles: "initial state"
+        suite._getStyleFor(data, 'from');
+        // apply target state
+        suite._addClass(data, 'to', true);
+        // grab current styles: "target state"
+        suite._getStyleFor(data, 'to');
+        // remove target state
+        suite._removeClass(data, 'to', true);
+
+        // clean up the mess created for value collection
+        data.container._values = [];
+        data.transition._values = [];
+        if (data.pseudo) {
+            data.pseudo._values = [];
+        }
+    },
+    // grab current styles and store in respective element's data container
+    _getStyleFor: function(data, key) {
+        data.container[key] = data.container.computedStyle(data.property);
+        data.transition[key] = data.transition.computedStyle(data.property);
+        if (data.pseudo) {
+            data.pseudo[key] = data.pseudo.computedStyle(data.property);
+        }
+    },
+    // add class to test's elements and possibly reflow
+    _addClass: function(data, className, forceReflow) {
+        data.container.node.classList.add(className);
+        data.transition.node.classList.add(className);
+        if (forceReflow) {
+            reflow();
+        }
+    },
+    // remove class from test's elements and possibly reflow
+    _removeClass: function(data, className, forceReflow) {
+        data.container.node.classList.remove(className);
+        data.transition.node.classList.remove(className);
+        if (forceReflow) {
+            reflow();
+        }
+    },
+    // add transition and to classes to container and transition
+    startTransition: function(data) {
+        // add transition-defining class
+        suite._addClass(data, 'how', true);
+        // add target state (without reflowing)
+        suite._addClass(data, 'to', false);
+    },
+    // requestAnimationFrame runLoop to collect computed values
+    startValueCollection: function(options) {
+        var raf = window.requestAnimationFrame || function(callback){
+            setTimeout(callback, 20);
+        };
+
+        // flag denoting if the runLoop should continue (true) or exit (false)
+        options._collectValues = true;
+
+        function runLoop() {
+            if (!options._collectValues) {
+                // test's are done, stop annoying the CPU
+                return;
+            }
+
+            // collect current style for test's elements
+            options.tests.forEach(function(data) {
+                if (!data.property) {
+                    return;
+                }
+
+                ['transition', 'container', 'pseudo'].forEach(function(elem) {
+                    var pseudo = null;
+                    if (!data[elem] || (elem === 'pseudo' && !data.pseudo)) {
+                        return;
+                    }
+
+                    var current = data[elem].computedStyle(data.property);
+                    var values = data[elem].values;
+                    var length = values.length;
+                    if (!length || values[length - 1] !== current) {
+                        values.push(current);
+                    }
+                });
+            });
+
+            // rinse and repeat
+            raf(runLoop);
+        }
+
+        runLoop();
+    },
+    // stop requestAnimationFrame runLoop collecting computed values
+    stopValueCollection: function(options) {
+        options._collectValues = false;
+    },
+
+    // generate test.step function asserting collected events match expected
+    assertExpectedEventsFunc: function(data, elem, expected) {
+        return function() {
+            var _result = data[elem].events.sort().join(" ");
+            var _expected = typeof expected === 'string' ? expected : expected.sort().join(" ");
+            assert_equals(_result, _expected, "Expected TransitionEnd events triggered on ." + elem);
+        };
+    },
+    // generate test.step function asserting collected values are neither initial nor target
+    assertIntermediateValuesFunc: function(data, elem) {
+        return function() {
+            // the first value (index: 0) is always going to be the initial value
+            // the last value is always going to be the target value
+            var values = data[elem].values;
+            if (data.flags.discrete) {
+                // a discrete value will just switch from one state to another without having passed intermediate states.
+                assert_equals(values[0], data[elem].from, "must be initial value while transitioning on ." + elem);
+                assert_equals(values[1], data[elem].to, "must be target value after transitioning on ." + elem);
+                assert_equals(values.length, 2, "discrete property only has 2 values ." + elem);
+            } else {
+                assert_not_equals(values[1], data[elem].from, "may not be initial value while transitioning on ." + elem);
+                assert_not_equals(values[1], data[elem].to, "may not be target value while transitioning on ." + elem);
+            }
+
+            // TODO: first value must be initial, last value must be target
+        };
+    }
+};
+
+})(window);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/helper.js b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/helper.js
new file mode 100644
index 0000000..f11e4347
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/helper.js
@@ -0,0 +1,199 @@
+//
+// Simple Helper Functions For Testing CSS
+//
+
+(function(root) {
+'use strict';
+
+// serialize styles object and dump to dom
+// appends <style id="dynamic-style"> to <head>
+// setStyle("#some-selector", {"some-style" : "value"})
+// setStyle({"#some-selector": {"some-style" : "value"}})
+root.setStyle = function(selector, styles) {
+    var target = document.getElementById('dynamic-style');
+    if (!target) {
+        target = document.createElement('style');
+        target.id = 'dynamic-style';
+        target.type = "text/css";
+        document.getElementsByTagName('head')[0].appendChild(target);
+    }
+
+    var data = [];
+    // single selector/styles
+    if (typeof selector === 'string' && styles !== undefined) {
+        data = [selector, '{', serializeStyles(styles), '}'];
+        target.textContent = data.join("\n");
+        return;
+    }
+    // map of selector/styles
+    for (var key in selector) {
+        if (Object.prototype.hasOwnProperty.call(selector, key)) {
+            var _data = [key, '{', serializeStyles(selector[key]), '}'];
+            data.push(_data.join('\n'));
+        }
+    }
+
+    target.textContent = data.join("\n");
+};
+
+function serializeStyles(styles) {
+    var data = [];
+    for (var property in styles) {
+        if (Object.prototype.hasOwnProperty.call(styles, property)) {
+            var prefixedProperty = addVendorPrefix(property);
+            data.push(prefixedProperty + ":" + styles[property] + ";");
+        }
+    }
+
+    return data.join('\n');
+}
+
+
+// shorthand for computed style
+root.computedStyle = function(element, property, pseudo) {
+    var prefixedProperty = addVendorPrefix(property);
+    return window
+        .getComputedStyle(element, pseudo || null)
+        .getPropertyValue(prefixedProperty);
+};
+
+// flush rendering buffer
+root.reflow = function() {
+    document.body.offsetWidth;
+};
+
+// merge objects
+root.extend = function(target /*, ..rest */) {
+    Array.prototype.slice.call(arguments, 1).forEach(function(obj) {
+        Object.keys(obj).forEach(function(key) {
+            target[key] = obj[key];
+        });
+    });
+
+    return target;
+};
+
+// dom fixture helper ("resetting dom test elements")
+var _domFixture;
+var _domFixtureSelector;
+root.domFixture = function(selector) {
+    var fixture = document.querySelector(selector || _domFixtureSelector);
+    if (!fixture) {
+        throw new Error('fixture ' + (selector || _domFixtureSelector) + ' not found!');
+    }
+    if (!_domFixture && selector) {
+        // save a copy
+        _domFixture = fixture.cloneNode(true);
+        _domFixtureSelector = selector;
+    } else if (_domFixture) {
+        // restore the copy
+        var tmp = _domFixture.cloneNode(true);
+        fixture.parentNode.replaceChild(tmp, fixture);
+    } else {
+        throw new Error('domFixture must be initialized first!');
+    }
+};
+
+/*
+ * The recommended minimum precision to use for time values.
+ *
+ * Based on Web Animations:
+ * https://w3c.github.io/web-animations/#precision-of-time-values
+ */
+const TIME_PRECISION = 0.0005; // ms
+
+/*
+ * Allow implementations to substitute an alternative method for comparing
+ * times based on their precision requirements.
+ */
+root.assert_times_equal = function(actual, expected, description) {
+  assert_approx_equals(actual, expected, TIME_PRECISION, description);
+}
+
+/**
+ * Assert that CSSTransition event, |evt|, has the expected property values
+ * defined by |propertyName|, |elapsedTime|, and |pseudoElement|.
+ */
+root.assert_end_events_equal = function(evt, propertyName, elapsedTime,
+                                        pseudoElement = '') {
+  assert_equals(evt.propertyName, propertyName);
+  assert_times_equal(evt.elapsedTime, elapsedTime);
+  assert_equals(evt.pseudoElement, pseudoElement);
+}
+
+/**
+ * Assert that array of simultaneous CSSTransition events, |evts|, have the
+ * corresponding property names listed in |propertyNames|, and the expected
+ * |elapsedTimes| and |pseudoElement| members.
+ *
+ * |elapsedTimes| may be a single value if all events are expected to have the
+ * same elapsedTime, or an array parallel to |propertyNames|.
+ */
+root.assert_end_event_batch_equal = function(evts, propertyNames, elapsedTimes,
+                                             pseudoElement = '') {
+  assert_equals(
+    evts.length,
+    propertyNames.length,
+    'Test harness error: should have waited for the correct number of events'
+  );
+  assert_true(
+    typeof elapsedTimes === 'number' ||
+      (Array.isArray(elapsedTimes) &&
+        elapsedTimes.length === propertyNames.length),
+    'Test harness error: elapsedTimes must either be a number or an array of' +
+      ' numbers with the same length as propertyNames'
+  );
+
+  if (typeof elapsedTimes === 'number') {
+    elapsedTimes = Array(propertyNames.length).fill(elapsedTimes);
+  }
+  const testPairs = propertyNames.map((propertyName, index) => ({
+    propertyName,
+    elapsedTime: elapsedTimes[index]
+  }));
+
+  const sortByPropertyName = (a, b) =>
+    a.propertyName.localeCompare(b.propertyName);
+  evts.sort(sortByPropertyName);
+  testPairs.sort(sortByPropertyName);
+
+  for (let evt of evts) {
+    const expected = testPairs.shift();
+    assert_end_events_equal(
+      evt,
+      expected.propertyName,
+      expected.elapsedTime,
+      pseudoElement
+    );
+  }
+}
+
+/**
+ * Appends a div to the document body.
+ *
+ * @param t  The testharness.js Test object. If provided, this will be used
+ *           to register a cleanup callback to remove the div when the test
+ *           finishes.
+ *
+ * @param attrs  A dictionary object with attribute names and values to set on
+ *               the div.
+ */
+root.addDiv = function(t, attrs) {
+  var div = document.createElement('div');
+  if (attrs) {
+    for (var attrName in attrs) {
+      div.setAttribute(attrName, attrs[attrName]);
+    }
+  }
+  document.body.appendChild(div);
+  if (t && typeof t.add_cleanup === 'function') {
+    t.add_cleanup(function() {
+      if (div.parentNode) {
+        div.remove();
+      }
+    });
+  }
+  return div;
+}
+
+})(window);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/import-green.css b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/import-green.css
new file mode 100644
index 0000000..537104e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/import-green.css
@@ -0,0 +1 @@
+.import { color: green; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/import-red.css b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/import-red.css
new file mode 100644
index 0000000..9945ef47
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/import-red.css
@@ -0,0 +1 @@
+.import { color: red; }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/one.gif b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/one.gif
new file mode 100644
index 0000000..74cf783
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/one.gif
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/pattern-grg-rgr-grg.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/pattern-grg-rgr-grg.png
new file mode 100644
index 0000000..9b88fbd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/pattern-grg-rgr-grg.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/pattern-grg-rrg-rgg.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/pattern-grg-rrg-rgg.png
new file mode 100644
index 0000000..fcf4f3f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/pattern-grg-rrg-rgg.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/pattern-rgr-grg-rgr.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/pattern-rgr-grg-rgr.png
new file mode 100644
index 0000000..d454e3a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/pattern-rgr-grg-rgr.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/pattern-tr.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/pattern-tr.png
new file mode 100644
index 0000000..8b4b253
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/pattern-tr.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/properties.js b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/properties.js
new file mode 100644
index 0000000..01fb6e7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/properties.js
@@ -0,0 +1,449 @@
+(function(root){
+
+/*
+ * General Value Types definition
+ * they return an object of arrays of type { <name>: [<start-value>, <end-value>], ... }
+ */
+var values = {
+    'length' : function() {
+        // http://www.w3.org/TR/css3-values/#lengths
+        return {
+            // CSS Values and Module Level 3
+            // ch: ['1ch', '10ch'],
+            // rem: ['1rem', '10rem'],
+            // vw: ['1vw', '10vw'],
+            // vh: ['1vh', '10vh'],
+            // vmin: ['1vmin', '10vmin'],
+            // vmax: ['1vmax', '10vmax'],
+            // CSS Values and Module Level 2
+            pt: ['1pt', '10pt'],
+            pc: ['1pc', '10pc'],
+            px: ['1px', '10px'],
+            // CSS Values and Module Level 1
+            em: ['1em', '10em'],
+            ex: ['1ex', '10ex'],
+            mm: ['1mm', '10mm'],
+            cm: ['1cm', '10cm'],
+            'in': ['1in', '10in']
+        };
+    },
+    'length-em': function() {
+        return {
+            em: ['1.1em', '1.5em']
+        };
+    },
+    'percentage': function() {
+        // http://www.w3.org/TR/css3-values/#percentages
+        return {
+            '%': ['33%', '80%']
+        };
+    },
+    'color': function() {
+        // http://www.w3.org/TR/css3-values/#colors
+        // http://www.w3.org/TR/css3-color/
+        return {
+            rgba: ['rgba(100,100,100,1)', 'rgba(10,10,10,0.4)']
+        };
+    },
+    'rectangle': function() {
+        // http://www.w3.org/TR/CSS2/visufx.html#value-def-shape
+        return {
+            rectangle: ['rect(10px,10px,10px,10px)', 'rect(15px,15px,5px,5px)']
+        };
+    },
+    'font-weight': function() {
+        // http://www.w3.org/TR/css3-fonts/#font-weight-prop
+        return {
+            keyword: ["normal", "bold"],
+            numeric: ["100", "900"]
+        };
+    },
+    'number': function() {
+        // http://www.w3.org/TR/css3-values/#number
+        return {
+            integer: ["1", "10"],
+            decimal: ["1.1", "9.55"]
+        };
+    },
+    'number[0,1]': function() {
+        // http://www.w3.org/TR/css3-values/#number
+        // applies to [0,1]-ranged properties like opacity
+        return {
+            "zero-to-one": ["0.2", "0.9"]
+        };
+    },
+    'integer': function() {
+        // http://www.w3.org/TR/css3-values/#integer
+        return {
+            integer: ["1", "10"]
+        };
+    },
+    'shadow': function() {
+        // http://www.w3.org/TR/css-text-decor-3/#text-shadow-property
+        return {
+            shadow: ['rgba(0,0,0,0.1) 5px 6px 7px', 'rgba(10,10,10,0.9) 5px 6px 7px']
+        };
+    },
+    'visibility': function() {
+        // http://www.w3.org/TR/CSS2/visufx.html#visibility
+        return {
+            keyword: ['visible', 'hidden', {discrete: true}]
+        };
+    },
+    'auto': function(property) {
+        var types = properties[property] || unspecified_properties[property];
+        var val = values[types[0]](property);
+        var key = Object.keys(val).shift();
+        return {
+            to: [val[key][1], 'auto'],
+            from: ['auto', val[key][1]]
+        };
+    },
+    // types reqired for non-specified properties
+    'border-radius': function() {
+        return {
+            px: ['1px', '10px'],
+            "px-px": ['1px 3px', '10px 13px']
+        };
+    },
+    'image' : function() {
+        var prefix = getValueVendorPrefix('background-image', 'linear-gradient(top, hsl(0, 80%, 70%), #bada55)');
+        return {
+            // Chrome implements this
+            url: ['url(support/one.gif)', 'url(support/two.gif)'],
+            data: ['url(data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=)', 'url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==)'],
+            // A hunch, as from the spec:
+            // http://www.w3.org/TR/css3-transitions/#animatable-types
+            // gradient: interpolated via the positions and colors of each stop. They must have the same type (radial or linear) and same number of stops in order to be animated. Note: [CSS3-IMAGES] may extend this definition.
+            gradient: [prefix + 'linear-gradient(top, hsl(0, 80%, 70%), #bada55)', prefix + 'linear-gradient(top, #bada55, hsl(0, 80%, 70%))']
+        };
+    },
+    'background-size': function() {
+        return {
+            keyword: ['cover', 'contain']
+        };
+    },
+    'box-shadow': function() {
+        // http://www.w3.org/TR/css3-background/#ltshadowgt
+        return {
+            shadow: ['60px -16px teal', '60px -16px red']
+        };
+    },
+    'vertical': function() {
+        return {
+            keyword: ['top', 'bottom']
+        };
+    },
+    'horizontal': function() {
+        return {
+            keyword: ['left', 'right']
+        };
+    },
+    'font-stretch': function() {
+        return {
+            keyword: ['condensed', 'expanded']
+        };
+    },
+    'transform': function() {
+        return {
+            rotate: ['rotate(10deg)', 'rotate(20deg)']
+        };
+    },
+    'position': function() {
+        return {
+            'static to absolute': ['static', 'absolute', {discrete: true}],
+            'relative to absolute': ['relative', 'absolute', {discrete: true}],
+            'absolute to fixed': ['absolute', 'fixed', {discrete: true}]
+        };
+    },
+    'display': function() {
+        return {
+            'static to absolute': ['none', 'block', {discrete: true}],
+            'block to inline-block': ['block', 'inline-block', {discrete: true}]
+        };
+    }
+};
+
+/*
+ * Property to Type table
+ * (as stated in specification)
+ */
+var properties = {
+    'background-color': ['color'],
+    'background-position': ['length', 'percentage'],
+
+    'border-top-width': ['length'],
+    'border-right-width': ['length'],
+    'border-bottom-width': ['length'],
+    'border-left-width': ['length'],
+
+    'border-top-color': ['color'],
+    'border-right-color': ['color'],
+    'border-bottom-color': ['color'],
+    'border-left-color': ['color'],
+
+    'padding-bottom': ['length'],
+    'padding-left': ['length'],
+    'padding-right': ['length'],
+    'padding-top': ['length'],
+
+    'margin-bottom': ['length'],
+    'margin-left': ['length'],
+    'margin-right': ['length'],
+    'margin-top': ['length'],
+
+    'height': ['length', 'percentage'],
+    'width': ['length', 'percentage'],
+    'min-height': ['length', 'percentage'],
+    'min-width': ['length', 'percentage'],
+    'max-height': ['length', 'percentage'],
+    'max-width': ['length', 'percentage'],
+
+    'top': ['length', 'percentage'],
+    'right': ['length', 'percentage'],
+    'bottom': ['length', 'percentage'],
+    'left': ['length', 'percentage'],
+
+    'color': ['color'],
+    'font-size': ['length', 'percentage'],
+    'font-weight': ['font-weight'],
+    'line-height': ['number', 'length', 'percentage'],
+    'letter-spacing': ['length'],
+    // Note: percentage is Level3 and not implemented anywhere yet
+    // https://drafts.csswg.org/css3-text/#word-spacing
+    'word-spacing': ['length', 'percentage'],
+    'text-indent': ['length', 'percentage'],
+    'text-shadow': ['shadow'],
+
+    'outline-color': ['color'],
+    // outline-offset <integer> used to be an error in the spec
+    'outline-offset': ['length'],
+    'outline-width': ['length'],
+
+    'clip': ['rectangle'],
+    // Note: doesn't seem implemented anywhere
+    'crop': ['rectangle'],
+
+    'vertical-align': ['length', 'percentage'],
+    'opacity': ['number[0,1]'],
+    'visibility': ['visibility'],
+    'z-index': ['integer']
+};
+
+/*
+ * Property to auto-value mapping
+ * (lazily taken from http://www.siliconbaytraining.com/pages/csspv.html)
+ */
+var properties_auto = [
+    'margin-top',
+    'margin-right',
+    'margin-bottom',
+    'margin-left',
+    'height',
+    'width',
+    'clip',
+    'marker-offset',
+    'top',
+    'right',
+    'left',
+    'bottom',
+    'z-index'
+];
+
+/*
+ * Property to Type table
+ * (missing value-types of specified properties)
+ */
+var missing_properties = {
+    'margin-bottom': ['percentage'],
+    'margin-left': ['percentage'],
+    'margin-right': ['percentage'],
+    'margin-top': ['percentage'],
+    'padding-bottom': ['percentage'],
+    'padding-left': ['percentage'],
+    'padding-right': ['percentage'],
+    'padding-top': ['percentage'],
+    'vertical-align': ['vertical']
+};
+
+/*
+ * Property to Type table
+ * (properties that haven't been specified but implemented)
+ */
+var unspecified_properties = {
+    // http://oli.jp/2010/css-animatable-properties/
+    'border-top-left-radius': ['border-radius'],
+    'border-top-right-radius': ['border-radius'],
+    'border-bottom-left-radius': ['border-radius'],
+    'border-bottom-right-radius': ['border-radius'],
+    'background-image': ['image'],
+    'background-size': ['background-size'],
+    // https://drafts.csswg.org/css3-background/#the-box-shadow
+    // Animatable:   yes, except between inner and outer shadows (Transition to/from an absent shadow is a transition to/from ‘0 0 transparent’ or ‘0 0 transparent inset’, as appropriate.)
+    'box-shadow': ['box-shadow'],
+    'font-size-adjust': ['number'],
+    'font-stretch': ['font-stretch'],
+    'marker-offset': ['length'],
+    'text-decoration-color': ['color'],
+    'column-count': ['integer'],
+    'column-gap': ['length'],
+    'column-rule-color': ['color'],
+    'column-rule-width': ['length'],
+    'column-width': ['length'],
+    'transform': ['transform'],
+    'transform-origin': ['horizontal'],
+    'zoom': ['number'],
+    'outline-radius-topleft': ['length', 'percentage'],
+    'outline-radius-topright': ['length', 'percentage'],
+    'outline-radius-bottomright': ['length', 'percentage'],
+    'outline-radius-bottomleft': ['length', 'percentage'],
+    'display': ['display'],
+    'position': ['position']
+};
+
+/*
+ * additional styles required to actually render
+ * (different browsers expect different environment)
+ */
+var additional_styles = {
+    // all browsers
+    'border-top-width': {'border-top-style' : 'solid'},
+    'border-right-width': {'border-right-style' : 'solid'},
+    'border-bottom-width': {'border-bottom-style' : 'solid'},
+    'border-left-width': {'border-left-style' : 'solid'},
+    'top': {'position': 'absolute'},
+    'right': {'position': 'absolute'},
+    'bottom': {'position': 'absolute'},
+    'left': {'position': 'absolute'},
+    'z-index': {'position': 'absolute'},
+    'outline-offset': {'outline-style': 'solid'},
+    'outline-width': {'outline-style': 'solid'},
+    'word-spacing': {'width': '100px', 'height': '100px'},
+    // unspecified properties
+    'column-rule-width': {'column-rule-style': 'solid'},
+    'position': {'width': '50px', 'height': '50px', top: '10px', left: '50px'}
+};
+
+/*
+ * additional styles required *on the parent* to actually render
+ * (different browsers expect different environment)
+ */
+var parent_styles = {
+    'border-top-width': {'border-top-style' : 'solid'},
+    'border-right-width': {'border-right-style' : 'solid'},
+    'border-bottom-width': {'border-bottom-style' : 'solid'},
+    'border-left-width': {'border-left-style' : 'solid'},
+    'height': {'width': '100px', 'height': '100px'},
+    'min-height': {'width': '100px', 'height': '100px'},
+    'max-height': {'width': '100px', 'height': '100px'},
+    'width': {'width': '100px', 'height': '100px'},
+    'min-width': {'width': '100px', 'height': '100px'},
+    'max-width': {'width': '100px', 'height': '100px'},
+    // unspecified properties
+    'position': {'position': 'relative', 'width': '100px', 'height': '100px'},
+    // inheritance tests
+    'top': {'width': '100px', 'height': '100px', 'position': 'relative'},
+    'right': {'width': '100px', 'height': '100px', 'position': 'relative'},
+    'bottom': {'width': '100px', 'height': '100px', 'position': 'relative'},
+    'left': {'width': '100px', 'height': '100px', 'position': 'relative'}
+};
+
+
+function assemble(props) {
+    var tests = [];
+
+    // assemble tests
+    for (var property in props) {
+        props[property].forEach(function(type) {
+            var _values = values[type](property);
+            Object.keys(_values).forEach(function(unit) {
+                var data = {
+                    name: property + ' ' + type + '(' + unit + ')',
+                    property: property,
+                    valueType : type,
+                    unit : unit,
+                    parentStyle: extend({}, parent_styles[property] || {}),
+                    from: extend({}, additional_styles[property] || {}),
+                    to: {}
+                };
+
+                data.from[property] = _values[unit][0];
+                data.to[property] = _values[unit][1];
+                data.flags = _values[unit][2] || {};
+
+                tests.push(data);
+            });
+        });
+    }
+
+    return tests;
+}
+
+root.getPropertyTests = function() {
+    return assemble(properties);
+};
+
+root.getMissingPropertyTests = function() {
+    return assemble(missing_properties);
+};
+
+root.getUnspecifiedPropertyTests = function() {
+    return assemble(unspecified_properties);
+};
+
+root.getFontSizeRelativePropertyTests = function() {
+    var accepted = {};
+
+    for (var key in properties) {
+        if (!Object.prototype.hasOwnProperty.call(properties, key) || key === "font-size") {
+            continue;
+        }
+
+        if (properties[key].indexOf('length') > -1) {
+            accepted[key] = ['length-em'];
+        }
+    }
+
+    return assemble(accepted);
+};
+
+root.getAutoPropertyTests = function() {
+    var accepted = {};
+
+    for (var i = 0, key; key = properties_auto[i]; i++) {
+        accepted[key] = ['auto'];
+    }
+
+    return assemble(accepted);
+};
+
+root.filterPropertyTests = function(tests, names) {
+    var allowed = {};
+    var accepted = [];
+
+    if (typeof names === "string") {
+        names = [names];
+    }
+
+    if (!(names instanceof RegExp)) {
+        names.forEach(function(name) {
+            allowed[name] = true;
+        });
+    }
+
+    tests.forEach(function(test) {
+        if (names instanceof RegExp) {
+            if (!test.name.match(names)) {
+                return;
+            }
+        } else if (!allowed[test.name]) {
+            return;
+        }
+
+        accepted.push(test);
+    });
+
+    return accepted;
+};
+
+})(window);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/ruler-h-50%.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/ruler-h-50%.png
new file mode 100644
index 0000000..cf2eea6b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/ruler-h-50%.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/ruler-h-50px.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/ruler-h-50px.png
new file mode 100644
index 0000000..9f465836
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/ruler-h-50px.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/ruler-v-100px.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/ruler-v-100px.png
new file mode 100644
index 0000000..a837eca
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/ruler-v-100px.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/ruler-v-50px.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/ruler-v-50px.png
new file mode 100644
index 0000000..8414102
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/ruler-v-50px.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/runParallelAsyncHarness.js b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/runParallelAsyncHarness.js
new file mode 100644
index 0000000..6403d40
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/runParallelAsyncHarness.js
@@ -0,0 +1,145 @@
+(function(root){
+'use strict';
+// testharness doesn't know about async test queues,
+// so this wrapper takes care of that
+
+/* USAGE:
+    runParallelAsyncHarness({
+        // list of data to test, must be array of objects.
+        // each object must contain a "name" property to describe the test
+        // besides name, the object can contain whatever data you need
+        tests: [
+            {name: "name of test 1", custom: "data"},
+            {name: "name of test 2", custom: "data"},
+            // ...
+        ],
+
+        // number of tests (tests, not test-cases!) to run concurrently
+        testsPerSlice: 100,
+
+        // time in milliseconds a test-run takes
+        duration: 1000,
+
+        // test-cases to run for for the test - there must be at least one
+        // each case creates its separate async_test() instance
+        cases: {
+            // test case named "test1"
+            test1: {
+                // run as a async_test.step() this callback contains your primary assertions
+                start: function(testCaseKey, data, options){},
+                // run as a async_test.step() this callback contains assertions to be run
+                // when the test ended, immediately before teardown
+                done: function(testCaseKey, data, options){}
+            },
+            // ...
+        }
+
+        // all callbacks are optional:
+
+        // invoked for individual test before it starts so you can setup the environment
+        // like DOM, CSS, adding event listeners and such
+        setup: function(data, options){},
+
+        // invoked after a test ended, so you can clean up the environment
+        // like DOM, CSS, removing event listeners and such
+        teardown: function(data, options){},
+
+        // invoked before a batch of tests ("slice") are run concurrently
+        // tests is an array of test data objects
+        sliceStart: function(options, tests)
+
+        // invoked after a batch of tests ("slice") were run concurrently
+        // tests is an array of test data objects
+        sliceDone: function(options, tests)
+
+        // invoked once all tests are done
+        done: function(options){}
+    })
+*/
+root.runParallelAsyncHarness = function(options) {
+    if (!options.cases) {
+        throw new Error("Options don't contain test cases!");
+    }
+
+    var noop = function(){};
+
+    // add a 100ms buffer to the test timeout, just in case
+    var duration = Math.ceil(options.duration + 100);
+
+    // names of individual tests
+    var cases = Object.keys(options.cases);
+
+    // run tests in a batch of slices
+    // primarily not to overload weak devices (tablets, phones, …)
+    // with too many tests running simultaneously
+    var iteration = -1;
+    var testPerSlice = options.testsPerSlice || 100;
+    var slices = Math.ceil(options.tests.length / testPerSlice);
+
+    // initialize all async test cases
+    // Note: satisfying testharness.js needs to know all async tests before load-event
+    options.tests.forEach(function(data, index) {
+        data.cases = {};
+        cases.forEach(function(name) {
+            data.cases[name] = async_test(data.name + " / " + name, {timeout: options.timeout || 60000});
+        });
+    });
+
+    function runLoop() {
+        iteration++;
+        if (iteration >= slices) {
+            // no more slice, we're done
+            (options.done || noop)(options);
+            return;
+        }
+
+        // grab a slice of testss and initialize them
+        var offset = iteration * testPerSlice;
+        var tests = options.tests.slice(offset, offset + testPerSlice);
+        tests.forEach(function(data) {
+            (options.setup || noop)(data, options);
+
+        });
+
+        // kick off the current slice of tests
+        (options.sliceStart || noop)(options, tests);
+
+        // perform individual "start" test-case
+        tests.forEach(function(data) {
+            cases.forEach(function(name) {
+                data.cases[name].step(function() {
+                    (options.cases[name].start || noop)(data.cases[name], data, options);
+                });
+            });
+        });
+
+        // conclude test (possibly abort)
+        setTimeout(function() {
+            tests.forEach(function(data) {
+                // perform individual "done" test-case
+                cases.forEach(function(name) {
+                    data.cases[name].step(function() {
+                        (options.cases[name].done || noop)(data.cases[name], data, options);
+                    });
+                });
+                // clean up after individual test
+                (options.teardown || noop)(data, options);
+                // tell harness we're done with individual test-cases
+                cases.forEach(function(name) {
+                    data.cases[name].done();
+                });
+            });
+
+            // finish the test for current slice of tests
+            (options.sliceDone || noop)(options, tests);
+
+            // next test please, give the browser 50ms to do catch its breath
+            setTimeout(runLoop, 50);
+        }, duration);
+    }
+
+    // allow DOMContentLoaded before actually doing something
+    setTimeout(runLoop, 100);
+};
+
+})(window);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/square-purple.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/square-purple.png
new file mode 100644
index 0000000..0f522d7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/square-purple.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/square-teal.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/square-teal.png
new file mode 100644
index 0000000..e567f51
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/square-teal.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/square-white.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/square-white.png
new file mode 100644
index 0000000..5853cbb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/square-white.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/support/README b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/support/README
new file mode 100644
index 0000000..ea8cb9e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/support/README
@@ -0,0 +1,4 @@
+The swatch-green.png file in this directory is really a RED swatch,
+and the swatch-red.png file is really a green swatch.
+
+This directory is used to test relative URIs.
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/support/swatch-green.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/support/swatch-green.png
new file mode 100644
index 0000000..1caf25c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/support/swatch-green.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/support/swatch-red.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/support/swatch-red.png
new file mode 100644
index 0000000..0aa79b0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/support/swatch-red.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/swatch-blue.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/swatch-blue.png
new file mode 100644
index 0000000..bf27596
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/swatch-blue.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/swatch-green.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/swatch-green.png
new file mode 100644
index 0000000..0aa79b0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/swatch-green.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/swatch-lime.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/swatch-lime.png
new file mode 100644
index 0000000..55fd7fd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/swatch-lime.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/swatch-orange.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/swatch-orange.png
new file mode 100644
index 0000000..d3cd498b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/swatch-orange.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/swatch-red.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/swatch-red.png
new file mode 100644
index 0000000..1caf25c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/swatch-red.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/swatch-teal.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/swatch-teal.png
new file mode 100644
index 0000000..0293ce8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/swatch-teal.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/swatch-white.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/swatch-white.png
new file mode 100644
index 0000000..1a7d4323
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/swatch-white.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/swatch-yellow.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/swatch-yellow.png
new file mode 100644
index 0000000..1591aa0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/swatch-yellow.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/test-bl.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/test-bl.png
new file mode 100644
index 0000000..904e24e9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/test-bl.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/test-br.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/test-br.png
new file mode 100644
index 0000000..f413ff5c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/test-br.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/test-inner-half-size.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/test-inner-half-size.png
new file mode 100644
index 0000000..e473bf80
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/test-inner-half-size.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/test-outer.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/test-outer.png
new file mode 100644
index 0000000..82eeace7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/test-outer.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/test-tl.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/test-tl.png
new file mode 100644
index 0000000..f6ac0ef
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/test-tl.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/test-tr.png b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/test-tr.png
new file mode 100644
index 0000000..59843ae5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/test-tr.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/two.gif b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/two.gif
new file mode 100644
index 0000000..01435c8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/two.gif
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/vendorPrefix.js b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/vendorPrefix.js
new file mode 100644
index 0000000..16a78a5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/support/vendorPrefix.js
@@ -0,0 +1,86 @@
+//
+// Vendor-Prefix Helper Functions For Testing CSS
+//
+
+(function(root) {
+'use strict';
+
+var prefixCache = {};
+
+// convert "foo-bar" to "fooBar"
+function camelCase(str) {
+	return str.replace(/\-(\w)/g, function(match, letter){
+		return letter.toUpperCase();
+	});
+}
+
+// vendor-prefix a css property
+root.addVendorPrefix = function (name) {
+    var prefix = getVendorPrefix(name);
+    if (prefix === false) {
+        // property unknown to browser
+        return name;
+    }
+
+    return prefix + name;
+};
+
+// vendor-prefix a css property value
+root.addValueVendorPrefix = function (property, value) {
+    var prefix = getValueVendorPrefix(property, value);
+    if (prefix === false) {
+        // property unknown to browser
+        return name;
+    }
+
+    return prefix + value;
+};
+
+// identify vendor-prefix for css property
+root.getVendorPrefix = function(name) {
+    if (prefixCache[name] !== undefined) {
+        return prefixCache[name];
+    }
+
+    var elem = document.createElement("div");
+    name = camelCase(name);
+
+    if (name in elem.style) {
+        return prefixCache[name] = "";
+    }
+
+    var prefixes = ["Webkit", "Moz", "O", "ms"];
+    var styles = ["-webkit-", "-moz-", "-o-", "-ms-"];
+    var _name = name.substring(0, 1).toUpperCase() + name.substring(1);
+
+    for (var i = 0, length = prefixes.length; i < length; i++) {
+        if (prefixes[i] + _name in elem.style) {
+            return prefixCache[name] = styles[i];
+        }
+    }
+
+    return prefixCache[name] = name in elem.style ? "" : false;
+};
+
+// identify vendor-prefix for css property value
+root.getValueVendorPrefix = function(property, value) {
+    var elem = document.createElement("div");
+    // note: webkit needs the element to be attached to the dom
+    document.body.appendChild(elem);
+    var styles = ["-webkit-", "-moz-", "-o-", "-ms-", ""];
+    var _property = getVendorPrefix(property) + property;
+    for (var i=0, length = styles.length; i < length; i++) {
+        var _value = styles[i] + value;
+        elem.setAttribute('style', _property + ": " + _value);
+        var _computed = computedStyle(elem, _property);
+        if (_computed && _computed !== 'none') {
+            document.body.removeChild(elem);
+            return styles[i];
+        }
+    }
+    document.body.removeChild(elem);
+    return false;
+};
+
+
+})(window);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-001-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-001-expected.txt
new file mode 100644
index 0000000..13345dc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-001-expected.txt
@@ -0,0 +1,15 @@
+This is a testharness.js-based test.
+FAIL parse '1s' assert_equals: transition-timing-function expected "cubic-bezier(0.25, 0.1, 0.25, 1)" but got "ease"
+FAIL parse '1s 2s' assert_equals: transition-timing-function expected "cubic-bezier(0.25, 0.1, 0.25, 1)" but got "ease"
+FAIL parse '1s 2s ease-in' assert_equals: transition-timing-function expected "cubic-bezier(0.42, 0, 1, 1)" but got "ease-in"
+FAIL parse '1s ease-in 2s' assert_equals: transition-timing-function expected "cubic-bezier(0.42, 0, 1, 1)" but got "ease-in"
+FAIL parse 'ease-in 1s 2s' assert_equals: transition-timing-function expected "cubic-bezier(0.42, 0, 1, 1)" but got "ease-in"
+FAIL parse '1s width' assert_equals: transition-timing-function expected "cubic-bezier(0.25, 0.1, 0.25, 1)" but got "ease"
+FAIL parse 'width 1s' assert_equals: transition-timing-function expected "cubic-bezier(0.25, 0.1, 0.25, 1)" but got "ease"
+FAIL parse '1s width 2s' assert_equals: transition-timing-function expected "cubic-bezier(0.25, 0.1, 0.25, 1)" but got "ease"
+FAIL parse '1s 2s width ease-in' assert_equals: transition-timing-function expected "cubic-bezier(0.42, 0, 1, 1)" but got "ease-in"
+FAIL parse '1s ease-in 2s width' assert_equals: transition-timing-function expected "cubic-bezier(0.42, 0, 1, 1)" but got "ease-in"
+FAIL parse 'width ease-in 1s 2s' assert_equals: transition-timing-function expected "cubic-bezier(0.42, 0, 1, 1)" but got "ease-in"
+FAIL parse 'width .1s ease-in .2s' assert_equals: transition-timing-function expected "cubic-bezier(0.42, 0, 1, 1)" but got "ease-in"
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-001.html
new file mode 100644
index 0000000..bf01393
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-001.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>CSS Transitions Test: Parsing transition shorthand</title>
+        <meta name="assert" content="Test checks that transition shorthand values are parsed properly">
+        <link rel="help" title="2.5. The 'transition' Shorthand Property" href="http://www.w3.org/TR/css3-transitions/#transition-shorthand-property">
+        <link rel="author" title="Rodney Rehm" href="http://rodneyrehm.de/en/">
+        <meta name="flags" content="dom">
+
+        <script src="/resources/testharness.js" type="text/javascript"></script>
+        <script src="/resources/testharnessreport.js" type="text/javascript"></script>
+
+        <script src="./support/vendorPrefix.js" type="text/javascript"></script>
+        <script src="./support/helper.js" type="text/javascript"></script>
+    </head>
+    <body>
+        <!-- required by testharnessreport.js -->
+        <div id="log"></div>
+        <!-- elements used for testing -->
+        <div id="container">
+            <div id="transition"></div>
+        </div>
+
+        <script>
+            var transition = document.getElementById('transition');
+            var ease = 'cubic-bezier(0.25, 0.1, 0.25, 1)';
+            var easeIn = 'cubic-bezier(0.42, 0, 1, 1)';
+            // Note that order is important in this property. The first value that can be parsed as a time is assigned to
+            // the transition-duration. The second value that can be parsed as a time is assigned to transition-delay.
+            // [<‘transition-property’> || <‘transition-duration’> || <‘transition-timing-function’> || <‘transition-delay’> [, [<‘transition-property’> || <‘transition-duration’> || <‘transition-timing-function’> || <‘transition-delay’>]]*
+            var values = {
+                // [property, duration, timing, delay]
+                // random order
+                '1s' : ["all", "1s", ease, "0s"],
+                '1s 2s' : ["all", "1s", ease, "2s"],
+                '1s 2s ease-in' : ["all", "1s", easeIn, "2s"],
+                '1s ease-in 2s' : ["all", "1s", easeIn, "2s"],
+                'ease-in 1s 2s' : ["all", "1s", easeIn, "2s"],
+                '1s width' : ["width", "1s", ease, "0s"],
+                'width 1s' : ["width", "1s", ease, "0s"],
+                '1s width 2s' : ["width", "1s", ease, "2s"],
+                '1s 2s width ease-in' : ["width", "1s", easeIn, "2s"],
+                '1s ease-in 2s width' : ["width", "1s", easeIn, "2s"],
+                'width ease-in 1s 2s' : ["width", "1s", easeIn, "2s"],
+                'width .1s ease-in .2s' : ["width", "0.1s", easeIn, "0.2s"]
+            };
+
+            for (var key in values) {
+                if (Object.prototype.hasOwnProperty.call(values, key)) {
+                    test(function() {
+                        setStyle('#transition', {
+                            'transition': key
+                        });
+                        // WET much?
+                        assert_equals(computedStyle(transition, 'transition-property'), values[key][0], "transition-property");
+                        assert_equals(computedStyle(transition, 'transition-duration'), values[key][1], "transition-duration");
+                        assert_equals(computedStyle(transition, 'transition-timing-function'), values[key][2], "transition-timing-function");
+                        assert_equals(computedStyle(transition, 'transition-delay'), values[key][3], "transition-delay");
+                    }, "parse '" + key + "'");
+                }
+            }
+        </script>
+    </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-delay-000.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-delay-000.html
new file mode 100644
index 0000000..2b4cedb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-delay-000.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transition Test: transition-delay - positive number</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="2.4. The 'transition-delay' Property" href="http://www.w3.org/TR/css3-transitions/#transition-delay-property">
+<meta name="flags" content="interact">
+<meta name="assert" content="The 'transition-delay' property set positive number to delay the execution of transition">
+<style>
+  #test {
+    background-color: blue;
+    height: 100px;
+    transition-delay: 3s;
+    transition-property: background-color;
+    width: 100px;
+  }
+</style>
+<body>
+  <p>Click the blue square below. Test passes if the <strong>color</strong> of square is changed to <strong>green</strong> immediately
+  when the number inside square is <strong>3</strong>.</p>
+  <div id="test">0</div>
+  <script>
+    var clicked = 0;
+    var div = document.getElementById("test");
+    div.addEventListener("click", function(evt) {
+      if (clicked == 0) {
+        div.setAttribute("style", "background-color: green;");
+        setInterval(function() {
+          clicked++;
+          div.innerHTML = clicked;
+        }, 1000);
+      }
+    }, false);
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-delay-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-delay-001.html
new file mode 100644
index 0000000..921525ea
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-delay-001.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>CSS Transitions Test: Parsing transition-delay</title>
+        <meta name="assert" content="Test checks that transition-delay values are parsed properly">
+        <link rel="help" title="2.4. The 'transition-delay' Property" href="http://www.w3.org/TR/css3-transitions/#transition-delay-property">
+        <link rel="help" title="CSS Values and Units Module Level 3 - 6.2. Times: the ‘<time>’ type and ‘s’, ‘ms’ units" href="http://www.w3.org/TR/css3-values/#time">
+        <link rel="author" title="Rodney Rehm" href="http://rodneyrehm.de/en/">
+        <meta name="flags" content="dom">
+
+        <script src="/resources/testharness.js" type="text/javascript"></script>
+        <script src="/resources/testharnessreport.js" type="text/javascript"></script>
+
+        <script src="./support/vendorPrefix.js" type="text/javascript"></script>
+        <script src="./support/helper.js" type="text/javascript"></script>
+    </head>
+    <body>
+        <!-- required by testharnessreport.js -->
+        <div id="log"></div>
+        <!-- elements used for testing -->
+        <div id="container">
+            <div id="transition"></div>
+        </div>
+
+        <script>
+            var transition = document.getElementById('transition');
+            // <time> [, <time>]*
+            var values = {
+                // seconds
+                '10.2s': '10.2s',
+                '1s': '1s',
+                '0.1s': '0.1s',
+                '0.01s': '0.01s',
+                '0.001s': '0.001s',
+                '0.009s': '0.009s',
+                '0s': '0s',
+                '0s': '0s',
+                '.0s': '0s',
+                '0.0s': '0s',
+                '.3s': '0.3s',
+                '-5s' : '-5s',
+                // milliseconds
+                '10200ms': '10.2s',
+                '1000ms': '1s',
+                '100ms': '0.1s',
+                '10ms': '0.01s',
+                '9ms': '0.009s',
+                '1ms': '0.001s',
+                '0ms': '0s',
+                '-500ms' : '-0.5s',
+                // combination
+                '1s, 0.1s, 10ms': '1s, 0.1s, 0.01s',
+                // invalid
+                'foobar': '0s'
+            };
+
+            // these tests are supposed to fail and
+            // possibly make the engine issue a parser warning
+            var invalidTests = {
+                'foobar': true
+            };
+
+            for (var key in values) {
+                if (Object.prototype.hasOwnProperty.call(values, key)) {
+                    test(function() {
+                        setStyle('#transition', {
+                            'transition-delay': key
+                        });
+                        var result = computedStyle(transition, 'transition-delay');
+                        assert_equals(result, values[key], "Expected computed value");
+                    }, "parse '" + key + "'",
+                    {
+                        // mark tests that fail as such
+                        flags: invalidTests[key] ? "invalid" : ""
+                    });
+                }
+            }
+        </script>
+    </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-delay-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-delay-002.html
new file mode 100644
index 0000000..70e952b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-delay-002.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transition Test: transition-delay - 0s</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="2.4. The 'transition-delay' Property" href="http://www.w3.org/TR/css3-transitions/#transition-delay-property">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'transition-delay' property set 0 will not delay the execution of transition">
+<style>
+  div {
+    height: 100px;
+    transition-property: background-color;
+    width: 100px;
+  }
+  #ref {
+    background-color: gray;
+    transition-delay: 3s;
+  }
+  #test {
+    background-color: blue;
+    transition-delay: 0s;
+  }
+</style>
+<body>
+  <p>Click the blue square below. Test passes if the <strong>color</strong> of blue and gray squares is all changed to <strong>green</strong> immediately
+  when the number inside blue square is 3.</p>
+  <div id="ref"></div>
+  <div id="test">0</div>
+  <script>
+    var clicked = 0;
+    var ref = document.getElementById("ref");
+    var test = document.getElementById("test");
+    test.addEventListener("click", function(evt) {
+      if (clicked == 0) {
+        ref.setAttribute("style", "background-color: green;");
+        setInterval(function() {console.log(clicked);
+          if (clicked == 2) {
+            test.setAttribute("style", "background-color: green;");
+          }
+          clicked++;
+          test.innerHTML = clicked;
+        }, 1000);
+      }
+    }, false);
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-delay-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-delay-003.html
new file mode 100644
index 0000000..3062e9a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-delay-003.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transition Test: transition-delay - negative number</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="2.4. The 'transition-delay' Property" href="http://www.w3.org/TR/css3-transitions/#transition-delay-property">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'transition-delay' property set negative number will not delay the execution of transition">
+<style>
+  div {
+    height: 100px;
+    transition-property: background-color;
+    width: 100px;
+  }
+  #ref {
+    background-color: gray;
+    transition-delay: 3s;
+  }
+  #test {
+    background-color: blue;
+    transition-delay: -3s;
+  }
+</style>
+<body>
+  <p>Click the blue square below. Test passes if the <strong>color</strong> of blue and gray squares is all changed to <strong>green</strong> immediately
+  when the number inside blue square is 3.</p>
+  <div id="ref"></div>
+  <div id="test">0</div>
+  <script>
+    var clicked = 0;
+    var ref = document.getElementById("ref");
+    var test = document.getElementById("test");
+    test.addEventListener("click", function(evt) {
+      if (clicked == 0) {
+        ref.setAttribute("style", "background-color: green;");
+        setInterval(function() {console.log(clicked);
+          if (clicked == 2) {
+            test.setAttribute("style", "background-color: green;");
+          }
+          clicked++;
+          test.innerHTML = clicked;
+        }, 1000);
+      }
+    }, false);
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-duration-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-duration-001.html
new file mode 100644
index 0000000..b5c095f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-duration-001.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>CSS Transitions Test: Parsing transition-duration</title>
+        <meta name="assert" content="Test checks that transition-duration values are parsed properly">
+        <link rel="help" title="2.2. The 'transition-duration' Property" href="http://www.w3.org/TR/css3-transitions/#transition-duration-property">
+        <link rel="help" title="CSS Values and Units Module Level 3 - 6.2. Times: the ‘<time>’ type and ‘s’, ‘ms’ units" href="http://www.w3.org/TR/css3-values/#time">
+        <link rel="author" title="Rodney Rehm" href="http://rodneyrehm.de/en/">
+        <meta name="flags" content="dom">
+
+        <script src="/resources/testharness.js" type="text/javascript"></script>
+        <script src="/resources/testharnessreport.js" type="text/javascript"></script>
+
+        <script src="./support/vendorPrefix.js" type="text/javascript"></script>
+        <script src="./support/helper.js" type="text/javascript"></script>
+    </head>
+    <body>
+        <!-- required by testharnessreport.js -->
+        <div id="log"></div>
+        <!-- elements used for testing -->
+        <div id="container">
+            <div id="transition"></div>
+        </div>
+
+        <script>
+            var transition = document.getElementById('transition');
+            // <time> [, <time>]*
+            var values = {
+                // seconds
+                '10.2s': '10.2s',
+                '1s': '1s',
+                '0.1s': '0.1s',
+                '0.01s': '0.01s',
+                '0.001s': '0.001s',
+                '0.009s': '0.009s',
+                '0s': '0s',
+                '.0s': '0s',
+                '0.0s': '0s',
+                '.3s': '0.3s',
+                '-5s' : '0s',
+                // milliseconds
+                '10200ms': '10.2s',
+                '1000ms': '1s',
+                '100ms': '0.1s',
+                '10ms': '0.01s',
+                '9ms': '0.009s',
+                '1ms': '0.001s',
+                '0ms': '0s',
+                '-500ms' : '0s',
+                // combination
+                '1s, 0.1s, 10ms': '1s, 0.1s, 0.01s',
+                // invalid
+                'foobar': '0s'
+            };
+
+            // these tests are supposed to fail and
+            // possibly make the engine issue a parser warning
+            var invalidTests = {
+                '-5s': true,
+                '-500ms': true,
+                'foobar': true
+            };
+
+            for (var key in values) {
+                if (Object.prototype.hasOwnProperty.call(values, key)) {
+                    test(function() {
+                        setStyle('#transition', {
+                            'transition-duration': key
+                        });
+                        var result = computedStyle(transition, 'transition-duration');
+                        assert_equals(result, values[key], "Expected computed value");
+                    }, "parse '" + key + "'",
+                    {
+                        // mark tests that fail as such
+                        flags: invalidTests[key] ? "invalid" : ""
+                    });
+                }
+            }
+        </script>
+    </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-duration-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-duration-002.html
new file mode 100644
index 0000000..e9ba5760
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-duration-002.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-duration - positive number</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="2.2. The 'transition-duration' Property" href="http://www.w3.org/TR/css3-transitions/#transition-duration-property">
+<meta name="flags" content="interact">
+<meta name="assert" content="The 'transition-duration' property set positive number specifies the time that transition from the old value to the new value should take.">
+<style>
+  div {
+    background-color: yellow;
+    height: 100px;
+    transition-duration: 2s;
+    transition-property: width;
+    transition-timing-function: linear;
+    width: 100px;
+  }
+</style>
+<body>
+  <p>Click the yellow square below. Test passes if the width of square stops growing when the number inside square is '2'.</p>
+  <div>0</div>
+  <script>
+    (function() {
+      var div = document.querySelector("div");
+      div.addEventListener("click", function(evt) {
+        div.setAttribute("style", "width: 200px;");
+        setInterval(function() {
+          var timer = parseInt(div.textContent, 10);
+          timer++;
+          div.textContent = timer;
+        }, 1000);
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-duration-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-duration-003.html
new file mode 100644
index 0000000..bb68b5f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-duration-003.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-duration - 0s(initial value)</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="2.2. The 'transition-duration' Property" href="http://www.w3.org/TR/css3-transitions/#transition-duration-property">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the initial value of 'transition-duration' property is '0s' which means the transition is immediate.">
+<style>
+  div {
+    height: 100px;
+    transition-property: width;
+    transition-timing-function: linear;
+    width: 100px;
+  }
+  #ref1 {
+    background-color: yellow;
+    transition-duration: 2s;
+  }
+  #ref2 {
+    background-color: gray;
+    transition-duration: 0s;
+  }
+  #test {
+    background-color: blue;
+  }
+</style>
+<body>
+  <p>Click the 'Start' button below. Test passes if the width of yellow square grows smoothly but the gray and blue grow immediately.</p>
+  <div id="ref1"></div>
+  <div id="ref2"></div>
+  <div id="test"></div>
+  <button>Start</button>
+  <script>
+    (function() {
+      var button = document.querySelector("button"),
+          test = document.querySelector("#test"),
+          ref1 = document.querySelector("#ref1"),
+          ref2 = document.querySelector("#ref2")
+      button.addEventListener("click", function(evt) {
+        test.setAttribute("style", "width: 300px;");
+        ref1.setAttribute("style", "width: 300px;");
+        ref2.setAttribute("style", "width: 300px;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-duration-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-duration-004.html
new file mode 100644
index 0000000..01c424733
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-duration-004.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-duration - negative number</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="2.2. The 'transition-duration' Property" href="http://www.w3.org/TR/css3-transitions/#transition-duration-property">
+<meta name="flags" content="interact">
+<meta name="assert" content="A negative value for 'transition-duration renders the declaration invalid which means the transition is immediate.">
+<style>
+  div {
+    height: 100px;
+    transition-property: width;
+    transition-timing-function: linear;
+    width: 100px;
+  }
+  #ref {
+    background-color: yellow;
+    transition-duration: 2s;
+  }
+  #test {
+    background-color: blue;
+    transition-duration: -2s;
+  }
+</style>
+<body>
+  <p>Click the 'Start' button below. Test passes if the width of yellow square grows smoothly but the blue grows immediately.</p>
+  <div id="ref"></div>
+  <div id="test"></div>
+  <button>Start</button>
+  <script>
+    (function() {
+      var button = document.querySelector("button"),
+          test = document.querySelector("#test"),
+          ref = document.querySelector("#ref");
+      button.addEventListener("click", function(evt) {
+        test.setAttribute("style", "width: 200px;");
+        ref.setAttribute("style", "width: 200px;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-001.html
new file mode 100644
index 0000000..47a14170
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-001.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>CSS Transitions Test: Parsing transition-property</title>
+        <meta name="assert" content="Test checks that transition-property values are parsed properly">
+        <link rel="help" title="2.1. The 'transition-property' Property" href="http://www.w3.org/TR/css3-transitions/#transition-property-property">
+        <link rel="author" title="Rodney Rehm" href="http://rodneyrehm.de/en/">
+        <meta name="flags" content="dom">
+
+        <script src="/resources/testharness.js" type="text/javascript"></script>
+        <script src="/resources/testharnessreport.js" type="text/javascript"></script>
+
+        <script src="./support/vendorPrefix.js" type="text/javascript"></script>
+        <script src="./support/helper.js" type="text/javascript"></script>
+    </head>
+    <body>
+        <!-- required by testharnessreport.js -->
+        <div id="log"></div>
+        <!-- elements used for testing -->
+        <div id="container">
+            <div id="transition"></div>
+        </div>
+
+        <script>
+            var transition = document.getElementById('transition');
+
+            // syntax: none | [ all | <IDENT> ] [ ‘,’ [ all | <IDENT> ] ]*
+            var values = [
+                'none', 'all', 'width', 'all, width', 'width, all'
+            ];
+
+            for (var i = 0, value; value = values[i]; i++) {
+                test(function() {
+                    setStyle('#transition', {
+                        'transition-property': value
+                    });
+                    var result = computedStyle(transition, 'transition-property');
+                    assert_equals(result, value);
+                }, "parse '" + value + "'");
+            }
+        </script>
+    </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-002-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-002-expected.txt
new file mode 100644
index 0000000..cdbe8a1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-002-expected.txt
@@ -0,0 +1,10 @@
+This is a testharness.js-based test.
+FAIL parse 'none, all' assert_equals: expected "none, all" but got "all"
+FAIL parse 'all, none' assert_equals: expected "all, none" but got "all"
+PASS parse 'foobar'
+PASS parse 'all, foobar'
+PASS parse 'foobar, all'
+PASS parse 'inherit'
+PASS parse 'initial'
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-002.html
new file mode 100644
index 0000000..99196b6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-002.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>CSS Transitions Test: Parsing invalid transition-property</title>
+        <meta name="assert" content="Test checks that unrecognized or non-animatable properties must be kept in the list to preserve the matching of indices.">
+        <link rel="help" title="2.1. The 'transition-property' Property" href="http://www.w3.org/TR/css3-transitions/#transition-property-property">
+        <link rel="author" title="Rodney Rehm" href="http://rodneyrehm.de/en/">
+        <meta name="flags" content="dom ">
+
+        <script src="/resources/testharness.js" type="text/javascript"></script>
+        <script src="/resources/testharnessreport.js" type="text/javascript"></script>
+
+        <script src="./support/vendorPrefix.js" type="text/javascript"></script>
+        <script src="./support/helper.js" type="text/javascript"></script>
+    </head>
+    <body>
+        <!-- required by testharnessreport.js -->
+        <div id="log"></div>
+        <!-- elements used for testing -->
+        <div id="container">
+            <div id="transition"></div>
+        </div>
+
+        <script>
+            var transition = document.getElementById('transition');
+
+            // syntax: none | [ all | <IDENT> ] [ ‘,’ [ all | <IDENT> ] ]*
+            var values = {
+                'none, all' : 'none, all',
+                'all, none' : 'all, none',
+                'foobar' : 'foobar',
+                'all, foobar' : 'all, foobar',
+                'foobar, all' : 'foobar, all',
+                'inherit' : 'padding',
+                'initial' : 'all'
+            };
+
+            for (var key in values) {
+                test(function() {
+                    setStyle({
+                        '#container': {'transition-property': 'padding'},
+                        '#transition': {'transition-property': key}
+                    });
+                    var result = computedStyle(transition, 'transition-property');
+                    assert_equals(result, values[key]);
+                }, "parse '" + key + "'");
+            }
+        </script>
+    </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-003.html
new file mode 100644
index 0000000..17668b05
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-003.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - none</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="2.1. The 'transition-property' Property" href="http://www.w3.org/TR/css3-transitions/#transition-property-property">
+<meta name="flags" content="interact">
+<meta name="assert" content="The 'transition-duration' property set 'none' means that no property will be transitioned.">
+<style>
+  div {
+    height: 100px;
+    transition-timing-function: linear;
+    width: 100px;
+  }
+  #ref {
+    background-color: yellow;
+    transition-duration: 2s;
+    transition-property: width;
+  }
+  #test {
+    background-color: blue;
+    transition-property: none;
+  }
+</style>
+<body>
+  <p>Click the 'Start' button below. Test passes if the width of yellow square grows smoothly but the blue grows immediately.</p>
+  <div id="ref"></div>
+  <div id="test"></div>
+  <button>Start</button>
+  <script>
+    (function() {
+      var button = document.querySelector("button"),
+          test = document.querySelector("#test"),
+          ref = document.querySelector("#ref");
+      button.addEventListener("click", function(evt) {
+        test.setAttribute("style", "width: 200px;");
+        ref.setAttribute("style", "width: 200px;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-004.html
new file mode 100644
index 0000000..6393c6e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-004.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - all</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="2.1. The 'transition-property' Property" href="http://www.w3.org/TR/css3-transitions/#transition-property-property">
+<meta name="flags" content="interact">
+<meta name="assert" content="The 'transition-duration' property set 'all' means that all properties are transitioned.">
+<style>
+  #test {
+    background-color: blue;
+    height: 100px;
+    transition-duration: 2s;
+    transition-property: all;
+    transition-timing-function: linear;
+    width: 100px;
+  }
+</style>
+<body>
+  <p>Click the blue square below. Test passes if both height and width of blue square grow smoothly.</p>
+  <div id="test"></div>
+  <script>
+    (function() {
+      var div = document.querySelector("#test");
+      div.addEventListener("click", function(evt) {
+        div.setAttribute("style", "height: 200px; width: 200px;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-005.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-005.html
new file mode 100644
index 0000000..a10ff4a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-005.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - height width(more than one properties specified)</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="2.1. The 'transition-property' Property" href="http://www.w3.org/TR/css3-transitions/#transition-property-property">
+<meta name="flags" content="interact">
+<meta name="assert" content="The 'transition-duration' property set more than one properties like 'height, width'
+means only the specified properties will be transitioned.">
+<style>
+  #test {
+    background-color: red;
+    height: 100px;
+    transition-duration: 2s;
+    transition-property: height, width;
+    transition-timing-function: linear;
+    width: 100px;
+  }
+</style>
+<body>
+  <p>Click the red square below. Test passes if both height and width of square grow smoothly but the color changed to green immediately.</p>
+  <div id="test"></div>
+  <script>
+    (function() {
+      var div = document.querySelector("#test");
+      div.addEventListener("click", function(evt) {
+        div.setAttribute("style", "background-color: green; height: 200px; width: 200px;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-006.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-006.html
new file mode 100644
index 0000000..e7d8c5e3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-006.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - background-position</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'background-position' property is animatable.">
+<style>
+  #test {
+    border: 1px solid;
+    background-image: url("support/cat.png");
+    background-position: left;
+    background-repeat: no-repeat;
+    height: 200px;
+    transition-duration: 8s;
+    transition-property: background-position;
+    transition-timing-function: linear;
+  }
+</style>
+<body>
+  <p>Click the image inside of box below. Test passes if the image moves gradually but not immediately from left to right until it stops.</p>
+  <div id="test"></div>
+  <script>
+    (function() {
+      var div = document.querySelector("#test");
+      div.addEventListener("click", function(evt) {
+        div.setAttribute("style", "background-position: right;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-007.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-007.html
new file mode 100644
index 0000000..0d006fe
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-007.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - border-bottom-color</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'border-bottom-color' property animatable.">
+<style>
+  #test {
+    border: 10px solid red;
+    height: 90px;
+    transition-duration: 2s;
+    transition-property: border-bottom-color;
+    transition-timing-function: linear;
+    width: 90px;
+  }
+</style>
+<body>
+  <p>Click the square with red border below. Test passes if the color of bottom border transforms to green gradually not immediately.</p>
+  <div id="test"></div>
+  <script>
+    (function() {
+      var div = document.querySelector("#test");
+      div.addEventListener("click", function(evt) {
+        div.setAttribute("style", "border-bottom-color: green;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-008.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-008.html
new file mode 100644
index 0000000..47ca1eee
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-008.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - border-bottom-width</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'border-bottom-width' property animatable.">
+<style>
+  #test {
+    border: 5px solid blue;
+    height: 90px;
+    transition-duration: 2s;
+    transition-property: border-bottom-width;
+    transition-timing-function: linear;
+    width: 90px;
+  }
+</style>
+<body>
+  <p>Click the square with blue border below. Test passes if the height of bottom border grows gradually not immediately until it stops.</p>
+  <div id="test"></div>
+  <script>
+    (function() {
+      var div = document.querySelector("#test");
+      div.addEventListener("click", function(evt) {
+        div.setAttribute("style", "border-bottom-width: 20px;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-009.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-009.html
new file mode 100644
index 0000000..b45948b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-009.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - border-left-color</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'border-left-color' property is animatable.">
+<style>
+  #test {
+    border: 10px solid red;
+    height: 90px;
+    transition-duration: 2s;
+    transition-property: border-left-color;
+    transition-timing-function: linear;
+    width: 90px;
+  }
+</style>
+<body>
+  <p>Click the square with red border below. Test passes if the color of left border transforms to green gradually not immediately.</p>
+  <div id="test"></div>
+  <script>
+    (function() {
+      var div = document.querySelector("#test");
+      div.addEventListener("click", function(evt) {
+        div.setAttribute("style", "border-left-color: green;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-010.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-010.html
new file mode 100644
index 0000000..f05f6aa
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-010.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - border-left-width</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'border-left-width' property is animatable.">
+<style>
+  #test {
+    border: 5px solid blue;
+    height: 90px;
+    transition-duration: 2s;
+    transition-property: border-left-width;
+    transition-timing-function: linear;
+    width: 90px;
+  }
+</style>
+<body>
+  <p>Click the square with blue border below. Test passes if the width of left border grows gradually not immediately until it stops.</p>
+  <div id="test"></div>
+  <script>
+    (function() {
+      var div = document.querySelector("#test");
+      div.addEventListener("click", function(evt) {
+        div.setAttribute("style", "border-left-width: 20px;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-011.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-011.html
new file mode 100644
index 0000000..7b3716d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-011.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - border-right-color</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'border-right-color' property is animatable.">
+<style>
+  #test {
+    border: 10px solid red;
+    height: 90px;
+    transition-duration: 2s;
+    transition-property: border-right-color;
+    transition-timing-function: linear;
+    width: 90px;
+  }
+</style>
+<body>
+  <p>Click the square with red border below. Test passes if the color of right border transforms to green gradually not immediately.</p>
+  <div id="test"></div>
+  <script>
+    (function() {
+      var div = document.querySelector("#test");
+      div.addEventListener("click", function(evt) {
+        div.setAttribute("style", "border-right-color: green;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-012.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-012.html
new file mode 100644
index 0000000..0e19e52
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-012.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - border-right-width</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'border-right-width' property is animatable.">
+<style>
+  #test {
+    border: 5px solid blue;
+    height: 90px;
+    transition-duration: 2s;
+    transition-property: border-right-width;
+    transition-timing-function: linear;
+    width: 90px;
+  }
+</style>
+<body>
+  <p>Click the square with blue border below. Test passes if the width of right border grows gradually not immediately until it stops.</p>
+  <div id="test"></div>
+  <script>
+    (function() {
+      var div = document.querySelector("#test");
+      div.addEventListener("click", function(evt) {
+        div.setAttribute("style", "border-right-width: 20px;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-013.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-013.html
new file mode 100644
index 0000000..9fb075b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-013.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - border-top-color</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'border-top-color' property is animatable.">
+<style>
+  #test {
+    border: 10px solid red;
+    height: 90px;
+    transition-duration: 2s;
+    transition-property: border-top-color;
+    transition-timing-function: linear;
+    width: 90px;
+  }
+</style>
+<body>
+  <p>Click the square with red border below. Test passes if the color of top border transforms to green gradually not immediately.</p>
+  <div id="test"></div>
+  <script>
+    (function() {
+      var div = document.querySelector("#test");
+      div.addEventListener("click", function(evt) {
+        div.setAttribute("style", "border-top-color: green;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-014.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-014.html
new file mode 100644
index 0000000..91075ff
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-014.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - border-top-width</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'border-top-width' property is animatable.">
+<style>
+  #test {
+    border: 5px solid blue;
+    height: 90px;
+    transition-duration: 2s;
+    transition-property: border-top-width;
+    transition-timing-function: linear;
+    width: 90px;
+  }
+</style>
+<body>
+  <p>Click the square with blue border below. Test passes if the height of top border grows gradually not immediately until it stops.</p>
+  <div id="test"></div>
+  <script>
+    (function() {
+      var div = document.querySelector("#test");
+      div.addEventListener("click", function(evt) {
+        div.setAttribute("style", "border-top-width: 20px;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-015.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-015.html
new file mode 100644
index 0000000..b37d4fc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-015.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - border-spacing</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'border-spacing' property is animatable.">
+<style>
+  #test {
+    border-spacing: 10px;
+    transition-duration: 2s;
+    transition-property: border-spacing;
+    transition-timing-function: linear;
+  }
+</style>
+<body>
+  <p>Click the 'FillerText' below. Test passes if the outermost border of 'FillerText' grows gradually not immediately until it stops.</p>
+  <table id="test" border="1">
+    <tr><td>FillerText</td></tr>
+  </table>
+  <script>
+    (function() {
+      var test = document.querySelector("#test");
+      test.addEventListener("click", function(evt) {
+        test.setAttribute("style", "border-spacing: 40px;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-016.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-016.html
new file mode 100644
index 0000000..2670cd7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-016.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - bottom</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'bottom' property is animatable.">
+<style>
+  #test {
+    background-color: blue;
+    bottom: -100px;
+    height: 100px;
+    position: relative;
+    transition-duration: 2s;
+    transition-property: bottom;
+    transition-timing-function: linear;
+    width: 100px;
+  }
+</style>
+<body>
+  <p>Click the blue square below. Test passes if blue square moves up gradually not immediately until it stops.</p>
+  <div id="test"></div>
+  <script>
+    (function() {
+      var div = document.querySelector("#test");
+      div.addEventListener("click", function(evt) {
+        div.setAttribute("style", "bottom: 10px;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-017.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-017.html
new file mode 100644
index 0000000..3b94ecd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-017.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - clip</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'clip' property is animatable.">
+<style>
+  #test {
+    clip: rect(0px, 60px, 60px, 0px);
+    position: absolute;
+    transition-duration: 2s;
+    transition-property: clip;
+    transition-timing-function: linear;
+  }
+</style>
+<body>
+  <p>Click the image(half green and half red) below. Test passes if the half red condenses gradually not immediately until only half green left.</p>
+  <image id="test" src="support/60x60-gg-rr.png"></image>
+  <script>
+    (function() {
+      var image = document.querySelector("#test");
+      image.addEventListener("click", function(evt) {
+        image.setAttribute("style", "clip: rect(0px, 60px, 30px, 0px);");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-018.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-018.html
new file mode 100644
index 0000000..593e3ff
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-018.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - color</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'color' property is animatable.">
+<style>
+  #test {
+    color: red;
+    transition-duration: 2s;
+    transition-property: color;
+    transition-timing-function: linear;
+  }
+</style>
+<body>
+  <p>Click the 'FillerText' whose color is red below. Test passes if the color transforms to green gradually not immediately.</p>
+  <div id="test">
+    FillerTextFillerTextFillerTextFillerText
+  </div>
+  <script>
+    (function() {
+      var test = document.querySelector("#test");
+      test.addEventListener("click", function(evt) {
+        test.setAttribute("style", "color: green;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-019.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-019.html
new file mode 100644
index 0000000..83f9000
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-019.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - font-size</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'font-size' property is animatable.">
+<style>
+  #test {
+    font-size: 20px;
+    transition-duration: 2s;
+    transition-property: font-size;
+    transition-timing-function: linear;
+  }
+</style>
+<body>
+  <p>Click the 'FillerText' below. Test passes if the size of 'FillerText' increases gradually not immediately until it stops.</p>
+  <div id="test">
+    FillerTextFillerTextFillerTextFillerText
+  </div>
+  <script>
+    (function() {
+      var test = document.querySelector("#test");
+      test.addEventListener("click", function(evt) {
+        test.setAttribute("style", "font-size: 40px;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-020.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-020.html
new file mode 100644
index 0000000..af0aea41
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-020.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - font-weight</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'font-weight' property is animatable.">
+<style>
+  #test {
+    font-weight: 100;
+    transition-duration: 2s;
+    transition-property: font-weight;
+    transition-timing-function: linear;
+  }
+</style>
+<body>
+  <p>Click the 'FillerText' below. Test passes if the weight of 'FillerText' increases gradually not immediately until it stops.</p>
+  <div id="test">
+    FillerTextFillerTextFillerTextFillerText
+  </div>
+  <script>
+    (function() {
+      var test = document.querySelector("#test");
+      test.addEventListener("click", function(evt) {
+        test.setAttribute("style", "font-weight: 900;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-021.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-021.html
new file mode 100644
index 0000000..f499c9a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-021.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - left</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'left' property is animatable.">
+<style>
+  #test {
+    background-color: blue;
+    height: 100px;
+    left: 10px;
+    position: relative;
+    transition-duration: 4s;
+    transition-property: left;
+    transition-timing-function: linear;
+    width: 100px;
+  }
+</style>
+<body>
+  <p>Click the blue square inside the box with black border below. Test passes if the blue square moves gradually not immediately from left to right until it stops.</p>
+  <div id="test"></div>
+  <script>
+    (function() {
+      var test = document.querySelector("#test");
+      test.addEventListener("click", function(evt) {
+        test.setAttribute("style", "left: 400px;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-022.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-022.html
new file mode 100644
index 0000000..eb29b11
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-022.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - letter-spacing</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="ahem interact">
+<meta name="assert" content="Test checks that the 'letter-spacing' property is animatable.">
+<style>
+  #test {
+    font-family: ahem;
+    letter-spacing: 0px;
+    transition-duration: 4s;
+    transition-property: letter-spacing;
+    transition-timing-function: linear;
+  }
+</style>
+<body>
+  <p>Click the black rectangle below. Test passes if the black rectangle splits into ten little squares and the spacing between little squares increases gradually not immediately until it stops.</p>
+  <div id="test">FillerText</div>
+  <script>
+    (function() {
+      var test = document.querySelector("#test");
+      test.addEventListener("click", function(evt) {
+        test.setAttribute("style", "letter-spacing: 20px;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-023.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-023.html
new file mode 100644
index 0000000..81c8cadac
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-023.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - line-height</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'line-height' property is animatable.">
+<style>
+  #test {
+    line-height: 10px;
+    transition-duration: 4s;
+    transition-property: line-height;
+    transition-timing-function: linear;
+  }
+</style>
+<body>
+  <p>Click the 'FillerText' below. Test passes if the 'FillerText' moves down gradually not immediately until it stops.</p>
+  <div id="test">FillerTextFillerText</div>
+  <script>
+    (function() {
+      var test = document.querySelector("#test");
+      test.addEventListener("click", function(evt) {
+        test.setAttribute("style", "line-height: 100px;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-024.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-024.html
new file mode 100644
index 0000000..b0e9d41d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-024.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - margin-bottom</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'margin-bottom' property is animatable.">
+<style>
+  #ref {
+    background-color: blue;
+    height: 100px;
+    width: 100px;
+  }
+  #test {
+    margin-bottom: 1px;
+    transition-duration: 4s;
+    transition-property: margin-bottom;
+    transition-timing-function: linear;
+  }
+</style>
+<body>
+  <p id="test">Click blue square below. Test passes if the blue square moves down gradually not immediately until it stops.</p>
+  <div id="ref"></div>
+  <script>
+    (function() {
+      var ref = document.querySelector("#ref");
+      ref.addEventListener("click", function(evt) {
+        document.querySelector("#test").setAttribute("style", "margin-bottom: 100px;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-025.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-025.html
new file mode 100644
index 0000000..bfa6f698
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-025.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - margin-left</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'margin-left' property is animatable.">
+<style>
+  #test {
+    background-color: blue;
+    height: 100px;
+    margin-left: 1px;
+    transition-duration: 4s;
+    transition-property: margin-left;
+    transition-timing-function: linear;
+    width: 100px;
+  }
+</style>
+<body>
+  <p>Click the blue square below. Test passes if the blue square moves gradually not immediately from left to right until it stops.</p>
+  <div id="test"></div>
+  <script>
+    (function() {
+      var test = document.querySelector("#test");
+      test.addEventListener("click", function(evt) {
+        test.setAttribute("style", "margin-left: 200px;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-026.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-026.html
new file mode 100644
index 0000000..d6f0481
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-026.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - margin-right</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'margin-right' property is animatable.">
+<style>
+  div {
+    float: left;
+  }
+  #ref {
+    height: 100px;
+    margin-right: 1px;
+    transition-duration: 4s;
+    transition-property: margin-right;
+    transition-timing-function: linear;
+    width: 1px;
+  }
+  #test {
+    background-color: blue;
+    height: 100px;
+    width: 100px;
+  }
+</style>
+<body>
+  <p>Click the blue square below. Test passes if the blue square moves gradually not immediately from left to right until it stops.</p>
+  <div id="ref"></div>
+  <div id="test"></div>
+  <script>
+    (function() {
+      var test = document.querySelector("#test");
+      test.addEventListener("click", function(evt) {
+        document.querySelector("#ref").setAttribute("style", "margin-right: 200px;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-027.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-027.html
new file mode 100644
index 0000000..01f50dc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-027.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - max-height</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'max-height' property is animatable.">
+<style>
+  #test {
+    background-color: blue;
+    height: 200px;
+    max-height: 200px;
+    transition-duration: 4s;
+    transition-property: max-height;
+    transition-timing-function: linear;
+    width: 100px;
+  }
+</style>
+<body>
+  <p>Click the blue rectangle below. Test passes if the height of blue rectangle narrows gradually not immediately until it stops.</p>
+  <div id="test"></div>
+  <script>
+    (function() {
+      var test = document.querySelector("#test");
+      test.addEventListener("click", function(evt) {
+        test.setAttribute("style", "max-height: 100px;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-028.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-028.html
new file mode 100644
index 0000000..83d87511
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-028.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - max-width</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'max-width' property is animatable.">
+<style>
+  #test {
+    background-color: blue;
+    height: 100px;
+    max-width: 200px;
+    transition-duration: 4s;
+    transition-property: max-width;
+    transition-timing-function: linear;
+    width: 200px;
+  }
+</style>
+<body>
+  <p>Click the blue rectangle below. Test passes if the width of blue rectangle narrows gradually not immediately until it stops.</p>
+  <div id="test"></div>
+  <script>
+    (function() {
+      var test = document.querySelector("#test");
+      test.addEventListener("click", function(evt) {
+        test.setAttribute("style", "max-width: 100px;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-029.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-029.html
new file mode 100644
index 0000000..fb435c91
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-029.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - min-height</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'min-height' property is animatable.">
+<style>
+  #test {
+    background-color: blue;
+    height: 50px;
+    min-height: 50px;
+    transition-duration: 4s;
+    transition-property: min-height;
+    transition-timing-function: linear;
+    width: 100px;
+  }
+</style>
+<body>
+  <p>Click the blue rectangle below. Test passes if the height of blue rectangle increases gradually not immediately until it stops.</p>
+  <div id="test"></div>
+  <script>
+    (function() {
+      var test = document.querySelector("#test");
+      test.addEventListener("click", function(evt) {
+        test.setAttribute("style", "min-height: 100px;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-030.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-030.html
new file mode 100644
index 0000000..286af42
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-030.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - min-width</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'min-width' property is animatable.">
+<style>
+  #test {
+    background-color: blue;
+    height: 100px;
+    min-width: 50px;
+    transition-duration: 4s;
+    transition-property: min-width;
+    transition-timing-function: linear;
+    width: 50px;
+  }
+</style>
+<body>
+  <p>Click the blue rectangle below. Test passes if the width of blue rectangle increases gradually not immediately until it stops.</p>
+  <div id="test"></div>
+  <script>
+    (function() {
+      var test = document.querySelector("#test");
+      test.addEventListener("click", function(evt) {
+        test.setAttribute("style", "min-width: 100px;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-031.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-031.html
new file mode 100644
index 0000000..d5bf232
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-031.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - opacity</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'opacity' property is animatable.">
+<style>
+  #test {
+    background-color: red;
+    height: 100px;
+    opacity: 1;
+    transition-duration: 2s;
+    transition-property: opacity;
+    transition-timing-function: linear;
+    width: 100px;
+  }
+</style>
+<body>
+  <p>Click the red square below. Test passes if the red square blurs gradually not immediately until it disappears.</p>
+  <div id="test"></div>
+  <script>
+    (function() {
+      var test = document.querySelector("#test");
+      test.addEventListener("click", function(evt) {
+        test.setAttribute("style", "opacity: 0;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-032.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-032.html
new file mode 100644
index 0000000..020a857
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-032.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - outline-color</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'outline-color' property is animatable.">
+<style>
+  #test {
+    height: 100px;
+    outline-style: solid;
+    outline-color: red;
+    outline-width: 4px;
+    transition-duration: 2s;
+    transition-property: outline-color;
+    transition-timing-function: linear;
+    width: 100px;
+  }
+</style>
+<body>
+  <p>Click the blank square with red border below. Test passes if the color of border transforms to green gradually not immediately.</p>
+  <div id="test"></div>
+  <script>
+    (function() {
+      var test = document.querySelector("#test");
+      test.addEventListener("click", function(evt) {
+        test.setAttribute("style", "outline-color: green;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-033.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-033.html
new file mode 100644
index 0000000..fcb999fa
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-033.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - outline-width</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'outline-width' property is animatable.">
+<style>
+  #test {
+    height: 100px;
+    margin-left: 20px;
+    outline-style: solid;
+    outline-width: 2px;
+    transition-duration: 2s;
+    transition-property: outline-width;
+    transition-timing-function: linear;
+    width: 100px;
+  }
+</style>
+<body>
+  <p>Click the blank square with black border below. Test passes if the width of border increases gradually not immediately until it stops.</p>
+  <div id="test"></div>
+  <script>
+    (function() {
+      var test = document.querySelector("#test");
+      test.addEventListener("click", function(evt) {
+        test.setAttribute("style", "outline-width: 10px;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-034.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-034.html
new file mode 100644
index 0000000..b4da3a9b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-034.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - padding-bottom</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'padding-bottom' property is animatable.">
+<style>
+  #test {
+    background-color: blue;
+    height: 100px;
+    padding-bottom: 0px;
+    transition-duration: 2s;
+    transition-property: padding-bottom;
+    transition-timing-function: linear;
+    width: 100px;
+  }
+</style>
+<body>
+  <p>Click the blue square below. Test passes if the height of blue square increases gradually not immediately until it stops.</p>
+  <div id="test"></div>
+  <script>
+    (function() {
+      var ref = document.querySelector("#test");
+      test.addEventListener("click", function(evt) {
+        test.setAttribute("style", "padding-bottom: 100px;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-035.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-035.html
new file mode 100644
index 0000000..27c9ea9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-035.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - padding-left</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'padding-left' property is animatable.">
+<style>
+  #test {
+    padding-left: 1px;
+    transition-duration: 2s;
+    transition-property: padding-left;
+    transition-timing-function: linear;
+  }
+  #ref {
+    background-color: blue;
+    height: 100px;
+    width: 100px;
+  }
+</style>
+<body>
+  <p>Click the blue square below. Test passes if the blue square moves gradually not immediately form left to right until it stops.</p>
+  <div id="test">
+    <div id="ref"></div>
+  </div>
+  <script>
+    (function() {
+      var test = document.querySelector("#test");
+      test.addEventListener("click", function(evt) {
+        test.setAttribute("style", "padding-left: 200px;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-036.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-036.html
new file mode 100644
index 0000000..326e615
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-036.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - padding-right</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'padding-right' property is animatable.">
+<style>
+  #test {
+    padding-right: 0px;
+    transition-duration: 2s;
+    transition-property: padding-right;
+    transition-timing-function: linear;
+  }
+  #ref {
+    background-color: blue;
+    float: right;
+    height: 100px;
+    width: 100px;
+  }
+</style>
+<body>
+  <p>Click the blue square below. Test passes if the blue square moves gradually not immediately from right to left until it stops.</p>
+  <div id="test">
+    <div id="ref"></div>
+  </div>
+  <script>
+    (function() {
+      var ref = document.querySelector("#ref");
+      ref.addEventListener("click", function(evt) {
+        document.querySelector("#test").setAttribute("style", "padding-right: 200px;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-037.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-037.html
new file mode 100644
index 0000000..79ce16f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-037.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - padding-top</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'padding-top' property is animatable.">
+<style>
+  #test {
+    padding-top: 1px;
+    transition-duration: 2s;
+    transition-property: padding-top;
+    transition-timing-function: linear;
+  }
+  #ref {
+    background-color: blue;
+    height: 100px;
+    width: 100px;
+  }
+</style>
+<body>
+  <p>Click the blue square below. Test passes if the blue square moves down gradually not immediately until it stops.</p>
+  <div id="test">
+    <div id="ref"></div>
+  </div>
+  <script>
+    (function() {
+      var test = document.querySelector("#test");
+      test.addEventListener("click", function(evt) {
+        test.setAttribute("style", "padding-top: 200px;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-038.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-038.html
new file mode 100644
index 0000000..5b16e41
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-038.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - right</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'right' property is animatable.">
+<style>
+  #test {
+    background-color: blue;
+    height: 100px;
+    position: relative;
+    transition-duration: 2s;
+    transition-property: right;
+    transition-timing-function: linear;
+    width: 100px;
+  }
+</style>
+<body>
+  <p>Click the blue square below. Test passes if the blue square moves gradually not immediately from left to right until it stops.</p>
+  <div id="test"></div>
+  <script>
+    (function() {
+      var test = document.querySelector("#test");
+      test.addEventListener("click", function(evt) {
+        test.setAttribute("style", "right: -200px;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-039.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-039.html
new file mode 100644
index 0000000..0ef6da5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-039.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - text-indent</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'text-indent' property is animatable.">
+<style>
+  #test {
+    transition-duration: 2s;
+    transition-property: text-indent;
+    transition-timing-function: linear;
+  }
+</style>
+<body>
+  <p>Click the 'FillerText' below. Test passes if the 'FillerText' moves gradually not immediately from left to right until it stops.</p>
+  <div id="test">FillerText</div>
+  <script>
+    (function() {
+      var test = document.querySelector("#test");
+      test.addEventListener("click", function(evt) {
+        test.setAttribute("style", "text-indent: 200px;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-040.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-040.html
new file mode 100644
index 0000000..b333f371
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-040.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - text-shadow</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'text-shadow' property is animatable.">
+<style>
+  #test {
+    transition-duration: 2s;
+    transition-property: text-shadow;
+    transition-timing-function: linear;
+  }
+</style>
+<body>
+  <p>Click the 'FillerText' that has no text shadow below. Test passes if the shadow of 'FillerText' appears gradually not immediately.</p>
+  <div id="test">FillerTextFillerText</div>
+  <script>
+    (function() {
+      var test = document.querySelector("#test");
+      test.addEventListener("click", function(evt) {
+        test.setAttribute("style", "text-shadow: 4px 5px;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-041.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-041.html
new file mode 100644
index 0000000..b3386a0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-041.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - top</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'top' property is animatable.">
+<style>
+  #test {
+    background-color: blue;
+    height: 100px;
+    position: relative;
+    transition-duration: 2s;
+    transition-property: top;
+    transition-timing-function: linear;
+    width: 100px;
+  }
+</style>
+<body>
+  <p>Click blue square below. Test passes if the blue square moves down gradually not immediately until it stops.</p>
+  <div id="test"></div>
+  <script>
+    (function() {
+      var test = document.querySelector("#test");
+      test.addEventListener("click", function(evt) {
+        test.setAttribute("style", "top: 200px;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-042.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-042.html
new file mode 100644
index 0000000..fbb3e2d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-042.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - vertical-align</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'vertical-align' property is animatable.">
+<style>
+  #test {
+    transition-duration: 2s;
+    transition-property: vertical-align;
+    transition-timing-function: linear;
+    vertical-align: top;
+  }
+</style>
+<body>
+  <p>Click the cat image below. Test passes if the 'FillerText' moves down to the bottom of the cat image gradually not immediately.</p>
+  <div id="test">
+    FillerText<image id="ref" src="support/cat.png"></image>
+  </div>
+  <script>
+    (function() {
+      var ref = document.querySelector("#ref");
+      ref.addEventListener("click", function(evt) {
+        document.querySelector("#test").setAttribute("style", "vertical-align: bottom;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-043.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-043.html
new file mode 100644
index 0000000..b87dc84
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-043.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - visibility</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'visibility' property is animatable.">
+<style>
+  #test {
+    background-color: blue;
+    height: 100px;
+    transition-duration: 2s;
+    transition-property: visibility;
+    transition-timing-function: linear;
+    visibility: display;
+    width: 100px;
+  }
+</style>
+<body>
+  <p>Click blue square below. Test passes if the blue square disappears gradually not immediately.</p>
+  <div id="test"></div>
+  <script>
+    (function() {
+      var test = document.querySelector("#test");
+      test.addEventListener("click", function(evt) {
+        test.setAttribute("style", "visibility: hidden;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-044.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-044.html
new file mode 100644
index 0000000..13279a3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-044.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - word-spacing</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="ahem interact">
+<meta name="assert" content="Test checks that the 'word-spacing' property is animatable.">
+<style>
+  #test {
+    font-family: ahem;
+    transition-duration: 2s;
+    transition-property: word-spacing;
+    transition-timing-function: linear;
+  }
+</style>
+<body>
+  <p>Click any black rectangle below. Test passes if the second rectangle moves gradually not immediately from left to right until it stops and the first one does not move.</p>
+  <div id="test">text text</div>
+  <script>
+    (function() {
+      var test = document.querySelector("#test");
+      test.addEventListener("click", function(evt) {
+        test.setAttribute("style", "word-spacing: 40px;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-045.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-045.html
new file mode 100644
index 0000000..3fa82c1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-property-045.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-property - z-index</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css">
+<meta name="flags" content="ahem interact">
+<meta name="assert" content="Test checks that the 'z-index' property is animatable.">
+<style>
+  div {
+    height: 100px;
+    width: 100px;
+  }
+  #ref {
+    background-color: red;
+    z-index: 1;
+  }
+  #test {
+    background-color: green;
+    position: relative;
+    top: -100px;
+    transition-duration: 2s;
+    transition-property: z-index;
+    transition-timing-function: linear;
+    z-index: -100;
+  }
+</style>
+<body>
+  <p>Click red square below. Test passes if the color of square changes to green after waiting a moment.</p>
+  <div id="ref"></div>
+  <div id="test"></div>
+  <script>
+    (function() {
+      var test = document.querySelector("#test");
+      document.addEventListener("click", function(evt) {
+        test.setAttribute("style", "z-index: 100;");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-test.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-test.html
new file mode 100644
index 0000000..10700abf
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-test.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>CSS Transition Test: invalid values cause all properites to animate.</title>
+    <link rel="author" title="Oleg Janeiko" href="mailto:oleg@the-incredible.me">
+    <link rel="help" href="http://www.w3.org/TR/css3-transitions/#transition-property-property">
+    <link rel="match" href="reference/transition-test-ref.html">
+    <meta name="assert" content="When an invalid value is specified as one of the transition properties, it causes the the transition-property to change to 'all'. Instead of leaving the invalid property in and animating the valid properites with matching durations.">
+    <style type="text/css">
+        .container {
+            background-color: red;
+            height: 200px;
+            width: 200px;
+        }
+        .box {
+            width: 100px;
+            height: 100px;
+            background-color: green;
+
+            transition-property: width, foo; /* invalid foo */
+            transition-duration: 0, 5s;
+        }
+        .box.transition {
+            width: 200px;
+            height: 200px;
+        }
+    </style>
+    <script type="text/javascript" charset="utf-8">
+        function ready(){
+            var box = document.querySelector('.box');
+            box.className = 'box transition';
+        }
+    </script>
+</head>
+<body onload="ready();">
+    <div>
+        <p>You should not see a red background during the transition. Note: if the test passes transition is instant.</p>
+    </div>
+    <div class="container">
+        <div class="box"></div>
+    </div>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-001-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-001-expected.txt
new file mode 100644
index 0000000..769c11c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-001-expected.txt
@@ -0,0 +1,23 @@
+This is a testharness.js-based test.
+FAIL parse 'ease' assert_equals: Expected computed value expected "cubic-bezier(0.25, 0.1, 0.25, 1)" but got "ease"
+FAIL parse 'linear' assert_equals: Expected computed value expected "cubic-bezier(0, 0, 1, 1)" but got "linear"
+FAIL parse 'ease-in' assert_equals: Expected computed value expected "cubic-bezier(0.42, 0, 1, 1)" but got "ease-in"
+FAIL parse 'ease-out' assert_equals: Expected computed value expected "cubic-bezier(0, 0, 0.58, 1)" but got "ease-out"
+FAIL parse 'ease-in-out' assert_equals: Expected computed value expected "cubic-bezier(0.42, 0, 0.58, 1)" but got "ease-in-out"
+FAIL parse 'step-start' assert_equals: Expected computed value expected "steps(1, start)" but got "step-start"
+FAIL parse 'step-end' assert_equals: Expected computed value expected "steps(1)" but got "step-end"
+PASS parse 'cubic-bezier(0.1, 0.2, 0.3, 0.4)'
+PASS parse 'cubic-bezier(0.1, -0.2, 0.3, -0.4)'
+PASS parse 'cubic-bezier(0.1, 1.2, 0.3, 1.4)'
+PASS parse 'steps(3, start)'
+FAIL parse 'steps(3, end)' assert_equals: Expected computed value expected "steps(3)" but got "steps(3, end)"
+FAIL parse 'steps(3)' assert_equals: Expected computed value expected "steps(3)" but got "steps(3, end)"
+FAIL parse 'cubic-bezier(foobar)' assert_equals: Expected computed value expected "cubic-bezier(0.25, 0.1, 0.25, 1)" but got "ease"
+FAIL parse 'steps(foobar)' assert_equals: Expected computed value expected "cubic-bezier(0.25, 0.1, 0.25, 1)" but got "ease"
+FAIL parse 'steps(3.3, end)' assert_equals: Expected computed value expected "cubic-bezier(0.25, 0.1, 0.25, 1)" but got "ease"
+FAIL parse 'steps(3, top)' assert_equals: Expected computed value expected "cubic-bezier(0.25, 0.1, 0.25, 1)" but got "ease"
+FAIL parse 'steps(-3, top)' assert_equals: Expected computed value expected "cubic-bezier(0.25, 0.1, 0.25, 1)" but got "ease"
+FAIL parse 'cubic-bezier(-0.1, -0.2, -0.3, -0.4)' assert_equals: Expected computed value expected "cubic-bezier(0.25, 0.1, 0.25, 1)" but got "ease"
+FAIL parse 'cubic-bezier(1.1, 1.2, 1.3, 1.4)' assert_equals: Expected computed value expected "cubic-bezier(0.25, 0.1, 0.25, 1)" but got "ease"
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-001.html
new file mode 100644
index 0000000..68669c7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-001.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>CSS Transitions Test: Parsing transition-timing-function</title>
+        <meta name="assert" content="Test checks that transition-timing-function values are parsed properly">
+        <link rel="help" title="2.3. The 'transition-timing-function' Property" href="http://www.w3.org/TR/css3-transitions/#transition-timing-function-property">
+        <link rel="author" title="Rodney Rehm" href="http://rodneyrehm.de/en/">
+        <meta name="flags" content="dom">
+
+        <script src="/resources/testharness.js" type="text/javascript"></script>
+        <script src="/resources/testharnessreport.js" type="text/javascript"></script>
+
+        <script src="./support/vendorPrefix.js" type="text/javascript"></script>
+        <script src="./support/helper.js" type="text/javascript"></script>
+    </head>
+    <body>
+        <!-- required by testharnessreport.js -->
+        <div id="log"></div>
+        <!-- elements used for testing -->
+        <div id="container">
+            <div id="transition"></div>
+        </div>
+
+        <script>
+            var transition = document.getElementById('transition');
+            // "ease"
+            var defaultValue = 'cubic-bezier(0.25, 0.1, 0.25, 1)';
+            var values = {
+                // keywords
+                'ease': 'cubic-bezier(0.25, 0.1, 0.25, 1)',
+                'linear': 'cubic-bezier(0, 0, 1, 1)',
+                'ease-in': 'cubic-bezier(0.42, 0, 1, 1)',
+                'ease-out': 'cubic-bezier(0, 0, 0.58, 1)',
+                'ease-in-out': 'cubic-bezier(0.42, 0, 0.58, 1)',
+                'step-start': 'steps(1, start)',
+                'step-end': 'steps(1)',
+                // cubic bezier
+                'cubic-bezier(0.1, 0.2, 0.3, 0.4)': 'cubic-bezier(0.1, 0.2, 0.3, 0.4)',
+                'cubic-bezier(0.1, -0.2, 0.3, -0.4)': 'cubic-bezier(0.1, -0.2, 0.3, -0.4)',
+                'cubic-bezier(0.1, 1.2, 0.3, 1.4)': 'cubic-bezier(0.1, 1.2, 0.3, 1.4)',
+                // steps
+                'steps(3, start)': 'steps(3, start)',
+                'steps(3, end)': 'steps(3)',
+                'steps(3)': 'steps(3)',
+                // invalid
+                'cubic-bezier(foobar)': defaultValue,
+                'steps(foobar)': defaultValue,
+                'steps(3.3, end)': defaultValue,
+                'steps(3, top)': defaultValue,
+                'steps(-3, top)': defaultValue,
+                // Both x values must be in the range [0, 1]
+                'cubic-bezier(-0.1, -0.2, -0.3, -0.4)': defaultValue,
+                'cubic-bezier(1.1, 1.2, 1.3, 1.4)': defaultValue
+            };
+
+            // these tests are supposed to fail and
+            // possibly make the engine issue a parser warning
+            var invalidTests = {
+                'cubic-bezier(foobar)': true,
+                'steps(foobar)': true,
+                'steps(3.3, end)': true,
+                'steps(3, top)': true,
+                'steps(-3, top)': true,
+                // Both x values must be in the range [0, 1]
+                'cubic-bezier(-0.1, -0.2, -0.3, -0.4)': true,
+                'cubic-bezier(1.1, 1.2, 1.3, 1.4)': true
+            };
+
+            for (var key in values) {
+                if (Object.prototype.hasOwnProperty.call(values, key)) {
+                    test(function() {
+                        setStyle('#transition', {
+                            'transition-timing-function': key
+                        });
+                        var result = computedStyle(transition, 'transition-timing-function');
+                        assert_equals(result, values[key], "Expected computed value");
+                    }, "parse '" + key + "'",
+                    {
+                        // mark tests that fail as such
+                        flags: invalidTests[key] ? "invalid" : ""
+                    });
+                }
+            }
+        </script>
+    </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-002.html
new file mode 100644
index 0000000..527eb9e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-002.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-timing-function - 'ease' equivalent to 'cubic-bezier(0.25, 0.1, 0.25, 1.0)'</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="2.3. The 'transition-timing-function' Property" href="http://www.w3.org/TR/css3-transitions/#transition-timing-function">
+<meta name="flags" content="interact">
+<meta name="assert" content="The 'transition-timing-function' property set 'ease' is equivalent to cubic-bezier(0.25, 0.1, 0.25, 1.0)">
+<style>
+  div {
+    height: 100px;
+    transition: width 2s;
+    width: 100px;
+  }
+  #test1 {
+    background-color: blue;
+    transition-timing-function: ease;
+  }
+  #test2 {
+    background-color: yellow;
+    transition-timing-function: cubic-bezier(0.25, 0.1, 0.25, 1.0);
+  }
+</style>
+<body>
+  <p>Click the 'Start' button. Test passes if the width growth of blue square is <strong>equivalent</strong> to the yellow square.</p>
+  <div id="test1"></div>
+  <div id="test2"></div>
+  <button>Start</button>
+  <script>
+    (function() {
+      var button = document.querySelector("button");
+      button.addEventListener("click", function(evt) {
+        var test1 = document.querySelector("#test1"),
+            test2 = document.querySelector("#test2");
+        test1.setAttribute("style", "width: 300px");
+        test2.setAttribute("style", "width: 300px");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-003.html
new file mode 100644
index 0000000..353b94e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-003.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-timing-function - 'ease-in' equivalent to 'cubic-bezier(0.42, 0, 1.0, 1.0)'</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="2.3. The 'transition-timing-function' Property" href="http://www.w3.org/TR/css3-transitions/#transition-timing-function">
+<meta name="flags" content="interact">
+<meta name="assert" content="The 'transition-timing-function' property set 'ease-in' is equivalent to cubic-bezier(0.42, 0, 1.0, 1.0)">
+<style>
+  div {
+    height: 100px;
+    transition: width 2s;
+    width: 100px;
+  }
+  #test1 {
+    background-color: blue;
+    transition-timing-function: ease-in;
+  }
+  #test2 {
+    background-color: yellow;
+    transition-timing-function: cubic-bezier(0.42, 0, 1.0, 1.0);
+  }
+</style>
+<body>
+  <p>Click the 'Start' button. Test passes if the width growth of blue square is <strong>equivalent</strong> to the yellow square.</p>
+  <div id="test1"></div>
+  <div id="test2"></div>
+  <button>Start</button>
+  <script>
+    (function() {
+      var button = document.querySelector("button");
+      button.addEventListener("click", function(evt) {
+        var test1 = document.querySelector("#test1"),
+            test2 = document.querySelector("#test2");
+        test1.setAttribute("style", "width: 300px");
+        test2.setAttribute("style", "width: 300px");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-004.html
new file mode 100644
index 0000000..0601b4b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-004.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-timing-function - 'ease-in-out' equivalent to 'cubic-bezier(0.42, 0, 0.58, 1.0)'</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="2.3. The 'transition-timing-function' Property" href="http://www.w3.org/TR/css3-transitions/#transition-timing-function">
+<meta name="flags" content="interact">
+<meta name="assert" content="The 'transition-timing-function' property set 'ease-in-out' is equivalent to cubic-bezier(0.42, 0, 0.58, 1.0)">
+<style>
+  div {
+    height: 100px;
+    transition: width 2s;
+    width: 100px;
+  }
+  #test1 {
+    background-color: blue;
+    transition-timing-function: ease-in-out;
+  }
+  #test2 {
+    background-color: yellow;
+    transition-timing-function: cubic-bezier(0.42, 0, 0.58, 1.0);
+  }
+</style>
+<body>
+  <p>Click the 'Start' button. Test passes if the width growth of blue square is <strong>equivalent</strong> to the yellow square.</p>
+  <div id="test1"></div>
+  <div id="test2"></div>
+  <button>Start</button>
+  <script>
+    (function() {
+      var button = document.querySelector("button");
+      button.addEventListener("click", function(evt) {
+        var test1 = document.querySelector("#test1"),
+            test2 = document.querySelector("#test2");
+        test1.setAttribute("style", "width: 300px");
+        test2.setAttribute("style", "width: 300px");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-005.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-005.html
new file mode 100644
index 0000000..eb46ece
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-005.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-timing-function - 'ease-out' equivalent to 'cubic-bezier(0, 0, 0.58, 1.0)'</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="2.3. The 'transition-timing-function' Property" href="http://www.w3.org/TR/css3-transitions/#transition-timing-function">
+<meta name="flags" content="interact">
+<meta name="assert" content="The 'transition-timing-function' property set 'ease-out' is equivalent to cubic-bezier(0, 0, 0.58, 1.0)">
+<style>
+  div {
+    height: 100px;
+    transition: width 2s;
+    width: 100px;
+  }
+  #test1 {
+    background-color: blue;
+    transition-timing-function: ease-out;
+  }
+  #test2 {
+    background-color: yellow;
+    transition-timing-function: cubic-bezier(0, 0, 0.58, 1.0);
+  }
+</style>
+<body>
+  <p>Click the 'Start' button. Test passes if the width growth of blue square is <strong>equivalent</strong> to the yellow square.</p>
+  <div id="test1"></div>
+  <div id="test2"></div>
+  <button>Start</button>
+  <script>
+    (function() {
+      var button = document.querySelector("button");
+      button.addEventListener("click", function(evt) {
+        var test1 = document.querySelector("#test1"),
+            test2 = document.querySelector("#test2");
+        test1.setAttribute("style", "width: 300px");
+        test2.setAttribute("style", "width: 300px");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-006.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-006.html
new file mode 100644
index 0000000..d8640d93
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-006.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-timing-function - 'linear' equivalent to 'cubic-bezier(0.0, 0.0, 1.0, 1.0)'</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="2.3. The 'transition-timing-function' Property" href="http://www.w3.org/TR/css3-transitions/#transition-timing-function">
+<meta name="flags" content="interact">
+<meta name="assert" content="The 'transition-timing-function' property set 'linear' is equivalent to cubic-bezier(0.0, 0.0, 1.0, 1.0)">
+<style>
+  div {
+    height: 100px;
+    transition: width 2s;
+    width: 100px;
+  }
+  #test1 {
+    background-color: blue;
+    transition-timing-function: linear;
+  }
+  #test2 {
+    background-color: yellow;
+    transition-timing-function: cubic-bezier(0, 0, 1.0, 1.0);
+  }
+</style>
+<body>
+  <p>Click the 'Start' button. Test passes if the width growth of blue square is <strong>equivalent</strong> to the yellow square.</p>
+  <div id="test1"></div>
+  <div id="test2"></div>
+  <button>Start</button>
+  <script>
+    (function() {
+      var button = document.querySelector("button");
+      button.addEventListener("click", function(evt) {
+        var test1 = document.querySelector("#test1"),
+            test2 = document.querySelector("#test2");
+        test1.setAttribute("style", "width: 300px");
+        test2.setAttribute("style", "width: 300px");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-007.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-007.html
new file mode 100644
index 0000000..72ffbf6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-007.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-timing-function - 'step-end' equivalent to 'steps(1, end)'</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="2.3. The 'transition-timing-function' Property" href="http://www.w3.org/TR/css3-transitions/#transition-timing-function">
+<meta name="flags" content="interact">
+<meta name="assert" content="The 'transition-timing-function' property set 'step-end' is equivalent to 'steps(1, end)'">
+<style>
+  div {
+    height: 100px;
+    transition: width 2s;
+    width: 100px;
+  }
+  #test1 {
+    background-color: blue;
+    transition-timing-function: step-end;
+  }
+  #test2 {
+    background-color: yellow;
+    transition-timing-function: steps(1, end);
+  }
+</style>
+<body>
+  <p>Click the 'Start' button. Test passes if the width growth of blue square is <strong>equivalent</strong> to the yellow square.</p>
+  <div id="test1"></div>
+  <div id="test2"></div>
+  <button>Start</button>
+  <script>
+    (function() {
+      var button = document.querySelector("button");
+      button.addEventListener("click", function(evt) {
+        var test1 = document.querySelector("#test1"),
+            test2 = document.querySelector("#test2");
+        test1.setAttribute("style", "width: 300px");
+        test2.setAttribute("style", "width: 300px");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-008.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-008.html
new file mode 100644
index 0000000..2e20f7e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-008.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-timing-function - 'step-start' equivalent to 'steps(1, start)'</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="2.3. The 'transition-timing-function' Property" href="http://www.w3.org/TR/css3-transitions/#transition-timing-function">
+<meta name="flags" content="interact">
+<meta name="assert" content="The 'transition-timing-function' property set 'step-start' is equivalent to 'steps(1, start)'">
+<style>
+  div {
+    height: 100px;
+    transition: width 2s;
+    width: 100px;
+  }
+  #test1 {
+    background-color: blue;
+    transition-timing-function: step-start;
+  }
+  #test2 {
+    background-color: yellow;
+    transition-timing-function: steps(1, start);
+  }
+</style>
+<body>
+  <p>Click the 'Start' button. Test passes if the width growth of blue square is <strong>equivalent</strong> to the yellow square.</p>
+  <div id="test1"></div>
+  <div id="test2"></div>
+  <button>Start</button>
+  <script>
+    (function() {
+      var button = document.querySelector("button");
+      button.addEventListener("click", function(evt) {
+        var test1 = document.querySelector("#test1"),
+            test2 = document.querySelector("#test2");
+        test1.setAttribute("style", "width: 300px");
+        test2.setAttribute("style", "width: 300px");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-009.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-009.html
new file mode 100644
index 0000000..a3e2f1a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-009.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-timing-function - ease(initial value)</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="2.3. The 'transition-timing-function' Property" href="http://www.w3.org/TR/css3-transitions/#transition-timing-function">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the initial value of 'transition-timing-function' property is 'ease'.">
+<style>
+  div {
+    height: 100px;
+    transition-duration: 2s;
+    transition-property: width;
+    width: 100px;
+  }
+  #test1 {
+    background-color: blue;
+    transition-timing-function: ease;
+  }
+  #test2 {
+    background-color: yellow;
+  }
+</style>
+<body>
+  <p>Click the 'Start' button. Test passes if the width growth of blue square is <strong>equivalent</strong> to the yellow square.</p>
+  <div id="test1"></div>
+  <div id="test2"></div>
+  <button>Start</button>
+  <script>
+    (function() {
+      var button = document.querySelector("button");
+      button.addEventListener("click", function(evt) {
+        var test1 = document.querySelector("#test1"),
+            test2 = document.querySelector("#test2");
+        test1.setAttribute("style", "width: 300px");
+        test2.setAttribute("style", "width: 300px");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-010.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-010.html
new file mode 100644
index 0000000..16af806
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-010.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-timing-function - steps(2)</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="2.3. The 'transition-timing-function' Property" href="http://www.w3.org/TR/css3-transitions/#transition-timing-function">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the first parameter of 'steps()' function specifies the number of intervals.">
+<style>
+  div {
+    background-color: blue;
+    height: 100px;
+    transition-duration: 1s;
+    transition-property: width;
+    transition-timing-function: steps(2);
+    width: 100px;
+  }
+</style>
+<body>
+  <p>Click the blue square. Test passes if the width of blue square grows <strong>twice</strong>.</p>
+  <div></div>
+  <script>
+    (function() {
+      var div = document.querySelector("div");
+      div.addEventListener("click", function(evt) {
+        div.setAttribute("style", "width: 300px");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-011.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-011.html
new file mode 100644
index 0000000..5d0f5a2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-011.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-timing-function - steps(the second parameter default 'end')</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="2.3. The 'transition-timing-function' Property" href="http://www.w3.org/TR/css3-transitions/#transition-timing-function">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the second parameter of 'steps()' function is default 'end'.">
+<style>
+  div {
+    height: 100px;
+    transition-duration: 2s;
+    transition-property: width;
+    width: 100px;
+  }
+  #test1 {
+    background-color: blue;
+    transition-timing-function: steps(2);
+  }
+  #test2 {
+    background-color: yellow;
+    transition-timing-function: steps(2, end);
+  }
+</style>
+<body>
+  <p>Click the 'Start' button. Test passes if the width growth of blue square is <strong>equivalent</strong> to the yellow square.</p>
+  <div id="test1"></div>
+  <div id="test2"></div>
+  <button>Start</button>
+  <script>
+    (function() {
+      var button = document.querySelector("button");
+      button.addEventListener("click", function(evt) {
+        var test1 = document.querySelector("#test1"),
+            test2 = document.querySelector("#test2");
+        test1.setAttribute("style", "width: 300px");
+        test2.setAttribute("style", "width: 300px");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-012.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-012.html
new file mode 100644
index 0000000..f3bc812
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-012.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-timing-function - steps(-2)</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="2.3. The 'transition-timing-function' Property" href="http://www.w3.org/TR/css3-transitions/#transition-timing-function">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'steps()' function with negative number is invalid, the transition-timing-function will use 'ease' as default.">
+<style>
+  div {
+    height: 100px;
+    transition-duration: 2s;
+    transition-property: width;
+    width: 100px;
+  }
+  #test1 {
+    background-color: blue;
+    transition-timing-function: steps(-2);
+  }
+  #test2 {
+    background-color: yellow;
+    transition-timing-function: ease;
+  }
+</style>
+<body>
+  <p>Click the 'Start' button. Test passes if the width growth of blue square is <strong>equivalent</strong> to the yellow square.</p>
+  <div id="test1"></div>
+  <div id="test2"></div>
+  <button>Start</button>
+  <script>
+    (function() {
+      var button = document.querySelector("button");
+      button.addEventListener("click", function(evt) {
+        var test1 = document.querySelector("#test1"),
+            test2 = document.querySelector("#test2");
+        test1.setAttribute("style", "width: 300px");
+        test2.setAttribute("style", "width: 300px");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-013.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-013.html
new file mode 100644
index 0000000..5d89c45e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transition-timing-function-013.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Transitions Test: transition-timing-function - steps(0)</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com">
+<link rel="help" title="2.3. The 'transition-timing-function' Property" href="http://www.w3.org/TR/css3-transitions/#transition-timing-function">
+<meta name="flags" content="interact">
+<meta name="assert" content="Test checks that the 'steps()' function with '0' is invalid, the transition-timing-function will use 'ease' as default.">
+<style>
+  div {
+    height: 100px;
+    transition-duration: 2s;
+    transition-property: width;
+    width: 100px;
+  }
+  #test1 {
+    background-color: blue;
+    transition-timing-function: steps(0);
+  }
+  #test2 {
+    background-color: yellow;
+    transition-timing-function: ease;
+  }
+</style>
+<body>
+  <p>Click the 'Start' button. Test passes if the width growth of blue square is <strong>equivalent</strong> to the yellow square.</p>
+  <div id="test1"></div>
+  <div id="test2"></div>
+  <button>Start</button>
+  <script>
+    (function() {
+      var button = document.querySelector("button");
+      button.addEventListener("click", function(evt) {
+        var test1 = document.querySelector("#test1"),
+            test2 = document.querySelector("#test2");
+        test1.setAttribute("style", "width: 300px");
+        test2.setAttribute("style", "width: 300px");
+      }, false);
+    })();
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transitioncancel-001-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transitioncancel-001-expected.txt
new file mode 100644
index 0000000..d5f00951
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transitioncancel-001-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL transitioncancel should be fired if the element is made display:none during the transition assert_true: transitioncancel event did fire expected true got false
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transitioncancel-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transitioncancel-001.html
new file mode 100644
index 0000000..abc2f38b9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transitioncancel-001.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8">
+    <title>CSS Transitions Test: display:none causes transitioncancel</title>
+    <link rel="author" title="Chris Rebert" href="http://chrisrebert.com">
+    <link rel="help" href="https://drafts.csswg.org/css-transitions-2/#dom-transitionevent-transitioncancel">
+    <link rel="help" href="https://lists.w3.org/Archives/Public/www-style/2015Apr/0405.html" title="[CSSWG] Minutes Telecon 2015-04-29" data-section-title="AnimationEnd events and display: none">
+    <meta name="flags" content="dom">
+    <meta name="assert" content="Making an element display:none; while it has a transition in progress should fire a transitioncancel event.">
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <style>
+#a {
+    height: 100px;
+    width: 100px;
+    transition: background-color 2s;
+}
+.red {
+    background-color: red;
+}
+.blue {
+    background-color: blue;
+}
+.hidden {
+    display: none !important;
+}
+    </style>
+    <script>
+async_test(function (t) {
+    window.addEventListener('load', function () {
+        var div = document.getElementById('a');
+        var canceled = false;
+        var after = false;
+        div.addEventListener('transitioncancel', function () {
+            canceled = true;
+            t.step(function () {
+                assert_true(true, "transitioncancel event did fire");
+            });
+        }, false);
+
+        div.className = 'blue';// initiate transition
+        window.setTimeout(function () {
+            t.step(function () {
+                assert_false(canceled, "transitioncancel did not fire before hiding callback ran");
+                assert_false(after, "hiding callback ran before the end of the test");
+            });
+            div.className += ' hidden';// force display:none during the transition
+        }, 1000);// halfway into the transition
+        window.setTimeout(function () {
+            after = true;
+            t.step(function () {
+                assert_true(canceled, "transitioncancel event did fire");
+                t.done();
+            });
+        }, 2100);// after the transition would have ended
+    }, false);
+}, "transitioncancel should be fired if the element is made display:none during the transition");
+    </script>
+</head>
+<body>
+    <div id="a" class="red"></div>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transitions-animatable-properties-01.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transitions-animatable-properties-01.html
new file mode 100644
index 0000000..06143d3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-transitions/transitions-animatable-properties-01.html
@@ -0,0 +1,180 @@
+<!DOCTYPE html>
+<html>
+<!-- Submitted from TestTWF Paris -->
+  <head>
+    <meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type">
+    <title> CSS Transitions: Animatable CSS properties </title>
+    <meta name="assert" content="Check that all animatable CSS properties are animatable and then accepted by the 'transition-property' property">
+    <link rel="author" title="Daniel Glazman" href="mailto:daniel.glazman@disruptive-innovations.com">
+    <link rel="help" href="http://www.w3.org/TR/css3-transitions/#transitions">
+    <link rel="help" href="http://www.w3.org/TR/css3-transitions/#animatable-properties">
+    <link rel="reviewer" title="Alan Stearns" href="mailto:stearns@adobe.com">
+
+    <style type="text/css">
+
+      html, body { margin: 0px; padding: 0px; }
+
+      .w50vw { width: 50vw; )
+      .h50vh { height: 50vh; }
+
+      .w50vm { width: 50vm; }
+      .h50vm { height: 50vm; }
+    </style>
+
+    <script src="/resources/testharness.js" type="text/javascript"></script>
+    <script src="/resources/testharnessreport.js" type="text/javascript"></script>
+
+    <style type="text/css" id="newStyles"></style>
+  </head>
+  <body>
+    <p>Check that all animatable CSS properties are animatable and
+      then accepted by the 'transition-property' property.<br>
+    </p>
+
+    <p id="testP">THIS PROSE NEEDED FOR TEST ITSELF</p>
+
+    <div id="log"></div><a href="transitions-animatable-properties-01.html" id="" title="transitions-animatable-properties-01">transitions-animatable-properties-01</a>
+
+    <script type="text/javascript">
+      var kANIMATABLE_CSS_PROPERTIES = [
+          ["background-color",    "white",                      "rgb(0, 128, 0)",               "", false],
+          ["background-position", "0px 0px",                    "100% 100%",                    "", false],
+          ["border-color",        "white",                      "rgb(0, 128, 0)",               "", false],
+          ["border-bottom-color", "white",                      "rgb(0, 128, 0)",               "", false],
+          ["border-bottom-width", "0px",                        "10px",                         "border-style: solid; border-color: black", false],
+          ["border-left-color",   "white",                      "rgb(0, 128, 0)",               "", false],
+          ["border-left-width",   "0px",                        "10px",                         "border-style: solid; border-color: black", false],
+          ["border-right-color",  "white",                      "rgb(0, 128, 0)",               "", false],
+          ["border-right-width",  "0px",                        "10px",                         "border-style: solid; border-color: black", false],
+          ["border-spacing",      "0px",                        "10px 15px",                    "", false],
+          ["border-top-color",    "white",                      "rgb(0, 128, 0)",               "", false],
+          ["border-top-width",    "0px",                        "10px",                         "border-style: solid; border-color: black", false],
+          ["bottom",              "0px",                        "10px",                         "", false],
+          ["clip",                "rect(0px, 0px, 10px, 10px)", "rect(10px, 10px, 20px, 20px)", "", false],
+          ["color",               "white",                      "rgb(0, 128, 0)",               "", false],
+          ["crop",                "rect(0px, 0px, 10px, 10px)", "rect(10px 10px 20px 20px)",    "", false],
+          ["font-size",           "12pt",                       "32px",                         "", false],
+          ["font-weight",         "400",                        "900",                          "", false],
+          ["height",              "1em",                        "64px",                         "", false],
+          ["left",                "0px",                        "10px",                         "", false],
+          ["letter-spacing",      "1em",                        "64px",                         "", false],
+          ["line-height",         "1em",                        "64px",                         "", false],
+          ["margin-bottom",       "0px",                        "10px",                         "", false],
+          ["margin-left",         "0px",                        "10px",                         "", false],
+          ["margin-right",        "0px",                        "10px",                         "", false],
+          ["margin-top",          "0px",                        "10px",                         "", false],
+          ["max-height",          "0px",                        "10px",                         "", false],
+          ["max-width",           "0px",                        "10px",                         "", false],
+          ["min-height",          "0px",                        "10px",                         "", false],
+          ["min-width",           "0px",                        "10px",                         "", false],
+          ["opacity",             "0",                          "1",                            "", false],
+          ["outline-color",       "white",                      "rgb(0, 128, 0)",               "", false],
+          ["outline-offset",      "0px",                        "10px",                         "", false],
+          ["outline-width",       "0px",                        "10px",                         "outline-style: solid; outline-style: black", false],
+          ["padding-bottom",      "0px",                        "10px",                         "", false],
+          ["padding-left",        "0px",                        "10px",                         "", false],
+          ["padding-right",       "0px",                        "10px",                         "", false],
+          ["padding-top",         "0px",                        "10px",                         "", false],
+          ["right",               "0px",                        "10px",                         "", false],
+          ["text-indent",         "0px",                        "10px",                         "", false],
+          ["text-shadow",         "orange 0 -2px",              "rgb(0, 128, 0) 0px 2px 0px",   "", false],
+          ["top",                 "0px",                        "10px",                         "", false],
+          ["vertical-align",      "0px",                        "10px",                         "", false],
+          ["visibility",          "visible",                    "hidden",                       "", true],
+          ["width",               "0px",                        "10px",                         "", false],
+          ["word-spacing",        "0px",                        "10px",                         "", false],
+          ["z-index",             "1",                           "10",                          "", false]
+      ];
+
+      // page timeout
+      var kTIMEOUT = 3000000;
+
+      var p = document.getElementById("testP");
+      var style = document.getElementById("newStyles");
+
+      var testsIntermediate = [];
+      var testsEnd = [];
+
+      setup({timeout: kTIMEOUT});
+
+      // create all the tests we need
+      for (var i = 0; i < kANIMATABLE_CSS_PROPERTIES.length; i++) {
+        testsIntermediate.push(async_test(kANIMATABLE_CSS_PROPERTIES[i][0] + " intermediate",
+                                          { timeout: 2000, assert: "property " + kANIMATABLE_CSS_PROPERTIES[i][0] + " is animatable" }));
+        testsEnd.push(async_test(kANIMATABLE_CSS_PROPERTIES[i][0] + " end",
+                                          { timeout: 2000, assert: "property " + kANIMATABLE_CSS_PROPERTIES[i][0] + " has correct value after transition's end" }));
+      }
+
+      // getComputedStyle helper
+      function gCS(aProperty)
+      {
+        return document.defaultView
+               .getComputedStyle(p, "")
+               .getPropertyValue(aProperty);
+      }
+
+      function Scheduler(aIndex)
+      {
+        if (aIndex >= kANIMATABLE_CSS_PROPERTIES.length) // we're done here
+          return;
+
+        var property   = kANIMATABLE_CSS_PROPERTIES[aIndex][0];
+        var startValue = kANIMATABLE_CSS_PROPERTIES[aIndex][1];
+        var endValue   = kANIMATABLE_CSS_PROPERTIES[aIndex][2];
+        var extras     = kANIMATABLE_CSS_PROPERTIES[aIndex][3];
+        var discrete   = kANIMATABLE_CSS_PROPERTIES[aIndex][4];
+
+        // create a style rule
+        var s = "#testP { ";
+        s += property + ": " + startValue + ";\n";
+        s += "transition-property: " + property + ";\n";
+        s += "transition-duration: 0.5s;\n";
+        s += "transition-delay: 0s;\n";
+        s += "transition-timing-function: linear;\n";
+        s += extras;
+        s += "}";
+        style.textContent = s;
+
+        // flush styles
+        gCS(property);
+
+        // set property to endValue
+        p.setAttribute("style", property + ": " + endValue + "; ");
+
+        // test for intermediate value
+        setTimeout(function()
+                   {
+                     testsIntermediate[aIndex].step(function()
+                                         {
+                                           var cs = gCS(property);
+                                           if (discrete) {
+                                             assert_equals(cs, startValue);
+                                           }
+                                           else {
+                                             assert_true((cs != startValue) && (null != cs));
+                                           }
+                                         });
+                     testsIntermediate[aIndex].done();
+                   }, 250);
+
+        // test for final value
+        setTimeout(function()
+                   {
+                     testsEnd[aIndex].step(function()
+                                           {
+                                             var cs = gCS(property);
+                                             assert_equals(cs, endValue);
+                                           }
+                                          );
+                     testsEnd[aIndex].done();
+                     Scheduler(aIndex + 1);
+                   }, 600);
+
+      }
+
+      // let's start
+      Scheduler(0);
+
+    </script>
+  </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-family.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-family.html
new file mode 100644
index 0000000..eb35ef17
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-family.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>'font-family' property</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-get">
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-set">
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#property-stle-value-normalization">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../resources/testhelper.js"></script>
+<script src="resources/testsuite.js"></script>
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+// FIXME: font-family is list-valued. Run list-valued tests here too.
+runUnsupportedPropertyTests('font-family', [
+  'Georgia',
+  '"Gill Sans"',
+  'sans-serif',
+]);
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-language-override-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-language-override-expected.txt
new file mode 100644
index 0000000..96484b9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-language-override-expected.txt
@@ -0,0 +1,13 @@
+This is a testharness.js-based test.
+FAIL Can set 'font-language-override' to CSS-wide keywords Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-language-override
+FAIL Can set 'font-language-override' to var() references Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-language-override
+FAIL Can set 'font-language-override' to the 'normal' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-language-override
+PASS Setting 'font-language-override' to a length throws TypeError
+PASS Setting 'font-language-override' to a percent throws TypeError
+PASS Setting 'font-language-override' to a time throws TypeError
+PASS Setting 'font-language-override' to a number throws TypeError
+PASS Setting 'font-language-override' to a position throws TypeError
+PASS Setting 'font-language-override' to a transform throws TypeError
+FAIL 'font-language-override' does not supported '"SRB"' Failed to execute 'get' on 'StylePropertyMapReadOnly': Invalid propertyName: font-language-override
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-language-override.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-language-override.html
new file mode 100644
index 0000000..daf38038
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-language-override.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>'font-language-override' property</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-get">
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-set">
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#property-stle-value-normalization">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../resources/testhelper.js"></script>
+<script src="resources/testsuite.js"></script>
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+runPropertyTests('font-language-override', [
+  { syntax: 'normal' },
+]);
+
+runUnsupportedPropertyTests('font-language-override', [
+  '"SRB"',
+]);
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-optical-sizing-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-optical-sizing-expected.txt
new file mode 100644
index 0000000..b01af90
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-optical-sizing-expected.txt
@@ -0,0 +1,13 @@
+This is a testharness.js-based test.
+FAIL Can set 'font-optical-sizing' to CSS-wide keywords Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-optical-sizing
+FAIL Can set 'font-optical-sizing' to var() references Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-optical-sizing
+FAIL Can set 'font-optical-sizing' to the 'auto' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-optical-sizing
+FAIL Can set 'font-optical-sizing' to the 'none' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-optical-sizing
+PASS Setting 'font-optical-sizing' to a length throws TypeError
+PASS Setting 'font-optical-sizing' to a percent throws TypeError
+PASS Setting 'font-optical-sizing' to a time throws TypeError
+PASS Setting 'font-optical-sizing' to a number throws TypeError
+PASS Setting 'font-optical-sizing' to a position throws TypeError
+PASS Setting 'font-optical-sizing' to a transform throws TypeError
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-optical-sizing.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-optical-sizing.html
new file mode 100644
index 0000000..0018ef13
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-optical-sizing.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>'font-optical-sizing' property</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-get">
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-set">
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#property-stle-value-normalization">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../resources/testhelper.js"></script>
+<script src="resources/testsuite.js"></script>
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+runPropertyTests('font-optical-sizing', [
+  { syntax: 'auto' },
+  { syntax: 'none' },
+]);
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-palette-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-palette-expected.txt
new file mode 100644
index 0000000..8ad14354
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-palette-expected.txt
@@ -0,0 +1,15 @@
+This is a testharness.js-based test.
+FAIL Can set 'font-palette' to CSS-wide keywords Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-palette
+FAIL Can set 'font-palette' to var() references Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-palette
+FAIL Can set 'font-palette' to the 'normal' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-palette
+FAIL Can set 'font-palette' to the 'light' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-palette
+FAIL Can set 'font-palette' to the 'dark' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-palette
+PASS Setting 'font-palette' to a length throws TypeError
+PASS Setting 'font-palette' to a percent throws TypeError
+PASS Setting 'font-palette' to a time throws TypeError
+PASS Setting 'font-palette' to a number throws TypeError
+PASS Setting 'font-palette' to a position throws TypeError
+PASS Setting 'font-palette' to a transform throws TypeError
+FAIL 'font-palette' does not supported 'Augusta' Failed to execute 'get' on 'StylePropertyMapReadOnly': Invalid propertyName: font-palette
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-palette.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-palette.html
new file mode 100644
index 0000000..ad62945
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-palette.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>'font-palette' property</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-get">
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-set">
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#property-stle-value-normalization">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../resources/testhelper.js"></script>
+<script src="resources/testsuite.js"></script>
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+runPropertyTests('font-palette', [
+  { syntax: 'normal' },
+  { syntax: 'light' },
+  { syntax: 'dark' },
+]);
+
+runUnsupportedPropertyTests('font-palette', [
+  'Augusta'
+]);
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-presentation-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-presentation-expected.txt
new file mode 100644
index 0000000..acb3aaf
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-presentation-expected.txt
@@ -0,0 +1,14 @@
+This is a testharness.js-based test.
+FAIL Can set 'font-presentation' to CSS-wide keywords Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-presentation
+FAIL Can set 'font-presentation' to var() references Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-presentation
+FAIL Can set 'font-presentation' to the 'auto' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-presentation
+FAIL Can set 'font-presentation' to the 'text' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-presentation
+FAIL Can set 'font-presentation' to the 'emoji' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-presentation
+PASS Setting 'font-presentation' to a length throws TypeError
+PASS Setting 'font-presentation' to a percent throws TypeError
+PASS Setting 'font-presentation' to a time throws TypeError
+PASS Setting 'font-presentation' to a number throws TypeError
+PASS Setting 'font-presentation' to a position throws TypeError
+PASS Setting 'font-presentation' to a transform throws TypeError
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-presentation.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-presentation.html
new file mode 100644
index 0000000..4448466
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-presentation.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>'font-presentation' property</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-get">
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-set">
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#property-stle-value-normalization">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../resources/testhelper.js"></script>
+<script src="resources/testsuite.js"></script>
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+runPropertyTests('font-presentation', [
+  { syntax: 'auto' },
+  { syntax: 'text' },
+  { syntax: 'emoji' },
+]);
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-size-adjust.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-size-adjust.html
new file mode 100644
index 0000000..71cb54c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-size-adjust.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>'font-size-adjust' property</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-get">
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-set">
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#property-stle-value-normalization">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../resources/testhelper.js"></script>
+<script src="resources/testsuite.js"></script>
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+runPropertyTests('font-size-adjust', [
+  { syntax: 'none' },
+  {
+    syntax: '<number>',
+    specified: assert_is_equal_with_range_handling
+  },
+]);
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-size-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-size-expected.txt
new file mode 100644
index 0000000..328a1851
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-size-expected.txt
@@ -0,0 +1,56 @@
+This is a testharness.js-based test.
+Found 52 tests; 25 PASS, 27 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS Can set 'font-size' to CSS-wide keywords
+PASS Can set 'font-size' to var() references
+PASS Can set 'font-size' to the 'xx-small' keyword
+PASS Can set 'font-size' to the 'x-small' keyword
+PASS Can set 'font-size' to the 'small' keyword
+PASS Can set 'font-size' to the 'medium' keyword
+PASS Can set 'font-size' to the 'large' keyword
+PASS Can set 'font-size' to the 'x-large' keyword
+PASS Can set 'font-size' to the 'xx-large' keyword
+PASS Can set 'font-size' to the 'larger' keyword
+PASS Can set 'font-size' to the 'smaller' keyword
+PASS Can set 'font-size' to a length
+PASS Can set 'font-size' to a percent
+PASS Setting 'font-size' to a time throws TypeError
+PASS Setting 'font-size' to a number throws TypeError
+PASS Setting 'font-size' to a position throws TypeError
+PASS Setting 'font-size' to a transform throws TypeError
+FAIL Can set 'font-min-size' to CSS-wide keywords Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-min-size
+FAIL Can set 'font-min-size' to var() references Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-min-size
+FAIL Can set 'font-min-size' to the 'xx-small' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-min-size
+FAIL Can set 'font-min-size' to the 'x-small' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-min-size
+FAIL Can set 'font-min-size' to the 'small' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-min-size
+FAIL Can set 'font-min-size' to the 'medium' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-min-size
+FAIL Can set 'font-min-size' to the 'large' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-min-size
+FAIL Can set 'font-min-size' to the 'x-large' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-min-size
+FAIL Can set 'font-min-size' to the 'xx-large' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-min-size
+FAIL Can set 'font-min-size' to the 'larger' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-min-size
+FAIL Can set 'font-min-size' to the 'smaller' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-min-size
+FAIL Can set 'font-min-size' to a length Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-min-size
+FAIL Can set 'font-min-size' to a percent Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-min-size
+PASS Setting 'font-min-size' to a time throws TypeError
+PASS Setting 'font-min-size' to a number throws TypeError
+PASS Setting 'font-min-size' to a position throws TypeError
+PASS Setting 'font-min-size' to a transform throws TypeError
+FAIL Can set 'font-max-size' to CSS-wide keywords Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-max-size
+FAIL Can set 'font-max-size' to var() references Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-max-size
+FAIL Can set 'font-max-size' to the 'infinity' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-max-size
+FAIL Can set 'font-max-size' to the 'xx-small' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-max-size
+FAIL Can set 'font-max-size' to the 'x-small' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-max-size
+FAIL Can set 'font-max-size' to the 'small' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-max-size
+FAIL Can set 'font-max-size' to the 'medium' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-max-size
+FAIL Can set 'font-max-size' to the 'large' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-max-size
+FAIL Can set 'font-max-size' to the 'x-large' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-max-size
+FAIL Can set 'font-max-size' to the 'xx-large' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-max-size
+FAIL Can set 'font-max-size' to the 'larger' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-max-size
+FAIL Can set 'font-max-size' to the 'smaller' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-max-size
+FAIL Can set 'font-max-size' to a length Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-max-size
+FAIL Can set 'font-max-size' to a percent Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-max-size
+PASS Setting 'font-max-size' to a time throws TypeError
+PASS Setting 'font-max-size' to a number throws TypeError
+PASS Setting 'font-max-size' to a position throws TypeError
+PASS Setting 'font-max-size' to a transform throws TypeError
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-size.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-size.html
index 620f68f..fc76e0f 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-size.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-size.html
@@ -13,53 +13,60 @@
 <script>
 'use strict';
 
-runPropertyTests('font-size', [
-  {
-    syntax: 'xx-small',
-    computed: (_, result) => assert_is_unit('px', result)
-  },
-  {
-    syntax: 'x-small',
-    computed: (_, result) => assert_is_unit('px', result)
-  },
-  {
-    syntax: 'small',
-    computed: (_, result) => assert_is_unit('px', result)
-  },
-  {
-    syntax: 'medium',
-    computed: (_, result) => assert_is_unit('px', result)
-  },
-  {
-    syntax: 'large',
-    computed: (_, result) => assert_is_unit('px', result)
-  },
-  {
-    syntax: 'x-large',
-    computed: (_, result) => assert_is_unit('px', result)
-  },
-  {
-    syntax: 'xx-large',
-    computed: (_, result) => assert_is_unit('px', result)
-  },
-  {
-    syntax: 'larger',
-    computed: (_, result) => assert_is_unit('px', result)
-  },
-  {
-    syntax: 'smaller',
-    computed: (_, result) => assert_is_unit('px', result)
-  },
-  {
-    syntax: '<length>',
-    specified: assert_is_equal_with_range_handling,
-    computed: (_, result) => assert_is_unit('px', result)
-  },
-  {
-    syntax: '<percentage>',
-    specified: assert_is_equal_with_range_handling,
-    computed: (_, result) => assert_is_unit('px', result)
-  },
-]);
+for (const property of ['font-size', 'font-min-size', 'font-max-size']) {
+  // font-max-size also supports 'infinity' keyword
+  const infinity = property === 'font-max-size' ?
+    [{ syntax: 'infinity'}] : [];
+
+  runPropertyTests(property, [
+    ...infinity,
+    {
+      syntax: 'xx-small',
+      computed: (_, result) => assert_is_unit('px', result)
+    },
+    {
+      syntax: 'x-small',
+      computed: (_, result) => assert_is_unit('px', result)
+    },
+    {
+      syntax: 'small',
+      computed: (_, result) => assert_is_unit('px', result)
+    },
+    {
+      syntax: 'medium',
+      computed: (_, result) => assert_is_unit('px', result)
+    },
+    {
+      syntax: 'large',
+      computed: (_, result) => assert_is_unit('px', result)
+    },
+    {
+      syntax: 'x-large',
+      computed: (_, result) => assert_is_unit('px', result)
+    },
+    {
+      syntax: 'xx-large',
+      computed: (_, result) => assert_is_unit('px', result)
+    },
+    {
+      syntax: 'larger',
+      computed: (_, result) => assert_is_unit('px', result)
+    },
+    {
+      syntax: 'smaller',
+      computed: (_, result) => assert_is_unit('px', result)
+    },
+    {
+      syntax: '<length>',
+      specified: assert_is_equal_with_range_handling,
+      computed: (_, result) => assert_is_unit('px', result)
+    },
+    {
+      syntax: '<percentage>',
+      specified: assert_is_equal_with_range_handling,
+      computed: (_, result) => assert_is_unit('px', result)
+    },
+  ]);
+}
 
 </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-stretch-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-stretch-expected.txt
new file mode 100644
index 0000000..078e50a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-stretch-expected.txt
@@ -0,0 +1,20 @@
+This is a testharness.js-based test.
+PASS Can set 'font-stretch' to CSS-wide keywords
+PASS Can set 'font-stretch' to var() references
+FAIL Can set 'font-stretch' to the 'normal' keyword assert_equals: expected "CSSKeywordValue" but got "CSSUnitValue"
+FAIL Can set 'font-stretch' to the 'ultra-condensed' keyword assert_equals: expected "CSSKeywordValue" but got "CSSUnitValue"
+FAIL Can set 'font-stretch' to the 'extra-condensed' keyword assert_equals: expected "CSSKeywordValue" but got "CSSUnitValue"
+FAIL Can set 'font-stretch' to the 'condensed' keyword assert_equals: expected "CSSKeywordValue" but got "CSSUnitValue"
+FAIL Can set 'font-stretch' to the 'semi-condensed' keyword assert_equals: expected "CSSKeywordValue" but got "CSSUnitValue"
+FAIL Can set 'font-stretch' to the 'semi-expanded' keyword assert_equals: expected "CSSKeywordValue" but got "CSSUnitValue"
+FAIL Can set 'font-stretch' to the 'expanded' keyword assert_equals: expected "CSSKeywordValue" but got "CSSUnitValue"
+FAIL Can set 'font-stretch' to the 'extra-expanded' keyword assert_equals: expected "CSSKeywordValue" but got "CSSUnitValue"
+FAIL Can set 'font-stretch' to the 'ultra-expanded' keyword assert_equals: expected "CSSKeywordValue" but got "CSSUnitValue"
+FAIL Can set 'font-stretch' to a percent assert_approx_equals: expected -3.14 +/- 0.000001 but got -3
+PASS Setting 'font-stretch' to a length throws TypeError
+PASS Setting 'font-stretch' to a time throws TypeError
+PASS Setting 'font-stretch' to a number throws TypeError
+PASS Setting 'font-stretch' to a position throws TypeError
+PASS Setting 'font-stretch' to a transform throws TypeError
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-stretch.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-stretch.html
new file mode 100644
index 0000000..3871ff3e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-stretch.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>'font-stretch' property</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-get">
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-set">
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#property-stle-value-normalization">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../resources/testhelper.js"></script>
+<script src="resources/testsuite.js"></script>
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+runPropertyTests('font-stretch', [
+  { syntax: 'normal' },
+  { syntax: 'ultra-condensed' },
+  { syntax: 'extra-condensed' },
+  { syntax: 'condensed' },
+  { syntax: 'semi-condensed' },
+  { syntax: 'semi-expanded' },
+  { syntax: 'expanded' },
+  { syntax: 'extra-expanded' },
+  { syntax: 'ultra-expanded' },
+  {
+    syntax: '<percentage>',
+    specified: assert_is_equal_with_range_handling
+  },
+]);
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-synthesis-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-synthesis-expected.txt
new file mode 100644
index 0000000..6a72df0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-synthesis-expected.txt
@@ -0,0 +1,18 @@
+This is a testharness.js-based test.
+FAIL Can set 'font-synthesis' to CSS-wide keywords Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-synthesis
+FAIL Can set 'font-synthesis' to var() references Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-synthesis
+FAIL Can set 'font-synthesis' to the 'none' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-synthesis
+FAIL Can set 'font-synthesis' to the 'weight' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-synthesis
+FAIL Can set 'font-synthesis' to the 'style' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-synthesis
+FAIL Can set 'font-synthesis' to the 'small-caps' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-synthesis
+PASS Setting 'font-synthesis' to a length throws TypeError
+PASS Setting 'font-synthesis' to a percent throws TypeError
+PASS Setting 'font-synthesis' to a time throws TypeError
+PASS Setting 'font-synthesis' to a number throws TypeError
+PASS Setting 'font-synthesis' to a position throws TypeError
+PASS Setting 'font-synthesis' to a transform throws TypeError
+FAIL 'font-synthesis' does not supported 'weight style' Failed to execute 'get' on 'StylePropertyMapReadOnly': Invalid propertyName: font-synthesis
+FAIL 'font-synthesis' does not supported 'style small-caps' Failed to execute 'get' on 'StylePropertyMapReadOnly': Invalid propertyName: font-synthesis
+FAIL 'font-synthesis' does not supported 'small-caps weight style' Failed to execute 'get' on 'StylePropertyMapReadOnly': Invalid propertyName: font-synthesis
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-synthesis.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-synthesis.html
new file mode 100644
index 0000000..b8c79e6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-synthesis.html
@@ -0,0 +1,27 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>'font-synthesis' property</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-get">
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-set">
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#property-stle-value-normalization">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../resources/testhelper.js"></script>
+<script src="resources/testsuite.js"></script>
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+runPropertyTests('font-synthesis', [
+  { syntax: 'none' },
+  { syntax: 'weight' },
+  { syntax: 'style' },
+  { syntax: 'small-caps' },
+]);
+
+runUnsupportedPropertyTests('font-synthesis', [
+  'weight style', 'style small-caps', 'small-caps weight style'
+]);
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-variant-alternates-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-variant-alternates-expected.txt
new file mode 100644
index 0000000..d90cff9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-variant-alternates-expected.txt
@@ -0,0 +1,20 @@
+This is a testharness.js-based test.
+FAIL Can set 'font-variant-alternates' to CSS-wide keywords Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-variant-alternates
+FAIL Can set 'font-variant-alternates' to var() references Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-variant-alternates
+FAIL Can set 'font-variant-alternates' to the 'normal' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-variant-alternates
+FAIL Can set 'font-variant-alternates' to the 'historical-forms' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-variant-alternates
+PASS Setting 'font-variant-alternates' to a length throws TypeError
+PASS Setting 'font-variant-alternates' to a percent throws TypeError
+PASS Setting 'font-variant-alternates' to a time throws TypeError
+PASS Setting 'font-variant-alternates' to a number throws TypeError
+PASS Setting 'font-variant-alternates' to a position throws TypeError
+PASS Setting 'font-variant-alternates' to a transform throws TypeError
+FAIL 'font-variant-alternates' does not supported 'stylistic(foo)' Failed to execute 'get' on 'StylePropertyMapReadOnly': Invalid propertyName: font-variant-alternates
+FAIL 'font-variant-alternates' does not supported 'styleset(foo)' Failed to execute 'get' on 'StylePropertyMapReadOnly': Invalid propertyName: font-variant-alternates
+FAIL 'font-variant-alternates' does not supported 'character-variant(foo)' Failed to execute 'get' on 'StylePropertyMapReadOnly': Invalid propertyName: font-variant-alternates
+FAIL 'font-variant-alternates' does not supported 'swash(foo)' Failed to execute 'get' on 'StylePropertyMapReadOnly': Invalid propertyName: font-variant-alternates
+FAIL 'font-variant-alternates' does not supported 'ornaments(foo)' Failed to execute 'get' on 'StylePropertyMapReadOnly': Invalid propertyName: font-variant-alternates
+FAIL 'font-variant-alternates' does not supported 'annotation(foo)' Failed to execute 'get' on 'StylePropertyMapReadOnly': Invalid propertyName: font-variant-alternates
+FAIL 'font-variant-alternates' does not supported 'swash(foo) annotation(foo2)' Failed to execute 'get' on 'StylePropertyMapReadOnly': Invalid propertyName: font-variant-alternates
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-variant-alternates.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-variant-alternates.html
new file mode 100644
index 0000000..521eb3a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-variant-alternates.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>'font-variant-alternates' property</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-get">
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-set">
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#property-stle-value-normalization">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../resources/testhelper.js"></script>
+<script src="resources/testsuite.js"></script>
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+runPropertyTests('font-variant-alternates', [
+  { syntax: 'normal' },
+  { syntax: 'historical-forms' },
+]);
+
+runUnsupportedPropertyTests('font-variant-alternates', [
+  'stylistic(foo)',
+  'styleset(foo)',
+  'character-variant(foo)',
+  'swash(foo)',
+  'ornaments(foo)',
+  'annotation(foo)',
+  'swash(foo) annotation(foo2)',
+]);
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-variant-emoji-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-variant-emoji-expected.txt
new file mode 100644
index 0000000..1ac0169
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-variant-emoji-expected.txt
@@ -0,0 +1,14 @@
+This is a testharness.js-based test.
+FAIL Can set 'font-variant-emoji' to CSS-wide keywords Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-variant-emoji
+FAIL Can set 'font-variant-emoji' to var() references Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-variant-emoji
+FAIL Can set 'font-variant-emoji' to the 'auto' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-variant-emoji
+FAIL Can set 'font-variant-emoji' to the 'text' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-variant-emoji
+FAIL Can set 'font-variant-emoji' to the 'emoji' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid propertyName: font-variant-emoji
+PASS Setting 'font-variant-emoji' to a length throws TypeError
+PASS Setting 'font-variant-emoji' to a percent throws TypeError
+PASS Setting 'font-variant-emoji' to a time throws TypeError
+PASS Setting 'font-variant-emoji' to a number throws TypeError
+PASS Setting 'font-variant-emoji' to a position throws TypeError
+PASS Setting 'font-variant-emoji' to a transform throws TypeError
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-variant-emoji.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-variant-emoji.html
new file mode 100644
index 0000000..38cd6d23
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-variant-emoji.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>'font-variant-emoji' property</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-get">
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-set">
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#property-stle-value-normalization">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../resources/testhelper.js"></script>
+<script src="resources/testsuite.js"></script>
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+runPropertyTests('font-variant-emoji', [
+  { syntax: 'auto' },
+  { syntax: 'text' },
+  { syntax: 'emoji' },
+]);
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-variant.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-variant.html
new file mode 100644
index 0000000..765ce28b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-variant.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>'font-variant' property</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-get">
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-set">
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#property-stle-value-normalization">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../resources/testhelper.js"></script>
+<script src="resources/testsuite.js"></script>
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+runUnsupportedPropertyTests('font-variant', [
+  'normal', 'no-common-ligatures proportional-nums',
+  'common-ligatures tabular-nums', 'small-caps slashed-zero'
+]);
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-variation-settings.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-variation-settings.html
new file mode 100644
index 0000000..12d6261
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font-variation-settings.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>'font-variation-settings' property</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-get">
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-set">
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#property-stle-value-normalization">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../resources/testhelper.js"></script>
+<script src="resources/testsuite.js"></script>
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+runPropertyTests('font-variation-settings', [
+  { syntax: 'normal' },
+]);
+
+runUnsupportedPropertyTests('font-variation-settings', [
+  '"XHGT" 0.7',
+]);
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font.html
new file mode 100644
index 0000000..b8a1e88
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/font.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>'font' property</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-get">
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-set">
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#property-stle-value-normalization">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../resources/testhelper.js"></script>
+<script src="resources/testsuite.js"></script>
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+runUnsupportedPropertyTests('font', [
+  '1.2em "Fira Sans", sans-serif',
+  'italic 1.2em "Fira Sans", serif',
+  'italic small-caps bold 16px/2 cursive',
+  'small-caps bold 24px/1 sans-serif',
+  'caption',
+]);
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/ch-units-vrl-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/ch-units-vrl-001.html
deleted file mode 100644
index 5591465b..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/ch-units-vrl-001.html
+++ /dev/null
@@ -1,56 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>upright vertical writing mode and ch unit on table rows</title>
-<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/">
-<link rel="help" href="https://www.w3.org/TR/css-writing-modes-3/#placement">
-<link rel="match" href="reference/ch-units-vrl-001-ref.html"
-<meta name="assert" content="The font-metric dependent ch unit on table rows takes the writing mode (with upright text-orientation) into account,
-                            even though theses properties do not apply to that element.">
-<style>
-table {
-  font-size: 20px;
-  border-collapse: collapse;
-  border: none;
-}
-td {
-  padding: 0;
-  background: green;
-  height: 5ch;
-}
-tr {
-  writing-mode: vertical-rl;
-  text-orientation: upright;
-  line-height: 5ch; /* using the inherited line-height (which the affects the content of the td)
-                       instead of directly using the height property,
-                       because sizing on table cells is complicated and out of scope for this. */
-}
-
-div {
-  font-size: 20px;
-  color: transparent;
-}
-
-/* Sizing the reference divs using the actual 0 (after which the ch unit is based) in the inline dimensions,
-   and using the ch unit in the block dimension,
-   to make sure that the ch unit itself works well in the general case.
-   If it doesn't, or if writing modes don't work, the divs won't be square.
- */
-div:nth-of-type(1) {
-  background: blue;
-  writing-mode: vertical-rl;
-  text-orientation: upright;
-  width: 5ch;
-}
-div:nth-of-type(2) {
-  background: orange;
-  height: 5ch;
-  display: inline-block; /* shrinkwrap */
-}
-</style>
-<body>
-  <p>Test passes if there is a <strong>green square</strong> below, and if it is the <strong>same size as the blue</strong> one, not the orange one.
-  <p>If any of the 3 colored shapes is not a square, or if the orange and blue squares are the same size, the test fails.
-  <table><tbody><tr><td>&nbsp;</td></tr></tbody></table>
-  <div>00000</div>
-  <div>00000</div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/ch-units-vrl-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/ch-units-vrl-002.html
deleted file mode 100644
index d1ff259c..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/ch-units-vrl-002.html
+++ /dev/null
@@ -1,56 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>upright vertical writing mode and ch unit on table row groups</title>
-<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/">
-<link rel="help" href="https://www.w3.org/TR/css-writing-modes-3/#placement">
-<link rel="match" href="reference/ch-units-vrl-001-ref.html"
-<meta name="assert" content="The font-metric dependent ch unit on table row groups takes the writing mode (with upright text-orientatino) into account,
-                            even though these properties do not apply to that element.">
-<style>
-table {
-  font-size: 20px;
-  border-collapse: collapse;
-  border: none;
-}
-td {
-  padding: 0;
-  background: green;
-  height: 5ch;
-}
-tbody {
-  writing-mode: vertical-rl;
-  text-orientation: upright;
-  line-height: 5ch; /* using the inherited line-height (which the affects the content of the td)
-                       instead of directly using the height property,
-                       because sizing on table cells is complicated and out of scope for this. */
-}
-
-div {
-  font-size: 20px;
-  color: transparent;
-}
-
-/* Sizing the reference divs using the actual 0 (after which the ch unit is based) in the inline dimensions,
-   and using the ch unit in the block dimension,
-   to make sure that the ch unit itself works well in the general case.
-   If it doesn't, or if writing modes don't work, the divs won't be square.
- */
-div:nth-of-type(1) {
-  background: blue;
-  writing-mode: vertical-rl;
-  text-orientation: upright;
-  width: 5ch;
-}
-div:nth-of-type(2) {
-  background: orange;
-  height: 5ch;
-  display: inline-block; /* shrinkwrap */
-}
-</style>
-<body>
-  <p>Test passes if there is a <strong>green square</strong> below, and if it is the <strong>same size as the blue</strong> one, not the orange one.
-  <p>If any of the 3 colored shapes is not a square, or if the orange and blue squares are the same size, the test fails.
-  <table><tbody><tr><td>&nbsp;</td></tr></tbody></table>
-  <div>00000</div>
-  <div>00000</div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/ch-units-vrl-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/ch-units-vrl-003.html
deleted file mode 100644
index 5f7de3c9..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/ch-units-vrl-003.html
+++ /dev/null
@@ -1,56 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>upright vertical writing mode and ch unit on table columns</title>
-<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/">
-<link rel="help" href="https://www.w3.org/TR/css-writing-modes-3/#placement">
-<link rel="match" href="reference/ch-units-vrl-001-ref.html"
-<meta name="assert" content="The font-metric dependent ch unit on table columns takes the writing mode (with upright orientation) into account,
-                            even though these properties do no apply to that element.">
-<style>
-table {
-  font-size: 20px;
-  border-collapse: collapse;
-  border: none;
-}
-td {
-  padding: 0;
-  background: green;
-  height: 5ch;
-  writing-mode: vertical-rl;
-  text-orientation: upright;
-}
-col {
-  writing-mode: vertical-rl;
-  text-orientation: upright;
-  width: 5ch;
-}
-
-div {
-  font-size: 20px;
-  color: transparent;
-}
-
-/* Sizing the reference divs using the actual 0 (after which the ch unit is based) in the inline dimensions,
-   and using the ch unit in the block dimension,
-   to make sure that the ch unit itself works well in the general case.
-   If it doesn't, or if writing modes don't work, the divs won't be square.
- */
-div:nth-of-type(1) {
-  background: blue;
-  writing-mode: vertical-rl;
-  text-orientation: upright;
-  width: 5ch;
-}
-div:nth-of-type(2) {
-  background: orange;
-  height: 5ch;
-  display: inline-block; /* shrinkwrap */
-}
-</style>
-<body>
-  <p>Test passes if there is a <strong>green square</strong> below, and if it is the <strong>same size as the blue</strong> one, not the orange one.
-  <p>If any of the 3 colored shapes is not a square, or if the orange and blue squares are the same size, the test fails.
-  <table><col><tbody><tr><td>&nbsp;</td></tr></tbody></table>
-  <div>00000</div>
-  <div>00000</div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/ch-units-vrl-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/ch-units-vrl-004.html
deleted file mode 100644
index 4264afd71..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/ch-units-vrl-004.html
+++ /dev/null
@@ -1,56 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>upright vertical writing mode and ch unit on table column groups</title>
-<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/">
-<link rel="help" href="https://www.w3.org/TR/css-writing-modes-3/#placement">
-<link rel="match" href="reference/ch-units-vrl-001-ref.html"
-<meta name="assert" content="The font-metric dependent ch unit on table column groups takes the writing mode (with upright text-orientation) into account,
-                            even though these properties do not apply to that element.">
-<style>
-table {
-  font-size: 20px;
-  border-collapse: collapse;
-  border: none;
-}
-td {
-  padding: 0;
-  background: green;
-  height: 5ch;
-  writing-mode: vertical-rl;
-  text-orientation: upright;
-}
-colgroup {
-  writing-mode: vertical-rl;
-  text-orientation: upright;
-  width: 5ch;
-}
-
-div {
-  font-size: 20px;
-  color: transparent;
-}
-
-/* Sizing the reference divs using the actual 0 (after which the ch unit is based) in the inline dimensions,
-   and using the ch unit in the block dimension,
-   to make sure that the ch unit itself works well in the general case.
-   If it doesn't, or if writing modes don't work, the divs won't be square.
- */
-div:nth-of-type(1) {
-  background: blue;
-  writing-mode: vertical-rl;
-  text-orientation: upright;
-  width: 5ch;
-}
-div:nth-of-type(2) {
-  background: orange;
-  height: 5ch;
-  display: inline-block; /* shrinkwrap */
-}
-</style>
-<body>
-  <p>Test passes if there is a <strong>green square</strong> below, and if it is the <strong>same size as the blue</strong> one, not the orange one.
-  <p>If any of the 3 colored shapes is not a square, or if the orange and blue squares are the same size, the test fails.
-  <table><colgroup><tbody><tr><td>&nbsp;</td></tr></tbody></table>
-  <div>00000</div>
-  <div>00000</div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/ch-units-vrl-005.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/ch-units-vrl-005.html
deleted file mode 100644
index 6348b0099..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/ch-units-vrl-005.html
+++ /dev/null
@@ -1,56 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>sideways vertical writing mode and ch unit on table rows</title>
-<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/">
-<link rel="help" href="https://www.w3.org/TR/css-writing-modes-3/#placement">
-<link rel="match" href="reference/ch-units-vrl-005-ref.html"
-<meta name="assert" content="The font-metric dependent ch unit on table rows takes the writing mode (with a sideways text-orientation) into account,
-                            even though theese properties do not apply to that element.">
-<style>
-table {
-  font-size: 20px;
-  border-collapse: collapse;
-  border: none;
-}
-td {
-  padding: 0;
-  background: green;
-  height: 5ch;
-}
-tr {
-  writing-mode: vertical-rl;
-  text-orientation: sideways;
-  line-height: 5ch; /* using the inherited line-height (which the affects the content of the td)
-                       instead of directly using the height property,
-                       because sizing on table cells is complicated and out of scope for this. */
-}
-
-div {
-  font-size: 20px;
-  color: transparent;
-}
-
-/* Sizing the reference divs using the actual 0 (after which the ch unit is based) in the inline dimensions,
-   and using the ch unit in the block dimension,
-   to make sure that the ch unit itself works well in the general case.
-   If it doesn't, or if writing modes don't work, the divs won't be square.
- */
-div:nth-of-type(2) {
-  background: orange;
-  writing-mode: vertical-rl;
-  text-orientation: upright;
-  width: 5ch;
-}
-div:nth-of-type(1) {
-  background: blue;
-  height: 5ch;
-  display: inline-block; /* shrinkwrap */
-}
-</style>
-<body>
-  <p>Test passes if there is a <strong>green square</strong> below, and if it is the <strong>same size as the blue</strong> one, not the orange one.
-  <p>If any of the 3 colored shapes is not a square, or if the orange and blue squares are the same size, the test fails.
-  <table><tbody><tr><td>&nbsp;</td></tr></tbody></table>
-  <div>00000</div>
-  <div>00000</div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/ch-units-vrl-006.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/ch-units-vrl-006.html
deleted file mode 100644
index 1395606..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/ch-units-vrl-006.html
+++ /dev/null
@@ -1,56 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>sideways vertical writing mode and ch unit on table row groups</title>
-<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/">
-<link rel="help" href="https://www.w3.org/TR/css-writing-modes-3/#placement">
-<link rel="match" href="reference/ch-units-vrl-005-ref.html"
-<meta name="assert" content="The font-metric dependent ch unit on table row groups takes the writing mode (with a sideways text-orientation) into account,
-                            even though these properties do not apply to that element.">
-<style>
-table {
-  font-size: 20px;
-  border-collapse: collapse;
-  border: none;
-}
-td {
-  padding: 0;
-  background: green;
-  height: 5ch;
-}
-tbody {
-  writing-mode: vertical-rl;
-  text-orientation: sideways;
-  line-height: 5ch; /* using the inherited line-height (which the affects the content of the td)
-                       instead of directly using the height property,
-                       because sizing on table cells is complicated and out of scope for this. */
-}
-
-div {
-  font-size: 20px;
-  color: transparent;
-}
-
-/* Sizing the reference divs using the actual 0 (after which the ch unit is based) in the inline dimensions,
-   and using the ch unit in the block dimension,
-   to make sure that the ch unit itself works well in the general case.
-   If it doesn't, or if writing modes don't work, the divs won't be square.
- */
-div:nth-of-type(2) {
-  background: orange;
-  writing-mode: vertical-rl;
-  text-orientation: upright;
-  width: 5ch;
-}
-div:nth-of-type(1) {
-  background: orange;
-  height: 5ch;
-  display: inline-block; /* shrinkwrap */
-}
-</style>
-<body>
-  <p>Test passes if there is a <strong>green square</strong> below, and if it is the <strong>same size as the blue</strong> one, not the orange one.
-  <p>If any of the 3 colored shapes is not a square, or if the orange and blue squares are the same size, the test fails.
-  <table><tbody><tr><td>&nbsp;</td></tr></tbody></table>
-  <div>00000</div>
-  <div>00000</div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/ch-units-vrl-007.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/ch-units-vrl-007.html
deleted file mode 100644
index 978e5ba..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/ch-units-vrl-007.html
+++ /dev/null
@@ -1,56 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>sideways vertical writing mode and ch unit on table columns</title>
-<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/">
-<link rel="help" href="https://www.w3.org/TR/css-writing-modes-3/#placement">
-<link rel="match" href="reference/ch-units-vrl-005-ref.html"
-<meta name="assert" content="The font-metric dependent ch unit on table columns takes the writing mode (with a sideways orientation) into account,
-                            even though these properties do not apply to that element.">
-<style>
-table {
-  font-size: 20px;
-  border-collapse: collapse;
-  border: none;
-}
-td {
-  padding: 0;
-  background: green;
-  height: 5ch;
-  writing-mode: vertical-rl;
-  text-orientation: upright;
-}
-col {
-  writing-mode: vertical-rl;
-  text-orientation: sideways;
-  width: 5ch;
-}
-
-div {
-  font-size: 20px;
-  color: transparent;
-}
-
-/* Sizing the reference divs using the actual 0 (after which the ch unit is based) in the inline dimensions,
-   and using the ch unit in the block dimension,
-   to make sure that the ch unit itself works well in the general case.
-   If it doesn't, or if writing modes don't work, the divs won't be square.
- */
-div:nth-of-type(2) {
-  background: orange;
-  writing-mode: vertical-rl;
-  text-orientation: upright;
-  width: 5ch;
-}
-div:nth-of-type(1) {
-  background: blue;
-  height: 5ch;
-  display: inline-block; /* shrinkwrap */
-}
-</style>
-<body>
-  <p>Test passes if there is a <strong>green square</strong> below, and if it is the <strong>same size as the blue</strong> one, not the orange one.
-  <p>If any of the 3 colored shapes is not a square, or if the orange and blue squares are the same size, the test fails.
-  <table><col><tbody><tr><td>&nbsp;</td></tr></tbody></table>
-  <div>00000</div>
-  <div>00000</div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/ch-units-vrl-008.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/ch-units-vrl-008.html
deleted file mode 100644
index eece597..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/ch-units-vrl-008.html
+++ /dev/null
@@ -1,56 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>sideways vertical writing mode and ch unit on table column groups</title>
-<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/">
-<link rel="help" href="https://www.w3.org/TR/css-writing-modes-3/#placement">
-<link rel="match" href="reference/ch-units-vrl-005-ref.html"
-<meta name="assert" content="The font-metric dependent ch unit on table column groups takes the writing mode (with a sideways orientation) into account,
-                            even though theses properties do not apply to that element.">
-<style>
-table {
-  font-size: 20px;
-  border-collapse: collapse;
-  border: none;
-}
-td {
-  padding: 0;
-  background: green;
-  height: 5ch;
-  writing-mode: vertical-rl;
-  text-orientation: upright;
-}
-colgroup {
-  writing-mode: vertical-rl;
-  text-orientation: sideways;
-  width: 5ch;
-}
-
-div {
-  font-size: 20px;
-  color: transparent;
-}
-
-/* Sizing the reference divs using the actual 0 (after which the ch unit is based) in the inline dimensions,
-   and using the ch unit in the block dimension,
-   to make sure that the ch unit itself works well in the general case.
-   If it doesn't, or if writing modes don't work, the divs won't be square.
- */
-div:nth-of-type(2) {
-  background: orange;
-  writing-mode: vertical-rl;
-  text-orientation: upright;
-  width: 5ch;
-}
-div:nth-of-type(1) {
-  background: blue;
-  height: 5ch;
-  display: inline-block; /* shrinkwrap */
-}
-</style>
-<body>
-  <p>Test passes if there is a <strong>green square</strong> below, and if it is the <strong>same size as the blue</strong> one, not the orange one.
-  <p>If any of the 3 colored shapes is not a square, or if the orange and blue squares are the same size, the test fails.
-  <table><colgroup><tbody><tr><td>&nbsp;</td></tr></tbody></table>
-  <div>00000</div>
-  <div>00000</div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/form-controls-slr-004.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/form-controls-slr-004.xht
deleted file mode 100644
index 7774f4b6..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/form-controls-slr-004.xht
+++ /dev/null
@@ -1,57 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-
- <head>
-
-  <title>CSS Writing Modes Test: order, orientation and layout of form controls in 'sideways-lr' writing-mode</title>
-
-  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-4/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
-
-  <meta content="image should" name="flags" />
-  <meta content="This test checks the order, the flow, the orientation and layout of form controls used in Example 4 of section 3.1 when the 'writing-mode' of the whole form element is set to 'sideways-lr'." name="assert" />
-
-  <style type="text/css"><![CDATA[
-  form
-    {
-      font-size: 18px;
-      writing-mode: sideways-lr;
-    }
-
-  select
-    {
-      vertical-align: top;
-    }
-  ]]></style>
- </head>
-
- <body>
-
-  <form action="">
-    <p><label>姓名 <input value="艾俐俐" size="10" /></label></p>
-
-    <p><label>语言 <select size="1"><option>English</option>
-                         <option>français</option>
-                         <option>فارسی</option>
-                         <option>中文</option>
-                         <option>日本語</option></select></label></p>
-  </form>
-
-  <p>Test passes if the characters and form controls of the form above have the <strong>same order</strong>, the <strong>same orientation</strong> and the <strong>same layout</strong> as the ones of the form below:</p>
-
-  <p><img src="support/form-controls-slr.png" width="180" height="185" alt="Image download support must be enabled" />
-<!--
-  Long description of image:
-  Screenshot of vertical layout: the input element is laid lengthwise
-  from bottom to top and its content rendered in a vertical writing mode,
-  matching the label outside it. The drop-down selection control (located on
-  the input element's righthand side) slides out to the side (towards the
-  after edge of the block) rather than downward as it would in horizontal writing mode.
-  The Asian glyphs in the input element and in the drop-down selection
-  control are rotated 90 degrees counter-clockwise.
--->
-  </p>
-
- </body>
-</html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/form-controls-slr-005.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/form-controls-slr-005.xht
deleted file mode 100644
index 35b4ace..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/form-controls-slr-005.xht
+++ /dev/null
@@ -1,57 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-
- <head>
-
-  <title>CSS Writing Modes Test: form controls in 'sideways-lr' writing-mode</title>
-
-  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-4/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
-
-  <meta content="should" name="flags" />
-  <meta content="This test checks the rendering of various form controls (select, optgroup, options, various types of input and buttons) written with latin text in 'sideways-lr' writing mode. The text of replaced content should match the replaced element's writing mode and line orientation; therefore, in this test, a) the text's inline base direction must be from bottom to top, b) the glyphs must be rotated 90° counter-clockwise and c) the block flow direction must be from left to right." name="assert" />
-
-  <style type="text/css"><![CDATA[
-  form
-    {
-      font-size: 1.25em;
-      writing-mode: sideways-lr;
-    }
-  ]]></style>
- </head>
-
- <body>
-
-  <p>Test passes if a) the form controls are appearing with Text sample1 on the left of the page and with Text sample10 on the right and if b) each of the 10 "Text sample" in the form controls are <strong>rotated 90° counter-clockwise</strong>.</p>
-
-  <form action="">
-
-    <p><input value="Text sample1" size="12" /></p>
-
-    <p>
-      <select size="3">
-        <optgroup label="Text sample2">
-          <option>Text sample3</option>
-          <option>Text sample4</option>
-        </optgroup>
-      </select>
-    </p>
-
-    <p><textarea cols="12" rows="2">Text sample5</textarea></p>
-
-    <p><input type="button" value="Text sample6" /></p>
-
-    <p><input type="submit" value="Text sample7" /></p>
-
-    <p><input type="reset" value="Text sample8" /></p>
-
-    <p><button type="button">Text sample9</button></p>
-
-    <p><button type="submit">Text sample10</button></p>
-
-  </form>
-
- </body>
-</html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/form-controls-srl-004.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/form-controls-srl-004.xht
deleted file mode 100644
index 37f4bb4..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/form-controls-srl-004.xht
+++ /dev/null
@@ -1,58 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-
- <head>
-
-  <title>CSS Writing Modes Test: order, orientation and layout of form controls in 'sideways-rl' writing-mode</title>
-
-  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-4/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
-
-  <meta content="image should" name="flags" />
-  <meta content="This test checks the order, the flow, the orientation and layout of form controls used in Example 4 of section 3.1 when the 'writing-mode' of the whole form element is set to 'sideways-rl'." name="assert" />
-
-  <style type="text/css"><![CDATA[
-  form
-    {
-      font-size: 18px;
-      margin-left: 7em;
-      writing-mode: sideways-rl;
-    }
-
-  select
-    {
-      vertical-align: top;
-    }
-  ]]></style>
- </head>
-
- <body>
-
-  <form action="">
-    <p><label>姓名 <input value="艾俐俐" size="10" /></label></p>
-
-    <p><label>语言 <select size="1"><option>English</option>
-                         <option>français</option>
-                         <option>فارسی</option>
-                         <option>中文</option>
-                         <option>日本語</option></select></label></p>
-  </form>
-
-  <p>Test passes if the characters and form controls of the form above have the <strong>same order</strong>, the <strong>same orientation</strong> and the <strong>same layout</strong> as the ones of the form below:</p>
-
-  <p><img src="support/form-controls-srl.png" width="180" height="185" alt="Image download support must be enabled" />
-<!--
-  Long description of image:
-  Screenshot of vertical layout: the input element is laid lengthwise
-  from top to bottom and its content rendered in a vertical writing mode,
-  matching the label outside it. The drop-down selection control (located on
-  the input element's lefthand side) slides out to the side (towards the
-  after edge of the block) rather than downward as it would in horizontal writing mode.
-  The Asian glyphs in the input element and in the drop-down selection
-  control are rotated 90 degrees clockwise.
--->
-  </p>
-
- </body>
-</html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/form-controls-srl-005.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/form-controls-srl-005.xht
deleted file mode 100644
index f092ecc..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/form-controls-srl-005.xht
+++ /dev/null
@@ -1,57 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-
- <head>
-
-  <title>CSS Writing Modes Test: form controls in 'sideways-rl' writing-mode</title>
-
-  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-4/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
-
-  <meta content="should" name="flags" />
-  <meta content="This test checks the rendering of various form controls (select, optgroup, options, various types of input and buttons) written with latin text in 'sideways-rl' writing mode. The text of replaced content should match the replaced element's writing mode and line orientation; therefore, in this test, a) the text's inline base direction must be from top to bottom, b) the glyphs must be rotated 90° clockwise and c) the block flow direction must be from right to left." name="assert" />
-
-  <style type="text/css"><![CDATA[
-  form
-    {
-      font-size: 1.25em;
-      writing-mode: sideways-rl;
-  }
-  ]]></style>
- </head>
-
- <body>
-
-  <p>Test passes if a) the form controls are appearing with Text sample1 on the right of the page and with Text sample10 on the left and if b) each of the 10 "Text sample" in the form controls are <strong>rotated 90° clockwise</strong>.</p>
-
-  <form action="">
-
-    <p><input value="Text sample1" size="12" /></p>
-
-    <p>
-      <select size="3">
-        <optgroup label="Text sample2">
-          <option>Text sample3</option>
-          <option>Text sample4</option>
-        </optgroup>
-      </select>
-    </p>
-
-    <p><textarea cols="12" rows="2">Text sample5</textarea></p>
-
-    <p><input type="button" value="Text sample6" /></p>
-
-    <p><input type="submit" value="Text sample7" /></p>
-
-    <p><input type="reset" value="Text sample8" /></p>
-
-    <p><button type="button">Text sample9</button></p>
-
-    <p><button type="submit">Text sample10</button></p>
-
-  </form>
-
- </body>
-</html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/inline-block-alignment-slr-009-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/inline-block-alignment-slr-009-ref.xht
deleted file mode 100644
index 1c98878f..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/inline-block-alignment-slr-009-ref.xht
+++ /dev/null
@@ -1,35 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
- <title>CSS Reftest Reference</title>
- <link rel="author" title="Hajime Shiozawa" href="mailto:hajime.shiozawa@gmail.com" />
-  <link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2015-12-12 -->
- <meta name="flags" content="image" />
- <style type="text/css"><![CDATA[
- img
- {
-  padding-left: 252px; /* 60px (padding-left) + 120px (B) + 96px (?) - 24px (?) == 252px */
-  vertical-align: top;
- }
-
- img + br + img
- {
-  padding-left: 60px; /* 60px (padding-left) */
- }
-
- img + br + img + br + img
- {
-  padding-left: 228px; /* 60px (padding-left) + 120px (B) + 96px (?) - 48px == 228px */
- }
- ]]></style>
-
-</head>
-
-<body>
-
-<p>Test passes if the <strong>right edge</strong> of an irregular polygon is straight and unbroken.</p>
-
-<div><img src="support/swatch-teal.png" width="24" height="30" alt="Image download support must be enabled" /><br /><img src="support/swatch-teal.png" width="216" height="120" alt="Image download support must be enabled" /><br /><img src="support/swatch-teal.png" width="48" height="60" alt="Image download support must be enabled" /></div>
-
-</body>
-</html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/logical-props-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/logical-props-001.html
deleted file mode 100644
index 599c80e..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/logical-props-001.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>writing-modes and logical props: tr</title>
-<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/">
-<link rel="help" href="https://www.w3.org/TR/css-writing-modes-3/#placement">
-<link rel="match" href="reference/logical-props-001-ref.html"
-<meta name="assert" content="The logical properties on table rows are resolved taking the writing mode of the element into account,
-                            even though the writing mode property does not apply to that element.">
-<style>
-table { border-collapse: collapse; }
-td {
-  padding: 0;
-  height: 100px;
-  width: 100px;
-}
-tr {
-  writing-mode: vertical-rl;
-  border-inline-start: 5px green solid;
-}
-
-.red {
-  position: absolute;
-  width: 100px;
-  height: 5px;
-  background: red;
-  z-index: -1;
-}
-
-</style>
-<body>
-  <p>Test passes if there is a <strong>horizontal green stripe</strong> below and <strong>no red</strong>.
-  <div class=red></div>
-  <table><tbody><tr><td>&nbsp;</td></tr></tbody></table>
-</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/logical-props-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/logical-props-002.html
deleted file mode 100644
index a018e59..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/logical-props-002.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>writing-modes and logical props: tbody</title>
-<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/">
-<link rel="help" href="https://www.w3.org/TR/css-writing-modes-3/#placement">
-<link rel="match" href="reference/logical-props-001-ref.html"
-<meta name="assert" content="The logical properties on table row groups are resolved taking the writing mode of the element into account,
-                            even though the writing mode property does not apply to that element.">
-<style>
-table { border-collapse: collapse; }
-td {
-  padding: 0;
-  height: 100px;
-  width: 100px;
-}
-tbody {
-  writing-mode: vertical-rl;
-  border-inline-start: 5px green solid;
-}
-
-.red {
-  position: absolute;
-  width: 100px;
-  height: 5px;
-  background: red;
-  z-index: -1;
-}
-
-</style>
-<body>
-  <p>Test passes if there is a <strong>horizontal green stripe</strong> below and <strong>no red</strong>.
-  <div class=red></div>
-  <table><tbody><tr><td>&nbsp;</td></tr></tbody></table>
-</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/logical-props-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/logical-props-003.html
deleted file mode 100644
index 64e272d..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/logical-props-003.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>writing-modes and logical props: col</title>
-<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/">
-<link rel="help" href="https://www.w3.org/TR/css-writing-modes-3/#placement">
-<link rel="match" href="reference/logical-props-001-ref.html"
-<meta name="assert" content="The logical properties on table columns are resolved taking the writing mode of the element into account,
-                            even though the writing mode property does not apply to that element.">
-<style>
-table { border-collapse: collapse; }
-td {
-  padding: 0;
-  height: 100px;
-  width: 100px;
-}
-col {
-  writing-mode: vertical-rl;
-  border-inline-start: 5px green solid;
-}
-
-.red {
-  position: absolute;
-  width: 100px;
-  height: 5px;
-  background: red;
-  z-index: -1;
-}
-
-</style>
-<body>
-  <p>Test passes if there is a <strong>horizontal green stripe</strong> below and <strong>no red</strong>.
-  <div class=red></div>
-  <table><col><tbody><tr><td>&nbsp;</td></tr></tbody></table>
-</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/logical-props-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/logical-props-004.html
deleted file mode 100644
index 556794d7..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/logical-props-004.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>writing-modes and logical props: colgroup</title>
-<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/">
-<link rel="help" href="https://www.w3.org/TR/css-writing-modes-3/#placement">
-<link rel="match" href="reference/logical-props-001-ref.html"
-<meta name="assert" content="The logical properties on table column groups are resolved taking the writing mode of the element into account,
-                            even though the writing mode property does not apply to that element.">
-<style>
-table { border-collapse: collapse; }
-td {
-  padding: 0;
-  height: 100px;
-  width: 100px;
-}
-colgroup {
-  writing-mode: vertical-rl;
-  border-inline-start: 5px green solid;
-}
-
-.red {
-  position: absolute;
-  width: 100px;
-  height: 5px;
-  background: red;
-  z-index: -1;
-}
-
-</style>
-<body>
-  <p>Test passes if there is a <strong>horizontal green stripe</strong> below and <strong>no red</strong>.
-  <div class=red></div>
-  <table><colgroup><tbody><tr><td>&nbsp;</td></tr></tbody></table>
-</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/outline-inline-slr-005.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/outline-inline-slr-005.xht
deleted file mode 100644
index 42adb38..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/outline-inline-slr-005.xht
+++ /dev/null
@@ -1,37 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-
- <head>
-
-  <title>CSS Writing Modes Test: outline layout and non-replaced inline in sideways-lr writing-mode</title>
-
-  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" title="7.1. Principles of Layout in Vertical Writing Modes" href="http://www.w3.org/TR/css-writing-modes-4/#vertical-layout" />
-  <link rel="help" title="18.4 Dynamic outlines: the 'outline' property" href="http://www.w3.org/TR/2011/REC-CSS2-20110607/ui.html#dynamic-outlines" />
-
-  <meta content="" name="flags" />
-
-  <style type="text/css"><![CDATA[
-  div
-    {
-      height: 200px;
-      writing-mode: sideways-lr;
-    }
-
-  span
-    {
-      outline: blue solid 2px;
-    }
-  ]]></style>
-
- </head>
-
- <body>
-
-  <p>Test passes if a blue border neatly encloses the words "foo bar" which is inside a latin text rotated 90° counter-clockwise.</p>
-
-  <div>Lorem ipsum dolor sit amet, <span>foo bar</span> consecteteur adipiscing elit urna elit.</div>
-
- </body>
-</html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/outline-inline-srl-004.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/outline-inline-srl-004.xht
deleted file mode 100644
index e9fc32a..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/outline-inline-srl-004.xht
+++ /dev/null
@@ -1,37 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-
- <head>
-
-  <title>CSS Writing Modes Test: outline layout and non-replaced inline and sideways-rl writing-mode</title>
-
-  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" title="7.1. Principles of Layout in Vertical Writing Modes" href="http://www.w3.org/TR/css-writing-modes-4/#vertical-layout" />
-  <link rel="help" title="18.4 Dynamic outlines: the 'outline' property" href="http://www.w3.org/TR/2011/REC-CSS2-20110607/ui.html#dynamic-outlines" />
-
-  <meta content="" name="flags" />
-
-  <style type="text/css"><![CDATA[
-  div
-    {
-      height: 200px;
-      writing-mode: sideways-rl;
-    }
-
-  span
-    {
-      outline: blue solid 2px;
-    }
-  ]]></style>
-
- </head>
-
- <body>
-
-  <p>Test passes if a blue border neatly encloses the words "foo bar" which is inside a latin text rotated 90° clockwise.</p>
-
-  <div>Lorem ipsum dolor sit amet, <span>foo bar</span> consecteteur adipiscing elit urna elit.</div>
-
- </body>
-</html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/page-flow-direction-slr-005.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/page-flow-direction-slr-005.xht
deleted file mode 100644
index 30d045d..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/page-flow-direction-slr-005.xht
+++ /dev/null
@@ -1,40 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-
- <head>
-
-  <title>CSS Writing Modes Test: 'writing-mode: sideways-lr' - default page flow (progression) direction</title>
-
-  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-4/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
-
-  <meta content="image paged" name="flags" />
-  <meta content="This test checks that when 'writing-mode' is set on the root element, then it determines the default page flow (or progression) direction. In this test, the page flow (or progression) direction is left-to-right." name="assert" />
-
-  <style type="text/css" media="print"><![CDATA[
-  html
-    {
-      writing-mode: sideways-lr;
-    }
-
-  body, div
-    {
-      width: 100%;
-  /* width: 100% will force a page-break in sideways-lr writing-mode */
-    }
-  ]]></style>
- </head>
-
- <body>
-
-  <div><img src="support/page-flow-direction-002p1.png" alt="Image download support must be enabled" /></div>
-
-  <div><img src="support/page-flow-direction-002p2.png" alt="Image download support must be enabled" /></div>
-
-  <div><img src="support/page-flow-direction-002p3.png" alt="Image download support must be enabled" /></div>
-
-  <div><img src="support/page-flow-direction-002p4.png" alt="Image download support must be enabled" /></div>
-
- </body>
-</html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/page-flow-direction-srl-004.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/page-flow-direction-srl-004.xht
deleted file mode 100644
index d1d1aa6..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/page-flow-direction-srl-004.xht
+++ /dev/null
@@ -1,40 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-
- <head>
-
-  <title>CSS Writing Modes Test: 'writing-mode: sideways-rl' - default page flow (progression) direction</title>
-
-  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-4/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
-
-  <meta content="image paged" name="flags" />
-  <meta content="This test checks that when 'writing-mode' is set on the root element, then it determines the default page flow (or progression) direction. In this test, the page flow (or progression) direction is right-to-left." name="assert" />
-
-  <style type="text/css" media="print"><![CDATA[
-  html
-    {
-      writing-mode: sideways-rl;
-    }
-
-  body, div
-    {
-      width: 100%;
-  /* width: 100% will force a page-break in sideways-rl writing-mode */
-    }
-  ]]></style>
- </head>
-
- <body>
-
-  <div><img src="support/page-flow-direction-002p1.png" alt="Image download support must be enabled" /></div>
-
-  <div><img src="support/page-flow-direction-002p2.png" alt="Image download support must be enabled" /></div>
-
-  <div><img src="support/page-flow-direction-002p3.png" alt="Image download support must be enabled" /></div>
-
-  <div><img src="support/page-flow-direction-002p4.png" alt="Image download support must be enabled" /></div>
-
- </body>
-</html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-cell-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-cell-001.html
deleted file mode 100644
index 7daa0b14a..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-cell-001.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<!doctype html>
-<html lang="en">
-<meta charset="utf-8">
-<title>CSS Writing Mode test: orthogonal table cell</title>
-<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow">
-<meta assert="The writing mode property applies to table cells: two adjacent cells can have orthogonal writing modes, and the enclosing table must be laid out correctly.">
-<meta flags="ahem">
-<link rel="match" href="reference/table-cell-001-ref.html">
-<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/">
-
-<style>
-table, td {
-  padding: 0;
-  border-spacing: 0;
-  font: 20px/20px ahem;
-}
-td { background: green; }
-#t2 { writing-mode: vertical-rl; }
-
-#red {
-  font: 20px/20px ahem;
-  position: absolute;
-  z-index: -1;
-  background: red;
-  height: 4em;
-  width: 5em;
-}
-
-
-</style>
-
-<p>There should be a <strong>green rectangle</strong> and <strong>no red</strong>.
-
-<div id=red></div>
-
-<table><tbody><tr><td id=t1>&nbsp;&nbsp;&nbsp;&nbsp;</td><td id=t2>&nbsp;&nbsp;&nbsp;&nbsp;</td></tr></tbody></table>
-<!--
-* Each table cell should be 4em in its inline dimention: horizontal for the first, vertical for the second.
-* The first table cell should be 4em tall, to match the height of the second one.
-* The second table cell should be 1em in its block dimention, which is horizontal.
-* Juxtaposing the two that give 4em x 5em.
--->
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-cell-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-cell-002.html
deleted file mode 100644
index 2f180bfc..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-cell-002.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<!doctype html>
-<html lang="en">
-<meta charset="utf-8">
-<title>CSS Writing Mode test: orthogonal table cell</title>
-<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow">
-<meta assert="The writing mode property applies to table cells: max-heights constrains on a vertical table cell (in a horizontal table)
-              ought to have the same effect on the cell as max-width would on horizontal ones.
-              Lines of longer than the max which have break opportunities are expected to wrap.">
-<meta flags="ahem">
-<link rel="match" href="reference/table-cell-002-ref.html">
-<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/">
-
-<style>
-table, td {
-  padding: 0;
-  border-spacing: 0;
-}
-td {
-  max-height: 100px;
-  font: 50px / 50px ahem;
-  color: green;
-  writing-mode: vertical-rl;
-  background: red;
-}
-</style>
-
-<p>There should be a <strong>green square</strong> and <strong>no red</strong>.
-
-<table><tbody><tr><td>xx xx</td></tr></tbody></table>
-
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-column-order-002.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-column-order-002.xht
deleted file mode 100644
index ed6f5f9..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-column-order-002.xht
+++ /dev/null
@@ -1,69 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-
- <head>
-
-  <title>CSS Writing Modes Test: 'direction: rtl' - table columns order and vertical-rl</title>
-
-  <link rel="author" title="Hajime Shiozawa" href="mailto:hajime.shiozawa@gmail.com" />
-  <link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2015-12-21 -->
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#direction" title="2.1 Specifying Directionality: the direction property" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes" />
-  <link rel="match" href="block-flow-direction-001-ref.xht" />
-
-  <meta content="ahem" name="flags" />
-  <meta content="This test checks that a table with 'writing-mode' set to 'vertical-rl' and with 'direction' set to 'rtl' will have its column displayed from bottom (1st column) to top (last column). This test relies on right-to-left directionality applying to characters that are strongly sensitive to directionality. In this test, we use digits [0-9] and non-breaking spaces which are all strongly sensitive to bidi directionality." name="assert" />
-
-  <style type="text/css"><![CDATA[
-  body
-    {
-      color: yellow;
-      font: 20px/1 Ahem;
-    }
-
-  table
-    {
-      background-color: blue;
-      border-spacing: 0em;
-      border: blue solid 1em;
-      height: 7em;
-      direction: rtl;
-      writing-mode: vertical-rl;
-    }
-
-  td
-    {
-      padding-bottom: 0em;
-      padding-left: 1em;
-      padding-right: 0em;
-      padding-top: 0em;
-    }
-
-  td.left-most-cell
-    {
-      padding-left: 0em;
-    }
-  ]]></style>
- </head>
-
- <body>
-
-  <table>
-
-   <!-- The right-most "S" -->
-   <tr><td><!-- bottommost column -->111 2 &nbsp; 3 &nbsp; 4 &nbsp;</td><td>5&nbsp; 6&nbsp; 7&nbsp; 88</td><td><!-- topmost column -->&nbsp;9 &nbsp;0 &nbsp;1 22</td></tr>
-
-   <!-- The left-most "S" -->
-   <tr><td><!-- bottommost column -->333 4 &nbsp; 5 &nbsp; 6 &nbsp;</td><td>7&nbsp; 8&nbsp; 9&nbsp; 00</td><td><!-- topmost column -->&nbsp;1 &nbsp;2 &nbsp;3 44</td></tr>
-
-   <!-- The "A" -->
-   <tr><td><!-- bottommost column -->555 &nbsp;&nbsp; &nbsp;&nbsp; 666</td><td>77 8&nbsp; 9&nbsp; 00</td><td><!-- topmost column -->11 &nbsp;2 &nbsp;3 44</td></tr>
-
-   <!-- The "P" -->
-   <tr><td class="left-most-cell"><!-- bottommost column -->&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 555</td><td class="left-most-cell">66 7&nbsp; 8&nbsp; 99</td><td class="left-most-cell"><!-- topmost column -->00 &nbsp;1 &nbsp;2 33</td></tr>
-
-  </table>
-
- </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-column-order-003.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-column-order-003.xht
deleted file mode 100644
index d044090..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-column-order-003.xht
+++ /dev/null
@@ -1,69 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-
- <head>
-
-  <title>CSS Writing Modes Test: 'direction: rtl' - table columns order and vertical-lr</title>
-
-  <link rel="author" title="Hajime Shiozawa" href="mailto:hajime.shiozawa@gmail.com" />
-  <link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2015-12-21 -->
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#direction" title="2.1 Specifying Directionality: the direction property" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes" />
-  <link rel="match" href="block-flow-direction-001-ref.xht" />
-
-  <meta content="ahem" name="flags" />
-  <meta content="This test checks that a table with 'writing-mode' set to 'vertical-lr' and with 'direction' set to 'rtl' will have its column displayed from bottom (1st column) to top (last column). This test relies on right-to-left directionality applying to characters that are strongly sensitive to directionality. In this test, we use digits [0-9] and non-breaking spaces which are all strongly sensitive to bidi directionality." name="assert" />
-
-  <style type="text/css"><![CDATA[
-  body
-    {
-      color: yellow;
-      font: 20px/1 Ahem;
-    }
-
-  table
-    {
-      background-color: blue;
-      border-spacing: 0em;
-      border: blue solid 1em;
-      height: 7em;
-      direction: rtl;
-      writing-mode: vertical-lr;
-    }
-
-  td
-    {
-      padding-bottom: 0em;
-      padding-left: 1em;
-      padding-right: 0em;
-      padding-top: 0em;
-    }
-
-  td.left-most-cell
-    {
-      padding-left: 0em;
-    }
-  ]]></style>
- </head>
-
- <body>
-
-  <table>
-
-   <!-- The "P" -->
-   <tr><td class="left-most-cell"><!-- bottommost column -->111 &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;</td><td class="left-most-cell">22 3&nbsp; 4&nbsp; 55</td><td class="left-most-cell"><!-- topmost column -->66 &nbsp;7 &nbsp;8 99</td></tr>
-
-   <!-- The "A" -->
-   <tr><td><!-- bottommost column -->000 &nbsp;&nbsp; &nbsp;&nbsp; 111</td><td>22 3&nbsp; 4&nbsp; 55</td><td><!-- topmost column -->66 &nbsp;7 &nbsp;8 99</td></tr>
-
-   <!-- The left-most "S" -->
-   <tr><td><!-- bottommost column -->0 &nbsp; 1 &nbsp; 2 &nbsp; 333</td><td>44 5&nbsp; 6&nbsp; 7&nbsp;</td><td><!-- topmost column -->88 &nbsp;9 &nbsp;0 &nbsp;1</td></tr>
-
-   <!-- The right-most "S" -->
-   <tr><td><!-- bottommost column -->2 &nbsp; 3 &nbsp; 4 &nbsp; 555</td><td>66 7&nbsp; 8&nbsp; 9&nbsp;</td><td><!-- topmost column -->00 &nbsp;1 &nbsp;2 &nbsp;3</td></tr>
-
-  </table>
-
- </body>
-</html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-column-order-004.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-column-order-004.xht
deleted file mode 100644
index 095dc463..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-column-order-004.xht
+++ /dev/null
@@ -1,69 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-
- <head>
-
-  <title>CSS Writing Modes Test: 'direction: rtl' - table columns order and vertical-rl</title>
-
-  <link rel="author" title="Hajime Shiozawa" href="mailto:hajime.shiozawa@gmail.com" />
-  <link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2015-12-21 -->
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#direction" title="2.1 Specifying Directionality: the direction property" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes" />
-  <link rel="match" href="block-flow-direction-001-ref.xht" />
-
-  <meta content="ahem" name="flags" />
-  <meta content="This test checks that colspanned cells in a table with 'direction' set to 'rtl' are handled according to a bottom-to-top column direction. This test relies on right-to-left directionality applying to characters that are strongly sensitive to directionality. In this test, we use digits [0-9] and non-breaking spaces which are all strongly sensitive to bidi directionality." name="assert" />
-
-  <style type="text/css"><![CDATA[
-  body
-    {
-      color: yellow;
-      font: 20px/1 Ahem;
-    }
-
-  table
-    {
-      background-color: blue;
-      border-spacing: 0em;
-      border: blue solid 1em;
-      height: 7em;
-      direction: rtl;
-      writing-mode: vertical-rl;
-    }
-
-  td
-    {
-      padding-bottom: 0em;
-      padding-left: 1em;
-      padding-right: 0em;
-      padding-top: 0em;
-    }
-
-  td.left-most-cell
-    {
-      padding-left: 0em;
-    }
-  ]]></style>
- </head>
-
- <body>
-
-  <table>
-
-   <!-- The right-most "S" -->
-   <tr><td><!-- bottommost column -->111 2 &nbsp; 3 &nbsp; 4 &nbsp;</td><td>5&nbsp; 6&nbsp; 7&nbsp; 88</td><td><!-- topmost column -->&nbsp;9 &nbsp;0 &nbsp;1 22</td></tr>
-
-   <!-- The left-most "S" -->
-   <tr><td colspan="2"><!-- bottommost column -->3333&nbsp; 4 &nbsp;5&nbsp; 6 &nbsp;7&nbsp; 8 &nbsp;99</td><td><!-- topmost column -->&nbsp;1 &nbsp;2 &nbsp;3 44</td></tr>
-
-   <!-- The "A" -->
-   <tr><td><!-- bottommost column -->555 &nbsp;&nbsp; &nbsp;&nbsp; 666</td><td colspan="2"><!-- topmost column -->7777 8&nbsp; 9 0&nbsp; 1 2222</td></tr>
-
-   <!-- The "P" -->
-   <tr><td class="left-most-cell"><!-- bottommost column -->&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 333</td><td class="left-most-cell">44 5&nbsp; 6&nbsp; 77</td><td class="left-most-cell"><!-- topmost column -->88 &nbsp;9 &nbsp;0 11</td></tr>
-
-  </table>
-
- </body>
-</html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-column-order-005.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-column-order-005.xht
deleted file mode 100644
index b769982..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-column-order-005.xht
+++ /dev/null
@@ -1,69 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-
- <head>
-
-  <title>CSS Writing Modes Test: 'direction: rtl' - table columns order and vertical-lr</title>
-
-  <link rel="author" title="Hajime Shiozawa" href="mailto:hajime.shiozawa@gmail.com" />
-  <link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2015-12-21 -->
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#direction" title="2.1 Specifying Directionality: the direction property" />
-  <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes" />
-  <link rel="match" href="block-flow-direction-001-ref.xht" />
-
-  <meta content="ahem" name="flags" />
-  <meta content="This test checks that colspanned cells in a table with 'direction' set to 'rtl' are handled according to a bottom-to-top column direction. This test relies on right-to-left directionality applying to characters that are strongly sensitive to directionality. In this test, we use digits [0-9] and non-breaking spaces which are all strongly sensitive to bidi directionality." name="assert" />
-
-  <style type="text/css"><![CDATA[
-  body
-    {
-      color: yellow;
-      font: 20px/1 Ahem;
-    }
-
-  table
-    {
-      background-color: blue;
-      border-spacing: 0em;
-      border: blue solid 1em;
-      height: 7em;
-      direction: rtl;
-      writing-mode: vertical-lr;
-    }
-
-  td
-    {
-      padding-bottom: 0em;
-      padding-left: 1em;
-      padding-right: 0em;
-      padding-top: 0em;
-    }
-
-  td.left-most-cell
-    {
-      padding-left: 0em;
-    }
-  ]]></style>
- </head>
-
- <body>
-
-  <table>
-
-   <!-- The "P" -->
-   <tr><td class="left-most-cell"><!-- bottommost column -->111 &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;</td><td class="left-most-cell">22 3&nbsp; 4&nbsp; 55</td><td class="left-most-cell"><!-- topmost column -->66 &nbsp;7 &nbsp;8 99</td></tr>
-
-   <!-- The "A" -->
-   <tr><td colspan="2"><!-- bottommost column -->00000 &nbsp;&nbsp;&nbsp;1&nbsp; &nbsp;&nbsp;&nbsp;2&nbsp; 33333</td><td><!-- topmost column -->44 &nbsp;5 &nbsp;6 77</td></tr>
-
-   <!-- The left-most "S" -->
-   <tr><td><!-- bottommost column -->8 &nbsp; 9 &nbsp; 0 &nbsp; 111</td><td colspan="2"><!-- topmost column -->2222 3 &nbsp;4 5 &nbsp;6 7 &nbsp;8</td></tr>
-
-   <!-- The right-most "S" -->
-   <tr><td><!-- bottommost column -->9 &nbsp; 0 &nbsp; 1 &nbsp; 222</td><td>33 4&nbsp; 5&nbsp; 6&nbsp;</td><td><!-- topmost column -->77 &nbsp;8 &nbsp;9 &nbsp;0</td></tr>
-
-  </table>
-
- </body>
-</html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-001-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-001-ref.html
deleted file mode 100644
index 41aa129..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-001-ref.html
+++ /dev/null
@@ -1,93 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>CSS Reference</title>
-<link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact">
-<link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2016-01-15 -->
-
-<style>
-  table {
-    border-spacing: 0;
-    margin: 1em;
-  }
-  td {
-    width: 1em;
-    height: 1em;
-    border: solid gray;
-  }
-
-  .navy { background: navy}
-  .blue { background: blue }
-  .aqua { background: aqua }
-  .teal { background: teal }
-  .purp { background: purple }
-  .pink { background: fuchsia }
-  .yllw { background: yellow }
-  .orng { background: orange }
-  caption { background: green; }
-</style>
-
-<p>Test passes if the following three tables look identical.
-
-<table>
-  <caption></caption>
-  <tr>
-    <td rowspan=2>
-    <td class="orng">
-    <td colspan=3>
-    <td class="navy">
-  <tr>
-    <td rowspan=3>
-    <td class="yllw">
-    <td class="pink">
-    <td rowspan=2>
-    <td class="blue">
-  <tr>
-    <td class="aqua">
-    <td rowspan=2 colspan=2>
-    <td rowspan=2>
-  <tr>
-    <td class="teal">
-    <td class="purp">
-</table>
-
-<table>
-  <tr>
-    <td rowspan=2>
-    <td class="orng">
-    <td colspan=3>
-    <td class="navy">
-  <tr>
-    <td rowspan=3>
-    <td class="yllw">
-    <td class="pink">
-    <td rowspan=2>
-    <td class="blue">
-  <tr>
-    <td class="aqua">
-    <td rowspan=2 colspan=2>
-    <td rowspan=2>
-  <tr>
-    <td class="teal">
-    <td class="purp">
-</table>
-
-<table>
-  <tr>
-    <td rowspan=2>
-    <td class="orng">
-    <td colspan=3>
-    <td class="navy">
-  <tr>
-    <td rowspan=3>
-    <td class="yllw">
-    <td class="pink">
-    <td rowspan=2>
-    <td class="blue">
-  <tr>
-    <td class="aqua">
-    <td rowspan=2 colspan=2>
-    <td rowspan=2>
-  <tr>
-    <td class="teal">
-    <td class="purp">
-</table>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-002-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-002-ref.html
deleted file mode 100644
index 37445460..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-002-ref.html
+++ /dev/null
@@ -1,68 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>CSS Reference</title>
-<link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact">
-<link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2016-01-15 -->
-
-<style>
-  table {
-    border-spacing: 0;
-    border: solid gray;
-    margin: 1em;
-    float: left;
-  }
-  td {
-    width: 1em;
-    height: 1em;
-  }
-
-  .navy { background: navy}
-  .blue { background: blue }
-  .aqua { background: aqua }
-  .teal { background: teal }
-</style>
-
-<p>Test passes if the following patterned boxes all look identical.
-
-<table class="reference">
-  <tr><td class="navy">
-  <tr><td class="navy">
-  <tr><td class="blue">
-  <tr><td class="aqua">
-  <tr><td class="aqua">
-</table>
-
-<table class="reference">
-  <tr><td class="navy">
-  <tr><td class="navy">
-  <tr><td class="blue">
-  <tr><td class="aqua">
-  <tr><td class="aqua">
-</table>
-
-
-<table class="reference">
-  <tr><td class="navy">
-  <tr><td class="navy">
-  <tr><td class="blue">
-  <tr><td class="aqua">
-  <tr><td class="aqua">
-</table>
-
-
-<table class="reference">
-  <tr><td class="navy">
-  <tr><td class="navy">
-  <tr><td class="blue">
-  <tr><td class="aqua">
-  <tr><td class="aqua">
-</table>
-
-
-<table class="reference">
-  <tr><td class="navy">
-  <tr><td class="navy">
-  <tr><td class="blue">
-  <tr><td class="aqua">
-  <tr><td class="aqua">
-</table>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-slr-001-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-slr-001-ref.html
deleted file mode 100644
index 0f772a3e..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-slr-001-ref.html
+++ /dev/null
@@ -1,96 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>CSS Reference</title>
-<link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
-<link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact">
-
-<style>
-  table {
-    border-spacing: 0;
-    margin: 1em;
-  }
-  td {
-    width: 1em;
-    height: 1em;
-    border: solid gray;
-  }
-
-  .navy { background: navy}
-  .blue { background: blue }
-  .aqua { background: aqua }
-  .teal { background: teal }
-  .purp { background: purple }
-  .pink { background: fuchsia }
-  .yllw { background: yellow }
-  .orng { background: orange }
-  caption { background: green; }
-</style>
-
-<p>Test passes if the following three tables look identical.
-
-<table>
-  <caption></caption>
-  <tr>
-    <td class="teal">
-    <td rowspan="3">
-    <td colspan="2" rowspan="2">
-    <td class="purp">
-    <td rowspan="2">
-  <tr>
-    <td class="aqua">
-    <td rowspan="2">
-  <tr>
-    <td rowspan="2">
-    <td class="yllw">
-    <td class="pink">
-    <td class="blue">
-
-  <tr>
-    <td class="orng">
-    <td colspan="3">
-    <td class="navy">
-</table>
-
-<table>
-  <tr>
-    <td class="teal">
-    <td rowspan="3">
-    <td colspan="2" rowspan="2">
-    <td class="purp">
-    <td rowspan="2">
-  <tr>
-    <td class="aqua">
-    <td rowspan="2">
-  <tr>
-    <td rowspan="2">
-    <td class="yllw">
-    <td class="pink">
-    <td class="blue">
-
-  <tr>
-    <td class="orng">
-    <td colspan="3">
-    <td class="navy">
-</table>
-
-<table>
-  <tr>
-    <td class="teal">
-    <td rowspan="3">
-    <td colspan="2" rowspan="2">
-    <td class="purp">
-    <td rowspan="2">
-  <tr>
-    <td class="aqua">
-    <td rowspan="2">
-  <tr>
-    <td rowspan="2">
-    <td class="yllw">
-    <td class="pink">
-    <td class="blue">
-
-  <tr>
-    <td class="orng">
-    <td colspan="3">
-    <td class="navy">
-</table>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-vlr-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-vlr-001.html
deleted file mode 100644
index 6b9d3c1..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-vlr-001.html
+++ /dev/null
@@ -1,135 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>CSS Test: vertical-lr Table Row/Rowgroup/Cell Ordering</title>
-<link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact">
-<link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/"> <!-- 2016-01-15 -->
-<link rel="match" href="table-progression-001-ref.html">
-<meta name="assert" content="This test checks that vertical-lr tables order rows/rowgroups left to right and cells top-to-bottom (LTR) or bottom-to-top (RTL) per 'direction'. This test also checks that 'writing-mode' and 'direction' do not apply to table rows and row groups.">
-<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the 'writing-mode' property">
-<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#direction" title="2.1 Specifying Directionality: the 'direction' property">
-
-<style>
-  .test {
-    writing-mode: vertical-lr;
-  }
-  [dir=rtl] {
-    direction: rtl;
-  }
-
-  table {
-    border-spacing: 0;
-    margin: 1em;
-  }
-  td {
-    width: 1em;
-    height: 1em;
-    border: solid gray;
-  }
-
-  .navy { background: navy}
-  .blue { background: blue }
-  .aqua { background: aqua }
-  .teal { background: teal }
-  .purp { background: purple }
-  .pink { background: fuchsia }
-  .yllw { background: yellow }
-  .orng { background: orange }
-
-
-  /* These rules must have no effect. */
-  .test thead,
-  .test tfoot,
-  .test tbody,
-  .test tr,
-  .test td {
-    writing-mode: horizontal-tb; /* For UAs not supporting vertical-rl */
-    writing-mode: vertical-rl;
-    direction: rtl;
-  }
-  .test[dir=rtl] thead,
-  .test[dir=rtl] tfoot,
-  .test[dir=rtl] tbody,
-  .test[dir=rtl] tr,
-  .test[dir=rtl] td {
-    direction: ltr;
-  }
-</style>
-
-<p>Test passes if the following three tables look identical.
-
-<table class="test">
-  <thead>
-    <tr>
-      <td colspan=2>
-      <td class="aqua">
-      <td class="teal">
-  <tfoot>
-    <tr>
-      <td class="navy">
-      <td class="blue">
-      <td colspan=2>
-  <tbody>
-    <tr>
-      <td class="orng">
-      <td colspan=3>
-  <tbody>
-    <tr>
-      <td rowspan=3>
-      <td class="yllw">
-      <td rowspan=2 colspan=2>
-    <tr>
-      <td class="pink">
-    <tr>
-      <td colspan=2>
-      <td class="purp">
-</table>
-
-<table dir=rtl class="test">
-  <thead>
-    <tr>
-      <td class="teal">
-      <td class="aqua">
-      <td colspan=2>
-  <tfoot>
-    <tr>
-      <td colspan=2>
-      <td class="blue">
-      <td class="navy">
-  <tbody>
-    <tr>
-      <td colspan=3>
-      <td class="orng">
-  <tbody>
-    <tr>
-      <td rowspan=2 colspan=2>
-      <td class="yllw">
-      <td rowspan=3>
-    <tr>
-      <td class="pink">
-    <tr>
-      <td class="purp">
-      <td colspan=2>
-</table>
-
-
-<table class="reference">
-  <tr>
-    <td rowspan=2>
-    <td class="orng">
-    <td colspan=3>
-    <td class="navy">
-
-  <tr>
-    <td rowspan=3>
-    <td class="yllw">
-    <td class="pink">
-    <td rowspan=2>
-    <td class="blue">
-  <tr>
-    <td class="aqua">
-    <td rowspan=2 colspan=2>
-    <td rowspan=2>
-  <tr>
-    <td class="teal">
-    <td class="purp">
-</table>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-vlr-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-vlr-002.html
deleted file mode 100644
index a3668178..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-vlr-002.html
+++ /dev/null
@@ -1,87 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>CSS Test: vertical-lr Table Column/Colgroup Ordering</title>
-<link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact">
-<link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/"> <!-- 2016-01-15 -->
-<link rel="match" href="table-progression-002-ref.html">
-<meta name="assert" content="This test checks that vertical-lr tables order columns top-to-bottom (LTR) or bottom-to-top (RTL) per the table's 'direction'. This test also checks that 'writing-mode' and 'direction' do not apply to table columns and column groups.">
-<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the 'writing-mode' property">
-<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#direction"z>
-
-<style>
-  .test {
-    writing-mode: vertical-lr;
-  }
-  [dir=rtl] {
-    direction: rtl;
-  }
-
-
-  table {
-    border-spacing: 0;
-    border: solid gray;
-    margin: 1em;
-    float: left;
-  }
-  td {
-    width: 1em;
-    height: 1em;
-  }
-
-  .navy { background: navy}
-  .blue { background: blue }
-  .aqua { background: aqua }
-  .teal { background: teal }
-
-  /* These declarations must have no effect. */
-  .test col,
-  .test colgroup {
-    writing-mode: horizontal-tb;
-    writing-mode: vertical-rl;
-    direction: rtl;
-  }
-  .test[dir=rtl] col,
-  .test[dir=rtl] colgroup {
-    direction: ltr;
-  }
-</style>
-
-<p>Test passes if the following patterned boxes all look identical.
-
-<table class="test">
-  <col span=2 class="navy">
-  <col class="blue">
-  <col span=2 class="aqua">
-  <tr><td><td><td><td><td>
-</table>
-<table class="test">
-  <colgroup span=2 class="navy"></colgroup>
-  <colgroup>
-    <col class="blue">
-    <col span=2 class="aqua">
-  </colgroup>
-  <tr><td><td><td><td><td>
-</table>
-
-<table dir=rtl class="test">
-  <col span=2 class="aqua">
-  <col class="blue">
-  <col span=2 class="navy">
-  <tr><td><td><td><td><td>
-</table>
-<table dir=rtl class="test">
-  <colgroup span=2 class="aqua"></colgroup>
-  <colgroup>
-    <col class="blue">
-    <col span=2 class="navy">
-  </colgroup>
-  <tr><td><td><td><td><td>
-</table>
-
-<table class="reference">
-  <tr><td class="navy">
-  <tr><td class="navy">
-  <tr><td class="blue">
-  <tr><td class="aqua">
-  <tr><td class="aqua">
-</table>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-vlr-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-vlr-003.html
deleted file mode 100644
index def5c3c..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-vlr-003.html
+++ /dev/null
@@ -1,116 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>CSS Test: vertical-lr upright orientation Table Row/Rowgroup/Cell Ordering</title>
-<link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact">
-<link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/"> <!-- 2016-01-19 -->
-<link rel="match" href="table-progression-001-ref.html">
-<meta name="assert" content="This test checks that vertical-lr tables, whether LTR or RTL, order rows/rowgroups left to right and cells top-to-bottom when text-orientation is upright.">
-<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the 'writing-mode' property">
-<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#direction" title="2.1 Specifying Directionality: the 'direction' property">
-<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#text-orientation" title="5.1 Orienting Text: the 'text-orientation' property">
-
-<style>
-  .test {
-    writing-mode: vertical-lr;
-    text-orientation: upright;
-  }
-  [dir=rtl] {
-    direction: rtl;
-  }
-
-  table {
-    border-spacing: 0;
-    margin: 1em;
-  }
-  td {
-    width: 1em;
-    height: 1em;
-    border: solid gray;
-  }
-
-  .navy { background: navy}
-  .blue { background: blue }
-  .aqua { background: aqua }
-  .teal { background: teal }
-  .purp { background: purple }
-  .pink { background: fuchsia }
-  .yllw { background: yellow }
-  .orng { background: orange }
-</style>
-
-<p>Test passes if the following three tables look identical.
-
-<table class="test">
-  <thead>
-    <tr>
-      <td colspan=2>
-      <td class="aqua">
-      <td class="teal">
-  <tfoot>
-    <tr>
-      <td class="navy">
-      <td class="blue">
-      <td colspan=2>
-  <tbody>
-    <tr>
-      <td class="orng">
-      <td colspan=3>
-  <tbody>
-    <tr>
-      <td rowspan=3>
-      <td class="yllw">
-      <td rowspan=2 colspan=2>
-    <tr>
-      <td class="pink">
-    <tr>
-      <td colspan=2>
-      <td class="purp">
-</table>
-
-<table class="test" dir=rtl>
-  <thead>
-    <tr>
-      <td colspan=2>
-      <td class="aqua">
-      <td class="teal">
-  <tfoot>
-    <tr>
-      <td class="navy">
-      <td class="blue">
-      <td colspan=2>
-  <tbody>
-    <tr>
-      <td class="orng">
-      <td colspan=3>
-  <tbody>
-    <tr>
-      <td rowspan=3>
-      <td class="yllw">
-      <td rowspan=2 colspan=2>
-    <tr>
-      <td class="pink">
-    <tr>
-      <td colspan=2>
-      <td class="purp">
-</table>
-
-<table class="reference">
-  <tr>
-    <td rowspan=2>
-    <td class="orng">
-    <td colspan="3">
-    <td class="navy">
-  <tr>
-    <td rowspan="3">
-    <td class="yllw">
-    <td class="pink">
-    <td rowspan="2">
-    <td class="blue">
-  <tr>
-    <td class="aqua">
-    <td rowspan=2 colspan=2>
-    <td rowspan=2>
-  <tr>
-    <td class="teal">
-    <td class="purp">
-</table>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-vlr-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-vlr-004.html
deleted file mode 100644
index dd444e3..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-vlr-004.html
+++ /dev/null
@@ -1,76 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>CSS Test: vertical-lr upright orientation Table Column/Colgroup Ordering</title>
-<link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact">
-<link rel="match" href="table-progression-002-ref.html">
-<meta name="assert" content="This test checks that vertical-lr tables, whether LTR or RTL, order columns top-to-bottom when text-orientation is upright.">
-<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the 'writing-mode' property">
-<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#direction"z>
-<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#text-orientation" title="5.1 Orienting Text: the 'text-orientation' property">
-
-<style>
-  .test {
-    writing-mode: vertical-lr;
-    text-orientation: upright;
-  }
-  [dir=rtl] {
-    direction: rtl;
-  }
-
-
-  table {
-    border-spacing: 0;
-    border: solid gray;
-    margin: 1em;
-    float: left;
-  }
-  td {
-    width: 1em;
-    height: 1em;
-  }
-
-  .navy { background: navy}
-  .blue { background: blue }
-  .aqua { background: aqua }
-  .teal { background: teal }
-</style>
-
-<p>Test passes if the following patterned boxes all look identical.
-
-<table class="test">
-  <col span=2 class="navy">
-  <col class="blue">
-  <col span=2 class="aqua">
-  <tr><td><td><td><td><td>
-</table>
-<table class="test">
-  <colgroup span=2 class="navy"></colgroup>
-  <colgroup>
-    <col class="blue">
-    <col span=2 class="aqua">
-  </colgroup>
-  <tr><td><td><td><td><td>
-</table>
-
-<table dir=rtl class="test">
-  <col span=2 class="navy">
-  <col class="blue">
-  <col span=2 class="aqua">
-  <tr><td><td><td><td><td>
-</table>
-<table dir=rtl class="test">
-  <colgroup span=2 class="navy"></colgroup>
-  <colgroup>
-    <col class="blue">
-    <col span=2 class="aqua">
-  </colgroup>
-  <tr><td><td><td><td><td>
-</table>
-
-<table class="reference">
-  <tr><td class="navy">
-  <tr><td class="navy">
-  <tr><td class="blue">
-  <tr><td class="aqua">
-  <tr><td class="aqua">
-</table>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-vrl-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-vrl-001.html
deleted file mode 100644
index c5c30900..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-vrl-001.html
+++ /dev/null
@@ -1,132 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>CSS Test: vertical-rl Table Row/Rowgroup/Cell Ordering</title>
-<link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact">
-<link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/"> <!-- 2016-01-15 -->
-<link rel="match" href="table-progression-001-ref.html">
-<meta name="assert" content="This test checks that vertical-rl tables order rows/rowgroups right to left and cells top-to-bottom (LTR) or bottom-to-top (RTL) per 'direction'. This test also checks that 'writing-mode' and 'direction' do not apply to table rows and row groups.">
-<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the 'writing-mode' property">
-<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#direction" title="2.1 Specifying Directionality: the 'direction' property">
-
-<style>
-  .test {
-    writing-mode: vertical-rl;
-  }
-  [dir=rtl] {
-    direction: rtl;
-  }
-
-  table {
-    border-spacing: 0;
-    margin: 1em;
-  }
-  td {
-    width: 1em;
-    height: 1em;
-    border: solid gray;
-  }
-
-  .navy { background: navy}
-  .blue { background: blue }
-  .aqua { background: aqua }
-  .teal { background: teal }
-  .purp { background: purple }
-  .pink { background: fuchsia }
-  .yllw { background: yellow }
-  .orng { background: orange }
-
-  /* These rules must have no effect. */
-  .test thead,
-  .test tfoot,
-  .test tbody,
-  .test tr,
-  .test td {
-    writing-mode: horizontal-tb; /* For UAs not supporting vertical-rl */
-    writing-mode: vertical-lr;
-    direction: rtl;
-  }
-  .test[dir=rtl] thead,
-  .test[dir=rtl] tfoot,
-  .test[dir=rtl] tbody,
-  .test[dir=rtl] tr,
-  .test[dir=rtl] td {
-    direction: ltr;
-  }
-</style>
-
-<p>Test passes if the following three tables look identical.
-
-<table class="test">
-  <thead>
-    <tr>
-      <td class="navy">
-      <td class="blue">
-      <td colspan=2>
-  <tfoot>
-    <tr>
-      <td colspan=2>
-      <td class="aqua">
-      <td class="teal">
-  <tbody>
-    <tr>
-      <td rowspan=3>
-      <td colspan=2>
-      <td class="purp">
-    <tr>
-      <td class="pink">
-      <td rowspan=2 colspan=2>
-    <tr>
-      <td class="yllw">
-  <tbody>
-    <tr>
-      <td class="orng">
-      <td colspan=3>
-</table>
-
-<table dir=rtl class="test">
-  <thead>
-    <tr>
-      <td colspan=2>
-      <td class="blue">
-      <td class="navy">
-  <tfoot>
-    <tr>
-      <td class="teal">
-      <td class="aqua">
-      <td colspan=2>
-  <tbody>
-    <tr>
-      <td class="purp">
-      <td colspan=2>
-      <td rowspan=3>
-    <tr>
-      <td rowspan=2 colspan=2>
-      <td class="pink">
-    <tr>
-      <td class="yllw">
-  <tbody>
-    <tr>
-      <td colspan=3>
-      <td class="orng">
-</table>
-
-<table class="reference">
-  <tr>
-    <td rowspan=2>
-    <td class="orng">
-    <td colspan="3">
-    <td class="navy">
-  <tr>
-    <td rowspan="3">
-    <td class="yllw">
-    <td class="pink">
-    <td rowspan="2">
-    <td class="blue">
-  <tr>
-    <td class="aqua">
-    <td rowspan=2 colspan=2>
-    <td rowspan=2>
-  <tr>
-    <td class="teal">
-    <td class="purp">
-</table>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-vrl-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-vrl-002.html
deleted file mode 100644
index 99fe815..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-vrl-002.html
+++ /dev/null
@@ -1,86 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>CSS Test: vertical-rl Table Column/Colgroup Ordering</title>
-<link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact">
-<link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/"> <!-- 2016-01-15 -->
-<link rel="match" href="table-progression-002-ref.html">
-<meta name="assert" content="This test checks that vertical-rl tables order columns top-to-bottom (LTR) or bottom-to-top (RTL) per the table's 'direction'. This test also checks that 'writing-mode' and 'direction' do not apply to table columns and column groups.">
-<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the 'writing-mode' property">
-<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#direction" title="2.1 Specifying Directionality: the 'direction' property">
-
-<style>
-  .test {
-    writing-mode: vertical-rl;
-  }
-  [dir=rtl] {
-    direction: rtl;
-  }
-
-  table {
-    border-spacing: 0;
-    border: solid gray;
-    margin: 1em;
-    float: left;
-  }
-  td {
-    width: 1em;
-    height: 1em;
-  }
-
-  .navy { background: navy}
-  .blue { background: blue }
-  .aqua { background: aqua }
-  .teal { background: teal }
-
-  /* These declarations must have no effect. */
-  .test col,
-  .test colgroup {
-    writing-mode: horizontal-tb;
-    writing-mode: vertical-lr;
-    direction: rtl;
-  }
-  .test[dir=rtl] col,
-  .test[dir=rtl] colgroup {
-    direction: ltr;
-  }
-</style>
-
-<p>Test passes if the following patterned boxes all look identical.
-
-<table class="test">
-  <col span=2 class="navy">
-  <col class="blue">
-  <col span=2 class="aqua">
-  <tr><td><td><td><td><td>
-</table>
-<table class="test">
-  <colgroup span=2 class="navy"></colgroup>
-  <colgroup>
-    <col class="blue">
-    <col span=2 class="aqua">
-  </colgroup>
-  <tr><td><td><td><td><td>
-</table>
-
-<table dir=rtl class="test">
-  <col span=2 class="aqua">
-  <col class="blue">
-  <col span=2 class="navy">
-  <tr><td><td><td><td><td>
-</table>
-<table dir=rtl class="test">
-  <colgroup span=2 class="aqua"></colgroup>
-  <colgroup>
-    <col class="blue">
-    <col span=2 class="navy">
-  </colgroup>
-  <tr><td><td><td><td><td>
-</table>
-
-<table class="reference">
-  <tr><td class="navy">
-  <tr><td class="navy">
-  <tr><td class="blue">
-  <tr><td class="aqua">
-  <tr><td class="aqua">
-</table>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-vrl-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-vrl-003.html
deleted file mode 100644
index 3116f30..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-vrl-003.html
+++ /dev/null
@@ -1,116 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>CSS Test: vertical-rl upright orientation Table Row/Rowgroup/Cell Ordering</title>
-<link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact">
-<link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/"> <!-- 2016-01-19 -->
-<link rel="match" href="table-progression-001-ref.html">
-<meta name="assert" content="This test checks that vertical-rl tables, whether LTR or RTL, order rows/rowgroups right to left and cells top-to-bottom when text-orientation is upright.">
-<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the 'writing-mode' property">
-<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#direction" title="2.1 Specifying Directionality: the 'direction' property">
-<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#text-orientation" title="5.1 Orienting Text: the 'text-orientation' property">
-
-<style>
-  .test {
-    writing-mode: vertical-rl;
-    text-orientation: upright;
-  }
-  [dir=rtl] {
-    direction: rtl;
-  }
-
-  table {
-    border-spacing: 0;
-    margin: 1em;
-  }
-  td {
-    width: 1em;
-    height: 1em;
-    border: solid gray;
-  }
-
-  .navy { background: navy}
-  .blue { background: blue }
-  .aqua { background: aqua }
-  .teal { background: teal }
-  .purp { background: purple }
-  .pink { background: fuchsia }
-  .yllw { background: yellow }
-  .orng { background: orange }
-</style>
-
-<p>Test passes if the following three tables look identical.
-
-<table class="test">
-  <thead>
-    <tr>
-      <td class="navy">
-      <td class="blue">
-      <td colspan=2>
-  <tfoot>
-    <tr>
-      <td colspan=2>
-      <td class="aqua">
-      <td class="teal">
-  <tbody>
-    <tr>
-      <td rowspan=3>
-      <td colspan=2>
-      <td class="purp">
-    <tr>
-      <td class="pink">
-      <td rowspan=2 colspan=2>
-    <tr>
-      <td class="yllw">
-  <tbody>
-    <tr>
-      <td class="orng">
-      <td colspan=3>
-</table>
-
-<table class="test" dir=rtl>
-  <thead>
-    <tr>
-      <td class="navy">
-      <td class="blue">
-      <td colspan=2>
-  <tfoot>
-    <tr>
-      <td colspan=2>
-      <td class="aqua">
-      <td class="teal">
-  <tbody>
-    <tr>
-      <td rowspan=3>
-      <td colspan=2>
-      <td class="purp">
-    <tr>
-      <td class="pink">
-      <td rowspan=2 colspan=2>
-    <tr>
-      <td class="yllw">
-  <tbody>
-    <tr>
-      <td class="orng">
-      <td colspan=3>
-</table>
-
-<table class="reference">
-  <tr>
-    <td rowspan=2>
-    <td class="orng">
-    <td colspan="3">
-    <td class="navy">
-  <tr>
-    <td rowspan="3">
-    <td class="yllw">
-    <td class="pink">
-    <td rowspan="2">
-    <td class="blue">
-  <tr>
-    <td class="aqua">
-    <td rowspan=2 colspan=2>
-    <td rowspan=2>
-  <tr>
-    <td class="teal">
-    <td class="purp">
-</table>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-vrl-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-vrl-004.html
deleted file mode 100644
index bcafef13..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/table-progression-vrl-004.html
+++ /dev/null
@@ -1,75 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>CSS Test: vertical-rl upright orientation Table Column/Colgroup Ordering</title>
-<link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact">
-<link rel="match" href="table-progression-002-ref.html">
-<meta name="assert" content="This test checks that vertical-rl tables, whether LTR or RTL, order columns top-to-bottom when text-orientation is upright.">
-<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the 'writing-mode' property">
-<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#direction" title="2.1 Specifying Directionality: the 'direction' property">
-<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#text-orientation" title="5.1 Orienting Text: the 'text-orientation' property">
-
-<style>
-  .test {
-    writing-mode: vertical-rl;
-    text-orientation: upright;
-  }
-  [dir=rtl] {
-    direction: rtl;
-  }
-
-  table {
-    border-spacing: 0;
-    border: solid gray;
-    margin: 1em;
-    float: left;
-  }
-  td {
-    width: 1em;
-    height: 1em;
-  }
-
-  .navy { background: navy}
-  .blue { background: blue }
-  .aqua { background: aqua }
-  .teal { background: teal }
-</style>
-
-<p>Test passes if the following patterned boxes all look identical.
-
-<table class="test">
-  <col span=2 class="navy">
-  <col class="blue">
-  <col span=2 class="aqua">
-  <tr><td><td><td><td><td>
-</table>
-<table class="test">
-  <colgroup span=2 class="navy"></colgroup>
-  <colgroup>
-    <col class="blue">
-    <col span=2 class="aqua">
-  </colgroup>
-  <tr><td><td><td><td><td>
-</table>
-
-<table dir=rtl class="test">
-  <col span=2 class="navy">
-  <col class="blue">
-  <col span=2 class="aqua">
-  <tr><td><td><td><td><td>
-</table>
-<table dir=rtl class="test">
-  <colgroup span=2 class="navy"></colgroup>
-  <colgroup>
-    <col class="blue">
-    <col span=2 class="aqua">
-  </colgroup>
-  <tr><td><td><td><td><td>
-</table>
-
-<table class="reference">
-  <tr><td class="navy">
-  <tr><td class="navy">
-  <tr><td class="blue">
-  <tr><td class="aqua">
-  <tr><td class="aqua">
-</table>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/text-baseline-slr-009-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/text-baseline-slr-009-ref.xht
deleted file mode 100644
index 6b4bb02..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/text-baseline-slr-009-ref.xht
+++ /dev/null
@@ -1,35 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
- <title>CSS Reftest Reference</title>
- <link rel="author" title="Hajime Shiozawa" href="mailto:hajime.shiozawa@gmail.com" />
- <meta name="flags" content="image" />
- <style type="text/css"><![CDATA[
-
-  img
- {
-  padding-left: 78px;
-  vertical-align: top;
- }
-
- img + br + img
- {
-  padding-left: 30px;
- }
-
- img + br + img + br + img
- {
-  padding-left: 102px;
- }
- ]]></style>
-
-</head>
-
-<body>
-
-<p>Test passes if the <strong>right edge</strong> of an irregular polygon is straight and unbroken.</p>
-
-<div><img src="support/swatch-fuchsia.png" width="48" height="60" alt="Image download support must be enabled" /><br /><img src="support/swatch-fuchsia.png" width="96" height="120" alt="Image download support must be enabled" /><br /><img src="support/swatch-fuchsia.png" width="24" height="30" alt="Image download support must be enabled" /></div>
-
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/text-orientation-mixed-slr-015.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/text-orientation-mixed-slr-015.xht
deleted file mode 100644
index c1d57ef..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/text-orientation-mixed-slr-015.xht
+++ /dev/null
@@ -1,44 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-
- <head>
-
-  <title>CSS Writing Modes Test: 'writing-mode: sideways-lr' - 'text-orientation: mixed' has no effect</title>
-
-  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" title="5.1. Orienting Text: the 'text-orientation' property" href="http://www.w3.org/TR/css-writing-modes-4/#text-orientation" />
-
-  <meta name="flags" content="image" />
-  <meta name="assert" content="This test checks that when 'writing-mode' is set to 'sideways-lr', then a 'text-orientation: mixed' declaration has no effect: the alphabetical baseline is used as the dominant baseline and all the glyphs remain rotated 90 degrees counter-clockwise. The typographic mode for 'sideways-lr' is horizontal and 'text-orientation' has no effect on boxes in horizontal typographic modes." />
-
-  <style type="text/css"><![CDATA[
-  @font-face
-    {
-      font-family: "mplus-1p-regular";
-      src: url("/fonts/mplus-1p-regular.woff") format("woff");
-      /* filesize: 803300 bytes (784.5 KBytes) */
-    }
-
-    div#slr
-    {
-      border: gray solid 1px;
-      font: bold 26px/32px "mplus-1p-regular";
-      margin-bottom: 4px;
-      writing-mode: sideways-lr;
-      text-orientation: mixed;
-    }
-  ]]></style>
-
- </head>
-
- <body>
-
-  <p>Test passes if the glyphs in both rectangles have the <strong>same order</strong>, the <strong>same orientation</strong> and the <strong>same layout</strong>.</p>
-
-  <div id="slr">月火水Abc<br />def木金土</div>
-
-  <div><img id="reference" src="support/text-orientation-sideways-lr.png" width="66" height="133" alt="Image download support must be enabled" /></div>
-
- </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/text-orientation-mixed-srl-016-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/text-orientation-mixed-srl-016-ref.xht
deleted file mode 100644
index bae223a..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/text-orientation-mixed-srl-016-ref.xht
+++ /dev/null
@@ -1,40 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-
- <head>
-
-  <title>CSS Reftest Reference</title>
-
-  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-
-  <style type="text/css"><![CDATA[
-  @font-face
-    {
-      font-family: "mplus-1p-regular";
-      src: url("/fonts/mplus-1p-regular.woff") format("woff");
-      /* filesize: 803300 bytes (784.5 KBytes) */
-    }
-
-  div
-    {
-      border: gray solid 1px;
-      font: bold 26px/32px "mplus-1p-regular";
-      margin-bottom: 4px;
-      text-orientation: sideways;
-      writing-mode: vertical-rl;
-    }
-  ]]></style>
-
- </head>
-
- <body>
-
-  <p>Test passes if the glyphs in both rectangles have the <strong>same order</strong>, the <strong>same orientation</strong> and the <strong>same layout</strong>.</p>
-
-  <div>月火水Abc<br />def木金土</div>
-
-  <div>月火水Abc<br />def木金土</div>
-
- </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/text-orientation-sideways-slr-019.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/text-orientation-sideways-slr-019.xht
deleted file mode 100644
index 9751a85..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/text-orientation-sideways-slr-019.xht
+++ /dev/null
@@ -1,44 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-
- <head>
-
-  <title>CSS Writing Modes Test: 'writing-mode: sideways-lr' - 'text-orientation: sideways' has no effect</title>
-
-  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" title="5.1. Orienting Text: the 'text-orientation' property" href="http://www.w3.org/TR/css-writing-modes-4/#text-orientation" />
-
-  <meta name="flags" content="image" />
-  <meta name="assert" content="This test checks that when 'writing-mode' is set to 'sideways-lr', then a 'text-orientation: sideways' declaration has no effect: the alphabetical baseline is used as the dominant baseline and all the glyphs remain rotated 90 degrees counter-clockwise. The typographic mode for 'sideways-lr' is horizontal and 'text-orientation' has no effect on boxes in horizontal typographic modes." />
-
-  <style type="text/css"><![CDATA[
-  @font-face
-    {
-      font-family: "mplus-1p-regular";
-      src: url("/fonts/mplus-1p-regular.woff") format("woff");
-      /* filesize: 803300 bytes (784.5 KBytes) */
-    }
-
-    div#slr
-    {
-      border: gray solid 1px;
-      font: bold 26px/32px "mplus-1p-regular";
-      margin-bottom: 4px;
-      writing-mode: sideways-lr;
-      text-orientation: sideways;
-    }
-  ]]></style>
-
- </head>
-
- <body>
-
-  <p>Test passes if the glyphs in both rectangles have the <strong>same order</strong>, the <strong>same orientation</strong> and the <strong>same layout</strong>.</p>
-
-  <div id="slr">月火水Abc<br />def木金土</div>
-
-  <div><img id="reference" src="support/text-orientation-sideways-lr.png" width="66" height="133" alt="Image download support must be enabled" /></div>
-
- </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/text-orientation-upright-slr-017.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/text-orientation-upright-slr-017.xht
deleted file mode 100644
index eb67dde..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/text-orientation-upright-slr-017.xht
+++ /dev/null
@@ -1,44 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-
- <head>
-
-  <title>CSS Writing Modes Test: 'writing-mode: sideways-lr' - 'text-orientation: upright' has no effect</title>
-
-  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" title="5.1. Orienting Text: the 'text-orientation' property" href="http://www.w3.org/TR/css-writing-modes-4/#text-orientation" />
-
-  <meta name="flags" content="image" />
-  <meta name="assert" content="This test checks that when 'writing-mode' is set to 'sideways-lr', then a 'text-orientation: upright' declaration has no effect: the alphabetical baseline is used as the dominant baseline and all the glyphs remain rotated 90 degrees counter-clockwise. The typographic mode for 'sideways-lr' is horizontal and 'text-orientation' has no effect on boxes in horizontal typographic modes." />
-
-  <style type="text/css"><![CDATA[
-  @font-face
-    {
-      font-family: "mplus-1p-regular";
-      src: url("/fonts/mplus-1p-regular.woff") format("woff");
-      /* filesize: 803300 bytes (784.5 KBytes) */
-    }
-
-    div#slr
-    {
-      border: gray solid 1px;
-      font: bold 26px/32px "mplus-1p-regular";
-      margin-bottom: 4px;
-      writing-mode: sideways-lr;
-      text-orientation: upright;
-    }
-  ]]></style>
-
- </head>
-
- <body>
-
-  <p>Test passes if the glyphs in both rectangles have the <strong>same order</strong>, the <strong>same orientation</strong> and the <strong>same layout</strong>.</p>
-
-  <div id="slr">月火水Abc<br />def木金土</div>
-
-  <div><img id="reference" src="support/text-orientation-sideways-lr.png" width="66" height="133" alt="Image download support must be enabled" /></div>
-
- </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/vertical-alignment-slr-037.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/vertical-alignment-slr-037.xht
deleted file mode 100644
index 2ce7a16..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/vertical-alignment-slr-037.xht
+++ /dev/null
@@ -1,36 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-  <head>
-    <title>CSS Writing Modes Test: vertical-align - 'super' and sideways-lr writing-mode</title>
-    <link rel="author" title="Hajime Shiozawa" href="mailto:hajime.shiozawa@gmail.com" />
-    <link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2015-12-11 -->
-    <link rel="help" title="7.5 Line-Relative Mappings" href="http://www.w3.org/TR/css-writing-modes-4/#line-mappings" />
-    <link rel="help" title="10.8.1 Leading and half-leading" href="http://www.w3.org/TR/2011/REC-CSS2-20110607/visudet.html#leading" />
-    <meta name="assert" content="This test checks the position of inline non-replaced box with vertical align property. When 'writing-mode' is 'sideways-lr' and 'vertical-align' is 'super', the baseline of the box is shifted to the left." />
-    <meta name="flags" content="ahem" />
-    <style type="text/css"><![CDATA[
-    div#slr
-    {
-      writing-mode: sideways-lr;
-      font: 60px/3 Ahem; /* computes to 60px/180px */
-      color: orange;
-    }
-
-    span
-    {
-      vertical-align: super;
-      color: blue;
-      margin-bottom: -1em;
-    }
-    ]]></style>
-
-  </head>
-
-  <body>
-
-  <p>Test passes if there are a blue square on the left and an orange rectangle on the right.</p>
-
-  <div id="slr">X<span>2</span></div>
-
-  </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/vertical-alignment-slr-039.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/vertical-alignment-slr-039.xht
deleted file mode 100644
index 4421bf4..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/vertical-alignment-slr-039.xht
+++ /dev/null
@@ -1,36 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-  <head>
-    <title>CSS Writing Modes Test: vertical-align - 'sub' and sideways-lr writing-mode</title>
-    <link rel="author" title="Hajime Shiozawa" href="mailto:hajime.shiozawa@gmail.com" />
-    <link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2015-12-11 -->
-    <link rel="help" title="7.5 Line-Relative Mappings" href="http://www.w3.org/TR/css-writing-modes-4/#line-mappings" />
-    <link rel="help" title="10.8.1 Leading and half-leading" href="http://www.w3.org/TR/2011/REC-CSS2-20110607/visudet.html#leading" />
-    <meta name="assert" content="This test checks the position of inline non-replaced box with vertical align property. When 'writing-mode' is 'sideways-lr' and 'vertical-align' is 'sub', the baseline of the box is shifted to the right." />
-    <meta name="flags" content="ahem" />
-    <style type="text/css"><![CDATA[
-    div#slr
-    {
-      writing-mode: sideways-lr;
-      font: 60px/3 Ahem; /* computes to 60px/180px */
-      color: orange;
-    }
-
-    span
-    {
-      vertical-align: sub;
-      color: blue;
-      margin-bottom: -1em;
-    }
-    ]]></style>
-
-  </head>
-
-  <body>
-
-  <p>Test passes if there are an orange rectangle on the left and a blue square on the right.</p>
-
-  <div id="slr">O<span>2</span></div>
-
-  </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/vertical-alignment-slr-049-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/vertical-alignment-slr-049-ref.xht
deleted file mode 100644
index 20f6252..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/vertical-alignment-slr-049-ref.xht
+++ /dev/null
@@ -1,31 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-  <title>CSS Reftest Reference</title>
-  <link rel="author" title="Hajime Shiozawa" href="mailto:hajime.shiozawa@gmail.com" />
-  <link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2015-12-11 -->
-  <meta name="flags" content="image" />
-  <style type="text/css"><![CDATA[
-    img
-    {
-      padding-left: 100px;
-      vertical-align: top;
-    }
-    img + br + img
-    {
-      padding-left: 100px;
-    }
-  ]]></style>
-
-</head>
-
-<body>
-
-<p>Test passes if the <strong>left edge</strong> of an irregular polygon is straight and unbroken.</p>
-
-<div>
-  <img src="support/swatch-blue.png" width="80" height="80" alt="Image download support must be enabled" /><br /><img src="support/swatch-blue.png" width="100" height="100" alt="Image download support must be enabled" />
-</div>
-
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/vertical-alignment-srl-036.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/vertical-alignment-srl-036.xht
deleted file mode 100644
index 59d49496..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/vertical-alignment-srl-036.xht
+++ /dev/null
@@ -1,36 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-  <head>
-    <title>CSS Writing Modes Test: vertical-align - 'super' and sideways-rl writing-mode</title>
-    <link rel="author" title="Hajime Shiozawa" href="mailto:hajime.shiozawa@gmail.com" />
-    <link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2015-12-11 -->
-    <link rel="help" title="7.5 Line-Relative Mappings" href="http://www.w3.org/TR/css-writing-modes-4/#line-mappings" />
-    <link rel="help" title="10.8.1 Leading and half-leading" href="http://www.w3.org/TR/2011/REC-CSS2-20110607/visudet.html#leading" />
-    <meta name="assert" content="This test checks the position of inline non-replaced box with vertical align property. When 'writing-mode' is 'sideways-rl' and 'vertical-align' is 'super', the baseline of the box is shifted to the right." />
-    <meta name="flags" content="ahem" />
-    <style type="text/css"><![CDATA[
-    div#srl
-    {
-      writing-mode: sideways-rl;
-      font: 60px/3 Ahem; /* computes to 60px/180px */
-      color: orange;
-    }
-
-    span
-    {
-      vertical-align: super;
-      color: blue;
-      margin-top: -1em;
-    }
-    ]]></style>
-
-  </head>
-
-  <body>
-
-  <p>Test passes if there are an orange rectangle on the left and a blue square on the right.</p>
-
-  <div id="srl">X<span>2</span></div>
-
-  </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/vertical-alignment-srl-038.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/vertical-alignment-srl-038.xht
deleted file mode 100644
index c8aa9756..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/vertical-alignment-srl-038.xht
+++ /dev/null
@@ -1,36 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-  <head>
-    <title>CSS Writing Modes Test: vertical-align - 'sub' and sideways-rl writing-mode</title>
-    <link rel="author" title="Hajime Shiozawa" href="mailto:hajime.shiozawa@gmail.com" />
-    <link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2015-12-11 -->
-    <link rel="help" title="7.5 Line-Relative Mappings" href="http://www.w3.org/TR/css-writing-modes-4/#line-mappings" />
-    <link rel="help" title="10.8.1 Leading and half-leading" href="http://www.w3.org/TR/2011/REC-CSS2-20110607/visudet.html#leading" />
-    <meta name="assert" content="This test checks the position of inline non-replaced box with vertical align property. When 'writing-mode' is 'sideways-rl' and 'vertical-align' is 'sub', the baseline of the box is shifted to the left." />
-    <meta name="flags" content="ahem" />
-    <style type="text/css"><![CDATA[
-    div#srl
-    {
-      writing-mode: sideways-rl;
-      font: 60px/3 Ahem; /* computes to 60px/180px */
-      color: orange;
-    }
-
-    span
-    {
-      vertical-align: sub;
-      color: blue;
-      margin-top: -1em;
-    }
-    ]]></style>
-
-  </head>
-
-  <body>
-
-  <p>Test passes if there are a blue square on the left and an orange rectangle on the right.</p>
-
-  <div id="srl">O<span>2</span></div>
-
-  </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/wm-propagation-body-008.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/wm-propagation-body-008.xht
deleted file mode 100644
index feeb857..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-writing-modes/wm-propagation-body-008.xht
+++ /dev/null
@@ -1,49 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-
- <head>
-
-  <title>CSS Writing Modes Test: 'writing-mode: sideways-rl' set to body element propagates to viewport</title>
-
-  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
-  <link rel="help" href="https://www.w3.org/TR/css-writing-modes-4/#principal-flow" title="8. The Principal Writing Mode" />
-  <link rel="match" href="block-flow-direction-025-ref.xht" />
-
-  <meta name="flags" content="image" />
-  <meta name="assert" content="This test checks that when the root element has a &lt;body&gt; child element, then the principal writing mode is instead taken from the values of writing-mode and direction on the first such child element instead of taken from the root element." />
-
-  <style type="text/css"><![CDATA[
-  html
-    {
-      writing-mode: horizontal-tb;
-    }
-
-  body
-    {
-      writing-mode: sideways-rl;
-    }
-
-  div
-    {
-      background-color: blue;
-      height: 100px;
-      width: 100px;
-    }
-  ]]></style>
- </head>
-
- <body>
-
-  <div></div>
-
-  <p><img src="support/block-flow-direction-025-exp-res.png" width="359" height="36" alt="Image download support must be enabled" /></p>
-
-  <!--
-  The image says:
-  Test passes if there is a blue square in the
-  <strong>upper-right corner</strong> of the page.
-  -->
-
- </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces-expected.txt
index c6a73d0..0b2059f 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces-expected.txt
@@ -1,1961 +1,4 @@
 This is a testharness.js-based test.
-Found 1957 tests; 1937 PASS, 20 FAIL, 0 TIMEOUT, 0 NOTRUN.
-PASS Test driver
-PASS WorkerGlobalScope interface: existence and properties of interface object
-PASS DedicatedWorkerGlobalScope interface: existence and properties of interface object
-PASS SharedWorkerGlobalScope interface: existence and properties of interface object
-PASS WorkerNavigator interface: existence and properties of interface object
-PASS WorkerLocation interface: existence and properties of interface object
-PASS Event interface: existence and properties of interface object
-PASS Event interface object length
-PASS Event interface object name
-PASS Event interface: existence and properties of interface prototype object
-PASS Event interface: existence and properties of interface prototype object's "constructor" property
-PASS Event interface: existence and properties of interface prototype object's @@unscopables property
-PASS Event interface: attribute type
-PASS Unscopable handled correctly for type property on Event
-PASS Event interface: attribute target
-PASS Unscopable handled correctly for target property on Event
-PASS Event interface: attribute currentTarget
-PASS Unscopable handled correctly for currentTarget property on Event
-PASS Event interface: constant NONE on interface object
-PASS Event interface: constant NONE on interface prototype object
-PASS Event interface: constant CAPTURING_PHASE on interface object
-PASS Event interface: constant CAPTURING_PHASE on interface prototype object
-PASS Event interface: constant AT_TARGET on interface object
-PASS Event interface: constant AT_TARGET on interface prototype object
-PASS Event interface: constant BUBBLING_PHASE on interface object
-PASS Event interface: constant BUBBLING_PHASE on interface prototype object
-PASS Event interface: attribute eventPhase
-PASS Unscopable handled correctly for eventPhase property on Event
-PASS Event interface: operation stopPropagation()
-PASS Unscopable handled correctly for stopPropagation() on Event
-PASS Event interface: operation stopImmediatePropagation()
-PASS Unscopable handled correctly for stopImmediatePropagation() on Event
-PASS Event interface: attribute bubbles
-PASS Unscopable handled correctly for bubbles property on Event
-PASS Event interface: attribute cancelable
-PASS Unscopable handled correctly for cancelable property on Event
-PASS Event interface: operation preventDefault()
-PASS Unscopable handled correctly for preventDefault() on Event
-PASS Event interface: attribute defaultPrevented
-PASS Unscopable handled correctly for defaultPrevented property on Event
-PASS Event interface: attribute timeStamp
-PASS Unscopable handled correctly for timeStamp property on Event
-PASS Event interface: operation initEvent(DOMString, boolean, boolean)
-PASS Unscopable handled correctly for initEvent(DOMString, boolean, boolean) on Event
-PASS Event must be primary interface of document.createEvent("Event")
-PASS Stringification of document.createEvent("Event")
-PASS Event interface: document.createEvent("Event") must inherit property "type" with the proper type
-PASS Event interface: document.createEvent("Event") must inherit property "target" with the proper type
-PASS Event interface: document.createEvent("Event") must inherit property "currentTarget" with the proper type
-PASS Event interface: document.createEvent("Event") must inherit property "NONE" with the proper type
-PASS Event interface: document.createEvent("Event") must inherit property "CAPTURING_PHASE" with the proper type
-PASS Event interface: document.createEvent("Event") must inherit property "AT_TARGET" with the proper type
-PASS Event interface: document.createEvent("Event") must inherit property "BUBBLING_PHASE" with the proper type
-PASS Event interface: document.createEvent("Event") must inherit property "eventPhase" with the proper type
-PASS Event interface: document.createEvent("Event") must inherit property "stopPropagation()" with the proper type
-PASS Event interface: document.createEvent("Event") must inherit property "stopImmediatePropagation()" with the proper type
-PASS Event interface: document.createEvent("Event") must inherit property "bubbles" with the proper type
-PASS Event interface: document.createEvent("Event") must inherit property "cancelable" with the proper type
-PASS Event interface: document.createEvent("Event") must inherit property "preventDefault()" with the proper type
-PASS Event interface: document.createEvent("Event") must inherit property "defaultPrevented" with the proper type
-PASS Event interface: document.createEvent("Event") must have own property "isTrusted"
-PASS Event interface: document.createEvent("Event") must inherit property "timeStamp" with the proper type
-PASS Event interface: document.createEvent("Event") must inherit property "initEvent(DOMString, boolean, boolean)" with the proper type
-PASS Event interface: calling initEvent(DOMString, boolean, boolean) on document.createEvent("Event") with too few arguments must throw TypeError
-PASS Event must be primary interface of new Event("foo")
-PASS Stringification of new Event("foo")
-PASS Event interface: new Event("foo") must inherit property "type" with the proper type
-PASS Event interface: new Event("foo") must inherit property "target" with the proper type
-PASS Event interface: new Event("foo") must inherit property "currentTarget" with the proper type
-PASS Event interface: new Event("foo") must inherit property "NONE" with the proper type
-PASS Event interface: new Event("foo") must inherit property "CAPTURING_PHASE" with the proper type
-PASS Event interface: new Event("foo") must inherit property "AT_TARGET" with the proper type
-PASS Event interface: new Event("foo") must inherit property "BUBBLING_PHASE" with the proper type
-PASS Event interface: new Event("foo") must inherit property "eventPhase" with the proper type
-PASS Event interface: new Event("foo") must inherit property "stopPropagation()" with the proper type
-PASS Event interface: new Event("foo") must inherit property "stopImmediatePropagation()" with the proper type
-PASS Event interface: new Event("foo") must inherit property "bubbles" with the proper type
-PASS Event interface: new Event("foo") must inherit property "cancelable" with the proper type
-PASS Event interface: new Event("foo") must inherit property "preventDefault()" with the proper type
-PASS Event interface: new Event("foo") must inherit property "defaultPrevented" with the proper type
-PASS Event interface: new Event("foo") must have own property "isTrusted"
-PASS Event interface: new Event("foo") must inherit property "timeStamp" with the proper type
-PASS Event interface: new Event("foo") must inherit property "initEvent(DOMString, boolean, boolean)" with the proper type
-PASS Event interface: calling initEvent(DOMString, boolean, boolean) on new Event("foo") with too few arguments must throw TypeError
-PASS CustomEvent interface: existence and properties of interface object
-PASS CustomEvent interface object length
-PASS CustomEvent interface object name
-PASS CustomEvent interface: existence and properties of interface prototype object
-PASS CustomEvent interface: existence and properties of interface prototype object's "constructor" property
-PASS CustomEvent interface: existence and properties of interface prototype object's @@unscopables property
-PASS CustomEvent interface: attribute detail
-PASS Unscopable handled correctly for detail property on CustomEvent
-PASS CustomEvent interface: operation initCustomEvent(DOMString, boolean, boolean, any)
-PASS Unscopable handled correctly for initCustomEvent(DOMString, boolean, boolean, any) on CustomEvent
-PASS CustomEvent must be primary interface of new CustomEvent("foo")
-PASS Stringification of new CustomEvent("foo")
-PASS CustomEvent interface: new CustomEvent("foo") must inherit property "detail" with the proper type
-PASS CustomEvent interface: new CustomEvent("foo") must inherit property "initCustomEvent(DOMString, boolean, boolean, any)" with the proper type
-PASS CustomEvent interface: calling initCustomEvent(DOMString, boolean, boolean, any) on new CustomEvent("foo") with too few arguments must throw TypeError
-PASS Event interface: new CustomEvent("foo") must inherit property "type" with the proper type
-PASS Event interface: new CustomEvent("foo") must inherit property "target" with the proper type
-PASS Event interface: new CustomEvent("foo") must inherit property "currentTarget" with the proper type
-PASS Event interface: new CustomEvent("foo") must inherit property "NONE" with the proper type
-PASS Event interface: new CustomEvent("foo") must inherit property "CAPTURING_PHASE" with the proper type
-PASS Event interface: new CustomEvent("foo") must inherit property "AT_TARGET" with the proper type
-PASS Event interface: new CustomEvent("foo") must inherit property "BUBBLING_PHASE" with the proper type
-PASS Event interface: new CustomEvent("foo") must inherit property "eventPhase" with the proper type
-PASS Event interface: new CustomEvent("foo") must inherit property "stopPropagation()" with the proper type
-PASS Event interface: new CustomEvent("foo") must inherit property "stopImmediatePropagation()" with the proper type
-PASS Event interface: new CustomEvent("foo") must inherit property "bubbles" with the proper type
-PASS Event interface: new CustomEvent("foo") must inherit property "cancelable" with the proper type
-PASS Event interface: new CustomEvent("foo") must inherit property "preventDefault()" with the proper type
-PASS Event interface: new CustomEvent("foo") must inherit property "defaultPrevented" with the proper type
-PASS Event interface: new CustomEvent("foo") must have own property "isTrusted"
-PASS Event interface: new CustomEvent("foo") must inherit property "timeStamp" with the proper type
-PASS Event interface: new CustomEvent("foo") must inherit property "initEvent(DOMString, boolean, boolean)" with the proper type
-PASS Event interface: calling initEvent(DOMString, boolean, boolean) on new CustomEvent("foo") with too few arguments must throw TypeError
-PASS EventTarget interface: existence and properties of interface object
-PASS EventTarget interface object length
-PASS EventTarget interface object name
-PASS EventTarget interface: existence and properties of interface prototype object
-PASS EventTarget interface: existence and properties of interface prototype object's "constructor" property
-PASS EventTarget interface: existence and properties of interface prototype object's @@unscopables property
-PASS EventTarget interface: operation addEventListener(DOMString, EventListener, [object Object],[object Object])
-PASS Unscopable handled correctly for addEventListener(DOMString, EventListener, [object Object],[object Object]) on EventTarget
-PASS EventTarget interface: operation removeEventListener(DOMString, EventListener, [object Object],[object Object])
-PASS Unscopable handled correctly for removeEventListener(DOMString, EventListener, [object Object],[object Object]) on EventTarget
-PASS EventTarget interface: operation dispatchEvent(Event)
-PASS Unscopable handled correctly for dispatchEvent(Event) on EventTarget
-PASS EventTarget must be primary interface of new EventTarget()
-PASS Stringification of new EventTarget()
-PASS EventTarget interface: new EventTarget() must inherit property "addEventListener(DOMString, EventListener, [object Object],[object Object])" with the proper type
-PASS EventTarget interface: calling addEventListener(DOMString, EventListener, [object Object],[object Object]) on new EventTarget() with too few arguments must throw TypeError
-PASS EventTarget interface: new EventTarget() must inherit property "removeEventListener(DOMString, EventListener, [object Object],[object Object])" with the proper type
-PASS EventTarget interface: calling removeEventListener(DOMString, EventListener, [object Object],[object Object]) on new EventTarget() with too few arguments must throw TypeError
-PASS EventTarget interface: new EventTarget() must inherit property "dispatchEvent(Event)" with the proper type
-PASS EventTarget interface: calling dispatchEvent(Event) on new EventTarget() with too few arguments must throw TypeError
-PASS EventListener interface: existence and properties of interface object
-PASS EventListener interface: existence and properties of interface prototype object
-PASS EventListener interface: existence and properties of interface prototype object's "constructor" property
-PASS EventListener interface: existence and properties of interface prototype object's @@unscopables property
-PASS EventListener interface: operation handleEvent(Event)
-PASS Unscopable handled correctly for handleEvent(Event) on EventListener
-PASS AbortController interface: existence and properties of interface object
-PASS AbortController interface object length
-PASS AbortController interface object name
-PASS AbortController interface: existence and properties of interface prototype object
-PASS AbortController interface: existence and properties of interface prototype object's "constructor" property
-PASS AbortController interface: existence and properties of interface prototype object's @@unscopables property
-PASS AbortController interface: attribute signal
-PASS Unscopable handled correctly for signal property on AbortController
-PASS AbortController interface: operation abort()
-PASS Unscopable handled correctly for abort() on AbortController
-PASS AbortController must be primary interface of new AbortController()
-PASS Stringification of new AbortController()
-PASS AbortController interface: new AbortController() must inherit property "signal" with the proper type
-PASS AbortController interface: new AbortController() must inherit property "abort()" with the proper type
-PASS AbortSignal interface: existence and properties of interface object
-PASS AbortSignal interface object length
-PASS AbortSignal interface object name
-PASS AbortSignal interface: existence and properties of interface prototype object
-PASS AbortSignal interface: existence and properties of interface prototype object's "constructor" property
-PASS AbortSignal interface: existence and properties of interface prototype object's @@unscopables property
-PASS AbortSignal interface: attribute aborted
-PASS Unscopable handled correctly for aborted property on AbortSignal
-PASS AbortSignal interface: attribute onabort
-PASS Unscopable handled correctly for onabort property on AbortSignal
-PASS AbortSignal must be primary interface of new AbortController().signal
-PASS Stringification of new AbortController().signal
-PASS AbortSignal interface: new AbortController().signal must inherit property "aborted" with the proper type
-PASS AbortSignal interface: new AbortController().signal must inherit property "onabort" with the proper type
-PASS EventTarget interface: new AbortController().signal must inherit property "addEventListener(DOMString, EventListener, [object Object],[object Object])" with the proper type
-PASS EventTarget interface: calling addEventListener(DOMString, EventListener, [object Object],[object Object]) on new AbortController().signal with too few arguments must throw TypeError
-PASS EventTarget interface: new AbortController().signal must inherit property "removeEventListener(DOMString, EventListener, [object Object],[object Object])" with the proper type
-PASS EventTarget interface: calling removeEventListener(DOMString, EventListener, [object Object],[object Object]) on new AbortController().signal with too few arguments must throw TypeError
-PASS EventTarget interface: new AbortController().signal must inherit property "dispatchEvent(Event)" with the proper type
-PASS EventTarget interface: calling dispatchEvent(Event) on new AbortController().signal with too few arguments must throw TypeError
-PASS NodeList interface: existence and properties of interface object
-PASS NodeList interface object length
-PASS NodeList interface object name
-PASS NodeList interface: existence and properties of interface prototype object
-PASS NodeList interface: existence and properties of interface prototype object's "constructor" property
-PASS NodeList interface: existence and properties of interface prototype object's @@unscopables property
-PASS NodeList interface: operation item(unsigned long)
-PASS Unscopable handled correctly for item(unsigned long) on NodeList
-PASS NodeList interface: attribute length
-PASS Unscopable handled correctly for length property on NodeList
-PASS NodeList must be primary interface of document.querySelectorAll("script")
-PASS Stringification of document.querySelectorAll("script")
-PASS NodeList interface: document.querySelectorAll("script") must inherit property "item(unsigned long)" with the proper type
-PASS NodeList interface: calling item(unsigned long) on document.querySelectorAll("script") with too few arguments must throw TypeError
-PASS NodeList interface: document.querySelectorAll("script") must inherit property "length" with the proper type
-PASS HTMLCollection interface: existence and properties of interface object
-PASS HTMLCollection interface object length
-PASS HTMLCollection interface object name
-PASS HTMLCollection interface: existence and properties of interface prototype object
-PASS HTMLCollection interface: existence and properties of interface prototype object's "constructor" property
-PASS HTMLCollection interface: existence and properties of interface prototype object's @@unscopables property
-PASS HTMLCollection interface: attribute length
-PASS Unscopable handled correctly for length property on HTMLCollection
-PASS HTMLCollection interface: operation item(unsigned long)
-PASS Unscopable handled correctly for item(unsigned long) on HTMLCollection
-PASS HTMLCollection interface: operation namedItem(DOMString)
-PASS Unscopable handled correctly for namedItem(DOMString) on HTMLCollection
-PASS HTMLCollection must be primary interface of document.body.children
-PASS Stringification of document.body.children
-PASS HTMLCollection interface: document.body.children must inherit property "length" with the proper type
-PASS HTMLCollection interface: document.body.children must inherit property "item(unsigned long)" with the proper type
-PASS HTMLCollection interface: calling item(unsigned long) on document.body.children with too few arguments must throw TypeError
-PASS HTMLCollection interface: document.body.children must inherit property "namedItem(DOMString)" with the proper type
-PASS HTMLCollection interface: calling namedItem(DOMString) on document.body.children with too few arguments must throw TypeError
-PASS MutationObserver interface: existence and properties of interface object
-PASS MutationObserver interface object length
-PASS MutationObserver interface object name
-PASS MutationObserver interface: existence and properties of interface prototype object
-PASS MutationObserver interface: existence and properties of interface prototype object's "constructor" property
-PASS MutationObserver interface: existence and properties of interface prototype object's @@unscopables property
-PASS MutationObserver interface: operation observe(Node, MutationObserverInit)
-PASS Unscopable handled correctly for observe(Node, MutationObserverInit) on MutationObserver
-PASS MutationObserver interface: operation disconnect()
-PASS Unscopable handled correctly for disconnect() on MutationObserver
-PASS MutationObserver interface: operation takeRecords()
-PASS Unscopable handled correctly for takeRecords() on MutationObserver
-PASS MutationRecord interface: existence and properties of interface object
-PASS MutationRecord interface object length
-PASS MutationRecord interface object name
-PASS MutationRecord interface: existence and properties of interface prototype object
-PASS MutationRecord interface: existence and properties of interface prototype object's "constructor" property
-PASS MutationRecord interface: existence and properties of interface prototype object's @@unscopables property
-PASS MutationRecord interface: attribute type
-PASS Unscopable handled correctly for type property on MutationRecord
-PASS MutationRecord interface: attribute target
-PASS Unscopable handled correctly for target property on MutationRecord
-PASS MutationRecord interface: attribute addedNodes
-PASS Unscopable handled correctly for addedNodes property on MutationRecord
-PASS MutationRecord interface: attribute removedNodes
-PASS Unscopable handled correctly for removedNodes property on MutationRecord
-PASS MutationRecord interface: attribute previousSibling
-PASS Unscopable handled correctly for previousSibling property on MutationRecord
-PASS MutationRecord interface: attribute nextSibling
-PASS Unscopable handled correctly for nextSibling property on MutationRecord
-PASS MutationRecord interface: attribute attributeName
-PASS Unscopable handled correctly for attributeName property on MutationRecord
-PASS MutationRecord interface: attribute attributeNamespace
-PASS Unscopable handled correctly for attributeNamespace property on MutationRecord
-PASS MutationRecord interface: attribute oldValue
-PASS Unscopable handled correctly for oldValue property on MutationRecord
-PASS Node interface: existence and properties of interface object
-PASS Node interface object length
-PASS Node interface object name
-PASS Node interface: existence and properties of interface prototype object
-PASS Node interface: existence and properties of interface prototype object's "constructor" property
-PASS Node interface: existence and properties of interface prototype object's @@unscopables property
-PASS Node interface: constant ELEMENT_NODE on interface object
-PASS Node interface: constant ELEMENT_NODE on interface prototype object
-PASS Node interface: constant ATTRIBUTE_NODE on interface object
-PASS Node interface: constant ATTRIBUTE_NODE on interface prototype object
-PASS Node interface: constant TEXT_NODE on interface object
-PASS Node interface: constant TEXT_NODE on interface prototype object
-PASS Node interface: constant CDATA_SECTION_NODE on interface object
-PASS Node interface: constant CDATA_SECTION_NODE on interface prototype object
-PASS Node interface: constant ENTITY_REFERENCE_NODE on interface object
-PASS Node interface: constant ENTITY_REFERENCE_NODE on interface prototype object
-PASS Node interface: constant ENTITY_NODE on interface object
-PASS Node interface: constant ENTITY_NODE on interface prototype object
-PASS Node interface: constant PROCESSING_INSTRUCTION_NODE on interface object
-PASS Node interface: constant PROCESSING_INSTRUCTION_NODE on interface prototype object
-PASS Node interface: constant COMMENT_NODE on interface object
-PASS Node interface: constant COMMENT_NODE on interface prototype object
-PASS Node interface: constant DOCUMENT_NODE on interface object
-PASS Node interface: constant DOCUMENT_NODE on interface prototype object
-PASS Node interface: constant DOCUMENT_TYPE_NODE on interface object
-PASS Node interface: constant DOCUMENT_TYPE_NODE on interface prototype object
-PASS Node interface: constant DOCUMENT_FRAGMENT_NODE on interface object
-PASS Node interface: constant DOCUMENT_FRAGMENT_NODE on interface prototype object
-PASS Node interface: constant NOTATION_NODE on interface object
-PASS Node interface: constant NOTATION_NODE on interface prototype object
-PASS Node interface: attribute nodeType
-PASS Unscopable handled correctly for nodeType property on Node
-PASS Node interface: attribute nodeName
-PASS Unscopable handled correctly for nodeName property on Node
-PASS Node interface: attribute baseURI
-PASS Unscopable handled correctly for baseURI property on Node
-PASS Node interface: attribute isConnected
-PASS Unscopable handled correctly for isConnected property on Node
-PASS Node interface: attribute ownerDocument
-PASS Unscopable handled correctly for ownerDocument property on Node
-PASS Node interface: operation getRootNode(GetRootNodeOptions)
-PASS Unscopable handled correctly for getRootNode(GetRootNodeOptions) on Node
-PASS Node interface: attribute parentNode
-PASS Unscopable handled correctly for parentNode property on Node
-PASS Node interface: attribute parentElement
-PASS Unscopable handled correctly for parentElement property on Node
-PASS Node interface: operation hasChildNodes()
-PASS Unscopable handled correctly for hasChildNodes() on Node
-PASS Node interface: attribute childNodes
-PASS Unscopable handled correctly for childNodes property on Node
-PASS Node interface: attribute firstChild
-PASS Unscopable handled correctly for firstChild property on Node
-PASS Node interface: attribute lastChild
-PASS Unscopable handled correctly for lastChild property on Node
-PASS Node interface: attribute previousSibling
-PASS Unscopable handled correctly for previousSibling property on Node
-PASS Node interface: attribute nextSibling
-PASS Unscopable handled correctly for nextSibling property on Node
-PASS Node interface: attribute nodeValue
-PASS Unscopable handled correctly for nodeValue property on Node
-PASS Node interface: attribute textContent
-PASS Unscopable handled correctly for textContent property on Node
-PASS Node interface: operation normalize()
-PASS Unscopable handled correctly for normalize() on Node
-PASS Node interface: operation cloneNode(boolean)
-PASS Unscopable handled correctly for cloneNode(boolean) on Node
-PASS Node interface: operation isEqualNode(Node)
-PASS Unscopable handled correctly for isEqualNode(Node) on Node
-PASS Node interface: operation isSameNode(Node)
-PASS Unscopable handled correctly for isSameNode(Node) on Node
-PASS Node interface: constant DOCUMENT_POSITION_DISCONNECTED on interface object
-PASS Node interface: constant DOCUMENT_POSITION_DISCONNECTED on interface prototype object
-PASS Node interface: constant DOCUMENT_POSITION_PRECEDING on interface object
-PASS Node interface: constant DOCUMENT_POSITION_PRECEDING on interface prototype object
-PASS Node interface: constant DOCUMENT_POSITION_FOLLOWING on interface object
-PASS Node interface: constant DOCUMENT_POSITION_FOLLOWING on interface prototype object
-PASS Node interface: constant DOCUMENT_POSITION_CONTAINS on interface object
-PASS Node interface: constant DOCUMENT_POSITION_CONTAINS on interface prototype object
-PASS Node interface: constant DOCUMENT_POSITION_CONTAINED_BY on interface object
-PASS Node interface: constant DOCUMENT_POSITION_CONTAINED_BY on interface prototype object
-PASS Node interface: constant DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC on interface object
-PASS Node interface: constant DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC on interface prototype object
-PASS Node interface: operation compareDocumentPosition(Node)
-PASS Unscopable handled correctly for compareDocumentPosition(Node) on Node
-PASS Node interface: operation contains(Node)
-PASS Unscopable handled correctly for contains(Node) on Node
-PASS Node interface: operation lookupPrefix(DOMString)
-PASS Unscopable handled correctly for lookupPrefix(DOMString) on Node
-PASS Node interface: operation lookupNamespaceURI(DOMString)
-PASS Unscopable handled correctly for lookupNamespaceURI(DOMString) on Node
-PASS Node interface: operation isDefaultNamespace(DOMString)
-PASS Unscopable handled correctly for isDefaultNamespace(DOMString) on Node
-PASS Node interface: operation insertBefore(Node, Node)
-PASS Unscopable handled correctly for insertBefore(Node, Node) on Node
-PASS Node interface: operation appendChild(Node)
-PASS Unscopable handled correctly for appendChild(Node) on Node
-PASS Node interface: operation replaceChild(Node, Node)
-PASS Unscopable handled correctly for replaceChild(Node, Node) on Node
-PASS Node interface: operation removeChild(Node)
-PASS Unscopable handled correctly for removeChild(Node) on Node
-PASS Document interface: existence and properties of interface object
-PASS Document interface object length
-PASS Document interface object name
-PASS Document interface: existence and properties of interface prototype object
-PASS Document interface: existence and properties of interface prototype object's "constructor" property
-FAIL Document interface: existence and properties of interface prototype object's @@unscopables property assert_false: Document.prototype[Symbol.unscopables] should not be writable expected false got true
-PASS Document interface: attribute implementation
-PASS Unscopable handled correctly for implementation property on Document
-PASS Document interface: attribute URL
-PASS Unscopable handled correctly for URL property on Document
-PASS Document interface: attribute documentURI
-PASS Unscopable handled correctly for documentURI property on Document
-PASS Document interface: attribute origin
-PASS Unscopable handled correctly for origin property on Document
-PASS Document interface: attribute compatMode
-PASS Unscopable handled correctly for compatMode property on Document
-PASS Document interface: attribute characterSet
-PASS Unscopable handled correctly for characterSet property on Document
-PASS Document interface: attribute charset
-PASS Unscopable handled correctly for charset property on Document
-PASS Document interface: attribute inputEncoding
-PASS Unscopable handled correctly for inputEncoding property on Document
-PASS Document interface: attribute contentType
-PASS Unscopable handled correctly for contentType property on Document
-PASS Document interface: attribute doctype
-PASS Unscopable handled correctly for doctype property on Document
-PASS Document interface: attribute documentElement
-PASS Unscopable handled correctly for documentElement property on Document
-PASS Document interface: operation getElementsByTagName(DOMString)
-PASS Unscopable handled correctly for getElementsByTagName(DOMString) on Document
-PASS Document interface: operation getElementsByTagNameNS(DOMString, DOMString)
-PASS Unscopable handled correctly for getElementsByTagNameNS(DOMString, DOMString) on Document
-PASS Document interface: operation getElementsByClassName(DOMString)
-PASS Unscopable handled correctly for getElementsByClassName(DOMString) on Document
-PASS Document interface: operation createElement(DOMString, [object Object],[object Object])
-PASS Unscopable handled correctly for createElement(DOMString, [object Object],[object Object]) on Document
-PASS Document interface: operation createElementNS(DOMString, DOMString, [object Object],[object Object])
-PASS Unscopable handled correctly for createElementNS(DOMString, DOMString, [object Object],[object Object]) on Document
-PASS Document interface: operation createDocumentFragment()
-PASS Unscopable handled correctly for createDocumentFragment() on Document
-PASS Document interface: operation createTextNode(DOMString)
-PASS Unscopable handled correctly for createTextNode(DOMString) on Document
-PASS Document interface: operation createCDATASection(DOMString)
-PASS Unscopable handled correctly for createCDATASection(DOMString) on Document
-PASS Document interface: operation createComment(DOMString)
-PASS Unscopable handled correctly for createComment(DOMString) on Document
-PASS Document interface: operation createProcessingInstruction(DOMString, DOMString)
-PASS Unscopable handled correctly for createProcessingInstruction(DOMString, DOMString) on Document
-PASS Document interface: operation importNode(Node, boolean)
-PASS Unscopable handled correctly for importNode(Node, boolean) on Document
-PASS Document interface: operation adoptNode(Node)
-PASS Unscopable handled correctly for adoptNode(Node) on Document
-PASS Document interface: operation createAttribute(DOMString)
-PASS Unscopable handled correctly for createAttribute(DOMString) on Document
-PASS Document interface: operation createAttributeNS(DOMString, DOMString)
-PASS Unscopable handled correctly for createAttributeNS(DOMString, DOMString) on Document
-PASS Document interface: operation createEvent(DOMString)
-PASS Unscopable handled correctly for createEvent(DOMString) on Document
-PASS Document interface: operation createRange()
-PASS Unscopable handled correctly for createRange() on Document
-PASS Document interface: operation createNodeIterator(Node, unsigned long, NodeFilter)
-PASS Unscopable handled correctly for createNodeIterator(Node, unsigned long, NodeFilter) on Document
-PASS Document interface: operation createTreeWalker(Node, unsigned long, NodeFilter)
-PASS Unscopable handled correctly for createTreeWalker(Node, unsigned long, NodeFilter) on Document
-PASS Document interface: operation getElementById(DOMString)
-PASS Unscopable handled correctly for getElementById(DOMString) on Document
-PASS Document interface: attribute children
-PASS Unscopable handled correctly for children property on Document
-PASS Document interface: attribute firstElementChild
-PASS Unscopable handled correctly for firstElementChild property on Document
-PASS Document interface: attribute lastElementChild
-PASS Unscopable handled correctly for lastElementChild property on Document
-PASS Document interface: attribute childElementCount
-PASS Unscopable handled correctly for childElementCount property on Document
-PASS Document interface: operation prepend([object Object],[object Object])
-PASS Unscopable handled correctly for prepend([object Object],[object Object]) on Document
-PASS Document interface: operation append([object Object],[object Object])
-PASS Unscopable handled correctly for append([object Object],[object Object]) on Document
-PASS Document interface: operation querySelector(DOMString)
-PASS Unscopable handled correctly for querySelector(DOMString) on Document
-PASS Document interface: operation querySelectorAll(DOMString)
-PASS Unscopable handled correctly for querySelectorAll(DOMString) on Document
-PASS Document must be primary interface of new Document()
-PASS Stringification of new Document()
-PASS Document interface: new Document() must inherit property "implementation" with the proper type
-PASS Document interface: new Document() must inherit property "URL" with the proper type
-PASS Document interface: new Document() must inherit property "documentURI" with the proper type
-PASS Document interface: new Document() must inherit property "origin" with the proper type
-PASS Document interface: new Document() must inherit property "compatMode" with the proper type
-PASS Document interface: new Document() must inherit property "characterSet" with the proper type
-PASS Document interface: new Document() must inherit property "charset" with the proper type
-PASS Document interface: new Document() must inherit property "inputEncoding" with the proper type
-PASS Document interface: new Document() must inherit property "contentType" with the proper type
-PASS Document interface: new Document() must inherit property "doctype" with the proper type
-PASS Document interface: new Document() must inherit property "documentElement" with the proper type
-PASS Document interface: new Document() must inherit property "getElementsByTagName(DOMString)" with the proper type
-PASS Document interface: calling getElementsByTagName(DOMString) on new Document() with too few arguments must throw TypeError
-PASS Document interface: new Document() must inherit property "getElementsByTagNameNS(DOMString, DOMString)" with the proper type
-PASS Document interface: calling getElementsByTagNameNS(DOMString, DOMString) on new Document() with too few arguments must throw TypeError
-PASS Document interface: new Document() must inherit property "getElementsByClassName(DOMString)" with the proper type
-PASS Document interface: calling getElementsByClassName(DOMString) on new Document() with too few arguments must throw TypeError
-PASS Document interface: new Document() must inherit property "createElement(DOMString, [object Object],[object Object])" with the proper type
-PASS Document interface: calling createElement(DOMString, [object Object],[object Object]) on new Document() with too few arguments must throw TypeError
-PASS Document interface: new Document() must inherit property "createElementNS(DOMString, DOMString, [object Object],[object Object])" with the proper type
-PASS Document interface: calling createElementNS(DOMString, DOMString, [object Object],[object Object]) on new Document() with too few arguments must throw TypeError
-PASS Document interface: new Document() must inherit property "createDocumentFragment()" with the proper type
-PASS Document interface: new Document() must inherit property "createTextNode(DOMString)" with the proper type
-PASS Document interface: calling createTextNode(DOMString) on new Document() with too few arguments must throw TypeError
-PASS Document interface: new Document() must inherit property "createCDATASection(DOMString)" with the proper type
-PASS Document interface: calling createCDATASection(DOMString) on new Document() with too few arguments must throw TypeError
-PASS Document interface: new Document() must inherit property "createComment(DOMString)" with the proper type
-PASS Document interface: calling createComment(DOMString) on new Document() with too few arguments must throw TypeError
-PASS Document interface: new Document() must inherit property "createProcessingInstruction(DOMString, DOMString)" with the proper type
-PASS Document interface: calling createProcessingInstruction(DOMString, DOMString) on new Document() with too few arguments must throw TypeError
-PASS Document interface: new Document() must inherit property "importNode(Node, boolean)" with the proper type
-PASS Document interface: calling importNode(Node, boolean) on new Document() with too few arguments must throw TypeError
-PASS Document interface: new Document() must inherit property "adoptNode(Node)" with the proper type
-PASS Document interface: calling adoptNode(Node) on new Document() with too few arguments must throw TypeError
-PASS Document interface: new Document() must inherit property "createAttribute(DOMString)" with the proper type
-PASS Document interface: calling createAttribute(DOMString) on new Document() with too few arguments must throw TypeError
-PASS Document interface: new Document() must inherit property "createAttributeNS(DOMString, DOMString)" with the proper type
-PASS Document interface: calling createAttributeNS(DOMString, DOMString) on new Document() with too few arguments must throw TypeError
-PASS Document interface: new Document() must inherit property "createEvent(DOMString)" with the proper type
-PASS Document interface: calling createEvent(DOMString) on new Document() with too few arguments must throw TypeError
-PASS Document interface: new Document() must inherit property "createRange()" with the proper type
-PASS Document interface: new Document() must inherit property "createNodeIterator(Node, unsigned long, NodeFilter)" with the proper type
-PASS Document interface: calling createNodeIterator(Node, unsigned long, NodeFilter) on new Document() with too few arguments must throw TypeError
-PASS Document interface: new Document() must inherit property "createTreeWalker(Node, unsigned long, NodeFilter)" with the proper type
-PASS Document interface: calling createTreeWalker(Node, unsigned long, NodeFilter) on new Document() with too few arguments must throw TypeError
-PASS Document interface: new Document() must inherit property "getElementById(DOMString)" with the proper type
-PASS Document interface: calling getElementById(DOMString) on new Document() with too few arguments must throw TypeError
-PASS Document interface: new Document() must inherit property "children" with the proper type
-PASS Document interface: new Document() must inherit property "firstElementChild" with the proper type
-PASS Document interface: new Document() must inherit property "lastElementChild" with the proper type
-PASS Document interface: new Document() must inherit property "childElementCount" with the proper type
-PASS Document interface: new Document() must inherit property "prepend([object Object],[object Object])" with the proper type
-PASS Document interface: calling prepend([object Object],[object Object]) on new Document() with too few arguments must throw TypeError
-PASS Document interface: new Document() must inherit property "append([object Object],[object Object])" with the proper type
-PASS Document interface: calling append([object Object],[object Object]) on new Document() with too few arguments must throw TypeError
-PASS Document interface: new Document() must inherit property "querySelector(DOMString)" with the proper type
-PASS Document interface: calling querySelector(DOMString) on new Document() with too few arguments must throw TypeError
-PASS Document interface: new Document() must inherit property "querySelectorAll(DOMString)" with the proper type
-PASS Document interface: calling querySelectorAll(DOMString) on new Document() with too few arguments must throw TypeError
-PASS Node interface: new Document() must inherit property "ELEMENT_NODE" with the proper type
-PASS Node interface: new Document() must inherit property "ATTRIBUTE_NODE" with the proper type
-PASS Node interface: new Document() must inherit property "TEXT_NODE" with the proper type
-PASS Node interface: new Document() must inherit property "CDATA_SECTION_NODE" with the proper type
-PASS Node interface: new Document() must inherit property "ENTITY_REFERENCE_NODE" with the proper type
-PASS Node interface: new Document() must inherit property "ENTITY_NODE" with the proper type
-PASS Node interface: new Document() must inherit property "PROCESSING_INSTRUCTION_NODE" with the proper type
-PASS Node interface: new Document() must inherit property "COMMENT_NODE" with the proper type
-PASS Node interface: new Document() must inherit property "DOCUMENT_NODE" with the proper type
-PASS Node interface: new Document() must inherit property "DOCUMENT_TYPE_NODE" with the proper type
-PASS Node interface: new Document() must inherit property "DOCUMENT_FRAGMENT_NODE" with the proper type
-PASS Node interface: new Document() must inherit property "NOTATION_NODE" with the proper type
-PASS Node interface: new Document() must inherit property "nodeType" with the proper type
-PASS Node interface: new Document() must inherit property "nodeName" with the proper type
-PASS Node interface: new Document() must inherit property "baseURI" with the proper type
-PASS Node interface: new Document() must inherit property "isConnected" with the proper type
-PASS Node interface: new Document() must inherit property "ownerDocument" with the proper type
-PASS Node interface: new Document() must inherit property "getRootNode(GetRootNodeOptions)" with the proper type
-PASS Node interface: calling getRootNode(GetRootNodeOptions) on new Document() with too few arguments must throw TypeError
-PASS Node interface: new Document() must inherit property "parentNode" with the proper type
-PASS Node interface: new Document() must inherit property "parentElement" with the proper type
-PASS Node interface: new Document() must inherit property "hasChildNodes()" with the proper type
-PASS Node interface: new Document() must inherit property "childNodes" with the proper type
-PASS Node interface: new Document() must inherit property "firstChild" with the proper type
-PASS Node interface: new Document() must inherit property "lastChild" with the proper type
-PASS Node interface: new Document() must inherit property "previousSibling" with the proper type
-PASS Node interface: new Document() must inherit property "nextSibling" with the proper type
-PASS Node interface: new Document() must inherit property "nodeValue" with the proper type
-PASS Node interface: new Document() must inherit property "textContent" with the proper type
-PASS Node interface: new Document() must inherit property "normalize()" with the proper type
-PASS Node interface: new Document() must inherit property "cloneNode(boolean)" with the proper type
-PASS Node interface: calling cloneNode(boolean) on new Document() with too few arguments must throw TypeError
-PASS Node interface: new Document() must inherit property "isEqualNode(Node)" with the proper type
-PASS Node interface: calling isEqualNode(Node) on new Document() with too few arguments must throw TypeError
-PASS Node interface: new Document() must inherit property "isSameNode(Node)" with the proper type
-PASS Node interface: calling isSameNode(Node) on new Document() with too few arguments must throw TypeError
-PASS Node interface: new Document() must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type
-PASS Node interface: new Document() must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type
-PASS Node interface: new Document() must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type
-PASS Node interface: new Document() must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type
-PASS Node interface: new Document() must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type
-PASS Node interface: new Document() must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type
-PASS Node interface: new Document() must inherit property "compareDocumentPosition(Node)" with the proper type
-PASS Node interface: calling compareDocumentPosition(Node) on new Document() with too few arguments must throw TypeError
-PASS Node interface: new Document() must inherit property "contains(Node)" with the proper type
-PASS Node interface: calling contains(Node) on new Document() with too few arguments must throw TypeError
-PASS Node interface: new Document() must inherit property "lookupPrefix(DOMString)" with the proper type
-PASS Node interface: calling lookupPrefix(DOMString) on new Document() with too few arguments must throw TypeError
-PASS Node interface: new Document() must inherit property "lookupNamespaceURI(DOMString)" with the proper type
-PASS Node interface: calling lookupNamespaceURI(DOMString) on new Document() with too few arguments must throw TypeError
-PASS Node interface: new Document() must inherit property "isDefaultNamespace(DOMString)" with the proper type
-PASS Node interface: calling isDefaultNamespace(DOMString) on new Document() with too few arguments must throw TypeError
-PASS Node interface: new Document() must inherit property "insertBefore(Node, Node)" with the proper type
-PASS Node interface: calling insertBefore(Node, Node) on new Document() with too few arguments must throw TypeError
-PASS Node interface: new Document() must inherit property "appendChild(Node)" with the proper type
-PASS Node interface: calling appendChild(Node) on new Document() with too few arguments must throw TypeError
-PASS Node interface: new Document() must inherit property "replaceChild(Node, Node)" with the proper type
-PASS Node interface: calling replaceChild(Node, Node) on new Document() with too few arguments must throw TypeError
-PASS Node interface: new Document() must inherit property "removeChild(Node)" with the proper type
-PASS Node interface: calling removeChild(Node) on new Document() with too few arguments must throw TypeError
-PASS EventTarget interface: new Document() must inherit property "addEventListener(DOMString, EventListener, [object Object],[object Object])" with the proper type
-PASS EventTarget interface: calling addEventListener(DOMString, EventListener, [object Object],[object Object]) on new Document() with too few arguments must throw TypeError
-PASS EventTarget interface: new Document() must inherit property "removeEventListener(DOMString, EventListener, [object Object],[object Object])" with the proper type
-PASS EventTarget interface: calling removeEventListener(DOMString, EventListener, [object Object],[object Object]) on new Document() with too few arguments must throw TypeError
-PASS EventTarget interface: new Document() must inherit property "dispatchEvent(Event)" with the proper type
-PASS EventTarget interface: calling dispatchEvent(Event) on new Document() with too few arguments must throw TypeError
-PASS XMLDocument interface: existence and properties of interface object
-PASS XMLDocument interface object length
-PASS XMLDocument interface object name
-PASS XMLDocument interface: existence and properties of interface prototype object
-PASS XMLDocument interface: existence and properties of interface prototype object's "constructor" property
-PASS XMLDocument interface: existence and properties of interface prototype object's @@unscopables property
-PASS XMLDocument must be primary interface of xmlDoc
-PASS Stringification of xmlDoc
-PASS Document interface: xmlDoc must inherit property "implementation" with the proper type
-PASS Document interface: xmlDoc must inherit property "URL" with the proper type
-PASS Document interface: xmlDoc must inherit property "documentURI" with the proper type
-PASS Document interface: xmlDoc must inherit property "origin" with the proper type
-PASS Document interface: xmlDoc must inherit property "compatMode" with the proper type
-PASS Document interface: xmlDoc must inherit property "characterSet" with the proper type
-PASS Document interface: xmlDoc must inherit property "charset" with the proper type
-PASS Document interface: xmlDoc must inherit property "inputEncoding" with the proper type
-PASS Document interface: xmlDoc must inherit property "contentType" with the proper type
-PASS Document interface: xmlDoc must inherit property "doctype" with the proper type
-PASS Document interface: xmlDoc must inherit property "documentElement" with the proper type
-PASS Document interface: xmlDoc must inherit property "getElementsByTagName(DOMString)" with the proper type
-PASS Document interface: calling getElementsByTagName(DOMString) on xmlDoc with too few arguments must throw TypeError
-PASS Document interface: xmlDoc must inherit property "getElementsByTagNameNS(DOMString, DOMString)" with the proper type
-PASS Document interface: calling getElementsByTagNameNS(DOMString, DOMString) on xmlDoc with too few arguments must throw TypeError
-PASS Document interface: xmlDoc must inherit property "getElementsByClassName(DOMString)" with the proper type
-PASS Document interface: calling getElementsByClassName(DOMString) on xmlDoc with too few arguments must throw TypeError
-PASS Document interface: xmlDoc must inherit property "createElement(DOMString, [object Object],[object Object])" with the proper type
-PASS Document interface: calling createElement(DOMString, [object Object],[object Object]) on xmlDoc with too few arguments must throw TypeError
-PASS Document interface: xmlDoc must inherit property "createElementNS(DOMString, DOMString, [object Object],[object Object])" with the proper type
-PASS Document interface: calling createElementNS(DOMString, DOMString, [object Object],[object Object]) on xmlDoc with too few arguments must throw TypeError
-PASS Document interface: xmlDoc must inherit property "createDocumentFragment()" with the proper type
-PASS Document interface: xmlDoc must inherit property "createTextNode(DOMString)" with the proper type
-PASS Document interface: calling createTextNode(DOMString) on xmlDoc with too few arguments must throw TypeError
-PASS Document interface: xmlDoc must inherit property "createCDATASection(DOMString)" with the proper type
-PASS Document interface: calling createCDATASection(DOMString) on xmlDoc with too few arguments must throw TypeError
-PASS Document interface: xmlDoc must inherit property "createComment(DOMString)" with the proper type
-PASS Document interface: calling createComment(DOMString) on xmlDoc with too few arguments must throw TypeError
-PASS Document interface: xmlDoc must inherit property "createProcessingInstruction(DOMString, DOMString)" with the proper type
-PASS Document interface: calling createProcessingInstruction(DOMString, DOMString) on xmlDoc with too few arguments must throw TypeError
-PASS Document interface: xmlDoc must inherit property "importNode(Node, boolean)" with the proper type
-PASS Document interface: calling importNode(Node, boolean) on xmlDoc with too few arguments must throw TypeError
-PASS Document interface: xmlDoc must inherit property "adoptNode(Node)" with the proper type
-PASS Document interface: calling adoptNode(Node) on xmlDoc with too few arguments must throw TypeError
-PASS Document interface: xmlDoc must inherit property "createAttribute(DOMString)" with the proper type
-PASS Document interface: calling createAttribute(DOMString) on xmlDoc with too few arguments must throw TypeError
-PASS Document interface: xmlDoc must inherit property "createAttributeNS(DOMString, DOMString)" with the proper type
-PASS Document interface: calling createAttributeNS(DOMString, DOMString) on xmlDoc with too few arguments must throw TypeError
-PASS Document interface: xmlDoc must inherit property "createEvent(DOMString)" with the proper type
-PASS Document interface: calling createEvent(DOMString) on xmlDoc with too few arguments must throw TypeError
-PASS Document interface: xmlDoc must inherit property "createRange()" with the proper type
-PASS Document interface: xmlDoc must inherit property "createNodeIterator(Node, unsigned long, NodeFilter)" with the proper type
-PASS Document interface: calling createNodeIterator(Node, unsigned long, NodeFilter) on xmlDoc with too few arguments must throw TypeError
-PASS Document interface: xmlDoc must inherit property "createTreeWalker(Node, unsigned long, NodeFilter)" with the proper type
-PASS Document interface: calling createTreeWalker(Node, unsigned long, NodeFilter) on xmlDoc with too few arguments must throw TypeError
-PASS Document interface: xmlDoc must inherit property "getElementById(DOMString)" with the proper type
-PASS Document interface: calling getElementById(DOMString) on xmlDoc with too few arguments must throw TypeError
-PASS Document interface: xmlDoc must inherit property "children" with the proper type
-PASS Document interface: xmlDoc must inherit property "firstElementChild" with the proper type
-PASS Document interface: xmlDoc must inherit property "lastElementChild" with the proper type
-PASS Document interface: xmlDoc must inherit property "childElementCount" with the proper type
-PASS Document interface: xmlDoc must inherit property "prepend([object Object],[object Object])" with the proper type
-PASS Document interface: calling prepend([object Object],[object Object]) on xmlDoc with too few arguments must throw TypeError
-PASS Document interface: xmlDoc must inherit property "append([object Object],[object Object])" with the proper type
-PASS Document interface: calling append([object Object],[object Object]) on xmlDoc with too few arguments must throw TypeError
-PASS Document interface: xmlDoc must inherit property "querySelector(DOMString)" with the proper type
-PASS Document interface: calling querySelector(DOMString) on xmlDoc with too few arguments must throw TypeError
-PASS Document interface: xmlDoc must inherit property "querySelectorAll(DOMString)" with the proper type
-PASS Document interface: calling querySelectorAll(DOMString) on xmlDoc with too few arguments must throw TypeError
-PASS Node interface: xmlDoc must inherit property "ELEMENT_NODE" with the proper type
-PASS Node interface: xmlDoc must inherit property "ATTRIBUTE_NODE" with the proper type
-PASS Node interface: xmlDoc must inherit property "TEXT_NODE" with the proper type
-PASS Node interface: xmlDoc must inherit property "CDATA_SECTION_NODE" with the proper type
-PASS Node interface: xmlDoc must inherit property "ENTITY_REFERENCE_NODE" with the proper type
-PASS Node interface: xmlDoc must inherit property "ENTITY_NODE" with the proper type
-PASS Node interface: xmlDoc must inherit property "PROCESSING_INSTRUCTION_NODE" with the proper type
-PASS Node interface: xmlDoc must inherit property "COMMENT_NODE" with the proper type
-PASS Node interface: xmlDoc must inherit property "DOCUMENT_NODE" with the proper type
-PASS Node interface: xmlDoc must inherit property "DOCUMENT_TYPE_NODE" with the proper type
-PASS Node interface: xmlDoc must inherit property "DOCUMENT_FRAGMENT_NODE" with the proper type
-PASS Node interface: xmlDoc must inherit property "NOTATION_NODE" with the proper type
-PASS Node interface: xmlDoc must inherit property "nodeType" with the proper type
-PASS Node interface: xmlDoc must inherit property "nodeName" with the proper type
-PASS Node interface: xmlDoc must inherit property "baseURI" with the proper type
-PASS Node interface: xmlDoc must inherit property "isConnected" with the proper type
-PASS Node interface: xmlDoc must inherit property "ownerDocument" with the proper type
-PASS Node interface: xmlDoc must inherit property "getRootNode(GetRootNodeOptions)" with the proper type
-PASS Node interface: calling getRootNode(GetRootNodeOptions) on xmlDoc with too few arguments must throw TypeError
-PASS Node interface: xmlDoc must inherit property "parentNode" with the proper type
-PASS Node interface: xmlDoc must inherit property "parentElement" with the proper type
-PASS Node interface: xmlDoc must inherit property "hasChildNodes()" with the proper type
-PASS Node interface: xmlDoc must inherit property "childNodes" with the proper type
-PASS Node interface: xmlDoc must inherit property "firstChild" with the proper type
-PASS Node interface: xmlDoc must inherit property "lastChild" with the proper type
-PASS Node interface: xmlDoc must inherit property "previousSibling" with the proper type
-PASS Node interface: xmlDoc must inherit property "nextSibling" with the proper type
-PASS Node interface: xmlDoc must inherit property "nodeValue" with the proper type
-PASS Node interface: xmlDoc must inherit property "textContent" with the proper type
-PASS Node interface: xmlDoc must inherit property "normalize()" with the proper type
-PASS Node interface: xmlDoc must inherit property "cloneNode(boolean)" with the proper type
-PASS Node interface: calling cloneNode(boolean) on xmlDoc with too few arguments must throw TypeError
-PASS Node interface: xmlDoc must inherit property "isEqualNode(Node)" with the proper type
-PASS Node interface: calling isEqualNode(Node) on xmlDoc with too few arguments must throw TypeError
-PASS Node interface: xmlDoc must inherit property "isSameNode(Node)" with the proper type
-PASS Node interface: calling isSameNode(Node) on xmlDoc with too few arguments must throw TypeError
-PASS Node interface: xmlDoc must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type
-PASS Node interface: xmlDoc must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type
-PASS Node interface: xmlDoc must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type
-PASS Node interface: xmlDoc must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type
-PASS Node interface: xmlDoc must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type
-PASS Node interface: xmlDoc must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type
-PASS Node interface: xmlDoc must inherit property "compareDocumentPosition(Node)" with the proper type
-PASS Node interface: calling compareDocumentPosition(Node) on xmlDoc with too few arguments must throw TypeError
-PASS Node interface: xmlDoc must inherit property "contains(Node)" with the proper type
-PASS Node interface: calling contains(Node) on xmlDoc with too few arguments must throw TypeError
-PASS Node interface: xmlDoc must inherit property "lookupPrefix(DOMString)" with the proper type
-PASS Node interface: calling lookupPrefix(DOMString) on xmlDoc with too few arguments must throw TypeError
-PASS Node interface: xmlDoc must inherit property "lookupNamespaceURI(DOMString)" with the proper type
-PASS Node interface: calling lookupNamespaceURI(DOMString) on xmlDoc with too few arguments must throw TypeError
-PASS Node interface: xmlDoc must inherit property "isDefaultNamespace(DOMString)" with the proper type
-PASS Node interface: calling isDefaultNamespace(DOMString) on xmlDoc with too few arguments must throw TypeError
-PASS Node interface: xmlDoc must inherit property "insertBefore(Node, Node)" with the proper type
-PASS Node interface: calling insertBefore(Node, Node) on xmlDoc with too few arguments must throw TypeError
-PASS Node interface: xmlDoc must inherit property "appendChild(Node)" with the proper type
-PASS Node interface: calling appendChild(Node) on xmlDoc with too few arguments must throw TypeError
-PASS Node interface: xmlDoc must inherit property "replaceChild(Node, Node)" with the proper type
-PASS Node interface: calling replaceChild(Node, Node) on xmlDoc with too few arguments must throw TypeError
-PASS Node interface: xmlDoc must inherit property "removeChild(Node)" with the proper type
-PASS Node interface: calling removeChild(Node) on xmlDoc with too few arguments must throw TypeError
-PASS EventTarget interface: xmlDoc must inherit property "addEventListener(DOMString, EventListener, [object Object],[object Object])" with the proper type
-PASS EventTarget interface: calling addEventListener(DOMString, EventListener, [object Object],[object Object]) on xmlDoc with too few arguments must throw TypeError
-PASS EventTarget interface: xmlDoc must inherit property "removeEventListener(DOMString, EventListener, [object Object],[object Object])" with the proper type
-PASS EventTarget interface: calling removeEventListener(DOMString, EventListener, [object Object],[object Object]) on xmlDoc with too few arguments must throw TypeError
-PASS EventTarget interface: xmlDoc must inherit property "dispatchEvent(Event)" with the proper type
-PASS EventTarget interface: calling dispatchEvent(Event) on xmlDoc with too few arguments must throw TypeError
-PASS DOMImplementation interface: existence and properties of interface object
-PASS DOMImplementation interface object length
-PASS DOMImplementation interface object name
-PASS DOMImplementation interface: existence and properties of interface prototype object
-PASS DOMImplementation interface: existence and properties of interface prototype object's "constructor" property
-PASS DOMImplementation interface: existence and properties of interface prototype object's @@unscopables property
-PASS DOMImplementation interface: operation createDocumentType(DOMString, DOMString, DOMString)
-PASS Unscopable handled correctly for createDocumentType(DOMString, DOMString, DOMString) on DOMImplementation
-PASS DOMImplementation interface: operation createDocument(DOMString, DOMString, DocumentType)
-PASS Unscopable handled correctly for createDocument(DOMString, DOMString, DocumentType) on DOMImplementation
-PASS DOMImplementation interface: operation createHTMLDocument(DOMString)
-PASS Unscopable handled correctly for createHTMLDocument(DOMString) on DOMImplementation
-PASS DOMImplementation interface: operation hasFeature()
-PASS Unscopable handled correctly for hasFeature() on DOMImplementation
-PASS DOMImplementation must be primary interface of document.implementation
-PASS Stringification of document.implementation
-PASS DOMImplementation interface: document.implementation must inherit property "createDocumentType(DOMString, DOMString, DOMString)" with the proper type
-PASS DOMImplementation interface: calling createDocumentType(DOMString, DOMString, DOMString) on document.implementation with too few arguments must throw TypeError
-PASS DOMImplementation interface: document.implementation must inherit property "createDocument(DOMString, DOMString, DocumentType)" with the proper type
-PASS DOMImplementation interface: calling createDocument(DOMString, DOMString, DocumentType) on document.implementation with too few arguments must throw TypeError
-PASS DOMImplementation interface: document.implementation must inherit property "createHTMLDocument(DOMString)" with the proper type
-PASS DOMImplementation interface: calling createHTMLDocument(DOMString) on document.implementation with too few arguments must throw TypeError
-PASS DOMImplementation interface: document.implementation must inherit property "hasFeature()" with the proper type
-PASS DocumentType interface: existence and properties of interface object
-PASS DocumentType interface object length
-PASS DocumentType interface object name
-PASS DocumentType interface: existence and properties of interface prototype object
-PASS DocumentType interface: existence and properties of interface prototype object's "constructor" property
-FAIL DocumentType interface: existence and properties of interface prototype object's @@unscopables property assert_false: DocumentType.prototype[Symbol.unscopables] should not be writable expected false got true
-PASS DocumentType interface: attribute name
-PASS Unscopable handled correctly for name property on DocumentType
-PASS DocumentType interface: attribute publicId
-PASS Unscopable handled correctly for publicId property on DocumentType
-PASS DocumentType interface: attribute systemId
-PASS Unscopable handled correctly for systemId property on DocumentType
-PASS DocumentType interface: operation before([object Object],[object Object])
-PASS Unscopable handled correctly for before([object Object],[object Object]) on DocumentType
-PASS DocumentType interface: operation after([object Object],[object Object])
-PASS Unscopable handled correctly for after([object Object],[object Object]) on DocumentType
-PASS DocumentType interface: operation replaceWith([object Object],[object Object])
-PASS Unscopable handled correctly for replaceWith([object Object],[object Object]) on DocumentType
-PASS DocumentType interface: operation remove()
-PASS Unscopable handled correctly for remove() on DocumentType
-PASS DocumentType must be primary interface of document.doctype
-PASS Stringification of document.doctype
-PASS DocumentType interface: document.doctype must inherit property "name" with the proper type
-PASS DocumentType interface: document.doctype must inherit property "publicId" with the proper type
-PASS DocumentType interface: document.doctype must inherit property "systemId" with the proper type
-PASS DocumentType interface: document.doctype must inherit property "before([object Object],[object Object])" with the proper type
-PASS DocumentType interface: calling before([object Object],[object Object]) on document.doctype with too few arguments must throw TypeError
-PASS DocumentType interface: document.doctype must inherit property "after([object Object],[object Object])" with the proper type
-PASS DocumentType interface: calling after([object Object],[object Object]) on document.doctype with too few arguments must throw TypeError
-PASS DocumentType interface: document.doctype must inherit property "replaceWith([object Object],[object Object])" with the proper type
-PASS DocumentType interface: calling replaceWith([object Object],[object Object]) on document.doctype with too few arguments must throw TypeError
-PASS DocumentType interface: document.doctype must inherit property "remove()" with the proper type
-PASS Node interface: document.doctype must inherit property "ELEMENT_NODE" with the proper type
-PASS Node interface: document.doctype must inherit property "ATTRIBUTE_NODE" with the proper type
-PASS Node interface: document.doctype must inherit property "TEXT_NODE" with the proper type
-PASS Node interface: document.doctype must inherit property "CDATA_SECTION_NODE" with the proper type
-PASS Node interface: document.doctype must inherit property "ENTITY_REFERENCE_NODE" with the proper type
-PASS Node interface: document.doctype must inherit property "ENTITY_NODE" with the proper type
-PASS Node interface: document.doctype must inherit property "PROCESSING_INSTRUCTION_NODE" with the proper type
-PASS Node interface: document.doctype must inherit property "COMMENT_NODE" with the proper type
-PASS Node interface: document.doctype must inherit property "DOCUMENT_NODE" with the proper type
-PASS Node interface: document.doctype must inherit property "DOCUMENT_TYPE_NODE" with the proper type
-PASS Node interface: document.doctype must inherit property "DOCUMENT_FRAGMENT_NODE" with the proper type
-PASS Node interface: document.doctype must inherit property "NOTATION_NODE" with the proper type
-PASS Node interface: document.doctype must inherit property "nodeType" with the proper type
-PASS Node interface: document.doctype must inherit property "nodeName" with the proper type
-PASS Node interface: document.doctype must inherit property "baseURI" with the proper type
-PASS Node interface: document.doctype must inherit property "isConnected" with the proper type
-PASS Node interface: document.doctype must inherit property "ownerDocument" with the proper type
-PASS Node interface: document.doctype must inherit property "getRootNode(GetRootNodeOptions)" with the proper type
-PASS Node interface: calling getRootNode(GetRootNodeOptions) on document.doctype with too few arguments must throw TypeError
-PASS Node interface: document.doctype must inherit property "parentNode" with the proper type
-PASS Node interface: document.doctype must inherit property "parentElement" with the proper type
-PASS Node interface: document.doctype must inherit property "hasChildNodes()" with the proper type
-PASS Node interface: document.doctype must inherit property "childNodes" with the proper type
-PASS Node interface: document.doctype must inherit property "firstChild" with the proper type
-PASS Node interface: document.doctype must inherit property "lastChild" with the proper type
-PASS Node interface: document.doctype must inherit property "previousSibling" with the proper type
-PASS Node interface: document.doctype must inherit property "nextSibling" with the proper type
-PASS Node interface: document.doctype must inherit property "nodeValue" with the proper type
-PASS Node interface: document.doctype must inherit property "textContent" with the proper type
-PASS Node interface: document.doctype must inherit property "normalize()" with the proper type
-PASS Node interface: document.doctype must inherit property "cloneNode(boolean)" with the proper type
-PASS Node interface: calling cloneNode(boolean) on document.doctype with too few arguments must throw TypeError
-PASS Node interface: document.doctype must inherit property "isEqualNode(Node)" with the proper type
-PASS Node interface: calling isEqualNode(Node) on document.doctype with too few arguments must throw TypeError
-PASS Node interface: document.doctype must inherit property "isSameNode(Node)" with the proper type
-PASS Node interface: calling isSameNode(Node) on document.doctype with too few arguments must throw TypeError
-PASS Node interface: document.doctype must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type
-PASS Node interface: document.doctype must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type
-PASS Node interface: document.doctype must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type
-PASS Node interface: document.doctype must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type
-PASS Node interface: document.doctype must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type
-PASS Node interface: document.doctype must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type
-PASS Node interface: document.doctype must inherit property "compareDocumentPosition(Node)" with the proper type
-PASS Node interface: calling compareDocumentPosition(Node) on document.doctype with too few arguments must throw TypeError
-PASS Node interface: document.doctype must inherit property "contains(Node)" with the proper type
-PASS Node interface: calling contains(Node) on document.doctype with too few arguments must throw TypeError
-PASS Node interface: document.doctype must inherit property "lookupPrefix(DOMString)" with the proper type
-PASS Node interface: calling lookupPrefix(DOMString) on document.doctype with too few arguments must throw TypeError
-PASS Node interface: document.doctype must inherit property "lookupNamespaceURI(DOMString)" with the proper type
-PASS Node interface: calling lookupNamespaceURI(DOMString) on document.doctype with too few arguments must throw TypeError
-PASS Node interface: document.doctype must inherit property "isDefaultNamespace(DOMString)" with the proper type
-PASS Node interface: calling isDefaultNamespace(DOMString) on document.doctype with too few arguments must throw TypeError
-PASS Node interface: document.doctype must inherit property "insertBefore(Node, Node)" with the proper type
-PASS Node interface: calling insertBefore(Node, Node) on document.doctype with too few arguments must throw TypeError
-PASS Node interface: document.doctype must inherit property "appendChild(Node)" with the proper type
-PASS Node interface: calling appendChild(Node) on document.doctype with too few arguments must throw TypeError
-PASS Node interface: document.doctype must inherit property "replaceChild(Node, Node)" with the proper type
-PASS Node interface: calling replaceChild(Node, Node) on document.doctype with too few arguments must throw TypeError
-PASS Node interface: document.doctype must inherit property "removeChild(Node)" with the proper type
-PASS Node interface: calling removeChild(Node) on document.doctype with too few arguments must throw TypeError
-PASS EventTarget interface: document.doctype must inherit property "addEventListener(DOMString, EventListener, [object Object],[object Object])" with the proper type
-PASS EventTarget interface: calling addEventListener(DOMString, EventListener, [object Object],[object Object]) on document.doctype with too few arguments must throw TypeError
-PASS EventTarget interface: document.doctype must inherit property "removeEventListener(DOMString, EventListener, [object Object],[object Object])" with the proper type
-PASS EventTarget interface: calling removeEventListener(DOMString, EventListener, [object Object],[object Object]) on document.doctype with too few arguments must throw TypeError
-PASS EventTarget interface: document.doctype must inherit property "dispatchEvent(Event)" with the proper type
-PASS EventTarget interface: calling dispatchEvent(Event) on document.doctype with too few arguments must throw TypeError
-PASS DocumentFragment interface: existence and properties of interface object
-PASS DocumentFragment interface object length
-PASS DocumentFragment interface object name
-PASS DocumentFragment interface: existence and properties of interface prototype object
-PASS DocumentFragment interface: existence and properties of interface prototype object's "constructor" property
-FAIL DocumentFragment interface: existence and properties of interface prototype object's @@unscopables property assert_false: DocumentFragment.prototype[Symbol.unscopables] should not be writable expected false got true
-PASS DocumentFragment interface: operation getElementById(DOMString)
-PASS Unscopable handled correctly for getElementById(DOMString) on DocumentFragment
-PASS DocumentFragment interface: attribute children
-PASS Unscopable handled correctly for children property on DocumentFragment
-PASS DocumentFragment interface: attribute firstElementChild
-PASS Unscopable handled correctly for firstElementChild property on DocumentFragment
-PASS DocumentFragment interface: attribute lastElementChild
-PASS Unscopable handled correctly for lastElementChild property on DocumentFragment
-PASS DocumentFragment interface: attribute childElementCount
-PASS Unscopable handled correctly for childElementCount property on DocumentFragment
-PASS DocumentFragment interface: operation prepend([object Object],[object Object])
-PASS Unscopable handled correctly for prepend([object Object],[object Object]) on DocumentFragment
-PASS DocumentFragment interface: operation append([object Object],[object Object])
-PASS Unscopable handled correctly for append([object Object],[object Object]) on DocumentFragment
-PASS DocumentFragment interface: operation querySelector(DOMString)
-PASS Unscopable handled correctly for querySelector(DOMString) on DocumentFragment
-PASS DocumentFragment interface: operation querySelectorAll(DOMString)
-PASS Unscopable handled correctly for querySelectorAll(DOMString) on DocumentFragment
-PASS DocumentFragment must be primary interface of document.createDocumentFragment()
-PASS Stringification of document.createDocumentFragment()
-PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "getElementById(DOMString)" with the proper type
-PASS DocumentFragment interface: calling getElementById(DOMString) on document.createDocumentFragment() with too few arguments must throw TypeError
-PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "children" with the proper type
-PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "firstElementChild" with the proper type
-PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "lastElementChild" with the proper type
-PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "childElementCount" with the proper type
-PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "prepend([object Object],[object Object])" with the proper type
-PASS DocumentFragment interface: calling prepend([object Object],[object Object]) on document.createDocumentFragment() with too few arguments must throw TypeError
-PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "append([object Object],[object Object])" with the proper type
-PASS DocumentFragment interface: calling append([object Object],[object Object]) on document.createDocumentFragment() with too few arguments must throw TypeError
-PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "querySelector(DOMString)" with the proper type
-PASS DocumentFragment interface: calling querySelector(DOMString) on document.createDocumentFragment() with too few arguments must throw TypeError
-PASS DocumentFragment interface: document.createDocumentFragment() must inherit property "querySelectorAll(DOMString)" with the proper type
-PASS DocumentFragment interface: calling querySelectorAll(DOMString) on document.createDocumentFragment() with too few arguments must throw TypeError
-PASS Node interface: document.createDocumentFragment() must inherit property "ELEMENT_NODE" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "ATTRIBUTE_NODE" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "TEXT_NODE" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "CDATA_SECTION_NODE" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "ENTITY_REFERENCE_NODE" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "ENTITY_NODE" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "PROCESSING_INSTRUCTION_NODE" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "COMMENT_NODE" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_NODE" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_TYPE_NODE" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_FRAGMENT_NODE" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "NOTATION_NODE" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "nodeType" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "nodeName" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "baseURI" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "isConnected" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "ownerDocument" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "getRootNode(GetRootNodeOptions)" with the proper type
-PASS Node interface: calling getRootNode(GetRootNodeOptions) on document.createDocumentFragment() with too few arguments must throw TypeError
-PASS Node interface: document.createDocumentFragment() must inherit property "parentNode" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "parentElement" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "hasChildNodes()" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "childNodes" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "firstChild" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "lastChild" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "previousSibling" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "nextSibling" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "nodeValue" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "textContent" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "normalize()" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "cloneNode(boolean)" with the proper type
-PASS Node interface: calling cloneNode(boolean) on document.createDocumentFragment() with too few arguments must throw TypeError
-PASS Node interface: document.createDocumentFragment() must inherit property "isEqualNode(Node)" with the proper type
-PASS Node interface: calling isEqualNode(Node) on document.createDocumentFragment() with too few arguments must throw TypeError
-PASS Node interface: document.createDocumentFragment() must inherit property "isSameNode(Node)" with the proper type
-PASS Node interface: calling isSameNode(Node) on document.createDocumentFragment() with too few arguments must throw TypeError
-PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type
-PASS Node interface: document.createDocumentFragment() must inherit property "compareDocumentPosition(Node)" with the proper type
-PASS Node interface: calling compareDocumentPosition(Node) on document.createDocumentFragment() with too few arguments must throw TypeError
-PASS Node interface: document.createDocumentFragment() must inherit property "contains(Node)" with the proper type
-PASS Node interface: calling contains(Node) on document.createDocumentFragment() with too few arguments must throw TypeError
-PASS Node interface: document.createDocumentFragment() must inherit property "lookupPrefix(DOMString)" with the proper type
-PASS Node interface: calling lookupPrefix(DOMString) on document.createDocumentFragment() with too few arguments must throw TypeError
-PASS Node interface: document.createDocumentFragment() must inherit property "lookupNamespaceURI(DOMString)" with the proper type
-PASS Node interface: calling lookupNamespaceURI(DOMString) on document.createDocumentFragment() with too few arguments must throw TypeError
-PASS Node interface: document.createDocumentFragment() must inherit property "isDefaultNamespace(DOMString)" with the proper type
-PASS Node interface: calling isDefaultNamespace(DOMString) on document.createDocumentFragment() with too few arguments must throw TypeError
-PASS Node interface: document.createDocumentFragment() must inherit property "insertBefore(Node, Node)" with the proper type
-PASS Node interface: calling insertBefore(Node, Node) on document.createDocumentFragment() with too few arguments must throw TypeError
-PASS Node interface: document.createDocumentFragment() must inherit property "appendChild(Node)" with the proper type
-PASS Node interface: calling appendChild(Node) on document.createDocumentFragment() with too few arguments must throw TypeError
-PASS Node interface: document.createDocumentFragment() must inherit property "replaceChild(Node, Node)" with the proper type
-PASS Node interface: calling replaceChild(Node, Node) on document.createDocumentFragment() with too few arguments must throw TypeError
-PASS Node interface: document.createDocumentFragment() must inherit property "removeChild(Node)" with the proper type
-PASS Node interface: calling removeChild(Node) on document.createDocumentFragment() with too few arguments must throw TypeError
-PASS EventTarget interface: document.createDocumentFragment() must inherit property "addEventListener(DOMString, EventListener, [object Object],[object Object])" with the proper type
-PASS EventTarget interface: calling addEventListener(DOMString, EventListener, [object Object],[object Object]) on document.createDocumentFragment() with too few arguments must throw TypeError
-PASS EventTarget interface: document.createDocumentFragment() must inherit property "removeEventListener(DOMString, EventListener, [object Object],[object Object])" with the proper type
-PASS EventTarget interface: calling removeEventListener(DOMString, EventListener, [object Object],[object Object]) on document.createDocumentFragment() with too few arguments must throw TypeError
-PASS EventTarget interface: document.createDocumentFragment() must inherit property "dispatchEvent(Event)" with the proper type
-PASS EventTarget interface: calling dispatchEvent(Event) on document.createDocumentFragment() with too few arguments must throw TypeError
-PASS ShadowRoot interface: existence and properties of interface object
-PASS ShadowRoot interface object length
-PASS ShadowRoot interface object name
-PASS ShadowRoot interface: existence and properties of interface prototype object
-PASS ShadowRoot interface: existence and properties of interface prototype object's "constructor" property
-PASS ShadowRoot interface: existence and properties of interface prototype object's @@unscopables property
-PASS ShadowRoot interface: attribute mode
-PASS Unscopable handled correctly for mode property on ShadowRoot
-PASS ShadowRoot interface: attribute host
-PASS Unscopable handled correctly for host property on ShadowRoot
-PASS Element interface: existence and properties of interface object
-PASS Element interface object length
-PASS Element interface object name
-PASS Element interface: existence and properties of interface prototype object
-PASS Element interface: existence and properties of interface prototype object's "constructor" property
-FAIL Element interface: existence and properties of interface prototype object's @@unscopables property assert_false: Element.prototype[Symbol.unscopables] should not be writable expected false got true
-PASS Element interface: attribute namespaceURI
-PASS Unscopable handled correctly for namespaceURI property on Element
-PASS Element interface: attribute prefix
-PASS Unscopable handled correctly for prefix property on Element
-PASS Element interface: attribute localName
-PASS Unscopable handled correctly for localName property on Element
-PASS Element interface: attribute tagName
-PASS Unscopable handled correctly for tagName property on Element
-PASS Element interface: attribute id
-PASS Unscopable handled correctly for id property on Element
-PASS Element interface: attribute className
-PASS Unscopable handled correctly for className property on Element
-PASS Element interface: attribute classList
-PASS Unscopable handled correctly for classList property on Element
-PASS Element interface: attribute slot
-PASS Unscopable handled correctly for slot property on Element
-PASS Element interface: operation hasAttributes()
-PASS Unscopable handled correctly for hasAttributes() on Element
-PASS Element interface: attribute attributes
-PASS Unscopable handled correctly for attributes property on Element
-PASS Element interface: operation getAttributeNames()
-PASS Unscopable handled correctly for getAttributeNames() on Element
-PASS Element interface: operation getAttribute(DOMString)
-PASS Unscopable handled correctly for getAttribute(DOMString) on Element
-PASS Element interface: operation getAttributeNS(DOMString, DOMString)
-PASS Unscopable handled correctly for getAttributeNS(DOMString, DOMString) on Element
-PASS Element interface: operation setAttribute(DOMString, DOMString)
-PASS Unscopable handled correctly for setAttribute(DOMString, DOMString) on Element
-PASS Element interface: operation setAttributeNS(DOMString, DOMString, DOMString)
-PASS Unscopable handled correctly for setAttributeNS(DOMString, DOMString, DOMString) on Element
-PASS Element interface: operation removeAttribute(DOMString)
-PASS Unscopable handled correctly for removeAttribute(DOMString) on Element
-PASS Element interface: operation removeAttributeNS(DOMString, DOMString)
-PASS Unscopable handled correctly for removeAttributeNS(DOMString, DOMString) on Element
-PASS Element interface: operation hasAttribute(DOMString)
-PASS Unscopable handled correctly for hasAttribute(DOMString) on Element
-PASS Element interface: operation hasAttributeNS(DOMString, DOMString)
-PASS Unscopable handled correctly for hasAttributeNS(DOMString, DOMString) on Element
-PASS Element interface: operation getAttributeNode(DOMString)
-PASS Unscopable handled correctly for getAttributeNode(DOMString) on Element
-PASS Element interface: operation getAttributeNodeNS(DOMString, DOMString)
-PASS Unscopable handled correctly for getAttributeNodeNS(DOMString, DOMString) on Element
-PASS Element interface: operation setAttributeNode(Attr)
-PASS Unscopable handled correctly for setAttributeNode(Attr) on Element
-PASS Element interface: operation setAttributeNodeNS(Attr)
-PASS Unscopable handled correctly for setAttributeNodeNS(Attr) on Element
-PASS Element interface: operation removeAttributeNode(Attr)
-PASS Unscopable handled correctly for removeAttributeNode(Attr) on Element
-PASS Element interface: operation attachShadow(ShadowRootInit)
-PASS Unscopable handled correctly for attachShadow(ShadowRootInit) on Element
-PASS Element interface: attribute shadowRoot
-PASS Unscopable handled correctly for shadowRoot property on Element
-PASS Element interface: operation closest(DOMString)
-PASS Unscopable handled correctly for closest(DOMString) on Element
-PASS Element interface: operation matches(DOMString)
-PASS Unscopable handled correctly for matches(DOMString) on Element
-PASS Element interface: operation webkitMatchesSelector(DOMString)
-PASS Unscopable handled correctly for webkitMatchesSelector(DOMString) on Element
-PASS Element interface: operation getElementsByTagName(DOMString)
-PASS Unscopable handled correctly for getElementsByTagName(DOMString) on Element
-PASS Element interface: operation getElementsByTagNameNS(DOMString, DOMString)
-PASS Unscopable handled correctly for getElementsByTagNameNS(DOMString, DOMString) on Element
-PASS Element interface: operation getElementsByClassName(DOMString)
-PASS Unscopable handled correctly for getElementsByClassName(DOMString) on Element
-PASS Element interface: operation insertAdjacentElement(DOMString, Element)
-PASS Unscopable handled correctly for insertAdjacentElement(DOMString, Element) on Element
-PASS Element interface: operation insertAdjacentText(DOMString, DOMString)
-PASS Unscopable handled correctly for insertAdjacentText(DOMString, DOMString) on Element
-PASS Element interface: attribute children
-PASS Unscopable handled correctly for children property on Element
-PASS Element interface: attribute firstElementChild
-PASS Unscopable handled correctly for firstElementChild property on Element
-PASS Element interface: attribute lastElementChild
-PASS Unscopable handled correctly for lastElementChild property on Element
-PASS Element interface: attribute childElementCount
-PASS Unscopable handled correctly for childElementCount property on Element
-PASS Element interface: operation prepend([object Object],[object Object])
-PASS Unscopable handled correctly for prepend([object Object],[object Object]) on Element
-PASS Element interface: operation append([object Object],[object Object])
-PASS Unscopable handled correctly for append([object Object],[object Object]) on Element
-PASS Element interface: operation querySelector(DOMString)
-PASS Unscopable handled correctly for querySelector(DOMString) on Element
-PASS Element interface: operation querySelectorAll(DOMString)
-PASS Unscopable handled correctly for querySelectorAll(DOMString) on Element
-PASS Element interface: attribute previousElementSibling
-PASS Unscopable handled correctly for previousElementSibling property on Element
-PASS Element interface: attribute nextElementSibling
-PASS Unscopable handled correctly for nextElementSibling property on Element
-PASS Element interface: operation before([object Object],[object Object])
-PASS Unscopable handled correctly for before([object Object],[object Object]) on Element
-PASS Element interface: operation after([object Object],[object Object])
-PASS Unscopable handled correctly for after([object Object],[object Object]) on Element
-PASS Element interface: operation replaceWith([object Object],[object Object])
-PASS Unscopable handled correctly for replaceWith([object Object],[object Object]) on Element
-PASS Element interface: operation remove()
-PASS Unscopable handled correctly for remove() on Element
-PASS Element interface: attribute assignedSlot
-PASS Unscopable handled correctly for assignedSlot property on Element
-PASS Element must be primary interface of element
-PASS Stringification of element
-PASS Element interface: element must inherit property "namespaceURI" with the proper type
-PASS Element interface: element must inherit property "prefix" with the proper type
-PASS Element interface: element must inherit property "localName" with the proper type
-PASS Element interface: element must inherit property "tagName" with the proper type
-PASS Element interface: element must inherit property "id" with the proper type
-PASS Element interface: element must inherit property "className" with the proper type
-PASS Element interface: element must inherit property "classList" with the proper type
-PASS Element interface: element must inherit property "slot" with the proper type
-PASS Element interface: element must inherit property "hasAttributes()" with the proper type
-PASS Element interface: element must inherit property "attributes" with the proper type
-PASS Element interface: element must inherit property "getAttributeNames()" with the proper type
-PASS Element interface: element must inherit property "getAttribute(DOMString)" with the proper type
-PASS Element interface: calling getAttribute(DOMString) on element with too few arguments must throw TypeError
-PASS Element interface: element must inherit property "getAttributeNS(DOMString, DOMString)" with the proper type
-PASS Element interface: calling getAttributeNS(DOMString, DOMString) on element with too few arguments must throw TypeError
-PASS Element interface: element must inherit property "setAttribute(DOMString, DOMString)" with the proper type
-PASS Element interface: calling setAttribute(DOMString, DOMString) on element with too few arguments must throw TypeError
-PASS Element interface: element must inherit property "setAttributeNS(DOMString, DOMString, DOMString)" with the proper type
-PASS Element interface: calling setAttributeNS(DOMString, DOMString, DOMString) on element with too few arguments must throw TypeError
-PASS Element interface: element must inherit property "removeAttribute(DOMString)" with the proper type
-PASS Element interface: calling removeAttribute(DOMString) on element with too few arguments must throw TypeError
-PASS Element interface: element must inherit property "removeAttributeNS(DOMString, DOMString)" with the proper type
-PASS Element interface: calling removeAttributeNS(DOMString, DOMString) on element with too few arguments must throw TypeError
-PASS Element interface: element must inherit property "hasAttribute(DOMString)" with the proper type
-PASS Element interface: calling hasAttribute(DOMString) on element with too few arguments must throw TypeError
-PASS Element interface: element must inherit property "hasAttributeNS(DOMString, DOMString)" with the proper type
-PASS Element interface: calling hasAttributeNS(DOMString, DOMString) on element with too few arguments must throw TypeError
-PASS Element interface: element must inherit property "getAttributeNode(DOMString)" with the proper type
-PASS Element interface: calling getAttributeNode(DOMString) on element with too few arguments must throw TypeError
-PASS Element interface: element must inherit property "getAttributeNodeNS(DOMString, DOMString)" with the proper type
-PASS Element interface: calling getAttributeNodeNS(DOMString, DOMString) on element with too few arguments must throw TypeError
-PASS Element interface: element must inherit property "setAttributeNode(Attr)" with the proper type
-PASS Element interface: calling setAttributeNode(Attr) on element with too few arguments must throw TypeError
-PASS Element interface: element must inherit property "setAttributeNodeNS(Attr)" with the proper type
-PASS Element interface: calling setAttributeNodeNS(Attr) on element with too few arguments must throw TypeError
-PASS Element interface: element must inherit property "removeAttributeNode(Attr)" with the proper type
-PASS Element interface: calling removeAttributeNode(Attr) on element with too few arguments must throw TypeError
-PASS Element interface: element must inherit property "attachShadow(ShadowRootInit)" with the proper type
-PASS Element interface: calling attachShadow(ShadowRootInit) on element with too few arguments must throw TypeError
-PASS Element interface: element must inherit property "shadowRoot" with the proper type
-PASS Element interface: element must inherit property "closest(DOMString)" with the proper type
-PASS Element interface: calling closest(DOMString) on element with too few arguments must throw TypeError
-PASS Element interface: element must inherit property "matches(DOMString)" with the proper type
-PASS Element interface: calling matches(DOMString) on element with too few arguments must throw TypeError
-PASS Element interface: element must inherit property "webkitMatchesSelector(DOMString)" with the proper type
-PASS Element interface: calling webkitMatchesSelector(DOMString) on element with too few arguments must throw TypeError
-PASS Element interface: element must inherit property "getElementsByTagName(DOMString)" with the proper type
-PASS Element interface: calling getElementsByTagName(DOMString) on element with too few arguments must throw TypeError
-PASS Element interface: element must inherit property "getElementsByTagNameNS(DOMString, DOMString)" with the proper type
-PASS Element interface: calling getElementsByTagNameNS(DOMString, DOMString) on element with too few arguments must throw TypeError
-PASS Element interface: element must inherit property "getElementsByClassName(DOMString)" with the proper type
-PASS Element interface: calling getElementsByClassName(DOMString) on element with too few arguments must throw TypeError
-PASS Element interface: element must inherit property "insertAdjacentElement(DOMString, Element)" with the proper type
-PASS Element interface: calling insertAdjacentElement(DOMString, Element) on element with too few arguments must throw TypeError
-PASS Element interface: element must inherit property "insertAdjacentText(DOMString, DOMString)" with the proper type
-PASS Element interface: calling insertAdjacentText(DOMString, DOMString) on element with too few arguments must throw TypeError
-PASS Element interface: element must inherit property "children" with the proper type
-PASS Element interface: element must inherit property "firstElementChild" with the proper type
-PASS Element interface: element must inherit property "lastElementChild" with the proper type
-PASS Element interface: element must inherit property "childElementCount" with the proper type
-PASS Element interface: element must inherit property "prepend([object Object],[object Object])" with the proper type
-PASS Element interface: calling prepend([object Object],[object Object]) on element with too few arguments must throw TypeError
-PASS Element interface: element must inherit property "append([object Object],[object Object])" with the proper type
-PASS Element interface: calling append([object Object],[object Object]) on element with too few arguments must throw TypeError
-PASS Element interface: element must inherit property "querySelector(DOMString)" with the proper type
-PASS Element interface: calling querySelector(DOMString) on element with too few arguments must throw TypeError
-PASS Element interface: element must inherit property "querySelectorAll(DOMString)" with the proper type
-PASS Element interface: calling querySelectorAll(DOMString) on element with too few arguments must throw TypeError
-PASS Element interface: element must inherit property "previousElementSibling" with the proper type
-PASS Element interface: element must inherit property "nextElementSibling" with the proper type
-PASS Element interface: element must inherit property "before([object Object],[object Object])" with the proper type
-PASS Element interface: calling before([object Object],[object Object]) on element with too few arguments must throw TypeError
-PASS Element interface: element must inherit property "after([object Object],[object Object])" with the proper type
-PASS Element interface: calling after([object Object],[object Object]) on element with too few arguments must throw TypeError
-PASS Element interface: element must inherit property "replaceWith([object Object],[object Object])" with the proper type
-PASS Element interface: calling replaceWith([object Object],[object Object]) on element with too few arguments must throw TypeError
-PASS Element interface: element must inherit property "remove()" with the proper type
-PASS Element interface: element must inherit property "assignedSlot" with the proper type
-PASS Node interface: element must inherit property "ELEMENT_NODE" with the proper type
-PASS Node interface: element must inherit property "ATTRIBUTE_NODE" with the proper type
-PASS Node interface: element must inherit property "TEXT_NODE" with the proper type
-PASS Node interface: element must inherit property "CDATA_SECTION_NODE" with the proper type
-PASS Node interface: element must inherit property "ENTITY_REFERENCE_NODE" with the proper type
-PASS Node interface: element must inherit property "ENTITY_NODE" with the proper type
-PASS Node interface: element must inherit property "PROCESSING_INSTRUCTION_NODE" with the proper type
-PASS Node interface: element must inherit property "COMMENT_NODE" with the proper type
-PASS Node interface: element must inherit property "DOCUMENT_NODE" with the proper type
-PASS Node interface: element must inherit property "DOCUMENT_TYPE_NODE" with the proper type
-PASS Node interface: element must inherit property "DOCUMENT_FRAGMENT_NODE" with the proper type
-PASS Node interface: element must inherit property "NOTATION_NODE" with the proper type
-PASS Node interface: element must inherit property "nodeType" with the proper type
-PASS Node interface: element must inherit property "nodeName" with the proper type
-PASS Node interface: element must inherit property "baseURI" with the proper type
-PASS Node interface: element must inherit property "isConnected" with the proper type
-PASS Node interface: element must inherit property "ownerDocument" with the proper type
-PASS Node interface: element must inherit property "getRootNode(GetRootNodeOptions)" with the proper type
-PASS Node interface: calling getRootNode(GetRootNodeOptions) on element with too few arguments must throw TypeError
-PASS Node interface: element must inherit property "parentNode" with the proper type
-PASS Node interface: element must inherit property "parentElement" with the proper type
-PASS Node interface: element must inherit property "hasChildNodes()" with the proper type
-PASS Node interface: element must inherit property "childNodes" with the proper type
-PASS Node interface: element must inherit property "firstChild" with the proper type
-PASS Node interface: element must inherit property "lastChild" with the proper type
-PASS Node interface: element must inherit property "previousSibling" with the proper type
-PASS Node interface: element must inherit property "nextSibling" with the proper type
-PASS Node interface: element must inherit property "nodeValue" with the proper type
-PASS Node interface: element must inherit property "textContent" with the proper type
-PASS Node interface: element must inherit property "normalize()" with the proper type
-PASS Node interface: element must inherit property "cloneNode(boolean)" with the proper type
-PASS Node interface: calling cloneNode(boolean) on element with too few arguments must throw TypeError
-PASS Node interface: element must inherit property "isEqualNode(Node)" with the proper type
-PASS Node interface: calling isEqualNode(Node) on element with too few arguments must throw TypeError
-PASS Node interface: element must inherit property "isSameNode(Node)" with the proper type
-PASS Node interface: calling isSameNode(Node) on element with too few arguments must throw TypeError
-PASS Node interface: element must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type
-PASS Node interface: element must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type
-PASS Node interface: element must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type
-PASS Node interface: element must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type
-PASS Node interface: element must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type
-PASS Node interface: element must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type
-PASS Node interface: element must inherit property "compareDocumentPosition(Node)" with the proper type
-PASS Node interface: calling compareDocumentPosition(Node) on element with too few arguments must throw TypeError
-PASS Node interface: element must inherit property "contains(Node)" with the proper type
-PASS Node interface: calling contains(Node) on element with too few arguments must throw TypeError
-PASS Node interface: element must inherit property "lookupPrefix(DOMString)" with the proper type
-PASS Node interface: calling lookupPrefix(DOMString) on element with too few arguments must throw TypeError
-PASS Node interface: element must inherit property "lookupNamespaceURI(DOMString)" with the proper type
-PASS Node interface: calling lookupNamespaceURI(DOMString) on element with too few arguments must throw TypeError
-PASS Node interface: element must inherit property "isDefaultNamespace(DOMString)" with the proper type
-PASS Node interface: calling isDefaultNamespace(DOMString) on element with too few arguments must throw TypeError
-PASS Node interface: element must inherit property "insertBefore(Node, Node)" with the proper type
-PASS Node interface: calling insertBefore(Node, Node) on element with too few arguments must throw TypeError
-PASS Node interface: element must inherit property "appendChild(Node)" with the proper type
-PASS Node interface: calling appendChild(Node) on element with too few arguments must throw TypeError
-PASS Node interface: element must inherit property "replaceChild(Node, Node)" with the proper type
-PASS Node interface: calling replaceChild(Node, Node) on element with too few arguments must throw TypeError
-PASS Node interface: element must inherit property "removeChild(Node)" with the proper type
-PASS Node interface: calling removeChild(Node) on element with too few arguments must throw TypeError
-PASS EventTarget interface: element must inherit property "addEventListener(DOMString, EventListener, [object Object],[object Object])" with the proper type
-PASS EventTarget interface: calling addEventListener(DOMString, EventListener, [object Object],[object Object]) on element with too few arguments must throw TypeError
-PASS EventTarget interface: element must inherit property "removeEventListener(DOMString, EventListener, [object Object],[object Object])" with the proper type
-PASS EventTarget interface: calling removeEventListener(DOMString, EventListener, [object Object],[object Object]) on element with too few arguments must throw TypeError
-PASS EventTarget interface: element must inherit property "dispatchEvent(Event)" with the proper type
-PASS EventTarget interface: calling dispatchEvent(Event) on element with too few arguments must throw TypeError
-PASS NamedNodeMap interface: existence and properties of interface object
-PASS NamedNodeMap interface object length
-PASS NamedNodeMap interface object name
-PASS NamedNodeMap interface: existence and properties of interface prototype object
-PASS NamedNodeMap interface: existence and properties of interface prototype object's "constructor" property
-PASS NamedNodeMap interface: existence and properties of interface prototype object's @@unscopables property
-PASS NamedNodeMap interface: attribute length
-PASS Unscopable handled correctly for length property on NamedNodeMap
-PASS NamedNodeMap interface: operation item(unsigned long)
-PASS Unscopable handled correctly for item(unsigned long) on NamedNodeMap
-PASS NamedNodeMap interface: operation getNamedItem(DOMString)
-PASS Unscopable handled correctly for getNamedItem(DOMString) on NamedNodeMap
-PASS NamedNodeMap interface: operation getNamedItemNS(DOMString, DOMString)
-PASS Unscopable handled correctly for getNamedItemNS(DOMString, DOMString) on NamedNodeMap
-PASS NamedNodeMap interface: operation setNamedItem(Attr)
-PASS Unscopable handled correctly for setNamedItem(Attr) on NamedNodeMap
-PASS NamedNodeMap interface: operation setNamedItemNS(Attr)
-PASS Unscopable handled correctly for setNamedItemNS(Attr) on NamedNodeMap
-PASS NamedNodeMap interface: operation removeNamedItem(DOMString)
-PASS Unscopable handled correctly for removeNamedItem(DOMString) on NamedNodeMap
-PASS NamedNodeMap interface: operation removeNamedItemNS(DOMString, DOMString)
-PASS Unscopable handled correctly for removeNamedItemNS(DOMString, DOMString) on NamedNodeMap
-PASS Attr interface: existence and properties of interface object
-PASS Attr interface object length
-PASS Attr interface object name
-PASS Attr interface: existence and properties of interface prototype object
-PASS Attr interface: existence and properties of interface prototype object's "constructor" property
-PASS Attr interface: existence and properties of interface prototype object's @@unscopables property
-PASS Attr interface: attribute namespaceURI
-PASS Unscopable handled correctly for namespaceURI property on Attr
-PASS Attr interface: attribute prefix
-PASS Unscopable handled correctly for prefix property on Attr
-PASS Attr interface: attribute localName
-PASS Unscopable handled correctly for localName property on Attr
-PASS Attr interface: attribute name
-PASS Unscopable handled correctly for name property on Attr
-PASS Attr interface: attribute value
-PASS Unscopable handled correctly for value property on Attr
-PASS Attr interface: attribute ownerElement
-PASS Unscopable handled correctly for ownerElement property on Attr
-PASS Attr interface: attribute specified
-PASS Unscopable handled correctly for specified property on Attr
-PASS Attr must be primary interface of document.querySelector("[id]").attributes[0]
-PASS Stringification of document.querySelector("[id]").attributes[0]
-PASS Attr interface: document.querySelector("[id]").attributes[0] must inherit property "namespaceURI" with the proper type
-PASS Attr interface: document.querySelector("[id]").attributes[0] must inherit property "prefix" with the proper type
-PASS Attr interface: document.querySelector("[id]").attributes[0] must inherit property "localName" with the proper type
-PASS Attr interface: document.querySelector("[id]").attributes[0] must inherit property "name" with the proper type
-PASS Attr interface: document.querySelector("[id]").attributes[0] must inherit property "value" with the proper type
-PASS Attr interface: document.querySelector("[id]").attributes[0] must inherit property "ownerElement" with the proper type
-PASS Attr interface: document.querySelector("[id]").attributes[0] must inherit property "specified" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "ELEMENT_NODE" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "ATTRIBUTE_NODE" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "TEXT_NODE" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "CDATA_SECTION_NODE" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "ENTITY_REFERENCE_NODE" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "ENTITY_NODE" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "PROCESSING_INSTRUCTION_NODE" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "COMMENT_NODE" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "DOCUMENT_NODE" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "DOCUMENT_TYPE_NODE" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "DOCUMENT_FRAGMENT_NODE" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "NOTATION_NODE" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "nodeType" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "nodeName" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "baseURI" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "isConnected" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "ownerDocument" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "getRootNode(GetRootNodeOptions)" with the proper type
-PASS Node interface: calling getRootNode(GetRootNodeOptions) on document.querySelector("[id]").attributes[0] with too few arguments must throw TypeError
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "parentNode" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "parentElement" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "hasChildNodes()" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "childNodes" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "firstChild" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "lastChild" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "previousSibling" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "nextSibling" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "nodeValue" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "textContent" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "normalize()" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "cloneNode(boolean)" with the proper type
-PASS Node interface: calling cloneNode(boolean) on document.querySelector("[id]").attributes[0] with too few arguments must throw TypeError
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "isEqualNode(Node)" with the proper type
-PASS Node interface: calling isEqualNode(Node) on document.querySelector("[id]").attributes[0] with too few arguments must throw TypeError
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "isSameNode(Node)" with the proper type
-PASS Node interface: calling isSameNode(Node) on document.querySelector("[id]").attributes[0] with too few arguments must throw TypeError
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "compareDocumentPosition(Node)" with the proper type
-PASS Node interface: calling compareDocumentPosition(Node) on document.querySelector("[id]").attributes[0] with too few arguments must throw TypeError
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "contains(Node)" with the proper type
-PASS Node interface: calling contains(Node) on document.querySelector("[id]").attributes[0] with too few arguments must throw TypeError
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "lookupPrefix(DOMString)" with the proper type
-PASS Node interface: calling lookupPrefix(DOMString) on document.querySelector("[id]").attributes[0] with too few arguments must throw TypeError
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "lookupNamespaceURI(DOMString)" with the proper type
-PASS Node interface: calling lookupNamespaceURI(DOMString) on document.querySelector("[id]").attributes[0] with too few arguments must throw TypeError
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "isDefaultNamespace(DOMString)" with the proper type
-PASS Node interface: calling isDefaultNamespace(DOMString) on document.querySelector("[id]").attributes[0] with too few arguments must throw TypeError
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "insertBefore(Node, Node)" with the proper type
-PASS Node interface: calling insertBefore(Node, Node) on document.querySelector("[id]").attributes[0] with too few arguments must throw TypeError
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "appendChild(Node)" with the proper type
-PASS Node interface: calling appendChild(Node) on document.querySelector("[id]").attributes[0] with too few arguments must throw TypeError
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "replaceChild(Node, Node)" with the proper type
-PASS Node interface: calling replaceChild(Node, Node) on document.querySelector("[id]").attributes[0] with too few arguments must throw TypeError
-PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "removeChild(Node)" with the proper type
-PASS Node interface: calling removeChild(Node) on document.querySelector("[id]").attributes[0] with too few arguments must throw TypeError
-PASS EventTarget interface: document.querySelector("[id]").attributes[0] must inherit property "addEventListener(DOMString, EventListener, [object Object],[object Object])" with the proper type
-PASS EventTarget interface: calling addEventListener(DOMString, EventListener, [object Object],[object Object]) on document.querySelector("[id]").attributes[0] with too few arguments must throw TypeError
-PASS EventTarget interface: document.querySelector("[id]").attributes[0] must inherit property "removeEventListener(DOMString, EventListener, [object Object],[object Object])" with the proper type
-PASS EventTarget interface: calling removeEventListener(DOMString, EventListener, [object Object],[object Object]) on document.querySelector("[id]").attributes[0] with too few arguments must throw TypeError
-PASS EventTarget interface: document.querySelector("[id]").attributes[0] must inherit property "dispatchEvent(Event)" with the proper type
-PASS EventTarget interface: calling dispatchEvent(Event) on document.querySelector("[id]").attributes[0] with too few arguments must throw TypeError
-PASS CharacterData interface: existence and properties of interface object
-PASS CharacterData interface object length
-PASS CharacterData interface object name
-PASS CharacterData interface: existence and properties of interface prototype object
-PASS CharacterData interface: existence and properties of interface prototype object's "constructor" property
-FAIL CharacterData interface: existence and properties of interface prototype object's @@unscopables property assert_false: CharacterData.prototype[Symbol.unscopables] should not be writable expected false got true
-PASS CharacterData interface: attribute data
-PASS Unscopable handled correctly for data property on CharacterData
-PASS CharacterData interface: attribute length
-PASS Unscopable handled correctly for length property on CharacterData
-PASS CharacterData interface: operation substringData(unsigned long, unsigned long)
-PASS Unscopable handled correctly for substringData(unsigned long, unsigned long) on CharacterData
-PASS CharacterData interface: operation appendData(DOMString)
-PASS Unscopable handled correctly for appendData(DOMString) on CharacterData
-PASS CharacterData interface: operation insertData(unsigned long, DOMString)
-PASS Unscopable handled correctly for insertData(unsigned long, DOMString) on CharacterData
-PASS CharacterData interface: operation deleteData(unsigned long, unsigned long)
-PASS Unscopable handled correctly for deleteData(unsigned long, unsigned long) on CharacterData
-PASS CharacterData interface: operation replaceData(unsigned long, unsigned long, DOMString)
-PASS Unscopable handled correctly for replaceData(unsigned long, unsigned long, DOMString) on CharacterData
-PASS CharacterData interface: attribute previousElementSibling
-PASS Unscopable handled correctly for previousElementSibling property on CharacterData
-PASS CharacterData interface: attribute nextElementSibling
-PASS Unscopable handled correctly for nextElementSibling property on CharacterData
-PASS CharacterData interface: operation before([object Object],[object Object])
-PASS Unscopable handled correctly for before([object Object],[object Object]) on CharacterData
-PASS CharacterData interface: operation after([object Object],[object Object])
-PASS Unscopable handled correctly for after([object Object],[object Object]) on CharacterData
-PASS CharacterData interface: operation replaceWith([object Object],[object Object])
-PASS Unscopable handled correctly for replaceWith([object Object],[object Object]) on CharacterData
-PASS CharacterData interface: operation remove()
-PASS Unscopable handled correctly for remove() on CharacterData
-PASS Text interface: existence and properties of interface object
-PASS Text interface object length
-PASS Text interface object name
-PASS Text interface: existence and properties of interface prototype object
-PASS Text interface: existence and properties of interface prototype object's "constructor" property
-PASS Text interface: existence and properties of interface prototype object's @@unscopables property
-PASS Text interface: operation splitText(unsigned long)
-PASS Unscopable handled correctly for splitText(unsigned long) on Text
-PASS Text interface: attribute wholeText
-PASS Unscopable handled correctly for wholeText property on Text
-PASS Text interface: attribute assignedSlot
-PASS Unscopable handled correctly for assignedSlot property on Text
-PASS Text must be primary interface of document.createTextNode("abc")
-PASS Stringification of document.createTextNode("abc")
-PASS Text interface: document.createTextNode("abc") must inherit property "splitText(unsigned long)" with the proper type
-PASS Text interface: calling splitText(unsigned long) on document.createTextNode("abc") with too few arguments must throw TypeError
-PASS Text interface: document.createTextNode("abc") must inherit property "wholeText" with the proper type
-PASS Text interface: document.createTextNode("abc") must inherit property "assignedSlot" with the proper type
-PASS CharacterData interface: document.createTextNode("abc") must inherit property "data" with the proper type
-PASS CharacterData interface: document.createTextNode("abc") must inherit property "length" with the proper type
-PASS CharacterData interface: document.createTextNode("abc") must inherit property "substringData(unsigned long, unsigned long)" with the proper type
-PASS CharacterData interface: calling substringData(unsigned long, unsigned long) on document.createTextNode("abc") with too few arguments must throw TypeError
-PASS CharacterData interface: document.createTextNode("abc") must inherit property "appendData(DOMString)" with the proper type
-PASS CharacterData interface: calling appendData(DOMString) on document.createTextNode("abc") with too few arguments must throw TypeError
-PASS CharacterData interface: document.createTextNode("abc") must inherit property "insertData(unsigned long, DOMString)" with the proper type
-PASS CharacterData interface: calling insertData(unsigned long, DOMString) on document.createTextNode("abc") with too few arguments must throw TypeError
-PASS CharacterData interface: document.createTextNode("abc") must inherit property "deleteData(unsigned long, unsigned long)" with the proper type
-PASS CharacterData interface: calling deleteData(unsigned long, unsigned long) on document.createTextNode("abc") with too few arguments must throw TypeError
-PASS CharacterData interface: document.createTextNode("abc") must inherit property "replaceData(unsigned long, unsigned long, DOMString)" with the proper type
-PASS CharacterData interface: calling replaceData(unsigned long, unsigned long, DOMString) on document.createTextNode("abc") with too few arguments must throw TypeError
-PASS CharacterData interface: document.createTextNode("abc") must inherit property "previousElementSibling" with the proper type
-PASS CharacterData interface: document.createTextNode("abc") must inherit property "nextElementSibling" with the proper type
-PASS CharacterData interface: document.createTextNode("abc") must inherit property "before([object Object],[object Object])" with the proper type
-PASS CharacterData interface: calling before([object Object],[object Object]) on document.createTextNode("abc") with too few arguments must throw TypeError
-PASS CharacterData interface: document.createTextNode("abc") must inherit property "after([object Object],[object Object])" with the proper type
-PASS CharacterData interface: calling after([object Object],[object Object]) on document.createTextNode("abc") with too few arguments must throw TypeError
-PASS CharacterData interface: document.createTextNode("abc") must inherit property "replaceWith([object Object],[object Object])" with the proper type
-PASS CharacterData interface: calling replaceWith([object Object],[object Object]) on document.createTextNode("abc") with too few arguments must throw TypeError
-PASS CharacterData interface: document.createTextNode("abc") must inherit property "remove()" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "ELEMENT_NODE" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "ATTRIBUTE_NODE" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "TEXT_NODE" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "CDATA_SECTION_NODE" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "ENTITY_REFERENCE_NODE" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "ENTITY_NODE" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "PROCESSING_INSTRUCTION_NODE" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "COMMENT_NODE" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "DOCUMENT_NODE" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "DOCUMENT_TYPE_NODE" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "DOCUMENT_FRAGMENT_NODE" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "NOTATION_NODE" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "nodeType" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "nodeName" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "baseURI" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "isConnected" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "ownerDocument" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "getRootNode(GetRootNodeOptions)" with the proper type
-PASS Node interface: calling getRootNode(GetRootNodeOptions) on document.createTextNode("abc") with too few arguments must throw TypeError
-PASS Node interface: document.createTextNode("abc") must inherit property "parentNode" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "parentElement" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "hasChildNodes()" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "childNodes" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "firstChild" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "lastChild" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "previousSibling" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "nextSibling" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "nodeValue" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "textContent" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "normalize()" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "cloneNode(boolean)" with the proper type
-PASS Node interface: calling cloneNode(boolean) on document.createTextNode("abc") with too few arguments must throw TypeError
-PASS Node interface: document.createTextNode("abc") must inherit property "isEqualNode(Node)" with the proper type
-PASS Node interface: calling isEqualNode(Node) on document.createTextNode("abc") with too few arguments must throw TypeError
-PASS Node interface: document.createTextNode("abc") must inherit property "isSameNode(Node)" with the proper type
-PASS Node interface: calling isSameNode(Node) on document.createTextNode("abc") with too few arguments must throw TypeError
-PASS Node interface: document.createTextNode("abc") must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type
-PASS Node interface: document.createTextNode("abc") must inherit property "compareDocumentPosition(Node)" with the proper type
-PASS Node interface: calling compareDocumentPosition(Node) on document.createTextNode("abc") with too few arguments must throw TypeError
-PASS Node interface: document.createTextNode("abc") must inherit property "contains(Node)" with the proper type
-PASS Node interface: calling contains(Node) on document.createTextNode("abc") with too few arguments must throw TypeError
-PASS Node interface: document.createTextNode("abc") must inherit property "lookupPrefix(DOMString)" with the proper type
-PASS Node interface: calling lookupPrefix(DOMString) on document.createTextNode("abc") with too few arguments must throw TypeError
-PASS Node interface: document.createTextNode("abc") must inherit property "lookupNamespaceURI(DOMString)" with the proper type
-PASS Node interface: calling lookupNamespaceURI(DOMString) on document.createTextNode("abc") with too few arguments must throw TypeError
-PASS Node interface: document.createTextNode("abc") must inherit property "isDefaultNamespace(DOMString)" with the proper type
-PASS Node interface: calling isDefaultNamespace(DOMString) on document.createTextNode("abc") with too few arguments must throw TypeError
-PASS Node interface: document.createTextNode("abc") must inherit property "insertBefore(Node, Node)" with the proper type
-PASS Node interface: calling insertBefore(Node, Node) on document.createTextNode("abc") with too few arguments must throw TypeError
-PASS Node interface: document.createTextNode("abc") must inherit property "appendChild(Node)" with the proper type
-PASS Node interface: calling appendChild(Node) on document.createTextNode("abc") with too few arguments must throw TypeError
-PASS Node interface: document.createTextNode("abc") must inherit property "replaceChild(Node, Node)" with the proper type
-PASS Node interface: calling replaceChild(Node, Node) on document.createTextNode("abc") with too few arguments must throw TypeError
-PASS Node interface: document.createTextNode("abc") must inherit property "removeChild(Node)" with the proper type
-PASS Node interface: calling removeChild(Node) on document.createTextNode("abc") with too few arguments must throw TypeError
-PASS EventTarget interface: document.createTextNode("abc") must inherit property "addEventListener(DOMString, EventListener, [object Object],[object Object])" with the proper type
-PASS EventTarget interface: calling addEventListener(DOMString, EventListener, [object Object],[object Object]) on document.createTextNode("abc") with too few arguments must throw TypeError
-PASS EventTarget interface: document.createTextNode("abc") must inherit property "removeEventListener(DOMString, EventListener, [object Object],[object Object])" with the proper type
-PASS EventTarget interface: calling removeEventListener(DOMString, EventListener, [object Object],[object Object]) on document.createTextNode("abc") with too few arguments must throw TypeError
-PASS EventTarget interface: document.createTextNode("abc") must inherit property "dispatchEvent(Event)" with the proper type
-PASS EventTarget interface: calling dispatchEvent(Event) on document.createTextNode("abc") with too few arguments must throw TypeError
-PASS CDATASection interface: existence and properties of interface object
-PASS CDATASection interface object length
-PASS CDATASection interface object name
-PASS CDATASection interface: existence and properties of interface prototype object
-PASS CDATASection interface: existence and properties of interface prototype object's "constructor" property
-PASS CDATASection interface: existence and properties of interface prototype object's @@unscopables property
-PASS ProcessingInstruction interface: existence and properties of interface object
-PASS ProcessingInstruction interface object length
-PASS ProcessingInstruction interface object name
-PASS ProcessingInstruction interface: existence and properties of interface prototype object
-PASS ProcessingInstruction interface: existence and properties of interface prototype object's "constructor" property
-PASS ProcessingInstruction interface: existence and properties of interface prototype object's @@unscopables property
-PASS ProcessingInstruction interface: attribute target
-PASS Unscopable handled correctly for target property on ProcessingInstruction
-PASS ProcessingInstruction must be primary interface of xmlDoc.createProcessingInstruction("abc", "def")
-PASS Stringification of xmlDoc.createProcessingInstruction("abc", "def")
-PASS ProcessingInstruction interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "target" with the proper type
-PASS CharacterData interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "data" with the proper type
-PASS CharacterData interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "length" with the proper type
-PASS CharacterData interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "substringData(unsigned long, unsigned long)" with the proper type
-PASS CharacterData interface: calling substringData(unsigned long, unsigned long) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError
-PASS CharacterData interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "appendData(DOMString)" with the proper type
-PASS CharacterData interface: calling appendData(DOMString) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError
-PASS CharacterData interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "insertData(unsigned long, DOMString)" with the proper type
-PASS CharacterData interface: calling insertData(unsigned long, DOMString) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError
-PASS CharacterData interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "deleteData(unsigned long, unsigned long)" with the proper type
-PASS CharacterData interface: calling deleteData(unsigned long, unsigned long) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError
-PASS CharacterData interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "replaceData(unsigned long, unsigned long, DOMString)" with the proper type
-PASS CharacterData interface: calling replaceData(unsigned long, unsigned long, DOMString) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError
-PASS CharacterData interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "previousElementSibling" with the proper type
-PASS CharacterData interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "nextElementSibling" with the proper type
-PASS CharacterData interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "before([object Object],[object Object])" with the proper type
-PASS CharacterData interface: calling before([object Object],[object Object]) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError
-PASS CharacterData interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "after([object Object],[object Object])" with the proper type
-PASS CharacterData interface: calling after([object Object],[object Object]) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError
-PASS CharacterData interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "replaceWith([object Object],[object Object])" with the proper type
-PASS CharacterData interface: calling replaceWith([object Object],[object Object]) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError
-PASS CharacterData interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "remove()" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "ELEMENT_NODE" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "ATTRIBUTE_NODE" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "TEXT_NODE" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "CDATA_SECTION_NODE" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "ENTITY_REFERENCE_NODE" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "ENTITY_NODE" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "PROCESSING_INSTRUCTION_NODE" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "COMMENT_NODE" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "DOCUMENT_NODE" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "DOCUMENT_TYPE_NODE" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "DOCUMENT_FRAGMENT_NODE" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "NOTATION_NODE" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "nodeType" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "nodeName" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "baseURI" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "isConnected" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "ownerDocument" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "getRootNode(GetRootNodeOptions)" with the proper type
-PASS Node interface: calling getRootNode(GetRootNodeOptions) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "parentNode" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "parentElement" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "hasChildNodes()" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "childNodes" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "firstChild" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "lastChild" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "previousSibling" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "nextSibling" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "nodeValue" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "textContent" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "normalize()" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "cloneNode(boolean)" with the proper type
-PASS Node interface: calling cloneNode(boolean) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "isEqualNode(Node)" with the proper type
-PASS Node interface: calling isEqualNode(Node) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "isSameNode(Node)" with the proper type
-PASS Node interface: calling isSameNode(Node) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "compareDocumentPosition(Node)" with the proper type
-PASS Node interface: calling compareDocumentPosition(Node) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "contains(Node)" with the proper type
-PASS Node interface: calling contains(Node) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "lookupPrefix(DOMString)" with the proper type
-PASS Node interface: calling lookupPrefix(DOMString) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "lookupNamespaceURI(DOMString)" with the proper type
-PASS Node interface: calling lookupNamespaceURI(DOMString) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "isDefaultNamespace(DOMString)" with the proper type
-PASS Node interface: calling isDefaultNamespace(DOMString) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "insertBefore(Node, Node)" with the proper type
-PASS Node interface: calling insertBefore(Node, Node) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "appendChild(Node)" with the proper type
-PASS Node interface: calling appendChild(Node) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "replaceChild(Node, Node)" with the proper type
-PASS Node interface: calling replaceChild(Node, Node) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError
-PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "removeChild(Node)" with the proper type
-PASS Node interface: calling removeChild(Node) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError
-PASS EventTarget interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "addEventListener(DOMString, EventListener, [object Object],[object Object])" with the proper type
-PASS EventTarget interface: calling addEventListener(DOMString, EventListener, [object Object],[object Object]) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError
-PASS EventTarget interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "removeEventListener(DOMString, EventListener, [object Object],[object Object])" with the proper type
-PASS EventTarget interface: calling removeEventListener(DOMString, EventListener, [object Object],[object Object]) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError
-PASS EventTarget interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "dispatchEvent(Event)" with the proper type
-PASS EventTarget interface: calling dispatchEvent(Event) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError
-PASS Comment interface: existence and properties of interface object
-PASS Comment interface object length
-PASS Comment interface object name
-PASS Comment interface: existence and properties of interface prototype object
-PASS Comment interface: existence and properties of interface prototype object's "constructor" property
-PASS Comment interface: existence and properties of interface prototype object's @@unscopables property
-PASS Comment must be primary interface of document.createComment("abc")
-PASS Stringification of document.createComment("abc")
-PASS CharacterData interface: document.createComment("abc") must inherit property "data" with the proper type
-PASS CharacterData interface: document.createComment("abc") must inherit property "length" with the proper type
-PASS CharacterData interface: document.createComment("abc") must inherit property "substringData(unsigned long, unsigned long)" with the proper type
-PASS CharacterData interface: calling substringData(unsigned long, unsigned long) on document.createComment("abc") with too few arguments must throw TypeError
-PASS CharacterData interface: document.createComment("abc") must inherit property "appendData(DOMString)" with the proper type
-PASS CharacterData interface: calling appendData(DOMString) on document.createComment("abc") with too few arguments must throw TypeError
-PASS CharacterData interface: document.createComment("abc") must inherit property "insertData(unsigned long, DOMString)" with the proper type
-PASS CharacterData interface: calling insertData(unsigned long, DOMString) on document.createComment("abc") with too few arguments must throw TypeError
-PASS CharacterData interface: document.createComment("abc") must inherit property "deleteData(unsigned long, unsigned long)" with the proper type
-PASS CharacterData interface: calling deleteData(unsigned long, unsigned long) on document.createComment("abc") with too few arguments must throw TypeError
-PASS CharacterData interface: document.createComment("abc") must inherit property "replaceData(unsigned long, unsigned long, DOMString)" with the proper type
-PASS CharacterData interface: calling replaceData(unsigned long, unsigned long, DOMString) on document.createComment("abc") with too few arguments must throw TypeError
-PASS CharacterData interface: document.createComment("abc") must inherit property "previousElementSibling" with the proper type
-PASS CharacterData interface: document.createComment("abc") must inherit property "nextElementSibling" with the proper type
-PASS CharacterData interface: document.createComment("abc") must inherit property "before([object Object],[object Object])" with the proper type
-PASS CharacterData interface: calling before([object Object],[object Object]) on document.createComment("abc") with too few arguments must throw TypeError
-PASS CharacterData interface: document.createComment("abc") must inherit property "after([object Object],[object Object])" with the proper type
-PASS CharacterData interface: calling after([object Object],[object Object]) on document.createComment("abc") with too few arguments must throw TypeError
-PASS CharacterData interface: document.createComment("abc") must inherit property "replaceWith([object Object],[object Object])" with the proper type
-PASS CharacterData interface: calling replaceWith([object Object],[object Object]) on document.createComment("abc") with too few arguments must throw TypeError
-PASS CharacterData interface: document.createComment("abc") must inherit property "remove()" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "ELEMENT_NODE" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "ATTRIBUTE_NODE" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "TEXT_NODE" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "CDATA_SECTION_NODE" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "ENTITY_REFERENCE_NODE" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "ENTITY_NODE" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "PROCESSING_INSTRUCTION_NODE" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "COMMENT_NODE" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "DOCUMENT_NODE" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "DOCUMENT_TYPE_NODE" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "DOCUMENT_FRAGMENT_NODE" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "NOTATION_NODE" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "nodeType" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "nodeName" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "baseURI" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "isConnected" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "ownerDocument" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "getRootNode(GetRootNodeOptions)" with the proper type
-PASS Node interface: calling getRootNode(GetRootNodeOptions) on document.createComment("abc") with too few arguments must throw TypeError
-PASS Node interface: document.createComment("abc") must inherit property "parentNode" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "parentElement" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "hasChildNodes()" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "childNodes" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "firstChild" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "lastChild" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "previousSibling" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "nextSibling" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "nodeValue" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "textContent" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "normalize()" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "cloneNode(boolean)" with the proper type
-PASS Node interface: calling cloneNode(boolean) on document.createComment("abc") with too few arguments must throw TypeError
-PASS Node interface: document.createComment("abc") must inherit property "isEqualNode(Node)" with the proper type
-PASS Node interface: calling isEqualNode(Node) on document.createComment("abc") with too few arguments must throw TypeError
-PASS Node interface: document.createComment("abc") must inherit property "isSameNode(Node)" with the proper type
-PASS Node interface: calling isSameNode(Node) on document.createComment("abc") with too few arguments must throw TypeError
-PASS Node interface: document.createComment("abc") must inherit property "DOCUMENT_POSITION_DISCONNECTED" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "DOCUMENT_POSITION_PRECEDING" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "DOCUMENT_POSITION_FOLLOWING" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "DOCUMENT_POSITION_CONTAINS" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "DOCUMENT_POSITION_CONTAINED_BY" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" with the proper type
-PASS Node interface: document.createComment("abc") must inherit property "compareDocumentPosition(Node)" with the proper type
-PASS Node interface: calling compareDocumentPosition(Node) on document.createComment("abc") with too few arguments must throw TypeError
-PASS Node interface: document.createComment("abc") must inherit property "contains(Node)" with the proper type
-PASS Node interface: calling contains(Node) on document.createComment("abc") with too few arguments must throw TypeError
-PASS Node interface: document.createComment("abc") must inherit property "lookupPrefix(DOMString)" with the proper type
-PASS Node interface: calling lookupPrefix(DOMString) on document.createComment("abc") with too few arguments must throw TypeError
-PASS Node interface: document.createComment("abc") must inherit property "lookupNamespaceURI(DOMString)" with the proper type
-PASS Node interface: calling lookupNamespaceURI(DOMString) on document.createComment("abc") with too few arguments must throw TypeError
-PASS Node interface: document.createComment("abc") must inherit property "isDefaultNamespace(DOMString)" with the proper type
-PASS Node interface: calling isDefaultNamespace(DOMString) on document.createComment("abc") with too few arguments must throw TypeError
-PASS Node interface: document.createComment("abc") must inherit property "insertBefore(Node, Node)" with the proper type
-PASS Node interface: calling insertBefore(Node, Node) on document.createComment("abc") with too few arguments must throw TypeError
-PASS Node interface: document.createComment("abc") must inherit property "appendChild(Node)" with the proper type
-PASS Node interface: calling appendChild(Node) on document.createComment("abc") with too few arguments must throw TypeError
-PASS Node interface: document.createComment("abc") must inherit property "replaceChild(Node, Node)" with the proper type
-PASS Node interface: calling replaceChild(Node, Node) on document.createComment("abc") with too few arguments must throw TypeError
-PASS Node interface: document.createComment("abc") must inherit property "removeChild(Node)" with the proper type
-PASS Node interface: calling removeChild(Node) on document.createComment("abc") with too few arguments must throw TypeError
-PASS EventTarget interface: document.createComment("abc") must inherit property "addEventListener(DOMString, EventListener, [object Object],[object Object])" with the proper type
-PASS EventTarget interface: calling addEventListener(DOMString, EventListener, [object Object],[object Object]) on document.createComment("abc") with too few arguments must throw TypeError
-PASS EventTarget interface: document.createComment("abc") must inherit property "removeEventListener(DOMString, EventListener, [object Object],[object Object])" with the proper type
-PASS EventTarget interface: calling removeEventListener(DOMString, EventListener, [object Object],[object Object]) on document.createComment("abc") with too few arguments must throw TypeError
-PASS EventTarget interface: document.createComment("abc") must inherit property "dispatchEvent(Event)" with the proper type
-PASS EventTarget interface: calling dispatchEvent(Event) on document.createComment("abc") with too few arguments must throw TypeError
-FAIL AbstractRange interface: existence and properties of interface object assert_own_property: self does not have own property "AbstractRange" expected property "AbstractRange" missing
-FAIL AbstractRange interface object length assert_own_property: self does not have own property "AbstractRange" expected property "AbstractRange" missing
-FAIL AbstractRange interface object name assert_own_property: self does not have own property "AbstractRange" expected property "AbstractRange" missing
-FAIL AbstractRange interface: existence and properties of interface prototype object assert_own_property: self does not have own property "AbstractRange" expected property "AbstractRange" missing
-FAIL AbstractRange interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "AbstractRange" expected property "AbstractRange" missing
-FAIL AbstractRange interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "AbstractRange" expected property "AbstractRange" missing
-FAIL AbstractRange interface: attribute startContainer assert_own_property: self does not have own property "AbstractRange" expected property "AbstractRange" missing
-PASS Unscopable handled correctly for startContainer property on AbstractRange
-FAIL AbstractRange interface: attribute startOffset assert_own_property: self does not have own property "AbstractRange" expected property "AbstractRange" missing
-PASS Unscopable handled correctly for startOffset property on AbstractRange
-FAIL AbstractRange interface: attribute endContainer assert_own_property: self does not have own property "AbstractRange" expected property "AbstractRange" missing
-PASS Unscopable handled correctly for endContainer property on AbstractRange
-FAIL AbstractRange interface: attribute endOffset assert_own_property: self does not have own property "AbstractRange" expected property "AbstractRange" missing
-PASS Unscopable handled correctly for endOffset property on AbstractRange
-FAIL AbstractRange interface: attribute collapsed assert_own_property: self does not have own property "AbstractRange" expected property "AbstractRange" missing
-PASS Unscopable handled correctly for collapsed property on AbstractRange
-FAIL StaticRange interface: existence and properties of interface object assert_own_property: should inherit from AbstractRange, but self has no such property expected property "AbstractRange" missing
-PASS StaticRange interface object length
-PASS StaticRange interface object name
-FAIL StaticRange interface: existence and properties of interface prototype object assert_own_property: should inherit from AbstractRange, but self has no such property expected property "AbstractRange" missing
-PASS StaticRange interface: existence and properties of interface prototype object's "constructor" property
-PASS StaticRange interface: existence and properties of interface prototype object's @@unscopables property
-FAIL Range interface: existence and properties of interface object assert_own_property: should inherit from AbstractRange, but self has no such property expected property "AbstractRange" missing
-PASS Range interface object length
-PASS Range interface object name
-FAIL Range interface: existence and properties of interface prototype object assert_own_property: should inherit from AbstractRange, but self has no such property expected property "AbstractRange" missing
-PASS Range interface: existence and properties of interface prototype object's "constructor" property
-PASS Range interface: existence and properties of interface prototype object's @@unscopables property
-PASS Range interface: attribute commonAncestorContainer
-PASS Unscopable handled correctly for commonAncestorContainer property on Range
-PASS Range interface: operation setStart(Node, unsigned long)
-PASS Unscopable handled correctly for setStart(Node, unsigned long) on Range
-PASS Range interface: operation setEnd(Node, unsigned long)
-PASS Unscopable handled correctly for setEnd(Node, unsigned long) on Range
-PASS Range interface: operation setStartBefore(Node)
-PASS Unscopable handled correctly for setStartBefore(Node) on Range
-PASS Range interface: operation setStartAfter(Node)
-PASS Unscopable handled correctly for setStartAfter(Node) on Range
-PASS Range interface: operation setEndBefore(Node)
-PASS Unscopable handled correctly for setEndBefore(Node) on Range
-PASS Range interface: operation setEndAfter(Node)
-PASS Unscopable handled correctly for setEndAfter(Node) on Range
-PASS Range interface: operation collapse(boolean)
-PASS Unscopable handled correctly for collapse(boolean) on Range
-PASS Range interface: operation selectNode(Node)
-PASS Unscopable handled correctly for selectNode(Node) on Range
-PASS Range interface: operation selectNodeContents(Node)
-PASS Unscopable handled correctly for selectNodeContents(Node) on Range
-PASS Range interface: constant START_TO_START on interface object
-PASS Range interface: constant START_TO_START on interface prototype object
-PASS Range interface: constant START_TO_END on interface object
-PASS Range interface: constant START_TO_END on interface prototype object
-PASS Range interface: constant END_TO_END on interface object
-PASS Range interface: constant END_TO_END on interface prototype object
-PASS Range interface: constant END_TO_START on interface object
-PASS Range interface: constant END_TO_START on interface prototype object
-PASS Range interface: operation compareBoundaryPoints(unsigned short, Range)
-PASS Unscopable handled correctly for compareBoundaryPoints(unsigned short, Range) on Range
-PASS Range interface: operation deleteContents()
-PASS Unscopable handled correctly for deleteContents() on Range
-PASS Range interface: operation extractContents()
-PASS Unscopable handled correctly for extractContents() on Range
-PASS Range interface: operation cloneContents()
-PASS Unscopable handled correctly for cloneContents() on Range
-PASS Range interface: operation insertNode(Node)
-PASS Unscopable handled correctly for insertNode(Node) on Range
-PASS Range interface: operation surroundContents(Node)
-PASS Unscopable handled correctly for surroundContents(Node) on Range
-PASS Range interface: operation cloneRange()
-PASS Unscopable handled correctly for cloneRange() on Range
-PASS Range interface: operation detach()
-PASS Unscopable handled correctly for detach() on Range
-PASS Range interface: operation isPointInRange(Node, unsigned long)
-PASS Unscopable handled correctly for isPointInRange(Node, unsigned long) on Range
-PASS Range interface: operation comparePoint(Node, unsigned long)
-PASS Unscopable handled correctly for comparePoint(Node, unsigned long) on Range
-PASS Range interface: operation intersectsNode(Node)
-PASS Unscopable handled correctly for intersectsNode(Node) on Range
-PASS Range interface: stringifier
-PASS Range must be primary interface of document.createRange()
-PASS Stringification of document.createRange()
-PASS Range interface: document.createRange() must inherit property "commonAncestorContainer" with the proper type
-PASS Range interface: document.createRange() must inherit property "setStart(Node, unsigned long)" with the proper type
-PASS Range interface: calling setStart(Node, unsigned long) on document.createRange() with too few arguments must throw TypeError
-PASS Range interface: document.createRange() must inherit property "setEnd(Node, unsigned long)" with the proper type
-PASS Range interface: calling setEnd(Node, unsigned long) on document.createRange() with too few arguments must throw TypeError
-PASS Range interface: document.createRange() must inherit property "setStartBefore(Node)" with the proper type
-PASS Range interface: calling setStartBefore(Node) on document.createRange() with too few arguments must throw TypeError
-PASS Range interface: document.createRange() must inherit property "setStartAfter(Node)" with the proper type
-PASS Range interface: calling setStartAfter(Node) on document.createRange() with too few arguments must throw TypeError
-PASS Range interface: document.createRange() must inherit property "setEndBefore(Node)" with the proper type
-PASS Range interface: calling setEndBefore(Node) on document.createRange() with too few arguments must throw TypeError
-PASS Range interface: document.createRange() must inherit property "setEndAfter(Node)" with the proper type
-PASS Range interface: calling setEndAfter(Node) on document.createRange() with too few arguments must throw TypeError
-PASS Range interface: document.createRange() must inherit property "collapse(boolean)" with the proper type
-PASS Range interface: calling collapse(boolean) on document.createRange() with too few arguments must throw TypeError
-PASS Range interface: document.createRange() must inherit property "selectNode(Node)" with the proper type
-PASS Range interface: calling selectNode(Node) on document.createRange() with too few arguments must throw TypeError
-PASS Range interface: document.createRange() must inherit property "selectNodeContents(Node)" with the proper type
-PASS Range interface: calling selectNodeContents(Node) on document.createRange() with too few arguments must throw TypeError
-PASS Range interface: document.createRange() must inherit property "START_TO_START" with the proper type
-PASS Range interface: document.createRange() must inherit property "START_TO_END" with the proper type
-PASS Range interface: document.createRange() must inherit property "END_TO_END" with the proper type
-PASS Range interface: document.createRange() must inherit property "END_TO_START" with the proper type
-PASS Range interface: document.createRange() must inherit property "compareBoundaryPoints(unsigned short, Range)" with the proper type
-PASS Range interface: calling compareBoundaryPoints(unsigned short, Range) on document.createRange() with too few arguments must throw TypeError
-PASS Range interface: document.createRange() must inherit property "deleteContents()" with the proper type
-PASS Range interface: document.createRange() must inherit property "extractContents()" with the proper type
-PASS Range interface: document.createRange() must inherit property "cloneContents()" with the proper type
-PASS Range interface: document.createRange() must inherit property "insertNode(Node)" with the proper type
-PASS Range interface: calling insertNode(Node) on document.createRange() with too few arguments must throw TypeError
-PASS Range interface: document.createRange() must inherit property "surroundContents(Node)" with the proper type
-PASS Range interface: calling surroundContents(Node) on document.createRange() with too few arguments must throw TypeError
-PASS Range interface: document.createRange() must inherit property "cloneRange()" with the proper type
-PASS Range interface: document.createRange() must inherit property "detach()" with the proper type
-PASS Range interface: document.createRange() must inherit property "isPointInRange(Node, unsigned long)" with the proper type
-PASS Range interface: calling isPointInRange(Node, unsigned long) on document.createRange() with too few arguments must throw TypeError
-PASS Range interface: document.createRange() must inherit property "comparePoint(Node, unsigned long)" with the proper type
-PASS Range interface: calling comparePoint(Node, unsigned long) on document.createRange() with too few arguments must throw TypeError
-PASS Range interface: document.createRange() must inherit property "intersectsNode(Node)" with the proper type
-PASS Range interface: calling intersectsNode(Node) on document.createRange() with too few arguments must throw TypeError
-PASS AbstractRange interface: document.createRange() must inherit property "startContainer" with the proper type
-PASS AbstractRange interface: document.createRange() must inherit property "startOffset" with the proper type
-PASS AbstractRange interface: document.createRange() must inherit property "endContainer" with the proper type
-PASS AbstractRange interface: document.createRange() must inherit property "endOffset" with the proper type
-PASS AbstractRange interface: document.createRange() must inherit property "collapsed" with the proper type
-PASS Range must be primary interface of detachedRange
-PASS Stringification of detachedRange
-PASS Range interface: detachedRange must inherit property "commonAncestorContainer" with the proper type
-PASS Range interface: detachedRange must inherit property "setStart(Node, unsigned long)" with the proper type
-PASS Range interface: calling setStart(Node, unsigned long) on detachedRange with too few arguments must throw TypeError
-PASS Range interface: detachedRange must inherit property "setEnd(Node, unsigned long)" with the proper type
-PASS Range interface: calling setEnd(Node, unsigned long) on detachedRange with too few arguments must throw TypeError
-PASS Range interface: detachedRange must inherit property "setStartBefore(Node)" with the proper type
-PASS Range interface: calling setStartBefore(Node) on detachedRange with too few arguments must throw TypeError
-PASS Range interface: detachedRange must inherit property "setStartAfter(Node)" with the proper type
-PASS Range interface: calling setStartAfter(Node) on detachedRange with too few arguments must throw TypeError
-PASS Range interface: detachedRange must inherit property "setEndBefore(Node)" with the proper type
-PASS Range interface: calling setEndBefore(Node) on detachedRange with too few arguments must throw TypeError
-PASS Range interface: detachedRange must inherit property "setEndAfter(Node)" with the proper type
-PASS Range interface: calling setEndAfter(Node) on detachedRange with too few arguments must throw TypeError
-PASS Range interface: detachedRange must inherit property "collapse(boolean)" with the proper type
-PASS Range interface: calling collapse(boolean) on detachedRange with too few arguments must throw TypeError
-PASS Range interface: detachedRange must inherit property "selectNode(Node)" with the proper type
-PASS Range interface: calling selectNode(Node) on detachedRange with too few arguments must throw TypeError
-PASS Range interface: detachedRange must inherit property "selectNodeContents(Node)" with the proper type
-PASS Range interface: calling selectNodeContents(Node) on detachedRange with too few arguments must throw TypeError
-PASS Range interface: detachedRange must inherit property "START_TO_START" with the proper type
-PASS Range interface: detachedRange must inherit property "START_TO_END" with the proper type
-PASS Range interface: detachedRange must inherit property "END_TO_END" with the proper type
-PASS Range interface: detachedRange must inherit property "END_TO_START" with the proper type
-PASS Range interface: detachedRange must inherit property "compareBoundaryPoints(unsigned short, Range)" with the proper type
-PASS Range interface: calling compareBoundaryPoints(unsigned short, Range) on detachedRange with too few arguments must throw TypeError
-PASS Range interface: detachedRange must inherit property "deleteContents()" with the proper type
-PASS Range interface: detachedRange must inherit property "extractContents()" with the proper type
-PASS Range interface: detachedRange must inherit property "cloneContents()" with the proper type
-PASS Range interface: detachedRange must inherit property "insertNode(Node)" with the proper type
-PASS Range interface: calling insertNode(Node) on detachedRange with too few arguments must throw TypeError
-PASS Range interface: detachedRange must inherit property "surroundContents(Node)" with the proper type
-PASS Range interface: calling surroundContents(Node) on detachedRange with too few arguments must throw TypeError
-PASS Range interface: detachedRange must inherit property "cloneRange()" with the proper type
-PASS Range interface: detachedRange must inherit property "detach()" with the proper type
-PASS Range interface: detachedRange must inherit property "isPointInRange(Node, unsigned long)" with the proper type
-PASS Range interface: calling isPointInRange(Node, unsigned long) on detachedRange with too few arguments must throw TypeError
-PASS Range interface: detachedRange must inherit property "comparePoint(Node, unsigned long)" with the proper type
-PASS Range interface: calling comparePoint(Node, unsigned long) on detachedRange with too few arguments must throw TypeError
-PASS Range interface: detachedRange must inherit property "intersectsNode(Node)" with the proper type
-PASS Range interface: calling intersectsNode(Node) on detachedRange with too few arguments must throw TypeError
-PASS AbstractRange interface: detachedRange must inherit property "startContainer" with the proper type
-PASS AbstractRange interface: detachedRange must inherit property "startOffset" with the proper type
-PASS AbstractRange interface: detachedRange must inherit property "endContainer" with the proper type
-PASS AbstractRange interface: detachedRange must inherit property "endOffset" with the proper type
-PASS AbstractRange interface: detachedRange must inherit property "collapsed" with the proper type
-PASS NodeIterator interface: existence and properties of interface object
-PASS NodeIterator interface object length
-PASS NodeIterator interface object name
-PASS NodeIterator interface: existence and properties of interface prototype object
-PASS NodeIterator interface: existence and properties of interface prototype object's "constructor" property
-PASS NodeIterator interface: existence and properties of interface prototype object's @@unscopables property
-PASS NodeIterator interface: attribute root
-PASS Unscopable handled correctly for root property on NodeIterator
-PASS NodeIterator interface: attribute referenceNode
-PASS Unscopable handled correctly for referenceNode property on NodeIterator
-PASS NodeIterator interface: attribute pointerBeforeReferenceNode
-PASS Unscopable handled correctly for pointerBeforeReferenceNode property on NodeIterator
-PASS NodeIterator interface: attribute whatToShow
-PASS Unscopable handled correctly for whatToShow property on NodeIterator
-PASS NodeIterator interface: attribute filter
-PASS Unscopable handled correctly for filter property on NodeIterator
-PASS NodeIterator interface: operation nextNode()
-PASS Unscopable handled correctly for nextNode() on NodeIterator
-PASS NodeIterator interface: operation previousNode()
-PASS Unscopable handled correctly for previousNode() on NodeIterator
-PASS NodeIterator interface: operation detach()
-PASS Unscopable handled correctly for detach() on NodeIterator
-PASS NodeIterator must be primary interface of document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, null, false)
-PASS Stringification of document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, null, false)
-PASS NodeIterator interface: document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "root" with the proper type
-PASS NodeIterator interface: document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "referenceNode" with the proper type
-PASS NodeIterator interface: document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "pointerBeforeReferenceNode" with the proper type
-PASS NodeIterator interface: document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "whatToShow" with the proper type
-PASS NodeIterator interface: document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "filter" with the proper type
-PASS NodeIterator interface: document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "nextNode()" with the proper type
-PASS NodeIterator interface: document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "previousNode()" with the proper type
-PASS NodeIterator interface: document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "detach()" with the proper type
-PASS TreeWalker interface: existence and properties of interface object
-PASS TreeWalker interface object length
-PASS TreeWalker interface object name
-PASS TreeWalker interface: existence and properties of interface prototype object
-PASS TreeWalker interface: existence and properties of interface prototype object's "constructor" property
-PASS TreeWalker interface: existence and properties of interface prototype object's @@unscopables property
-PASS TreeWalker interface: attribute root
-PASS Unscopable handled correctly for root property on TreeWalker
-PASS TreeWalker interface: attribute whatToShow
-PASS Unscopable handled correctly for whatToShow property on TreeWalker
-PASS TreeWalker interface: attribute filter
-PASS Unscopable handled correctly for filter property on TreeWalker
-PASS TreeWalker interface: attribute currentNode
-PASS Unscopable handled correctly for currentNode property on TreeWalker
-PASS TreeWalker interface: operation parentNode()
-PASS Unscopable handled correctly for parentNode() on TreeWalker
-PASS TreeWalker interface: operation firstChild()
-PASS Unscopable handled correctly for firstChild() on TreeWalker
-PASS TreeWalker interface: operation lastChild()
-PASS Unscopable handled correctly for lastChild() on TreeWalker
-PASS TreeWalker interface: operation previousSibling()
-PASS Unscopable handled correctly for previousSibling() on TreeWalker
-PASS TreeWalker interface: operation nextSibling()
-PASS Unscopable handled correctly for nextSibling() on TreeWalker
-PASS TreeWalker interface: operation previousNode()
-PASS Unscopable handled correctly for previousNode() on TreeWalker
-PASS TreeWalker interface: operation nextNode()
-PASS Unscopable handled correctly for nextNode() on TreeWalker
-PASS TreeWalker must be primary interface of document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false)
-PASS Stringification of document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false)
-PASS TreeWalker interface: document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "root" with the proper type
-PASS TreeWalker interface: document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "whatToShow" with the proper type
-PASS TreeWalker interface: document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "filter" with the proper type
-PASS TreeWalker interface: document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "currentNode" with the proper type
-PASS TreeWalker interface: document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "parentNode()" with the proper type
-PASS TreeWalker interface: document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "firstChild()" with the proper type
-PASS TreeWalker interface: document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "lastChild()" with the proper type
-PASS TreeWalker interface: document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "previousSibling()" with the proper type
-PASS TreeWalker interface: document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "nextSibling()" with the proper type
-PASS TreeWalker interface: document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "previousNode()" with the proper type
-PASS TreeWalker interface: document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "nextNode()" with the proper type
-PASS NodeFilter interface: existence and properties of interface object
-PASS NodeFilter interface object name
-PASS NodeFilter interface: existence and properties of interface prototype object
-PASS NodeFilter interface: existence and properties of interface prototype object's "constructor" property
-PASS NodeFilter interface: existence and properties of interface prototype object's @@unscopables property
-PASS NodeFilter interface: constant FILTER_ACCEPT on interface object
-PASS NodeFilter interface: constant FILTER_ACCEPT on interface prototype object
-PASS NodeFilter interface: constant FILTER_REJECT on interface object
-PASS NodeFilter interface: constant FILTER_REJECT on interface prototype object
-PASS NodeFilter interface: constant FILTER_SKIP on interface object
-PASS NodeFilter interface: constant FILTER_SKIP on interface prototype object
-PASS NodeFilter interface: constant SHOW_ALL on interface object
-PASS NodeFilter interface: constant SHOW_ALL on interface prototype object
-PASS NodeFilter interface: constant SHOW_ELEMENT on interface object
-PASS NodeFilter interface: constant SHOW_ELEMENT on interface prototype object
-PASS NodeFilter interface: constant SHOW_ATTRIBUTE on interface object
-PASS NodeFilter interface: constant SHOW_ATTRIBUTE on interface prototype object
-PASS NodeFilter interface: constant SHOW_TEXT on interface object
-PASS NodeFilter interface: constant SHOW_TEXT on interface prototype object
-PASS NodeFilter interface: constant SHOW_CDATA_SECTION on interface object
-PASS NodeFilter interface: constant SHOW_CDATA_SECTION on interface prototype object
-PASS NodeFilter interface: constant SHOW_ENTITY_REFERENCE on interface object
-PASS NodeFilter interface: constant SHOW_ENTITY_REFERENCE on interface prototype object
-PASS NodeFilter interface: constant SHOW_ENTITY on interface object
-PASS NodeFilter interface: constant SHOW_ENTITY on interface prototype object
-PASS NodeFilter interface: constant SHOW_PROCESSING_INSTRUCTION on interface object
-PASS NodeFilter interface: constant SHOW_PROCESSING_INSTRUCTION on interface prototype object
-PASS NodeFilter interface: constant SHOW_COMMENT on interface object
-PASS NodeFilter interface: constant SHOW_COMMENT on interface prototype object
-PASS NodeFilter interface: constant SHOW_DOCUMENT on interface object
-PASS NodeFilter interface: constant SHOW_DOCUMENT on interface prototype object
-PASS NodeFilter interface: constant SHOW_DOCUMENT_TYPE on interface object
-PASS NodeFilter interface: constant SHOW_DOCUMENT_TYPE on interface prototype object
-PASS NodeFilter interface: constant SHOW_DOCUMENT_FRAGMENT on interface object
-PASS NodeFilter interface: constant SHOW_DOCUMENT_FRAGMENT on interface prototype object
-PASS NodeFilter interface: constant SHOW_NOTATION on interface object
-PASS NodeFilter interface: constant SHOW_NOTATION on interface prototype object
-PASS NodeFilter interface: operation acceptNode(Node)
-PASS Unscopable handled correctly for acceptNode(Node) on NodeFilter
-PASS DOMTokenList interface: existence and properties of interface object
-PASS DOMTokenList interface object length
-PASS DOMTokenList interface object name
-PASS DOMTokenList interface: existence and properties of interface prototype object
-PASS DOMTokenList interface: existence and properties of interface prototype object's "constructor" property
-PASS DOMTokenList interface: existence and properties of interface prototype object's @@unscopables property
-PASS DOMTokenList interface: attribute length
-PASS Unscopable handled correctly for length property on DOMTokenList
-PASS DOMTokenList interface: operation item(unsigned long)
-PASS Unscopable handled correctly for item(unsigned long) on DOMTokenList
-PASS DOMTokenList interface: operation contains(DOMString)
-PASS Unscopable handled correctly for contains(DOMString) on DOMTokenList
-PASS DOMTokenList interface: operation add(DOMString)
-PASS Unscopable handled correctly for add(DOMString) on DOMTokenList
-PASS DOMTokenList interface: operation remove(DOMString)
-PASS Unscopable handled correctly for remove(DOMString) on DOMTokenList
-PASS DOMTokenList interface: operation toggle(DOMString, boolean)
-PASS Unscopable handled correctly for toggle(DOMString, boolean) on DOMTokenList
-PASS DOMTokenList interface: operation replace(DOMString, DOMString)
-PASS Unscopable handled correctly for replace(DOMString, DOMString) on DOMTokenList
-PASS DOMTokenList interface: operation supports(DOMString)
-PASS Unscopable handled correctly for supports(DOMString) on DOMTokenList
-PASS DOMTokenList interface: attribute value
-PASS Unscopable handled correctly for value property on DOMTokenList
-PASS DOMTokenList interface: stringifier
-PASS DOMTokenList must be primary interface of document.body.classList
-PASS Stringification of document.body.classList
-PASS DOMTokenList interface: document.body.classList must inherit property "length" with the proper type
-PASS DOMTokenList interface: document.body.classList must inherit property "item(unsigned long)" with the proper type
-PASS DOMTokenList interface: calling item(unsigned long) on document.body.classList with too few arguments must throw TypeError
-PASS DOMTokenList interface: document.body.classList must inherit property "contains(DOMString)" with the proper type
-PASS DOMTokenList interface: calling contains(DOMString) on document.body.classList with too few arguments must throw TypeError
-PASS DOMTokenList interface: document.body.classList must inherit property "add(DOMString)" with the proper type
-PASS DOMTokenList interface: calling add(DOMString) on document.body.classList with too few arguments must throw TypeError
-PASS DOMTokenList interface: document.body.classList must inherit property "remove(DOMString)" with the proper type
-PASS DOMTokenList interface: calling remove(DOMString) on document.body.classList with too few arguments must throw TypeError
-PASS DOMTokenList interface: document.body.classList must inherit property "toggle(DOMString, boolean)" with the proper type
-PASS DOMTokenList interface: calling toggle(DOMString, boolean) on document.body.classList with too few arguments must throw TypeError
-PASS DOMTokenList interface: document.body.classList must inherit property "replace(DOMString, DOMString)" with the proper type
-PASS DOMTokenList interface: calling replace(DOMString, DOMString) on document.body.classList with too few arguments must throw TypeError
-PASS DOMTokenList interface: document.body.classList must inherit property "supports(DOMString)" with the proper type
-PASS DOMTokenList interface: calling supports(DOMString) on document.body.classList with too few arguments must throw TypeError
-PASS DOMTokenList interface: document.body.classList must inherit property "value" with the proper type
+FAIL Test driver promise_test: Unhandled rejection with value: "SVGElement includes HTMLOrSVGElement, but SVGElement is undefined."
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/cors/cors-cookies-redirect.any.js b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/cors/cors-cookies-redirect.any.js
new file mode 100644
index 0000000..f5217b4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/cors/cors-cookies-redirect.any.js
@@ -0,0 +1,49 @@
+// META: script=/common/utils.js
+// META: script=../resources/utils.js
+// META: script=/common/get-host-info.sub.js
+
+var redirectUrl = get_host_info().HTTP_REMOTE_ORIGIN + dirname(location.pathname) + RESOURCES_DIR + "redirect.py";
+var urlSetCookies1 = get_host_info().HTTP_REMOTE_ORIGIN + dirname(location.pathname) + RESOURCES_DIR + "top.txt";
+var urlSetCookies2 = get_host_info().HTTP_ORIGIN_WITH_DIFFERENT_PORT + dirname(location.pathname) + RESOURCES_DIR + "top.txt";
+var urlCheckCookies = get_host_info().HTTP_ORIGIN_WITH_DIFFERENT_PORT + dirname(location.pathname) + RESOURCES_DIR + "inspect-headers.py?cors&headers=cookie";
+
+var urlSetCookiesParameters = "?pipe=header(Access-Control-Allow-Origin," + location.origin + ")";
+urlSetCookiesParameters += "|header(Access-Control-Allow-Credentials,true)";
+
+urlSetCookiesParameters1 = urlSetCookiesParameters + "|header(Set-Cookie,a=1)";
+urlSetCookiesParameters2 = urlSetCookiesParameters + "|header(Set-Cookie,a=2)";
+
+urlClearCookiesParameters1 = urlSetCookiesParameters + "|header(Set-Cookie,a=1%3B%20max-age=0)";
+urlClearCookiesParameters2 = urlSetCookiesParameters + "|header(Set-Cookie,a=2%3B%20max-age=0)";
+
+promise_test(async (test) => {
+    await fetch(urlSetCookies1 + urlSetCookiesParameters1, {"credentials": "include", "mode": "cors"});
+    await fetch(urlSetCookies2 + urlSetCookiesParameters2, {"credentials": "include", "mode": "cors"});
+}, "Set cookies");
+
+function doTest(usePreflight) {
+    promise_test(async (test) => {
+        var url = redirectUrl;
+        var uuid_token = token();
+        var urlParameters = "?token=" + uuid_token + "&max_age=0";
+        urlParameters += "&redirect_status=301";
+        urlParameters += "&location=" + encodeURIComponent(urlCheckCookies);
+        urlParameters += "&allow_headers=a&headers=Cookie";
+        headers = [];
+        if (usePreflight)
+            headers.push(["a", "b"]);
+
+        var requestInit = {"credentials": "include", "mode": "cors", "headers": headers};
+        var response = await fetch(url + urlParameters, requestInit);
+
+        assert_equals(response.headers.get("x-request-cookie") , "a=2", "Request includes cookie(s)");
+    }, "Testing credentials after cross-origin redirection with CORS and " + (usePreflight ? "" : "no ") + "preflight");
+}
+
+doTest(false);
+doTest(true);
+
+promise_test(async (test) => {
+    await fetch(urlSetCookies1 + urlClearCookiesParameters1, {"credentials": "include", "mode": "cors"});
+    await fetch(urlSetCookies2 + urlClearCookiesParameters2, {"credentials": "include", "mode": "cors"});
+}, "Clean cookies");
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/resources/inspect-headers.py b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/resources/inspect-headers.py
index c4ace18a..d53038c 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/resources/inspect-headers.py
+++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/resources/inspect-headers.py
@@ -16,7 +16,10 @@
         headers.append(("Access-Control-Allow-Methods", "GET, POST, HEAD"))
         exposed_headers = ["x-request-" + header for header in checked_headers]
         headers.append(("Access-Control-Expose-Headers", ", ".join(exposed_headers)))
-        headers.append(("Access-Control-Allow-Headers", ", ".join(request.headers)))
+        if "allow_headers" in request.GET:
+            headers.append(("Access-Control-Allow-Headers", request.GET['allow_headers']))
+        else:
+            headers.append(("Access-Control-Allow-Headers", ", ".join(request.headers)))
 
     headers.append(("content-type", "text/plain"))
     return headers, ""
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/resources/redirect.py b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/resources/redirect.py
index 3d313e5..40c1b999 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/resources/redirect.py
+++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/resources/redirect.py
@@ -7,10 +7,14 @@
     status = 302
     headers = [("Content-Type", "text/plain"),
                ("Cache-Control", "no-cache"),
-               ("Pragma", "no-cache"),
-               ("Access-Control-Allow-Origin", "*")]
-    token = None
+               ("Pragma", "no-cache")]
+    if "Origin" in request.headers:
+        headers.append(("Access-Control-Allow-Origin", request.headers.get("Origin", "")))
+        headers.append(("Access-Control-Allow-Credentials", "true"))
+    else:
+        headers.append(("Access-Control-Allow-Origin", "*"))
 
+    token = None
     if "token" in request.GET:
         token = request.GET.first("token")
         data = request.server.stash.take(token)
diff --git a/third_party/WebKit/LayoutTests/external/wpt/hr-time/idlharness-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/hr-time/idlharness-expected.txt
new file mode 100644
index 0000000..169a07f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/hr-time/idlharness-expected.txt
@@ -0,0 +1,21 @@
+This is a testharness.js-based test.
+FAIL Test driver promise_test: Unhandled rejection with value: object "Error: undefined EventTarget not found (inherited by Performance)"
+FAIL Performance interface: existence and properties of interface object Cannot read property 'has_extended_attribute' of undefined
+PASS Performance interface object length
+PASS Performance interface object name
+FAIL Performance interface: existence and properties of interface prototype object Cannot read property 'has_extended_attribute' of undefined
+PASS Performance interface: existence and properties of interface prototype object's "constructor" property
+PASS Performance interface: existence and properties of interface prototype object's @@unscopables property
+PASS Performance interface: operation now()
+PASS Unscopable handled correctly for now() on Performance
+PASS Performance interface: attribute timeOrigin
+PASS Unscopable handled correctly for timeOrigin property on Performance
+PASS Performance interface: operation toJSON()
+PASS Unscopable handled correctly for toJSON() on Performance
+PASS Performance must be primary interface of window.performance
+FAIL Stringification of window.performance Cannot read property 'has_stringifier' of undefined
+PASS Performance interface: window.performance must inherit property "now()" with the proper type
+PASS Performance interface: window.performance must inherit property "timeOrigin" with the proper type
+PASS Performance interface: window.performance must inherit property "toJSON()" with the proper type
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/hr-time/idlharness.html b/third_party/WebKit/LayoutTests/external/wpt/hr-time/idlharness.html
index c3fd9070..4abaf60 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/hr-time/idlharness.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/hr-time/idlharness.html
@@ -18,12 +18,7 @@
 
 function doTest([html, hr_time]) {
   var idl_array = new IdlArray();
-  // HTML is needed for WindowOrWorkerGlobalScope. Provide dummy interfaces for
-  // things that HTML depends on in turn which are not under tests.
-  idl_array.add_untested_idls('interface Document {};');
-  idl_array.add_untested_idls('interface EventTarget {};');
-  idl_array.add_untested_idls('interface LinkStyle {};');
-  idl_array.add_untested_idls(html);
+  idl_array.add_untested_idls(html, { only: ['WindowOrWorkerGlobalScope'] });
   idl_array.add_idls(hr_time);
   idl_array.add_objects({
     Performance: ["window.performance"],
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces-expected.txt
index dfcde73..55836211 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 6702 tests; 6596 PASS, 106 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 6700 tests; 6601 PASS, 99 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Test driver
 PASS Document interface: attribute domain
 PASS Unscopable handled correctly for domain property on Document
@@ -582,6 +582,16 @@
 PASS Document interface: document.implementation.createDocument(null, "", null) must inherit property "oncopy" with the proper type
 PASS Document interface: document.implementation.createDocument(null, "", null) must inherit property "oncut" with the proper type
 PASS Document interface: document.implementation.createDocument(null, "", null) must inherit property "onpaste" with the proper type
+PASS SVGElement interface: attribute dataset
+PASS Unscopable handled correctly for dataset property on SVGElement
+PASS SVGElement interface: attribute nonce
+PASS Unscopable handled correctly for nonce property on SVGElement
+PASS SVGElement interface: attribute tabIndex
+PASS Unscopable handled correctly for tabIndex property on SVGElement
+PASS SVGElement interface: operation focus(FocusOptions)
+PASS Unscopable handled correctly for focus(FocusOptions) on SVGElement
+PASS SVGElement interface: operation blur()
+PASS Unscopable handled correctly for blur() on SVGElement
 PASS HTMLAllCollection interface: existence and properties of interface object
 PASS HTMLAllCollection interface object length
 PASS HTMLAllCollection interface object name
@@ -669,18 +679,10 @@
 PASS Unscopable handled correctly for translate property on HTMLElement
 PASS HTMLElement interface: attribute dir
 PASS Unscopable handled correctly for dir property on HTMLElement
-PASS HTMLElement interface: attribute dataset
-PASS Unscopable handled correctly for dataset property on HTMLElement
 PASS HTMLElement interface: attribute hidden
 PASS Unscopable handled correctly for hidden property on HTMLElement
 PASS HTMLElement interface: operation click()
 PASS Unscopable handled correctly for click() on HTMLElement
-PASS HTMLElement interface: attribute tabIndex
-PASS Unscopable handled correctly for tabIndex property on HTMLElement
-PASS HTMLElement interface: operation focus(FocusOptions)
-PASS Unscopable handled correctly for focus(FocusOptions) on HTMLElement
-PASS HTMLElement interface: operation blur()
-PASS Unscopable handled correctly for blur() on HTMLElement
 PASS HTMLElement interface: attribute accessKey
 PASS Unscopable handled correctly for accessKey property on HTMLElement
 FAIL HTMLElement interface: attribute accessKeyLabel assert_true: The prototype object must have a property "accessKeyLabel" expected true got false
@@ -827,19 +829,24 @@
 PASS Unscopable handled correctly for isContentEditable property on HTMLElement
 PASS HTMLElement interface: attribute inputMode
 PASS Unscopable handled correctly for inputMode property on HTMLElement
+PASS HTMLElement interface: attribute dataset
+PASS Unscopable handled correctly for dataset property on HTMLElement
+PASS HTMLElement interface: attribute nonce
+PASS Unscopable handled correctly for nonce property on HTMLElement
+PASS HTMLElement interface: attribute tabIndex
+PASS Unscopable handled correctly for tabIndex property on HTMLElement
+PASS HTMLElement interface: operation focus(FocusOptions)
+PASS Unscopable handled correctly for focus(FocusOptions) on HTMLElement
+PASS HTMLElement interface: operation blur()
+PASS Unscopable handled correctly for blur() on HTMLElement
 PASS HTMLElement must be primary interface of document.createElement("noscript")
 PASS Stringification of document.createElement("noscript")
 PASS HTMLElement interface: document.createElement("noscript") must inherit property "title" with the proper type
 PASS HTMLElement interface: document.createElement("noscript") must inherit property "lang" with the proper type
 PASS HTMLElement interface: document.createElement("noscript") must inherit property "translate" with the proper type
 PASS HTMLElement interface: document.createElement("noscript") must inherit property "dir" with the proper type
-PASS HTMLElement interface: document.createElement("noscript") must inherit property "dataset" with the proper type
 PASS HTMLElement interface: document.createElement("noscript") must inherit property "hidden" with the proper type
 PASS HTMLElement interface: document.createElement("noscript") must inherit property "click()" with the proper type
-PASS HTMLElement interface: document.createElement("noscript") must inherit property "tabIndex" with the proper type
-PASS HTMLElement interface: document.createElement("noscript") must inherit property "focus(FocusOptions)" with the proper type
-PASS HTMLElement interface: calling focus(FocusOptions) on document.createElement("noscript") with too few arguments must throw TypeError
-PASS HTMLElement interface: document.createElement("noscript") must inherit property "blur()" with the proper type
 PASS HTMLElement interface: document.createElement("noscript") must inherit property "accessKey" with the proper type
 FAIL HTMLElement interface: document.createElement("noscript") must inherit property "accessKeyLabel" with the proper type assert_inherits: property "accessKeyLabel" not found in prototype chain
 PASS HTMLElement interface: document.createElement("noscript") must inherit property "draggable" with the proper type
@@ -913,6 +920,12 @@
 PASS HTMLElement interface: document.createElement("noscript") must inherit property "contentEditable" with the proper type
 PASS HTMLElement interface: document.createElement("noscript") must inherit property "isContentEditable" with the proper type
 PASS HTMLElement interface: document.createElement("noscript") must inherit property "inputMode" with the proper type
+PASS HTMLElement interface: document.createElement("noscript") must inherit property "dataset" with the proper type
+PASS HTMLElement interface: document.createElement("noscript") must inherit property "nonce" with the proper type
+PASS HTMLElement interface: document.createElement("noscript") must inherit property "tabIndex" with the proper type
+PASS HTMLElement interface: document.createElement("noscript") must inherit property "focus(FocusOptions)" with the proper type
+PASS HTMLElement interface: calling focus(FocusOptions) on document.createElement("noscript") with too few arguments must throw TypeError
+PASS HTMLElement interface: document.createElement("noscript") must inherit property "blur()" with the proper type
 PASS HTMLUnknownElement interface: existence and properties of interface object
 PASS HTMLUnknownElement interface object length
 PASS HTMLUnknownElement interface object name
@@ -991,8 +1004,6 @@
 PASS Unscopable handled correctly for relList property on HTMLLinkElement
 PASS HTMLLinkElement interface: attribute media
 PASS Unscopable handled correctly for media property on HTMLLinkElement
-FAIL HTMLLinkElement interface: attribute nonce assert_own_property: expected property "nonce" missing
-PASS Unscopable handled correctly for nonce property on HTMLLinkElement
 PASS HTMLLinkElement interface: attribute integrity
 PASS Unscopable handled correctly for integrity property on HTMLLinkElement
 PASS HTMLLinkElement interface: attribute hreflang
@@ -1003,10 +1014,6 @@
 PASS Unscopable handled correctly for sizes property on HTMLLinkElement
 PASS HTMLLinkElement interface: attribute referrerPolicy
 PASS Unscopable handled correctly for referrerPolicy property on HTMLLinkElement
-FAIL HTMLLinkElement interface: attribute workerType assert_true: The prototype object must have a property "workerType" expected true got false
-PASS Unscopable handled correctly for workerType property on HTMLLinkElement
-FAIL HTMLLinkElement interface: attribute updateViaCache assert_true: The prototype object must have a property "updateViaCache" expected true got false
-PASS Unscopable handled correctly for updateViaCache property on HTMLLinkElement
 PASS HTMLLinkElement interface: attribute charset
 PASS Unscopable handled correctly for charset property on HTMLLinkElement
 PASS HTMLLinkElement interface: attribute rev
@@ -1021,14 +1028,11 @@
 PASS HTMLLinkElement interface: document.createElement("link") must inherit property "as" with the proper type
 PASS HTMLLinkElement interface: document.createElement("link") must inherit property "relList" with the proper type
 PASS HTMLLinkElement interface: document.createElement("link") must inherit property "media" with the proper type
-PASS HTMLLinkElement interface: document.createElement("link") must inherit property "nonce" with the proper type
 PASS HTMLLinkElement interface: document.createElement("link") must inherit property "integrity" with the proper type
 PASS HTMLLinkElement interface: document.createElement("link") must inherit property "hreflang" with the proper type
 PASS HTMLLinkElement interface: document.createElement("link") must inherit property "type" with the proper type
 PASS HTMLLinkElement interface: document.createElement("link") must inherit property "sizes" with the proper type
 PASS HTMLLinkElement interface: document.createElement("link") must inherit property "referrerPolicy" with the proper type
-FAIL HTMLLinkElement interface: document.createElement("link") must inherit property "workerType" with the proper type assert_inherits: property "workerType" not found in prototype chain
-FAIL HTMLLinkElement interface: document.createElement("link") must inherit property "updateViaCache" with the proper type assert_inherits: property "updateViaCache" not found in prototype chain
 PASS HTMLLinkElement interface: document.createElement("link") must inherit property "charset" with the proper type
 PASS HTMLLinkElement interface: document.createElement("link") must inherit property "rev" with the proper type
 PASS HTMLLinkElement interface: document.createElement("link") must inherit property "target" with the proper type
@@ -1060,14 +1064,11 @@
 PASS HTMLStyleElement interface: existence and properties of interface prototype object's @@unscopables property
 PASS HTMLStyleElement interface: attribute media
 PASS Unscopable handled correctly for media property on HTMLStyleElement
-FAIL HTMLStyleElement interface: attribute nonce assert_own_property: expected property "nonce" missing
-PASS Unscopable handled correctly for nonce property on HTMLStyleElement
 PASS HTMLStyleElement interface: attribute type
 PASS Unscopable handled correctly for type property on HTMLStyleElement
 PASS HTMLStyleElement must be primary interface of document.createElement("style")
 PASS Stringification of document.createElement("style")
 PASS HTMLStyleElement interface: document.createElement("style") must inherit property "media" with the proper type
-PASS HTMLStyleElement interface: document.createElement("style") must inherit property "nonce" with the proper type
 PASS HTMLStyleElement interface: document.createElement("style") must inherit property "type" with the proper type
 PASS HTMLBodyElement interface: existence and properties of interface object
 PASS HTMLBodyElement interface object length
@@ -4839,8 +4840,6 @@
 PASS Unscopable handled correctly for crossOrigin property on HTMLScriptElement
 PASS HTMLScriptElement interface: attribute text
 PASS Unscopable handled correctly for text property on HTMLScriptElement
-FAIL HTMLScriptElement interface: attribute nonce assert_own_property: expected property "nonce" missing
-PASS Unscopable handled correctly for nonce property on HTMLScriptElement
 PASS HTMLScriptElement interface: attribute integrity
 PASS Unscopable handled correctly for integrity property on HTMLScriptElement
 PASS HTMLScriptElement interface: attribute charset
@@ -4858,7 +4857,6 @@
 PASS HTMLScriptElement interface: document.createElement("script") must inherit property "defer" with the proper type
 PASS HTMLScriptElement interface: document.createElement("script") must inherit property "crossOrigin" with the proper type
 PASS HTMLScriptElement interface: document.createElement("script") must inherit property "text" with the proper type
-PASS HTMLScriptElement interface: document.createElement("script") must inherit property "nonce" with the proper type
 PASS HTMLScriptElement interface: document.createElement("script") must inherit property "integrity" with the proper type
 PASS HTMLScriptElement interface: document.createElement("script") must inherit property "charset" with the proper type
 PASS HTMLScriptElement interface: document.createElement("script") must inherit property "event" with the proper type
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-select-element/selected-index.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-select-element/selected-index.html
index 46f19da..70f6772b 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-select-element/selected-index.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/forms/the-select-element/selected-index.html
@@ -25,6 +25,11 @@
     <option></option>
     <option selected></option>
   </select>
+
+  <select id=display-none>
+    <option style="display:none"></option>
+    <option></option>
+  </select>
 </form>
 
 <script>
@@ -100,4 +105,19 @@
   form.reset();
   assertSelectedIndex(select, 1);
 }, "set and reset (HTMLOptionsCollection)");
+
+test(function () {
+  var select = document.getElementById('display-none');
+  assertSelectedIndex(select, 0);
+}, "get display:none");
+
+test(function () {
+  var select = document.getElementById('display-none');
+  select.offsetTop; // force rendering
+  assertSelectedIndex(select, 0);
+  select.options[1].selected = true;
+  assertSelectedIndex(select, 1);
+  select.options[1].selected = false;
+  assertSelectedIndex(select, 0);
+}, "reset to display:none");
 </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/html.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/html.idl
index 89558dfe..af85b42 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/interfaces/html.idl
+++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/html.idl
@@ -97,14 +97,10 @@
   [CEReactions] attribute DOMString lang;
   [CEReactions] attribute boolean translate;
   [CEReactions] attribute DOMString dir;
-  [SameObject] readonly attribute DOMStringMap dataset;
 
   // user interaction
   [CEReactions] attribute boolean hidden;
   void click();
-  [CEReactions] attribute long tabIndex;
-  void focus(optional FocusOptions options);
-  void blur();
   [CEReactions] attribute DOMString accessKey;
   readonly attribute DOMString accessKeyLabel;
   [CEReactions] attribute boolean draggable;
@@ -124,6 +120,17 @@
 // Note: intentionally not [HTMLConstructor]
 interface HTMLUnknownElement : HTMLElement { };
 
+interface mixin HTMLOrSVGElement {
+  [SameObject] readonly attribute DOMStringMap dataset;
+  attribute DOMString nonce;
+
+  [CEReactions] attribute long tabIndex;
+  void focus(optional FocusOptions options);
+  void blur();
+};
+HTMLElement includes HTMLOrSVGElement;
+SVGElement includes HTMLOrSVGElement;
+
 [Exposed=Window,
  OverrideBuiltins]
 interface DOMStringMap {
@@ -164,16 +171,11 @@
   [CEReactions] attribute DOMString as; // (default "")
   [SameObject, PutForwards=value] readonly attribute DOMTokenList relList;
   [CEReactions] attribute DOMString media;
-  [CEReactions] attribute DOMString nonce;
   [CEReactions] attribute DOMString integrity;
   [CEReactions] attribute DOMString hreflang;
   [CEReactions] attribute DOMString type;
   [SameObject, PutForwards=value] readonly attribute DOMTokenList sizes;
   [CEReactions] attribute DOMString referrerPolicy;
-  [CEReactions] attribute DOMString workerType;
-  [CEReactions] attribute DOMString updateViaCache;
-
-  // also has obsolete members
 };
 HTMLLinkElement includes LinkStyle;
 
@@ -191,8 +193,6 @@
  HTMLConstructor]
 interface HTMLStyleElement : HTMLElement {
   [CEReactions] attribute DOMString media;
-  [CEReactions] attribute DOMString nonce;
-  [CEReactions] attribute DOMString type;
 };
 HTMLStyleElement includes LinkStyle;
 
@@ -1108,11 +1108,8 @@
   [CEReactions] attribute boolean defer;
   [CEReactions] attribute DOMString? crossOrigin;
   [CEReactions] attribute DOMString text;
-  [CEReactions] attribute DOMString nonce;
   [CEReactions] attribute DOMString integrity;
 
-
-  // also has obsolete members
 };
 
 [Exposed=Window,
@@ -2379,6 +2376,10 @@
   [CEReactions] attribute long width;
 };
 
+partial interface HTMLStyleElement {
+  [CEReactions] attribute DOMString type;
+};
+
 partial interface HTMLScriptElement {
   [CEReactions] attribute DOMString charset;
   [CEReactions] attribute DOMString event;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaDevices-IDL-enumerateDevices-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaDevices-IDL-enumerateDevices-expected.txt
index 27b53f2a..a882132 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaDevices-IDL-enumerateDevices-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaDevices-IDL-enumerateDevices-expected.txt
@@ -133,6 +133,6 @@
 PASS MediaDeviceInfo interface: [object InputDeviceInfo] must inherit property "label" with the proper type
 PASS MediaDeviceInfo interface: [object InputDeviceInfo] must inherit property "groupId" with the proper type
 PASS MediaDeviceInfo interface: [object InputDeviceInfo] must inherit property "toJSON()" with the proper type
-PASS Test default toJSON operation of MediaDeviceInfo
+PASS Test default toJSON operation of InputDeviceInfo
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaDevices-enumerateDevices.https.html b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaDevices-enumerateDevices.https.html
index a29b583..c66251a 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaDevices-enumerateDevices.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaDevices-enumerateDevices.https.html
@@ -33,6 +33,8 @@
         assert_equals(typeof capabilities.groupId, "string", "groupId must be a string.");
         if (mediainfo.kind == "audioinput") {
           assert_equals(typeof capabilities.echoCancellation, "object", "echoCancellation must be an object.");
+          assert_equals(typeof capabilities.autoGainControl, "object", "autoGainControl must be an object.");
+          assert_equals(typeof capabilities.noiseSuppression, "object", "noiseSuppression must be an object.");
         }
         if (mediainfo.kind == "videoinput") {
           assert_equals(typeof capabilities.facingMode, "object", "facingMode must be an object.");
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaStreamTrack-getCapabilities.https.html b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaStreamTrack-getCapabilities.https.html
index 30f5d500..257578f 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaStreamTrack-getCapabilities.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaStreamTrack-getCapabilities.https.html
@@ -12,6 +12,8 @@
       var videoCapabilities = stream.getVideoTracks()[0].getCapabilities();
       assert_true(undefined !== audioCapabilities.deviceId, "MediaTrackCapabilities's deviceId should exist for an audio track.");
       assert_true(undefined !== audioCapabilities.echoCancellation, "MediaTrackCapabilities's echoCancellation should exist for an audio track.");
+      assert_true(undefined !== audioCapabilities.autoGainControl, "MediaTrackCapabilities's autoGainControl should exist for an audio track.");
+      assert_true(undefined !== audioCapabilities.noiseSuppression, "MediaTrackCapabilities's noiseSuppression should exist for an audio track.");
       assert_true(undefined !== videoCapabilities.deviceId, "MediaTrackCapabilities's deviceId should exist for a video track.");
     });
   });
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/PaymentItem/type_member.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/payment-request/PaymentItem/type_member.https-expected.txt
new file mode 100644
index 0000000..ab4a200f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/PaymentItem/type_member.https-expected.txt
@@ -0,0 +1,11 @@
+This is a testharness.js-based test.
+PASS Smoke test
+FAIL An invalid enum value for PaymentDetailsInit.total's type throws TypeError assert_throws: function "() => {
+    new PaymentRequest(validMethods, invalidDetails);
+  }" did not throw
+FAIL Invalid enum value for PaymentItem.type member throws a TypeError assert_throws: function "() => {
+    new PaymentRequest(validMethods, invalidDetails);
+  }" did not throw
+PASS Valid enum values for PaymentItem.type member does not throw
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/PaymentItem/type_member.https.html b/third_party/WebKit/LayoutTests/external/wpt/payment-request/PaymentItem/type_member.https.html
new file mode 100644
index 0000000..dc62a83
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/PaymentItem/type_member.https.html
@@ -0,0 +1,77 @@
+<!doctype html>
+<meta charset="utf8">
+<link rel="help" href="https://w3c.github.io/payment-request/#dom-paymentitem-type">
+<title>
+  PaymentItem type member
+</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+const validMethods = [
+  { supportedMethods: "basic-card" },
+  { supportedMethods: "https://apple.com/apple-pay" },
+];
+const validTotal = {
+  label: "Total",
+  amount: {
+    currency: "USD",
+    value: "5.00",
+  },
+};
+const validDisplayItem = {
+  label: "Item",
+  amount: {
+    currency: "USD",
+    value: "1.00",
+  },
+};
+const validDetails = {
+  total: validTotal,
+  displayItems: [validDisplayItem],
+};
+
+test(() => {
+  new PaymentRequest(validMethods, validDetails);
+}, "Smoke test");
+
+test(() => {
+  // Let's make an invalid DisplayItem for the total
+  const invalidTotal = Object.assign({}, validTotal, {
+    type: "this is not valid",
+  });
+  const invalidDetails = Object.assign({}, validDetails, {
+    total: invalidTotal,
+  });
+  assert_throws(new TypeError(), () => {
+    new PaymentRequest(validMethods, invalidDetails);
+  });
+}, "An invalid enum value for PaymentDetailsInit.total's type throws TypeError");
+
+test(() => {
+  // Let's make an invalid DisplayItem to add to displayItems
+  const invalidDisplayItem = Object.assign({}, validDisplayItem, {
+    type: "this is not valid",
+  });
+  const invalidDetails = Object.assign({}, validDetails, {
+    displayItems: [invalidDisplayItem, validDisplayItem],
+  });
+  assert_throws(new TypeError(), () => {
+    new PaymentRequest(validMethods, invalidDetails);
+  });
+}, "Invalid enum value for PaymentItem.type member throws a TypeError");
+
+test(() => {
+  // Let's make an invalid DisplayItem to add to displayItems
+  const taxDisplayItem = Object.assign({}, validDisplayItem, { type: "tax" });
+  const taxTotal = Object.assign({}, validTotal, { type: "tax" });
+  const validDetailsWithType = Object.assign({}, validDetails, {
+    total: taxTotal,
+    displayItems: [taxDisplayItem],
+  });
+  try {
+    new PaymentRequest(validMethods, validDetailsWithType);
+  } catch (err) {
+    assert_unexpected(err.message);
+  }
+}, "Valid enum values for PaymentItem.type member does not throw");
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-insecure.http-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-insecure.http-expected.txt
new file mode 100644
index 0000000..3b796d72
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-insecure.http-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL PaymentRequest constructor must not be exposed in insecure context assert_false: expected false got true
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-insecure.http.html b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-insecure.http.html
new file mode 100644
index 0000000..0212220
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-insecure.http.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<!-- Copyright © 2017 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). -->
+<meta charset="utf-8">
+<title>Test for PaymentRequest Constructor (insecure)</title>
+<link rel="help" href="https://w3c.github.io/payment-request/#paymentrequest-interface">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(() => {
+  assert_false(isSecureContext);
+  assert_false("PaymentRequest" in window);
+}, "PaymentRequest constructor must not be exposed in insecure context");
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/fake_bluetooth.mojom.js b/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/fake_bluetooth.mojom.js
index 4daf3f0..08c26b6 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/fake_bluetooth.mojom.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/fake_bluetooth.mojom.js
@@ -2270,6 +2270,155 @@
     encoder.writeUint32(0);
     encoder.encodeStruct(codec.NullableString, val.descriptorId);
   };
+  function FakeCentral_RemoveFakeDescriptor_Params(values) {
+    this.initDefaults_();
+    this.initFields_(values);
+  }
+
+
+  FakeCentral_RemoveFakeDescriptor_Params.prototype.initDefaults_ = function() {
+    this.descriptorId = null;
+    this.characteristicId = null;
+    this.serviceId = null;
+    this.peripheralAddress = null;
+  };
+  FakeCentral_RemoveFakeDescriptor_Params.prototype.initFields_ = function(fields) {
+    for(var field in fields) {
+        if (this.hasOwnProperty(field))
+          this[field] = fields[field];
+    }
+  };
+
+  FakeCentral_RemoveFakeDescriptor_Params.validate = function(messageValidator, offset) {
+    var err;
+    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+    if (err !== validator.validationError.NONE)
+        return err;
+
+    var kVersionSizes = [
+      {version: 0, numBytes: 40}
+    ];
+    err = messageValidator.validateStructVersion(offset, kVersionSizes);
+    if (err !== validator.validationError.NONE)
+        return err;
+
+
+    // validate FakeCentral_RemoveFakeDescriptor_Params.descriptorId
+    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
+    if (err !== validator.validationError.NONE)
+        return err;
+
+
+    // validate FakeCentral_RemoveFakeDescriptor_Params.characteristicId
+    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false)
+    if (err !== validator.validationError.NONE)
+        return err;
+
+
+    // validate FakeCentral_RemoveFakeDescriptor_Params.serviceId
+    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 16, false)
+    if (err !== validator.validationError.NONE)
+        return err;
+
+
+    // validate FakeCentral_RemoveFakeDescriptor_Params.peripheralAddress
+    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 24, false)
+    if (err !== validator.validationError.NONE)
+        return err;
+
+    return validator.validationError.NONE;
+  };
+
+  FakeCentral_RemoveFakeDescriptor_Params.encodedSize = codec.kStructHeaderSize + 32;
+
+  FakeCentral_RemoveFakeDescriptor_Params.decode = function(decoder) {
+    var packed;
+    var val = new FakeCentral_RemoveFakeDescriptor_Params();
+    var numberOfBytes = decoder.readUint32();
+    var version = decoder.readUint32();
+    val.descriptorId = decoder.decodeStruct(codec.String);
+    val.characteristicId = decoder.decodeStruct(codec.String);
+    val.serviceId = decoder.decodeStruct(codec.String);
+    val.peripheralAddress = decoder.decodeStruct(codec.String);
+    return val;
+  };
+
+  FakeCentral_RemoveFakeDescriptor_Params.encode = function(encoder, val) {
+    var packed;
+    encoder.writeUint32(FakeCentral_RemoveFakeDescriptor_Params.encodedSize);
+    encoder.writeUint32(0);
+    encoder.encodeStruct(codec.String, val.descriptorId);
+    encoder.encodeStruct(codec.String, val.characteristicId);
+    encoder.encodeStruct(codec.String, val.serviceId);
+    encoder.encodeStruct(codec.String, val.peripheralAddress);
+  };
+  function FakeCentral_RemoveFakeDescriptor_ResponseParams(values) {
+    this.initDefaults_();
+    this.initFields_(values);
+  }
+
+
+  FakeCentral_RemoveFakeDescriptor_ResponseParams.prototype.initDefaults_ = function() {
+    this.success = false;
+  };
+  FakeCentral_RemoveFakeDescriptor_ResponseParams.prototype.initFields_ = function(fields) {
+    for(var field in fields) {
+        if (this.hasOwnProperty(field))
+          this[field] = fields[field];
+    }
+  };
+
+  FakeCentral_RemoveFakeDescriptor_ResponseParams.validate = function(messageValidator, offset) {
+    var err;
+    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+    if (err !== validator.validationError.NONE)
+        return err;
+
+    var kVersionSizes = [
+      {version: 0, numBytes: 16}
+    ];
+    err = messageValidator.validateStructVersion(offset, kVersionSizes);
+    if (err !== validator.validationError.NONE)
+        return err;
+
+
+    return validator.validationError.NONE;
+  };
+
+  FakeCentral_RemoveFakeDescriptor_ResponseParams.encodedSize = codec.kStructHeaderSize + 8;
+
+  FakeCentral_RemoveFakeDescriptor_ResponseParams.decode = function(decoder) {
+    var packed;
+    var val = new FakeCentral_RemoveFakeDescriptor_ResponseParams();
+    var numberOfBytes = decoder.readUint32();
+    var version = decoder.readUint32();
+    packed = decoder.readUint8();
+    val.success = (packed >> 0) & 1 ? true : false;
+    decoder.skip(1);
+    decoder.skip(1);
+    decoder.skip(1);
+    decoder.skip(1);
+    decoder.skip(1);
+    decoder.skip(1);
+    decoder.skip(1);
+    return val;
+  };
+
+  FakeCentral_RemoveFakeDescriptor_ResponseParams.encode = function(encoder, val) {
+    var packed;
+    encoder.writeUint32(FakeCentral_RemoveFakeDescriptor_ResponseParams.encodedSize);
+    encoder.writeUint32(0);
+    packed = 0;
+    packed |= (val.success & 1) << 0
+    encoder.writeUint8(packed);
+    encoder.skip(1);
+    encoder.skip(1);
+    encoder.skip(1);
+    encoder.skip(1);
+    encoder.skip(1);
+    encoder.skip(1);
+    encoder.skip(1);
+  };
   function FakeCentral_SetNextReadCharacteristicResponse_Params(values) {
     this.initDefaults_();
     this.initFields_(values);
@@ -2747,25 +2896,25 @@
     encoder.skip(1);
     encoder.skip(1);
   };
-  function FakeCentral_GetLastWrittenValue_Params(values) {
+  function FakeCentral_GetLastWrittenCharacteristicValue_Params(values) {
     this.initDefaults_();
     this.initFields_(values);
   }
 
 
-  FakeCentral_GetLastWrittenValue_Params.prototype.initDefaults_ = function() {
+  FakeCentral_GetLastWrittenCharacteristicValue_Params.prototype.initDefaults_ = function() {
     this.characteristicId = null;
     this.serviceId = null;
     this.peripheralAddress = null;
   };
-  FakeCentral_GetLastWrittenValue_Params.prototype.initFields_ = function(fields) {
+  FakeCentral_GetLastWrittenCharacteristicValue_Params.prototype.initFields_ = function(fields) {
     for(var field in fields) {
         if (this.hasOwnProperty(field))
           this[field] = fields[field];
     }
   };
 
-  FakeCentral_GetLastWrittenValue_Params.validate = function(messageValidator, offset) {
+  FakeCentral_GetLastWrittenCharacteristicValue_Params.validate = function(messageValidator, offset) {
     var err;
     err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
     if (err !== validator.validationError.NONE)
@@ -2779,19 +2928,19 @@
         return err;
 
 
-    // validate FakeCentral_GetLastWrittenValue_Params.characteristicId
+    // validate FakeCentral_GetLastWrittenCharacteristicValue_Params.characteristicId
     err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
     if (err !== validator.validationError.NONE)
         return err;
 
 
-    // validate FakeCentral_GetLastWrittenValue_Params.serviceId
+    // validate FakeCentral_GetLastWrittenCharacteristicValue_Params.serviceId
     err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false)
     if (err !== validator.validationError.NONE)
         return err;
 
 
-    // validate FakeCentral_GetLastWrittenValue_Params.peripheralAddress
+    // validate FakeCentral_GetLastWrittenCharacteristicValue_Params.peripheralAddress
     err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 16, false)
     if (err !== validator.validationError.NONE)
         return err;
@@ -2799,11 +2948,11 @@
     return validator.validationError.NONE;
   };
 
-  FakeCentral_GetLastWrittenValue_Params.encodedSize = codec.kStructHeaderSize + 24;
+  FakeCentral_GetLastWrittenCharacteristicValue_Params.encodedSize = codec.kStructHeaderSize + 24;
 
-  FakeCentral_GetLastWrittenValue_Params.decode = function(decoder) {
+  FakeCentral_GetLastWrittenCharacteristicValue_Params.decode = function(decoder) {
     var packed;
-    var val = new FakeCentral_GetLastWrittenValue_Params();
+    var val = new FakeCentral_GetLastWrittenCharacteristicValue_Params();
     var numberOfBytes = decoder.readUint32();
     var version = decoder.readUint32();
     val.characteristicId = decoder.decodeStruct(codec.String);
@@ -2812,32 +2961,32 @@
     return val;
   };
 
-  FakeCentral_GetLastWrittenValue_Params.encode = function(encoder, val) {
+  FakeCentral_GetLastWrittenCharacteristicValue_Params.encode = function(encoder, val) {
     var packed;
-    encoder.writeUint32(FakeCentral_GetLastWrittenValue_Params.encodedSize);
+    encoder.writeUint32(FakeCentral_GetLastWrittenCharacteristicValue_Params.encodedSize);
     encoder.writeUint32(0);
     encoder.encodeStruct(codec.String, val.characteristicId);
     encoder.encodeStruct(codec.String, val.serviceId);
     encoder.encodeStruct(codec.String, val.peripheralAddress);
   };
-  function FakeCentral_GetLastWrittenValue_ResponseParams(values) {
+  function FakeCentral_GetLastWrittenCharacteristicValue_ResponseParams(values) {
     this.initDefaults_();
     this.initFields_(values);
   }
 
 
-  FakeCentral_GetLastWrittenValue_ResponseParams.prototype.initDefaults_ = function() {
+  FakeCentral_GetLastWrittenCharacteristicValue_ResponseParams.prototype.initDefaults_ = function() {
     this.success = false;
     this.value = null;
   };
-  FakeCentral_GetLastWrittenValue_ResponseParams.prototype.initFields_ = function(fields) {
+  FakeCentral_GetLastWrittenCharacteristicValue_ResponseParams.prototype.initFields_ = function(fields) {
     for(var field in fields) {
         if (this.hasOwnProperty(field))
           this[field] = fields[field];
     }
   };
 
-  FakeCentral_GetLastWrittenValue_ResponseParams.validate = function(messageValidator, offset) {
+  FakeCentral_GetLastWrittenCharacteristicValue_ResponseParams.validate = function(messageValidator, offset) {
     var err;
     err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
     if (err !== validator.validationError.NONE)
@@ -2852,7 +3001,7 @@
 
 
 
-    // validate FakeCentral_GetLastWrittenValue_ResponseParams.value
+    // validate FakeCentral_GetLastWrittenCharacteristicValue_ResponseParams.value
     err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 8, 1, codec.Uint8, true, [0], 0);
     if (err !== validator.validationError.NONE)
         return err;
@@ -2860,11 +3009,11 @@
     return validator.validationError.NONE;
   };
 
-  FakeCentral_GetLastWrittenValue_ResponseParams.encodedSize = codec.kStructHeaderSize + 16;
+  FakeCentral_GetLastWrittenCharacteristicValue_ResponseParams.encodedSize = codec.kStructHeaderSize + 16;
 
-  FakeCentral_GetLastWrittenValue_ResponseParams.decode = function(decoder) {
+  FakeCentral_GetLastWrittenCharacteristicValue_ResponseParams.decode = function(decoder) {
     var packed;
-    var val = new FakeCentral_GetLastWrittenValue_ResponseParams();
+    var val = new FakeCentral_GetLastWrittenCharacteristicValue_ResponseParams();
     var numberOfBytes = decoder.readUint32();
     var version = decoder.readUint32();
     packed = decoder.readUint8();
@@ -2880,9 +3029,9 @@
     return val;
   };
 
-  FakeCentral_GetLastWrittenValue_ResponseParams.encode = function(encoder, val) {
+  FakeCentral_GetLastWrittenCharacteristicValue_ResponseParams.encode = function(encoder, val) {
     var packed;
-    encoder.writeUint32(FakeCentral_GetLastWrittenValue_ResponseParams.encodedSize);
+    encoder.writeUint32(FakeCentral_GetLastWrittenCharacteristicValue_ResponseParams.encodedSize);
     encoder.writeUint32(0);
     packed = 0;
     packed |= (val.success & 1) << 0
@@ -3070,6 +3219,329 @@
     encoder.skip(1);
     encoder.skip(1);
   };
+  function FakeCentral_SetNextWriteDescriptorResponse_Params(values) {
+    this.initDefaults_();
+    this.initFields_(values);
+  }
+
+
+  FakeCentral_SetNextWriteDescriptorResponse_Params.prototype.initDefaults_ = function() {
+    this.gattCode = 0;
+    this.descriptorId = null;
+    this.characteristicId = null;
+    this.serviceId = null;
+    this.peripheralAddress = null;
+  };
+  FakeCentral_SetNextWriteDescriptorResponse_Params.prototype.initFields_ = function(fields) {
+    for(var field in fields) {
+        if (this.hasOwnProperty(field))
+          this[field] = fields[field];
+    }
+  };
+
+  FakeCentral_SetNextWriteDescriptorResponse_Params.validate = function(messageValidator, offset) {
+    var err;
+    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+    if (err !== validator.validationError.NONE)
+        return err;
+
+    var kVersionSizes = [
+      {version: 0, numBytes: 48}
+    ];
+    err = messageValidator.validateStructVersion(offset, kVersionSizes);
+    if (err !== validator.validationError.NONE)
+        return err;
+
+
+
+    // validate FakeCentral_SetNextWriteDescriptorResponse_Params.descriptorId
+    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false)
+    if (err !== validator.validationError.NONE)
+        return err;
+
+
+    // validate FakeCentral_SetNextWriteDescriptorResponse_Params.characteristicId
+    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 16, false)
+    if (err !== validator.validationError.NONE)
+        return err;
+
+
+    // validate FakeCentral_SetNextWriteDescriptorResponse_Params.serviceId
+    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 24, false)
+    if (err !== validator.validationError.NONE)
+        return err;
+
+
+    // validate FakeCentral_SetNextWriteDescriptorResponse_Params.peripheralAddress
+    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 32, false)
+    if (err !== validator.validationError.NONE)
+        return err;
+
+    return validator.validationError.NONE;
+  };
+
+  FakeCentral_SetNextWriteDescriptorResponse_Params.encodedSize = codec.kStructHeaderSize + 40;
+
+  FakeCentral_SetNextWriteDescriptorResponse_Params.decode = function(decoder) {
+    var packed;
+    var val = new FakeCentral_SetNextWriteDescriptorResponse_Params();
+    var numberOfBytes = decoder.readUint32();
+    var version = decoder.readUint32();
+    val.gattCode = decoder.decodeStruct(codec.Uint16);
+    decoder.skip(1);
+    decoder.skip(1);
+    decoder.skip(1);
+    decoder.skip(1);
+    decoder.skip(1);
+    decoder.skip(1);
+    val.descriptorId = decoder.decodeStruct(codec.String);
+    val.characteristicId = decoder.decodeStruct(codec.String);
+    val.serviceId = decoder.decodeStruct(codec.String);
+    val.peripheralAddress = decoder.decodeStruct(codec.String);
+    return val;
+  };
+
+  FakeCentral_SetNextWriteDescriptorResponse_Params.encode = function(encoder, val) {
+    var packed;
+    encoder.writeUint32(FakeCentral_SetNextWriteDescriptorResponse_Params.encodedSize);
+    encoder.writeUint32(0);
+    encoder.encodeStruct(codec.Uint16, val.gattCode);
+    encoder.skip(1);
+    encoder.skip(1);
+    encoder.skip(1);
+    encoder.skip(1);
+    encoder.skip(1);
+    encoder.skip(1);
+    encoder.encodeStruct(codec.String, val.descriptorId);
+    encoder.encodeStruct(codec.String, val.characteristicId);
+    encoder.encodeStruct(codec.String, val.serviceId);
+    encoder.encodeStruct(codec.String, val.peripheralAddress);
+  };
+  function FakeCentral_SetNextWriteDescriptorResponse_ResponseParams(values) {
+    this.initDefaults_();
+    this.initFields_(values);
+  }
+
+
+  FakeCentral_SetNextWriteDescriptorResponse_ResponseParams.prototype.initDefaults_ = function() {
+    this.success = false;
+  };
+  FakeCentral_SetNextWriteDescriptorResponse_ResponseParams.prototype.initFields_ = function(fields) {
+    for(var field in fields) {
+        if (this.hasOwnProperty(field))
+          this[field] = fields[field];
+    }
+  };
+
+  FakeCentral_SetNextWriteDescriptorResponse_ResponseParams.validate = function(messageValidator, offset) {
+    var err;
+    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+    if (err !== validator.validationError.NONE)
+        return err;
+
+    var kVersionSizes = [
+      {version: 0, numBytes: 16}
+    ];
+    err = messageValidator.validateStructVersion(offset, kVersionSizes);
+    if (err !== validator.validationError.NONE)
+        return err;
+
+
+    return validator.validationError.NONE;
+  };
+
+  FakeCentral_SetNextWriteDescriptorResponse_ResponseParams.encodedSize = codec.kStructHeaderSize + 8;
+
+  FakeCentral_SetNextWriteDescriptorResponse_ResponseParams.decode = function(decoder) {
+    var packed;
+    var val = new FakeCentral_SetNextWriteDescriptorResponse_ResponseParams();
+    var numberOfBytes = decoder.readUint32();
+    var version = decoder.readUint32();
+    packed = decoder.readUint8();
+    val.success = (packed >> 0) & 1 ? true : false;
+    decoder.skip(1);
+    decoder.skip(1);
+    decoder.skip(1);
+    decoder.skip(1);
+    decoder.skip(1);
+    decoder.skip(1);
+    decoder.skip(1);
+    return val;
+  };
+
+  FakeCentral_SetNextWriteDescriptorResponse_ResponseParams.encode = function(encoder, val) {
+    var packed;
+    encoder.writeUint32(FakeCentral_SetNextWriteDescriptorResponse_ResponseParams.encodedSize);
+    encoder.writeUint32(0);
+    packed = 0;
+    packed |= (val.success & 1) << 0
+    encoder.writeUint8(packed);
+    encoder.skip(1);
+    encoder.skip(1);
+    encoder.skip(1);
+    encoder.skip(1);
+    encoder.skip(1);
+    encoder.skip(1);
+    encoder.skip(1);
+  };
+  function FakeCentral_GetLastWrittenDescriptorValue_Params(values) {
+    this.initDefaults_();
+    this.initFields_(values);
+  }
+
+
+  FakeCentral_GetLastWrittenDescriptorValue_Params.prototype.initDefaults_ = function() {
+    this.descriptorId = null;
+    this.characteristicId = null;
+    this.serviceId = null;
+    this.peripheralAddress = null;
+  };
+  FakeCentral_GetLastWrittenDescriptorValue_Params.prototype.initFields_ = function(fields) {
+    for(var field in fields) {
+        if (this.hasOwnProperty(field))
+          this[field] = fields[field];
+    }
+  };
+
+  FakeCentral_GetLastWrittenDescriptorValue_Params.validate = function(messageValidator, offset) {
+    var err;
+    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+    if (err !== validator.validationError.NONE)
+        return err;
+
+    var kVersionSizes = [
+      {version: 0, numBytes: 40}
+    ];
+    err = messageValidator.validateStructVersion(offset, kVersionSizes);
+    if (err !== validator.validationError.NONE)
+        return err;
+
+
+    // validate FakeCentral_GetLastWrittenDescriptorValue_Params.descriptorId
+    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
+    if (err !== validator.validationError.NONE)
+        return err;
+
+
+    // validate FakeCentral_GetLastWrittenDescriptorValue_Params.characteristicId
+    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false)
+    if (err !== validator.validationError.NONE)
+        return err;
+
+
+    // validate FakeCentral_GetLastWrittenDescriptorValue_Params.serviceId
+    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 16, false)
+    if (err !== validator.validationError.NONE)
+        return err;
+
+
+    // validate FakeCentral_GetLastWrittenDescriptorValue_Params.peripheralAddress
+    err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 24, false)
+    if (err !== validator.validationError.NONE)
+        return err;
+
+    return validator.validationError.NONE;
+  };
+
+  FakeCentral_GetLastWrittenDescriptorValue_Params.encodedSize = codec.kStructHeaderSize + 32;
+
+  FakeCentral_GetLastWrittenDescriptorValue_Params.decode = function(decoder) {
+    var packed;
+    var val = new FakeCentral_GetLastWrittenDescriptorValue_Params();
+    var numberOfBytes = decoder.readUint32();
+    var version = decoder.readUint32();
+    val.descriptorId = decoder.decodeStruct(codec.String);
+    val.characteristicId = decoder.decodeStruct(codec.String);
+    val.serviceId = decoder.decodeStruct(codec.String);
+    val.peripheralAddress = decoder.decodeStruct(codec.String);
+    return val;
+  };
+
+  FakeCentral_GetLastWrittenDescriptorValue_Params.encode = function(encoder, val) {
+    var packed;
+    encoder.writeUint32(FakeCentral_GetLastWrittenDescriptorValue_Params.encodedSize);
+    encoder.writeUint32(0);
+    encoder.encodeStruct(codec.String, val.descriptorId);
+    encoder.encodeStruct(codec.String, val.characteristicId);
+    encoder.encodeStruct(codec.String, val.serviceId);
+    encoder.encodeStruct(codec.String, val.peripheralAddress);
+  };
+  function FakeCentral_GetLastWrittenDescriptorValue_ResponseParams(values) {
+    this.initDefaults_();
+    this.initFields_(values);
+  }
+
+
+  FakeCentral_GetLastWrittenDescriptorValue_ResponseParams.prototype.initDefaults_ = function() {
+    this.success = false;
+    this.value = null;
+  };
+  FakeCentral_GetLastWrittenDescriptorValue_ResponseParams.prototype.initFields_ = function(fields) {
+    for(var field in fields) {
+        if (this.hasOwnProperty(field))
+          this[field] = fields[field];
+    }
+  };
+
+  FakeCentral_GetLastWrittenDescriptorValue_ResponseParams.validate = function(messageValidator, offset) {
+    var err;
+    err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+    if (err !== validator.validationError.NONE)
+        return err;
+
+    var kVersionSizes = [
+      {version: 0, numBytes: 24}
+    ];
+    err = messageValidator.validateStructVersion(offset, kVersionSizes);
+    if (err !== validator.validationError.NONE)
+        return err;
+
+
+
+    // validate FakeCentral_GetLastWrittenDescriptorValue_ResponseParams.value
+    err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 8, 1, codec.Uint8, true, [0], 0);
+    if (err !== validator.validationError.NONE)
+        return err;
+
+    return validator.validationError.NONE;
+  };
+
+  FakeCentral_GetLastWrittenDescriptorValue_ResponseParams.encodedSize = codec.kStructHeaderSize + 16;
+
+  FakeCentral_GetLastWrittenDescriptorValue_ResponseParams.decode = function(decoder) {
+    var packed;
+    var val = new FakeCentral_GetLastWrittenDescriptorValue_ResponseParams();
+    var numberOfBytes = decoder.readUint32();
+    var version = decoder.readUint32();
+    packed = decoder.readUint8();
+    val.success = (packed >> 0) & 1 ? true : false;
+    decoder.skip(1);
+    decoder.skip(1);
+    decoder.skip(1);
+    decoder.skip(1);
+    decoder.skip(1);
+    decoder.skip(1);
+    decoder.skip(1);
+    val.value = decoder.decodeArrayPointer(codec.Uint8);
+    return val;
+  };
+
+  FakeCentral_GetLastWrittenDescriptorValue_ResponseParams.encode = function(encoder, val) {
+    var packed;
+    encoder.writeUint32(FakeCentral_GetLastWrittenDescriptorValue_ResponseParams.encodedSize);
+    encoder.writeUint32(0);
+    packed = 0;
+    packed |= (val.success & 1) << 0
+    encoder.writeUint8(packed);
+    encoder.skip(1);
+    encoder.skip(1);
+    encoder.skip(1);
+    encoder.skip(1);
+    encoder.skip(1);
+    encoder.skip(1);
+    encoder.skip(1);
+    encoder.encodeArrayPointer(codec.Uint8, val.value);
+  };
   var kFakeBluetooth_SetLESupported_Name = 0;
   var kFakeBluetooth_SimulateCentral_Name = 1;
   var kFakeBluetooth_AllResponsesConsumed_Name = 2;
@@ -3310,11 +3782,14 @@
   var kFakeCentral_AddFakeCharacteristic_Name = 8;
   var kFakeCentral_RemoveFakeCharacteristic_Name = 9;
   var kFakeCentral_AddFakeDescriptor_Name = 10;
-  var kFakeCentral_SetNextReadCharacteristicResponse_Name = 11;
-  var kFakeCentral_SetNextWriteCharacteristicResponse_Name = 12;
-  var kFakeCentral_SetNextSubscribeToNotificationsResponse_Name = 13;
-  var kFakeCentral_GetLastWrittenValue_Name = 14;
-  var kFakeCentral_SetNextReadDescriptorResponse_Name = 15;
+  var kFakeCentral_RemoveFakeDescriptor_Name = 11;
+  var kFakeCentral_SetNextReadCharacteristicResponse_Name = 12;
+  var kFakeCentral_SetNextWriteCharacteristicResponse_Name = 13;
+  var kFakeCentral_SetNextSubscribeToNotificationsResponse_Name = 14;
+  var kFakeCentral_GetLastWrittenCharacteristicValue_Name = 15;
+  var kFakeCentral_SetNextReadDescriptorResponse_Name = 16;
+  var kFakeCentral_SetNextWriteDescriptorResponse_Name = 17;
+  var kFakeCentral_GetLastWrittenDescriptorValue_Name = 18;
 
   function FakeCentralPtr(handleOrPtrInfo) {
     this.ptr = new bindings.InterfacePtrController(FakeCentral,
@@ -3623,6 +4098,34 @@
       });
     }.bind(this));
   };
+  FakeCentralPtr.prototype.removeFakeDescriptor = function() {
+    return FakeCentralProxy.prototype.removeFakeDescriptor
+        .apply(this.ptr.getProxy(), arguments);
+  };
+
+  FakeCentralProxy.prototype.removeFakeDescriptor = function(descriptorId, characteristicId, serviceId, peripheralAddress) {
+    var params = new FakeCentral_RemoveFakeDescriptor_Params();
+    params.descriptorId = descriptorId;
+    params.characteristicId = characteristicId;
+    params.serviceId = serviceId;
+    params.peripheralAddress = peripheralAddress;
+    return new Promise(function(resolve, reject) {
+      var builder = new codec.MessageV1Builder(
+          kFakeCentral_RemoveFakeDescriptor_Name,
+          codec.align(FakeCentral_RemoveFakeDescriptor_Params.encodedSize),
+          codec.kMessageExpectsResponse, 0);
+      builder.encodeStruct(FakeCentral_RemoveFakeDescriptor_Params, params);
+      var message = builder.finish();
+      this.receiver_.acceptAndExpectResponse(message).then(function(message) {
+        var reader = new codec.MessageReader(message);
+        var responseParams =
+            reader.decodeStruct(FakeCentral_RemoveFakeDescriptor_ResponseParams);
+        resolve(responseParams);
+      }).catch(function(result) {
+        reject(Error("Connection error: " + result));
+      });
+    }.bind(this));
+  };
   FakeCentralPtr.prototype.setNextReadCharacteristicResponse = function() {
     return FakeCentralProxy.prototype.setNextReadCharacteristicResponse
         .apply(this.ptr.getProxy(), arguments);
@@ -3708,27 +4211,27 @@
       });
     }.bind(this));
   };
-  FakeCentralPtr.prototype.getLastWrittenValue = function() {
-    return FakeCentralProxy.prototype.getLastWrittenValue
+  FakeCentralPtr.prototype.getLastWrittenCharacteristicValue = function() {
+    return FakeCentralProxy.prototype.getLastWrittenCharacteristicValue
         .apply(this.ptr.getProxy(), arguments);
   };
 
-  FakeCentralProxy.prototype.getLastWrittenValue = function(characteristicId, serviceId, peripheralAddress) {
-    var params = new FakeCentral_GetLastWrittenValue_Params();
+  FakeCentralProxy.prototype.getLastWrittenCharacteristicValue = function(characteristicId, serviceId, peripheralAddress) {
+    var params = new FakeCentral_GetLastWrittenCharacteristicValue_Params();
     params.characteristicId = characteristicId;
     params.serviceId = serviceId;
     params.peripheralAddress = peripheralAddress;
     return new Promise(function(resolve, reject) {
       var builder = new codec.MessageV1Builder(
-          kFakeCentral_GetLastWrittenValue_Name,
-          codec.align(FakeCentral_GetLastWrittenValue_Params.encodedSize),
+          kFakeCentral_GetLastWrittenCharacteristicValue_Name,
+          codec.align(FakeCentral_GetLastWrittenCharacteristicValue_Params.encodedSize),
           codec.kMessageExpectsResponse, 0);
-      builder.encodeStruct(FakeCentral_GetLastWrittenValue_Params, params);
+      builder.encodeStruct(FakeCentral_GetLastWrittenCharacteristicValue_Params, params);
       var message = builder.finish();
       this.receiver_.acceptAndExpectResponse(message).then(function(message) {
         var reader = new codec.MessageReader(message);
         var responseParams =
-            reader.decodeStruct(FakeCentral_GetLastWrittenValue_ResponseParams);
+            reader.decodeStruct(FakeCentral_GetLastWrittenCharacteristicValue_ResponseParams);
         resolve(responseParams);
       }).catch(function(result) {
         reject(Error("Connection error: " + result));
@@ -3765,6 +4268,63 @@
       });
     }.bind(this));
   };
+  FakeCentralPtr.prototype.setNextWriteDescriptorResponse = function() {
+    return FakeCentralProxy.prototype.setNextWriteDescriptorResponse
+        .apply(this.ptr.getProxy(), arguments);
+  };
+
+  FakeCentralProxy.prototype.setNextWriteDescriptorResponse = function(gattCode, descriptorId, characteristicId, serviceId, peripheralAddress) {
+    var params = new FakeCentral_SetNextWriteDescriptorResponse_Params();
+    params.gattCode = gattCode;
+    params.descriptorId = descriptorId;
+    params.characteristicId = characteristicId;
+    params.serviceId = serviceId;
+    params.peripheralAddress = peripheralAddress;
+    return new Promise(function(resolve, reject) {
+      var builder = new codec.MessageV1Builder(
+          kFakeCentral_SetNextWriteDescriptorResponse_Name,
+          codec.align(FakeCentral_SetNextWriteDescriptorResponse_Params.encodedSize),
+          codec.kMessageExpectsResponse, 0);
+      builder.encodeStruct(FakeCentral_SetNextWriteDescriptorResponse_Params, params);
+      var message = builder.finish();
+      this.receiver_.acceptAndExpectResponse(message).then(function(message) {
+        var reader = new codec.MessageReader(message);
+        var responseParams =
+            reader.decodeStruct(FakeCentral_SetNextWriteDescriptorResponse_ResponseParams);
+        resolve(responseParams);
+      }).catch(function(result) {
+        reject(Error("Connection error: " + result));
+      });
+    }.bind(this));
+  };
+  FakeCentralPtr.prototype.getLastWrittenDescriptorValue = function() {
+    return FakeCentralProxy.prototype.getLastWrittenDescriptorValue
+        .apply(this.ptr.getProxy(), arguments);
+  };
+
+  FakeCentralProxy.prototype.getLastWrittenDescriptorValue = function(descriptorId, characteristicId, serviceId, peripheralAddress) {
+    var params = new FakeCentral_GetLastWrittenDescriptorValue_Params();
+    params.descriptorId = descriptorId;
+    params.characteristicId = characteristicId;
+    params.serviceId = serviceId;
+    params.peripheralAddress = peripheralAddress;
+    return new Promise(function(resolve, reject) {
+      var builder = new codec.MessageV1Builder(
+          kFakeCentral_GetLastWrittenDescriptorValue_Name,
+          codec.align(FakeCentral_GetLastWrittenDescriptorValue_Params.encodedSize),
+          codec.kMessageExpectsResponse, 0);
+      builder.encodeStruct(FakeCentral_GetLastWrittenDescriptorValue_Params, params);
+      var message = builder.finish();
+      this.receiver_.acceptAndExpectResponse(message).then(function(message) {
+        var reader = new codec.MessageReader(message);
+        var responseParams =
+            reader.decodeStruct(FakeCentral_GetLastWrittenDescriptorValue_ResponseParams);
+        resolve(responseParams);
+      }).catch(function(result) {
+        reject(Error("Connection error: " + result));
+      });
+    }.bind(this));
+  };
 
   function FakeCentralStub(delegate) {
     this.delegate_ = delegate;
@@ -3802,6 +4362,9 @@
   FakeCentralStub.prototype.addFakeDescriptor = function(descriptorUuid, characteristicId, serviceId, peripheralAddress) {
     return this.delegate_ && this.delegate_.addFakeDescriptor && this.delegate_.addFakeDescriptor(descriptorUuid, characteristicId, serviceId, peripheralAddress);
   }
+  FakeCentralStub.prototype.removeFakeDescriptor = function(descriptorId, characteristicId, serviceId, peripheralAddress) {
+    return this.delegate_ && this.delegate_.removeFakeDescriptor && this.delegate_.removeFakeDescriptor(descriptorId, characteristicId, serviceId, peripheralAddress);
+  }
   FakeCentralStub.prototype.setNextReadCharacteristicResponse = function(gattCode, value, characteristicId, serviceId, peripheralAddress) {
     return this.delegate_ && this.delegate_.setNextReadCharacteristicResponse && this.delegate_.setNextReadCharacteristicResponse(gattCode, value, characteristicId, serviceId, peripheralAddress);
   }
@@ -3811,12 +4374,18 @@
   FakeCentralStub.prototype.setNextSubscribeToNotificationsResponse = function(gattCode, characteristicId, serviceId, peripheralAddress) {
     return this.delegate_ && this.delegate_.setNextSubscribeToNotificationsResponse && this.delegate_.setNextSubscribeToNotificationsResponse(gattCode, characteristicId, serviceId, peripheralAddress);
   }
-  FakeCentralStub.prototype.getLastWrittenValue = function(characteristicId, serviceId, peripheralAddress) {
-    return this.delegate_ && this.delegate_.getLastWrittenValue && this.delegate_.getLastWrittenValue(characteristicId, serviceId, peripheralAddress);
+  FakeCentralStub.prototype.getLastWrittenCharacteristicValue = function(characteristicId, serviceId, peripheralAddress) {
+    return this.delegate_ && this.delegate_.getLastWrittenCharacteristicValue && this.delegate_.getLastWrittenCharacteristicValue(characteristicId, serviceId, peripheralAddress);
   }
   FakeCentralStub.prototype.setNextReadDescriptorResponse = function(gattCode, value, descriptorId, characteristicId, serviceId, peripheralAddress) {
     return this.delegate_ && this.delegate_.setNextReadDescriptorResponse && this.delegate_.setNextReadDescriptorResponse(gattCode, value, descriptorId, characteristicId, serviceId, peripheralAddress);
   }
+  FakeCentralStub.prototype.setNextWriteDescriptorResponse = function(gattCode, descriptorId, characteristicId, serviceId, peripheralAddress) {
+    return this.delegate_ && this.delegate_.setNextWriteDescriptorResponse && this.delegate_.setNextWriteDescriptorResponse(gattCode, descriptorId, characteristicId, serviceId, peripheralAddress);
+  }
+  FakeCentralStub.prototype.getLastWrittenDescriptorValue = function(descriptorId, characteristicId, serviceId, peripheralAddress) {
+    return this.delegate_ && this.delegate_.getLastWrittenDescriptorValue && this.delegate_.getLastWrittenDescriptorValue(descriptorId, characteristicId, serviceId, peripheralAddress);
+  }
 
   FakeCentralStub.prototype.accept = function(message) {
     var reader = new codec.MessageReader(message);
@@ -4004,6 +4573,22 @@
         responder.accept(message);
       });
       return true;
+    case kFakeCentral_RemoveFakeDescriptor_Name:
+      var params = reader.decodeStruct(FakeCentral_RemoveFakeDescriptor_Params);
+      this.removeFakeDescriptor(params.descriptorId, params.characteristicId, params.serviceId, params.peripheralAddress).then(function(response) {
+        var responseParams =
+            new FakeCentral_RemoveFakeDescriptor_ResponseParams();
+        responseParams.success = response.success;
+        var builder = new codec.MessageV1Builder(
+            kFakeCentral_RemoveFakeDescriptor_Name,
+            codec.align(FakeCentral_RemoveFakeDescriptor_ResponseParams.encodedSize),
+            codec.kMessageIsResponse, reader.requestID);
+        builder.encodeStruct(FakeCentral_RemoveFakeDescriptor_ResponseParams,
+                             responseParams);
+        var message = builder.finish();
+        responder.accept(message);
+      });
+      return true;
     case kFakeCentral_SetNextReadCharacteristicResponse_Name:
       var params = reader.decodeStruct(FakeCentral_SetNextReadCharacteristicResponse_Params);
       this.setNextReadCharacteristicResponse(params.gattCode, params.value, params.characteristicId, params.serviceId, params.peripheralAddress).then(function(response) {
@@ -4052,18 +4637,18 @@
         responder.accept(message);
       });
       return true;
-    case kFakeCentral_GetLastWrittenValue_Name:
-      var params = reader.decodeStruct(FakeCentral_GetLastWrittenValue_Params);
-      this.getLastWrittenValue(params.characteristicId, params.serviceId, params.peripheralAddress).then(function(response) {
+    case kFakeCentral_GetLastWrittenCharacteristicValue_Name:
+      var params = reader.decodeStruct(FakeCentral_GetLastWrittenCharacteristicValue_Params);
+      this.getLastWrittenCharacteristicValue(params.characteristicId, params.serviceId, params.peripheralAddress).then(function(response) {
         var responseParams =
-            new FakeCentral_GetLastWrittenValue_ResponseParams();
+            new FakeCentral_GetLastWrittenCharacteristicValue_ResponseParams();
         responseParams.success = response.success;
         responseParams.value = response.value;
         var builder = new codec.MessageV1Builder(
-            kFakeCentral_GetLastWrittenValue_Name,
-            codec.align(FakeCentral_GetLastWrittenValue_ResponseParams.encodedSize),
+            kFakeCentral_GetLastWrittenCharacteristicValue_Name,
+            codec.align(FakeCentral_GetLastWrittenCharacteristicValue_ResponseParams.encodedSize),
             codec.kMessageIsResponse, reader.requestID);
-        builder.encodeStruct(FakeCentral_GetLastWrittenValue_ResponseParams,
+        builder.encodeStruct(FakeCentral_GetLastWrittenCharacteristicValue_ResponseParams,
                              responseParams);
         var message = builder.finish();
         responder.accept(message);
@@ -4085,6 +4670,39 @@
         responder.accept(message);
       });
       return true;
+    case kFakeCentral_SetNextWriteDescriptorResponse_Name:
+      var params = reader.decodeStruct(FakeCentral_SetNextWriteDescriptorResponse_Params);
+      this.setNextWriteDescriptorResponse(params.gattCode, params.descriptorId, params.characteristicId, params.serviceId, params.peripheralAddress).then(function(response) {
+        var responseParams =
+            new FakeCentral_SetNextWriteDescriptorResponse_ResponseParams();
+        responseParams.success = response.success;
+        var builder = new codec.MessageV1Builder(
+            kFakeCentral_SetNextWriteDescriptorResponse_Name,
+            codec.align(FakeCentral_SetNextWriteDescriptorResponse_ResponseParams.encodedSize),
+            codec.kMessageIsResponse, reader.requestID);
+        builder.encodeStruct(FakeCentral_SetNextWriteDescriptorResponse_ResponseParams,
+                             responseParams);
+        var message = builder.finish();
+        responder.accept(message);
+      });
+      return true;
+    case kFakeCentral_GetLastWrittenDescriptorValue_Name:
+      var params = reader.decodeStruct(FakeCentral_GetLastWrittenDescriptorValue_Params);
+      this.getLastWrittenDescriptorValue(params.descriptorId, params.characteristicId, params.serviceId, params.peripheralAddress).then(function(response) {
+        var responseParams =
+            new FakeCentral_GetLastWrittenDescriptorValue_ResponseParams();
+        responseParams.success = response.success;
+        responseParams.value = response.value;
+        var builder = new codec.MessageV1Builder(
+            kFakeCentral_GetLastWrittenDescriptorValue_Name,
+            codec.align(FakeCentral_GetLastWrittenDescriptorValue_ResponseParams.encodedSize),
+            codec.kMessageIsResponse, reader.requestID);
+        builder.encodeStruct(FakeCentral_GetLastWrittenDescriptorValue_ResponseParams,
+                             responseParams);
+        var message = builder.finish();
+        responder.accept(message);
+      });
+      return true;
     default:
       return false;
     }
@@ -4138,6 +4756,10 @@
         if (message.expectsResponse())
           paramsClass = FakeCentral_AddFakeDescriptor_Params;
       break;
+      case kFakeCentral_RemoveFakeDescriptor_Name:
+        if (message.expectsResponse())
+          paramsClass = FakeCentral_RemoveFakeDescriptor_Params;
+      break;
       case kFakeCentral_SetNextReadCharacteristicResponse_Name:
         if (message.expectsResponse())
           paramsClass = FakeCentral_SetNextReadCharacteristicResponse_Params;
@@ -4150,14 +4772,22 @@
         if (message.expectsResponse())
           paramsClass = FakeCentral_SetNextSubscribeToNotificationsResponse_Params;
       break;
-      case kFakeCentral_GetLastWrittenValue_Name:
+      case kFakeCentral_GetLastWrittenCharacteristicValue_Name:
         if (message.expectsResponse())
-          paramsClass = FakeCentral_GetLastWrittenValue_Params;
+          paramsClass = FakeCentral_GetLastWrittenCharacteristicValue_Params;
       break;
       case kFakeCentral_SetNextReadDescriptorResponse_Name:
         if (message.expectsResponse())
           paramsClass = FakeCentral_SetNextReadDescriptorResponse_Params;
       break;
+      case kFakeCentral_SetNextWriteDescriptorResponse_Name:
+        if (message.expectsResponse())
+          paramsClass = FakeCentral_SetNextWriteDescriptorResponse_Params;
+      break;
+      case kFakeCentral_GetLastWrittenDescriptorValue_Name:
+        if (message.expectsResponse())
+          paramsClass = FakeCentral_GetLastWrittenDescriptorValue_Params;
+      break;
     }
     if (paramsClass === null)
       return validator.validationError.NONE;
@@ -4212,6 +4842,10 @@
         if (message.isResponse())
           paramsClass = FakeCentral_AddFakeDescriptor_ResponseParams;
         break;
+      case kFakeCentral_RemoveFakeDescriptor_Name:
+        if (message.isResponse())
+          paramsClass = FakeCentral_RemoveFakeDescriptor_ResponseParams;
+        break;
       case kFakeCentral_SetNextReadCharacteristicResponse_Name:
         if (message.isResponse())
           paramsClass = FakeCentral_SetNextReadCharacteristicResponse_ResponseParams;
@@ -4224,14 +4858,22 @@
         if (message.isResponse())
           paramsClass = FakeCentral_SetNextSubscribeToNotificationsResponse_ResponseParams;
         break;
-      case kFakeCentral_GetLastWrittenValue_Name:
+      case kFakeCentral_GetLastWrittenCharacteristicValue_Name:
         if (message.isResponse())
-          paramsClass = FakeCentral_GetLastWrittenValue_ResponseParams;
+          paramsClass = FakeCentral_GetLastWrittenCharacteristicValue_ResponseParams;
         break;
       case kFakeCentral_SetNextReadDescriptorResponse_Name:
         if (message.isResponse())
           paramsClass = FakeCentral_SetNextReadDescriptorResponse_ResponseParams;
         break;
+      case kFakeCentral_SetNextWriteDescriptorResponse_Name:
+        if (message.isResponse())
+          paramsClass = FakeCentral_SetNextWriteDescriptorResponse_ResponseParams;
+        break;
+      case kFakeCentral_GetLastWrittenDescriptorValue_Name:
+        if (message.isResponse())
+          paramsClass = FakeCentral_GetLastWrittenDescriptorValue_ResponseParams;
+        break;
     }
     if (paramsClass === null)
       return validator.validationError.NONE;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/web-bluetooth-test.js b/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/web-bluetooth-test.js
index c10685f..e08c8c4a 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/web-bluetooth-test.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/web-bluetooth-test.js
@@ -377,7 +377,7 @@
       await this.fake_central_ptr_.setNextWriteCharacteristicResponse(
         gatt_code, ...this.ids_);
 
-    if (!success) throw 'setNextWriteResponse failed';
+    if (!success) throw 'setNextWriteCharacteristicResponse failed';
   }
 
   // Sets the next subscribe to notifications response for characteristic with
@@ -397,9 +397,10 @@
   // Returns null if no value has yet been written to the characteristic.
   async getLastWrittenValue() {
     let {success, value} =
-      await this.fake_central_ptr_.getLastWrittenValue(...this.ids_);
+      await this.fake_central_ptr_.getLastWrittenCharacteristicValue(
+          ...this.ids_);
 
-    if (!success) throw 'getLastWrittenValue failed';
+    if (!success) throw 'getLastWrittenCharacteristicValue failed';
 
     return value;
   }
@@ -444,6 +445,39 @@
 
     if (!success) throw 'setNextReadDescriptorResponse failed';
   }
+
+  // Sets the next write response for this descriptor to |code|.
+  // |code| could be a GATT Error Response from
+  // BT 4.2 Vol 3 Part F 3.4.1.1 Error Response or a number outside that range
+  // returned by specific platforms e.g. Android returns 0x101 to signal a GATT
+  // failure.
+  async setNextWriteResponse(gatt_code) {
+    let {success} =
+      await this.fake_central_ptr_.setNextWriteDescriptorResponse(
+        gatt_code, ...this.ids_);
+
+    if (!success) throw 'setNextWriteDescriptorResponse failed';
+  }
+
+  // Gets the last successfully written value to the descriptor.
+  // Returns null if no value has yet been written to the descriptor.
+  async getLastWrittenValue() {
+    let {success, value} =
+      await this.fake_central_ptr_.getLastWrittenDescriptorValue(
+          ...this.ids_);
+
+    if (!success) throw 'getLastWrittenDescriptorValue failed';
+
+    return value;
+  }
+
+  // Removes the fake GATT Descriptor from its fake characteristic.
+  async remove() {
+    let {success} =
+        await this.fake_central_ptr_.removeFakeDescriptor(...this.ids_);
+
+    if (!success) throw 'remove failed';
+  }
 }
 
 // FakeChooser allows clients to simulate events that a user would trigger when
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js b/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js
index af17cee6..fee33fd1 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js
@@ -177,7 +177,7 @@
 };
 
 //@}
-IdlArray.prototype.add_untested_idls = function(raw_idls)
+IdlArray.prototype.add_untested_idls = function(raw_idls, options)
 //@{
 {
     /** Entry point.  See documentation at beginning of file. */
@@ -193,7 +193,7 @@
             }
         }
     }
-    this.internal_add_idls(parsed_idls);
+    this.internal_add_idls(parsed_idls, options);
 };
 
 //@}
@@ -274,14 +274,14 @@
         }
 
         parsed_idl.array = this;
-        if (parsed_idl.name in this.members)
-        {
-            throw "Duplicate identifier " + parsed_idl.name;
-        }
         if (should_skip(parsed_idl.name))
         {
             return;
         }
+        if (parsed_idl.name in this.members)
+        {
+            throw "Duplicate identifier " + parsed_idl.name;
+        }
         switch(parsed_idl.type)
         {
         case "interface":
@@ -2069,6 +2069,7 @@
 };
 
 IdlInterface.prototype.test_to_json_operation = function(memberHolderObject, member) {
+    var instanceName = memberHolderObject.constructor.name;
     if (member.has_extended_attribute("Default")) {
         var map = this.default_to_json_operation();
         test(function() {
@@ -2082,12 +2083,12 @@
                 this.array.assert_type_is(json[k], type);
                 delete json[k];
             }, this);
-        }.bind(this), "Test default toJSON operation of " + this.name);
+        }.bind(this), "Test default toJSON operation of " + instanceName);
     } else {
         test(function() {
-            assert_true(this.array.is_json_type(member.idlType), JSON.stringify(member.idlType) + " is not an appropriate return value for the toJSON operation of " + this.name);
+            assert_true(this.array.is_json_type(member.idlType), JSON.stringify(member.idlType) + " is not an appropriate return value for the toJSON operation of " + instanceName);
             this.array.assert_type_is(memberHolderObject.toJSON(), member.idlType);
-        }.bind(this), "Test toJSON operation of " + this.name);
+        }.bind(this), "Test toJSON operation of " + instanceName);
     }
 };
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/idlharness-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/idlharness-expected.txt
index 5a7f45d4..ff09919 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/idlharness-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/web-animations/interfaces/KeyframeEffect/idlharness-expected.txt
@@ -1,4 +1,28 @@
 This is a testharness.js-based test.
-FAIL KeyframeEffect interface. promise_test: Unhandled rejection with value: "Duplicate identifier AnimationEffect"
+PASS KeyframeEffect interface.
+PASS KeyframeEffect interface: existence and properties of interface object
+PASS KeyframeEffect interface object length
+PASS KeyframeEffect interface object name
+PASS KeyframeEffect interface: existence and properties of interface prototype object
+PASS KeyframeEffect interface: existence and properties of interface prototype object's "constructor" property
+PASS KeyframeEffect interface: existence and properties of interface prototype object's @@unscopables property
+FAIL KeyframeEffect interface: attribute target assert_equals: setter must be function for PutForwards, Replaceable, or non-readonly attributes expected "function" but got "undefined"
+PASS Unscopable handled correctly for target property on KeyframeEffect
+FAIL KeyframeEffect interface: attribute iterationComposite assert_true: The prototype object must have a property "iterationComposite" expected true got false
+PASS Unscopable handled correctly for iterationComposite property on KeyframeEffect
+PASS KeyframeEffect interface: attribute composite
+PASS Unscopable handled correctly for composite property on KeyframeEffect
+PASS KeyframeEffect interface: operation getKeyframes()
+PASS Unscopable handled correctly for getKeyframes() on KeyframeEffect
+PASS KeyframeEffect interface: operation setKeyframes(object)
+PASS Unscopable handled correctly for setKeyframes(object) on KeyframeEffect
+PASS KeyframeEffect must be primary interface of new KeyframeEffect(null, null)
+PASS Stringification of new KeyframeEffect(null, null)
+PASS KeyframeEffect interface: new KeyframeEffect(null, null) must inherit property "target" with the proper type
+FAIL KeyframeEffect interface: new KeyframeEffect(null, null) must inherit property "iterationComposite" with the proper type assert_inherits: property "iterationComposite" not found in prototype chain
+PASS KeyframeEffect interface: new KeyframeEffect(null, null) must inherit property "composite" with the proper type
+PASS KeyframeEffect interface: new KeyframeEffect(null, null) must inherit property "getKeyframes()" with the proper type
+PASS KeyframeEffect interface: new KeyframeEffect(null, null) must inherit property "setKeyframes(object)" with the proper type
+PASS KeyframeEffect interface: calling setKeyframes(object) on new KeyframeEffect(null, null) with too few arguments must throw TypeError
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webaudio/idlharness.https.html b/third_party/WebKit/LayoutTests/external/wpt/webaudio/idlharness.https.html
index a8be8d0..9e15e47 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webaudio/idlharness.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/webaudio/idlharness.https.html
@@ -25,12 +25,15 @@
 
   const idl_array = new IdlArray();
 
-
-  idl_array.add_untested_idls('interface LinkStyle {};'); // Dependency of HTML
+  // Dependencies of HTML
+  idl_array.add_untested_idls('interface LinkStyle {};');
+  idl_array.add_untested_idls('interface SVGElement {};');
   idl_array.add_untested_idls(html);
+
   idl_array.add_untested_idls(dom);
   idl_array.add_untested_idls(mediacapture);
   idl_array.add_untested_idls('interface Worklet {};');
+
   idl_array.add_idls(webaudio);
 
   const sample_rate = 44100;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-setLocalDescription-answer-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-setLocalDescription-answer-expected.txt
index bec610c..1568cb7 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-setLocalDescription-answer-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-setLocalDescription-answer-expected.txt
@@ -1,9 +1,9 @@
 This is a testharness.js-based test.
 FAIL setLocalDescription() with valid answer should succeed assert_not_equals: Expect session description to be defined got disallowed value undefined
-FAIL setLocalDescription() with type answer and null sdp should use lastAnswer generated from createAnswer promise_test: Unhandled rejection with value: object "OperationError: Failed to parse SessionDescription.  Expect line: v="
-FAIL setLocalDescription() with answer not created by own createAnswer() should reject with InvalidModificationError assert_throws: function "function () { throw e }" threw object "OperationError: Failed to set local answer sdp: Failed to push down transport description: Local fingerprint does not match identity. Expected: sha-256 B5:81:44:BA:F9:E4:DB:24:6C:1C:7E:FF:52:82:7A:67:3C:52:69:F6:5C:D8:BF:B8:FC:34:A2:23:E5:B2:5D:0D Got: sha-256 9D:21:20:4B:66:BC:27:C1:C5:C1:3F:48:63:4A:A9:AC:ED:9F:1C:18:CF:BC:D5:88:9D:19:4F:A3:FC:D2:13:23" that is not a DOMException InvalidModificationError: property "code" is equal to 0, expected 13
-FAIL Calling setLocalDescription(answer) from stable state should reject with InvalidStateError assert_throws: function "function () { throw e }" threw object "OperationError: Failed to set local answer sdp: Called in wrong state: STATE_INIT" that is not a DOMException InvalidStateError: property "code" is equal to 0, expected 11
-FAIL Calling setLocalDescription(answer) from have-local-offer state should reject with InvalidStateError assert_throws: function "function () { throw e }" threw object "OperationError: Failed to set local answer sdp: Called in wrong state: STATE_SENTOFFER" that is not a DOMException InvalidStateError: property "code" is equal to 0, expected 11
+FAIL setLocalDescription() with type answer and null sdp should use lastAnswer generated from createAnswer assert_not_equals: Expect session description to be defined got disallowed value undefined
+PASS setLocalDescription() with answer not created by own createAnswer() should reject with InvalidModificationError
+PASS Calling setLocalDescription(answer) from stable state should reject with InvalidStateError
+PASS Calling setLocalDescription(answer) from have-local-offer state should reject with InvalidStateError
 PASS Test onsignalingstatechange event for setLocalDescription() with valid answer should succeed
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-setLocalDescription-offer-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-setLocalDescription-offer-expected.txt
index 11f65b4b..85ae4dc 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-setLocalDescription-offer-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-setLocalDescription-offer-expected.txt
@@ -1,7 +1,7 @@
 This is a testharness.js-based test.
 FAIL setLocalDescription with valid offer should succeed assert_not_equals: Expect session description to be defined got disallowed value undefined
-FAIL setLocalDescription with type offer and null sdp should use lastOffer generated from createOffer promise_test: Unhandled rejection with value: object "OperationError: Failed to parse SessionDescription.  Expect line: v="
-FAIL setLocalDescription() with offer not created by own createOffer() should reject with InvalidModificationError assert_unreached: Should have rejected: undefined Reached unreachable code
+FAIL setLocalDescription with type offer and null sdp should use lastOffer generated from createOffer assert_not_equals: Expect session description to be defined got disallowed value undefined
+PASS setLocalDescription() with offer not created by own createOffer() should reject with InvalidModificationError
 FAIL Set created offer other than last offer should reject with InvalidModificationError assert_unreached: Should have rejected: undefined Reached unreachable code
 FAIL Creating and setting offer multiple times should succeed assert_not_equals: Expect session description to be defined got disallowed value undefined
 PASS Test onsignalingstatechange event for setLocalDescription with valid offer should succeed
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-setLocalDescription-offer.html b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-setLocalDescription-offer.html
index 5de04e91..76df63a8 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-setLocalDescription-offer.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-setLocalDescription-offer.html
@@ -99,11 +99,12 @@
    */
   promise_test(t => {
     const pc = new RTCPeerConnection();
+    const pc2 = new RTCPeerConnection();
 
     return generateOffer({ pc, data: true })
     .then(offer =>
       promise_rejects(t, 'InvalidModificationError',
-        pc.setLocalDescription(offer)));
+        pc2.setLocalDescription(offer)));
   }, 'setLocalDescription() with offer not created by own createOffer() should reject with InvalidModificationError');
 
   promise_test(t => {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-setLocalDescription-pranswer-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-setLocalDescription-pranswer-expected.txt
index 850de44..4f25eadc 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-setLocalDescription-pranswer-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCPeerConnection-setLocalDescription-pranswer-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-FAIL setLocalDescription(pranswer) from stable state should reject with InvalidStateError assert_throws: function "function() { throw e }" threw object "OperationError: Failed to set local pranswer sdp: Called in wrong state: kStable" that is not a DOMException InvalidStateError: property "code" is equal to 0, expected 11
+PASS setLocalDescription(pranswer) from stable state should reject with InvalidStateError
 FAIL setLocalDescription(pranswer) should succeed assert_not_equals: Expect session description to be defined got disallowed value undefined
 PASS setLocalDescription(pranswer) can be applied multiple times while still in have-local-pranswer
 FAIL setLocalDescription(answer) from have-local-pranswer state should succeed assert_not_equals: Expect session description to be defined got disallowed value undefined
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/interfaces.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/webrtc/interfaces.https-expected.txt
index bfe77a0..4ef1e875 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/interfaces.https-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/interfaces.https-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-PASS Main test driver
+FAIL Main test driver promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'constructor' of undefined"
 PASS Test driver for asyncInitCertificate
 FAIL Test driver for asyncInitTransports assert_unreached: Failed to run asyncInitTransports: ReferenceError: RTCSctpTransport is not defined Reached unreachable code
 PASS Test driver for asyncInitMediaStreamTrack
@@ -268,430 +268,5 @@
 FAIL RTCIceCandidate interface: new RTCIceCandidate({ sdpMid: 1 }) must inherit property "relatedPort" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeMismatchError: Failed to construct 'RTCIceCandidate': The 'candidate' property is not a string, or is empty."
 FAIL RTCIceCandidate interface: new RTCIceCandidate({ sdpMid: 1 }) must inherit property "usernameFragment" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeMismatchError: Failed to construct 'RTCIceCandidate': The 'candidate' property is not a string, or is empty."
 FAIL RTCIceCandidate interface: new RTCIceCandidate({ sdpMid: 1 }) must inherit property "toJSON()" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeMismatchError: Failed to construct 'RTCIceCandidate': The 'candidate' property is not a string, or is empty."
-FAIL Test toJSON operation of RTCIceCandidate Cannot read property 'toJSON' of undefined
-FAIL RTCPeerConnectionIceEvent interface: existence and properties of interface object Cannot read property 'has_extended_attribute' of undefined
-PASS RTCPeerConnectionIceEvent interface object length
-PASS RTCPeerConnectionIceEvent interface object name
-FAIL RTCPeerConnectionIceEvent interface: existence and properties of interface prototype object Cannot read property 'has_extended_attribute' of undefined
-PASS RTCPeerConnectionIceEvent interface: existence and properties of interface prototype object's "constructor" property
-PASS RTCPeerConnectionIceEvent interface: existence and properties of interface prototype object's @@unscopables property
-PASS RTCPeerConnectionIceEvent interface: attribute candidate
-PASS Unscopable handled correctly for candidate property on RTCPeerConnectionIceEvent
-FAIL RTCPeerConnectionIceEvent interface: attribute url assert_true: The prototype object must have a property "url" expected true got false
-PASS Unscopable handled correctly for url property on RTCPeerConnectionIceEvent
-PASS RTCPeerConnectionIceEvent must be primary interface of new RTCPeerConnectionIceEvent('ice')
-FAIL Stringification of new RTCPeerConnectionIceEvent('ice') Cannot read property 'has_stringifier' of undefined
-PASS RTCPeerConnectionIceEvent interface: new RTCPeerConnectionIceEvent('ice') must inherit property "candidate" with the proper type
-FAIL RTCPeerConnectionIceEvent interface: new RTCPeerConnectionIceEvent('ice') must inherit property "url" with the proper type assert_inherits: property "url" not found in prototype chain
-FAIL RTCPeerConnectionIceErrorEvent interface: existence and properties of interface object assert_own_property: self does not have own property "RTCPeerConnectionIceErrorEvent" expected property "RTCPeerConnectionIceErrorEvent" missing
-FAIL RTCPeerConnectionIceErrorEvent interface object length assert_own_property: self does not have own property "RTCPeerConnectionIceErrorEvent" expected property "RTCPeerConnectionIceErrorEvent" missing
-FAIL RTCPeerConnectionIceErrorEvent interface object name assert_own_property: self does not have own property "RTCPeerConnectionIceErrorEvent" expected property "RTCPeerConnectionIceErrorEvent" missing
-FAIL RTCPeerConnectionIceErrorEvent interface: existence and properties of interface prototype object assert_own_property: self does not have own property "RTCPeerConnectionIceErrorEvent" expected property "RTCPeerConnectionIceErrorEvent" missing
-FAIL RTCPeerConnectionIceErrorEvent interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "RTCPeerConnectionIceErrorEvent" expected property "RTCPeerConnectionIceErrorEvent" missing
-FAIL RTCPeerConnectionIceErrorEvent interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "RTCPeerConnectionIceErrorEvent" expected property "RTCPeerConnectionIceErrorEvent" missing
-FAIL RTCPeerConnectionIceErrorEvent interface: attribute hostCandidate assert_own_property: self does not have own property "RTCPeerConnectionIceErrorEvent" expected property "RTCPeerConnectionIceErrorEvent" missing
-PASS Unscopable handled correctly for hostCandidate property on RTCPeerConnectionIceErrorEvent
-FAIL RTCPeerConnectionIceErrorEvent interface: attribute url assert_own_property: self does not have own property "RTCPeerConnectionIceErrorEvent" expected property "RTCPeerConnectionIceErrorEvent" missing
-PASS Unscopable handled correctly for url property on RTCPeerConnectionIceErrorEvent
-FAIL RTCPeerConnectionIceErrorEvent interface: attribute errorCode assert_own_property: self does not have own property "RTCPeerConnectionIceErrorEvent" expected property "RTCPeerConnectionIceErrorEvent" missing
-PASS Unscopable handled correctly for errorCode property on RTCPeerConnectionIceErrorEvent
-FAIL RTCPeerConnectionIceErrorEvent interface: attribute errorText assert_own_property: self does not have own property "RTCPeerConnectionIceErrorEvent" expected property "RTCPeerConnectionIceErrorEvent" missing
-PASS Unscopable handled correctly for errorText property on RTCPeerConnectionIceErrorEvent
-FAIL RTCPeerConnectionIceErrorEvent must be primary interface of new RTCPeerConnectionIceErrorEvent('ice-error', { errorCode: 701 }); assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: RTCPeerConnectionIceErrorEvent is not defined"
-FAIL Stringification of new RTCPeerConnectionIceErrorEvent('ice-error', { errorCode: 701 }); assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: RTCPeerConnectionIceErrorEvent is not defined"
-FAIL RTCPeerConnectionIceErrorEvent interface: new RTCPeerConnectionIceErrorEvent('ice-error', { errorCode: 701 }); must inherit property "hostCandidate" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: RTCPeerConnectionIceErrorEvent is not defined"
-FAIL RTCPeerConnectionIceErrorEvent interface: new RTCPeerConnectionIceErrorEvent('ice-error', { errorCode: 701 }); must inherit property "url" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: RTCPeerConnectionIceErrorEvent is not defined"
-FAIL RTCPeerConnectionIceErrorEvent interface: new RTCPeerConnectionIceErrorEvent('ice-error', { errorCode: 701 }); must inherit property "errorCode" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: RTCPeerConnectionIceErrorEvent is not defined"
-FAIL RTCPeerConnectionIceErrorEvent interface: new RTCPeerConnectionIceErrorEvent('ice-error', { errorCode: 701 }); must inherit property "errorText" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: RTCPeerConnectionIceErrorEvent is not defined"
-PASS RTCCertificate interface: existence and properties of interface object
-PASS RTCCertificate interface object length
-PASS RTCCertificate interface object name
-PASS RTCCertificate interface: existence and properties of interface prototype object
-PASS RTCCertificate interface: existence and properties of interface prototype object's "constructor" property
-PASS RTCCertificate interface: existence and properties of interface prototype object's @@unscopables property
-PASS RTCCertificate interface: attribute expires
-PASS Unscopable handled correctly for expires property on RTCCertificate
-PASS RTCCertificate interface: operation getFingerprints()
-PASS Unscopable handled correctly for getFingerprints() on RTCCertificate
-FAIL RTCCertificate interface: operation getAlgorithm() assert_own_property: interface prototype object missing non-static operation expected property "getAlgorithm" missing
-PASS Unscopable handled correctly for getAlgorithm() on RTCCertificate
-PASS RTCCertificate must be primary interface of idlTestObjects.certificate
-PASS Stringification of idlTestObjects.certificate
-PASS RTCCertificate interface: idlTestObjects.certificate must inherit property "expires" with the proper type
-PASS RTCCertificate interface: idlTestObjects.certificate must inherit property "getFingerprints()" with the proper type
-FAIL RTCCertificate interface: idlTestObjects.certificate must inherit property "getAlgorithm()" with the proper type assert_inherits: property "getAlgorithm" not found in prototype chain
-PASS RTCRtpSender interface: existence and properties of interface object
-PASS RTCRtpSender interface object length
-PASS RTCRtpSender interface object name
-PASS RTCRtpSender interface: existence and properties of interface prototype object
-PASS RTCRtpSender interface: existence and properties of interface prototype object's "constructor" property
-PASS RTCRtpSender interface: existence and properties of interface prototype object's @@unscopables property
-PASS RTCRtpSender interface: attribute track
-PASS Unscopable handled correctly for track property on RTCRtpSender
-FAIL RTCRtpSender interface: attribute transport assert_true: The prototype object must have a property "transport" expected true got false
-PASS Unscopable handled correctly for transport property on RTCRtpSender
-FAIL RTCRtpSender interface: attribute rtcpTransport assert_true: The prototype object must have a property "rtcpTransport" expected true got false
-PASS Unscopable handled correctly for rtcpTransport property on RTCRtpSender
-FAIL RTCRtpSender interface: operation getCapabilities(DOMString) assert_own_property: interface object missing static operation expected property "getCapabilities" missing
-PASS Unscopable handled correctly for getCapabilities(DOMString) on RTCRtpSender
-PASS RTCRtpSender interface: operation setParameters(RTCRtpParameters)
-PASS Unscopable handled correctly for setParameters(RTCRtpParameters) on RTCRtpSender
-PASS RTCRtpSender interface: operation getParameters()
-PASS Unscopable handled correctly for getParameters() on RTCRtpSender
-PASS RTCRtpSender interface: operation replaceTrack(MediaStreamTrack)
-PASS Unscopable handled correctly for replaceTrack(MediaStreamTrack) on RTCRtpSender
-FAIL RTCRtpSender interface: operation getStats() assert_own_property: interface prototype object missing non-static operation expected property "getStats" missing
-PASS Unscopable handled correctly for getStats() on RTCRtpSender
-PASS RTCRtpSender interface: attribute dtmf
-PASS Unscopable handled correctly for dtmf property on RTCRtpSender
-FAIL RTCRtpSender must be primary interface of new RTCPeerConnection().addTransceiver('audio').sender assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL Stringification of new RTCPeerConnection().addTransceiver('audio').sender assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCRtpSender interface: new RTCPeerConnection().addTransceiver('audio').sender must inherit property "track" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCRtpSender interface: new RTCPeerConnection().addTransceiver('audio').sender must inherit property "transport" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCRtpSender interface: new RTCPeerConnection().addTransceiver('audio').sender must inherit property "rtcpTransport" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCRtpSender interface: new RTCPeerConnection().addTransceiver('audio').sender must inherit property "getCapabilities(DOMString)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCRtpSender interface: calling getCapabilities(DOMString) on new RTCPeerConnection().addTransceiver('audio').sender with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCRtpSender interface: new RTCPeerConnection().addTransceiver('audio').sender must inherit property "setParameters(RTCRtpParameters)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCRtpSender interface: calling setParameters(RTCRtpParameters) on new RTCPeerConnection().addTransceiver('audio').sender with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCRtpSender interface: new RTCPeerConnection().addTransceiver('audio').sender must inherit property "getParameters()" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCRtpSender interface: new RTCPeerConnection().addTransceiver('audio').sender must inherit property "replaceTrack(MediaStreamTrack)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCRtpSender interface: calling replaceTrack(MediaStreamTrack) on new RTCPeerConnection().addTransceiver('audio').sender with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCRtpSender interface: new RTCPeerConnection().addTransceiver('audio').sender must inherit property "getStats()" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCRtpSender interface: new RTCPeerConnection().addTransceiver('audio').sender must inherit property "dtmf" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-PASS RTCRtpReceiver interface: existence and properties of interface object
-PASS RTCRtpReceiver interface object length
-PASS RTCRtpReceiver interface object name
-PASS RTCRtpReceiver interface: existence and properties of interface prototype object
-PASS RTCRtpReceiver interface: existence and properties of interface prototype object's "constructor" property
-PASS RTCRtpReceiver interface: existence and properties of interface prototype object's @@unscopables property
-PASS RTCRtpReceiver interface: attribute track
-PASS Unscopable handled correctly for track property on RTCRtpReceiver
-FAIL RTCRtpReceiver interface: attribute transport assert_true: The prototype object must have a property "transport" expected true got false
-PASS Unscopable handled correctly for transport property on RTCRtpReceiver
-FAIL RTCRtpReceiver interface: attribute rtcpTransport assert_true: The prototype object must have a property "rtcpTransport" expected true got false
-PASS Unscopable handled correctly for rtcpTransport property on RTCRtpReceiver
-FAIL RTCRtpReceiver interface: operation getCapabilities(DOMString) assert_own_property: interface object missing static operation expected property "getCapabilities" missing
-PASS Unscopable handled correctly for getCapabilities(DOMString) on RTCRtpReceiver
-FAIL RTCRtpReceiver interface: operation getParameters() assert_own_property: interface prototype object missing non-static operation expected property "getParameters" missing
-PASS Unscopable handled correctly for getParameters() on RTCRtpReceiver
-PASS RTCRtpReceiver interface: operation getContributingSources()
-PASS Unscopable handled correctly for getContributingSources() on RTCRtpReceiver
-FAIL RTCRtpReceiver interface: operation getSynchronizationSources() assert_own_property: interface prototype object missing non-static operation expected property "getSynchronizationSources" missing
-PASS Unscopable handled correctly for getSynchronizationSources() on RTCRtpReceiver
-FAIL RTCRtpReceiver interface: operation getStats() assert_own_property: interface prototype object missing non-static operation expected property "getStats" missing
-PASS Unscopable handled correctly for getStats() on RTCRtpReceiver
-FAIL RTCRtpReceiver must be primary interface of new RTCPeerConnection().addTransceiver('audio').receiver assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL Stringification of new RTCPeerConnection().addTransceiver('audio').receiver assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCRtpReceiver interface: new RTCPeerConnection().addTransceiver('audio').receiver must inherit property "track" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCRtpReceiver interface: new RTCPeerConnection().addTransceiver('audio').receiver must inherit property "transport" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCRtpReceiver interface: new RTCPeerConnection().addTransceiver('audio').receiver must inherit property "rtcpTransport" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCRtpReceiver interface: new RTCPeerConnection().addTransceiver('audio').receiver must inherit property "getCapabilities(DOMString)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCRtpReceiver interface: calling getCapabilities(DOMString) on new RTCPeerConnection().addTransceiver('audio').receiver with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCRtpReceiver interface: new RTCPeerConnection().addTransceiver('audio').receiver must inherit property "getParameters()" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCRtpReceiver interface: new RTCPeerConnection().addTransceiver('audio').receiver must inherit property "getContributingSources()" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCRtpReceiver interface: new RTCPeerConnection().addTransceiver('audio').receiver must inherit property "getSynchronizationSources()" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCRtpReceiver interface: new RTCPeerConnection().addTransceiver('audio').receiver must inherit property "getStats()" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-PASS RTCRtpContributingSource interface: existence and properties of interface object
-PASS RTCRtpContributingSource interface object length
-PASS RTCRtpContributingSource interface object name
-PASS RTCRtpContributingSource interface: existence and properties of interface prototype object
-PASS RTCRtpContributingSource interface: existence and properties of interface prototype object's "constructor" property
-PASS RTCRtpContributingSource interface: existence and properties of interface prototype object's @@unscopables property
-PASS RTCRtpContributingSource interface: attribute timestamp
-PASS Unscopable handled correctly for timestamp property on RTCRtpContributingSource
-PASS RTCRtpContributingSource interface: attribute source
-PASS Unscopable handled correctly for source property on RTCRtpContributingSource
-FAIL RTCRtpContributingSource interface: attribute audioLevel assert_true: The prototype object must have a property "audioLevel" expected true got false
-PASS Unscopable handled correctly for audioLevel property on RTCRtpContributingSource
-FAIL RTCRtpSynchronizationSource interface: existence and properties of interface object assert_own_property: self does not have own property "RTCRtpSynchronizationSource" expected property "RTCRtpSynchronizationSource" missing
-FAIL RTCRtpSynchronizationSource interface object length assert_own_property: self does not have own property "RTCRtpSynchronizationSource" expected property "RTCRtpSynchronizationSource" missing
-FAIL RTCRtpSynchronizationSource interface object name assert_own_property: self does not have own property "RTCRtpSynchronizationSource" expected property "RTCRtpSynchronizationSource" missing
-FAIL RTCRtpSynchronizationSource interface: existence and properties of interface prototype object assert_own_property: self does not have own property "RTCRtpSynchronizationSource" expected property "RTCRtpSynchronizationSource" missing
-FAIL RTCRtpSynchronizationSource interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "RTCRtpSynchronizationSource" expected property "RTCRtpSynchronizationSource" missing
-FAIL RTCRtpSynchronizationSource interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "RTCRtpSynchronizationSource" expected property "RTCRtpSynchronizationSource" missing
-FAIL RTCRtpSynchronizationSource interface: attribute timestamp assert_own_property: self does not have own property "RTCRtpSynchronizationSource" expected property "RTCRtpSynchronizationSource" missing
-PASS Unscopable handled correctly for timestamp property on RTCRtpSynchronizationSource
-FAIL RTCRtpSynchronizationSource interface: attribute source assert_own_property: self does not have own property "RTCRtpSynchronizationSource" expected property "RTCRtpSynchronizationSource" missing
-PASS Unscopable handled correctly for source property on RTCRtpSynchronizationSource
-FAIL RTCRtpSynchronizationSource interface: attribute audioLevel assert_own_property: self does not have own property "RTCRtpSynchronizationSource" expected property "RTCRtpSynchronizationSource" missing
-PASS Unscopable handled correctly for audioLevel property on RTCRtpSynchronizationSource
-FAIL RTCRtpSynchronizationSource interface: attribute voiceActivityFlag assert_own_property: self does not have own property "RTCRtpSynchronizationSource" expected property "RTCRtpSynchronizationSource" missing
-PASS Unscopable handled correctly for voiceActivityFlag property on RTCRtpSynchronizationSource
-FAIL RTCRtpTransceiver interface: existence and properties of interface object assert_own_property: self does not have own property "RTCRtpTransceiver" expected property "RTCRtpTransceiver" missing
-FAIL RTCRtpTransceiver interface object length assert_own_property: self does not have own property "RTCRtpTransceiver" expected property "RTCRtpTransceiver" missing
-FAIL RTCRtpTransceiver interface object name assert_own_property: self does not have own property "RTCRtpTransceiver" expected property "RTCRtpTransceiver" missing
-FAIL RTCRtpTransceiver interface: existence and properties of interface prototype object assert_own_property: self does not have own property "RTCRtpTransceiver" expected property "RTCRtpTransceiver" missing
-FAIL RTCRtpTransceiver interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "RTCRtpTransceiver" expected property "RTCRtpTransceiver" missing
-FAIL RTCRtpTransceiver interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "RTCRtpTransceiver" expected property "RTCRtpTransceiver" missing
-FAIL RTCRtpTransceiver interface: attribute mid assert_own_property: self does not have own property "RTCRtpTransceiver" expected property "RTCRtpTransceiver" missing
-PASS Unscopable handled correctly for mid property on RTCRtpTransceiver
-FAIL RTCRtpTransceiver interface: attribute sender assert_own_property: self does not have own property "RTCRtpTransceiver" expected property "RTCRtpTransceiver" missing
-PASS Unscopable handled correctly for sender property on RTCRtpTransceiver
-FAIL RTCRtpTransceiver interface: attribute receiver assert_own_property: self does not have own property "RTCRtpTransceiver" expected property "RTCRtpTransceiver" missing
-PASS Unscopable handled correctly for receiver property on RTCRtpTransceiver
-FAIL RTCRtpTransceiver interface: attribute stopped assert_own_property: self does not have own property "RTCRtpTransceiver" expected property "RTCRtpTransceiver" missing
-PASS Unscopable handled correctly for stopped property on RTCRtpTransceiver
-FAIL RTCRtpTransceiver interface: attribute direction assert_own_property: self does not have own property "RTCRtpTransceiver" expected property "RTCRtpTransceiver" missing
-PASS Unscopable handled correctly for direction property on RTCRtpTransceiver
-FAIL RTCRtpTransceiver interface: attribute currentDirection assert_own_property: self does not have own property "RTCRtpTransceiver" expected property "RTCRtpTransceiver" missing
-PASS Unscopable handled correctly for currentDirection property on RTCRtpTransceiver
-FAIL RTCRtpTransceiver interface: operation setDirection(RTCRtpTransceiverDirection) assert_own_property: self does not have own property "RTCRtpTransceiver" expected property "RTCRtpTransceiver" missing
-PASS Unscopable handled correctly for setDirection(RTCRtpTransceiverDirection) on RTCRtpTransceiver
-FAIL RTCRtpTransceiver interface: operation stop() assert_own_property: self does not have own property "RTCRtpTransceiver" expected property "RTCRtpTransceiver" missing
-PASS Unscopable handled correctly for stop() on RTCRtpTransceiver
-FAIL RTCRtpTransceiver interface: operation setCodecPreferences([object Object]) assert_own_property: self does not have own property "RTCRtpTransceiver" expected property "RTCRtpTransceiver" missing
-PASS Unscopable handled correctly for setCodecPreferences([object Object]) on RTCRtpTransceiver
-FAIL RTCRtpTransceiver must be primary interface of new RTCPeerConnection().addTransceiver('audio') assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL Stringification of new RTCPeerConnection().addTransceiver('audio') assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCRtpTransceiver interface: new RTCPeerConnection().addTransceiver('audio') must inherit property "mid" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCRtpTransceiver interface: new RTCPeerConnection().addTransceiver('audio') must inherit property "sender" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCRtpTransceiver interface: new RTCPeerConnection().addTransceiver('audio') must inherit property "receiver" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCRtpTransceiver interface: new RTCPeerConnection().addTransceiver('audio') must inherit property "stopped" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCRtpTransceiver interface: new RTCPeerConnection().addTransceiver('audio') must inherit property "direction" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCRtpTransceiver interface: new RTCPeerConnection().addTransceiver('audio') must inherit property "currentDirection" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCRtpTransceiver interface: new RTCPeerConnection().addTransceiver('audio') must inherit property "setDirection(RTCRtpTransceiverDirection)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCRtpTransceiver interface: calling setDirection(RTCRtpTransceiverDirection) on new RTCPeerConnection().addTransceiver('audio') with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCRtpTransceiver interface: new RTCPeerConnection().addTransceiver('audio') must inherit property "stop()" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCRtpTransceiver interface: new RTCPeerConnection().addTransceiver('audio') must inherit property "setCodecPreferences([object Object])" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCRtpTransceiver interface: calling setCodecPreferences([object Object]) on new RTCPeerConnection().addTransceiver('audio') with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: (intermediate value).addTransceiver is not a function"
-FAIL RTCDtlsTransport interface: existence and properties of interface object assert_own_property: self does not have own property "RTCDtlsTransport" expected property "RTCDtlsTransport" missing
-FAIL RTCDtlsTransport interface object length assert_own_property: self does not have own property "RTCDtlsTransport" expected property "RTCDtlsTransport" missing
-FAIL RTCDtlsTransport interface object name assert_own_property: self does not have own property "RTCDtlsTransport" expected property "RTCDtlsTransport" missing
-FAIL RTCDtlsTransport interface: existence and properties of interface prototype object assert_own_property: self does not have own property "RTCDtlsTransport" expected property "RTCDtlsTransport" missing
-FAIL RTCDtlsTransport interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "RTCDtlsTransport" expected property "RTCDtlsTransport" missing
-FAIL RTCDtlsTransport interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "RTCDtlsTransport" expected property "RTCDtlsTransport" missing
-FAIL RTCDtlsTransport interface: attribute transport assert_own_property: self does not have own property "RTCDtlsTransport" expected property "RTCDtlsTransport" missing
-PASS Unscopable handled correctly for transport property on RTCDtlsTransport
-FAIL RTCDtlsTransport interface: attribute state assert_own_property: self does not have own property "RTCDtlsTransport" expected property "RTCDtlsTransport" missing
-PASS Unscopable handled correctly for state property on RTCDtlsTransport
-FAIL RTCDtlsTransport interface: operation getRemoteCertificates() assert_own_property: self does not have own property "RTCDtlsTransport" expected property "RTCDtlsTransport" missing
-PASS Unscopable handled correctly for getRemoteCertificates() on RTCDtlsTransport
-FAIL RTCDtlsTransport interface: attribute onstatechange assert_own_property: self does not have own property "RTCDtlsTransport" expected property "RTCDtlsTransport" missing
-PASS Unscopable handled correctly for onstatechange property on RTCDtlsTransport
-FAIL RTCDtlsTransport must be primary interface of idlTestObjects.dtlsTransport assert_equals: wrong typeof object expected "object" but got "undefined"
-FAIL Stringification of idlTestObjects.dtlsTransport assert_equals: wrong typeof object expected "object" but got "undefined"
-FAIL RTCDtlsTransport interface: idlTestObjects.dtlsTransport must inherit property "transport" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined"
-FAIL RTCDtlsTransport interface: idlTestObjects.dtlsTransport must inherit property "state" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined"
-FAIL RTCDtlsTransport interface: idlTestObjects.dtlsTransport must inherit property "getRemoteCertificates()" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined"
-FAIL RTCDtlsTransport interface: idlTestObjects.dtlsTransport must inherit property "onstatechange" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined"
-FAIL RTCIceTransport interface: existence and properties of interface object assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing
-FAIL RTCIceTransport interface object length assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing
-FAIL RTCIceTransport interface object name assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing
-FAIL RTCIceTransport interface: existence and properties of interface prototype object assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing
-FAIL RTCIceTransport interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing
-FAIL RTCIceTransport interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing
-FAIL RTCIceTransport interface: attribute role assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing
-PASS Unscopable handled correctly for role property on RTCIceTransport
-FAIL RTCIceTransport interface: attribute component assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing
-PASS Unscopable handled correctly for component property on RTCIceTransport
-FAIL RTCIceTransport interface: attribute state assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing
-PASS Unscopable handled correctly for state property on RTCIceTransport
-FAIL RTCIceTransport interface: attribute gatheringState assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing
-PASS Unscopable handled correctly for gatheringState property on RTCIceTransport
-FAIL RTCIceTransport interface: operation getLocalCandidates() assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing
-PASS Unscopable handled correctly for getLocalCandidates() on RTCIceTransport
-FAIL RTCIceTransport interface: operation getRemoteCandidates() assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing
-PASS Unscopable handled correctly for getRemoteCandidates() on RTCIceTransport
-FAIL RTCIceTransport interface: operation getSelectedCandidatePair() assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing
-PASS Unscopable handled correctly for getSelectedCandidatePair() on RTCIceTransport
-FAIL RTCIceTransport interface: operation getLocalParameters() assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing
-PASS Unscopable handled correctly for getLocalParameters() on RTCIceTransport
-FAIL RTCIceTransport interface: operation getRemoteParameters() assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing
-PASS Unscopable handled correctly for getRemoteParameters() on RTCIceTransport
-FAIL RTCIceTransport interface: attribute onstatechange assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing
-PASS Unscopable handled correctly for onstatechange property on RTCIceTransport
-FAIL RTCIceTransport interface: attribute ongatheringstatechange assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing
-PASS Unscopable handled correctly for ongatheringstatechange property on RTCIceTransport
-FAIL RTCIceTransport interface: attribute onselectedcandidatepairchange assert_own_property: self does not have own property "RTCIceTransport" expected property "RTCIceTransport" missing
-PASS Unscopable handled correctly for onselectedcandidatepairchange property on RTCIceTransport
-FAIL RTCIceTransport must be primary interface of idlTestObjects.iceTransport assert_equals: wrong typeof object expected "object" but got "undefined"
-FAIL Stringification of idlTestObjects.iceTransport assert_equals: wrong typeof object expected "object" but got "undefined"
-FAIL RTCIceTransport interface: idlTestObjects.iceTransport must inherit property "role" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined"
-FAIL RTCIceTransport interface: idlTestObjects.iceTransport must inherit property "component" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined"
-FAIL RTCIceTransport interface: idlTestObjects.iceTransport must inherit property "state" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined"
-FAIL RTCIceTransport interface: idlTestObjects.iceTransport must inherit property "gatheringState" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined"
-FAIL RTCIceTransport interface: idlTestObjects.iceTransport must inherit property "getLocalCandidates()" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined"
-FAIL RTCIceTransport interface: idlTestObjects.iceTransport must inherit property "getRemoteCandidates()" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined"
-FAIL RTCIceTransport interface: idlTestObjects.iceTransport must inherit property "getSelectedCandidatePair()" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined"
-FAIL RTCIceTransport interface: idlTestObjects.iceTransport must inherit property "getLocalParameters()" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined"
-FAIL RTCIceTransport interface: idlTestObjects.iceTransport must inherit property "getRemoteParameters()" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined"
-FAIL RTCIceTransport interface: idlTestObjects.iceTransport must inherit property "onstatechange" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined"
-FAIL RTCIceTransport interface: idlTestObjects.iceTransport must inherit property "ongatheringstatechange" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined"
-FAIL RTCIceTransport interface: idlTestObjects.iceTransport must inherit property "onselectedcandidatepairchange" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined"
-FAIL RTCTrackEvent interface: existence and properties of interface object Cannot read property 'has_extended_attribute' of undefined
-PASS RTCTrackEvent interface object length
-PASS RTCTrackEvent interface object name
-FAIL RTCTrackEvent interface: existence and properties of interface prototype object Cannot read property 'has_extended_attribute' of undefined
-PASS RTCTrackEvent interface: existence and properties of interface prototype object's "constructor" property
-PASS RTCTrackEvent interface: existence and properties of interface prototype object's @@unscopables property
-PASS RTCTrackEvent interface: attribute receiver
-PASS Unscopable handled correctly for receiver property on RTCTrackEvent
-PASS RTCTrackEvent interface: attribute track
-PASS Unscopable handled correctly for track property on RTCTrackEvent
-PASS RTCTrackEvent interface: attribute streams
-PASS Unscopable handled correctly for streams property on RTCTrackEvent
-FAIL RTCTrackEvent interface: attribute transceiver assert_true: The prototype object must have a property "transceiver" expected true got false
-PASS Unscopable handled correctly for transceiver property on RTCTrackEvent
-FAIL RTCTrackEvent must be primary interface of initTrackEvent() assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: pc.addTransceiver is not a function"
-FAIL Stringification of initTrackEvent() assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: pc.addTransceiver is not a function"
-FAIL RTCTrackEvent interface: initTrackEvent() must inherit property "receiver" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: pc.addTransceiver is not a function"
-FAIL RTCTrackEvent interface: initTrackEvent() must inherit property "track" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: pc.addTransceiver is not a function"
-FAIL RTCTrackEvent interface: initTrackEvent() must inherit property "streams" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: pc.addTransceiver is not a function"
-FAIL RTCTrackEvent interface: initTrackEvent() must inherit property "transceiver" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: pc.addTransceiver is not a function"
-FAIL RTCSctpTransport interface: existence and properties of interface object assert_own_property: self does not have own property "RTCSctpTransport" expected property "RTCSctpTransport" missing
-FAIL RTCSctpTransport interface object length assert_own_property: self does not have own property "RTCSctpTransport" expected property "RTCSctpTransport" missing
-FAIL RTCSctpTransport interface object name assert_own_property: self does not have own property "RTCSctpTransport" expected property "RTCSctpTransport" missing
-FAIL RTCSctpTransport interface: existence and properties of interface prototype object assert_own_property: self does not have own property "RTCSctpTransport" expected property "RTCSctpTransport" missing
-FAIL RTCSctpTransport interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "RTCSctpTransport" expected property "RTCSctpTransport" missing
-FAIL RTCSctpTransport interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "RTCSctpTransport" expected property "RTCSctpTransport" missing
-FAIL RTCSctpTransport interface: attribute transport assert_own_property: self does not have own property "RTCSctpTransport" expected property "RTCSctpTransport" missing
-PASS Unscopable handled correctly for transport property on RTCSctpTransport
-FAIL RTCSctpTransport interface: attribute maxMessageSize assert_own_property: self does not have own property "RTCSctpTransport" expected property "RTCSctpTransport" missing
-PASS Unscopable handled correctly for maxMessageSize property on RTCSctpTransport
-FAIL RTCSctpTransport must be primary interface of idlTestObjects.sctpTransport assert_equals: wrong typeof object expected "object" but got "undefined"
-FAIL Stringification of idlTestObjects.sctpTransport assert_equals: wrong typeof object expected "object" but got "undefined"
-FAIL RTCSctpTransport interface: idlTestObjects.sctpTransport must inherit property "transport" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined"
-FAIL RTCSctpTransport interface: idlTestObjects.sctpTransport must inherit property "maxMessageSize" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined"
-FAIL RTCDataChannel interface: existence and properties of interface object Cannot read property 'has_extended_attribute' of undefined
-PASS RTCDataChannel interface object length
-PASS RTCDataChannel interface object name
-FAIL RTCDataChannel interface: existence and properties of interface prototype object Cannot read property 'has_extended_attribute' of undefined
-PASS RTCDataChannel interface: existence and properties of interface prototype object's "constructor" property
-PASS RTCDataChannel interface: existence and properties of interface prototype object's @@unscopables property
-PASS RTCDataChannel interface: attribute label
-PASS Unscopable handled correctly for label property on RTCDataChannel
-PASS RTCDataChannel interface: attribute ordered
-PASS Unscopable handled correctly for ordered property on RTCDataChannel
-FAIL RTCDataChannel interface: attribute maxPacketLifeTime assert_true: The prototype object must have a property "maxPacketLifeTime" expected true got false
-PASS Unscopable handled correctly for maxPacketLifeTime property on RTCDataChannel
-PASS RTCDataChannel interface: attribute maxRetransmits
-PASS Unscopable handled correctly for maxRetransmits property on RTCDataChannel
-PASS RTCDataChannel interface: attribute protocol
-PASS Unscopable handled correctly for protocol property on RTCDataChannel
-PASS RTCDataChannel interface: attribute negotiated
-PASS Unscopable handled correctly for negotiated property on RTCDataChannel
-PASS RTCDataChannel interface: attribute id
-PASS Unscopable handled correctly for id property on RTCDataChannel
-FAIL RTCDataChannel interface: attribute priority assert_true: The prototype object must have a property "priority" expected true got false
-PASS Unscopable handled correctly for priority property on RTCDataChannel
-PASS RTCDataChannel interface: attribute readyState
-PASS Unscopable handled correctly for readyState property on RTCDataChannel
-PASS RTCDataChannel interface: attribute bufferedAmount
-PASS Unscopable handled correctly for bufferedAmount property on RTCDataChannel
-PASS RTCDataChannel interface: attribute bufferedAmountLowThreshold
-PASS Unscopable handled correctly for bufferedAmountLowThreshold property on RTCDataChannel
-PASS RTCDataChannel interface: attribute onopen
-PASS Unscopable handled correctly for onopen property on RTCDataChannel
-PASS RTCDataChannel interface: attribute onbufferedamountlow
-PASS Unscopable handled correctly for onbufferedamountlow property on RTCDataChannel
-PASS RTCDataChannel interface: attribute onerror
-PASS Unscopable handled correctly for onerror property on RTCDataChannel
-PASS RTCDataChannel interface: attribute onclose
-PASS Unscopable handled correctly for onclose property on RTCDataChannel
-PASS RTCDataChannel interface: operation close()
-PASS Unscopable handled correctly for close() on RTCDataChannel
-PASS RTCDataChannel interface: attribute onmessage
-PASS Unscopable handled correctly for onmessage property on RTCDataChannel
-PASS RTCDataChannel interface: attribute binaryType
-PASS Unscopable handled correctly for binaryType property on RTCDataChannel
-PASS RTCDataChannel interface: operation send(USVString)
-PASS Unscopable handled correctly for send(USVString) on RTCDataChannel
-PASS RTCDataChannel interface: operation send(Blob)
-PASS Unscopable handled correctly for send(Blob) on RTCDataChannel
-PASS RTCDataChannel interface: operation send(ArrayBuffer)
-PASS Unscopable handled correctly for send(ArrayBuffer) on RTCDataChannel
-PASS RTCDataChannel interface: operation send(ArrayBufferView)
-PASS Unscopable handled correctly for send(ArrayBufferView) on RTCDataChannel
-PASS RTCDataChannel must be primary interface of new RTCPeerConnection().createDataChannel('')
-FAIL Stringification of new RTCPeerConnection().createDataChannel('') Cannot read property 'has_stringifier' of undefined
-PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "label" with the proper type
-PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "ordered" with the proper type
-FAIL RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "maxPacketLifeTime" with the proper type assert_inherits: property "maxPacketLifeTime" not found in prototype chain
-PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "maxRetransmits" with the proper type
-PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "protocol" with the proper type
-PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "negotiated" with the proper type
-PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "id" with the proper type
-FAIL RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "priority" with the proper type assert_inherits: property "priority" not found in prototype chain
-PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "readyState" with the proper type
-PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "bufferedAmount" with the proper type
-PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "bufferedAmountLowThreshold" with the proper type
-PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "onopen" with the proper type
-PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "onbufferedamountlow" with the proper type
-PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "onerror" with the proper type
-PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "onclose" with the proper type
-PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "close()" with the proper type
-PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "onmessage" with the proper type
-PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "binaryType" with the proper type
-PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "send(USVString)" with the proper type
-PASS RTCDataChannel interface: calling send(USVString) on new RTCPeerConnection().createDataChannel('') with too few arguments must throw TypeError
-PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "send(Blob)" with the proper type
-PASS RTCDataChannel interface: calling send(Blob) on new RTCPeerConnection().createDataChannel('') with too few arguments must throw TypeError
-PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "send(ArrayBuffer)" with the proper type
-PASS RTCDataChannel interface: calling send(ArrayBuffer) on new RTCPeerConnection().createDataChannel('') with too few arguments must throw TypeError
-PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "send(ArrayBufferView)" with the proper type
-PASS RTCDataChannel interface: calling send(ArrayBufferView) on new RTCPeerConnection().createDataChannel('') with too few arguments must throw TypeError
-FAIL RTCDataChannelEvent interface: existence and properties of interface object Cannot read property 'has_extended_attribute' of undefined
-PASS RTCDataChannelEvent interface object length
-PASS RTCDataChannelEvent interface object name
-FAIL RTCDataChannelEvent interface: existence and properties of interface prototype object Cannot read property 'has_extended_attribute' of undefined
-PASS RTCDataChannelEvent interface: existence and properties of interface prototype object's "constructor" property
-PASS RTCDataChannelEvent interface: existence and properties of interface prototype object's @@unscopables property
-PASS RTCDataChannelEvent interface: attribute channel
-PASS Unscopable handled correctly for channel property on RTCDataChannelEvent
-PASS RTCDataChannelEvent must be primary interface of new RTCDataChannelEvent('channel',
-        { channel: new RTCPeerConnection().createDataChannel('') })
-FAIL Stringification of new RTCDataChannelEvent('channel',
-        { channel: new RTCPeerConnection().createDataChannel('') }) Cannot read property 'has_stringifier' of undefined
-PASS RTCDataChannelEvent interface: new RTCDataChannelEvent('channel',
-        { channel: new RTCPeerConnection().createDataChannel('') }) must inherit property "channel" with the proper type
-FAIL RTCDTMFSender interface: existence and properties of interface object Cannot read property 'has_extended_attribute' of undefined
-PASS RTCDTMFSender interface object length
-PASS RTCDTMFSender interface object name
-FAIL RTCDTMFSender interface: existence and properties of interface prototype object Cannot read property 'has_extended_attribute' of undefined
-PASS RTCDTMFSender interface: existence and properties of interface prototype object's "constructor" property
-PASS RTCDTMFSender interface: existence and properties of interface prototype object's @@unscopables property
-PASS RTCDTMFSender interface: operation insertDTMF(DOMString, unsigned long, unsigned long)
-PASS Unscopable handled correctly for insertDTMF(DOMString, unsigned long, unsigned long) on RTCDTMFSender
-PASS RTCDTMFSender interface: attribute ontonechange
-PASS Unscopable handled correctly for ontonechange property on RTCDTMFSender
-PASS RTCDTMFSender interface: attribute toneBuffer
-PASS Unscopable handled correctly for toneBuffer property on RTCDTMFSender
-FAIL RTCDTMFToneChangeEvent interface: existence and properties of interface object Cannot read property 'has_extended_attribute' of undefined
-PASS RTCDTMFToneChangeEvent interface object length
-PASS RTCDTMFToneChangeEvent interface object name
-FAIL RTCDTMFToneChangeEvent interface: existence and properties of interface prototype object Cannot read property 'has_extended_attribute' of undefined
-PASS RTCDTMFToneChangeEvent interface: existence and properties of interface prototype object's "constructor" property
-PASS RTCDTMFToneChangeEvent interface: existence and properties of interface prototype object's @@unscopables property
-PASS RTCDTMFToneChangeEvent interface: attribute tone
-PASS Unscopable handled correctly for tone property on RTCDTMFToneChangeEvent
-PASS RTCStatsReport interface: existence and properties of interface object
-PASS RTCStatsReport interface object length
-PASS RTCStatsReport interface object name
-PASS RTCStatsReport interface: existence and properties of interface prototype object
-PASS RTCStatsReport interface: existence and properties of interface prototype object's "constructor" property
-PASS RTCStatsReport interface: existence and properties of interface prototype object's @@unscopables property
-PASS RTCIdentityProviderGlobalScope interface: existence and properties of interface object
-PASS RTCIdentityProviderRegistrar interface: existence and properties of interface object
-FAIL RTCIdentityAssertion interface: existence and properties of interface object assert_own_property: self does not have own property "RTCIdentityAssertion" expected property "RTCIdentityAssertion" missing
-FAIL RTCIdentityAssertion interface object length assert_own_property: self does not have own property "RTCIdentityAssertion" expected property "RTCIdentityAssertion" missing
-FAIL RTCIdentityAssertion interface object name assert_own_property: self does not have own property "RTCIdentityAssertion" expected property "RTCIdentityAssertion" missing
-FAIL RTCIdentityAssertion interface: existence and properties of interface prototype object assert_own_property: self does not have own property "RTCIdentityAssertion" expected property "RTCIdentityAssertion" missing
-FAIL RTCIdentityAssertion interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "RTCIdentityAssertion" expected property "RTCIdentityAssertion" missing
-FAIL RTCIdentityAssertion interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "RTCIdentityAssertion" expected property "RTCIdentityAssertion" missing
-FAIL RTCIdentityAssertion interface: attribute idp assert_own_property: self does not have own property "RTCIdentityAssertion" expected property "RTCIdentityAssertion" missing
-PASS Unscopable handled correctly for idp property on RTCIdentityAssertion
-FAIL RTCIdentityAssertion interface: attribute name assert_own_property: self does not have own property "RTCIdentityAssertion" expected property "RTCIdentityAssertion" missing
-PASS Unscopable handled correctly for name property on RTCIdentityAssertion
-FAIL RTCErrorEvent interface: existence and properties of interface object assert_own_property: self does not have own property "RTCErrorEvent" expected property "RTCErrorEvent" missing
-FAIL RTCErrorEvent interface object length assert_own_property: self does not have own property "RTCErrorEvent" expected property "RTCErrorEvent" missing
-FAIL RTCErrorEvent interface object name assert_own_property: self does not have own property "RTCErrorEvent" expected property "RTCErrorEvent" missing
-FAIL RTCErrorEvent interface: existence and properties of interface prototype object assert_own_property: self does not have own property "RTCErrorEvent" expected property "RTCErrorEvent" missing
-FAIL RTCErrorEvent interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "RTCErrorEvent" expected property "RTCErrorEvent" missing
-FAIL RTCErrorEvent interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "RTCErrorEvent" expected property "RTCErrorEvent" missing
-FAIL RTCErrorEvent interface: attribute error assert_own_property: self does not have own property "RTCErrorEvent" expected property "RTCErrorEvent" missing
-PASS Unscopable handled correctly for error property on RTCErrorEvent
-FAIL RTCErrorEvent must be primary interface of new RTCErrorEvent('error') assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: RTCErrorEvent is not defined"
-FAIL Stringification of new RTCErrorEvent('error') assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: RTCErrorEvent is not defined"
-FAIL RTCErrorEvent interface: new RTCErrorEvent('error') must inherit property "error" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: RTCErrorEvent is not defined"
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/workers/modules/dedicated-worker-import.html b/third_party/WebKit/LayoutTests/external/wpt/workers/modules/dedicated-worker-import.html
new file mode 100644
index 0000000..3d423639
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/workers/modules/dedicated-worker-import.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<title>DedicatedWorker: import</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+// Start a dedicated worker for |scriptURL| and wait until MessageEvents from
+// imported modules up to |expectedNumberOfImportedModules|.
+function RunImportTest(scriptURL, expectedNumberOfImportedModules) {
+  return new Promise(resolve => {
+    let numberOfImportedModules = 0;
+    const worker = new Worker(scriptURL, { type: 'module' });
+    worker.onmessage = e => {
+      if (e.data === 'LOADED')
+        ++numberOfImportedModules;
+      if (numberOfImportedModules === expectedNumberOfImportedModules)
+        resolve();
+    };
+  });
+}
+
+promise_test(() => {
+  return RunImportTest('resources/static-import-worker.js', 2);
+}, 'Test static import on DedicatedWorkerGlobalScope.');
+
+promise_test(() => {
+  return RunImportTest('resources/nested-static-import-worker.js', 3);
+}, 'Test nested static import on DedicatedWorkerGlobalScope.');
+
+promise_test(() => {
+  return RunImportTest(
+      'resources/static-import-and-then-dynamic-import-worker.js', 3);
+}, 'Test static import and then dynamic import on DedicatedWorkerGlobalScope.');
+
+promise_test(() => {
+  return RunImportTest('resources/dynamic-import-worker.js', 2);
+}, 'Test dynamic import on DedicatedWorkerGlobalScope.');
+
+promise_test(() => {
+  return RunImportTest('resources/nested-dynamic-import-worker.js', 3);
+}, 'Test nested dynamic import on DedicatedWorkerGlobalScope.');
+
+promise_test(() => {
+  return RunImportTest(
+      'resources/dynamic-import-and-then-static-import-worker.js', 3);
+}, 'Test dynamic import and then static import on DedicatedWorkerGlobalScope.');
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/workers/modules/dedicated-worker-static-import.html b/third_party/WebKit/LayoutTests/external/wpt/workers/modules/dedicated-worker-static-import.html
deleted file mode 100644
index ee5de185..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/workers/modules/dedicated-worker-static-import.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<title>DedicatedWorker: static import</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
-
-promise_test(() => {
-  const worker = new Worker('resources/static-import-worker.js',
-                            { type: 'module' });
-  return new Promise(resolve => worker.onmessage = resolve)
-      .then(msg_event => assert_equals(msg_event.data, 'LOADED'));
-}, 'Test static import on DedicatedWorkerGlobalScope.');
-
-promise_test(() => {
-  const worker = new Worker('resources/nested-static-import-worker.js',
-                            { type: 'module' });
-  return new Promise(resolve => worker.onmessage = resolve)
-      .then(msg_event => assert_equals(msg_event.data, 'LOADED'));
-}, 'Test nested static import on DedicatedWorkerGlobalScope.');
-
-</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/workers/modules/resources/dynamic-import-and-then-static-import-worker.js b/third_party/WebKit/LayoutTests/external/wpt/workers/modules/resources/dynamic-import-and-then-static-import-worker.js
new file mode 100644
index 0000000..eaa3f1c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/workers/modules/resources/dynamic-import-and-then-static-import-worker.js
@@ -0,0 +1,2 @@
+import('./static-import-worker.js')
+  .then(module => postMessage('LOADED'));
diff --git a/third_party/WebKit/LayoutTests/external/wpt/workers/modules/resources/dynamic-import-worker.js b/third_party/WebKit/LayoutTests/external/wpt/workers/modules/resources/dynamic-import-worker.js
new file mode 100644
index 0000000..98381b9d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/workers/modules/resources/dynamic-import-worker.js
@@ -0,0 +1,2 @@
+import('./post-message-on-load-worker.js')
+  .then(module => postMessage('LOADED'));
diff --git a/third_party/WebKit/LayoutTests/external/wpt/workers/modules/resources/nested-dynamic-import-worker.js b/third_party/WebKit/LayoutTests/external/wpt/workers/modules/resources/nested-dynamic-import-worker.js
new file mode 100644
index 0000000..8f56d15
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/workers/modules/resources/nested-dynamic-import-worker.js
@@ -0,0 +1,2 @@
+import('./dynamic-import-worker.js')
+  .then(module => postMessage('LOADED'));
diff --git a/third_party/WebKit/LayoutTests/external/wpt/workers/modules/resources/nested-static-import-worker.js b/third_party/WebKit/LayoutTests/external/wpt/workers/modules/resources/nested-static-import-worker.js
index bcaf7d89..f2ef5207 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/workers/modules/resources/nested-static-import-worker.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/workers/modules/resources/nested-static-import-worker.js
@@ -1 +1,2 @@
 import './static-import-worker.js';
+postMessage('LOADED')
diff --git a/third_party/WebKit/LayoutTests/external/wpt/workers/modules/resources/static-import-and-then-dynamic-import-worker.js b/third_party/WebKit/LayoutTests/external/wpt/workers/modules/resources/static-import-and-then-dynamic-import-worker.js
new file mode 100644
index 0000000..4e66d04
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/workers/modules/resources/static-import-and-then-dynamic-import-worker.js
@@ -0,0 +1,2 @@
+import './dynamic-import-worker.js';
+postMessage('LOADED');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/workers/modules/resources/static-import-worker.js b/third_party/WebKit/LayoutTests/external/wpt/workers/modules/resources/static-import-worker.js
index edb8caf3..4693169 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/workers/modules/resources/static-import-worker.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/workers/modules/resources/static-import-worker.js
@@ -1 +1,2 @@
 import './post-message-on-load-worker.js';
+postMessage('LOADED');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/xhr/send-sync-response-event-order-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/xhr/send-sync-response-event-order-expected.txt
deleted file mode 100644
index 855a866..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/xhr/send-sync-response-event-order-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL XMLHttpRequest: The send() method: event order when synchronous flag is set assert_equals: expected "load(12,12,true)" but got "load(12,0,false)"
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/fast/backgrounds/svg-as-mask-expected.png b/third_party/WebKit/LayoutTests/fast/backgrounds/svg-as-mask-expected.png
index e991e62..b1d9776 100644
--- a/third_party/WebKit/LayoutTests/fast/backgrounds/svg-as-mask-expected.png
+++ b/third_party/WebKit/LayoutTests/fast/backgrounds/svg-as-mask-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/dom/HTMLLinkElement/link-preload-unused-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/HTMLLinkElement/link-preload-unused-expected.txt
index 39ec5ad5..2bfb27b1 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/HTMLLinkElement/link-preload-unused-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/dom/HTMLLinkElement/link-preload-unused-expected.txt
@@ -1,2 +1,2 @@
-CONSOLE WARNING: The resource nick.jpg?name=value was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it Please make sure it has an appropriate `as` value and it is preloaded intentionally.
+CONSOLE WARNING: The resource nick.jpg?name=value was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally.
  This test verifies that unused preload resources (and only unused ones) issue a warning.
diff --git a/third_party/WebKit/LayoutTests/fast/dynamic/anonymous-block-layer-lost-expected.png b/third_party/WebKit/LayoutTests/fast/dynamic/anonymous-block-layer-lost-expected.png
index f87d11b..16b3506 100644
--- a/third_party/WebKit/LayoutTests/fast/dynamic/anonymous-block-layer-lost-expected.png
+++ b/third_party/WebKit/LayoutTests/fast/dynamic/anonymous-block-layer-lost-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/layers/opacity-stacking-expected.png b/third_party/WebKit/LayoutTests/fast/layers/opacity-stacking-expected.png
index 8f9b429..7832ca71 100644
--- a/third_party/WebKit/LayoutTests/fast/layers/opacity-stacking-expected.png
+++ b/third_party/WebKit/LayoutTests/fast/layers/opacity-stacking-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/fast/mediastream/MediaDevices-getSupportedConstraints.html b/third_party/WebKit/LayoutTests/fast/mediastream/MediaDevices-getSupportedConstraints.html
index b570a7e..ecc23b4 100644
--- a/third_party/WebKit/LayoutTests/fast/mediastream/MediaDevices-getSupportedConstraints.html
+++ b/third_party/WebKit/LayoutTests/fast/mediastream/MediaDevices-getSupportedConstraints.html
@@ -16,6 +16,8 @@
   assert_true(supported_constraints.sampleRate);
   assert_true(supported_constraints.sampleSize);
   assert_true(supported_constraints.echoCancellation);
+  assert_true(supported_constraints.autoGainControl);
+  assert_true(supported_constraints.noiseSuppression);
   assert_true(supported_constraints.latency);
   assert_true(supported_constraints.channelCount);
   assert_true(supported_constraints.deviceId);
diff --git a/third_party/WebKit/LayoutTests/fast/mediastream/MediaStreamTrack-getCapabilities.html b/third_party/WebKit/LayoutTests/fast/mediastream/MediaStreamTrack-getCapabilities.html
index 5573e8b..7ad96c5 100644
--- a/third_party/WebKit/LayoutTests/fast/mediastream/MediaStreamTrack-getCapabilities.html
+++ b/third_party/WebKit/LayoutTests/fast/mediastream/MediaStreamTrack-getCapabilities.html
@@ -6,10 +6,9 @@
   return navigator.mediaDevices.getUserMedia({audio: true})
       .then(function(stream) {
     var capabilities = stream.getAudioTracks()[0].getCapabilities();
-    assert_equals(Object.keys(capabilities).length, 2);
+    assert_equals(Object.keys(capabilities).length, 4);
     assert_true(capabilities.hasOwnProperty('deviceId'));
-    assert_true(capabilities.hasOwnProperty('echoCancellation'));
-    assert_equals(Object.keys(capabilities.echoCancellation).length, 2);
+    verifyAudioProcessingProperties(capabilities, true);
   });
 }, 'getCapabilities() support for getUserMedia() audio track.');
 
@@ -27,11 +26,9 @@
 test(function() {
   var stream = (new AudioContext()).createMediaStreamDestination().stream;
   var capabilities = stream.getAudioTracks()[0].getCapabilities();
-  assert_equals(Object.keys(capabilities).length, 2);
+  assert_equals(Object.keys(capabilities).length, 4);
   assert_true(capabilities.hasOwnProperty('deviceId'));
-  assert_true(capabilities.hasOwnProperty('echoCancellation'));
-  assert_equals(Object.keys(capabilities.echoCancellation).length, 1);
-  assert_equals(capabilities.echoCancellation[0], false);
+  verifyAudioProcessingProperties(capabilities, false);
 }, 'getCapabilities() support for audio track associated with a MediaStreamAudioDestinationNode.');
 
 test(function() {
@@ -53,11 +50,9 @@
     var stream = video.captureStream();
     var audioCapabilities = stream.getAudioTracks()[0].getCapabilities();
     var videoCapabilities = stream.getVideoTracks()[0].getCapabilities();
-    assert_equals(Object.keys(audioCapabilities).length, 2);
+    assert_equals(Object.keys(audioCapabilities).length, 4);
     assert_true(audioCapabilities.hasOwnProperty('deviceId'));
-    assert_true(audioCapabilities.hasOwnProperty('echoCancellation'));
-    assert_equals(Object.keys(audioCapabilities.echoCancellation).length, 1);
-    assert_equals(audioCapabilities.echoCancellation[0], false);
+    verifyAudioProcessingProperties(audioCapabilities, false);
     assert_greater_than(Object.keys(videoCapabilities).length, 0);
     assert_true(videoCapabilities.hasOwnProperty('deviceId'));
     assert_true(videoCapabilities.hasOwnProperty('facingMode'));
@@ -77,11 +72,9 @@
     var remoteStream = callee.getRemoteStreams()[0];
     var audioCapabilities = remoteStream.getAudioTracks()[0].getCapabilities();
     var videoCapabilities = remoteStream.getVideoTracks()[0].getCapabilities();
-    assert_equals(Object.keys(audioCapabilities).length, 2);
+    assert_equals(Object.keys(audioCapabilities).length, 4);
     assert_true(audioCapabilities.hasOwnProperty('deviceId'));
-    assert_true(audioCapabilities.hasOwnProperty('echoCancellation'));
-    assert_equals(Object.keys(audioCapabilities.echoCancellation).length, 1);
-    assert_equals(audioCapabilities.echoCancellation[0], false);
+    verifyAudioProcessingProperties(audioCapabilities, false);
     assert_greater_than(Object.keys(videoCapabilities).length, 0);
     assert_true(videoCapabilities.hasOwnProperty('deviceId'));
     assert_true(videoCapabilities.hasOwnProperty('facingMode'));
@@ -100,6 +93,15 @@
   });
 }
 
+function verifyAudioProcessingProperties(capabilities, is_get_user_media) {
+  assert_true(capabilities.hasOwnProperty('echoCancellation'));
+  assert_equals(Object.keys(capabilities.echoCancellation).length, is_get_user_media ? 2 : 1);
+  assert_true(capabilities.hasOwnProperty('autoGainControl'));
+  assert_equals(Object.keys(capabilities.autoGainControl).length, is_get_user_media ? 2 : 1);
+  assert_true(capabilities.hasOwnProperty('noiseSuppression'));
+  assert_equals(Object.keys(capabilities.noiseSuppression).length, is_get_user_media ? 2 : 1);
+}
+
 function verifyVideoRangeProperties(capabilities) {
   if (capabilities.hasOwnProperty('width')) {
       assert_equals(Object.keys(capabilities.width).length, 2);
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/balance-float-with-insane-offset-crash.html b/third_party/WebKit/LayoutTests/fast/multicol/balance-float-with-insane-offset-crash.html
new file mode 100644
index 0000000..79a4fb5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/multicol/balance-float-with-insane-offset-crash.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<div style="columns:2;">
+  <div style="height:100px; background:lime;"></div>
+  <br>
+  <div style="float:left; margin-top:4294967296px;"></div>
+</div>
+<script>
+test(() => { }, "No crash or assertion failure.");
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/sub-pixel/save-layer-bounds-should-snap-expected.html b/third_party/WebKit/LayoutTests/fast/sub-pixel/save-layer-bounds-should-snap-expected.html
index 9e29dc74..1647a28 100644
--- a/third_party/WebKit/LayoutTests/fast/sub-pixel/save-layer-bounds-should-snap-expected.html
+++ b/third_party/WebKit/LayoutTests/fast/sub-pixel/save-layer-bounds-should-snap-expected.html
@@ -1,2 +1,2 @@
 <!DOCTYPE html>
-<div style="width:100px; height:100px; background:green; opacity:0.5;"></div>
+<div style="width:100px; height:100px; background:rgb(127,191,127);"></div>
diff --git a/third_party/WebKit/LayoutTests/fast/workers/chromium/worker-dynamic-import.html b/third_party/WebKit/LayoutTests/fast/workers/chromium/worker-dynamic-import.html
deleted file mode 100644
index b0e6794..0000000
--- a/third_party/WebKit/LayoutTests/fast/workers/chromium/worker-dynamic-import.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!DOCTYPE html>
-<title>Worker: Dynamic import() on DedicatedWorkerGlobalScope</title>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script>
-
-// This test should not be upstreamed to WPT because this tests Chrome-specific
-// behavior.
-
-promise_test(() => {
-  const worker = new Worker('resources/worker-dynamic-import.js');
-  return new Promise(resolve => worker.onmessage = resolve)
-      .then(msg_event => {
-        assert_equals(msg_event.data.name, 'TypeError');
-        assert_equals(msg_event.data.message,
-                      'Module scripts are not supported on WorkerGlobalScope ' +
-                      'yet (see https://crbug.com/680046).');
-      });
-}, 'Dynamic import() on DedicatedWorkerGlobalScope should reject the ' +
-   'promise.');
-
-</script>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/compositing/reflections/reflection-positioning-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/compositing/reflections/reflection-positioning-expected.png
deleted file mode 100644
index 1bcbba6..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/compositing/reflections/reflection-positioning-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/compositing/reflections/reflection-positioning2-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/compositing/reflections/reflection-positioning2-expected.png
deleted file mode 100644
index f64d191b..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/compositing/reflections/reflection-positioning2-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/compositing/sibling-positioning-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/compositing/sibling-positioning-expected.png
deleted file mode 100644
index a2f27013..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/compositing/sibling-positioning-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/basic/containment-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/basic/containment-expected.png
index db5d1f9..a4f9f275 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/basic/containment-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/basic/containment-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/basic/contextual_selectors-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/basic/contextual_selectors-expected.png
index 5f022aba..19984d8 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/basic/contextual_selectors-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/basic/contextual_selectors-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/basic/id_as_selector-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/basic/id_as_selector-expected.png
index d7220099..99c0c22 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/basic/id_as_selector-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/basic/id_as_selector-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/acid_test-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/acid_test-expected.png
deleted file mode 100644
index 9ae04e5..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/acid_test-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/border_bottom-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/border_bottom-expected.png
index 1fa1629..bc10b0c 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/border_bottom-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/border_bottom-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/border_color_inline-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/border_color_inline-expected.png
index e20d0ad..4e10acb5 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/border_color_inline-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/border_color_inline-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/border_left-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/border_left-expected.png
index 09a912c..20fa03e1 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/border_left-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/border_left-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/border_right_inline-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/border_right_inline-expected.png
index d1f8bf89..45584cb 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/border_right_inline-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/border_right_inline-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/border_style-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/border_style-expected.png
index ba5c9f93..3ab5eaf5 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/border_style-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/border_style-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/border_style_inline-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/border_style_inline-expected.png
index eb97148..ceb0db6 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/border_style_inline-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/border_style_inline-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/border_top-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/border_top-expected.png
index 836f242..1b71206c 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/border_top-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/border_top-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/clear_float-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/clear_float-expected.png
index 235b1c5..9c0fd53 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/clear_float-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/clear_float-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/float_margin-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/float_margin-expected.png
index fc27df9..82697a1 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/float_margin-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/float_margin-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/margin-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/margin-expected.png
index e517aa0..ad3a669 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/margin-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/margin-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/margin_left-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/margin_left-expected.png
index c22482c..f23df24 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/margin_left-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/margin_left-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/margin_right-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/margin_right-expected.png
index 27aabe2..4b141e9 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/margin_right-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/margin_right-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/padding_left-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/padding_left-expected.png
index c7fffedd..43b5edba 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/padding_left-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/padding_left-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/padding_right-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/padding_right-expected.png
index ae1e9623..2c5cc2de 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/padding_right-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/box_properties/padding_right-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/cascade/cascade_order-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/cascade/cascade_order-expected.png
index 7e39310..e3ec0d5 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/cascade/cascade_order-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/cascade/cascade_order-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/classification/display-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/classification/display-expected.png
index 617b0e40..3a28484 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/classification/display-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/classification/display-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/classification/list_style_position-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/classification/list_style_position-expected.png
index f02ead1..10487b6b 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/classification/list_style_position-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/classification/list_style_position-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/classification/list_style_type-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/classification/list_style_type-expected.png
index 730515ae..5a5a3558 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/classification/list_style_type-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/classification/list_style_type-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/color_and_background/background_attachment-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/color_and_background/background_attachment-expected.png
index fcb8ca15..b4bb998 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/color_and_background/background_attachment-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/color_and_background/background_attachment-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/color_and_background/background_color-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/color_and_background/background_color-expected.png
index 28534d9..d11bf2b8 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/color_and_background/background_color-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/color_and_background/background_color-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/font_properties/font-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/font_properties/font-expected.png
index 53eca15b..9cbe964 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/font_properties/font-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/font_properties/font-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/font_properties/font_variant-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/font_properties/font_variant-expected.png
index afa0dd9a..e414882 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/font_properties/font_variant-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/font_properties/font_variant-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/formatting_model/canvas-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/formatting_model/canvas-expected.png
index f35a440c..908420b 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/formatting_model/canvas-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/formatting_model/canvas-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/formatting_model/floating_elements-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/formatting_model/floating_elements-expected.png
index 5542acb..c45b207 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/formatting_model/floating_elements-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/formatting_model/floating_elements-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/formatting_model/height_of_lines-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/formatting_model/height_of_lines-expected.png
index 1039c77..fbf1794f 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/formatting_model/height_of_lines-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/formatting_model/height_of_lines-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/formatting_model/inline_elements-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/formatting_model/inline_elements-expected.png
index 2f06180..94bd80f 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/formatting_model/inline_elements-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/formatting_model/inline_elements-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/pseudo/anchor-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/pseudo/anchor-expected.png
index 6d36d56..674002bd 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/pseudo/anchor-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/pseudo/anchor-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/pseudo/firstline-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/pseudo/firstline-expected.png
index 5fba63ad..9d5eacc 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/pseudo/firstline-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/pseudo/firstline-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/pseudo/pseudo_elements_in_selectors-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/pseudo/pseudo_elements_in_selectors-expected.png
index 7f0d8e4b..21dbe410 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/pseudo/pseudo_elements_in_selectors-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/pseudo/pseudo_elements_in_selectors-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/text_properties/text_align-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/text_properties/text_align-expected.png
index e01e01ea..588a4ce 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/text_properties/text_align-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/text_properties/text_align-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/text_properties/text_decoration-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/text_properties/text_decoration-expected.png
index 1670b7a..9ad774c 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/text_properties/text_decoration-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/text_properties/text_decoration-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/text_properties/text_transform-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/text_properties/text_transform-expected.png
index 53fe6a0..5070d95 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/text_properties/text_transform-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/text_properties/text_transform-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/units/length_units-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/units/length_units-expected.png
index 4fbb3c52..1a09bee 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/units/length_units-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css1/units/length_units-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/c543-txt-decor-000-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/c543-txt-decor-000-expected.png
index f292824..53e598a 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/c543-txt-decor-000-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/c543-txt-decor-000-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/inline-table-001-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/inline-table-001-expected.png
deleted file mode 100644
index 7ccc756..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/inline-table-001-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/margin-applies-to-010-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/margin-applies-to-010-expected.png
index f7fc38b..2f6dfa7 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/margin-applies-to-010-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/margin-applies-to-010-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/table-caption-001-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/table-caption-001-expected.png
deleted file mode 100644
index e524e89..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/table-caption-001-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/table-caption-horizontal-alignment-001-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/table-caption-horizontal-alignment-001-expected.png
deleted file mode 100644
index cb917ea..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/table-caption-horizontal-alignment-001-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/table-caption-optional-001-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/table-caption-optional-001-expected.png
deleted file mode 100644
index c693aec6..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/table-caption-optional-001-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/table-caption-optional-002-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/table-caption-optional-002-expected.png
deleted file mode 100644
index 5139e7fb..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/table-caption-optional-002-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/table-height-algorithm-023-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/table-height-algorithm-023-expected.png
index a3d2c4a..14ae186f 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/table-height-algorithm-023-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/table-height-algorithm-023-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/table-height-algorithm-024-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/table-height-algorithm-024-expected.png
index a3d2c4a..14ae186f 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/table-height-algorithm-024-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/table-height-algorithm-024-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0402-c71-fwd-parsing-02-f-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0402-c71-fwd-parsing-02-f-expected.png
index 2379415..34f44e0 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0402-c71-fwd-parsing-02-f-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0402-c71-fwd-parsing-02-f-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t050803-c14-classes-00-e-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t050803-c14-classes-00-e-expected.png
index e95f5b2..afe589f7 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t050803-c14-classes-00-e-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t050803-c14-classes-00-e-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0509-c15-ids-01-e-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0509-c15-ids-01-e-expected.png
index ab74e27..891b473 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0509-c15-ids-01-e-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0509-c15-ids-01-e-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t051103-dom-hover-01-c-io-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t051103-dom-hover-01-c-io-expected.png
deleted file mode 100644
index 7b3d989..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t051103-dom-hover-01-c-io-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t051103-dom-hover-02-c-io-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t051103-dom-hover-02-c-io-expected.png
deleted file mode 100644
index caaac7d..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t051103-dom-hover-02-c-io-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5516-brdr-c-00-a-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5516-brdr-c-00-a-expected.png
deleted file mode 100644
index b33629e3..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5516-brdr-c-00-a-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5516-ibrdr-c-00-a-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5516-ibrdr-c-00-a-expected.png
deleted file mode 100644
index a4ccf0fa..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5516-ibrdr-c-00-a-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5517-brdr-s-00-c-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5517-brdr-s-00-c-expected.png
index eed68cf..f10eecc 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5517-brdr-s-00-c-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5517-brdr-s-00-c-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5517-ibrdr-s-00-a-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5517-ibrdr-s-00-a-expected.png
index 027186b..0ad7fb5a 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5517-ibrdr-s-00-a-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5517-ibrdr-s-00-a-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5518-brdr-t-01-e-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5518-brdr-t-01-e-expected.png
index 43cec79..0c60fe5d 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5518-brdr-t-01-e-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5518-brdr-t-01-e-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5519-brdr-r-02-e-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5519-brdr-r-02-e-expected.png
index 2a1887c..19ee336f 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5519-brdr-r-02-e-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5519-brdr-r-02-e-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5520-brdr-b-01-e-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5520-brdr-b-01-e-expected.png
index c9f88da..4c2497f 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5520-brdr-b-01-e-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5520-brdr-b-01-e-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5521-brdr-l-02-e-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5521-brdr-l-02-e-expected.png
index 9b5d2079..1771ec4 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5521-brdr-l-02-e-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5521-brdr-l-02-e-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5522-brdr-00-b-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5522-brdr-00-b-expected.png
index 018afab..3958d58d 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5522-brdr-00-b-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0805-c5522-brdr-00-b-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t09-c5526c-display-00-e-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t09-c5526c-display-00-e-expected.png
deleted file mode 100644
index b47156a7..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t09-c5526c-display-00-e-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0905-c414-flt-02-c-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0905-c414-flt-02-c-expected.png
index e08fa13..ffd4192 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0905-c414-flt-02-c-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0905-c414-flt-02-c-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0905-c414-flt-03-c-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0905-c414-flt-03-c-expected.png
index 1556013a..5688d81c 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0905-c414-flt-03-c-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0905-c414-flt-03-c-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0905-c414-flt-04-c-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0905-c414-flt-04-c-expected.png
index 4abf6d0..6177543 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0905-c414-flt-04-c-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0905-c414-flt-04-c-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0905-c5525-fltcont-00-d-g-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0905-c5525-fltcont-00-d-g-expected.png
index 3eb368b6..d880082 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0905-c5525-fltcont-00-d-g-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0905-c5525-fltcont-00-d-g-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0905-c5525-fltwidth-00-c-g-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0905-c5525-fltwidth-00-c-g-expected.png
index b83e960..3b08fbf3 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0905-c5525-fltwidth-00-c-g-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0905-c5525-fltwidth-00-c-g-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0905-c5525-fltwrap-00-b-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0905-c5525-fltwrap-00-b-expected.png
deleted file mode 100644
index 3a88fe18e..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t0905-c5525-fltwrap-00-b-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t090501-c414-flt-00-d-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t090501-c414-flt-00-d-expected.png
deleted file mode 100644
index b00a3504..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t090501-c414-flt-00-d-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t090501-c414-flt-01-b-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t090501-c414-flt-01-b-expected.png
deleted file mode 100644
index d1df56f7..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t090501-c414-flt-01-b-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t090501-c414-flt-ln-00-d-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t090501-c414-flt-ln-00-d-expected.png
index 5512e20..7878170 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t090501-c414-flt-ln-00-d-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t090501-c414-flt-ln-00-d-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t090501-c414-flt-ln-02-d-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t090501-c414-flt-ln-02-d-expected.png
index 51e0280..04c6a42 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t090501-c414-flt-ln-02-d-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t090501-c414-flt-ln-02-d-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t090501-c414-flt-ln-03-d-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t090501-c414-flt-ln-03-d-expected.png
index 45eafef..fca53b1f 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t090501-c414-flt-ln-03-d-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t090501-c414-flt-ln-03-d-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1202-counter-08-b-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1202-counter-08-b-expected.png
deleted file mode 100644
index 9f234b5..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1202-counter-08-b-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1202-counter-13-b-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1202-counter-13-b-expected.png
deleted file mode 100644
index f59d06da..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1202-counter-13-b-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1202-counter-14-b-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1202-counter-14-b-expected.png
deleted file mode 100644
index f59d06da..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1202-counter-14-b-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1202-counters-08-b-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1202-counters-08-b-expected.png
deleted file mode 100644
index e1dbaa66..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1202-counters-08-b-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1202-counters-13-b-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1202-counters-13-b-expected.png
index 68f26064..5b8fa6b 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1202-counters-13-b-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1202-counters-13-b-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1202-counters-14-b-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1202-counters-14-b-expected.png
index 68f26064..5b8fa6b 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1202-counters-14-b-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1202-counters-14-b-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1204-order-01-d-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1204-order-01-d-expected.png
deleted file mode 100644
index 8e8a535b..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1204-order-01-d-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t120401-scope-00-b-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t120401-scope-00-b-expected.png
index 9e63e18..ac647fb7 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t120401-scope-00-b-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t120401-scope-00-b-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1402-c45-bg-canvas-00-b-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1402-c45-bg-canvas-00-b-expected.png
deleted file mode 100644
index 9eff48f5..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1402-c45-bg-canvas-00-b-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t140201-c535-bg-fixd-00-b-g-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t140201-c535-bg-fixd-00-b-g-expected.png
index 44ca81d5..7f93cb0 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t140201-c535-bg-fixd-00-b-g-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t140201-c535-bg-fixd-00-b-g-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t140201-c537-bgfxps-00-c-ag-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t140201-c537-bgfxps-00-c-ag-expected.png
index 10791621..642218bb 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t140201-c537-bgfxps-00-c-ag-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t140201-c537-bgfxps-00-c-ag-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1505-c524-font-var-00-b-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1505-c524-font-var-00-b-expected.png
index 350204f..c41b099e 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1505-c524-font-var-00-b-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1505-c524-font-var-00-b-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1506-c525-font-wt-00-b-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1506-c525-font-wt-00-b-expected.png
deleted file mode 100644
index 56d53dd..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1506-c525-font-wt-00-b-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1602-c546-txt-align-00-b-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1602-c546-txt-align-00-b-expected.png
index 837de13..5a9c1b8 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1602-c546-txt-align-00-b-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/t1602-c546-txt-align-00-b-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/css3-modsel-35-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/css3-modsel-35-expected.png
deleted file mode 100644
index 151b1de..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/css3-modsel-35-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/flexbox/button-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/flexbox/button-expected.png
deleted file mode 100644
index d74b1727..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/flexbox/button-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/font-feature-settings-rendering-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/font-feature-settings-rendering-expected.png
deleted file mode 100644
index fb7d5f2b..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/font-feature-settings-rendering-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/masking/clip-path-inset-corners-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/masking/clip-path-inset-corners-expected.png
deleted file mode 100644
index 2bd546c..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/masking/clip-path-inset-corners-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-13-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-13-expected.png
index 15d2f22..da8a1bf 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-13-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-13-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-15-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-15-expected.png
index 5e4aded..2f2974f 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-15-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-15-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-18a-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-18a-expected.png
deleted file mode 100644
index 2a24b9d..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-18a-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-21-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-21-expected.png
deleted file mode 100644
index 05e9ab7..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-21-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-22-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-22-expected.png
index 1758b829..24223e0 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-22-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-22-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-35-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-35-expected.png
deleted file mode 100644
index 151b1de..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-35-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-39-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-39-expected.png
deleted file mode 100644
index 6e442f5..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-39-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-39b-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-39b-expected.png
deleted file mode 100644
index 6e442f5..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-39b-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-41-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-41-expected.png
deleted file mode 100644
index b7898f595..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-41-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-41a-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-41a-expected.png
deleted file mode 100644
index b7898f595..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-41a-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-42-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-42-expected.png
deleted file mode 100644
index 53219b9..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-42-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-42a-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-42a-expected.png
deleted file mode 100644
index 53219b9..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-42a-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-66-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-66-expected.png
deleted file mode 100644
index 1a8512c3..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-66-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-79-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-79-expected.png
deleted file mode 100644
index cb1b9f0..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/html/css3-modsel-79-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-13-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-13-expected.png
index 15d2f22..da8a1bf 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-13-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-13-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-15-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-15-expected.png
index 5e4aded..2f2974f 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-15-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-15-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-18a-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-18a-expected.png
deleted file mode 100644
index 2a24b9d..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-18a-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-21-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-21-expected.png
deleted file mode 100644
index 05e9ab7..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-21-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-22-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-22-expected.png
index 1758b829..24223e0 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-22-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-22-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-3-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-3-expected.png
index 745f811..90de159 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-3-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-3-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-35-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-35-expected.png
deleted file mode 100644
index 151b1de..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-35-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-39-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-39-expected.png
deleted file mode 100644
index 6e442f5..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-39-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-39b-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-39b-expected.png
deleted file mode 100644
index 6e442f5..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-39b-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-41-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-41-expected.png
deleted file mode 100644
index b7898f595..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-41-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-41a-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-41a-expected.png
deleted file mode 100644
index b7898f595..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-41a-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-42-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-42-expected.png
deleted file mode 100644
index 53219b9..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-42-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-42a-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-42a-expected.png
deleted file mode 100644
index 53219b9..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-42a-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-66-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-66-expected.png
deleted file mode 100644
index 1a8512c3..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-66-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-79-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-79-expected.png
deleted file mode 100644
index cb1b9f0..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xhtml/css3-modsel-79-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-13-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-13-expected.png
index 5febe4dd..9c15e53 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-13-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-13-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-15-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-15-expected.png
index 1fdcf00..d0f320e 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-15-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-15-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-18a-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-18a-expected.png
deleted file mode 100644
index d873f24..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-18a-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-21-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-21-expected.png
deleted file mode 100644
index 5e92284..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-21-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-22-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-22-expected.png
index d2af8090..817e01b 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-22-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-22-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-3-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-3-expected.png
index e40c20a..f01686fd 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-3-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-3-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-35-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-35-expected.png
deleted file mode 100644
index 10decd4..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-35-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-39-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-39-expected.png
deleted file mode 100644
index 7e051227..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-39-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-39b-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-39b-expected.png
deleted file mode 100644
index 7e051227..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-39b-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-41-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-41-expected.png
deleted file mode 100644
index bfa059e..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-41-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-41a-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-41a-expected.png
deleted file mode 100644
index bfa059e..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-41a-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-42-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-42-expected.png
deleted file mode 100644
index 48c7737..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-42-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-42a-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-42a-expected.png
deleted file mode 100644
index 48c7737..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-42a-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-66-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-66-expected.png
deleted file mode 100644
index 096cc7e4..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-66-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-79-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-79-expected.png
deleted file mode 100644
index 0a73188..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css3/selectors3/xml/css3-modsel-79-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/5131716-2-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/5131716-2-expected.png
deleted file mode 100644
index 7b3dd3c..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/5131716-2-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/6476-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/6476-expected.png
deleted file mode 100644
index 0c1bb1b..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/6476-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/caret-and-focus-ring-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/caret-and-focus-ring-expected.png
deleted file mode 100644
index b3141c11..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/caret-and-focus-ring-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/caret-ltr-2-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/caret-ltr-2-expected.png
deleted file mode 100644
index 17d3f2d..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/caret-ltr-2-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/caret-ltr-2-left-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/caret-ltr-2-left-expected.png
deleted file mode 100644
index 915f189..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/caret-ltr-2-left-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/caret-rtl-2-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/caret-rtl-2-expected.png
deleted file mode 100644
index 0d2af914..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/caret-rtl-2-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/caret-rtl-2-left-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/caret-rtl-2-left-expected.png
deleted file mode 100644
index fd4849d..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/caret-rtl-2-left-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/caret-rtl-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/caret-rtl-expected.png
deleted file mode 100644
index c9ed209..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/caret-rtl-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/caret-rtl-right-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/caret-rtl-right-expected.png
deleted file mode 100644
index 953cd15..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/caret-rtl-right-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/click-start-of-line-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/click-start-of-line-expected.png
deleted file mode 100644
index b085d74..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/click-start-of-line-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/contains-boundaries-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/contains-boundaries-expected.png
deleted file mode 100644
index c768a6ea..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/contains-boundaries-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/leave-requested-block-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/leave-requested-block-expected.png
index 28def78..395f7a26 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/leave-requested-block-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/leave-requested-block-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/mixed-editability-6-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/mixed-editability-6-expected.png
deleted file mode 100644
index f1a92bb..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/mixed-editability-6-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/previous-line-position-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/previous-line-position-expected.png
index d0d9e8a1..b5e8ab27 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/previous-line-position-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/previous-line-position-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/selectNode-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/selectNode-expected.png
index d3ee7e4..b6605bb 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/selectNode-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/selectNode-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/selectNodeContents-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/selectNodeContents-expected.png
index 0f4c68f..bdfa362 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/selectNodeContents-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/selectNodeContents-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/selection-background-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/selection-background-expected.png
deleted file mode 100644
index a31feb6..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/selection/selection-background-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/list-delete-003-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/list-delete-003-expected.png
deleted file mode 100644
index a4163a5..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/list-delete-003-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/list-type-after-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/list-type-after-expected.png
index 33064b8f..14b15fa1 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/list-type-after-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/list-type-after-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/list-type-before-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/list-type-before-expected.png
index 92bd7374..9271e87 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/list-type-before-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/list-type-before-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/table-delete-001-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/table-delete-001-expected.png
deleted file mode 100644
index debe9a6..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/table-delete-001-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/table-delete-003-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/table-delete-003-expected.png
deleted file mode 100644
index 7dc12a1c..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/table-delete-003-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/backgrounds/animated-gif-as-background-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/backgrounds/animated-gif-as-background-expected.png
index f44ebd4..3c3d5db 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/backgrounds/animated-gif-as-background-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/backgrounds/animated-gif-as-background-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/backgrounds/animated-gif-as-background-rounded-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/backgrounds/animated-gif-as-background-rounded-expected.png
index e2e5f3a..8a0b183 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/backgrounds/animated-gif-as-background-rounded-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/backgrounds/animated-gif-as-background-rounded-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/basic/011-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/basic/011-expected.png
deleted file mode 100644
index 9ae04e5..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/basic/011-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/basic/014-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/basic/014-expected.png
index 48d4f00..da92e4b 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/basic/014-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/basic/014-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/basic/015-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/basic/015-expected.png
index cc8b117..1adbc7c 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/basic/015-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/basic/015-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/basic/016-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/basic/016-expected.png
deleted file mode 100644
index 4213812..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/basic/016-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/basic/020-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/basic/020-expected.png
deleted file mode 100644
index 2cd81d5..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/basic/020-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/basic/truncation-rtl-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/basic/truncation-rtl-expected.png
index fc29067..f9fe174 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/basic/truncation-rtl-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/basic/truncation-rtl-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/basic/white-space-pre-wraps-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/basic/white-space-pre-wraps-expected.png
deleted file mode 100644
index 550b20b7..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/basic/white-space-pre-wraps-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/float/001-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/float/001-expected.png
deleted file mode 100644
index f2f58d4..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/float/001-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/float/002-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/float/002-expected.png
deleted file mode 100644
index af553bbe..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/float/002-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/float/014-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/float/014-expected.png
index 1db7316..d7da708 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/float/014-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/float/014-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/float/avoidance-percent-width-strict-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/float/avoidance-percent-width-strict-expected.png
deleted file mode 100644
index c75646d..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/float/avoidance-percent-width-strict-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/float/centered-float-avoidance-complexity-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/float/centered-float-avoidance-complexity-expected.png
index d529a55fe..d81342c 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/float/centered-float-avoidance-complexity-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/float/centered-float-avoidance-complexity-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/float/editable-text-overlapping-float-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/float/editable-text-overlapping-float-expected.png
index db323db5..34dda8c 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/float/editable-text-overlapping-float-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/float/editable-text-overlapping-float-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/float/independent-align-positioning-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/float/independent-align-positioning-expected.png
deleted file mode 100644
index 50019cef..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/float/independent-align-positioning-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/float/shrink-to-fit-width-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/float/shrink-to-fit-width-expected.png
deleted file mode 100644
index f549ca8..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/float/shrink-to-fit-width-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/float/vertical-move-relayout-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/float/vertical-move-relayout-expected.png
deleted file mode 100644
index 33f85f7..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/float/vertical-move-relayout-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/margin-collapse/103-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/margin-collapse/103-expected.png
index 29d0cdb6..7736f52 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/margin-collapse/103-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/margin-collapse/103-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/positioning/absolute-in-inline-short-rtl-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/positioning/absolute-in-inline-short-rtl-expected.png
deleted file mode 100644
index 1d01f37..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/block/positioning/absolute-in-inline-short-rtl-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/canvas/fillrect_gradient-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/canvas/fillrect_gradient-expected.png
deleted file mode 100644
index d8ff85b3..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/canvas/fillrect_gradient-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/001-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/001-expected.png
index 95a1644..fa95bb0 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/001-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/001-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/004-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/004-expected.png
deleted file mode 100644
index 03fea1c0..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/004-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/005-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/005-expected.png
deleted file mode 100644
index 6d5a524..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/005-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/ZeroOpacityLayers-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/ZeroOpacityLayers-expected.png
deleted file mode 100644
index 12a8c5f..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/ZeroOpacityLayers-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/ZeroOpacityLayers2-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/ZeroOpacityLayers2-expected.png
deleted file mode 100644
index d78bc37..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/ZeroOpacityLayers2-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/background-shorthand-invalid-url-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/background-shorthand-invalid-url-expected.png
index 4db2373..177a0396 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/background-shorthand-invalid-url-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/background-shorthand-invalid-url-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/beforeSelectorOnCodeElement-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/beforeSelectorOnCodeElement-expected.png
index 338401a..7ab21086 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/beforeSelectorOnCodeElement-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/beforeSelectorOnCodeElement-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/bidi-override-in-anonymous-block-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/bidi-override-in-anonymous-block-expected.png
index 9b4942d..e37652d 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/bidi-override-in-anonymous-block-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/bidi-override-in-anonymous-block-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/border-radius-outline-offset-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/border-radius-outline-offset-expected.png
deleted file mode 100644
index 61ab9e3..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/border-radius-outline-offset-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/clip-zooming-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/clip-zooming-expected.png
index 90eab68..577d59c 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/clip-zooming-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/clip-zooming-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/color-correction-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/color-correction-expected.png
deleted file mode 100644
index 2e0a0514..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/color-correction-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/css-imports-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/css-imports-expected.png
deleted file mode 100644
index 0b84335e..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/css-imports-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/css1_forward_compatible_parsing-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/css1_forward_compatible_parsing-expected.png
deleted file mode 100644
index df8a3184..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/css1_forward_compatible_parsing-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/css3-modsel-22-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/css3-modsel-22-expected.png
index 1758b829..24223e0 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/css3-modsel-22-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/css3-modsel-22-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/css3-space-in-nth-and-lang-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/css3-space-in-nth-and-lang-expected.png
deleted file mode 100644
index 94f992a1..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/css3-space-in-nth-and-lang-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/ex-after-font-variant-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/ex-after-font-variant-expected.png
deleted file mode 100644
index 454f6d84..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/ex-after-font-variant-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/find-next-layer-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/find-next-layer-expected.png
deleted file mode 100644
index 1ebee02..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/find-next-layer-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/first-letter-capitalized-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/first-letter-capitalized-expected.png
deleted file mode 100644
index 83c64dd..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/first-letter-capitalized-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/first-letter-detach-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/first-letter-detach-expected.png
index ae9a550a..d73f523f 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/first-letter-detach-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/first-letter-detach-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/first-letter-float-after-float-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/first-letter-float-after-float-expected.png
deleted file mode 100644
index e86b443..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/first-letter-float-after-float-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/first-letter-float-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/first-letter-float-expected.png
deleted file mode 100644
index eb7a8c1..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/first-letter-float-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/first-letter-visibility-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/first-letter-visibility-expected.png
deleted file mode 100644
index 48fce2e..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/first-letter-visibility-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/focus-ring-detached-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/focus-ring-detached-expected.png
index 1bacc33..cfa604b7 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/focus-ring-detached-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/focus-ring-detached-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/focus-ring-multiline-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/focus-ring-multiline-expected.png
deleted file mode 100644
index e15035f5..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/focus-ring-multiline-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/focus-ring-outline-color-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/focus-ring-outline-color-expected.png
deleted file mode 100644
index da877a6..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/focus-ring-outline-color-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/focus-ring-outline-offset-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/focus-ring-outline-offset-expected.png
deleted file mode 100644
index 20cf929..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/focus-ring-outline-offset-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/focus-ring-outline-width-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/focus-ring-outline-width-expected.png
deleted file mode 100644
index d30153b..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/focus-ring-outline-width-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/font-face-opentype-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/font-face-opentype-expected.png
deleted file mode 100644
index 4557fcf..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/font-face-opentype-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/font-face-synthetic-bold-italic-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/font-face-synthetic-bold-italic-expected.png
deleted file mode 100644
index 49d7923..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/font-face-synthetic-bold-italic-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/font-face-synthetic-bold-italic-for-locally-installed-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/font-face-synthetic-bold-italic-for-locally-installed-expected.png
deleted file mode 100644
index 952bbe88..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/font-face-synthetic-bold-italic-for-locally-installed-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/font-face-weight-matching-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/font-face-weight-matching-expected.png
deleted file mode 100644
index dbd53d9..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/font-face-weight-matching-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/font-shorthand-weight-only-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/font-shorthand-weight-only-expected.png
deleted file mode 100644
index 8eedf14..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/font-shorthand-weight-only-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/font_property_normal-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/font_property_normal-expected.png
index 18766d4..57ee119 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/font_property_normal-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/font_property_normal-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/image-orientation/image-orientation-default-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/image-orientation/image-orientation-default-expected.png
index 047d1ac..d98648d9 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/image-orientation/image-orientation-default-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/image-orientation/image-orientation-default-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/image-orientation/image-orientation-from-image-composited-dynamic-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/image-orientation/image-orientation-from-image-composited-dynamic-expected.png
index 32c7acc..4429b51 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/image-orientation/image-orientation-from-image-composited-dynamic-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/image-orientation/image-orientation-from-image-composited-dynamic-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/image-orientation/image-orientation-from-image-composited-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/image-orientation/image-orientation-from-image-composited-expected.png
index 32c7acc..4429b51 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/image-orientation/image-orientation-from-image-composited-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/image-orientation/image-orientation-from-image-composited-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/image-orientation/image-orientation-from-image-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/image-orientation/image-orientation-from-image-expected.png
index 5ca56204..b5dbe8f 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/image-orientation/image-orientation-from-image-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/image-orientation/image-orientation-from-image-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/import-rule-regression-11590-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/import-rule-regression-11590-expected.png
deleted file mode 100644
index b30c063..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/import-rule-regression-11590-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/invalid-percentage-property-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/invalid-percentage-property-expected.png
deleted file mode 100644
index 77d15b3..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/invalid-percentage-property-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/invalidation-errors-2-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/invalidation-errors-2-expected.png
deleted file mode 100644
index a1dfc14..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/invalidation-errors-2-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/invalidation-errors-3-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/invalidation-errors-3-expected.png
deleted file mode 100644
index 3f9b575..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/invalidation-errors-3-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/invalidation-errors-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/invalidation-errors-expected.png
deleted file mode 100644
index a1dfc14..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/invalidation-errors-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/line-height-determined-by-primary-font-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/line-height-determined-by-primary-font-expected.png
index 88076ca..5cf8058b 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/line-height-determined-by-primary-font-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/line-height-determined-by-primary-font-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/line-height-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/line-height-expected.png
deleted file mode 100644
index 47626cb..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/line-height-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/list-outline-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/list-outline-expected.png
deleted file mode 100644
index cd90434..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/list-outline-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/nth-child-dynamic-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/nth-child-dynamic-expected.png
deleted file mode 100644
index b0379d86..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/nth-child-dynamic-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/relative-positioned-block-nested-with-inline-parent-dynamic-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/relative-positioned-block-nested-with-inline-parent-dynamic-expected.png
index da99e6d..acd01f2 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/relative-positioned-block-nested-with-inline-parent-dynamic-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/relative-positioned-block-nested-with-inline-parent-dynamic-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/relative-positioned-block-nested-with-inline-parent-multiple-descendant-blocks-dynamic-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/relative-positioned-block-nested-with-inline-parent-multiple-descendant-blocks-dynamic-expected.png
index 6d7daf3..08f4d4f 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/relative-positioned-block-nested-with-inline-parent-multiple-descendant-blocks-dynamic-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/relative-positioned-block-nested-with-inline-parent-multiple-descendant-blocks-dynamic-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/relative-positioned-block-with-inline-ancestor-and-parent-dynamic-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/relative-positioned-block-with-inline-ancestor-and-parent-dynamic-expected.png
index b7b5959..1e3af47 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/relative-positioned-block-with-inline-ancestor-and-parent-dynamic-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/relative-positioned-block-with-inline-ancestor-and-parent-dynamic-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/relative-positioned-block-with-inline-ancestor-dynamic-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/relative-positioned-block-with-inline-ancestor-dynamic-expected.png
index b7b5959..1e3af47 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/relative-positioned-block-with-inline-ancestor-dynamic-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/relative-positioned-block-with-inline-ancestor-dynamic-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/relative-positioned-block-with-inline-ancestor-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/relative-positioned-block-with-inline-ancestor-expected.png
index b7b5959..1e3af47 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/relative-positioned-block-with-inline-ancestor-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/relative-positioned-block-with-inline-ancestor-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/relative-positioned-block-with-inline-parent-dynamic-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/relative-positioned-block-with-inline-parent-dynamic-expected.png
index b7b5959..1e3af47 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/relative-positioned-block-with-inline-parent-dynamic-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/relative-positioned-block-with-inline-parent-dynamic-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/resize-corner-tracking-transformed-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/resize-corner-tracking-transformed-expected.png
deleted file mode 100644
index f03ba61..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/resize-corner-tracking-transformed-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/resize-corner-tracking-transformed-iframe-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/resize-corner-tracking-transformed-iframe-expected.png
deleted file mode 100644
index 88924268..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/resize-corner-tracking-transformed-iframe-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/selector-set-attribute-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/selector-set-attribute-expected.png
index 95763be..0d9ac58b 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/selector-set-attribute-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/selector-set-attribute-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/text-align-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/text-align-expected.png
deleted file mode 100644
index 3ae482b..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/text-align-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/text-overflow-ellipsis-bidi-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/text-overflow-ellipsis-bidi-expected.png
index 00021ad..1420281 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/text-overflow-ellipsis-bidi-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/text-overflow-ellipsis-bidi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/text-rendering-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/text-rendering-expected.png
index cefc834..ffbcd4d3 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/text-rendering-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/text-rendering-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/textCapitalizeEdgeCases-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/textCapitalizeEdgeCases-expected.png
index 4587b877..0e2cab7 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/textCapitalizeEdgeCases-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/textCapitalizeEdgeCases-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/universal-hover-quirk-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/universal-hover-quirk-expected.png
index 5f68a3a..e504a0e7 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/universal-hover-quirk-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/universal-hover-quirk-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png
index 4f937bf..a724f033 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css3-text/css3-text-decoration/text-decoration-style-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
deleted file mode 100644
index d85a69a..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png
deleted file mode 100644
index d627106a..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-links-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png
deleted file mode 100644
index ce4c560..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css3-text/css3-text-decoration/text-decoration-style-inherit-simple-underlines-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css3-text/css3-text-justify/text-justify-8bits-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css3-text/css3-text-justify/text-justify-8bits-expected.png
index 0707f8f..f3a88412 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css3-text/css3-text-justify/text-justify-8bits-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css3-text/css3-text-justify/text-justify-8bits-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/dom/Element/class-attribute-whitespace-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/dom/Element/class-attribute-whitespace-expected.png
deleted file mode 100644
index 3efd81a..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/dom/Element/class-attribute-whitespace-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/dynamic/anonymous-block-orphaned-lines-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/dynamic/anonymous-block-orphaned-lines-expected.png
deleted file mode 100644
index 8543fef1..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/dynamic/anonymous-block-orphaned-lines-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/dynamic/create-renderer-for-whitespace-only-text-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/dynamic/create-renderer-for-whitespace-only-text-expected.png
deleted file mode 100644
index 0fa2e5e..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/dynamic/create-renderer-for-whitespace-only-text-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/dynamic/float-in-trailing-whitespace-after-last-line-break-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/dynamic/float-in-trailing-whitespace-after-last-line-break-expected.png
deleted file mode 100644
index 13fb6a8..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/dynamic/float-in-trailing-whitespace-after-last-line-break-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/001-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/001-expected.png
index b0f5dd0..65b8ba8 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/001-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/001-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/006-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/006-expected.png
deleted file mode 100644
index c180eef..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/006-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/button-text-transform-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/button-text-transform-expected.png
deleted file mode 100644
index a127416..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/button-text-transform-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/calendar-picker/calendar-picker-appearance-zoom125-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/calendar-picker/calendar-picker-appearance-zoom125-expected.png
index 496feac..1c671a6 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/calendar-picker/calendar-picker-appearance-zoom125-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/calendar-picker/calendar-picker-appearance-zoom125-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/color/input-appearance-color-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/color/input-appearance-color-expected.png
index 3b75fc8..4c14dfa 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/color/input-appearance-color-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/color/input-appearance-color-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/datalist/input-appearance-range-with-padding-with-datalist-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/datalist/input-appearance-range-with-padding-with-datalist-expected.png
deleted file mode 100644
index f73390c..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/datalist/input-appearance-range-with-padding-with-datalist-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/date/date-appearance-basic-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/date/date-appearance-basic-expected.png
index 5565a87..bba729ed 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/date/date-appearance-basic-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/date/date-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/date/date-appearance-pseudo-elements-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/date/date-appearance-pseudo-elements-expected.png
index cc4846b..574a8d6 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/date/date-appearance-pseudo-elements-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/date/date-appearance-pseudo-elements-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/datetimelocal/datetimelocal-appearance-basic-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/datetimelocal/datetimelocal-appearance-basic-expected.png
index 2cd9840..f0c9180 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/datetimelocal/datetimelocal-appearance-basic-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/datetimelocal/datetimelocal-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/form-element-geometry-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/form-element-geometry-expected.png
index 8c5e89c..fae411f 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/form-element-geometry-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/form-element-geometry-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/image/image-alt-text-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/image/image-alt-text-expected.png
deleted file mode 100644
index 22d1c33..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/image/image-alt-text-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/month/month-appearance-basic-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/month/month-appearance-basic-expected.png
index e93710d..0b737f8 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/month/month-appearance-basic-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/month/month-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/month/month-appearance-pseudo-elements-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/month/month-appearance-pseudo-elements-expected.png
index 052f61a..c0e6610 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/month/month-appearance-pseudo-elements-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/month/month-appearance-pseudo-elements-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/plaintext-mode-2-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/plaintext-mode-2-expected.png
deleted file mode 100644
index 34d94a0..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/plaintext-mode-2-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/range/slider-thumb-shared-style-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/range/slider-thumb-shared-style-expected.png
deleted file mode 100644
index 5438a9d..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/range/slider-thumb-shared-style-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/search/search-rtl-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/search/search-rtl-expected.png
deleted file mode 100644
index b0f3974..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/search/search-rtl-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select-popup/popup-menu-appearance-transform-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select-popup/popup-menu-appearance-transform-expected.png
index 09dbb329..337068c 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select-popup/popup-menu-appearance-transform-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select-popup/popup-menu-appearance-transform-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select-popup/popup-menu-appearance-zoom-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select-popup/popup-menu-appearance-zoom-expected.png
deleted file mode 100644
index c5fb786..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select-popup/popup-menu-appearance-zoom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/listbox-scrollbar-incremental-load-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/listbox-scrollbar-incremental-load-expected.png
deleted file mode 100644
index e566843..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/listbox-scrollbar-incremental-load-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/menulist-appearance-none-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/menulist-appearance-none-expected.png
deleted file mode 100644
index af750e9..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/menulist-appearance-none-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/menulist-appearance-rtl-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/menulist-appearance-rtl-expected.txt
index ec8e944..3088c9f5 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/menulist-appearance-rtl-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/menulist-appearance-rtl-expected.txt
@@ -74,11 +74,11 @@
 layer at (8,345) size 784x2 clip at (0,0) size 0x0
   LayoutNGBlockFlow {HR} at (0,329) size 784x2 [border: (1px inset #EEEEEE)]
 layer at (8,399) size 784x160
-  LayoutNGBlockFlow {DIV} at (0,383) size 784x160
+  LayoutBlockFlow {DIV} at (0,383) size 784x160
     LayoutMultiColumnSet (anonymous) at (0,0) size 784x160
 layer at (8,399) size 384x320 backgroundClip at (0,0) size 400x559 clip at (0,0) size 400x559
   LayoutMultiColumnFlowThread (anonymous) at (0,0) size 384x320
-    LayoutNGBlockFlow {DIV} at (0,0) size 384x160
+    LayoutBlockFlow {DIV} at (0,0) size 384x160
       LayoutMenuList {SELECT} at (0,0) size 350x22 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
         LayoutNGBlockFlow (anonymous) at (1,1) size 348x21
           LayoutText (anonymous) at (4,1) size 174x18
@@ -87,12 +87,12 @@
             text run at (91,1) width 18: "03"
             text run at (109,1) width 40 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
             text run at (149,1) width 29: " fifth"
-      LayoutNGBlockFlow {DIV} at (0,22) size 352x18
+      LayoutBlockFlow {DIV} at (0,22) size 352x18
         LayoutText {#text} at (1,1) size 133x15
           text run at (1,1) width 27: "First "
-          text run at (28,1) width 38: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
+          text run at (28,1) width 38 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
           text run at (66,1) width 14: "03"
-          text run at (80,1) width 28: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+          text run at (80,1) width 28 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
           text run at (108,1) width 26: " fifth"
       LayoutMenuList {SELECT} at (0,40) size 350x22 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
         LayoutNGBlockFlow (anonymous) at (1,1) size 348x21
@@ -102,28 +102,28 @@
             text run at (85,1) width 18: "03"
             text run at (103,1) width 44 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
             text run at (147,1) width 31: "First"
-      LayoutNGBlockFlow {DIV} at (0,62) size 352x18
+      LayoutBlockFlow {DIV} at (0,62) size 352x18
         LayoutText {#text} at (1,1) size 133x15
           text run at (1,1) width 23: "fifth"
-          text run at (24,1) width 41: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
+          text run at (24,1) width 41 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
           text run at (65,1) width 14: "03"
-          text run at (79,1) width 31: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+          text run at (79,1) width 31 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
           text run at (110,1) width 24: "First"
       LayoutMenuList {SELECT} at (0,80) size 350x22 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
         LayoutNGBlockFlow (anonymous) at (1,1) size 348x21
           LayoutText (anonymous) at (4,1) size 174x18
             text run at (4,1) width 174 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-      LayoutNGBlockFlow {DIV} at (0,102) size 352x18
+      LayoutBlockFlow {DIV} at (0,102) size 352x18
         LayoutText {#text} at (1,1) size 133x15
-          text run at (1,1) width 133: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+          text run at (1,1) width 133 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
       LayoutMenuList {SELECT} at (0,120) size 350x22 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
         LayoutNGBlockFlow (anonymous) at (1,1) size 348x21
           LayoutText (anonymous) at (4,1) size 174x18
             text run at (4,1) width 174 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-      LayoutNGBlockFlow {DIV} at (0,142) size 352x18
+      LayoutBlockFlow {DIV} at (0,142) size 352x18
         LayoutText {#text} at (1,1) size 133x15
-          text run at (1,1) width 133: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-    LayoutNGBlockFlow {DIV} at (0,160) size 384x160
+          text run at (1,1) width 133 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+    LayoutBlockFlow {DIV} at (0,160) size 384x160
       LayoutMenuList {SELECT} at (0,0) size 350x22 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
         LayoutNGBlockFlow (anonymous) at (1,1) size 348x21
           LayoutText (anonymous) at (170,1) size 174x18
@@ -132,12 +132,12 @@
             text run at (257,1) width 18: "03"
             text run at (275,1) width 40 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
             text run at (315,1) width 29: " fifth"
-      LayoutNGBlockFlow {DIV} at (0,22) size 352x18
+      LayoutBlockFlow {DIV} at (0,22) size 352x18
         LayoutText {#text} at (218,1) size 133x15
           text run at (218,1) width 27: "First "
-          text run at (245,1) width 38: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
+          text run at (245,1) width 38 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
           text run at (283,1) width 14: "03"
-          text run at (297,1) width 28: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+          text run at (297,1) width 28 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
           text run at (325,1) width 26: " fifth"
       LayoutMenuList {SELECT} at (0,40) size 350x22 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
         LayoutNGBlockFlow (anonymous) at (1,1) size 348x21
@@ -147,24 +147,24 @@
             text run at (251,1) width 18: "03"
             text run at (269,1) width 44 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
             text run at (313,1) width 31: "First"
-      LayoutNGBlockFlow {DIV} at (0,62) size 352x18
+      LayoutBlockFlow {DIV} at (0,62) size 352x18
         LayoutText {#text} at (218,1) size 133x15
           text run at (218,1) width 23: "fifth"
-          text run at (241,1) width 41: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
+          text run at (241,1) width 41 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
           text run at (282,1) width 14: "03"
-          text run at (296,1) width 31: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+          text run at (296,1) width 31 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
           text run at (327,1) width 24: "First"
       LayoutMenuList {SELECT} at (0,80) size 350x22 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
         LayoutNGBlockFlow (anonymous) at (1,1) size 348x21
           LayoutText (anonymous) at (170,1) size 174x18
             text run at (170,1) width 174 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-      LayoutNGBlockFlow {DIV} at (0,102) size 352x18
+      LayoutBlockFlow {DIV} at (0,102) size 352x18
         LayoutText {#text} at (218,1) size 133x15
-          text run at (218,1) width 133: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+          text run at (218,1) width 133 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
       LayoutMenuList {SELECT} at (0,120) size 350x22 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
         LayoutNGBlockFlow (anonymous) at (1,1) size 348x21
           LayoutText (anonymous) at (170,1) size 174x18
             text run at (170,1) width 174 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-      LayoutNGBlockFlow {DIV} at (0,142) size 352x18
+      LayoutBlockFlow {DIV} at (0,142) size 352x18
         LayoutText {#text} at (218,1) size 133x15
-          text run at (218,1) width 133: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+          text run at (218,1) width 133 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/menulist-option-wrap-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/menulist-option-wrap-expected.png
index 9e44d26..0772591 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/menulist-option-wrap-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/menulist-option-wrap-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/option-script-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/option-script-expected.png
deleted file mode 100644
index 036dd32..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/option-script-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/option-strip-whitespace-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/option-strip-whitespace-expected.png
deleted file mode 100644
index 67d69464..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/option-strip-whitespace-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/select-change-listbox-size-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/select-change-listbox-size-expected.png
deleted file mode 100644
index 12f74b4..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/select-change-listbox-size-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/select-disabled-appearance-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/select-disabled-appearance-expected.png
deleted file mode 100644
index 13af574..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/select-disabled-appearance-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/select-display-none-style-resolve-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/select-display-none-style-resolve-expected.png
deleted file mode 100644
index 708c90f..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/select-display-none-style-resolve-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/select-item-background-clip-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/select-item-background-clip-expected.png
deleted file mode 100644
index c80bd18..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/select-item-background-clip-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/select-multiple-rtl-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/select-multiple-rtl-expected.png
deleted file mode 100644
index 67baf6f..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/select-multiple-rtl-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/select-writing-direction-natural-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/select-writing-direction-natural-expected.png
index 17bd314..c6c5a3a 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/select-writing-direction-natural-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/select/select-writing-direction-natural-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/targeted-frame-submission-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/targeted-frame-submission-expected.png
index 57aaac0..3da3744 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/targeted-frame-submission-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/targeted-frame-submission-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/text/input-appearance-focus-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/text/input-appearance-focus-expected.png
deleted file mode 100644
index 1735267..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/text/input-appearance-focus-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/textarea/basic-textareas-quirks-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/textarea/basic-textareas-quirks-expected.png
index ee0f098..17796eb3 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/textarea/basic-textareas-quirks-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/textarea/basic-textareas-quirks-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/time/time-appearance-basic-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/time/time-appearance-basic-expected.png
index d017c6ee..c5dfbaa 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/time/time-appearance-basic-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/time/time-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/time/time-appearance-pseudo-elements-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/time/time-appearance-pseudo-elements-expected.png
index b28159f..2baa0db 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/time/time-appearance-pseudo-elements-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/time/time-appearance-pseudo-elements-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/validation-bubble-appearance-rtl-ui-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/validation-bubble-appearance-rtl-ui-expected.png
index 511d16c..5ae5408 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/validation-bubble-appearance-rtl-ui-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/validation-bubble-appearance-rtl-ui-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/week/week-appearance-basic-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/week/week-appearance-basic-expected.png
index af4de22..3603cb0 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/week/week-appearance-basic-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/week/week-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/week/week-appearance-pseudo-elements-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/week/week-appearance-pseudo-elements-expected.png
index ec646d5..323f2d92 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/week/week-appearance-pseudo-elements-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/forms/week/week-appearance-pseudo-elements-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/inline/br-text-decoration-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/inline/br-text-decoration-expected.png
deleted file mode 100644
index 4c379f19..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/inline/br-text-decoration-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/inline/drawStyledEmptyInlines-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/inline/drawStyledEmptyInlines-expected.png
deleted file mode 100644
index 74296ed1..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/inline/drawStyledEmptyInlines-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/inline/emptyInlinesWithinLists-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/inline/emptyInlinesWithinLists-expected.png
index 8fe2ad8..1632d966 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/inline/emptyInlinesWithinLists-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/inline/emptyInlinesWithinLists-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/inline/inline-borders-with-bidi-override-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/inline/inline-borders-with-bidi-override-expected.png
deleted file mode 100644
index e5abe397..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/inline/inline-borders-with-bidi-override-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/inline/nested-top-alignment-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/inline/nested-top-alignment-expected.png
index a141797..03c1482b 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/inline/nested-top-alignment-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/inline/nested-top-alignment-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/layers/inline-dirty-z-order-lists-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/layers/inline-dirty-z-order-lists-expected.png
deleted file mode 100644
index 7985cad8..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/layers/inline-dirty-z-order-lists-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/layers/normal-flow-hit-test-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/layers/normal-flow-hit-test-expected.png
deleted file mode 100644
index 55168be..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/layers/normal-flow-hit-test-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/layers/opacity-transforms-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/layers/opacity-transforms-expected.png
deleted file mode 100644
index d070ae2b..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/layers/opacity-transforms-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/002-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/002-expected.png
index 4573e15..848fc52 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/002-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/002-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/007-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/007-expected.png
index fc57a132..1140a2c 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/007-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/007-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/008-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/008-expected.png
index 2380c9e0..b5e9678 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/008-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/008-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/big-list-marker-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/big-list-marker-expected.png
index 1b515e9..8eb336d 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/big-list-marker-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/big-list-marker-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/dynamic-marker-crash-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/dynamic-marker-crash-expected.png
index 32881b2..2919cf13 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/dynamic-marker-crash-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/dynamic-marker-crash-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/marker-image-error-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/marker-image-error-expected.png
index 97875cf..943211a 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/marker-image-error-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/marker-image-error-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/ol-display-types-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/ol-display-types-expected.png
index 5762682b9..4b3e4ca 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/ol-display-types-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/ol-display-types-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/ordered-list-with-no-ol-tag-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/ordered-list-with-no-ol-tag-expected.png
index c515328..263b982 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/ordered-list-with-no-ol-tag-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/ordered-list-with-no-ol-tag-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/scrolled-marker-paint-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/scrolled-marker-paint-expected.png
index be3da4c..aae8992 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/scrolled-marker-paint-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/lists/scrolled-marker-paint-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/multicol/composited-layer-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/multicol/composited-layer-expected.txt
deleted file mode 100644
index 15ae8c55..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/multicol/composited-layer-expected.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-{
-"layers": [
-{
-"name": "LayoutView #document",
-"bounds": [800, 600],
-"drawsContent": false,
-"backgroundColor": "#FFFFFF"
-},
-{
-"name": "Scrolling Layer",
-"bounds": [800, 600],
-"drawsContent": false
-},
-{
-"name": "Scrolling Contents Layer",
-"bounds": [800, 600],
-"contentsOpaque": true,
-"backgroundColor": "#FFFFFF"
-},
-{
-"name": "LayoutNGBlockFlow DIV id='multicol'",
-"bounds": [200, 100],
-"transform": 1
-}
-],
-"transforms": [
-{
-"id": 1,
-"transform": [
-[1, 0, 0, 0],
-[0, 1, 0, 0],
-[0, 0, 1, 0],
-[8, 8, 0, 1]
-]
-}
-]
-}
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/multicol/dynamic/insert-spanner-after-inner-multicol-crash-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/multicol/dynamic/insert-spanner-after-inner-multicol-crash-expected.txt
deleted file mode 100644
index 31f175b..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/multicol/dynamic/insert-spanner-after-inner-multicol-crash-expected.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-Insert a spanner right after an inner multicol container and before column content, splitting an existing column row.
-
-PASS if no crash or assertion failure.
-

-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/multicol/fixedpos-in-transform-at-column-boundary-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/multicol/fixedpos-in-transform-at-column-boundary-expected.txt
deleted file mode 100644
index 9a73c31..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/multicol/fixedpos-in-transform-at-column-boundary-expected.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-Test that a fixed positioned object inside a transform inside a multicol isn't paginated.
-
-The word "YO" should be seen below, with large letter spacing.
-
-Y
-O
-PASS
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/multicol/nested-after-composited-layer-crash-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/multicol/nested-after-composited-layer-crash-expected.txt
deleted file mode 100644
index 9c314504..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/multicol/nested-after-composited-layer-crash-expected.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-PASS if no crash or assertion failure.
-
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/overflow/float-in-relpositioned-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/overflow/float-in-relpositioned-expected.png
deleted file mode 100644
index e15fb93f..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/overflow/float-in-relpositioned-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/overflow/hit-test-overflow-controls-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/overflow/hit-test-overflow-controls-expected.png
deleted file mode 100644
index 78310c3..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/overflow/hit-test-overflow-controls-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/overflow/position-fixed-transform-clipping-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/overflow/position-fixed-transform-clipping-expected.png
deleted file mode 100644
index c406ffb..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/overflow/position-fixed-transform-clipping-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/overflow/scrollbar-position-update-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/overflow/scrollbar-position-update-expected.png
deleted file mode 100644
index 661b095..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/overflow/scrollbar-position-update-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/replaced/image-resize-width-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/replaced/image-resize-width-expected.png
deleted file mode 100644
index ca9d613..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/replaced/image-resize-width-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/replaced/image-solid-color-with-alpha-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/replaced/image-solid-color-with-alpha-expected.png
deleted file mode 100644
index 929c4e6..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/replaced/image-solid-color-with-alpha-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/replaced/selection-rect-in-table-cell-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/replaced/selection-rect-in-table-cell-expected.png
deleted file mode 100644
index 744c9a0..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/replaced/selection-rect-in-table-cell-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/replaced/selection-rect-transform-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/replaced/selection-rect-transform-expected.png
deleted file mode 100644
index 170a6df..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/replaced/selection-rect-transform-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/table/100-percent-cell-width-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/table/100-percent-cell-width-expected.png
deleted file mode 100644
index c8d225a..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/table/100-percent-cell-width-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/table/generated-caption-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/table/generated-caption-expected.png
deleted file mode 100644
index c2477c0..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/table/generated-caption-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/table/insert-before-anonymous-ancestors-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/table/insert-before-anonymous-ancestors-expected.png
deleted file mode 100644
index 127db486..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/table/insert-before-anonymous-ancestors-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/table/insert-cell-before-form-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/table/insert-cell-before-form-expected.png
deleted file mode 100644
index a393d0e..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/table/insert-cell-before-form-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/table/insert-row-before-form-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/table/insert-row-before-form-expected.png
deleted file mode 100644
index a393d0e..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/table/insert-row-before-form-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/table/prepend-in-anonymous-table-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/table/prepend-in-anonymous-table-expected.png
index b9948c8..0648084 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/table/prepend-in-anonymous-table-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/table/prepend-in-anonymous-table-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/table/row-height-recalc-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/table/row-height-recalc-expected.png
deleted file mode 100644
index c504345..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/table/row-height-recalc-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/table/stale-grid-crash-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/table/stale-grid-crash-expected.png
deleted file mode 100644
index 804ce62..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/table/stale-grid-crash-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/atomic-inline-before-ellipsis-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/atomic-inline-before-ellipsis-expected.png
deleted file mode 100644
index 676483e07..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/atomic-inline-before-ellipsis-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/atsui-spacing-features-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/atsui-spacing-features-expected.png
deleted file mode 100644
index 621cc8bd..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/atsui-spacing-features-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/basic/002-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/basic/002-expected.png
deleted file mode 100644
index b20c61f5..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/basic/002-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/basic/007-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/basic/007-expected.png
deleted file mode 100644
index fc3848d..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/basic/007-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/basic/009-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/basic/009-expected.png
index 0196f54..5936b5b 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/basic/009-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/basic/009-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/basic/013-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/basic/013-expected.png
index 296047f..580bb43 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/basic/013-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/basic/013-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/basic/015-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/basic/015-expected.png
index 5f36149..be87955 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/basic/015-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/basic/015-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/basic/generic-family-changes-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/basic/generic-family-changes-expected.png
index 6da9f08..65506141 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/basic/generic-family-changes-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/basic/generic-family-changes-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/bidi-img-alt-text-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/bidi-img-alt-text-expected.png
deleted file mode 100644
index 10c55c46..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/bidi-img-alt-text-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/break-word-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/break-word-expected.png
deleted file mode 100644
index 3c1de53..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/break-word-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/capitalize-boundaries-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/capitalize-boundaries-expected.png
index 349d64a..aa2ab107 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/capitalize-boundaries-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/capitalize-boundaries-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/capitalize-preserve-nbsp-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/capitalize-preserve-nbsp-expected.png
deleted file mode 100644
index 3492612..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/capitalize-preserve-nbsp-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/cg-fallback-bolding-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/cg-fallback-bolding-expected.png
deleted file mode 100644
index e1c270d..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/cg-fallback-bolding-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/color-emoji-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/color-emoji-expected.png
index 9881404..6693c97 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/color-emoji-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/color-emoji-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/drawBidiText-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/drawBidiText-expected.png
deleted file mode 100644
index 7a8de5c2..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/drawBidiText-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/ellipsis-at-edge-of-ltr-text-in-rtl-flow-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/ellipsis-at-edge-of-ltr-text-in-rtl-flow-expected.png
index e3e37e3..4deb838 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/ellipsis-at-edge-of-ltr-text-in-rtl-flow-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/ellipsis-at-edge-of-ltr-text-in-rtl-flow-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/ellipsis-ltr-text-in-rtl-flow-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/ellipsis-ltr-text-in-rtl-flow-expected.png
index 27144e0..e4412ed 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/ellipsis-ltr-text-in-rtl-flow-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/ellipsis-ltr-text-in-rtl-flow-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/ellipsis-ltr-text-in-rtl-flow-leading-space-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/ellipsis-ltr-text-in-rtl-flow-leading-space-expected.png
index 6911adff..5761c0a 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/ellipsis-ltr-text-in-rtl-flow-leading-space-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/ellipsis-ltr-text-in-rtl-flow-leading-space-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/fake-italic-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/fake-italic-expected.png
deleted file mode 100644
index ff412bc..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/fake-italic-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/fallback-for-custom-font-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/fallback-for-custom-font-expected.png
deleted file mode 100644
index e5faad7e..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/fallback-for-custom-font-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/font-features/caps-native-synthesis-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/font-features/caps-native-synthesis-expected.png
index e80dc37..462f4b30 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/font-features/caps-native-synthesis-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/font-features/caps-native-synthesis-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/font-initial-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/font-initial-expected.png
deleted file mode 100644
index 977c5b6..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/font-initial-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/font-stretch-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/font-stretch-expected.png
deleted file mode 100644
index c09efc5a..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/font-stretch-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/font-stretch-variant-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/font-stretch-variant-expected.png
index bb0bca6..20aaa61 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/font-stretch-variant-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/font-stretch-variant-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/in-rendered-text-rtl-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/in-rendered-text-rtl-expected.png
deleted file mode 100644
index 6f5593a..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/in-rendered-text-rtl-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-AN-after-empty-run-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-AN-after-empty-run-expected.png
deleted file mode 100644
index c7cd283..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-AN-after-empty-run-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-CS-after-AN-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-CS-after-AN-expected.png
deleted file mode 100644
index 179b150..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-CS-after-AN-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-LDB-2-CSS-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-LDB-2-CSS-expected.png
index de3e3477e..61c08a5e 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-LDB-2-CSS-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-LDB-2-CSS-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-LDB-2-HTML-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-LDB-2-HTML-expected.png
index 2d7caf9..cf54d44 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-LDB-2-HTML-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-LDB-2-HTML-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-LDB-2-formatting-characters-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-LDB-2-formatting-characters-expected.png
index cea1c7a..18da868 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-LDB-2-formatting-characters-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-LDB-2-formatting-characters-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-ignored-for-first-child-inline-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-ignored-for-first-child-inline-expected.png
index 9ba8668..1c02e705 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-ignored-for-first-child-inline-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-ignored-for-first-child-inline-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-innertext-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-innertext-expected.png
deleted file mode 100644
index 4ec9f18..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-innertext-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-linebreak-001-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-linebreak-001-expected.png
deleted file mode 100644
index 35066b6..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-linebreak-001-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-listbox-atsui-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-listbox-atsui-expected.png
deleted file mode 100644
index cd19f068..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-listbox-atsui-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-mirror-he-ar-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-mirror-he-ar-expected.png
deleted file mode 100644
index 62cf1ab..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-mirror-he-ar-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-neutral-directionality-paragraph-start-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-neutral-directionality-paragraph-start-expected.png
deleted file mode 100644
index a50e010b..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/bidi-neutral-directionality-paragraph-start-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/complex-character-based-fallback-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/complex-character-based-fallback-expected.png
deleted file mode 100644
index d6fecf45..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/complex-character-based-fallback-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/danda-space-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/danda-space-expected.png
deleted file mode 100644
index 084d459..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/danda-space-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/thai-baht-space-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/thai-baht-space-expected.png
index c9bffb9d..139d446 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/thai-baht-space-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/thai-baht-space-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/unicode-bidi-plaintext-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/unicode-bidi-plaintext-expected.png
index a5888af6..d22f2bd 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/unicode-bidi-plaintext-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/unicode-bidi-plaintext-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/vertical-text-glyph-test-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/vertical-text-glyph-test-expected.png
deleted file mode 100644
index d2493eb..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/international/vertical-text-glyph-test-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/midword-break-after-breakable-char-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/midword-break-after-breakable-char-expected.png
deleted file mode 100644
index c4d6097..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/midword-break-after-breakable-char-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/reset-emptyRun-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/reset-emptyRun-expected.png
deleted file mode 100644
index 8af17a98..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/reset-emptyRun-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/selection/atsui-kerning-and-ligatures-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/selection/atsui-kerning-and-ligatures-expected.png
deleted file mode 100644
index c222271..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/selection/atsui-kerning-and-ligatures-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/selection/atsui-partial-selection-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/selection/atsui-partial-selection-expected.png
deleted file mode 100644
index 8c3a504..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/selection/atsui-partial-selection-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/selection/delete-hard-break-character-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/selection/delete-hard-break-character-expected.png
deleted file mode 100644
index a27d6546..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/selection/delete-hard-break-character-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/selection/justified-selection-at-edge-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/selection/justified-selection-at-edge-expected.png
index b5f14e0..6468a16 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/selection/justified-selection-at-edge-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/selection/justified-selection-at-edge-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/selection/justified-selection-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/selection/justified-selection-expected.png
deleted file mode 100644
index 6bc9cf8..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/selection/justified-selection-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/selection/should-use-atsui-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/selection/should-use-atsui-expected.png
deleted file mode 100644
index d22c3730..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/selection/should-use-atsui-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/shaping/same-script-different-lang-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/shaping/same-script-different-lang-expected.png
index 939b2b4ac..8635c83 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/shaping/same-script-different-lang-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/shaping/same-script-different-lang-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/stroking-decorations-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/stroking-decorations-expected.png
index c1a9368..c6d9f9a 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/stroking-decorations-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/stroking-decorations-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/text-letter-spacing-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/text-letter-spacing-expected.png
deleted file mode 100644
index 4955d65..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/text-letter-spacing-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/wbr-in-pre-crash-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/wbr-in-pre-crash-expected.png
deleted file mode 100644
index 0dbe5254..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/wbr-in-pre-crash-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/wbr-styled-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/wbr-styled-expected.png
index 45dd8ce..a1afecf6 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/wbr-styled-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/wbr-styled-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/whitespace/028-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/whitespace/028-expected.png
deleted file mode 100644
index 6ad9204..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/whitespace/028-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/whitespace/pre-wrap-last-char-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/whitespace/pre-wrap-last-char-expected.png
deleted file mode 100644
index 82fc693..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/whitespace/pre-wrap-last-char-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/word-break-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/word-break-expected.png
index 7f3e7dc0..c0158ce 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/word-break-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/word-break-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/word-break-run-rounding-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/word-break-run-rounding-expected.png
deleted file mode 100644
index b46bb212..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/word-break-run-rounding-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/word-break-soft-hyphen-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/word-break-soft-hyphen-expected.png
deleted file mode 100644
index 0e1eeea9..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/word-break-soft-hyphen-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/word-space-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/word-space-expected.png
deleted file mode 100644
index e16314b2..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/text/word-space-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fragmentation/block-with-float-and-1-orphaned-line-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fragmentation/block-with-float-and-1-orphaned-line-expected.txt
deleted file mode 100644
index 734601f..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fragmentation/block-with-float-and-1-orphaned-line-expected.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-First column.
-This cyan block should all be in the first column.Second column.
-PASS
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fragmentation/single-cell-too-large-for-page-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fragmentation/single-cell-too-large-for-page-expected.txt
deleted file mode 100644
index d97b83c..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fragmentation/single-cell-too-large-for-page-expected.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-crbug.com/99124: Table rows shouldn't straddle page boundaries.
-
-Text
-Text
-Text
-Text
-Text
-Text
-Text
-Text
-Text
-Text
-Text
-Text
-Text
-Text
-Text
-Text
-PASS
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/ietestcenter/css3/text/textshadow-002-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/ietestcenter/css3/text/textshadow-002-expected.png
index b441555b..a648b00 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/ietestcenter/css3/text/textshadow-002-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/ietestcenter/css3/text/textshadow-002-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/ietestcenter/css3/text/textshadow-003-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/ietestcenter/css3/text/textshadow-003-expected.png
deleted file mode 100644
index 20de7bb..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/ietestcenter/css3/text/textshadow-003-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/ietestcenter/css3/text/textshadow-010-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/ietestcenter/css3/text/textshadow-010-expected.png
deleted file mode 100644
index 3b884f6..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/ietestcenter/css3/text/textshadow-010-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/images/exif-orientation-css-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/images/exif-orientation-css-expected.png
deleted file mode 100644
index 302d1848..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/images/exif-orientation-css-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/images/exif-orientation-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/images/exif-orientation-expected.png
index 9139d2f..d37208e 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/images/exif-orientation-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/images/exif-orientation-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/images/exif-orientation-image-document-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/images/exif-orientation-image-document-expected.png
index e2728d4..bbf86e87 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/images/exif-orientation-image-document-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/images/exif-orientation-image-document-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/images/imagemap-focus-ring-outline-color-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/images/imagemap-focus-ring-outline-color-expected.png
deleted file mode 100644
index a2bc1a4..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/images/imagemap-focus-ring-outline-color-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/images/imagemap-focus-ring-zoom-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/images/imagemap-focus-ring-zoom-expected.png
deleted file mode 100644
index 1144003..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/images/imagemap-focus-ring-zoom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/printing/ellipsis-printing-style-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/printing/ellipsis-printing-style-expected.txt
deleted file mode 100644
index d9e9377..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/printing/ellipsis-printing-style-expected.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 1066x799
-layer at (0,0) size 1066x40 backgroundClip at (0,0) size 800x600 clip at (0,0) size 800x600
-  LayoutNGBlockFlow {HTML} at (0,0) size 1066x40
-    LayoutNGBlockFlow {BODY} at (8,8) size 1050x24
-layer at (8,8) size 168x24
-  LayoutNGBlockFlow {DIV} at (0,0) size 168x24 [color=#FFFFFF] [bgcolor=#000000]
-    LayoutText {#text} at (0,0) size 160x16
-      text run at (0,0) width 144: "This text"
-      text run at (144,0) width 16: "\x{2026}"
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/printing/page-height-zero-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/printing/page-height-zero-expected.txt
deleted file mode 100644
index 333b0b7..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/printing/page-height-zero-expected.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-Test that an exception is thrown when attempting to set zero page height
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS internals.numberOfPages(100, 0) threw exception TypeError: Failed to execute 'numberOfPages' on 'Internals': Page width and height must be larger than 0..
-PASS internals.pageNumber(document.body, 100, 0) threw exception TypeError: Failed to execute 'pageNumber' on 'Internals': Page width and height must be larger than 0..
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/printing/webgl-repeated-printing-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/printing/webgl-repeated-printing-expected.txt
deleted file mode 100644
index fa71a2b..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/printing/webgl-repeated-printing-expected.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-PASS successfullyParsed is true
-
-TEST COMPLETE
-Snapshot width: 800 height: 600
-Test 0: canvas should be green
-PASS pixel[0] is within 1 of 0
-PASS pixel[1] is within 1 of 255
-PASS pixel[2] is within 1 of 0
-Snapshot width: 800 height: 600
-Test 1: canvas should be red
-PASS pixel[0] is within 1 of 255
-PASS pixel[1] is within 1 of 0
-PASS pixel[2] is within 1 of 0
-Snapshot width: 800 height: 600
-Test 2: canvas should be blue
-PASS pixel[0] is within 1 of 0
-PASS pixel[1] is within 1 of 0
-PASS pixel[2] is within 1 of 255
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/printing/webgl-repeated-printing-preservedrawingbuffer-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/printing/webgl-repeated-printing-preservedrawingbuffer-expected.txt
deleted file mode 100644
index fa71a2b..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/printing/webgl-repeated-printing-preservedrawingbuffer-expected.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-PASS successfullyParsed is true
-
-TEST COMPLETE
-Snapshot width: 800 height: 600
-Test 0: canvas should be green
-PASS pixel[0] is within 1 of 0
-PASS pixel[1] is within 1 of 255
-PASS pixel[2] is within 1 of 0
-Snapshot width: 800 height: 600
-Test 1: canvas should be red
-PASS pixel[0] is within 1 of 255
-PASS pixel[1] is within 1 of 0
-PASS pixel[2] is within 1 of 0
-Snapshot width: 800 height: 600
-Test 2: canvas should be blue
-PASS pixel[0] is within 1 of 0
-PASS pixel[1] is within 1 of 0
-PASS pixel[2] is within 1 of 255
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/svg/W3C-SVG-1.1/text-align-05-b-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/svg/W3C-SVG-1.1/text-align-05-b-expected.png
deleted file mode 100644
index a20216fb..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/svg/W3C-SVG-1.1/text-align-05-b-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/svg/text/text-selection-align-05-b-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/svg/text/text-selection-align-05-b-expected.png
deleted file mode 100644
index 973876b6..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/svg/text/text-selection-align-05-b-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/bugs/bug17130-2-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/bugs/bug17130-2-expected.png
deleted file mode 100644
index a822be0..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/bugs/bug17130-2-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/bugs/bug17138-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/bugs/bug17138-expected.png
deleted file mode 100644
index 3143df93..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/bugs/bug17138-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/bugs/bug20804-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/bugs/bug20804-expected.png
deleted file mode 100644
index d4f41c2..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/bugs/bug20804-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/bugs/bug43854-2-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/bugs/bug43854-2-expected.png
index ab69693..c5e7d926 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/bugs/bug43854-2-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/bugs/bug43854-2-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/bugs/bug8411-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/bugs/bug8411-expected.png
deleted file mode 100644
index 62928d0..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/bugs/bug8411-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/colgroup_align_center-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/colgroup_align_center-expected.png
deleted file mode 100644
index 80151ea..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/colgroup_align_center-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/colgroup_align_justify-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/colgroup_align_justify-expected.png
deleted file mode 100644
index 59787c1..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/colgroup_align_justify-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/colgroup_align_left-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/colgroup_align_left-expected.png
deleted file mode 100644
index af41a871..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/colgroup_align_left-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/colgroup_align_right-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/colgroup_align_right-expected.png
deleted file mode 100644
index 2c12bb58..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/colgroup_align_right-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/colgroup_valign_baseline-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/colgroup_valign_baseline-expected.png
deleted file mode 100644
index c7ac8c9..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/colgroup_valign_baseline-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/colgroup_valign_bottom-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/colgroup_valign_bottom-expected.png
deleted file mode 100644
index c43b9670..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/colgroup_valign_bottom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/colgroup_valign_middle-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/colgroup_valign_middle-expected.png
deleted file mode 100644
index 1698b01..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/colgroup_valign_middle-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/colgroup_valign_top-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/colgroup_valign_top-expected.png
deleted file mode 100644
index 15e691d..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/colgroup_valign_top-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tables_td_align_center-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tables_td_align_center-expected.png
deleted file mode 100644
index e7958231..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tables_td_align_center-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tables_td_align_left-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tables_td_align_left-expected.png
deleted file mode 100644
index 44a93e9..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tables_td_align_left-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tables_td_align_right-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tables_td_align_right-expected.png
deleted file mode 100644
index 3e99272c3..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tables_td_align_right-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tables_th_align_center-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tables_th_align_center-expected.png
deleted file mode 100644
index d220099..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tables_th_align_center-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tables_th_align_left-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tables_th_align_left-expected.png
deleted file mode 100644
index 253ae55..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tables_th_align_left-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tables_th_align_right-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tables_th_align_right-expected.png
deleted file mode 100644
index 485293e..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tables_th_align_right-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tbody_align_center-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tbody_align_center-expected.png
deleted file mode 100644
index c583b9e..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tbody_align_center-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tbody_align_char-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tbody_align_char-expected.png
deleted file mode 100644
index 83bf924b..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tbody_align_char-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tbody_align_justify-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tbody_align_justify-expected.png
deleted file mode 100644
index e599ae6..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tbody_align_justify-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tbody_align_left-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tbody_align_left-expected.png
deleted file mode 100644
index 618fc83..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tbody_align_left-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tbody_align_right-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tbody_align_right-expected.png
deleted file mode 100644
index 1d8807be..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tbody_align_right-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tbody_valign_baseline-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tbody_valign_baseline-expected.png
deleted file mode 100644
index 02f7f61..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tbody_valign_baseline-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tbody_valign_bottom-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tbody_valign_bottom-expected.png
deleted file mode 100644
index 5d2f1b5..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tbody_valign_bottom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tbody_valign_middle-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tbody_valign_middle-expected.png
deleted file mode 100644
index 508f88d6..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tbody_valign_middle-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tbody_valign_top-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tbody_valign_top-expected.png
deleted file mode 100644
index 3338a55..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tbody_valign_top-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/td_valign_bottom-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/td_valign_bottom-expected.png
deleted file mode 100644
index 0adb7d4..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/td_valign_bottom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/td_valign_top-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/td_valign_top-expected.png
deleted file mode 100644
index bf5ff78..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/td_valign_top-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tfoot_align_center-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tfoot_align_center-expected.png
deleted file mode 100644
index b9036c6..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tfoot_align_center-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tfoot_align_char-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tfoot_align_char-expected.png
deleted file mode 100644
index 4f7b3a7..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tfoot_align_char-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tfoot_align_justify-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tfoot_align_justify-expected.png
deleted file mode 100644
index bab593a..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tfoot_align_justify-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tfoot_align_left-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tfoot_align_left-expected.png
deleted file mode 100644
index 3996af8..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tfoot_align_left-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tfoot_align_right-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tfoot_align_right-expected.png
deleted file mode 100644
index e2dda60..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tfoot_align_right-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tfoot_valign_baseline-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tfoot_valign_baseline-expected.png
deleted file mode 100644
index e1ce4698..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tfoot_valign_baseline-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tfoot_valign_bottom-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tfoot_valign_bottom-expected.png
deleted file mode 100644
index 66708b1..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tfoot_valign_bottom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tfoot_valign_middle-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tfoot_valign_middle-expected.png
deleted file mode 100644
index d1eff6a3..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tfoot_valign_middle-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tfoot_valign_top-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tfoot_valign_top-expected.png
deleted file mode 100644
index bfc9f22..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tfoot_valign_top-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/th_valign_bottom-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/th_valign_bottom-expected.png
deleted file mode 100644
index da71859..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/th_valign_bottom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/th_valign_top-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/th_valign_top-expected.png
deleted file mode 100644
index 2d71dde..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/th_valign_top-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/thead_align_center-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/thead_align_center-expected.png
deleted file mode 100644
index 082c425..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/thead_align_center-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/thead_align_char-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/thead_align_char-expected.png
deleted file mode 100644
index 477f060..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/thead_align_char-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/thead_align_justify-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/thead_align_justify-expected.png
deleted file mode 100644
index ed310b4..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/thead_align_justify-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/thead_align_left-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/thead_align_left-expected.png
deleted file mode 100644
index e55a5fc4..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/thead_align_left-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/thead_align_right-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/thead_align_right-expected.png
deleted file mode 100644
index 1e14433..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/thead_align_right-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/thead_valign_bottom-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/thead_valign_bottom-expected.png
deleted file mode 100644
index ab11fcb..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/thead_valign_bottom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/thead_valign_top-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/thead_valign_top-expected.png
deleted file mode 100644
index 68bd5e8..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/thead_valign_top-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tr_valign_bottom-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tr_valign_bottom-expected.png
deleted file mode 100644
index 34bd4ff6..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tr_valign_bottom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tr_valign_top-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tr_valign_top-expected.png
deleted file mode 100644
index 2e3a3b8..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/tr_valign_top-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_col_valign_baseline-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_col_valign_baseline-expected.png
deleted file mode 100644
index a409449..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_col_valign_baseline-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_col_valign_bottom-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_col_valign_bottom-expected.png
deleted file mode 100644
index 9dd906a..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_col_valign_bottom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_col_valign_middle-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_col_valign_middle-expected.png
deleted file mode 100644
index 2dd1a1e..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_col_valign_middle-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_col_valign_top-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_col_valign_top-expected.png
deleted file mode 100644
index 9ab345d..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_col_valign_top-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_colgroup_valign_baseline-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_colgroup_valign_baseline-expected.png
deleted file mode 100644
index a4512e16..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_colgroup_valign_baseline-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_colgroup_valign_bottom-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_colgroup_valign_bottom-expected.png
deleted file mode 100644
index 8630ec3..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_colgroup_valign_bottom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_colgroup_valign_middle-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_colgroup_valign_middle-expected.png
deleted file mode 100644
index 43e69a4..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_colgroup_valign_middle-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_colgroup_valign_top-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_colgroup_valign_top-expected.png
deleted file mode 100644
index 90cf17be..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_colgroup_valign_top-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tbody_align_center-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tbody_align_center-expected.png
deleted file mode 100644
index 3623219a..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tbody_align_center-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tbody_align_char-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tbody_align_char-expected.png
deleted file mode 100644
index ca2dfb6..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tbody_align_char-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tbody_align_justify-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tbody_align_justify-expected.png
deleted file mode 100644
index d1bc76f9..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tbody_align_justify-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tbody_align_left-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tbody_align_left-expected.png
deleted file mode 100644
index 7a9a0e8..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tbody_align_left-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tbody_align_right-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tbody_align_right-expected.png
deleted file mode 100644
index 35b76d5..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tbody_align_right-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tbody_valign_baseline-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tbody_valign_baseline-expected.png
deleted file mode 100644
index 8d30586..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tbody_valign_baseline-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tbody_valign_bottom-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tbody_valign_bottom-expected.png
deleted file mode 100644
index 8ccf399..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tbody_valign_bottom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tbody_valign_middle-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tbody_valign_middle-expected.png
deleted file mode 100644
index 575a520d..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tbody_valign_middle-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tbody_valign_top-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tbody_valign_top-expected.png
deleted file mode 100644
index 8e66951..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tbody_valign_top-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_td_align_justify-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_td_align_justify-expected.png
index e996a391..aef1907b 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_td_align_justify-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_td_align_justify-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_td_valign_bottom-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_td_valign_bottom-expected.png
deleted file mode 100644
index c6a12aa..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_td_valign_bottom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_td_valign_top-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_td_valign_top-expected.png
deleted file mode 100644
index 38c354a..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_td_valign_top-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tfoot_align_center-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tfoot_align_center-expected.png
deleted file mode 100644
index d7af80f..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tfoot_align_center-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tfoot_align_char-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tfoot_align_char-expected.png
deleted file mode 100644
index e029767..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tfoot_align_char-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tfoot_align_justify-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tfoot_align_justify-expected.png
deleted file mode 100644
index f6c72f4..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tfoot_align_justify-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tfoot_align_left-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tfoot_align_left-expected.png
deleted file mode 100644
index a276f7f..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tfoot_align_left-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tfoot_align_right-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tfoot_align_right-expected.png
deleted file mode 100644
index cc506a8..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tfoot_align_right-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tfoot_valign_baseline-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tfoot_valign_baseline-expected.png
deleted file mode 100644
index 1d8fea1..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tfoot_valign_baseline-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tfoot_valign_bottom-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tfoot_valign_bottom-expected.png
deleted file mode 100644
index c07a5ee..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tfoot_valign_bottom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tfoot_valign_middle-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tfoot_valign_middle-expected.png
deleted file mode 100644
index 691eb06..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tfoot_valign_middle-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tfoot_valign_top-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tfoot_valign_top-expected.png
deleted file mode 100644
index b010f1e..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tfoot_valign_top-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_th_valign_bottom-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_th_valign_bottom-expected.png
deleted file mode 100644
index a2519fba..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_th_valign_bottom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_th_valign_top-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_th_valign_top-expected.png
deleted file mode 100644
index 3ba6074..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_th_valign_top-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_thead_align_justify-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_thead_align_justify-expected.png
deleted file mode 100644
index 84ecc73..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_thead_align_justify-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_thead_valign_bottom-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_thead_valign_bottom-expected.png
deleted file mode 100644
index 72369a26..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_thead_valign_bottom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_thead_valign_top-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_thead_valign_top-expected.png
deleted file mode 100644
index 6af1882..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_thead_valign_top-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tr_align_justify-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tr_align_justify-expected.png
index 5fa3550..d0a8e8e 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tr_align_justify-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tr_align_justify-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tr_valign_bottom-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tr_valign_bottom-expected.png
deleted file mode 100644
index a879a105..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tr_valign_bottom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tr_valign_top-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tr_valign_top-expected.png
deleted file mode 100644
index a888b6e3..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/marvin/x_tr_valign_top-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/other/wa_table_tr_align-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/other/wa_table_tr_align-expected.png
index cece42e0..cc6b060 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/other/wa_table_tr_align-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla/other/wa_table_tr_align-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla_expected_failures/other/test4-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla_expected_failures/other/test4-expected.png
deleted file mode 100644
index 8eaa471..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/tables/mozilla_expected_failures/other/test4-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/transforms/transform-on-inline-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/transforms/transform-on-inline-expected.png
new file mode 100644
index 0000000..156bfe3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/transforms/transform-on-inline-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/virtual/gpu-rasterization/images/exif-orientation-css-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/virtual/gpu-rasterization/images/exif-orientation-css-expected.png
deleted file mode 100644
index 92c8782..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/virtual/gpu-rasterization/images/exif-orientation-css-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/virtual/gpu-rasterization/images/exif-orientation-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/virtual/gpu-rasterization/images/exif-orientation-expected.png
index 5a3ef4ac..cb8d6f42 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/virtual/gpu-rasterization/images/exif-orientation-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/virtual/gpu-rasterization/images/exif-orientation-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/virtual/gpu-rasterization/images/exif-orientation-image-document-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/virtual/gpu-rasterization/images/exif-orientation-image-document-expected.png
index da8d521f..d8abfef 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/virtual/gpu-rasterization/images/exif-orientation-image-document-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/virtual/gpu-rasterization/images/exif-orientation-image-document-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/virtual/gpu-rasterization/images/imagemap-focus-ring-outline-color-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/virtual/gpu-rasterization/images/imagemap-focus-ring-outline-color-expected.png
deleted file mode 100644
index fbfdc84..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/virtual/gpu-rasterization/images/imagemap-focus-ring-outline-color-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/virtual/gpu-rasterization/images/imagemap-focus-ring-zoom-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/virtual/gpu-rasterization/images/imagemap-focus-ring-zoom-expected.png
deleted file mode 100644
index 7061307..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/virtual/gpu-rasterization/images/imagemap-focus-ring-zoom-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/compositing/sibling-positioning-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/compositing/sibling-positioning-expected.png
new file mode 100644
index 0000000..2906dd21
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/compositing/sibling-positioning-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/fast/clip/nestedTransparencyClip-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/fast/clip/nestedTransparencyClip-expected.png
new file mode 100644
index 0000000..cd02ed7e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/fast/clip/nestedTransparencyClip-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/fast/clip/nestedTransparencyClip-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/fast/clip/nestedTransparencyClip-expected.txt
new file mode 100644
index 0000000..1c4cbcc9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/fast/clip/nestedTransparencyClip-expected.txt
@@ -0,0 +1,23 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutBlockFlow {HTML} at (0,0) size 800x600
+    LayoutBlockFlow {BODY} at (8,8) size 784x584
+      LayoutBlockFlow (anonymous) at (0,0) size 784x60
+        LayoutText {#text} at (0,0) size 741x39
+          text run at (0,0) width 741: "This test is for a bug we had with clipping transparency layers. The bug is visual, so the pixel test is more worthwhile."
+          text run at (0,20) width 644: "Below, \"Peach,\" \"Plum,\" and \"Pear\" should appear. Before, we were clipping out \"Plum\" and \"Pear.\""
+        LayoutBR {BR} at (644,35) size 0x0
+        LayoutBR {BR} at (0,40) size 0x19
+layer at (8,68) size 784x20 transparent
+  LayoutBlockFlow {DIV} at (0,60) size 784x20
+    LayoutText {#text} at (0,0) size 38x19
+      text run at (0,0) width 38: "Peach"
+layer at (8,88) size 33x20 transparent
+  LayoutBlockFlow (positioned) {DIV} at (8,88) size 33x20
+    LayoutText {#text} at (0,0) size 33x19
+      text run at (0,0) width 33: "Plum"
+layer at (8,108) size 28x20 transparent
+  LayoutBlockFlow (positioned) {DIV} at (0,20) size 28x20
+    LayoutText {#text} at (0,0) size 28x19
+      text run at (0,0) width 28: "Pear"
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/fast/css/ZeroOpacityLayers-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/fast/css/ZeroOpacityLayers-expected.png
new file mode 100644
index 0000000..c755bc45
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/fast/css/ZeroOpacityLayers-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/fast/css/ZeroOpacityLayers2-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/fast/css/ZeroOpacityLayers2-expected.png
new file mode 100644
index 0000000..bb27c4c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/fast/css/ZeroOpacityLayers2-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/fast/dynamic/anonymous-block-layer-lost-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/fast/dynamic/anonymous-block-layer-lost-expected.png
new file mode 100644
index 0000000..f87d11b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/fast/dynamic/anonymous-block-layer-lost-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/fast/layers/opacity-stacking-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/fast/layers/opacity-stacking-expected.png
new file mode 100644
index 0000000..8f9b429
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/fast/layers/opacity-stacking-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/fast/table/multiple-captions-display-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/fast/table/multiple-captions-display-expected.png
new file mode 100644
index 0000000..4a1fff2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/fast/table/multiple-captions-display-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/fast/table/multiple-captions-display-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/fast/table/multiple-captions-display-expected.txt
new file mode 100644
index 0000000..7c34ca6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/fast/table/multiple-captions-display-expected.txt
@@ -0,0 +1,65 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x308
+  LayoutBlockFlow {html} at (0,0) size 800x308
+    LayoutBlockFlow {body} at (8,8) size 784x292
+      LayoutTable {table} at (0,0) size 126x292
+        LayoutTableSection (anonymous) at (0,164) size 126x2
+          LayoutTableRow (anonymous) at (0,0) size 126x0
+            LayoutTableCell (anonymous) at (2,0) size 122x0 [r=0 c=0 rs=1 cs=1]
+        LayoutBlockFlow {caption} at (0,40) size 126x40
+          LayoutText {#text} at (16,0) size 94x39
+            text run at (16,0) width 94: "PASS: Normal"
+            text run at (38,20) width 50: "Caption"
+        LayoutTableSection {thead} at (0,140) size 126x24
+          LayoutTableRow (anonymous) at (0,2) size 126x20
+            LayoutTableCell (anonymous) at (2,2) size 122x20 [r=0 c=0 rs=1 cs=1]
+              LayoutText {#text} at (0,0) size 67x19
+                text run at (0,0) width 67: "HEADER"
+        LayoutTableSection {tbody} at (0,166) size 126x42
+          LayoutTableRow (anonymous) at (0,0) size 126x40
+            LayoutTableCell (anonymous) at (2,0) size 122x40 [r=0 c=0 rs=1 cs=1]
+              LayoutBR {br} at (0,0) size 0x19
+              LayoutText {#text} at (0,20) size 122x19
+                text run at (0,20) width 122: "Some body content"
+              LayoutBR {br} at (122,20) size 0x19
+        LayoutTableSection {tfoot} at (0,210) size 126x22
+          LayoutTableRow (anonymous) at (0,0) size 126x20
+            LayoutTableCell (anonymous) at (2,0) size 122x20 [r=0 c=0 rs=1 cs=1]
+              LayoutText {#text} at (0,0) size 64x19
+                text run at (0,0) width 64: "FOOTER"
+        LayoutTableSection (anonymous) at (0,208) size 126x2
+          LayoutTableRow (anonymous) at (0,0) size 126x0
+            LayoutTableCell (anonymous) at (2,0) size 122x0 [r=0 c=0 rs=1 cs=1]
+        LayoutBlockFlow {caption} at (0,80) size 126x60
+          LayoutText {#text} at (0,0) size 0x0
+        LayoutBlockFlow {caption} at (0,140) size 126x0
+layer at (8,240) size 126x60 transparent
+  LayoutBlockFlow {caption} at (0,232) size 126x60
+    LayoutText {#text} at (26,0) size 116x59
+      text run at (26,0) width 74: "PASS: First"
+      text run at (5,20) width 116: "Caption aligned to"
+      text run at (29,40) width 68: "the bottom"
+layer at (10,172) size 228x20
+  LayoutBlockFlow (positioned) {caption} at (10,172) size 228x20
+    LayoutText {#text} at (0,0) size 228x19
+      text run at (0,0) width 228: "PASS: Caption with a fixed position"
+layer at (8,8) size 126x40 transparent
+  LayoutBlockFlow {caption} at (0,0) size 126x40
+    LayoutText {#text} at (15,0) size 102x39
+      text run at (15,0) width 96: "PASS: Caption"
+      text run at (12,20) width 102: "with opacity 0.7"
+layer at (10,216) size 329x20 transparent
+  LayoutBlockFlow (positioned) {caption} at (10,216) size 329x20
+    LayoutText {#text} at (0,0) size 329x19
+      text run at (0,0) width 329: "PASS: Caption with a fixed position and opacity 0.6"
+layer at (8,88) size 118x59 transparent
+  LayoutInline {a} at (0,0) size 118x59
+    LayoutText {#text} at (15,0) size 118x59
+      text run at (15,0) width 96: "PASS: Caption"
+      text run at (4,20) width 118: "with opacity 0.5 in"
+      text run at (14,40) width 98: "one of its child."
+layer at (71,148) size 441x20 transparent
+  LayoutBlockFlow (positioned) {a} at (71,148) size 441x20
+    LayoutText {#text} at (0,0) size 441x19
+      text run at (0,0) width 441: "PASS: Caption with opacity 0.4 and fixed position of one of the child."
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/fast/text/complex-text-opacity-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/fast/text/complex-text-opacity-expected.png
new file mode 100644
index 0000000..4c04dd97
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/fast/text/complex-text-opacity-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/fast/text/complex-text-opacity-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/fast/text/complex-text-opacity-expected.txt
new file mode 100644
index 0000000..1e38f2329
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/fast/text/complex-text-opacity-expected.txt
@@ -0,0 +1,144 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutBlockFlow {HTML} at (0,0) size 800x600
+    LayoutBlockFlow {BODY} at (8,8) size 784x584
+      LayoutBlockFlow (anonymous) at (0,0) size 784x20
+        LayoutText {#text} at (0,0) size 419x19
+          text run at (0,0) width 419: "Pixel test for complex text rendering with opacity (Chromium bug "
+        LayoutInline {A} at (0,0) size 32x19 [color=#0000EE]
+          LayoutText {#text} at (419,0) size 32x19
+            text run at (419,0) width 32: "8768"
+        LayoutText {#text} at (451,0) size 9x19
+          text run at (451,0) width 9: ")."
+      LayoutBlockFlow {P} at (0,36) size 784x0
+      LayoutBlockFlow {DIV} at (0,36) size 784x46
+        LayoutInline {SPAN} at (0,0) size 45x29
+          LayoutText {#text} at (0,7) size 45x29
+            text run at (0,7) width 45: "\x{916}\x{94B}\x{91C}\x{947}\x{902}"
+        LayoutText {#text} at (45,7) size 6x29
+          text run at (45,7) width 6: " "
+        LayoutText {#text} at (96,7) size 6x29
+          text run at (96,7) width 6: " "
+        LayoutText {#text} at (147,7) size 6x29
+          text run at (147,7) width 6: " "
+        LayoutText {#text} at (198,7) size 6x29
+          text run at (198,7) width 6: " "
+        LayoutText {#text} at (249,7) size 6x29
+          text run at (249,7) width 6: " "
+        LayoutText {#text} at (300,7) size 6x29
+          text run at (300,7) width 6: " "
+        LayoutText {#text} at (351,7) size 6x29
+          text run at (351,7) width 6: " "
+        LayoutText {#text} at (402,7) size 6x29
+          text run at (402,7) width 6: " "
+        LayoutText {#text} at (453,7) size 6x29
+          text run at (453,7) width 6: " "
+        LayoutText {#text} at (504,7) size 6x29
+          text run at (504,7) width 6: " "
+        LayoutText {#text} at (0,0) size 0x0
+      LayoutBlockFlow {DIV} at (0,82) size 784x30
+        LayoutInline {SPAN} at (0,0) size 53x29
+          LayoutText {#text} at (590,0) size 53x29
+            text run at (590,0) width 53 RTL: "\x{64A}\x{624}\x{644}\x{645}\x{646}\x{64A}"
+        LayoutText {#text} at (584,0) size 6x29
+          text run at (584,0) width 6 RTL: " "
+        LayoutText {#text} at (525,0) size 6x29
+          text run at (525,0) width 6 RTL: " "
+        LayoutText {#text} at (466,0) size 6x29
+          text run at (466,0) width 6 RTL: " "
+        LayoutText {#text} at (407,0) size 6x29
+          text run at (407,0) width 6 RTL: " "
+        LayoutText {#text} at (348,0) size 6x29
+          text run at (348,0) width 6 RTL: " "
+        LayoutText {#text} at (289,0) size 6x29
+          text run at (289,0) width 6 RTL: " "
+        LayoutText {#text} at (230,0) size 6x29
+          text run at (230,0) width 6 RTL: " "
+        LayoutText {#text} at (171,0) size 6x29
+          text run at (171,0) width 6 RTL: " "
+        LayoutText {#text} at (112,0) size 6x29
+          text run at (112,0) width 6 RTL: " "
+        LayoutText {#text} at (53,0) size 6x29
+          text run at (53,0) width 6 RTL: " "
+        LayoutText {#text} at (0,0) size 0x0
+layer at (8,44) size 45x29 transparent
+  LayoutInline {SPAN} at (0,0) size 45x29
+    LayoutText {#text} at (51,7) size 45x29
+      text run at (51,7) width 45: "\x{916}\x{94B}\x{91C}\x{947}\x{902}"
+layer at (8,44) size 45x29 transparent
+  LayoutInline {SPAN} at (0,0) size 45x29
+    LayoutText {#text} at (102,7) size 45x29
+      text run at (102,7) width 45: "\x{916}\x{94B}\x{91C}\x{947}\x{902}"
+layer at (8,44) size 45x29 transparent
+  LayoutInline {SPAN} at (0,0) size 45x29
+    LayoutText {#text} at (153,7) size 45x29
+      text run at (153,7) width 45: "\x{916}\x{94B}\x{91C}\x{947}\x{902}"
+layer at (8,44) size 45x29 transparent
+  LayoutInline {SPAN} at (0,0) size 45x29
+    LayoutText {#text} at (204,7) size 45x29
+      text run at (204,7) width 45: "\x{916}\x{94B}\x{91C}\x{947}\x{902}"
+layer at (8,44) size 45x29 transparent
+  LayoutInline {SPAN} at (0,0) size 45x29
+    LayoutText {#text} at (255,7) size 45x29
+      text run at (255,7) width 45: "\x{916}\x{94B}\x{91C}\x{947}\x{902}"
+layer at (8,44) size 45x29 transparent
+  LayoutInline {SPAN} at (0,0) size 45x29
+    LayoutText {#text} at (306,7) size 45x29
+      text run at (306,7) width 45: "\x{916}\x{94B}\x{91C}\x{947}\x{902}"
+layer at (8,44) size 45x29 transparent
+  LayoutInline {SPAN} at (0,0) size 45x29
+    LayoutText {#text} at (357,7) size 45x29
+      text run at (357,7) width 45: "\x{916}\x{94B}\x{91C}\x{947}\x{902}"
+layer at (8,44) size 45x29 transparent
+  LayoutInline {SPAN} at (0,0) size 45x29
+    LayoutText {#text} at (408,7) size 45x29
+      text run at (408,7) width 45: "\x{916}\x{94B}\x{91C}\x{947}\x{902}"
+layer at (8,44) size 45x29 transparent
+  LayoutInline {SPAN} at (0,0) size 45x29
+    LayoutText {#text} at (459,7) size 45x29
+      text run at (459,7) width 45: "\x{916}\x{94B}\x{91C}\x{947}\x{902}"
+layer at (8,44) size 45x29 transparent
+  LayoutInline {SPAN} at (0,0) size 45x29
+    LayoutText {#text} at (510,7) size 45x29
+      text run at (510,7) width 45: "\x{916}\x{94B}\x{91C}\x{947}\x{902}"
+layer at (8,90) size 53x29 transparent
+  LayoutInline {SPAN} at (0,0) size 53x29
+    LayoutText {#text} at (531,0) size 53x29
+      text run at (531,0) width 53 RTL: "\x{64A}\x{624}\x{644}\x{645}\x{646}\x{64A}"
+layer at (8,90) size 53x29 transparent
+  LayoutInline {SPAN} at (0,0) size 53x29
+    LayoutText {#text} at (472,0) size 53x29
+      text run at (472,0) width 53 RTL: "\x{64A}\x{624}\x{644}\x{645}\x{646}\x{64A}"
+layer at (8,90) size 53x29 transparent
+  LayoutInline {SPAN} at (0,0) size 53x29
+    LayoutText {#text} at (413,0) size 53x29
+      text run at (413,0) width 53 RTL: "\x{64A}\x{624}\x{644}\x{645}\x{646}\x{64A}"
+layer at (8,90) size 53x29 transparent
+  LayoutInline {SPAN} at (0,0) size 53x29
+    LayoutText {#text} at (354,0) size 53x29
+      text run at (354,0) width 53 RTL: "\x{64A}\x{624}\x{644}\x{645}\x{646}\x{64A}"
+layer at (8,90) size 53x29 transparent
+  LayoutInline {SPAN} at (0,0) size 53x29
+    LayoutText {#text} at (295,0) size 53x29
+      text run at (295,0) width 53 RTL: "\x{64A}\x{624}\x{644}\x{645}\x{646}\x{64A}"
+layer at (8,90) size 53x29 transparent
+  LayoutInline {SPAN} at (0,0) size 53x29
+    LayoutText {#text} at (236,0) size 53x29
+      text run at (236,0) width 53 RTL: "\x{64A}\x{624}\x{644}\x{645}\x{646}\x{64A}"
+layer at (8,90) size 53x29 transparent
+  LayoutInline {SPAN} at (0,0) size 53x29
+    LayoutText {#text} at (177,0) size 53x29
+      text run at (177,0) width 53 RTL: "\x{64A}\x{624}\x{644}\x{645}\x{646}\x{64A}"
+layer at (8,90) size 53x29 transparent
+  LayoutInline {SPAN} at (0,0) size 53x29
+    LayoutText {#text} at (118,0) size 53x29
+      text run at (118,0) width 53 RTL: "\x{64A}\x{624}\x{644}\x{645}\x{646}\x{64A}"
+layer at (8,90) size 53x29 transparent
+  LayoutInline {SPAN} at (0,0) size 53x29
+    LayoutText {#text} at (59,0) size 53x29
+      text run at (59,0) width 53 RTL: "\x{64A}\x{624}\x{644}\x{645}\x{646}\x{64A}"
+layer at (8,90) size 53x29 transparent
+  LayoutInline {SPAN} at (0,0) size 53x29
+    LayoutText {#text} at (0,0) size 53x29
+      text run at (0,0) width 53 RTL: "\x{64A}\x{624}\x{644}\x{645}\x{646}\x{64A}"
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/cull-rect-change-crash-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/cull-rect-change-crash-expected.txt
new file mode 100644
index 0000000..4171b8e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/cull-rect-change-crash-expected.txt
@@ -0,0 +1,24 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutSVGForeignObject foreignObject",
+          "rect": [0, 8, 1, 1],
+          "reason": "disappeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutSVGContainer g id='g'",
+      "reason": "full"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/hdr/color-profile-video-expected.png b/third_party/WebKit/LayoutTests/hdr/color-profile-video-expected.png
deleted file mode 100644
index c0e37a6..0000000
--- a/third_party/WebKit/LayoutTests/hdr/color-profile-video-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/hdr/video-canvas-alpha-expected.png b/third_party/WebKit/LayoutTests/hdr/video-canvas-alpha-expected.png
deleted file mode 100644
index 82d2988..0000000
--- a/third_party/WebKit/LayoutTests/hdr/video-canvas-alpha-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/http/conf/php.ini b/third_party/WebKit/LayoutTests/http/conf/php.ini
new file mode 100644
index 0000000..dcd2322f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/conf/php.ini
@@ -0,0 +1,2 @@
+; Let <meta charset> work. A charset provided in Content-Type takes precedence, and PHP 5.6+ defaults to UTF-8.
+default_charset = ""
diff --git a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-create-basics.html b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-create-basics.html
index ce3a8eb..c743e3c 100644
--- a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-create-basics.html
+++ b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-create-basics.html
@@ -5,10 +5,11 @@
 <script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
 <script src="/gen/third_party/WebKit/public/platform/modules/credentialmanager/credential_manager.mojom.js"></script>
 <script src="/gen/third_party/WebKit/public/platform/modules/webauth/authenticator.mojom.js"></script>
-<script src="resources/credential-helpers.js"></script>
+<script src="resources/test-inputs.js"></script>
+<script src="resources/mock-navigator-credentials.js"></script>
 <script>
 
-if (document.location.hostname == "127.0.0.1") {
+if (document.location.host != "subdomain.example.test:8443") {
   document.location = "https://subdomain.example.test:8443/credentialmanager/credentialscontainer-create-basics.html";
   promise_test(_ => new Promise(_ => {}), "Stall tests on the wrong host.");
 }
diff --git a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-create-from-nested-frame.html b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-create-from-nested-frame.html
index f39c768..b4b53e0 100644
--- a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-create-from-nested-frame.html
+++ b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-create-from-nested-frame.html
@@ -5,11 +5,12 @@
 <script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
 <script src="/gen/third_party/WebKit/public/platform/modules/credentialmanager/credential_manager.mojom.js"></script>
 <script src="/gen/third_party/WebKit/public/platform/modules/webauth/authenticator.mojom.js"></script>
-<script src="resources/credential-helpers.js"></script>
+<script src="resources/test-inputs.js"></script>
+<script src="resources/mock-navigator-credentials.js"></script>
 <body>
 <script>
 
-if (document.location.hostname == "127.0.0.1") {
+if (document.location.host != "subdomain.example.test:8443") {
   document.location = "https://subdomain.example.test:8443/credentialmanager/credentialscontainer-create-from-nested-frame.html";
   promise_test(_ => new Promise(_ => {}), "Stall tests on the wrong host.");
 }
diff --git a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-create-origins.html b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-create-origins.html
index 8a62a9bd..8f0c1f1 100644
--- a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-create-origins.html
+++ b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-create-origins.html
@@ -5,7 +5,7 @@
 <script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
 <script src="/gen/third_party/WebKit/public/platform/modules/credentialmanager/credential_manager.mojom.js"></script>
 <script src="/gen/third_party/WebKit/public/platform/modules/webauth/authenticator.mojom.js"></script>
-<script src="resources/credential-helpers.js"></script>
+<script src="resources/test-inputs.js"></script>
 <script>
 
 // For tests that require custom-set origins.
diff --git a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-basics.html b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-basics.html
index 63f3e8e..e18ca8e2 100644
--- a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-basics.html
+++ b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-basics.html
@@ -5,10 +5,11 @@
 <script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
 <script src="/gen/third_party/WebKit/public/platform/modules/credentialmanager/credential_manager.mojom.js"></script>
 <script src="/gen/third_party/WebKit/public/platform/modules/webauth/authenticator.mojom.js"></script>
-<script src="resources/credential-helpers.js"></script>
+<script src="resources/test-inputs.js"></script>
+<script src="resources/mock-navigator-credentials.js"></script>
 <script>
 
-if (document.location.hostname == "127.0.0.1") {
+if (document.location.host != "subdomain.example.test:8443") {
   document.location = "https://subdomain.example.test:8443/credentialmanager/credentialscontainer-get-basics.html";
   promise_test(_ => new Promise(_ => {}), "Stall tests on the wrong host.");
 }
diff --git a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-errors.html b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-errors.html
index 0216e0b..dafb28b 100644
--- a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-errors.html
+++ b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-errors.html
@@ -4,7 +4,8 @@
 <script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
 <script src="/gen/third_party/WebKit/public/platform/modules/credentialmanager/credential_manager.mojom.js"></script>
 <script src="/gen/third_party/WebKit/public/platform/modules/webauth/authenticator.mojom.js"></script>
-<script src="resources/credential-helpers.js"></script>
+<script src="resources/test-inputs.js"></script>
+<script src="resources/mock-navigator-credentials.js"></script>
 <script>
 
 add_completion_callback(() => {
diff --git a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-from-nested-frame.html b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-from-nested-frame.html
index 39c22bb..35eefc59 100644
--- a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-from-nested-frame.html
+++ b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-from-nested-frame.html
@@ -5,11 +5,12 @@
 <script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
 <script src="/gen/third_party/WebKit/public/platform/modules/credentialmanager/credential_manager.mojom.js"></script>
 <script src="/gen/third_party/WebKit/public/platform/modules/webauth/authenticator.mojom.js"></script>
-<script src="resources/credential-helpers.js"></script>
+<script src="resources/test-inputs.js"></script>
+<script src="resources/mock-navigator-credentials.js"></script>
 <body>
 <script>
 
-if (document.location.hostname == "127.0.0.1") {
+if (document.location.host != "subdomain.example.test:8443") {
   document.location = "https://subdomain.example.test:8443/credentialmanager/credentialscontainer-get-from-nested-frame.html";
   promise_test(_ => new Promise(_ => {}), "Stall tests on the wrong host.");
 }
diff --git a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-origins.html b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-origins.html
index d0dd88d..447b6f8c 100644
--- a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-origins.html
+++ b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-origins.html
@@ -5,7 +5,8 @@
 <script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
 <script src="/gen/third_party/WebKit/public/platform/modules/credentialmanager/credential_manager.mojom.js"></script>
 <script src="/gen/third_party/WebKit/public/platform/modules/webauth/authenticator.mojom.js"></script>
-<script src="resources/credential-helpers.js"></script>
+<script src="resources/test-inputs.js"></script>
+<script src="resources/mock-navigator-credentials.js"></script>
 <script>
 
 // For tests that require custom-set origins.
diff --git a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-preventsilentaccess-basics.html b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-preventsilentaccess-basics.html
index bcaaaed..367d1a7 100644
--- a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-preventsilentaccess-basics.html
+++ b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-preventsilentaccess-basics.html
@@ -5,7 +5,8 @@
 <script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
 <script src="/gen/third_party/WebKit/public/platform/modules/credentialmanager/credential_manager.mojom.js"></script>
 <script src="/gen/third_party/WebKit/public/platform/modules/webauth/authenticator.mojom.js"></script>
-<script src="resources/credential-helpers.js"></script>
+<script src="resources/test-inputs.js"></script>
+<script src="resources/mock-navigator-credentials.js"></script>
 <script>
 
 promise_test(_ => {
diff --git a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-store-basics.html b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-store-basics.html
index 72223298..bfe8ba6 100644
--- a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-store-basics.html
+++ b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-store-basics.html
@@ -5,7 +5,8 @@
 <script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
 <script src="/gen/third_party/WebKit/public/platform/modules/credentialmanager/credential_manager.mojom.js"></script>
 <script src="/gen/third_party/WebKit/public/platform/modules/webauth/authenticator.mojom.js"></script>
-<script src="resources/credential-helpers.js"></script>
+<script src="resources/test-inputs.js"></script>
+<script src="resources/mock-navigator-credentials.js"></script>
 <script>
 
 add_completion_callback(() => {
diff --git a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/mock-authenticator.html b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/mock-authenticator.html
index 47bd04f..1c664d1 100644
--- a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/mock-authenticator.html
+++ b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/mock-authenticator.html
@@ -4,7 +4,8 @@
 <script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
 <script src="/gen/third_party/WebKit/public/platform/modules/credentialmanager/credential_manager.mojom.js"></script>
 <script src="/gen/third_party/WebKit/public/platform/modules/webauth/authenticator.mojom.js"></script>
-<script src="resources/credential-helpers.js"></script>
+<script src="resources/test-inputs.js"></script>
+<script src="resources/mock-navigator-credentials.js"></script>
 <script>
 
 'use strict';
diff --git a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/credential-helpers.js b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/credential-helpers.js
deleted file mode 100644
index 7865ab3..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/credential-helpers.js
+++ /dev/null
@@ -1,338 +0,0 @@
-'use strict';
-
-// Converts an ECMAScript String object to an instance of
-// mojo_base.mojom.String16.
-function stringToMojoString16(string) {
-  let array = new Array(string.length);
-  for (var i = 0; i < string.length; ++i) {
-    array[i] = string.charCodeAt(i);
-  }
-  return { data: array }
-}
-
-// Mocks the CredentialManager interface defined in credential_manager.mojom.
-class MockCredentialManager {
-  constructor() {
-    this.reset();
-
-    this.binding_ = new mojo.Binding(passwordManager.mojom.CredentialManager, this);
-    this.interceptor_ = new MojoInterfaceInterceptor(
-        passwordManager.mojom.CredentialManager.name);
-    this.interceptor_.oninterfacerequest = e => {
-      this.binding_.bind(e.handle);
-    };
-    this.interceptor_.start();
-  }
-
-  constructCredentialInfo_(type, id, password, name, icon) {
-  return new passwordManager.mojom.CredentialInfo({
-      type: type,
-      id: stringToMojoString16(id),
-      name: stringToMojoString16(name),
-      icon: new url.mojom.Url({url: icon}),
-      password: stringToMojoString16(password),
-      federation: new url.mojom.Origin(
-          {scheme: '', host: '', port: 0, unique: true})
-    });
-  }
-
-  // Mock functions:
-
-  async get(mediation, includePasswords, federations) {
-    console.log(passwordManager.mojom.CredentialType.PASSWORD);
-    if (this.error_ == passwordManager.mojom.CredentialManagerError.SUCCESS) {
-      return {error: this.error_, credential: this.credentialInfo_};
-    } else {
-      return {error: this.error_, credential: null};
-    }
-  }
-
-  async store(credential) {
-    return {};
-  }
-
-  async preventSilentAccess() {
-    return {};
-  }
-
-  // Resets state of mock CredentialManager.
-  reset() {
-    this.error_ = passwordManager.mojom.CredentialManagerError.SUCCESS;
-    this.credentialInfo_ = this.constructCredentialInfo_(
-        passwordManager.mojom.CredentialType.EMPTY, '', '', '', '');
-  }
-
-  setResponse(id, password, name, icon) {
-    this.credentialInfo_ = this.constructCredentialInfo_(
-        passwordManager.mojom.CredentialType.PASSWORD, id, password, name,
-        icon);
-  }
-
-  setError(error) {
-    this.error_ = error;
-  }
-}
-
-// Class that mocks Authenticator interface defined in authenticator.mojom.
-class MockAuthenticator {
-  constructor() {
-    this.reset();
-
-    this.binding_ = new mojo.Binding(webauth.mojom.Authenticator, this);
-    this.interceptor_ = new MojoInterfaceInterceptor(
-        webauth.mojom.Authenticator.name);
-    this.interceptor_.oninterfacerequest = e => {
-      this.binding_.bind(e.handle);
-    };
-    this.interceptor_.start();
-  }
-
-  // Returns a MakeCredentialResponse to the client.
-  async makeCredential(options) {
-    var response = null;
-    if (this.status_ == webauth.mojom.AuthenticatorStatus.SUCCESS) {
-      let info = new webauth.mojom.CommonCredentialInfo(
-          { id: this.id_,
-            rawId: this.rawId_,
-            clientDataJson: this.clientDataJson_,
-          });
-      response = new webauth.mojom.MakeCredentialAuthenticatorResponse(
-          { info: info,
-            attestationObject: this.attestationObject_
-          });
-    }
-    let status = this.status_;
-    this.reset();
-    return {status, credential: response};
-  }
-
-  async getAssertion(options) {
-    var response = null;
-    if (this.status_ == webauth.mojom.AuthenticatorStatus.SUCCESS) {
-      let info = new webauth.mojom.CommonCredentialInfo(
-          { id: this.id_,
-            rawId: this.rawId_,
-            clientDataJson: this.clientDataJson_,
-          });
-      response = new webauth.mojom.GetAssertionAuthenticatorResponse(
-          { info: info,
-            authenticatorData: this.authenticatorData_,
-            signature: this.signature_,
-            userHandle: this.userHandle_,
-          });
-    }
-    let status = this.status_;
-    this.reset();
-    return {status, credential: response};
-  }
-
-  // Resets state of mock Authenticator.
-  reset() {
-    this.status_ = webauth.mojom.AuthenticatorStatus.UNKNOWN_ERROR;
-    this.id_ = null;
-    this.rawId_ = new Uint8Array(0);
-    this.clientDataJson_ = new Uint8Array(0);
-    this.attestationObject_ = new Uint8Array(0);
-    this.authenticatorData_ = new Uint8Array(0);
-    this.signature_ = new Uint8Array(0);
-    this.userHandle_ = new Uint8Array(0);
-  }
-
-  // Sets everything needed for a MakeCredential success response.
-  setDefaultsForSuccessfulMakeCredential() {
-    mockAuthenticator.setRawId(RAW_ID);
-    mockAuthenticator.setId(ID);
-    mockAuthenticator.setClientDataJson(CLIENT_DATA_JSON);
-    mockAuthenticator.setAttestationObject(ATTESTATION_OBJECT);
-    mockAuthenticator.setAuthenticatorStatus(
-        webauth.mojom.AuthenticatorStatus.SUCCESS);
-  }
-
-  // Sets everything needed for a GetAssertion success response.
-  setDefaultsForSuccessfulGetAssertion() {
-    mockAuthenticator.setRawId(RAW_ID);
-    mockAuthenticator.setId(ID);
-    mockAuthenticator.setClientDataJson(CLIENT_DATA_JSON);
-    mockAuthenticator.setAuthenticatorData(AUTHENTICATOR_DATA);
-    mockAuthenticator.setSignature(SIGNATURE);
-    mockAuthenticator.setAuthenticatorStatus(
-        webauth.mojom.AuthenticatorStatus.SUCCESS);
-  }
-
-  setAuthenticatorStatus(status) {
-    this.status_ = status;
-  }
-
-  setId(id) {
-    this.id_ = id;
-  }
-
-  setRawId(rawId) {
-    this.rawId_ = rawId;
-  }
-
-  setClientDataJson(clientDataJson) {
-    this.clientDataJson_ = clientDataJson;
-  }
-
-  setAttestationObject(attestationObject) {
-    this.attestationObject_ = attestationObject;
-  }
-
-  setAuthenticatorData(authenticatorData) {
-    this.authenticatorData_ = authenticatorData;
-  }
-
-  setSignature(signature) {
-    this.signature_ = signature;
-  }
-
-  setUserHandle(userHandle) {
-    this.userHandle_ = userHandle;
-  }
-}
-
-var mockAuthenticator = new MockAuthenticator();
-var mockCredentialManager = new MockCredentialManager();
-
-// Common mock values for the mockAuthenticator.
-var CHALLENGE = new TextEncoder().encode("climb a mountain");
-
-var PUBLIC_KEY_RP = {
-    id: "subdomain.example.test",
-    name: "Acme"
-};
-
-var PUBLIC_KEY_USER = {
-    id: new TextEncoder().encode("1098237235409872"),
-    name: "avery.a.jones@example.com",
-    displayName: "Avery A. Jones",
-    icon: "https://pics.acme.com/00/p/aBjjjpqPb.png"
-};
-
-var PUBLIC_KEY_PARAMETERS =  [{
-    type: "public-key",
-    alg: -7,
-},];
-
-var AUTHENTICATOR_SELECTION_CRITERIA = {
-    requireResidentKey: false,
-    userVerification: "preferred",
-};
-
-var MAKE_CREDENTIAL_OPTIONS = {
-    challenge: CHALLENGE,
-    rp: PUBLIC_KEY_RP,
-    user: PUBLIC_KEY_USER,
-    pubKeyCredParams: PUBLIC_KEY_PARAMETERS,
-    authenticatorSelection: AUTHENTICATOR_SELECTION_CRITERIA,
-    excludeCredentials: [],
-};
-
-var ACCEPTABLE_CREDENTIAL = {
-    type: "public-key",
-    id: new TextEncoder().encode("acceptableCredential"),
-    transports: ["usb", "nfc", "ble"]
-};
-
-var GET_CREDENTIAL_OPTIONS = {
-    challenge: CHALLENGE,
-    rpId: "subdomain.example.test",
-    allowCredentials: [ACCEPTABLE_CREDENTIAL],
-    userVerification: "preferred",
-};
-
-var RAW_ID = new TextEncoder("utf-8").encode("rawId");
-var ID = btoa("rawId");
-var CLIENT_DATA_JSON = new TextEncoder("utf-8").encode("clientDataJSON");
-var ATTESTATION_OBJECT = new TextEncoder("utf-8").encode("attestationObject");
-var AUTHENTICATOR_DATA = new TextEncoder("utf-8").encode("authenticatorData");
-var SIGNATURE = new TextEncoder("utf-8").encode("signature");
-
-var TEST_NESTED_CREDENTIAL_ID = "nestedCredentialId";
-
-// Use a 3-second timeout in the parameters for "success" cases
-// so that each test will exercise the rpID checks in both the renderer
-// and browser but will time out instead of wait for a device response.
-var CUSTOM_MAKE_CREDENTIAL_OPTIONS = 'var customPublicKey = '
-    + '{challenge: new TextEncoder().encode("challenge"), '
-    + 'rp: {id: "subdomain.example.test", name: "Acme"}, '
-    + 'user: {id: new TextEncoder().encode("1098237235409872"), '
-    + 'name: "acme@example.com", displayName: "Acme", icon:"iconUrl"}, '
-    + 'timeout: 2000, '
-    + 'pubKeyCredParams: [{type: "public-key", alg: -7,},], excludeCredentials:[],};';
-
-var CREATE_CUSTOM_CREDENTIALS = CUSTOM_MAKE_CREDENTIAL_OPTIONS
-    + "navigator.credentials.create({publicKey : customPublicKey})"
-    + ".then(c => window.parent.postMessage(c.id, '*'))"
-    + ".catch(e => window.parent.postMessage(e.name, '*'));";
-
-var CREATE_CREDENTIALS = "navigator.credentials.create({publicKey : MAKE_CREDENTIAL_OPTIONS})"
-    + ".then(c => window.parent.postMessage(c.id, '*'));";
-
-var CUSTOM_GET_CREDENTIAL_OPTIONS = 'var customPublicKey = '
-    + '{challenge: new TextEncoder().encode("challenge"), '
-    + 'rpId: "subdomain.example.test", '
-    + 'timeout: 2000, '
-    + 'allowCredentials: [{type: "public-key", id: new TextEncoder().encode("allowedCredential"), transports: ["usb", "nfc", "ble"]},],};';
-
-var GET_CUSTOM_CREDENTIALS = CUSTOM_GET_CREDENTIAL_OPTIONS
-    + "navigator.credentials.get({publicKey : customPublicKey})"
-    + ".then(c => window.parent.postMessage(c.id, '*'))"
-    + ".catch(e => window.parent.postMessage(e.name, '*'));";
-
-var GET_CREDENTIAL = "navigator.credentials.get({publicKey : GET_CREDENTIAL_OPTIONS})"
-    + ".then(c => window.parent.postMessage(c.id, '*'));";
-
-function EncloseInScriptTag(code) {
-  return "<script>" + code + "</scr" + "ipt>";
-}
-
-function deepCopy(value) {
-  if ([Number, String, Uint8Array].includes(value.constructor))
-    return value;
-
-  let copy = (value.constructor == Array) ? [] : {};
-  for (let key of Object.keys(value))
-    copy[key] = deepCopy(value[key]);
-  return copy;
-}
-
-// Verifies if |r| is the valid response to credentials.create(publicKey).
-function assertValidMakeCredentialResponse(r) {
-assert_equals(r.id, ID, 'id');
-    assert_true(r.rawId instanceof ArrayBuffer);
-    assert_array_equals(new Uint8Array(r.rawId),
-        RAW_ID, "rawId returned is the same");
-    assert_true(r.response instanceof AuthenticatorAttestationResponse);
-    assert_true(r.response.clientDataJSON instanceof ArrayBuffer);
-    assert_array_equals(new Uint8Array(r.response.clientDataJSON),
-        CLIENT_DATA_JSON, "clientDataJSON returned is the same");
-    assert_true(r.response.attestationObject instanceof ArrayBuffer);
-    assert_array_equals(new Uint8Array(r.response.attestationObject),
-        ATTESTATION_OBJECT, "attestationObject returned is the same");
-    assert_not_exists(r.response, 'authenticatorData');
-    assert_not_exists(r.response, 'signature');
-}
-
-// Verifies if |r| is the valid response to credentials.get(publicKey).
-function assertValidGetCredentialResponse(r) {
-    assert_equals(r.id, ID, 'id');
-    assert_true(r.rawId instanceof ArrayBuffer);
-    assert_array_equals(new Uint8Array(r.rawId),
-        RAW_ID, "rawId returned is the same");
-
-    // The call returned an AssertionResponse, meaning it has
-    //  authenticatorData and signature and does not have an attestationObject.
-    assert_true(r.response instanceof AuthenticatorAssertionResponse);
-    assert_true(r.response.clientDataJSON instanceof ArrayBuffer);
-    assert_array_equals(new Uint8Array(r.response.clientDataJSON),
-        CLIENT_DATA_JSON, "clientDataJSON returned is the same");
-    assert_true(r.response.authenticatorData instanceof ArrayBuffer);
-    assert_true(r.response.signature instanceof ArrayBuffer);
-    assert_array_equals(new Uint8Array(r.response.authenticatorData),
-        AUTHENTICATOR_DATA, "authenticator_data returned is the same");
-    assert_array_equals(new Uint8Array(r.response.signature),
-        SIGNATURE, "signature returned is the same");
-    assert_not_exists(r.response, 'attestationObject');
-}
diff --git a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/mock-navigator-credentials.js b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/mock-navigator-credentials.js
new file mode 100644
index 0000000..16d6583
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/mock-navigator-credentials.js
@@ -0,0 +1,195 @@
+'use strict';
+
+// Converts an ECMAScript String object to an instance of
+// mojo_base.mojom.String16.
+function stringToMojoString16(string) {
+  let array = new Array(string.length);
+  for (var i = 0; i < string.length; ++i) {
+    array[i] = string.charCodeAt(i);
+  }
+  return { data: array }
+}
+
+// Mocks the CredentialManager interface defined in credential_manager.mojom.
+class MockCredentialManager {
+  constructor() {
+    this.reset();
+
+    this.binding_ = new mojo.Binding(passwordManager.mojom.CredentialManager, this);
+    this.interceptor_ = new MojoInterfaceInterceptor(
+        passwordManager.mojom.CredentialManager.name);
+    this.interceptor_.oninterfacerequest = e => {
+      this.binding_.bind(e.handle);
+    };
+    this.interceptor_.start();
+  }
+
+  constructCredentialInfo_(type, id, password, name, icon) {
+  return new passwordManager.mojom.CredentialInfo({
+      type: type,
+      id: stringToMojoString16(id),
+      name: stringToMojoString16(name),
+      icon: new url.mojom.Url({url: icon}),
+      password: stringToMojoString16(password),
+      federation: new url.mojom.Origin(
+          {scheme: '', host: '', port: 0, unique: true})
+    });
+  }
+
+  // Mock functions:
+
+  async get(mediation, includePasswords, federations) {
+    if (this.error_ == passwordManager.mojom.CredentialManagerError.SUCCESS) {
+      return {error: this.error_, credential: this.credentialInfo_};
+    } else {
+      return {error: this.error_, credential: null};
+    }
+  }
+
+  async store(credential) {
+    return {};
+  }
+
+  async preventSilentAccess() {
+    return {};
+  }
+
+  // Resets state of mock CredentialManager.
+  reset() {
+    this.error_ = passwordManager.mojom.CredentialManagerError.SUCCESS;
+    this.credentialInfo_ = this.constructCredentialInfo_(
+        passwordManager.mojom.CredentialType.EMPTY, '', '', '', '');
+  }
+
+  setResponse(id, password, name, icon) {
+    this.credentialInfo_ = this.constructCredentialInfo_(
+        passwordManager.mojom.CredentialType.PASSWORD, id, password, name,
+        icon);
+  }
+
+  setError(error) {
+    this.error_ = error;
+  }
+}
+
+// Class that mocks Authenticator interface defined in authenticator.mojom.
+class MockAuthenticator {
+  constructor() {
+    this.reset();
+
+    this.binding_ = new mojo.Binding(webauth.mojom.Authenticator, this);
+    this.interceptor_ = new MojoInterfaceInterceptor(
+        webauth.mojom.Authenticator.name);
+    this.interceptor_.oninterfacerequest = e => {
+      this.binding_.bind(e.handle);
+    };
+    this.interceptor_.start();
+  }
+
+  // Returns a MakeCredentialResponse to the client.
+  async makeCredential(options) {
+    var response = null;
+    if (this.status_ == webauth.mojom.AuthenticatorStatus.SUCCESS) {
+      let info = new webauth.mojom.CommonCredentialInfo(
+          { id: this.id_,
+            rawId: this.rawId_,
+            clientDataJson: this.clientDataJson_,
+          });
+      response = new webauth.mojom.MakeCredentialAuthenticatorResponse(
+          { info: info,
+            attestationObject: this.attestationObject_
+          });
+    }
+    let status = this.status_;
+    this.reset();
+    return {status, credential: response};
+  }
+
+  async getAssertion(options) {
+    var response = null;
+    if (this.status_ == webauth.mojom.AuthenticatorStatus.SUCCESS) {
+      let info = new webauth.mojom.CommonCredentialInfo(
+          { id: this.id_,
+            rawId: this.rawId_,
+            clientDataJson: this.clientDataJson_,
+          });
+      response = new webauth.mojom.GetAssertionAuthenticatorResponse(
+          { info: info,
+            authenticatorData: this.authenticatorData_,
+            signature: this.signature_,
+            userHandle: this.userHandle_,
+          });
+    }
+    let status = this.status_;
+    this.reset();
+    return {status, credential: response};
+  }
+
+  // Resets state of mock Authenticator.
+  reset() {
+    this.status_ = webauth.mojom.AuthenticatorStatus.UNKNOWN_ERROR;
+    this.id_ = null;
+    this.rawId_ = new Uint8Array(0);
+    this.clientDataJson_ = new Uint8Array(0);
+    this.attestationObject_ = new Uint8Array(0);
+    this.authenticatorData_ = new Uint8Array(0);
+    this.signature_ = new Uint8Array(0);
+    this.userHandle_ = new Uint8Array(0);
+  }
+
+  // Sets everything needed for a MakeCredential success response.
+  setDefaultsForSuccessfulMakeCredential() {
+    mockAuthenticator.setRawId(RAW_ID);
+    mockAuthenticator.setId(ID);
+    mockAuthenticator.setClientDataJson(CLIENT_DATA_JSON);
+    mockAuthenticator.setAttestationObject(ATTESTATION_OBJECT);
+    mockAuthenticator.setAuthenticatorStatus(
+        webauth.mojom.AuthenticatorStatus.SUCCESS);
+  }
+
+  // Sets everything needed for a GetAssertion success response.
+  setDefaultsForSuccessfulGetAssertion() {
+    mockAuthenticator.setRawId(RAW_ID);
+    mockAuthenticator.setId(ID);
+    mockAuthenticator.setClientDataJson(CLIENT_DATA_JSON);
+    mockAuthenticator.setAuthenticatorData(AUTHENTICATOR_DATA);
+    mockAuthenticator.setSignature(SIGNATURE);
+    mockAuthenticator.setAuthenticatorStatus(
+        webauth.mojom.AuthenticatorStatus.SUCCESS);
+  }
+
+  setAuthenticatorStatus(status) {
+    this.status_ = status;
+  }
+
+  setId(id) {
+    this.id_ = id;
+  }
+
+  setRawId(rawId) {
+    this.rawId_ = rawId;
+  }
+
+  setClientDataJson(clientDataJson) {
+    this.clientDataJson_ = clientDataJson;
+  }
+
+  setAttestationObject(attestationObject) {
+    this.attestationObject_ = attestationObject;
+  }
+
+  setAuthenticatorData(authenticatorData) {
+    this.authenticatorData_ = authenticatorData;
+  }
+
+  setSignature(signature) {
+    this.signature_ = signature;
+  }
+
+  setUserHandle(userHandle) {
+    this.userHandle_ = userHandle;
+  }
+}
+
+var mockAuthenticator = new MockAuthenticator();
+var mockCredentialManager = new MockCredentialManager();
diff --git a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/nested-mock-authenticator-client.html b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/nested-mock-authenticator-client.html
index 19dc356..2a45a89 100644
--- a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/nested-mock-authenticator-client.html
+++ b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/nested-mock-authenticator-client.html
@@ -5,7 +5,8 @@
 <script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
 <script src="/gen/third_party/WebKit/public/platform/modules/credentialmanager/credential_manager.mojom.js"></script>
 <script src="/gen/third_party/WebKit/public/platform/modules/webauth/authenticator.mojom.js"></script>
-<script src="/credentialmanager/resources/credential-helpers.js"></script>
+<script src="/credentialmanager/resources/test-inputs.js"></script>
+<script src="/credentialmanager/resources/mock-navigator-credentials.js"></script>
 <script>
 mockAuthenticator.setRawId(RAW_ID);
 mockAuthenticator.setId(TEST_NESTED_CREDENTIAL_ID);
@@ -15,4 +16,4 @@
 mockAuthenticator.setSignature(SIGNATURE);
 mockAuthenticator.setAuthenticatorStatus(
     webauth.mojom.AuthenticatorStatus.SUCCESS);
-</script>
\ No newline at end of file
+</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/publickey-create-helper.html b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/publickey-create-helper.html
index b583f814..e70acbb 100644
--- a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/publickey-create-helper.html
+++ b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/publickey-create-helper.html
@@ -2,7 +2,8 @@
 <script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
 <script src="/gen/third_party/WebKit/public/platform/modules/credentialmanager/credential_manager.mojom.js"></script>
 <script src="/gen/third_party/WebKit/public/platform/modules/webauth/authenticator.mojom.js"></script>
-<script src="credential-helpers.js"></script>
+<script src="test-inputs.js"></script>
+<script src="mock-navigator-credentials.js"></script>
 <script>
 mockAuthenticator.setRawId(RAW_ID);
 mockAuthenticator.setId(ID);
diff --git a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/publickey-get-helper.html b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/publickey-get-helper.html
index 86ff8dc..aff7176 100644
--- a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/publickey-get-helper.html
+++ b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/publickey-get-helper.html
@@ -2,7 +2,8 @@
 <script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
 <script src="/gen/third_party/WebKit/public/platform/modules/credentialmanager/credential_manager.mojom.js"></script>
 <script src="/gen/third_party/WebKit/public/platform/modules/webauth/authenticator.mojom.js"></script>
-<script src="credential-helpers.js"></script>
+<script src="test-inputs.js"></script>
+<script src="mock-navigator-credentials.js"></script>
 <script>
 mockAuthenticator.setRawId(RAW_ID);
 mockAuthenticator.setId(ID);
diff --git a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/test-inputs.js b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/test-inputs.js
new file mode 100644
index 0000000..b5c90980
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/test-inputs.js
@@ -0,0 +1,143 @@
+'use strict';
+
+// Common mock values for the mockAuthenticator.
+var CHALLENGE = new TextEncoder().encode("climb a mountain");
+
+var PUBLIC_KEY_RP = {
+    id: "subdomain.example.test",
+    name: "Acme"
+};
+
+var PUBLIC_KEY_USER = {
+    id: new TextEncoder().encode("1098237235409872"),
+    name: "avery.a.jones@example.com",
+    displayName: "Avery A. Jones",
+    icon: "https://pics.acme.com/00/p/aBjjjpqPb.png"
+};
+
+var PUBLIC_KEY_PARAMETERS =  [{
+    type: "public-key",
+    alg: -7,
+},];
+
+var AUTHENTICATOR_SELECTION_CRITERIA = {
+    requireResidentKey: false,
+    userVerification: "preferred",
+};
+
+var MAKE_CREDENTIAL_OPTIONS = {
+    challenge: CHALLENGE,
+    rp: PUBLIC_KEY_RP,
+    user: PUBLIC_KEY_USER,
+    pubKeyCredParams: PUBLIC_KEY_PARAMETERS,
+    authenticatorSelection: AUTHENTICATOR_SELECTION_CRITERIA,
+    excludeCredentials: [],
+};
+
+var ACCEPTABLE_CREDENTIAL = {
+    type: "public-key",
+    id: new TextEncoder().encode("acceptableCredential"),
+    transports: ["usb", "nfc", "ble"]
+};
+
+var GET_CREDENTIAL_OPTIONS = {
+    challenge: CHALLENGE,
+    rpId: "subdomain.example.test",
+    allowCredentials: [ACCEPTABLE_CREDENTIAL],
+    userVerification: "preferred",
+};
+
+var RAW_ID = new TextEncoder("utf-8").encode("rawId");
+var ID = btoa("rawId");
+var CLIENT_DATA_JSON = new TextEncoder("utf-8").encode("clientDataJSON");
+var ATTESTATION_OBJECT = new TextEncoder("utf-8").encode("attestationObject");
+var AUTHENTICATOR_DATA = new TextEncoder("utf-8").encode("authenticatorData");
+var SIGNATURE = new TextEncoder("utf-8").encode("signature");
+
+var TEST_NESTED_CREDENTIAL_ID = "nestedCredentialId";
+
+// Use a 3-second timeout in the parameters for "success" cases
+// so that each test will exercise the rpID checks in both the renderer
+// and browser but will time out instead of wait for a device response.
+var CUSTOM_MAKE_CREDENTIAL_OPTIONS = 'var customPublicKey = '
+    + '{challenge: new TextEncoder().encode("challenge"), '
+    + 'rp: {id: "subdomain.example.test", name: "Acme"}, '
+    + 'user: {id: new TextEncoder().encode("1098237235409872"), '
+    + 'name: "acme@example.com", displayName: "Acme", icon:"iconUrl"}, '
+    + 'timeout: 2000, '
+    + 'pubKeyCredParams: [{type: "public-key", alg: -7,},], excludeCredentials:[],};';
+
+var CREATE_CUSTOM_CREDENTIALS = CUSTOM_MAKE_CREDENTIAL_OPTIONS
+    + "navigator.credentials.create({publicKey : customPublicKey})"
+    + ".then(c => window.parent.postMessage(c.id, '*'))"
+    + ".catch(e => window.parent.postMessage(e.name, '*'));";
+
+var CREATE_CREDENTIALS = "navigator.credentials.create({publicKey : MAKE_CREDENTIAL_OPTIONS})"
+    + ".then(c => window.parent.postMessage(c.id, '*'));";
+
+var CUSTOM_GET_CREDENTIAL_OPTIONS = 'var customPublicKey = '
+    + '{challenge: new TextEncoder().encode("challenge"), '
+    + 'rpId: "subdomain.example.test", '
+    + 'timeout: 2000, '
+    + 'allowCredentials: [{type: "public-key", id: new TextEncoder().encode("allowedCredential"), transports: ["usb", "nfc", "ble"]},],};';
+
+var GET_CUSTOM_CREDENTIALS = CUSTOM_GET_CREDENTIAL_OPTIONS
+    + "navigator.credentials.get({publicKey : customPublicKey})"
+    + ".then(c => window.parent.postMessage(c.id, '*'))"
+    + ".catch(e => window.parent.postMessage(e.name, '*'));";
+
+var GET_CREDENTIAL = "navigator.credentials.get({publicKey : GET_CREDENTIAL_OPTIONS})"
+    + ".then(c => window.parent.postMessage(c.id, '*'));";
+
+function EncloseInScriptTag(code) {
+  return "<script>" + code + "</scr" + "ipt>";
+}
+
+function deepCopy(value) {
+  if ([Number, String, Uint8Array].includes(value.constructor))
+    return value;
+
+  let copy = (value.constructor == Array) ? [] : {};
+  for (let key of Object.keys(value))
+    copy[key] = deepCopy(value[key]);
+  return copy;
+}
+
+// Verifies if |r| is the valid response to credentials.create(publicKey).
+function assertValidMakeCredentialResponse(r) {
+assert_equals(r.id, ID, 'id');
+    assert_true(r.rawId instanceof ArrayBuffer);
+    assert_array_equals(new Uint8Array(r.rawId),
+        RAW_ID, "rawId returned is the same");
+    assert_true(r.response instanceof AuthenticatorAttestationResponse);
+    assert_true(r.response.clientDataJSON instanceof ArrayBuffer);
+    assert_array_equals(new Uint8Array(r.response.clientDataJSON),
+        CLIENT_DATA_JSON, "clientDataJSON returned is the same");
+    assert_true(r.response.attestationObject instanceof ArrayBuffer);
+    assert_array_equals(new Uint8Array(r.response.attestationObject),
+        ATTESTATION_OBJECT, "attestationObject returned is the same");
+    assert_not_exists(r.response, 'authenticatorData');
+    assert_not_exists(r.response, 'signature');
+}
+
+// Verifies if |r| is the valid response to credentials.get(publicKey).
+function assertValidGetCredentialResponse(r) {
+    assert_equals(r.id, ID, 'id');
+    assert_true(r.rawId instanceof ArrayBuffer);
+    assert_array_equals(new Uint8Array(r.rawId),
+        RAW_ID, "rawId returned is the same");
+
+    // The call returned an AssertionResponse, meaning it has
+    //  authenticatorData and signature and does not have an attestationObject.
+    assert_true(r.response instanceof AuthenticatorAssertionResponse);
+    assert_true(r.response.clientDataJSON instanceof ArrayBuffer);
+    assert_array_equals(new Uint8Array(r.response.clientDataJSON),
+        CLIENT_DATA_JSON, "clientDataJSON returned is the same");
+    assert_true(r.response.authenticatorData instanceof ArrayBuffer);
+    assert_true(r.response.signature instanceof ArrayBuffer);
+    assert_array_equals(new Uint8Array(r.response.authenticatorData),
+        AUTHENTICATOR_DATA, "authenticator_data returned is the same");
+    assert_array_equals(new Uint8Array(r.response.signature),
+        SIGNATURE, "signature returned is the same");
+    assert_not_exists(r.response, 'attestationObject');
+}
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/animation/animation-KeyframeEffect-crash-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/animation/animation-KeyframeEffect-crash-expected.txt
new file mode 100644
index 0000000..2a3f37d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/animation/animation-KeyframeEffect-crash-expected.txt
@@ -0,0 +1,3 @@
+Tests that animations can be created with KeyframeEffect without crashing.
+
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/animation/animation-KeyframeEffect-crash.js b/third_party/WebKit/LayoutTests/http/tests/devtools/animation/animation-KeyframeEffect-crash.js
new file mode 100644
index 0000000..7dc3f56
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/animation/animation-KeyframeEffect-crash.js
@@ -0,0 +1,30 @@
+// 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.
+
+(async function() {
+  TestRunner.addResult(
+      `Tests that animations can be created with KeyframeEffect without crashing.\n`);
+  await TestRunner.loadModule('elements_test_runner');
+  await TestRunner.showPanel('elements');
+  await TestRunner.loadHTML(`
+      <div id="node" style="background-color: red; height: 100px"></div>
+    `);
+  await TestRunner.evaluateInPagePromise(`
+      function startAnimationWithKeyframeEffect()
+      {
+          var effect = new KeyframeEffect(node, { opacity : [ 0, 0.9 ] }, 1000);
+          var anim = node.animate(null);
+          anim.effect = effect;
+      }
+  `);
+
+  await UI.viewManager.showView('animations');
+  var timeline = self.runtime.sharedInstance(Animation.AnimationTimeline);
+  TestRunner.evaluateInPage('startAnimationWithKeyframeEffect()');
+  ElementsTestRunner.waitForAnimationAdded(step2);
+
+  function step2(group) {
+    TestRunner.completeTest();
+  }
+})();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/animation/animation-KeyframeEffectReadOnly-crash-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/animation/animation-KeyframeEffectReadOnly-crash-expected.txt
deleted file mode 100644
index 6db79bd..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/animation/animation-KeyframeEffectReadOnly-crash-expected.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Tests that animations can be created with KeyframeEffect and KeyframeEffectReadOnly without crashing.
-
-
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/animation/animation-KeyframeEffectReadOnly-crash.js b/third_party/WebKit/LayoutTests/http/tests/devtools/animation/animation-KeyframeEffectReadOnly-crash.js
deleted file mode 100644
index 1e202ea..0000000
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/animation/animation-KeyframeEffectReadOnly-crash.js
+++ /dev/null
@@ -1,43 +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.
-
-(async function() {
-  TestRunner.addResult(
-      `Tests that animations can be created with KeyframeEffect and KeyframeEffectReadOnly without crashing.\n`);
-  await TestRunner.loadModule('elements_test_runner');
-  await TestRunner.showPanel('elements');
-  await TestRunner.loadHTML(`
-      <div id="node" style="background-color: red; height: 100px"></div>
-      <div id="nodeRO" style="background-color: red; height: 100px"></div>
-    `);
-  await TestRunner.evaluateInPagePromise(`
-      function startAnimationWithKeyframeEffect()
-      {
-          var effect = new KeyframeEffect(node, { opacity : [ 0, 0.9 ] }, 1000);
-          var anim = node.animate(null);
-          anim.effect = effect;
-      }
-
-      function startAnimationWithKeyframeEffectReadOnly()
-      {
-          var effect = new KeyframeEffectReadOnly(nodeRO, { opacity : [ 0, 0.9 ] }, 1000);
-          var anim = nodeRO.animate(null);
-          anim.effect = effect;
-      }
-  `);
-
-  await UI.viewManager.showView('animations');
-  var timeline = self.runtime.sharedInstance(Animation.AnimationTimeline);
-  TestRunner.evaluateInPage('startAnimationWithKeyframeEffect()');
-  ElementsTestRunner.waitForAnimationAdded(step2);
-
-  function step2(group) {
-    ElementsTestRunner.waitForAnimationAdded(step3);
-    TestRunner.evaluateInPage('startAnimationWithKeyframeEffectReadOnly()');
-  }
-
-  function step3(group) {
-    TestRunner.completeTest();
-  }
-})();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/resources-panel-on-navigation-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/resources-panel-on-navigation-expected.txt
index 2ac086c..1c9c29d 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/resources-panel-on-navigation-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/resources-panel-on-navigation-expected.txt
@@ -21,7 +21,6 @@
   Application Cache
 Frames
   top
-    inspected-page.html
 Visible view is a query view: true
 Page reloaded.
 After navigation:
@@ -44,6 +43,5 @@
   Application Cache
 Frames
   top
-    inspected-page.html
 Visible view is a query view: false
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/resources-panel-resource-preview-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/resources-panel-resource-preview-expected.txt
index cfe83ea..526a5fd 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/resources-panel-resource-preview-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/resources-panel-resource-preview-expected.txt
@@ -19,11 +19,6 @@
   Application Cache
 Frames
   top
-    Images
-      image.png
-    Scripts
-      json-value.js
-    inspected-page.html
 log: visible view: unknown
 Revealed json-value.js:
 Application
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/resources-panel-selection-on-reload-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/resources-panel-selection-on-reload-expected.txt
index 73b7ac1..8e62242 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/resources-panel-selection-on-reload-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/resources-panel-selection-on-reload-expected.txt
@@ -21,7 +21,6 @@
   Application Cache
 Frames
   top
-    inspected-page.html
 Selection: ["cookies://http://127.0.0.1:8000","category://Cookies"]
 Visible view is a cookie view: true
 Page reloaded.
@@ -45,7 +44,6 @@
   Application Cache
 Frames
   top
-    inspected-page.html
 Selection: ["cookies://http://127.0.0.1:8000","category://Cookies"]
 Visible view is a cookie view: true
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/resources-panel-websql-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/resources-panel-websql-expected.txt
index 61015ea..658806b 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/resources-panel-websql-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/resources-panel-websql-expected.txt
@@ -19,9 +19,6 @@
   Application Cache
 Frames
   top
-    Scripts
-      json-value.js
-    inspected-page.html
 Found: true
 Database created state:
 Application
@@ -43,9 +40,6 @@
   Application Cache
 Frames
   top
-    Scripts
-      json-value.js
-    inspected-page.html
 Table added:
 Application
   Manifest
@@ -67,7 +61,4 @@
   Application Cache
 Frames
   top
-    Scripts
-      json-value.js
-    inspected-page.html
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/console/command-line-api-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/console/command-line-api-expected.txt
index 680f042..e377a3a 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/console/command-line-api-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/console/command-line-api-expected.txt
@@ -38,6 +38,5 @@
 undefined
 
 queryObjects(Foo)
-undefined
-Array(1)
+[Foo]
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/resource-tree/resource-tree-non-unique-url-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/resource-tree/resource-tree-non-unique-url-expected.txt
index e5eef21..547456b 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/resource-tree/resource-tree-non-unique-url-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/resource-tree/resource-tree-non-unique-url-expected.txt
@@ -6,8 +6,6 @@
         resource-tree-non-unique-url-iframe.html
             Images
                 styles-non-unique-url.css
-            Stylesheets
-                styles-non-unique-url.css
             resource-tree-non-unique-url-iframe.html
         inspected-page.html
 Sources:
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-redundant-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-redundant-expected.txt
index e921747..5325bce 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-redundant-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-redundant-expected.txt
@@ -13,17 +13,6 @@
 stop
 Clients
 Push

-Test
- 
-push
- 
-message
- 
-from
- 
-DevTools
-.
 Push
 Sync
 Sync
@@ -46,17 +35,6 @@
 http://127.0.0.1:8000/devtools/resources/inspected-page.html
 focus
 Push

-Test
- 
-push
- 
-message
- 
-from
- 
-DevTools
-.
 Push
 Sync
 Sync
@@ -74,17 +52,6 @@
 stop
 Clients
 Push

-Test
- 
-push
- 
-message
- 
-from
- 
-DevTools
-.
 Push
 Sync
 Sync
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-view-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-view-expected.txt
index 82ab15c1..9733a2a8 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-view-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-view-expected.txt
@@ -13,17 +13,6 @@
 stop
 Clients
 Push

-Test
- 
-push
- 
-message
- 
-from
- 
-DevTools
-.
 Push
 Sync
 Sync
@@ -39,17 +28,6 @@
 stop
 Clients
 Push

-Test
- 
-push
- 
-message
- 
-from
- 
-DevTools
-.
 Push
 Sync
 Sync
@@ -64,18 +42,6 @@
 stop
 Clients
 Push
-xxxxxxxxxx

-Test
- 
-push
- 
-message
- 
-from
- 
-DevTools
-.
 Push
 Sync
 Sync
@@ -90,17 +56,6 @@
 #N is redundant
 Clients
 Push

-Test
- 
-push
- 
-message
- 
-from
- 
-DevTools
-.
 Push
 Sync
 Sync
@@ -115,18 +70,6 @@
 stop
 Clients
 Push
-xxxxxxxxxx

-Test
- 
-push
- 
-message
- 
-from
- 
-DevTools
-.
 Push
 Sync
 Sync
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/network/interception-blank-frame-crash-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/network/interception-blank-frame-crash-expected.txt
new file mode 100644
index 0000000..adbb159e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/network/interception-blank-frame-crash-expected.txt
@@ -0,0 +1,2 @@
+Tests providing HTTP auth credentials for main resource over DevTools protocol.
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/network/interception-blank-frame-crash.js b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/network/interception-blank-frame-crash.js
new file mode 100644
index 0000000..88aab12
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/network/interception-blank-frame-crash.js
@@ -0,0 +1,16 @@
+(async function(testRunner) {
+  var {page, session, dp} = await testRunner.startBlank(
+      `Tests providing HTTP auth credentials for main resource over DevTools protocol.`);
+
+  await session.evaluateAsync(`
+    var frame = document.createElement('iframe');
+    document.body.appendChild(frame);
+  `);
+
+  await dp.Network.enable();
+  await dp.Network.setRequestInterception({patterns: [{}]});
+  dp.Network.onRequestIntercepted(event =>
+    dp.Network.continueInterceptedRequest({interceptionId: event.params.interceptionId}));
+  await dp.Page.navigate({url: 'http://127.0.0.1:8000/inspector-protocol/network/resources/simple-iframe.html'});
+  testRunner.completeTest();
+})
diff --git a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/workers/access-control-basic-get-fail-non-simple-expected.txt b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/workers/access-control-basic-get-fail-non-simple-expected.txt
index 2351d41..c6c9460f 100644
--- a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/workers/access-control-basic-get-fail-non-simple-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/workers/access-control-basic-get-fail-non-simple-expected.txt
@@ -1,4 +1,4 @@
-CONSOLE ERROR: Failed to load http://localhost:8000/xmlhttprequest/resources/access-control-basic-get-fail-non-simple.cgi: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:8000' is therefore not allowed access. The response had HTTP status code 403.
+CONSOLE ERROR: line 37: Failed to load http://localhost:8000/xmlhttprequest/resources/access-control-basic-get-fail-non-simple.cgi: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:8000' is therefore not allowed access. The response had HTTP status code 403.
 GET should not trigger a preflight request from a worker unless it has non-simple headers.
 
 PASS: Cross-domain access allowed for simple get.
diff --git a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/workers/cross-origin-unsupported-url-expected.txt b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/workers/cross-origin-unsupported-url-expected.txt
index e4a0621..8bd184cc 100644
--- a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/workers/cross-origin-unsupported-url-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/workers/cross-origin-unsupported-url-expected.txt
@@ -1,14 +1,14 @@
-CONSOLE ERROR: Failed to load ftp://127.0.0.1/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 20: Failed to load ftp://127.0.0.1/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
 CONSOLE ERROR: line 1: Failed to load ftp://127.0.0.1/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
-CONSOLE ERROR: Failed to load ftp://127.0.0.1/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 20: Failed to load ftp://127.0.0.1/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
 CONSOLE ERROR: line 1: Failed to load ftp://127.0.0.1/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
-CONSOLE ERROR: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 20: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
 CONSOLE ERROR: line 1: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
-CONSOLE ERROR: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 20: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
 CONSOLE ERROR: line 1: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
-CONSOLE ERROR: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 20: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
 CONSOLE ERROR: line 1: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
-CONSOLE ERROR: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 20: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
 CONSOLE ERROR: line 1: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
 [Worker] Test cross-origin XHRs to CORS-unsupported protocol schemes in the URL.
 
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/performance/perf-metrics-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/performance/perf-metrics-expected.txt
index 770c5e9..3e9a4cab 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/performance/perf-metrics-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/performance/perf-metrics-expected.txt
@@ -17,6 +17,7 @@
 	WorkerGlobalScopes
 	UACSSResources
 	RTCPeerConnections
+	ResourceFetchers
 	LayoutCount
 	RecalcStyleCount
 	LayoutDuration
@@ -45,6 +46,7 @@
 	WorkerGlobalScopes
 	UACSSResources
 	RTCPeerConnections
+	ResourceFetchers
 	LayoutCount
 	RecalcStyleCount
 	LayoutDuration
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/performance/perf-push-metrics-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/performance/perf-push-metrics-expected.txt
index b97763fa..7052f3f 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/performance/perf-push-metrics-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/performance/perf-push-metrics-expected.txt
@@ -16,6 +16,7 @@
 	WorkerGlobalScopes
 	UACSSResources
 	RTCPeerConnections
+	ResourceFetchers
 	LayoutCount
 	RecalcStyleCount
 	LayoutDuration
@@ -44,6 +45,7 @@
 	WorkerGlobalScopes
 	UACSSResources
 	RTCPeerConnections
+	ResourceFetchers
 	LayoutCount
 	RecalcStyleCount
 	LayoutDuration
@@ -72,6 +74,7 @@
 	WorkerGlobalScopes
 	UACSSResources
 	RTCPeerConnections
+	ResourceFetchers
 	LayoutCount
 	RecalcStyleCount
 	LayoutDuration
diff --git a/third_party/WebKit/LayoutTests/media/color-profile-video-expected.png b/third_party/WebKit/LayoutTests/media/color-profile-video-expected.png
deleted file mode 100644
index 132ad68c..0000000
--- a/third_party/WebKit/LayoutTests/media/color-profile-video-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/media/color-profile-video-seek-expected.png b/third_party/WebKit/LayoutTests/media/color-profile-video-seek-expected.png
deleted file mode 100644
index 5b24f3e..0000000
--- a/third_party/WebKit/LayoutTests/media/color-profile-video-seek-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/media/color-profile-video-seek-filter-expected.png b/third_party/WebKit/LayoutTests/media/color-profile-video-seek-filter-expected.png
deleted file mode 100644
index 2b5e0b3..0000000
--- a/third_party/WebKit/LayoutTests/media/color-profile-video-seek-filter-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/media/color-profile-video-seek-object-fit-expected.png b/third_party/WebKit/LayoutTests/media/color-profile-video-seek-object-fit-expected.png
deleted file mode 100644
index c4a1a2f..0000000
--- a/third_party/WebKit/LayoutTests/media/color-profile-video-seek-object-fit-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/media/controls/modern/video-does-not-go-fullscreen-on-double-click-before-preload.html b/third_party/WebKit/LayoutTests/media/controls/modern/video-does-not-go-fullscreen-on-double-click-before-preload.html
new file mode 100644
index 0000000..f8595bd1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/media/controls/modern/video-does-not-go-fullscreen-on-double-click-before-preload.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>Test that videos do not fullscreen when double-clicked before preload.</title>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="../../media-controls.js"></script>
+<video controls width=400 preload=none src="../../content/60_sec_video.webm"></video>
+<script>
+async_test(t => {
+  const video = document.querySelector('video');
+  video.addEventListener("webkitfullscreenchange", t.unreached_func());
+
+  window.onload = t.step_func(() => {
+    const coordinates = coordinatesOutsideElement(mediaControlsOverlayPlayButton(video));
+    doubleTapAtCoordinates(coordinates[0] + 1, coordinates[1] + 1, undefined, t.step_func(() => {
+      // Wait to see if the video attempts to go fullscreen.
+      setTimeout(t.done.bind(t));
+    }));
+  });
+});
+</script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/media/controls/modern/video-preload-none-has-disabled-controls.html b/third_party/WebKit/LayoutTests/media/controls/modern/video-preload-none-has-disabled-controls.html
new file mode 100644
index 0000000..434b542
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/media/controls/modern/video-preload-none-has-disabled-controls.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<title>Test that videos have disabled mute/fullscreen buttons before preload.</title>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="../../media-controls.js"></script>
+<video controls width=400 preload=none src="../../content/60_sec_video.webm"></video>
+<script>
+async_test(t => {
+  const video = document.querySelector('video');
+  const fullscreenBtn = fullscreenButton(video);
+  const muteBtn = muteButton(video);
+
+  window.onload = t.step_func(() => {
+    // Test that the controls are visible and look disabled.
+    assert_true(isControlVisible(fullscreenBtn));
+    assert_true(fullscreenBtn.disabled);
+    assert_true(isControlVisible(muteBtn));
+    assert_true(muteBtn.disabled);
+
+    // Test that the fullscreen button is actually disabled.
+    video.addEventListener("webkitfullscreenchange", t.unreached_func());
+    singleTapOnControl(fullscreenBtn, t.step_func(() => {
+      // Test that the mute button is actually disabled.
+      assert_false(video.muted);
+      singleTapOnControl(muteBtn, t.step_func_done(() => {
+        assert_false(video.muted);
+      }));
+    }));
+  });
+});
+</script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/media/media-controls.js b/third_party/WebKit/LayoutTests/media/media-controls.js
index 2f6e3d19..25e41c8 100644
--- a/third_party/WebKit/LayoutTests/media/media-controls.js
+++ b/third_party/WebKit/LayoutTests/media/media-controls.js
@@ -385,6 +385,11 @@
   ], callback);
 }
 
+function singleTapOnControl(control, callback) {
+  const coordinates = elementCoordinates(control);
+  singleTapAtCoordinates(coordinates[0], coordinates[1], callback);
+}
+
 function singleTouchAtCoordinates(xPos, yPos, callback) {
   chrome.gpuBenchmarking.pointerActionSequence([
     {
diff --git a/third_party/WebKit/LayoutTests/media/video-canvas-alpha-expected.png b/third_party/WebKit/LayoutTests/media/video-canvas-alpha-expected.png
deleted file mode 100644
index 6af9546..0000000
--- a/third_party/WebKit/LayoutTests/media/video-canvas-alpha-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/media/video-remove-insert-repaints-expected.png b/third_party/WebKit/LayoutTests/media/video-remove-insert-repaints-expected.png
deleted file mode 100644
index 47efc6a..0000000
--- a/third_party/WebKit/LayoutTests/media/video-remove-insert-repaints-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/cull-rect-change-crash-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/cull-rect-change-crash-expected.txt
new file mode 100644
index 0000000..1ab94f3d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/cull-rect-change-crash-expected.txt
@@ -0,0 +1,35 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutSVGForeignObject foreignObject",
+          "rect": [0, 8, 1, 1],
+          "reason": "disappeared"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutSVGContainer g id='g'",
+      "reason": "full"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/cull-rect-change-crash.html b/third_party/WebKit/LayoutTests/paint/invalidation/cull-rect-change-crash.html
new file mode 100644
index 0000000..5f615147
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/cull-rect-change-crash.html
@@ -0,0 +1,18 @@
+<!doctype HTML>
+<script src="resources/text-based-repaint.js"></script>
+<svg style="position: absolute; left: 0px; height: 200px">
+   <g id="g" transform="scale(0.001)">
+    <foreignobject height="100" width="100">
+       PASS
+      </p>
+    <script>
+    function repaintTest() {
+        document.getElementById("g").setAttribute('transform', 'scale(-5)');
+    }
+</script>
+<script>
+   if (window.internals)
+    internals.runtimeFlags.paintUnderInvalidationCheckingEnabled = true;
+  runRepaintTest()
+ 
+</script>
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/sibling-positioning-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/sibling-positioning-expected.png
index 2906dd21..c974d254 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/sibling-positioning-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/sibling-positioning-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/video-frame-size-change-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/video-frame-size-change-expected.png
index 4de05e8..aff30ff 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/compositing/video-frame-size-change-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/video-frame-size-change-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/composition-underline-color-expected.png b/third_party/WebKit/LayoutTests/platform/linux/editing/composition-underline-color-expected.png
new file mode 100644
index 0000000..c191e67b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/editing/composition-underline-color-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/composition-underline-color-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/editing/composition-underline-color-expected.txt
new file mode 100644
index 0000000..3560e2f9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/editing/composition-underline-color-expected.txt
@@ -0,0 +1,13 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x200
+  LayoutBlockFlow {HTML} at (0,0) size 800x200
+    LayoutBlockFlow {BODY} at (8,16) size 784x176
+      LayoutBlockFlow {P} at (0,0) size 784x40
+        LayoutText {#text} at (0,0) size 782x39
+          text run at (0,0) width 782: "This test checks that composition underline color uses the color of the text and is not always black. The test passes if you see"
+          text run at (0,20) width 472: "the word \"foobar\" in green with a composition underline in the same color."
+      LayoutBlockFlow {DIV} at (0,56) size 784x120 [color=#00FF00] [bgcolor=#000000]
+        LayoutText {#text} at (50,50) size 41x19
+          text run at (50,50) width 41: "foobar"
+caret: position 6 of child 0 {#text} of child 2 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/linux/external/wpt/css/css-font-loading/idlharness.https-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/external/wpt/css/css-font-loading/idlharness.https-expected.txt
deleted file mode 100644
index 61a0d30..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/external/wpt/css/css-font-loading/idlharness.https-expected.txt
+++ /dev/null
@@ -1,78 +0,0 @@
-frame (anonymous) - didStartProvisionalLoadForFrame
-frame (anonymous) - didCommitLoadForFrame
-main frame - didReceiveTitle: Font Loading API IDL tests
-main frame - didFinishDocumentLoadForFrame
-main frame - didHandleOnloadEventsForFrame
-main frame - didFinishLoadForFrame
-This is a testharness.js-based test.
-PASS Test IDL implementation of CSS Font Loading
-PASS Document interface: attribute fonts
-PASS Unscopable handled correctly for fonts property on Document
-PASS Document interface: document must inherit property "fonts" with the proper type
-PASS WorkerGlobalScope interface: existence and properties of interface object
-PASS FontFace interface: existence and properties of interface object
-PASS FontFace interface object length
-PASS FontFace interface object name
-PASS FontFace interface: existence and properties of interface prototype object
-PASS FontFace interface: existence and properties of interface prototype object's "constructor" property
-PASS FontFace interface: existence and properties of interface prototype object's @@unscopables property
-PASS FontFace interface: attribute family
-PASS Unscopable handled correctly for family property on FontFace
-PASS FontFace interface: attribute style
-PASS Unscopable handled correctly for style property on FontFace
-PASS FontFace interface: attribute weight
-PASS Unscopable handled correctly for weight property on FontFace
-PASS FontFace interface: attribute stretch
-PASS Unscopable handled correctly for stretch property on FontFace
-PASS FontFace interface: attribute unicodeRange
-PASS Unscopable handled correctly for unicodeRange property on FontFace
-PASS FontFace interface: attribute variant
-PASS Unscopable handled correctly for variant property on FontFace
-PASS FontFace interface: attribute featureSettings
-PASS Unscopable handled correctly for featureSettings property on FontFace
-FAIL FontFace interface: attribute variationSettings assert_true: The prototype object must have a property "variationSettings" expected true got false
-PASS Unscopable handled correctly for variationSettings property on FontFace
-PASS FontFace interface: attribute display
-PASS Unscopable handled correctly for display property on FontFace
-PASS FontFace interface: attribute status
-PASS Unscopable handled correctly for status property on FontFace
-PASS FontFace interface: operation load()
-PASS Unscopable handled correctly for load() on FontFace
-PASS FontFace interface: attribute loaded
-PASS Unscopable handled correctly for loaded property on FontFace
-PASS FontFaceSetLoadEvent interface: existence and properties of interface object
-PASS FontFaceSetLoadEvent interface object length
-PASS FontFaceSetLoadEvent interface object name
-PASS FontFaceSetLoadEvent interface: existence and properties of interface prototype object
-PASS FontFaceSetLoadEvent interface: existence and properties of interface prototype object's "constructor" property
-PASS FontFaceSetLoadEvent interface: existence and properties of interface prototype object's @@unscopables property
-PASS FontFaceSetLoadEvent interface: attribute fontfaces
-PASS Unscopable handled correctly for fontfaces property on FontFaceSetLoadEvent
-FAIL FontFaceSet interface: existence and properties of interface object assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-FAIL FontFaceSet interface object length assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-FAIL FontFaceSet interface object name assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-FAIL FontFaceSet interface: existence and properties of interface prototype object assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-FAIL FontFaceSet interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-FAIL FontFaceSet interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-FAIL FontFaceSet interface: operation add(FontFace) assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-PASS Unscopable handled correctly for add(FontFace) on FontFaceSet
-FAIL FontFaceSet interface: operation delete(FontFace) assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-PASS Unscopable handled correctly for delete(FontFace) on FontFaceSet
-FAIL FontFaceSet interface: operation clear() assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-PASS Unscopable handled correctly for clear() on FontFaceSet
-FAIL FontFaceSet interface: attribute onloading assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-PASS Unscopable handled correctly for onloading property on FontFaceSet
-FAIL FontFaceSet interface: attribute onloadingdone assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-PASS Unscopable handled correctly for onloadingdone property on FontFaceSet
-FAIL FontFaceSet interface: attribute onloadingerror assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-PASS Unscopable handled correctly for onloadingerror property on FontFaceSet
-FAIL FontFaceSet interface: operation load(CSSOMString, CSSOMString) assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-PASS Unscopable handled correctly for load(CSSOMString, CSSOMString) on FontFaceSet
-FAIL FontFaceSet interface: operation check(CSSOMString, CSSOMString) assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-PASS Unscopable handled correctly for check(CSSOMString, CSSOMString) on FontFaceSet
-FAIL FontFaceSet interface: attribute ready assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-PASS Unscopable handled correctly for ready property on FontFaceSet
-FAIL FontFaceSet interface: attribute status assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-PASS Unscopable handled correctly for status property on FontFaceSet
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/platform/linux/external/wpt/css/css-transitions/properties-value-auto-001-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/external/wpt/css/css-transitions/properties-value-auto-001-expected.txt
new file mode 100644
index 0000000..e537a17
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/external/wpt/css/css-transitions/properties-value-auto-001-expected.txt
@@ -0,0 +1,56 @@
+This is a testharness.js-based test.
+Found 52 tests; 0 PASS, 52 FAIL, 0 TIMEOUT, 0 NOTRUN.
+FAIL margin-top auto(to) / values assert_not_equals: must not be target value after start got disallowed value "0px"
+FAIL margin-top auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "margin-top:0.5s" but got ""
+FAIL margin-top auto(from) / values assert_not_equals: must not be target value after start got disallowed value "13.3333px"
+FAIL margin-top auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "margin-top:0.5s" but got ""
+FAIL margin-right auto(to) / values assert_not_equals: must not be target value after start got disallowed value "0px"
+FAIL margin-right auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "margin-right:0.5s" but got ""
+FAIL margin-right auto(from) / values assert_not_equals: must not be target value after start got disallowed value "13.3333px"
+FAIL margin-right auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "margin-right:0.5s" but got ""
+FAIL margin-bottom auto(to) / values assert_not_equals: must not be target value after start got disallowed value "0px"
+FAIL margin-bottom auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "margin-bottom:0.5s" but got ""
+FAIL margin-bottom auto(from) / values assert_not_equals: must not be target value after start got disallowed value "13.3333px"
+FAIL margin-bottom auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "margin-bottom:0.5s" but got ""
+FAIL margin-left auto(to) / values assert_not_equals: must not be target value after start got disallowed value "0px"
+FAIL margin-left auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "margin-left:0.5s" but got ""
+FAIL margin-left auto(from) / values assert_not_equals: must not be target value after start got disallowed value "13.3333px"
+FAIL margin-left auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "margin-left:0.5s" but got ""
+FAIL height auto(to) / values assert_not_equals: must not be target value after start got disallowed value "20px"
+FAIL height auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "height:0.5s" but got ""
+FAIL height auto(from) / values assert_not_equals: must not be target value after start got disallowed value "13.3281px"
+FAIL height auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "height:0.5s" but got ""
+FAIL width auto(to) / values assert_not_equals: must not be target value after start got disallowed value "100px"
+FAIL width auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "width:0.5s" but got ""
+FAIL width auto(from) / values assert_not_equals: must not be target value after start got disallowed value "13.3281px"
+FAIL width auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "width:0.5s" but got ""
+FAIL clip auto(to) / values assert_not_equals: must not be target value after start got disallowed value "auto"
+FAIL clip auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "clip:0.5s" but got ""
+FAIL clip auto(from) / values assert_not_equals: must not be target value after start got disallowed value "rect(15px, 15px, 5px, 5px)"
+FAIL clip auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "clip:0.5s" but got ""
+FAIL marker-offset auto(to) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL marker-offset auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "marker-offset:0.5s" but got ""
+FAIL marker-offset auto(from) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL marker-offset auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "marker-offset:0.5s" but got ""
+FAIL top auto(to) / values assert_not_equals: must not be target value after start got disallowed value "0px"
+FAIL top auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "top:0.5s" but got ""
+FAIL top auto(from) / values assert_not_equals: must not be target value after start got disallowed value "13.3333px"
+FAIL top auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "top:0.5s" but got ""
+FAIL right auto(to) / values assert_not_equals: must not be target value after start got disallowed value "25px"
+FAIL right auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "right:0.5s" but got ""
+FAIL right auto(from) / values assert_not_equals: must not be target value after start got disallowed value "13.3333px"
+FAIL right auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "right:0.5s" but got ""
+FAIL left auto(to) / values assert_not_equals: must not be target value after start got disallowed value "0px"
+FAIL left auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "left:0.5s" but got ""
+FAIL left auto(from) / values assert_not_equals: must not be target value after start got disallowed value "13.3333px"
+FAIL left auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "left:0.5s" but got ""
+FAIL bottom auto(to) / values assert_not_equals: must not be target value after start got disallowed value "80px"
+FAIL bottom auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "bottom:0.5s" but got ""
+FAIL bottom auto(from) / values assert_not_equals: must not be target value after start got disallowed value "13.3333px"
+FAIL bottom auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "bottom:0.5s" but got ""
+FAIL z-index auto(to) / values assert_not_equals: must not be target value after start got disallowed value "auto"
+FAIL z-index auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "z-index:0.5s" but got ""
+FAIL z-index auto(from) / values assert_not_equals: must not be target value after start got disallowed value "10"
+FAIL z-index auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "z-index:0.5s" but got ""
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-mask-video-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-mask-video-expected.png
index 70aad4a..a2642e3 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-mask-video-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-mask-video-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-mask-video-ratio-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-mask-video-ratio-expected.png
index eea84cf..8a4d2fb 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-mask-video-ratio-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-mask-video-ratio-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-mask-video-shadow-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-mask-video-shadow-expected.png
index 3cc91f5..d0aef67 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-mask-video-shadow-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/borders/border-radius-mask-video-shadow-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/clip/nestedTransparencyClip-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/clip/nestedTransparencyClip-expected.png
index cd02ed7e..0b7f955d 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/clip/nestedTransparencyClip-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/clip/nestedTransparencyClip-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/css/ZeroOpacityLayers-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/css/ZeroOpacityLayers-expected.png
index c755bc45..1d9e55b 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/css/ZeroOpacityLayers-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/css/ZeroOpacityLayers-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/css/ZeroOpacityLayers2-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/css/ZeroOpacityLayers2-expected.png
index bb27c4c..c1a1fe2 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/css/ZeroOpacityLayers2-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/css/ZeroOpacityLayers2-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/layers/remove-layer-with-nested-stacking-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/layers/remove-layer-with-nested-stacking-expected.png
index d6dbea8..6b72702 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/layers/remove-layer-with-nested-stacking-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/layers/remove-layer-with-nested-stacking-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/multicol/composited-with-child-layer-in-next-column-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/multicol/composited-with-child-layer-in-next-column-expected.png
index b37a29b9..6e374f73 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/multicol/composited-with-child-layer-in-next-column-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/multicol/composited-with-child-layer-in-next-column-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/table/multiple-captions-display-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/table/multiple-captions-display-expected.png
index 4a1fff2..0ec5f7f3 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/table/multiple-captions-display-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/table/multiple-captions-display-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/text/complex-text-opacity-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/text/complex-text-opacity-expected.png
index 4c04dd97..1de7f90 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/text/complex-text-opacity-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/text/complex-text-opacity-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/hdr/video-canvas-alpha-expected.png b/third_party/WebKit/LayoutTests/platform/linux/hdr/video-canvas-alpha-expected.png
index f4230b7..f908ee7 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/hdr/video-canvas-alpha-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/hdr/video-canvas-alpha-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/http/tests/images/bmp-partial-load-expected.png b/third_party/WebKit/LayoutTests/platform/linux/http/tests/images/bmp-partial-load-expected.png
deleted file mode 100644
index f27f228..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/http/tests/images/bmp-partial-load-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/http/tests/images/gif-animated-partial-load-expected.png b/third_party/WebKit/LayoutTests/platform/linux/http/tests/images/gif-animated-partial-load-expected.png
deleted file mode 100644
index 92dcd244..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/http/tests/images/gif-animated-partial-load-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/http/tests/images/webp-partial-load-expected.png b/third_party/WebKit/LayoutTests/platform/linux/http/tests/images/webp-partial-load-expected.png
deleted file mode 100644
index 54ecd5a..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/http/tests/images/webp-partial-load-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/controls-after-reload-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/controls-after-reload-expected.png
index e65f6be..6d0fb747 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/media/controls-after-reload-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/media/controls-after-reload-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/controls-strict-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/controls-strict-expected.png
index 4a36e7ea..43974bc 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/media/controls-strict-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/media/controls-strict-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/controls-styling-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/controls-styling-expected.png
index 142d62aed..63af006 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/media/controls-styling-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/media/controls-styling-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/controls-styling-strict-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/controls-styling-strict-expected.png
index 0f5da75c..45e9a41 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/media/controls-styling-strict-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/media/controls-styling-strict-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/controls-without-preload-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/controls-without-preload-expected.png
index 719fbd97..b4b7d60 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/media/controls-without-preload-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/media/controls-without-preload-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/controls/video-controls-with-cast-rendering-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/controls/video-controls-with-cast-rendering-expected.png
index a2dbbef..b3bdfd8 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/media/controls/video-controls-with-cast-rendering-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/media/controls/video-controls-with-cast-rendering-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/controls/video-overlay-cast-dark-rendering-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/controls/video-overlay-cast-dark-rendering-expected.png
index a344c15f..57711ed 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/media/controls/video-overlay-cast-dark-rendering-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/media/controls/video-overlay-cast-dark-rendering-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/track/track-cue-rendering-horizontal-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/track/track-cue-rendering-horizontal-expected.png
index 3df7c7c..85feea95 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/media/track/track-cue-rendering-horizontal-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/media/track/track-cue-rendering-horizontal-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/track/track-cue-rendering-vertical-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/track/track-cue-rendering-vertical-expected.png
index 56c075d0..be234bc 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/media/track/track-cue-rendering-vertical-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/media/track/track-cue-rendering-vertical-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/video-aspect-ratio-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/video-aspect-ratio-expected.png
index 43fac98d..c882d43 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/media/video-aspect-ratio-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/media/video-aspect-ratio-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/video-canvas-alpha-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/video-canvas-alpha-expected.png
index 15149966..b883aeb 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/media/video-canvas-alpha-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/media/video-canvas-alpha-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/video-controls-rendering-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/video-controls-rendering-expected.png
index 73e8f5b..028d01ec 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/media/video-controls-rendering-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/media/video-controls-rendering-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/video-display-toggle-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/video-display-toggle-expected.png
index 1fbf430..cd565cd 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/media/video-display-toggle-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/media/video-display-toggle-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/video-layer-crash-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/video-layer-crash-expected.png
index 54a60f1..fd9d1b0 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/media/video-layer-crash-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/media/video-layer-crash-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/video-replaces-poster-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/video-replaces-poster-expected.png
index 1a76121..31a2fd2 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/media/video-replaces-poster-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/media/video-replaces-poster-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/video-transformed-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/video-transformed-expected.png
index 3c8f17e..2a1e8e9 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/media/video-transformed-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/media/video-transformed-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/video-zoom-controls-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/video-zoom-controls-expected.png
index a8f4e32..c9177ac 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/media/video-zoom-controls-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/media/video-zoom-controls-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/media/video-zoom-expected.png b/third_party/WebKit/LayoutTests/platform/linux/media/video-zoom-expected.png
index 484c5b1..16d50899 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/media/video-zoom-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/media/video-zoom-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/as-background-image/svg-as-background-6-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/as-background-image/svg-as-background-6-expected.png
index ff38505..c654d1ed 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/as-background-image/svg-as-background-6-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/as-background-image/svg-as-background-6-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/batik/text/textFeatures-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/batik/text/textFeatures-expected.png
index affb1a5..c35e016 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/batik/text/textFeatures-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/batik/text/textFeatures-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/text-image-opacity-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/custom/text-image-opacity-expected.png
index 935fff6..68e5189 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/custom/text-image-opacity-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/custom/text-image-opacity-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png
index e9fcef5..e5788ce 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.txt
index 7acd29999..e5149d4 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.txt
@@ -1,106 +1,106 @@
 layer at (0,0) size 800x600
   LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x348
-  LayoutBlockFlow {HTML} at (0,0) size 800x348.09
-    LayoutBlockFlow {BODY} at (5.55,5.55) size 788.91x337
-      LayoutTable {TABLE} at (0,0) size 464x337
-        LayoutTableSection {TBODY} at (0,0) size 464x337
-          LayoutTableRow {TR} at (0,1) size 464x15
-            LayoutTableCell {TH} at (1,1) size 65x15.38 [bgcolor=#DDDD99] [r=0 c=0 rs=1 cs=1]
-              LayoutText {#text} at (6,0) size 53x15
+layer at (0,0) size 800x339
+  LayoutBlockFlow {HTML} at (0,0) size 800x339.09
+    LayoutBlockFlow {BODY} at (5.55,5.55) size 788.91x328
+      LayoutTable {TABLE} at (0,0) size 464x328
+        LayoutTableSection {TBODY} at (0,0) size 464x328
+          LayoutTableRow {TR} at (0,1) size 464x14
+            LayoutTableCell {TH} at (1,1) size 65x14 [bgcolor=#DDDD99] [r=0 c=0 rs=1 cs=1]
+              LayoutText {#text} at (6,0) size 53x14
                 text run at (6,0) width 53: "viewBox?"
-            LayoutTableCell {TH} at (67,1) size 112x15.38 [bgcolor=#DDDD99] [r=0 c=1 rs=1 cs=1]
-              LayoutText {#text} at (1,0) size 110x15
+            LayoutTableCell {TH} at (67,1) size 112x14 [bgcolor=#DDDD99] [r=0 c=1 rs=1 cs=1]
+              LayoutText {#text} at (1,0) size 110x14
                 text run at (1,0) width 110: "preserve\x{AD}Aspect\x{AD}Ratio"
-            LayoutTableCell {TH} at (180,1) size 141x15.38 [bgcolor=#DDDD99] [r=0 c=2 rs=1 cs=1]
-              LayoutText {#text} at (54,0) size 33x15
+            LayoutTableCell {TH} at (180,1) size 141x14 [bgcolor=#DDDD99] [r=0 c=2 rs=1 cs=1]
+              LayoutText {#text} at (54,0) size 33x14
                 text run at (54,0) width 33: "<img>"
-            LayoutTableCell {TH} at (322,1) size 141x15.38 [bgcolor=#DDDD99] [r=0 c=3 rs=1 cs=1]
-              LayoutText {#text} at (48,0) size 45x15
+            LayoutTableCell {TH} at (322,1) size 141x14 [bgcolor=#DDDD99] [r=0 c=3 rs=1 cs=1]
+              LayoutText {#text} at (48,0) size 45x14
                 text run at (48,0) width 45: "<object>"
-          LayoutTableRow {TR} at (0,17) size 464x39
-            LayoutTableCell {TH} at (1,89) size 65x15.38 [bgcolor=#DDDD99] [r=1 c=0 rs=4 cs=1]
-              LayoutText {#text} at (1,0) size 63x15
+          LayoutTableRow {TR} at (0,16) size 464x38
+            LayoutTableCell {TH} at (1,86) size 65x14 [bgcolor=#DDDD99] [r=1 c=0 rs=4 cs=1]
+              LayoutText {#text} at (1,0) size 63x14
                 text run at (1,0) width 63: "No viewBox"
-            LayoutTableCell {TH} at (67,36) size 112x1.38 [bgcolor=#DDDD99] [r=1 c=1 rs=1 cs=1]
-            LayoutTableCell {TD} at (180,17) size 141x39.09 [r=1 c=2 rs=1 cs=1]
-              LayoutImage {IMG} at (0.69,0.69) size 138.88x34.72 [border: (1.38px dashed #800000)]
+            LayoutTableCell {TH} at (67,35) size 112x0 [bgcolor=#DDDD99] [r=1 c=1 rs=1 cs=1]
+            LayoutTableCell {TD} at (180,16) size 141x37.72 [r=1 c=2 rs=1 cs=1]
+              LayoutImage {IMG} at (0.69,0) size 138.88x34.72 [border: (1.38px dashed #800000)]
               LayoutText {#text} at (0,0) size 0x0
-            LayoutTableCell {TD} at (322,17) size 141x39.09 [r=1 c=3 rs=1 cs=1]
+            LayoutTableCell {TD} at (322,16) size 141x37.72 [r=1 c=3 rs=1 cs=1]
               LayoutText {#text} at (0,0) size 0x0
-          LayoutTableRow {TR} at (0,57) size 464x39
-            LayoutTableCell {TH} at (67,69) size 112x15.38 [bgcolor=#DDDD99] [r=2 c=1 rs=1 cs=1]
-              LayoutText {#text} at (42,0) size 28x15
+          LayoutTableRow {TR} at (0,55) size 464x38
+            LayoutTableCell {TH} at (67,67) size 112x14 [bgcolor=#DDDD99] [r=2 c=1 rs=1 cs=1]
+              LayoutText {#text} at (42,0) size 28x14
                 text run at (42,0) width 28: "none"
-            LayoutTableCell {TD} at (180,57) size 141x39.09 [r=2 c=2 rs=1 cs=1]
-              LayoutImage {IMG} at (0.69,0.69) size 138.88x34.72 [border: (1.38px dashed #800000)]
+            LayoutTableCell {TD} at (180,55) size 141x37.72 [r=2 c=2 rs=1 cs=1]
+              LayoutImage {IMG} at (0.69,0) size 138.88x34.72 [border: (1.38px dashed #800000)]
               LayoutText {#text} at (0,0) size 0x0
-            LayoutTableCell {TD} at (322,57) size 141x39.09 [r=2 c=3 rs=1 cs=1]
+            LayoutTableCell {TD} at (322,55) size 141x37.72 [r=2 c=3 rs=1 cs=1]
               LayoutText {#text} at (0,0) size 0x0
-          LayoutTableRow {TR} at (0,97) size 464x39
-            LayoutTableCell {TH} at (67,109) size 112x15.38 [bgcolor=#DDDD99] [r=3 c=1 rs=1 cs=1]
-              LayoutText {#text} at (43,0) size 26x15
+          LayoutTableRow {TR} at (0,94) size 464x38
+            LayoutTableCell {TH} at (67,106) size 112x14 [bgcolor=#DDDD99] [r=3 c=1 rs=1 cs=1]
+              LayoutText {#text} at (43,0) size 26x14
                 text run at (43,0) width 26: "meet"
-            LayoutTableCell {TD} at (180,97) size 141x39.09 [r=3 c=2 rs=1 cs=1]
-              LayoutImage {IMG} at (0.69,0.69) size 138.88x34.72 [border: (1.38px dashed #800000)]
+            LayoutTableCell {TD} at (180,94) size 141x37.72 [r=3 c=2 rs=1 cs=1]
+              LayoutImage {IMG} at (0.69,0) size 138.88x34.72 [border: (1.38px dashed #800000)]
               LayoutText {#text} at (0,0) size 0x0
-            LayoutTableCell {TD} at (322,97) size 141x39.09 [r=3 c=3 rs=1 cs=1]
+            LayoutTableCell {TD} at (322,94) size 141x37.72 [r=3 c=3 rs=1 cs=1]
               LayoutText {#text} at (0,0) size 0x0
-          LayoutTableRow {TR} at (0,137) size 464x39
-            LayoutTableCell {TH} at (67,149) size 112x15.38 [bgcolor=#DDDD99] [r=4 c=1 rs=1 cs=1]
-              LayoutText {#text} at (44,0) size 24x15
+          LayoutTableRow {TR} at (0,133) size 464x38
+            LayoutTableCell {TH} at (67,145) size 112x14 [bgcolor=#DDDD99] [r=4 c=1 rs=1 cs=1]
+              LayoutText {#text} at (44,0) size 24x14
                 text run at (44,0) width 24: "slice"
-            LayoutTableCell {TD} at (180,137) size 141x39.09 [r=4 c=2 rs=1 cs=1]
-              LayoutImage {IMG} at (0.69,0.69) size 138.88x34.72 [border: (1.38px dashed #800000)]
+            LayoutTableCell {TD} at (180,133) size 141x37.72 [r=4 c=2 rs=1 cs=1]
+              LayoutImage {IMG} at (0.69,0) size 138.88x34.72 [border: (1.38px dashed #800000)]
               LayoutText {#text} at (0,0) size 0x0
-            LayoutTableCell {TD} at (322,137) size 141x39.09 [r=4 c=3 rs=1 cs=1]
+            LayoutTableCell {TD} at (322,133) size 141x37.72 [r=4 c=3 rs=1 cs=1]
               LayoutText {#text} at (0,0) size 0x0
-          LayoutTableRow {TR} at (0,177) size 464x39
-            LayoutTableCell {TH} at (1,249) size 65x15.38 [bgcolor=#DDDD99] [r=5 c=0 rs=4 cs=1]
-              LayoutText {#text} at (10,0) size 45x15
+          LayoutTableRow {TR} at (0,172) size 464x38
+            LayoutTableCell {TH} at (1,242) size 65x14 [bgcolor=#DDDD99] [r=5 c=0 rs=4 cs=1]
+              LayoutText {#text} at (10,0) size 45x14
                 text run at (10,0) width 45: "viewBox"
-            LayoutTableCell {TH} at (67,196) size 112x1.38 [bgcolor=#DDDD99] [r=5 c=1 rs=1 cs=1]
-            LayoutTableCell {TD} at (180,177) size 141x39.09 [r=5 c=2 rs=1 cs=1]
-              LayoutImage {IMG} at (0.69,0.69) size 138.88x34.72 [border: (1.38px dashed #800000)]
+            LayoutTableCell {TH} at (67,191) size 112x0 [bgcolor=#DDDD99] [r=5 c=1 rs=1 cs=1]
+            LayoutTableCell {TD} at (180,172) size 141x37.72 [r=5 c=2 rs=1 cs=1]
+              LayoutImage {IMG} at (0.69,0) size 138.88x34.72 [border: (1.38px dashed #800000)]
               LayoutText {#text} at (0,0) size 0x0
-            LayoutTableCell {TD} at (322,177) size 141x39.09 [r=5 c=3 rs=1 cs=1]
+            LayoutTableCell {TD} at (322,172) size 141x37.72 [r=5 c=3 rs=1 cs=1]
               LayoutText {#text} at (0,0) size 0x0
-          LayoutTableRow {TR} at (0,217) size 464x39
-            LayoutTableCell {TH} at (67,229) size 112x15.38 [bgcolor=#DDDD99] [r=6 c=1 rs=1 cs=1]
-              LayoutText {#text} at (42,0) size 28x15
+          LayoutTableRow {TR} at (0,211) size 464x38
+            LayoutTableCell {TH} at (67,223) size 112x14 [bgcolor=#DDDD99] [r=6 c=1 rs=1 cs=1]
+              LayoutText {#text} at (42,0) size 28x14
                 text run at (42,0) width 28: "none"
-            LayoutTableCell {TD} at (180,217) size 141x39.09 [r=6 c=2 rs=1 cs=1]
-              LayoutImage {IMG} at (0.69,0.69) size 138.88x34.72 [border: (1.38px dashed #800000)]
+            LayoutTableCell {TD} at (180,211) size 141x37.72 [r=6 c=2 rs=1 cs=1]
+              LayoutImage {IMG} at (0.69,0) size 138.88x34.72 [border: (1.38px dashed #800000)]
               LayoutText {#text} at (0,0) size 0x0
-            LayoutTableCell {TD} at (322,217) size 141x39.09 [r=6 c=3 rs=1 cs=1]
+            LayoutTableCell {TD} at (322,211) size 141x37.72 [r=6 c=3 rs=1 cs=1]
               LayoutText {#text} at (0,0) size 0x0
-          LayoutTableRow {TR} at (0,257) size 464x39
-            LayoutTableCell {TH} at (67,269) size 112x15.38 [bgcolor=#DDDD99] [r=7 c=1 rs=1 cs=1]
-              LayoutText {#text} at (43,0) size 26x15
+          LayoutTableRow {TR} at (0,250) size 464x38
+            LayoutTableCell {TH} at (67,262) size 112x14 [bgcolor=#DDDD99] [r=7 c=1 rs=1 cs=1]
+              LayoutText {#text} at (43,0) size 26x14
                 text run at (43,0) width 26: "meet"
-            LayoutTableCell {TD} at (180,257) size 141x39.09 [r=7 c=2 rs=1 cs=1]
-              LayoutImage {IMG} at (0.69,0.69) size 138.88x34.72 [border: (1.38px dashed #800000)]
+            LayoutTableCell {TD} at (180,250) size 141x37.72 [r=7 c=2 rs=1 cs=1]
+              LayoutImage {IMG} at (0.69,0) size 138.88x34.72 [border: (1.38px dashed #800000)]
               LayoutText {#text} at (0,0) size 0x0
-            LayoutTableCell {TD} at (322,257) size 141x39.09 [r=7 c=3 rs=1 cs=1]
+            LayoutTableCell {TD} at (322,250) size 141x37.72 [r=7 c=3 rs=1 cs=1]
               LayoutText {#text} at (0,0) size 0x0
-          LayoutTableRow {TR} at (0,297) size 464x39
-            LayoutTableCell {TH} at (67,309) size 112x15.38 [bgcolor=#DDDD99] [r=8 c=1 rs=1 cs=1]
-              LayoutText {#text} at (44,0) size 24x15
+          LayoutTableRow {TR} at (0,289) size 464x38
+            LayoutTableCell {TH} at (67,301) size 112x14 [bgcolor=#DDDD99] [r=8 c=1 rs=1 cs=1]
+              LayoutText {#text} at (44,0) size 24x14
                 text run at (44,0) width 24: "slice"
-            LayoutTableCell {TD} at (180,297) size 141x39.09 [r=8 c=2 rs=1 cs=1]
-              LayoutImage {IMG} at (0.69,0.69) size 138.88x34.72 [border: (1.38px dashed #800000)]
+            LayoutTableCell {TD} at (180,289) size 141x37.72 [r=8 c=2 rs=1 cs=1]
+              LayoutImage {IMG} at (0.69,0) size 138.88x34.72 [border: (1.38px dashed #800000)]
               LayoutText {#text} at (0,0) size 0x0
-            LayoutTableCell {TD} at (322,297) size 141x39.09 [r=8 c=3 rs=1 cs=1]
+            LayoutTableCell {TD} at (322,289) size 141x37.72 [r=8 c=3 rs=1 cs=1]
               LayoutText {#text} at (0,0) size 0x0
-layer at (328,23) size 139x34
-  LayoutEmbeddedObject {OBJECT} at (0.69,0.69) size 138.88x34.72 [border: (0.69px dashed #008000)]
+layer at (328,22) size 139x35
+  LayoutEmbeddedObject {OBJECT} at (0.69,0) size 138.88x34.72 [border: (0.69px dashed #008000)]
     layer at (0,0) size 133x29
       LayoutView at (0,0) size 133x29
     layer at (0,0) size 133x29
       LayoutSVGRoot {svg} at (0,0) size 133x29
         LayoutSVGEllipse {circle} at (0,0) size 220x220 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#D9BB7A] [fill rule=EVEN-ODD]}] [cx=110.00] [cy=110.00] [r=110.00]
-layer at (328,63) size 139x34
-  LayoutEmbeddedObject {OBJECT} at (0.69,0.69) size 138.88x34.72 [border: (0.69px dashed #008000)]
+layer at (328,61) size 139x35
+  LayoutEmbeddedObject {OBJECT} at (0.69,0) size 138.88x34.72 [border: (0.69px dashed #008000)]
     layer at (0,0) size 133x29
       LayoutView at (0,0) size 133x29
     layer at (0,0) size 133x29
@@ -108,8 +108,8 @@
         LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
         LayoutSVGContainer {g} at (162.86,403.79) size 362.86x362.86 [transform={m=((1.00,0.00)(0.00,1.00)) t=(-162.36,-403.29)}]
           LayoutSVGPath {path} at (162.86,403.79) size 362.86x362.86 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#D9BB7A] [fill rule=EVEN-ODD]}] [data="M 525.714 585.219 A 181.429 181.429 0 1 1 162.857 585.219 A 181.429 181.429 0 1 1 525.714 585.219 Z"]
-layer at (328,103) size 139x34
-  LayoutEmbeddedObject {OBJECT} at (0.69,0.69) size 138.88x34.72 [border: (0.69px dashed #008000)]
+layer at (328,100) size 139x35
+  LayoutEmbeddedObject {OBJECT} at (0.69,0) size 138.88x34.72 [border: (0.69px dashed #008000)]
     layer at (0,0) size 133x29
       LayoutView at (0,0) size 133x29
     layer at (0,0) size 133x29
@@ -117,8 +117,8 @@
         LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
         LayoutSVGContainer {g} at (162.86,403.79) size 362.86x362.86 [transform={m=((1.00,0.00)(0.00,1.00)) t=(-162.36,-403.29)}]
           LayoutSVGPath {path} at (162.86,403.79) size 362.86x362.86 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#D9BB7A] [fill rule=EVEN-ODD]}] [data="M 525.714 585.219 A 181.429 181.429 0 1 1 162.857 585.219 A 181.429 181.429 0 1 1 525.714 585.219 Z"]
-layer at (328,143) size 139x34
-  LayoutEmbeddedObject {OBJECT} at (0.69,0.69) size 138.88x34.72 [border: (0.69px dashed #008000)]
+layer at (328,139) size 139x35
+  LayoutEmbeddedObject {OBJECT} at (0.69,0) size 138.88x34.72 [border: (0.69px dashed #008000)]
     layer at (0,0) size 133x29
       LayoutView at (0,0) size 133x29
     layer at (0,0) size 133x29
@@ -126,8 +126,8 @@
         LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
         LayoutSVGContainer {g} at (162.86,403.79) size 362.86x362.86 [transform={m=((1.00,0.00)(0.00,1.00)) t=(-162.36,-403.29)}]
           LayoutSVGPath {path} at (162.86,403.79) size 362.86x362.86 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#D9BB7A] [fill rule=EVEN-ODD]}] [data="M 525.714 585.219 A 181.429 181.429 0 1 1 162.857 585.219 A 181.429 181.429 0 1 1 525.714 585.219 Z"]
-layer at (328,183) size 139x34
-  LayoutEmbeddedObject {OBJECT} at (0.69,0.69) size 138.88x34.72 [border: (0.69px dashed #008000)]
+layer at (328,178) size 139x35
+  LayoutEmbeddedObject {OBJECT} at (0.69,0) size 138.88x34.72 [border: (0.69px dashed #008000)]
     layer at (0,0) size 133x29
       LayoutView at (0,0) size 133x29
     layer at (0,0) size 133x29
@@ -135,8 +135,8 @@
         LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
         LayoutSVGContainer {g} at (162.86,403.79) size 362.86x362.86 [transform={m=((1.00,0.00)(0.00,1.00)) t=(-162.36,-403.29)}]
           LayoutSVGPath {path} at (162.86,403.79) size 362.86x362.86 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#D9BB7A] [fill rule=EVEN-ODD]}] [data="M 525.714 585.219 A 181.429 181.429 0 1 1 162.857 585.219 A 181.429 181.429 0 1 1 525.714 585.219 Z"]
-layer at (328,223) size 139x34
-  LayoutEmbeddedObject {OBJECT} at (0.69,0.69) size 138.88x34.72 [border: (0.69px dashed #008000)]
+layer at (328,217) size 139x35
+  LayoutEmbeddedObject {OBJECT} at (0.69,0) size 138.88x34.72 [border: (0.69px dashed #008000)]
     layer at (0,0) size 133x29
       LayoutView at (0,0) size 133x29
     layer at (0,0) size 133x29
@@ -144,8 +144,8 @@
         LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
         LayoutSVGContainer {g} at (162.86,403.79) size 362.86x362.86 [transform={m=((1.00,0.00)(0.00,1.00)) t=(-162.36,-403.29)}]
           LayoutSVGPath {path} at (162.86,403.79) size 362.86x362.86 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#D9BB7A] [fill rule=EVEN-ODD]}] [data="M 525.714 585.219 A 181.429 181.429 0 1 1 162.857 585.219 A 181.429 181.429 0 1 1 525.714 585.219 Z"]
-layer at (328,263) size 139x34
-  LayoutEmbeddedObject {OBJECT} at (0.69,0.69) size 138.88x34.72 [border: (0.69px dashed #008000)]
+layer at (328,256) size 139x35
+  LayoutEmbeddedObject {OBJECT} at (0.69,0) size 138.88x34.72 [border: (0.69px dashed #008000)]
     layer at (0,0) size 133x29
       LayoutView at (0,0) size 133x29
     layer at (0,0) size 133x29
@@ -153,8 +153,8 @@
         LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
         LayoutSVGContainer {g} at (162.86,403.79) size 362.86x362.86 [transform={m=((1.00,0.00)(0.00,1.00)) t=(-162.36,-403.29)}]
           LayoutSVGPath {path} at (162.86,403.79) size 362.86x362.86 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#D9BB7A] [fill rule=EVEN-ODD]}] [data="M 525.714 585.219 A 181.429 181.429 0 1 1 162.857 585.219 A 181.429 181.429 0 1 1 525.714 585.219 Z"]
-layer at (328,303) size 139x34
-  LayoutEmbeddedObject {OBJECT} at (0.69,0.69) size 138.88x34.72 [border: (0.69px dashed #008000)]
+layer at (328,295) size 139x35
+  LayoutEmbeddedObject {OBJECT} at (0.69,0) size 138.88x34.72 [border: (0.69px dashed #008000)]
     layer at (0,0) size 133x29
       LayoutView at (0,0) size 133x29
     layer at (0,0) size 133x29
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-svg-through-object-with-absolute-size-2-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-svg-through-object-with-absolute-size-2-expected.png
index f23e3ec2..9e86f385 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-svg-through-object-with-absolute-size-2-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-svg-through-object-with-absolute-size-2-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-svg-through-object-with-absolute-size-2-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-svg-through-object-with-absolute-size-2-expected.txt
index 0df6a6c..9bb190e 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-svg-through-object-with-absolute-size-2-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-svg-through-object-with-absolute-size-2-expected.txt
@@ -1,34 +1,34 @@
 layer at (0,0) size 800x600
   LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x205
-  LayoutBlockFlow {html} at (0,0) size 800x205.09
-    LayoutBlockFlow {body} at (5.55,5.55) size 788.91x194
-      LayoutTable {table} at (141.45,0) size 506x194
-        LayoutTableSection (anonymous) at (0,0) size 506x194
-          LayoutTableRow {tr} at (0,0) size 506x194
-            LayoutTableCell {td} at (0,0) size 506x193.88 [r=0 c=0 rs=1 cs=3]
-              LayoutTable {table} at (7,6.94) size 492x180
-                LayoutTableSection (anonymous) at (0,0) size 492x180
-                  LayoutTableRow {tr} at (0,1) size 492x67
-                    LayoutTableCell {td} at (1,1) size 490x66.84 [r=0 c=0 rs=1 cs=2]
-                      LayoutBlockFlow {h1} at (5.55,20.42) size 478.91x26
+layer at (0,0) size 800x199
+  LayoutBlockFlow {html} at (0,0) size 800x199.09
+    LayoutBlockFlow {body} at (5.55,5.55) size 788.91x188
+      LayoutTable {table} at (141.45,0) size 506x188
+        LayoutTableSection (anonymous) at (0,0) size 506x188
+          LayoutTableRow {tr} at (0,0) size 506x188
+            LayoutTableCell {td} at (0,0) size 506x188 [r=0 c=0 rs=1 cs=3]
+              LayoutTable {table} at (7,6) size 492x176
+                LayoutTableSection (anonymous) at (0,0) size 492x176
+                  LayoutTableRow {tr} at (0,1) size 492x66
+                    LayoutTableCell {td} at (1,1) size 490x65.75 [r=0 c=0 rs=1 cs=2]
+                      LayoutBlockFlow {h1} at (5.55,19.88) size 478.91x26
                         LayoutText {#text} at (0,0) size 479x25
                           text run at (0,0) width 479: "Both sides should have identical size after zooming"
-                  LayoutTableRow {tr} at (0,69) size 492x25
-                    LayoutTableCell {td} at (1,69) size 244x25.09 [r=1 c=0 rs=1 cs=1]
-                      LayoutText {#text} at (95,5) size 54x15
+                  LayoutTableRow {tr} at (0,68) size 492x24
+                    LayoutTableCell {td} at (1,68) size 244x24 [r=1 c=0 rs=1 cs=1]
+                      LayoutText {#text} at (95,5) size 54x14
                         text run at (95,5) width 54: "SVG Image"
-                    LayoutTableCell {td} at (246,69) size 245x25.09 [r=1 c=1 rs=1 cs=1]
-                      LayoutText {#text} at (95,5) size 55x15
+                    LayoutTableCell {td} at (246,68) size 245x24 [r=1 c=1 rs=1 cs=1]
+                      LayoutText {#text} at (95,5) size 55x14
                         text run at (95,5) width 55: "PNG Image"
-                  LayoutTableRow {tr} at (0,95) size 492x84
-                    LayoutTableCell {td} at (1,95) size 244x83.53 [r=2 c=0 rs=1 cs=1]
+                  LayoutTableRow {tr} at (0,93) size 492x82
+                    LayoutTableCell {td} at (1,93) size 244x82.44 [r=2 c=0 rs=1 cs=1]
                       LayoutText {#text} at (0,0) size 0x0
-                    LayoutTableCell {td} at (246,95) size 245x83.53 [r=2 c=1 rs=1 cs=1]
-                      LayoutImage {img} at (5.55,5.55) size 138.88x69.44
+                    LayoutTableCell {td} at (246,93) size 245x82.44 [r=2 c=1 rs=1 cs=1]
+                      LayoutImage {img} at (5.55,5) size 138.88x69.44
                       LayoutText {#text} at (0,0) size 0x0
-layer at (255,113) size 138x69
-  LayoutEmbeddedObject {object} at (99.58,5.55) size 138.88x69.44
+layer at (255,110) size 138x69
+  LayoutEmbeddedObject {object} at (99.58,5) size 138.88x69.44
     layer at (0,0) size 139x69
       LayoutView at (0,0) size 139x69
     layer at (0,0) size 139x69
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-svg-through-object-with-absolute-size-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-svg-through-object-with-absolute-size-expected.png
index f23e3ec2..9e86f385 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-svg-through-object-with-absolute-size-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-svg-through-object-with-absolute-size-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-svg-through-object-with-absolute-size-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-svg-through-object-with-absolute-size-expected.txt
index 0df6a6c..9bb190e 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-svg-through-object-with-absolute-size-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-svg-through-object-with-absolute-size-expected.txt
@@ -1,34 +1,34 @@
 layer at (0,0) size 800x600
   LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x205
-  LayoutBlockFlow {html} at (0,0) size 800x205.09
-    LayoutBlockFlow {body} at (5.55,5.55) size 788.91x194
-      LayoutTable {table} at (141.45,0) size 506x194
-        LayoutTableSection (anonymous) at (0,0) size 506x194
-          LayoutTableRow {tr} at (0,0) size 506x194
-            LayoutTableCell {td} at (0,0) size 506x193.88 [r=0 c=0 rs=1 cs=3]
-              LayoutTable {table} at (7,6.94) size 492x180
-                LayoutTableSection (anonymous) at (0,0) size 492x180
-                  LayoutTableRow {tr} at (0,1) size 492x67
-                    LayoutTableCell {td} at (1,1) size 490x66.84 [r=0 c=0 rs=1 cs=2]
-                      LayoutBlockFlow {h1} at (5.55,20.42) size 478.91x26
+layer at (0,0) size 800x199
+  LayoutBlockFlow {html} at (0,0) size 800x199.09
+    LayoutBlockFlow {body} at (5.55,5.55) size 788.91x188
+      LayoutTable {table} at (141.45,0) size 506x188
+        LayoutTableSection (anonymous) at (0,0) size 506x188
+          LayoutTableRow {tr} at (0,0) size 506x188
+            LayoutTableCell {td} at (0,0) size 506x188 [r=0 c=0 rs=1 cs=3]
+              LayoutTable {table} at (7,6) size 492x176
+                LayoutTableSection (anonymous) at (0,0) size 492x176
+                  LayoutTableRow {tr} at (0,1) size 492x66
+                    LayoutTableCell {td} at (1,1) size 490x65.75 [r=0 c=0 rs=1 cs=2]
+                      LayoutBlockFlow {h1} at (5.55,19.88) size 478.91x26
                         LayoutText {#text} at (0,0) size 479x25
                           text run at (0,0) width 479: "Both sides should have identical size after zooming"
-                  LayoutTableRow {tr} at (0,69) size 492x25
-                    LayoutTableCell {td} at (1,69) size 244x25.09 [r=1 c=0 rs=1 cs=1]
-                      LayoutText {#text} at (95,5) size 54x15
+                  LayoutTableRow {tr} at (0,68) size 492x24
+                    LayoutTableCell {td} at (1,68) size 244x24 [r=1 c=0 rs=1 cs=1]
+                      LayoutText {#text} at (95,5) size 54x14
                         text run at (95,5) width 54: "SVG Image"
-                    LayoutTableCell {td} at (246,69) size 245x25.09 [r=1 c=1 rs=1 cs=1]
-                      LayoutText {#text} at (95,5) size 55x15
+                    LayoutTableCell {td} at (246,68) size 245x24 [r=1 c=1 rs=1 cs=1]
+                      LayoutText {#text} at (95,5) size 55x14
                         text run at (95,5) width 55: "PNG Image"
-                  LayoutTableRow {tr} at (0,95) size 492x84
-                    LayoutTableCell {td} at (1,95) size 244x83.53 [r=2 c=0 rs=1 cs=1]
+                  LayoutTableRow {tr} at (0,93) size 492x82
+                    LayoutTableCell {td} at (1,93) size 244x82.44 [r=2 c=0 rs=1 cs=1]
                       LayoutText {#text} at (0,0) size 0x0
-                    LayoutTableCell {td} at (246,95) size 245x83.53 [r=2 c=1 rs=1 cs=1]
-                      LayoutImage {img} at (5.55,5.55) size 138.88x69.44
+                    LayoutTableCell {td} at (246,93) size 245x82.44 [r=2 c=1 rs=1 cs=1]
+                      LayoutImage {img} at (5.55,5) size 138.88x69.44
                       LayoutText {#text} at (0,0) size 0x0
-layer at (255,113) size 138x69
-  LayoutEmbeddedObject {object} at (99.58,5.55) size 138.88x69.44
+layer at (255,110) size 138x69
+  LayoutEmbeddedObject {object} at (99.58,5) size 138.88x69.44
     layer at (0,0) size 139x69
       LayoutView at (0,0) size 139x69
     layer at (0,0) size 139x69
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-svg-through-object-with-percentage-size-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-svg-through-object-with-percentage-size-expected.png
index fa921587f..e0c7e61 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-svg-through-object-with-percentage-size-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-svg-through-object-with-percentage-size-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-svg-through-object-with-percentage-size-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-svg-through-object-with-percentage-size-expected.txt
index 24eafaf..d5e446860 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-svg-through-object-with-percentage-size-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/zoom/page/zoom-svg-through-object-with-percentage-size-expected.txt
@@ -1,34 +1,34 @@
 layer at (0,0) size 800x600
   LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x385
-  LayoutBlockFlow {html} at (0,0) size 800x385.09
-    LayoutBlockFlow {body} at (5.55,5.55) size 788.91x374
-      LayoutTable {table} at (40.95,0) size 707x374
-        LayoutTableSection (anonymous) at (0,0) size 707x374
-          LayoutTableRow {tr} at (0,0) size 707x374
-            LayoutTableCell {td} at (0,0) size 707x373.88 [r=0 c=0 rs=1 cs=3]
-              LayoutTable {table} at (7,6.94) size 693x360
-                LayoutTableSection (anonymous) at (0,0) size 693x360
-                  LayoutTableRow {tr} at (0,1) size 693x67
-                    LayoutTableCell {td} at (1,1) size 691x66.84 [r=0 c=0 rs=1 cs=2]
-                      LayoutBlockFlow {h1} at (5.55,20.42) size 679.91x26
+layer at (0,0) size 800x380
+  LayoutBlockFlow {html} at (0,0) size 800x380.09
+    LayoutBlockFlow {body} at (5.55,5.55) size 788.91x369
+      LayoutTable {table} at (40.95,0) size 707x369
+        LayoutTableSection (anonymous) at (0,0) size 707x369
+          LayoutTableRow {tr} at (0,0) size 707x369
+            LayoutTableCell {td} at (0,0) size 707x369 [r=0 c=0 rs=1 cs=3]
+              LayoutTable {table} at (7,6) size 693x357
+                LayoutTableSection (anonymous) at (0,0) size 693x357
+                  LayoutTableRow {tr} at (0,1) size 693x66
+                    LayoutTableCell {td} at (1,1) size 691x65.75 [r=0 c=0 rs=1 cs=2]
+                      LayoutBlockFlow {h1} at (5.55,19.88) size 679.91x26
                         LayoutText {#text} at (100,0) size 479x25
                           text run at (100,0) width 479: "Both sides should have identical size after zooming"
-                  LayoutTableRow {tr} at (0,69) size 693x25
-                    LayoutTableCell {td} at (1,69) size 345x25.09 [r=1 c=0 rs=1 cs=1]
-                      LayoutText {#text} at (145,5) size 55x15
+                  LayoutTableRow {tr} at (0,68) size 693x24
+                    LayoutTableCell {td} at (1,68) size 345x24 [r=1 c=0 rs=1 cs=1]
+                      LayoutText {#text} at (145,5) size 55x14
                         text run at (145,5) width 55: "SVG Image"
-                    LayoutTableCell {td} at (347,69) size 345x25.09 [r=1 c=1 rs=1 cs=1]
-                      LayoutText {#text} at (145,5) size 55x15
+                    LayoutTableCell {td} at (347,68) size 345x24 [r=1 c=1 rs=1 cs=1]
+                      LayoutText {#text} at (145,5) size 55x14
                         text run at (145,5) width 55: "PNG Image"
-                  LayoutTableRow {tr} at (0,95) size 693x264
-                    LayoutTableCell {td} at (1,95) size 345x264.08 [r=2 c=0 rs=1 cs=1]
+                  LayoutTableRow {tr} at (0,93) size 693x263
+                    LayoutTableCell {td} at (1,93) size 345x262.98 [r=2 c=0 rs=1 cs=1]
                       LayoutText {#text} at (0,0) size 0x0
-                    LayoutTableCell {td} at (347,95) size 345x264.06 [r=2 c=1 rs=1 cs=1]
-                      LayoutImage {img} at (5.55,5.55) size 333.33x249.97
+                    LayoutTableCell {td} at (347,93) size 345x262.97 [r=2 c=1 rs=1 cs=1]
+                      LayoutImage {img} at (5.55,5) size 333.33x249.97
                       LayoutText {#text} at (0,0) size 0x0
-layer at (61,113) size 333x250
-  LayoutEmbeddedObject {object} at (6.13,5.55) size 333.33x249.98
+layer at (61,110) size 333x250
+  LayoutEmbeddedObject {object} at (6.13,5) size 333.33x249.98
     layer at (0,0) size 333x250
       LayoutView at (0,0) size 333x250
     layer at (0,0) size 333x250
diff --git a/third_party/WebKit/LayoutTests/platform/linux/transforms/2d/hindi-rotated-expected.png b/third_party/WebKit/LayoutTests/platform/linux/transforms/2d/hindi-rotated-expected.png
index 9958b5d..509cb8b 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/transforms/2d/hindi-rotated-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/transforms/2d/hindi-rotated-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/transforms/bounding-rect-zoom-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/transforms/bounding-rect-zoom-expected.txt
index 0f29e50b..de37ce79 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/transforms/bounding-rect-zoom-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/transforms/bounding-rect-zoom-expected.txt
@@ -9,14 +9,14 @@
         LayoutBR {BR} at (301,13) size 0x0
         LayoutText {#text} at (0,17) size 176x16
           text run at (0,17) width 176: "There should be no red visible."
-      LayoutTable {TABLE} at (0,48.39) size 785x21
-        LayoutTableSection {TBODY} at (0,0) size 785x21
-          LayoutTableRow {TR} at (0,1) size 785x19
-            LayoutTableCell {TD} at (1,1) size 181x18.78 [r=0 c=0 rs=1 cs=1]
-              LayoutText {#text} at (0,0) size 146x17
+      LayoutTable {TABLE} at (0,48.39) size 785x19
+        LayoutTableSection {TBODY} at (0,0) size 785x19
+          LayoutTableRow {TR} at (0,1) size 785x17
+            LayoutTableCell {TD} at (1,1) size 181x17 [r=0 c=0 rs=1 cs=1]
+              LayoutText {#text} at (0,0) size 146x16
                 text run at (0,0) width 146: "getClientBoundingRect():"
-            LayoutTableCell {TD} at (183,1) size 601x18.78 [r=0 c=1 rs=1 cs=1]
-              LayoutText {#text} at (0,0) size 96x17
+            LayoutTableCell {TD} at (183,1) size 601x17 [r=0 c=1 rs=1 cs=1]
+              LayoutText {#text} at (0,0) size 96x16
                 text run at (0,0) width 96: "getClientRects():"
 layer at (90,90) size 90x90
   LayoutBlockFlow (positioned) {DIV} at (90,90) size 90x90 [bgcolor=#FF0000]
diff --git a/third_party/WebKit/LayoutTests/platform/linux/transforms/transform-on-inline-expected.png b/third_party/WebKit/LayoutTests/platform/linux/transforms/transform-on-inline-expected.png
index 156bfe3..1768e98 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/transforms/transform-on-inline-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/transforms/transform-on-inline-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/android/fullscreen/full-screen-iframe-allowed-video-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/android/fullscreen/full-screen-iframe-allowed-video-expected.png
index 829b8c45..8005665 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/android/fullscreen/full-screen-iframe-allowed-video-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/android/fullscreen/full-screen-iframe-allowed-video-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/android/fullscreen/video-controls-timeline-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/android/fullscreen/video-controls-timeline-expected.png
index 829b8c45..8005665 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/android/fullscreen/video-controls-timeline-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/android/fullscreen/video-controls-timeline-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/android/fullscreen/video-scrolled-iframe-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/android/fullscreen/video-scrolled-iframe-expected.png
index 829b8c45..8005665 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/android/fullscreen/video-scrolled-iframe-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/android/fullscreen/video-scrolled-iframe-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spv175/compositing/video-frame-size-change-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spv175/compositing/video-frame-size-change-expected.png
index 4de05e8..aff30ff 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spv175/compositing/video-frame-size-change-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spv175/compositing/video-frame-size-change-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spv175/fast/borders/border-radius-mask-video-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spv175/fast/borders/border-radius-mask-video-expected.png
new file mode 100644
index 0000000..a2642e3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spv175/fast/borders/border-radius-mask-video-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spv175/fast/borders/border-radius-mask-video-ratio-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spv175/fast/borders/border-radius-mask-video-ratio-expected.png
new file mode 100644
index 0000000..8a4d2fb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spv175/fast/borders/border-radius-mask-video-ratio-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spv175/fast/borders/border-radius-mask-video-shadow-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spv175/fast/borders/border-radius-mask-video-shadow-expected.png
new file mode 100644
index 0000000..d0aef67
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/disable-spv175/fast/borders/border-radius-mask-video-shadow-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/new-remote-playback-pipeline/media/controls/video-controls-with-cast-rendering-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/new-remote-playback-pipeline/media/controls/video-controls-with-cast-rendering-expected.png
index a2dbbef..b3bdfd8 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/new-remote-playback-pipeline/media/controls/video-controls-with-cast-rendering-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/new-remote-playback-pipeline/media/controls/video-controls-with-cast-rendering-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/new-remote-playback-pipeline/media/controls/video-overlay-cast-dark-rendering-expected.png b/third_party/WebKit/LayoutTests/platform/linux/virtual/new-remote-playback-pipeline/media/controls/video-overlay-cast-dark-rendering-expected.png
index a344c15f..57711ed 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/new-remote-playback-pipeline/media/controls/video-overlay-cast-dark-rendering-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/new-remote-playback-pipeline/media/controls/video-overlay-cast-dark-rendering-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/complex-text-opacity-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/complex-text-opacity-expected.png
index ffd72f9..147f795 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/complex-text-opacity-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/complex-text-opacity-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/media/controls/lazy-loaded-style-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/media/controls/lazy-loaded-style-expected.png
new file mode 100644
index 0000000..dc1da62
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/media/controls/lazy-loaded-style-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/media/track/track-cue-rendering-vertical-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/media/track/track-cue-rendering-vertical-expected.png
index 036197b..719f566 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/media/track/track-cue-rendering-vertical-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/media/track/track-cue-rendering-vertical-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/transforms/2d/hindi-rotated-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/transforms/2d/hindi-rotated-expected.png
index b03117d..ae91e24 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/transforms/2d/hindi-rotated-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/transforms/2d/hindi-rotated-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/new-remote-playback-pipeline/media/controls/lazy-loaded-style-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/new-remote-playback-pipeline/media/controls/lazy-loaded-style-expected.png
new file mode 100644
index 0000000..dc1da62
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/virtual/new-remote-playback-pipeline/media/controls/lazy-loaded-style-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/http/tests/misc/bad-charset-alias-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/http/tests/misc/bad-charset-alias-expected.txt
deleted file mode 100644
index 88c213f6..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/http/tests/misc/bad-charset-alias-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Test that iso-8859-1 aliases that aren't known to Firefox and IE aren't supported (we should fall back to parent frame charset).
-
-SUCCESS
-
-
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/lazy-loaded-style-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/media/controls/lazy-loaded-style-expected.png
similarity index 100%
copy from third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/lazy-loaded-style-expected.png
copy to third_party/WebKit/LayoutTests/platform/mac-mac10.11/media/controls/lazy-loaded-style-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/media/track/track-cue-rendering-vertical-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/media/track/track-cue-rendering-vertical-expected.png
index 3167590f5..4376130 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/media/track/track-cue-rendering-vertical-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/media/track/track-cue-rendering-vertical-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/lazy-loaded-style-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/virtual/new-remote-playback-pipeline/media/controls/lazy-loaded-style-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/lazy-loaded-style-expected.png
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.11/virtual/new-remote-playback-pipeline/media/controls/lazy-loaded-style-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.12/fast/text/complex-text-opacity-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.12/fast/text/complex-text-opacity-expected.png
index 4440daa..30b2ae7 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.12/fast/text/complex-text-opacity-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.12/fast/text/complex-text-opacity-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.12/media/controls/lazy-loaded-style-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.12/media/controls/lazy-loaded-style-expected.png
new file mode 100644
index 0000000..dc1da62
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.12/media/controls/lazy-loaded-style-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/lazy-loaded-style-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.12/media/controls/lazy-loaded-style-expected.txt
similarity index 100%
copy from third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/lazy-loaded-style-expected.txt
copy to third_party/WebKit/LayoutTests/platform/mac-mac10.12/media/controls/lazy-loaded-style-expected.txt
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.12/media/track/track-cue-rendering-horizontal-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.12/media/track/track-cue-rendering-horizontal-expected.png
index 12a7f5b..ec347ff 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.12/media/track/track-cue-rendering-horizontal-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.12/media/track/track-cue-rendering-horizontal-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.12/media/video-zoom-controls-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.12/media/video-zoom-controls-expected.png
index f4549b6b..8bfbdc3 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.12/media/video-zoom-controls-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.12/media/video-zoom-controls-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.12/svg/as-background-image/svg-as-background-6-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.12/svg/as-background-image/svg-as-background-6-expected.png
index 16c5c3d..b73ca85 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.12/svg/as-background-image/svg-as-background-6-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.12/svg/as-background-image/svg-as-background-6-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.12/virtual/new-remote-playback-pipeline/media/controls/lazy-loaded-style-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.12/virtual/new-remote-playback-pipeline/media/controls/lazy-loaded-style-expected.png
new file mode 100644
index 0000000..dc1da62
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.12/virtual/new-remote-playback-pipeline/media/controls/lazy-loaded-style-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/lazy-loaded-style-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.12/virtual/new-remote-playback-pipeline/media/controls/lazy-loaded-style-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/mac/virtual/new-remote-playback-pipeline/media/controls/lazy-loaded-style-expected.txt
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.12/virtual/new-remote-playback-pipeline/media/controls/lazy-loaded-style-expected.txt
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/sibling-positioning-expected.png b/third_party/WebKit/LayoutTests/platform/mac/compositing/sibling-positioning-expected.png
index 8b34d9b..78701f1 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/compositing/sibling-positioning-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/sibling-positioning-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/video-frame-size-change-expected.png b/third_party/WebKit/LayoutTests/platform/mac/compositing/video-frame-size-change-expected.png
index b53221b..3c098d8 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/compositing/video-frame-size-change-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/video-frame-size-change-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/video/video-reflection-expected.png b/third_party/WebKit/LayoutTests/platform/mac/compositing/video/video-reflection-expected.png
new file mode 100644
index 0000000..acac9e0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/video/video-reflection-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/composition-underline-color-expected.png b/third_party/WebKit/LayoutTests/platform/mac/editing/composition-underline-color-expected.png
new file mode 100644
index 0000000..6265292
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/editing/composition-underline-color-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/composition-underline-color-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/editing/composition-underline-color-expected.txt
new file mode 100644
index 0000000..8043fd83
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/editing/composition-underline-color-expected.txt
@@ -0,0 +1,13 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x194
+  LayoutBlockFlow {HTML} at (0,0) size 800x194
+    LayoutBlockFlow {BODY} at (8,16) size 784x170
+      LayoutBlockFlow {P} at (0,0) size 784x36
+        LayoutText {#text} at (0,0) size 775x36
+          text run at (0,0) width 775: "This test checks that composition underline color uses the color of the text and is not always black. The test passes if you"
+          text run at (0,18) width 504: "see the word \"foobar\" in green with a composition underline in the same color."
+      LayoutBlockFlow {DIV} at (0,52) size 784x118 [color=#00FF00] [bgcolor=#000000]
+        LayoutText {#text} at (50,50) size 42x18
+          text run at (50,50) width 42: "foobar"
+caret: position 6 of child 0 {#text} of child 2 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac/external/wpt/css/css-transitions/properties-value-auto-001-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/external/wpt/css/css-transitions/properties-value-auto-001-expected.txt
new file mode 100644
index 0000000..72da538
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/external/wpt/css/css-transitions/properties-value-auto-001-expected.txt
@@ -0,0 +1,56 @@
+This is a testharness.js-based test.
+Found 52 tests; 0 PASS, 52 FAIL, 0 TIMEOUT, 0 NOTRUN.
+FAIL margin-top auto(to) / values assert_not_equals: must not be target value after start got disallowed value "0px"
+FAIL margin-top auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "margin-top:0.5s" but got ""
+FAIL margin-top auto(from) / values assert_not_equals: must not be target value after start got disallowed value "13.3333px"
+FAIL margin-top auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "margin-top:0.5s" but got ""
+FAIL margin-right auto(to) / values assert_not_equals: must not be target value after start got disallowed value "0px"
+FAIL margin-right auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "margin-right:0.5s" but got ""
+FAIL margin-right auto(from) / values assert_not_equals: must not be target value after start got disallowed value "13.3333px"
+FAIL margin-right auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "margin-right:0.5s" but got ""
+FAIL margin-bottom auto(to) / values assert_not_equals: must not be target value after start got disallowed value "0px"
+FAIL margin-bottom auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "margin-bottom:0.5s" but got ""
+FAIL margin-bottom auto(from) / values assert_not_equals: must not be target value after start got disallowed value "13.3333px"
+FAIL margin-bottom auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "margin-bottom:0.5s" but got ""
+FAIL margin-left auto(to) / values assert_not_equals: must not be target value after start got disallowed value "0px"
+FAIL margin-left auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "margin-left:0.5s" but got ""
+FAIL margin-left auto(from) / values assert_not_equals: must not be target value after start got disallowed value "13.3333px"
+FAIL margin-left auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "margin-left:0.5s" but got ""
+FAIL height auto(to) / values assert_not_equals: must not be target value after start got disallowed value "18px"
+FAIL height auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "height:0.5s" but got ""
+FAIL height auto(from) / values assert_not_equals: must not be target value after start got disallowed value "13.3281px"
+FAIL height auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "height:0.5s" but got ""
+FAIL width auto(to) / values assert_not_equals: must not be target value after start got disallowed value "100px"
+FAIL width auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "width:0.5s" but got ""
+FAIL width auto(from) / values assert_not_equals: must not be target value after start got disallowed value "13.3281px"
+FAIL width auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "width:0.5s" but got ""
+FAIL clip auto(to) / values assert_not_equals: must not be target value after start got disallowed value "auto"
+FAIL clip auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "clip:0.5s" but got ""
+FAIL clip auto(from) / values assert_not_equals: must not be target value after start got disallowed value "rect(15px, 15px, 5px, 5px)"
+FAIL clip auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "clip:0.5s" but got ""
+FAIL marker-offset auto(to) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL marker-offset auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "marker-offset:0.5s" but got ""
+FAIL marker-offset auto(from) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL marker-offset auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "marker-offset:0.5s" but got ""
+FAIL top auto(to) / values assert_not_equals: must not be target value after start got disallowed value "0px"
+FAIL top auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "top:0.5s" but got ""
+FAIL top auto(from) / values assert_not_equals: must not be target value after start got disallowed value "13.3333px"
+FAIL top auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "top:0.5s" but got ""
+FAIL right auto(to) / values assert_not_equals: must not be target value after start got disallowed value "22.4688px"
+FAIL right auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "right:0.5s" but got ""
+FAIL right auto(from) / values assert_not_equals: must not be target value after start got disallowed value "13.3333px"
+FAIL right auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "right:0.5s" but got ""
+FAIL left auto(to) / values assert_not_equals: must not be target value after start got disallowed value "0px"
+FAIL left auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "left:0.5s" but got ""
+FAIL left auto(from) / values assert_not_equals: must not be target value after start got disallowed value "13.3333px"
+FAIL left auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "left:0.5s" but got ""
+FAIL bottom auto(to) / values assert_not_equals: must not be target value after start got disallowed value "82px"
+FAIL bottom auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "bottom:0.5s" but got ""
+FAIL bottom auto(from) / values assert_not_equals: must not be target value after start got disallowed value "13.3333px"
+FAIL bottom auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "bottom:0.5s" but got ""
+FAIL z-index auto(to) / values assert_not_equals: must not be target value after start got disallowed value "auto"
+FAIL z-index auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "z-index:0.5s" but got ""
+FAIL z-index auto(from) / values assert_not_equals: must not be target value after start got disallowed value "10"
+FAIL z-index auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "z-index:0.5s" but got ""
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/borders/border-radius-mask-video-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/borders/border-radius-mask-video-expected.png
index 25524d4..3e5f285 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/borders/border-radius-mask-video-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/borders/border-radius-mask-video-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/borders/border-radius-mask-video-ratio-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/borders/border-radius-mask-video-ratio-expected.png
index 0ac166cc..6ee2b61c 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/borders/border-radius-mask-video-ratio-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/borders/border-radius-mask-video-ratio-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/borders/border-radius-mask-video-shadow-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/borders/border-radius-mask-video-shadow-expected.png
index 256346b..5ba4f99 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/borders/border-radius-mask-video-shadow-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/borders/border-radius-mask-video-shadow-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/css/ZeroOpacityLayers-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/css/ZeroOpacityLayers-expected.png
index 439ba135..3b0398c3 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/css/ZeroOpacityLayers-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/css/ZeroOpacityLayers-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/css/ZeroOpacityLayers2-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/css/ZeroOpacityLayers2-expected.png
index 0132876..55200b4 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/css/ZeroOpacityLayers2-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/css/ZeroOpacityLayers2-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/layers/remove-layer-with-nested-stacking-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/layers/remove-layer-with-nested-stacking-expected.png
index 2cfb9d0..415932d 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/layers/remove-layer-with-nested-stacking-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/layers/remove-layer-with-nested-stacking-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/table/multiple-captions-display-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/table/multiple-captions-display-expected.png
index 40ad4e6..6e9be25 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/table/multiple-captions-display-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/table/multiple-captions-display-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/text/complex-text-opacity-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/text/complex-text-opacity-expected.png
index c79519f..8347327 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/text/complex-text-opacity-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/text/complex-text-opacity-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/hdr/color-profile-video-expected.png b/third_party/WebKit/LayoutTests/platform/mac/hdr/color-profile-video-expected.png
index 85f7439..0a24b92 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/hdr/color-profile-video-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/hdr/color-profile-video-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/hdr/video-canvas-alpha-expected.png b/third_party/WebKit/LayoutTests/platform/mac/hdr/video-canvas-alpha-expected.png
index 1d92b9de..613d9db 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/hdr/video-canvas-alpha-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/hdr/video-canvas-alpha-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/http/tests/misc/bad-charset-alias-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/http/tests/misc/bad-charset-alias-expected.txt
deleted file mode 100644
index 4434684..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac/http/tests/misc/bad-charset-alias-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Test that iso-8859-1 aliases that aren't known to Firefox and IE aren't supported (we should fall back to parent frame charset).
-
-FAIL: foobar 8859_1 ISO8859_1 8859-1 ISO_2022,locale=ja,version=0 utf 8 utf_8 8859 1 8859*1 8859:1 88591 ISO_88591 ISO-88591 ISO-88-59-1 latin-1
-
-
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/color-profile-video-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/color-profile-video-expected.png
new file mode 100644
index 0000000..3ddda41
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/color-profile-video-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/color-profile-video-seek-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/color-profile-video-seek-expected.png
new file mode 100644
index 0000000..5f889e87
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/color-profile-video-seek-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/color-profile-video-seek-filter-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/color-profile-video-seek-filter-expected.png
new file mode 100644
index 0000000..70b6eb4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/color-profile-video-seek-filter-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/color-profile-video-seek-object-fit-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/color-profile-video-seek-object-fit-expected.png
new file mode 100644
index 0000000..0319aa5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/color-profile-video-seek-object-fit-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/controls-after-reload-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/controls-after-reload-expected.png
index 8cc6409..6282ec6 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/media/controls-after-reload-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/controls-after-reload-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/controls-strict-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/controls-strict-expected.png
index 753131c..2d07d63 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/media/controls-strict-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/controls-strict-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/controls-styling-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/controls-styling-expected.png
index db06ed33..93628c9 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/media/controls-styling-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/controls-styling-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/controls-styling-strict-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/controls-styling-strict-expected.png
index b1f264c..a75e60c 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/media/controls-styling-strict-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/controls-styling-strict-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/controls-without-preload-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/controls-without-preload-expected.png
index 4fc95ee..a3eecde 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/media/controls-without-preload-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/controls-without-preload-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/controls/lazy-loaded-style-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/controls/lazy-loaded-style-expected.png
index c1390f5..7fbb666b 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/media/controls/lazy-loaded-style-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/controls/lazy-loaded-style-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/controls/lazy-loaded-style-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/media/controls/lazy-loaded-style-expected.txt
index 73a4622..9632bf9 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/media/controls/lazy-loaded-style-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/controls/lazy-loaded-style-expected.txt
@@ -37,8 +37,8 @@
   LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 93.28x0
 layer at (301,291) size 57x2
   LayoutBlockFlow (positioned) {DIV} at (18,-1) size 57.28x2 [bgcolor=#DADADA]
-layer at (116,291) size 117x2
-  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 117x2 [bgcolor=#5A5A5A]
+layer at (116,291) size 116x2
+  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 116x2 [bgcolor=#5A5A5A]
 layer at (116,291) size 0x2
   LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#4285F4]
 layer at (301,291) size 0x2
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/controls/video-overlay-cast-dark-rendering-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/controls/video-overlay-cast-dark-rendering-expected.png
index 65da69a..27177950 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/media/controls/video-overlay-cast-dark-rendering-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/controls/video-overlay-cast-dark-rendering-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/track/track-cue-rendering-horizontal-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/track/track-cue-rendering-horizontal-expected.png
index ed51a0af..cc26d78 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/media/track/track-cue-rendering-horizontal-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/track/track-cue-rendering-horizontal-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/track/track-cue-rendering-vertical-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/track/track-cue-rendering-vertical-expected.png
index 948a7075..80f3d73 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/media/track/track-cue-rendering-vertical-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/track/track-cue-rendering-vertical-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/video-aspect-ratio-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/video-aspect-ratio-expected.png
index 1a784a2..4fb3e17 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/media/video-aspect-ratio-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/video-aspect-ratio-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/video-canvas-alpha-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/video-canvas-alpha-expected.png
new file mode 100644
index 0000000..907f9892
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/video-canvas-alpha-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/video-controls-rendering-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/video-controls-rendering-expected.png
index 031719a..03130cda9 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/media/video-controls-rendering-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/video-controls-rendering-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/video-display-toggle-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/video-display-toggle-expected.png
index 703ba0c..e05332a2 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/media/video-display-toggle-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/video-display-toggle-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/video-layer-crash-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/video-layer-crash-expected.png
index 6c84ef55..1f801bf 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/media/video-layer-crash-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/video-layer-crash-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/video-remove-insert-repaints-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/video-remove-insert-repaints-expected.png
new file mode 100644
index 0000000..b83161a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/video-remove-insert-repaints-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/video-replaces-poster-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/video-replaces-poster-expected.png
index 76e5c5a..01c618f 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/media/video-replaces-poster-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/video-replaces-poster-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/video-transformed-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/video-transformed-expected.png
index fca42cd..dc45fd3 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/media/video-transformed-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/video-transformed-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/video-zoom-controls-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/video-zoom-controls-expected.png
index a2abd4ef..3f1e08d8 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/media/video-zoom-controls-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/video-zoom-controls-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/media/video-zoom-expected.png b/third_party/WebKit/LayoutTests/platform/mac/media/video-zoom-expected.png
index 76c3c66..cf33037 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/media/video-zoom-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/media/video-zoom-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/svg-as-background-6-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/svg-as-background-6-expected.png
index 7244078..5083aab 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/svg-as-background-6-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/as-background-image/svg-as-background-6-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/batik/text/textFeatures-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/batik/text/textFeatures-expected.png
index f56620c9..ed4ebea 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/batik/text/textFeatures-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/batik/text/textFeatures-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/text-image-opacity-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/custom/text-image-opacity-expected.png
index 183ff743..9f756c1 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/custom/text-image-opacity-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/custom/text-image-opacity-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png
index 1cf661c..b648de12 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.txt
index f52a4a22..21b2136 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.txt
@@ -1,106 +1,106 @@
 layer at (0,0) size 800x600
   LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x348
-  LayoutBlockFlow {HTML} at (0,0) size 800x348.09
-    LayoutBlockFlow {BODY} at (5.55,5.55) size 788.91x337
-      LayoutTable {TABLE} at (0,0) size 465x337
-        LayoutTableSection {TBODY} at (0,0) size 465x337
-          LayoutTableRow {TR} at (0,1) size 465x15
-            LayoutTableCell {TH} at (1,1) size 65x15.38 [bgcolor=#DDDD99] [r=0 c=0 rs=1 cs=1]
-              LayoutText {#text} at (6,0) size 53x15
+layer at (0,0) size 800x339
+  LayoutBlockFlow {HTML} at (0,0) size 800x339.09
+    LayoutBlockFlow {BODY} at (5.55,5.55) size 788.91x328
+      LayoutTable {TABLE} at (0,0) size 465x328
+        LayoutTableSection {TBODY} at (0,0) size 465x328
+          LayoutTableRow {TR} at (0,1) size 465x14
+            LayoutTableCell {TH} at (1,1) size 65x14 [bgcolor=#DDDD99] [r=0 c=0 rs=1 cs=1]
+              LayoutText {#text} at (6,0) size 53x14
                 text run at (6,0) width 53: "viewBox?"
-            LayoutTableCell {TH} at (67,1) size 113x15.38 [bgcolor=#DDDD99] [r=0 c=1 rs=1 cs=1]
-              LayoutText {#text} at (0,0) size 113x15
+            LayoutTableCell {TH} at (67,1) size 113x14 [bgcolor=#DDDD99] [r=0 c=1 rs=1 cs=1]
+              LayoutText {#text} at (0,0) size 113x14
                 text run at (0,0) width 113: "preserve\x{AD}Aspect\x{AD}Ratio"
-            LayoutTableCell {TH} at (181,1) size 141x15.38 [bgcolor=#DDDD99] [r=0 c=2 rs=1 cs=1]
-              LayoutText {#text} at (54,0) size 33x15
+            LayoutTableCell {TH} at (181,1) size 141x14 [bgcolor=#DDDD99] [r=0 c=2 rs=1 cs=1]
+              LayoutText {#text} at (54,0) size 33x14
                 text run at (54,0) width 33: "<img>"
-            LayoutTableCell {TH} at (323,1) size 141x15.38 [bgcolor=#DDDD99] [r=0 c=3 rs=1 cs=1]
-              LayoutText {#text} at (47,0) size 47x15
+            LayoutTableCell {TH} at (323,1) size 141x14 [bgcolor=#DDDD99] [r=0 c=3 rs=1 cs=1]
+              LayoutText {#text} at (47,0) size 47x14
                 text run at (47,0) width 47: "<object>"
-          LayoutTableRow {TR} at (0,17) size 465x39
-            LayoutTableCell {TH} at (1,89) size 65x15.38 [bgcolor=#DDDD99] [r=1 c=0 rs=4 cs=1]
-              LayoutText {#text} at (1,0) size 63x15
+          LayoutTableRow {TR} at (0,16) size 465x38
+            LayoutTableCell {TH} at (1,86) size 65x14 [bgcolor=#DDDD99] [r=1 c=0 rs=4 cs=1]
+              LayoutText {#text} at (1,0) size 63x14
                 text run at (1,0) width 63: "No viewBox"
-            LayoutTableCell {TH} at (67,36) size 113x1.38 [bgcolor=#DDDD99] [r=1 c=1 rs=1 cs=1]
-            LayoutTableCell {TD} at (181,17) size 141x39.09 [r=1 c=2 rs=1 cs=1]
-              LayoutImage {IMG} at (0.69,0.69) size 138.88x34.72 [border: (1.38px dashed #800000)]
+            LayoutTableCell {TH} at (67,35) size 113x0 [bgcolor=#DDDD99] [r=1 c=1 rs=1 cs=1]
+            LayoutTableCell {TD} at (181,16) size 141x37.72 [r=1 c=2 rs=1 cs=1]
+              LayoutImage {IMG} at (0.69,0) size 138.88x34.72 [border: (1.38px dashed #800000)]
               LayoutText {#text} at (0,0) size 0x0
-            LayoutTableCell {TD} at (323,17) size 141x39.09 [r=1 c=3 rs=1 cs=1]
+            LayoutTableCell {TD} at (323,16) size 141x37.72 [r=1 c=3 rs=1 cs=1]
               LayoutText {#text} at (0,0) size 0x0
-          LayoutTableRow {TR} at (0,57) size 465x39
-            LayoutTableCell {TH} at (67,69) size 113x15.38 [bgcolor=#DDDD99] [r=2 c=1 rs=1 cs=1]
-              LayoutText {#text} at (43,0) size 27x15
+          LayoutTableRow {TR} at (0,55) size 465x38
+            LayoutTableCell {TH} at (67,67) size 113x14 [bgcolor=#DDDD99] [r=2 c=1 rs=1 cs=1]
+              LayoutText {#text} at (43,0) size 27x14
                 text run at (43,0) width 27: "none"
-            LayoutTableCell {TD} at (181,57) size 141x39.09 [r=2 c=2 rs=1 cs=1]
-              LayoutImage {IMG} at (0.69,0.69) size 138.88x34.72 [border: (1.38px dashed #800000)]
+            LayoutTableCell {TD} at (181,55) size 141x37.72 [r=2 c=2 rs=1 cs=1]
+              LayoutImage {IMG} at (0.69,0) size 138.88x34.72 [border: (1.38px dashed #800000)]
               LayoutText {#text} at (0,0) size 0x0
-            LayoutTableCell {TD} at (323,57) size 141x39.09 [r=2 c=3 rs=1 cs=1]
+            LayoutTableCell {TD} at (323,55) size 141x37.72 [r=2 c=3 rs=1 cs=1]
               LayoutText {#text} at (0,0) size 0x0
-          LayoutTableRow {TR} at (0,97) size 465x39
-            LayoutTableCell {TH} at (67,109) size 113x15.38 [bgcolor=#DDDD99] [r=3 c=1 rs=1 cs=1]
-              LayoutText {#text} at (43,0) size 27x15
+          LayoutTableRow {TR} at (0,94) size 465x38
+            LayoutTableCell {TH} at (67,106) size 113x14 [bgcolor=#DDDD99] [r=3 c=1 rs=1 cs=1]
+              LayoutText {#text} at (43,0) size 27x14
                 text run at (43,0) width 27: "meet"
-            LayoutTableCell {TD} at (181,97) size 141x39.09 [r=3 c=2 rs=1 cs=1]
-              LayoutImage {IMG} at (0.69,0.69) size 138.88x34.72 [border: (1.38px dashed #800000)]
+            LayoutTableCell {TD} at (181,94) size 141x37.72 [r=3 c=2 rs=1 cs=1]
+              LayoutImage {IMG} at (0.69,0) size 138.88x34.72 [border: (1.38px dashed #800000)]
               LayoutText {#text} at (0,0) size 0x0
-            LayoutTableCell {TD} at (323,97) size 141x39.09 [r=3 c=3 rs=1 cs=1]
+            LayoutTableCell {TD} at (323,94) size 141x37.72 [r=3 c=3 rs=1 cs=1]
               LayoutText {#text} at (0,0) size 0x0
-          LayoutTableRow {TR} at (0,137) size 465x39
-            LayoutTableCell {TH} at (67,149) size 113x15.38 [bgcolor=#DDDD99] [r=4 c=1 rs=1 cs=1]
-              LayoutText {#text} at (44,0) size 25x15
+          LayoutTableRow {TR} at (0,133) size 465x38
+            LayoutTableCell {TH} at (67,145) size 113x14 [bgcolor=#DDDD99] [r=4 c=1 rs=1 cs=1]
+              LayoutText {#text} at (44,0) size 25x14
                 text run at (44,0) width 25: "slice"
-            LayoutTableCell {TD} at (181,137) size 141x39.09 [r=4 c=2 rs=1 cs=1]
-              LayoutImage {IMG} at (0.69,0.69) size 138.88x34.72 [border: (1.38px dashed #800000)]
+            LayoutTableCell {TD} at (181,133) size 141x37.72 [r=4 c=2 rs=1 cs=1]
+              LayoutImage {IMG} at (0.69,0) size 138.88x34.72 [border: (1.38px dashed #800000)]
               LayoutText {#text} at (0,0) size 0x0
-            LayoutTableCell {TD} at (323,137) size 141x39.09 [r=4 c=3 rs=1 cs=1]
+            LayoutTableCell {TD} at (323,133) size 141x37.72 [r=4 c=3 rs=1 cs=1]
               LayoutText {#text} at (0,0) size 0x0
-          LayoutTableRow {TR} at (0,177) size 465x39
-            LayoutTableCell {TH} at (1,249) size 65x15.38 [bgcolor=#DDDD99] [r=5 c=0 rs=4 cs=1]
-              LayoutText {#text} at (9,0) size 47x15
+          LayoutTableRow {TR} at (0,172) size 465x38
+            LayoutTableCell {TH} at (1,242) size 65x14 [bgcolor=#DDDD99] [r=5 c=0 rs=4 cs=1]
+              LayoutText {#text} at (9,0) size 47x14
                 text run at (9,0) width 47: "viewBox"
-            LayoutTableCell {TH} at (67,196) size 113x1.38 [bgcolor=#DDDD99] [r=5 c=1 rs=1 cs=1]
-            LayoutTableCell {TD} at (181,177) size 141x39.09 [r=5 c=2 rs=1 cs=1]
-              LayoutImage {IMG} at (0.69,0.69) size 138.88x34.72 [border: (1.38px dashed #800000)]
+            LayoutTableCell {TH} at (67,191) size 113x0 [bgcolor=#DDDD99] [r=5 c=1 rs=1 cs=1]
+            LayoutTableCell {TD} at (181,172) size 141x37.72 [r=5 c=2 rs=1 cs=1]
+              LayoutImage {IMG} at (0.69,0) size 138.88x34.72 [border: (1.38px dashed #800000)]
               LayoutText {#text} at (0,0) size 0x0
-            LayoutTableCell {TD} at (323,177) size 141x39.09 [r=5 c=3 rs=1 cs=1]
+            LayoutTableCell {TD} at (323,172) size 141x37.72 [r=5 c=3 rs=1 cs=1]
               LayoutText {#text} at (0,0) size 0x0
-          LayoutTableRow {TR} at (0,217) size 465x39
-            LayoutTableCell {TH} at (67,229) size 113x15.38 [bgcolor=#DDDD99] [r=6 c=1 rs=1 cs=1]
-              LayoutText {#text} at (43,0) size 27x15
+          LayoutTableRow {TR} at (0,211) size 465x38
+            LayoutTableCell {TH} at (67,223) size 113x14 [bgcolor=#DDDD99] [r=6 c=1 rs=1 cs=1]
+              LayoutText {#text} at (43,0) size 27x14
                 text run at (43,0) width 27: "none"
-            LayoutTableCell {TD} at (181,217) size 141x39.09 [r=6 c=2 rs=1 cs=1]
-              LayoutImage {IMG} at (0.69,0.69) size 138.88x34.72 [border: (1.38px dashed #800000)]
+            LayoutTableCell {TD} at (181,211) size 141x37.72 [r=6 c=2 rs=1 cs=1]
+              LayoutImage {IMG} at (0.69,0) size 138.88x34.72 [border: (1.38px dashed #800000)]
               LayoutText {#text} at (0,0) size 0x0
-            LayoutTableCell {TD} at (323,217) size 141x39.09 [r=6 c=3 rs=1 cs=1]
+            LayoutTableCell {TD} at (323,211) size 141x37.72 [r=6 c=3 rs=1 cs=1]
               LayoutText {#text} at (0,0) size 0x0
-          LayoutTableRow {TR} at (0,257) size 465x39
-            LayoutTableCell {TH} at (67,269) size 113x15.38 [bgcolor=#DDDD99] [r=7 c=1 rs=1 cs=1]
-              LayoutText {#text} at (43,0) size 27x15
+          LayoutTableRow {TR} at (0,250) size 465x38
+            LayoutTableCell {TH} at (67,262) size 113x14 [bgcolor=#DDDD99] [r=7 c=1 rs=1 cs=1]
+              LayoutText {#text} at (43,0) size 27x14
                 text run at (43,0) width 27: "meet"
-            LayoutTableCell {TD} at (181,257) size 141x39.09 [r=7 c=2 rs=1 cs=1]
-              LayoutImage {IMG} at (0.69,0.69) size 138.88x34.72 [border: (1.38px dashed #800000)]
+            LayoutTableCell {TD} at (181,250) size 141x37.72 [r=7 c=2 rs=1 cs=1]
+              LayoutImage {IMG} at (0.69,0) size 138.88x34.72 [border: (1.38px dashed #800000)]
               LayoutText {#text} at (0,0) size 0x0
-            LayoutTableCell {TD} at (323,257) size 141x39.09 [r=7 c=3 rs=1 cs=1]
+            LayoutTableCell {TD} at (323,250) size 141x37.72 [r=7 c=3 rs=1 cs=1]
               LayoutText {#text} at (0,0) size 0x0
-          LayoutTableRow {TR} at (0,297) size 465x39
-            LayoutTableCell {TH} at (67,309) size 113x15.38 [bgcolor=#DDDD99] [r=8 c=1 rs=1 cs=1]
-              LayoutText {#text} at (44,0) size 25x15
+          LayoutTableRow {TR} at (0,289) size 465x38
+            LayoutTableCell {TH} at (67,301) size 113x14 [bgcolor=#DDDD99] [r=8 c=1 rs=1 cs=1]
+              LayoutText {#text} at (44,0) size 25x14
                 text run at (44,0) width 25: "slice"
-            LayoutTableCell {TD} at (181,297) size 141x39.09 [r=8 c=2 rs=1 cs=1]
-              LayoutImage {IMG} at (0.69,0.69) size 138.88x34.72 [border: (1.38px dashed #800000)]
+            LayoutTableCell {TD} at (181,289) size 141x37.72 [r=8 c=2 rs=1 cs=1]
+              LayoutImage {IMG} at (0.69,0) size 138.88x34.72 [border: (1.38px dashed #800000)]
               LayoutText {#text} at (0,0) size 0x0
-            LayoutTableCell {TD} at (323,297) size 141x39.09 [r=8 c=3 rs=1 cs=1]
+            LayoutTableCell {TD} at (323,289) size 141x37.72 [r=8 c=3 rs=1 cs=1]
               LayoutText {#text} at (0,0) size 0x0
-layer at (329,23) size 139x34
-  LayoutEmbeddedObject {OBJECT} at (0.69,0.69) size 138.88x34.72 [border: (0.69px dashed #008000)]
+layer at (329,22) size 139x35
+  LayoutEmbeddedObject {OBJECT} at (0.69,0) size 138.88x34.72 [border: (0.69px dashed #008000)]
     layer at (0,0) size 133x29
       LayoutView at (0,0) size 133x29
     layer at (0,0) size 133x29
       LayoutSVGRoot {svg} at (0,0) size 133x29
         LayoutSVGEllipse {circle} at (0,0) size 220x220 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#D9BB7A] [fill rule=EVEN-ODD]}] [cx=110.00] [cy=110.00] [r=110.00]
-layer at (329,63) size 139x34
-  LayoutEmbeddedObject {OBJECT} at (0.69,0.69) size 138.88x34.72 [border: (0.69px dashed #008000)]
+layer at (329,61) size 139x35
+  LayoutEmbeddedObject {OBJECT} at (0.69,0) size 138.88x34.72 [border: (0.69px dashed #008000)]
     layer at (0,0) size 133x29
       LayoutView at (0,0) size 133x29
     layer at (0,0) size 133x29
@@ -108,8 +108,8 @@
         LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
         LayoutSVGContainer {g} at (162.86,403.79) size 362.86x362.86 [transform={m=((1.00,0.00)(0.00,1.00)) t=(-162.36,-403.29)}]
           LayoutSVGPath {path} at (162.86,403.79) size 362.86x362.86 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#D9BB7A] [fill rule=EVEN-ODD]}] [data="M 525.714 585.219 A 181.429 181.429 0 1 1 162.857 585.219 A 181.429 181.429 0 1 1 525.714 585.219 Z"]
-layer at (329,103) size 139x34
-  LayoutEmbeddedObject {OBJECT} at (0.69,0.69) size 138.88x34.72 [border: (0.69px dashed #008000)]
+layer at (329,100) size 139x35
+  LayoutEmbeddedObject {OBJECT} at (0.69,0) size 138.88x34.72 [border: (0.69px dashed #008000)]
     layer at (0,0) size 133x29
       LayoutView at (0,0) size 133x29
     layer at (0,0) size 133x29
@@ -117,8 +117,8 @@
         LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
         LayoutSVGContainer {g} at (162.86,403.79) size 362.86x362.86 [transform={m=((1.00,0.00)(0.00,1.00)) t=(-162.36,-403.29)}]
           LayoutSVGPath {path} at (162.86,403.79) size 362.86x362.86 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#D9BB7A] [fill rule=EVEN-ODD]}] [data="M 525.714 585.219 A 181.429 181.429 0 1 1 162.857 585.219 A 181.429 181.429 0 1 1 525.714 585.219 Z"]
-layer at (329,143) size 139x34
-  LayoutEmbeddedObject {OBJECT} at (0.69,0.69) size 138.88x34.72 [border: (0.69px dashed #008000)]
+layer at (329,139) size 139x35
+  LayoutEmbeddedObject {OBJECT} at (0.69,0) size 138.88x34.72 [border: (0.69px dashed #008000)]
     layer at (0,0) size 133x29
       LayoutView at (0,0) size 133x29
     layer at (0,0) size 133x29
@@ -126,8 +126,8 @@
         LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
         LayoutSVGContainer {g} at (162.86,403.79) size 362.86x362.86 [transform={m=((1.00,0.00)(0.00,1.00)) t=(-162.36,-403.29)}]
           LayoutSVGPath {path} at (162.86,403.79) size 362.86x362.86 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#D9BB7A] [fill rule=EVEN-ODD]}] [data="M 525.714 585.219 A 181.429 181.429 0 1 1 162.857 585.219 A 181.429 181.429 0 1 1 525.714 585.219 Z"]
-layer at (329,183) size 139x34
-  LayoutEmbeddedObject {OBJECT} at (0.69,0.69) size 138.88x34.72 [border: (0.69px dashed #008000)]
+layer at (329,178) size 139x35
+  LayoutEmbeddedObject {OBJECT} at (0.69,0) size 138.88x34.72 [border: (0.69px dashed #008000)]
     layer at (0,0) size 133x29
       LayoutView at (0,0) size 133x29
     layer at (0,0) size 133x29
@@ -135,8 +135,8 @@
         LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
         LayoutSVGContainer {g} at (162.86,403.79) size 362.86x362.86 [transform={m=((1.00,0.00)(0.00,1.00)) t=(-162.36,-403.29)}]
           LayoutSVGPath {path} at (162.86,403.79) size 362.86x362.86 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#D9BB7A] [fill rule=EVEN-ODD]}] [data="M 525.714 585.219 A 181.429 181.429 0 1 1 162.857 585.219 A 181.429 181.429 0 1 1 525.714 585.219 Z"]
-layer at (329,223) size 139x34
-  LayoutEmbeddedObject {OBJECT} at (0.69,0.69) size 138.88x34.72 [border: (0.69px dashed #008000)]
+layer at (329,217) size 139x35
+  LayoutEmbeddedObject {OBJECT} at (0.69,0) size 138.88x34.72 [border: (0.69px dashed #008000)]
     layer at (0,0) size 133x29
       LayoutView at (0,0) size 133x29
     layer at (0,0) size 133x29
@@ -144,8 +144,8 @@
         LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
         LayoutSVGContainer {g} at (162.86,403.79) size 362.86x362.86 [transform={m=((1.00,0.00)(0.00,1.00)) t=(-162.36,-403.29)}]
           LayoutSVGPath {path} at (162.86,403.79) size 362.86x362.86 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#D9BB7A] [fill rule=EVEN-ODD]}] [data="M 525.714 585.219 A 181.429 181.429 0 1 1 162.857 585.219 A 181.429 181.429 0 1 1 525.714 585.219 Z"]
-layer at (329,263) size 139x34
-  LayoutEmbeddedObject {OBJECT} at (0.69,0.69) size 138.88x34.72 [border: (0.69px dashed #008000)]
+layer at (329,256) size 139x35
+  LayoutEmbeddedObject {OBJECT} at (0.69,0) size 138.88x34.72 [border: (0.69px dashed #008000)]
     layer at (0,0) size 133x29
       LayoutView at (0,0) size 133x29
     layer at (0,0) size 133x29
@@ -153,8 +153,8 @@
         LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
         LayoutSVGContainer {g} at (162.86,403.79) size 362.86x362.86 [transform={m=((1.00,0.00)(0.00,1.00)) t=(-162.36,-403.29)}]
           LayoutSVGPath {path} at (162.86,403.79) size 362.86x362.86 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#D9BB7A] [fill rule=EVEN-ODD]}] [data="M 525.714 585.219 A 181.429 181.429 0 1 1 162.857 585.219 A 181.429 181.429 0 1 1 525.714 585.219 Z"]
-layer at (329,303) size 139x34
-  LayoutEmbeddedObject {OBJECT} at (0.69,0.69) size 138.88x34.72 [border: (0.69px dashed #008000)]
+layer at (329,295) size 139x35
+  LayoutEmbeddedObject {OBJECT} at (0.69,0) size 138.88x34.72 [border: (0.69px dashed #008000)]
     layer at (0,0) size 133x29
       LayoutView at (0,0) size 133x29
     layer at (0,0) size 133x29
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-svg-through-object-with-absolute-size-2-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-svg-through-object-with-absolute-size-2-expected.png
index a62f2a7c8..33fbbe3c 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-svg-through-object-with-absolute-size-2-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-svg-through-object-with-absolute-size-2-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-svg-through-object-with-absolute-size-2-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-svg-through-object-with-absolute-size-2-expected.txt
index 810fcc40..cf297a67 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-svg-through-object-with-absolute-size-2-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-svg-through-object-with-absolute-size-2-expected.txt
@@ -1,34 +1,34 @@
 layer at (0,0) size 800x600
   LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x204
-  LayoutBlockFlow {html} at (0,0) size 800x204.09
-    LayoutBlockFlow {body} at (5.55,5.55) size 788.91x193
-      LayoutTable {table} at (140.95,0) size 507x193
-        LayoutTableSection (anonymous) at (0,0) size 507x193
-          LayoutTableRow {tr} at (0,0) size 507x193
-            LayoutTableCell {td} at (0,0) size 507x192.88 [r=0 c=0 rs=1 cs=3]
-              LayoutTable {table} at (7,6.94) size 493x179
-                LayoutTableSection (anonymous) at (0,0) size 493x179
-                  LayoutTableRow {tr} at (0,1) size 493x67
-                    LayoutTableCell {td} at (1,1) size 491x66.84 [r=0 c=0 rs=1 cs=2]
-                      LayoutBlockFlow {h1} at (5.55,20.42) size 479.91x26
+layer at (0,0) size 800x198
+  LayoutBlockFlow {html} at (0,0) size 800x198.09
+    LayoutBlockFlow {body} at (5.55,5.55) size 788.91x187
+      LayoutTable {table} at (140.95,0) size 507x187
+        LayoutTableSection (anonymous) at (0,0) size 507x187
+          LayoutTableRow {tr} at (0,0) size 507x187
+            LayoutTableCell {td} at (0,0) size 507x187 [r=0 c=0 rs=1 cs=3]
+              LayoutTable {table} at (7,6) size 493x175
+                LayoutTableSection (anonymous) at (0,0) size 493x175
+                  LayoutTableRow {tr} at (0,1) size 493x66
+                    LayoutTableCell {td} at (1,1) size 491x65.75 [r=0 c=0 rs=1 cs=2]
+                      LayoutBlockFlow {h1} at (5.55,19.88) size 479.91x26
                         LayoutText {#text} at (0,0) size 480x26
                           text run at (0,0) width 480: "Both sides should have identical size after zooming"
-                  LayoutTableRow {tr} at (0,69) size 493x24
-                    LayoutTableCell {td} at (1,69) size 245x24.09 [r=1 c=0 rs=1 cs=1]
-                      LayoutText {#text} at (96,5) size 53x14
+                  LayoutTableRow {tr} at (0,68) size 493x23
+                    LayoutTableCell {td} at (1,68) size 245x23 [r=1 c=0 rs=1 cs=1]
+                      LayoutText {#text} at (96,5) size 53x13
                         text run at (96,5) width 53: "SVG Image"
-                    LayoutTableCell {td} at (247,69) size 245x24.09 [r=1 c=1 rs=1 cs=1]
-                      LayoutText {#text} at (96,5) size 53x14
+                    LayoutTableCell {td} at (247,68) size 245x23 [r=1 c=1 rs=1 cs=1]
+                      LayoutText {#text} at (96,5) size 53x13
                         text run at (96,5) width 53: "PNG Image"
-                  LayoutTableRow {tr} at (0,94) size 493x84
-                    LayoutTableCell {td} at (1,94) size 245x83.53 [r=2 c=0 rs=1 cs=1]
+                  LayoutTableRow {tr} at (0,92) size 493x82
+                    LayoutTableCell {td} at (1,92) size 245x82.44 [r=2 c=0 rs=1 cs=1]
                       LayoutText {#text} at (0,0) size 0x0
-                    LayoutTableCell {td} at (247,94) size 245x83.53 [r=2 c=1 rs=1 cs=1]
-                      LayoutImage {img} at (5.55,5.55) size 138.88x69.44
+                    LayoutTableCell {td} at (247,92) size 245x82.44 [r=2 c=1 rs=1 cs=1]
+                      LayoutImage {img} at (5.55,5) size 138.88x69.44
                       LayoutText {#text} at (0,0) size 0x0
-layer at (255,112) size 138x69
-  LayoutEmbeddedObject {object} at (100.58,5.55) size 138.88x69.44
+layer at (255,109) size 138x69
+  LayoutEmbeddedObject {object} at (100.58,5) size 138.88x69.44
     layer at (0,0) size 139x69
       LayoutView at (0,0) size 139x69
     layer at (0,0) size 139x69
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-svg-through-object-with-absolute-size-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-svg-through-object-with-absolute-size-expected.png
index a62f2a7c8..33fbbe3c 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-svg-through-object-with-absolute-size-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-svg-through-object-with-absolute-size-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-svg-through-object-with-absolute-size-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-svg-through-object-with-absolute-size-expected.txt
index 810fcc40..cf297a67 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-svg-through-object-with-absolute-size-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-svg-through-object-with-absolute-size-expected.txt
@@ -1,34 +1,34 @@
 layer at (0,0) size 800x600
   LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x204
-  LayoutBlockFlow {html} at (0,0) size 800x204.09
-    LayoutBlockFlow {body} at (5.55,5.55) size 788.91x193
-      LayoutTable {table} at (140.95,0) size 507x193
-        LayoutTableSection (anonymous) at (0,0) size 507x193
-          LayoutTableRow {tr} at (0,0) size 507x193
-            LayoutTableCell {td} at (0,0) size 507x192.88 [r=0 c=0 rs=1 cs=3]
-              LayoutTable {table} at (7,6.94) size 493x179
-                LayoutTableSection (anonymous) at (0,0) size 493x179
-                  LayoutTableRow {tr} at (0,1) size 493x67
-                    LayoutTableCell {td} at (1,1) size 491x66.84 [r=0 c=0 rs=1 cs=2]
-                      LayoutBlockFlow {h1} at (5.55,20.42) size 479.91x26
+layer at (0,0) size 800x198
+  LayoutBlockFlow {html} at (0,0) size 800x198.09
+    LayoutBlockFlow {body} at (5.55,5.55) size 788.91x187
+      LayoutTable {table} at (140.95,0) size 507x187
+        LayoutTableSection (anonymous) at (0,0) size 507x187
+          LayoutTableRow {tr} at (0,0) size 507x187
+            LayoutTableCell {td} at (0,0) size 507x187 [r=0 c=0 rs=1 cs=3]
+              LayoutTable {table} at (7,6) size 493x175
+                LayoutTableSection (anonymous) at (0,0) size 493x175
+                  LayoutTableRow {tr} at (0,1) size 493x66
+                    LayoutTableCell {td} at (1,1) size 491x65.75 [r=0 c=0 rs=1 cs=2]
+                      LayoutBlockFlow {h1} at (5.55,19.88) size 479.91x26
                         LayoutText {#text} at (0,0) size 480x26
                           text run at (0,0) width 480: "Both sides should have identical size after zooming"
-                  LayoutTableRow {tr} at (0,69) size 493x24
-                    LayoutTableCell {td} at (1,69) size 245x24.09 [r=1 c=0 rs=1 cs=1]
-                      LayoutText {#text} at (96,5) size 53x14
+                  LayoutTableRow {tr} at (0,68) size 493x23
+                    LayoutTableCell {td} at (1,68) size 245x23 [r=1 c=0 rs=1 cs=1]
+                      LayoutText {#text} at (96,5) size 53x13
                         text run at (96,5) width 53: "SVG Image"
-                    LayoutTableCell {td} at (247,69) size 245x24.09 [r=1 c=1 rs=1 cs=1]
-                      LayoutText {#text} at (96,5) size 53x14
+                    LayoutTableCell {td} at (247,68) size 245x23 [r=1 c=1 rs=1 cs=1]
+                      LayoutText {#text} at (96,5) size 53x13
                         text run at (96,5) width 53: "PNG Image"
-                  LayoutTableRow {tr} at (0,94) size 493x84
-                    LayoutTableCell {td} at (1,94) size 245x83.53 [r=2 c=0 rs=1 cs=1]
+                  LayoutTableRow {tr} at (0,92) size 493x82
+                    LayoutTableCell {td} at (1,92) size 245x82.44 [r=2 c=0 rs=1 cs=1]
                       LayoutText {#text} at (0,0) size 0x0
-                    LayoutTableCell {td} at (247,94) size 245x83.53 [r=2 c=1 rs=1 cs=1]
-                      LayoutImage {img} at (5.55,5.55) size 138.88x69.44
+                    LayoutTableCell {td} at (247,92) size 245x82.44 [r=2 c=1 rs=1 cs=1]
+                      LayoutImage {img} at (5.55,5) size 138.88x69.44
                       LayoutText {#text} at (0,0) size 0x0
-layer at (255,112) size 138x69
-  LayoutEmbeddedObject {object} at (100.58,5.55) size 138.88x69.44
+layer at (255,109) size 138x69
+  LayoutEmbeddedObject {object} at (100.58,5) size 138.88x69.44
     layer at (0,0) size 139x69
       LayoutView at (0,0) size 139x69
     layer at (0,0) size 139x69
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-svg-through-object-with-percentage-size-expected.png b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-svg-through-object-with-percentage-size-expected.png
index 7757e3a..48d301818 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-svg-through-object-with-percentage-size-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-svg-through-object-with-percentage-size-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-svg-through-object-with-percentage-size-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-svg-through-object-with-percentage-size-expected.txt
index 70b72677e..c8fd021 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-svg-through-object-with-percentage-size-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/zoom/page/zoom-svg-through-object-with-percentage-size-expected.txt
@@ -1,34 +1,34 @@
 layer at (0,0) size 800x600
   LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x384
-  LayoutBlockFlow {html} at (0,0) size 800x384.09
-    LayoutBlockFlow {body} at (5.55,5.55) size 788.91x373
-      LayoutTable {table} at (40.95,0) size 707x373
-        LayoutTableSection (anonymous) at (0,0) size 707x373
-          LayoutTableRow {tr} at (0,0) size 707x373
-            LayoutTableCell {td} at (0,0) size 707x372.88 [r=0 c=0 rs=1 cs=3]
-              LayoutTable {table} at (7,6.94) size 693x359
-                LayoutTableSection (anonymous) at (0,0) size 693x359
-                  LayoutTableRow {tr} at (0,1) size 693x67
-                    LayoutTableCell {td} at (1,1) size 691x66.84 [r=0 c=0 rs=1 cs=2]
-                      LayoutBlockFlow {h1} at (5.55,20.42) size 679.91x26
+layer at (0,0) size 800x379
+  LayoutBlockFlow {html} at (0,0) size 800x379.09
+    LayoutBlockFlow {body} at (5.55,5.55) size 788.91x368
+      LayoutTable {table} at (40.95,0) size 707x368
+        LayoutTableSection (anonymous) at (0,0) size 707x368
+          LayoutTableRow {tr} at (0,0) size 707x368
+            LayoutTableCell {td} at (0,0) size 707x368 [r=0 c=0 rs=1 cs=3]
+              LayoutTable {table} at (7,6) size 693x356
+                LayoutTableSection (anonymous) at (0,0) size 693x356
+                  LayoutTableRow {tr} at (0,1) size 693x66
+                    LayoutTableCell {td} at (1,1) size 691x65.75 [r=0 c=0 rs=1 cs=2]
+                      LayoutBlockFlow {h1} at (5.55,19.88) size 679.91x26
                         LayoutText {#text} at (100,0) size 480x26
                           text run at (100,0) width 480: "Both sides should have identical size after zooming"
-                  LayoutTableRow {tr} at (0,69) size 693x24
-                    LayoutTableCell {td} at (1,69) size 345x24.09 [r=1 c=0 rs=1 cs=1]
-                      LayoutText {#text} at (146,5) size 53x14
+                  LayoutTableRow {tr} at (0,68) size 693x23
+                    LayoutTableCell {td} at (1,68) size 345x23 [r=1 c=0 rs=1 cs=1]
+                      LayoutText {#text} at (146,5) size 53x13
                         text run at (146,5) width 53: "SVG Image"
-                    LayoutTableCell {td} at (347,69) size 345x24.09 [r=1 c=1 rs=1 cs=1]
-                      LayoutText {#text} at (146,5) size 53x14
+                    LayoutTableCell {td} at (347,68) size 345x23 [r=1 c=1 rs=1 cs=1]
+                      LayoutText {#text} at (146,5) size 53x13
                         text run at (146,5) width 53: "PNG Image"
-                  LayoutTableRow {tr} at (0,94) size 693x264
-                    LayoutTableCell {td} at (1,94) size 345x264.08 [r=2 c=0 rs=1 cs=1]
+                  LayoutTableRow {tr} at (0,92) size 693x263
+                    LayoutTableCell {td} at (1,92) size 345x262.98 [r=2 c=0 rs=1 cs=1]
                       LayoutText {#text} at (0,0) size 0x0
-                    LayoutTableCell {td} at (347,94) size 345x264.06 [r=2 c=1 rs=1 cs=1]
-                      LayoutImage {img} at (5.55,5.55) size 333.33x249.97
+                    LayoutTableCell {td} at (347,92) size 345x262.97 [r=2 c=1 rs=1 cs=1]
+                      LayoutImage {img} at (5.55,5) size 333.33x249.97
                       LayoutText {#text} at (0,0) size 0x0
-layer at (61,112) size 333x250
-  LayoutEmbeddedObject {object} at (6.13,5.55) size 333.33x249.98
+layer at (61,109) size 333x250
+  LayoutEmbeddedObject {object} at (6.13,5) size 333.33x249.98
     layer at (0,0) size 333x250
       LayoutView at (0,0) size 333x250
     layer at (0,0) size 333x250
diff --git a/third_party/WebKit/LayoutTests/platform/mac/transforms/2d/hindi-rotated-expected.png b/third_party/WebKit/LayoutTests/platform/mac/transforms/2d/hindi-rotated-expected.png
index 40d9a06..228c645 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/transforms/2d/hindi-rotated-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/transforms/2d/hindi-rotated-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/transforms/bounding-rect-zoom-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/transforms/bounding-rect-zoom-expected.txt
index 0520a72..1b09754 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/transforms/bounding-rect-zoom-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/transforms/bounding-rect-zoom-expected.txt
@@ -9,14 +9,14 @@
         LayoutBR {BR} at (307,13) size 1x0
         LayoutText {#text} at (0,17) size 179x17
           text run at (0,17) width 179: "There should be no red visible."
-      LayoutTable {TABLE} at (0,48.39) size 785x21
-        LayoutTableSection {TBODY} at (0,0) size 785x21
-          LayoutTableRow {TR} at (0,1) size 785x19
-            LayoutTableCell {TD} at (1,1) size 181x18.78 [r=0 c=0 rs=1 cs=1]
-              LayoutText {#text} at (0,0) size 151x18
+      LayoutTable {TABLE} at (0,48.39) size 785x19
+        LayoutTableSection {TBODY} at (0,0) size 785x19
+          LayoutTableRow {TR} at (0,1) size 785x17
+            LayoutTableCell {TD} at (1,1) size 181x17 [r=0 c=0 rs=1 cs=1]
+              LayoutText {#text} at (0,0) size 151x17
                 text run at (0,0) width 151: "getClientBoundingRect():"
-            LayoutTableCell {TD} at (183,1) size 601x18.78 [r=0 c=1 rs=1 cs=1]
-              LayoutText {#text} at (0,0) size 100x18
+            LayoutTableCell {TD} at (183,1) size 601x17 [r=0 c=1 rs=1 cs=1]
+              LayoutText {#text} at (0,0) size 100x17
                 text run at (0,0) width 100: "getClientRects():"
 layer at (90,90) size 90x90
   LayoutBlockFlow (positioned) {DIV} at (90,90) size 90x90 [bgcolor=#FF0000]
diff --git a/third_party/WebKit/LayoutTests/platform/mac/transforms/transform-on-inline-expected.png b/third_party/WebKit/LayoutTests/platform/mac/transforms/transform-on-inline-expected.png
index bd5999b..5d1c40ad9 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/transforms/transform-on-inline-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/transforms/transform-on-inline-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/sibling-positioning-expected.png b/third_party/WebKit/LayoutTests/platform/win/compositing/sibling-positioning-expected.png
index a52e226..9dd1422 100644
--- a/third_party/WebKit/LayoutTests/platform/win/compositing/sibling-positioning-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/compositing/sibling-positioning-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/video-frame-size-change-expected.png b/third_party/WebKit/LayoutTests/platform/win/compositing/video-frame-size-change-expected.png
index 0097a407..b512846 100644
--- a/third_party/WebKit/LayoutTests/platform/win/compositing/video-frame-size-change-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/compositing/video-frame-size-change-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/video/video-reflection-expected.png b/third_party/WebKit/LayoutTests/platform/win/compositing/video/video-reflection-expected.png
index 69bd2df..e97cb570 100644
--- a/third_party/WebKit/LayoutTests/platform/win/compositing/video/video-reflection-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/compositing/video/video-reflection-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/composition-underline-color-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/composition-underline-color-expected.png
new file mode 100644
index 0000000..facd377
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/editing/composition-underline-color-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/composition-underline-color-expected.txt b/third_party/WebKit/LayoutTests/platform/win/editing/composition-underline-color-expected.txt
new file mode 100644
index 0000000..6852ef4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/editing/composition-underline-color-expected.txt
@@ -0,0 +1,13 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x200
+  LayoutBlockFlow {HTML} at (0,0) size 800x200
+    LayoutBlockFlow {BODY} at (8,16) size 784x176
+      LayoutBlockFlow {P} at (0,0) size 784x40
+        LayoutText {#text} at (0,0) size 770x39
+          text run at (0,0) width 770: "This test checks that composition underline color uses the color of the text and is not always black. The test passes if you see the"
+          text run at (0,20) width 422: "word \"foobar\" in green with a composition underline in the same color."
+      LayoutBlockFlow {DIV} at (0,56) size 784x120 [color=#00FF00] [bgcolor=#000000]
+        LayoutText {#text} at (50,50) size 40x19
+          text run at (50,50) width 40: "foobar"
+caret: position 6 of child 0 {#text} of child 2 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win/external/wpt/css/css-font-loading/idlharness.https-expected.txt b/third_party/WebKit/LayoutTests/platform/win/external/wpt/css/css-font-loading/idlharness.https-expected.txt
deleted file mode 100644
index 2bf96bb..0000000
--- a/third_party/WebKit/LayoutTests/platform/win/external/wpt/css/css-font-loading/idlharness.https-expected.txt
+++ /dev/null
@@ -1,78 +0,0 @@
-main frame - didStartProvisionalLoadForFrame
-main frame - didCommitLoadForFrame
-main frame - didReceiveTitle: Font Loading API IDL tests
-main frame - didFinishDocumentLoadForFrame
-main frame - didHandleOnloadEventsForFrame
-main frame - didFinishLoadForFrame
-This is a testharness.js-based test.
-PASS Test IDL implementation of CSS Font Loading
-PASS Document interface: attribute fonts
-PASS Unscopable handled correctly for fonts property on Document
-PASS Document interface: document must inherit property "fonts" with the proper type
-PASS WorkerGlobalScope interface: existence and properties of interface object
-PASS FontFace interface: existence and properties of interface object
-PASS FontFace interface object length
-PASS FontFace interface object name
-PASS FontFace interface: existence and properties of interface prototype object
-PASS FontFace interface: existence and properties of interface prototype object's "constructor" property
-PASS FontFace interface: existence and properties of interface prototype object's @@unscopables property
-PASS FontFace interface: attribute family
-PASS Unscopable handled correctly for family property on FontFace
-PASS FontFace interface: attribute style
-PASS Unscopable handled correctly for style property on FontFace
-PASS FontFace interface: attribute weight
-PASS Unscopable handled correctly for weight property on FontFace
-PASS FontFace interface: attribute stretch
-PASS Unscopable handled correctly for stretch property on FontFace
-PASS FontFace interface: attribute unicodeRange
-PASS Unscopable handled correctly for unicodeRange property on FontFace
-PASS FontFace interface: attribute variant
-PASS Unscopable handled correctly for variant property on FontFace
-PASS FontFace interface: attribute featureSettings
-PASS Unscopable handled correctly for featureSettings property on FontFace
-FAIL FontFace interface: attribute variationSettings assert_true: The prototype object must have a property "variationSettings" expected true got false
-PASS Unscopable handled correctly for variationSettings property on FontFace
-PASS FontFace interface: attribute display
-PASS Unscopable handled correctly for display property on FontFace
-PASS FontFace interface: attribute status
-PASS Unscopable handled correctly for status property on FontFace
-PASS FontFace interface: operation load()
-PASS Unscopable handled correctly for load() on FontFace
-PASS FontFace interface: attribute loaded
-PASS Unscopable handled correctly for loaded property on FontFace
-PASS FontFaceSetLoadEvent interface: existence and properties of interface object
-PASS FontFaceSetLoadEvent interface object length
-PASS FontFaceSetLoadEvent interface object name
-PASS FontFaceSetLoadEvent interface: existence and properties of interface prototype object
-PASS FontFaceSetLoadEvent interface: existence and properties of interface prototype object's "constructor" property
-PASS FontFaceSetLoadEvent interface: existence and properties of interface prototype object's @@unscopables property
-PASS FontFaceSetLoadEvent interface: attribute fontfaces
-PASS Unscopable handled correctly for fontfaces property on FontFaceSetLoadEvent
-FAIL FontFaceSet interface: existence and properties of interface object assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-FAIL FontFaceSet interface object length assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-FAIL FontFaceSet interface object name assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-FAIL FontFaceSet interface: existence and properties of interface prototype object assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-FAIL FontFaceSet interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-FAIL FontFaceSet interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-FAIL FontFaceSet interface: operation add(FontFace) assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-PASS Unscopable handled correctly for add(FontFace) on FontFaceSet
-FAIL FontFaceSet interface: operation delete(FontFace) assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-PASS Unscopable handled correctly for delete(FontFace) on FontFaceSet
-FAIL FontFaceSet interface: operation clear() assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-PASS Unscopable handled correctly for clear() on FontFaceSet
-FAIL FontFaceSet interface: attribute onloading assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-PASS Unscopable handled correctly for onloading property on FontFaceSet
-FAIL FontFaceSet interface: attribute onloadingdone assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-PASS Unscopable handled correctly for onloadingdone property on FontFaceSet
-FAIL FontFaceSet interface: attribute onloadingerror assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-PASS Unscopable handled correctly for onloadingerror property on FontFaceSet
-FAIL FontFaceSet interface: operation load(CSSOMString, CSSOMString) assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-PASS Unscopable handled correctly for load(CSSOMString, CSSOMString) on FontFaceSet
-FAIL FontFaceSet interface: operation check(CSSOMString, CSSOMString) assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-PASS Unscopable handled correctly for check(CSSOMString, CSSOMString) on FontFaceSet
-FAIL FontFaceSet interface: attribute ready assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-PASS Unscopable handled correctly for ready property on FontFaceSet
-FAIL FontFaceSet interface: attribute status assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-PASS Unscopable handled correctly for status property on FontFaceSet
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/platform/win/external/wpt/css/css-transitions/properties-value-auto-001-expected.txt b/third_party/WebKit/LayoutTests/platform/win/external/wpt/css/css-transitions/properties-value-auto-001-expected.txt
new file mode 100644
index 0000000..9fd1775
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/external/wpt/css/css-transitions/properties-value-auto-001-expected.txt
@@ -0,0 +1,56 @@
+This is a testharness.js-based test.
+Found 52 tests; 0 PASS, 52 FAIL, 0 TIMEOUT, 0 NOTRUN.
+FAIL margin-top auto(to) / values assert_not_equals: must not be target value after start got disallowed value "0px"
+FAIL margin-top auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "margin-top:0.5s" but got ""
+FAIL margin-top auto(from) / values assert_not_equals: must not be target value after start got disallowed value "13.3333px"
+FAIL margin-top auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "margin-top:0.5s" but got ""
+FAIL margin-right auto(to) / values assert_not_equals: must not be target value after start got disallowed value "0px"
+FAIL margin-right auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "margin-right:0.5s" but got ""
+FAIL margin-right auto(from) / values assert_not_equals: must not be target value after start got disallowed value "13.3333px"
+FAIL margin-right auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "margin-right:0.5s" but got ""
+FAIL margin-bottom auto(to) / values assert_not_equals: must not be target value after start got disallowed value "0px"
+FAIL margin-bottom auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "margin-bottom:0.5s" but got ""
+FAIL margin-bottom auto(from) / values assert_not_equals: must not be target value after start got disallowed value "13.3333px"
+FAIL margin-bottom auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "margin-bottom:0.5s" but got ""
+FAIL margin-left auto(to) / values assert_not_equals: must not be target value after start got disallowed value "0px"
+FAIL margin-left auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "margin-left:0.5s" but got ""
+FAIL margin-left auto(from) / values assert_not_equals: must not be target value after start got disallowed value "13.3333px"
+FAIL margin-left auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "margin-left:0.5s" but got ""
+FAIL height auto(to) / values assert_not_equals: must not be target value after start got disallowed value "20px"
+FAIL height auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "height:0.5s" but got ""
+FAIL height auto(from) / values assert_not_equals: must not be target value after start got disallowed value "13.3281px"
+FAIL height auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "height:0.5s" but got ""
+FAIL width auto(to) / values assert_not_equals: must not be target value after start got disallowed value "100px"
+FAIL width auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "width:0.5s" but got ""
+FAIL width auto(from) / values assert_not_equals: must not be target value after start got disallowed value "13.3281px"
+FAIL width auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "width:0.5s" but got ""
+FAIL clip auto(to) / values assert_not_equals: must not be target value after start got disallowed value "auto"
+FAIL clip auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "clip:0.5s" but got ""
+FAIL clip auto(from) / values assert_not_equals: must not be target value after start got disallowed value "rect(15px, 15px, 5px, 5px)"
+FAIL clip auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "clip:0.5s" but got ""
+FAIL marker-offset auto(to) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL marker-offset auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "marker-offset:0.5s" but got ""
+FAIL marker-offset auto(from) / values assert_not_equals: initial and target values may not match got disallowed value ""
+FAIL marker-offset auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "marker-offset:0.5s" but got ""
+FAIL top auto(to) / values assert_not_equals: must not be target value after start got disallowed value "0px"
+FAIL top auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "top:0.5s" but got ""
+FAIL top auto(from) / values assert_not_equals: must not be target value after start got disallowed value "13.3333px"
+FAIL top auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "top:0.5s" but got ""
+FAIL right auto(to) / values assert_not_equals: must not be target value after start got disallowed value "28px"
+FAIL right auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "right:0.5s" but got ""
+FAIL right auto(from) / values assert_not_equals: must not be target value after start got disallowed value "13.3333px"
+FAIL right auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "right:0.5s" but got ""
+FAIL left auto(to) / values assert_not_equals: must not be target value after start got disallowed value "0px"
+FAIL left auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "left:0.5s" but got ""
+FAIL left auto(from) / values assert_not_equals: must not be target value after start got disallowed value "13.3333px"
+FAIL left auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "left:0.5s" but got ""
+FAIL bottom auto(to) / values assert_not_equals: must not be target value after start got disallowed value "80px"
+FAIL bottom auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "bottom:0.5s" but got ""
+FAIL bottom auto(from) / values assert_not_equals: must not be target value after start got disallowed value "13.3333px"
+FAIL bottom auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "bottom:0.5s" but got ""
+FAIL z-index auto(to) / values assert_not_equals: must not be target value after start got disallowed value "auto"
+FAIL z-index auto(to) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "z-index:0.5s" but got ""
+FAIL z-index auto(from) / values assert_not_equals: must not be target value after start got disallowed value "10"
+FAIL z-index auto(from) / events assert_equals: Expected TransitionEnd events triggered on .transition expected "z-index:0.5s" but got ""
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/borders/border-radius-mask-video-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/borders/border-radius-mask-video-expected.png
index b699fab..98e10fd 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/borders/border-radius-mask-video-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/borders/border-radius-mask-video-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/borders/border-radius-mask-video-ratio-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/borders/border-radius-mask-video-ratio-expected.png
index 3941c380..986a73e 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/borders/border-radius-mask-video-ratio-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/borders/border-radius-mask-video-ratio-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/borders/border-radius-mask-video-shadow-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/borders/border-radius-mask-video-shadow-expected.png
index 1e1f1c74..8b6831f 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/borders/border-radius-mask-video-shadow-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/borders/border-radius-mask-video-shadow-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/css/ZeroOpacityLayers-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/css/ZeroOpacityLayers-expected.png
index 31a560e..a5df9bb 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/css/ZeroOpacityLayers-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/css/ZeroOpacityLayers-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/css/ZeroOpacityLayers2-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/css/ZeroOpacityLayers2-expected.png
index c5af46c..5358858 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/css/ZeroOpacityLayers2-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/css/ZeroOpacityLayers2-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/layers/remove-layer-with-nested-stacking-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/layers/remove-layer-with-nested-stacking-expected.png
index cebda39..cf0cddf8 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/layers/remove-layer-with-nested-stacking-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/layers/remove-layer-with-nested-stacking-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/table/multiple-captions-display-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/table/multiple-captions-display-expected.png
index be821c7..07382118 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/table/multiple-captions-display-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/table/multiple-captions-display-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/text/complex-text-opacity-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/text/complex-text-opacity-expected.png
index 36f2a39..c48a456a 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/text/complex-text-opacity-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/text/complex-text-opacity-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/hdr/color-profile-video-expected.png b/third_party/WebKit/LayoutTests/platform/win/hdr/color-profile-video-expected.png
new file mode 100644
index 0000000..ccce5e4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/hdr/color-profile-video-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/hdr/video-canvas-alpha-expected.png b/third_party/WebKit/LayoutTests/platform/win/hdr/video-canvas-alpha-expected.png
new file mode 100644
index 0000000..37ccdbf
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/hdr/video-canvas-alpha-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/color-profile-video-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/color-profile-video-expected.png
index 3dc10d8..dd75b4b 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/color-profile-video-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/media/color-profile-video-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/color-profile-video-seek-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/color-profile-video-seek-expected.png
index 9b77569..34526ee 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/color-profile-video-seek-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/media/color-profile-video-seek-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/color-profile-video-seek-filter-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/color-profile-video-seek-filter-expected.png
index 8c95422..113a0811 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/color-profile-video-seek-filter-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/media/color-profile-video-seek-filter-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/color-profile-video-seek-object-fit-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/color-profile-video-seek-object-fit-expected.png
index 73d0bcf1..dffb76a 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/color-profile-video-seek-object-fit-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/media/color-profile-video-seek-object-fit-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/controls-after-reload-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/controls-after-reload-expected.png
index 58cd524e..717c51db 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/controls-after-reload-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/media/controls-after-reload-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/controls-strict-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/controls-strict-expected.png
index 3227315..c59c0fd 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/controls-strict-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/media/controls-strict-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/controls-styling-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/controls-styling-expected.png
index cfad00c..cdf8612 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/controls-styling-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/media/controls-styling-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/controls-styling-strict-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/controls-styling-strict-expected.png
index 535b12b7..7a090564 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/controls-styling-strict-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/media/controls-styling-strict-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/controls-without-preload-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/controls-without-preload-expected.png
index b749a6d..7742c5b 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/controls-without-preload-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/media/controls-without-preload-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/controls/lazy-loaded-style-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/controls/lazy-loaded-style-expected.png
index cca34db..f51612ad 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/controls/lazy-loaded-style-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/media/controls/lazy-loaded-style-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/controls/video-overlay-cast-dark-rendering-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/controls/video-overlay-cast-dark-rendering-expected.png
index a4d2403..3fa715ed 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/controls/video-overlay-cast-dark-rendering-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/media/controls/video-overlay-cast-dark-rendering-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/track/track-cue-rendering-horizontal-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/track/track-cue-rendering-horizontal-expected.png
index 5fa92e6..021412e 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/track/track-cue-rendering-horizontal-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/media/track/track-cue-rendering-horizontal-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/track/track-cue-rendering-vertical-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/track/track-cue-rendering-vertical-expected.png
index ce63cf77..bf871e7 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/track/track-cue-rendering-vertical-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/media/track/track-cue-rendering-vertical-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/video-aspect-ratio-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/video-aspect-ratio-expected.png
index 2ea706d9b..d330366 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/video-aspect-ratio-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/media/video-aspect-ratio-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/video-canvas-alpha-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/video-canvas-alpha-expected.png
index 875e0a2a..c35a9743 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/video-canvas-alpha-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/media/video-canvas-alpha-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/video-controls-rendering-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/video-controls-rendering-expected.png
index 54608f6..692eba4 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/video-controls-rendering-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/media/video-controls-rendering-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/video-display-toggle-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/video-display-toggle-expected.png
index 4ec2f2b..90527add 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/video-display-toggle-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/media/video-display-toggle-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/video-layer-crash-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/video-layer-crash-expected.png
index ec98eb1..f0a5be86 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/video-layer-crash-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/media/video-layer-crash-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/video-remove-insert-repaints-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/video-remove-insert-repaints-expected.png
index 2869b87..1a19a91 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/video-remove-insert-repaints-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/media/video-remove-insert-repaints-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/video-replaces-poster-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/video-replaces-poster-expected.png
index 9e350ce..8d1cd52d 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/video-replaces-poster-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/media/video-replaces-poster-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/video-transformed-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/video-transformed-expected.png
index 7eec14a..c30d6211 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/video-transformed-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/media/video-transformed-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/video-zoom-controls-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/video-zoom-controls-expected.png
index 80c8762..7696fd2 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/video-zoom-controls-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/media/video-zoom-controls-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/media/video-zoom-expected.png b/third_party/WebKit/LayoutTests/platform/win/media/video-zoom-expected.png
index 64cbe7cf..ceea35d 100644
--- a/third_party/WebKit/LayoutTests/platform/win/media/video-zoom-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/media/video-zoom-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/as-background-image/svg-as-background-6-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/as-background-image/svg-as-background-6-expected.png
index b2c78b2..03fe6d0 100644
--- a/third_party/WebKit/LayoutTests/platform/win/svg/as-background-image/svg-as-background-6-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/svg/as-background-image/svg-as-background-6-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/textFeatures-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/textFeatures-expected.png
index f8ec1328..b7e7755b9 100644
--- a/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/textFeatures-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/svg/batik/text/textFeatures-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/custom/text-image-opacity-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/custom/text-image-opacity-expected.png
index 4a2ef56..54bca81 100644
--- a/third_party/WebKit/LayoutTests/platform/win/svg/custom/text-image-opacity-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/svg/custom/text-image-opacity-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png
index 4443be37..c155bf0 100644
--- a/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.txt b/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.txt
index c525263..11d07f9 100644
--- a/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.txt
@@ -1,106 +1,106 @@
 layer at (0,0) size 800x600
   LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x348
-  LayoutBlockFlow {HTML} at (0,0) size 800x348.09
-    LayoutBlockFlow {BODY} at (5.55,5.55) size 788.91x337
-      LayoutTable {TABLE} at (0,0) size 471x337
-        LayoutTableSection {TBODY} at (0,0) size 471x337
-          LayoutTableRow {TR} at (0,1) size 471x15
-            LayoutTableCell {TH} at (1,1) size 65x15.38 [bgcolor=#DDDD99] [r=0 c=0 rs=1 cs=1]
-              LayoutText {#text} at (6,0) size 53x15
+layer at (0,0) size 800x339
+  LayoutBlockFlow {HTML} at (0,0) size 800x339.09
+    LayoutBlockFlow {BODY} at (5.55,5.55) size 788.91x328
+      LayoutTable {TABLE} at (0,0) size 471x328
+        LayoutTableSection {TBODY} at (0,0) size 471x328
+          LayoutTableRow {TR} at (0,1) size 471x14
+            LayoutTableCell {TH} at (1,1) size 65x14 [bgcolor=#DDDD99] [r=0 c=0 rs=1 cs=1]
+              LayoutText {#text} at (6,0) size 53x14
                 text run at (6,0) width 53: "viewBox?"
-            LayoutTableCell {TH} at (67,1) size 119x15.38 [bgcolor=#DDDD99] [r=0 c=1 rs=1 cs=1]
-              LayoutText {#text} at (1,0) size 117x15
+            LayoutTableCell {TH} at (67,1) size 119x14 [bgcolor=#DDDD99] [r=0 c=1 rs=1 cs=1]
+              LayoutText {#text} at (1,0) size 117x14
                 text run at (1,0) width 117: "preserve\x{AD}Aspect\x{AD}Ratio"
-            LayoutTableCell {TH} at (187,1) size 141x15.38 [bgcolor=#DDDD99] [r=0 c=2 rs=1 cs=1]
-              LayoutText {#text} at (54,0) size 33x15
+            LayoutTableCell {TH} at (187,1) size 141x14 [bgcolor=#DDDD99] [r=0 c=2 rs=1 cs=1]
+              LayoutText {#text} at (54,0) size 33x14
                 text run at (54,0) width 33: "<img>"
-            LayoutTableCell {TH} at (329,1) size 141x15.38 [bgcolor=#DDDD99] [r=0 c=3 rs=1 cs=1]
-              LayoutText {#text} at (47,0) size 47x15
+            LayoutTableCell {TH} at (329,1) size 141x14 [bgcolor=#DDDD99] [r=0 c=3 rs=1 cs=1]
+              LayoutText {#text} at (47,0) size 47x14
                 text run at (47,0) width 47: "<object>"
-          LayoutTableRow {TR} at (0,17) size 471x39
-            LayoutTableCell {TH} at (1,89) size 65x15.38 [bgcolor=#DDDD99] [r=1 c=0 rs=4 cs=1]
-              LayoutText {#text} at (1,0) size 63x15
+          LayoutTableRow {TR} at (0,16) size 471x38
+            LayoutTableCell {TH} at (1,86) size 65x14 [bgcolor=#DDDD99] [r=1 c=0 rs=4 cs=1]
+              LayoutText {#text} at (1,0) size 63x14
                 text run at (1,0) width 63: "No viewBox"
-            LayoutTableCell {TH} at (67,36) size 119x1.38 [bgcolor=#DDDD99] [r=1 c=1 rs=1 cs=1]
-            LayoutTableCell {TD} at (187,17) size 141x39.09 [r=1 c=2 rs=1 cs=1]
-              LayoutImage {IMG} at (0.69,0.69) size 138.88x34.72 [border: (1.38px dashed #800000)]
+            LayoutTableCell {TH} at (67,35) size 119x0 [bgcolor=#DDDD99] [r=1 c=1 rs=1 cs=1]
+            LayoutTableCell {TD} at (187,16) size 141x37.72 [r=1 c=2 rs=1 cs=1]
+              LayoutImage {IMG} at (0.69,0) size 138.88x34.72 [border: (1.38px dashed #800000)]
               LayoutText {#text} at (0,0) size 0x0
-            LayoutTableCell {TD} at (329,17) size 141x39.09 [r=1 c=3 rs=1 cs=1]
+            LayoutTableCell {TD} at (329,16) size 141x37.72 [r=1 c=3 rs=1 cs=1]
               LayoutText {#text} at (0,0) size 0x0
-          LayoutTableRow {TR} at (0,57) size 471x39
-            LayoutTableCell {TH} at (67,69) size 119x15.38 [bgcolor=#DDDD99] [r=2 c=1 rs=1 cs=1]
-              LayoutText {#text} at (45,0) size 29x15
+          LayoutTableRow {TR} at (0,55) size 471x38
+            LayoutTableCell {TH} at (67,67) size 119x14 [bgcolor=#DDDD99] [r=2 c=1 rs=1 cs=1]
+              LayoutText {#text} at (45,0) size 29x14
                 text run at (45,0) width 29: "none"
-            LayoutTableCell {TD} at (187,57) size 141x39.09 [r=2 c=2 rs=1 cs=1]
-              LayoutImage {IMG} at (0.69,0.69) size 138.88x34.72 [border: (1.38px dashed #800000)]
+            LayoutTableCell {TD} at (187,55) size 141x37.72 [r=2 c=2 rs=1 cs=1]
+              LayoutImage {IMG} at (0.69,0) size 138.88x34.72 [border: (1.38px dashed #800000)]
               LayoutText {#text} at (0,0) size 0x0
-            LayoutTableCell {TD} at (329,57) size 141x39.09 [r=2 c=3 rs=1 cs=1]
+            LayoutTableCell {TD} at (329,55) size 141x37.72 [r=2 c=3 rs=1 cs=1]
               LayoutText {#text} at (0,0) size 0x0
-          LayoutTableRow {TR} at (0,97) size 471x39
-            LayoutTableCell {TH} at (67,109) size 119x15.38 [bgcolor=#DDDD99] [r=3 c=1 rs=1 cs=1]
-              LayoutText {#text} at (45,0) size 29x15
+          LayoutTableRow {TR} at (0,94) size 471x38
+            LayoutTableCell {TH} at (67,106) size 119x14 [bgcolor=#DDDD99] [r=3 c=1 rs=1 cs=1]
+              LayoutText {#text} at (45,0) size 29x14
                 text run at (45,0) width 29: "meet"
-            LayoutTableCell {TD} at (187,97) size 141x39.09 [r=3 c=2 rs=1 cs=1]
-              LayoutImage {IMG} at (0.69,0.69) size 138.88x34.72 [border: (1.38px dashed #800000)]
+            LayoutTableCell {TD} at (187,94) size 141x37.72 [r=3 c=2 rs=1 cs=1]
+              LayoutImage {IMG} at (0.69,0) size 138.88x34.72 [border: (1.38px dashed #800000)]
               LayoutText {#text} at (0,0) size 0x0
-            LayoutTableCell {TD} at (329,97) size 141x39.09 [r=3 c=3 rs=1 cs=1]
+            LayoutTableCell {TD} at (329,94) size 141x37.72 [r=3 c=3 rs=1 cs=1]
               LayoutText {#text} at (0,0) size 0x0
-          LayoutTableRow {TR} at (0,137) size 471x39
-            LayoutTableCell {TH} at (67,149) size 119x15.38 [bgcolor=#DDDD99] [r=4 c=1 rs=1 cs=1]
-              LayoutText {#text} at (46,0) size 27x15
+          LayoutTableRow {TR} at (0,133) size 471x38
+            LayoutTableCell {TH} at (67,145) size 119x14 [bgcolor=#DDDD99] [r=4 c=1 rs=1 cs=1]
+              LayoutText {#text} at (46,0) size 27x14
                 text run at (46,0) width 27: "slice"
-            LayoutTableCell {TD} at (187,137) size 141x39.09 [r=4 c=2 rs=1 cs=1]
-              LayoutImage {IMG} at (0.69,0.69) size 138.88x34.72 [border: (1.38px dashed #800000)]
+            LayoutTableCell {TD} at (187,133) size 141x37.72 [r=4 c=2 rs=1 cs=1]
+              LayoutImage {IMG} at (0.69,0) size 138.88x34.72 [border: (1.38px dashed #800000)]
               LayoutText {#text} at (0,0) size 0x0
-            LayoutTableCell {TD} at (329,137) size 141x39.09 [r=4 c=3 rs=1 cs=1]
+            LayoutTableCell {TD} at (329,133) size 141x37.72 [r=4 c=3 rs=1 cs=1]
               LayoutText {#text} at (0,0) size 0x0
-          LayoutTableRow {TR} at (0,177) size 471x39
-            LayoutTableCell {TH} at (1,249) size 65x15.38 [bgcolor=#DDDD99] [r=5 c=0 rs=4 cs=1]
-              LayoutText {#text} at (9,0) size 47x15
+          LayoutTableRow {TR} at (0,172) size 471x38
+            LayoutTableCell {TH} at (1,242) size 65x14 [bgcolor=#DDDD99] [r=5 c=0 rs=4 cs=1]
+              LayoutText {#text} at (9,0) size 47x14
                 text run at (9,0) width 47: "viewBox"
-            LayoutTableCell {TH} at (67,196) size 119x1.38 [bgcolor=#DDDD99] [r=5 c=1 rs=1 cs=1]
-            LayoutTableCell {TD} at (187,177) size 141x39.09 [r=5 c=2 rs=1 cs=1]
-              LayoutImage {IMG} at (0.69,0.69) size 138.88x34.72 [border: (1.38px dashed #800000)]
+            LayoutTableCell {TH} at (67,191) size 119x0 [bgcolor=#DDDD99] [r=5 c=1 rs=1 cs=1]
+            LayoutTableCell {TD} at (187,172) size 141x37.72 [r=5 c=2 rs=1 cs=1]
+              LayoutImage {IMG} at (0.69,0) size 138.88x34.72 [border: (1.38px dashed #800000)]
               LayoutText {#text} at (0,0) size 0x0
-            LayoutTableCell {TD} at (329,177) size 141x39.09 [r=5 c=3 rs=1 cs=1]
+            LayoutTableCell {TD} at (329,172) size 141x37.72 [r=5 c=3 rs=1 cs=1]
               LayoutText {#text} at (0,0) size 0x0
-          LayoutTableRow {TR} at (0,217) size 471x39
-            LayoutTableCell {TH} at (67,229) size 119x15.38 [bgcolor=#DDDD99] [r=6 c=1 rs=1 cs=1]
-              LayoutText {#text} at (45,0) size 29x15
+          LayoutTableRow {TR} at (0,211) size 471x38
+            LayoutTableCell {TH} at (67,223) size 119x14 [bgcolor=#DDDD99] [r=6 c=1 rs=1 cs=1]
+              LayoutText {#text} at (45,0) size 29x14
                 text run at (45,0) width 29: "none"
-            LayoutTableCell {TD} at (187,217) size 141x39.09 [r=6 c=2 rs=1 cs=1]
-              LayoutImage {IMG} at (0.69,0.69) size 138.88x34.72 [border: (1.38px dashed #800000)]
+            LayoutTableCell {TD} at (187,211) size 141x37.72 [r=6 c=2 rs=1 cs=1]
+              LayoutImage {IMG} at (0.69,0) size 138.88x34.72 [border: (1.38px dashed #800000)]
               LayoutText {#text} at (0,0) size 0x0
-            LayoutTableCell {TD} at (329,217) size 141x39.09 [r=6 c=3 rs=1 cs=1]
+            LayoutTableCell {TD} at (329,211) size 141x37.72 [r=6 c=3 rs=1 cs=1]
               LayoutText {#text} at (0,0) size 0x0
-          LayoutTableRow {TR} at (0,257) size 471x39
-            LayoutTableCell {TH} at (67,269) size 119x15.38 [bgcolor=#DDDD99] [r=7 c=1 rs=1 cs=1]
-              LayoutText {#text} at (45,0) size 29x15
+          LayoutTableRow {TR} at (0,250) size 471x38
+            LayoutTableCell {TH} at (67,262) size 119x14 [bgcolor=#DDDD99] [r=7 c=1 rs=1 cs=1]
+              LayoutText {#text} at (45,0) size 29x14
                 text run at (45,0) width 29: "meet"
-            LayoutTableCell {TD} at (187,257) size 141x39.09 [r=7 c=2 rs=1 cs=1]
-              LayoutImage {IMG} at (0.69,0.69) size 138.88x34.72 [border: (1.38px dashed #800000)]
+            LayoutTableCell {TD} at (187,250) size 141x37.72 [r=7 c=2 rs=1 cs=1]
+              LayoutImage {IMG} at (0.69,0) size 138.88x34.72 [border: (1.38px dashed #800000)]
               LayoutText {#text} at (0,0) size 0x0
-            LayoutTableCell {TD} at (329,257) size 141x39.09 [r=7 c=3 rs=1 cs=1]
+            LayoutTableCell {TD} at (329,250) size 141x37.72 [r=7 c=3 rs=1 cs=1]
               LayoutText {#text} at (0,0) size 0x0
-          LayoutTableRow {TR} at (0,297) size 471x39
-            LayoutTableCell {TH} at (67,309) size 119x15.38 [bgcolor=#DDDD99] [r=8 c=1 rs=1 cs=1]
-              LayoutText {#text} at (46,0) size 27x15
+          LayoutTableRow {TR} at (0,289) size 471x38
+            LayoutTableCell {TH} at (67,301) size 119x14 [bgcolor=#DDDD99] [r=8 c=1 rs=1 cs=1]
+              LayoutText {#text} at (46,0) size 27x14
                 text run at (46,0) width 27: "slice"
-            LayoutTableCell {TD} at (187,297) size 141x39.09 [r=8 c=2 rs=1 cs=1]
-              LayoutImage {IMG} at (0.69,0.69) size 138.88x34.72 [border: (1.38px dashed #800000)]
+            LayoutTableCell {TD} at (187,289) size 141x37.72 [r=8 c=2 rs=1 cs=1]
+              LayoutImage {IMG} at (0.69,0) size 138.88x34.72 [border: (1.38px dashed #800000)]
               LayoutText {#text} at (0,0) size 0x0
-            LayoutTableCell {TD} at (329,297) size 141x39.09 [r=8 c=3 rs=1 cs=1]
+            LayoutTableCell {TD} at (329,289) size 141x37.72 [r=8 c=3 rs=1 cs=1]
               LayoutText {#text} at (0,0) size 0x0
-layer at (335,23) size 139x34
-  LayoutEmbeddedObject {OBJECT} at (0.69,0.69) size 138.88x34.72 [border: (0.69px dashed #008000)]
+layer at (335,22) size 139x35
+  LayoutEmbeddedObject {OBJECT} at (0.69,0) size 138.88x34.72 [border: (0.69px dashed #008000)]
     layer at (0,0) size 133x29
       LayoutView at (0,0) size 133x29
     layer at (0,0) size 133x29
       LayoutSVGRoot {svg} at (0,0) size 133x29
         LayoutSVGEllipse {circle} at (0,0) size 220x220 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#D9BB7A] [fill rule=EVEN-ODD]}] [cx=110.00] [cy=110.00] [r=110.00]
-layer at (335,63) size 139x34
-  LayoutEmbeddedObject {OBJECT} at (0.69,0.69) size 138.88x34.72 [border: (0.69px dashed #008000)]
+layer at (335,61) size 139x35
+  LayoutEmbeddedObject {OBJECT} at (0.69,0) size 138.88x34.72 [border: (0.69px dashed #008000)]
     layer at (0,0) size 133x29
       LayoutView at (0,0) size 133x29
     layer at (0,0) size 133x29
@@ -108,8 +108,8 @@
         LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
         LayoutSVGContainer {g} at (162.86,403.79) size 362.86x362.86 [transform={m=((1.00,0.00)(0.00,1.00)) t=(-162.36,-403.29)}]
           LayoutSVGPath {path} at (162.86,403.79) size 362.86x362.86 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#D9BB7A] [fill rule=EVEN-ODD]}] [data="M 525.714 585.219 A 181.429 181.429 0 1 1 162.857 585.219 A 181.429 181.429 0 1 1 525.714 585.219 Z"]
-layer at (335,103) size 139x34
-  LayoutEmbeddedObject {OBJECT} at (0.69,0.69) size 138.88x34.72 [border: (0.69px dashed #008000)]
+layer at (335,100) size 139x35
+  LayoutEmbeddedObject {OBJECT} at (0.69,0) size 138.88x34.72 [border: (0.69px dashed #008000)]
     layer at (0,0) size 133x29
       LayoutView at (0,0) size 133x29
     layer at (0,0) size 133x29
@@ -117,8 +117,8 @@
         LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
         LayoutSVGContainer {g} at (162.86,403.79) size 362.86x362.86 [transform={m=((1.00,0.00)(0.00,1.00)) t=(-162.36,-403.29)}]
           LayoutSVGPath {path} at (162.86,403.79) size 362.86x362.86 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#D9BB7A] [fill rule=EVEN-ODD]}] [data="M 525.714 585.219 A 181.429 181.429 0 1 1 162.857 585.219 A 181.429 181.429 0 1 1 525.714 585.219 Z"]
-layer at (335,143) size 139x34
-  LayoutEmbeddedObject {OBJECT} at (0.69,0.69) size 138.88x34.72 [border: (0.69px dashed #008000)]
+layer at (335,139) size 139x35
+  LayoutEmbeddedObject {OBJECT} at (0.69,0) size 138.88x34.72 [border: (0.69px dashed #008000)]
     layer at (0,0) size 133x29
       LayoutView at (0,0) size 133x29
     layer at (0,0) size 133x29
@@ -126,8 +126,8 @@
         LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
         LayoutSVGContainer {g} at (162.86,403.79) size 362.86x362.86 [transform={m=((1.00,0.00)(0.00,1.00)) t=(-162.36,-403.29)}]
           LayoutSVGPath {path} at (162.86,403.79) size 362.86x362.86 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#D9BB7A] [fill rule=EVEN-ODD]}] [data="M 525.714 585.219 A 181.429 181.429 0 1 1 162.857 585.219 A 181.429 181.429 0 1 1 525.714 585.219 Z"]
-layer at (335,183) size 139x34
-  LayoutEmbeddedObject {OBJECT} at (0.69,0.69) size 138.88x34.72 [border: (0.69px dashed #008000)]
+layer at (335,178) size 139x35
+  LayoutEmbeddedObject {OBJECT} at (0.69,0) size 138.88x34.72 [border: (0.69px dashed #008000)]
     layer at (0,0) size 133x29
       LayoutView at (0,0) size 133x29
     layer at (0,0) size 133x29
@@ -135,8 +135,8 @@
         LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
         LayoutSVGContainer {g} at (162.86,403.79) size 362.86x362.86 [transform={m=((1.00,0.00)(0.00,1.00)) t=(-162.36,-403.29)}]
           LayoutSVGPath {path} at (162.86,403.79) size 362.86x362.86 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#D9BB7A] [fill rule=EVEN-ODD]}] [data="M 525.714 585.219 A 181.429 181.429 0 1 1 162.857 585.219 A 181.429 181.429 0 1 1 525.714 585.219 Z"]
-layer at (335,223) size 139x34
-  LayoutEmbeddedObject {OBJECT} at (0.69,0.69) size 138.88x34.72 [border: (0.69px dashed #008000)]
+layer at (335,217) size 139x35
+  LayoutEmbeddedObject {OBJECT} at (0.69,0) size 138.88x34.72 [border: (0.69px dashed #008000)]
     layer at (0,0) size 133x29
       LayoutView at (0,0) size 133x29
     layer at (0,0) size 133x29
@@ -144,8 +144,8 @@
         LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
         LayoutSVGContainer {g} at (162.86,403.79) size 362.86x362.86 [transform={m=((1.00,0.00)(0.00,1.00)) t=(-162.36,-403.29)}]
           LayoutSVGPath {path} at (162.86,403.79) size 362.86x362.86 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#D9BB7A] [fill rule=EVEN-ODD]}] [data="M 525.714 585.219 A 181.429 181.429 0 1 1 162.857 585.219 A 181.429 181.429 0 1 1 525.714 585.219 Z"]
-layer at (335,263) size 139x34
-  LayoutEmbeddedObject {OBJECT} at (0.69,0.69) size 138.88x34.72 [border: (0.69px dashed #008000)]
+layer at (335,256) size 139x35
+  LayoutEmbeddedObject {OBJECT} at (0.69,0) size 138.88x34.72 [border: (0.69px dashed #008000)]
     layer at (0,0) size 133x29
       LayoutView at (0,0) size 133x29
     layer at (0,0) size 133x29
@@ -153,8 +153,8 @@
         LayoutSVGHiddenContainer {defs} at (0,0) size 0x0
         LayoutSVGContainer {g} at (162.86,403.79) size 362.86x362.86 [transform={m=((1.00,0.00)(0.00,1.00)) t=(-162.36,-403.29)}]
           LayoutSVGPath {path} at (162.86,403.79) size 362.86x362.86 [stroke={[type=SOLID] [color=#000000]}] [fill={[type=SOLID] [color=#D9BB7A] [fill rule=EVEN-ODD]}] [data="M 525.714 585.219 A 181.429 181.429 0 1 1 162.857 585.219 A 181.429 181.429 0 1 1 525.714 585.219 Z"]
-layer at (335,303) size 139x34
-  LayoutEmbeddedObject {OBJECT} at (0.69,0.69) size 138.88x34.72 [border: (0.69px dashed #008000)]
+layer at (335,295) size 139x35
+  LayoutEmbeddedObject {OBJECT} at (0.69,0) size 138.88x34.72 [border: (0.69px dashed #008000)]
     layer at (0,0) size 133x29
       LayoutView at (0,0) size 133x29
     layer at (0,0) size 133x29
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-svg-through-object-with-absolute-size-2-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-svg-through-object-with-absolute-size-2-expected.png
index 25a075a..32621864 100644
--- a/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-svg-through-object-with-absolute-size-2-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-svg-through-object-with-absolute-size-2-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-svg-through-object-with-absolute-size-2-expected.txt b/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-svg-through-object-with-absolute-size-2-expected.txt
index 1fe2fe9..0654e2b 100644
--- a/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-svg-through-object-with-absolute-size-2-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-svg-through-object-with-absolute-size-2-expected.txt
@@ -1,34 +1,34 @@
 layer at (0,0) size 800x600
   LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x205
-  LayoutBlockFlow {html} at (0,0) size 800x205.09
-    LayoutBlockFlow {body} at (5.55,5.55) size 788.91x194
-      LayoutTable {table} at (142.45,0) size 504x194
-        LayoutTableSection (anonymous) at (0,0) size 504x194
-          LayoutTableRow {tr} at (0,0) size 504x194
-            LayoutTableCell {td} at (0,0) size 504x193.88 [r=0 c=0 rs=1 cs=3]
-              LayoutTable {table} at (7,6.94) size 490x180
-                LayoutTableSection (anonymous) at (0,0) size 490x180
-                  LayoutTableRow {tr} at (0,1) size 490x67
-                    LayoutTableCell {td} at (1,1) size 488x66.84 [r=0 c=0 rs=1 cs=2]
-                      LayoutBlockFlow {h1} at (5.55,20.42) size 476.91x26
+layer at (0,0) size 800x199
+  LayoutBlockFlow {html} at (0,0) size 800x199.09
+    LayoutBlockFlow {body} at (5.55,5.55) size 788.91x188
+      LayoutTable {table} at (142.45,0) size 504x188
+        LayoutTableSection (anonymous) at (0,0) size 504x188
+          LayoutTableRow {tr} at (0,0) size 504x188
+            LayoutTableCell {td} at (0,0) size 504x188 [r=0 c=0 rs=1 cs=3]
+              LayoutTable {table} at (7,6) size 490x176
+                LayoutTableSection (anonymous) at (0,0) size 490x176
+                  LayoutTableRow {tr} at (0,1) size 490x66
+                    LayoutTableCell {td} at (1,1) size 488x65.75 [r=0 c=0 rs=1 cs=2]
+                      LayoutBlockFlow {h1} at (5.55,19.88) size 476.91x26
                         LayoutText {#text} at (0,0) size 477x25
                           text run at (0,0) width 477: "Both sides should have identical size after zooming"
-                  LayoutTableRow {tr} at (0,69) size 490x25
-                    LayoutTableCell {td} at (1,69) size 243x25.09 [r=1 c=0 rs=1 cs=1]
-                      LayoutText {#text} at (96,5) size 51x15
+                  LayoutTableRow {tr} at (0,68) size 490x24
+                    LayoutTableCell {td} at (1,68) size 243x24 [r=1 c=0 rs=1 cs=1]
+                      LayoutText {#text} at (96,5) size 51x14
                         text run at (96,5) width 51: "SVG Image"
-                    LayoutTableCell {td} at (245,69) size 244x25.09 [r=1 c=1 rs=1 cs=1]
-                      LayoutText {#text} at (95,5) size 54x15
+                    LayoutTableCell {td} at (245,68) size 244x24 [r=1 c=1 rs=1 cs=1]
+                      LayoutText {#text} at (95,5) size 54x14
                         text run at (95,5) width 54: "PNG Image"
-                  LayoutTableRow {tr} at (0,95) size 490x84
-                    LayoutTableCell {td} at (1,95) size 243x83.53 [r=2 c=0 rs=1 cs=1]
+                  LayoutTableRow {tr} at (0,93) size 490x82
+                    LayoutTableCell {td} at (1,93) size 243x82.44 [r=2 c=0 rs=1 cs=1]
                       LayoutText {#text} at (0,0) size 0x0
-                    LayoutTableCell {td} at (245,95) size 244x83.53 [r=2 c=1 rs=1 cs=1]
-                      LayoutImage {img} at (5.55,5.55) size 138.88x69.44
+                    LayoutTableCell {td} at (245,93) size 244x82.44 [r=2 c=1 rs=1 cs=1]
+                      LayoutImage {img} at (5.55,5) size 138.88x69.44
                       LayoutText {#text} at (0,0) size 0x0
-layer at (255,113) size 138x69
-  LayoutEmbeddedObject {object} at (98.58,5.55) size 138.88x69.44
+layer at (255,110) size 138x69
+  LayoutEmbeddedObject {object} at (98.58,5) size 138.88x69.44
     layer at (0,0) size 139x69
       LayoutView at (0,0) size 139x69
     layer at (0,0) size 139x69
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-svg-through-object-with-absolute-size-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-svg-through-object-with-absolute-size-expected.png
index 25a075a..32621864 100644
--- a/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-svg-through-object-with-absolute-size-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-svg-through-object-with-absolute-size-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-svg-through-object-with-absolute-size-expected.txt b/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-svg-through-object-with-absolute-size-expected.txt
index 1fe2fe9..0654e2b 100644
--- a/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-svg-through-object-with-absolute-size-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-svg-through-object-with-absolute-size-expected.txt
@@ -1,34 +1,34 @@
 layer at (0,0) size 800x600
   LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x205
-  LayoutBlockFlow {html} at (0,0) size 800x205.09
-    LayoutBlockFlow {body} at (5.55,5.55) size 788.91x194
-      LayoutTable {table} at (142.45,0) size 504x194
-        LayoutTableSection (anonymous) at (0,0) size 504x194
-          LayoutTableRow {tr} at (0,0) size 504x194
-            LayoutTableCell {td} at (0,0) size 504x193.88 [r=0 c=0 rs=1 cs=3]
-              LayoutTable {table} at (7,6.94) size 490x180
-                LayoutTableSection (anonymous) at (0,0) size 490x180
-                  LayoutTableRow {tr} at (0,1) size 490x67
-                    LayoutTableCell {td} at (1,1) size 488x66.84 [r=0 c=0 rs=1 cs=2]
-                      LayoutBlockFlow {h1} at (5.55,20.42) size 476.91x26
+layer at (0,0) size 800x199
+  LayoutBlockFlow {html} at (0,0) size 800x199.09
+    LayoutBlockFlow {body} at (5.55,5.55) size 788.91x188
+      LayoutTable {table} at (142.45,0) size 504x188
+        LayoutTableSection (anonymous) at (0,0) size 504x188
+          LayoutTableRow {tr} at (0,0) size 504x188
+            LayoutTableCell {td} at (0,0) size 504x188 [r=0 c=0 rs=1 cs=3]
+              LayoutTable {table} at (7,6) size 490x176
+                LayoutTableSection (anonymous) at (0,0) size 490x176
+                  LayoutTableRow {tr} at (0,1) size 490x66
+                    LayoutTableCell {td} at (1,1) size 488x65.75 [r=0 c=0 rs=1 cs=2]
+                      LayoutBlockFlow {h1} at (5.55,19.88) size 476.91x26
                         LayoutText {#text} at (0,0) size 477x25
                           text run at (0,0) width 477: "Both sides should have identical size after zooming"
-                  LayoutTableRow {tr} at (0,69) size 490x25
-                    LayoutTableCell {td} at (1,69) size 243x25.09 [r=1 c=0 rs=1 cs=1]
-                      LayoutText {#text} at (96,5) size 51x15
+                  LayoutTableRow {tr} at (0,68) size 490x24
+                    LayoutTableCell {td} at (1,68) size 243x24 [r=1 c=0 rs=1 cs=1]
+                      LayoutText {#text} at (96,5) size 51x14
                         text run at (96,5) width 51: "SVG Image"
-                    LayoutTableCell {td} at (245,69) size 244x25.09 [r=1 c=1 rs=1 cs=1]
-                      LayoutText {#text} at (95,5) size 54x15
+                    LayoutTableCell {td} at (245,68) size 244x24 [r=1 c=1 rs=1 cs=1]
+                      LayoutText {#text} at (95,5) size 54x14
                         text run at (95,5) width 54: "PNG Image"
-                  LayoutTableRow {tr} at (0,95) size 490x84
-                    LayoutTableCell {td} at (1,95) size 243x83.53 [r=2 c=0 rs=1 cs=1]
+                  LayoutTableRow {tr} at (0,93) size 490x82
+                    LayoutTableCell {td} at (1,93) size 243x82.44 [r=2 c=0 rs=1 cs=1]
                       LayoutText {#text} at (0,0) size 0x0
-                    LayoutTableCell {td} at (245,95) size 244x83.53 [r=2 c=1 rs=1 cs=1]
-                      LayoutImage {img} at (5.55,5.55) size 138.88x69.44
+                    LayoutTableCell {td} at (245,93) size 244x82.44 [r=2 c=1 rs=1 cs=1]
+                      LayoutImage {img} at (5.55,5) size 138.88x69.44
                       LayoutText {#text} at (0,0) size 0x0
-layer at (255,113) size 138x69
-  LayoutEmbeddedObject {object} at (98.58,5.55) size 138.88x69.44
+layer at (255,110) size 138x69
+  LayoutEmbeddedObject {object} at (98.58,5) size 138.88x69.44
     layer at (0,0) size 139x69
       LayoutView at (0,0) size 139x69
     layer at (0,0) size 139x69
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-svg-through-object-with-percentage-size-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-svg-through-object-with-percentage-size-expected.png
index 61eb3fd..fb208257 100644
--- a/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-svg-through-object-with-percentage-size-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-svg-through-object-with-percentage-size-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-svg-through-object-with-percentage-size-expected.txt b/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-svg-through-object-with-percentage-size-expected.txt
index 9392a37..74b0f1e0 100644
--- a/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-svg-through-object-with-percentage-size-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/svg/zoom/page/zoom-svg-through-object-with-percentage-size-expected.txt
@@ -1,34 +1,34 @@
 layer at (0,0) size 800x600
   LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x385
-  LayoutBlockFlow {html} at (0,0) size 800x385.09
-    LayoutBlockFlow {body} at (5.55,5.55) size 788.91x374
-      LayoutTable {table} at (40.95,0) size 707x374
-        LayoutTableSection (anonymous) at (0,0) size 707x374
-          LayoutTableRow {tr} at (0,0) size 707x374
-            LayoutTableCell {td} at (0,0) size 707x373.88 [r=0 c=0 rs=1 cs=3]
-              LayoutTable {table} at (7,6.94) size 693x360
-                LayoutTableSection (anonymous) at (0,0) size 693x360
-                  LayoutTableRow {tr} at (0,1) size 693x67
-                    LayoutTableCell {td} at (1,1) size 691x66.84 [r=0 c=0 rs=1 cs=2]
-                      LayoutBlockFlow {h1} at (5.55,20.42) size 679.91x26
+layer at (0,0) size 800x380
+  LayoutBlockFlow {html} at (0,0) size 800x380.09
+    LayoutBlockFlow {body} at (5.55,5.55) size 788.91x369
+      LayoutTable {table} at (40.95,0) size 707x369
+        LayoutTableSection (anonymous) at (0,0) size 707x369
+          LayoutTableRow {tr} at (0,0) size 707x369
+            LayoutTableCell {td} at (0,0) size 707x369 [r=0 c=0 rs=1 cs=3]
+              LayoutTable {table} at (7,6) size 693x357
+                LayoutTableSection (anonymous) at (0,0) size 693x357
+                  LayoutTableRow {tr} at (0,1) size 693x66
+                    LayoutTableCell {td} at (1,1) size 691x65.75 [r=0 c=0 rs=1 cs=2]
+                      LayoutBlockFlow {h1} at (5.55,19.88) size 679.91x26
                         LayoutText {#text} at (101,0) size 477x25
                           text run at (101,0) width 477: "Both sides should have identical size after zooming"
-                  LayoutTableRow {tr} at (0,69) size 693x25
-                    LayoutTableCell {td} at (1,69) size 345x25.09 [r=1 c=0 rs=1 cs=1]
-                      LayoutText {#text} at (147,5) size 51x15
+                  LayoutTableRow {tr} at (0,68) size 693x24
+                    LayoutTableCell {td} at (1,68) size 345x24 [r=1 c=0 rs=1 cs=1]
+                      LayoutText {#text} at (147,5) size 51x14
                         text run at (147,5) width 51: "SVG Image"
-                    LayoutTableCell {td} at (347,69) size 345x25.09 [r=1 c=1 rs=1 cs=1]
-                      LayoutText {#text} at (146,5) size 53x15
+                    LayoutTableCell {td} at (347,68) size 345x24 [r=1 c=1 rs=1 cs=1]
+                      LayoutText {#text} at (146,5) size 53x14
                         text run at (146,5) width 53: "PNG Image"
-                  LayoutTableRow {tr} at (0,95) size 693x264
-                    LayoutTableCell {td} at (1,95) size 345x264.08 [r=2 c=0 rs=1 cs=1]
+                  LayoutTableRow {tr} at (0,93) size 693x263
+                    LayoutTableCell {td} at (1,93) size 345x262.98 [r=2 c=0 rs=1 cs=1]
                       LayoutText {#text} at (0,0) size 0x0
-                    LayoutTableCell {td} at (347,95) size 345x264.06 [r=2 c=1 rs=1 cs=1]
-                      LayoutImage {img} at (5.55,5.55) size 333.33x249.97
+                    LayoutTableCell {td} at (347,93) size 345x262.97 [r=2 c=1 rs=1 cs=1]
+                      LayoutImage {img} at (5.55,5) size 333.33x249.97
                       LayoutText {#text} at (0,0) size 0x0
-layer at (61,113) size 333x250
-  LayoutEmbeddedObject {object} at (6.13,5.55) size 333.33x249.98
+layer at (61,110) size 333x250
+  LayoutEmbeddedObject {object} at (6.13,5) size 333.33x249.98
     layer at (0,0) size 333x250
       LayoutView at (0,0) size 333x250
     layer at (0,0) size 333x250
diff --git a/third_party/WebKit/LayoutTests/platform/win/transforms/2d/hindi-rotated-expected.png b/third_party/WebKit/LayoutTests/platform/win/transforms/2d/hindi-rotated-expected.png
index dc0781a..7a7e2069 100644
--- a/third_party/WebKit/LayoutTests/platform/win/transforms/2d/hindi-rotated-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/transforms/2d/hindi-rotated-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/transforms/bounding-rect-zoom-expected.txt b/third_party/WebKit/LayoutTests/platform/win/transforms/bounding-rect-zoom-expected.txt
index 8f7e2f0..c227433 100644
--- a/third_party/WebKit/LayoutTests/platform/win/transforms/bounding-rect-zoom-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/transforms/bounding-rect-zoom-expected.txt
@@ -9,14 +9,14 @@
         LayoutBR {BR} at (306,13) size 0x0
         LayoutText {#text} at (0,17) size 174x16
           text run at (0,17) width 174: "There should be no red visible."
-      LayoutTable {TABLE} at (0,48.39) size 785x21
-        LayoutTableSection {TBODY} at (0,0) size 785x21
-          LayoutTableRow {TR} at (0,1) size 785x19
-            LayoutTableCell {TD} at (1,1) size 181x18.78 [r=0 c=0 rs=1 cs=1]
-              LayoutText {#text} at (0,0) size 142x17
+      LayoutTable {TABLE} at (0,48.39) size 785x19
+        LayoutTableSection {TBODY} at (0,0) size 785x19
+          LayoutTableRow {TR} at (0,1) size 785x17
+            LayoutTableCell {TD} at (1,1) size 181x17 [r=0 c=0 rs=1 cs=1]
+              LayoutText {#text} at (0,0) size 142x16
                 text run at (0,0) width 142: "getClientBoundingRect():"
-            LayoutTableCell {TD} at (183,1) size 601x18.78 [r=0 c=1 rs=1 cs=1]
-              LayoutText {#text} at (0,0) size 95x17
+            LayoutTableCell {TD} at (183,1) size 601x17 [r=0 c=1 rs=1 cs=1]
+              LayoutText {#text} at (0,0) size 95x16
                 text run at (0,0) width 95: "getClientRects():"
 layer at (90,90) size 90x90
   LayoutBlockFlow (positioned) {DIV} at (90,90) size 90x90 [bgcolor=#FF0000]
diff --git a/third_party/WebKit/LayoutTests/platform/win/transforms/transform-on-inline-expected.png b/third_party/WebKit/LayoutTests/platform/win/transforms/transform-on-inline-expected.png
index 363f65ba..a2d832f 100644
--- a/third_party/WebKit/LayoutTests/platform/win/transforms/transform-on-inline-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/transforms/transform-on-inline-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/new-remote-playback-pipeline/media/controls/lazy-loaded-style-expected.txt b/third_party/WebKit/LayoutTests/platform/win/virtual/new-remote-playback-pipeline/media/controls/lazy-loaded-style-expected.txt
deleted file mode 100644
index 4f1f7976..0000000
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/new-remote-playback-pipeline/media/controls/lazy-loaded-style-expected.txt
+++ /dev/null
@@ -1,51 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x321
-  LayoutBlockFlow {HTML} at (0,0) size 800x321
-    LayoutBlockFlow {BODY} at (8,8) size 784x305
-      LayoutText {#text} at (0,0) size 0x0
-layer at (8,8) size 400x300
-  LayoutVideo {VIDEO} at (0,0) size 400x300
-layer at (8,8) size 400x300
-  LayoutFlexibleBox (relative positioned) {DIV} at (0,0) size 400x300
-    LayoutBlockFlow {DIV} at (0,268) size 400x32
-layer at (8,8) size 400x258
-  LayoutFlexibleBox (relative positioned) {DIV} at (0,0) size 400x258
-layer at (8,276) size 400x32 scrollHeight 40
-  LayoutFlexibleBox (relative positioned) {DIV} at (0,0) size 400x32 [bgcolor=#FAFAFA]
-    LayoutButton {INPUT} at (0,0) size 32x32
-    LayoutFlexibleBox {DIV} at (32,0) size 24x32 [color=#5A5A5A]
-      LayoutBlockFlow (anonymous) at (0,0) size 24x32
-        LayoutText {#text} at (0,8) size 24x15
-          text run at (0,8) width 24: "0:00"
-    LayoutFlexibleBox {DIV} at (56,0) size 34x32 [color=#5A5A5A]
-      LayoutBlockFlow (anonymous) at (4,0) size 30x32
-        LayoutText {#text} at (0,8) size 30x15
-          text run at (0,8) width 30: "/ 0:06"
-    LayoutSlider {INPUT} at (108,1) size 116.69x30
-      LayoutFlexibleBox {DIV} at (0,14) size 116.69x2
-    LayoutButton {INPUT} at (242.69,0) size 32x32
-    LayoutSlider {INPUT} at (292.69,1) size 57.31x30
-      LayoutFlexibleBox {DIV} at (0,14) size 57.31x2
-layer at (376,276) size 32x32
-  LayoutButton {INPUT} at (368,0) size 32x32
-layer at (98,292) size 153x0
-  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 152.69x0
-layer at (116,291) size 117x2
-  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 116.69x2 [bgcolor=#DADADA]
-layer at (283,292) size 93x0
-  LayoutBlockFlow (relative positioned) {DIV} at (-18,1) size 93.31x0
-layer at (301,291) size 57x2
-  LayoutBlockFlow (positioned) {DIV} at (18,-1) size 57.31x2 [bgcolor=#DADADA]
-layer at (116,291) size 117x2
-  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 117x2 [bgcolor=#5A5A5A]
-layer at (116,291) size 0x2
-  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#4285F4]
-layer at (301,291) size 0x2
-  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 0x2 [bgcolor=#5A5A5A]
-layer at (301,291) size 57x2
-  LayoutBlockFlow (positioned) zI: 1 {DIV} at (0,0) size 57x2 [bgcolor=#4285F4]
-layer at (98,268) size 36x48 backgroundClip at (8,276) size 400x32 clip at (8,276) size 400x32
-  LayoutBlockFlow (positioned) zI: 2 {DIV} at (0,-24) size 36x48
-layer at (340,268) size 36x48 backgroundClip at (8,276) size 400x32 clip at (8,276) size 400x32
-  LayoutBlockFlow (positioned) zI: 2 {DIV} at (57.31,-24) size 36x48
diff --git a/third_party/WebKit/LayoutTests/platform/win7/editing/composition-underline-color-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/editing/composition-underline-color-expected.txt
new file mode 100644
index 0000000..78fbb8f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win7/editing/composition-underline-color-expected.txt
@@ -0,0 +1,13 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x200
+  LayoutBlockFlow {HTML} at (0,0) size 800x200
+    LayoutBlockFlow {BODY} at (8,16) size 784x176
+      LayoutBlockFlow {P} at (0,0) size 784x40
+        LayoutText {#text} at (0,0) size 770x39
+          text run at (0,0) width 770: "This test checks that composition underline color uses the color of the text and is not always black. The test passes if you see the"
+          text run at (0,20) width 421: "word \"foobar\" in green with a composition underline in the same color."
+      LayoutBlockFlow {DIV} at (0,56) size 784x120 [color=#00FF00] [bgcolor=#000000]
+        LayoutText {#text} at (50,50) size 40x19
+          text run at (50,50) width 40: "foobar"
+caret: position 6 of child 0 {#text} of child 2 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win7/external/wpt/css/css-font-loading/idlharness.https-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/external/wpt/css/css-font-loading/idlharness.https-expected.txt
deleted file mode 100644
index 61a0d30..0000000
--- a/third_party/WebKit/LayoutTests/platform/win7/external/wpt/css/css-font-loading/idlharness.https-expected.txt
+++ /dev/null
@@ -1,78 +0,0 @@
-frame (anonymous) - didStartProvisionalLoadForFrame
-frame (anonymous) - didCommitLoadForFrame
-main frame - didReceiveTitle: Font Loading API IDL tests
-main frame - didFinishDocumentLoadForFrame
-main frame - didHandleOnloadEventsForFrame
-main frame - didFinishLoadForFrame
-This is a testharness.js-based test.
-PASS Test IDL implementation of CSS Font Loading
-PASS Document interface: attribute fonts
-PASS Unscopable handled correctly for fonts property on Document
-PASS Document interface: document must inherit property "fonts" with the proper type
-PASS WorkerGlobalScope interface: existence and properties of interface object
-PASS FontFace interface: existence and properties of interface object
-PASS FontFace interface object length
-PASS FontFace interface object name
-PASS FontFace interface: existence and properties of interface prototype object
-PASS FontFace interface: existence and properties of interface prototype object's "constructor" property
-PASS FontFace interface: existence and properties of interface prototype object's @@unscopables property
-PASS FontFace interface: attribute family
-PASS Unscopable handled correctly for family property on FontFace
-PASS FontFace interface: attribute style
-PASS Unscopable handled correctly for style property on FontFace
-PASS FontFace interface: attribute weight
-PASS Unscopable handled correctly for weight property on FontFace
-PASS FontFace interface: attribute stretch
-PASS Unscopable handled correctly for stretch property on FontFace
-PASS FontFace interface: attribute unicodeRange
-PASS Unscopable handled correctly for unicodeRange property on FontFace
-PASS FontFace interface: attribute variant
-PASS Unscopable handled correctly for variant property on FontFace
-PASS FontFace interface: attribute featureSettings
-PASS Unscopable handled correctly for featureSettings property on FontFace
-FAIL FontFace interface: attribute variationSettings assert_true: The prototype object must have a property "variationSettings" expected true got false
-PASS Unscopable handled correctly for variationSettings property on FontFace
-PASS FontFace interface: attribute display
-PASS Unscopable handled correctly for display property on FontFace
-PASS FontFace interface: attribute status
-PASS Unscopable handled correctly for status property on FontFace
-PASS FontFace interface: operation load()
-PASS Unscopable handled correctly for load() on FontFace
-PASS FontFace interface: attribute loaded
-PASS Unscopable handled correctly for loaded property on FontFace
-PASS FontFaceSetLoadEvent interface: existence and properties of interface object
-PASS FontFaceSetLoadEvent interface object length
-PASS FontFaceSetLoadEvent interface object name
-PASS FontFaceSetLoadEvent interface: existence and properties of interface prototype object
-PASS FontFaceSetLoadEvent interface: existence and properties of interface prototype object's "constructor" property
-PASS FontFaceSetLoadEvent interface: existence and properties of interface prototype object's @@unscopables property
-PASS FontFaceSetLoadEvent interface: attribute fontfaces
-PASS Unscopable handled correctly for fontfaces property on FontFaceSetLoadEvent
-FAIL FontFaceSet interface: existence and properties of interface object assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-FAIL FontFaceSet interface object length assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-FAIL FontFaceSet interface object name assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-FAIL FontFaceSet interface: existence and properties of interface prototype object assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-FAIL FontFaceSet interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-FAIL FontFaceSet interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-FAIL FontFaceSet interface: operation add(FontFace) assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-PASS Unscopable handled correctly for add(FontFace) on FontFaceSet
-FAIL FontFaceSet interface: operation delete(FontFace) assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-PASS Unscopable handled correctly for delete(FontFace) on FontFaceSet
-FAIL FontFaceSet interface: operation clear() assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-PASS Unscopable handled correctly for clear() on FontFaceSet
-FAIL FontFaceSet interface: attribute onloading assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-PASS Unscopable handled correctly for onloading property on FontFaceSet
-FAIL FontFaceSet interface: attribute onloadingdone assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-PASS Unscopable handled correctly for onloadingdone property on FontFaceSet
-FAIL FontFaceSet interface: attribute onloadingerror assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-PASS Unscopable handled correctly for onloadingerror property on FontFaceSet
-FAIL FontFaceSet interface: operation load(CSSOMString, CSSOMString) assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-PASS Unscopable handled correctly for load(CSSOMString, CSSOMString) on FontFaceSet
-FAIL FontFaceSet interface: operation check(CSSOMString, CSSOMString) assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-PASS Unscopable handled correctly for check(CSSOMString, CSSOMString) on FontFaceSet
-FAIL FontFaceSet interface: attribute ready assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-PASS Unscopable handled correctly for ready property on FontFaceSet
-FAIL FontFaceSet interface: attribute status assert_own_property: self does not have own property "FontFaceSet" expected property "FontFaceSet" missing
-PASS Unscopable handled correctly for status property on FontFaceSet
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/platform/win7/fast/text/complex-text-opacity-expected.png b/third_party/WebKit/LayoutTests/platform/win7/fast/text/complex-text-opacity-expected.png
index 163271b..fb49f0b 100644
--- a/third_party/WebKit/LayoutTests/platform/win7/fast/text/complex-text-opacity-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win7/fast/text/complex-text-opacity-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/media/color-profile-video-seek-filter-expected.png b/third_party/WebKit/LayoutTests/platform/win7/media/color-profile-video-seek-filter-expected.png
new file mode 100644
index 0000000..8c95422
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win7/media/color-profile-video-seek-filter-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/new-remote-playback-pipeline/media/controls/lazy-loaded-style-expected.png b/third_party/WebKit/LayoutTests/platform/win7/media/controls/lazy-loaded-style-expected.png
similarity index 100%
copy from third_party/WebKit/LayoutTests/platform/win/virtual/new-remote-playback-pipeline/media/controls/lazy-loaded-style-expected.png
copy to third_party/WebKit/LayoutTests/platform/win7/media/controls/lazy-loaded-style-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/media/track/track-cue-rendering-vertical-expected.png b/third_party/WebKit/LayoutTests/platform/win7/media/track/track-cue-rendering-vertical-expected.png
index acccbfb2..39ab448 100644
--- a/third_party/WebKit/LayoutTests/platform/win7/media/track/track-cue-rendering-vertical-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win7/media/track/track-cue-rendering-vertical-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/new-remote-playback-pipeline/media/controls/lazy-loaded-style-expected.png b/third_party/WebKit/LayoutTests/platform/win7/virtual/new-remote-playback-pipeline/media/controls/lazy-loaded-style-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win/virtual/new-remote-playback-pipeline/media/controls/lazy-loaded-style-expected.png
rename to third_party/WebKit/LayoutTests/platform/win7/virtual/new-remote-playback-pipeline/media/controls/lazy-loaded-style-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-dom-height-attr-expected.png b/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-dom-height-attr-expected.png
index 0ed2eaa..b5de8e2 100644
--- a/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-dom-height-attr-expected.png
+++ b/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-dom-height-attr-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-dom-maskContentUnits-attr-expected.png b/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-dom-maskContentUnits-attr-expected.png
index 0ed2eaa..b5de8e2 100644
--- a/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-dom-maskContentUnits-attr-expected.png
+++ b/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-dom-maskContentUnits-attr-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-dom-maskUnits-attr-expected.png b/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-dom-maskUnits-attr-expected.png
index 4bf20c1..2292c99 100644
--- a/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-dom-maskUnits-attr-expected.png
+++ b/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-dom-maskUnits-attr-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-dom-width-attr-expected.png b/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-dom-width-attr-expected.png
index 0ed2eaa..b5de8e2 100644
--- a/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-dom-width-attr-expected.png
+++ b/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-dom-width-attr-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-dom-x-attr-expected.png b/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-dom-x-attr-expected.png
index 0ed2eaa..b5de8e2 100644
--- a/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-dom-x-attr-expected.png
+++ b/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-dom-x-attr-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-dom-y-attr-expected.png b/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-dom-y-attr-expected.png
index 0ed2eaa..b5de8e2 100644
--- a/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-dom-y-attr-expected.png
+++ b/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-dom-y-attr-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-svgdom-height-prop-expected.png b/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-svgdom-height-prop-expected.png
index 0ed2eaa..b5de8e2 100644
--- a/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-svgdom-height-prop-expected.png
+++ b/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-svgdom-height-prop-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-svgdom-maskContentUnits-prop-expected.png b/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-svgdom-maskContentUnits-prop-expected.png
index 0ed2eaa..b5de8e2 100644
--- a/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-svgdom-maskContentUnits-prop-expected.png
+++ b/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-svgdom-maskContentUnits-prop-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-svgdom-maskUnits-prop-expected.png b/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-svgdom-maskUnits-prop-expected.png
index 4bf20c1..2292c99 100644
--- a/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-svgdom-maskUnits-prop-expected.png
+++ b/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-svgdom-maskUnits-prop-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-svgdom-width-prop-expected.png b/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-svgdom-width-prop-expected.png
index 0ed2eaa..b5de8e2 100644
--- a/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-svgdom-width-prop-expected.png
+++ b/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-svgdom-width-prop-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-svgdom-x-prop-expected.png b/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-svgdom-x-prop-expected.png
index 0ed2eaa..b5de8e2 100644
--- a/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-svgdom-x-prop-expected.png
+++ b/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-svgdom-x-prop-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-svgdom-y-prop-expected.png b/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-svgdom-y-prop-expected.png
index 0ed2eaa..b5de8e2 100644
--- a/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-svgdom-y-prop-expected.png
+++ b/third_party/WebKit/LayoutTests/svg/dynamic-updates/SVGMaskElement-svgdom-y-prop-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/svg/foreignObject/clip-expected.png b/third_party/WebKit/LayoutTests/svg/foreignObject/clip-expected.png
index f42980c..2ad1e2d 100644
--- a/third_party/WebKit/LayoutTests/svg/foreignObject/clip-expected.png
+++ b/third_party/WebKit/LayoutTests/svg/foreignObject/clip-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/disable-spv175/paint/invalidation/cull-rect-change-crash-expected.txt b/third_party/WebKit/LayoutTests/virtual/disable-spv175/paint/invalidation/cull-rect-change-crash-expected.txt
new file mode 100644
index 0000000..12908223
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/disable-spv175/paint/invalidation/cull-rect-change-crash-expected.txt
@@ -0,0 +1,74 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutBlockFlow (anonymous)",
+          "rect": [0, 8, 1, 1],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutSVGContainer g id='g'",
+          "rect": [0, 8, 1, 1],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutSVGForeignObject foreignObject",
+          "rect": [0, 8, 1, 1],
+          "reason": "subtree"
+        },
+        {
+          "object": "LayoutText #text",
+          "rect": [0, 8, 1, 1],
+          "reason": "subtree"
+        }
+      ]
+    }
+  ],
+  "objectPaintInvalidations": [
+    {
+      "object": "LayoutSVGContainer g id='g'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutSVGForeignObject foreignObject",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutBlockFlow (anonymous)",
+      "reason": "subtree"
+    },
+    {
+      "object": "RootInlineBox",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutText #text",
+      "reason": "subtree"
+    },
+    {
+      "object": "InlineTextBox 'PASS'",
+      "reason": "subtree"
+    },
+    {
+      "object": "LayoutBlockFlow P",
+      "reason": "subtree"
+    }
+  ]
+}
+
diff --git a/third_party/WebKit/LayoutTests/virtual/outofblink-cors/external/wpt/fetch/api/cors/cors-cookies-redirect.any-expected.txt b/third_party/WebKit/LayoutTests/virtual/outofblink-cors/external/wpt/fetch/api/cors/cors-cookies-redirect.any-expected.txt
new file mode 100644
index 0000000..2c0512c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/outofblink-cors/external/wpt/fetch/api/cors/cors-cookies-redirect.any-expected.txt
@@ -0,0 +1,7 @@
+This is a testharness.js-based test.
+PASS Set cookies
+FAIL Testing credentials after cross-origin redirection with CORS and no preflight promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
+FAIL Testing credentials after cross-origin redirection with CORS and preflight promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
+PASS Clean cookies
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/virtual/outofblink-cors/external/wpt/fetch/api/cors/cors-cookies-redirect.any.worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/outofblink-cors/external/wpt/fetch/api/cors/cors-cookies-redirect.any.worker-expected.txt
new file mode 100644
index 0000000..2c0512c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/outofblink-cors/external/wpt/fetch/api/cors/cors-cookies-redirect.any.worker-expected.txt
@@ -0,0 +1,7 @@
+This is a testharness.js-based test.
+PASS Set cookies
+FAIL Testing credentials after cross-origin redirection with CORS and no preflight promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
+FAIL Testing credentials after cross-origin redirection with CORS and preflight promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
+PASS Clean cookies
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/virtual/threaded/animations/KeyframeEffect-composited-animation.html b/third_party/WebKit/LayoutTests/virtual/threaded/animations/KeyframeEffect-composited-animation.html
new file mode 100644
index 0000000..775ad67
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/threaded/animations/KeyframeEffect-composited-animation.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Animating with KeyframeEffect objects</title>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<body>
+<div id="target">x</div>
+<script>
+"use strict";
+
+promise_test(function(t) {
+  var effect = new KeyframeEffect(target, { opacity: [0, 0.9] }, 1000);
+  var anim = target.animate(null);
+  anim.effect = effect;
+
+  return Promise.all([anim.ready]).then(function() {
+    assert_true(internals.isCompositedAnimation(anim),
+        "Opacity animation with KeyframeEffect should be composited");
+  });
+}, "Using KeyframeEffect should not change whether an animation is composited");
+
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/virtual/threaded/animations/KeyframeEffectReadOnly-composited-animation.html b/third_party/WebKit/LayoutTests/virtual/threaded/animations/KeyframeEffectReadOnly-composited-animation.html
deleted file mode 100644
index dc9d1bb..0000000
--- a/third_party/WebKit/LayoutTests/virtual/threaded/animations/KeyframeEffectReadOnly-composited-animation.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>Animating with KeyframeEffectReadOnly objects</title>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<body>
-<div id="target">x</div>
-<div id="targetRO">x</div>
-<script>
-"use strict";
-
-promise_test(function(t) {
-  var effect = new KeyframeEffect(target, { opacity: [0, 0.9] }, 1000);
-  var anim = target.animate(null);
-  anim.effect = effect;
-
-  var effectRO = new KeyframeEffectReadOnly(
-      targetRO, { opacity: [0, 0.9] }, 1000);
-  var animRO = targetRO.animate(null);
-  animRO.effect = effectRO;
-
-  return Promise.all([anim.ready, animRO.ready]).then(function() {
-    assert_true(internals.isCompositedAnimation(anim),
-        "Opacity animation with KeyframeEffect should be composited");
-    assert_true(internals.isCompositedAnimation(animRO),
-        "Opacity animation with KeyframeEffectReadOnly should be"
-        + " composited");
-  });
-}, "Using KeyframeEffect or KeyframeEffectReadOnly should not change whether an"
-   + " animation is composited");
-
-</script>
-</body>
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 00b31779..63aac22 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -190,7 +190,7 @@
     setter onfinish
     setter playbackRate
     setter startTime
-interface AnimationEffectReadOnly
+interface AnimationEffect
     attribute @@toStringTag
     getter timing
     method constructor
@@ -4034,18 +4034,14 @@
     method constructor
     method getModifierState
     method initKeyboardEvent
-interface KeyframeEffect : KeyframeEffectReadOnly
-    attribute @@toStringTag
-    getter composite
-    method constructor
-    method setKeyframes
-    setter composite
-interface KeyframeEffectReadOnly : AnimationEffectReadOnly
+interface KeyframeEffect : AnimationEffect
     attribute @@toStringTag
     getter composite
     getter target
     method constructor
     method getKeyframes
+    method setKeyframes
+    setter composite
 interface LinearAccelerationSensor : Accelerometer
     attribute @@toStringTag
     method constructor
diff --git a/third_party/WebKit/PerformanceTests/Skipped b/third_party/WebKit/PerformanceTests/Skipped
deleted file mode 100644
index eaa8e1c..0000000
--- a/third_party/WebKit/PerformanceTests/Skipped
+++ /dev/null
@@ -1,55 +0,0 @@
-# Micro benchmarks not worth running at the moment.
-DOM/TraverseChildNodes.html
-
-# Not enabled by default on some ports
-Mutation
-
-# Unstable SVG page loading tests
-SVG/Samurai.html
-
-# Takes too long to load
-SVG/SierpinskiCarpet.html
-
-SVG/France.html
-SVG/FrancoBolloGnomeEzechi.html
-SVG/GearFlowers.html
-SVG/HereGear.html
-
-# Takes 22s on MacBookPro
-SVG/MtSaintHelens.html
-
-# Do not conform to WebKit or Chromium perf test styles
-SunSpider
-XSSAuditor
-
-# https://bugs.webkit.org/show_bug.cgi?id=98708
-Layout/subtree-detaching.html
-
-# We have pure JS tests separately outside Dromaeo.
-Dromaeo
-
-# Bug 77024 - Web Inspector: tests in PerformanceTests/inspector/ are timing out
-inspector
-
-Canvas/drawimage.html
-# crbug.com/727919, crbug.com/736374
-Canvas/getImageDataColorManaged.html
-
-# Redundant with chromium's page cyclers.
-Replay
-
-# Requires manual intervention.
-Bindings/event-target-wrapper.html
-
-# Microbenchmark that we aren't interested in monitoring.
-Bindings/gc-forest.html
-Bindings/gc-mini-tree.html
-Bindings/gc-tree.html
-Bindings/named-property-enumerator.html
-
-# Times out on Android. crbug.com/384857
-Animation/overlay-background-color-transitions.html
-
-# Assumes window.eventSender is always supported; it only is for "content-shell" performance runs.
-DOM/click_webkit_user_select_none.html
-Editing/mouse-move-with-hidden-elements.html
\ No newline at end of file
diff --git a/third_party/WebKit/Source/DEPS b/third_party/WebKit/Source/DEPS
index a7977e7..b82f39e 100644
--- a/third_party/WebKit/Source/DEPS
+++ b/third_party/WebKit/Source/DEPS
@@ -8,7 +8,9 @@
     "+base/macros.h",
     "+base/memory/ptr_util.h",
     "+base/memory/weak_ptr.h",
+    "+base/sequenced_task_runner.h",
     "+base/single_thread_task_runner.h",
+    "+base/task_scheduler/post_task.h",
     "+base/thread_annotations.h",
     "+base/time/time.h",
     "+build",
@@ -20,8 +22,6 @@
     "+testing/gtest/include/gtest",
     "+v8",
 
-    # DataLog.h is deprecated. Use base/logging.h instead. crbug.com/720442
-    "!platform/wtf/DataLog.h",
     # We are moving from WTF_MAKE_NONCOPYABLE to DISALLOW_COPY_AND_ASSIGN. Stop
     # new dependencies on WTF_MAKE_NONCOPYABLE.
     "!platform/wtf/Noncopyable.h",
diff --git a/third_party/WebKit/Source/bindings/IDLExtendedAttributes.md b/third_party/WebKit/Source/bindings/IDLExtendedAttributes.md
index e8589cf..44e086a7 100644
--- a/third_party/WebKit/Source/bindings/IDLExtendedAttributes.md
+++ b/third_party/WebKit/Source/bindings/IDLExtendedAttributes.md
@@ -493,9 +493,7 @@
 
 By default, interface members are configurable (i.e. you can modify a property descriptor corresponding to the member and also you can delete the property). `[Unforgeable]` makes the member unconfiguable so that you cannot modify or delete the property corresponding to the member.
 
-`[Unconfiguable]` changes where the member is defined, too. By default, attribute getters/setters and methods are defined on a prototype chain. `[Unforgeable]` defines the member on the instance object instead of the prototype object.
-
-Implementation: **Non-standard**: `[Unforgeable]` for attributes has an unspeced side-effect that it makes the property data-type property (`{writable: ..., value: ...}`) although it must be accessor-type property (`{get: ..., set: ...}`). ([Bug 497616](https://crbug.co/497616))
+`[Unforgeable]` changes where the member is defined, too. By default, attribute getters/setters and methods are defined on a prototype chain. `[Unforgeable]` defines the member on the instance object instead of the prototype object.
 
 ### [Unscopable] _(o, a)_
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptModule.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptModule.cpp
index 7bca09e..7653d1b 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptModule.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptModule.cpp
@@ -15,9 +15,12 @@
 
 ScriptModule::ScriptModule() = default;
 
-ScriptModule::ScriptModule(v8::Isolate* isolate, v8::Local<v8::Module> module)
+ScriptModule::ScriptModule(v8::Isolate* isolate,
+                           v8::Local<v8::Module> module,
+                           const KURL& source_url)
     : module_(SharedPersistent<v8::Module>::Create(module, isolate)),
-      identity_hash_(static_cast<unsigned>(module->GetIdentityHash())) {
+      identity_hash_(static_cast<unsigned>(module->GetIdentityHash())),
+      source_url_(source_url.GetString()) {
   DCHECK(!module_->IsEmpty());
 }
 
@@ -43,7 +46,7 @@
     return ScriptModule();
   }
   DCHECK(!try_catch.HasCaught());
-  return ScriptModule(isolate, module);
+  return ScriptModule(isolate, module, source_url);
 }
 
 ScriptValue ScriptModule::Instantiate(ScriptState* script_state) {
@@ -53,7 +56,7 @@
 
   DCHECK(!IsNull());
   v8::Local<v8::Context> context = script_state->GetContext();
-  probe::ExecuteScript probe(ExecutionContext::From(script_state));
+  probe::ExecuteScript probe(ExecutionContext::From(script_state), source_url_);
   bool success;
   if (!NewLocal(script_state->GetIsolate())
            ->InstantiateModule(context, &ResolveModuleCallback)
@@ -74,7 +77,8 @@
   // returning from here.
   v8::TryCatch try_catch(isolate);
 
-  probe::ExecuteScript probe(ExecutionContext::From(script_state));
+  probe::ExecuteScript probe(ExecutionContext::From(script_state), source_url_);
+
   // TODO(kouhei): We currently don't have a code-path which use return value of
   // EvaluateModule. Stop ignoring result once we have such path.
   v8::Local<v8::Value> result;
@@ -142,7 +146,8 @@
   Modulator* modulator = Modulator::From(ScriptState::From(context));
   DCHECK(modulator);
 
-  ScriptModule referrer_record(isolate, referrer);
+  // TODO(shivanisha): Can a valid source url be passed to the constructor.
+  ScriptModule referrer_record(isolate, referrer, KURL());
   ExceptionState exception_state(isolate, ExceptionState::kExecutionContext,
                                  "ScriptModule", "resolveModuleCallback");
   ScriptModule resolved = modulator->GetScriptModuleResolver()->Resolve(
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptModule.h b/third_party/WebKit/Source/bindings/core/v8/ScriptModule.h
index cfde621a..ddb3ed1 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptModule.h
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptModule.h
@@ -46,7 +46,7 @@
   ScriptModule();
   ~ScriptModule();
 
-  ScriptModule(v8::Isolate*, v8::Local<v8::Module>);
+  ScriptModule(v8::Isolate*, v8::Local<v8::Module>, const KURL&);
 
   // Returns exception, if any.
   ScriptValue Instantiate(ScriptState*);
@@ -83,6 +83,7 @@
 
   scoped_refptr<SharedPersistent<v8::Module>> module_;
   unsigned identity_hash_ = 0;
+  String source_url_;
 
   friend struct ScriptModuleHash;
   friend struct WTF::HashTraits<blink::ScriptModule>;
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8BindingForCore.cpp b/third_party/WebKit/Source/bindings/core/v8/V8BindingForCore.cpp
index e97ff466..c9814532 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8BindingForCore.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8BindingForCore.cpp
@@ -43,7 +43,6 @@
 #include "bindings/core/v8/WindowProxy.h"
 #include "bindings/core/v8/WorkerOrWorkletScriptController.h"
 #include "bindings/core/v8/custom/V8CustomXPathNSResolver.h"
-#include "build/build_config.h"
 #include "core/dom/Document.h"
 #include "core/dom/Element.h"
 #include "core/dom/QualifiedName.h"
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp b/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp
index 04ae4948..1e917a7 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp
@@ -500,8 +500,9 @@
   if (!modulator)
     return;
 
-  ModuleImportMeta host_meta =
-      modulator->HostGetImportMetaProperties(ScriptModule(isolate, module));
+  // TODO(shivanisha): Can a valid source url be passed to the constructor.
+  ModuleImportMeta host_meta = modulator->HostGetImportMetaProperties(
+      ScriptModule(isolate, module, KURL()));
 
   // 3. Return <<Record { [[Key]]: "url", [[Value]]: urlString }>>. [spec text]
   v8::Local<v8::String> url_key = V8String(isolate, "url");
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.cpp b/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.cpp
index bd1bc7a..61e1601 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.cpp
@@ -89,12 +89,15 @@
   v8::MicrotasksScope microtasks_scope(
       isolate, v8::MicrotasksScope::kDoNotRunMicrotasks);
   V8PerIsolateData::From(isolate)->SetIsHandlingRecursionLevelError(true);
+
+  ScriptForbiddenScope::AllowUserAgentScript allow_script;
   v8::Local<v8::Value> result =
       v8::Function::New(isolate->GetCurrentContext(),
                         ThrowStackOverflowException, v8::Local<v8::Value>(), 0,
                         v8::ConstructorBehavior::kThrow)
           .ToLocalChecked()
           ->Call(v8::Undefined(isolate), 0, nullptr);
+
   V8PerIsolateData::From(isolate)->SetIsHandlingRecursionLevelError(false);
   return result;
 }
@@ -441,9 +444,11 @@
   DCHECK(!script.IsEmpty());
   ScopedFrameBlamer frame_blamer(
       context->IsDocument() ? ToDocument(context)->GetFrame() : nullptr);
+
+  v8::Local<v8::Value> script_name =
+      script->GetUnboundScript()->GetScriptName();
   TRACE_EVENT1("v8", "v8.run", "fileName",
-               TRACE_STR_COPY(*v8::String::Utf8Value(
-                   isolate, script->GetUnboundScript()->GetScriptName())));
+               TRACE_STR_COPY(*v8::String::Utf8Value(isolate, script_name)));
   RuntimeCallStatsScopedTracer rcs_scoped_tracer(isolate);
   RUNTIME_CALL_TIMER_SCOPE(isolate, RuntimeCallStats::CounterId::kV8);
 
@@ -461,7 +466,10 @@
     }
     v8::MicrotasksScope microtasks_scope(isolate,
                                          v8::MicrotasksScope::kRunMicrotasks);
-    probe::ExecuteScript probe(context);
+    // ToCoreString here should be zero copy due to externalized string
+    // unpacked.
+    String script_url = ToCoreString(script_name->ToString());
+    probe::ExecuteScript probe(context, script_url);
     result = script->Run(isolate->GetCurrentContext());
   }
 
diff --git a/third_party/WebKit/Source/bindings/modules/v8/generated.gni b/third_party/WebKit/Source/bindings/modules/v8/generated.gni
index 29b0f62e..08a0f5d1 100644
--- a/third_party/WebKit/Source/bindings/modules/v8/generated.gni
+++ b/third_party/WebKit/Source/bindings/modules/v8/generated.gni
@@ -14,8 +14,8 @@
 
 # TODO(bashi): It would be better to have a way to update this list automatically.
 bindings_modules_generated_union_type_files = [
-  "$bindings_modules_v8_output_dir/animation_effect_read_only_or_animation_effect_read_only_sequence.cc",
-  "$bindings_modules_v8_output_dir/animation_effect_read_only_or_animation_effect_read_only_sequence.h",
+  "$bindings_modules_v8_output_dir/animation_effect_or_animation_effect_sequence.cc",
+  "$bindings_modules_v8_output_dir/animation_effect_or_animation_effect_sequence.h",
   "$bindings_modules_v8_output_dir/array_buffer_or_array_buffer_view_or_dictionary.cc",
   "$bindings_modules_v8_output_dir/array_buffer_or_array_buffer_view_or_dictionary.h",
   "$bindings_modules_v8_output_dir/array_buffer_or_array_buffer_view_or_usv_string.cc",
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn
index 525c6866..663e69ad 100644
--- a/third_party/WebKit/Source/core/BUILD.gn
+++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -1651,7 +1651,7 @@
   testonly = true
   sources = [
     "animation/AnimationClockTest.cpp",
-    "animation/AnimationEffectReadOnlyTest.cpp",
+    "animation/AnimationEffectTest.cpp",
     "animation/AnimationInputHelpersTest.cpp",
     "animation/AnimationSimTest.cpp",
     "animation/AnimationTest.cpp",
@@ -1706,6 +1706,7 @@
     "css/cssom/CSSResourceValueTest.cpp",
     "css/cssom/CSSStyleImageValueTest.cpp",
     "css/cssom/CSSUnitValueTest.cpp",
+    "css/cssom/CSSUnparsedValueTest.cpp",
     "css/cssom/PrepopulatedComputedStylePropertyMapTest.cpp",
     "css/invalidation/InvalidationSetTest.cpp",
     "css/invalidation/StyleInvalidatorTest.cpp",
@@ -1806,6 +1807,7 @@
     "fetch/ReadableStreamBytesConsumerTest.cpp",
     "fetch/RequestTest.cpp",
     "fetch/ResponseTest.cpp",
+    "frame/AdTrackerTest.cpp",
     "frame/BrowserControlsTest.cpp",
     "frame/DOMTimerTest.cpp",
     "frame/DeferredLoadingTest.cpp",
diff --git a/third_party/WebKit/Source/core/DEPS b/third_party/WebKit/Source/core/DEPS
index 021ac60..2c01d6f6 100644
--- a/third_party/WebKit/Source/core/DEPS
+++ b/third_party/WebKit/Source/core/DEPS
@@ -1,6 +1,7 @@
 include_rules = [
     "+base/atomic_sequence_num.h",
     "+base/memory/scoped_refptr.h",
+    "+base/synchronization/waitable_event.h",
     "+base/unguessable_token.h",
     "+bindings/core",
     "+build/mac",
diff --git a/third_party/WebKit/Source/core/animation/Animation.cpp b/third_party/WebKit/Source/core/animation/Animation.cpp
index cb07466e..4379fc9 100644
--- a/third_party/WebKit/Source/core/animation/Animation.cpp
+++ b/third_party/WebKit/Source/core/animation/Animation.cpp
@@ -35,7 +35,7 @@
 
 #include "core/animation/AnimationTimeline.h"
 #include "core/animation/DocumentTimeline.h"
-#include "core/animation/KeyframeEffectReadOnly.h"
+#include "core/animation/KeyframeEffect.h"
 #include "core/animation/PendingAnimations.h"
 #include "core/animation/css/CSSAnimations.h"
 #include "core/css/StyleChangeReason.h"
@@ -68,7 +68,7 @@
 }
 }
 
-Animation* Animation::Create(AnimationEffectReadOnly* effect,
+Animation* Animation::Create(AnimationEffect* effect,
                              AnimationTimeline* timeline) {
   if (!timeline || !timeline->IsDocumentTimeline()) {
     // FIXME: Support creating animations without a timeline.
@@ -90,7 +90,7 @@
 }
 
 Animation* Animation::Create(ExecutionContext* execution_context,
-                             AnimationEffectReadOnly* effect,
+                             AnimationEffect* effect,
                              ExceptionState& exception_state) {
   DCHECK(RuntimeEnabledFeatures::WebAnimationsAPIEnabled());
 
@@ -99,7 +99,7 @@
 }
 
 Animation* Animation::Create(ExecutionContext* execution_context,
-                             AnimationEffectReadOnly* effect,
+                             AnimationEffect* effect,
                              AnimationTimeline* timeline,
                              ExceptionState& exception_state) {
   DCHECK(RuntimeEnabledFeatures::WebAnimationsAPIEnabled());
@@ -113,7 +113,7 @@
 
 Animation::Animation(ExecutionContext* execution_context,
                      DocumentTimeline& timeline,
-                     AnimationEffectReadOnly* content)
+                     AnimationEffect* content)
     : ContextLifecycleObserver(execution_context),
       play_state_(kIdle),
       playback_rate_(1),
@@ -460,11 +460,10 @@
 
 bool Animation::Affects(const Element& element,
                         const CSSProperty& property) const {
-  if (!content_ || !content_->IsKeyframeEffectReadOnly())
+  if (!content_ || !content_->IsKeyframeEffect())
     return false;
 
-  const KeyframeEffectReadOnly* effect =
-      ToKeyframeEffectReadOnly(content_.Get());
+  const KeyframeEffect* effect = ToKeyframeEffect(content_.Get());
   return (effect->target() == &element) &&
          effect->Affects(PropertyHandle(property));
 }
@@ -529,7 +528,7 @@
   }
 }
 
-void Animation::setEffect(AnimationEffectReadOnly* new_effect) {
+void Animation::setEffect(AnimationEffect* new_effect) {
   if (content_ == new_effect)
     return;
   PlayStateUpdateScope update_scope(*this, kTimingUpdateOnDemand,
@@ -818,7 +817,7 @@
   if (!code.Ok()) {
     return code;
   }
-  return ToKeyframeEffectReadOnly(content_.Get())
+  return ToKeyframeEffect(content_.Get())
       ->CheckCanStartAnimationOnCompositor(playback_rate_);
 }
 
@@ -860,7 +859,7 @@
     return CompositorAnimations::FailureCode::Actionable(
         "Animation has no animation effect");
   }
-  if (!content_->IsKeyframeEffectReadOnly()) {
+  if (!content_->IsKeyframeEffect()) {
     return CompositorAnimations::FailureCode::NonActionable(
         "Animation effect is not keyframe-based");
   }
@@ -869,8 +868,7 @@
   // which case we trust the compositing logic will create a layer if needed.
   if (composited_element_ids) {
     DCHECK(RuntimeEnabledFeatures::SlimmingPaintV2Enabled());
-    Element* target_element =
-        ToKeyframeEffectReadOnly(content_.Get())->target();
+    Element* target_element = ToKeyframeEffect(content_.Get())->target();
     if (!target_element) {
       return CompositorAnimations::FailureCode::Actionable(
           "Animation is not attached to an element");
@@ -922,7 +920,7 @@
   }
 
   DCHECK_NE(compositor_group_, 0);
-  ToKeyframeEffectReadOnly(content_.Get())
+  ToKeyframeEffect(content_.Get())
       ->StartAnimationOnCompositor(compositor_group_, start_time, time_offset,
                                    playback_rate_);
 }
@@ -956,7 +954,7 @@
 
 void Animation::CancelAnimationOnCompositor() {
   if (HasActiveAnimationsOnCompositor())
-    ToKeyframeEffectReadOnly(content_.Get())->CancelAnimationOnCompositor();
+    ToKeyframeEffect(content_.Get())->CancelAnimationOnCompositor();
 
   DestroyCompositorAnimation();
 }
@@ -965,22 +963,21 @@
   if (!HasActiveAnimationsOnCompositor())
     return;
 
-  if (ToKeyframeEffectReadOnly(content_.Get())->CancelAnimationOnCompositor())
+  if (ToKeyframeEffect(content_.Get())->CancelAnimationOnCompositor())
     SetCompositorPending(true);
 }
 
 void Animation::CancelIncompatibleAnimationsOnCompositor() {
-  if (content_ && content_->IsKeyframeEffectReadOnly())
-    ToKeyframeEffectReadOnly(content_.Get())
+  if (content_ && content_->IsKeyframeEffect())
+    ToKeyframeEffect(content_.Get())
         ->CancelIncompatibleAnimationsOnCompositor();
 }
 
 bool Animation::HasActiveAnimationsOnCompositor() {
-  if (!content_ || !content_->IsKeyframeEffectReadOnly())
+  if (!content_ || !content_->IsKeyframeEffect())
     return false;
 
-  return ToKeyframeEffectReadOnly(content_.Get())
-      ->HasActiveAnimationsOnCompositor();
+  return ToKeyframeEffect(content_.Get())->HasActiveAnimationsOnCompositor();
 }
 
 bool Animation::Update(TimingUpdateReason reason) {
@@ -1065,7 +1062,7 @@
                       : content_->TimeToReverseEffectChange() / -playback_rate_;
 
   return !HasActiveAnimationsOnCompositor() &&
-                 content_->GetPhase() == AnimationEffectReadOnly::kPhaseActive
+                 content_->GetPhase() == AnimationEffect::kPhaseActive
              ? 0
              : result;
 }
@@ -1140,9 +1137,9 @@
     return;
 
   DCHECK(content_);
-  DCHECK(content_->IsKeyframeEffectReadOnly());
+  DCHECK(content_->IsKeyframeEffect());
 
-  ToKeyframeEffectReadOnly(content_.Get())->AttachCompositedLayers();
+  ToKeyframeEffect(content_.Get())->AttachCompositedLayers();
 }
 
 void Animation::DetachCompositedLayers() {
@@ -1274,7 +1271,7 @@
 void Animation::PauseForTesting(double pause_time) {
   SetCurrentTimeInternal(pause_time, kTimingUpdateOnDemand);
   if (HasActiveAnimationsOnCompositor())
-    ToKeyframeEffectReadOnly(content_.Get())
+    ToKeyframeEffect(content_.Get())
         ->PauseAnimationForTestingOnCompositor(CurrentTimeInternal());
   is_paused_for_testing_ = true;
   pause();
@@ -1292,10 +1289,10 @@
 }
 
 void Animation::InvalidateKeyframeEffect(const TreeScope& tree_scope) {
-  if (!content_ || !content_->IsKeyframeEffectReadOnly())
+  if (!content_ || !content_->IsKeyframeEffect())
     return;
 
-  Element* target = ToKeyframeEffectReadOnly(content_.Get())->target();
+  Element* target = ToKeyframeEffect(content_.Get())->target();
 
   // TODO(alancutter): Remove dependency of this function on CSSAnimations.
   // This function makes the incorrect assumption that the animation uses
diff --git a/third_party/WebKit/Source/core/animation/Animation.h b/third_party/WebKit/Source/core/animation/Animation.h
index d5fe968..8fe0b38 100644
--- a/third_party/WebKit/Source/core/animation/Animation.h
+++ b/third_party/WebKit/Source/core/animation/Animation.h
@@ -40,8 +40,8 @@
 #include "bindings/core/v8/ScriptPromise.h"
 #include "bindings/core/v8/ScriptPromiseProperty.h"
 #include "core/CoreExport.h"
+#include "core/animation/AnimationEffect.h"
 #include "core/animation/AnimationEffectOwner.h"
-#include "core/animation/AnimationEffectReadOnly.h"
 #include "core/animation/CompositorAnimations.h"
 #include "core/animation/DocumentTimeline.h"
 #include "core/css_property_names.h"
@@ -80,14 +80,14 @@
     kFinished
   };
 
-  static Animation* Create(AnimationEffectReadOnly*, AnimationTimeline*);
+  static Animation* Create(AnimationEffect*, AnimationTimeline*);
 
   // Web Animations API IDL constructors.
   static Animation* Create(ExecutionContext*,
-                           AnimationEffectReadOnly*,
+                           AnimationEffect*,
                            ExceptionState&);
   static Animation* Create(ExecutionContext*,
-                           AnimationEffectReadOnly*,
+                           AnimationEffect*,
                            AnimationTimeline*,
                            ExceptionState&);
 
@@ -163,9 +163,9 @@
   WTF::Optional<double> StartTimeInternal() const { return start_time_; }
   void setStartTime(double, bool is_null);
 
-  const AnimationEffectReadOnly* effect() const { return content_.Get(); }
-  AnimationEffectReadOnly* effect() { return content_.Get(); }
-  void setEffect(AnimationEffectReadOnly*);
+  const AnimationEffect* effect() const { return content_.Get(); }
+  AnimationEffect* effect() { return content_.Get(); }
+  void setEffect(AnimationEffect*);
 
   void setId(const String& id) { id_ = id; }
   const String& id() const { return id_; }
@@ -234,7 +234,7 @@
                           RegisteredEventListener&) override;
 
  private:
-  Animation(ExecutionContext*, DocumentTimeline&, AnimationEffectReadOnly*);
+  Animation(ExecutionContext*, DocumentTimeline&, AnimationEffect*);
 
   void ClearOutdated();
   void ForceServiceOnNextFrame();
@@ -286,7 +286,7 @@
   Member<AnimationPromise> finished_promise_;
   Member<AnimationPromise> ready_promise_;
 
-  Member<AnimationEffectReadOnly> content_;
+  Member<AnimationEffect> content_;
   Member<DocumentTimeline> timeline_;
 
   // Reflects all pausing, including via pauseForTesting().
diff --git a/third_party/WebKit/Source/core/animation/Animation.idl b/third_party/WebKit/Source/core/animation/Animation.idl
index dbce735..a096e1d 100644
--- a/third_party/WebKit/Source/core/animation/Animation.idl
+++ b/third_party/WebKit/Source/core/animation/Animation.idl
@@ -33,14 +33,14 @@
 enum AnimationPlayState { "idle", "pending", "running", "paused", "finished" };
 
 [
-    Constructor(optional AnimationEffectReadOnly? effect = null, optional AnimationTimeline? timeline),
+    Constructor(optional AnimationEffect? effect = null, optional AnimationTimeline? timeline),
     Exposed(Window WebAnimationsAPI),
     ConstructorCallWith=ExecutionContext,
     RaisesException=Constructor,
     ActiveScriptWrappable
 ] interface Animation : EventTarget {
     // TODO(suzyh): Make timeline mutable.
-    [RuntimeEnabled=WebAnimationsAPI] attribute AnimationEffectReadOnly? effect;
+    [RuntimeEnabled=WebAnimationsAPI] attribute AnimationEffect? effect;
     [RuntimeEnabled=WebAnimationsAPI] readonly attribute AnimationTimeline? timeline;
     [Measure] attribute double?    startTime;
     [Measure, RaisesException=Setter] attribute double?    currentTime;
diff --git a/third_party/WebKit/Source/core/animation/AnimationEffect.cpp b/third_party/WebKit/Source/core/animation/AnimationEffect.cpp
new file mode 100644
index 0000000..3bbffa86
--- /dev/null
+++ b/third_party/WebKit/Source/core/animation/AnimationEffect.cpp
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "core/animation/AnimationEffect.h"
+
+#include "core/animation/Animation.h"
+#include "core/animation/AnimationEffectTimingReadOnly.h"
+#include "core/animation/ComputedTimingProperties.h"
+#include "core/animation/TimingCalculations.h"
+
+namespace blink {
+
+namespace {
+
+Timing::FillMode ResolvedFillMode(Timing::FillMode fill_mode,
+                                  bool is_animation) {
+  if (fill_mode != Timing::FillMode::AUTO)
+    return fill_mode;
+  if (is_animation)
+    return Timing::FillMode::NONE;
+  return Timing::FillMode::BOTH;
+}
+
+}  // namespace
+
+AnimationEffect::AnimationEffect(const Timing& timing,
+                                 EventDelegate* event_delegate)
+    : owner_(nullptr),
+      timing_(timing),
+      event_delegate_(event_delegate),
+      calculated_(),
+      needs_update_(true),
+      last_update_time_(NullValue()) {
+  timing_.AssertValid();
+}
+
+double AnimationEffect::IterationDuration() const {
+  double result = std::isnan(timing_.iteration_duration)
+                      ? IntrinsicIterationDuration()
+                      : timing_.iteration_duration;
+  DCHECK_GE(result, 0);
+  return result;
+}
+
+double AnimationEffect::RepeatedDuration() const {
+  const double result =
+      MultiplyZeroAlwaysGivesZero(IterationDuration(), timing_.iteration_count);
+  DCHECK_GE(result, 0);
+  return result;
+}
+
+double AnimationEffect::ActiveDurationInternal() const {
+  const double result =
+      timing_.playback_rate
+          ? RepeatedDuration() / std::abs(timing_.playback_rate)
+          : std::numeric_limits<double>::infinity();
+  DCHECK_GE(result, 0);
+  return result;
+}
+
+void AnimationEffect::UpdateSpecifiedTiming(const Timing& timing) {
+  // FIXME: Test whether the timing is actually different?
+  timing_ = timing;
+  Invalidate();
+  if (owner_)
+    owner_->SpecifiedTimingChanged();
+}
+
+void AnimationEffect::getComputedTiming(
+    ComputedTimingProperties& computed_timing) {
+  // ComputedTimingProperties members.
+  computed_timing.setEndTime(EndTimeInternal() * 1000);
+  computed_timing.setActiveDuration(ActiveDurationInternal() * 1000);
+
+  if (EnsureCalculated().is_in_effect) {
+    computed_timing.setLocalTime(EnsureCalculated().local_time * 1000);
+    computed_timing.setProgress(EnsureCalculated().progress.value());
+    computed_timing.setCurrentIteration(EnsureCalculated().current_iteration);
+  } else {
+    computed_timing.setLocalTimeToNull();
+    computed_timing.setProgressToNull();
+    computed_timing.setCurrentIterationToNull();
+  }
+
+  // KeyframeEffectOptions members.
+  computed_timing.setDelay(SpecifiedTiming().start_delay * 1000);
+  computed_timing.setEndDelay(SpecifiedTiming().end_delay * 1000);
+  computed_timing.setFill(Timing::FillModeString(
+      ResolvedFillMode(SpecifiedTiming().fill_mode, IsKeyframeEffect())));
+  computed_timing.setIterationStart(SpecifiedTiming().iteration_start);
+  computed_timing.setIterations(SpecifiedTiming().iteration_count);
+
+  UnrestrictedDoubleOrString duration;
+  duration.SetUnrestrictedDouble(IterationDuration() * 1000);
+  computed_timing.setDuration(duration);
+
+  computed_timing.setDirection(
+      Timing::PlaybackDirectionString(SpecifiedTiming().direction));
+  computed_timing.setEasing(SpecifiedTiming().timing_function->ToString());
+}
+
+ComputedTimingProperties AnimationEffect::getComputedTiming() {
+  ComputedTimingProperties result;
+  getComputedTiming(result);
+  return result;
+}
+
+void AnimationEffect::UpdateInheritedTime(double inherited_time,
+                                          TimingUpdateReason reason) const {
+  bool needs_update =
+      needs_update_ ||
+      (last_update_time_ != inherited_time &&
+       !(IsNull(last_update_time_) && IsNull(inherited_time))) ||
+      (owner_ && owner_->EffectSuppressed());
+  needs_update_ = false;
+  last_update_time_ = inherited_time;
+
+  const double local_time = inherited_time;
+  double time_to_next_iteration = std::numeric_limits<double>::infinity();
+  if (needs_update) {
+    const double active_duration = this->ActiveDurationInternal();
+
+    const Phase current_phase =
+        CalculatePhase(active_duration, local_time, timing_);
+    // FIXME: parentPhase depends on groups being implemented.
+    const AnimationEffect::Phase kParentPhase = AnimationEffect::kPhaseActive;
+    const double active_time = CalculateActiveTime(
+        active_duration,
+        ResolvedFillMode(timing_.fill_mode, IsKeyframeEffect()), local_time,
+        kParentPhase, current_phase, timing_);
+
+    double current_iteration;
+    WTF::Optional<double> progress;
+    if (const double iteration_duration = this->IterationDuration()) {
+      const double start_offset = MultiplyZeroAlwaysGivesZero(
+          timing_.iteration_start, iteration_duration);
+      DCHECK_GE(start_offset, 0);
+      const double scaled_active_time = CalculateScaledActiveTime(
+          active_duration, active_time, start_offset, timing_);
+      const double iteration_time = CalculateIterationTime(
+          iteration_duration, RepeatedDuration(), scaled_active_time,
+          start_offset, current_phase, timing_);
+
+      current_iteration = CalculateCurrentIteration(
+          iteration_duration, iteration_time, scaled_active_time, timing_);
+      const WTF::Optional<double> transformed_time = CalculateTransformedTime(
+          current_iteration, iteration_duration, iteration_time, timing_);
+
+      // The infinite iterationDuration case here is a workaround because
+      // the specified behaviour does not handle infinite durations well.
+      // There is an open issue against the spec to fix this:
+      // https://github.com/w3c/web-animations/issues/142
+      if (!std::isfinite(iteration_duration))
+        progress = fmod(timing_.iteration_start, 1.0);
+      else if (transformed_time)
+        progress = transformed_time.value() / iteration_duration;
+
+      if (!IsNull(iteration_time)) {
+        time_to_next_iteration = (iteration_duration - iteration_time) /
+                                 std::abs(timing_.playback_rate);
+        if (active_duration - active_time < time_to_next_iteration)
+          time_to_next_iteration = std::numeric_limits<double>::infinity();
+      }
+    } else {
+      const double kLocalIterationDuration = 1;
+      const double local_repeated_duration =
+          kLocalIterationDuration * timing_.iteration_count;
+      DCHECK_GE(local_repeated_duration, 0);
+      const double local_active_duration =
+          timing_.playback_rate
+              ? local_repeated_duration / std::abs(timing_.playback_rate)
+              : std::numeric_limits<double>::infinity();
+      DCHECK_GE(local_active_duration, 0);
+      const double local_local_time =
+          local_time < timing_.start_delay
+              ? local_time
+              : local_active_duration + timing_.start_delay;
+      const AnimationEffect::Phase local_current_phase =
+          CalculatePhase(local_active_duration, local_local_time, timing_);
+      const double local_active_time = CalculateActiveTime(
+          local_active_duration,
+          ResolvedFillMode(timing_.fill_mode, IsKeyframeEffect()),
+          local_local_time, kParentPhase, local_current_phase, timing_);
+      const double start_offset =
+          timing_.iteration_start * kLocalIterationDuration;
+      DCHECK_GE(start_offset, 0);
+      const double scaled_active_time = CalculateScaledActiveTime(
+          local_active_duration, local_active_time, start_offset, timing_);
+      const double iteration_time = CalculateIterationTime(
+          kLocalIterationDuration, local_repeated_duration, scaled_active_time,
+          start_offset, current_phase, timing_);
+
+      current_iteration = CalculateCurrentIteration(
+          kLocalIterationDuration, iteration_time, scaled_active_time, timing_);
+      progress = CalculateTransformedTime(
+          current_iteration, kLocalIterationDuration, iteration_time, timing_);
+    }
+
+    calculated_.current_iteration = current_iteration;
+    calculated_.progress = progress;
+
+    calculated_.phase = current_phase;
+    calculated_.is_in_effect = !IsNull(active_time);
+    calculated_.is_in_play = GetPhase() == kPhaseActive;
+    calculated_.is_current = GetPhase() == kPhaseBefore || IsInPlay();
+    calculated_.local_time = last_update_time_;
+  }
+
+  // Test for events even if timing didn't need an update as the animation may
+  // have gained a start time.
+  // FIXME: Refactor so that we can DCHECK(owner_) here, this is currently
+  // required to be nullable for testing.
+  if (reason == kTimingUpdateForAnimationFrame &&
+      (!owner_ || owner_->IsEventDispatchAllowed())) {
+    if (event_delegate_)
+      event_delegate_->OnEventCondition(*this);
+  }
+
+  if (needs_update) {
+    // FIXME: This probably shouldn't be recursive.
+    UpdateChildrenAndEffects();
+    calculated_.time_to_forwards_effect_change =
+        CalculateTimeToEffectChange(true, local_time, time_to_next_iteration);
+    calculated_.time_to_reverse_effect_change =
+        CalculateTimeToEffectChange(false, local_time, time_to_next_iteration);
+  }
+}
+
+const AnimationEffect::CalculatedTiming& AnimationEffect::EnsureCalculated()
+    const {
+  if (!owner_)
+    return calculated_;
+
+  owner_->UpdateIfNecessary();
+  return calculated_;
+}
+
+AnimationEffectTimingReadOnly* AnimationEffect::timing() {
+  return AnimationEffectTimingReadOnly::Create(this);
+}
+
+Animation* AnimationEffect::GetAnimation() {
+  return owner_ ? owner_->GetAnimation() : nullptr;
+}
+const Animation* AnimationEffect::GetAnimation() const {
+  return owner_ ? owner_->GetAnimation() : nullptr;
+}
+
+void AnimationEffect::Trace(blink::Visitor* visitor) {
+  visitor->Trace(owner_);
+  visitor->Trace(event_delegate_);
+  ScriptWrappable::Trace(visitor);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/animation/AnimationEffect.h b/third_party/WebKit/Source/core/animation/AnimationEffect.h
new file mode 100644
index 0000000..93508fc7
--- /dev/null
+++ b/third_party/WebKit/Source/core/animation/AnimationEffect.h
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef AnimationEffect_h
+#define AnimationEffect_h
+
+#include "core/CoreExport.h"
+#include "core/animation/Timing.h"
+#include "platform/bindings/ScriptWrappable.h"
+#include "platform/heap/Handle.h"
+#include "platform/wtf/Optional.h"
+
+namespace blink {
+
+class Animation;
+class AnimationEffectOwner;
+class AnimationEffectTimingReadOnly;
+class ComputedTimingProperties;
+
+enum TimingUpdateReason {
+  kTimingUpdateOnDemand,
+  kTimingUpdateForAnimationFrame
+};
+
+static inline bool IsNull(double value) {
+  return std::isnan(value);
+}
+
+static inline double NullValue() {
+  return std::numeric_limits<double>::quiet_NaN();
+}
+
+// Represents the content of an Animation and its fractional timing state.
+// https://drafts.csswg.org/web-animations/#the-animationeffect-interface
+class CORE_EXPORT AnimationEffect : public ScriptWrappable {
+  DEFINE_WRAPPERTYPEINFO();
+  // Calls Attach/Detach, GetAnimation, UpdateInheritedTime.
+  friend class Animation;
+
+  // Calls GetAnimation().
+  // TODO(majidvp): Remove this. EffectStack should not need to access animation
+  // directly.
+  friend class EffectStack;
+
+ public:
+  // Note that logic in CSSAnimations depends on the order of these values.
+  enum Phase {
+    kPhaseBefore,
+    kPhaseActive,
+    kPhaseAfter,
+    kPhaseNone,
+  };
+
+  class EventDelegate : public GarbageCollectedFinalized<EventDelegate> {
+   public:
+    virtual ~EventDelegate() = default;
+    virtual bool RequiresIterationEvents(const AnimationEffect&) = 0;
+    virtual void OnEventCondition(const AnimationEffect&) = 0;
+    virtual void Trace(blink::Visitor* visitor) {}
+  };
+
+  virtual ~AnimationEffect() = default;
+
+  virtual bool IsKeyframeEffect() const { return false; }
+  virtual bool IsInertEffect() const { return false; }
+
+  Phase GetPhase() const { return EnsureCalculated().phase; }
+  bool IsCurrent() const { return EnsureCalculated().is_current; }
+  bool IsInEffect() const { return EnsureCalculated().is_in_effect; }
+  bool IsInPlay() const { return EnsureCalculated().is_in_play; }
+  double CurrentIteration() const {
+    return EnsureCalculated().current_iteration;
+  }
+  WTF::Optional<double> Progress() const { return EnsureCalculated().progress; }
+  double TimeToForwardsEffectChange() const {
+    return EnsureCalculated().time_to_forwards_effect_change;
+  }
+  double TimeToReverseEffectChange() const {
+    return EnsureCalculated().time_to_reverse_effect_change;
+  }
+
+  double IterationDuration() const;
+  double ActiveDurationInternal() const;
+  double EndTimeInternal() const {
+    return SpecifiedTiming().start_delay + ActiveDurationInternal() +
+           SpecifiedTiming().end_delay;
+  }
+
+  const Timing& SpecifiedTiming() const { return timing_; }
+  virtual AnimationEffectTimingReadOnly* timing();
+  void UpdateSpecifiedTiming(const Timing&);
+  EventDelegate* GetEventDelegate() { return event_delegate_; }
+
+  void getComputedTiming(ComputedTimingProperties&);
+  ComputedTimingProperties getComputedTiming();
+
+  const Animation* GetAnimationForTesting() const { return GetAnimation(); }
+
+  virtual void Trace(blink::Visitor*);
+
+ protected:
+  explicit AnimationEffect(const Timing&, EventDelegate* = nullptr);
+
+  // When AnimationEffect receives a new inherited time via updateInheritedTime
+  // it will (if necessary) recalculate timings and (if necessary) call
+  // updateChildrenAndEffects.
+  void UpdateInheritedTime(double inherited_time, TimingUpdateReason) const;
+  void Invalidate() const { needs_update_ = true; }
+  bool RequiresIterationEvents() const {
+    return event_delegate_ && event_delegate_->RequiresIterationEvents(*this);
+  }
+  void ClearEventDelegate() { event_delegate_ = nullptr; }
+
+  virtual void Attach(AnimationEffectOwner* owner) { owner_ = owner; }
+
+  virtual void Detach() {
+    DCHECK(owner_);
+    owner_ = nullptr;
+  }
+
+  double RepeatedDuration() const;
+
+  virtual void UpdateChildrenAndEffects() const = 0;
+  virtual double IntrinsicIterationDuration() const { return 0; }
+  virtual double CalculateTimeToEffectChange(
+      bool forwards,
+      double local_time,
+      double time_to_next_iteration) const = 0;
+
+  const Animation* GetAnimation() const;
+  Animation* GetAnimation();
+
+  Member<AnimationEffectOwner> owner_;
+  Timing timing_;
+  Member<EventDelegate> event_delegate_;
+
+  mutable struct CalculatedTiming {
+    DISALLOW_NEW();
+    Phase phase;
+    double current_iteration;
+    WTF::Optional<double> progress;
+    bool is_current;
+    bool is_in_effect;
+    bool is_in_play;
+    double local_time;
+    double time_to_forwards_effect_change;
+    double time_to_reverse_effect_change;
+  } calculated_;
+  mutable bool needs_update_;
+  mutable double last_update_time_;
+  String name_;
+
+  const CalculatedTiming& EnsureCalculated() const;
+};
+
+}  // namespace blink
+
+#endif  // AnimationEffect_h
diff --git a/third_party/WebKit/Source/core/animation/AnimationEffect.idl b/third_party/WebKit/Source/core/animation/AnimationEffect.idl
new file mode 100644
index 0000000..e161322
--- /dev/null
+++ b/third_party/WebKit/Source/core/animation/AnimationEffect.idl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// https://drafts.csswg.org/web-animations/#the-animationeffect-interface
+
+[
+    RuntimeEnabled=WebAnimationsAPI
+] interface AnimationEffect {
+    readonly attribute AnimationEffectTimingReadOnly timing;
+    ComputedTimingProperties getComputedTiming();
+};
diff --git a/third_party/WebKit/Source/core/animation/AnimationEffectReadOnly.cpp b/third_party/WebKit/Source/core/animation/AnimationEffectReadOnly.cpp
deleted file mode 100644
index 14bfa0e..0000000
--- a/third_party/WebKit/Source/core/animation/AnimationEffectReadOnly.cpp
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "core/animation/AnimationEffectReadOnly.h"
-
-#include "core/animation/Animation.h"
-#include "core/animation/AnimationEffectTimingReadOnly.h"
-#include "core/animation/ComputedTimingProperties.h"
-#include "core/animation/TimingCalculations.h"
-
-namespace blink {
-
-namespace {
-
-Timing::FillMode ResolvedFillMode(Timing::FillMode fill_mode,
-                                  bool is_animation) {
-  if (fill_mode != Timing::FillMode::AUTO)
-    return fill_mode;
-  if (is_animation)
-    return Timing::FillMode::NONE;
-  return Timing::FillMode::BOTH;
-}
-
-}  // namespace
-
-AnimationEffectReadOnly::AnimationEffectReadOnly(const Timing& timing,
-                                                 EventDelegate* event_delegate)
-    : owner_(nullptr),
-      timing_(timing),
-      event_delegate_(event_delegate),
-      calculated_(),
-      needs_update_(true),
-      last_update_time_(NullValue()) {
-  timing_.AssertValid();
-}
-
-double AnimationEffectReadOnly::IterationDuration() const {
-  double result = std::isnan(timing_.iteration_duration)
-                      ? IntrinsicIterationDuration()
-                      : timing_.iteration_duration;
-  DCHECK_GE(result, 0);
-  return result;
-}
-
-double AnimationEffectReadOnly::RepeatedDuration() const {
-  const double result =
-      MultiplyZeroAlwaysGivesZero(IterationDuration(), timing_.iteration_count);
-  DCHECK_GE(result, 0);
-  return result;
-}
-
-double AnimationEffectReadOnly::ActiveDurationInternal() const {
-  const double result =
-      timing_.playback_rate
-          ? RepeatedDuration() / std::abs(timing_.playback_rate)
-          : std::numeric_limits<double>::infinity();
-  DCHECK_GE(result, 0);
-  return result;
-}
-
-void AnimationEffectReadOnly::UpdateSpecifiedTiming(const Timing& timing) {
-  // FIXME: Test whether the timing is actually different?
-  timing_ = timing;
-  Invalidate();
-  if (owner_)
-    owner_->SpecifiedTimingChanged();
-}
-
-void AnimationEffectReadOnly::getComputedTiming(
-    ComputedTimingProperties& computed_timing) {
-  // ComputedTimingProperties members.
-  computed_timing.setEndTime(EndTimeInternal() * 1000);
-  computed_timing.setActiveDuration(ActiveDurationInternal() * 1000);
-
-  if (EnsureCalculated().is_in_effect) {
-    computed_timing.setLocalTime(EnsureCalculated().local_time * 1000);
-    computed_timing.setProgress(EnsureCalculated().progress.value());
-    computed_timing.setCurrentIteration(EnsureCalculated().current_iteration);
-  } else {
-    computed_timing.setLocalTimeToNull();
-    computed_timing.setProgressToNull();
-    computed_timing.setCurrentIterationToNull();
-  }
-
-  // KeyframeEffectOptions members.
-  computed_timing.setDelay(SpecifiedTiming().start_delay * 1000);
-  computed_timing.setEndDelay(SpecifiedTiming().end_delay * 1000);
-  computed_timing.setFill(Timing::FillModeString(ResolvedFillMode(
-      SpecifiedTiming().fill_mode, IsKeyframeEffectReadOnly())));
-  computed_timing.setIterationStart(SpecifiedTiming().iteration_start);
-  computed_timing.setIterations(SpecifiedTiming().iteration_count);
-
-  UnrestrictedDoubleOrString duration;
-  duration.SetUnrestrictedDouble(IterationDuration() * 1000);
-  computed_timing.setDuration(duration);
-
-  computed_timing.setDirection(
-      Timing::PlaybackDirectionString(SpecifiedTiming().direction));
-  computed_timing.setEasing(SpecifiedTiming().timing_function->ToString());
-}
-
-ComputedTimingProperties AnimationEffectReadOnly::getComputedTiming() {
-  ComputedTimingProperties result;
-  getComputedTiming(result);
-  return result;
-}
-
-void AnimationEffectReadOnly::UpdateInheritedTime(
-    double inherited_time,
-    TimingUpdateReason reason) const {
-  bool needs_update =
-      needs_update_ ||
-      (last_update_time_ != inherited_time &&
-       !(IsNull(last_update_time_) && IsNull(inherited_time))) ||
-      (owner_ && owner_->EffectSuppressed());
-  needs_update_ = false;
-  last_update_time_ = inherited_time;
-
-  const double local_time = inherited_time;
-  double time_to_next_iteration = std::numeric_limits<double>::infinity();
-  if (needs_update) {
-    const double active_duration = this->ActiveDurationInternal();
-
-    const Phase current_phase =
-        CalculatePhase(active_duration, local_time, timing_);
-    // FIXME: parentPhase depends on groups being implemented.
-    const AnimationEffectReadOnly::Phase kParentPhase =
-        AnimationEffectReadOnly::kPhaseActive;
-    const double active_time = CalculateActiveTime(
-        active_duration,
-        ResolvedFillMode(timing_.fill_mode, IsKeyframeEffectReadOnly()),
-        local_time, kParentPhase, current_phase, timing_);
-
-    double current_iteration;
-    WTF::Optional<double> progress;
-    if (const double iteration_duration = this->IterationDuration()) {
-      const double start_offset = MultiplyZeroAlwaysGivesZero(
-          timing_.iteration_start, iteration_duration);
-      DCHECK_GE(start_offset, 0);
-      const double scaled_active_time = CalculateScaledActiveTime(
-          active_duration, active_time, start_offset, timing_);
-      const double iteration_time = CalculateIterationTime(
-          iteration_duration, RepeatedDuration(), scaled_active_time,
-          start_offset, current_phase, timing_);
-
-      current_iteration = CalculateCurrentIteration(
-          iteration_duration, iteration_time, scaled_active_time, timing_);
-      const WTF::Optional<double> transformed_time = CalculateTransformedTime(
-          current_iteration, iteration_duration, iteration_time, timing_);
-
-      // The infinite iterationDuration case here is a workaround because
-      // the specified behaviour does not handle infinite durations well.
-      // There is an open issue against the spec to fix this:
-      // https://github.com/w3c/web-animations/issues/142
-      if (!std::isfinite(iteration_duration))
-        progress = fmod(timing_.iteration_start, 1.0);
-      else if (transformed_time)
-        progress = transformed_time.value() / iteration_duration;
-
-      if (!IsNull(iteration_time)) {
-        time_to_next_iteration = (iteration_duration - iteration_time) /
-                                 std::abs(timing_.playback_rate);
-        if (active_duration - active_time < time_to_next_iteration)
-          time_to_next_iteration = std::numeric_limits<double>::infinity();
-      }
-    } else {
-      const double kLocalIterationDuration = 1;
-      const double local_repeated_duration =
-          kLocalIterationDuration * timing_.iteration_count;
-      DCHECK_GE(local_repeated_duration, 0);
-      const double local_active_duration =
-          timing_.playback_rate
-              ? local_repeated_duration / std::abs(timing_.playback_rate)
-              : std::numeric_limits<double>::infinity();
-      DCHECK_GE(local_active_duration, 0);
-      const double local_local_time =
-          local_time < timing_.start_delay
-              ? local_time
-              : local_active_duration + timing_.start_delay;
-      const AnimationEffectReadOnly::Phase local_current_phase =
-          CalculatePhase(local_active_duration, local_local_time, timing_);
-      const double local_active_time = CalculateActiveTime(
-          local_active_duration,
-          ResolvedFillMode(timing_.fill_mode, IsKeyframeEffectReadOnly()),
-          local_local_time, kParentPhase, local_current_phase, timing_);
-      const double start_offset =
-          timing_.iteration_start * kLocalIterationDuration;
-      DCHECK_GE(start_offset, 0);
-      const double scaled_active_time = CalculateScaledActiveTime(
-          local_active_duration, local_active_time, start_offset, timing_);
-      const double iteration_time = CalculateIterationTime(
-          kLocalIterationDuration, local_repeated_duration, scaled_active_time,
-          start_offset, current_phase, timing_);
-
-      current_iteration = CalculateCurrentIteration(
-          kLocalIterationDuration, iteration_time, scaled_active_time, timing_);
-      progress = CalculateTransformedTime(
-          current_iteration, kLocalIterationDuration, iteration_time, timing_);
-    }
-
-    calculated_.current_iteration = current_iteration;
-    calculated_.progress = progress;
-
-    calculated_.phase = current_phase;
-    calculated_.is_in_effect = !IsNull(active_time);
-    calculated_.is_in_play = GetPhase() == kPhaseActive;
-    calculated_.is_current = GetPhase() == kPhaseBefore || IsInPlay();
-    calculated_.local_time = last_update_time_;
-  }
-
-  // Test for events even if timing didn't need an update as the animation may
-  // have gained a start time.
-  // FIXME: Refactor so that we can DCHECK(owner_) here, this is currently
-  // required to be nullable for testing.
-  if (reason == kTimingUpdateForAnimationFrame &&
-      (!owner_ || owner_->IsEventDispatchAllowed())) {
-    if (event_delegate_)
-      event_delegate_->OnEventCondition(*this);
-  }
-
-  if (needs_update) {
-    // FIXME: This probably shouldn't be recursive.
-    UpdateChildrenAndEffects();
-    calculated_.time_to_forwards_effect_change =
-        CalculateTimeToEffectChange(true, local_time, time_to_next_iteration);
-    calculated_.time_to_reverse_effect_change =
-        CalculateTimeToEffectChange(false, local_time, time_to_next_iteration);
-  }
-}
-
-const AnimationEffectReadOnly::CalculatedTiming&
-AnimationEffectReadOnly::EnsureCalculated() const {
-  if (!owner_)
-    return calculated_;
-
-  owner_->UpdateIfNecessary();
-  return calculated_;
-}
-
-AnimationEffectTimingReadOnly* AnimationEffectReadOnly::timing() {
-  return AnimationEffectTimingReadOnly::Create(this);
-}
-
-Animation* AnimationEffectReadOnly::GetAnimation() {
-  return owner_ ? owner_->GetAnimation() : nullptr;
-}
-const Animation* AnimationEffectReadOnly::GetAnimation() const {
-  return owner_ ? owner_->GetAnimation() : nullptr;
-}
-
-void AnimationEffectReadOnly::Trace(blink::Visitor* visitor) {
-  visitor->Trace(owner_);
-  visitor->Trace(event_delegate_);
-  ScriptWrappable::Trace(visitor);
-}
-
-}  // namespace blink
diff --git a/third_party/WebKit/Source/core/animation/AnimationEffectReadOnly.h b/third_party/WebKit/Source/core/animation/AnimationEffectReadOnly.h
deleted file mode 100644
index 60085ef0e..0000000
--- a/third_party/WebKit/Source/core/animation/AnimationEffectReadOnly.h
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef AnimationEffectReadOnly_h
-#define AnimationEffectReadOnly_h
-
-#include "core/CoreExport.h"
-#include "core/animation/Timing.h"
-#include "platform/bindings/ScriptWrappable.h"
-#include "platform/heap/Handle.h"
-#include "platform/wtf/Optional.h"
-
-namespace blink {
-
-class Animation;
-class AnimationEffectOwner;
-class AnimationEffectReadOnly;
-class AnimationEffectTimingReadOnly;
-class ComputedTimingProperties;
-
-enum TimingUpdateReason {
-  kTimingUpdateOnDemand,
-  kTimingUpdateForAnimationFrame
-};
-
-static inline bool IsNull(double value) {
-  return std::isnan(value);
-}
-
-static inline double NullValue() {
-  return std::numeric_limits<double>::quiet_NaN();
-}
-
-// Represents the content of an Animation and its fractional timing state.
-// http://drafts.csswg.org/web-animations/#animation-effect
-class CORE_EXPORT AnimationEffectReadOnly : public ScriptWrappable {
-  DEFINE_WRAPPERTYPEINFO();
-  // Calls Attach/Detach, GetAnimation, UpdateInheritedTime.
-  friend class Animation;
-
-  // Calls GetAnimation().
-  // TODO(majidvp): Remove this. EffectStack should not need to access animation
-  // directly.
-  friend class EffectStack;
-
- public:
-  // Note that logic in CSSAnimations depends on the order of these values.
-  enum Phase {
-    kPhaseBefore,
-    kPhaseActive,
-    kPhaseAfter,
-    kPhaseNone,
-  };
-
-  class EventDelegate : public GarbageCollectedFinalized<EventDelegate> {
-   public:
-    virtual ~EventDelegate() = default;
-    virtual bool RequiresIterationEvents(const AnimationEffectReadOnly&) = 0;
-    virtual void OnEventCondition(const AnimationEffectReadOnly&) = 0;
-    virtual void Trace(blink::Visitor* visitor) {}
-  };
-
-  virtual ~AnimationEffectReadOnly() = default;
-
-  virtual bool IsKeyframeEffectReadOnly() const { return false; }
-  virtual bool IsKeyframeEffect() const { return false; }
-  virtual bool IsInertEffect() const { return false; }
-
-  Phase GetPhase() const { return EnsureCalculated().phase; }
-  bool IsCurrent() const { return EnsureCalculated().is_current; }
-  bool IsInEffect() const { return EnsureCalculated().is_in_effect; }
-  bool IsInPlay() const { return EnsureCalculated().is_in_play; }
-  double CurrentIteration() const {
-    return EnsureCalculated().current_iteration;
-  }
-  WTF::Optional<double> Progress() const { return EnsureCalculated().progress; }
-  double TimeToForwardsEffectChange() const {
-    return EnsureCalculated().time_to_forwards_effect_change;
-  }
-  double TimeToReverseEffectChange() const {
-    return EnsureCalculated().time_to_reverse_effect_change;
-  }
-
-  double IterationDuration() const;
-  double ActiveDurationInternal() const;
-  double EndTimeInternal() const {
-    return SpecifiedTiming().start_delay + ActiveDurationInternal() +
-           SpecifiedTiming().end_delay;
-  }
-
-  const Timing& SpecifiedTiming() const { return timing_; }
-  virtual AnimationEffectTimingReadOnly* timing();
-  void UpdateSpecifiedTiming(const Timing&);
-  EventDelegate* GetEventDelegate() { return event_delegate_; }
-
-  void getComputedTiming(ComputedTimingProperties&);
-  ComputedTimingProperties getComputedTiming();
-
-  const Animation* GetAnimationForTesting() const { return GetAnimation(); }
-
-  virtual void Trace(blink::Visitor*);
-
- protected:
-  explicit AnimationEffectReadOnly(const Timing&, EventDelegate* = nullptr);
-
-  // When AnimationEffectReadOnly receives a new inherited time via
-  // updateInheritedTime it will (if necessary) recalculate timings and (if
-  // necessary) call updateChildrenAndEffects.
-  void UpdateInheritedTime(double inherited_time, TimingUpdateReason) const;
-  void Invalidate() const { needs_update_ = true; }
-  bool RequiresIterationEvents() const {
-    return event_delegate_ && event_delegate_->RequiresIterationEvents(*this);
-  }
-  void ClearEventDelegate() { event_delegate_ = nullptr; }
-
-  virtual void Attach(AnimationEffectOwner* owner) { owner_ = owner; }
-
-  virtual void Detach() {
-    DCHECK(owner_);
-    owner_ = nullptr;
-  }
-
-  double RepeatedDuration() const;
-
-  virtual void UpdateChildrenAndEffects() const = 0;
-  virtual double IntrinsicIterationDuration() const { return 0; }
-  virtual double CalculateTimeToEffectChange(
-      bool forwards,
-      double local_time,
-      double time_to_next_iteration) const = 0;
-
-  const Animation* GetAnimation() const;
-  Animation* GetAnimation();
-
-  Member<AnimationEffectOwner> owner_;
-  Timing timing_;
-  Member<EventDelegate> event_delegate_;
-
-  mutable struct CalculatedTiming {
-    DISALLOW_NEW();
-    Phase phase;
-    double current_iteration;
-    WTF::Optional<double> progress;
-    bool is_current;
-    bool is_in_effect;
-    bool is_in_play;
-    double local_time;
-    double time_to_forwards_effect_change;
-    double time_to_reverse_effect_change;
-  } calculated_;
-  mutable bool needs_update_;
-  mutable double last_update_time_;
-  String name_;
-
-  const CalculatedTiming& EnsureCalculated() const;
-};
-
-}  // namespace blink
-
-#endif  // AnimationEffectReadOnly_h
diff --git a/third_party/WebKit/Source/core/animation/AnimationEffectReadOnly.idl b/third_party/WebKit/Source/core/animation/AnimationEffectReadOnly.idl
deleted file mode 100644
index 7c4a980..0000000
--- a/third_party/WebKit/Source/core/animation/AnimationEffectReadOnly.idl
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-// https://drafts.csswg.org/web-animations/#the-animationeffectreadonly-interface
-
-[
-    RuntimeEnabled=WebAnimationsAPI
-] interface AnimationEffectReadOnly {
-    readonly attribute AnimationEffectTimingReadOnly timing;
-    ComputedTimingProperties getComputedTiming();
-};
diff --git a/third_party/WebKit/Source/core/animation/AnimationEffectReadOnlyTest.cpp b/third_party/WebKit/Source/core/animation/AnimationEffectReadOnlyTest.cpp
deleted file mode 100644
index fb7c60c..0000000
--- a/third_party/WebKit/Source/core/animation/AnimationEffectReadOnlyTest.cpp
+++ /dev/null
@@ -1,770 +0,0 @@
-/*
- * Copyright (c) 2013, Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "core/animation/AnimationEffectReadOnly.h"
-
-#include "core/animation/ComputedTimingProperties.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace blink {
-
-class TestAnimationEffectEventDelegate
-    : public AnimationEffectReadOnly::EventDelegate {
- public:
-  void OnEventCondition(
-      const AnimationEffectReadOnly& animation_node) override {
-    event_triggered_ = true;
-  }
-  bool RequiresIterationEvents(
-      const AnimationEffectReadOnly& animation_node) override {
-    return true;
-  }
-  void Reset() { event_triggered_ = false; }
-  bool EventTriggered() { return event_triggered_; }
-
- private:
-  bool event_triggered_;
-};
-
-class TestAnimationEffectReadOnly : public AnimationEffectReadOnly {
- public:
-  static TestAnimationEffectReadOnly* Create(const Timing& specified) {
-    return new TestAnimationEffectReadOnly(
-        specified, new TestAnimationEffectEventDelegate());
-  }
-
-  void UpdateInheritedTime(double time) {
-    UpdateInheritedTime(time, kTimingUpdateForAnimationFrame);
-  }
-
-  void UpdateInheritedTime(double time, TimingUpdateReason reason) {
-    event_delegate_->Reset();
-    AnimationEffectReadOnly::UpdateInheritedTime(time, reason);
-  }
-
-  void UpdateChildrenAndEffects() const override {}
-  void WillDetach() {}
-  TestAnimationEffectEventDelegate* EventDelegate() {
-    return event_delegate_.Get();
-  }
-  double CalculateTimeToEffectChange(
-      bool forwards,
-      double local_time,
-      double time_to_next_iteration) const override {
-    local_time_ = local_time;
-    time_to_next_iteration_ = time_to_next_iteration;
-    return -1;
-  }
-  double TakeLocalTime() {
-    const double result = local_time_;
-    local_time_ = NullValue();
-    return result;
-  }
-
-  double TakeTimeToNextIteration() {
-    const double result = time_to_next_iteration_;
-    time_to_next_iteration_ = NullValue();
-    return result;
-  }
-
-  void Trace(blink::Visitor* visitor) override {
-    visitor->Trace(event_delegate_);
-    AnimationEffectReadOnly::Trace(visitor);
-  }
-
- private:
-  TestAnimationEffectReadOnly(const Timing& specified,
-                              TestAnimationEffectEventDelegate* event_delegate)
-      : AnimationEffectReadOnly(specified, event_delegate),
-        event_delegate_(event_delegate) {}
-
-  Member<TestAnimationEffectEventDelegate> event_delegate_;
-  mutable double local_time_;
-  mutable double time_to_next_iteration_;
-};
-
-TEST(AnimationAnimationEffectReadOnlyTest, Sanity) {
-  Timing timing;
-  timing.iteration_duration = 2;
-  TestAnimationEffectReadOnly* animation_node =
-      TestAnimationEffectReadOnly::Create(timing);
-
-  animation_node->UpdateInheritedTime(0);
-
-  EXPECT_EQ(AnimationEffectReadOnly::kPhaseActive, animation_node->GetPhase());
-  EXPECT_TRUE(animation_node->IsInPlay());
-  EXPECT_TRUE(animation_node->IsCurrent());
-  EXPECT_TRUE(animation_node->IsInEffect());
-  EXPECT_EQ(0, animation_node->CurrentIteration());
-  EXPECT_EQ(2, animation_node->ActiveDurationInternal());
-  EXPECT_EQ(0, animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(1);
-
-  EXPECT_EQ(AnimationEffectReadOnly::kPhaseActive, animation_node->GetPhase());
-  EXPECT_TRUE(animation_node->IsInPlay());
-  EXPECT_TRUE(animation_node->IsCurrent());
-  EXPECT_TRUE(animation_node->IsInEffect());
-  EXPECT_EQ(0, animation_node->CurrentIteration());
-  EXPECT_EQ(2, animation_node->ActiveDurationInternal());
-  EXPECT_EQ(0.5, animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(2);
-
-  EXPECT_EQ(AnimationEffectReadOnly::kPhaseAfter, animation_node->GetPhase());
-  EXPECT_FALSE(animation_node->IsInPlay());
-  EXPECT_FALSE(animation_node->IsCurrent());
-  EXPECT_TRUE(animation_node->IsInEffect());
-  EXPECT_EQ(0, animation_node->CurrentIteration());
-  EXPECT_EQ(2, animation_node->ActiveDurationInternal());
-  EXPECT_EQ(1, animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(3);
-
-  EXPECT_EQ(AnimationEffectReadOnly::kPhaseAfter, animation_node->GetPhase());
-  EXPECT_FALSE(animation_node->IsInPlay());
-  EXPECT_FALSE(animation_node->IsCurrent());
-  EXPECT_TRUE(animation_node->IsInEffect());
-  EXPECT_EQ(0, animation_node->CurrentIteration());
-  EXPECT_EQ(2, animation_node->ActiveDurationInternal());
-  EXPECT_EQ(1, animation_node->Progress());
-}
-
-TEST(AnimationAnimationEffectReadOnlyTest, FillAuto) {
-  Timing timing;
-  timing.iteration_duration = 1;
-  TestAnimationEffectReadOnly* animation_node =
-      TestAnimationEffectReadOnly::Create(timing);
-
-  animation_node->UpdateInheritedTime(-1);
-  EXPECT_EQ(0, animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(2);
-  EXPECT_EQ(1, animation_node->Progress());
-}
-
-TEST(AnimationAnimationEffectReadOnlyTest, FillForwards) {
-  Timing timing;
-  timing.iteration_duration = 1;
-  timing.fill_mode = Timing::FillMode::FORWARDS;
-  TestAnimationEffectReadOnly* animation_node =
-      TestAnimationEffectReadOnly::Create(timing);
-
-  animation_node->UpdateInheritedTime(-1);
-  EXPECT_FALSE(animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(2);
-  EXPECT_EQ(1, animation_node->Progress());
-}
-
-TEST(AnimationAnimationEffectReadOnlyTest, FillBackwards) {
-  Timing timing;
-  timing.iteration_duration = 1;
-  timing.fill_mode = Timing::FillMode::BACKWARDS;
-  TestAnimationEffectReadOnly* animation_node =
-      TestAnimationEffectReadOnly::Create(timing);
-
-  animation_node->UpdateInheritedTime(-1);
-  EXPECT_EQ(0, animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(2);
-  EXPECT_FALSE(animation_node->Progress());
-}
-
-TEST(AnimationAnimationEffectReadOnlyTest, FillBoth) {
-  Timing timing;
-  timing.iteration_duration = 1;
-  timing.fill_mode = Timing::FillMode::BOTH;
-  TestAnimationEffectReadOnly* animation_node =
-      TestAnimationEffectReadOnly::Create(timing);
-
-  animation_node->UpdateInheritedTime(-1);
-  EXPECT_EQ(0, animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(2);
-  EXPECT_EQ(1, animation_node->Progress());
-}
-
-TEST(AnimationAnimationEffectReadOnlyTest, StartDelay) {
-  Timing timing;
-  timing.iteration_duration = 1;
-  timing.fill_mode = Timing::FillMode::FORWARDS;
-  timing.start_delay = 0.5;
-  TestAnimationEffectReadOnly* animation_node =
-      TestAnimationEffectReadOnly::Create(timing);
-
-  animation_node->UpdateInheritedTime(0);
-  EXPECT_FALSE(animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(0.5);
-  EXPECT_EQ(0, animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(1.5);
-  EXPECT_EQ(1, animation_node->Progress());
-}
-
-TEST(AnimationAnimationEffectReadOnlyTest, ZeroIteration) {
-  Timing timing;
-  timing.iteration_duration = 1;
-  timing.fill_mode = Timing::FillMode::FORWARDS;
-  timing.iteration_count = 0;
-  TestAnimationEffectReadOnly* animation_node =
-      TestAnimationEffectReadOnly::Create(timing);
-
-  animation_node->UpdateInheritedTime(-1);
-  EXPECT_EQ(0, animation_node->ActiveDurationInternal());
-  EXPECT_TRUE(IsNull(animation_node->CurrentIteration()));
-  EXPECT_FALSE(animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(0);
-  EXPECT_EQ(0, animation_node->ActiveDurationInternal());
-  EXPECT_EQ(0, animation_node->CurrentIteration());
-  EXPECT_EQ(0, animation_node->Progress());
-}
-
-TEST(AnimationAnimationEffectReadOnlyTest, InfiniteIteration) {
-  Timing timing;
-  timing.iteration_duration = 1;
-  timing.fill_mode = Timing::FillMode::FORWARDS;
-  timing.iteration_count = std::numeric_limits<double>::infinity();
-  TestAnimationEffectReadOnly* animation_node =
-      TestAnimationEffectReadOnly::Create(timing);
-
-  animation_node->UpdateInheritedTime(-1);
-  EXPECT_TRUE(IsNull(animation_node->CurrentIteration()));
-  EXPECT_FALSE(animation_node->Progress());
-
-  EXPECT_EQ(std::numeric_limits<double>::infinity(),
-            animation_node->ActiveDurationInternal());
-
-  animation_node->UpdateInheritedTime(0);
-  EXPECT_EQ(0, animation_node->CurrentIteration());
-  EXPECT_EQ(0, animation_node->Progress());
-}
-
-TEST(AnimationAnimationEffectReadOnlyTest, Iteration) {
-  Timing timing;
-  timing.iteration_count = 2;
-  timing.iteration_duration = 2;
-  TestAnimationEffectReadOnly* animation_node =
-      TestAnimationEffectReadOnly::Create(timing);
-
-  animation_node->UpdateInheritedTime(0);
-  EXPECT_EQ(0, animation_node->CurrentIteration());
-  EXPECT_EQ(0, animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(1);
-  EXPECT_EQ(0, animation_node->CurrentIteration());
-  EXPECT_EQ(0.5, animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(2);
-  EXPECT_EQ(1, animation_node->CurrentIteration());
-  EXPECT_EQ(0, animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(2);
-  EXPECT_EQ(1, animation_node->CurrentIteration());
-  EXPECT_EQ(0, animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(5);
-  EXPECT_EQ(1, animation_node->CurrentIteration());
-  EXPECT_EQ(1, animation_node->Progress());
-}
-
-TEST(AnimationAnimationEffectReadOnlyTest, IterationStart) {
-  Timing timing;
-  timing.iteration_start = 1.2;
-  timing.iteration_count = 2.2;
-  timing.iteration_duration = 1;
-  timing.fill_mode = Timing::FillMode::BOTH;
-  TestAnimationEffectReadOnly* animation_node =
-      TestAnimationEffectReadOnly::Create(timing);
-
-  animation_node->UpdateInheritedTime(-1);
-  EXPECT_EQ(1, animation_node->CurrentIteration());
-  EXPECT_NEAR(0.2, animation_node->Progress().value(), 0.000000000000001);
-
-  animation_node->UpdateInheritedTime(0);
-  EXPECT_EQ(1, animation_node->CurrentIteration());
-  EXPECT_NEAR(0.2, animation_node->Progress().value(), 0.000000000000001);
-
-  animation_node->UpdateInheritedTime(10);
-  EXPECT_EQ(3, animation_node->CurrentIteration());
-  EXPECT_NEAR(0.4, animation_node->Progress().value(), 0.000000000000001);
-}
-
-TEST(AnimationAnimationEffectReadOnlyTest, IterationAlternate) {
-  Timing timing;
-  timing.iteration_count = 10;
-  timing.iteration_duration = 1;
-  timing.direction = Timing::PlaybackDirection::ALTERNATE_NORMAL;
-  TestAnimationEffectReadOnly* animation_node =
-      TestAnimationEffectReadOnly::Create(timing);
-
-  animation_node->UpdateInheritedTime(0.75);
-  EXPECT_EQ(0, animation_node->CurrentIteration());
-  EXPECT_EQ(0.75, animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(1.75);
-  EXPECT_EQ(1, animation_node->CurrentIteration());
-  EXPECT_EQ(0.25, animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(2.75);
-  EXPECT_EQ(2, animation_node->CurrentIteration());
-  EXPECT_EQ(0.75, animation_node->Progress());
-}
-
-TEST(AnimationAnimationEffectReadOnlyTest, IterationAlternateReverse) {
-  Timing timing;
-  timing.iteration_count = 10;
-  timing.iteration_duration = 1;
-  timing.direction = Timing::PlaybackDirection::ALTERNATE_REVERSE;
-  TestAnimationEffectReadOnly* animation_node =
-      TestAnimationEffectReadOnly::Create(timing);
-
-  animation_node->UpdateInheritedTime(0.75);
-  EXPECT_EQ(0, animation_node->CurrentIteration());
-  EXPECT_EQ(0.25, animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(1.75);
-  EXPECT_EQ(1, animation_node->CurrentIteration());
-  EXPECT_EQ(0.75, animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(2.75);
-  EXPECT_EQ(2, animation_node->CurrentIteration());
-  EXPECT_EQ(0.25, animation_node->Progress());
-}
-
-TEST(AnimationAnimationEffectReadOnlyTest, ZeroDurationSanity) {
-  Timing timing;
-  TestAnimationEffectReadOnly* animation_node =
-      TestAnimationEffectReadOnly::Create(timing);
-
-  animation_node->UpdateInheritedTime(0);
-
-  EXPECT_EQ(AnimationEffectReadOnly::kPhaseAfter, animation_node->GetPhase());
-  EXPECT_FALSE(animation_node->IsInPlay());
-  EXPECT_FALSE(animation_node->IsCurrent());
-  EXPECT_TRUE(animation_node->IsInEffect());
-  EXPECT_EQ(0, animation_node->CurrentIteration());
-  EXPECT_EQ(0, animation_node->ActiveDurationInternal());
-  EXPECT_EQ(1, animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(1);
-
-  EXPECT_EQ(AnimationEffectReadOnly::kPhaseAfter, animation_node->GetPhase());
-  EXPECT_FALSE(animation_node->IsInPlay());
-  EXPECT_FALSE(animation_node->IsCurrent());
-  EXPECT_TRUE(animation_node->IsInEffect());
-  EXPECT_EQ(0, animation_node->CurrentIteration());
-  EXPECT_EQ(0, animation_node->ActiveDurationInternal());
-  EXPECT_EQ(1, animation_node->Progress());
-}
-
-TEST(AnimationAnimationEffectReadOnlyTest, ZeroDurationFillForwards) {
-  Timing timing;
-  timing.fill_mode = Timing::FillMode::FORWARDS;
-  TestAnimationEffectReadOnly* animation_node =
-      TestAnimationEffectReadOnly::Create(timing);
-
-  animation_node->UpdateInheritedTime(-1);
-  EXPECT_FALSE(animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(0);
-  EXPECT_EQ(1, animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(1);
-  EXPECT_EQ(1, animation_node->Progress());
-}
-
-TEST(AnimationAnimationEffectReadOnlyTest, ZeroDurationFillBackwards) {
-  Timing timing;
-  timing.fill_mode = Timing::FillMode::BACKWARDS;
-  TestAnimationEffectReadOnly* animation_node =
-      TestAnimationEffectReadOnly::Create(timing);
-
-  animation_node->UpdateInheritedTime(-1);
-  EXPECT_EQ(0, animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(0);
-  EXPECT_FALSE(animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(1);
-  EXPECT_FALSE(animation_node->Progress());
-}
-
-TEST(AnimationAnimationEffectReadOnlyTest, ZeroDurationFillBoth) {
-  Timing timing;
-  timing.fill_mode = Timing::FillMode::BOTH;
-  TestAnimationEffectReadOnly* animation_node =
-      TestAnimationEffectReadOnly::Create(timing);
-
-  animation_node->UpdateInheritedTime(-1);
-  EXPECT_EQ(0, animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(0);
-  EXPECT_EQ(1, animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(1);
-  EXPECT_EQ(1, animation_node->Progress());
-}
-
-TEST(AnimationAnimationEffectReadOnlyTest, ZeroDurationStartDelay) {
-  Timing timing;
-  timing.fill_mode = Timing::FillMode::FORWARDS;
-  timing.start_delay = 0.5;
-  TestAnimationEffectReadOnly* animation_node =
-      TestAnimationEffectReadOnly::Create(timing);
-
-  animation_node->UpdateInheritedTime(0);
-  EXPECT_FALSE(animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(0.5);
-  EXPECT_EQ(1, animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(1.5);
-  EXPECT_EQ(1, animation_node->Progress());
-}
-
-TEST(AnimationAnimationEffectReadOnlyTest, ZeroDurationIterationStartAndCount) {
-  Timing timing;
-  timing.iteration_start = 0.1;
-  timing.iteration_count = 0.2;
-  timing.fill_mode = Timing::FillMode::BOTH;
-  timing.start_delay = 0.3;
-  TestAnimationEffectReadOnly* animation_node =
-      TestAnimationEffectReadOnly::Create(timing);
-
-  animation_node->UpdateInheritedTime(0);
-  EXPECT_EQ(0.1, animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(0.3);
-  EXPECT_DOUBLE_EQ(0.3, animation_node->Progress().value());
-
-  animation_node->UpdateInheritedTime(1);
-  EXPECT_DOUBLE_EQ(0.3, animation_node->Progress().value());
-}
-
-// FIXME: Needs specification work.
-TEST(AnimationAnimationEffectReadOnlyTest, ZeroDurationInfiniteIteration) {
-  Timing timing;
-  timing.fill_mode = Timing::FillMode::FORWARDS;
-  timing.iteration_count = std::numeric_limits<double>::infinity();
-  TestAnimationEffectReadOnly* animation_node =
-      TestAnimationEffectReadOnly::Create(timing);
-
-  animation_node->UpdateInheritedTime(-1);
-  EXPECT_EQ(0, animation_node->ActiveDurationInternal());
-  EXPECT_TRUE(IsNull(animation_node->CurrentIteration()));
-  EXPECT_FALSE(animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(0);
-  EXPECT_EQ(0, animation_node->ActiveDurationInternal());
-  EXPECT_EQ(std::numeric_limits<double>::infinity(),
-            animation_node->CurrentIteration());
-  EXPECT_EQ(1, animation_node->Progress());
-}
-
-TEST(AnimationAnimationEffectReadOnlyTest, ZeroDurationIteration) {
-  Timing timing;
-  timing.fill_mode = Timing::FillMode::FORWARDS;
-  timing.iteration_count = 2;
-  TestAnimationEffectReadOnly* animation_node =
-      TestAnimationEffectReadOnly::Create(timing);
-
-  animation_node->UpdateInheritedTime(-1);
-  EXPECT_TRUE(IsNull(animation_node->CurrentIteration()));
-  EXPECT_FALSE(animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(0);
-  EXPECT_EQ(1, animation_node->CurrentIteration());
-  EXPECT_EQ(1, animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(1);
-  EXPECT_EQ(1, animation_node->CurrentIteration());
-  EXPECT_EQ(1, animation_node->Progress());
-}
-
-TEST(AnimationAnimationEffectReadOnlyTest, ZeroDurationIterationStart) {
-  Timing timing;
-  timing.iteration_start = 1.2;
-  timing.iteration_count = 2.2;
-  timing.fill_mode = Timing::FillMode::BOTH;
-  TestAnimationEffectReadOnly* animation_node =
-      TestAnimationEffectReadOnly::Create(timing);
-
-  animation_node->UpdateInheritedTime(-1);
-  EXPECT_EQ(1, animation_node->CurrentIteration());
-  EXPECT_NEAR(0.2, animation_node->Progress().value(), 0.000000000000001);
-
-  animation_node->UpdateInheritedTime(0);
-  EXPECT_EQ(3, animation_node->CurrentIteration());
-  EXPECT_NEAR(0.4, animation_node->Progress().value(), 0.000000000000001);
-
-  animation_node->UpdateInheritedTime(10);
-  EXPECT_EQ(3, animation_node->CurrentIteration());
-  EXPECT_NEAR(0.4, animation_node->Progress().value(), 0.000000000000001);
-}
-
-TEST(AnimationAnimationEffectReadOnlyTest, ZeroDurationIterationAlternate) {
-  Timing timing;
-  timing.fill_mode = Timing::FillMode::FORWARDS;
-  timing.iteration_count = 2;
-  timing.direction = Timing::PlaybackDirection::ALTERNATE_NORMAL;
-  TestAnimationEffectReadOnly* animation_node =
-      TestAnimationEffectReadOnly::Create(timing);
-
-  animation_node->UpdateInheritedTime(-1);
-  EXPECT_TRUE(IsNull(animation_node->CurrentIteration()));
-  EXPECT_FALSE(animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(0);
-  EXPECT_EQ(1, animation_node->CurrentIteration());
-  EXPECT_EQ(0, animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(1);
-  EXPECT_EQ(1, animation_node->CurrentIteration());
-  EXPECT_EQ(0, animation_node->Progress());
-}
-
-TEST(AnimationAnimationEffectReadOnlyTest,
-     ZeroDurationIterationAlternateReverse) {
-  Timing timing;
-  timing.fill_mode = Timing::FillMode::FORWARDS;
-  timing.iteration_count = 2;
-  timing.direction = Timing::PlaybackDirection::ALTERNATE_REVERSE;
-  TestAnimationEffectReadOnly* animation_node =
-      TestAnimationEffectReadOnly::Create(timing);
-
-  animation_node->UpdateInheritedTime(-1);
-  EXPECT_TRUE(IsNull(animation_node->CurrentIteration()));
-  EXPECT_FALSE(animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(0);
-  EXPECT_EQ(1, animation_node->CurrentIteration());
-  EXPECT_EQ(1, animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(1);
-  EXPECT_EQ(1, animation_node->CurrentIteration());
-  EXPECT_EQ(1, animation_node->Progress());
-}
-
-TEST(AnimationAnimationEffectReadOnlyTest, InfiniteDurationSanity) {
-  Timing timing;
-  timing.iteration_duration = std::numeric_limits<double>::infinity();
-  timing.iteration_count = 1;
-  TestAnimationEffectReadOnly* animation_node =
-      TestAnimationEffectReadOnly::Create(timing);
-
-  animation_node->UpdateInheritedTime(0);
-
-  EXPECT_EQ(std::numeric_limits<double>::infinity(),
-            animation_node->ActiveDurationInternal());
-  EXPECT_EQ(AnimationEffectReadOnly::kPhaseActive, animation_node->GetPhase());
-  EXPECT_TRUE(animation_node->IsInPlay());
-  EXPECT_TRUE(animation_node->IsCurrent());
-  EXPECT_TRUE(animation_node->IsInEffect());
-  EXPECT_EQ(0, animation_node->CurrentIteration());
-  EXPECT_EQ(0, animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(1);
-
-  EXPECT_EQ(std::numeric_limits<double>::infinity(),
-            animation_node->ActiveDurationInternal());
-  EXPECT_EQ(AnimationEffectReadOnly::kPhaseActive, animation_node->GetPhase());
-  EXPECT_TRUE(animation_node->IsInPlay());
-  EXPECT_TRUE(animation_node->IsCurrent());
-  EXPECT_TRUE(animation_node->IsInEffect());
-  EXPECT_EQ(0, animation_node->CurrentIteration());
-  EXPECT_EQ(0, animation_node->Progress());
-}
-
-// FIXME: Needs specification work.
-TEST(AnimationAnimationEffectReadOnlyTest, InfiniteDurationZeroIterations) {
-  Timing timing;
-  timing.iteration_duration = std::numeric_limits<double>::infinity();
-  timing.iteration_count = 0;
-  TestAnimationEffectReadOnly* animation_node =
-      TestAnimationEffectReadOnly::Create(timing);
-
-  animation_node->UpdateInheritedTime(0);
-
-  EXPECT_EQ(0, animation_node->ActiveDurationInternal());
-  EXPECT_EQ(AnimationEffectReadOnly::kPhaseAfter, animation_node->GetPhase());
-  EXPECT_FALSE(animation_node->IsInPlay());
-  EXPECT_FALSE(animation_node->IsCurrent());
-  EXPECT_TRUE(animation_node->IsInEffect());
-  EXPECT_EQ(0, animation_node->CurrentIteration());
-  EXPECT_EQ(0, animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(1);
-
-  EXPECT_EQ(AnimationEffectReadOnly::kPhaseAfter, animation_node->GetPhase());
-  EXPECT_EQ(AnimationEffectReadOnly::kPhaseAfter, animation_node->GetPhase());
-  EXPECT_FALSE(animation_node->IsInPlay());
-  EXPECT_FALSE(animation_node->IsCurrent());
-  EXPECT_TRUE(animation_node->IsInEffect());
-  EXPECT_EQ(0, animation_node->CurrentIteration());
-  EXPECT_EQ(0, animation_node->Progress());
-}
-
-TEST(AnimationAnimationEffectReadOnlyTest, InfiniteDurationInfiniteIterations) {
-  Timing timing;
-  timing.iteration_duration = std::numeric_limits<double>::infinity();
-  timing.iteration_count = std::numeric_limits<double>::infinity();
-  TestAnimationEffectReadOnly* animation_node =
-      TestAnimationEffectReadOnly::Create(timing);
-
-  animation_node->UpdateInheritedTime(0);
-
-  EXPECT_EQ(std::numeric_limits<double>::infinity(),
-            animation_node->ActiveDurationInternal());
-  EXPECT_EQ(AnimationEffectReadOnly::kPhaseActive, animation_node->GetPhase());
-  EXPECT_TRUE(animation_node->IsInPlay());
-  EXPECT_TRUE(animation_node->IsCurrent());
-  EXPECT_TRUE(animation_node->IsInEffect());
-  EXPECT_EQ(0, animation_node->CurrentIteration());
-  EXPECT_EQ(0, animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(1);
-
-  EXPECT_EQ(std::numeric_limits<double>::infinity(),
-            animation_node->ActiveDurationInternal());
-  EXPECT_EQ(AnimationEffectReadOnly::kPhaseActive, animation_node->GetPhase());
-  EXPECT_TRUE(animation_node->IsInPlay());
-  EXPECT_TRUE(animation_node->IsCurrent());
-  EXPECT_TRUE(animation_node->IsInEffect());
-  EXPECT_EQ(0, animation_node->CurrentIteration());
-  EXPECT_EQ(0, animation_node->Progress());
-}
-
-TEST(AnimationAnimationEffectReadOnlyTest, InfiniteDurationZeroPlaybackRate) {
-  Timing timing;
-  timing.iteration_duration = std::numeric_limits<double>::infinity();
-  timing.playback_rate = 0;
-  TestAnimationEffectReadOnly* animation_node =
-      TestAnimationEffectReadOnly::Create(timing);
-
-  animation_node->UpdateInheritedTime(0);
-
-  EXPECT_EQ(std::numeric_limits<double>::infinity(),
-            animation_node->ActiveDurationInternal());
-  EXPECT_EQ(AnimationEffectReadOnly::kPhaseActive, animation_node->GetPhase());
-  EXPECT_TRUE(animation_node->IsInPlay());
-  EXPECT_TRUE(animation_node->IsCurrent());
-  EXPECT_TRUE(animation_node->IsInEffect());
-  EXPECT_EQ(0, animation_node->CurrentIteration());
-  EXPECT_EQ(0, animation_node->Progress());
-
-  animation_node->UpdateInheritedTime(std::numeric_limits<double>::infinity());
-
-  EXPECT_EQ(std::numeric_limits<double>::infinity(),
-            animation_node->ActiveDurationInternal());
-  EXPECT_EQ(AnimationEffectReadOnly::kPhaseAfter, animation_node->GetPhase());
-  EXPECT_FALSE(animation_node->IsInPlay());
-  EXPECT_FALSE(animation_node->IsCurrent());
-  EXPECT_TRUE(animation_node->IsInEffect());
-  EXPECT_EQ(0, animation_node->CurrentIteration());
-  EXPECT_EQ(0, animation_node->Progress());
-}
-
-TEST(AnimationAnimationEffectReadOnlyTest, EndTime) {
-  Timing timing;
-  timing.start_delay = 1;
-  timing.end_delay = 2;
-  timing.iteration_duration = 4;
-  timing.iteration_count = 2;
-  TestAnimationEffectReadOnly* animation_node =
-      TestAnimationEffectReadOnly::Create(timing);
-  EXPECT_EQ(11, animation_node->EndTimeInternal());
-}
-
-TEST(AnimationAnimationEffectReadOnlyTest, Events) {
-  Timing timing;
-  timing.iteration_duration = 1;
-  timing.fill_mode = Timing::FillMode::FORWARDS;
-  timing.iteration_count = 2;
-  timing.start_delay = 1;
-  TestAnimationEffectReadOnly* animation_node =
-      TestAnimationEffectReadOnly::Create(timing);
-
-  animation_node->UpdateInheritedTime(0.0, kTimingUpdateOnDemand);
-  EXPECT_FALSE(animation_node->EventDelegate()->EventTriggered());
-
-  animation_node->UpdateInheritedTime(0.0, kTimingUpdateForAnimationFrame);
-  EXPECT_TRUE(animation_node->EventDelegate()->EventTriggered());
-
-  animation_node->UpdateInheritedTime(1.5, kTimingUpdateOnDemand);
-  EXPECT_FALSE(animation_node->EventDelegate()->EventTriggered());
-
-  animation_node->UpdateInheritedTime(1.5, kTimingUpdateForAnimationFrame);
-  EXPECT_TRUE(animation_node->EventDelegate()->EventTriggered());
-}
-
-TEST(AnimationAnimationEffectReadOnlyTest, TimeToEffectChange) {
-  Timing timing;
-  timing.iteration_duration = 1;
-  timing.fill_mode = Timing::FillMode::FORWARDS;
-  timing.iteration_start = 0.2;
-  timing.iteration_count = 2.5;
-  timing.start_delay = 1;
-  timing.direction = Timing::PlaybackDirection::ALTERNATE_NORMAL;
-  TestAnimationEffectReadOnly* animation_node =
-      TestAnimationEffectReadOnly::Create(timing);
-
-  animation_node->UpdateInheritedTime(0);
-  EXPECT_EQ(0, animation_node->TakeLocalTime());
-  EXPECT_TRUE(std::isinf(animation_node->TakeTimeToNextIteration()));
-
-  // Normal iteration.
-  animation_node->UpdateInheritedTime(1.75);
-  EXPECT_EQ(1.75, animation_node->TakeLocalTime());
-  EXPECT_NEAR(0.05, animation_node->TakeTimeToNextIteration(),
-              0.000000000000001);
-
-  // Reverse iteration.
-  animation_node->UpdateInheritedTime(2.75);
-  EXPECT_EQ(2.75, animation_node->TakeLocalTime());
-  EXPECT_NEAR(0.05, animation_node->TakeTimeToNextIteration(),
-              0.000000000000001);
-
-  // Item ends before iteration finishes.
-  animation_node->UpdateInheritedTime(3.4);
-  EXPECT_EQ(AnimationEffectReadOnly::kPhaseActive, animation_node->GetPhase());
-  EXPECT_EQ(3.4, animation_node->TakeLocalTime());
-  EXPECT_TRUE(std::isinf(animation_node->TakeTimeToNextIteration()));
-
-  // Item has finished.
-  animation_node->UpdateInheritedTime(3.5);
-  EXPECT_EQ(AnimationEffectReadOnly::kPhaseAfter, animation_node->GetPhase());
-  EXPECT_EQ(3.5, animation_node->TakeLocalTime());
-  EXPECT_TRUE(std::isinf(animation_node->TakeTimeToNextIteration()));
-}
-
-}  // namespace blink
diff --git a/third_party/WebKit/Source/core/animation/AnimationEffectTest.cpp b/third_party/WebKit/Source/core/animation/AnimationEffectTest.cpp
new file mode 100644
index 0000000..c3cb204
--- /dev/null
+++ b/third_party/WebKit/Source/core/animation/AnimationEffectTest.cpp
@@ -0,0 +1,736 @@
+/*
+ * Copyright (c) 2013, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "core/animation/AnimationEffect.h"
+
+#include "core/animation/ComputedTimingProperties.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+
+class TestAnimationEffectEventDelegate : public AnimationEffect::EventDelegate {
+ public:
+  void OnEventCondition(const AnimationEffect& animation_node) override {
+    event_triggered_ = true;
+  }
+  bool RequiresIterationEvents(const AnimationEffect& animation_node) override {
+    return true;
+  }
+  void Reset() { event_triggered_ = false; }
+  bool EventTriggered() { return event_triggered_; }
+
+ private:
+  bool event_triggered_;
+};
+
+class TestAnimationEffect : public AnimationEffect {
+ public:
+  static TestAnimationEffect* Create(const Timing& specified) {
+    return new TestAnimationEffect(specified,
+                                   new TestAnimationEffectEventDelegate());
+  }
+
+  void UpdateInheritedTime(double time) {
+    UpdateInheritedTime(time, kTimingUpdateForAnimationFrame);
+  }
+
+  void UpdateInheritedTime(double time, TimingUpdateReason reason) {
+    event_delegate_->Reset();
+    AnimationEffect::UpdateInheritedTime(time, reason);
+  }
+
+  void UpdateChildrenAndEffects() const override {}
+  void WillDetach() {}
+  TestAnimationEffectEventDelegate* EventDelegate() {
+    return event_delegate_.Get();
+  }
+  double CalculateTimeToEffectChange(
+      bool forwards,
+      double local_time,
+      double time_to_next_iteration) const override {
+    local_time_ = local_time;
+    time_to_next_iteration_ = time_to_next_iteration;
+    return -1;
+  }
+  double TakeLocalTime() {
+    const double result = local_time_;
+    local_time_ = NullValue();
+    return result;
+  }
+
+  double TakeTimeToNextIteration() {
+    const double result = time_to_next_iteration_;
+    time_to_next_iteration_ = NullValue();
+    return result;
+  }
+
+  void Trace(blink::Visitor* visitor) override {
+    visitor->Trace(event_delegate_);
+    AnimationEffect::Trace(visitor);
+  }
+
+ private:
+  TestAnimationEffect(const Timing& specified,
+                      TestAnimationEffectEventDelegate* event_delegate)
+      : AnimationEffect(specified, event_delegate),
+        event_delegate_(event_delegate) {}
+
+  Member<TestAnimationEffectEventDelegate> event_delegate_;
+  mutable double local_time_;
+  mutable double time_to_next_iteration_;
+};
+
+TEST(AnimationAnimationEffectTest, Sanity) {
+  Timing timing;
+  timing.iteration_duration = 2;
+  TestAnimationEffect* animation_node = TestAnimationEffect::Create(timing);
+
+  animation_node->UpdateInheritedTime(0);
+
+  EXPECT_EQ(AnimationEffect::kPhaseActive, animation_node->GetPhase());
+  EXPECT_TRUE(animation_node->IsInPlay());
+  EXPECT_TRUE(animation_node->IsCurrent());
+  EXPECT_TRUE(animation_node->IsInEffect());
+  EXPECT_EQ(0, animation_node->CurrentIteration());
+  EXPECT_EQ(2, animation_node->ActiveDurationInternal());
+  EXPECT_EQ(0, animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(1);
+
+  EXPECT_EQ(AnimationEffect::kPhaseActive, animation_node->GetPhase());
+  EXPECT_TRUE(animation_node->IsInPlay());
+  EXPECT_TRUE(animation_node->IsCurrent());
+  EXPECT_TRUE(animation_node->IsInEffect());
+  EXPECT_EQ(0, animation_node->CurrentIteration());
+  EXPECT_EQ(2, animation_node->ActiveDurationInternal());
+  EXPECT_EQ(0.5, animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(2);
+
+  EXPECT_EQ(AnimationEffect::kPhaseAfter, animation_node->GetPhase());
+  EXPECT_FALSE(animation_node->IsInPlay());
+  EXPECT_FALSE(animation_node->IsCurrent());
+  EXPECT_TRUE(animation_node->IsInEffect());
+  EXPECT_EQ(0, animation_node->CurrentIteration());
+  EXPECT_EQ(2, animation_node->ActiveDurationInternal());
+  EXPECT_EQ(1, animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(3);
+
+  EXPECT_EQ(AnimationEffect::kPhaseAfter, animation_node->GetPhase());
+  EXPECT_FALSE(animation_node->IsInPlay());
+  EXPECT_FALSE(animation_node->IsCurrent());
+  EXPECT_TRUE(animation_node->IsInEffect());
+  EXPECT_EQ(0, animation_node->CurrentIteration());
+  EXPECT_EQ(2, animation_node->ActiveDurationInternal());
+  EXPECT_EQ(1, animation_node->Progress());
+}
+
+TEST(AnimationAnimationEffectTest, FillAuto) {
+  Timing timing;
+  timing.iteration_duration = 1;
+  TestAnimationEffect* animation_node = TestAnimationEffect::Create(timing);
+
+  animation_node->UpdateInheritedTime(-1);
+  EXPECT_EQ(0, animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(2);
+  EXPECT_EQ(1, animation_node->Progress());
+}
+
+TEST(AnimationAnimationEffectTest, FillForwards) {
+  Timing timing;
+  timing.iteration_duration = 1;
+  timing.fill_mode = Timing::FillMode::FORWARDS;
+  TestAnimationEffect* animation_node = TestAnimationEffect::Create(timing);
+
+  animation_node->UpdateInheritedTime(-1);
+  EXPECT_FALSE(animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(2);
+  EXPECT_EQ(1, animation_node->Progress());
+}
+
+TEST(AnimationAnimationEffectTest, FillBackwards) {
+  Timing timing;
+  timing.iteration_duration = 1;
+  timing.fill_mode = Timing::FillMode::BACKWARDS;
+  TestAnimationEffect* animation_node = TestAnimationEffect::Create(timing);
+
+  animation_node->UpdateInheritedTime(-1);
+  EXPECT_EQ(0, animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(2);
+  EXPECT_FALSE(animation_node->Progress());
+}
+
+TEST(AnimationAnimationEffectTest, FillBoth) {
+  Timing timing;
+  timing.iteration_duration = 1;
+  timing.fill_mode = Timing::FillMode::BOTH;
+  TestAnimationEffect* animation_node = TestAnimationEffect::Create(timing);
+
+  animation_node->UpdateInheritedTime(-1);
+  EXPECT_EQ(0, animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(2);
+  EXPECT_EQ(1, animation_node->Progress());
+}
+
+TEST(AnimationAnimationEffectTest, StartDelay) {
+  Timing timing;
+  timing.iteration_duration = 1;
+  timing.fill_mode = Timing::FillMode::FORWARDS;
+  timing.start_delay = 0.5;
+  TestAnimationEffect* animation_node = TestAnimationEffect::Create(timing);
+
+  animation_node->UpdateInheritedTime(0);
+  EXPECT_FALSE(animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(0.5);
+  EXPECT_EQ(0, animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(1.5);
+  EXPECT_EQ(1, animation_node->Progress());
+}
+
+TEST(AnimationAnimationEffectTest, ZeroIteration) {
+  Timing timing;
+  timing.iteration_duration = 1;
+  timing.fill_mode = Timing::FillMode::FORWARDS;
+  timing.iteration_count = 0;
+  TestAnimationEffect* animation_node = TestAnimationEffect::Create(timing);
+
+  animation_node->UpdateInheritedTime(-1);
+  EXPECT_EQ(0, animation_node->ActiveDurationInternal());
+  EXPECT_TRUE(IsNull(animation_node->CurrentIteration()));
+  EXPECT_FALSE(animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(0);
+  EXPECT_EQ(0, animation_node->ActiveDurationInternal());
+  EXPECT_EQ(0, animation_node->CurrentIteration());
+  EXPECT_EQ(0, animation_node->Progress());
+}
+
+TEST(AnimationAnimationEffectTest, InfiniteIteration) {
+  Timing timing;
+  timing.iteration_duration = 1;
+  timing.fill_mode = Timing::FillMode::FORWARDS;
+  timing.iteration_count = std::numeric_limits<double>::infinity();
+  TestAnimationEffect* animation_node = TestAnimationEffect::Create(timing);
+
+  animation_node->UpdateInheritedTime(-1);
+  EXPECT_TRUE(IsNull(animation_node->CurrentIteration()));
+  EXPECT_FALSE(animation_node->Progress());
+
+  EXPECT_EQ(std::numeric_limits<double>::infinity(),
+            animation_node->ActiveDurationInternal());
+
+  animation_node->UpdateInheritedTime(0);
+  EXPECT_EQ(0, animation_node->CurrentIteration());
+  EXPECT_EQ(0, animation_node->Progress());
+}
+
+TEST(AnimationAnimationEffectTest, Iteration) {
+  Timing timing;
+  timing.iteration_count = 2;
+  timing.iteration_duration = 2;
+  TestAnimationEffect* animation_node = TestAnimationEffect::Create(timing);
+
+  animation_node->UpdateInheritedTime(0);
+  EXPECT_EQ(0, animation_node->CurrentIteration());
+  EXPECT_EQ(0, animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(1);
+  EXPECT_EQ(0, animation_node->CurrentIteration());
+  EXPECT_EQ(0.5, animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(2);
+  EXPECT_EQ(1, animation_node->CurrentIteration());
+  EXPECT_EQ(0, animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(2);
+  EXPECT_EQ(1, animation_node->CurrentIteration());
+  EXPECT_EQ(0, animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(5);
+  EXPECT_EQ(1, animation_node->CurrentIteration());
+  EXPECT_EQ(1, animation_node->Progress());
+}
+
+TEST(AnimationAnimationEffectTest, IterationStart) {
+  Timing timing;
+  timing.iteration_start = 1.2;
+  timing.iteration_count = 2.2;
+  timing.iteration_duration = 1;
+  timing.fill_mode = Timing::FillMode::BOTH;
+  TestAnimationEffect* animation_node = TestAnimationEffect::Create(timing);
+
+  animation_node->UpdateInheritedTime(-1);
+  EXPECT_EQ(1, animation_node->CurrentIteration());
+  EXPECT_NEAR(0.2, animation_node->Progress().value(), 0.000000000000001);
+
+  animation_node->UpdateInheritedTime(0);
+  EXPECT_EQ(1, animation_node->CurrentIteration());
+  EXPECT_NEAR(0.2, animation_node->Progress().value(), 0.000000000000001);
+
+  animation_node->UpdateInheritedTime(10);
+  EXPECT_EQ(3, animation_node->CurrentIteration());
+  EXPECT_NEAR(0.4, animation_node->Progress().value(), 0.000000000000001);
+}
+
+TEST(AnimationAnimationEffectTest, IterationAlternate) {
+  Timing timing;
+  timing.iteration_count = 10;
+  timing.iteration_duration = 1;
+  timing.direction = Timing::PlaybackDirection::ALTERNATE_NORMAL;
+  TestAnimationEffect* animation_node = TestAnimationEffect::Create(timing);
+
+  animation_node->UpdateInheritedTime(0.75);
+  EXPECT_EQ(0, animation_node->CurrentIteration());
+  EXPECT_EQ(0.75, animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(1.75);
+  EXPECT_EQ(1, animation_node->CurrentIteration());
+  EXPECT_EQ(0.25, animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(2.75);
+  EXPECT_EQ(2, animation_node->CurrentIteration());
+  EXPECT_EQ(0.75, animation_node->Progress());
+}
+
+TEST(AnimationAnimationEffectTest, IterationAlternateReverse) {
+  Timing timing;
+  timing.iteration_count = 10;
+  timing.iteration_duration = 1;
+  timing.direction = Timing::PlaybackDirection::ALTERNATE_REVERSE;
+  TestAnimationEffect* animation_node = TestAnimationEffect::Create(timing);
+
+  animation_node->UpdateInheritedTime(0.75);
+  EXPECT_EQ(0, animation_node->CurrentIteration());
+  EXPECT_EQ(0.25, animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(1.75);
+  EXPECT_EQ(1, animation_node->CurrentIteration());
+  EXPECT_EQ(0.75, animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(2.75);
+  EXPECT_EQ(2, animation_node->CurrentIteration());
+  EXPECT_EQ(0.25, animation_node->Progress());
+}
+
+TEST(AnimationAnimationEffectTest, ZeroDurationSanity) {
+  Timing timing;
+  TestAnimationEffect* animation_node = TestAnimationEffect::Create(timing);
+
+  animation_node->UpdateInheritedTime(0);
+
+  EXPECT_EQ(AnimationEffect::kPhaseAfter, animation_node->GetPhase());
+  EXPECT_FALSE(animation_node->IsInPlay());
+  EXPECT_FALSE(animation_node->IsCurrent());
+  EXPECT_TRUE(animation_node->IsInEffect());
+  EXPECT_EQ(0, animation_node->CurrentIteration());
+  EXPECT_EQ(0, animation_node->ActiveDurationInternal());
+  EXPECT_EQ(1, animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(1);
+
+  EXPECT_EQ(AnimationEffect::kPhaseAfter, animation_node->GetPhase());
+  EXPECT_FALSE(animation_node->IsInPlay());
+  EXPECT_FALSE(animation_node->IsCurrent());
+  EXPECT_TRUE(animation_node->IsInEffect());
+  EXPECT_EQ(0, animation_node->CurrentIteration());
+  EXPECT_EQ(0, animation_node->ActiveDurationInternal());
+  EXPECT_EQ(1, animation_node->Progress());
+}
+
+TEST(AnimationAnimationEffectTest, ZeroDurationFillForwards) {
+  Timing timing;
+  timing.fill_mode = Timing::FillMode::FORWARDS;
+  TestAnimationEffect* animation_node = TestAnimationEffect::Create(timing);
+
+  animation_node->UpdateInheritedTime(-1);
+  EXPECT_FALSE(animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(0);
+  EXPECT_EQ(1, animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(1);
+  EXPECT_EQ(1, animation_node->Progress());
+}
+
+TEST(AnimationAnimationEffectTest, ZeroDurationFillBackwards) {
+  Timing timing;
+  timing.fill_mode = Timing::FillMode::BACKWARDS;
+  TestAnimationEffect* animation_node = TestAnimationEffect::Create(timing);
+
+  animation_node->UpdateInheritedTime(-1);
+  EXPECT_EQ(0, animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(0);
+  EXPECT_FALSE(animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(1);
+  EXPECT_FALSE(animation_node->Progress());
+}
+
+TEST(AnimationAnimationEffectTest, ZeroDurationFillBoth) {
+  Timing timing;
+  timing.fill_mode = Timing::FillMode::BOTH;
+  TestAnimationEffect* animation_node = TestAnimationEffect::Create(timing);
+
+  animation_node->UpdateInheritedTime(-1);
+  EXPECT_EQ(0, animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(0);
+  EXPECT_EQ(1, animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(1);
+  EXPECT_EQ(1, animation_node->Progress());
+}
+
+TEST(AnimationAnimationEffectTest, ZeroDurationStartDelay) {
+  Timing timing;
+  timing.fill_mode = Timing::FillMode::FORWARDS;
+  timing.start_delay = 0.5;
+  TestAnimationEffect* animation_node = TestAnimationEffect::Create(timing);
+
+  animation_node->UpdateInheritedTime(0);
+  EXPECT_FALSE(animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(0.5);
+  EXPECT_EQ(1, animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(1.5);
+  EXPECT_EQ(1, animation_node->Progress());
+}
+
+TEST(AnimationAnimationEffectTest, ZeroDurationIterationStartAndCount) {
+  Timing timing;
+  timing.iteration_start = 0.1;
+  timing.iteration_count = 0.2;
+  timing.fill_mode = Timing::FillMode::BOTH;
+  timing.start_delay = 0.3;
+  TestAnimationEffect* animation_node = TestAnimationEffect::Create(timing);
+
+  animation_node->UpdateInheritedTime(0);
+  EXPECT_EQ(0.1, animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(0.3);
+  EXPECT_DOUBLE_EQ(0.3, animation_node->Progress().value());
+
+  animation_node->UpdateInheritedTime(1);
+  EXPECT_DOUBLE_EQ(0.3, animation_node->Progress().value());
+}
+
+// FIXME: Needs specification work.
+TEST(AnimationAnimationEffectTest, ZeroDurationInfiniteIteration) {
+  Timing timing;
+  timing.fill_mode = Timing::FillMode::FORWARDS;
+  timing.iteration_count = std::numeric_limits<double>::infinity();
+  TestAnimationEffect* animation_node = TestAnimationEffect::Create(timing);
+
+  animation_node->UpdateInheritedTime(-1);
+  EXPECT_EQ(0, animation_node->ActiveDurationInternal());
+  EXPECT_TRUE(IsNull(animation_node->CurrentIteration()));
+  EXPECT_FALSE(animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(0);
+  EXPECT_EQ(0, animation_node->ActiveDurationInternal());
+  EXPECT_EQ(std::numeric_limits<double>::infinity(),
+            animation_node->CurrentIteration());
+  EXPECT_EQ(1, animation_node->Progress());
+}
+
+TEST(AnimationAnimationEffectTest, ZeroDurationIteration) {
+  Timing timing;
+  timing.fill_mode = Timing::FillMode::FORWARDS;
+  timing.iteration_count = 2;
+  TestAnimationEffect* animation_node = TestAnimationEffect::Create(timing);
+
+  animation_node->UpdateInheritedTime(-1);
+  EXPECT_TRUE(IsNull(animation_node->CurrentIteration()));
+  EXPECT_FALSE(animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(0);
+  EXPECT_EQ(1, animation_node->CurrentIteration());
+  EXPECT_EQ(1, animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(1);
+  EXPECT_EQ(1, animation_node->CurrentIteration());
+  EXPECT_EQ(1, animation_node->Progress());
+}
+
+TEST(AnimationAnimationEffectTest, ZeroDurationIterationStart) {
+  Timing timing;
+  timing.iteration_start = 1.2;
+  timing.iteration_count = 2.2;
+  timing.fill_mode = Timing::FillMode::BOTH;
+  TestAnimationEffect* animation_node = TestAnimationEffect::Create(timing);
+
+  animation_node->UpdateInheritedTime(-1);
+  EXPECT_EQ(1, animation_node->CurrentIteration());
+  EXPECT_NEAR(0.2, animation_node->Progress().value(), 0.000000000000001);
+
+  animation_node->UpdateInheritedTime(0);
+  EXPECT_EQ(3, animation_node->CurrentIteration());
+  EXPECT_NEAR(0.4, animation_node->Progress().value(), 0.000000000000001);
+
+  animation_node->UpdateInheritedTime(10);
+  EXPECT_EQ(3, animation_node->CurrentIteration());
+  EXPECT_NEAR(0.4, animation_node->Progress().value(), 0.000000000000001);
+}
+
+TEST(AnimationAnimationEffectTest, ZeroDurationIterationAlternate) {
+  Timing timing;
+  timing.fill_mode = Timing::FillMode::FORWARDS;
+  timing.iteration_count = 2;
+  timing.direction = Timing::PlaybackDirection::ALTERNATE_NORMAL;
+  TestAnimationEffect* animation_node = TestAnimationEffect::Create(timing);
+
+  animation_node->UpdateInheritedTime(-1);
+  EXPECT_TRUE(IsNull(animation_node->CurrentIteration()));
+  EXPECT_FALSE(animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(0);
+  EXPECT_EQ(1, animation_node->CurrentIteration());
+  EXPECT_EQ(0, animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(1);
+  EXPECT_EQ(1, animation_node->CurrentIteration());
+  EXPECT_EQ(0, animation_node->Progress());
+}
+
+TEST(AnimationAnimationEffectTest, ZeroDurationIterationAlternateReverse) {
+  Timing timing;
+  timing.fill_mode = Timing::FillMode::FORWARDS;
+  timing.iteration_count = 2;
+  timing.direction = Timing::PlaybackDirection::ALTERNATE_REVERSE;
+  TestAnimationEffect* animation_node = TestAnimationEffect::Create(timing);
+
+  animation_node->UpdateInheritedTime(-1);
+  EXPECT_TRUE(IsNull(animation_node->CurrentIteration()));
+  EXPECT_FALSE(animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(0);
+  EXPECT_EQ(1, animation_node->CurrentIteration());
+  EXPECT_EQ(1, animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(1);
+  EXPECT_EQ(1, animation_node->CurrentIteration());
+  EXPECT_EQ(1, animation_node->Progress());
+}
+
+TEST(AnimationAnimationEffectTest, InfiniteDurationSanity) {
+  Timing timing;
+  timing.iteration_duration = std::numeric_limits<double>::infinity();
+  timing.iteration_count = 1;
+  TestAnimationEffect* animation_node = TestAnimationEffect::Create(timing);
+
+  animation_node->UpdateInheritedTime(0);
+
+  EXPECT_EQ(std::numeric_limits<double>::infinity(),
+            animation_node->ActiveDurationInternal());
+  EXPECT_EQ(AnimationEffect::kPhaseActive, animation_node->GetPhase());
+  EXPECT_TRUE(animation_node->IsInPlay());
+  EXPECT_TRUE(animation_node->IsCurrent());
+  EXPECT_TRUE(animation_node->IsInEffect());
+  EXPECT_EQ(0, animation_node->CurrentIteration());
+  EXPECT_EQ(0, animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(1);
+
+  EXPECT_EQ(std::numeric_limits<double>::infinity(),
+            animation_node->ActiveDurationInternal());
+  EXPECT_EQ(AnimationEffect::kPhaseActive, animation_node->GetPhase());
+  EXPECT_TRUE(animation_node->IsInPlay());
+  EXPECT_TRUE(animation_node->IsCurrent());
+  EXPECT_TRUE(animation_node->IsInEffect());
+  EXPECT_EQ(0, animation_node->CurrentIteration());
+  EXPECT_EQ(0, animation_node->Progress());
+}
+
+// FIXME: Needs specification work.
+TEST(AnimationAnimationEffectTest, InfiniteDurationZeroIterations) {
+  Timing timing;
+  timing.iteration_duration = std::numeric_limits<double>::infinity();
+  timing.iteration_count = 0;
+  TestAnimationEffect* animation_node = TestAnimationEffect::Create(timing);
+
+  animation_node->UpdateInheritedTime(0);
+
+  EXPECT_EQ(0, animation_node->ActiveDurationInternal());
+  EXPECT_EQ(AnimationEffect::kPhaseAfter, animation_node->GetPhase());
+  EXPECT_FALSE(animation_node->IsInPlay());
+  EXPECT_FALSE(animation_node->IsCurrent());
+  EXPECT_TRUE(animation_node->IsInEffect());
+  EXPECT_EQ(0, animation_node->CurrentIteration());
+  EXPECT_EQ(0, animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(1);
+
+  EXPECT_EQ(AnimationEffect::kPhaseAfter, animation_node->GetPhase());
+  EXPECT_EQ(AnimationEffect::kPhaseAfter, animation_node->GetPhase());
+  EXPECT_FALSE(animation_node->IsInPlay());
+  EXPECT_FALSE(animation_node->IsCurrent());
+  EXPECT_TRUE(animation_node->IsInEffect());
+  EXPECT_EQ(0, animation_node->CurrentIteration());
+  EXPECT_EQ(0, animation_node->Progress());
+}
+
+TEST(AnimationAnimationEffectTest, InfiniteDurationInfiniteIterations) {
+  Timing timing;
+  timing.iteration_duration = std::numeric_limits<double>::infinity();
+  timing.iteration_count = std::numeric_limits<double>::infinity();
+  TestAnimationEffect* animation_node = TestAnimationEffect::Create(timing);
+
+  animation_node->UpdateInheritedTime(0);
+
+  EXPECT_EQ(std::numeric_limits<double>::infinity(),
+            animation_node->ActiveDurationInternal());
+  EXPECT_EQ(AnimationEffect::kPhaseActive, animation_node->GetPhase());
+  EXPECT_TRUE(animation_node->IsInPlay());
+  EXPECT_TRUE(animation_node->IsCurrent());
+  EXPECT_TRUE(animation_node->IsInEffect());
+  EXPECT_EQ(0, animation_node->CurrentIteration());
+  EXPECT_EQ(0, animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(1);
+
+  EXPECT_EQ(std::numeric_limits<double>::infinity(),
+            animation_node->ActiveDurationInternal());
+  EXPECT_EQ(AnimationEffect::kPhaseActive, animation_node->GetPhase());
+  EXPECT_TRUE(animation_node->IsInPlay());
+  EXPECT_TRUE(animation_node->IsCurrent());
+  EXPECT_TRUE(animation_node->IsInEffect());
+  EXPECT_EQ(0, animation_node->CurrentIteration());
+  EXPECT_EQ(0, animation_node->Progress());
+}
+
+TEST(AnimationAnimationEffectTest, InfiniteDurationZeroPlaybackRate) {
+  Timing timing;
+  timing.iteration_duration = std::numeric_limits<double>::infinity();
+  timing.playback_rate = 0;
+  TestAnimationEffect* animation_node = TestAnimationEffect::Create(timing);
+
+  animation_node->UpdateInheritedTime(0);
+
+  EXPECT_EQ(std::numeric_limits<double>::infinity(),
+            animation_node->ActiveDurationInternal());
+  EXPECT_EQ(AnimationEffect::kPhaseActive, animation_node->GetPhase());
+  EXPECT_TRUE(animation_node->IsInPlay());
+  EXPECT_TRUE(animation_node->IsCurrent());
+  EXPECT_TRUE(animation_node->IsInEffect());
+  EXPECT_EQ(0, animation_node->CurrentIteration());
+  EXPECT_EQ(0, animation_node->Progress());
+
+  animation_node->UpdateInheritedTime(std::numeric_limits<double>::infinity());
+
+  EXPECT_EQ(std::numeric_limits<double>::infinity(),
+            animation_node->ActiveDurationInternal());
+  EXPECT_EQ(AnimationEffect::kPhaseAfter, animation_node->GetPhase());
+  EXPECT_FALSE(animation_node->IsInPlay());
+  EXPECT_FALSE(animation_node->IsCurrent());
+  EXPECT_TRUE(animation_node->IsInEffect());
+  EXPECT_EQ(0, animation_node->CurrentIteration());
+  EXPECT_EQ(0, animation_node->Progress());
+}
+
+TEST(AnimationAnimationEffectTest, EndTime) {
+  Timing timing;
+  timing.start_delay = 1;
+  timing.end_delay = 2;
+  timing.iteration_duration = 4;
+  timing.iteration_count = 2;
+  TestAnimationEffect* animation_node = TestAnimationEffect::Create(timing);
+  EXPECT_EQ(11, animation_node->EndTimeInternal());
+}
+
+TEST(AnimationAnimationEffectTest, Events) {
+  Timing timing;
+  timing.iteration_duration = 1;
+  timing.fill_mode = Timing::FillMode::FORWARDS;
+  timing.iteration_count = 2;
+  timing.start_delay = 1;
+  TestAnimationEffect* animation_node = TestAnimationEffect::Create(timing);
+
+  animation_node->UpdateInheritedTime(0.0, kTimingUpdateOnDemand);
+  EXPECT_FALSE(animation_node->EventDelegate()->EventTriggered());
+
+  animation_node->UpdateInheritedTime(0.0, kTimingUpdateForAnimationFrame);
+  EXPECT_TRUE(animation_node->EventDelegate()->EventTriggered());
+
+  animation_node->UpdateInheritedTime(1.5, kTimingUpdateOnDemand);
+  EXPECT_FALSE(animation_node->EventDelegate()->EventTriggered());
+
+  animation_node->UpdateInheritedTime(1.5, kTimingUpdateForAnimationFrame);
+  EXPECT_TRUE(animation_node->EventDelegate()->EventTriggered());
+}
+
+TEST(AnimationAnimationEffectTest, TimeToEffectChange) {
+  Timing timing;
+  timing.iteration_duration = 1;
+  timing.fill_mode = Timing::FillMode::FORWARDS;
+  timing.iteration_start = 0.2;
+  timing.iteration_count = 2.5;
+  timing.start_delay = 1;
+  timing.direction = Timing::PlaybackDirection::ALTERNATE_NORMAL;
+  TestAnimationEffect* animation_node = TestAnimationEffect::Create(timing);
+
+  animation_node->UpdateInheritedTime(0);
+  EXPECT_EQ(0, animation_node->TakeLocalTime());
+  EXPECT_TRUE(std::isinf(animation_node->TakeTimeToNextIteration()));
+
+  // Normal iteration.
+  animation_node->UpdateInheritedTime(1.75);
+  EXPECT_EQ(1.75, animation_node->TakeLocalTime());
+  EXPECT_NEAR(0.05, animation_node->TakeTimeToNextIteration(),
+              0.000000000000001);
+
+  // Reverse iteration.
+  animation_node->UpdateInheritedTime(2.75);
+  EXPECT_EQ(2.75, animation_node->TakeLocalTime());
+  EXPECT_NEAR(0.05, animation_node->TakeTimeToNextIteration(),
+              0.000000000000001);
+
+  // Item ends before iteration finishes.
+  animation_node->UpdateInheritedTime(3.4);
+  EXPECT_EQ(AnimationEffect::kPhaseActive, animation_node->GetPhase());
+  EXPECT_EQ(3.4, animation_node->TakeLocalTime());
+  EXPECT_TRUE(std::isinf(animation_node->TakeTimeToNextIteration()));
+
+  // Item has finished.
+  animation_node->UpdateInheritedTime(3.5);
+  EXPECT_EQ(AnimationEffect::kPhaseAfter, animation_node->GetPhase());
+  EXPECT_EQ(3.5, animation_node->TakeLocalTime());
+  EXPECT_TRUE(std::isinf(animation_node->TakeTimeToNextIteration()));
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/animation/AnimationEffectTiming.cpp b/third_party/WebKit/Source/core/animation/AnimationEffectTiming.cpp
index 03e98aba..9d14b253 100644
--- a/third_party/WebKit/Source/core/animation/AnimationEffectTiming.cpp
+++ b/third_party/WebKit/Source/core/animation/AnimationEffectTiming.cpp
@@ -6,7 +6,7 @@
 
 #include "bindings/core/v8/ExceptionState.h"
 #include "bindings/core/v8/unrestricted_double_or_string.h"
-#include "core/animation/AnimationEffectReadOnly.h"
+#include "core/animation/AnimationEffect.h"
 #include "core/animation/AnimationEffectTimingReadOnly.h"
 #include "core/animation/KeyframeEffect.h"
 #include "core/animation/TimingInput.h"
@@ -14,12 +14,11 @@
 
 namespace blink {
 
-AnimationEffectTiming* AnimationEffectTiming::Create(
-    AnimationEffectReadOnly* parent) {
+AnimationEffectTiming* AnimationEffectTiming::Create(AnimationEffect* parent) {
   return new AnimationEffectTiming(parent);
 }
 
-AnimationEffectTiming::AnimationEffectTiming(AnimationEffectReadOnly* parent)
+AnimationEffectTiming::AnimationEffectTiming(AnimationEffect* parent)
     : AnimationEffectTimingReadOnly(parent) {}
 
 void AnimationEffectTiming::setDelay(double delay) {
diff --git a/third_party/WebKit/Source/core/animation/AnimationEffectTiming.h b/third_party/WebKit/Source/core/animation/AnimationEffectTiming.h
index f8d4e1d..6b6897b 100644
--- a/third_party/WebKit/Source/core/animation/AnimationEffectTiming.h
+++ b/third_party/WebKit/Source/core/animation/AnimationEffectTiming.h
@@ -6,7 +6,7 @@
 #define AnimationEffectTiming_h
 
 #include "core/CoreExport.h"
-#include "core/animation/AnimationEffectReadOnly.h"
+#include "core/animation/AnimationEffect.h"
 #include "core/animation/AnimationEffectTimingReadOnly.h"
 #include "platform/wtf/text/WTFString.h"
 
@@ -19,7 +19,7 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static AnimationEffectTiming* Create(AnimationEffectReadOnly* parent);
+  static AnimationEffectTiming* Create(AnimationEffect* parent);
 
   void setDelay(double);
   void setEndDelay(double);
@@ -36,7 +36,7 @@
   void Trace(blink::Visitor*) override;
 
  private:
-  explicit AnimationEffectTiming(AnimationEffectReadOnly*);
+  explicit AnimationEffectTiming(AnimationEffect*);
 };
 
 DEFINE_TYPE_CASTS(AnimationEffectTiming,
diff --git a/third_party/WebKit/Source/core/animation/AnimationEffectTimingReadOnly.cpp b/third_party/WebKit/Source/core/animation/AnimationEffectTimingReadOnly.cpp
index b05fb2b8..de6fa5cf 100644
--- a/third_party/WebKit/Source/core/animation/AnimationEffectTimingReadOnly.cpp
+++ b/third_party/WebKit/Source/core/animation/AnimationEffectTimingReadOnly.cpp
@@ -5,19 +5,19 @@
 #include "core/animation/AnimationEffectTimingReadOnly.h"
 
 #include "bindings/core/v8/unrestricted_double_or_string.h"
-#include "core/animation/AnimationEffectReadOnly.h"
+#include "core/animation/AnimationEffect.h"
 #include "core/animation/KeyframeEffect.h"
 #include "platform/animation/TimingFunction.h"
 
 namespace blink {
 
 AnimationEffectTimingReadOnly* AnimationEffectTimingReadOnly::Create(
-    AnimationEffectReadOnly* parent) {
+    AnimationEffect* parent) {
   return new AnimationEffectTimingReadOnly(parent);
 }
 
 AnimationEffectTimingReadOnly::AnimationEffectTimingReadOnly(
-    AnimationEffectReadOnly* parent)
+    AnimationEffect* parent)
     : parent_(parent) {}
 
 double AnimationEffectTimingReadOnly::delay() {
diff --git a/third_party/WebKit/Source/core/animation/AnimationEffectTimingReadOnly.h b/third_party/WebKit/Source/core/animation/AnimationEffectTimingReadOnly.h
index 089fea04..e1b04d50 100644
--- a/third_party/WebKit/Source/core/animation/AnimationEffectTimingReadOnly.h
+++ b/third_party/WebKit/Source/core/animation/AnimationEffectTimingReadOnly.h
@@ -6,7 +6,7 @@
 #define AnimationEffectTimingReadOnly_h
 
 #include "core/CoreExport.h"
-#include "core/animation/AnimationEffectReadOnly.h"
+#include "core/animation/AnimationEffect.h"
 #include "platform/bindings/ScriptWrappable.h"
 #include "platform/wtf/text/WTFString.h"
 
@@ -18,7 +18,7 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  static AnimationEffectTimingReadOnly* Create(AnimationEffectReadOnly* parent);
+  static AnimationEffectTimingReadOnly* Create(AnimationEffect* parent);
   double delay();
   double endDelay();
   String fill();
@@ -34,8 +34,8 @@
   virtual void Trace(blink::Visitor*);
 
  protected:
-  Member<AnimationEffectReadOnly> parent_;
-  explicit AnimationEffectTimingReadOnly(AnimationEffectReadOnly*);
+  Member<AnimationEffect> parent_;
+  explicit AnimationEffectTimingReadOnly(AnimationEffect*);
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/animation/AnimationTest.cpp b/third_party/WebKit/Source/core/animation/AnimationTest.cpp
index 260de5e..4153bea7 100644
--- a/third_party/WebKit/Source/core/animation/AnimationTest.cpp
+++ b/third_party/WebKit/Source/core/animation/AnimationTest.cpp
@@ -549,8 +549,8 @@
 TEST_F(AnimationAnimationTest, SetEffect) {
   animation = timeline->Play(nullptr);
   animation->setStartTime(0, false);
-  AnimationEffectReadOnly* effect1 = MakeAnimation();
-  AnimationEffectReadOnly* effect2 = MakeAnimation();
+  AnimationEffect* effect1 = MakeAnimation();
+  AnimationEffect* effect2 = MakeAnimation();
   animation->setEffect(effect1);
   EXPECT_EQ(effect1, animation->effect());
   EXPECT_EQ(0, animation->CurrentTimeInternal());
@@ -592,7 +592,7 @@
 }
 
 TEST_F(AnimationAnimationTest, AnimationsDisassociateFromEffect) {
-  AnimationEffectReadOnly* animation_node = animation->effect();
+  AnimationEffect* animation_node = animation->effect();
   Animation* animation2 = timeline->Play(animation_node);
   EXPECT_EQ(nullptr, animation->effect());
   animation->setEffect(animation_node);
diff --git a/third_party/WebKit/Source/core/animation/BUILD.gn b/third_party/WebKit/Source/core/animation/BUILD.gn
index 46012d1d..8b9c9b5 100644
--- a/third_party/WebKit/Source/core/animation/BUILD.gn
+++ b/third_party/WebKit/Source/core/animation/BUILD.gn
@@ -12,9 +12,9 @@
     "Animation.h",
     "AnimationClock.cpp",
     "AnimationClock.h",
+    "AnimationEffect.cpp",
+    "AnimationEffect.h",
     "AnimationEffectOwner.h",
-    "AnimationEffectReadOnly.cpp",
-    "AnimationEffectReadOnly.h",
     "AnimationEffectTiming.cpp",
     "AnimationEffectTiming.h",
     "AnimationEffectTimingReadOnly.cpp",
@@ -138,8 +138,6 @@
     "KeyframeEffect.h",
     "KeyframeEffectModel.cpp",
     "KeyframeEffectModel.h",
-    "KeyframeEffectReadOnly.cpp",
-    "KeyframeEffectReadOnly.h",
     "LengthInterpolationFunctions.cpp",
     "LengthInterpolationFunctions.h",
     "LengthListPropertyFunctions.cpp",
diff --git a/third_party/WebKit/Source/core/animation/CompositorAnimations.cpp b/third_party/WebKit/Source/core/animation/CompositorAnimations.cpp
index 1cd03a2..3d3e1ff4 100644
--- a/third_party/WebKit/Source/core/animation/CompositorAnimations.cpp
+++ b/third_party/WebKit/Source/core/animation/CompositorAnimations.cpp
@@ -33,7 +33,7 @@
 #include <algorithm>
 #include <cmath>
 #include <memory>
-#include "core/animation/AnimationEffectReadOnly.h"
+#include "core/animation/AnimationEffect.h"
 #include "core/animation/ElementAnimations.h"
 #include "core/animation/KeyframeEffectModel.h"
 #include "core/animation/animatable/AnimatableDouble.h"
@@ -152,23 +152,6 @@
     const Animation* animation_to_add,
     const EffectModel& effect,
     double animation_playback_rate) {
-  // Check whether this animation is main thread compositable or not.
-  // If this runtime feature is on + we have either opacity or 2d transform
-  // animation, then this animation is main thread compositable.
-  if (RuntimeEnabledFeatures::
-          TurnOff2DAndOpacityCompositorAnimationsEnabled()) {
-    LayoutObject* layout_object = target_element.GetLayoutObject();
-    if (layout_object) {
-      const ComputedStyle* style = layout_object->Style();
-      if (style && (style->HasCurrentOpacityAnimation() ||
-                    (style->HasCurrentTransformAnimation() &&
-                     !style->Has3DTransform()))) {
-        return FailureCode::AcceleratableAnimNotAccelerated(
-            "Acceleratable animation not accelerated due to an experiment");
-      }
-    }
-  }
-
   const KeyframeEffectModelBase& keyframe_effect =
       ToKeyframeEffectModelBase(effect);
 
@@ -272,6 +255,24 @@
         "animations");
   }
 
+  if (RuntimeEnabledFeatures::
+          TurnOff2DAndOpacityCompositorAnimationsEnabled()) {
+    LayoutObject* layout_object = target_element.GetLayoutObject();
+    if (layout_object && layout_object->PaintingLayer()) {
+      CompositingReasons compositing_reasons =
+          layout_object->PaintingLayer()->GetCompositingReasons();
+      bool has_other_compositing_reasons =
+          compositing_reasons != CompositingReason::kNone;
+      // If we are already compositing the element for other reasons, then not
+      // starting the animation on the compositor will not save memory and will
+      // have worse performance.
+      if (!has_other_compositing_reasons) {
+        return FailureCode::AcceleratableAnimNotAccelerated(
+            "Acceleratable animation not accelerated due to an experiment");
+      }
+    }
+  }
+
   return FailureCode::None();
 }
 
diff --git a/third_party/WebKit/Source/core/animation/CompositorAnimations.h b/third_party/WebKit/Source/core/animation/CompositorAnimations.h
index 2b7a61c..1919e330 100644
--- a/third_party/WebKit/Source/core/animation/CompositorAnimations.h
+++ b/third_party/WebKit/Source/core/animation/CompositorAnimations.h
@@ -165,6 +165,10 @@
       AnimationCompositorAnimationsTest,
       cannotStartElementOnCompositorEffectWithRuntimeFeature);
   FRIEND_TEST_ALL_PREFIXES(AnimationCompositorAnimationsTest,
+                           canStartOpacityWithWillChangeWithRuntimeFeature);
+  FRIEND_TEST_ALL_PREFIXES(AnimationCompositorAnimationsTest,
+                           canStartOpacityWith3DTransformWithRuntimeFeature);
+  FRIEND_TEST_ALL_PREFIXES(AnimationCompositorAnimationsTest,
                            cancelIncompatibleCompositorAnimations);
 };
 
diff --git a/third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp b/third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp
index dc7f058..b3c4cf4 100644
--- a/third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp
+++ b/third_party/WebKit/Source/core/animation/CompositorAnimationsTest.cpp
@@ -49,6 +49,7 @@
 #include "core/frame/WebLocalFrameImpl.h"
 #include "core/layout/LayoutObject.h"
 #include "core/paint/ObjectPaintProperties.h"
+#include "core/paint/PaintLayer.h"
 #include "core/style/ComputedStyle.h"
 #include "core/style/FilterOperations.h"
 #include "core/testing/CoreUnitTestHelper.h"
@@ -1405,9 +1406,9 @@
   EXPECT_EQ(host->GetCompositedAnimationsCountForTesting(), 1u);
 }
 
-// Regression test for crbug.com/781305. When we have a transform animation
-// on a SVG element, the effect can be started on compositor but the element
-// itself cannot. The animation should not be a main thread compositable
+// Regression test for https://crbug.com/781305. When we have a transform
+// animation on a SVG element, the effect can be started on compositor but the
+// element itself cannot. The animation should not be a main thread compositable
 // animation.
 TEST_F(AnimationCompositorAnimationsTest,
        cannotStartElementOnCompositorEffectSVG) {
@@ -1427,6 +1428,49 @@
   EXPECT_EQ(host->GetCompositedAnimationsCountForTesting(), 0u);
 }
 
+// A helper function for the next two tests to avoid duplicate code
+void CanStartOpacityTestHelper(CompositorAnimations::FailureCode code,
+                               Document* document,
+                               size_t composited_animations_count) {
+  EXPECT_EQ(code, CompositorAnimations::FailureCode::None());
+  EXPECT_EQ(document->Timeline().PendingAnimationsCount(), 1u);
+  EXPECT_EQ(document->Timeline().MainThreadCompositableAnimationsCount(), 0u);
+  CompositorAnimationHost* host =
+      document->View()->GetCompositorAnimationHost();
+  EXPECT_EQ(host->GetMainThreadAnimationsCountForTesting(), 0u);
+  EXPECT_EQ(host->GetMainThreadCompositableAnimationsCountForTesting(), 0u);
+  EXPECT_EQ(host->GetCompositedAnimationsCountForTesting(),
+            composited_animations_count);
+}
+
+// Regression tests for https://crbug.com/818809. When an element has an
+// animation that will be composited regardless of an experiment (such as
+// will-change: transform), then an opacity animation on this element will be
+// composited as well.
+TEST_F(AnimationCompositorAnimationsTest,
+       canStartOpacityWithWillChangeWithRuntimeFeature) {
+  ScopedTurnOff2DAndOpacityCompositorAnimationsForTest
+      turn_off_2d_and_opacity_compositors_animation(true);
+  LoadTestData("opacity-with-will-change-transform.html");
+  Document* document = GetFrame()->GetDocument();
+  Element* target = document->getElementById("target");
+  CompositorAnimations::FailureCode code =
+      CompositorAnimations::CheckCanStartElementOnCompositor(*target);
+  CanStartOpacityTestHelper(code, document, 1u);
+}
+
+TEST_F(AnimationCompositorAnimationsTest,
+       canStartOpacityWith3DTransformWithRuntimeFeature) {
+  ScopedTurnOff2DAndOpacityCompositorAnimationsForTest
+      turn_off_2d_and_opacity_compositors_animation(true);
+  LoadTestData("opacity-with-3d-transform.html");
+  Document* document = GetFrame()->GetDocument();
+  Element* target = document->getElementById("target");
+  CompositorAnimations::FailureCode code =
+      CompositorAnimations::CheckCanStartElementOnCompositor(*target);
+  CanStartOpacityTestHelper(code, document, 2u);
+}
+
 TEST_F(AnimationCompositorAnimationsTest,
        cannotStartAnimationOnCompositorWithRuntimeFeature) {
   ScopedTurnOff2DAndOpacityCompositorAnimationsForTest
@@ -1437,16 +1481,15 @@
   const ObjectPaintProperties* properties =
       target->GetLayoutObject()->FirstFragment().PaintProperties();
   EXPECT_TRUE(properties->Transform()->HasDirectCompositingReasons());
-  Timing timing;
-  KeyframeEffectModelBase* effect =
-      StringKeyframeEffectModel::Create(StringKeyframeVector());
-  CompositorAnimations::FailureCode code =
-      CompositorAnimations::CheckCanStartAnimationOnCompositor(
-          timing, *target, nullptr, *effect, 1.0);
-  EXPECT_EQ(
-      code,
-      CompositorAnimations::FailureCode::AcceleratableAnimNotAccelerated(
-          "Acceleratable animation not accelerated due to an experiment"));
+  LayoutObject* layout_object = target->GetLayoutObject();
+  DCHECK(layout_object && layout_object->PaintingLayer());
+  // LoadTestData calls ForceFullCompositingUpdate, which have called
+  // CheckCanStartAnimationOnCompositor on the target element. In this test,
+  // there is one single transform animation, and it should not be composited
+  // because the runtime flag is on.
+  CompositingReasons compositing_reasons =
+      layout_object->PaintingLayer()->GetCompositingReasons();
+  EXPECT_EQ(compositing_reasons, CompositingReason::kNone);
   EXPECT_EQ(document->Timeline().PendingAnimationsCount(), 1u);
   EXPECT_EQ(document->Timeline().MainThreadCompositableAnimationsCount(), 1u);
   CompositorAnimationHost* host =
diff --git a/third_party/WebKit/Source/core/animation/DocumentTimeline.cpp b/third_party/WebKit/Source/core/animation/DocumentTimeline.cpp
index c1af88c..80264cf2 100644
--- a/third_party/WebKit/Source/core/animation/DocumentTimeline.cpp
+++ b/third_party/WebKit/Source/core/animation/DocumentTimeline.cpp
@@ -33,6 +33,7 @@
 #include <algorithm>
 #include "core/animation/Animation.h"
 #include "core/animation/AnimationClock.h"
+#include "core/animation/AnimationEffect.h"
 #include "core/animation/DocumentTimelineOptions.h"
 #include "core/animation/ElementAnimations.h"
 #include "core/dom/Document.h"
@@ -102,7 +103,7 @@
   animations_.insert(&animation);
 }
 
-Animation* DocumentTimeline::Play(AnimationEffectReadOnly* child) {
+Animation* DocumentTimeline::Play(AnimationEffect* child) {
   if (!document_)
     return nullptr;
 
diff --git a/third_party/WebKit/Source/core/animation/DocumentTimeline.h b/third_party/WebKit/Source/core/animation/DocumentTimeline.h
index 5dad714..a53a916d 100644
--- a/third_party/WebKit/Source/core/animation/DocumentTimeline.h
+++ b/third_party/WebKit/Source/core/animation/DocumentTimeline.h
@@ -34,7 +34,7 @@
 #include <memory>
 #include "base/memory/scoped_refptr.h"
 #include "core/CoreExport.h"
-#include "core/animation/AnimationEffectReadOnly.h"
+#include "core/animation/AnimationEffect.h"
 #include "core/animation/AnimationTimeline.h"
 #include "core/animation/EffectModel.h"
 #include "core/dom/Document.h"
@@ -49,7 +49,7 @@
 namespace blink {
 
 class Animation;
-class AnimationEffectReadOnly;
+class AnimationEffect;
 class Document;
 class DocumentTimelineOptions;
 
@@ -83,7 +83,7 @@
   void ServiceAnimations(TimingUpdateReason);
   void ScheduleNextService();
 
-  Animation* Play(AnimationEffectReadOnly*);
+  Animation* Play(AnimationEffect*);
   HeapVector<Member<Animation>> getAnimations();
 
   void AnimationAttached(Animation&);
diff --git a/third_party/WebKit/Source/core/animation/DocumentTimelineTest.cpp b/third_party/WebKit/Source/core/animation/DocumentTimelineTest.cpp
index 0eb1ae8..29a2684 100644
--- a/third_party/WebKit/Source/core/animation/DocumentTimelineTest.cpp
+++ b/third_party/WebKit/Source/core/animation/DocumentTimelineTest.cpp
@@ -32,7 +32,7 @@
 
 #include <memory>
 #include "core/animation/AnimationClock.h"
-#include "core/animation/AnimationEffectReadOnly.h"
+#include "core/animation/AnimationEffect.h"
 #include "core/animation/KeyframeEffect.h"
 #include "core/animation/KeyframeEffectModel.h"
 #include "core/animation/PendingAnimations.h"
diff --git a/third_party/WebKit/Source/core/animation/EffectStack.cpp b/third_party/WebKit/Source/core/animation/EffectStack.cpp
index 25036bc..4178695 100644
--- a/third_party/WebKit/Source/core/animation/EffectStack.cpp
+++ b/third_party/WebKit/Source/core/animation/EffectStack.cpp
@@ -111,7 +111,7 @@
     EffectStack* effect_stack,
     const HeapVector<Member<const InertEffect>>* new_animations,
     const HeapHashSet<Member<const Animation>>* suppressed_animations,
-    KeyframeEffectReadOnly::Priority priority,
+    KeyframeEffect::Priority priority,
     PropertyHandleFilter property_handle_filter) {
   ActiveInterpolationsMap result;
 
@@ -124,7 +124,7 @@
     for (const auto& sampled_effect : sampled_effects) {
       if (sampled_effect->GetPriority() != priority ||
           // TODO(majidvp): Instead of accessing the effect's animation move the
-          // check inside KeyframeEffectReadOnly. http://crbug.com/812410
+          // check inside KeyframeEffect. http://crbug.com/812410
           (suppressed_animations && sampled_effect->Effect() &&
            suppressed_animations->Contains(
                sampled_effect->Effect()->GetAnimation())))
diff --git a/third_party/WebKit/Source/core/animation/EffectStack.h b/third_party/WebKit/Source/core/animation/EffectStack.h
index 8a7dd21..c9c06d1 100644
--- a/third_party/WebKit/Source/core/animation/EffectStack.h
+++ b/third_party/WebKit/Source/core/animation/EffectStack.h
@@ -66,7 +66,7 @@
       EffectStack*,
       const HeapVector<Member<const InertEffect>>* new_animations,
       const HeapHashSet<Member<const Animation>>* suppressed_animations,
-      KeyframeEffectReadOnly::Priority,
+      KeyframeEffect::Priority,
       PropertyHandleFilter = nullptr);
 
   void Trace(blink::Visitor*);
diff --git a/third_party/WebKit/Source/core/animation/EffectStackTest.cpp b/third_party/WebKit/Source/core/animation/EffectStackTest.cpp
index 81cecf90..dac92d6 100644
--- a/third_party/WebKit/Source/core/animation/EffectStackTest.cpp
+++ b/third_party/WebKit/Source/core/animation/EffectStackTest.cpp
@@ -114,7 +114,7 @@
   Play(MakeKeyframeEffect(MakeEffectModel(CSSPropertyFontSize, "3px")), 5);
   ActiveInterpolationsMap result = EffectStack::ActiveInterpolations(
       &element->GetElementAnimations()->GetEffectStack(), nullptr, nullptr,
-      KeyframeEffectReadOnly::kDefaultPriority);
+      KeyframeEffect::kDefaultPriority);
   EXPECT_EQ(1u, result.size());
   EXPECT_EQ(GetFontSizeValue(result), 3);
 }
@@ -131,7 +131,7 @@
   new_animations.push_back(inert2);
   ActiveInterpolationsMap result = EffectStack::ActiveInterpolations(
       &element->GetElementAnimations()->GetEffectStack(), &new_animations,
-      nullptr, KeyframeEffectReadOnly::kDefaultPriority);
+      nullptr, KeyframeEffect::kDefaultPriority);
   EXPECT_EQ(2u, result.size());
   EXPECT_EQ(GetFontSizeValue(result), 3);
   EXPECT_EQ(GetZIndexValue(result), 4);
@@ -145,7 +145,7 @@
   Play(MakeKeyframeEffect(MakeEffectModel(CSSPropertyZIndex, "2")), 0);
   ActiveInterpolationsMap result = EffectStack::ActiveInterpolations(
       &element->GetElementAnimations()->GetEffectStack(), nullptr,
-      &cancelled_animations, KeyframeEffectReadOnly::kDefaultPriority);
+      &cancelled_animations, KeyframeEffect::kDefaultPriority);
   EXPECT_EQ(1u, result.size());
   EXPECT_EQ(GetZIndexValue(result), 2);
 }
@@ -155,14 +155,14 @@
       Play(MakeKeyframeEffect(MakeEffectModel(CSSPropertyFontSize, "1px")), 10);
   ActiveInterpolationsMap result = EffectStack::ActiveInterpolations(
       &element->GetElementAnimations()->GetEffectStack(), nullptr, nullptr,
-      KeyframeEffectReadOnly::kDefaultPriority);
+      KeyframeEffect::kDefaultPriority);
   EXPECT_EQ(1u, result.size());
   EXPECT_EQ(GetFontSizeValue(result), 1);
 
   animation->setEffect(nullptr);
   result = EffectStack::ActiveInterpolations(
       &element->GetElementAnimations()->GetEffectStack(), nullptr, nullptr,
-      KeyframeEffectReadOnly::kDefaultPriority);
+      KeyframeEffect::kDefaultPriority);
   EXPECT_EQ(0u, result.size());
 }
 
@@ -178,7 +178,7 @@
   ThreadState::Current()->CollectAllGarbage();
   interpolations = EffectStack::ActiveInterpolations(
       &element->GetElementAnimations()->GetEffectStack(), nullptr, nullptr,
-      KeyframeEffectReadOnly::kDefaultPriority);
+      KeyframeEffect::kDefaultPriority);
   EXPECT_EQ(1u, interpolations.size());
   EXPECT_EQ(GetFontSizeValue(interpolations), 3);
   EXPECT_EQ(3u, SampledEffectCount());
@@ -187,7 +187,7 @@
   ThreadState::Current()->CollectAllGarbage();
   interpolations = EffectStack::ActiveInterpolations(
       &element->GetElementAnimations()->GetEffectStack(), nullptr, nullptr,
-      KeyframeEffectReadOnly::kDefaultPriority);
+      KeyframeEffect::kDefaultPriority);
   EXPECT_EQ(1u, interpolations.size());
   EXPECT_EQ(GetFontSizeValue(interpolations), 3);
   EXPECT_EQ(3u, SampledEffectCount());
@@ -196,7 +196,7 @@
   ThreadState::Current()->CollectAllGarbage();
   interpolations = EffectStack::ActiveInterpolations(
       &element->GetElementAnimations()->GetEffectStack(), nullptr, nullptr,
-      KeyframeEffectReadOnly::kDefaultPriority);
+      KeyframeEffect::kDefaultPriority);
   EXPECT_EQ(1u, interpolations.size());
   EXPECT_EQ(GetFontSizeValue(interpolations), 3);
   EXPECT_EQ(2u, SampledEffectCount());
@@ -205,7 +205,7 @@
   ThreadState::Current()->CollectAllGarbage();
   interpolations = EffectStack::ActiveInterpolations(
       &element->GetElementAnimations()->GetEffectStack(), nullptr, nullptr,
-      KeyframeEffectReadOnly::kDefaultPriority);
+      KeyframeEffect::kDefaultPriority);
   EXPECT_EQ(1u, interpolations.size());
   EXPECT_EQ(GetFontSizeValue(interpolations), 3);
   EXPECT_EQ(1u, SampledEffectCount());
diff --git a/third_party/WebKit/Source/core/animation/ElementAnimation.cpp b/third_party/WebKit/Source/core/animation/ElementAnimation.cpp
index 037b977..4239e63 100644
--- a/third_party/WebKit/Source/core/animation/ElementAnimation.cpp
+++ b/third_party/WebKit/Source/core/animation/ElementAnimation.cpp
@@ -11,7 +11,6 @@
 #include "core/animation/EffectModel.h"
 #include "core/animation/KeyframeEffect.h"
 #include "core/animation/KeyframeEffectModel.h"
-#include "core/animation/KeyframeEffectReadOnly.h"
 #include "core/animation/Timing.h"
 #include "core/animation/TimingInput.h"
 #include "core/dom/Document.h"
@@ -71,7 +70,7 @@
   for (const auto& animation :
        element.GetDocument().Timeline().getAnimations()) {
     DCHECK(animation->effect());
-    if (ToKeyframeEffectReadOnly(animation->effect())->target() == element &&
+    if (ToKeyframeEffect(animation->effect())->target() == element &&
         (animation->effect()->IsCurrent() || animation->effect()->IsInEffect()))
       animations.push_back(animation);
   }
diff --git a/third_party/WebKit/Source/core/animation/ElementAnimations.cpp b/third_party/WebKit/Source/core/animation/ElementAnimations.cpp
index e2c2c94f..f75d9f5 100644
--- a/third_party/WebKit/Source/core/animation/ElementAnimations.cpp
+++ b/third_party/WebKit/Source/core/animation/ElementAnimations.cpp
@@ -36,7 +36,7 @@
 
 namespace {
 
-void UpdateAnimationFlagsForEffect(const KeyframeEffectReadOnly& effect,
+void UpdateAnimationFlagsForEffect(const KeyframeEffect& effect,
                                    ComputedStyle& style) {
   if (effect.Affects(PropertyHandle(GetCSSPropertyOpacity())))
     style.SetHasCurrentOpacityAnimation(true);
@@ -62,16 +62,15 @@
     const Animation& animation = *entry.key;
     DCHECK(animation.effect());
     // FIXME: Needs to consider AnimationGroup once added.
-    DCHECK(animation.effect()->IsKeyframeEffectReadOnly());
-    const KeyframeEffectReadOnly& effect =
-        *ToKeyframeEffectReadOnly(animation.effect());
+    DCHECK(animation.effect()->IsKeyframeEffect());
+    const KeyframeEffect& effect = *ToKeyframeEffect(animation.effect());
     if (!effect.IsCurrent())
       continue;
     UpdateAnimationFlagsForEffect(effect, style);
   }
 
   for (const auto& entry : worklet_animations_) {
-    const KeyframeEffectReadOnly& effect = *entry->GetEffect();
+    const KeyframeEffect& effect = *entry->GetEffect();
     // TODO(majidvp): we should check the effect's phase before updating the
     // style once the timing of effect is ready to use.
     // https://crbug.com/814851.
diff --git a/third_party/WebKit/Source/core/animation/InertEffect.cpp b/third_party/WebKit/Source/core/animation/InertEffect.cpp
index efeb7c5..b737e18 100644
--- a/third_party/WebKit/Source/core/animation/InertEffect.cpp
+++ b/third_party/WebKit/Source/core/animation/InertEffect.cpp
@@ -45,7 +45,7 @@
                          const Timing& timing,
                          bool paused,
                          double inherited_time)
-    : AnimationEffectReadOnly(timing),
+    : AnimationEffect(timing),
       model_(model),
       paused_(paused),
       inherited_time_(inherited_time) {}
@@ -69,7 +69,7 @@
 
 void InertEffect::Trace(blink::Visitor* visitor) {
   visitor->Trace(model_);
-  AnimationEffectReadOnly::Trace(visitor);
+  AnimationEffect::Trace(visitor);
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/animation/InertEffect.h b/third_party/WebKit/Source/core/animation/InertEffect.h
index cc029a2..a332e60 100644
--- a/third_party/WebKit/Source/core/animation/InertEffect.h
+++ b/third_party/WebKit/Source/core/animation/InertEffect.h
@@ -33,7 +33,7 @@
 
 #include "base/memory/scoped_refptr.h"
 #include "core/CoreExport.h"
-#include "core/animation/AnimationEffectReadOnly.h"
+#include "core/animation/AnimationEffect.h"
 #include "core/animation/KeyframeEffectModel.h"
 
 namespace blink {
@@ -41,7 +41,7 @@
 // Lightweight subset of KeyframeEffect.
 // Used to transport data for deferred KeyframeEffect construction and one off
 // Interpolation sampling.
-class CORE_EXPORT InertEffect final : public AnimationEffectReadOnly {
+class CORE_EXPORT InertEffect final : public AnimationEffect {
  public:
   static InertEffect* Create(KeyframeEffectModelBase*,
                              const Timing&,
@@ -73,7 +73,7 @@
 };
 
 DEFINE_TYPE_CASTS(InertEffect,
-                  AnimationEffectReadOnly,
+                  AnimationEffect,
                   animationEffect,
                   animationEffect->IsInertEffect(),
                   animationEffect.IsInertEffect());
diff --git a/third_party/WebKit/Source/core/animation/Keyframe.h b/third_party/WebKit/Source/core/animation/Keyframe.h
index 7c2192e0..5c71705 100644
--- a/third_party/WebKit/Source/core/animation/Keyframe.h
+++ b/third_party/WebKit/Source/core/animation/Keyframe.h
@@ -8,7 +8,7 @@
 #include "base/macros.h"
 #include "base/memory/scoped_refptr.h"
 #include "core/CoreExport.h"
-#include "core/animation/AnimationEffectReadOnly.h"
+#include "core/animation/AnimationEffect.h"
 #include "core/animation/EffectModel.h"
 #include "core/animation/PropertyHandle.h"
 #include "core/animation/animatable/AnimatableValue.h"
diff --git a/third_party/WebKit/Source/core/animation/KeyframeEffect.cpp b/third_party/WebKit/Source/core/animation/KeyframeEffect.cpp
index 900c1fc..df1ac38 100644
--- a/third_party/WebKit/Source/core/animation/KeyframeEffect.cpp
+++ b/third_party/WebKit/Source/core/animation/KeyframeEffect.cpp
@@ -31,24 +31,29 @@
 #include "core/animation/KeyframeEffect.h"
 
 #include "bindings/core/v8/ExceptionState.h"
+#include "bindings/core/v8/V8ObjectBuilder.h"
 #include "bindings/core/v8/unrestricted_double_or_keyframe_effect_options.h"
-#include "core/animation/AnimationEffectTiming.h"
 #include "core/animation/EffectInput.h"
+#include "core/animation/ElementAnimations.h"
+#include "core/animation/KeyframeEffectModel.h"
 #include "core/animation/KeyframeEffectOptions.h"
-#include "core/animation/KeyframeEffectReadOnly.h"
+#include "core/animation/SampledEffect.h"
 #include "core/animation/TimingInput.h"
 #include "core/dom/Element.h"
+#include "core/dom/NodeComputedStyle.h"
 #include "core/frame/UseCounter.h"
+#include "core/paint/PaintLayer.h"
+#include "core/style/ComputedStyle.h"
+#include "core/svg/SVGElement.h"
 #include "platform/runtime_enabled_features.h"
 
 namespace blink {
 
-KeyframeEffect* KeyframeEffect::Create(
-    Element* target,
-    KeyframeEffectModelBase* model,
-    const Timing& timing,
-    KeyframeEffectReadOnly::Priority priority,
-    EventDelegate* event_delegate) {
+KeyframeEffect* KeyframeEffect::Create(Element* target,
+                                       KeyframeEffectModelBase* model,
+                                       const Timing& timing,
+                                       Priority priority,
+                                       EventDelegate* event_delegate) {
   return new KeyframeEffect(target, model, timing, priority, event_delegate);
 }
 
@@ -101,7 +106,7 @@
 }
 
 KeyframeEffect* KeyframeEffect::Create(ScriptState* script_state,
-                                       KeyframeEffectReadOnly* source,
+                                       KeyframeEffect* source,
                                        ExceptionState& exception_state) {
   Timing new_timing = source->SpecifiedTiming();
   KeyframeEffectModelBase* model = source->Model()->Clone();
@@ -112,17 +117,52 @@
 KeyframeEffect::KeyframeEffect(Element* target,
                                KeyframeEffectModelBase* model,
                                const Timing& timing,
-                               KeyframeEffectReadOnly::Priority priority,
+                               Priority priority,
                                EventDelegate* event_delegate)
-    : KeyframeEffectReadOnly(target, model, timing, priority, event_delegate) {}
+    : AnimationEffect(timing, event_delegate),
+      target_(target),
+      model_(model),
+      sampled_effect_(nullptr),
+      priority_(priority) {
+  DCHECK(model_);
+}
 
 KeyframeEffect::~KeyframeEffect() = default;
 
+String KeyframeEffect::composite() const {
+  return EffectModel::CompositeOperationToString(CompositeInternal());
+}
+
 void KeyframeEffect::setComposite(String composite_string) {
   Model()->SetComposite(
       EffectModel::StringToCompositeOperation(composite_string));
 }
 
+Vector<ScriptValue> KeyframeEffect::getKeyframes(ScriptState* script_state) {
+  Vector<ScriptValue> computed_keyframes;
+  if (!model_->HasFrames())
+    return computed_keyframes;
+
+  // getKeyframes() returns a list of 'ComputedKeyframes'. A ComputedKeyframe
+  // consists of the normal keyframe data combined with the computed offset for
+  // the given keyframe.
+  //
+  // https://w3c.github.io/web-animations/#dom-keyframeeffectreadonly-getkeyframes
+  const KeyframeVector& keyframes = model_->GetFrames();
+  Vector<double> computed_offsets =
+      KeyframeEffectModelBase::GetComputedOffsets(keyframes);
+  computed_keyframes.ReserveInitialCapacity(keyframes.size());
+  ScriptState::Scope scope(script_state);
+  for (size_t i = 0; i < keyframes.size(); i++) {
+    V8ObjectBuilder object_builder(script_state);
+    keyframes[i]->AddKeyframePropertiesToV8Object(object_builder);
+    object_builder.Add("computedOffset", computed_offsets[i]);
+    computed_keyframes.push_back(object_builder.GetScriptValue());
+  }
+
+  return computed_keyframes;
+}
+
 void KeyframeEffect::setKeyframes(ScriptState* script_state,
                                   const ScriptValue& keyframes,
                                   ExceptionState& exception_state) {
@@ -147,8 +187,299 @@
   ToStringKeyframeEffectModel(Model())->SetFrames(new_keyframes);
 }
 
+bool KeyframeEffect::Affects(const PropertyHandle& property) const {
+  return model_->Affects(property);
+}
+
 AnimationEffectTiming* KeyframeEffect::timing() {
   return AnimationEffectTiming::Create(this);
 }
 
+void KeyframeEffect::NotifySampledEffectRemovedFromEffectStack() {
+  sampled_effect_ = nullptr;
+}
+
+CompositorAnimations::FailureCode
+KeyframeEffect::CheckCanStartAnimationOnCompositor(
+    double animation_playback_rate) const {
+  if (!model_->HasFrames()) {
+    return CompositorAnimations::FailureCode::Actionable(
+        "Animation effect has no keyframes");
+  }
+
+  if (!target_) {
+    return CompositorAnimations::FailureCode::Actionable(
+        "Animation effect has no target element");
+  }
+
+  if (target_->GetComputedStyle() && target_->GetComputedStyle()->HasOffset()) {
+    return CompositorAnimations::FailureCode::Actionable(
+        "Accelerated animations do not support elements with offset-position "
+        "or offset-path CSS properties");
+  }
+
+  // Do not put transforms on compositor if more than one of them are defined
+  // in computed style because they need to be explicitly ordered
+  if (HasMultipleTransformProperties()) {
+    return CompositorAnimations::FailureCode::Actionable(
+        "Animation effect applies to multiple transform-related properties");
+  }
+
+  return CompositorAnimations::CheckCanStartAnimationOnCompositor(
+      SpecifiedTiming(), *target_, GetAnimation(), *Model(),
+      animation_playback_rate);
+}
+
+void KeyframeEffect::StartAnimationOnCompositor(
+    int group,
+    double start_time,
+    double current_time,
+    double animation_playback_rate,
+    CompositorAnimation* compositor_animation) {
+  DCHECK(!HasActiveAnimationsOnCompositor());
+  DCHECK(CheckCanStartAnimationOnCompositor(animation_playback_rate).Ok());
+
+  if (!compositor_animation)
+    compositor_animation = GetAnimation()->GetCompositorAnimation();
+  DCHECK(compositor_animation);
+
+  CompositorAnimations::StartAnimationOnCompositor(
+      *target_, group, start_time, current_time, SpecifiedTiming(),
+      GetAnimation(), *compositor_animation, *Model(),
+      compositor_animation_ids_, animation_playback_rate);
+  DCHECK(!compositor_animation_ids_.IsEmpty());
+}
+
+bool KeyframeEffect::HasActiveAnimationsOnCompositor() const {
+  return !compositor_animation_ids_.IsEmpty();
+}
+
+bool KeyframeEffect::HasActiveAnimationsOnCompositor(
+    const PropertyHandle& property) const {
+  return HasActiveAnimationsOnCompositor() && Affects(property);
+}
+
+bool KeyframeEffect::CancelAnimationOnCompositor() {
+  // FIXME: cancelAnimationOnCompositor is called from withins style recalc.
+  // This queries compositingState, which is not necessarily up to date.
+  // https://code.google.com/p/chromium/issues/detail?id=339847
+  DisableCompositingQueryAsserts disabler;
+  if (!HasActiveAnimationsOnCompositor())
+    return false;
+  if (!target_ || !target_->GetLayoutObject())
+    return false;
+  DCHECK(GetAnimation());
+  for (const auto& compositor_animation_id : compositor_animation_ids_) {
+    CompositorAnimations::CancelAnimationOnCompositor(*target_, *GetAnimation(),
+                                                      compositor_animation_id);
+  }
+  compositor_animation_ids_.clear();
+  return true;
+}
+
+void KeyframeEffect::CancelIncompatibleAnimationsOnCompositor() {
+  if (target_ && GetAnimation() && model_->HasFrames()) {
+    CompositorAnimations::CancelIncompatibleAnimationsOnCompositor(
+        *target_, *GetAnimation(), *Model());
+  }
+}
+
+void KeyframeEffect::PauseAnimationForTestingOnCompositor(double pause_time) {
+  DCHECK(HasActiveAnimationsOnCompositor());
+  if (!target_ || !target_->GetLayoutObject())
+    return;
+  DCHECK(GetAnimation());
+  for (const auto& compositor_animation_id : compositor_animation_ids_) {
+    CompositorAnimations::PauseAnimationForTestingOnCompositor(
+        *target_, *GetAnimation(), compositor_animation_id, pause_time);
+  }
+}
+
+void KeyframeEffect::AttachCompositedLayers() {
+  DCHECK(target_);
+  DCHECK(GetAnimation());
+  CompositorAnimations::AttachCompositedLayers(
+      *target_, GetAnimation()->GetCompositorAnimation());
+}
+
+bool KeyframeEffect::HasAnimation() const {
+  return !!owner_;
+}
+
+bool KeyframeEffect::HasPlayingAnimation() const {
+  return owner_ && owner_->Playing();
+}
+
+void KeyframeEffect::Trace(blink::Visitor* visitor) {
+  visitor->Trace(target_);
+  visitor->Trace(model_);
+  visitor->Trace(sampled_effect_);
+  AnimationEffect::Trace(visitor);
+}
+
+EffectModel::CompositeOperation KeyframeEffect::CompositeInternal() const {
+  return model_->Composite();
+}
+
+void KeyframeEffect::ApplyEffects() {
+  DCHECK(IsInEffect());
+  DCHECK(GetAnimation());
+  if (!target_ || !model_->HasFrames())
+    return;
+
+  if (HasIncompatibleStyle())
+    GetAnimation()->CancelAnimationOnCompositor();
+
+  double iteration = CurrentIteration();
+  DCHECK_GE(iteration, 0);
+  bool changed = false;
+  if (sampled_effect_) {
+    changed = model_->Sample(clampTo<int>(iteration, 0), Progress().value(),
+                             IterationDuration(),
+                             sampled_effect_->MutableInterpolations());
+  } else {
+    Vector<scoped_refptr<Interpolation>> interpolations;
+    model_->Sample(clampTo<int>(iteration, 0), Progress().value(),
+                   IterationDuration(), interpolations);
+    if (!interpolations.IsEmpty()) {
+      SampledEffect* sampled_effect =
+          SampledEffect::Create(this, owner_->SequenceNumber());
+      sampled_effect->MutableInterpolations().swap(interpolations);
+      sampled_effect_ = sampled_effect;
+      target_->EnsureElementAnimations().GetEffectStack().Add(sampled_effect);
+      changed = true;
+    } else {
+      return;
+    }
+  }
+
+  if (changed) {
+    target_->SetNeedsAnimationStyleRecalc();
+    if (RuntimeEnabledFeatures::WebAnimationsSVGEnabled() &&
+        target_->IsSVGElement())
+      ToSVGElement(*target_).SetWebAnimationsPending();
+  }
+}
+
+void KeyframeEffect::ClearEffects() {
+  DCHECK(GetAnimation());
+  DCHECK(sampled_effect_);
+
+  sampled_effect_->Clear();
+  sampled_effect_ = nullptr;
+  GetAnimation()->RestartAnimationOnCompositor();
+  target_->SetNeedsAnimationStyleRecalc();
+  if (RuntimeEnabledFeatures::WebAnimationsSVGEnabled() &&
+      target_->IsSVGElement())
+    ToSVGElement(*target_).ClearWebAnimatedAttributes();
+  Invalidate();
+}
+
+void KeyframeEffect::UpdateChildrenAndEffects() const {
+  if (!model_->HasFrames())
+    return;
+  DCHECK(GetAnimation());
+  if (IsInEffect() && !owner_->EffectSuppressed())
+    const_cast<KeyframeEffect*>(this)->ApplyEffects();
+  else if (sampled_effect_)
+    const_cast<KeyframeEffect*>(this)->ClearEffects();
+}
+
+void KeyframeEffect::Attach(AnimationEffectOwner* owner) {
+  if (target_ && owner->GetAnimation()) {
+    target_->EnsureElementAnimations().Animations().insert(
+        owner->GetAnimation());
+    target_->SetNeedsAnimationStyleRecalc();
+    if (RuntimeEnabledFeatures::WebAnimationsSVGEnabled() &&
+        target_->IsSVGElement())
+      ToSVGElement(target_)->SetWebAnimationsPending();
+  }
+  AnimationEffect::Attach(owner);
+}
+
+void KeyframeEffect::Detach() {
+  if (target_ && GetAnimation())
+    target_->GetElementAnimations()->Animations().erase(GetAnimation());
+  if (sampled_effect_)
+    ClearEffects();
+  AnimationEffect::Detach();
+}
+
+double KeyframeEffect::CalculateTimeToEffectChange(
+    bool forwards,
+    double local_time,
+    double time_to_next_iteration) const {
+  const double start_time = SpecifiedTiming().start_delay;
+  const double end_time_minus_end_delay = start_time + ActiveDurationInternal();
+  const double end_time =
+      end_time_minus_end_delay + SpecifiedTiming().end_delay;
+  const double after_time = std::min(end_time_minus_end_delay, end_time);
+
+  switch (GetPhase()) {
+    case kPhaseNone:
+      return std::numeric_limits<double>::infinity();
+    case kPhaseBefore:
+      DCHECK_GE(start_time, local_time);
+      return forwards ? start_time - local_time
+                      : std::numeric_limits<double>::infinity();
+    case kPhaseActive:
+      if (forwards) {
+        // Need service to apply fill / fire events.
+        const double time_to_end = after_time - local_time;
+        if (RequiresIterationEvents()) {
+          return std::min(time_to_end, time_to_next_iteration);
+        }
+        return time_to_end;
+      }
+      return 0;
+    case kPhaseAfter:
+      DCHECK_GE(local_time, after_time);
+      // If this KeyframeEffect is still in effect then it will need to update
+      // when its parent goes out of effect. We have no way of knowing when
+      // that will be, however, so the parent will need to supply it.
+      return forwards ? std::numeric_limits<double>::infinity()
+                      : local_time - after_time;
+    default:
+      NOTREACHED();
+      return std::numeric_limits<double>::infinity();
+  }
+}
+
+// Returns true if transform, translate, rotate or scale is composited
+// and a motion path or other transform properties
+// has been introduced on the element
+bool KeyframeEffect::HasIncompatibleStyle() const {
+  if (!target_->GetComputedStyle())
+    return false;
+
+  bool affects_transform = Affects(PropertyHandle(GetCSSPropertyTransform())) ||
+                           Affects(PropertyHandle(GetCSSPropertyScale())) ||
+                           Affects(PropertyHandle(GetCSSPropertyRotate())) ||
+                           Affects(PropertyHandle(GetCSSPropertyTranslate()));
+
+  if (HasActiveAnimationsOnCompositor()) {
+    if (target_->GetComputedStyle()->HasOffset() && affects_transform)
+      return true;
+    return HasMultipleTransformProperties();
+  }
+
+  return false;
+}
+
+bool KeyframeEffect::HasMultipleTransformProperties() const {
+  if (!target_->GetComputedStyle())
+    return false;
+
+  unsigned transform_property_count = 0;
+  if (target_->GetComputedStyle()->HasTransformOperations())
+    transform_property_count++;
+  if (target_->GetComputedStyle()->Rotate())
+    transform_property_count++;
+  if (target_->GetComputedStyle()->Scale())
+    transform_property_count++;
+  if (target_->GetComputedStyle()->Translate())
+    transform_property_count++;
+  return transform_property_count > 1;
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/animation/KeyframeEffect.h b/third_party/WebKit/Source/core/animation/KeyframeEffect.h
index 175b034..2bfc88b 100644
--- a/third_party/WebKit/Source/core/animation/KeyframeEffect.h
+++ b/third_party/WebKit/Source/core/animation/KeyframeEffect.h
@@ -31,28 +31,32 @@
 #ifndef KeyframeEffect_h
 #define KeyframeEffect_h
 
+#include "bindings/core/v8/ScriptValue.h"
 #include "core/CoreExport.h"
+#include "core/animation/AnimationEffect.h"
 #include "core/animation/AnimationEffectTiming.h"
-#include "core/animation/KeyframeEffectModel.h"
-#include "core/animation/KeyframeEffectReadOnly.h"
+#include "core/animation/CompositorAnimations.h"
 
 namespace blink {
 
 class Element;
 class ExceptionState;
+class KeyframeEffectModelBase;
+class SampledEffect;
 class UnrestrictedDoubleOrKeyframeEffectOptions;
 
 // Represents the effect of an Animation on an Element's properties.
 // https://drafts.csswg.org/web-animations/#keyframe-effect
-class CORE_EXPORT KeyframeEffect final : public KeyframeEffectReadOnly {
+class CORE_EXPORT KeyframeEffect final : public AnimationEffect {
   DEFINE_WRAPPERTYPEINFO();
 
  public:
+  enum Priority { kDefaultPriority, kTransitionPriority };
+
   static KeyframeEffect* Create(Element*,
                                 KeyframeEffectModelBase*,
                                 const Timing&,
-                                KeyframeEffectReadOnly::Priority =
-                                    KeyframeEffectReadOnly::kDefaultPriority,
+                                Priority = kDefaultPriority,
                                 EventDelegate* = nullptr);
   // Web Animations API Bindings constructors.
   static KeyframeEffect* Create(
@@ -65,32 +69,94 @@
                                 Element*,
                                 const ScriptValue&,
                                 ExceptionState&);
-  static KeyframeEffect* Create(ScriptState*,
-                                KeyframeEffectReadOnly*,
-                                ExceptionState&);
+  static KeyframeEffect* Create(ScriptState*, KeyframeEffect*, ExceptionState&);
 
   ~KeyframeEffect() override;
 
+  bool IsKeyframeEffect() const override { return true; }
+
   // IDL implementation.
+  Element* target() const { return target_; }
+  String composite() const;
   void setComposite(String);
+  Vector<ScriptValue> getKeyframes(ScriptState*);
   void setKeyframes(ScriptState*,
                     const ScriptValue& keyframes,
                     ExceptionState&);
 
-  bool IsKeyframeEffect() const override { return true; }
+  bool Affects(const PropertyHandle&) const;
+  const KeyframeEffectModelBase* Model() const { return model_.Get(); }
+  KeyframeEffectModelBase* Model() { return model_.Get(); }
+  void SetModel(KeyframeEffectModelBase* model) {
+    DCHECK(model);
+    model_ = model;
+  }
+  Priority GetPriority() const { return priority_; }
 
   AnimationEffectTiming* timing() override;
 
+  void NotifySampledEffectRemovedFromEffectStack();
+
+  CompositorAnimations::FailureCode CheckCanStartAnimationOnCompositor(
+      double animation_playback_rate) const;
+  // Must only be called once.
+  void StartAnimationOnCompositor(int group,
+                                  double start_time,
+                                  double time_offset,
+                                  double animation_playback_rate,
+                                  CompositorAnimation* = nullptr);
+  bool HasActiveAnimationsOnCompositor() const;
+  bool HasActiveAnimationsOnCompositor(const PropertyHandle&) const;
+  bool CancelAnimationOnCompositor();
+  void CancelIncompatibleAnimationsOnCompositor();
+  void PauseAnimationForTestingOnCompositor(double pause_time);
+
+  void AttachCompositedLayers();
+
+  void SetCompositorAnimationIdsForTesting(
+      const Vector<int>& compositor_animation_ids) {
+    compositor_animation_ids_ = compositor_animation_ids;
+  }
+
+  void DowngradeToNormal() { priority_ = kDefaultPriority; }
+
+  bool HasAnimation() const;
+  bool HasPlayingAnimation() const;
+
+  void Trace(blink::Visitor*) override;
+
  private:
   KeyframeEffect(Element*,
                  KeyframeEffectModelBase*,
                  const Timing&,
-                 KeyframeEffectReadOnly::Priority,
+                 Priority,
                  EventDelegate*);
+
+  EffectModel::CompositeOperation CompositeInternal() const;
+
+  void ApplyEffects();
+  void ClearEffects();
+  void UpdateChildrenAndEffects() const override;
+  void Attach(AnimationEffectOwner*) override;
+  void Detach() override;
+  double CalculateTimeToEffectChange(
+      bool forwards,
+      double inherited_time,
+      double time_to_next_iteration) const override;
+  bool HasIncompatibleStyle() const;
+  bool HasMultipleTransformProperties() const;
+
+  Member<Element> target_;
+  Member<KeyframeEffectModelBase> model_;
+  Member<SampledEffect> sampled_effect_;
+
+  Priority priority_;
+
+  Vector<int> compositor_animation_ids_;
 };
 
 DEFINE_TYPE_CASTS(KeyframeEffect,
-                  AnimationEffectReadOnly,
+                  AnimationEffect,
                   animationNode,
                   animationNode->IsKeyframeEffect(),
                   animationNode.IsKeyframeEffect());
diff --git a/third_party/WebKit/Source/core/animation/KeyframeEffect.idl b/third_party/WebKit/Source/core/animation/KeyframeEffect.idl
index 4d8aab90..2bf5748 100644
--- a/third_party/WebKit/Source/core/animation/KeyframeEffect.idl
+++ b/third_party/WebKit/Source/core/animation/KeyframeEffect.idl
@@ -30,13 +30,17 @@
 
 // https://drafts.csswg.org/web-animations/#the-keyframeeffect-interfaces
 
+enum CompositeOperation { "replace", "add", "accumulate" };
+
 [
     Constructor(Element? target, object? keyframes, optional (unrestricted double or KeyframeEffectOptions) options),
-    Constructor(KeyframeEffectReadOnly source),
+    Constructor(KeyframeEffect source),
     ConstructorCallWith=ScriptState,
     RaisesException=Constructor,
     RuntimeEnabled=WebAnimationsAPI
-] interface KeyframeEffect : KeyframeEffectReadOnly {
-  inherit attribute CompositeOperation composite;
+] interface KeyframeEffect : AnimationEffect {
+  readonly attribute Element? target;
+  attribute CompositeOperation composite;
+  [CallWith=ScriptState] sequence<object> getKeyframes();
   [CallWith=ScriptState, RaisesException] void setKeyframes(object? keyframes);
 };
diff --git a/third_party/WebKit/Source/core/animation/KeyframeEffectModel.cpp b/third_party/WebKit/Source/core/animation/KeyframeEffectModel.cpp
index 43f63fdf..a6fc4e1 100644
--- a/third_party/WebKit/Source/core/animation/KeyframeEffectModel.cpp
+++ b/third_party/WebKit/Source/core/animation/KeyframeEffectModel.cpp
@@ -33,7 +33,7 @@
 #include <limits>
 #include <utility>
 
-#include "core/animation/AnimationEffectReadOnly.h"
+#include "core/animation/AnimationEffect.h"
 #include "core/animation/CompositorAnimations.h"
 #include "core/animation/css/CSSAnimatableValueFactory.h"
 #include "core/css/CSSPropertyEquality.h"
diff --git a/third_party/WebKit/Source/core/animation/KeyframeEffectModel.h b/third_party/WebKit/Source/core/animation/KeyframeEffectModel.h
index c18fa95a..e936ef8 100644
--- a/third_party/WebKit/Source/core/animation/KeyframeEffectModel.h
+++ b/third_party/WebKit/Source/core/animation/KeyframeEffectModel.h
@@ -34,7 +34,7 @@
 #include <memory>
 #include "base/memory/scoped_refptr.h"
 #include "core/CoreExport.h"
-#include "core/animation/AnimationEffectReadOnly.h"
+#include "core/animation/AnimationEffect.h"
 #include "core/animation/EffectModel.h"
 #include "core/animation/InterpolationEffect.h"
 #include "core/animation/PropertyHandle.h"
diff --git a/third_party/WebKit/Source/core/animation/KeyframeEffectReadOnly.cpp b/third_party/WebKit/Source/core/animation/KeyframeEffectReadOnly.cpp
deleted file mode 100644
index c731c83db..0000000
--- a/third_party/WebKit/Source/core/animation/KeyframeEffectReadOnly.cpp
+++ /dev/null
@@ -1,436 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "core/animation/KeyframeEffectReadOnly.h"
-
-#include "bindings/core/v8/ExceptionState.h"
-#include "bindings/core/v8/ScriptValue.h"
-#include "bindings/core/v8/V8ObjectBuilder.h"
-#include "bindings/core/v8/unrestricted_double_or_keyframe_effect_options.h"
-#include "core/animation/Animation.h"
-#include "core/animation/EffectInput.h"
-#include "core/animation/ElementAnimations.h"
-#include "core/animation/Interpolation.h"
-#include "core/animation/KeyframeEffect.h"
-#include "core/animation/KeyframeEffectOptions.h"
-#include "core/animation/PropertyHandle.h"
-#include "core/animation/SampledEffect.h"
-#include "core/animation/TimingInput.h"
-#include "core/dom/Element.h"
-#include "core/dom/NodeComputedStyle.h"
-#include "core/frame/UseCounter.h"
-#include "core/paint/PaintLayer.h"
-#include "core/svg/SVGElement.h"
-#include "platform/bindings/ScriptState.h"
-#include "platform/runtime_enabled_features.h"
-
-namespace blink {
-
-KeyframeEffectReadOnly* KeyframeEffectReadOnly::Create(
-    Element* target,
-    KeyframeEffectModelBase* model,
-    const Timing& timing,
-    Priority priority,
-    EventDelegate* event_delegate) {
-  return new KeyframeEffectReadOnly(target, model, timing, priority,
-                                    event_delegate);
-}
-
-KeyframeEffectReadOnly* KeyframeEffectReadOnly::Create(
-    ScriptState* script_state,
-    Element* element,
-    const ScriptValue& keyframes,
-    const UnrestrictedDoubleOrKeyframeEffectOptions& options,
-    ExceptionState& exception_state) {
-  DCHECK(RuntimeEnabledFeatures::WebAnimationsAPIEnabled());
-  if (element) {
-    UseCounter::Count(
-        element->GetDocument(),
-        WebFeature::kAnimationConstructorKeyframeListEffectObjectTiming);
-  }
-  Timing timing;
-  Document* document = element ? &element->GetDocument() : nullptr;
-  if (!TimingInput::Convert(options, timing, document, exception_state))
-    return nullptr;
-
-  EffectModel::CompositeOperation composite = EffectModel::kCompositeReplace;
-  if (options.IsKeyframeEffectOptions()) {
-    composite = EffectModel::StringToCompositeOperation(
-        options.GetAsKeyframeEffectOptions().composite());
-  }
-
-  KeyframeEffectModelBase* model = EffectInput::Convert(
-      element, keyframes, composite, script_state, exception_state);
-  if (exception_state.HadException())
-    return nullptr;
-
-  return Create(element, model, timing);
-}
-
-KeyframeEffectReadOnly* KeyframeEffectReadOnly::Create(
-    ScriptState* script_state,
-    Element* element,
-    const ScriptValue& keyframes,
-    ExceptionState& exception_state) {
-  DCHECK(RuntimeEnabledFeatures::WebAnimationsAPIEnabled());
-  if (element) {
-    UseCounter::Count(
-        element->GetDocument(),
-        WebFeature::kAnimationConstructorKeyframeListEffectNoTiming);
-  }
-  KeyframeEffectModelBase* model =
-      EffectInput::Convert(element, keyframes, EffectModel::kCompositeReplace,
-                           script_state, exception_state);
-  if (exception_state.HadException())
-    return nullptr;
-  return Create(element, model, Timing());
-}
-
-KeyframeEffectReadOnly* KeyframeEffectReadOnly::Create(
-    ScriptState* script_state,
-    KeyframeEffectReadOnly* source,
-    ExceptionState& exception_state) {
-  Timing new_timing = source->SpecifiedTiming();
-  KeyframeEffectModelBase* model = source->Model()->Clone();
-  return new KeyframeEffectReadOnly(source->target(), model, new_timing,
-                                    source->GetPriority(),
-                                    source->GetEventDelegate());
-}
-
-KeyframeEffectReadOnly::KeyframeEffectReadOnly(Element* target,
-                                               KeyframeEffectModelBase* model,
-                                               const Timing& timing,
-                                               Priority priority,
-                                               EventDelegate* event_delegate)
-    : AnimationEffectReadOnly(timing, event_delegate),
-      target_(target),
-      model_(model),
-      sampled_effect_(nullptr),
-      priority_(priority) {
-  DCHECK(model_);
-}
-
-void KeyframeEffectReadOnly::Attach(AnimationEffectOwner* owner) {
-  if (target_ && owner->GetAnimation()) {
-    target_->EnsureElementAnimations().Animations().insert(
-        owner->GetAnimation());
-    target_->SetNeedsAnimationStyleRecalc();
-    if (RuntimeEnabledFeatures::WebAnimationsSVGEnabled() &&
-        target_->IsSVGElement())
-      ToSVGElement(target_)->SetWebAnimationsPending();
-  }
-  AnimationEffectReadOnly::Attach(owner);
-}
-
-void KeyframeEffectReadOnly::Detach() {
-  if (target_ && GetAnimation())
-    target_->GetElementAnimations()->Animations().erase(GetAnimation());
-  if (sampled_effect_)
-    ClearEffects();
-  AnimationEffectReadOnly::Detach();
-}
-
-static EffectStack& EnsureEffectStack(Element* element) {
-  return element->EnsureElementAnimations().GetEffectStack();
-}
-
-bool KeyframeEffectReadOnly::HasMultipleTransformProperties() const {
-  if (!target_->GetComputedStyle())
-    return false;
-
-  unsigned transform_property_count = 0;
-  if (target_->GetComputedStyle()->HasTransformOperations())
-    transform_property_count++;
-  if (target_->GetComputedStyle()->Rotate())
-    transform_property_count++;
-  if (target_->GetComputedStyle()->Scale())
-    transform_property_count++;
-  if (target_->GetComputedStyle()->Translate())
-    transform_property_count++;
-  return transform_property_count > 1;
-}
-
-// Returns true if transform, translate, rotate or scale is composited
-// and a motion path or other transform properties
-// has been introduced on the element
-bool KeyframeEffectReadOnly::HasIncompatibleStyle() {
-  if (!target_->GetComputedStyle())
-    return false;
-
-  bool affects_transform = Affects(PropertyHandle(GetCSSPropertyTransform())) ||
-                           Affects(PropertyHandle(GetCSSPropertyScale())) ||
-                           Affects(PropertyHandle(GetCSSPropertyRotate())) ||
-                           Affects(PropertyHandle(GetCSSPropertyTranslate()));
-
-  if (HasActiveAnimationsOnCompositor()) {
-    if (target_->GetComputedStyle()->HasOffset() && affects_transform)
-      return true;
-    return HasMultipleTransformProperties();
-  }
-
-  return false;
-}
-
-void KeyframeEffectReadOnly::ApplyEffects() {
-  DCHECK(IsInEffect());
-  DCHECK(GetAnimation());
-  if (!target_ || !model_->HasFrames())
-    return;
-
-  if (HasIncompatibleStyle())
-    GetAnimation()->CancelAnimationOnCompositor();
-
-  double iteration = CurrentIteration();
-  DCHECK_GE(iteration, 0);
-  bool changed = false;
-  if (sampled_effect_) {
-    changed = model_->Sample(clampTo<int>(iteration, 0), Progress().value(),
-                             IterationDuration(),
-                             sampled_effect_->MutableInterpolations());
-  } else {
-    Vector<scoped_refptr<Interpolation>> interpolations;
-    model_->Sample(clampTo<int>(iteration, 0), Progress().value(),
-                   IterationDuration(), interpolations);
-    if (!interpolations.IsEmpty()) {
-      SampledEffect* sampled_effect =
-          SampledEffect::Create(this, owner_->SequenceNumber());
-      sampled_effect->MutableInterpolations().swap(interpolations);
-      sampled_effect_ = sampled_effect;
-      EnsureEffectStack(target_).Add(sampled_effect);
-      changed = true;
-    } else {
-      return;
-    }
-  }
-
-  if (changed) {
-    target_->SetNeedsAnimationStyleRecalc();
-    if (RuntimeEnabledFeatures::WebAnimationsSVGEnabled() &&
-        target_->IsSVGElement())
-      ToSVGElement(*target_).SetWebAnimationsPending();
-  }
-}
-
-void KeyframeEffectReadOnly::ClearEffects() {
-  DCHECK(GetAnimation());
-  DCHECK(sampled_effect_);
-
-  sampled_effect_->Clear();
-  sampled_effect_ = nullptr;
-  GetAnimation()->RestartAnimationOnCompositor();
-  target_->SetNeedsAnimationStyleRecalc();
-  if (RuntimeEnabledFeatures::WebAnimationsSVGEnabled() &&
-      target_->IsSVGElement())
-    ToSVGElement(*target_).ClearWebAnimatedAttributes();
-  Invalidate();
-}
-
-void KeyframeEffectReadOnly::UpdateChildrenAndEffects() const {
-  if (!model_->HasFrames())
-    return;
-  DCHECK(GetAnimation());
-  if (IsInEffect() && !owner_->EffectSuppressed())
-    const_cast<KeyframeEffectReadOnly*>(this)->ApplyEffects();
-  else if (sampled_effect_)
-    const_cast<KeyframeEffectReadOnly*>(this)->ClearEffects();
-}
-
-double KeyframeEffectReadOnly::CalculateTimeToEffectChange(
-    bool forwards,
-    double local_time,
-    double time_to_next_iteration) const {
-  const double start_time = SpecifiedTiming().start_delay;
-  const double end_time_minus_end_delay = start_time + ActiveDurationInternal();
-  const double end_time =
-      end_time_minus_end_delay + SpecifiedTiming().end_delay;
-  const double after_time = std::min(end_time_minus_end_delay, end_time);
-
-  switch (GetPhase()) {
-    case kPhaseNone:
-      return std::numeric_limits<double>::infinity();
-    case kPhaseBefore:
-      DCHECK_GE(start_time, local_time);
-      return forwards ? start_time - local_time
-                      : std::numeric_limits<double>::infinity();
-    case kPhaseActive:
-      if (forwards) {
-        // Need service to apply fill / fire events.
-        const double time_to_end = after_time - local_time;
-        if (RequiresIterationEvents()) {
-          return std::min(time_to_end, time_to_next_iteration);
-        }
-        return time_to_end;
-      }
-      return 0;
-    case kPhaseAfter:
-      DCHECK_GE(local_time, after_time);
-      // If this KeyframeEffect is still in effect then it will need to update
-      // when its parent goes out of effect. We have no way of knowing when
-      // that will be, however, so the parent will need to supply it.
-      return forwards ? std::numeric_limits<double>::infinity()
-                      : local_time - after_time;
-    default:
-      NOTREACHED();
-      return std::numeric_limits<double>::infinity();
-  }
-}
-
-void KeyframeEffectReadOnly::NotifySampledEffectRemovedFromEffectStack() {
-  sampled_effect_ = nullptr;
-}
-
-CompositorAnimations::FailureCode
-KeyframeEffectReadOnly::CheckCanStartAnimationOnCompositor(
-    double animation_playback_rate) const {
-  if (!model_->HasFrames()) {
-    return CompositorAnimations::FailureCode::Actionable(
-        "Animation effect has no keyframes");
-  }
-
-  if (!target_) {
-    return CompositorAnimations::FailureCode::Actionable(
-        "Animation effect has no target element");
-  }
-
-  if (target_->GetComputedStyle() && target_->GetComputedStyle()->HasOffset()) {
-    return CompositorAnimations::FailureCode::Actionable(
-        "Accelerated animations do not support elements with offset-position "
-        "or offset-path CSS properties");
-  }
-
-  // Do not put transforms on compositor if more than one of them are defined
-  // in computed style because they need to be explicitly ordered
-  if (HasMultipleTransformProperties()) {
-    return CompositorAnimations::FailureCode::Actionable(
-        "Animation effect applies to multiple transform-related properties");
-  }
-
-  return CompositorAnimations::CheckCanStartAnimationOnCompositor(
-      SpecifiedTiming(), *target_, GetAnimation(), *Model(),
-      animation_playback_rate);
-}
-
-void KeyframeEffectReadOnly::StartAnimationOnCompositor(
-    int group,
-    double start_time,
-    double current_time,
-    double animation_playback_rate,
-    CompositorAnimation* compositor_animation) {
-  DCHECK(!HasActiveAnimationsOnCompositor());
-  DCHECK(CheckCanStartAnimationOnCompositor(animation_playback_rate).Ok());
-
-  if (!compositor_animation)
-    compositor_animation = GetAnimation()->GetCompositorAnimation();
-  DCHECK(compositor_animation);
-
-  CompositorAnimations::StartAnimationOnCompositor(
-      *target_, group, start_time, current_time, SpecifiedTiming(),
-      GetAnimation(), *compositor_animation, *Model(),
-      compositor_animation_ids_, animation_playback_rate);
-  DCHECK(!compositor_animation_ids_.IsEmpty());
-}
-
-String KeyframeEffectReadOnly::composite() const {
-  return EffectModel::CompositeOperationToString(compositeInternal());
-}
-
-Vector<ScriptValue> KeyframeEffectReadOnly::getKeyframes(
-    ScriptState* script_state) {
-  Vector<ScriptValue> computed_keyframes;
-  if (!model_->HasFrames())
-    return computed_keyframes;
-
-  // getKeyframes() returns a list of 'ComputedKeyframes'. A ComputedKeyframe
-  // consists of the normal keyframe data combined with the computed offset for
-  // the given keyframe.
-  //
-  // https://drafts.csswg.org/web-animations/#dom-keyframeeffectreadonly-getkeyframes
-  const KeyframeVector& keyframes = model_->GetFrames();
-  Vector<double> computed_offsets =
-      KeyframeEffectModelBase::GetComputedOffsets(keyframes);
-  computed_keyframes.ReserveInitialCapacity(keyframes.size());
-  ScriptState::Scope scope(script_state);
-  for (size_t i = 0; i < keyframes.size(); i++) {
-    V8ObjectBuilder object_builder(script_state);
-    keyframes[i]->AddKeyframePropertiesToV8Object(object_builder);
-    object_builder.Add("computedOffset", computed_offsets[i]);
-    computed_keyframes.push_back(object_builder.GetScriptValue());
-  }
-
-  return computed_keyframes;
-}
-
-bool KeyframeEffectReadOnly::HasActiveAnimationsOnCompositor() const {
-  return !compositor_animation_ids_.IsEmpty();
-}
-
-bool KeyframeEffectReadOnly::HasActiveAnimationsOnCompositor(
-    const PropertyHandle& property) const {
-  return HasActiveAnimationsOnCompositor() && Affects(property);
-}
-
-bool KeyframeEffectReadOnly::Affects(const PropertyHandle& property) const {
-  return model_->Affects(property);
-}
-
-bool KeyframeEffectReadOnly::CancelAnimationOnCompositor() {
-  // FIXME: cancelAnimationOnCompositor is called from withins style recalc.
-  // This queries compositingState, which is not necessarily up to date.
-  // https://code.google.com/p/chromium/issues/detail?id=339847
-  DisableCompositingQueryAsserts disabler;
-  if (!HasActiveAnimationsOnCompositor())
-    return false;
-  if (!target_ || !target_->GetLayoutObject())
-    return false;
-  DCHECK(GetAnimation());
-  for (const auto& compositor_animation_id : compositor_animation_ids_) {
-    CompositorAnimations::CancelAnimationOnCompositor(*target_, *GetAnimation(),
-                                                      compositor_animation_id);
-  }
-  compositor_animation_ids_.clear();
-  return true;
-}
-
-void KeyframeEffectReadOnly::CancelIncompatibleAnimationsOnCompositor() {
-  if (target_ && GetAnimation() && model_->HasFrames()) {
-    CompositorAnimations::CancelIncompatibleAnimationsOnCompositor(
-        *target_, *GetAnimation(), *Model());
-  }
-}
-
-void KeyframeEffectReadOnly::PauseAnimationForTestingOnCompositor(
-    double pause_time) {
-  DCHECK(HasActiveAnimationsOnCompositor());
-  if (!target_ || !target_->GetLayoutObject())
-    return;
-  DCHECK(GetAnimation());
-  for (const auto& compositor_animation_id : compositor_animation_ids_) {
-    CompositorAnimations::PauseAnimationForTestingOnCompositor(
-        *target_, *GetAnimation(), compositor_animation_id, pause_time);
-  }
-}
-
-void KeyframeEffectReadOnly::AttachCompositedLayers() {
-  DCHECK(target_);
-  DCHECK(GetAnimation());
-  CompositorAnimations::AttachCompositedLayers(
-      *target_, GetAnimation()->GetCompositorAnimation());
-}
-
-bool KeyframeEffectReadOnly::HasAnimation() const {
-  return !!owner_;
-}
-
-bool KeyframeEffectReadOnly::HasPlayingAnimation() const {
-  return owner_ && owner_->Playing();
-}
-
-void KeyframeEffectReadOnly::Trace(blink::Visitor* visitor) {
-  visitor->Trace(target_);
-  visitor->Trace(model_);
-  visitor->Trace(sampled_effect_);
-  AnimationEffectReadOnly::Trace(visitor);
-}
-
-}  // namespace blink
diff --git a/third_party/WebKit/Source/core/animation/KeyframeEffectReadOnly.h b/third_party/WebKit/Source/core/animation/KeyframeEffectReadOnly.h
deleted file mode 100644
index b7de7289..0000000
--- a/third_party/WebKit/Source/core/animation/KeyframeEffectReadOnly.h
+++ /dev/null
@@ -1,140 +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.
-
-#ifndef KeyframeEffectReadOnly_h
-#define KeyframeEffectReadOnly_h
-
-#include "bindings/core/v8/ScriptValue.h"
-#include "core/CoreExport.h"
-#include "core/animation/AnimationEffectReadOnly.h"
-#include "core/animation/CompositorAnimations.h"
-#include "core/animation/KeyframeEffectModel.h"
-
-namespace blink {
-
-class Element;
-class ExceptionState;
-class PropertyHandle;
-class SampledEffect;
-class ScriptState;
-class UnrestrictedDoubleOrKeyframeEffectOptions;
-
-// Represents the effect of an Animation on an Element's properties.
-// https://drafts.csswg.org/web-animations/#the-keyframeeffect-interfaces
-class CORE_EXPORT KeyframeEffectReadOnly : public AnimationEffectReadOnly {
-  DEFINE_WRAPPERTYPEINFO();
-
- public:
-  enum Priority { kDefaultPriority, kTransitionPriority };
-
-  static KeyframeEffectReadOnly* Create(Element*,
-                                        KeyframeEffectModelBase*,
-                                        const Timing&,
-                                        Priority = kDefaultPriority,
-                                        EventDelegate* = nullptr);
-  // Web Animations API Bindings constructors.
-  static KeyframeEffectReadOnly* Create(
-      ScriptState*,
-      Element*,
-      const ScriptValue&,
-      const UnrestrictedDoubleOrKeyframeEffectOptions&,
-      ExceptionState&);
-  static KeyframeEffectReadOnly* Create(ScriptState*,
-                                        Element*,
-                                        const ScriptValue&,
-                                        ExceptionState&);
-  static KeyframeEffectReadOnly* Create(ScriptState*,
-                                        KeyframeEffectReadOnly*,
-                                        ExceptionState&);
-
-  ~KeyframeEffectReadOnly() override = default;
-
-  bool IsKeyframeEffectReadOnly() const override { return true; }
-
-  // IDL implementation.
-  String composite() const;
-  Vector<ScriptValue> getKeyframes(ScriptState*);
-  Element* target() const { return target_; }
-
-  EffectModel::CompositeOperation compositeInternal() const {
-    return model_->Composite();
-  }
-
-  bool Affects(const PropertyHandle&) const;
-  const KeyframeEffectModelBase* Model() const { return model_.Get(); }
-  KeyframeEffectModelBase* Model() { return model_.Get(); }
-  void SetModel(KeyframeEffectModelBase* model) {
-    DCHECK(model);
-    model_ = model;
-  }
-  Priority GetPriority() const { return priority_; }
-
-  void NotifySampledEffectRemovedFromEffectStack();
-
-  CompositorAnimations::FailureCode CheckCanStartAnimationOnCompositor(
-      double animation_playback_rate) const;
-  // Must only be called once.
-  void StartAnimationOnCompositor(int group,
-                                  double start_time,
-                                  double time_offset,
-                                  double animation_playback_rate,
-                                  CompositorAnimation* = nullptr);
-  bool HasActiveAnimationsOnCompositor() const;
-  bool HasActiveAnimationsOnCompositor(const PropertyHandle&) const;
-  bool CancelAnimationOnCompositor();
-  void CancelIncompatibleAnimationsOnCompositor();
-  void PauseAnimationForTestingOnCompositor(double pause_time);
-
-  void AttachCompositedLayers();
-
-  void SetCompositorAnimationIdsForTesting(
-      const Vector<int>& compositor_animation_ids) {
-    compositor_animation_ids_ = compositor_animation_ids;
-  }
-
-  void Trace(blink::Visitor*) override;
-
-  void DowngradeToNormal() { priority_ = kDefaultPriority; }
-
-  bool HasAnimation() const;
-  bool HasPlayingAnimation() const;
-
- protected:
-  KeyframeEffectReadOnly(Element*,
-                         KeyframeEffectModelBase*,
-                         const Timing&,
-                         Priority,
-                         EventDelegate*);
-
-  void ApplyEffects();
-  void ClearEffects();
-  void UpdateChildrenAndEffects() const override;
-  void Attach(AnimationEffectOwner*) override;
-  void Detach() override;
-  double CalculateTimeToEffectChange(
-      bool forwards,
-      double inherited_time,
-      double time_to_next_iteration) const override;
-  virtual bool HasIncompatibleStyle();
-  bool HasMultipleTransformProperties() const;
-
- private:
-  Member<Element> target_;
-  Member<KeyframeEffectModelBase> model_;
-  Member<SampledEffect> sampled_effect_;
-
-  Priority priority_;
-
-  Vector<int> compositor_animation_ids_;
-};
-
-DEFINE_TYPE_CASTS(KeyframeEffectReadOnly,
-                  AnimationEffectReadOnly,
-                  animationNode,
-                  animationNode->IsKeyframeEffectReadOnly(),
-                  animationNode.IsKeyframeEffectReadOnly());
-
-}  // namespace blink
-
-#endif  // KeyframeEffectReadOnly_h
diff --git a/third_party/WebKit/Source/core/animation/KeyframeEffectReadOnly.idl b/third_party/WebKit/Source/core/animation/KeyframeEffectReadOnly.idl
deleted file mode 100644
index 1f3d7c3..0000000
--- a/third_party/WebKit/Source/core/animation/KeyframeEffectReadOnly.idl
+++ /dev/null
@@ -1,19 +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.
-
-// https://drafts.csswg.org/web-animations/#the-keyframeeffect-interfaces
-
-enum CompositeOperation { "replace", "add", "accumulate" };
-
-[
-    Constructor(Element? target, object? keyframes, optional (unrestricted double or KeyframeEffectOptions) options),
-    Constructor(KeyframeEffectReadOnly source),
-    ConstructorCallWith=ScriptState,
-    RaisesException=Constructor,
-    RuntimeEnabled=WebAnimationsAPI
-] interface KeyframeEffectReadOnly : AnimationEffectReadOnly {
-  readonly attribute CompositeOperation composite;
-  [CallWith=ScriptState] sequence<object> getKeyframes();
-  readonly attribute Element? target;
-};
diff --git a/third_party/WebKit/Source/core/animation/README.md b/third_party/WebKit/Source/core/animation/README.md
index 51b36cd..6a64431 100644
--- a/third_party/WebKit/Source/core/animation/README.md
+++ b/third_party/WebKit/Source/core/animation/README.md
@@ -194,7 +194,7 @@
             `transfrom: rotate(40deg)`.
 
 [Animation]: https://cs.chromium.org/search/?q=class:blink::Animation$
-[AnimationEffect]: https://cs.chromium.org/search/?q=class:blink::AnimationEffectReadOnly$
+[AnimationEffect]: https://cs.chromium.org/search/?q=class:blink::AnimationEffect$
 [DocumentTimeline]: https://cs.chromium.org/search/?q=class:blink::DocumentTimeline$
 [EffectStack]: https://cs.chromium.org/search/?q=class:blink::EffectStack
 
@@ -286,10 +286,10 @@
 [Element]: https://cs.chromium.org/search/?q=class:blink::Element$
 [KeyframeGroupMap]: https://cs.chromium.org/search/?q=class:blink::KeyframeEffectModelBase+KeyframeGroupMap
 [PropertySpecificKeyframe]: https://cs.chromium.org/search/?q=class:blink::Keyframe::PropertySpecificKeyframe
-[KeyframeEffect]: https://cs.chromium.org/search/?q=class:blink::KeyframeEffectReadOnly$
+[KeyframeEffect]: https://cs.chromium.org/search/?q=class:blink::KeyframeEffect$
 [KeyframeEffectModel]: https://cs.chromium.org/search/?q=class:blink::KeyframeEffectModelBase$
 [Timing]: https://cs.chromium.org/search/?q=class:blink::Timing$
-[UpdateInheritedTime()]: https://cs.chromium.org/search/?q=function:%5CbAnimationEffectReadOnly::UpdateInheritedTime
+[UpdateInheritedTime()]: https://cs.chromium.org/search/?q=function:%5CbAnimationEffect::UpdateInheritedTime
 
 #### Lifecycle of an [Interpolation][]
 
diff --git a/third_party/WebKit/Source/core/animation/SampledEffect.cpp b/third_party/WebKit/Source/core/animation/SampledEffect.cpp
index 4073093..5fd89930 100644
--- a/third_party/WebKit/Source/core/animation/SampledEffect.cpp
+++ b/third_party/WebKit/Source/core/animation/SampledEffect.cpp
@@ -6,8 +6,7 @@
 
 namespace blink {
 
-SampledEffect::SampledEffect(KeyframeEffectReadOnly* effect,
-                             unsigned sequence_number)
+SampledEffect::SampledEffect(KeyframeEffect* effect, unsigned sequence_number)
     : effect_(effect),
       sequence_number_(sequence_number),
       priority_(effect->GetPriority()) {}
diff --git a/third_party/WebKit/Source/core/animation/SampledEffect.h b/third_party/WebKit/Source/core/animation/SampledEffect.h
index 34855e0d..5544b41 100644
--- a/third_party/WebKit/Source/core/animation/SampledEffect.h
+++ b/third_party/WebKit/Source/core/animation/SampledEffect.h
@@ -8,7 +8,7 @@
 #include "base/macros.h"
 #include "core/animation/Animation.h"
 #include "core/animation/Interpolation.h"
-#include "core/animation/KeyframeEffectReadOnly.h"
+#include "core/animation/KeyframeEffect.h"
 #include "platform/wtf/Allocator.h"
 #include "platform/wtf/Vector.h"
 
@@ -18,7 +18,7 @@
 // effect ordering and managing composited animations.
 class SampledEffect : public GarbageCollectedFinalized<SampledEffect> {
  public:
-  static SampledEffect* Create(KeyframeEffectReadOnly* effect,
+  static SampledEffect* Create(KeyframeEffect* effect,
                                unsigned sequence_number) {
     return new SampledEffect(effect, sequence_number);
   }
@@ -32,9 +32,9 @@
     return interpolations_;
   }
 
-  KeyframeEffectReadOnly* Effect() const { return effect_; }
+  KeyframeEffect* Effect() const { return effect_; }
   unsigned SequenceNumber() const { return sequence_number_; }
-  KeyframeEffectReadOnly::Priority GetPriority() const { return priority_; }
+  KeyframeEffect::Priority GetPriority() const { return priority_; }
   bool WillNeverChange() const;
   void RemoveReplacedInterpolations(const HashSet<PropertyHandle>&);
   void UpdateReplacedProperties(HashSet<PropertyHandle>&);
@@ -42,12 +42,12 @@
   void Trace(blink::Visitor*);
 
  private:
-  SampledEffect(KeyframeEffectReadOnly*, unsigned sequence_number);
+  SampledEffect(KeyframeEffect*, unsigned sequence_number);
 
-  WeakMember<KeyframeEffectReadOnly> effect_;
+  WeakMember<KeyframeEffect> effect_;
   Vector<scoped_refptr<Interpolation>> interpolations_;
   const unsigned sequence_number_;
-  KeyframeEffectReadOnly::Priority priority_;
+  KeyframeEffect::Priority priority_;
   DISALLOW_COPY_AND_ASSIGN(SampledEffect);
 };
 
diff --git a/third_party/WebKit/Source/core/animation/TimingCalculations.h b/third_party/WebKit/Source/core/animation/TimingCalculations.h
index 2212692..48e0892b 100644
--- a/third_party/WebKit/Source/core/animation/TimingCalculations.h
+++ b/third_party/WebKit/Source/core/animation/TimingCalculations.h
@@ -31,7 +31,7 @@
 #ifndef TimingCalculations_h
 #define TimingCalculations_h
 
-#include "core/animation/AnimationEffectReadOnly.h"
+#include "core/animation/AnimationEffect.h"
 #include "core/animation/Timing.h"
 #include "platform/animation/AnimationUtilities.h"
 #include "platform/wtf/MathExtras.h"
@@ -44,32 +44,30 @@
   return x && y ? x * y : 0;
 }
 
-static inline AnimationEffectReadOnly::Phase CalculatePhase(
-    double active_duration,
-    double local_time,
-    const Timing& specified) {
+static inline AnimationEffect::Phase CalculatePhase(double active_duration,
+                                                    double local_time,
+                                                    const Timing& specified) {
   DCHECK_GE(active_duration, 0);
   if (IsNull(local_time))
-    return AnimationEffectReadOnly::kPhaseNone;
+    return AnimationEffect::kPhaseNone;
   double end_time =
       specified.start_delay + active_duration + specified.end_delay;
   if (local_time < std::min(specified.start_delay, end_time))
-    return AnimationEffectReadOnly::kPhaseBefore;
+    return AnimationEffect::kPhaseBefore;
   if (local_time >= std::min(specified.start_delay + active_duration, end_time))
-    return AnimationEffectReadOnly::kPhaseAfter;
-  return AnimationEffectReadOnly::kPhaseActive;
+    return AnimationEffect::kPhaseAfter;
+  return AnimationEffect::kPhaseActive;
 }
 
-static inline bool IsActiveInParentPhase(
-    AnimationEffectReadOnly::Phase parent_phase,
-    Timing::FillMode fill_mode) {
+static inline bool IsActiveInParentPhase(AnimationEffect::Phase parent_phase,
+                                         Timing::FillMode fill_mode) {
   switch (parent_phase) {
-    case AnimationEffectReadOnly::kPhaseBefore:
+    case AnimationEffect::kPhaseBefore:
       return fill_mode == Timing::FillMode::BACKWARDS ||
              fill_mode == Timing::FillMode::BOTH;
-    case AnimationEffectReadOnly::kPhaseActive:
+    case AnimationEffect::kPhaseActive:
       return true;
-    case AnimationEffectReadOnly::kPhaseAfter:
+    case AnimationEffect::kPhaseAfter:
       return fill_mode == Timing::FillMode::FORWARDS ||
              fill_mode == Timing::FillMode::BOTH;
     default:
@@ -78,33 +76,32 @@
   }
 }
 
-static inline double CalculateActiveTime(
-    double active_duration,
-    Timing::FillMode fill_mode,
-    double local_time,
-    AnimationEffectReadOnly::Phase parent_phase,
-    AnimationEffectReadOnly::Phase phase,
-    const Timing& specified) {
+static inline double CalculateActiveTime(double active_duration,
+                                         Timing::FillMode fill_mode,
+                                         double local_time,
+                                         AnimationEffect::Phase parent_phase,
+                                         AnimationEffect::Phase phase,
+                                         const Timing& specified) {
   DCHECK_GE(active_duration, 0);
   DCHECK_EQ(phase, CalculatePhase(active_duration, local_time, specified));
 
   switch (phase) {
-    case AnimationEffectReadOnly::kPhaseBefore:
+    case AnimationEffect::kPhaseBefore:
       if (fill_mode == Timing::FillMode::BACKWARDS ||
           fill_mode == Timing::FillMode::BOTH)
         return 0;
       return NullValue();
-    case AnimationEffectReadOnly::kPhaseActive:
+    case AnimationEffect::kPhaseActive:
       if (IsActiveInParentPhase(parent_phase, fill_mode))
         return local_time - specified.start_delay;
       return NullValue();
-    case AnimationEffectReadOnly::kPhaseAfter:
+    case AnimationEffect::kPhaseAfter:
       if (fill_mode == Timing::FillMode::FORWARDS ||
           fill_mode == Timing::FillMode::BOTH)
         return std::max(0.0, std::min(active_duration,
                                       active_duration + specified.end_delay));
       return NullValue();
-    case AnimationEffectReadOnly::kPhaseNone:
+    case AnimationEffect::kPhaseNone:
       DCHECK(IsNull(local_time));
       return NullValue();
     default:
@@ -146,13 +143,12 @@
 
 // TODO(crbug.com/630915): Align this function with current Web Animations spec
 // text.
-static inline double CalculateIterationTime(
-    double iteration_duration,
-    double repeated_duration,
-    double scaled_active_time,
-    double start_offset,
-    AnimationEffectReadOnly::Phase phase,
-    const Timing& specified) {
+static inline double CalculateIterationTime(double iteration_duration,
+                                            double repeated_duration,
+                                            double scaled_active_time,
+                                            double start_offset,
+                                            AnimationEffect::Phase phase,
+                                            const Timing& specified) {
   DCHECK_GT(iteration_duration, 0);
   DCHECK_EQ(repeated_duration,
             MultiplyZeroAlwaysGivesZero(iteration_duration,
@@ -176,7 +172,7 @@
 
   // This implements step 3 of
   // https://drafts.csswg.org/web-animations/#calculating-the-simple-iteration-progress
-  if (iteration_time == 0 && phase == AnimationEffectReadOnly::kPhaseAfter &&
+  if (iteration_time == 0 && phase == AnimationEffect::kPhaseAfter &&
       repeated_duration != 0 && scaled_active_time != 0)
     return iteration_duration;
 
diff --git a/third_party/WebKit/Source/core/animation/TimingCalculationsTest.cpp b/third_party/WebKit/Source/core/animation/TimingCalculationsTest.cpp
index 1db47cf..c464f52 100644
--- a/third_party/WebKit/Source/core/animation/TimingCalculationsTest.cpp
+++ b/third_party/WebKit/Source/core/animation/TimingCalculationsTest.cpp
@@ -28,6 +28,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include "core/animation/AnimationEffect.h"
 #include "core/animation/TimingCalculations.h"
 
 #include "testing/gtest/include/gtest/gtest.h"
@@ -43,65 +44,58 @@
   // Before Phase
   timing.start_delay = 10;
   EXPECT_TRUE(IsNull(CalculateActiveTime(
-      20, Timing::FillMode::FORWARDS, 0, AnimationEffectReadOnly::kPhaseActive,
-      AnimationEffectReadOnly::kPhaseBefore, timing)));
+      20, Timing::FillMode::FORWARDS, 0, AnimationEffect::kPhaseActive,
+      AnimationEffect::kPhaseBefore, timing)));
   EXPECT_TRUE(IsNull(CalculateActiveTime(
-      20, Timing::FillMode::NONE, 0, AnimationEffectReadOnly::kPhaseActive,
-      AnimationEffectReadOnly::kPhaseBefore, timing)));
-  EXPECT_EQ(0,
-            CalculateActiveTime(20, Timing::FillMode::BACKWARDS, 0,
-                                AnimationEffectReadOnly::kPhaseActive,
-                                AnimationEffectReadOnly::kPhaseBefore, timing));
-  EXPECT_EQ(0,
-            CalculateActiveTime(20, Timing::FillMode::BOTH, 0,
-                                AnimationEffectReadOnly::kPhaseActive,
-                                AnimationEffectReadOnly::kPhaseBefore, timing));
+      20, Timing::FillMode::NONE, 0, AnimationEffect::kPhaseActive,
+      AnimationEffect::kPhaseBefore, timing)));
+  EXPECT_EQ(0, CalculateActiveTime(20, Timing::FillMode::BACKWARDS, 0,
+                                   AnimationEffect::kPhaseActive,
+                                   AnimationEffect::kPhaseBefore, timing));
+  EXPECT_EQ(0, CalculateActiveTime(20, Timing::FillMode::BOTH, 0,
+                                   AnimationEffect::kPhaseActive,
+                                   AnimationEffect::kPhaseBefore, timing));
 
   // Active Phase
   timing.start_delay = 10;
   // Active, and parent Before
   EXPECT_TRUE(IsNull(CalculateActiveTime(
-      20, Timing::FillMode::NONE, 15, AnimationEffectReadOnly::kPhaseBefore,
-      AnimationEffectReadOnly::kPhaseActive, timing)));
+      20, Timing::FillMode::NONE, 15, AnimationEffect::kPhaseBefore,
+      AnimationEffect::kPhaseActive, timing)));
   EXPECT_TRUE(IsNull(CalculateActiveTime(
-      20, Timing::FillMode::FORWARDS, 15, AnimationEffectReadOnly::kPhaseBefore,
-      AnimationEffectReadOnly::kPhaseActive, timing)));
+      20, Timing::FillMode::FORWARDS, 15, AnimationEffect::kPhaseBefore,
+      AnimationEffect::kPhaseActive, timing)));
   // Active, and parent After
   EXPECT_TRUE(IsNull(CalculateActiveTime(
-      20, Timing::FillMode::NONE, 15, AnimationEffectReadOnly::kPhaseAfter,
-      AnimationEffectReadOnly::kPhaseActive, timing)));
+      20, Timing::FillMode::NONE, 15, AnimationEffect::kPhaseAfter,
+      AnimationEffect::kPhaseActive, timing)));
   EXPECT_TRUE(IsNull(CalculateActiveTime(
-      20, Timing::FillMode::BACKWARDS, 15, AnimationEffectReadOnly::kPhaseAfter,
-      AnimationEffectReadOnly::kPhaseActive, timing)));
+      20, Timing::FillMode::BACKWARDS, 15, AnimationEffect::kPhaseAfter,
+      AnimationEffect::kPhaseActive, timing)));
   // Active, and parent Active
-  EXPECT_EQ(5,
-            CalculateActiveTime(20, Timing::FillMode::FORWARDS, 15,
-                                AnimationEffectReadOnly::kPhaseActive,
-                                AnimationEffectReadOnly::kPhaseActive, timing));
+  EXPECT_EQ(5, CalculateActiveTime(20, Timing::FillMode::FORWARDS, 15,
+                                   AnimationEffect::kPhaseActive,
+                                   AnimationEffect::kPhaseActive, timing));
 
   // After Phase
   timing.start_delay = 10;
-  EXPECT_EQ(21,
-            CalculateActiveTime(21, Timing::FillMode::FORWARDS, 45,
-                                AnimationEffectReadOnly::kPhaseActive,
-                                AnimationEffectReadOnly::kPhaseAfter, timing));
-  EXPECT_EQ(21,
-            CalculateActiveTime(21, Timing::FillMode::BOTH, 45,
-                                AnimationEffectReadOnly::kPhaseActive,
-                                AnimationEffectReadOnly::kPhaseAfter, timing));
-  EXPECT_TRUE(IsNull(CalculateActiveTime(21, Timing::FillMode::BACKWARDS, 45,
-                                         AnimationEffectReadOnly::kPhaseActive,
-                                         AnimationEffectReadOnly::kPhaseAfter,
-                                         timing)));
+  EXPECT_EQ(21, CalculateActiveTime(21, Timing::FillMode::FORWARDS, 45,
+                                    AnimationEffect::kPhaseActive,
+                                    AnimationEffect::kPhaseAfter, timing));
+  EXPECT_EQ(21, CalculateActiveTime(21, Timing::FillMode::BOTH, 45,
+                                    AnimationEffect::kPhaseActive,
+                                    AnimationEffect::kPhaseAfter, timing));
   EXPECT_TRUE(IsNull(CalculateActiveTime(
-      21, Timing::FillMode::NONE, 45, AnimationEffectReadOnly::kPhaseActive,
-      AnimationEffectReadOnly::kPhaseAfter, timing)));
+      21, Timing::FillMode::BACKWARDS, 45, AnimationEffect::kPhaseActive,
+      AnimationEffect::kPhaseAfter, timing)));
+  EXPECT_TRUE(IsNull(CalculateActiveTime(
+      21, Timing::FillMode::NONE, 45, AnimationEffect::kPhaseActive,
+      AnimationEffect::kPhaseAfter, timing)));
 
   // None
-  EXPECT_TRUE(
-      IsNull(CalculateActiveTime(32, Timing::FillMode::NONE, NullValue(),
-                                 AnimationEffectReadOnly::kPhaseNone,
-                                 AnimationEffectReadOnly::kPhaseNone, timing)));
+  EXPECT_TRUE(IsNull(CalculateActiveTime(
+      32, Timing::FillMode::NONE, NullValue(), AnimationEffect::kPhaseNone,
+      AnimationEffect::kPhaseNone, timing)));
 }
 
 TEST(AnimationTimingCalculationsTest, ScaledActiveTime) {
@@ -148,25 +142,21 @@
 
   // if the scaled active time is null
   EXPECT_TRUE(IsNull(CalculateIterationTime(
-      1, 1, NullValue(), 1, AnimationEffectReadOnly::kPhaseActive, timing)));
+      1, 1, NullValue(), 1, AnimationEffect::kPhaseActive, timing)));
 
   // if (complex-conditions)...
-  EXPECT_EQ(12,
-            CalculateIterationTime(
-                12, 12, 12, 0, AnimationEffectReadOnly::kPhaseActive, timing));
+  EXPECT_EQ(12, CalculateIterationTime(12, 12, 12, 0,
+                                       AnimationEffect::kPhaseActive, timing));
 
   // otherwise
   timing.iteration_count = 10;
-  EXPECT_EQ(
-      5, CalculateIterationTime(10, 100, 25, 4,
-                                AnimationEffectReadOnly::kPhaseActive, timing));
-  EXPECT_EQ(
-      7, CalculateIterationTime(11, 110, 29, 1,
-                                AnimationEffectReadOnly::kPhaseActive, timing));
+  EXPECT_EQ(5, CalculateIterationTime(10, 100, 25, 4,
+                                      AnimationEffect::kPhaseActive, timing));
+  EXPECT_EQ(7, CalculateIterationTime(11, 110, 29, 1,
+                                      AnimationEffect::kPhaseActive, timing));
   timing.iteration_start = 1.1;
-  EXPECT_EQ(
-      8, CalculateIterationTime(12, 120, 20, 7,
-                                AnimationEffectReadOnly::kPhaseActive, timing));
+  EXPECT_EQ(8, CalculateIterationTime(12, 120, 20, 7,
+                                      AnimationEffect::kPhaseActive, timing));
 }
 
 TEST(AnimationTimingCalculationsTest, CurrentIteration) {
diff --git a/third_party/WebKit/Source/core/animation/WorkletAnimationBase.h b/third_party/WebKit/Source/core/animation/WorkletAnimationBase.h
index 8a28f09..3b69c840 100644
--- a/third_party/WebKit/Source/core/animation/WorkletAnimationBase.h
+++ b/third_party/WebKit/Source/core/animation/WorkletAnimationBase.h
@@ -12,7 +12,7 @@
 namespace blink {
 
 class Document;
-class KeyframeEffectReadOnly;
+class KeyframeEffect;
 
 class CORE_EXPORT WorkletAnimationBase : public ScriptWrappable {
  public:
@@ -28,7 +28,7 @@
   virtual bool StartOnCompositor(String* failure_message) = 0;
 
   virtual Document* GetDocument() const = 0;
-  virtual KeyframeEffectReadOnly* GetEffect() const = 0;
+  virtual KeyframeEffect* GetEffect() const = 0;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp b/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp
index d95255ca..8d0ba0e 100644
--- a/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp
+++ b/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp
@@ -41,8 +41,8 @@
 #include "core/animation/Interpolation.h"
 #include "core/animation/InterpolationEnvironment.h"
 #include "core/animation/InterpolationType.h"
+#include "core/animation/KeyframeEffect.h"
 #include "core/animation/KeyframeEffectModel.h"
-#include "core/animation/KeyframeEffectReadOnly.h"
 #include "core/animation/TransitionInterpolation.h"
 #include "core/animation/css/CSSAnimatableValueFactory.h"
 #include "core/css/CSSKeyframeRule.h"
@@ -224,12 +224,12 @@
 namespace {
 
 const KeyframeEffectModelBase* GetKeyframeEffectModelBase(
-    const AnimationEffectReadOnly* effect) {
+    const AnimationEffect* effect) {
   if (!effect)
     return nullptr;
   const EffectModel* model = nullptr;
-  if (effect->IsKeyframeEffectReadOnly())
-    model = ToKeyframeEffectReadOnly(effect)->Model();
+  if (effect->IsKeyframeEffect())
+    model = ToKeyframeEffect(effect)->Model();
   else if (effect->IsInertEffect())
     model = ToInertEffect(effect)->Model();
   if (!model || !model->IsKeyframeEffectModel())
@@ -420,7 +420,7 @@
     const ComputedStyle& style,
     const ComputedStyle* parent_style) {
   const auto& snapshot = [&element, &style,
-                          parent_style](const AnimationEffectReadOnly* effect) {
+                          parent_style](const AnimationEffect* effect) {
     const KeyframeEffectModelBase* keyframe_effect =
         GetKeyframeEffectModelBase(effect);
     if (keyframe_effect && keyframe_effect->NeedsCompositorKeyframesSnapshot())
@@ -476,8 +476,7 @@
     animation->SetCompositorPending(true);
 
   for (const auto& entry : pending_update_.AnimationsWithUpdates()) {
-    KeyframeEffectReadOnly* effect =
-        ToKeyframeEffectReadOnly(entry.animation->effect());
+    KeyframeEffect* effect = ToKeyframeEffect(entry.animation->effect());
 
     effect->SetModel(entry.effect->Model());
     effect->UpdateSpecifiedTiming(entry.effect->SpecifiedTiming());
@@ -503,7 +502,7 @@
         new AnimationEventDelegate(element, entry.name);
     KeyframeEffect* effect = KeyframeEffect::Create(
         element, inert_animation->Model(), inert_animation->SpecifiedTiming(),
-        KeyframeEffectReadOnly::kDefaultPriority, event_delegate);
+        KeyframeEffect::kDefaultPriority, event_delegate);
     Animation* animation = element->GetDocument().Timeline().Play(effect);
     animation->setId(entry.name);
     if (inert_animation->Paused())
@@ -518,30 +517,29 @@
   // be when transitions are retargeted. Instead of triggering complete style
   // recalculation, we find these cases by searching for new transitions that
   // have matching cancelled animation property IDs on the compositor.
-  HeapHashMap<PropertyHandle, std::pair<Member<KeyframeEffectReadOnly>, double>>
+  HeapHashMap<PropertyHandle, std::pair<Member<KeyframeEffect>, double>>
       retargeted_compositor_transitions;
   for (const PropertyHandle& property :
        pending_update_.CancelledTransitions()) {
     DCHECK(transitions_.Contains(property));
 
     Animation* animation = transitions_.Take(property).animation;
-    KeyframeEffectReadOnly* effect =
-        ToKeyframeEffectReadOnly(animation->effect());
+    KeyframeEffect* effect = ToKeyframeEffect(animation->effect());
     if (effect->HasActiveAnimationsOnCompositor(property) &&
         pending_update_.NewTransitions().find(property) !=
             pending_update_.NewTransitions().end() &&
         !animation->Limited()) {
       retargeted_compositor_transitions.insert(
           property,
-          std::pair<KeyframeEffectReadOnly*, double>(
+          std::pair<KeyframeEffect*, double>(
               effect, animation->StartTimeInternal().value_or(NullValue())));
     }
     animation->cancel();
     // after cancelation, transitions must be downgraded or they'll fail
     // to be considered when retriggering themselves. This can happen if
     // the transition is captured through getAnimations then played.
-    if (animation->effect() && animation->effect()->IsKeyframeEffectReadOnly())
-      ToKeyframeEffectReadOnly(animation->effect())->DowngradeToNormal();
+    if (animation->effect() && animation->effect()->IsKeyframeEffect())
+      ToKeyframeEffect(animation->effect())->DowngradeToNormal();
     animation->Update(kTimingUpdateOnDemand);
   }
 
@@ -550,9 +548,8 @@
     if (transitions_.Contains(property)) {
       Animation* animation = transitions_.Take(property).animation;
       // Transition must be downgraded
-      if (animation->effect() &&
-          animation->effect()->IsKeyframeEffectReadOnly())
-        ToKeyframeEffectReadOnly(animation->effect())->DowngradeToNormal();
+      if (animation->effect() && animation->effect()->IsKeyframeEffect())
+        ToKeyframeEffect(animation->effect())->DowngradeToNormal();
     }
   }
 
@@ -575,9 +572,9 @@
     KeyframeEffectModelBase* model = inert_animation->Model();
 
     if (retargeted_compositor_transitions.Contains(property)) {
-      const std::pair<Member<KeyframeEffectReadOnly>, double>& old_transition =
+      const std::pair<Member<KeyframeEffect>, double>& old_transition =
           retargeted_compositor_transitions.at(property);
-      KeyframeEffectReadOnly* old_animation = old_transition.first;
+      KeyframeEffect* old_animation = old_transition.first;
       double old_start_time = old_transition.second;
       double inherited_time =
           IsNull(old_start_time)
@@ -614,7 +611,7 @@
 
     KeyframeEffect* transition = KeyframeEffect::Create(
         element, model, inert_animation->SpecifiedTiming(),
-        KeyframeEffectReadOnly::kTransitionPriority, event_delegate);
+        KeyframeEffect::kTransitionPriority, event_delegate);
     Animation* animation = element->GetDocument().Timeline().Play(transition);
     if (property.IsCSSCustomProperty()) {
       animation->setId(property.CustomPropertyName());
@@ -990,13 +987,13 @@
   ActiveInterpolationsMap custom_interpolations(
       EffectStack::ActiveInterpolations(
           effect_stack, new_animations, suppressed_animations,
-          KeyframeEffectReadOnly::kDefaultPriority, IsCustomPropertyHandle));
+          KeyframeEffect::kDefaultPriority, IsCustomPropertyHandle));
   update.AdoptActiveInterpolationsForCustomAnimations(custom_interpolations);
 
   ActiveInterpolationsMap standard_interpolations(
       EffectStack::ActiveInterpolations(
           effect_stack, new_animations, suppressed_animations,
-          KeyframeEffectReadOnly::kDefaultPriority, IsStandardPropertyHandle));
+          KeyframeEffect::kDefaultPriority, IsStandardPropertyHandle));
   update.AdoptActiveInterpolationsForStandardAnimations(
       standard_interpolations);
 }
@@ -1055,8 +1052,7 @@
   if (update.NewTransitions().IsEmpty() &&
       update.CancelledTransitions().IsEmpty()) {
     active_interpolations_for_transitions = EffectStack::ActiveInterpolations(
-        effect_stack, nullptr, nullptr,
-        KeyframeEffectReadOnly::kTransitionPriority,
+        effect_stack, nullptr, nullptr, KeyframeEffect::kTransitionPriority,
         PropertyFilter(property_pass));
   } else {
     HeapVector<Member<const InertEffect>> new_transitions;
@@ -1077,8 +1073,7 @@
 
     active_interpolations_for_transitions = EffectStack::ActiveInterpolations(
         effect_stack, &new_transitions, &cancelled_animations,
-        KeyframeEffectReadOnly::kTransitionPriority,
-        PropertyFilter(property_pass));
+        KeyframeEffect::kTransitionPriority, PropertyFilter(property_pass));
   }
 
   const ActiveInterpolationsMap& animations =
@@ -1120,28 +1115,27 @@
 }
 
 bool CSSAnimations::AnimationEventDelegate::RequiresIterationEvents(
-    const AnimationEffectReadOnly& animation_node) {
+    const AnimationEffect& animation_node) {
   return GetDocument().HasListenerType(Document::kAnimationIterationListener);
 }
 
 void CSSAnimations::AnimationEventDelegate::OnEventCondition(
-    const AnimationEffectReadOnly& animation_node) {
-  const AnimationEffectReadOnly::Phase current_phase =
-      animation_node.GetPhase();
+    const AnimationEffect& animation_node) {
+  const AnimationEffect::Phase current_phase = animation_node.GetPhase();
   const double current_iteration = animation_node.CurrentIteration();
 
   if (previous_phase_ != current_phase &&
-      (current_phase == AnimationEffectReadOnly::kPhaseActive ||
-       current_phase == AnimationEffectReadOnly::kPhaseAfter) &&
-      (previous_phase_ == AnimationEffectReadOnly::kPhaseNone ||
-       previous_phase_ == AnimationEffectReadOnly::kPhaseBefore)) {
+      (current_phase == AnimationEffect::kPhaseActive ||
+       current_phase == AnimationEffect::kPhaseAfter) &&
+      (previous_phase_ == AnimationEffect::kPhaseNone ||
+       previous_phase_ == AnimationEffect::kPhaseBefore)) {
     const double start_delay = animation_node.SpecifiedTiming().start_delay;
     const double elapsed_time = start_delay < 0 ? -start_delay : 0;
     MaybeDispatch(Document::kAnimationStartListener,
                   EventTypeNames::animationstart, elapsed_time);
   }
 
-  if (current_phase == AnimationEffectReadOnly::kPhaseActive &&
+  if (current_phase == AnimationEffect::kPhaseActive &&
       previous_phase_ == current_phase &&
       previous_iteration_ != current_iteration) {
     // We fire only a single event for all iterations thast terminate
@@ -1156,8 +1150,8 @@
                   EventTypeNames::animationiteration, elapsed_time);
   }
 
-  if (current_phase == AnimationEffectReadOnly::kPhaseAfter &&
-      previous_phase_ != AnimationEffectReadOnly::kPhaseAfter)
+  if (current_phase == AnimationEffect::kPhaseAfter &&
+      previous_phase_ != AnimationEffect::kPhaseAfter)
     MaybeDispatch(Document::kAnimationEndListener, EventTypeNames::animationend,
                   animation_node.ActiveDurationInternal());
 
@@ -1167,7 +1161,7 @@
 
 void CSSAnimations::AnimationEventDelegate::Trace(blink::Visitor* visitor) {
   visitor->Trace(animation_target_);
-  AnimationEffectReadOnly::EventDelegate::Trace(visitor);
+  AnimationEffect::EventDelegate::Trace(visitor);
 }
 
 EventTarget* CSSAnimations::TransitionEventDelegate::GetEventTarget() const {
@@ -1175,10 +1169,9 @@
 }
 
 void CSSAnimations::TransitionEventDelegate::OnEventCondition(
-    const AnimationEffectReadOnly& animation_node) {
-  const AnimationEffectReadOnly::Phase current_phase =
-      animation_node.GetPhase();
-  if (current_phase == AnimationEffectReadOnly::kPhaseAfter &&
+    const AnimationEffect& animation_node) {
+  const AnimationEffect::Phase current_phase = animation_node.GetPhase();
+  if (current_phase == AnimationEffect::kPhaseAfter &&
       current_phase != previous_phase_ &&
       GetDocument().HasListenerType(Document::kTransitionEndListener)) {
     String property_name =
@@ -1201,7 +1194,7 @@
 
 void CSSAnimations::TransitionEventDelegate::Trace(blink::Visitor* visitor) {
   visitor->Trace(transition_target_);
-  AnimationEffectReadOnly::EventDelegate::Trace(visitor);
+  AnimationEffect::EventDelegate::Trace(visitor);
 }
 
 const StylePropertyShorthand& CSSAnimations::PropertiesForTransitionAll() {
diff --git a/third_party/WebKit/Source/core/animation/css/CSSAnimations.h b/third_party/WebKit/Source/core/animation/css/CSSAnimations.h
index fe24565..62248c7 100644
--- a/third_party/WebKit/Source/core/animation/css/CSSAnimations.h
+++ b/third_party/WebKit/Source/core/animation/css/CSSAnimations.h
@@ -194,16 +194,15 @@
       PropertyPass,
       const Element* animating_element);
 
-  class AnimationEventDelegate final
-      : public AnimationEffectReadOnly::EventDelegate {
+  class AnimationEventDelegate final : public AnimationEffect::EventDelegate {
    public:
     AnimationEventDelegate(Element* animation_target, const AtomicString& name)
         : animation_target_(animation_target),
           name_(name),
-          previous_phase_(AnimationEffectReadOnly::kPhaseNone),
+          previous_phase_(AnimationEffect::kPhaseNone),
           previous_iteration_(NullValue()) {}
-    bool RequiresIterationEvents(const AnimationEffectReadOnly&) override;
-    void OnEventCondition(const AnimationEffectReadOnly&) override;
+    bool RequiresIterationEvents(const AnimationEffect&) override;
+    void OnEventCondition(const AnimationEffect&) override;
     void Trace(blink::Visitor*) override;
 
    private:
@@ -216,22 +215,21 @@
                        double elapsed_time);
     Member<Element> animation_target_;
     const AtomicString name_;
-    AnimationEffectReadOnly::Phase previous_phase_;
+    AnimationEffect::Phase previous_phase_;
     double previous_iteration_;
   };
 
-  class TransitionEventDelegate final
-      : public AnimationEffectReadOnly::EventDelegate {
+  class TransitionEventDelegate final : public AnimationEffect::EventDelegate {
    public:
     TransitionEventDelegate(Element* transition_target,
                             const PropertyHandle& property)
         : transition_target_(transition_target),
           property_(property),
-          previous_phase_(AnimationEffectReadOnly::kPhaseNone) {}
-    bool RequiresIterationEvents(const AnimationEffectReadOnly&) override {
+          previous_phase_(AnimationEffect::kPhaseNone) {}
+    bool RequiresIterationEvents(const AnimationEffect&) override {
       return false;
     }
-    void OnEventCondition(const AnimationEffectReadOnly&) override;
+    void OnEventCondition(const AnimationEffect&) override;
     void Trace(blink::Visitor*) override;
 
    private:
@@ -242,7 +240,7 @@
 
     Member<Element> transition_target_;
     PropertyHandle property_;
-    AnimationEffectReadOnly::Phase previous_phase_;
+    AnimationEffect::Phase previous_phase_;
   };
 
   DISALLOW_COPY_AND_ASSIGN(CSSAnimations);
diff --git a/third_party/WebKit/Source/core/animation/test_data/opacity-with-3d-transform.html b/third_party/WebKit/Source/core/animation/test_data/opacity-with-3d-transform.html
new file mode 100644
index 0000000..7620a67
--- /dev/null
+++ b/third_party/WebKit/Source/core/animation/test_data/opacity-with-3d-transform.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<style>
+@keyframes test {
+  0% { opacity: 0; transform: rotateX(0deg); }
+  100% { opacity: 1; transform: rotateX(90deg); }
+}
+
+.animate {
+  animation-name: test;
+  animation-duration: 1s;
+}
+</style>
+<div id="target" class="animate"></div>;
diff --git a/third_party/WebKit/Source/core/animation/test_data/opacity-with-will-change-transform.html b/third_party/WebKit/Source/core/animation/test_data/opacity-with-will-change-transform.html
new file mode 100644
index 0000000..0943c70
--- /dev/null
+++ b/third_party/WebKit/Source/core/animation/test_data/opacity-with-will-change-transform.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<style>
+@keyframes test {
+  0% { opacity: 0; }
+  100% { opacity: 1; }
+}
+
+.animate {
+  animation-name: test;
+  animation-duration: 1s;
+}
+</style>
+<div id="target" style="will-change: transform;" class="animate"></div>;
diff --git a/third_party/WebKit/Source/core/clipboard/DataTransfer.cpp b/third_party/WebKit/Source/core/clipboard/DataTransfer.cpp
index b99045cb..afe55061 100644
--- a/third_party/WebKit/Source/core/clipboard/DataTransfer.cpp
+++ b/third_party/WebKit/Source/core/clipboard/DataTransfer.cpp
@@ -133,13 +133,17 @@
     dragged_layout_object->GetDocument().Lifecycle().AdvanceTo(
         DocumentLifecycle::kPaintClean);
 
+    FloatPoint paint_offset = dragged_layout_object->LocalToAncestorPoint(
+        FloatPoint(), &layer->GetLayoutObject(), kUseTransforms);
     PropertyTreeState border_box_properties = PropertyTreeState::Root();
     if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
       border_box_properties =
           layer->GetLayoutObject().FirstFragment().LocalBorderBoxProperties();
+      // In SPv175+ we paint in the containing transform node's space. Add the
+      // offset from the layer to this transform space.
+      paint_offset +=
+          FloatPoint(layer->GetLayoutObject().FirstFragment().PaintOffset());
     }
-    FloatPoint paint_offset = dragged_layout_object->LocalToAncestorPoint(
-        FloatPoint(), &layer->GetLayoutObject(), kUseTransforms);
     return DataTransfer::CreateDragImageForFrame(
         *local_frame_, 1.0f,
         LayoutObject::ShouldRespectImageOrientation(dragged_layout_object),
diff --git a/third_party/WebKit/Source/core/clipboard/DataTransferTest.cpp b/third_party/WebKit/Source/core/clipboard/DataTransferTest.cpp
index 17671d73..49a5db55 100644
--- a/third_party/WebKit/Source/core/clipboard/DataTransferTest.cpp
+++ b/third_party/WebKit/Source/core/clipboard/DataTransferTest.cpp
@@ -315,4 +315,38 @@
   EXPECT_EQ(IntSize(200, 100), image->Size());
 }
 
+TEST_P(DataTransferTest, NodeImageInOffsetStackingContext) {
+  SetBodyInnerHTML(R"HTML(
+    <style>
+      * { margin: 0; }
+      #container {
+        position: absolute;
+        top: 4px;
+        z-index: 10;
+      }
+      #drag {
+        width: 5px;
+        height: 5px;
+        background: #0F0;
+      }
+    </style>
+    <div id="container">
+      <div id="drag" draggable="true"></div>
+    </div>
+  )HTML");
+  Element& drag = *GetDocument().getElementById("drag");
+  const auto image = DataTransfer::NodeImage(GetFrame(), drag);
+  constexpr int drag_width = 5;
+  constexpr int drag_height = 5;
+  EXPECT_EQ(IntSize(drag_width, drag_height), image->Size());
+
+  // The dragged image should be (drag_width x drag_height) and fully green.
+  Color green = 0xFF00FF00;
+  const SkBitmap& bitmap = image->Bitmap();
+  for (int x = 0; x < drag_width; ++x) {
+    for (int y = 0; y < drag_height; ++y)
+      EXPECT_EQ(green, bitmap.getColor(x, y));
+  }
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/core_idl_files.gni b/third_party/WebKit/Source/core/core_idl_files.gni
index fcb1bd0..1357a358 100644
--- a/third_party/WebKit/Source/core/core_idl_files.gni
+++ b/third_party/WebKit/Source/core/core_idl_files.gni
@@ -37,13 +37,12 @@
 core_idl_files =
     get_path_info([
                     "animation/Animation.idl",
-                    "animation/AnimationEffectReadOnly.idl",
+                    "animation/AnimationEffect.idl",
                     "animation/AnimationEffectTiming.idl",
                     "animation/AnimationEffectTimingReadOnly.idl",
                     "animation/AnimationTimeline.idl",
                     "animation/DocumentTimeline.idl",
                     "animation/KeyframeEffect.idl",
-                    "animation/KeyframeEffectReadOnly.idl",
                     "animation/ScrollTimeline.idl",
                     "clipboard/DataTransfer.idl",
                     "clipboard/DataTransferItemList.idl",
diff --git a/third_party/WebKit/Source/core/css/CSSProperties.json5 b/third_party/WebKit/Source/core/css/CSSProperties.json5
index 5cb95123..9ca53a44 100644
--- a/third_party/WebKit/Source/core/css/CSSProperties.json5
+++ b/third_party/WebKit/Source/core/css/CSSProperties.json5
@@ -507,6 +507,8 @@
       name_for_methods: "SizeAdjust",
       converter: "ConvertFontSizeAdjust",
       priority: "High",
+      keywords: ["none"],
+      typedom_types: ["Keyword", "Number"]
     },
     {
       name: "font-stretch",
@@ -517,6 +519,11 @@
       name_for_methods: "Stretch",
       converter: "ConvertFontStretch",
       priority: "High",
+      keywords: [
+        "normal", "ultra-condensed", "extra-condensed", "condensed",
+        "semi-condensed", "semi-expanded", "expanded", "extra-expanded", "ultra-expanded"
+      ],
+      typedom_types: ["Keyword", "Percentage"]
     },
     {
       name: "font-style",
@@ -599,6 +606,8 @@
       name_for_methods: "VariationSettings",
       converter: "ConvertFontVariationSettings",
       priority: "High",
+      keywords: ["normal"],
+      typedom_types: ["Keyword"]
     },
     {
       name: "-webkit-font-smoothing",
diff --git a/third_party/WebKit/Source/core/css/CSSSelector.cpp b/third_party/WebKit/Source/core/css/CSSSelector.cpp
index e950288..91dafa2 100644
--- a/third_party/WebKit/Source/core/css/CSSSelector.cpp
+++ b/third_party/WebKit/Source/core/css/CSSSelector.cpp
@@ -862,6 +862,7 @@
       case kSubSelector:
         NOTREACHED();
         break;
+      case kShadowPart:
       case kShadowPseudo:
       case kShadowSlot:
         result = builder.ToString() + result;
diff --git a/third_party/WebKit/Source/core/css/CSSSelector.h b/third_party/WebKit/Source/core/css/CSSSelector.h
index c105ea7..cd161882 100644
--- a/third_party/WebKit/Source/core/css/CSSSelector.h
+++ b/third_party/WebKit/Source/core/css/CSSSelector.h
@@ -136,7 +136,8 @@
     kShadowDeep,                // /deep/ combinator
     kShadowDeepAsDescendant,    // /deep/ as an alias for descendant
     kShadowPseudo,              // ::shadow pseudo element
-    kShadowSlot                 // ::slotted() pseudo element
+    kShadowSlot,                // ::slotted() pseudo element
+    kShadowPart,                // ::part() pseudo element
   };
 
   enum PseudoType {
diff --git a/third_party/WebKit/Source/core/css/ElementRuleCollector.cpp b/third_party/WebKit/Source/core/css/ElementRuleCollector.cpp
index 5b1c9729..38b033156 100644
--- a/third_party/WebKit/Source/core/css/ElementRuleCollector.cpp
+++ b/third_party/WebKit/Source/core/css/ElementRuleCollector.cpp
@@ -247,6 +247,15 @@
                               cascade_order, match_request);
 }
 
+void ElementRuleCollector::CollectMatchingPartPseudoRules(
+    const MatchRequest& match_request,
+    CascadeOrder cascade_order) {
+  if (!RuntimeEnabledFeatures::CSSPartPseudoElementEnabled())
+    return;
+  CollectMatchingRulesForList(match_request.rule_set->PartPseudoRules(),
+                              cascade_order, match_request);
+}
+
 template <class CSSRuleCollection>
 CSSRule* ElementRuleCollector::FindStyleRule(CSSRuleCollection* css_rules,
                                              StyleRule* style_rule) {
diff --git a/third_party/WebKit/Source/core/css/ElementRuleCollector.h b/third_party/WebKit/Source/core/css/ElementRuleCollector.h
index 56d0b68..87046e8 100644
--- a/third_party/WebKit/Source/core/css/ElementRuleCollector.h
+++ b/third_party/WebKit/Source/core/css/ElementRuleCollector.h
@@ -132,6 +132,8 @@
                             bool matching_tree_boundary_rules = false);
   void CollectMatchingShadowHostRules(const MatchRequest&,
                                       CascadeOrder = kIgnoreCascadeOrder);
+  void CollectMatchingPartPseudoRules(const MatchRequest&,
+                                      CascadeOrder = kIgnoreCascadeOrder);
   void SortAndTransferMatchedRules();
   void ClearMatchedRules();
   void AddElementStyleProperties(const CSSPropertyValueSet*,
diff --git a/third_party/WebKit/Source/core/css/RuleSet.cpp b/third_party/WebKit/Source/core/css/RuleSet.cpp
index 572a095..8b90a28 100644
--- a/third_party/WebKit/Source/core/css/RuleSet.cpp
+++ b/third_party/WebKit/Source/core/css/RuleSet.cpp
@@ -123,6 +123,7 @@
         case CSSSelector::kPseudoAnyLink:
         case CSSSelector::kPseudoFocus:
         case CSSSelector::kPseudoPlaceholder:
+        case CSSSelector::kPseudoPart:
         case CSSSelector::kPseudoHost:
         case CSSSelector::kPseudoHostContext:
           pseudo_type = selector->GetPseudoType();
diff --git a/third_party/WebKit/Source/core/css/SelectorChecker.cpp b/third_party/WebKit/Source/core/css/SelectorChecker.cpp
index 4956fb3..38d6ebe9 100644
--- a/third_party/WebKit/Source/core/css/SelectorChecker.cpp
+++ b/third_party/WebKit/Source/core/css/SelectorChecker.cpp
@@ -515,6 +515,23 @@
       return MatchSelector(next_context, result);
     }
 
+    case CSSSelector::kShadowPart:
+      // We ascend through ancestor shadow host elements until we reach the host
+      // in the TreeScope associated with the style rule. We then match against
+      // that host.
+      if (RuntimeEnabledFeatures::CSSPartPseudoElementEnabled()) {
+        while (next_context.element) {
+          next_context.element = next_context.element->OwnerShadowHost();
+          if (!next_context.element)
+            return kSelectorFailsCompletely;
+
+          if (next_context.element->GetTreeScope() ==
+              context.scope->GetTreeScope())
+            return MatchSelector(next_context, result);
+        }
+      }
+      return kSelectorFailsCompletely;
+      break;
     case CSSSelector::kSubSelector:
       break;
   }
diff --git a/third_party/WebKit/Source/core/css/SelectorFilter.cpp b/third_party/WebKit/Source/core/css/SelectorFilter.cpp
index 685a0cb..8651444c 100644
--- a/third_party/WebKit/Source/core/css/SelectorFilter.cpp
+++ b/third_party/WebKit/Source/core/css/SelectorFilter.cpp
@@ -158,7 +158,7 @@
     return;
   }
 
-  // Skip the topmost selector. It is handled quickly by the rule hashes.
+  // Skip the rightmost compound. It is handled quickly by the rule hashes.
   bool skip_over_subselectors = true;
   for (const CSSSelector* current = selector.TagHistory(); current;
        current = current->TagHistory()) {
@@ -179,8 +179,8 @@
       case CSSSelector::kDescendant:
       case CSSSelector::kShadowDeepAsDescendant:
       case CSSSelector::kChild:
-      // Fall through.
       case CSSSelector::kShadowPseudo:
+      case CSSSelector::kShadowPart:
       case CSSSelector::kShadowDeep:
       case CSSSelector::kShadowPiercingDescendant:
         skip_over_subselectors = false;
diff --git a/third_party/WebKit/Source/core/css/StyleSheetList.cpp b/third_party/WebKit/Source/core/css/StyleSheetList.cpp
index 6b5ef15..6f8fc5e 100644
--- a/third_party/WebKit/Source/core/css/StyleSheetList.cpp
+++ b/third_party/WebKit/Source/core/css/StyleSheetList.cpp
@@ -77,6 +77,9 @@
 }
 
 HTMLStyleElement* StyleSheetList::GetNamedItem(const AtomicString& name) const {
+  if (!tree_scope_)
+    return nullptr;
+
   // IE also supports retrieving a stylesheet by name, using the name/id of the
   // <style> tag (this is consistent with all the other collections) ### Bad
   // implementation because returns a single element (are IDs always unique?)
diff --git a/third_party/WebKit/Source/core/css/StyleSheetListTest.cpp b/third_party/WebKit/Source/core/css/StyleSheetListTest.cpp
index 9ddfcc7..cbdaf623 100644
--- a/third_party/WebKit/Source/core/css/StyleSheetListTest.cpp
+++ b/third_party/WebKit/Source/core/css/StyleSheetListTest.cpp
@@ -58,4 +58,9 @@
   EXPECT_EQ(sheet_list->item(1), blue_style_sheet);
 }
 
+TEST_F(StyleSheetListTest, GetNamedItemNoTreeScope) {
+  StyleSheetList* list = StyleSheetList::Create();
+  EXPECT_FALSE(list->GetNamedItem("id"));
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSUnitValue.cpp b/third_party/WebKit/Source/core/css/cssom/CSSUnitValue.cpp
index 2ce54238..6041cc0f 100644
--- a/third_party/WebKit/Source/core/css/cssom/CSSUnitValue.cpp
+++ b/third_party/WebKit/Source/core/css/cssom/CSSUnitValue.cpp
@@ -47,6 +47,8 @@
     case CSSPropertyFlexGrow:
     case CSSPropertyFlexShrink:
     case CSSPropertyFontSize:
+    case CSSPropertyFontSizeAdjust:
+    case CSSPropertyFontStretch:
       return value < 0;
     case CSSPropertyFontWeight:
       return value < 0 || value > 1000;
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.cpp b/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.cpp
index a94b85b..a15ccb51b 100644
--- a/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.cpp
+++ b/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.cpp
@@ -4,6 +4,7 @@
 
 #include "core/css/cssom/CSSUnparsedValue.h"
 
+#include "core/css/CSSCustomPropertyDeclaration.h"
 #include "core/css/CSSVariableData.h"
 #include "core/css/CSSVariableReferenceValue.h"
 #include "core/css/cssom/CSSStyleVariableReferenceValue.h"
@@ -66,16 +67,26 @@
 CSSUnparsedValue* CSSUnparsedValue::FromCSSValue(
     const CSSVariableReferenceValue& value) {
   DCHECK(value.VariableDataValue());
-  return FromCSSValue(*value.VariableDataValue());
+  return FromCSSVariableData(*value.VariableDataValue());
 }
 
-CSSUnparsedValue* CSSUnparsedValue::FromCSSValue(const CSSVariableData& value) {
+CSSUnparsedValue* CSSUnparsedValue::FromCSSValue(
+    const CSSCustomPropertyDeclaration& value) {
+  if (const CSSVariableData* data = value.Value())
+    return FromCSSVariableData(*data);
+
+  // Otherwise, it's a CSS-wide keyword
+  return FromString(value.CustomCSSText());
+}
+
+CSSUnparsedValue* CSSUnparsedValue::FromCSSVariableData(
+    const CSSVariableData& value) {
   return CSSUnparsedValue::Create(ParserTokenRangeToTokens(value.TokenRange()));
 }
 
 CSSUnparsedSegment CSSUnparsedValue::AnonymousIndexedGetter(
     unsigned index,
-    ExceptionState& exception_state) {
+    ExceptionState& exception_state) const {
   if (index < tokens_.size())
     return tokens_[index];
   return {};
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.h b/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.h
index 0f1d622c..9365790 100644
--- a/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.h
+++ b/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValue.h
@@ -13,6 +13,7 @@
 namespace blink {
 
 class CSSVariableReferenceValue;
+class CSSCustomPropertyDeclaration;
 class CSSVariableData;
 using CSSUnparsedSegment = StringOrCSSVariableReferenceValue;
 
@@ -30,13 +31,14 @@
     return Create(HeapVector<CSSUnparsedSegment>());
   }
   static CSSUnparsedValue* FromCSSValue(const CSSVariableReferenceValue&);
-  static CSSUnparsedValue* FromCSSValue(const CSSVariableData&);
+  static CSSUnparsedValue* FromCSSValue(const CSSCustomPropertyDeclaration&);
+  static CSSUnparsedValue* FromCSSVariableData(const CSSVariableData&);
 
   const CSSValue* ToCSSValue() const override;
 
   StyleValueType GetType() const override { return kUnparsedType; }
 
-  CSSUnparsedSegment AnonymousIndexedGetter(unsigned, ExceptionState&);
+  CSSUnparsedSegment AnonymousIndexedGetter(unsigned, ExceptionState&) const;
   bool AnonymousIndexedSetter(unsigned,
                               const CSSUnparsedSegment&,
                               ExceptionState&);
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValueTest.cpp b/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValueTest.cpp
new file mode 100644
index 0000000..fb012fc
--- /dev/null
+++ b/third_party/WebKit/Source/core/css/cssom/CSSUnparsedValueTest.cpp
@@ -0,0 +1,25 @@
+// Copyright 2018 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/CSSCustomPropertyDeclaration.h"
+#include "core/css/cssom/CSSUnparsedValue.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+
+TEST(CSSUnparsedValueTest, FromCustomPropertyDeclarationWithCSSWideKeyword) {
+  const auto* initial_value =
+      CSSCustomPropertyDeclaration::Create("--var", CSSValueInitial);
+  const auto* unparsed_value = CSSUnparsedValue::FromCSSValue(*initial_value);
+  ASSERT_NE(nullptr, unparsed_value);
+  ASSERT_EQ(1U, unparsed_value->length());
+
+  const auto& item =
+      unparsed_value->AnonymousIndexedGetter(0, ASSERT_NO_EXCEPTION);
+  ASSERT_TRUE(item.IsString());
+  EXPECT_EQ("initial", item.GetAsString());
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/css/cssom/StyleValueFactory.cpp b/third_party/WebKit/Source/core/css/cssom/StyleValueFactory.cpp
index e7692029..633b692 100644
--- a/third_party/WebKit/Source/core/css/cssom/StyleValueFactory.cpp
+++ b/third_party/WebKit/Source/core/css/cssom/StyleValueFactory.cpp
@@ -105,10 +105,8 @@
   if (value.IsVariableReferenceValue())
     return CSSUnparsedValue::FromCSSValue(ToCSSVariableReferenceValue(value));
   if (value.IsCustomPropertyDeclaration()) {
-    const CSSVariableData* variable_data =
-        ToCSSCustomPropertyDeclaration(value).Value();
-    DCHECK(variable_data);
-    return CSSUnparsedValue::FromCSSValue(*variable_data);
+    return CSSUnparsedValue::FromCSSValue(
+        ToCSSCustomPropertyDeclaration(value));
   }
 
   if (!CSSOMTypes::IsPropertySupported(property_id))
@@ -166,7 +164,7 @@
         CSSVariableData::Create(range, false /* is_animation_tainted */,
                                 false /* needs variable resolution */);
     CSSStyleValueVector values;
-    values.push_back(CSSUnparsedValue::FromCSSValue(*variable_data));
+    values.push_back(CSSUnparsedValue::FromCSSVariableData(*variable_data));
     return values;
   }
 
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserSelector.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserSelector.cpp
index de2e852..3f3390a 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSParserSelector.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSParserSelector.cpp
@@ -125,6 +125,8 @@
     case PseudoType::kPseudoPlaceholder:
     case PseudoType::kPseudoShadow:
       return RelationType::kShadowPseudo;
+    case PseudoType::kPseudoPart:
+      return RelationType::kShadowPart;
     default:
       return RelationType::kSubSelector;
   }
diff --git a/third_party/WebKit/Source/core/css/parser/CSSSelectorParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSSelectorParser.cpp
index dfb4aa1..ebe8b24 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSSelectorParser.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSSelectorParser.cpp
@@ -904,6 +904,9 @@
   // Likewise, ::slotted() pseudo element has an implicit ShadowSlot combinator
   // to its left for finding matching slot element in other TreeScope.
   //
+  // ::part has a implicit ShadowPart combinator to it's left finding the host
+  // element in the scope of the style rule.
+  //
   // Example:
   //
   // slot[name=foo]::slotted(div) -> [ ::slotted(div), slot, [name=foo] ]
diff --git a/third_party/WebKit/Source/core/css/resolver/ScopedStyleResolver.cpp b/third_party/WebKit/Source/core/css/resolver/ScopedStyleResolver.cpp
index 8df7231..a45051e 100644
--- a/third_party/WebKit/Source/core/css/resolver/ScopedStyleResolver.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/ScopedStyleResolver.cpp
@@ -266,6 +266,21 @@
   }
 }
 
+void ScopedStyleResolver::CollectMatchingPartPseudoRules(
+    ElementRuleCollector& collector,
+    CascadeOrder cascade_order) {
+  if (!RuntimeEnabledFeatures::CSSPartPseudoElementEnabled())
+    return;
+  size_t sheet_index = 0;
+  for (auto sheet : author_style_sheets_) {
+    if (!RuntimeEnabledFeatures::ConstructableStylesheetsEnabled())
+      DCHECK(sheet->ownerNode());
+    MatchRequest match_request(&sheet->Contents()->GetRuleSet(),
+                               &scope_->RootNode(), sheet, sheet_index++);
+    collector.CollectMatchingPartPseudoRules(match_request, cascade_order);
+  }
+}
+
 void ScopedStyleResolver::MatchPageRules(PageRuleCollector& collector) {
   // Only consider the global author RuleSet for @page rules, as per the HTML5
   // spec.
diff --git a/third_party/WebKit/Source/core/css/resolver/ScopedStyleResolver.h b/third_party/WebKit/Source/core/css/resolver/ScopedStyleResolver.h
index 3cd1f3b5..78a9f5c 100644
--- a/third_party/WebKit/Source/core/css/resolver/ScopedStyleResolver.h
+++ b/third_party/WebKit/Source/core/css/resolver/ScopedStyleResolver.h
@@ -70,6 +70,8 @@
   void CollectMatchingTreeBoundaryCrossingRules(
       ElementRuleCollector&,
       CascadeOrder = kIgnoreCascadeOrder);
+  void CollectMatchingPartPseudoRules(ElementRuleCollector&,
+                                      CascadeOrder = kIgnoreCascadeOrder);
   void MatchPageRules(PageRuleCollector&);
   void CollectFeaturesTo(RuleFeatureSet&,
                          HeapHashSet<Member<const StyleSheetContents>>&
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleAdjuster.cpp b/third_party/WebKit/Source/core/css/resolver/StyleAdjuster.cpp
index 26fba52..a0b96714 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleAdjuster.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/StyleAdjuster.cpp
@@ -667,22 +667,34 @@
     }
   }
 
-  if (RuntimeEnabledFeatures::LayoutNGEnabled() && !style.ForceLegacyLayout()) {
-    // Form controls are not supported yet.
-    if (element && element->ShouldForceLegacyLayout()) {
+  if (RuntimeEnabledFeatures::LayoutNGEnabled() && !style.ForceLegacyLayout() &&
+      element) {
+    const Document& document = element->GetDocument();
+    if (element->ShouldForceLegacyLayout()) {
+      // Form controls are not supported yet.
       style.SetForceLegacyLayout(true);
-    }
-
-    // TODO(layout-dev): Once LayoutNG handles inline content editable, we
-    // should get rid of following code fragment.
-    else if (style.UserModify() != EUserModify::kReadOnly ||
-             (element && element->GetDocument().InDesignMode())) {
+    } else if (style.UserModify() != EUserModify::kReadOnly ||
+               document.InDesignMode()) {
+      // TODO(layout-dev): Once LayoutNG handles inline content editable, we
+      // should get rid of following code fragment.
       style.SetForceLegacyLayout(true);
 
       if (style.Display() == EDisplay::kInline &&
           parent_style.UserModify() == EUserModify::kReadOnly) {
         style.SetDisplay(EDisplay::kInlineBlock);
       }
+    } else if (!RuntimeEnabledFeatures::LayoutNGBlockFragmentationEnabled()) {
+      // Disable NG for the entire subtree if we're establishing a block
+      // fragmentation context.
+      if (style.SpecifiesColumns() ||
+          (style.IsOverflowPaged() &&
+           element != document.ViewportDefiningElement())) {
+        style.SetForceLegacyLayout(true);
+      } else if (document.Paginated()) {
+        // This needs to be discovered on the root element.
+        DCHECK_EQ(element, document.documentElement());
+        style.SetForceLegacyLayout(true);
+      }
     }
   }
 
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp b/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
index 2130764..ea41e3a 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
@@ -242,6 +242,32 @@
   collector.FinishAddingAuthorRulesForTreeScope();
 }
 
+void StyleResolver::MatchPseudoPartRules(const Element& element,
+                                         ElementRuleCollector& collector) {
+  if (!RuntimeEnabledFeatures::CSSPartPseudoElementEnabled())
+    return;
+
+  if (!element.HasPartName())
+    return;
+
+  TreeScope& tree_scope = element.GetTreeScope();
+  if (tree_scope == GetDocument().GetTreeScope())
+    return;
+
+  TreeScope* parent_tree_scope = &tree_scope;
+  // TODO(b/805271): We can terminate early if we pass through a host with no
+  // exported parts. Requires implementing partmap.
+  while ((parent_tree_scope = parent_tree_scope->ParentTreeScope())) {
+    if (ScopedStyleResolver* resolver =
+            parent_tree_scope->GetScopedStyleResolver()) {
+      collector.ClearMatchedRules();
+      resolver->CollectMatchingPartPseudoRules(collector);
+      collector.SortAndTransferMatchedRules();
+      collector.FinishAddingAuthorRulesForTreeScope();
+    }
+  }
+}
+
 static bool ShouldCheckScope(const Element& element,
                              const Node& scoping_node,
                              bool is_inner_tree_scope) {
@@ -286,6 +312,7 @@
   if (!GetDocument().MayContainV0Shadow()) {
     MatchSlottedRules(element, collector);
     MatchElementScopeRules(element, element_scope_resolver, collector);
+    MatchPseudoPartRules(element, collector);
     return;
   }
 
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleResolver.h b/third_party/WebKit/Source/core/css/resolver/StyleResolver.h
index ce278ca..f35a30d1 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleResolver.h
+++ b/third_party/WebKit/Source/core/css/resolver/StyleResolver.h
@@ -165,6 +165,7 @@
   void MatchRuleSet(ElementRuleCollector&, RuleSet*);
   void MatchUARules(ElementRuleCollector&);
   void MatchUserRules(ElementRuleCollector&);
+  void MatchPseudoPartRules(const Element&, ElementRuleCollector&);
   void MatchScopedRules(const Element&, ElementRuleCollector&);
   void MatchAuthorRules(const Element&, ElementRuleCollector&);
   void MatchAuthorRulesV0(const Element&, ElementRuleCollector&);
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp
index e599c01..00b6940 100644
--- a/third_party/WebKit/Source/core/dom/Document.cpp
+++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -232,7 +232,6 @@
 #include "platform/InstanceCounters.h"
 #include "platform/Language.h"
 #include "platform/LengthFunctions.h"
-#include "platform/WebFrameScheduler.h"
 #include "platform/bindings/DOMDataStore.h"
 #include "platform/bindings/Microtask.h"
 #include "platform/bindings/ScriptForbiddenScope.h"
@@ -2340,11 +2339,8 @@
   ScriptForbiddenScope forbid_script;
 
   LocalFrameView* frame_view = View();
-  if (frame_view && frame_view->IsInPerformLayout()) {
-    // View layout should not be re-entrant.
-    NOTREACHED();
-    return;
-  }
+  DCHECK(!frame_view || !frame_view->IsInPerformLayout())
+      << "View layout should not be re-entrant";
 
   if (HTMLFrameOwnerElement* owner = LocalOwner())
     owner->GetDocument().UpdateStyleAndLayout();
@@ -2354,17 +2350,17 @@
   if (!IsActive())
     return;
 
-  if (frame_view->NeedsLayout())
+  if (frame_view && frame_view->NeedsLayout())
     frame_view->UpdateLayout();
 
-  if (goto_anchor_needed_after_stylesheets_load_)
+  if (frame_view && goto_anchor_needed_after_stylesheets_load_)
     frame_view->ProcessUrlFragment(url_);
 
   if (Lifecycle().GetState() < DocumentLifecycle::kLayoutClean)
     Lifecycle().AdvanceTo(DocumentLifecycle::kLayoutClean);
 
-  if (LocalFrameView* frame_view = View())
-    frame_view->PerformScrollAnchoringAdjustments();
+  if (LocalFrameView* frame_view_anchored = View())
+    frame_view_anchored->PerformScrollAnchoringAdjustments();
 }
 
 void Document::LayoutUpdated() {
diff --git a/third_party/WebKit/Source/core/dom/Element.cpp b/third_party/WebKit/Source/core/dom/Element.cpp
index 69ab855..e0d8f4b2 100644
--- a/third_party/WebKit/Source/core/dom/Element.cpp
+++ b/third_party/WebKit/Source/core/dom/Element.cpp
@@ -3664,14 +3664,18 @@
   if (style.Display() == EDisplay::kContents && !NeedsReattachLayoutTree())
     DCHECK(!GetLayoutObject() || IsPseudoElement());
 #endif
+  if (style.Display() == EDisplay::kNone)
+    return false;
   if (IsSVGElement()) {
     Element* parent_element = LayoutTreeBuilderTraversal::ParentElement(*this);
     if (parent_element && !parent_element->IsSVGElement())
       return false;
+    if (IsSVGStopElement(*this))
+      return true;
   }
-  return style.Display() == EDisplay::kContents ||
-         IsHTMLOptGroupElement(*this) || IsHTMLOptionElement(*this) ||
-         IsSVGStopElement(*this);
+  if (style.Display() == EDisplay::kContents)
+    return true;
+  return IsHTMLOptGroupElement(*this) || IsHTMLOptionElement(*this);
 }
 
 void Element::StoreNonLayoutObjectComputedStyle(
diff --git a/third_party/WebKit/Source/core/dom/ElementTest.cpp b/third_party/WebKit/Source/core/dom/ElementTest.cpp
index 9cb1be94..efcc11b9 100644
--- a/third_party/WebKit/Source/core/dom/ElementTest.cpp
+++ b/third_party/WebKit/Source/core/dom/ElementTest.cpp
@@ -6,6 +6,7 @@
 
 #include <memory>
 #include "core/dom/Document.h"
+#include "core/dom/NodeComputedStyle.h"
 #include "core/editing/testing/EditingTestBase.h"
 #include "core/frame/LocalFrameView.h"
 #include "core/geometry/DOMRect.h"
@@ -390,4 +391,21 @@
   }
 }
 
+TEST_F(ElementTest, OptionElementDisplayNoneComputedStyle) {
+  Document& document = GetDocument();
+  SetBodyContent(R"HTML(
+    <optgroup id=group style='display:none'></optgroup>
+    <option id=option style='display:none'></option>
+    <div style='display:none'>
+      <optgroup id=inner-group></optgroup>
+      <option id=inner-option></option>
+    </div>
+  )HTML");
+
+  EXPECT_FALSE(document.getElementById("group")->GetComputedStyle());
+  EXPECT_FALSE(document.getElementById("option")->GetComputedStyle());
+  EXPECT_FALSE(document.getElementById("inner-group")->GetComputedStyle());
+  EXPECT_FALSE(document.getElementById("inner-option")->GetComputedStyle());
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/BUILD.gn b/third_party/WebKit/Source/core/editing/BUILD.gn
index 157b63d..0a3005a 100644
--- a/third_party/WebKit/Source/core/editing/BUILD.gn
+++ b/third_party/WebKit/Source/core/editing/BUILD.gn
@@ -129,6 +129,7 @@
     "commands/FormatBlockCommand.h",
     "commands/IndentOutdentCommand.cpp",
     "commands/IndentOutdentCommand.h",
+    "commands/InsertCommands.h",
     "commands/InsertIncrementalTextCommand.cpp",
     "commands/InsertIncrementalTextCommand.h",
     "commands/InsertIntoTextNodeCommand.cpp",
diff --git a/third_party/WebKit/Source/core/editing/SelectionModifierCharacter.cpp b/third_party/WebKit/Source/core/editing/SelectionModifierCharacter.cpp
index a2d3a81..3d16e0a 100644
--- a/third_party/WebKit/Source/core/editing/SelectionModifierCharacter.cpp
+++ b/third_party/WebKit/Source/core/editing/SelectionModifierCharacter.cpp
@@ -116,9 +116,12 @@
       TextDirection direction,
       const VisiblePositionTemplate<Strategy>& visible_position,
       const PositionTemplate<Strategy>& anchor) {
-    if (direction == TextDirection::kLtr)
-      return HonorEditingBoundaryAtOrBefore(visible_position, anchor);
-    return HonorEditingBoundaryAtOrAfter(visible_position, anchor);
+    if (direction == TextDirection::kLtr) {
+      return AdjustBackwardPositionToAvoidCrossingEditingBoundaries(
+          visible_position, anchor);
+    }
+    return AdjustForwardPositionToAvoidCrossingEditingBoundaries(
+        visible_position, anchor);
   }
 
   static Node* LogicalStartBoxOf(TextDirection direction,
@@ -208,9 +211,12 @@
       TextDirection direction,
       const VisiblePositionTemplate<Strategy>& visible_position,
       const PositionTemplate<Strategy>& anchor) {
-    if (direction == TextDirection::kLtr)
-      return HonorEditingBoundaryAtOrAfter(visible_position, anchor);
-    return HonorEditingBoundaryAtOrBefore(visible_position, anchor);
+    if (direction == TextDirection::kLtr) {
+      return AdjustForwardPositionToAvoidCrossingEditingBoundaries(
+          visible_position, anchor);
+    }
+    return AdjustBackwardPositionToAvoidCrossingEditingBoundaries(
+        visible_position, anchor);
   }
 
   static Node* LogicalStartBoxOf(TextDirection direction,
diff --git a/third_party/WebKit/Source/core/editing/SelectionModifierWord.cpp b/third_party/WebKit/Source/core/editing/SelectionModifierWord.cpp
index ca962c2..3ac788a9 100644
--- a/third_party/WebKit/Source/core/editing/SelectionModifierWord.cpp
+++ b/third_party/WebKit/Source/core/editing/SelectionModifierWord.cpp
@@ -387,8 +387,8 @@
     }
 
     if (is_word_break) {
-      return HonorEditingBoundaryAtOrBefore(adjacent_character_position,
-                                            visible_position.DeepEquivalent());
+      return AdjustBackwardPositionToAvoidCrossingEditingBoundaries(
+          adjacent_character_position, visible_position.DeepEquivalent());
     }
 
     current = adjacent_character_position;
diff --git a/third_party/WebKit/Source/core/editing/VisibleUnits.cpp b/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
index dee81e7..3531dd3 100644
--- a/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
+++ b/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
@@ -60,6 +60,7 @@
 #include "core/layout/api/LineLayoutItem.h"
 #include "core/layout/line/InlineIterator.h"
 #include "core/layout/line/InlineTextBox.h"
+#include "core/svg_element_type_helpers.h"
 #include "platform/heap/Handle.h"
 #include "platform/text/TextBoundaries.h"
 
@@ -165,7 +166,7 @@
 
 template <typename Strategy>
 static PositionWithAffinityTemplate<Strategy>
-HonorEditingBoundaryAtOrBeforeTemplate(
+AdjustBackwardPositionToAvoidCrossingEditingBoundariesTemplate(
     const PositionWithAffinityTemplate<Strategy>& pos,
     const PositionTemplate<Strategy>& anchor) {
   if (pos.IsNull())
@@ -199,42 +200,50 @@
                                                *highest_root));
 }
 
-PositionWithAffinity HonorEditingBoundaryAtOrBefore(
+PositionWithAffinity AdjustBackwardPositionToAvoidCrossingEditingBoundaries(
     const PositionWithAffinity& pos,
     const Position& anchor) {
-  return HonorEditingBoundaryAtOrBeforeTemplate(pos, anchor);
+  return AdjustBackwardPositionToAvoidCrossingEditingBoundariesTemplate(pos,
+                                                                        anchor);
 }
 
-PositionInFlatTreeWithAffinity HonorEditingBoundaryAtOrBefore(
+PositionInFlatTreeWithAffinity
+AdjustBackwardPositionToAvoidCrossingEditingBoundaries(
     const PositionInFlatTreeWithAffinity& pos,
     const PositionInFlatTree& anchor) {
-  return HonorEditingBoundaryAtOrBeforeTemplate(pos, anchor);
+  return AdjustBackwardPositionToAvoidCrossingEditingBoundariesTemplate(pos,
+                                                                        anchor);
 }
 
 template <typename Strategy>
-VisiblePositionTemplate<Strategy> HonorEditingBoundaryAtOrBeforeAlgorithm(
+VisiblePositionTemplate<Strategy>
+AdjustBackwardPositionToAvoidCrossingEditingBoundariesAlgorithm(
     const VisiblePositionTemplate<Strategy>& pos,
     const PositionTemplate<Strategy>& anchor) {
   DCHECK(pos.IsValid()) << pos;
   return CreateVisiblePosition(
-      HonorEditingBoundaryAtOrBefore(pos.ToPositionWithAffinity(), anchor));
+      AdjustBackwardPositionToAvoidCrossingEditingBoundaries(
+          pos.ToPositionWithAffinity(), anchor));
 }
 
-VisiblePosition HonorEditingBoundaryAtOrBefore(
+VisiblePosition AdjustBackwardPositionToAvoidCrossingEditingBoundaries(
     const VisiblePosition& visiblePosition,
     const Position& anchor) {
-  return HonorEditingBoundaryAtOrBeforeAlgorithm(visiblePosition, anchor);
+  return AdjustBackwardPositionToAvoidCrossingEditingBoundariesAlgorithm(
+      visiblePosition, anchor);
 }
 
-VisiblePositionInFlatTree HonorEditingBoundaryAtOrBefore(
+VisiblePositionInFlatTree
+AdjustBackwardPositionToAvoidCrossingEditingBoundaries(
     const VisiblePositionInFlatTree& visiblePosition,
     const PositionInFlatTree& anchor) {
-  return HonorEditingBoundaryAtOrBeforeAlgorithm(visiblePosition, anchor);
+  return AdjustBackwardPositionToAvoidCrossingEditingBoundariesAlgorithm(
+      visiblePosition, anchor);
 }
 
 template <typename Strategy>
 static PositionWithAffinityTemplate<Strategy>
-HonorEditingBoundaryAtOrAfterTemplate(
+AdjustForwardPositionToAvoidCrossingEditingBoundariesTemplate(
     const PositionWithAffinityTemplate<Strategy>& pos,
     const PositionTemplate<Strategy>& anchor) {
   if (pos.IsNull())
@@ -275,32 +284,37 @@
                                                *highest_root));
 }
 
-PositionWithAffinity HonorEditingBoundaryAtOrAfter(
+PositionWithAffinity AdjustForwardPositionToAvoidCrossingEditingBoundaries(
     const PositionWithAffinity& pos,
     const Position& anchor) {
-  return HonorEditingBoundaryAtOrAfterTemplate(pos, anchor);
+  return AdjustForwardPositionToAvoidCrossingEditingBoundariesTemplate(pos,
+                                                                       anchor);
 }
 
-PositionInFlatTreeWithAffinity HonorEditingBoundaryAtOrAfter(
+PositionInFlatTreeWithAffinity
+AdjustForwardPositionToAvoidCrossingEditingBoundaries(
     const PositionInFlatTreeWithAffinity& pos,
     const PositionInFlatTree& anchor) {
-  return HonorEditingBoundaryAtOrAfterTemplate(
+  return AdjustForwardPositionToAvoidCrossingEditingBoundariesTemplate(
       PositionInFlatTreeWithAffinity(pos), anchor);
 }
 
-VisiblePosition HonorEditingBoundaryAtOrAfter(const VisiblePosition& pos,
-                                              const Position& anchor) {
+VisiblePosition AdjustForwardPositionToAvoidCrossingEditingBoundaries(
+    const VisiblePosition& pos,
+    const Position& anchor) {
   DCHECK(pos.IsValid()) << pos;
   return CreateVisiblePosition(
-      HonorEditingBoundaryAtOrAfter(pos.ToPositionWithAffinity(), anchor));
+      AdjustForwardPositionToAvoidCrossingEditingBoundaries(
+          pos.ToPositionWithAffinity(), anchor));
 }
 
-VisiblePositionInFlatTree HonorEditingBoundaryAtOrAfter(
+VisiblePositionInFlatTree AdjustForwardPositionToAvoidCrossingEditingBoundaries(
     const VisiblePositionInFlatTree& pos,
     const PositionInFlatTree& anchor) {
   DCHECK(pos.IsValid()) << pos;
   return CreateVisiblePosition(
-      HonorEditingBoundaryAtOrAfter(pos.ToPositionWithAffinity(), anchor));
+      AdjustForwardPositionToAvoidCrossingEditingBoundaries(
+          pos.ToPositionWithAffinity(), anchor));
 }
 
 template <typename Strategy>
@@ -880,6 +894,10 @@
       last_node = current_node;
     }
 
+    // There is no caret position in non-text svg elements.
+    if (current_node->IsSVGElement() && !IsSVGTextElement(current_node))
+      continue;
+
     // If we've moved to a position that is visually distinct, return the last
     // saved position. There is code below that terminates early if we're
     // *about* to move to a visually distinct position.
@@ -1003,6 +1021,10 @@
     if (IsHTMLBodyElement(*current_node) && current_pos.AtEndOfNode())
       break;
 
+    // There is no caret position in non-text svg elements.
+    if (current_node->IsSVGElement() && !IsSVGTextElement(current_node))
+      continue;
+
     // Do not move to a visually distinct position.
     if (EndsOfNodeAreVisuallyDistinctPositions(current_node) &&
         current_node != boundary)
@@ -1320,12 +1342,14 @@
     case kCanCrossEditingBoundary:
       return next;
     case kCannotCrossEditingBoundary:
-      return HonorEditingBoundaryAtOrAfter(next, position.GetPosition());
+      return AdjustForwardPositionToAvoidCrossingEditingBoundaries(
+          next, position.GetPosition());
     case kCanSkipOverEditingBoundary:
       return SkipToEndOfEditingBoundary(next, position.GetPosition());
   }
   NOTREACHED();
-  return HonorEditingBoundaryAtOrAfter(next, position.GetPosition());
+  return AdjustForwardPositionToAvoidCrossingEditingBoundaries(
+      next, position.GetPosition());
 }
 
 VisiblePosition NextPositionOf(const VisiblePosition& visible_position,
@@ -1398,13 +1422,14 @@
     case kCanCrossEditingBoundary:
       return prev;
     case kCannotCrossEditingBoundary:
-      return HonorEditingBoundaryAtOrBefore(prev, position);
+      return AdjustBackwardPositionToAvoidCrossingEditingBoundaries(prev,
+                                                                    position);
     case kCanSkipOverEditingBoundary:
       return SkipToStartOfEditingBoundary(prev, position);
   }
 
   NOTREACHED();
-  return HonorEditingBoundaryAtOrBefore(prev, position);
+  return AdjustBackwardPositionToAvoidCrossingEditingBoundaries(prev, position);
 }
 
 VisiblePosition PreviousPositionOf(const VisiblePosition& visible_position,
diff --git a/third_party/WebKit/Source/core/editing/VisibleUnits.h b/third_party/WebKit/Source/core/editing/VisibleUnits.h
index fb95449..a1004e2d 100644
--- a/third_party/WebKit/Source/core/editing/VisibleUnits.h
+++ b/third_party/WebKit/Source/core/editing/VisibleUnits.h
@@ -305,31 +305,39 @@
                                     BoundarySearchFunction);
 
 CORE_EXPORT PositionWithAffinity
-HonorEditingBoundaryAtOrAfter(const PositionWithAffinity&, const Position&);
+AdjustForwardPositionToAvoidCrossingEditingBoundaries(
+    const PositionWithAffinity&,
+    const Position&);
 
-PositionInFlatTreeWithAffinity HonorEditingBoundaryAtOrAfter(
+PositionInFlatTreeWithAffinity
+AdjustForwardPositionToAvoidCrossingEditingBoundaries(
     const PositionInFlatTreeWithAffinity&,
     const PositionInFlatTree&);
 
-PositionWithAffinity HonorEditingBoundaryAtOrBefore(const PositionWithAffinity&,
-                                                    const Position&);
+PositionWithAffinity AdjustBackwardPositionToAvoidCrossingEditingBoundaries(
+    const PositionWithAffinity&,
+    const Position&);
 
-PositionInFlatTreeWithAffinity HonorEditingBoundaryAtOrBefore(
+PositionInFlatTreeWithAffinity
+AdjustBackwardPositionToAvoidCrossingEditingBoundaries(
     const PositionInFlatTreeWithAffinity&,
     const PositionInFlatTree&);
 
-VisiblePosition HonorEditingBoundaryAtOrAfter(const VisiblePosition&,
-                                              const Position&);
+VisiblePosition AdjustForwardPositionToAvoidCrossingEditingBoundaries(
+    const VisiblePosition&,
+    const Position&);
 
-VisiblePositionInFlatTree HonorEditingBoundaryAtOrAfter(
+VisiblePositionInFlatTree AdjustForwardPositionToAvoidCrossingEditingBoundaries(
     const VisiblePositionInFlatTree&,
     const PositionInFlatTree&);
 
 // Export below functions only for |SelectionModifier|.
-VisiblePosition HonorEditingBoundaryAtOrBefore(const VisiblePosition&,
-                                               const Position&);
+VisiblePosition AdjustBackwardPositionToAvoidCrossingEditingBoundaries(
+    const VisiblePosition&,
+    const Position&);
 
-VisiblePositionInFlatTree HonorEditingBoundaryAtOrBefore(
+VisiblePositionInFlatTree
+AdjustBackwardPositionToAvoidCrossingEditingBoundaries(
     const VisiblePositionInFlatTree&,
     const PositionInFlatTree&);
 
diff --git a/third_party/WebKit/Source/core/editing/VisibleUnitsLine.cpp b/third_party/WebKit/Source/core/editing/VisibleUnitsLine.cpp
index aec4a62..6199748 100644
--- a/third_party/WebKit/Source/core/editing/VisibleUnitsLine.cpp
+++ b/third_party/WebKit/Source/core/editing/VisibleUnitsLine.cpp
@@ -259,7 +259,8 @@
   // Please refer to https://bugs.webkit.org/show_bug.cgi?id=49107 for detail.
   PositionWithAffinityTemplate<Strategy> vis_pos =
       StartPositionForLine<Strategy, VisualOrdering>(c);
-  return HonorEditingBoundaryAtOrBefore(vis_pos, c.GetPosition());
+  return AdjustBackwardPositionToAvoidCrossingEditingBoundaries(
+      vis_pos, c.GetPosition());
 }
 
 PositionWithAffinity StartOfLine(const PositionWithAffinity& current_position) {
@@ -393,7 +394,8 @@
     }
   }
 
-  return HonorEditingBoundaryAtOrBefore(vis_pos, c.GetPosition());
+  return AdjustBackwardPositionToAvoidCrossingEditingBoundaries(
+      vis_pos, c.GetPosition());
 }
 
 static PositionWithAffinity LogicalStartOfLine(
@@ -481,15 +483,15 @@
   // with "webkit-line-break:after-white-space" style versus lines without
   // that style, which would break before a space by default.
   if (InSameLine(current_position, candidate_position)) {
-    return HonorEditingBoundaryAtOrAfter(candidate_position,
-                                         current_position.GetPosition());
+    return AdjustForwardPositionToAvoidCrossingEditingBoundaries(
+        candidate_position, current_position.GetPosition());
   }
   const PositionWithAffinityTemplate<Strategy>& adjusted_position =
       PreviousPositionOf(CreateVisiblePosition(current_position))
           .ToPositionWithAffinity();
   if (adjusted_position.IsNull())
     return PositionWithAffinityTemplate<Strategy>();
-  return HonorEditingBoundaryAtOrAfter(
+  return AdjustForwardPositionToAvoidCrossingEditingBoundaries(
       EndPositionForLine<Strategy, VisualOrdering>(adjusted_position),
       current_position.GetPosition());
 }
@@ -556,7 +558,8 @@
     }
   }
 
-  return HonorEditingBoundaryAtOrAfter(vis_pos, current_position.GetPosition());
+  return AdjustForwardPositionToAvoidCrossingEditingBoundaries(
+      vis_pos, current_position.GetPosition());
 }
 
 static PositionWithAffinity LogicalEndOfLine(
diff --git a/third_party/WebKit/Source/core/editing/VisibleUnitsSentence.cpp b/third_party/WebKit/Source/core/editing/VisibleUnitsSentence.cpp
index 953b14e0..3b40175c 100644
--- a/third_party/WebKit/Source/core/editing/VisibleUnitsSentence.cpp
+++ b/third_party/WebKit/Source/core/editing/VisibleUnitsSentence.cpp
@@ -145,14 +145,16 @@
   VisiblePosition next =
       CreateVisiblePosition(NextBoundary(c, NextSentencePositionBoundary),
                             TextAffinity::kUpstreamIfPossible);
-  return HonorEditingBoundaryAtOrAfter(next, c.DeepEquivalent());
+  return AdjustForwardPositionToAvoidCrossingEditingBoundaries(
+      next, c.DeepEquivalent());
 }
 
 VisiblePosition PreviousSentencePosition(const VisiblePosition& c) {
   DCHECK(c.IsValid()) << c;
   VisiblePosition prev = CreateVisiblePosition(
       PreviousBoundary(c, PreviousSentencePositionBoundary));
-  return HonorEditingBoundaryAtOrBefore(prev, c.DeepEquivalent());
+  return AdjustBackwardPositionToAvoidCrossingEditingBoundaries(
+      prev, c.DeepEquivalent());
 }
 
 VisiblePosition StartOfSentence(const VisiblePosition& c) {
diff --git a/third_party/WebKit/Source/core/editing/VisibleUnitsTest.cpp b/third_party/WebKit/Source/core/editing/VisibleUnitsTest.cpp
index 74f2f89..816643d 100644
--- a/third_party/WebKit/Source/core/editing/VisibleUnitsTest.cpp
+++ b/third_party/WebKit/Source/core/editing/VisibleUnitsTest.cpp
@@ -223,15 +223,17 @@
           .DeepEquivalent());
 }
 
-TEST_F(VisibleUnitsTest, HonorEditingBoundaryAtOrAfterNestedEditable) {
+TEST_F(VisibleUnitsTest,
+       AdjustForwardPositionToAvoidCrossingEditingBoundariesNestedEditable) {
   const SelectionInDOMTree& selection = SetSelectionTextToBody(
       "<div contenteditable>"
       "abc"
       "<span contenteditable=\"false\">A^BC</span>"
       "d|ef"
       "</div>");
-  const PositionWithAffinity& result = HonorEditingBoundaryAtOrAfter(
-      PositionWithAffinity(selection.Extent()), selection.Base());
+  const PositionWithAffinity& result =
+      AdjustForwardPositionToAvoidCrossingEditingBoundaries(
+          PositionWithAffinity(selection.Extent()), selection.Base());
   ASSERT_TRUE(result.IsNotNull());
   EXPECT_EQ(
       "<div contenteditable>"
diff --git a/third_party/WebKit/Source/core/editing/VisibleUnitsWord.cpp b/third_party/WebKit/Source/core/editing/VisibleUnitsWord.cpp
index 393b6bd..cd597380 100644
--- a/third_party/WebKit/Source/core/editing/VisibleUnitsWord.cpp
+++ b/third_party/WebKit/Source/core/editing/VisibleUnitsWord.cpp
@@ -172,14 +172,16 @@
   VisiblePosition next =
       CreateVisiblePosition(NextBoundary(c, NextWordPositionBoundary),
                             TextAffinity::kUpstreamIfPossible);
-  return HonorEditingBoundaryAtOrAfter(next, c.DeepEquivalent());
+  return AdjustForwardPositionToAvoidCrossingEditingBoundaries(
+      next, c.DeepEquivalent());
 }
 
 VisiblePosition PreviousWordPosition(const VisiblePosition& c) {
   DCHECK(c.IsValid()) << c;
   VisiblePosition prev =
       CreateVisiblePosition(PreviousBoundary(c, PreviousWordPositionBoundary));
-  return HonorEditingBoundaryAtOrBefore(prev, c.DeepEquivalent());
+  return AdjustBackwardPositionToAvoidCrossingEditingBoundaries(
+      prev, c.DeepEquivalent());
 }
 
 Position StartOfWordPosition(const VisiblePosition& position, EWordSide side) {
diff --git a/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp b/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
index f48d492..d576b74a 100644
--- a/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
@@ -54,6 +54,7 @@
 #include "core/editing/commands/EditorCommandNames.h"
 #include "core/editing/commands/FormatBlockCommand.h"
 #include "core/editing/commands/IndentOutdentCommand.h"
+#include "core/editing/commands/InsertCommands.h"
 #include "core/editing/commands/InsertListCommand.h"
 #include "core/editing/commands/RemoveFormatCommand.h"
 #include "core/editing/commands/ReplaceSelectionCommand.h"
@@ -261,7 +262,7 @@
 // Related to Editor::selectionForCommand.
 // Certain operations continue to use the target control's selection even if the
 // event handler already moved the selection outside of the text control.
-static LocalFrame* TargetFrame(LocalFrame& frame, Event* event) {
+LocalFrame* InsertCommands::TargetFrame(LocalFrame& frame, Event* event) {
   if (!event)
     return &frame;
   Node* node = event->target()->ToNode();
@@ -444,8 +445,8 @@
   return false;
 }
 
-static bool ExecuteInsertFragment(LocalFrame& frame,
-                                  DocumentFragment* fragment) {
+bool InsertCommands::ExecuteInsertFragment(LocalFrame& frame,
+                                           DocumentFragment* fragment) {
   DCHECK(frame.GetDocument());
   return ReplaceSelectionCommand::Create(
              *frame.GetDocument(), fragment,
@@ -454,7 +455,8 @@
       ->Apply();
 }
 
-static bool ExecuteInsertElement(LocalFrame& frame, HTMLElement* content) {
+bool InsertCommands::ExecuteInsertElement(LocalFrame& frame,
+                                          HTMLElement* content) {
   DCHECK(frame.GetDocument());
   DocumentFragment* fragment = DocumentFragment::Create(*frame.GetDocument());
   DummyExceptionStateForTesting exception_state;
@@ -464,8 +466,8 @@
   return ExecuteInsertFragment(frame, fragment);
 }
 
-static bool ExpandSelectionToGranularity(LocalFrame& frame,
-                                         TextGranularity granularity) {
+bool ExpandSelectionToGranularity(LocalFrame& frame,
+                                  TextGranularity granularity) {
   const VisibleSelection& selection = CreateVisibleSelectionWithGranularity(
       SelectionInDOMTree::Builder()
           .SetBaseAndExtent(
@@ -1087,19 +1089,19 @@
       ->Apply();
 }
 
-static bool ExecuteInsertBacktab(LocalFrame& frame,
-                                 Event* event,
-                                 EditorCommandSource,
-                                 const String&) {
+bool InsertCommands::ExecuteInsertBacktab(LocalFrame& frame,
+                                          Event* event,
+                                          EditorCommandSource,
+                                          const String&) {
   return TargetFrame(frame, event)
       ->GetEventHandler()
       .HandleTextInputEvent("\t", event);
 }
 
-static bool ExecuteInsertHorizontalRule(LocalFrame& frame,
-                                        Event*,
-                                        EditorCommandSource,
-                                        const String& value) {
+bool InsertCommands::ExecuteInsertHorizontalRule(LocalFrame& frame,
+                                                 Event*,
+                                                 EditorCommandSource,
+                                                 const String& value) {
   DCHECK(frame.GetDocument());
   HTMLHRElement* rule = HTMLHRElement::Create(*frame.GetDocument());
   if (!value.IsEmpty())
@@ -1107,19 +1109,19 @@
   return ExecuteInsertElement(frame, rule);
 }
 
-static bool ExecuteInsertHTML(LocalFrame& frame,
-                              Event*,
-                              EditorCommandSource,
-                              const String& value) {
+bool InsertCommands::ExecuteInsertHTML(LocalFrame& frame,
+                                       Event*,
+                                       EditorCommandSource,
+                                       const String& value) {
   DCHECK(frame.GetDocument());
   return ExecuteInsertFragment(
       frame, CreateFragmentFromMarkup(*frame.GetDocument(), value, ""));
 }
 
-static bool ExecuteInsertImage(LocalFrame& frame,
-                               Event*,
-                               EditorCommandSource,
-                               const String& value) {
+bool InsertCommands::ExecuteInsertImage(LocalFrame& frame,
+                                        Event*,
+                                        EditorCommandSource,
+                                        const String& value) {
   DCHECK(frame.GetDocument());
   HTMLImageElement* image = HTMLImageElement::Create(*frame.GetDocument());
   if (!value.IsEmpty())
@@ -1127,10 +1129,10 @@
   return ExecuteInsertElement(frame, image);
 }
 
-static bool ExecuteInsertLineBreak(LocalFrame& frame,
-                                   Event* event,
-                                   EditorCommandSource source,
-                                   const String&) {
+bool InsertCommands::ExecuteInsertLineBreak(LocalFrame& frame,
+                                            Event* event,
+                                            EditorCommandSource source,
+                                            const String&) {
   switch (source) {
     case EditorCommandSource::kMenuOrKeyBinding:
       return TargetFrame(frame, event)
@@ -1148,66 +1150,66 @@
   return false;
 }
 
-static bool ExecuteInsertNewline(LocalFrame& frame,
-                                 Event* event,
-                                 EditorCommandSource,
-                                 const String&) {
-  LocalFrame* target_frame = blink::TargetFrame(frame, event);
+bool InsertCommands::ExecuteInsertNewline(LocalFrame& frame,
+                                          Event* event,
+                                          EditorCommandSource,
+                                          const String&) {
+  LocalFrame* target_frame = TargetFrame(frame, event);
   return target_frame->GetEventHandler().HandleTextInputEvent(
       "\n", event,
       target_frame->GetEditor().CanEditRichly() ? kTextEventInputKeyboard
                                                 : kTextEventInputLineBreak);
 }
 
-static bool ExecuteInsertNewlineInQuotedContent(LocalFrame& frame,
-                                                Event*,
-                                                EditorCommandSource,
-                                                const String&) {
+bool InsertCommands::ExecuteInsertNewlineInQuotedContent(LocalFrame& frame,
+                                                         Event*,
+                                                         EditorCommandSource,
+                                                         const String&) {
   DCHECK(frame.GetDocument());
   return TypingCommand::InsertParagraphSeparatorInQuotedContent(
       *frame.GetDocument());
 }
 
-static bool ExecuteInsertOrderedList(LocalFrame& frame,
-                                     Event*,
-                                     EditorCommandSource,
-                                     const String&) {
+bool InsertCommands::ExecuteInsertOrderedList(LocalFrame& frame,
+                                              Event*,
+                                              EditorCommandSource,
+                                              const String&) {
   DCHECK(frame.GetDocument());
   return InsertListCommand::Create(*frame.GetDocument(),
                                    InsertListCommand::kOrderedList)
       ->Apply();
 }
 
-static bool ExecuteInsertParagraph(LocalFrame& frame,
-                                   Event*,
-                                   EditorCommandSource,
-                                   const String&) {
+bool InsertCommands::ExecuteInsertParagraph(LocalFrame& frame,
+                                            Event*,
+                                            EditorCommandSource,
+                                            const String&) {
   DCHECK(frame.GetDocument());
   return TypingCommand::InsertParagraphSeparator(*frame.GetDocument());
 }
 
-static bool ExecuteInsertTab(LocalFrame& frame,
-                             Event* event,
-                             EditorCommandSource,
-                             const String&) {
+bool InsertCommands::ExecuteInsertTab(LocalFrame& frame,
+                                      Event* event,
+                                      EditorCommandSource,
+                                      const String&) {
   return TargetFrame(frame, event)
       ->GetEventHandler()
       .HandleTextInputEvent("\t", event);
 }
 
-static bool ExecuteInsertText(LocalFrame& frame,
-                              Event*,
-                              EditorCommandSource,
-                              const String& value) {
+bool InsertCommands::ExecuteInsertText(LocalFrame& frame,
+                                       Event*,
+                                       EditorCommandSource,
+                                       const String& value) {
   DCHECK(frame.GetDocument());
   TypingCommand::InsertText(*frame.GetDocument(), value, 0);
   return true;
 }
 
-static bool ExecuteInsertUnorderedList(LocalFrame& frame,
-                                       Event*,
-                                       EditorCommandSource,
-                                       const String&) {
+bool InsertCommands::ExecuteInsertUnorderedList(LocalFrame& frame,
+                                                Event*,
+                                                EditorCommandSource,
+                                                const String&) {
   DCHECK(frame.GetDocument());
   return InsertListCommand::Create(*frame.GetDocument(),
                                    InsertListCommand::kUnorderedList)
@@ -2646,44 +2648,50 @@
       {WebEditingCommandType::kIndent, ExecuteIndent, Supported,
        EnabledInRichlyEditableText, StateNone, ValueStateOrNull,
        kNotTextInsertion, CanNotExecuteWhenDisabled},
-      {WebEditingCommandType::kInsertBacktab, ExecuteInsertBacktab,
-       SupportedFromMenuOrKeyBinding, EnabledInEditableText, StateNone,
-       ValueStateOrNull, kIsTextInsertion, CanNotExecuteWhenDisabled},
-      {WebEditingCommandType::kInsertHTML, ExecuteInsertHTML, Supported,
-       EnabledInEditableText, StateNone, ValueStateOrNull, kNotTextInsertion,
-       CanNotExecuteWhenDisabled},
-      {WebEditingCommandType::kInsertHorizontalRule,
-       ExecuteInsertHorizontalRule, Supported, EnabledInRichlyEditableText,
-       StateNone, ValueStateOrNull, kNotTextInsertion,
-       CanNotExecuteWhenDisabled},
-      {WebEditingCommandType::kInsertImage, ExecuteInsertImage, Supported,
-       EnabledInRichlyEditableText, StateNone, ValueStateOrNull,
-       kNotTextInsertion, CanNotExecuteWhenDisabled},
-      {WebEditingCommandType::kInsertLineBreak, ExecuteInsertLineBreak,
-       Supported, EnabledInEditableText, StateNone, ValueStateOrNull,
-       kIsTextInsertion, CanNotExecuteWhenDisabled},
-      {WebEditingCommandType::kInsertNewline, ExecuteInsertNewline,
-       SupportedFromMenuOrKeyBinding, EnabledInEditableText, StateNone,
-       ValueStateOrNull, kIsTextInsertion, CanNotExecuteWhenDisabled},
-      {WebEditingCommandType::kInsertNewlineInQuotedContent,
-       ExecuteInsertNewlineInQuotedContent, Supported,
-       EnabledInRichlyEditableText, StateNone, ValueStateOrNull,
-       kNotTextInsertion, CanNotExecuteWhenDisabled},
-      {WebEditingCommandType::kInsertOrderedList, ExecuteInsertOrderedList,
-       Supported, EnabledInRichlyEditableText, StateOrderedList,
-       ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled},
-      {WebEditingCommandType::kInsertParagraph, ExecuteInsertParagraph,
-       Supported, EnabledInEditableText, StateNone, ValueStateOrNull,
-       kNotTextInsertion, CanNotExecuteWhenDisabled},
-      {WebEditingCommandType::kInsertTab, ExecuteInsertTab,
-       SupportedFromMenuOrKeyBinding, EnabledInEditableText, StateNone,
-       ValueStateOrNull, kIsTextInsertion, CanNotExecuteWhenDisabled},
-      {WebEditingCommandType::kInsertText, ExecuteInsertText, Supported,
+      {WebEditingCommandType::kInsertBacktab,
+       InsertCommands::ExecuteInsertBacktab, SupportedFromMenuOrKeyBinding,
        EnabledInEditableText, StateNone, ValueStateOrNull, kIsTextInsertion,
        CanNotExecuteWhenDisabled},
-      {WebEditingCommandType::kInsertUnorderedList, ExecuteInsertUnorderedList,
-       Supported, EnabledInRichlyEditableText, StateUnorderedList,
-       ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled},
+      {WebEditingCommandType::kInsertHTML, InsertCommands::ExecuteInsertHTML,
+       Supported, EnabledInEditableText, StateNone, ValueStateOrNull,
+       kNotTextInsertion, CanNotExecuteWhenDisabled},
+      {WebEditingCommandType::kInsertHorizontalRule,
+       InsertCommands::ExecuteInsertHorizontalRule, Supported,
+       EnabledInRichlyEditableText, StateNone, ValueStateOrNull,
+       kNotTextInsertion, CanNotExecuteWhenDisabled},
+      {WebEditingCommandType::kInsertImage, InsertCommands::ExecuteInsertImage,
+       Supported, EnabledInRichlyEditableText, StateNone, ValueStateOrNull,
+       kNotTextInsertion, CanNotExecuteWhenDisabled},
+      {WebEditingCommandType::kInsertLineBreak,
+       InsertCommands::ExecuteInsertLineBreak, Supported, EnabledInEditableText,
+       StateNone, ValueStateOrNull, kIsTextInsertion,
+       CanNotExecuteWhenDisabled},
+      {WebEditingCommandType::kInsertNewline,
+       InsertCommands::ExecuteInsertNewline, SupportedFromMenuOrKeyBinding,
+       EnabledInEditableText, StateNone, ValueStateOrNull, kIsTextInsertion,
+       CanNotExecuteWhenDisabled},
+      {WebEditingCommandType::kInsertNewlineInQuotedContent,
+       InsertCommands::ExecuteInsertNewlineInQuotedContent, Supported,
+       EnabledInRichlyEditableText, StateNone, ValueStateOrNull,
+       kNotTextInsertion, CanNotExecuteWhenDisabled},
+      {WebEditingCommandType::kInsertOrderedList,
+       InsertCommands::ExecuteInsertOrderedList, Supported,
+       EnabledInRichlyEditableText, StateOrderedList, ValueStateOrNull,
+       kNotTextInsertion, CanNotExecuteWhenDisabled},
+      {WebEditingCommandType::kInsertParagraph,
+       InsertCommands::ExecuteInsertParagraph, Supported, EnabledInEditableText,
+       StateNone, ValueStateOrNull, kNotTextInsertion,
+       CanNotExecuteWhenDisabled},
+      {WebEditingCommandType::kInsertTab, InsertCommands::ExecuteInsertTab,
+       SupportedFromMenuOrKeyBinding, EnabledInEditableText, StateNone,
+       ValueStateOrNull, kIsTextInsertion, CanNotExecuteWhenDisabled},
+      {WebEditingCommandType::kInsertText, InsertCommands::ExecuteInsertText,
+       Supported, EnabledInEditableText, StateNone, ValueStateOrNull,
+       kIsTextInsertion, CanNotExecuteWhenDisabled},
+      {WebEditingCommandType::kInsertUnorderedList,
+       InsertCommands::ExecuteInsertUnorderedList, Supported,
+       EnabledInRichlyEditableText, StateUnorderedList, ValueStateOrNull,
+       kNotTextInsertion, CanNotExecuteWhenDisabled},
       {WebEditingCommandType::kItalic, ExecuteToggleItalic, Supported,
        EnabledInRichlyEditableText, StateItalic, ValueStateOrNull,
        kNotTextInsertion, CanNotExecuteWhenDisabled},
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertCommands.h b/third_party/WebKit/Source/core/editing/commands/InsertCommands.h
new file mode 100644
index 0000000..e5047b7c
--- /dev/null
+++ b/third_party/WebKit/Source/core/editing/commands/InsertCommands.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2009 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Copyright 2018 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 InsertCommands_h
+#define InsertCommands_h
+
+#include "platform/wtf/Allocator.h"
+#include "platform/wtf/Forward.h"
+
+namespace blink {
+
+class DocumentFragment;
+class Event;
+class HTMLElement;
+class LocalFrame;
+
+enum class EditorCommandSource;
+
+// This class provides static functions about commands related to insert.
+class InsertCommands {
+  STATIC_ONLY(InsertCommands);
+
+ public:
+  // Returns |bool| value for Document#execCommand().
+  static bool ExecuteInsertBacktab(LocalFrame&,
+                                   Event*,
+                                   EditorCommandSource,
+                                   const String&);
+  static bool ExecuteInsertHorizontalRule(LocalFrame&,
+                                          Event*,
+                                          EditorCommandSource,
+                                          const String&);
+  static bool ExecuteInsertHTML(LocalFrame&,
+                                Event*,
+                                EditorCommandSource,
+                                const String&);
+  static bool ExecuteInsertImage(LocalFrame&,
+                                 Event*,
+                                 EditorCommandSource,
+                                 const String&);
+  static bool ExecuteInsertLineBreak(LocalFrame&,
+                                     Event*,
+                                     EditorCommandSource,
+                                     const String&);
+  static bool ExecuteInsertNewline(LocalFrame&,
+                                   Event*,
+                                   EditorCommandSource,
+                                   const String&);
+  static bool ExecuteInsertNewlineInQuotedContent(LocalFrame&,
+                                                  Event*,
+                                                  EditorCommandSource,
+                                                  const String&);
+  static bool ExecuteInsertOrderedList(LocalFrame&,
+                                       Event*,
+                                       EditorCommandSource,
+                                       const String&);
+  static bool ExecuteInsertParagraph(LocalFrame&,
+                                     Event*,
+                                     EditorCommandSource,
+                                     const String&);
+  static bool ExecuteInsertTab(LocalFrame&,
+                               Event*,
+                               EditorCommandSource,
+                               const String&);
+  static bool ExecuteInsertText(LocalFrame&,
+                                Event*,
+                                EditorCommandSource,
+                                const String&);
+  static bool ExecuteInsertUnorderedList(LocalFrame&,
+                                         Event*,
+                                         EditorCommandSource,
+                                         const String&);
+
+ private:
+  static bool ExecuteInsertFragment(LocalFrame&, DocumentFragment*);
+  static bool ExecuteInsertElement(LocalFrame&, HTMLElement*);
+
+  // Related to Editor::selectionForCommand.
+  // Certain operations continue to use the target control's selection even if
+  // the event handler already moved the selection outside of the text control.
+  static LocalFrame* TargetFrame(LocalFrame&, Event*);
+};
+
+}  // namespace blink
+
+#endif
diff --git a/third_party/WebKit/Source/core/editing/ime/InputMethodController.cpp b/third_party/WebKit/Source/core/editing/ime/InputMethodController.cpp
index 145f0113..41fd5f3 100644
--- a/third_party/WebKit/Source/core/editing/ime/InputMethodController.cpp
+++ b/third_party/WebKit/Source/core/editing/ime/InputMethodController.cpp
@@ -901,7 +901,7 @@
 
   if (ime_text_spans.IsEmpty()) {
     GetDocument().Markers().AddCompositionMarker(
-        CompositionEphemeralRange(), Color::kBlack,
+        CompositionEphemeralRange(), Color::kTransparent,
         ui::mojom::ImeTextSpanThickness::kThin,
         LayoutTheme::GetTheme().PlatformDefaultCompositionBackgroundColor());
     return;
diff --git a/third_party/WebKit/Source/core/editing/markers/ActiveSuggestionMarkerListImplTest.cpp b/third_party/WebKit/Source/core/editing/markers/ActiveSuggestionMarkerListImplTest.cpp
index c175ee3..a208fcb 100644
--- a/third_party/WebKit/Source/core/editing/markers/ActiveSuggestionMarkerListImplTest.cpp
+++ b/third_party/WebKit/Source/core/editing/markers/ActiveSuggestionMarkerListImplTest.cpp
@@ -15,9 +15,9 @@
       : marker_list_(new ActiveSuggestionMarkerListImpl()) {}
 
   DocumentMarker* CreateMarker(unsigned start_offset, unsigned end_offset) {
-    return new ActiveSuggestionMarker(start_offset, end_offset, Color::kBlack,
-                                      ui::mojom::ImeTextSpanThickness::kThin,
-                                      Color::kBlack);
+    return new ActiveSuggestionMarker(
+        start_offset, end_offset, Color::kTransparent,
+        ui::mojom::ImeTextSpanThickness::kThin, Color::kBlack);
   }
 
   Persistent<ActiveSuggestionMarkerListImpl> marker_list_;
diff --git a/third_party/WebKit/Source/core/editing/markers/CompositionMarkerListImplTest.cpp b/third_party/WebKit/Source/core/editing/markers/CompositionMarkerListImplTest.cpp
index ab82770..b337194 100644
--- a/third_party/WebKit/Source/core/editing/markers/CompositionMarkerListImplTest.cpp
+++ b/third_party/WebKit/Source/core/editing/markers/CompositionMarkerListImplTest.cpp
@@ -16,7 +16,7 @@
       : marker_list_(new CompositionMarkerListImpl()) {}
 
   DocumentMarker* CreateMarker(unsigned start_offset, unsigned end_offset) {
-    return new CompositionMarker(start_offset, end_offset, Color::kBlack,
+    return new CompositionMarker(start_offset, end_offset, Color::kTransparent,
                                  ui::mojom::ImeTextSpanThickness::kThin,
                                  Color::kBlack);
   }
diff --git a/third_party/WebKit/Source/core/editing/markers/DocumentMarkerControllerTest.cpp b/third_party/WebKit/Source/core/editing/markers/DocumentMarkerControllerTest.cpp
index b42aa75..8e81428 100644
--- a/third_party/WebKit/Source/core/editing/markers/DocumentMarkerControllerTest.cpp
+++ b/third_party/WebKit/Source/core/editing/markers/DocumentMarkerControllerTest.cpp
@@ -208,10 +208,10 @@
   SetBodyContent("<div style='margin: 100px'>foo</div>");
   Node* text = GetDocument().body()->firstChild()->firstChild();
   MarkerController().AddCompositionMarker(
-      EphemeralRange(Position(text, 0), Position(text, 1)), Color::kBlack,
+      EphemeralRange(Position(text, 0), Position(text, 1)), Color::kTransparent,
       ui::mojom::ImeTextSpanThickness::kThin, Color::kBlack);
   MarkerController().AddCompositionMarker(
-      EphemeralRange(Position(text, 1), Position(text, 3)), Color::kBlack,
+      EphemeralRange(Position(text, 1), Position(text, 3)), Color::kTransparent,
       ui::mojom::ImeTextSpanThickness::kThick, Color::kBlack);
 
   EXPECT_EQ(2u, MarkerController().Markers().size());
diff --git a/third_party/WebKit/Source/core/editing/markers/StyleableMarker.cpp b/third_party/WebKit/Source/core/editing/markers/StyleableMarker.cpp
index ed7cce3..c8a384fe 100644
--- a/third_party/WebKit/Source/core/editing/markers/StyleableMarker.cpp
+++ b/third_party/WebKit/Source/core/editing/markers/StyleableMarker.cpp
@@ -34,6 +34,11 @@
   return thickness_ == ImeTextSpanThickness::kThick;
 }
 
+bool StyleableMarker::UseTextColor() const {
+  return thickness_ != ImeTextSpanThickness::kNone &&
+         underline_color_ == Color::kTransparent;
+}
+
 Color StyleableMarker::BackgroundColor() const {
   return background_color_;
 }
diff --git a/third_party/WebKit/Source/core/editing/markers/StyleableMarker.h b/third_party/WebKit/Source/core/editing/markers/StyleableMarker.h
index e75373c..e915736 100644
--- a/third_party/WebKit/Source/core/editing/markers/StyleableMarker.h
+++ b/third_party/WebKit/Source/core/editing/markers/StyleableMarker.h
@@ -25,6 +25,7 @@
   bool HasThicknessNone() const;
   bool HasThicknessThin() const;
   bool HasThicknessThick() const;
+  bool UseTextColor() const;
   Color BackgroundColor() const;
 
  private:
diff --git a/third_party/WebKit/Source/core/editing/suggestion/TextSuggestionControllerTest.cpp b/third_party/WebKit/Source/core/editing/suggestion/TextSuggestionControllerTest.cpp
index 0089369..b2f22e50 100644
--- a/third_party/WebKit/Source/core/editing/suggestion/TextSuggestionControllerTest.cpp
+++ b/third_party/WebKit/Source/core/editing/suggestion/TextSuggestionControllerTest.cpp
@@ -209,8 +209,8 @@
 
   // Mark "word2" as the active suggestion range
   GetDocument().Markers().AddActiveSuggestionMarker(
-      EphemeralRange(Position(text, 6), Position(text, 11)), Color::kBlack,
-      ImeTextSpanThickness::kThin, Color::kBlack);
+      EphemeralRange(Position(text, 6), Position(text, 11)),
+      Color::kTransparent, ImeTextSpanThickness::kThin, Color::kBlack);
   // Select immediately before word2
   GetDocument().GetFrame()->Selection().SetSelectionAndEndTyping(
       SelectionInDOMTree::Builder()
@@ -235,8 +235,8 @@
 
   // Mark "word2" as the active suggestion range
   GetDocument().Markers().AddActiveSuggestionMarker(
-      EphemeralRange(Position(text, 6), Position(text, 11)), Color::kBlack,
-      ImeTextSpanThickness::kThin, Color::kBlack);
+      EphemeralRange(Position(text, 6), Position(text, 11)),
+      Color::kTransparent, ImeTextSpanThickness::kThin, Color::kBlack);
   // Select immediately before word2
   GetDocument().GetFrame()->Selection().SetSelectionAndEndTyping(
       SelectionInDOMTree::Builder()
@@ -262,7 +262,7 @@
 
   // Mark "word1" as the active suggestion range
   GetDocument().Markers().AddActiveSuggestionMarker(
-      EphemeralRange(Position(text, 0), Position(text, 5)), Color::kBlack,
+      EphemeralRange(Position(text, 0), Position(text, 5)), Color::kTransparent,
       ImeTextSpanThickness::kThin, Color::kBlack);
   // Select immediately before word1
   GetDocument().GetFrame()->Selection().SetSelectionAndEndTyping(
@@ -290,7 +290,7 @@
 
   // Mark "word1" as the active suggestion range
   GetDocument().Markers().AddActiveSuggestionMarker(
-      EphemeralRange(Position(text, 0), Position(text, 5)), Color::kBlack,
+      EphemeralRange(Position(text, 0), Position(text, 5)), Color::kTransparent,
       ImeTextSpanThickness::kThin, Color::kBlack);
   // Select immediately before word1
   GetDocument().GetFrame()->Selection().SetSelectionAndEndTyping(
@@ -321,8 +321,8 @@
 
   // Mark "word2" as the active suggestion range
   GetDocument().Markers().AddActiveSuggestionMarker(
-      EphemeralRange(Position(text, 5), Position(text, 10)), Color::kBlack,
-      ImeTextSpanThickness::kThin, Color::kBlack);
+      EphemeralRange(Position(text, 5), Position(text, 10)),
+      Color::kTransparent, ImeTextSpanThickness::kThin, Color::kBlack);
   // Select immediately before word2
   GetDocument().GetFrame()->Selection().SetSelectionAndEndTyping(
       SelectionInDOMTree::Builder()
@@ -347,8 +347,8 @@
 
   // Mark "word2" as the active suggestion range
   GetDocument().Markers().AddActiveSuggestionMarker(
-      EphemeralRange(Position(text, 6), Position(text, 11)), Color::kBlack,
-      ImeTextSpanThickness::kThin, Color::kBlack);
+      EphemeralRange(Position(text, 6), Position(text, 11)),
+      Color::kTransparent, ImeTextSpanThickness::kThin, Color::kBlack);
   // Select immediately before word2
   GetDocument().GetFrame()->Selection().SetSelectionAndEndTyping(
       SelectionInDOMTree::Builder()
@@ -373,7 +373,7 @@
 
   // Mark "word1" as the active suggestion range
   GetDocument().Markers().AddActiveSuggestionMarker(
-      EphemeralRange(Position(text, 0), Position(text, 5)), Color::kBlack,
+      EphemeralRange(Position(text, 0), Position(text, 5)), Color::kTransparent,
       ImeTextSpanThickness::kThin, Color::kBlack);
   // Select immediately before word1
   GetDocument().GetFrame()->Selection().SetSelectionAndEndTyping(
diff --git a/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.cpp b/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.cpp
index d93bed54..2f8a4b2b 100644
--- a/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.cpp
+++ b/third_party/WebKit/Source/core/exported/LocalFrameClientImpl.cpp
@@ -65,7 +65,6 @@
 #include "core/loader/HistoryItem.h"
 #include "core/page/Page.h"
 #include "platform/Histogram.h"
-#include "platform/WebFrameScheduler.h"
 #include "platform/exported/WrappedResourceRequest.h"
 #include "platform/exported/WrappedResourceResponse.h"
 #include "platform/feature_policy/FeaturePolicy.h"
diff --git a/third_party/WebKit/Source/core/exported/WebDocumentLoaderImpl.cpp b/third_party/WebKit/Source/core/exported/WebDocumentLoaderImpl.cpp
index 68fd3aa..0672328 100644
--- a/third_party/WebKit/Source/core/exported/WebDocumentLoaderImpl.cpp
+++ b/third_party/WebKit/Source/core/exported/WebDocumentLoaderImpl.cpp
@@ -81,17 +81,18 @@
   DocumentLoader::AppendRedirect(url);
 }
 
-void WebDocumentLoaderImpl::UpdateNavigation(double redirect_start_time,
-                                             double redirect_end_time,
-                                             double fetch_start_time,
-                                             bool has_redirect) {
+void WebDocumentLoaderImpl::UpdateNavigation(
+    base::TimeTicks redirect_start_time,
+    base::TimeTicks redirect_end_time,
+    base::TimeTicks fetch_start_time,
+    bool has_redirect) {
   // Updates the redirection timing if there is at least one redirection
   // (between two URLs).
   if (has_redirect) {
-    GetTiming().SetRedirectStart(TimeTicksFromSeconds(redirect_start_time));
-    GetTiming().SetRedirectEnd(TimeTicksFromSeconds(redirect_end_time));
+    GetTiming().SetRedirectStart(redirect_start_time);
+    GetTiming().SetRedirectEnd(redirect_end_time);
   }
-  GetTiming().SetFetchStart(TimeTicksFromSeconds(fetch_start_time));
+  GetTiming().SetFetchStart(fetch_start_time);
 }
 
 void WebDocumentLoaderImpl::RedirectChain(WebVector<WebURL>& result) const {
@@ -120,8 +121,9 @@
   extra_data_ = base::WrapUnique(extra_data);
 }
 
-void WebDocumentLoaderImpl::SetNavigationStartTime(double navigation_start) {
-  GetTiming().SetNavigationStart(TimeTicksFromSeconds(navigation_start));
+void WebDocumentLoaderImpl::SetNavigationStartTime(
+    base::TimeTicks navigation_start) {
+  GetTiming().SetNavigationStart(navigation_start);
 }
 
 WebNavigationType WebDocumentLoaderImpl::ToWebNavigationType(
diff --git a/third_party/WebKit/Source/core/exported/WebDocumentLoaderImpl.h b/third_party/WebKit/Source/core/exported/WebDocumentLoaderImpl.h
index ca60add..65fc959 100644
--- a/third_party/WebKit/Source/core/exported/WebDocumentLoaderImpl.h
+++ b/third_party/WebKit/Source/core/exported/WebDocumentLoaderImpl.h
@@ -73,10 +73,10 @@
   WebNavigationType GetNavigationType() const override;
   ExtraData* GetExtraData() const override;
   void SetExtraData(ExtraData*) override;
-  void SetNavigationStartTime(double) override;
-  void UpdateNavigation(double redirect_start_time,
-                        double redirect_end_time,
-                        double fetch_start_time,
+  void SetNavigationStartTime(base::TimeTicks) override;
+  void UpdateNavigation(base::TimeTicks redirect_start_time,
+                        base::TimeTicks redirect_end_time,
+                        base::TimeTicks fetch_start_time,
                         bool has_redirect) override;
   void SetSubresourceFilter(WebDocumentSubresourceFilter*) override;
   void SetServiceWorkerNetworkProvider(
diff --git a/third_party/WebKit/Source/core/exported/WebFrameTest.cpp b/third_party/WebKit/Source/core/exported/WebFrameTest.cpp
index 5ab5313..1c2caed 100644
--- a/third_party/WebKit/Source/core/exported/WebFrameTest.cpp
+++ b/third_party/WebKit/Source/core/exported/WebFrameTest.cpp
@@ -88,6 +88,7 @@
 #include "core/loader/DocumentThreadableLoaderClient.h"
 #include "core/loader/FrameLoadRequest.h"
 #include "core/loader/ThreadableLoader.h"
+#include "core/loader/ThreadableLoadingContext.h"
 #include "core/page/ChromeClient.h"
 #include "core/page/Page.h"
 #include "core/page/ScopedPagePauser.h"
@@ -10124,14 +10125,16 @@
   request.SetFetchRequestMode(network::mojom::FetchRequestMode::kCORS);
   ResourceLoaderOptions resource_loader_options;
   DocumentThreadableLoader::LoadResourceSynchronously(
-      *frame->GetDocument(), request, client, options, resource_loader_options);
+      *ThreadableLoadingContext::Create(*frame->GetDocument()), request, client,
+      options, resource_loader_options);
   EXPECT_TRUE(client.Failed());
 
   client.Reset();
   // Try to load the request with cross origin access. Should succeed.
   request.SetFetchRequestMode(network::mojom::FetchRequestMode::kNoCORS);
   DocumentThreadableLoader::LoadResourceSynchronously(
-      *frame->GetDocument(), request, client, options, resource_loader_options);
+      *ThreadableLoadingContext::Create(*frame->GetDocument()), request, client,
+      options, resource_loader_options);
   EXPECT_FALSE(client.Failed());
 }
 
diff --git a/third_party/WebKit/Source/core/exported/WebViewTest.cpp b/third_party/WebKit/Source/core/exported/WebViewTest.cpp
index 96f6a0d..10ceab30 100644
--- a/third_party/WebKit/Source/core/exported/WebViewTest.cpp
+++ b/third_party/WebKit/Source/core/exported/WebViewTest.cpp
@@ -1527,9 +1527,8 @@
       base_url_ + "input_field_populated.html");
   web_view->SetInitialFocus(false);
   WebVector<WebImeTextSpan> ime_text_spans(static_cast<size_t>(1));
-  ime_text_spans[0] =
-      WebImeTextSpan(WebImeTextSpan::Type::kComposition, 0, 4, 0,
-                     ui::mojom::ImeTextSpanThickness::kThin, 0);
+  ime_text_spans[0] = WebImeTextSpan(WebImeTextSpan::Type::kComposition, 0, 4,
+                                     ui::mojom::ImeTextSpanThickness::kThin, 0);
   WebLocalFrameImpl* frame = web_view->MainFrameImpl();
   WebInputMethodController* active_input_method_controller =
       frame->GetInputMethodController();
@@ -1555,9 +1554,8 @@
       base_url_ + "text_area_populated.html");
   web_view->SetInitialFocus(false);
   WebVector<WebImeTextSpan> ime_text_spans(static_cast<size_t>(1));
-  ime_text_spans[0] =
-      WebImeTextSpan(WebImeTextSpan::Type::kComposition, 0, 4, 0,
-                     ui::mojom::ImeTextSpanThickness::kThin, 0);
+  ime_text_spans[0] = WebImeTextSpan(WebImeTextSpan::Type::kComposition, 0, 4,
+                                     ui::mojom::ImeTextSpanThickness::kThin, 0);
   WebLocalFrameImpl* frame = web_view->MainFrameImpl();
   WebInputMethodController* active_input_method_controller =
       frame->FrameWidget()->GetActiveWebInputMethodController();
@@ -1600,9 +1598,8 @@
       base_url_ + "content_editable_rich_text.html");
   web_view->SetInitialFocus(false);
   WebVector<WebImeTextSpan> ime_text_spans(static_cast<size_t>(1));
-  ime_text_spans[0] =
-      WebImeTextSpan(WebImeTextSpan::Type::kComposition, 0, 4, 0,
-                     ui::mojom::ImeTextSpanThickness::kThin, 0);
+  ime_text_spans[0] = WebImeTextSpan(WebImeTextSpan::Type::kComposition, 0, 4,
+                                     ui::mojom::ImeTextSpanThickness::kThin, 0);
   WebLocalFrameImpl* frame = web_view->MainFrameImpl();
   frame->SetEditableSelectionOffsets(1, 1);
   WebDocument document = web_view->MainFrameImpl()->GetDocument();
diff --git a/third_party/WebKit/Source/core/fileapi/File.cpp b/third_party/WebKit/Source/core/fileapi/File.cpp
index 739f7bb3..3e24c3d 100644
--- a/third_party/WebKit/Source/core/fileapi/File.cpp
+++ b/third_party/WebKit/Source/core/fileapi/File.cpp
@@ -319,14 +319,9 @@
   long long length = end - start;
   std::unique_ptr<BlobData> blob_data = BlobData::Create();
   blob_data->SetContentType(NormalizeType(content_type));
-  if (!file_system_url_.IsEmpty()) {
-    blob_data->AppendFileSystemURL(file_system_url_, start, length,
-                                   modification_time_ms / kMsPerSecond);
-  } else {
-    DCHECK(!path_.IsEmpty());
-    blob_data->AppendFile(path_, start, length,
-                          modification_time_ms / kMsPerSecond);
-  }
+  DCHECK(!path_.IsEmpty());
+  blob_data->AppendFile(path_, start, length,
+                        modification_time_ms / kMsPerSecond);
   return Blob::Create(BlobDataHandle::Create(std::move(blob_data), length));
 }
 
@@ -364,11 +359,6 @@
   long long size;
   double modification_time_ms;
   CaptureSnapshot(size, modification_time_ms);
-  if (!file_system_url_.IsEmpty()) {
-    blob_data.AppendFileSystemURL(file_system_url_, 0, size,
-                                  modification_time_ms / kMsPerSecond);
-    return;
-  }
   DCHECK(!path_.IsEmpty());
   blob_data.AppendFile(path_, 0, size, modification_time_ms / kMsPerSecond);
 }
diff --git a/third_party/WebKit/Source/core/frame/AdTracker.cpp b/third_party/WebKit/Source/core/frame/AdTracker.cpp
new file mode 100644
index 0000000..fd8c8bb
--- /dev/null
+++ b/third_party/WebKit/Source/core/frame/AdTracker.cpp
@@ -0,0 +1,106 @@
+// Copyright 2018 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/frame/AdTracker.h"
+
+#include "core/CoreProbeSink.h"
+#include "core/frame/LocalFrame.h"
+#include "core/probe/CoreProbes.h"
+#include "platform/loader/fetch/ResourceRequest.h"
+#include "platform/weborigin/KURL.h"
+
+namespace blink {
+
+AdTracker::AdTracker(LocalFrame* local_root) : local_root_(local_root) {
+  local_root_->GetProbeSink()->addAdTracker(this);
+}
+
+AdTracker::~AdTracker() {
+  DCHECK(!local_root_);
+}
+
+void AdTracker::Shutdown() {
+  if (!local_root_)
+    return;
+  local_root_->GetProbeSink()->removeAdTracker(this);
+  local_root_ = nullptr;
+}
+
+void AdTracker::WillExecuteScript(const String& script_url) {
+  bool is_ad =
+      script_url.IsEmpty() ? false : known_ad_scripts_.Contains(script_url);
+  ExecutingScript script(script_url, is_ad);
+  executing_scripts_.push_back(script);
+}
+
+void AdTracker::DidExecuteScript() {
+  executing_scripts_.pop_back();
+}
+
+void AdTracker::Will(const probe::ExecuteScript& probe) {
+  WillExecuteScript(probe.script_url);
+}
+
+void AdTracker::Did(const probe::ExecuteScript& probe) {
+  DidExecuteScript();
+}
+
+void AdTracker::Will(const probe::CallFunction& probe) {
+  // Do not process nested microtasks as that might potentially lead to a
+  // slowdown of custom element callbacks.
+  if (probe.depth)
+    return;
+
+  v8::Local<v8::Value> resource_name =
+      probe.function->GetScriptOrigin().ResourceName();
+  String script_url;
+  if (!resource_name.IsEmpty())
+    script_url = ToCoreString(resource_name->ToString());
+  WillExecuteScript(script_url);
+}
+
+void AdTracker::Did(const probe::CallFunction& probe) {
+  if (probe.depth)
+    return;
+
+  DidExecuteScript();
+}
+
+void AdTracker::WillSendRequest(ExecutionContext* execution_context,
+                                unsigned long identifier,
+                                DocumentLoader* loader,
+                                ResourceRequest& request,
+                                const ResourceResponse& redirect_response,
+                                const FetchInitiatorInfo& initiator_info,
+                                Resource::Type resource_type) {
+  // If the resource is not already marked as an ad, check if any executing
+  // script is an ad. If yes, mark this as an ad.
+  if (!request.IsAdResource() && AnyExecutingScriptsTaggedAsAdResource())
+    request.SetIsAdResource();
+
+  // If it is a script marked as an ad, append it to the known ad scripts set.
+  if (resource_type != Resource::kScript || !request.IsAdResource()) {
+    return;
+  }
+  AppendToKnownAdScripts(request.Url());
+}
+
+// Keeping a separate function to easily access from tests.
+void AdTracker::AppendToKnownAdScripts(const KURL& url) {
+  known_ad_scripts_.insert(url.GetString());
+}
+
+bool AdTracker::AnyExecutingScriptsTaggedAsAdResource() {
+  for (const auto& executing_script : executing_scripts_) {
+    if (executing_script.is_ad)
+      return true;
+  }
+  return false;
+}
+
+void AdTracker::Trace(blink::Visitor* visitor) {
+  visitor->Trace(local_root_);
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/AdTracker.h b/third_party/WebKit/Source/core/frame/AdTracker.h
new file mode 100644
index 0000000..ba3aa0d
--- /dev/null
+++ b/third_party/WebKit/Source/core/frame/AdTracker.h
@@ -0,0 +1,93 @@
+// Copyright 2018 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 AdTracker_h
+#define AdTracker_h
+
+#include "base/macros.h"
+#include "core/frame/LocalFrame.h"
+#include "platform/loader/fetch/Resource.h"
+#include "platform/weborigin/KURL.h"
+#include "platform/wtf/HashSet.h"
+#include "platform/wtf/Vector.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+class ExecutionContext;
+class DocumentLoader;
+class ResourceRequest;
+class ResourceResponse;
+struct FetchInitiatorInfo;
+
+namespace probe {
+class CallFunction;
+class ExecuteScript;
+}  // namespace probe
+
+// Tracker for tagging resources as ads based on the call stack scripts.
+// The tracker is maintained per local root.
+class CORE_EXPORT AdTracker final
+    : public GarbageCollectedFinalized<AdTracker> {
+ public:
+  // Instrumenting methods.
+  // Called when a script module or script gets executed from native code.
+  void Will(const probe::ExecuteScript&);
+  void Did(const probe::ExecuteScript&);
+
+  // Called when a function gets called from native code.
+  void Will(const probe::CallFunction&);
+  void Did(const probe::CallFunction&);
+
+  // Called when a resource request is about to be sent. This will do the
+  // following:
+  // - Mark a resource request as an ad if any executing scripts contain an ad.
+  // - If the marked resource is a script, also save it to keep track of all
+  // those script resources that have been identified as ads.
+  void WillSendRequest(ExecutionContext*,
+                       unsigned long identifier,
+                       DocumentLoader*,
+                       ResourceRequest&,
+                       const ResourceResponse& redirect_response,
+                       const FetchInitiatorInfo&,
+                       Resource::Type);
+
+  virtual void Trace(blink::Visitor*);
+
+  void Shutdown();
+  explicit AdTracker(LocalFrame*);
+  ~AdTracker();
+
+ private:
+  friend class FrameFetchContextSubresourceFilterTest;
+  friend class AdTrackerTest;
+
+  void WillExecuteScript(const String& script_name);
+  void DidExecuteScript();
+  void AppendToKnownAdScripts(const KURL&);
+
+  // Returns true if any script in the pseudo call stack has been identified as
+  // an ad earlier. An ad is identified as an ad if AppendToKnownAdScripts has
+  // been called on it earlier.
+  bool AnyExecutingScriptsTaggedAsAdResource();
+
+  Member<LocalFrame> local_root_;
+
+  // Since the script URLs should be external strings in v8 (allocated in Blink)
+  // getting it as String should end up with the same StringImpl. Thus storing a
+  // vector of Strings here should not be expensive.
+  struct ExecutingScript {
+    String url;
+    bool is_ad;
+    ExecutingScript(String script_url, bool is_ad_script)
+        : url(script_url), is_ad(is_ad_script){};
+  };
+  Vector<ExecutingScript> executing_scripts_;
+  HashSet<String> known_ad_scripts_;
+
+  DISALLOW_COPY_AND_ASSIGN(AdTracker);
+};
+
+}  // namespace blink
+
+#endif  // AdTracker_h
diff --git a/third_party/WebKit/Source/core/frame/AdTrackerTest.cpp b/third_party/WebKit/Source/core/frame/AdTrackerTest.cpp
new file mode 100644
index 0000000..8ee4384
--- /dev/null
+++ b/third_party/WebKit/Source/core/frame/AdTrackerTest.cpp
@@ -0,0 +1,67 @@
+// Copyright 2018 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/frame/AdTracker.h"
+
+#include "core/frame/LocalFrame.h"
+#include "core/probe/CoreProbes.h"
+#include "core/testing/DummyPageHolder.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#include <memory>
+
+namespace blink {
+
+class AdTrackerTest : public ::testing::Test {
+ protected:
+  void SetUp() override;
+  void TearDown() override;
+  LocalFrame* GetFrame() const {
+    return page_holder_->GetDocument().GetFrame();
+  }
+
+  void WillExecuteScript(const String& script_url) {
+    ad_tracker_->WillExecuteScript(script_url);
+  }
+
+  bool AnyExecutingScriptsTaggedAsAdResource() {
+    return ad_tracker_->AnyExecutingScriptsTaggedAsAdResource();
+  }
+
+  void AppendToKnownAdScripts(const KURL& url) {
+    ad_tracker_->AppendToKnownAdScripts(url);
+  }
+
+  Persistent<AdTracker> ad_tracker_;
+  std::unique_ptr<DummyPageHolder> page_holder_;
+};
+
+void AdTrackerTest::SetUp() {
+  page_holder_ = DummyPageHolder::Create(IntSize(800, 600));
+  page_holder_->GetDocument().SetURL(KURL("https://example.com/foo"));
+  ad_tracker_ = new AdTracker(GetFrame());
+}
+
+void AdTrackerTest::TearDown() {
+  ad_tracker_->Shutdown();
+}
+
+TEST_F(AdTrackerTest, AnyExecutingScriptsTaggedAsAdResource) {
+  KURL ad_script_url("https://example.com/bar.js");
+  AppendToKnownAdScripts(ad_script_url);
+
+  WillExecuteScript("https://example.com/foo.js");
+  WillExecuteScript("https://example.com/bar.js");
+  EXPECT_TRUE(AnyExecutingScriptsTaggedAsAdResource());
+}
+
+// Tests that if neither script in the stack is an ad,
+// AnyExecutingScriptsTaggedAsAdResource should return false.
+TEST_F(AdTrackerTest, AnyExecutingScriptsTaggedAsAdResource_False) {
+  WillExecuteScript("https://example.com/foo.js");
+  WillExecuteScript("https://example.com/bar.js");
+  EXPECT_FALSE(AnyExecutingScriptsTaggedAsAdResource());
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/BUILD.gn b/third_party/WebKit/Source/core/frame/BUILD.gn
index 0a57a14..a5f1b66 100644
--- a/third_party/WebKit/Source/core/frame/BUILD.gn
+++ b/third_party/WebKit/Source/core/frame/BUILD.gn
@@ -6,6 +6,8 @@
 
 blink_core_sources("frame") {
   sources = [
+    "AdTracker.cpp",
+    "AdTracker.h",
     "BarProp.cpp",
     "BarProp.h",
     "BrowserControls.cpp",
diff --git a/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp b/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
index 434cac0..dc09847 100644
--- a/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
+++ b/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
@@ -91,7 +91,6 @@
 #include "core/timing/DOMWindowPerformance.h"
 #include "core/timing/WindowPerformance.h"
 #include "platform/EventDispatchForbiddenScope.h"
-#include "platform/WebFrameScheduler.h"
 #include "platform/loader/fetch/ResourceFetcher.h"
 #include "platform/scroll/ScrollTypes.h"
 #include "platform/scroll/ScrollbarTheme.h"
diff --git a/third_party/WebKit/Source/core/frame/LocalFrame.cpp b/third_party/WebKit/Source/core/frame/LocalFrame.cpp
index edee3fb9..5e5c1d3 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrame.cpp
+++ b/third_party/WebKit/Source/core/frame/LocalFrame.cpp
@@ -48,6 +48,7 @@
 #include "core/editing/spellcheck/SpellChecker.h"
 #include "core/editing/suggestion/TextSuggestionController.h"
 #include "core/exported/WebPluginContainerImpl.h"
+#include "core/frame/AdTracker.h"
 #include "core/frame/ContentSettingsClient.h"
 #include "core/frame/EventHandlerRegistry.h"
 #include "core/frame/FrameConsole.h"
@@ -79,8 +80,8 @@
 #include "core/paint/compositing/PaintLayerCompositor.h"
 #include "core/probe/CoreProbes.h"
 #include "core/svg/SVGDocumentExtensions.h"
+#include "platform/FrameScheduler.h"
 #include "platform/Histogram.h"
-#include "platform/WebFrameScheduler.h"
 #include "platform/bindings/ScriptForbiddenScope.h"
 #include "platform/graphics/paint/ClipRecorder.h"
 #include "platform/graphics/paint/PaintCanvas.h"
@@ -141,7 +142,7 @@
   return true;
 }
 
-class EmptyFrameScheduler final : public WebFrameScheduler {
+class EmptyFrameScheduler final : public FrameScheduler {
  public:
   EmptyFrameScheduler() { DCHECK(IsMainThread()); }
 
@@ -162,8 +163,8 @@
   void SetCrossOrigin(bool) override {}
   bool IsCrossOrigin() const override { return false; }
   void TraceUrlChange(const String& override) {}
-  WebFrameScheduler::FrameType GetFrameType() const override {
-    return WebFrameScheduler::FrameType::kSubframe;
+  FrameScheduler::FrameType GetFrameType() const override {
+    return FrameScheduler::FrameType::kSubframe;
   }
   PageScheduler* GetPageScheduler() const override { return nullptr; }
   WebScopedVirtualTimePauser CreateWebScopedVirtualTimePauser(
@@ -265,6 +266,7 @@
 }
 
 void LocalFrame::Trace(blink::Visitor* visitor) {
+  visitor->Trace(ad_tracker_);
   visitor->Trace(probe_sink_);
   visitor->Trace(performance_monitor_);
   visitor->Trace(idleness_detector_);
@@ -328,8 +330,10 @@
   // DCHECK(isAttached()) here.
   lifecycle_.AdvanceTo(FrameLifecycle::kDetaching);
 
-  if (IsLocalRoot())
+  if (IsLocalRoot()) {
     performance_monitor_->Shutdown();
+    ad_tracker_->Shutdown();
+  }
   idleness_detector_->Shutdown();
   if (inspector_trace_events_)
     probe_sink_->removeInspectorTraceEvents(inspector_trace_events_);
@@ -843,8 +847,8 @@
                            ? page.GetPageScheduler()->CreateFrameScheduler(
                                  client->GetFrameBlameContext(),
                                  IsMainFrame()
-                                     ? WebFrameScheduler::FrameType::kMainFrame
-                                     : WebFrameScheduler::FrameType::kSubframe)
+                                     ? FrameScheduler::FrameType::kMainFrame
+                                     : FrameScheduler::FrameType::kSubframe)
                            : std::make_unique<EmptyFrameScheduler>()),
       loader_(this),
       navigation_scheduler_(NavigationScheduler::Create(this)),
@@ -867,6 +871,7 @@
       interface_registry_(interface_registry) {
   if (IsLocalRoot()) {
     probe_sink_ = new CoreProbeSink();
+    ad_tracker_ = new AdTracker(this);
     performance_monitor_ = new PerformanceMonitor(this);
     inspector_trace_events_ = new InspectorTraceEvents();
     probe_sink_->addInspectorTraceEvents(inspector_trace_events_);
@@ -876,13 +881,14 @@
     // it will be updated later.
     UpdateInertIfPossible();
     probe_sink_ = LocalFrameRoot().probe_sink_;
+    ad_tracker_ = LocalFrameRoot().ad_tracker_;
     performance_monitor_ = LocalFrameRoot().performance_monitor_;
   }
   idleness_detector_ = new IdlenessDetector(this);
   inspector_task_runner_->InitIsolate(V8PerIsolateData::MainThreadIsolate());
 }
 
-WebFrameScheduler* LocalFrame::FrameScheduler() {
+FrameScheduler* LocalFrame::GetFrameScheduler() {
   return frame_scheduler_.get();
 }
 
diff --git a/third_party/WebKit/Source/core/frame/LocalFrame.h b/third_party/WebKit/Source/core/frame/LocalFrame.h
index d971b4d..b20045b 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrame.h
+++ b/third_party/WebKit/Source/core/frame/LocalFrame.h
@@ -54,6 +54,7 @@
 
 namespace blink {
 
+class AdTracker;
 class AssociatedInterfaceProvider;
 class Color;
 class ComputedAccessibleNode;
@@ -66,6 +67,7 @@
 class FloatSize;
 class FrameConsole;
 class FrameResourceCoordinator;
+class FrameScheduler;
 class FrameSelection;
 class InputMethodController;
 class InspectorTraceEvents;
@@ -87,7 +89,6 @@
 class SpellChecker;
 class TextSuggestionController;
 class WebComputedAXTree;
-class WebFrameScheduler;
 class WebPluginContainerImpl;
 class WebURLLoaderFactory;
 
@@ -226,7 +227,7 @@
   bool ShouldThrottleRendering() const;
 
   // Returns the frame scheduler, creating one if needed.
-  WebFrameScheduler* FrameScheduler();
+  FrameScheduler* GetFrameScheduler();
   scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(TaskType);
   void ScheduleVisualUpdateUnlessThrottled();
 
@@ -265,6 +266,7 @@
 
   PerformanceMonitor* GetPerformanceMonitor() { return performance_monitor_; }
   IdlenessDetector* GetIdlenessDetector() { return idleness_detector_; }
+  AdTracker* GetAdTracker() { return ad_tracker_; }
 
   // Convenience function to allow loading image placeholders for the request if
   // either the flag in Settings() for using image placeholders is set, or if
@@ -355,7 +357,7 @@
                    const FloatSize& original_page_size,
                    float maximum_shrink_ratio);
 
-  std::unique_ptr<WebFrameScheduler> frame_scheduler_;
+  std::unique_ptr<FrameScheduler> frame_scheduler_;
 
   mutable FrameLoader loader_;
   Member<NavigationScheduler> navigation_scheduler_;
@@ -390,6 +392,7 @@
   Member<CoreProbeSink> probe_sink_;
   scoped_refptr<InspectorTaskRunner> inspector_task_runner_;
   Member<PerformanceMonitor> performance_monitor_;
+  Member<AdTracker> ad_tracker_;
   Member<IdlenessDetector> idleness_detector_;
   Member<InspectorTraceEvents> inspector_trace_events_;
 
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
index 2ff905d..6b10f2b 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
+++ b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
@@ -100,10 +100,10 @@
 #include "core/resize_observer/ResizeObserverController.h"
 #include "core/style/ComputedStyle.h"
 #include "core/svg/SVGSVGElement.h"
+#include "platform/FrameScheduler.h"
 #include "platform/Histogram.h"
 #include "platform/Language.h"
 #include "platform/PlatformChromeClient.h"
-#include "platform/WebFrameScheduler.h"
 #include "platform/bindings/ScriptForbiddenScope.h"
 #include "platform/fonts/FontCache.h"
 #include "platform/geometry/DoubleRect.h"
@@ -3812,6 +3812,13 @@
   return local_frame + LayoutSize(GetScrollOffset());
 }
 
+IntPoint LocalFrameView::RootFrameToAbsolute(
+    const IntPoint& point_in_root_frame) const {
+  IntPoint local_frame = ConvertFromRootFrame(point_in_root_frame);
+  // With RLS turned on, this will be a no-op.
+  return local_frame + FlooredIntSize(GetScrollOffset());
+}
+
 IntRect LocalFrameView::RootFrameToAbsolute(
     const IntRect& rect_in_root_frame) const {
   IntRect absolute_rect = ConvertFromRootFrame(rect_in_root_frame);
@@ -5021,7 +5028,7 @@
 }
 
 LayoutRect LocalFrameView::ScrollIntoView(
-    const LayoutRect& rect_in_content,
+    const LayoutRect& rect_in_absolute,
     const WebScrollIntoViewParams& params) {
   GetLayoutBox()->SetPendingOffsetToScroll(LayoutSize());
 
@@ -5029,7 +5036,7 @@
 
   ScrollOffset new_scroll_offset =
       ClampScrollOffset(ScrollAlignment::GetScrollOffsetToExpose(
-          scroll_snapport_rect, rect_in_content, params.GetScrollAlignmentX(),
+          scroll_snapport_rect, rect_in_absolute, params.GetScrollAlignmentX(),
           params.GetScrollAlignmentY(), GetScrollOffset()));
   ScrollOffset old_scroll_offset = GetScrollOffset();
 
@@ -5057,7 +5064,7 @@
   // relative to the document.
   // TODO(szager): PaintLayerScrollableArea::ScrollIntoView clips the return
   // value to the visible content rect, but this does not.
-  return rect_in_content;
+  return rect_in_absolute;
 }
 
 IntRect LocalFrameView::ScrollCornerRect() const {
@@ -5483,11 +5490,10 @@
         &GetFrame().LocalFrameRoot());
   }
 
-  if (frame_->FrameScheduler()) {
-    frame_->FrameScheduler()->SetFrameVisible(!hidden_for_throttling_);
-    frame_->FrameScheduler()->SetCrossOrigin(frame_->IsCrossOriginSubframe());
-    frame_->FrameScheduler()->TraceUrlChange(
-        frame_->GetDocument()->Url().GetString());
+  if (FrameScheduler* frame_scheduler = frame_->GetFrameScheduler()) {
+    frame_scheduler->SetFrameVisible(!hidden_for_throttling_);
+    frame_scheduler->SetCrossOrigin(frame_->IsCrossOriginSubframe());
+    frame_scheduler->TraceUrlChange(frame_->GetDocument()->Url().GetString());
   }
 
 #if DCHECK_IS_ON()
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameView.h b/third_party/WebKit/Source/core/frame/LocalFrameView.h
index faad33e..760793e 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrameView.h
+++ b/third_party/WebKit/Source/core/frame/LocalFrameView.h
@@ -503,7 +503,7 @@
                                       unsigned = 0) const final;
   scoped_refptr<base::SingleThreadTaskRunner> GetTimerTaskRunner() const final;
 
-  LayoutRect ScrollIntoView(const LayoutRect& rect_in_content,
+  LayoutRect ScrollIntoView(const LayoutRect& rect_in_absolute,
                             const WebScrollIntoViewParams& params) override;
 
   // The window that hosts the LocalFrameView. The LocalFrameView will
@@ -704,6 +704,7 @@
   IntPoint RootFrameToDocument(const IntPoint&);
   FloatPoint RootFrameToDocument(const FloatPoint&);
   LayoutPoint RootFrameToAbsolute(const LayoutPoint&) const;
+  IntPoint RootFrameToAbsolute(const IntPoint&) const;
   IntRect RootFrameToAbsolute(const IntRect&) const;
   DoublePoint DocumentToAbsolute(const DoublePoint&) const;
   FloatPoint DocumentToAbsolute(const FloatPoint&) const;
diff --git a/third_party/WebKit/Source/core/frame/RootFrameViewport.cpp b/third_party/WebKit/Source/core/frame/RootFrameViewport.cpp
index 1bb3234f..8c32029 100644
--- a/third_party/WebKit/Source/core/frame/RootFrameViewport.cpp
+++ b/third_party/WebKit/Source/core/frame/RootFrameViewport.cpp
@@ -245,13 +245,17 @@
 }
 
 LayoutRect RootFrameViewport::ScrollIntoView(
-    const LayoutRect& rect_in_content,
+    const LayoutRect& rect_in_absolute,
     const WebScrollIntoViewParams& params) {
   LayoutRect scroll_snapport_rect(VisibleScrollSnapportRect());
 
+  LayoutRect rect_in_document = rect_in_absolute;
+  if (RuntimeEnabledFeatures::RootLayerScrollingEnabled())
+    rect_in_document.Move(LayoutSize(LayoutViewport().GetScrollOffset()));
+
   ScrollOffset new_scroll_offset =
       ClampScrollOffset(ScrollAlignment::GetScrollOffsetToExpose(
-          scroll_snapport_rect, rect_in_content, params.GetScrollAlignmentX(),
+          scroll_snapport_rect, rect_in_document, params.GetScrollAlignmentX(),
           params.GetScrollAlignmentY(), GetScrollOffset()));
 
   if (new_scroll_offset != GetScrollOffset()) {
@@ -267,11 +271,12 @@
     }
   }
 
-  // RootFrameViewport only changes the viewport relative to the document so we
-  // can't change the input rect's location relative to the document origin.
+  // Return the newly moved rect to absolute coordinates.
   // TODO(szager): PaintLayerScrollableArea::ScrollIntoView clips the return
   // value to the visible content rect, but this does not.
-  return rect_in_content;
+  if (RuntimeEnabledFeatures::RootLayerScrollingEnabled())
+    rect_in_document.Move(-LayoutSize(LayoutViewport().GetScrollOffset()));
+  return rect_in_document;
 }
 
 void RootFrameViewport::UpdateScrollOffset(const ScrollOffset& offset,
diff --git a/third_party/WebKit/Source/core/frame/RootFrameViewport.h b/third_party/WebKit/Source/core/frame/RootFrameViewport.h
index c7c1986..75bcbaa 100644
--- a/third_party/WebKit/Source/core/frame/RootFrameViewport.h
+++ b/third_party/WebKit/Source/core/frame/RootFrameViewport.h
@@ -59,8 +59,8 @@
   void SetScrollOffset(const ScrollOffset&,
                        ScrollType,
                        ScrollBehavior = kScrollBehaviorInstant) override;
-  LayoutRect ScrollIntoView(const LayoutRect& rect_in_content,
-                            const WebScrollIntoViewParams& params) override;
+  LayoutRect ScrollIntoView(const LayoutRect&,
+                            const WebScrollIntoViewParams&) override;
   IntRect VisibleContentRect(
       IncludeScrollbarsInRect = kExcludeScrollbars) const override;
   LayoutRect VisibleScrollSnapportRect() const override;
diff --git a/third_party/WebKit/Source/core/frame/RootFrameViewportTest.cpp b/third_party/WebKit/Source/core/frame/RootFrameViewportTest.cpp
index 837011273..8136884 100644
--- a/third_party/WebKit/Source/core/frame/RootFrameViewportTest.cpp
+++ b/third_party/WebKit/Source/core/frame/RootFrameViewportTest.cpp
@@ -148,6 +148,15 @@
     return ScrollOffset(ContentsSize() - ViewportSize());
   }
 
+  LayoutRect DocumentToAbsolute(const LayoutRect& rect) const {
+    if (!RuntimeEnabledFeatures::RootLayerScrollingEnabled())
+      return rect;
+
+    LayoutRect ret = rect;
+    ret.Move(LayoutSize(-GetScrollOffset()));
+    return ret;
+  }
+
  private:
   RootFrameViewStub(const IntSize& viewport_size, const IntSize& contents_size)
       : ScrollableAreaStub(viewport_size, contents_size) {}
@@ -321,7 +330,7 @@
   // scaled.
   visual_viewport->SetViewportSize(IntSize(100, 100));
   root_frame_viewport->ScrollIntoView(
-      LayoutRect(100, 250, 50, 50),
+      layout_viewport->DocumentToAbsolute(LayoutRect(100, 250, 50, 50)),
       WebScrollIntoViewParams(ScrollAlignment::kAlignToEdgeIfNeeded,
                               ScrollAlignment::kAlignToEdgeIfNeeded,
                               kProgrammaticScroll, true,
@@ -330,7 +339,7 @@
   EXPECT_EQ(ScrollOffset(0, 50), visual_viewport->GetScrollOffset());
 
   root_frame_viewport->ScrollIntoView(
-      LayoutRect(25, 75, 50, 50),
+      layout_viewport->DocumentToAbsolute(LayoutRect(25, 75, 50, 50)),
       WebScrollIntoViewParams(ScrollAlignment::kAlignToEdgeIfNeeded,
                               ScrollAlignment::kAlignToEdgeIfNeeded,
                               kProgrammaticScroll, true,
@@ -344,7 +353,7 @@
   root_frame_viewport->SetScrollOffset(ScrollOffset(), kProgrammaticScroll);
 
   root_frame_viewport->ScrollIntoView(
-      LayoutRect(50, 75, 50, 75),
+      layout_viewport->DocumentToAbsolute(LayoutRect(50, 75, 50, 75)),
       WebScrollIntoViewParams(ScrollAlignment::kAlignToEdgeIfNeeded,
                               ScrollAlignment::kAlignToEdgeIfNeeded,
                               kProgrammaticScroll, true,
@@ -353,7 +362,7 @@
   EXPECT_EQ(ScrollOffset(50, 75), visual_viewport->GetScrollOffset());
 
   root_frame_viewport->ScrollIntoView(
-      LayoutRect(190, 290, 10, 10),
+      layout_viewport->DocumentToAbsolute(LayoutRect(190, 290, 10, 10)),
       WebScrollIntoViewParams(ScrollAlignment::kAlignToEdgeIfNeeded,
                               ScrollAlignment::kAlignToEdgeIfNeeded,
                               kProgrammaticScroll, true,
@@ -370,7 +379,8 @@
                                        kProgrammaticScroll);
 
   root_frame_viewport->ScrollIntoView(
-      LayoutRect(root_frame_viewport->VisibleContentRect(kExcludeScrollbars)),
+      layout_viewport->DocumentToAbsolute(LayoutRect(
+          root_frame_viewport->VisibleContentRect(kExcludeScrollbars))),
       WebScrollIntoViewParams(ScrollAlignment::kAlignToEdgeIfNeeded,
                               ScrollAlignment::kAlignToEdgeIfNeeded,
                               kProgrammaticScroll, true,
@@ -379,7 +389,8 @@
   EXPECT_EQ(ScrollOffset(0, 10), visual_viewport->GetScrollOffset());
 
   root_frame_viewport->ScrollIntoView(
-      LayoutRect(root_frame_viewport->VisibleContentRect(kExcludeScrollbars)),
+      layout_viewport->DocumentToAbsolute(LayoutRect(
+          root_frame_viewport->VisibleContentRect(kExcludeScrollbars))),
       WebScrollIntoViewParams(ScrollAlignment::kAlignCenterAlways,
                               ScrollAlignment::kAlignCenterAlways,
                               kProgrammaticScroll, true,
@@ -388,7 +399,8 @@
   EXPECT_EQ(ScrollOffset(0, 10), visual_viewport->GetScrollOffset());
 
   root_frame_viewport->ScrollIntoView(
-      LayoutRect(root_frame_viewport->VisibleContentRect(kExcludeScrollbars)),
+      layout_viewport->DocumentToAbsolute(LayoutRect(
+          root_frame_viewport->VisibleContentRect(kExcludeScrollbars))),
       WebScrollIntoViewParams(
           ScrollAlignment::kAlignTopAlways, ScrollAlignment::kAlignTopAlways,
           kProgrammaticScroll, true, kScrollBehaviorInstant));
diff --git a/third_party/WebKit/Source/core/frame/WebFrameWidgetImpl.cpp b/third_party/WebKit/Source/core/frame/WebFrameWidgetImpl.cpp
index ccc7a812..049ddfd9 100644
--- a/third_party/WebKit/Source/core/frame/WebFrameWidgetImpl.cpp
+++ b/third_party/WebKit/Source/core/frame/WebFrameWidgetImpl.cpp
@@ -69,7 +69,6 @@
 #include "core/page/ValidationMessageClient.h"
 #include "core/paint/compositing/PaintLayerCompositor.h"
 #include "platform/KeyboardCodes.h"
-#include "platform/WebFrameScheduler.h"
 #include "platform/animation/CompositorAnimationHost.h"
 #include "platform/graphics/Color.h"
 #include "platform/graphics/CompositorMutatorClient.h"
diff --git a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp
index 6ccc799..2a9d45a 100644
--- a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp
+++ b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp
@@ -182,7 +182,7 @@
 #include "core/paint/TransformRecorder.h"
 #include "core/timing/DOMWindowPerformance.h"
 #include "core/timing/WindowPerformance.h"
-#include "platform/WebFrameScheduler.h"
+#include "platform/FrameScheduler.h"
 #include "platform/bindings/DOMWrapperWorld.h"
 #include "platform/bindings/ScriptForbiddenScope.h"
 #include "platform/bindings/V8PerIsolateData.h"
@@ -742,6 +742,28 @@
   GetFrame()->GetDocument()->AddConsoleMessage(console_message);
 }
 
+void WebLocalFrameImpl::Alert(const WebString& message) {
+  DCHECK(GetFrame());
+  ScriptState* script_state = ToScriptStateForMainWorld(GetFrame());
+  DCHECK(script_state);
+  GetFrame()->DomWindow()->alert(script_state, message);
+}
+
+bool WebLocalFrameImpl::Confirm(const WebString& message) {
+  DCHECK(GetFrame());
+  ScriptState* script_state = ToScriptStateForMainWorld(GetFrame());
+  DCHECK(script_state);
+  return GetFrame()->DomWindow()->confirm(script_state, message);
+}
+
+WebString WebLocalFrameImpl::Prompt(const WebString& message,
+                                    const WebString& default_value) {
+  DCHECK(GetFrame());
+  ScriptState* script_state = ToScriptStateForMainWorld(GetFrame());
+  DCHECK(script_state);
+  return GetFrame()->DomWindow()->prompt(script_state, message, default_value);
+}
+
 void WebLocalFrameImpl::CollectGarbage() {
   if (!GetFrame())
     return;
@@ -1763,7 +1785,7 @@
   frame_ = frame;
 
   local_frame_client_->SetVirtualTimePauser(
-      frame_ ? frame_->FrameScheduler()->CreateWebScopedVirtualTimePauser(
+      frame_ ? frame_->GetFrameScheduler()->CreateWebScopedVirtualTimePauser(
                    WebScopedVirtualTimePauser::VirtualTaskDuration::kInstant)
              : WebScopedVirtualTimePauser());
 }
@@ -2416,8 +2438,8 @@
   Deprecation::CountDeprecation(GetFrame(), feature);
 }
 
-WebFrameScheduler* WebLocalFrameImpl::Scheduler() const {
-  return GetFrame()->FrameScheduler();
+FrameScheduler* WebLocalFrameImpl::Scheduler() const {
+  return GetFrame()->GetFrameScheduler();
 }
 
 scoped_refptr<base::SingleThreadTaskRunner> WebLocalFrameImpl::GetTaskRunner(
diff --git a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.h b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.h
index fe164546..cc5718a 100644
--- a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.h
+++ b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.h
@@ -109,6 +109,11 @@
   void SetIsolatedWorldHumanReadableName(int world_id,
                                          const WebString&) override;
   void AddMessageToConsole(const WebConsoleMessage&) override;
+  void Alert(const WebString& message) override;
+  bool Confirm(const WebString& message) override;
+  WebString Prompt(const WebString& message,
+                   const WebString& default_value) override;
+
   void CollectGarbage() override;
   v8::Local<v8::Value> ExecuteScriptAndReturnValue(
       const WebScriptSource&) override;
@@ -323,7 +328,7 @@
   void SetEngagementLevel(mojom::EngagementLevel) override;
   void ClearActiveFindMatch() override;
   void UsageCountChromeLoadTimes(const WebString& metric) override;
-  WebFrameScheduler* Scheduler() const override;
+  FrameScheduler* Scheduler() const override;
   scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(TaskType) override;
   WebInputMethodController* GetInputMethodController() override;
 
diff --git a/third_party/WebKit/Source/core/html/HTMLAnchorElement.cpp b/third_party/WebKit/Source/core/html/HTMLAnchorElement.cpp
index 35f9ac7..595640d04 100644
--- a/third_party/WebKit/Source/core/html/HTMLAnchorElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLAnchorElement.cpp
@@ -392,9 +392,8 @@
         static_cast<String>(FastGetAttribute(downloadAttr)));
   }
   request.SetRequestContext(WebURLRequest::kRequestContextHyperlink);
-  FrameLoadRequest frame_request(
-      &GetDocument(), request,
-      hasAttribute(downloadAttr) ? g_null_atom : getAttribute(targetAttr));
+  FrameLoadRequest frame_request(&GetDocument(), request,
+                                 getAttribute(targetAttr));
   frame_request.SetTriggeringEvent(event);
   if (HasRel(kRelationNoReferrer)) {
     frame_request.SetShouldSendReferrer(kNeverSendReferrer);
diff --git a/third_party/WebKit/Source/core/html/forms/HTMLOptionElement.cpp b/third_party/WebKit/Source/core/html/forms/HTMLOptionElement.cpp
index 97417fab..498a1826 100644
--- a/third_party/WebKit/Source/core/html/forms/HTMLOptionElement.cpp
+++ b/third_party/WebKit/Source/core/html/forms/HTMLOptionElement.cpp
@@ -398,26 +398,8 @@
 }
 
 bool HTMLOptionElement::IsDisplayNone() const {
-  // If the style is not set, then the node is still unattached.
-  // We have to wait till it gets attached to read the display property.
-  const ComputedStyle* style = NonLayoutObjectComputedStyle();
-  if (!style)
-    return false;
-
-  if (style->Display() != EDisplay::kNone) {
-    // We need to check the parent's display property.  Parent's
-    // display:none doesn't override children's display properties in
-    // ComputedStyle.
-    Element* parent = parentElement();
-    DCHECK(parent);
-    if (IsHTMLOptGroupElement(*parent)) {
-      const ComputedStyle* parent_style = parent->GetComputedStyle()
-                                              ? parent->GetComputedStyle()
-                                              : parent->EnsureComputedStyle();
-      return !parent_style || parent_style->Display() == EDisplay::kNone;
-    }
-  }
-  return style->Display() == EDisplay::kNone;
+  const ComputedStyle* style = GetComputedStyle();
+  return !style || style->Display() == EDisplay::kNone;
 }
 
 String HTMLOptionElement::innerText() {
diff --git a/third_party/WebKit/Source/core/html/forms/HTMLSelectElement.cpp b/third_party/WebKit/Source/core/html/forms/HTMLSelectElement.cpp
index caad9be..dffea41 100644
--- a/third_party/WebKit/Source/core/html/forms/HTMLSelectElement.cpp
+++ b/third_party/WebKit/Source/core/html/forms/HTMLSelectElement.cpp
@@ -921,14 +921,7 @@
   else if (!UsesMenuList() || IsMultiple())
     SelectOption(nullptr, IsMultiple() ? 0 : kDeselectOtherOptions);
   else
-    SelectOption(NextSelectableOption(nullptr), kDeselectOtherOptions);
-
-  if (GetDocument().IsActive()) {
-    GetDocument()
-        .GetPage()
-        ->GetChromeClient()
-        .DidChangeSelectionInSelectControl(*this);
-  }
+    ResetToDefaultSelection();
 }
 
 void HTMLSelectElement::OptionInserted(HTMLOptionElement& option,
@@ -1051,6 +1044,14 @@
   }
 
   NotifyFormStateChanged();
+
+  if (Frame::HasTransientUserActivation(GetDocument().GetFrame()) &&
+      GetDocument().IsActive()) {
+    GetDocument()
+        .GetPage()
+        ->GetChromeClient()
+        .DidChangeSelectionInSelectControl(*this);
+  }
 }
 
 void HTMLSelectElement::DispatchFocusEvent(
@@ -1860,9 +1861,8 @@
 bool HTMLSelectElement::ItemIsDisplayNone(Element& element) const {
   if (auto* option = ToHTMLOptionElementOrNull(element))
     return option->IsDisplayNone();
-  if (const ComputedStyle* style = ItemComputedStyle(element))
-    return style->Display() == EDisplay::kNone;
-  return false;
+  const ComputedStyle* style = ItemComputedStyle(element);
+  return !style || style->Display() == EDisplay::kNone;
 }
 
 const ComputedStyle* HTMLSelectElement::ItemComputedStyle(
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp
index 191857d..fc77460 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp
@@ -50,7 +50,6 @@
 #include "platform/CrossThreadFunctional.h"
 #include "platform/Histogram.h"
 #include "platform/SharedBuffer.h"
-#include "platform/WebFrameScheduler.h"
 #include "platform/bindings/RuntimeCallStats.h"
 #include "platform/bindings/V8PerIsolateData.h"
 #include "platform/heap/Handle.h"
@@ -225,7 +224,7 @@
   DCHECK(!HasInsertionPoint() || have_background_parser_);
 
   // NOTE: This pump should only ever emit buffered character tokens.
-  if (tokenizer_) {
+  if (tokenizer_ && !GetDocument()->IsPrefetchOnly()) {
     DCHECK(!have_background_parser_);
     PumpTokenizerIfPossible();
   }
@@ -639,6 +638,7 @@
 }
 
 void HTMLDocumentParser::PumpTokenizer() {
+  DCHECK(!GetDocument()->IsPrefetchOnly());
   DCHECK(!IsStopped());
   DCHECK(tokenizer_);
   DCHECK(token_);
@@ -714,6 +714,7 @@
 }
 
 void HTMLDocumentParser::ConstructTreeFromHTMLToken() {
+  DCHECK(!GetDocument()->IsPrefetchOnly());
   AtomicHTMLToken atomic_token(Token());
 
   // We clear the m_token in case constructTreeFromAtomicToken
@@ -744,6 +745,7 @@
 
 void HTMLDocumentParser::ConstructTreeFromCompactHTMLToken(
     const CompactHTMLToken& compact_token) {
+  DCHECK(!GetDocument()->IsPrefetchOnly());
   AtomicHTMLToken token(compact_token);
   tree_builder_->ConstructTree(&token);
   CheckIfBodyStylesheetAdded();
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParserTest.cpp b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParserTest.cpp
index d93a123..de7c39a2 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParserTest.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParserTest.cpp
@@ -10,6 +10,7 @@
 #include "core/loader/PrerendererClient.h"
 #include "core/loader/TextResourceDecoderBuilder.h"
 #include "core/testing/PageTestBase.h"
+#include "public/platform/WebPrerenderingSupport.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace blink {
@@ -28,6 +29,21 @@
   bool is_prefetch_only_;
 };
 
+class TestPrerenderingSupport : public WebPrerenderingSupport {
+ public:
+  TestPrerenderingSupport() { Initialize(this); }
+
+  virtual void Add(const WebPrerender&) {}
+  virtual void Cancel(const WebPrerender&) {}
+  virtual void Abandon(const WebPrerender&) {}
+  virtual void PrefetchFinished() { prefetch_finished_ = true; }
+
+  bool IsPrefetchFinished() const { return prefetch_finished_; }
+
+ private:
+  bool prefetch_finished_ = false;
+};
+
 class HTMLDocumentParserTest : public PageTestBase {
  protected:
   void SetUp() override {
@@ -43,6 +59,13 @@
     parser->SetDecoder(std::move(decoder));
     return parser;
   }
+
+  bool PrefetchFinishedCleanly() {
+    return prerendering_support_.IsPrefetchFinished();
+  }
+
+ private:
+  TestPrerenderingSupport prerendering_support_;
 };
 
 }  // namespace
@@ -62,6 +85,11 @@
       parser->AsHTMLParserScriptRunnerHostForTesting();
   EXPECT_TRUE(script_runner_host->HasPreloadScanner());
   EXPECT_EQ(HTMLTokenizer::kDataState, parser->Tokenizer()->GetState());
+  // Finishing should not cause parsing to start (verified via an internal
+  // DCHECK).
+  static_cast<DocumentParser*>(parser)->Finish();
+  EXPECT_EQ(HTMLTokenizer::kDataState, parser->Tokenizer()->GetState());
+  EXPECT_TRUE(PrefetchFinishedCleanly());
 }
 
 TEST_F(HTMLDocumentParserTest, AppendNoPrefetch) {
diff --git a/third_party/WebKit/Source/core/inspector/InspectorAnimationAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorAnimationAgent.cpp
index 354b657..9de4fe3b 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorAnimationAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorAnimationAgent.cpp
@@ -7,14 +7,14 @@
 #include <memory>
 #include "bindings/core/v8/V8BindingForCore.h"
 #include "core/animation/Animation.h"
-#include "core/animation/AnimationEffectReadOnly.h"
+#include "core/animation/AnimationEffect.h"
 #include "core/animation/AnimationEffectTiming.h"
 #include "core/animation/ComputedTimingProperties.h"
 #include "core/animation/EffectModel.h"
 #include "core/animation/ElementAnimation.h"
 #include "core/animation/ElementAnimations.h"
+#include "core/animation/KeyframeEffect.h"
 #include "core/animation/KeyframeEffectModel.h"
-#include "core/animation/KeyframeEffectReadOnly.h"
 #include "core/animation/StringKeyframe.h"
 #include "core/animation/css/CSSAnimations.h"
 #include "core/css/CSSKeyframeRule.h"
@@ -95,8 +95,7 @@
 }
 
 static std::unique_ptr<protocol::Animation::AnimationEffect>
-BuildObjectForAnimationEffect(KeyframeEffectReadOnly* effect,
-                              bool is_transition) {
+BuildObjectForAnimationEffect(KeyframeEffect* effect, bool is_transition) {
   ComputedTimingProperties computed_timing = effect->getComputedTiming();
   double delay = computed_timing.delay();
   double duration = computed_timing.duration().GetAsUnrestrictedDouble();
@@ -146,7 +145,7 @@
 }
 
 static std::unique_ptr<protocol::Animation::KeyframesRule>
-BuildObjectForAnimationKeyframes(const KeyframeEffectReadOnly* effect) {
+BuildObjectForAnimationKeyframes(const KeyframeEffect* effect) {
   if (!effect || !effect->Model() || !effect->Model()->IsKeyframeEffectModel())
     return nullptr;
   const KeyframeEffectModelBase* model = effect->Model();
@@ -177,8 +176,7 @@
   if (!animation.effect()) {
     animation_type = AnimationType::WebAnimation;
   } else {
-    const Element* element =
-        ToKeyframeEffectReadOnly(animation.effect())->target();
+    const Element* element = ToKeyframeEffect(animation.effect())->target();
     std::unique_ptr<protocol::Animation::KeyframesRule> keyframe_rule;
 
     if (!element) {
@@ -193,7 +191,7 @@
       } else {
         // Keyframe based animations
         keyframe_rule = BuildObjectForAnimationKeyframes(
-            ToKeyframeEffectReadOnly(animation.effect()));
+            ToKeyframeEffect(animation.effect()));
         animation_type = css_animations.IsAnimationForInspector(animation)
                              ? AnimationType::CSSAnimation
                              : AnimationType::WebAnimation;
@@ -201,7 +199,7 @@
     }
 
     animation_effect_object = BuildObjectForAnimationEffect(
-        ToKeyframeEffectReadOnly(animation.effect()),
+        ToKeyframeEffect(animation.effect()),
         animation_type == AnimationType::CSSTransition);
     animation_effect_object->setKeyframesRule(std::move(keyframe_rule));
   }
@@ -289,8 +287,7 @@
     blink::Animation* animation) {
   const String id = String::Number(animation->SequenceNumber());
   if (!id_to_animation_clone_.at(id)) {
-    KeyframeEffectReadOnly* old_effect =
-        ToKeyframeEffectReadOnly(animation->effect());
+    KeyframeEffect* old_effect = ToKeyframeEffect(animation->effect());
     DCHECK(old_effect->Model()->IsKeyframeEffectModel());
     KeyframeEffectModelBase* old_model = old_effect->Model();
     KeyframeEffectModelBase* new_model = nullptr;
@@ -420,8 +417,7 @@
     return response;
   if (id_to_animation_clone_.at(animation_id))
     animation = id_to_animation_clone_.at(animation_id);
-  const Element* element =
-      ToKeyframeEffectReadOnly(animation->effect())->target();
+  const Element* element = ToKeyframeEffect(animation->effect())->target();
   Document* document = element->ownerDocument();
   LocalFrame* frame = document ? document->GetFrame() : nullptr;
   ScriptState* script_state =
@@ -463,7 +459,7 @@
       id_to_animation_type_.at(String::Number(animation.SequenceNumber()));
   DCHECK_NE(type, AnimationType::WebAnimation);
 
-  KeyframeEffectReadOnly* effect = ToKeyframeEffectReadOnly(animation.effect());
+  KeyframeEffect* effect = ToKeyframeEffect(animation.effect());
   Vector<const CSSProperty*> css_properties;
   if (type == AnimationType::CSSAnimation) {
     for (const CSSProperty* property : g_animation_properties)
diff --git a/third_party/WebKit/Source/core/inspector/InspectorTraceEvents.cpp b/third_party/WebKit/Source/core/inspector/InspectorTraceEvents.cpp
index 3c6ea40..2ad1ac9 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorTraceEvents.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorTraceEvents.cpp
@@ -11,7 +11,7 @@
 #include "bindings/core/v8/ScriptSourceCode.h"
 #include "bindings/core/v8/SourceLocation.h"
 #include "core/animation/Animation.h"
-#include "core/animation/KeyframeEffectReadOnly.h"
+#include "core/animation/KeyframeEffect.h"
 #include "core/css/StyleChangeReason.h"
 #include "core/css/invalidation/InvalidationSet.h"
 #include "core/dom/DOMNodeIds.h"
@@ -1300,10 +1300,10 @@
   std::unique_ptr<TracedValue> value = TracedValue::Create();
   value->SetString("id", String::Number(animation.SequenceNumber()));
   value->SetString("state", animation.playState());
-  if (const AnimationEffectReadOnly* effect = animation.effect()) {
+  if (const AnimationEffect* effect = animation.effect()) {
     value->SetString("name", animation.id());
-    if (effect->IsKeyframeEffectReadOnly()) {
-      if (Element* target = ToKeyframeEffectReadOnly(effect)->target())
+    if (effect->IsKeyframeEffect()) {
+      if (Element* target = ToKeyframeEffect(effect)->target())
         SetNodeInfo(value.get(), target, "nodeId", "nodeName");
     }
   }
diff --git a/third_party/WebKit/Source/core/intersection_observer/IntersectionObserver.cpp b/third_party/WebKit/Source/core/intersection_observer/IntersectionObserver.cpp
index 56e2975..7c733d4 100644
--- a/third_party/WebKit/Source/core/intersection_observer/IntersectionObserver.cpp
+++ b/third_party/WebKit/Source/core/intersection_observer/IntersectionObserver.cpp
@@ -5,6 +5,7 @@
 #include "core/intersection_observer/IntersectionObserver.h"
 
 #include <algorithm>
+
 #include "base/macros.h"
 #include "bindings/core/v8/ExceptionState.h"
 #include "bindings/core/v8/V8IntersectionObserverDelegate.h"
@@ -179,7 +180,8 @@
     Element* root,
     const Vector<Length>& root_margin,
     const Vector<float>& thresholds)
-    : delegate_(&delegate),
+    : ContextClient(delegate.GetExecutionContext()),
+      delegate_(&delegate),
       root_(root),
       thresholds_(thresholds),
       top_margin_(kFixed),
@@ -363,6 +365,10 @@
   delegate_->Deliver(entries, *this);
 }
 
+bool IntersectionObserver::HasPendingActivity() const {
+  return !observations_.IsEmpty();
+}
+
 void IntersectionObserver::Trace(blink::Visitor* visitor) {
   visitor->template RegisterWeakMembers<
       IntersectionObserver, &IntersectionObserver::ClearWeakMembers>(this);
@@ -370,6 +376,7 @@
   visitor->Trace(observations_);
   visitor->Trace(entries_);
   ScriptWrappable::Trace(visitor);
+  ContextClient::Trace(visitor);
 }
 
 void IntersectionObserver::TraceWrappers(
diff --git a/third_party/WebKit/Source/core/intersection_observer/IntersectionObserver.h b/third_party/WebKit/Source/core/intersection_observer/IntersectionObserver.h
index 6fd1b5d..4fd4f60 100644
--- a/third_party/WebKit/Source/core/intersection_observer/IntersectionObserver.h
+++ b/third_party/WebKit/Source/core/intersection_observer/IntersectionObserver.h
@@ -6,7 +6,9 @@
 #define IntersectionObserver_h
 
 #include "base/callback.h"
+#include "bindings/core/v8/ActiveScriptWrappable.h"
 #include "bindings/core/v8/ExceptionState.h"
+#include "core/dom/ContextLifecycleObserver.h"
 #include "core/intersection_observer/IntersectionObservation.h"
 #include "core/intersection_observer/IntersectionObserverEntry.h"
 #include "platform/Length.h"
@@ -26,7 +28,11 @@
 class ScriptState;
 class V8IntersectionObserverCallback;
 
-class CORE_EXPORT IntersectionObserver final : public ScriptWrappable {
+class CORE_EXPORT IntersectionObserver final
+    : public ScriptWrappable,
+      public ActiveScriptWrappable<IntersectionObserver>,
+      public ContextClient {
+  USING_GARBAGE_COLLECTED_MIXIN(IntersectionObserver);
   DEFINE_WRAPPERTYPEINFO();
 
  public:
@@ -84,6 +90,9 @@
     return observations_;
   }
 
+  // ScriptWrappable override:
+  bool HasPendingActivity() const override;
+
   void Trace(blink::Visitor*);
   void TraceWrappers(const ScriptWrappableVisitor*) const;
 
diff --git a/third_party/WebKit/Source/core/intersection_observer/IntersectionObserver.idl b/third_party/WebKit/Source/core/intersection_observer/IntersectionObserver.idl
index d7858c9..180b996 100644
--- a/third_party/WebKit/Source/core/intersection_observer/IntersectionObserver.idl
+++ b/third_party/WebKit/Source/core/intersection_observer/IntersectionObserver.idl
@@ -9,6 +9,7 @@
 // https://wicg.github.io/IntersectionObserver/#intersection-observer-interface
 
 [
+    ActiveScriptWrappable,
     Constructor(IntersectionObserverCallback callback, optional IntersectionObserverInit options),
     ConstructorCallWith=ScriptState,
     MeasureAs=IntersectionObserver_Constructor,
diff --git a/third_party/WebKit/Source/core/layout/ColumnBalancer.cpp b/third_party/WebKit/Source/core/layout/ColumnBalancer.cpp
index ccdf8bd..7abbcb84 100644
--- a/third_party/WebKit/Source/core/layout/ColumnBalancer.cpp
+++ b/third_party/WebKit/Source/core/layout/ColumnBalancer.cpp
@@ -110,6 +110,10 @@
     LayoutUnit offset_for_this_child =
         child_box.IsTableRow() ? LayoutUnit() : logical_top;
 
+    // Include this child's offset in the flow thread offset. Note that rather
+    // than subtracting the offset again when done, we set it back to the old
+    // value. This matters in saturated arithmetic situations.
+    auto old_flow_thread_offset = flow_thread_offset_;
     flow_thread_offset_ += offset_for_this_child;
 
     ExamineBoxAfterEntering(child_box, logical_height,
@@ -122,14 +126,15 @@
       // We need to get to the border edge before processing content inside
       // this child. If the child is floated, we're currently at the margin
       // edge.
+      auto old_flow_thread_offset = flow_thread_offset_;
       flow_thread_offset_ += border_edge_offset;
       TraverseSubtree(child_box);
-      flow_thread_offset_ -= border_edge_offset;
+      flow_thread_offset_ = old_flow_thread_offset;
     }
     previous_break_after_value = child_box.BreakAfter();
     ExamineBoxBeforeLeaving(child_box, logical_height);
 
-    flow_thread_offset_ -= offset_for_this_child;
+    flow_thread_offset_ = old_flow_thread_offset;
   }
 }
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
index f10cbb6..a7d6bd20 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
@@ -685,22 +685,13 @@
     if (LocalFrameView* frame_view = GetFrameView()) {
       HTMLFrameOwnerElement* owner_element = GetDocument().LocalOwner();
       if (!IsDisallowedAutoscroll(owner_element, frame_view)) {
-        if (params.make_visible_in_visual_viewport) {
-          // RootFrameViewport::ScrollIntoView expects a rect in layout
-          // viewport content coordinates.
-          if (IsLayoutView() && GetFrame()->IsMainFrame() &&
-              RuntimeEnabledFeatures::RootLayerScrollingEnabled()) {
-            absolute_rect_to_scroll.Move(
-                LayoutSize(GetScrollableArea()->GetScrollOffset()));
-          }
-          absolute_rect_to_scroll =
-              frame_view->GetScrollableArea()->ScrollIntoView(
-                  absolute_rect_to_scroll, params);
-        } else {
-          absolute_rect_to_scroll =
-              frame_view->LayoutViewportScrollableArea()->ScrollIntoView(
-                  absolute_rect_to_scroll, params);
-        }
+        ScrollableArea* area_to_scroll =
+            params.make_visible_in_visual_viewport
+                ? frame_view->GetScrollableArea()
+                : frame_view->LayoutViewportScrollableArea();
+        absolute_rect_to_scroll =
+            area_to_scroll->ScrollIntoView(absolute_rect_to_scroll, params);
+
         if (params.is_for_scroll_sequence)
           absolute_rect_to_scroll.Move(PendingOffsetToScroll());
         if (owner_element && owner_element->GetLayoutObject()) {
@@ -1066,10 +1057,10 @@
   if (!frame_view)
     return;
 
-  IntPoint position_in_content =
-      frame_view->RootFrameToContents(position_in_root_frame);
+  IntPoint absolute_position =
+      frame_view->RootFrameToAbsolute(position_in_root_frame);
   ScrollRectToVisibleRecursive(
-      LayoutRect(position_in_content, LayoutSize(1, 1)),
+      LayoutRect(absolute_position, LayoutSize(1, 1)),
       WebScrollIntoViewParams(ScrollAlignment::kAlignToEdgeIfNeeded,
                               ScrollAlignment::kAlignToEdgeIfNeeded,
                               kUserScroll));
diff --git a/third_party/WebKit/Source/core/layout/LayoutFlowThread.cpp b/third_party/WebKit/Source/core/layout/LayoutFlowThread.cpp
index 2ab81c87..2080cdc6 100644
--- a/third_party/WebKit/Source/core/layout/LayoutFlowThread.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutFlowThread.cpp
@@ -238,8 +238,7 @@
 
 LayoutRect LayoutFlowThread::FragmentsBoundingBox(
     const LayoutRect& layer_bounding_box) const {
-  DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV175Enabled() ||
-         !column_sets_invalidated_);
+  DCHECK(!column_sets_invalidated_);
 
   LayoutRect result;
   for (auto* column_set : multi_column_set_list_)
diff --git a/third_party/WebKit/Source/core/layout/LayoutGrid.cpp b/third_party/WebKit/Source/core/layout/LayoutGrid.cpp
index 14cfeb6e..7ec8f8e 100644
--- a/third_party/WebKit/Source/core/layout/LayoutGrid.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutGrid.cpp
@@ -684,14 +684,16 @@
   if (free_space <= 0)
     return auto_repeat_track_list_length;
 
-  size_t repetitions =
-      1 + (free_space / (auto_repeat_tracks_size + gap_size)).ToInt();
+  LayoutUnit auto_repeat_size_with_gap = auto_repeat_tracks_size + gap_size;
+
+  size_t repetitions = 1 + (free_space / auto_repeat_size_with_gap).ToInt();
+  free_space -= auto_repeat_size_with_gap * (repetitions - 1);
 
   // Provided the grid container does not have a definite size or max-size in
   // the relevant axis, if the min size is definite then the number of
   // repetitions is the largest possible positive integer that fulfills that
   // minimum requirement.
-  if (needs_to_fulfill_minimum_size)
+  if (needs_to_fulfill_minimum_size && free_space)
     ++repetitions;
 
   return repetitions * auto_repeat_track_list_length;
diff --git a/third_party/WebKit/Source/core/layout/LayoutListBox.cpp b/third_party/WebKit/Source/core/layout/LayoutListBox.cpp
index 4da650d..86171c95 100644
--- a/third_party/WebKit/Source/core/layout/LayoutListBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutListBox.cpp
@@ -130,15 +130,15 @@
     min_logical_width = LayoutUnit();
 }
 
-void LayoutListBox::ScrollToRect(const LayoutRect& rect) {
+void LayoutListBox::ScrollToRect(const LayoutRect& absolute_rect) {
   if (HasOverflowClip()) {
     DCHECK(Layer());
     DCHECK(Layer()->GetScrollableArea());
     Layer()->GetScrollableArea()->ScrollIntoView(
-        rect, WebScrollIntoViewParams(ScrollAlignment::kAlignToEdgeIfNeeded,
-                                      ScrollAlignment::kAlignToEdgeIfNeeded,
-                                      kProgrammaticScroll, false,
-                                      kScrollBehaviorInstant));
+        absolute_rect, WebScrollIntoViewParams(
+                           ScrollAlignment::kAlignToEdgeIfNeeded,
+                           ScrollAlignment::kAlignToEdgeIfNeeded,
+                           kProgrammaticScroll, false, kScrollBehaviorInstant));
   }
 }
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableCell.cpp b/third_party/WebKit/Source/core/layout/LayoutTableCell.cpp
index 1c63788..28d62e9 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableCell.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTableCell.cpp
@@ -312,21 +312,39 @@
 }
 
 LayoutUnit LayoutTableCell::PaddingTop() const {
-  return ComputedCSSPaddingTop() + LogicalIntrinsicPaddingToPhysical().Top();
+  auto result =
+      ComputedCSSPaddingTop() + LogicalIntrinsicPaddingToPhysical().Top();
+  // TODO(crbug.com/377847): The ToInt call should be removed when Table is
+  // sub-pixel aware.
+  return Style()->IsHorizontalWritingMode() ? LayoutUnit(result.ToInt())
+                                            : result;
 }
 
 LayoutUnit LayoutTableCell::PaddingBottom() const {
-  return ComputedCSSPaddingBottom() +
-         LogicalIntrinsicPaddingToPhysical().Bottom();
+  auto result =
+      ComputedCSSPaddingBottom() + LogicalIntrinsicPaddingToPhysical().Bottom();
+  // TODO(crbug.com/377847): The ToInt call should be removed when Table is
+  // sub-pixel aware.
+  return Style()->IsHorizontalWritingMode() ? LayoutUnit(result.ToInt())
+                                            : result;
 }
 
 LayoutUnit LayoutTableCell::PaddingLeft() const {
-  return ComputedCSSPaddingLeft() + LogicalIntrinsicPaddingToPhysical().Left();
+  auto result =
+      ComputedCSSPaddingLeft() + LogicalIntrinsicPaddingToPhysical().Left();
+  // TODO(crbug.com/377847): The ToInt call should be removed when Table is
+  // sub-pixel aware.
+  return Style()->IsHorizontalWritingMode() ? result
+                                            : LayoutUnit(result.ToInt());
 }
 
 LayoutUnit LayoutTableCell::PaddingRight() const {
-  return ComputedCSSPaddingRight() +
-         LogicalIntrinsicPaddingToPhysical().Right();
+  auto result =
+      ComputedCSSPaddingRight() + LogicalIntrinsicPaddingToPhysical().Right();
+  // TODO(crbug.com/377847): The ToInt call should be removed when Table is
+  // sub-pixel aware.
+  return Style()->IsHorizontalWritingMode() ? result
+                                            : LayoutUnit(result.ToInt());
 }
 
 void LayoutTableCell::SetOverrideLogicalContentHeightFromRowHeight(
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node_test.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node_test.cc
index 3501653..6242ee7 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node_test.cc
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node_test.cc
@@ -22,7 +22,7 @@
  public:
   using NGInlineNode::NGInlineNode;
 
-  String& Text() { return MutableData()->text_content_; }
+  std::string Text() const { return Data().text_content_.Utf8().data(); }
   Vector<NGInlineItem>& Items() { return MutableData()->items_; }
   static Vector<NGInlineItem>& Items(NGInlineNodeData& data) {
     return data.items_;
@@ -173,6 +173,44 @@
   EXPECT_EQ(3u, items.size());
 }
 
+TEST_F(NGInlineNodeTest, CollectInlinesFloat) {
+  SetupHtml("t",
+            "<div id=t>"
+            "abc"
+            "<span style='float:right'>DEF</span>"
+            "ghi"
+            "<span style='float:left'>JKL</span>"
+            "mno"
+            "</div>");
+  NGInlineNodeForTest node = CreateInlineNode();
+  node.CollectInlines();
+  EXPECT_EQ(u8"abc\uFFFCghi\uFFFCmno", node.Text())
+      << "floats are appeared as an object replacement character";
+  Vector<NGInlineItem>& items = node.Items();
+  ASSERT_EQ(5u, items.size());
+  TEST_ITEM_TYPE_OFFSET(items[0], kText, 0u, 3u);
+  TEST_ITEM_TYPE_OFFSET(items[1], kFloating, 3u, 4u);
+  TEST_ITEM_TYPE_OFFSET(items[2], kText, 4u, 7u);
+  TEST_ITEM_TYPE_OFFSET(items[3], kFloating, 7u, 8u);
+  TEST_ITEM_TYPE_OFFSET(items[4], kText, 8u, 11u);
+}
+
+TEST_F(NGInlineNodeTest, CollectInlinesInlineBlock) {
+  SetupHtml("t",
+            "<div id=t>"
+            "abc<span style='display:inline-block'>DEF</span>jkl"
+            "</div>");
+  NGInlineNodeForTest node = CreateInlineNode();
+  node.CollectInlines();
+  EXPECT_EQ(u8"abc\uFFFCjkl", node.Text())
+      << "inline-block is appeared as an object replacement character";
+  Vector<NGInlineItem>& items = node.Items();
+  ASSERT_EQ(3u, items.size());
+  TEST_ITEM_TYPE_OFFSET(items[0], kText, 0u, 3u);
+  TEST_ITEM_TYPE_OFFSET(items[1], kAtomicInline, 3u, 4u);
+  TEST_ITEM_TYPE_OFFSET(items[2], kText, 4u, 7u);
+}
+
 TEST_F(NGInlineNodeTest, CollectInlinesUTF16) {
   SetupHtml("t", u"<div id=t>Hello \u3042</div>");
   NGInlineNodeForTest node = CreateInlineNode();
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_column_layout_algorithm_test.cc b/third_party/WebKit/Source/core/layout/ng/ng_column_layout_algorithm_test.cc
index e2f0f4f..b557120 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_column_layout_algorithm_test.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_column_layout_algorithm_test.cc
@@ -16,6 +16,14 @@
   void SetUp() override {
     NGBaseLayoutAlgorithmTest::SetUp();
     style_ = ComputedStyle::Create();
+    was_block_fragmentation_enabled_ =
+        RuntimeEnabledFeatures::LayoutNGBlockFragmentationEnabled();
+    RuntimeEnabledFeatures::SetLayoutNGBlockFragmentationEnabled(true);
+  }
+
+  void TearDown() override {
+    RuntimeEnabledFeatures::SetLayoutNGBlockFragmentationEnabled(
+        was_block_fragmentation_enabled_);
   }
 
   scoped_refptr<NGPhysicalBoxFragment> RunBlockLayoutAlgorithm(
@@ -52,6 +60,7 @@
   }
 
   scoped_refptr<ComputedStyle> style_;
+  bool was_block_fragmentation_enabled_ = false;
 };
 
 TEST_F(NGColumnLayoutAlgorithmTest, EmptyMulticol) {
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceClipper.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceClipper.cpp
index 18a2d17..64aa5fb 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceClipper.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceClipper.cpp
@@ -114,8 +114,9 @@
   cached_paint_record_.reset();
   local_clip_bounds_ = FloatRect();
   MarkAllClientsForInvalidation(
-      mark_for_invalidation ? kLayoutInvalidation | kBoundariesInvalidation
-                            : kParentOnlyInvalidation);
+      mark_for_invalidation ? SVGResourceClient::kLayoutInvalidation |
+                                  SVGResourceClient::kBoundariesInvalidation
+                            : SVGResourceClient::kParentOnlyInvalidation);
 }
 
 Optional<Path> LayoutSVGResourceClipper::AsPath() {
@@ -268,7 +269,8 @@
 }
 
 void LayoutSVGResourceClipper::WillBeDestroyed() {
-  MarkAllClientsForInvalidation(kBoundariesInvalidation | kPaintInvalidation);
+  MarkAllClientsForInvalidation(SVGResourceClient::kBoundariesInvalidation |
+                                SVGResourceClient::kPaintInvalidation);
   LayoutSVGResourceContainer::WillBeDestroyed();
 }
 
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceContainer.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceContainer.cpp
index 9fffb658..9893905 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceContainer.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceContainer.cpp
@@ -115,8 +115,10 @@
   completed_invalidations_mask_ |= invalidation_mask;
 
   is_invalidating_ = true;
-  bool needs_layout = invalidation_mask & kLayoutInvalidation;
-  bool mark_for_invalidation = invalidation_mask & ~kParentOnlyInvalidation;
+  bool needs_layout =
+      invalidation_mask & SVGResourceClient::kLayoutInvalidation;
+  bool mark_for_invalidation =
+      invalidation_mask & ~SVGResourceClient::kParentOnlyInvalidation;
 
   // Invalidate clients registered on the this object (via SVGResources).
   for (auto* client : clients_) {
@@ -135,7 +137,7 @@
 
   // Invalidate clients registered via an SVGResource.
   if (resource)
-    resource->NotifyContentChanged();
+    resource->NotifyContentChanged(invalidation_mask);
 
   is_invalidating_ = false;
 }
@@ -143,7 +145,7 @@
 void LayoutSVGResourceContainer::MarkClientForInvalidation(
     LayoutObject& client,
     InvalidationModeMask invalidation_mask) {
-  if (invalidation_mask & kPaintInvalidation) {
+  if (invalidation_mask & SVGResourceClient::kPaintInvalidation) {
     // Since LayoutSVGInlineTexts don't have SVGResources (they use their
     // parent's), they will not be notified of changes to paint servers. So
     // if the client is one that could have a LayoutSVGInlineText use a
@@ -156,7 +158,7 @@
     client.SetNeedsPaintPropertyUpdate();
   }
 
-  if (invalidation_mask & kBoundariesInvalidation)
+  if (invalidation_mask & SVGResourceClient::kBoundariesInvalidation)
     client.SetNeedsBoundariesUpdate();
 }
 
@@ -207,11 +209,9 @@
 
   ToSVGElement(object.GetNode())
       ->NotifyIncomingReferences([needs_layout](SVGElement& element) {
-        LayoutObject* layout_object = element.GetLayoutObject();
-        if (!layout_object)
-          return;
+        DCHECK(element.GetLayoutObject());
         LayoutSVGResourceContainer::MarkForLayoutAndParentResourceInvalidation(
-            *layout_object, needs_layout);
+            *element.GetLayoutObject(), needs_layout);
       });
 }
 
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceContainer.h b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceContainer.h
index 4fcefdc7..f24b7b2 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceContainer.h
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceContainer.h
@@ -21,6 +21,7 @@
 #define LayoutSVGResourceContainer_h
 
 #include "core/layout/svg/LayoutSVGHiddenContainer.h"
+#include "core/svg/SVGResourceClient.h"
 
 namespace blink {
 
@@ -36,8 +37,6 @@
   kClipperResourceType
 };
 
-typedef unsigned InvalidationModeMask;
-
 class LayoutSVGResourceContainer : public LayoutSVGHiddenContainer {
  public:
   explicit LayoutSVGResourceContainer(SVGElement*);
@@ -76,14 +75,6 @@
   static void MarkForLayoutAndParentResourceInvalidation(
       LayoutObject&,
       bool needs_layout = true);
-
-  // When adding modes, make sure we don't overflow m_invalidationMask below.
-  enum InvalidationMode {
-    kLayoutInvalidation = 1 << 0,
-    kBoundariesInvalidation = 1 << 1,
-    kPaintInvalidation = 1 << 2,
-    kParentOnlyInvalidation = 1 << 3
-  };
   static void MarkClientForInvalidation(LayoutObject&, InvalidationModeMask);
 
   void ClearInvalidationMask() { completed_invalidations_mask_ = 0; }
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceFilter.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceFilter.cpp
index 996dd3884..5f0602d 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceFilter.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceFilter.cpp
@@ -70,8 +70,9 @@
   // display item invalidation is needed here.
   DisposeFilterMap();
   MarkAllClientsForInvalidation(
-      mark_for_invalidation ? kLayoutInvalidation | kBoundariesInvalidation
-                            : kParentOnlyInvalidation);
+      mark_for_invalidation ? SVGResourceClient::kLayoutInvalidation |
+                                  SVGResourceClient::kBoundariesInvalidation
+                            : SVGResourceClient::kParentOnlyInvalidation);
 }
 
 bool LayoutSVGResourceFilter::RemoveClientFromCache(LayoutObject& client) {
@@ -128,11 +129,12 @@
     node_map->InvalidateDependentEffects(effect);
 
     // Issue paint invalidations for the image on the screen.
-    MarkClientForInvalidation(*filter.key, kPaintInvalidation);
+    MarkClientForInvalidation(*filter.key,
+                              SVGResourceClient::kPaintInvalidation);
   }
   if (LocalSVGResource* resource =
           ToSVGFilterElement(GetElement())->AssociatedResource())
-    resource->NotifyContentChanged();
+    resource->NotifyContentChanged(SVGResourceClient::kPaintInvalidation);
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceGradient.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceGradient.cpp
index dfec5bca..73323d9 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceGradient.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceGradient.cpp
@@ -36,7 +36,8 @@
   should_collect_gradient_attributes_ = true;
   ToSVGGradientElement(*GetElement()).InvalidateDependentGradients();
   MarkAllClientsForInvalidation(
-      mark_for_invalidation ? kPaintInvalidation : kParentOnlyInvalidation);
+      mark_for_invalidation ? SVGResourceClient::kPaintInvalidation
+                            : SVGResourceClient::kParentOnlyInvalidation);
 }
 
 bool LayoutSVGResourceGradient::RemoveClientFromCache(LayoutObject& client) {
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceMarker.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceMarker.cpp
index 3fe4d40..0879219e9 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceMarker.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceMarker.cpp
@@ -49,8 +49,9 @@
 void LayoutSVGResourceMarker::RemoveAllClientsFromCache(
     bool mark_for_invalidation) {
   MarkAllClientsForInvalidation(
-      mark_for_invalidation ? kLayoutInvalidation | kBoundariesInvalidation
-                            : kParentOnlyInvalidation);
+      mark_for_invalidation ? SVGResourceClient::kLayoutInvalidation |
+                                  SVGResourceClient::kBoundariesInvalidation
+                            : SVGResourceClient::kParentOnlyInvalidation);
 }
 
 FloatRect LayoutSVGResourceMarker::MarkerBoundaries(
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceMasker.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceMasker.cpp
index 5e3aa6a..548710fe 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceMasker.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceMasker.cpp
@@ -39,8 +39,9 @@
   cached_paint_record_.reset();
   mask_content_boundaries_ = FloatRect();
   MarkAllClientsForInvalidation(
-      mark_for_invalidation ? kLayoutInvalidation | kBoundariesInvalidation
-                            : kParentOnlyInvalidation);
+      mark_for_invalidation ? SVGResourceClient::kLayoutInvalidation |
+                                  SVGResourceClient::kBoundariesInvalidation
+                            : SVGResourceClient::kParentOnlyInvalidation);
 }
 
 sk_sp<const PaintRecord> LayoutSVGResourceMasker::CreatePaintRecord(
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourcePattern.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourcePattern.cpp
index 452560a..d35f7ed 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourcePattern.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourcePattern.cpp
@@ -56,7 +56,8 @@
   pattern_map_.clear();
   should_collect_pattern_attributes_ = true;
   MarkAllClientsForInvalidation(
-      mark_for_invalidation ? kPaintInvalidation : kParentOnlyInvalidation);
+      mark_for_invalidation ? SVGResourceClient::kPaintInvalidation
+                            : SVGResourceClient::kParentOnlyInvalidation);
 }
 
 bool LayoutSVGResourcePattern::RemoveClientFromCache(LayoutObject& client) {
diff --git a/third_party/WebKit/Source/core/layout/svg/SVGResources.cpp b/third_party/WebKit/Source/core/layout/svg/SVGResources.cpp
index db68c3a6..a66a116 100644
--- a/third_party/WebKit/Source/core/layout/svg/SVGResources.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/SVGResources.cpp
@@ -302,12 +302,11 @@
     clipper->RemoveClientFromCache(client);
   if (LayoutSVGResourceFilter* filter = clipper_filter_masker_data_->filter) {
     if (filter->RemoveClientFromCache(client))
-      invalidation_flags |= LayoutSVGResourceContainer::kPaintInvalidation;
+      invalidation_flags |= SVGResourceClient::kPaintInvalidation;
   }
   if (LayoutSVGResourceMasker* masker = clipper_filter_masker_data_->masker)
     masker->RemoveClientFromCache(client);
-  return invalidation_flags |
-         LayoutSVGResourceContainer::kBoundariesInvalidation;
+  return invalidation_flags | SVGResourceClient::kBoundariesInvalidation;
 }
 
 InvalidationModeMask SVGResources::RemoveClientFromCache(
@@ -322,7 +321,7 @@
     linked_resource_->RemoveClientFromCache(client);
     // The only linked resources are gradients and patterns, i.e
     // always a paint server.
-    return LayoutSVGResourceContainer::kPaintInvalidation;
+    return SVGResourceClient::kPaintInvalidation;
   }
 
   InvalidationModeMask invalidation_flags =
@@ -335,7 +334,7 @@
       marker->RemoveClientFromCache(client);
     if (LayoutSVGResourceMarker* marker = marker_data_->marker_end)
       marker->RemoveClientFromCache(client);
-    invalidation_flags |= LayoutSVGResourceContainer::kBoundariesInvalidation;
+    invalidation_flags |= SVGResourceClient::kBoundariesInvalidation;
   }
 
   if (fill_stroke_data_) {
@@ -343,7 +342,7 @@
       fill->RemoveClientFromCache(client);
     if (LayoutSVGResourcePaintServer* stroke = fill_stroke_data_->stroke)
       stroke->RemoveClientFromCache(client);
-    invalidation_flags |= LayoutSVGResourceContainer::kPaintInvalidation;
+    invalidation_flags |= SVGResourceClient::kPaintInvalidation;
   }
 
   return invalidation_flags;
diff --git a/third_party/WebKit/Source/core/leak_detector/WebLeakDetector.cpp b/third_party/WebKit/Source/core/leak_detector/WebLeakDetector.cpp
index d6dd54d..32a80ce4 100644
--- a/third_party/WebKit/Source/core/leak_detector/WebLeakDetector.cpp
+++ b/third_party/WebKit/Source/core/leak_detector/WebLeakDetector.cpp
@@ -99,6 +99,8 @@
       InstanceCounters::kWorkerGlobalScopeCounter);
   result.number_of_live_ua_css_resources =
       InstanceCounters::CounterValue(InstanceCounters::kUACSSResourceCounter);
+  result.number_of_live_resource_fetchers =
+      InstanceCounters::CounterValue(InstanceCounters::kResourceFetcherCounter);
 
   client_->OnLeakDetectionComplete(result);
   // Reset the client for BlinkLeakDetector
diff --git a/third_party/WebKit/Source/core/loader/DocumentLoadTiming.cpp b/third_party/WebKit/Source/core/loader/DocumentLoadTiming.cpp
index 1986d87..1da0ae2 100644
--- a/third_party/WebKit/Source/core/loader/DocumentLoadTiming.cpp
+++ b/third_party/WebKit/Source/core/loader/DocumentLoadTiming.cpp
@@ -100,21 +100,31 @@
   DCHECK(!reference_wall_time_);
   EnsureReferenceTimesSet();
   navigation_start_ = reference_monotonic_time_;
-  TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "navigationStart",
-                                   navigation_start_, "frame",
-                                   ToTraceValue(GetFrame()));
+  TRACE_EVENT_MARK_WITH_TIMESTAMP2(
+      "blink.user_timing", "navigationStart", navigation_start_, "frame",
+      ToTraceValue(GetFrame()), "data", GetNavigationStartTracingData());
   NotifyDocumentTimingChanged();
 }
 
+std::unique_ptr<TracedValue> DocumentLoadTiming::GetNavigationStartTracingData()
+    const {
+  std::unique_ptr<TracedValue> data = TracedValue::Create();
+  data->SetString("documentLoaderURL",
+                  document_loader_ ? document_loader_->Url().GetString() : "");
+  data->SetBoolean("isLoadingMainFrame",
+                   GetFrame() ? GetFrame()->IsMainFrame() : false);
+  return data;
+}
+
 void DocumentLoadTiming::SetNavigationStart(TimeTicks navigation_start) {
   // |m_referenceMonotonicTime| and |m_referenceWallTime| represent
   // navigationStart. We must set these to the current time if they haven't
   // been set yet in order to have a valid reference time in both units.
   EnsureReferenceTimesSet();
   navigation_start_ = navigation_start;
-  TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing", "navigationStart",
-                                   navigation_start_, "frame",
-                                   ToTraceValue(GetFrame()));
+  TRACE_EVENT_MARK_WITH_TIMESTAMP2(
+      "blink.user_timing", "navigationStart", navigation_start_, "frame",
+      ToTraceValue(GetFrame()), "data", GetNavigationStartTracingData());
 
   // The reference times are adjusted based on the embedder's navigationStart.
   DCHECK(!reference_monotonic_time_.is_null());
diff --git a/third_party/WebKit/Source/core/loader/DocumentLoadTiming.h b/third_party/WebKit/Source/core/loader/DocumentLoadTiming.h
index 4a198bc..fecfc13 100644
--- a/third_party/WebKit/Source/core/loader/DocumentLoadTiming.h
+++ b/third_party/WebKit/Source/core/loader/DocumentLoadTiming.h
@@ -28,6 +28,7 @@
 
 #include "core/CoreExport.h"
 #include "platform/heap/Handle.h"
+#include "platform/instrumentation/tracing/TracedValue.h"
 #include "platform/wtf/Time.h"
 
 namespace blink {
@@ -96,6 +97,7 @@
   void NotifyDocumentTimingChanged();
   void EnsureReferenceTimesSet();
   LocalFrame* GetFrame() const;
+  std::unique_ptr<TracedValue> GetNavigationStartTracingData() const;
 
   TimeTicks reference_monotonic_time_;
   double reference_wall_time_;
diff --git a/third_party/WebKit/Source/core/loader/DocumentLoader.cpp b/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
index 801fab3..db1d850 100644
--- a/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
@@ -68,7 +68,7 @@
 #include "core/probe/CoreProbes.h"
 #include "core/timing/DOMWindowPerformance.h"
 #include "core/timing/WindowPerformance.h"
-#include "platform/WebFrameScheduler.h"
+#include "platform/FrameScheduler.h"
 #include "platform/feature_policy/FeaturePolicy.h"
 #include "platform/loader/fetch/FetchParameters.h"
 #include "platform/loader/fetch/FetchUtils.h"
@@ -332,7 +332,7 @@
     history_item_->SetScrollRestorationType(scroll_restoration_type);
   }
   HistoryCommitType commit_type = LoadTypeToCommitType(type);
-  frame_->FrameScheduler()->DidCommitProvisionalLoad(
+  frame_->GetFrameScheduler()->DidCommitProvisionalLoad(
       commit_type == kHistoryInertCommit, type == kFrameLoadTypeReload,
       frame_->IsLocalRoot());
   GetLocalFrameClient().DispatchDidNavigateWithinPage(
@@ -958,7 +958,7 @@
   }
 
   HistoryCommitType commit_type = LoadTypeToCommitType(load_type_);
-  frame_->FrameScheduler()->DidCommitProvisionalLoad(
+  frame_->GetFrameScheduler()->DidCommitProvisionalLoad(
       commit_type == kHistoryInertCommit, load_type_ == kFrameLoadTypeReload,
       frame_->IsLocalRoot());
   GetLocalFrameClient().DispatchDidCommitLoad(history_item_.Get(), commit_type,
diff --git a/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp b/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp
index 499c85b2..673c9a2 100644
--- a/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp
@@ -154,14 +154,13 @@
 
 // static
 void DocumentThreadableLoader::LoadResourceSynchronously(
-    Document& document,
+    ThreadableLoadingContext& loading_context,
     const ResourceRequest& request,
     ThreadableLoaderClient& client,
     const ThreadableLoaderOptions& options,
     const ResourceLoaderOptions& resource_loader_options) {
-  (new DocumentThreadableLoader(*ThreadableLoadingContext::Create(document),
-                                &client, kLoadSynchronously, options,
-                                resource_loader_options))
+  (new DocumentThreadableLoader(loading_context, &client, kLoadSynchronously,
+                                options, resource_loader_options))
       ->Start(request);
 }
 
@@ -1264,9 +1263,14 @@
     ResourceLoaderOptions resource_loader_options) {
   FetchParameters fetch_params(request, resource_loader_options);
   if (request.GetFetchRequestMode() ==
-      network::mojom::FetchRequestMode::kNoCORS)
+      network::mojom::FetchRequestMode::kNoCORS) {
     fetch_params.SetOriginRestriction(FetchParameters::kNoOriginRestriction);
-  Resource* resource = RawResource::FetchSynchronously(
+  }
+  if (options_.timeout_milliseconds > 0) {
+    fetch_params.MutableResourceRequest().SetTimeoutInterval(
+        options_.timeout_milliseconds / 1000.0);
+  }
+  RawResource* resource = RawResource::FetchSynchronously(
       fetch_params, loading_context_->GetResourceFetcher());
   ResourceResponse response = resource->GetResponse();
   unsigned long identifier = resource->Identifier();
@@ -1321,6 +1325,12 @@
   if (!client_)
     return;
 
+  WTF::Optional<int64_t> downloaded_file_length =
+      resource->DownloadedFileLength();
+  if (downloaded_file_length) {
+    client_->DidDownloadData(*downloaded_file_length);
+  }
+
   HandleSuccessfulFinish(identifier, 0.0);
 }
 
diff --git a/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.h b/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.h
index bbcfffd..3d73ff21 100644
--- a/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.h
+++ b/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.h
@@ -61,7 +61,7 @@
   USING_GARBAGE_COLLECTED_MIXIN(DocumentThreadableLoader);
 
  public:
-  static void LoadResourceSynchronously(Document&,
+  static void LoadResourceSynchronously(ThreadableLoadingContext&,
                                         const ResourceRequest&,
                                         ThreadableLoaderClient&,
                                         const ThreadableLoaderOptions&,
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
index d7676d24..e869abcb 100644
--- a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
+++ b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
@@ -317,10 +317,10 @@
   return GetFrame()->GetTaskRunner(TaskType::kNetworking);
 }
 
-WebFrameScheduler* FrameFetchContext::GetFrameScheduler() const {
+FrameScheduler* FrameFetchContext::GetFrameScheduler() const {
   if (IsDetached())
     return nullptr;
-  return GetFrame()->FrameScheduler();
+  return GetFrame()->GetFrameScheduler();
 }
 
 KURL FrameFetchContext::GetSiteForCookies() const {
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContext.h b/third_party/WebKit/Source/core/loader/FrameFetchContext.h
index d2a54fd..6382c786 100644
--- a/third_party/WebKit/Source/core/loader/FrameFetchContext.h
+++ b/third_party/WebKit/Source/core/loader/FrameFetchContext.h
@@ -192,7 +192,7 @@
   LocalFrame* FrameOfImportsController() const;
 
   // FetchContext overrides:
-  WebFrameScheduler* GetFrameScheduler() const override;
+  FrameScheduler* GetFrameScheduler() const override;
   scoped_refptr<base::SingleThreadTaskRunner> GetLoadingTaskRunner() override;
 
   // BaseFetchContext overrides:
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp b/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp
index d1286fef..87c824e6 100644
--- a/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp
+++ b/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp
@@ -32,6 +32,7 @@
 
 #include <memory>
 #include "core/dom/Document.h"
+#include "core/frame/AdTracker.h"
 #include "core/frame/FrameOwner.h"
 #include "core/frame/FrameTypes.h"
 #include "core/frame/LocalFrameView.h"
@@ -227,6 +228,26 @@
     return reason;
   }
 
+  bool DispatchWillSendRequestAndVerifyIsAd(const KURL& url) {
+    ResourceRequest request(url);
+    ResourceResponse response;
+    FetchInitiatorInfo initiator_info;
+
+    fetch_context->DispatchWillSendRequest(1, request, response,
+                                           Resource::kImage, initiator_info);
+    return request.IsAdResource();
+  }
+
+  void AppendExecutingScriptToAdTracker(const String& url) {
+    AdTracker* ad_tracker = document->GetFrame()->GetAdTracker();
+    ad_tracker->WillExecuteScript(url);
+  }
+
+  void AppendAdScriptToAdTracker(const KURL& ad_script_url) {
+    AdTracker* ad_tracker = document->GetFrame()->GetAdTracker();
+    ad_tracker->AppendToKnownAdScripts(ad_script_url);
+  }
+
  private:
   ResourceRequestBlockedReason CanRequestInternal(
       SecurityViolationReportingPolicy reporting_policy) {
@@ -1273,6 +1294,27 @@
   EXPECT_EQ(0, GetFilteredLoadCallCount());
 }
 
+// Tests that if a subresource is allowed as per subresource filter ruleset and
+// is not fetched from a frame that is tagged as an ad, then the subresource
+// should be tagged as ad if one of the executing scripts is tagged as an ad.
+TEST_F(FrameFetchContextSubresourceFilterTest,
+       AdTaggingBasedOnExecutingScript) {
+  SetFilterPolicy(WebDocumentSubresourceFilter::kAllow,
+                  false /* is_associated_with_ad_subframe */);
+
+  KURL ad_script_url("https://example.com/bar.js");
+  AppendAdScriptToAdTracker(ad_script_url);
+  AppendExecutingScriptToAdTracker(ad_script_url.GetString());
+
+  EXPECT_EQ(ResourceRequestBlockedReason::kNone,
+            CanRequestAndVerifyIsAd(false));
+  EXPECT_EQ(0, GetFilteredLoadCallCount());
+
+  // After WillSendRequest probe, it should be marked as an ad.
+  EXPECT_TRUE(DispatchWillSendRequestAndVerifyIsAd(
+      KURL("https://www.example.com/image.jpg")));
+}
+
 TEST_F(FrameFetchContextTest, AddAdditionalRequestHeadersWhenDetached) {
   const KURL document_url("https://www2.example.com/fuga/hoge.html");
   const String origin = "https://www2.example.com";
diff --git a/third_party/WebKit/Source/core/loader/FrameLoader.cpp b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
index e0180965..36c9302 100644
--- a/third_party/WebKit/Source/core/loader/FrameLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
@@ -78,9 +78,9 @@
 #include "core/probe/CoreProbes.h"
 #include "core/svg/graphics/SVGImage.h"
 #include "core/xml/parser/XMLDocumentParser.h"
+#include "platform/FrameScheduler.h"
 #include "platform/Histogram.h"
 #include "platform/InstanceCounters.h"
-#include "platform/WebFrameScheduler.h"
 #include "platform/bindings/DOMWrapperWorld.h"
 #include "platform/bindings/ScriptForbiddenScope.h"
 #include "platform/instrumentation/tracing/TraceEvent.h"
@@ -1612,7 +1612,7 @@
   }
 
   DCHECK(!frame_load_request.GetResourceRequest().IsSameDocumentNavigation());
-  frame_->FrameScheduler()->DidStartProvisionalLoad(frame_->IsMainFrame());
+  frame_->GetFrameScheduler()->DidStartProvisionalLoad(frame_->IsMainFrame());
 
   // TODO(ananta):
   // We should get rid of the dependency on the DocumentLoader in consumers of
diff --git a/third_party/WebKit/Source/core/loader/NavigationScheduler.cpp b/third_party/WebKit/Source/core/loader/NavigationScheduler.cpp
index f481d405..e943c95 100644
--- a/third_party/WebKit/Source/core/loader/NavigationScheduler.cpp
+++ b/third_party/WebKit/Source/core/loader/NavigationScheduler.cpp
@@ -542,7 +542,7 @@
   // wrapWeakPersistent(this) is safe because a posted task is canceled when the
   // task handle is destroyed on the dtor of this NavigationScheduler.
   navigate_task_handle_ = PostDelayedCancellableTask(
-      *frame_->FrameScheduler()->GetTaskRunner(TaskType::kUnspecedLoading),
+      *frame_->GetFrameScheduler()->GetTaskRunner(TaskType::kUnspecedLoading),
       FROM_HERE,
       WTF::Bind(&NavigationScheduler::NavigateTask, WrapWeakPersistent(this)),
       TimeDelta::FromSecondsD(redirect_->Delay()));
diff --git a/third_party/WebKit/Source/core/loader/ThreadableLoader.cpp b/third_party/WebKit/Source/core/loader/ThreadableLoader.cpp
index 2238f73..b5296c33 100644
--- a/third_party/WebKit/Source/core/loader/ThreadableLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/ThreadableLoader.cpp
@@ -67,14 +67,15 @@
     const ThreadableLoaderOptions& options,
     const ResourceLoaderOptions& resource_loader_options) {
   if (context.IsWorkerGlobalScope()) {
-    WorkerThreadableLoader::LoadResourceSynchronously(
-        ToWorkerGlobalScope(context), request, client, options,
-        resource_loader_options);
+    DocumentThreadableLoader::LoadResourceSynchronously(
+        *ThreadableLoadingContext::Create(*ToWorkerGlobalScope(&context)),
+        request, client, options, resource_loader_options);
     return;
   }
 
   DocumentThreadableLoader::LoadResourceSynchronously(
-      ToDocument(context), request, client, options, resource_loader_options);
+      *ThreadableLoadingContext::Create(*ToDocument(&context)), request, client,
+      options, resource_loader_options);
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/loader/ThreadableLoaderTest.cpp b/third_party/WebKit/Source/core/loader/ThreadableLoaderTest.cpp
index b41e3e4..aef8b1b0 100644
--- a/third_party/WebKit/Source/core/loader/ThreadableLoaderTest.cpp
+++ b/third_party/WebKit/Source/core/loader/ThreadableLoaderTest.cpp
@@ -235,6 +235,7 @@
  public:
   WebWorkerFetchContextForTest(KURL site_for_cookies)
       : site_for_cookies_(site_for_cookies.Copy()) {}
+  base::WaitableEvent* GetTerminateSyncLoadEvent() override { return nullptr; }
   void InitializeOnWorkerThread() override {}
 
   std::unique_ptr<WebURLLoaderFactory> CreateURLLoaderFactory() override {
diff --git a/third_party/WebKit/Source/core/page/Page.cpp b/third_party/WebKit/Source/core/page/Page.cpp
index 007996cc..f9657bd 100644
--- a/third_party/WebKit/Source/core/page/Page.cpp
+++ b/third_party/WebKit/Source/core/page/Page.cpp
@@ -61,7 +61,7 @@
 #include "core/page/scrolling/TopDocumentRootScrollerController.h"
 #include "core/paint/PaintLayer.h"
 #include "core/probe/CoreProbes.h"
-#include "platform/WebFrameScheduler.h"
+#include "platform/FrameScheduler.h"
 #include "platform/graphics/GraphicsLayer.h"
 #include "platform/loader/fetch/ResourceFetcher.h"
 #include "platform/plugins/PluginData.h"
@@ -360,7 +360,7 @@
       continue;
     LocalFrame* local_frame = ToLocalFrame(frame);
     local_frame->Loader().SetDefersLoading(paused);
-    local_frame->FrameScheduler()->SetPaused(paused);
+    local_frame->GetFrameScheduler()->SetPaused(paused);
   }
 }
 
diff --git a/third_party/WebKit/Source/core/page/scrolling/SnapCoordinator.cpp b/third_party/WebKit/Source/core/page/scrolling/SnapCoordinator.cpp
index 57e95ec..80ebf0a 100644
--- a/third_party/WebKit/Source/core/page/scrolling/SnapCoordinator.cpp
+++ b/third_party/WebKit/Source/core/page/scrolling/SnapCoordinator.cpp
@@ -422,10 +422,12 @@
   if (!data.size())
     return point;
 
-  gfx::ScrollOffset position = data.FindSnapPosition(
-      gfx::ScrollOffset(point.X(), point.Y()), did_scroll_x, did_scroll_y);
-
-  return FloatPoint(position.x(), position.y());
+  gfx::ScrollOffset snap_position;
+  if (data.FindSnapPosition(gfx::ScrollOffset(point.X(), point.Y()),
+                            did_scroll_x, did_scroll_y, &snap_position)) {
+    return FloatPoint(snap_position.x(), snap_position.y());
+  }
+  return point;
 }
 
 void SnapCoordinator::PerformSnapping(const LayoutBox& snap_container,
diff --git a/third_party/WebKit/Source/core/paint/CSSMaskPainter.cpp b/third_party/WebKit/Source/core/paint/CSSMaskPainter.cpp
index c93ca23..0e5dcf4d 100644
--- a/third_party/WebKit/Source/core/paint/CSSMaskPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/CSSMaskPainter.cpp
@@ -26,7 +26,7 @@
       return EnclosingIntRect(masker->ResourceBoundingBox(&object));
   }
 
-  if (object.IsSVGChild())
+  if (object.IsSVGChild() && !object.IsSVGForeignObject())
     return WTF::nullopt;
 
   const ComputedStyle& style = object.StyleRef();
diff --git a/third_party/WebKit/Source/core/paint/FragmentData.cpp b/third_party/WebKit/Source/core/paint/FragmentData.cpp
index 6e48144..ca19c609 100644
--- a/third_party/WebKit/Source/core/paint/FragmentData.cpp
+++ b/third_party/WebKit/Source/core/paint/FragmentData.cpp
@@ -52,10 +52,8 @@
   return LocalBorderBoxProperties().Transform();
 }
 
-const ClipPaintPropertyNode* FragmentData::PreCssClip() const {
+const ClipPaintPropertyNode* FragmentData::ClipPathClip() const {
   if (const auto* properties = PaintProperties()) {
-    if (properties->CssClip())
-      return properties->CssClip()->Parent();
     if (properties->ClipPathClip()) {
       // SPv1 composited clip-path has an alternative clip tree structure.
       // If the clip-path is parented by the mask clip, it is only used
@@ -65,6 +63,8 @@
     }
     if (properties->MaskClip())
       return properties->MaskClip()->Parent();
+    if (properties->CssClip())
+      return properties->CssClip()->Parent();
   }
   return LocalBorderBoxProperties().Clip();
 }
diff --git a/third_party/WebKit/Source/core/paint/FragmentData.h b/third_party/WebKit/Source/core/paint/FragmentData.h
index 005ca7c..e4d11c7 100644
--- a/third_party/WebKit/Source/core/paint/FragmentData.h
+++ b/third_party/WebKit/Source/core/paint/FragmentData.h
@@ -172,7 +172,7 @@
   // from the ancestor before applying any local CSS properties,
   // but includes paint offset transform.
   PropertyTreeState PreEffectProperties() const {
-    return PropertyTreeState(PreTransform(), PreCssClip(), PreEffect());
+    return PropertyTreeState(PreTransform(), ClipPathClip(), PreEffect());
   }
 
   // This is the complete set of property nodes that can be used to
@@ -198,7 +198,7 @@
 
   const TransformPaintPropertyNode* PreTransform() const;
   const TransformPaintPropertyNode* PostScrollTranslation() const;
-  const ClipPaintPropertyNode* PreCssClip() const;
+  const ClipPaintPropertyNode* ClipPathClip() const;
   const ClipPaintPropertyNode* PostOverflowClip() const;
   const EffectPaintPropertyNode* PreEffect() const;
   const EffectPaintPropertyNode* PreFilter() const;
diff --git a/third_party/WebKit/Source/core/paint/FragmentDataTest.cpp b/third_party/WebKit/Source/core/paint/FragmentDataTest.cpp
index d986e75..55cf4561 100644
--- a/third_party/WebKit/Source/core/paint/FragmentDataTest.cpp
+++ b/third_party/WebKit/Source/core/paint/FragmentDataTest.cpp
@@ -3,11 +3,11 @@
 // found in the LICENSE file.
 
 #include "core/paint/FragmentData.h"
-#include "testing/gtest/include/gtest/gtest.h"
+#include "core/testing/CoreUnitTestHelper.h"
 
 namespace blink {
 
-class FragmentDataTest : public ::testing::Test {
+class FragmentDataTest : public RenderingTest {
  protected:
   bool HasRareData(const FragmentData& data) { return !!data.rare_data_; }
 };
@@ -40,4 +40,26 @@
   EXPECT_EQ(LayoutRect(), fragment.SelectionVisualRect());
 }
 
+TEST_F(FragmentDataTest, PreEffectClipProperties) {
+  SetBodyInnerHTML(R"HTML(
+    <style>
+      #target {
+        width: 400px; height: 400px; position: absolute;
+        clip: rect(0, 50px, 100px, 0);
+        clip-path: inset(0%);
+      }
+    </style>
+    <div id='target'></div>
+  )HTML");
+
+  LayoutObject* target = GetLayoutObjectByElementId("target");
+  const ObjectPaintProperties* properties =
+      target->FirstFragment().PaintProperties();
+  EXPECT_TRUE(properties->ClipPathClip());
+  EXPECT_TRUE(properties->CssClip());
+  EXPECT_EQ(properties->ClipPathClip(), properties->CssClip()->Parent());
+  EXPECT_EQ(properties->ClipPathClip()->Parent(),
+            target->FirstFragment().PreEffectProperties().Clip());
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp b/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp
index 2785af6..bf97d87 100644
--- a/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp
@@ -1013,8 +1013,9 @@
     const StyleableMarker& marker,
     const ComputedStyle& style,
     const Font& font) {
-  if (marker.UnderlineColor() == Color::kTransparent ||
-      marker.HasThicknessNone())
+  if (marker.HasThicknessNone() ||
+      (marker.UnderlineColor() == Color::kTransparent &&
+       !marker.UseTextColor()))
     return;
 
   if (inline_text_box_.Truncation() == kCFullTruncation)
@@ -1053,7 +1054,13 @@
       inline_text_box_.LogicalHeight() - baseline >= 2)
     line_thickness = 2;
 
-  context.SetStrokeColor(marker.UnderlineColor());
+  Color marker_color =
+      marker.UseTextColor()
+          ? inline_text_box_.GetLineLayoutItem().Style()->VisitedDependentColor(
+                GetCSSPropertyWebkitTextFillColor())
+          : marker.UnderlineColor();
+  context.SetStrokeColor(marker_color);
+
   context.SetStrokeThickness(line_thickness);
   context.DrawLineForText(
       FloatPoint(
diff --git a/third_party/WebKit/Source/core/paint/PaintLayer.cpp b/third_party/WebKit/Source/core/paint/PaintLayer.cpp
index d1c7909..925bcf9 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayer.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayer.cpp
@@ -2029,9 +2029,11 @@
   // fragment.
   PaintLayerFragments layer_fragments;
   if (applied_transform) {
+    DCHECK(root_layer == this);
+    LayoutPoint offset;
     AppendSingleFragmentIgnoringPagination(
         layer_fragments, root_layer, hit_test_rect,
-        kExcludeOverlayScrollbarSizeForHitTesting, clip_behavior);
+        kExcludeOverlayScrollbarSizeForHitTesting, clip_behavior, &offset);
   } else {
     CollectFragments(layer_fragments, root_layer, hit_test_rect,
                      kExcludeOverlayScrollbarSizeForHitTesting, clip_behavior);
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerClipperTest.cpp b/third_party/WebKit/Source/core/paint/PaintLayerClipperTest.cpp
index 2191f40..562981f 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerClipperTest.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerClipperTest.cpp
@@ -464,6 +464,7 @@
       #target {
         width: 400px; height: 400px; position: absolute;
         clip: rect(0, 50px, 100px, 0);
+        clip-path: inset(0%);
       }
     </style>
     <div id='target'></div>
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp b/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp
index d512b61..79fb0c3 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp
@@ -368,13 +368,16 @@
   ShouldRespectOverflowClipType respect_overflow_clip =
       ShouldRespectOverflowClip(paint_flags, paint_layer_.GetLayoutObject());
 
+  PaintLayerPaintingInfo painting_info = painting_info_arg;
+  AdjustForPaintProperties(painting_info, paint_flags);
+
   bool should_create_subsequence = ShouldCreateSubsequence(
       paint_layer_, context, painting_info_arg, paint_flags);
 
   Optional<SubsequenceRecorder> subsequence_recorder;
   bool should_clear_empty_paint_phase_flags = false;
   if (should_create_subsequence) {
-    if (!ShouldRepaintSubsequence(paint_layer_, painting_info_arg,
+    if (!ShouldRepaintSubsequence(paint_layer_, painting_info,
                                   respect_overflow_clip,
                                   should_clear_empty_paint_phase_flags) &&
         SubsequenceRecorder::UseCachedSubsequenceIfPossible(context,
@@ -392,9 +395,6 @@
     paint_layer_.SetPreviousPaintPhaseDescendantBlockBackgroundsEmpty(false);
   }
 
-  PaintLayerPaintingInfo painting_info = painting_info_arg;
-  AdjustForPaintProperties(painting_info, paint_flags);
-
   LayoutPoint offset_from_root;
   paint_layer_.ConvertToLayerCoords(painting_info.root_layer, offset_from_root);
   offset_from_root.Move(subpixel_accumulation);
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerResourceInfo.cpp b/third_party/WebKit/Source/core/paint/PaintLayerResourceInfo.cpp
index 44571167..49da267 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerResourceInfo.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerResourceInfo.cpp
@@ -41,7 +41,7 @@
   DCHECK(!layer_);
 }
 
-void PaintLayerResourceInfo::ResourceContentChanged() {
+void PaintLayerResourceInfo::ResourceContentChanged(InvalidationModeMask) {
   DCHECK(layer_);
   LayoutObject& layout_object = layer_->GetLayoutObject();
   layout_object.SetShouldDoFullPaintInvalidation();
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerResourceInfo.h b/third_party/WebKit/Source/core/paint/PaintLayerResourceInfo.h
index 8f05371..5218e745 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerResourceInfo.h
+++ b/third_party/WebKit/Source/core/paint/PaintLayerResourceInfo.h
@@ -63,7 +63,7 @@
 
   void ClearLayer() { layer_ = nullptr; }
 
-  void ResourceContentChanged() override;
+  void ResourceContentChanged(InvalidationModeMask) override;
   void ResourceElementChanged() override;
 
   void Trace(blink::Visitor*) override;
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
index ea75ee3..f7e19242 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
@@ -2012,9 +2012,10 @@
 }
 
 LayoutRect PaintLayerScrollableArea::ScrollIntoView(
-    const LayoutRect& rect,
+    const LayoutRect& absolute_rect,
     const WebScrollIntoViewParams& params) {
-  LayoutRect local_expose_rect = AbsoluteToLocal(*GetLayoutBox(), rect);
+  LayoutRect local_expose_rect =
+      AbsoluteToLocal(*GetLayoutBox(), absolute_rect);
   LayoutSize border_origin_to_scroll_origin =
       LayoutSize(-GetLayoutBox()->BorderLeft(), -GetLayoutBox()->BorderTop()) +
       LayoutSize(GetScrollOffset());
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerTest.cpp b/third_party/WebKit/Source/core/paint/PaintLayerTest.cpp
index a5dcc51..c90cbf1e 100644
--- a/third_party/WebKit/Source/core/paint/PaintLayerTest.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintLayerTest.cpp
@@ -1224,6 +1224,27 @@
   EXPECT_EQ(body, GetDocument().ElementFromPoint(60, 151));
 }
 
+TEST_P(PaintLayerTest, FragmentedHitTest) {
+  SetHtmlInnerHTML(R"HTML(
+    <style>
+    div {
+      break-inside: avoid-column;
+      width: 50px;
+      height: 50px;
+      position: relative;
+    }
+    </style>
+    <ul style="column-count: 4; position: relative">
+      <div></div>
+      <div id=target style=" position: relative; transform: translateY(0px);">
+      </div>
+    </ul>
+  )HTML");
+
+  auto* target = GetDocument().getElementById("target");
+  EXPECT_EQ(target, GetDocument().ElementFromPoint(280, 30));
+}
+
 TEST_P(PaintLayerTest, SquashingOffsets) {
   if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
     return;
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
index d0944b56..0729467 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
@@ -580,6 +580,9 @@
 }
 
 static CompositingReasons CompositingReasonsForTransform(const LayoutBox& box) {
+  if (!box.HasLayer())
+    return CompositingReason::kNone;
+
   const ComputedStyle& style = box.StyleRef();
   CompositingReasons compositing_reasons = CompositingReason::kNone;
   if (CompositingReasonFinder::RequiresCompositingForTransform(box))
@@ -1780,11 +1783,11 @@
 
   if (properties_) {
     UpdateTransform();
-    UpdateCssClip();
     UpdateClipPathClip(false);
     if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
       UpdateEffect();
     UpdateClipPathClip(true);  // Special pass for SPv1 composited clip-path.
+    UpdateCssClip();
     UpdateFilter();
     UpdateOverflowControlsClip();
   }
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
index 4b90351..7f80d98 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
@@ -1288,6 +1288,33 @@
   EXPECT_EQ(LayoutPoint(10, 10), div.FirstFragment().PaintOffset());
 }
 
+TEST_P(PaintPropertyTreeBuilderTest, ForeignObjectWithMask) {
+  // SPV1 has no effect tree.
+  if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
+    return;
+
+  SetBodyInnerHTML(R"HTML(
+    <style> body { margin: 0px; } </style>
+    <svg id='svg' style='position; relative'>
+      <foreignObject id="foreignObject"
+          x="10" y="10" width="50" height="40"
+          style="-webkit-mask:linear-gradient(red,red)">
+        <div id='div'></div>
+      </foreignObject>
+    </svg>
+  )HTML");
+
+  LayoutObject& svg = *GetLayoutObjectByElementId("svg");
+  LayoutObject& foreign_object = *GetLayoutObjectByElementId("foreignObject");
+  const ObjectPaintProperties* foreign_object_properties =
+      foreign_object.FirstFragment().PaintProperties();
+  EXPECT_TRUE(foreign_object_properties->Mask());
+  EXPECT_EQ(foreign_object_properties->MaskClip(),
+            foreign_object_properties->Mask()->OutputClip());
+  EXPECT_EQ(svg.FirstFragment().LocalBorderBoxProperties().Transform(),
+            foreign_object_properties->Mask()->LocalTransformSpace());
+}
+
 TEST_P(PaintPropertyTreeBuilderTest, PaintOffsetTranslationSVGHTMLBoundary) {
   SetBodyInnerHTML(R"HTML(
     <svg id='svg'
@@ -5333,4 +5360,10 @@
                    ->HasDirectCompositingReasons());
 }
 
+TEST_P(PaintPropertyTreeBuilderTest,
+       NoTransformPropertyForWillChangeWithoutLayer) {
+  SetBodyInnerHTML("<svg id='target' style='will-change: left'></svg>");
+  EXPECT_EQ(nullptr, PaintPropertiesForElement("target")->Transform());
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/PaintTiming.cpp b/third_party/WebKit/Source/core/paint/PaintTiming.cpp
index 6ebdcf9..11ffcdf 100644
--- a/third_party/WebKit/Source/core/paint/PaintTiming.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintTiming.cpp
@@ -20,8 +20,8 @@
 #include "core/timing/DOMWindowPerformance.h"
 #include "core/timing/WindowPerformance.h"
 #include "platform/CrossThreadFunctional.h"
+#include "platform/FrameScheduler.h"
 #include "platform/Histogram.h"
-#include "platform/WebFrameScheduler.h"
 #include "platform/instrumentation/tracing/TraceEvent.h"
 #include "public/platform/WebLayerTreeView.h"
 
@@ -92,7 +92,7 @@
     return;
   first_meaningful_paint_candidate_ = timestamp;
   if (GetFrame() && GetFrame()->View() && !GetFrame()->View()->IsAttached()) {
-    GetFrame()->FrameScheduler()->OnFirstMeaningfulPaint();
+    GetFrame()->GetFrameScheduler()->OnFirstMeaningfulPaint();
   }
 }
 
diff --git a/third_party/WebKit/Source/core/probe/CoreProbes.json5 b/third_party/WebKit/Source/core/probe/CoreProbes.json5
index 620068d..b2fbb4f 100644
--- a/third_party/WebKit/Source/core/probe/CoreProbes.json5
+++ b/third_party/WebKit/Source/core/probe/CoreProbes.json5
@@ -9,6 +9,15 @@
     ],
   },
   observers: {
+    AdTracker: {
+      class: "AdTracker",
+      include_path: "core/frame",
+      probes: [
+        "CallFunction",
+        "ExecuteScript",
+        "willSendRequest",
+      ]
+    },
     Animation: {
       probes: [
         "animationPlayStateChanged",
diff --git a/third_party/WebKit/Source/core/probe/CoreProbes.pidl b/third_party/WebKit/Source/core/probe/CoreProbes.pidl
index 37f441e..280f92cf9 100644
--- a/third_party/WebKit/Source/core/probe/CoreProbes.pidl
+++ b/third_party/WebKit/Source/core/probe/CoreProbes.pidl
@@ -155,7 +155,7 @@
   void breakableLocation(ExecutionContext* context, const char* name);
   RecalculateStyle(Document* document);
   UpdateLayout(Document* document);
-  ExecuteScript([Keep] ExecutionContext* context);
+  ExecuteScript([Keep] ExecutionContext* context, const String& script_url);
   CallFunction([Keep] ExecutionContext* context, v8::Local<v8::Function> function, int depth = 0);
   UserCallback([Keep] ExecutionContext* context, const char* name, const AtomicString& atomicName, bool recurring, EventTarget* eventTarget = nullptr);
   V8Compile([Keep] ExecutionContext* context, const String& file_name, int line, int column);
diff --git a/third_party/WebKit/Source/core/resize_observer/ResizeObserver.h b/third_party/WebKit/Source/core/resize_observer/ResizeObserver.h
index 4564e50..ac9b5e0 100644
--- a/third_party/WebKit/Source/core/resize_observer/ResizeObserver.h
+++ b/third_party/WebKit/Source/core/resize_observer/ResizeObserver.h
@@ -58,7 +58,7 @@
   void ElementSizeChanged();
   bool HasElementSizeChanged() { return element_size_changed_; }
 
-  // ContextClient override:
+  // ScriptWrappable override:
   bool HasPendingActivity() const override;
 
   void Trace(blink::Visitor*);
diff --git a/third_party/WebKit/Source/core/scheduler/FrameSchedulerTest.cpp b/third_party/WebKit/Source/core/scheduler/FrameSchedulerTest.cpp
index ede4c53c..aeb1320 100644
--- a/third_party/WebKit/Source/core/scheduler/FrameSchedulerTest.cpp
+++ b/third_party/WebKit/Source/core/scheduler/FrameSchedulerTest.cpp
@@ -5,16 +5,16 @@
 #include "core/frame/WebLocalFrameImpl.h"
 #include "core/testing/sim/SimRequest.h"
 #include "core/testing/sim/SimTest.h"
-#include "platform/WebFrameScheduler.h"
+#include "platform/FrameScheduler.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using ::testing::ElementsAre;
 
 namespace blink {
 
-class WebFrameSchedulerFrameTypeTest : public SimTest {};
+class FrameSchedulerFrameTypeTest : public SimTest {};
 
-TEST_F(WebFrameSchedulerFrameTypeTest, GetFrameType) {
+TEST_F(FrameSchedulerFrameTypeTest, GetFrameType) {
   SimRequest main_resource("https://example.com/", "text/html");
   LoadURL("https://example.com/");
   main_resource.Complete(R"HTML(
@@ -24,13 +24,13 @@
     </body>
   )HTML");
 
-  EXPECT_EQ(WebFrameScheduler::FrameType::kMainFrame,
-            MainFrame().GetFrame()->FrameScheduler()->GetFrameType());
+  EXPECT_EQ(FrameScheduler::FrameType::kMainFrame,
+            MainFrame().GetFrame()->GetFrameScheduler()->GetFrameType());
 
   Frame* child = MainFrame().GetFrame()->Tree().FirstChild();
   ASSERT_TRUE(child->IsLocalFrame());
-  EXPECT_EQ(WebFrameScheduler::FrameType::kSubframe,
-            ToLocalFrame(child)->FrameScheduler()->GetFrameType());
+  EXPECT_EQ(FrameScheduler::FrameType::kSubframe,
+            ToLocalFrame(child)->GetFrameScheduler()->GetFrameType());
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/script/DocumentModulatorImpl.cpp b/third_party/WebKit/Source/core/script/DocumentModulatorImpl.cpp
index 69ba6b5..56aa315 100644
--- a/third_party/WebKit/Source/core/script/DocumentModulatorImpl.cpp
+++ b/third_party/WebKit/Source/core/script/DocumentModulatorImpl.cpp
@@ -30,4 +30,8 @@
   DCHECK(fetcher_);
 }
 
+bool DocumentModulatorImpl::IsDynamicImportForbidden(String* reason) {
+  return false;
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/script/DocumentModulatorImpl.h b/third_party/WebKit/Source/core/script/DocumentModulatorImpl.h
index 06d214e..5e38449 100644
--- a/third_party/WebKit/Source/core/script/DocumentModulatorImpl.h
+++ b/third_party/WebKit/Source/core/script/DocumentModulatorImpl.h
@@ -30,6 +30,9 @@
   void Trace(blink::Visitor*);
 
  private:
+  // Implements ModulatorImplBase.
+  bool IsDynamicImportForbidden(String* reason);
+
   DocumentModulatorImpl(scoped_refptr<ScriptState>, ResourceFetcher*);
   Member<ResourceFetcher> fetcher_;
 };
diff --git a/third_party/WebKit/Source/core/script/HTMLParserScriptRunner.cpp b/third_party/WebKit/Source/core/script/HTMLParserScriptRunner.cpp
index d0d7768..cde66e3 100644
--- a/third_party/WebKit/Source/core/script/HTMLParserScriptRunner.cpp
+++ b/third_party/WebKit/Source/core/script/HTMLParserScriptRunner.cpp
@@ -36,7 +36,6 @@
 #include "core/script/IgnoreDestructiveWriteCountIncrementer.h"
 #include "core/script/ScriptLoader.h"
 #include "platform/Histogram.h"
-#include "platform/WebFrameScheduler.h"
 #include "platform/bindings/Microtask.h"
 #include "platform/bindings/V8PerIsolateData.h"
 #include "platform/instrumentation/tracing/TraceEvent.h"
diff --git a/third_party/WebKit/Source/core/script/ModulatorImplBase.cpp b/third_party/WebKit/Source/core/script/ModulatorImplBase.cpp
index 81b4ec8..14a00ec9 100644
--- a/third_party/WebKit/Source/core/script/ModulatorImplBase.cpp
+++ b/third_party/WebKit/Source/core/script/ModulatorImplBase.cpp
@@ -4,6 +4,7 @@
 
 #include "core/script/ModulatorImplBase.h"
 
+#include "bindings/core/v8/ScriptPromiseResolver.h"
 #include "core/dom/ExecutionContext.h"
 #include "core/loader/modulescript/ModuleScriptFetchRequest.h"
 #include "core/loader/modulescript/ModuleScriptLoaderRegistry.h"
@@ -12,6 +13,7 @@
 #include "core/script/ModuleMap.h"
 #include "core/script/ModuleScript.h"
 #include "core/script/ScriptModuleResolverImpl.h"
+#include "platform/bindings/V8ThrowException.h"
 #include "public/platform/TaskType.h"
 
 namespace blink {
@@ -98,6 +100,12 @@
     const KURL& referrer_url,
     const ReferrerScriptInfo& referrer_info,
     ScriptPromiseResolver* resolver) {
+  String reason;
+  if (IsDynamicImportForbidden(&reason)) {
+    resolver->Reject(V8ThrowException::CreateTypeError(
+        GetScriptState()->GetIsolate(), reason));
+    return;
+  }
   dynamic_module_resolver_->ResolveDynamically(specifier, referrer_url,
                                                referrer_info, resolver);
 }
diff --git a/third_party/WebKit/Source/core/script/ModulatorImplBase.h b/third_party/WebKit/Source/core/script/ModulatorImplBase.h
index 76698af..4b5f17c 100644
--- a/third_party/WebKit/Source/core/script/ModulatorImplBase.h
+++ b/third_party/WebKit/Source/core/script/ModulatorImplBase.h
@@ -78,6 +78,13 @@
   Vector<ModuleRequest> ModuleRequestsFromScriptModule(ScriptModule) override;
   ScriptValue ExecuteModule(const ModuleScript*, CaptureEvalErrorFlag) override;
 
+  // Populates |reason| and returns true if the dynamic import is disallowed on
+  // the associated execution context. In that case, a caller of this function
+  // is expected to reject the dynamic import with |reason|. If the dynamic
+  // import is allowed on the execution context, returns false without
+  // modification of |reason|.
+  virtual bool IsDynamicImportForbidden(String* reason) = 0;
+
   scoped_refptr<ScriptState> script_state_;
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
   TraceWrapperMember<ModuleMap> map_;
diff --git a/third_party/WebKit/Source/core/script/ModuleScript.cpp b/third_party/WebKit/Source/core/script/ModuleScript.cpp
index d79e36e..b363ac9 100644
--- a/third_party/WebKit/Source/core/script/ModuleScript.cpp
+++ b/third_party/WebKit/Source/core/script/ModuleScript.cpp
@@ -51,8 +51,9 @@
   // Steps 8-13 before Step 6. In a case that compile failed, we will
   // immediately turn the script into errored state. Thus the members will not
   // be used for the speced algorithms, but may be used from inspector.
-  ModuleScript* script = CreateInternal(source_text, modulator, result,
-                                        base_url, options, start_position);
+  ModuleScript* script =
+      CreateInternal(source_text, modulator, result, source_url, base_url,
+                     options, start_position);
 
   // Step 6. "If result is a list of errors, then:" [spec text]
   if (exception_state.HadException()) {
@@ -101,13 +102,15 @@
                                           const KURL& base_url,
                                           const ScriptFetchOptions& options) {
   String dummy_source_text = "";
-  return CreateInternal(dummy_source_text, modulator, record, base_url, options,
-                        TextPosition::MinimumPosition());
+  KURL dummy_source_url;
+  return CreateInternal(dummy_source_text, modulator, record, dummy_source_url,
+                        base_url, options, TextPosition::MinimumPosition());
 }
 
 ModuleScript* ModuleScript::CreateInternal(const String& source_text,
                                            Modulator* modulator,
                                            ScriptModule result,
+                                           const KURL& source_url,
                                            const KURL& base_url,
                                            const ScriptFetchOptions& options,
                                            const TextPosition& start_position) {
@@ -117,8 +120,9 @@
   // Step 9. Set script's base URL to baseURL.
   // Step 10. Set script's fetch options to options.
   // [nospec] |source_text| is saved for CSP checks.
-  ModuleScript* module_script = new ModuleScript(
-      modulator, result, base_url, options, source_text, start_position);
+  ModuleScript* module_script =
+      new ModuleScript(modulator, result, source_url, base_url, options,
+                       source_text, start_position);
 
   // Step 5, a part of ParseModule(): Passing script as the last parameter
   // here ensures result.[[HostDefined]] will be script.
@@ -129,6 +133,7 @@
 
 ModuleScript::ModuleScript(Modulator* settings_object,
                            ScriptModule record,
+                           const KURL& source_url,
                            const KURL& base_url,
                            const ScriptFetchOptions& fetch_options,
                            const String& source_text,
@@ -136,7 +141,8 @@
     : Script(fetch_options, base_url),
       settings_object_(settings_object),
       source_text_(source_text),
-      start_position_(start_position) {
+      start_position_(start_position),
+      source_url_(source_url) {
   if (record.IsNull()) {
     // We allow empty records for module infra tests which never touch records.
     // This should never happen outside unit tests.
@@ -155,7 +161,7 @@
 
   v8::Isolate* isolate = settings_object_->GetScriptState()->GetIsolate();
   v8::HandleScope scope(isolate);
-  return ScriptModule(isolate, record_.NewLocal(isolate));
+  return ScriptModule(isolate, record_.NewLocal(isolate), source_url_);
 }
 
 bool ModuleScript::HasEmptyRecord() const {
diff --git a/third_party/WebKit/Source/core/script/ModuleScript.h b/third_party/WebKit/Source/core/script/ModuleScript.h
index 5da11008..ee237f00 100644
--- a/third_party/WebKit/Source/core/script/ModuleScript.h
+++ b/third_party/WebKit/Source/core/script/ModuleScript.h
@@ -68,6 +68,7 @@
  private:
   ModuleScript(Modulator* settings_object,
                ScriptModule record,
+               const KURL& source_url,
                const KURL& base_url,
                const ScriptFetchOptions&,
                const String& source_text,
@@ -76,6 +77,7 @@
   static ModuleScript* CreateInternal(const String& source_text,
                                       Modulator*,
                                       ScriptModule,
+                                      const KURL& source_url,
                                       const KURL& base_url,
                                       const ScriptFetchOptions&,
                                       const TextPosition&);
@@ -138,6 +140,7 @@
 
   const TextPosition start_position_;
   HashMap<String, KURL> specifier_to_url_cache_;
+  KURL source_url_;
 };
 
 CORE_EXPORT std::ostream& operator<<(std::ostream&, const ModuleScript&);
diff --git a/third_party/WebKit/Source/core/script/PendingScript.cpp b/third_party/WebKit/Source/core/script/PendingScript.cpp
index 3a07da4d..7de13a37 100644
--- a/third_party/WebKit/Source/core/script/PendingScript.cpp
+++ b/third_party/WebKit/Source/core/script/PendingScript.cpp
@@ -28,7 +28,7 @@
 #include "core/dom/Document.h"
 #include "core/frame/LocalFrame.h"
 #include "core/script/ScriptElementBase.h"
-#include "platform/WebFrameScheduler.h"
+#include "platform/FrameScheduler.h"
 #include "platform/wtf/Time.h"
 
 namespace blink {
@@ -40,7 +40,7 @@
     return WebScopedVirtualTimePauser();
   return element->GetDocument()
       .GetFrame()
-      ->FrameScheduler()
+      ->GetFrameScheduler()
       ->CreateWebScopedVirtualTimePauser(
           WebScopedVirtualTimePauser::VirtualTaskDuration::kInstant);
 }
diff --git a/third_party/WebKit/Source/core/script/ScriptLoader.cpp b/third_party/WebKit/Source/core/script/ScriptLoader.cpp
index 1ad3f1f..8f2bde29 100644
--- a/third_party/WebKit/Source/core/script/ScriptLoader.cpp
+++ b/third_party/WebKit/Source/core/script/ScriptLoader.cpp
@@ -50,7 +50,6 @@
 #include "core/script/ScriptElementBase.h"
 #include "core/script/ScriptRunner.h"
 #include "core/svg_names.h"
-#include "platform/WebFrameScheduler.h"
 #include "platform/loader/SubresourceIntegrity.h"
 #include "platform/loader/fetch/AccessControlStatus.h"
 #include "platform/loader/fetch/FetchParameters.h"
diff --git a/third_party/WebKit/Source/core/script/WorkerModulatorImpl.cpp b/third_party/WebKit/Source/core/script/WorkerModulatorImpl.cpp
index 5a12ea1..d6ad47b6 100644
--- a/third_party/WebKit/Source/core/script/WorkerModulatorImpl.cpp
+++ b/third_party/WebKit/Source/core/script/WorkerModulatorImpl.cpp
@@ -8,6 +8,7 @@
 #include "core/loader/modulescript/WorkerOrWorkletModuleScriptFetcher.h"
 #include "core/workers/WorkerGlobalScope.h"
 #include "platform/bindings/V8ThrowException.h"
+#include "platform/runtime_enabled_features.h"
 
 namespace blink {
 
@@ -26,16 +27,20 @@
       global_scope->ModuleFetchCoordinatorProxy());
 }
 
-void WorkerModulatorImpl::ResolveDynamically(const String& specifier,
-                                             const KURL&,
-                                             const ReferrerScriptInfo&,
-                                             ScriptPromiseResolver* resolver) {
-  // TODO(nhiroki): Support module loading for workers.
+bool WorkerModulatorImpl::IsDynamicImportForbidden(String* reason) {
+  // TODO(nhiroki): Remove this flag check once module loading for
+  // DedicatedWorker is enabled by default (https://crbug.com/680046).
+  if (GetExecutionContext()->IsDedicatedWorkerGlobalScope() &&
+      RuntimeEnabledFeatures::ModuleDedicatedWorkerEnabled()) {
+    return false;
+  }
+
+  // TODO(nhiroki): Support module loading for SharedWorker and Service Worker.
   // (https://crbug.com/680046)
-  resolver->Reject(V8ThrowException::CreateTypeError(
-      GetScriptState()->GetIsolate(),
+  *reason =
       "Module scripts are not supported on WorkerGlobalScope yet (see "
-      "https://crbug.com/680046)."));
+      "https://crbug.com/680046).";
+  return true;
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/script/WorkerModulatorImpl.h b/third_party/WebKit/Source/core/script/WorkerModulatorImpl.h
index 40bd3d0..979c985 100644
--- a/third_party/WebKit/Source/core/script/WorkerModulatorImpl.h
+++ b/third_party/WebKit/Source/core/script/WorkerModulatorImpl.h
@@ -26,10 +26,7 @@
   explicit WorkerModulatorImpl(scoped_refptr<ScriptState>);
 
   // Implements ModulatorImplBase.
-  void ResolveDynamically(const String& specifier,
-                          const KURL&,
-                          const ReferrerScriptInfo&,
-                          ScriptPromiseResolver*) override;
+  bool IsDynamicImportForbidden(String* reason) override;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/script/WorkletModulatorImpl.cpp b/third_party/WebKit/Source/core/script/WorkletModulatorImpl.cpp
index f1f5440..40120e45 100644
--- a/third_party/WebKit/Source/core/script/WorkletModulatorImpl.cpp
+++ b/third_party/WebKit/Source/core/script/WorkletModulatorImpl.cpp
@@ -4,10 +4,8 @@
 
 #include "core/script/WorkletModulatorImpl.h"
 
-#include "bindings/core/v8/ScriptPromiseResolver.h"
 #include "core/loader/modulescript/WorkerOrWorkletModuleScriptFetcher.h"
 #include "core/workers/WorkletGlobalScope.h"
-#include "platform/bindings/V8ThrowException.h"
 
 namespace blink {
 
@@ -30,13 +28,9 @@
       global_scope->ModuleFetchCoordinatorProxy());
 }
 
-void WorkletModulatorImpl::ResolveDynamically(const String&,
-                                              const KURL&,
-                                              const ReferrerScriptInfo&,
-                                              ScriptPromiseResolver* resolver) {
-  resolver->Reject(V8ThrowException::CreateTypeError(
-      GetScriptState()->GetIsolate(),
-      "import() is disallowed on WorkletGlobalScope."));
+bool WorkletModulatorImpl::IsDynamicImportForbidden(String* reason) {
+  *reason = "import() is disallowed on WorkletGlobalScope.";
+  return true;
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/script/WorkletModulatorImpl.h b/third_party/WebKit/Source/core/script/WorkletModulatorImpl.h
index 3457c5f..a5f738b 100644
--- a/third_party/WebKit/Source/core/script/WorkletModulatorImpl.h
+++ b/third_party/WebKit/Source/core/script/WorkletModulatorImpl.h
@@ -29,10 +29,7 @@
   explicit WorkletModulatorImpl(scoped_refptr<ScriptState>);
 
   // Implements ModulatorImplBase.
-  void ResolveDynamically(const String& specifier,
-                          const KURL&,
-                          const ReferrerScriptInfo&,
-                          ScriptPromiseResolver*) final;
+  bool IsDynamicImportForbidden(String* reason) override;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/svg/SVGElement.cpp b/third_party/WebKit/Source/core/svg/SVGElement.cpp
index 35c9b5c..bf7efdf 100644
--- a/third_party/WebKit/Source/core/svg/SVGElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGElement.cpp
@@ -29,6 +29,7 @@
 #include "core/animation/EffectStack.h"
 #include "core/animation/ElementAnimations.h"
 #include "core/animation/InvalidatableInterpolation.h"
+#include "core/animation/KeyframeEffect.h"
 #include "core/animation/SVGInterpolationEnvironment.h"
 #include "core/animation/SVGInterpolationTypesMap.h"
 #include "core/css/resolver/StyleResolver.h"
@@ -202,7 +203,7 @@
   ActiveInterpolationsMap active_interpolations_map =
       EffectStack::ActiveInterpolations(
           &GetElementAnimations()->GetEffectStack(), nullptr, nullptr,
-          KeyframeEffectReadOnly::kDefaultPriority, IsSVGAttributeHandle);
+          KeyframeEffect::kDefaultPriority, IsSVGAttributeHandle);
   for (auto& entry : active_interpolations_map) {
     const QualifiedName& attribute = entry.key.SvgAttribute();
     SVGInterpolationTypesMap map;
diff --git a/third_party/WebKit/Source/core/svg/SVGElement.h b/third_party/WebKit/Source/core/svg/SVGElement.h
index a18eb4cd..d30cb478 100644
--- a/third_party/WebKit/Source/core/svg/SVGElement.h
+++ b/third_party/WebKit/Source/core/svg/SVGElement.h
@@ -299,6 +299,8 @@
   SVGElementSet& invalidating_dependencies = GetDependencyTraversalVisitedSet();
 
   for (SVGElement* element : *dependencies) {
+    if (!element->GetLayoutObject())
+      continue;
     if (UNLIKELY(!invalidating_dependencies.insert(element).is_new_entry)) {
       // Reference cycle: we are in process of invalidating this dependant.
       continue;
diff --git a/third_party/WebKit/Source/core/svg/SVGFilterElement.cpp b/third_party/WebKit/Source/core/svg/SVGFilterElement.cpp
index 85dfcda8..9d28570 100644
--- a/third_party/WebKit/Source/core/svg/SVGFilterElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGFilterElement.cpp
@@ -116,15 +116,17 @@
     ToLayoutSVGResourceFilter(layout_object)
         ->PrimitiveAttributeChanged(primitive, attribute);
   } else if (LocalSVGResource* resource = AssociatedResource()) {
-    resource->NotifyContentChanged();
+    resource->NotifyContentChanged(SVGResourceClient::kPaintInvalidation);
   }
 }
 
 void SVGFilterElement::InvalidateFilterChain() {
-  if (LayoutObject* layout_object = GetLayoutObject())
+  if (LayoutObject* layout_object = GetLayoutObject()) {
     ToLayoutSVGResourceFilter(layout_object)->RemoveAllClientsFromCache();
-  else if (LocalSVGResource* resource = AssociatedResource())
-    resource->NotifyContentChanged();
+  } else if (LocalSVGResource* resource = AssociatedResource()) {
+    resource->NotifyContentChanged(SVGResourceClient::kLayoutInvalidation |
+                                   SVGResourceClient::kBoundariesInvalidation);
+  }
 }
 
 void SVGFilterElement::ChildrenChanged(const ChildrenChange& change) {
diff --git a/third_party/WebKit/Source/core/svg/SVGResource.cpp b/third_party/WebKit/Source/core/svg/SVGResource.cpp
index 95b186d..919dced 100644
--- a/third_party/WebKit/Source/core/svg/SVGResource.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGResource.cpp
@@ -94,12 +94,13 @@
   }
 }
 
-void LocalSVGResource::NotifyContentChanged() {
+void LocalSVGResource::NotifyContentChanged(
+    InvalidationModeMask invalidation_mask) {
   HeapVector<Member<SVGResourceClient>> clients;
   CopyToVector(clients_, clients);
 
   for (SVGResourceClient* client : clients)
-    client->ResourceContentChanged();
+    client->ResourceContentChanged(invalidation_mask);
 }
 
 void LocalSVGResource::TargetChanged(const AtomicString& id) {
diff --git a/third_party/WebKit/Source/core/svg/SVGResource.h b/third_party/WebKit/Source/core/svg/SVGResource.h
index a4d4d35..fced0da3 100644
--- a/third_party/WebKit/Source/core/svg/SVGResource.h
+++ b/third_party/WebKit/Source/core/svg/SVGResource.h
@@ -6,6 +6,7 @@
 #define SVGResource_h
 
 #include "base/macros.h"
+#include "core/svg/SVGResourceClient.h"
 #include "platform/heap/Handle.h"
 #include "platform/loader/fetch/ResourceClient.h"
 #include "platform/weborigin/KURL.h"
@@ -21,7 +22,6 @@
 class IdTargetObserver;
 class LayoutSVGResourceContainer;
 class SVGElement;
-class SVGResourceClient;
 class TreeScope;
 
 // A class tracking a reference to an SVG resource (an element that constitutes
@@ -101,7 +101,7 @@
   bool IsEmpty() const;
 
   void NotifyPendingClients();
-  void NotifyContentChanged();
+  void NotifyContentChanged(InvalidationModeMask);
 
   void Trace(Visitor*) override;
 
diff --git a/third_party/WebKit/Source/core/svg/SVGResourceClient.h b/third_party/WebKit/Source/core/svg/SVGResourceClient.h
index 81e938aa..993a6b52 100644
--- a/third_party/WebKit/Source/core/svg/SVGResourceClient.h
+++ b/third_party/WebKit/Source/core/svg/SVGResourceClient.h
@@ -10,11 +10,21 @@
 
 namespace blink {
 
+typedef unsigned InvalidationModeMask;
+
 class CORE_EXPORT SVGResourceClient : public GarbageCollectedMixin {
  public:
   virtual ~SVGResourceClient() = default;
 
-  virtual void ResourceContentChanged() = 0;
+  // When adding modes, make sure we don't overflow
+  // |LayoutSVGResourceContainer::completed_invalidation_mask_|.
+  enum InvalidationMode {
+    kLayoutInvalidation = 1 << 0,
+    kBoundariesInvalidation = 1 << 1,
+    kPaintInvalidation = 1 << 2,
+    kParentOnlyInvalidation = 1 << 3
+  };
+  virtual void ResourceContentChanged(InvalidationModeMask) = 0;
   virtual void ResourceElementChanged() = 0;
 
  protected:
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorker.cpp b/third_party/WebKit/Source/core/workers/DedicatedWorker.cpp
index 9796790e..426afa7 100644
--- a/third_party/WebKit/Source/core/workers/DedicatedWorker.cpp
+++ b/third_party/WebKit/Source/core/workers/DedicatedWorker.cpp
@@ -71,8 +71,8 @@
     return nullptr;
   }
 
-  // TODO(nhiroki): Remove this check once module scripts are supported on
-  // WorkerGlobalScope (https://crbug.com/680046).
+  // TODO(nhiroki): Remove this flag check once module loading for
+  // DedicatedWorker is enabled by default (https://crbug.com/680046).
   if (options.type() == "module" &&
       !RuntimeEnabledFeatures::ModuleDedicatedWorkerEnabled()) {
     exception_state.ThrowTypeError(
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorkerThread.cpp b/third_party/WebKit/Source/core/workers/DedicatedWorkerThread.cpp
index f36a572..16ebde7 100644
--- a/third_party/WebKit/Source/core/workers/DedicatedWorkerThread.cpp
+++ b/third_party/WebKit/Source/core/workers/DedicatedWorkerThread.cpp
@@ -46,14 +46,13 @@
 
 namespace {
 
-WebFrameScheduler* GetFrameScheduler(
-    ThreadableLoadingContext* loading_context) {
+FrameScheduler* GetFrameScheduler(ThreadableLoadingContext* loading_context) {
   // |loading_context| can be null in unittests.
   if (!loading_context)
     return nullptr;
   return ToDocument(loading_context->GetExecutionContext())
       ->GetFrame()
-      ->FrameScheduler();
+      ->GetFrameScheduler();
 }
 
 }  // namespace
diff --git a/third_party/WebKit/Source/core/workers/MainThreadWorkletGlobalScope.cpp b/third_party/WebKit/Source/core/workers/MainThreadWorkletGlobalScope.cpp
index 038ef81c..9943825 100644
--- a/third_party/WebKit/Source/core/workers/MainThreadWorkletGlobalScope.cpp
+++ b/third_party/WebKit/Source/core/workers/MainThreadWorkletGlobalScope.cpp
@@ -26,8 +26,9 @@
           reporting_proxy,
           // Specify |kUnspecedLoading| because these task runners are used
           // during module loading and this usage is not explicitly spec'ed.
-          frame->FrameScheduler()->GetTaskRunner(TaskType::kUnspecedLoading),
-          frame->FrameScheduler()->GetTaskRunner(TaskType::kUnspecedLoading)),
+          frame->GetFrameScheduler()->GetTaskRunner(TaskType::kUnspecedLoading),
+          frame->GetFrameScheduler()->GetTaskRunner(
+              TaskType::kUnspecedLoading)),
       ContextClient(frame) {}
 
 MainThreadWorkletGlobalScope::~MainThreadWorkletGlobalScope() = default;
@@ -43,7 +44,7 @@
   // MainThreadWorkletGlobalScope lives on the main thread and its GetThread()
   // doesn't return a valid worker thread. Instead, retrieve a task runner
   // from the frame.
-  return GetFrame()->FrameScheduler()->GetTaskRunner(type);
+  return GetFrame()->GetFrameScheduler()->GetTaskRunner(type);
 }
 
 // TODO(nhiroki): Add tests for termination.
diff --git a/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.cpp b/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.cpp
index 6577ede..6ed65797 100644
--- a/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.cpp
+++ b/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.cpp
@@ -4,6 +4,7 @@
 
 #include "core/workers/ThreadedMessagingProxyBase.h"
 
+#include "base/synchronization/waitable_event.h"
 #include "bindings/core/v8/SourceLocation.h"
 #include "core/dom/Document.h"
 #include "core/frame/Deprecation.h"
@@ -67,6 +68,8 @@
     std::unique_ptr<WebWorkerFetchContext> web_worker_fetch_context =
         web_frame->Client()->CreateWorkerFetchContext();
     DCHECK(web_worker_fetch_context);
+    terminate_sync_load_event_ =
+        web_worker_fetch_context->GetTerminateSyncLoadEvent();
     web_worker_fetch_context->SetApplicationCacheHostID(
         document->Fetcher()->Context().ApplicationCacheHostID());
     web_worker_fetch_context->SetIsOnSubframe(
@@ -141,6 +144,11 @@
     return;
   asked_to_terminate_ = true;
 
+  if (terminate_sync_load_event_) {
+    terminate_sync_load_event_->Signal();
+    terminate_sync_load_event_ = nullptr;
+  }
+
   if (worker_thread_)
     worker_thread_->Terminate();
 
diff --git a/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.h b/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.h
index 802a56bd..31796d1f 100644
--- a/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.h
+++ b/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.h
@@ -15,6 +15,12 @@
 #include "platform/wtf/Forward.h"
 #include "platform/wtf/Optional.h"
 
+namespace base {
+
+class WaitableEvent;
+
+}  // namespace base
+
 namespace blink {
 
 class ExecutionContext;
@@ -98,6 +104,8 @@
 
   bool asked_to_terminate_ = false;
 
+  base::WaitableEvent* terminate_sync_load_event_ = nullptr;
+
   // Used to keep this alive until the worker thread gets terminated. This is
   // necessary because the co-owner (i.e., Worker or Worklet object) can be
   // destroyed before thread termination.
diff --git a/third_party/WebKit/Source/core/workers/WorkerThread.cpp b/third_party/WebKit/Source/core/workers/WorkerThread.cpp
index 16d3a8e..745a2a2 100644
--- a/third_party/WebKit/Source/core/workers/WorkerThread.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkerThread.cpp
@@ -383,7 +383,6 @@
   global_scope_scheduler_ =
       std::make_unique<scheduler::WorkerGlobalScopeScheduler>(
           web_thread_for_worker.GetWorkerScheduler());
-  web_thread_for_worker.GetWorkerScheduler()->SetThreadType(GetThreadType());
   waitable_event->Signal();
 }
 
diff --git a/third_party/WebKit/Source/devtools/BUILD.gn b/third_party/WebKit/Source/devtools/BUILD.gn
index 44d476a6..8148d4cd 100644
--- a/third_party/WebKit/Source/devtools/BUILD.gn
+++ b/third_party/WebKit/Source/devtools/BUILD.gn
@@ -790,7 +790,6 @@
   "front_end/ui/ListWidget.js",
   "front_end/ui/module.json",
   "front_end/ui/Panel.js",
-  "front_end/ui/panelEnablerView.css",
   "front_end/ui/popover.css",
   "front_end/ui/Popover.js",
   "front_end/ui/progressIndicator.css",
diff --git a/third_party/WebKit/Source/devtools/front_end/audits2/Audits2Panel.js b/third_party/WebKit/Source/devtools/front_end/audits2/Audits2Panel.js
index 3dd365d..7aea16d5 100644
--- a/third_party/WebKit/Source/devtools/front_end/audits2/Audits2Panel.js
+++ b/third_party/WebKit/Source/devtools/front_end/audits2/Audits2Panel.js
@@ -527,7 +527,8 @@
 
     const dom = new DOM(/** @type {!Document} */ (this._resultsView.ownerDocument));
     const detailsRenderer = new Audits2.DetailsRenderer(dom);
-    const categoryRenderer = new CategoryRenderer(dom, detailsRenderer);
+    const categoryRenderer = new Audits2.CategoryRenderer(dom, detailsRenderer);
+    categoryRenderer.setTraceArtifact(this._lighthouseResult);
     const renderer = new Audits2.Audits2Panel.ReportRenderer(dom, categoryRenderer);
 
     const templatesHTML = Runtime.cachedResources['audits2/lighthouse/templates.html'];
@@ -540,6 +541,49 @@
   }
 };
 
+Audits2.CategoryRenderer = class extends CategoryRenderer {
+  /**
+   * @override
+   * @param {!DOM} dom
+   * @param {!DetailsRenderer} detailsRenderer
+   */
+  constructor(dom, detailsRenderer) {
+    super(dom, detailsRenderer);
+    this._defaultPassTrace = null;
+  }
+
+  /**
+   * @param {!ReportRenderer.ReportJSON} lhr
+   */
+  setTraceArtifact(lhr) {
+    if (!lhr.artifacts || !lhr.artifacts.traces || !lhr.artifacts.traces.defaultPass)
+      return;
+    this._defaultPassTrace = lhr.artifacts.traces.defaultPass;
+  }
+
+  /**
+   * @override
+   * @param {!ReportRenderer.CategoryJSON} category
+   * @param {!Object<string, !ReportRenderer.GroupJSON>} groups
+   * @return {!Element}
+   */
+  renderPerformanceCategory(category, groups) {
+    const defaultPassTrace = this._defaultPassTrace;
+    const element = super.renderPerformanceCategory(category, groups);
+    if (!defaultPassTrace)
+      return element;
+
+    const timelineButton = UI.createTextButton(Common.UIString('View Trace'), onViewTraceClick, 'view-trace');
+    element.querySelector('.lh-audit-group').prepend(timelineButton);
+    return element;
+
+    async function onViewTraceClick() {
+      await UI.inspectorView.showPanel('timeline');
+      Timeline.TimelinePanel.instance().loadFromEvents(defaultPassTrace.traceEvents);
+    }
+  }
+};
+
 Audits2.DetailsRenderer = class extends DetailsRenderer {
   /**
    * @param {!DOM} dom
diff --git a/third_party/WebKit/Source/devtools/front_end/audits2/audits2Panel.css b/third_party/WebKit/Source/devtools/front_end/audits2/audits2Panel.css
index e97f577..22f9278 100644
--- a/third_party/WebKit/Source/devtools/front_end/audits2/audits2Panel.css
+++ b/third_party/WebKit/Source/devtools/front_end/audits2/audits2Panel.css
@@ -73,6 +73,15 @@
   word-wrap: break-word;
 }
 
+/* for View Trace button */
+.lh-audit-group {
+  position: relative;
+}
+button.view-trace {
+  position: absolute;
+  right: 0;
+}
+
 .audits2-landing-center button {
     margin-top: 20px;
 }
diff --git a/third_party/WebKit/Source/devtools/front_end/audits2/lighthouse/renderer/category-renderer.js b/third_party/WebKit/Source/devtools/front_end/audits2/lighthouse/renderer/category-renderer.js
index dff47f1..c361200f 100644
--- a/third_party/WebKit/Source/devtools/front_end/audits2/lighthouse/renderer/category-renderer.js
+++ b/third_party/WebKit/Source/devtools/front_end/audits2/lighthouse/renderer/category-renderer.js
@@ -343,7 +343,7 @@
   render(category, groups) {
     switch (category.id) {
       case 'performance':
-        return this._renderPerformanceCategory(category, groups);
+        return this.renderPerformanceCategory(category, groups);
       case 'accessibility':
         return this._renderAccessibilityCategory(category, groups);
       default:
@@ -393,7 +393,7 @@
    * @param {!Object<string, !ReportRenderer.GroupJSON>} groups
    * @return {!Element}
    */
-  _renderPerformanceCategory(category, groups) {
+  renderPerformanceCategory(category, groups) {
     const element = this._dom.createElement('div', 'lh-category');
     this._createPermalinkSpan(element, category.id);
     element.appendChild(this._renderCategoryScore(category));
diff --git a/third_party/WebKit/Source/devtools/front_end/audits2/lighthouse/renderer/report-renderer.js b/third_party/WebKit/Source/devtools/front_end/audits2/lighthouse/renderer/report-renderer.js
index 4d5e4e13..92ca071 100644
--- a/third_party/WebKit/Source/devtools/front_end/audits2/lighthouse/renderer/report-renderer.js
+++ b/third_party/WebKit/Source/devtools/front_end/audits2/lighthouse/renderer/report-renderer.js
@@ -225,7 +225,7 @@
  *     initialUrl: string,
  *     url: string,
  *     runWarnings: (!Array<string>|undefined),
- *     artifacts: {traces: !Object},
+ *     artifacts: {traces: {defaultPass: {traceEvents: !Array}}},
  *     reportCategories: !Array<!ReportRenderer.CategoryJSON>,
  *     reportGroups: !Object<string, !ReportRenderer.GroupJSON>,
  *     runtimeConfig: {
diff --git a/third_party/WebKit/Source/devtools/front_end/audits2/module.json b/third_party/WebKit/Source/devtools/front_end/audits2/module.json
index 1d7a7df..2ec939f53 100644
--- a/third_party/WebKit/Source/devtools/front_end/audits2/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/audits2/module.json
@@ -12,6 +12,7 @@
     "dependencies": [
         "components",
         "emulation",
+        "timeline",
         "inspector_main",
         "sdk",
         "services",
diff --git a/third_party/WebKit/Source/devtools/front_end/audits2_worker/Audits2Service.js b/third_party/WebKit/Source/devtools/front_end/audits2_worker/Audits2Service.js
index 2681c4d..f19bee6 100644
--- a/third_party/WebKit/Source/devtools/front_end/audits2_worker/Audits2Service.js
+++ b/third_party/WebKit/Source/devtools/front_end/audits2_worker/Audits2Service.js
@@ -50,8 +50,7 @@
     return Promise.resolve()
         .then(_ => self.runLighthouseInWorker(this, params.url, {flags: params.flags}, params.categoryIDs))
         .then(/** @type {!ReportRenderer.ReportJSON} */ result => {
-          // Delete artifacts to minimize report size.
-          delete result.artifacts;
+          // Keep all artifacts on the result, no trimming
           return result;
         })
         .catch(err => ({
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/elementsTreeOutline.css b/third_party/WebKit/Source/devtools/front_end/elements/elementsTreeOutline.css
index 54a0609..c57ea71 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/elementsTreeOutline.css
+++ b/third_party/WebKit/Source/devtools/front_end/elements/elementsTreeOutline.css
@@ -36,6 +36,10 @@
 
 .elements-disclosure li.selected .selected-hint:before {
     opacity: 0.6;
+    color: var(--selection-inactive-fg-color);
+}
+
+.elements-disclosure li.selected:focus .selected-hint:before {
     color: var(--selection-fg-color);
 }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/externs.js b/third_party/WebKit/Source/devtools/front_end/externs.js
index db622bb..54fe8f8 100644
--- a/third_party/WebKit/Source/devtools/front_end/externs.js
+++ b/third_party/WebKit/Source/devtools/front_end/externs.js
@@ -639,6 +639,13 @@
 Element.prototype.animate = function(keyframes, timing) {};
 
 /**
+ * @param {...!Node} nodes
+ * @return {undefined}
+ * @see https://dom.spec.whatwg.org/#dom-parentnode-prepend
+ */
+Element.prototype.prepend = function(nodes) {};
+
+/**
  * @override
  * @param {string} type
  * @param {(!EventListener|!function (!Event): (boolean|undefined)|null)} listener
diff --git a/third_party/WebKit/Source/devtools/front_end/persistence/Automapping.js b/third_party/WebKit/Source/devtools/front_end/persistence/Automapping.js
index 08c9fd8..ab71f33 100644
--- a/third_party/WebKit/Source/devtools/front_end/persistence/Automapping.js
+++ b/third_party/WebKit/Source/devtools/front_end/persistence/Automapping.js
@@ -208,6 +208,8 @@
       ]);
       const fileSystemContent = contents[0];
       const networkContent = contents[1];
+      if (fileSystemContent === null || networkContent === null)
+        return null;
 
       if (networkSourceCode[Persistence.Automapping._processingPromise] !== createBindingPromise)
         return null;
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/HeapProfilerPanel.js b/third_party/WebKit/Source/devtools/front_end/profiler/HeapProfilerPanel.js
index 5de3ff9..c3ae83db 100644
--- a/third_party/WebKit/Source/devtools/front_end/profiler/HeapProfilerPanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/profiler/HeapProfilerPanel.js
@@ -10,7 +10,7 @@
   constructor() {
     const registry = Profiler.ProfileTypeRegistry.instance;
     const profileTypes =
-        [registry.heapSnapshotProfileType, registry.samplingHeapProfileType, registry.trackingHeapSnapshotProfileType];
+        [registry.heapSnapshotProfileType, registry.trackingHeapSnapshotProfileType, registry.samplingHeapProfileType];
     if (Runtime.experiments.isEnabled('nativeHeapProfiler'))
       profileTypes.push(registry.samplingNativeHeapProfileType, registry.samplingNativeHeapSnapshotType);
     super('heap_profiler', profileTypes, 'profiler.heap-toggle-recording');
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotView.js b/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotView.js
index 4469cb5..7bbd007 100644
--- a/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotView.js
+++ b/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotView.js
@@ -81,7 +81,7 @@
     this._diffWidget = this._diffDataGrid.asWidget();
     this._diffWidget.setMinimumSize(50, 25);
 
-    if (isHeapTimeline && Common.moduleSetting('recordAllocationStacks').get()) {
+    if (isHeapTimeline) {
       this._allocationDataGrid = new Profiler.AllocationDataGrid(profile._heapProfilerModel, this);
       this._allocationDataGrid.addEventListener(
           DataGrid.DataGrid.Events.SelectedNode, this._onSelectAllocationNode, this);
@@ -1097,6 +1097,7 @@
 Profiler.TrackingHeapSnapshotProfileType = class extends Profiler.HeapSnapshotProfileType {
   constructor() {
     super(Profiler.TrackingHeapSnapshotProfileType.TypeId, ls`Allocation instrumentation on timeline`);
+    this._recordAllocationStacksSetting = Common.settings.createSetting('recordAllocationStacks', false);
   }
 
   /**
@@ -1191,8 +1192,16 @@
     const heapProfilerModel = this._addNewProfile();
     if (!heapProfilerModel)
       return;
-    const recordAllocationStacks = Common.moduleSetting('recordAllocationStacks').get();
-    heapProfilerModel.startTrackingHeapObjects(recordAllocationStacks);
+    heapProfilerModel.startTrackingHeapObjects(this._recordAllocationStacksSetting.get());
+  }
+
+  /**
+   * @override
+   * @return {?Element}
+   */
+  customContent() {
+    return UI.SettingsUI.createSettingCheckbox(
+        ls`Record allocation stacks (extra performance overhead)`, this._recordAllocationStacksSetting, true);
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/IsolateSelector.js b/third_party/WebKit/Source/devtools/front_end/profiler/IsolateSelector.js
index f0b0b6c..cf3460cd 100644
--- a/third_party/WebKit/Source/devtools/front_end/profiler/IsolateSelector.js
+++ b/third_party/WebKit/Source/devtools/front_end/profiler/IsolateSelector.js
@@ -195,15 +195,18 @@
     const modelCountByName = new Map();
     for (const model of this._models.values()) {
       const target = model.target();
-      const name = target.decorateLabel(target.name() || ls`(empty)`);
+      const name = SDK.targetManager.mainTarget() !== target ? target.name() : '';
       const parsedURL = new Common.ParsedURL(target.inspectedURL());
       const domain = parsedURL.isValid ? parsedURL.domain() : '';
-      const title = domain ? `${domain}: ${name}` : name;
+      const title = target.decorateLabel(domain && name ? `${domain}: ${name}` : name || domain || ls`(empty)`);
       modelCountByName.set(title, (modelCountByName.get(title) || 0) + 1);
     }
-    const titles = [];
-    for (const [name, count] of modelCountByName)
-      titles.push(count > 1 ? `${name} (${count})` : name);
-    this._nameDiv.textContent = titles.join(', ');
+    this._nameDiv.removeChildren();
+    for (const [name, count] of modelCountByName) {
+      const lineDiv = this._nameDiv.createChild('div');
+      const title = count > 1 ? `${name} (${count})` : name;
+      lineDiv.textContent = title;
+      lineDiv.setAttribute('title', title);
+    }
   }
 };
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/ProfileLauncherView.js b/third_party/WebKit/Source/devtools/front_end/profiler/ProfileLauncherView.js
index a6772adc..6e049fef 100644
--- a/third_party/WebKit/Source/devtools/front_end/profiler/ProfileLauncherView.js
+++ b/third_party/WebKit/Source/devtools/front_end/profiler/ProfileLauncherView.js
@@ -38,17 +38,18 @@
   constructor(profilesPanel) {
     super();
     this._panel = profilesPanel;
-    this.element.classList.add('profile-launcher-view', 'panel-enabler-view');
+    this.element.classList.add('profile-launcher-view');
 
     this._contentElement = this.element.createChild('div', 'profile-launcher-view-content');
     this._innerContentElement = this._contentElement.createChild('div');
     const controlDiv = this._contentElement.createChild('div', 'hbox profile-launcher-control');
     if (Runtime.experiments.isEnabled('memoryLauncherViewV2')) {
+      controlDiv.createChild('h1').textContent = ls`Select JavaScript VM instance`;
       const targetDiv = controlDiv.createChild('div', 'hbox profile-launcher-target-list');
       new Profiler.IsolateSelector().show(targetDiv);
     } else {
       const targetDiv = controlDiv.createChild('div', 'hbox profile-launcher-target');
-      targetDiv.createChild('div').textContent = Common.UIString('Target:');
+      targetDiv.createChild('div').textContent = ls`Target:`;
       const targetsSelect = targetDiv.createChild('select', 'chrome-select');
       new Profiler.TargetsComboBoxController(targetsSelect, targetDiv);
     }
@@ -129,11 +130,11 @@
     optionElement.addEventListener('change', this._profileTypeChanged.bind(this, profileType), false);
     const descriptionElement = this._profileTypeSelectorForm.createChild('p');
     descriptionElement.textContent = profileType.description;
-    const decorationElement = profileType.decorationElement();
-    if (decorationElement)
-      labelElement.appendChild(decorationElement);
+    const customContent = profileType.customContent();
+    if (customContent)
+      this._profileTypeSelectorForm.createChild('p').appendChild(customContent);
     if (this._typeIdToOptionElement.size > 1)
-      this._header.textContent = Common.UIString('Select profiling type');
+      this._header.textContent = ls`Select profiling type`;
     else
       this._header.textContent = profileType.name;
   }
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/ProfileType.js b/third_party/WebKit/Source/devtools/front_end/profiler/ProfileType.js
index c5c3257e..a8be4a1a 100644
--- a/third_party/WebKit/Source/devtools/front_end/profiler/ProfileType.js
+++ b/third_party/WebKit/Source/devtools/front_end/profiler/ProfileType.js
@@ -119,7 +119,7 @@
   /**
    * @return {?Element}
    */
-  decorationElement() {
+  customContent() {
     return null;
   }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/ProfilesPanel.js b/third_party/WebKit/Source/devtools/front_end/profiler/ProfilesPanel.js
index cdcc363a..d66f2f4 100644
--- a/third_party/WebKit/Source/devtools/front_end/profiler/ProfilesPanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/profiler/ProfilesPanel.js
@@ -36,7 +36,6 @@
   constructor(name, profileTypes, recordingActionId) {
     super(name);
     this._profileTypes = profileTypes;
-    this.registerRequiredCSS('ui/panelEnablerView.css');
     this.registerRequiredCSS('profiler/heapProfiler.css');
     this.registerRequiredCSS('profiler/profilesPanel.css');
     this.registerRequiredCSS('object_ui/objectValue.css');
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/module.json b/third_party/WebKit/Source/devtools/front_end/profiler/module.json
index e7fbac6..1b77a51 100644
--- a/third_party/WebKit/Source/devtools/front_end/profiler/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/profiler/module.json
@@ -18,14 +18,6 @@
         {
             "type": "setting",
             "category": "Performance",
-            "title": "Record heap allocation stack traces",
-            "settingName": "recordAllocationStacks",
-            "settingType": "boolean",
-            "defaultValue": false
-        },
-        {
-            "type": "setting",
-            "category": "Performance",
             "title": "High resolution CPU profiling",
             "settingName": "highResolutionCpuProfiling",
             "settingType": "boolean",
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/profileLauncherView.css b/third_party/WebKit/Source/devtools/front_end/profiler/profileLauncherView.css
index 4a65c162..207dee2 100644
--- a/third_party/WebKit/Source/devtools/front_end/profiler/profileLauncherView.css
+++ b/third_party/WebKit/Source/devtools/front_end/profiler/profileLauncherView.css
@@ -5,8 +5,10 @@
  */
 
 .profile-isolate-item {
-    padding: 5px;
+    padding: 4px;
+    line-height: 16px;
     border-left: 2px solid transparent;
+    overflow-x: hidden;
 }
 
 .profile-isolate-item:hover {
@@ -19,7 +21,7 @@
 }
 
 .profile-isolate-item > div {
-    flex-shrink:  0;
+    flex-shrink: 0;
     margin-left: 9px;
 }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/profilesPanel.css b/third_party/WebKit/Source/devtools/front_end/profiler/profilesPanel.css
index 7bf89a853..a28a50d 100644
--- a/third_party/WebKit/Source/devtools/front_end/profiler/profilesPanel.css
+++ b/third_party/WebKit/Source/devtools/front_end/profiler/profilesPanel.css
@@ -113,8 +113,18 @@
 }
 
 .profile-launcher-view-content {
-    padding: 0 16px;
-    text-align: left;
+    padding: 10px 16px;
+}
+
+.profile-launcher-view-content h1 {
+    font-size: 15px;
+    font-weight: normal;
+    padding: 6px 0;
+    margin: 0 0 5px 0;
+}
+
+.profile-launcher-view-content label {
+    font-size: 13px;
 }
 
 .profile-launcher-control {
@@ -122,7 +132,7 @@
     flex-wrap: wrap;
 }
 
-.profile-launcher-control > * {
+.profile-launcher-control {
     margin-top: 10px;
     margin-right: 6px;
 }
@@ -147,26 +157,16 @@
     margin-right: 8px;
 }
 
-.profile-launcher-view-content h1 {
-    padding: 15px 0 10px;
-}
-
-.panel-enabler-view.profile-launcher-view form {
-    padding: 0;
-    font-size: 13px;
-    width: 100%;
-}
-
-.panel-enabler-view.profile-launcher-view label {
-    margin: 0;
-}
-
 .profile-launcher-view-content p {
     color: grey;
     margin-top: 1px;
     margin-left: 22px;
 }
 
+.profile-launcher-view-content p label {
+    display: flex;
+}
+
 .profile-launcher-view-content button.running {
     color: hsl(0, 100%, 58%);
 }
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/ApplicationPanelSidebar.js b/third_party/WebKit/Source/devtools/front_end/resources/ApplicationPanelSidebar.js
index 62bfba7..ae46e2c 100644
--- a/third_party/WebKit/Source/devtools/front_end/resources/ApplicationPanelSidebar.js
+++ b/third_party/WebKit/Source/devtools/front_end/resources/ApplicationPanelSidebar.js
@@ -353,9 +353,7 @@
    * @return {!Promise}
    */
   async showResource(resource, line, column) {
-    const resourceTreeElement = Resources.FrameResourceTreeElement.forResource(resource);
-    if (resourceTreeElement)
-      await resourceTreeElement.revealResource(line, column);
+    await this._resourcesSection.revealResource(resource, line, column);
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/ResourcesSection.js b/third_party/WebKit/Source/devtools/front_end/resources/ResourcesSection.js
index 4397dcb..3187665a 100644
--- a/third_party/WebKit/Source/devtools/front_end/resources/ResourcesSection.js
+++ b/third_party/WebKit/Source/devtools/front_end/resources/ResourcesSection.js
@@ -25,7 +25,7 @@
     const resourceTreeModel = mainTarget && mainTarget.model(SDK.ResourceTreeModel);
     const mainFrame = resourceTreeModel && resourceTreeModel.mainFrame;
     if (mainFrame)
-      this._populateFrame(mainFrame);
+      this._frameAdded(mainFrame);
   }
 
   /**
@@ -43,17 +43,45 @@
   }
 
   /**
+   * @param {?SDK.ResourceTreeFrame} frame
+   * @return {boolean}
+   */
+  _expandFrame(frame) {
+    if (!frame)
+      return false;
+    let treeElement = this._treeElementForFrameId.get(frame.id);
+    if (!treeElement && !this._expandFrame(Resources.ResourcesSection._getParentFrame(frame)))
+      return false;
+    treeElement = this._treeElementForFrameId.get(frame.id);
+    if (!treeElement)
+      return false;
+    treeElement.expand();
+    return true;
+  }
+
+  /**
+   * @param {!SDK.Resource} resource
+   * @param {number=} line
+   * @param {number=} column
+   * @return {!Promise}
+   */
+  async revealResource(resource, line, column) {
+    if (!this._expandFrame(resource.frame()))
+      return;
+    const resourceTreeElement = Resources.FrameResourceTreeElement.forResource(resource);
+    if (resourceTreeElement)
+      await resourceTreeElement.revealResource(line, column);
+  }
+
+  /**
    * @param {!SDK.ResourceTreeFrame} frame
    */
   _frameAdded(frame) {
     const parentFrame = Resources.ResourcesSection._getParentFrame(frame);
     const parentTreeElement = parentFrame ? this._treeElementForFrameId.get(parentFrame.id) : this._treeElement;
-    if (!parentTreeElement) {
-      console.warn(`No frame to route ${frame.url} to.`);
+    if (!parentTreeElement)
       return;
-    }
-
-    const frameTreeElement = new Resources.FrameTreeElement(this._panel, frame);
+    const frameTreeElement = new Resources.FrameTreeElement(this, frame);
     this._treeElementForFrameId.set(frame.id, frameTreeElement);
     parentTreeElement.appendChild(frameTreeElement);
   }
@@ -84,17 +112,12 @@
    * @param {!SDK.Resource} resource
    */
   _resourceAdded(resource) {
-    const statusCode = resource['statusCode'];
-    if (statusCode >= 301 && statusCode <= 303)
-      return;
-
     const frameTreeElement = this._treeElementForFrameId.get(resource.frameId);
     if (!frameTreeElement) {
       // This is a frame's main resource, it will be retained
       // and re-added by the resource manager;
       return;
     }
-
     frameTreeElement.appendResource(resource);
   }
 
@@ -102,31 +125,22 @@
     this._treeElement.removeChildren();
     this._treeElementForFrameId.clear();
   }
-
-  /**
-   * @param {!SDK.ResourceTreeFrame} frame
-   */
-  _populateFrame(frame) {
-    this._frameAdded(frame);
-    for (const child of frame.childFrames)
-      this._populateFrame(child);
-    for (const resource of frame.resources())
-      this._resourceAdded(resource);
-  }
 };
 
 Resources.FrameTreeElement = class extends Resources.BaseStorageTreeElement {
   /**
-   * @param {!Resources.ResourcesPanel} storagePanel
+   * @param {!Resources.ResourcesSection} section
    * @param {!SDK.ResourceTreeFrame} frame
    */
-  constructor(storagePanel, frame) {
-    super(storagePanel, '', false);
-    this._panel = storagePanel;
+  constructor(section, frame) {
+    super(section._panel, '', false);
+    this._populated = false;
+    this._section = section;
     this._frame = frame;
     this._frameId = frame.id;
     this._categoryElements = {};
     this._treeElementForResource = {};
+    this.setExpandable(true);
     this.frameNavigated(frame);
 
     const icon = UI.Icon.create('largeicon-navigator-frame', 'navigator-tree-item');
@@ -134,8 +148,11 @@
     this.setLeadingIcons([icon]);
   }
 
+  /**
+   * @param {!SDK.ResourceTreeFrame} frame
+   */
   frameNavigated(frame) {
-    this.removeChildren();
+    this.invalidateChildren();
     this._frameId = frame.id;
     this.title = frame.displayName();
     this._categoryElements = {};
@@ -152,7 +169,7 @@
    */
   onselect(selectedByUser) {
     super.onselect(selectedByUser);
-    this._panel.showCategoryView(this.titleAsText());
+    this._section._panel.showCategoryView(this.titleAsText());
 
     this.listItemElement.classList.remove('hovered');
     SDK.OverlayModel.hideDOMNodeHighlight();
@@ -173,16 +190,22 @@
    * @param {!SDK.Resource} resource
    */
   appendResource(resource) {
+    if (!this._populated)
+      return;
+    const statusCode = resource['statusCode'];
+    if (statusCode >= 301 && statusCode <= 303)
+      return;
+
     const resourceType = resource.resourceType();
     const categoryName = resourceType.name();
     let categoryElement = resourceType === Common.resourceTypes.Document ? this : this._categoryElements[categoryName];
     if (!categoryElement) {
-      categoryElement =
-          new Resources.StorageCategoryTreeElement(this._panel, resource.resourceType().category().title, categoryName);
+      categoryElement = new Resources.StorageCategoryTreeElement(
+          this._section._panel, resource.resourceType().category().title, categoryName);
       this._categoryElements[resourceType.name()] = categoryElement;
       this._insertInPresentationOrder(this, categoryElement);
     }
-    const resourceTreeElement = new Resources.FrameResourceTreeElement(this._panel, resource);
+    const resourceTreeElement = new Resources.FrameResourceTreeElement(this._section._panel, resource);
     this._insertInPresentationOrder(categoryElement, resourceTreeElement);
     this._treeElementForResource[resource.url] = resourceTreeElement;
   }
@@ -198,8 +221,11 @@
 
   /**
    * @override
+   * @param {!UI.TreeElement} treeElement
    */
   appendChild(treeElement) {
+    if (!this._populated)
+      return;
     this._insertInPresentationOrder(this, treeElement);
   }
 
@@ -235,6 +261,17 @@
     }
     parentTreeElement.insertChild(childTreeElement, i);
   }
+
+  /**
+   * @override
+   */
+  onpopulate() {
+    this._populated = true;
+    for (const child of this._frame.childFrames)
+      this._section._frameAdded(child);
+    for (const resource of this._frame.resources())
+      this.appendResource(resource);
+  }
 };
 
 Resources.FrameResourceTreeElement = class extends Resources.BaseStorageTreeElement {
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/ServiceWorkersView.js b/third_party/WebKit/Source/devtools/front_end/resources/ServiceWorkersView.js
index 2b8138d8..a8f3da1 100644
--- a/third_party/WebKit/Source/devtools/front_end/resources/ServiceWorkersView.js
+++ b/third_party/WebKit/Source/devtools/front_end/resources/ServiceWorkersView.js
@@ -307,8 +307,11 @@
     this._sourceField = this._wrapWidget(this._section.appendField(Common.UIString('Source')));
     this._statusField = this._wrapWidget(this._section.appendField(Common.UIString('Status')));
     this._clientsField = this._wrapWidget(this._section.appendField(Common.UIString('Clients')));
-    this._createPushNotificationField();
-    this._createSyncNotificationField();
+    this._createSyncNotificationField(
+        Common.UIString('Push'), this._pushNotificationDataSetting.get(), Common.UIString('Push data'),
+        this._push.bind(this));
+    this._createSyncNotificationField(
+        Common.UIString('Sync'), this._syncTagNameSetting.get(), Common.UIString('Sync tag'), this._sync.bind(this));
 
     this._linkifier = new Components.Linkifier();
     /** @type {!Map<string, !Protocol.Target.TargetInfo>} */
@@ -316,42 +319,25 @@
     this._throttler = new Common.Throttler(500);
   }
 
-  _createPushNotificationField() {
-    const form = this._wrapWidget(this._section.appendField(Common.UIString('Push')))
-                     .createChild('form', 'service-worker-editor-with-button');
-    const editorContainer = form.createChild('div', 'service-worker-notification-editor');
-    const button = UI.createTextButton(Common.UIString('Push'));
-    button.type = 'submit';
-    form.appendChild(button);
-
-    const editorOptions =
-        {lineNumbers: false, lineWrapping: true, autoHeight: true, padBottom: false, mimeType: 'application/json'};
-    const editor = new TextEditor.CodeMirrorTextEditor(editorOptions);
-    editor.setText(this._pushNotificationDataSetting.get());
-    editor.element.addEventListener('keydown', e => {
-      if (e.key === 'Tab')
-        e.consume(false);
-    }, true);
-    editor.show(editorContainer);
-    form.addEventListener('submit', e => {
-      this._push(editor.text() || '');
-      e.consume(true);
-    });
-  }
-
-  _createSyncNotificationField() {
-    const form = this._wrapWidget(this._section.appendField(Common.UIString('Sync')))
-                     .createChild('form', 'service-worker-editor-with-button');
+  /**
+   * @param {string} label
+   * @param {string} initialValue
+   * @param {string} placeholder
+   * @param {function(string)} callback
+   */
+  _createSyncNotificationField(label, initialValue, placeholder, callback) {
+    const form =
+        this._wrapWidget(this._section.appendField(label)).createChild('form', 'service-worker-editor-with-button');
     const editor = form.createChild('input', 'source-code service-worker-notification-editor');
-    const button = UI.createTextButton(Common.UIString('Sync'));
+    const button = UI.createTextButton(label);
     button.type = 'submit';
     form.appendChild(button);
 
-    editor.value = this._syncTagNameSetting.get();
-    editor.placeholder = Common.UIString('Sync tag');
+    editor.value = initialValue;
+    editor.placeholder = placeholder;
 
     form.addEventListener('submit', e => {
-      this._sync(true, editor.value || '');
+      callback(editor.value || '');
       e.consume(true);
     });
   }
@@ -524,12 +510,11 @@
   }
 
   /**
-   * @param {boolean} lastChance
    * @param {string} tag
    */
-  _sync(lastChance, tag) {
+  _sync(tag) {
     this._syncTagNameSetting.set(tag);
-    this._manager.dispatchSyncEvent(this._registration.id, tag, lastChance);
+    this._manager.dispatchSyncEvent(this._registration.id, tag, true);
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/Resource.js b/third_party/WebKit/Source/devtools/front_end/sdk/Resource.js
index 28babb0..8f0c412 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/Resource.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/Resource.js
@@ -284,4 +284,11 @@
       return !!this._content && !this._contentEncoded;
     return false;
   }
+
+  /**
+   * @return {!SDK.ResourceTreeFrame}
+   */
+  frame() {
+    return this._resourceTreeModel.frameForId(this._frameId);
+  }
 };
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineLoader.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineLoader.js
index 4609653..6bb573a 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineLoader.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineLoader.js
@@ -46,6 +46,31 @@
   }
 
   /**
+   * @param {!Array.<!SDK.TracingManager.EventPayload>} events
+   * @param {!Timeline.TimelineLoader.Client} client
+   * @return {!Timeline.TimelineLoader}
+   */
+  static loadFromEvents(events, client) {
+    const loader = new Timeline.TimelineLoader(client);
+
+    setTimeout(async () => {
+      const eventsPerChunk = 5000;
+      const yieldEventLoopToPaint = () => new Promise(res => setTimeout(res, 0));
+
+      client.loadingStarted();
+      for (let i = 0; i < events.length; i += eventsPerChunk) {
+        const chunk = events.slice(i, i + eventsPerChunk);
+        loader._tracingModel.addEvents(chunk);
+        client.loadingProgress((i + chunk.length) / events.length);
+        await yieldEventLoopToPaint();
+      }
+      loader.close();
+    }, 0);
+
+    return loader;
+  }
+
+  /**
    * @param {string} url
    * @param {!Timeline.TimelineLoader.Client} client
    * @return {!Timeline.TimelineLoader}
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js
index df7d911..7bb2b6e 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js
@@ -160,6 +160,16 @@
   }
 
   /**
+   * @param {!Array.<!SDK.TracingManager.EventPayload>} events
+   */
+  loadFromEvents(events) {
+    if (this._state !== Timeline.TimelinePanel.State.Idle)
+      return;
+    this._prepareToLoadTimeline();
+    this._loader = Timeline.TimelineLoader.loadFromEvents(events, this);
+  }
+
+  /**
    * @param {!Common.Event} event
    */
   _onWindowChanged(event) {
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js
index 1dd3bc093..1e76f37 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js
@@ -62,6 +62,9 @@
     this._textFilter = new Timeline.TimelineFilters.RegExp();
     this._filters = [...filters, this._textFilter];
 
+    this._currentThreadSetting = Common.settings.createSetting('timelineTreeCurrentThread', 0);
+    this._currentThreadSetting.addChangeListener(this.refreshTree, this);
+
     const columns = /** @type {!Array<!DataGrid.DataGrid.ColumnDescriptor>} */ ([]);
     this.populateColumns(columns);
 
@@ -127,10 +130,11 @@
    * @param {!UI.Toolbar} toolbar
    */
   populateToolbar(toolbar) {
-    this._threadSelector = new UI.ToolbarComboBox(targetChanged.bind(this));
+    this._threadSelector = new UI.ToolbarSettingComboBox([], this._currentThreadSetting);
+    this._threadSelector.setVisible(false);
     this._threadSelector.setMaxWidth(230);
-    this._currentThreadSetting = Common.settings.createSetting('timelineTreeCurrentThread', 0);
     toolbar.appendToolbarItem(this._threadSelector);
+
     this._textFilterUI = new UI.ToolbarInput(Common.UIString('Filter'));
     this._textFilterUI.addEventListener(UI.ToolbarInput.Event.TextChanged, textFilterChanged, this);
     toolbar.appendToolbarItem(this._textFilterUI);
@@ -143,14 +147,6 @@
       this._textFilter.setRegExp(searchQuery ? createPlainTextSearchRegex(searchQuery, 'i') : null);
       this.refreshTree();
     }
-
-    /**
-     * @this {Timeline.TimelineTreeView}
-     */
-    function targetChanged() {
-      this._currentThreadSetting.set(this._threadSelector.selectedIndex());
-      this.refreshTree();
-    }
   }
 
   /**
@@ -163,26 +159,21 @@
   }
 
   _populateThreadSelector() {
-    this._threadSelector.removeOptions();
-    this._threadEvents = [];
-    if (!this._model) {
-      this._threadSelector.setVisible(false);
-      this._currentThreadSetting.set(0);
+    if (!this._model)
       return;
-    }
-    let option = this._threadSelector.createOption(Common.UIString('Main'), '', '0');
-    this._threadEvents.push(this._model.timelineModel().mainThreadEvents());
-    this._threadSelector.addOption(option);
+    const options = [];
+    this._threadEvents = [this._model.timelineModel().mainThreadEvents()];
+    options.push({value: '0', label: ls`Main`, title: ls`Main`});
     for (const thread of this._model.timelineModel().virtualThreads()) {
       if (!thread.name)
         continue;
-      if (!thread.events.some(e => e.name === TimelineModel.TimelineModel.RecordType.JSFrame))
+      if (!thread.events.some(e => SDK.TracingModel.isTopLevelEvent(e)))
         continue;
-      option = this._threadSelector.createOption(thread.name, '', String(this._threadEvents.length));
-      this._threadSelector.addOption(option);
+      options.push({value: String(this._threadEvents.length), label: thread.name, title: thread.name});
       this._threadEvents.push(thread.events);
     }
-    this._threadSelector.setSelectedIndex(this._currentThreadSetting.get());
+
+    this._threadSelector.setOptions(options);
     this._threadSelector.setVisible(this._threadEvents.length > 1);
   }
 
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/Toolbar.js b/third_party/WebKit/Source/devtools/front_end/ui/Toolbar.js
index c8e18a9ac..d04dfc3 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/Toolbar.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/Toolbar.js
@@ -982,7 +982,7 @@
  */
 UI.ToolbarSettingComboBox = class extends UI.ToolbarComboBox {
   /**
-   * @param {!Array.<!{value: string, label: string, title: string, default:(boolean|undefined)}>} options
+   * @param {!Array<!{value: string, label: string, title: string}>} options
    * @param {!Common.Setting} setting
    * @param {string=} optGroup
    */
@@ -991,21 +991,30 @@
     this._setting = setting;
     this._options = options;
     this._selectElement.addEventListener('change', this._valueChanged.bind(this), false);
-    let optionContainer = this._selectElement;
-    const optGroupElement = optGroup ? this._selectElement.createChild('optgroup') : null;
-    if (optGroupElement) {
+    if (optGroup) {
+      const optGroupElement = this._selectElement.createChild('optgroup');
       optGroupElement.label = optGroup;
-      optionContainer = optGroupElement;
+      this._optionContainer = optGroupElement;
+    } else {
+      this._optionContainer = this._selectElement;
     }
+    this.setOptions(options);
+    setting.addChangeListener(this._settingChanged, this);
+  }
+
+  /**
+   * @param {!Array<!{value: string, label: string, title: string}>} options
+   */
+  setOptions(options) {
+    this._options = options;
+    this._optionContainer.removeChildren();
     for (let i = 0; i < options.length; ++i) {
       const dataOption = options[i];
       const option = this.createOption(dataOption.label, dataOption.title, dataOption.value);
-      optionContainer.appendChild(option);
-      if (setting.get() === dataOption.value)
+      this._optionContainer.appendChild(option);
+      if (this._setting.get() === dataOption.value)
         this.setSelectedIndex(i);
     }
-
-    setting.addChangeListener(this._settingChanged, this);
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/module.json b/third_party/WebKit/Source/devtools/front_end/ui/module.json
index df48b544..bd5f5a1e 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/ui/module.json
@@ -78,7 +78,6 @@
         "inspectorSyntaxHighlightDark.css",
         "inspectorViewTabbedPane.css",
         "listWidget.css",
-        "panelEnablerView.css",
         "popover.css",
         "progressIndicator.css",
         "radioButton.css",
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/panelEnablerView.css b/third_party/WebKit/Source/devtools/front_end/ui/panelEnablerView.css
deleted file mode 100644
index ebfbb92e..0000000
--- a/third_party/WebKit/Source/devtools/front_end/ui/panelEnablerView.css
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2006, 2007, 2008 Apple Inc.  All rights reserved.
- * Copyright (C) 2009 Anthony Ricaud <rik@webkit.org>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- *     its contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-.panel-enabler-view {
-    background-color: white;
-    font-size: 13px;
-    text-align: center;
-    overflow-x: hidden;
-    overflow-y: overlay;
-    flex: auto;
-    display: flex;
-}
-
-.panel-enabler-view h1 {
-    color: rgb(110, 116, 128);
-    font-size: 16px;
-    line-height: 20px;
-    font-weight: normal;
-    margin-top: 0;
-}
-
-.panel-enabler-view img {
-    height: 100%;
-    min-height: 200px;
-    max-width: 100%;
-    top: 0;
-    bottom: 0;
-    padding: 20px 0 20px 20px;
-    margin: auto;
-    vertical-align: middle;
-}
-
-.panel-enabler-view img.hidden {
-    display: initial !important;
-    width: 0;
-}
-
-.panel-enabler-view .flexible-space {
-    -webkit-flex: 1;
-}
-
-.panel-enabler-view form {
-    display: inline-block;
-    vertical-align: middle;
-    width: 330px;
-    margin: 0;
-    padding: 15px;
-    white-space: normal;
-}
-
-.panel-enabler-view label {
-    position: relative;
-    display: block;
-    text-align: left;
-    word-break: break-word;
-    margin: 0 0 5px 20px;
-}
-
-.panel-enabler-view label:only-of-type {
-    display: none;
-}
diff --git a/third_party/WebKit/Source/modules/animationworklet/WorkletAnimation.cpp b/third_party/WebKit/Source/modules/animationworklet/WorkletAnimation.cpp
index ea7b9f6..f99ba485 100644
--- a/third_party/WebKit/Source/modules/animationworklet/WorkletAnimation.cpp
+++ b/third_party/WebKit/Source/modules/animationworklet/WorkletAnimation.cpp
@@ -4,7 +4,7 @@
 
 #include "modules/animationworklet/WorkletAnimation.h"
 
-#include "bindings/modules/v8/animation_effect_read_only_or_animation_effect_read_only_sequence.h"
+#include "bindings/modules/v8/animation_effect_or_animation_effect_sequence.h"
 #include "core/animation/ElementAnimations.h"
 #include "core/animation/KeyframeEffectModel.h"
 #include "core/animation/ScrollTimeline.h"
@@ -20,29 +20,29 @@
 
 namespace {
 bool ConvertAnimationEffects(
-    const AnimationEffectReadOnlyOrAnimationEffectReadOnlySequence& effects,
-    HeapVector<Member<KeyframeEffectReadOnly>>& keyframe_effects,
+    const AnimationEffectOrAnimationEffectSequence& effects,
+    HeapVector<Member<KeyframeEffect>>& keyframe_effects,
     String& error_string) {
   DCHECK(keyframe_effects.IsEmpty());
 
-  // Currently we only support KeyframeEffectReadOnly (and its subclasses).
-  if (effects.IsAnimationEffectReadOnly()) {
-    const auto& effect = effects.GetAsAnimationEffectReadOnly();
-    if (!effect->IsKeyframeEffectReadOnly()) {
-      error_string = "Effect must be a KeyframeEffectReadOnly object";
+  // Currently we only support KeyframeEffect.
+  if (effects.IsAnimationEffect()) {
+    const auto& effect = effects.GetAsAnimationEffect();
+    if (!effect->IsKeyframeEffect()) {
+      error_string = "Effect must be a KeyframeEffect object";
       return false;
     }
-    keyframe_effects.push_back(ToKeyframeEffectReadOnly(effect));
+    keyframe_effects.push_back(ToKeyframeEffect(effect));
   } else {
-    const HeapVector<Member<AnimationEffectReadOnly>>& effect_sequence =
-        effects.GetAsAnimationEffectReadOnlySequence();
+    const HeapVector<Member<AnimationEffect>>& effect_sequence =
+        effects.GetAsAnimationEffectSequence();
     keyframe_effects.ReserveInitialCapacity(effect_sequence.size());
     for (const auto& effect : effect_sequence) {
-      if (!effect->IsKeyframeEffectReadOnly()) {
-        error_string = "Effects must all be KeyframeEffectReadOnly objects";
+      if (!effect->IsKeyframeEffect()) {
+        error_string = "Effects must all be KeyframeEffect objects";
         return false;
       }
-      keyframe_effects.push_back(ToKeyframeEffectReadOnly(effect));
+      keyframe_effects.push_back(ToKeyframeEffect(effect));
     }
   }
 
@@ -149,13 +149,13 @@
 
 WorkletAnimation* WorkletAnimation::Create(
     String animator_name,
-    const AnimationEffectReadOnlyOrAnimationEffectReadOnlySequence& effects,
+    const AnimationEffectOrAnimationEffectSequence& effects,
     DocumentTimelineOrScrollTimeline timeline,
     scoped_refptr<SerializedScriptValue> options,
     ExceptionState& exception_state) {
   DCHECK(IsMainThread());
 
-  HeapVector<Member<KeyframeEffectReadOnly>> keyframe_effects;
+  HeapVector<Member<KeyframeEffect>> keyframe_effects;
   String error_string;
   if (!ConvertAnimationEffects(effects, keyframe_effects, error_string)) {
     exception_state.ThrowDOMException(kNotSupportedError, error_string);
@@ -177,7 +177,7 @@
 WorkletAnimation::WorkletAnimation(
     const String& animator_name,
     Document& document,
-    const HeapVector<Member<KeyframeEffectReadOnly>>& effects,
+    const HeapVector<Member<KeyframeEffect>>& effects,
     DocumentTimelineOrScrollTimeline timeline,
     scoped_refptr<SerializedScriptValue> options)
     : animator_name_(animator_name),
@@ -203,7 +203,7 @@
   document_->GetWorkletAnimationController().AttachAnimation(*this);
   play_state_ = Animation::kPending;
 
-  KeyframeEffectReadOnly* target_effect = effects_.at(0);
+  KeyframeEffect* target_effect = effects_.at(0);
   Element* target = target_effect->target();
   if (!target)
     return;
@@ -220,7 +220,7 @@
   document_->GetWorkletAnimationController().DetachAnimation(*this);
   play_state_ = Animation::kIdle;
 
-  KeyframeEffectReadOnly* target_effect = effects_.at(0);
+  KeyframeEffect* target_effect = effects_.at(0);
   Element* target = target_effect->target();
   if (!target)
     return;
@@ -232,7 +232,7 @@
 
 bool WorkletAnimation::StartOnCompositor(String* failure_message) {
   DCHECK(IsMainThread());
-  KeyframeEffectReadOnly* target_effect = effects_.at(0);
+  KeyframeEffect* target_effect = effects_.at(0);
   Element& target = *target_effect->target();
 
   // CheckCanStartAnimationOnCompositor requires that the property-specific
diff --git a/third_party/WebKit/Source/modules/animationworklet/WorkletAnimation.h b/third_party/WebKit/Source/modules/animationworklet/WorkletAnimation.h
index c303d083..1ffd40f7bc 100644
--- a/third_party/WebKit/Source/modules/animationworklet/WorkletAnimation.h
+++ b/third_party/WebKit/Source/modules/animationworklet/WorkletAnimation.h
@@ -8,7 +8,7 @@
 #include "bindings/core/v8/serialization/SerializedScriptValue.h"
 #include "bindings/modules/v8/document_timeline_or_scroll_timeline.h"
 #include "core/animation/Animation.h"
-#include "core/animation/KeyframeEffectReadOnly.h"
+#include "core/animation/KeyframeEffect.h"
 #include "core/animation/WorkletAnimationBase.h"
 #include "modules/ModulesExport.h"
 #include "platform/animation/CompositorAnimation.h"
@@ -17,7 +17,7 @@
 
 namespace blink {
 
-class AnimationEffectReadOnlyOrAnimationEffectReadOnlySequence;
+class AnimationEffectOrAnimationEffectSequence;
 
 // The main-thread controller for a single AnimationWorklet animator instance.
 //
@@ -39,7 +39,7 @@
  public:
   static WorkletAnimation* Create(
       String animator_name,
-      const AnimationEffectReadOnlyOrAnimationEffectReadOnlySequence&,
+      const AnimationEffectOrAnimationEffectSequence&,
       DocumentTimelineOrScrollTimeline,
       scoped_refptr<SerializedScriptValue>,
       ExceptionState&);
@@ -71,14 +71,14 @@
   const DocumentTimelineOrScrollTimeline& Timeline() { return timeline_; }
 
   const scoped_refptr<SerializedScriptValue> Options() { return options_; }
-  KeyframeEffectReadOnly* GetEffect() const override { return effects_.at(0); }
+  KeyframeEffect* GetEffect() const override { return effects_.at(0); }
 
   void Trace(blink::Visitor*) override;
 
  private:
   WorkletAnimation(const String& animator_name,
                    Document&,
-                   const HeapVector<Member<KeyframeEffectReadOnly>>&,
+                   const HeapVector<Member<KeyframeEffect>>&,
                    DocumentTimelineOrScrollTimeline,
                    scoped_refptr<SerializedScriptValue>);
 
@@ -87,7 +87,7 @@
 
   Member<Document> document_;
 
-  HeapVector<Member<KeyframeEffectReadOnly>> effects_;
+  HeapVector<Member<KeyframeEffect>> effects_;
   DocumentTimelineOrScrollTimeline timeline_;
   scoped_refptr<SerializedScriptValue> options_;
 
diff --git a/third_party/WebKit/Source/modules/animationworklet/WorkletAnimation.idl b/third_party/WebKit/Source/modules/animationworklet/WorkletAnimation.idl
index 1d8c199..b640db3e 100644
--- a/third_party/WebKit/Source/modules/animationworklet/WorkletAnimation.idl
+++ b/third_party/WebKit/Source/modules/animationworklet/WorkletAnimation.idl
@@ -7,7 +7,7 @@
 // TODO(smcgruer): Update constructor to match latest spec.
 [
     Constructor(DOMString animatorName,
-                (AnimationEffectReadOnly or sequence<AnimationEffectReadOnly>) effects,
+                (AnimationEffect or sequence<AnimationEffect>) effects,
                 (DocumentTimeline or ScrollTimeline) timeline,
                 SerializedScriptValue options),
     RaisesException=Constructor,
diff --git a/third_party/WebKit/Source/modules/animationworklet/WorkletAnimationTest.cpp b/third_party/WebKit/Source/modules/animationworklet/WorkletAnimationTest.cpp
index 662cb212..c78a961 100644
--- a/third_party/WebKit/Source/modules/animationworklet/WorkletAnimationTest.cpp
+++ b/third_party/WebKit/Source/modules/animationworklet/WorkletAnimationTest.cpp
@@ -4,7 +4,7 @@
 
 #include "modules/animationworklet/WorkletAnimation.h"
 
-#include "bindings/modules/v8/animation_effect_read_only_or_animation_effect_read_only_sequence.h"
+#include "bindings/modules/v8/animation_effect_or_animation_effect_sequence.h"
 #include "core/animation/ElementAnimations.h"
 #include "core/animation/KeyframeEffect.h"
 #include "core/animation/KeyframeEffectModel.h"
@@ -40,9 +40,9 @@
 }
 
 WorkletAnimation* CreateWorkletAnimation(Element* element) {
-  AnimationEffectReadOnlyOrAnimationEffectReadOnlySequence effects;
-  AnimationEffectReadOnly* effect = CreateKeyframeEffect(element);
-  effects.SetAnimationEffectReadOnly(effect);
+  AnimationEffectOrAnimationEffectSequence effects;
+  AnimationEffect* effect = CreateKeyframeEffect(element);
+  effects.SetAnimationEffect(effect);
   DocumentTimelineOrScrollTimeline timeline;
   scoped_refptr<SerializedScriptValue> options;
   DummyExceptionStateForTesting exception_state;
diff --git a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.cpp b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.cpp
index aa6007fc..c417968 100644
--- a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.cpp
+++ b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.cpp
@@ -596,7 +596,7 @@
   filter_operations_ = filters;
 }
 
-void CanvasRenderingContext2D::ResourceContentChanged() {
+void CanvasRenderingContext2D::ResourceContentChanged(InvalidationModeMask) {
   ResourceElementChanged();
 }
 
diff --git a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.h b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.h
index 46a8ca2..4faf52d 100644
--- a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.h
+++ b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.h
@@ -150,7 +150,7 @@
   String GetIdFromControl(const Element*) override;
 
   // SVGResourceClient implementation
-  void ResourceContentChanged() override;
+  void ResourceContentChanged(InvalidationModeMask) override;
   void ResourceElementChanged() override;
 
   void UpdateFilterReferences(const FilterOperations&);
diff --git a/third_party/WebKit/Source/modules/canvas/imagebitmap/ImageBitmapRenderingContextBase.cpp b/third_party/WebKit/Source/modules/canvas/imagebitmap/ImageBitmapRenderingContextBase.cpp
index af9c6cb5..af917a5 100644
--- a/third_party/WebKit/Source/modules/canvas/imagebitmap/ImageBitmapRenderingContextBase.cpp
+++ b/third_party/WebKit/Source/modules/canvas/imagebitmap/ImageBitmapRenderingContextBase.cpp
@@ -44,6 +44,11 @@
   return image_layer_bridge_->GetImage();
 }
 
+void ImageBitmapRenderingContextBase::SetUV(const FloatPoint left_top,
+                                            const FloatPoint right_bottom) {
+  image_layer_bridge_->SetUV(left_top, right_bottom);
+}
+
 WebLayer* ImageBitmapRenderingContextBase::PlatformLayer() const {
   return image_layer_bridge_->PlatformLayer();
 }
diff --git a/third_party/WebKit/Source/modules/canvas/imagebitmap/ImageBitmapRenderingContextBase.h b/third_party/WebKit/Source/modules/canvas/imagebitmap/ImageBitmapRenderingContextBase.h
index 2725998..24694e3 100644
--- a/third_party/WebKit/Source/modules/canvas/imagebitmap/ImageBitmapRenderingContextBase.h
+++ b/third_party/WebKit/Source/modules/canvas/imagebitmap/ImageBitmapRenderingContextBase.h
@@ -9,6 +9,7 @@
 #include "core/html/canvas/CanvasRenderingContext.h"
 #include "core/html/canvas/CanvasRenderingContextFactory.h"
 #include "modules/ModulesExport.h"
+#include "platform/geometry/FloatPoint.h"
 
 namespace blink {
 
@@ -33,6 +34,7 @@
   bool isContextLost() const override { return false; }
   void SetImage(ImageBitmap*);
   scoped_refptr<StaticBitmapImage> GetImage(AccelerationHint) const final;
+  void SetUV(const FloatPoint left_top, const FloatPoint right_bottom);
   bool IsComposited() const final { return true; }
   bool IsAccelerated() const final;
 
diff --git a/third_party/WebKit/Source/modules/keyboard/Keyboard.idl b/third_party/WebKit/Source/modules/keyboard/Keyboard.idl
index f7781e7c..360ca3a 100644
--- a/third_party/WebKit/Source/modules/keyboard/Keyboard.idl
+++ b/third_party/WebKit/Source/modules/keyboard/Keyboard.idl
@@ -7,6 +7,9 @@
     RuntimeEnabled=KeyboardLock,
     SecureContext
 ] interface Keyboard {
-    [CallWith=ScriptState] Promise<void> lock(optional sequence<DOMString> keyCodes = []);
-    void unlock();
+    [CallWith=ScriptState,
+     MeasureAs=KeyboardApiLock
+    ] Promise<void> lock(optional sequence<DOMString> keyCodes = []);
+
+    [MeasureAs=KeyboardApiUnlock] void unlock();
 };
diff --git a/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp b/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp
index 9611ad5..c53a10d1 100644
--- a/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.cpp
@@ -749,13 +749,23 @@
         ShouldShowPictureInPictureButton(MediaElement()));
   }
 
+  UpdateCSSClassFromState();
   OnControlsListUpdated();
 }
 
 void MediaControlsImpl::OnControlsListUpdated() {
   BatchedControlUpdate batch(this);
 
-  fullscreen_button_->SetIsWanted(ShouldShowFullscreenButton(MediaElement()));
+  if (ShouldShowDisabledControls()) {
+    fullscreen_button_->SetIsWanted(true);
+    fullscreen_button_->setAttribute(HTMLNames::disabledAttr,
+                                     ShouldShowFullscreenButton(MediaElement())
+                                         ? AtomicString()
+                                         : AtomicString(""));
+  } else {
+    fullscreen_button_->SetIsWanted(ShouldShowFullscreenButton(MediaElement()));
+    fullscreen_button_->removeAttribute(HTMLNames::disabledAttr);
+  }
 
   RefreshCastButtonVisibilityWithoutUpdate();
 
@@ -1049,6 +1059,11 @@
   Fullscreen::ExitFullscreen(GetDocument());
 }
 
+bool MediaControlsImpl::IsFullscreenEnabled() const {
+  return fullscreen_button_->IsWanted() &&
+         !fullscreen_button_->hasAttribute(HTMLNames::disabledAttr);
+}
+
 void MediaControlsImpl::RemotePlaybackStateChanged() {
   cast_button_->UpdateDisplayType();
   overlay_cast_button_->UpdateDisplayType();
@@ -1360,7 +1375,15 @@
   BatchedControlUpdate batch(this);
   volume_slider_->SetIsWanted(MediaElement().HasAudio() &&
                               !PreferHiddenVolumeControls(GetDocument()));
-  mute_button_->SetIsWanted(MediaElement().HasAudio());
+  if (ShouldShowDisabledControls()) {
+    mute_button_->SetIsWanted(true);
+    mute_button_->setAttribute(
+        HTMLNames::disabledAttr,
+        MediaElement().HasAudio() ? AtomicString() : AtomicString(""));
+  } else {
+    mute_button_->SetIsWanted(MediaElement().HasAudio());
+    mute_button_->removeAttribute(HTMLNames::disabledAttr);
+  }
 }
 
 void MediaControlsImpl::OnFocusIn() {
@@ -1720,8 +1743,7 @@
 
   is_acting_as_audio_controls_ = true;
   PopulatePanel();
-  UpdateCSSClassFromState();
-  UpdateOverflowMenuWanted();
+  Reset();
 }
 
 void MediaControlsImpl::StopActingAsAudioControls() {
@@ -1730,8 +1752,12 @@
 
   is_acting_as_audio_controls_ = false;
   PopulatePanel();
-  UpdateCSSClassFromState();
-  UpdateOverflowMenuWanted();
+  Reset();
+}
+
+bool MediaControlsImpl::ShouldShowDisabledControls() const {
+  return IsModern() && MediaElement().IsHTMLVideoElement() &&
+         !is_acting_as_audio_controls_;
 }
 
 void MediaControlsImpl::Invalidate(Element* element) {
diff --git a/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.h b/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.h
index def3314..f8f8cfb 100644
--- a/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.h
+++ b/third_party/WebKit/Source/modules/media_controls/MediaControlsImpl.h
@@ -114,6 +114,10 @@
   void EnterFullscreen();
   void ExitFullscreen();
 
+  // Called by the MediaControlOverlayPlayButtonElement to check if toggling
+  // fullscreen is allowed.
+  bool IsFullscreenEnabled() const;
+
   // Text track related methods exposed to components handling closed captions.
   void ToggleTextTrackList();
   void ShowTextTrackAtIndex(unsigned);
@@ -262,6 +266,8 @@
   void StartActingAsAudioControls();
   void StopActingAsAudioControls();
 
+  bool ShouldShowDisabledControls() const;
+
   // Node
   bool IsMediaControls() const override { return true; }
   bool WillRespondToMouseMoveEvents() override { return true; }
diff --git a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.cpp b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.cpp
index b3329463..3d9f23f 100644
--- a/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.cpp
+++ b/third_party/WebKit/Source/modules/media_controls/elements/MediaControlOverlayPlayButtonElement.cpp
@@ -232,11 +232,13 @@
           MaybeJump(kNumberOfSecondsToJump * -1);
         }
       } else {
-        // Enter or exit fullscreen.
-        if (MediaElement().IsFullscreen())
-          GetMediaControls().ExitFullscreen();
-        else
-          GetMediaControls().EnterFullscreen();
+        if (GetMediaControls().IsFullscreenEnabled()) {
+          // Enter or exit fullscreen.
+          if (MediaElement().IsFullscreen())
+            GetMediaControls().ExitFullscreen();
+          else
+            GetMediaControls().EnterFullscreen();
+        }
       }
 
       event->SetDefaultHandled();
diff --git a/third_party/WebKit/Source/modules/media_controls/resources/modernMediaControls.css b/third_party/WebKit/Source/modules/media_controls/resources/modernMediaControls.css
index f8f433f..2accbcda 100644
--- a/third_party/WebKit/Source/modules/media_controls/resources/modernMediaControls.css
+++ b/third_party/WebKit/Source/modules/media_controls/resources/modernMediaControls.css
@@ -206,6 +206,11 @@
     url(default_200_percent/modern/ic_fullscreen_exit_white.png) 2x);
 }
 
+video::-webkit-media-controls-mute-button:disabled,
+video::-webkit-media-controls-fullscreen-button:disabled {
+  opacity: 0.3;
+}
+
 audio::-internal-media-controls-cast-button,
 video::-internal-media-controls-cast-button {
   background-image: -webkit-image-set(
@@ -630,7 +635,6 @@
   display: none;
 }
 
-
 .state-no-source input[pseudo="-webkit-media-controls-overlay-play-button" i],
 .state-no-source div[pseudo="-internal-media-controls-button-panel" i],
 video::-webkit-media-controls.state-no-source input[pseudo="-webkit-media-controls-timeline" i] {
diff --git a/third_party/WebKit/Source/modules/mediastream/InputDeviceInfo.cpp b/third_party/WebKit/Source/modules/mediastream/InputDeviceInfo.cpp
index a580e8c17..d135eb5 100644
--- a/third_party/WebKit/Source/modules/mediastream/InputDeviceInfo.cpp
+++ b/third_party/WebKit/Source/modules/mediastream/InputDeviceInfo.cpp
@@ -80,8 +80,11 @@
   capabilities.setDeviceId(deviceId());
   capabilities.setGroupId(groupId());
 
-  if (DeviceType() == MediaDeviceType::MEDIA_AUDIO_INPUT)
+  if (DeviceType() == MediaDeviceType::MEDIA_AUDIO_INPUT) {
     capabilities.setEchoCancellation({true, false});
+    capabilities.setAutoGainControl({true, false});
+    capabilities.setNoiseSuppression({true, false});
+  }
 
   if (DeviceType() == MediaDeviceType::MEDIA_VIDEO_INPUT) {
     if (!platform_capabilities_.width.empty()) {
diff --git a/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.cpp b/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.cpp
index 77f056e8..6da8aba 100644
--- a/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.cpp
+++ b/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.cpp
@@ -313,10 +313,16 @@
   capabilities.setDeviceId(platform_capabilities.device_id);
 
   if (component_->Source()->GetType() == MediaStreamSource::kTypeAudio) {
-    Vector<bool> echo_cancellation;
+    Vector<bool> echo_cancellation, auto_gain_control, noise_suppression;
     for (bool value : platform_capabilities.echo_cancellation)
       echo_cancellation.push_back(value);
     capabilities.setEchoCancellation(echo_cancellation);
+    for (bool value : platform_capabilities.auto_gain_control)
+      auto_gain_control.push_back(value);
+    capabilities.setAutoGainControl(auto_gain_control);
+    for (bool value : platform_capabilities.noise_suppression)
+      noise_suppression.push_back(value);
+    capabilities.setNoiseSuppression(noise_suppression);
   }
 
   if (component_->Source()->GetType() == MediaStreamSource::kTypeVideo) {
diff --git a/third_party/WebKit/Source/modules/mediastream/MediaTrackCapabilities.idl b/third_party/WebKit/Source/modules/mediastream/MediaTrackCapabilities.idl
index f8958be..10667aa 100644
--- a/third_party/WebKit/Source/modules/mediastream/MediaTrackCapabilities.idl
+++ b/third_party/WebKit/Source/modules/mediastream/MediaTrackCapabilities.idl
@@ -9,6 +9,8 @@
     DoubleRange frameRate;
     sequence<DOMString> facingMode;
     sequence<boolean> echoCancellation;
+    sequence<boolean> autoGainControl;
+    sequence<boolean> noiseSuppression;
     DOMString deviceId;
     DOMString groupId;
     // W3C Image Capture API
diff --git a/third_party/WebKit/Source/modules/mediastream/MediaTrackSupportedConstraints.idl b/third_party/WebKit/Source/modules/mediastream/MediaTrackSupportedConstraints.idl
index 4f07446..5fd9c79f 100644
--- a/third_party/WebKit/Source/modules/mediastream/MediaTrackSupportedConstraints.idl
+++ b/third_party/WebKit/Source/modules/mediastream/MediaTrackSupportedConstraints.idl
@@ -17,6 +17,8 @@
     boolean sampleRate = true;
     boolean sampleSize = true;
     boolean echoCancellation = true;
+    boolean autoGainControl = true;
+    boolean noiseSuppression = true;
     boolean latency = true;
     boolean channelCount = true;
     boolean deviceId = true;
diff --git a/third_party/WebKit/Source/modules/payments/PaymentInstruments.cpp b/third_party/WebKit/Source/modules/payments/PaymentInstruments.cpp
index cee4aaf..d1a8ed7 100644
--- a/third_party/WebKit/Source/modules/payments/PaymentInstruments.cpp
+++ b/third_party/WebKit/Source/modules/payments/PaymentInstruments.cpp
@@ -15,6 +15,7 @@
 #include "core/dom/Document.h"
 #include "core/frame/Frame.h"
 #include "core/frame/LocalFrame.h"
+#include "core/frame/UseCounter.h"
 #include "core/inspector/ConsoleMessage.h"
 #include "modules/payments/BasicCardHelper.h"
 #include "modules/payments/PaymentInstrument.h"
@@ -24,6 +25,7 @@
 #include "public/platform/TaskType.h"
 #include "public/platform/WebIconSizesParser.h"
 #include "public/platform/modules/manifest/manifest.mojom-blink.h"
+#include "public/platform/web_feature.mojom-blink.h"
 
 namespace blink {
 namespace {
@@ -278,6 +280,9 @@
     instrument->stringified_capabilities = WTF::g_empty_string;
   }
 
+  UseCounter::Count(resolver->GetExecutionContext(),
+                    WebFeature::kPaymentHandler);
+
   manager_->SetPaymentInstrument(
       instrument_key, std::move(instrument),
       WTF::Bind(&PaymentInstruments::onSetPaymentInstrument,
diff --git a/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.cpp b/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.cpp
index 70aaa5d..41452ed 100644
--- a/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.cpp
+++ b/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.cpp
@@ -118,6 +118,14 @@
 
 const char kSignalingStateClosedMessage[] =
     "The RTCPeerConnection's signalingState is 'closed'.";
+const char kSignalingStatePreventsOfferMessage[] =
+    "The RTCPeerConnection's signalingState must be 'stable' or "
+    "'have-local-offer' to apply an offer";
+const char kSignalingStatePreventsAnswerMessage[] =
+    "The RTCPeerConnection's signalingState must be 'have-remote-offer' or "
+    "'have-local-pranswer' to apply an answer";
+const char kModifiedSdpMessage[] =
+    "The SDP does not match the previously generated SDP for this type";
 
 // The maximum number of PeerConnections that can exist simultaneously.
 const long kMaxPeerConnections = 500;
@@ -437,6 +445,30 @@
   Persistent<ScriptPromiseResolver> resolver_;
 };
 
+bool FingerprintMismatch(String old_sdp, String new_sdp) {
+  // Check special case of externally generated SDP without fingerprints.
+  // It's impossible to generate a valid fingerprint without createOffer
+  // or createAnswer, so this only applies when there are no fingerprints.
+  // This is allowed.
+  const size_t new_fingerprint_pos = new_sdp.Find("\na=fingerprint:");
+  if (new_fingerprint_pos == kNotFound)
+    return false;
+  // Look for fingerprint having been added. Not allowed.
+  const size_t old_fingerprint_pos = old_sdp.Find("\na=fingerprint:");
+  if (old_fingerprint_pos == kNotFound) {
+    return true;
+  }
+  // Look for fingerprint being modified. Not allowed.
+  const size_t old_fingerprint_end =
+      old_sdp.Find("\n", old_fingerprint_pos + 1);
+  const size_t new_fingerprint_end =
+      new_sdp.Find("\n", new_fingerprint_pos + 1);
+  return old_sdp.Substring(old_fingerprint_pos,
+                           old_fingerprint_end - old_fingerprint_pos) !=
+         new_sdp.Substring(new_fingerprint_pos,
+                           new_fingerprint_end - new_fingerprint_pos);
+}
+
 }  // namespace
 
 RTCPeerConnection::EventWrapper::EventWrapper(Event* event,
@@ -579,7 +611,7 @@
   }
 
   connection_handle_for_scheduler_ =
-      document->GetFrame()->FrameScheduler()->OnActiveConnectionCreated();
+      document->GetFrame()->GetFrameScheduler()->OnActiveConnectionCreated();
 }
 
 RTCPeerConnection::~RTCPeerConnection() {
@@ -735,20 +767,71 @@
   return ScriptPromise::CastUndefined(script_state);
 }
 
+DOMException* RTCPeerConnection::checkSdpForStateErrors(
+    ExecutionContext* context,
+    const RTCSessionDescriptionInit& session_description_init,
+    String* sdp) {
+  if (signaling_state_ == kSignalingStateClosed) {
+    return DOMException::Create(kInvalidStateError,
+                                kSignalingStateClosedMessage);
+  }
+
+  *sdp = session_description_init.sdp();
+  if (session_description_init.type() == "offer") {
+    if (signaling_state_ != kSignalingStateStable &&
+        signaling_state_ != kSignalingStateHaveLocalOffer) {
+      return DOMException::Create(kInvalidStateError,
+                                  kSignalingStatePreventsOfferMessage);
+    }
+    if (sdp->IsNull() || sdp->IsEmpty()) {
+      *sdp = last_offer_;
+    } else if (session_description_init.sdp() != last_offer_) {
+      if (FingerprintMismatch(last_offer_, *sdp)) {
+        return DOMException::Create(kInvalidModificationError,
+                                    kModifiedSdpMessage);
+      } else {
+        UseCounter::Count(context, WebFeature::kRTCLocalSdpModification);
+        return nullptr;
+        // TODO(https://crbug.com/823036): Return failure for all modification.
+      }
+    }
+  } else if (session_description_init.type() == "answer" ||
+             session_description_init.type() == "pranswer") {
+    if (signaling_state_ != kSignalingStateHaveRemoteOffer &&
+        signaling_state_ != kSignalingStateHaveLocalPrAnswer) {
+      return DOMException::Create(kInvalidStateError,
+                                  kSignalingStatePreventsAnswerMessage);
+    }
+    if (sdp->IsNull() || sdp->IsEmpty()) {
+      *sdp = last_answer_;
+    } else if (session_description_init.sdp() != last_answer_) {
+      if (FingerprintMismatch(last_answer_, *sdp)) {
+        return DOMException::Create(kInvalidModificationError,
+                                    kModifiedSdpMessage);
+      } else {
+        UseCounter::Count(context, WebFeature::kRTCLocalSdpModification);
+        return nullptr;
+        // TODO(https://crbug.com/823036): Return failure for all modification.
+      }
+    }
+  }
+  return nullptr;
+}
+
 ScriptPromise RTCPeerConnection::setLocalDescription(
     ScriptState* script_state,
     const RTCSessionDescriptionInit& session_description_init) {
-  if (signaling_state_ == kSignalingStateClosed)
-    return ScriptPromise::RejectWithDOMException(
-        script_state,
-        DOMException::Create(kInvalidStateError, kSignalingStateClosedMessage));
-
+  String sdp;
+  DOMException* exception = checkSdpForStateErrors(
+      ExecutionContext::From(script_state), session_description_init, &sdp);
+  if (exception) {
+    return ScriptPromise::RejectWithDOMException(script_state, exception);
+  }
   ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
   ScriptPromise promise = resolver->Promise();
   RTCVoidRequest* request = RTCVoidRequestPromiseImpl::Create(this, resolver);
   peer_handler_->SetLocalDescription(
-      request, WebRTCSessionDescription(session_description_init.type(),
-                                        session_description_init.sdp()));
+      request, WebRTCSessionDescription(session_description_init.type(), sdp));
   return promise;
 }
 
@@ -775,8 +858,14 @@
               kRTCPeerConnectionSetLocalDescriptionLegacyNoFailureCallback);
   }
 
-  if (CallErrorCallbackIfSignalingStateClosed(signaling_state_, error_callback))
+  String sdp;
+  DOMException* exception =
+      checkSdpForStateErrors(context, session_description_init, &sdp);
+  if (exception) {
+    if (error_callback)
+      AsyncCallErrorCallback(error_callback, exception);
     return ScriptPromise::CastUndefined(script_state);
+  }
 
   RTCVoidRequest* request = RTCVoidRequestImpl::Create(
       GetExecutionContext(), this, success_callback, error_callback);
@@ -1454,6 +1543,14 @@
   CloseInternal();
 }
 
+void RTCPeerConnection::NoteSdpCreated(const RTCSessionDescription& desc) {
+  if (desc.type() == "offer") {
+    last_offer_ = desc.sdp();
+  } else if (desc.type() == "answer") {
+    last_answer_ = desc.sdp();
+  }
+}
+
 void RTCPeerConnection::OnStreamAddTrack(MediaStream* stream,
                                          MediaStreamTrack* track) {
   ExceptionState exception_state(nullptr, ExceptionState::kUnknownContext,
diff --git a/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.h b/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.h
index e5ea469..efa039e 100644
--- a/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.h
+++ b/third_party/WebKit/Source/modules/peerconnection/RTCPeerConnection.h
@@ -41,7 +41,7 @@
 #include "modules/mediastream/MediaStream.h"
 #include "modules/peerconnection/RTCIceCandidate.h"
 #include "platform/AsyncMethodRunner.h"
-#include "platform/WebFrameScheduler.h"
+#include "platform/FrameScheduler.h"
 #include "platform/heap/HeapAllocator.h"
 #include "public/platform/WebMediaConstraints.h"
 #include "public/platform/WebRTCPeerConnectionHandler.h"
@@ -190,6 +190,9 @@
   DEFINE_ATTRIBUTE_EVENT_LISTENER(icegatheringstatechange);
   DEFINE_ATTRIBUTE_EVENT_LISTENER(datachannel);
 
+  // Utility to note result of CreateOffer / CreateAnswer
+  void NoteSdpCreated(const RTCSessionDescription&);
+
   // MediaStreamObserver
   void OnStreamAddTrack(MediaStream*, MediaStreamTrack*) override;
   void OnStreamRemoveTrack(MediaStream*, MediaStreamTrack*) override;
@@ -304,6 +307,10 @@
 
   void RecordRapporMetrics();
 
+  DOMException* checkSdpForStateErrors(ExecutionContext*,
+                                       const RTCSessionDescriptionInit&,
+                                       String* sdp);
+
   SignalingState signaling_state_;
   ICEGatheringState ice_gathering_state_;
   ICEConnectionState ice_connection_state_;
@@ -322,13 +329,17 @@
 
   // This handle notifies scheduler about an active connection associated
   // with a frame. Handle should be destroyed when connection is closed.
-  std::unique_ptr<WebFrameScheduler::ActiveConnectionHandle>
+  std::unique_ptr<FrameScheduler::ActiveConnectionHandle>
       connection_handle_for_scheduler_;
 
   bool negotiation_needed_;
   bool stopped_;
   bool closed_;
 
+  // Internal state [[LastOffer]] and [[LastAnswer]]
+  String last_offer_;
+  String last_answer_;
+
   bool has_data_channels_;  // For RAPPOR metrics
 };
 
diff --git a/third_party/WebKit/Source/modules/peerconnection/RTCSessionDescription.cpp b/third_party/WebKit/Source/modules/peerconnection/RTCSessionDescription.cpp
index b9e3d05f..91be64d 100644
--- a/third_party/WebKit/Source/modules/peerconnection/RTCSessionDescription.cpp
+++ b/third_party/WebKit/Source/modules/peerconnection/RTCSessionDescription.cpp
@@ -65,7 +65,7 @@
     WebRTCSessionDescription web_session_description)
     : web_session_description_(web_session_description) {}
 
-String RTCSessionDescription::type() {
+String RTCSessionDescription::type() const {
   return web_session_description_.GetType();
 }
 
@@ -73,7 +73,7 @@
   web_session_description_.SetType(type);
 }
 
-String RTCSessionDescription::sdp() {
+String RTCSessionDescription::sdp() const {
   return web_session_description_.Sdp();
 }
 
diff --git a/third_party/WebKit/Source/modules/peerconnection/RTCSessionDescription.h b/third_party/WebKit/Source/modules/peerconnection/RTCSessionDescription.h
index 0c22975..cc2d98413 100644
--- a/third_party/WebKit/Source/modules/peerconnection/RTCSessionDescription.h
+++ b/third_party/WebKit/Source/modules/peerconnection/RTCSessionDescription.h
@@ -50,10 +50,10 @@
                                        const RTCSessionDescriptionInit&);
   static RTCSessionDescription* Create(WebRTCSessionDescription);
 
-  String type();
+  String type() const;
   void setType(const String&);
 
-  String sdp();
+  String sdp() const;
   void setSdp(const String&);
 
   ScriptValue toJSONForBinding(ScriptState*);
diff --git a/third_party/WebKit/Source/modules/peerconnection/RTCSessionDescriptionRequestImpl.cpp b/third_party/WebKit/Source/modules/peerconnection/RTCSessionDescriptionRequestImpl.cpp
index 340ee16..24635076 100644
--- a/third_party/WebKit/Source/modules/peerconnection/RTCSessionDescriptionRequestImpl.cpp
+++ b/third_party/WebKit/Source/modules/peerconnection/RTCSessionDescriptionRequestImpl.cpp
@@ -67,8 +67,9 @@
   bool should_fire_callback =
       requester_ ? requester_->ShouldFireDefaultCallbacks() : false;
   if (should_fire_callback && success_callback_) {
-    success_callback_->InvokeAndReportException(
-        nullptr, RTCSessionDescription::Create(web_session_description));
+    auto description = RTCSessionDescription::Create(web_session_description);
+    requester_->NoteSdpCreated(*description);
+    success_callback_->InvokeAndReportException(nullptr, description);
   }
   Clear();
 }
diff --git a/third_party/WebKit/Source/modules/peerconnection/RTCSessionDescriptionRequestPromiseImpl.cpp b/third_party/WebKit/Source/modules/peerconnection/RTCSessionDescriptionRequestPromiseImpl.cpp
index 0b9b412a..0b93bd2 100644
--- a/third_party/WebKit/Source/modules/peerconnection/RTCSessionDescriptionRequestPromiseImpl.cpp
+++ b/third_party/WebKit/Source/modules/peerconnection/RTCSessionDescriptionRequestPromiseImpl.cpp
@@ -34,7 +34,9 @@
 void RTCSessionDescriptionRequestPromiseImpl::RequestSucceeded(
     const WebRTCSessionDescription& web_session_description) {
   if (requester_ && requester_->ShouldFireDefaultCallbacks()) {
-    resolver_->Resolve(RTCSessionDescription::Create(web_session_description));
+    auto description = RTCSessionDescription::Create(web_session_description);
+    requester_->NoteSdpCreated(*description);
+    resolver_->Resolve(description);
   } else {
     // This is needed to have the resolver release its internal resources
     // while leaving the associated promise pending as specified.
diff --git a/third_party/WebKit/Source/modules/websockets/DEPS b/third_party/WebKit/Source/modules/websockets/DEPS
index c37370d..5b2f1f8 100644
--- a/third_party/WebKit/Source/modules/websockets/DEPS
+++ b/third_party/WebKit/Source/modules/websockets/DEPS
@@ -5,4 +5,5 @@
     "+modules/ModulesExport.h",
     "+modules/websockets",
     "+mojo/public/cpp/bindings",
+    "+services/network/public/mojom/websocket.mojom-blink.h",
 ]
diff --git a/third_party/WebKit/Source/modules/websockets/DOMWebSocket.cpp b/third_party/WebKit/Source/modules/websockets/DOMWebSocket.cpp
index 308db28..88fe2b2 100644
--- a/third_party/WebKit/Source/modules/websockets/DOMWebSocket.cpp
+++ b/third_party/WebKit/Source/modules/websockets/DOMWebSocket.cpp
@@ -502,9 +502,9 @@
   buffered_amount_ += size;
   DCHECK(channel_);
 
-  // When the runtime type of |binaryData| is File,
-  // binaryData->blobDataHandle()->size() returns -1. However, in order to
-  // maintain the value of |m_bufferedAmount| correctly, the WebSocket code
+  // When the runtime type of |binary_data| is File,
+  // binary_data->GetBlobDataHandle()->size() returns -1. However, in order to
+  // maintain the value of |buffered_amount_| correctly, the WebSocket code
   // needs to fix the size of the File at this point. For this reason,
   // construct a new BlobDataHandle here with the size that this method
   // observed.
diff --git a/third_party/WebKit/Source/modules/websockets/DOMWebSocket.h b/third_party/WebKit/Source/modules/websockets/DOMWebSocket.h
index 06832220..9a3fc00 100644
--- a/third_party/WebKit/Source/modules/websockets/DOMWebSocket.h
+++ b/third_party/WebKit/Source/modules/websockets/DOMWebSocket.h
@@ -222,7 +222,7 @@
   // not.
   void CloseInternal(int, const String&, ExceptionState&);
 
-  // Updates m_bufferedAmountAfterClose given the amount of data passed to
+  // Updates |buffered_amount_after_close_| given the amount of data passed to
   // send() method after the state changed to CLOSING or CLOSED.
   void UpdateBufferedAmountAfterClose(uint64_t);
   void ReflectBufferedAmountConsumption(TimerBase*);
@@ -241,7 +241,7 @@
   String origin_string_;
 
   uint64_t buffered_amount_;
-  // The consumed buffered amount that will be reflected to m_bufferedAmount
+  // The consumed buffered amount that will be reflected to |buffered_amount_|
   // later. It will be cleared once reflected.
   uint64_t consumed_buffered_amount_;
   uint64_t buffered_amount_after_close_;
diff --git a/third_party/WebKit/Source/modules/websockets/DOMWebSocketTest.cpp b/third_party/WebKit/Source/modules/websockets/DOMWebSocketTest.cpp
index 02cffa9f..0833022 100644
--- a/third_party/WebKit/Source/modules/websockets/DOMWebSocketTest.cpp
+++ b/third_party/WebKit/Source/modules/websockets/DOMWebSocketTest.cpp
@@ -114,7 +114,7 @@
   ~DOMWebSocketTestScope() {
     if (!websocket_)
       return;
-    // These statements are needed to clear WebSocket::m_channel to
+    // These statements are needed to clear WebSocket::channel_ to
     // avoid ASSERTION failure on ~DOMWebSocket.
     DCHECK(Socket().Channel());
     ::testing::Mock::VerifyAndClear(Socket().Channel());
diff --git a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp
index af64deb..4f241891 100644
--- a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp
+++ b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp
@@ -54,7 +54,7 @@
 #include "modules/websockets/WebSocketChannelClient.h"
 #include "modules/websockets/WebSocketHandleImpl.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
-#include "platform/WebFrameScheduler.h"
+#include "platform/FrameScheduler.h"
 #include "platform/loader/fetch/UniqueIdentifier.h"
 #include "platform/network/NetworkLog.h"
 #include "platform/network/WebSocketHandshakeRequest.h"
@@ -200,9 +200,10 @@
   DCHECK(!blob_loader_);
 }
 
-bool DocumentWebSocketChannel::Connect(const KURL& url,
-                                       const String& protocol,
-                                       mojom::blink::WebSocketPtr socket_ptr) {
+bool DocumentWebSocketChannel::Connect(
+    const KURL& url,
+    const String& protocol,
+    network::mojom::blink::WebSocketPtr socket_ptr) {
   NETWORK_DVLOG(1) << this << " Connect()";
   if (!handle_)
     return false;
@@ -225,7 +226,7 @@
     if (GetDocument()->GetFrame()) {
       connection_handle_for_scheduler_ = GetDocument()
                                              ->GetFrame()
-                                             ->FrameScheduler()
+                                             ->GetFrameScheduler()
                                              ->OnActiveConnectionCreated();
     }
   }
@@ -286,7 +287,7 @@
 
 bool DocumentWebSocketChannel::Connect(const KURL& url,
                                        const String& protocol) {
-  mojom::blink::WebSocketPtr socket_ptr;
+  network::mojom::blink::WebSocketPtr socket_ptr;
   auto socket_request = mojo::MakeRequest(&socket_ptr);
   if (GetDocument() && GetDocument()->GetFrame()) {
     GetDocument()->GetFrame()->GetInterfaceProvider().GetInterface(
@@ -785,7 +786,7 @@
 void DocumentWebSocketChannel::DidFinishLoadingBlob(DOMArrayBuffer* buffer) {
   blob_loader_.Clear();
   DCHECK(handle_);
-  // The loaded blob is always placed on m_messages[0].
+  // The loaded blob is always placed on |messages_[0]|.
   DCHECK_GT(messages_.size(), 0u);
   DCHECK_EQ(messages_.front()->type, kMessageTypeBlob);
   // We replace it with the loaded blob.
@@ -807,7 +808,7 @@
 }
 
 void DocumentWebSocketChannel::TearDownFailedConnection() {
-  // m_handle and m_client can be null here.
+  // |handle_| and |client_| can be null here.
   connection_handle_for_scheduler_.reset();
   handshake_throttle_.reset();
 
diff --git a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.h b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.h
index 6d83b098..6a7e1c7f9 100644
--- a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.h
+++ b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.h
@@ -43,7 +43,7 @@
 #include "modules/websockets/WebSocketChannel.h"
 #include "modules/websockets/WebSocketHandle.h"
 #include "modules/websockets/WebSocketHandleClient.h"
-#include "platform/WebFrameScheduler.h"
+#include "platform/FrameScheduler.h"
 #include "platform/heap/Handle.h"
 #include "platform/weborigin/KURL.h"
 #include "platform/wtf/Deque.h"
@@ -51,7 +51,7 @@
 #include "platform/wtf/text/CString.h"
 #include "platform/wtf/text/WTFString.h"
 #include "public/platform/WebCallbacks.h"
-#include "public/platform/modules/websockets/websocket.mojom-blink.h"
+#include "services/network/public/mojom/websocket.mojom-blink.h"
 
 namespace blink {
 
@@ -91,7 +91,9 @@
 
   // Allows the caller to provide the Mojo pipe through which the socket is
   // connected, overriding the interface provider of the Document.
-  bool Connect(const KURL&, const String& protocol, mojom::blink::WebSocketPtr);
+  bool Connect(const KURL&,
+               const String& protocol,
+               network::mojom::blink::WebSocketPtr);
 
   // WebSocketChannel functions.
   bool Connect(const KURL&, const String& protocol) override;
@@ -190,15 +192,14 @@
   void TearDownFailedConnection();
   bool ShouldDisallowConnection(const KURL&);
 
-  // m_handle is a handle of the connection.
-  // m_handle == 0 means this channel is closed.
+  // |handle_| is a handle of the connection.
+  // |handle_| == nullptr means this channel is closed.
   std::unique_ptr<WebSocketHandle> handle_;
 
-  // m_client can be deleted while this channel is alive, but this class
+  // |client_| can be deleted while this channel is alive, but this class
   // expects that disconnect() is called before the deletion.
   Member<WebSocketChannelClient> client_;
   KURL url_;
-  // m_identifier > 0 means calling scriptContextExecution() returns a Document.
   unsigned long identifier_;
   Member<BlobLoader> blob_loader_;
   HeapDeque<Member<Message>> messages_;
@@ -209,7 +210,7 @@
   uint64_t sending_quota_;
   uint64_t received_data_size_for_flow_control_;
   size_t sent_size_of_top_message_;
-  std::unique_ptr<WebFrameScheduler::ActiveConnectionHandle>
+  std::unique_ptr<FrameScheduler::ActiveConnectionHandle>
       connection_handle_for_scheduler_;
 
   std::unique_ptr<SourceLocation> location_at_construction_;
diff --git a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannelTest.cpp b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannelTest.cpp
index 40c3469..2cbc35a 100644
--- a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannelTest.cpp
+++ b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannelTest.cpp
@@ -82,8 +82,8 @@
 
   ~MockWebSocketHandle() override = default;
 
-  MOCK_METHOD1(DoInitialize, void(mojom::blink::WebSocketPtr*));
-  void Initialize(mojom::blink::WebSocketPtr websocket) override {
+  MOCK_METHOD1(DoInitialize, void(network::mojom::blink::WebSocketPtr*));
+  void Initialize(network::mojom::blink::WebSocketPtr websocket) override {
     DoInitialize(&websocket);
   }
 
diff --git a/third_party/WebKit/Source/modules/websockets/WebPepperSocketImpl.h b/third_party/WebKit/Source/modules/websockets/WebPepperSocketImpl.h
index 1bf66f0..71617e7 100644
--- a/third_party/WebKit/Source/modules/websockets/WebPepperSocketImpl.h
+++ b/third_party/WebKit/Source/modules/websockets/WebPepperSocketImpl.h
@@ -79,7 +79,7 @@
   Persistent<WebPepperSocketChannelClientProxy> channel_proxy_;
   WebString subprotocol_;
   bool is_closing_or_closed_;
-  // m_bufferedAmount includes m_bufferedAmountAfterClose.
+  // |buffered_amount_| includes |buffered_amount_after_close_|.
   unsigned long buffered_amount_;
   unsigned long buffered_amount_after_close_;
 };
diff --git a/third_party/WebKit/Source/modules/websockets/WebSocketHandle.h b/third_party/WebKit/Source/modules/websockets/WebSocketHandle.h
index 959149a9..c939970 100644
--- a/third_party/WebKit/Source/modules/websockets/WebSocketHandle.h
+++ b/third_party/WebKit/Source/modules/websockets/WebSocketHandle.h
@@ -35,7 +35,7 @@
 #include "base/single_thread_task_runner.h"
 #include "platform/wtf/Forward.h"
 #include "platform/wtf/Vector.h"
-#include "public/platform/modules/websockets/websocket.mojom-blink.h"
+#include "services/network/public/mojom/websocket.mojom-blink.h"
 
 namespace blink {
 
@@ -60,7 +60,7 @@
 
   virtual ~WebSocketHandle() = default;
 
-  virtual void Initialize(mojom::blink::WebSocketPtr) = 0;
+  virtual void Initialize(network::mojom::blink::WebSocketPtr) = 0;
   virtual void Connect(const KURL&,
                        const Vector<String>& protocols,
                        const KURL& site_for_cookies,
diff --git a/third_party/WebKit/Source/modules/websockets/WebSocketHandleImpl.cpp b/third_party/WebKit/Source/modules/websockets/WebSocketHandleImpl.cpp
index 3df5e8b..f0b1154 100644
--- a/third_party/WebKit/Source/modules/websockets/WebSocketHandleImpl.cpp
+++ b/third_party/WebKit/Source/modules/websockets/WebSocketHandleImpl.cpp
@@ -34,7 +34,8 @@
     websocket_->StartClosingHandshake(kAbnormalShutdownOpCode, g_empty_string);
 }
 
-void WebSocketHandleImpl::Initialize(mojom::blink::WebSocketPtr websocket) {
+void WebSocketHandleImpl::Initialize(
+    network::mojom::blink::WebSocketPtr websocket) {
   NETWORK_DVLOG(1) << this << " initialize(...)";
 
   DCHECK(!websocket_);
@@ -57,7 +58,7 @@
   DCHECK(client);
   client_ = client;
 
-  mojom::blink::WebSocketClientPtr client_proxy;
+  network::mojom::blink::WebSocketClientPtr client_proxy;
   client_binding_.Bind(mojo::MakeRequest(&client_proxy, task_runner));
   websocket_->AddChannelRequest(
       url, protocols, site_for_cookies,
@@ -71,16 +72,16 @@
                                size_t size) {
   DCHECK(websocket_);
 
-  mojom::blink::WebSocketMessageType type_to_pass;
+  network::mojom::blink::WebSocketMessageType type_to_pass;
   switch (type) {
     case WebSocketHandle::kMessageTypeContinuation:
-      type_to_pass = mojom::blink::WebSocketMessageType::CONTINUATION;
+      type_to_pass = network::mojom::blink::WebSocketMessageType::CONTINUATION;
       break;
     case WebSocketHandle::kMessageTypeText:
-      type_to_pass = mojom::blink::WebSocketMessageType::TEXT;
+      type_to_pass = network::mojom::blink::WebSocketMessageType::TEXT;
       break;
     case WebSocketHandle::kMessageTypeBinary:
-      type_to_pass = mojom::blink::WebSocketMessageType::BINARY;
+      type_to_pass = network::mojom::blink::WebSocketMessageType::BINARY;
       break;
     default:
       NOTREACHED();
@@ -124,7 +125,8 @@
   // Our connection to the WebSocket was dropped. This could be due to
   // exceeding the maximum number of concurrent websockets from this process.
   String failure_message;
-  if (custom_reason == mojom::blink::WebSocket::kInsufficientResources) {
+  if (custom_reason ==
+      network::mojom::blink::WebSocket::kInsufficientResources) {
     failure_message =
         description.empty()
             ? "Insufficient resources"
@@ -149,14 +151,14 @@
 }
 
 void WebSocketHandleImpl::OnStartOpeningHandshake(
-    mojom::blink::WebSocketHandshakeRequestPtr request) {
+    network::mojom::blink::WebSocketHandshakeRequestPtr request) {
   NETWORK_DVLOG(1) << this << " OnStartOpeningHandshake("
                    << request->url.GetString() << ")";
 
   scoped_refptr<WebSocketHandshakeRequest> request_to_pass =
       WebSocketHandshakeRequest::Create(request->url);
   for (size_t i = 0; i < request->headers.size(); ++i) {
-    const mojom::blink::HttpHeaderPtr& header = request->headers[i];
+    const network::mojom::blink::HttpHeaderPtr& header = request->headers[i];
     request_to_pass->AddHeaderField(AtomicString(header->name),
                                     AtomicString(header->value));
   }
@@ -165,7 +167,7 @@
 }
 
 void WebSocketHandleImpl::OnFinishOpeningHandshake(
-    mojom::blink::WebSocketHandshakeResponsePtr response) {
+    network::mojom::blink::WebSocketHandshakeResponsePtr response) {
   NETWORK_DVLOG(1) << this << " OnFinishOpeningHandshake("
                    << response->url.GetString() << ")";
 
@@ -173,7 +175,7 @@
   response_to_pass.SetStatusCode(response->status_code);
   response_to_pass.SetStatusText(response->status_text);
   for (size_t i = 0; i < response->headers.size(); ++i) {
-    const mojom::blink::HttpHeaderPtr& header = response->headers[i];
+    const network::mojom::blink::HttpHeaderPtr& header = response->headers[i];
     response_to_pass.AddHeaderField(AtomicString(header->name),
                                     AtomicString(header->value));
   }
@@ -193,9 +195,10 @@
   // |this| can be deleted here.
 }
 
-void WebSocketHandleImpl::OnDataFrame(bool fin,
-                                      mojom::blink::WebSocketMessageType type,
-                                      const Vector<uint8_t>& data) {
+void WebSocketHandleImpl::OnDataFrame(
+    bool fin,
+    network::mojom::blink::WebSocketMessageType type,
+    const Vector<uint8_t>& data) {
   NETWORK_DVLOG(1) << this << " OnDataFrame(" << fin << ", " << type << ", "
                    << "(data size = " << data.size() << "))";
   if (!client_)
@@ -204,13 +207,13 @@
   WebSocketHandle::MessageType type_to_pass =
       WebSocketHandle::kMessageTypeContinuation;
   switch (type) {
-    case mojom::blink::WebSocketMessageType::CONTINUATION:
+    case network::mojom::blink::WebSocketMessageType::CONTINUATION:
       type_to_pass = WebSocketHandle::kMessageTypeContinuation;
       break;
-    case mojom::blink::WebSocketMessageType::TEXT:
+    case network::mojom::blink::WebSocketMessageType::TEXT:
       type_to_pass = WebSocketHandle::kMessageTypeText;
       break;
-    case mojom::blink::WebSocketMessageType::BINARY:
+    case network::mojom::blink::WebSocketMessageType::BINARY:
       type_to_pass = WebSocketHandle::kMessageTypeBinary;
       break;
   }
diff --git a/third_party/WebKit/Source/modules/websockets/WebSocketHandleImpl.h b/third_party/WebKit/Source/modules/websockets/WebSocketHandleImpl.h
index db8fe9fb..1c5ebac2 100644
--- a/third_party/WebKit/Source/modules/websockets/WebSocketHandleImpl.h
+++ b/third_party/WebKit/Source/modules/websockets/WebSocketHandleImpl.h
@@ -33,17 +33,17 @@
 
 #include "modules/websockets/WebSocketHandle.h"
 #include "mojo/public/cpp/bindings/binding.h"
-#include "public/platform/modules/websockets/websocket.mojom-blink.h"
+#include "services/network/public/mojom/websocket.mojom-blink.h"
 
 namespace blink {
 
 class WebSocketHandleImpl : public WebSocketHandle,
-                            public mojom::blink::WebSocketClient {
+                            public network::mojom::blink::WebSocketClient {
  public:
   WebSocketHandleImpl();
   ~WebSocketHandleImpl() override;
 
-  void Initialize(mojom::blink::WebSocketPtr) override;
+  void Initialize(network::mojom::blink::WebSocketPtr) override;
   void Connect(const KURL&,
                const Vector<String>& protocols,
                const KURL& site_for_cookies,
@@ -59,16 +59,16 @@
   void OnConnectionError(uint32_t custom_reason,
                          const std::string& description);
 
-  // mojom::blink::WebSocketClient methods:
+  // network::mojom::blink::WebSocketClient methods:
   void OnFailChannel(const String& reason) override;
   void OnStartOpeningHandshake(
-      mojom::blink::WebSocketHandshakeRequestPtr) override;
+      network::mojom::blink::WebSocketHandshakeRequestPtr) override;
   void OnFinishOpeningHandshake(
-      mojom::blink::WebSocketHandshakeResponsePtr) override;
+      network::mojom::blink::WebSocketHandshakeResponsePtr) override;
   void OnAddChannelResponse(const String& selected_protocol,
                             const String& extensions) override;
   void OnDataFrame(bool fin,
-                   mojom::blink::WebSocketMessageType,
+                   network::mojom::blink::WebSocketMessageType,
                    const Vector<uint8_t>& data) override;
   void OnFlowControl(int64_t quota) override;
   void OnDropChannel(bool was_clean,
@@ -78,8 +78,8 @@
 
   WebSocketHandleClient* client_;
 
-  mojom::blink::WebSocketPtr websocket_;
-  mojo::Binding<mojom::blink::WebSocketClient> client_binding_;
+  network::mojom::blink::WebSocketPtr websocket_;
+  mojo::Binding<network::mojom::blink::WebSocketClient> client_binding_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.cpp b/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.cpp
index ad09763..f1c8994 100644
--- a/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.cpp
+++ b/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.cpp
@@ -184,9 +184,10 @@
   return true;
 }
 
-bool MainChannelClient::Connect(const KURL& url,
-                                const String& protocol,
-                                mojom::blink::WebSocketPtr socket_ptr) {
+bool MainChannelClient::Connect(
+    const KURL& url,
+    const String& protocol,
+    network::mojom::blink::WebSocketPtr socket_ptr) {
   DCHECK(IsMainThread());
   if (!main_channel_)
     return false;
@@ -382,7 +383,7 @@
     WorkerThreadLifecycleContext* worker_thread_lifecycle_context,
     const KURL& url,
     const String& protocol,
-    mojom::blink::WebSocketPtrInfo socket_ptr_info,
+    network::mojom::blink::WebSocketPtrInfo socket_ptr_info,
     WebSocketChannelSyncHelper* sync_helper) {
   DCHECK(IsMainThread());
   DCHECK(!main_channel_client_);
@@ -412,7 +413,7 @@
   // document and so can make requests using that context. In the case of
   // https://crbug.com/760708 for example this is necessary to apply the user's
   // SSL interstitial decision to WebSocket connections from the worker.
-  mojom::blink::WebSocketPtrInfo socket_ptr_info;
+  network::mojom::blink::WebSocketPtrInfo socket_ptr_info;
   if (!worker_global_scope_->IsDedicatedWorkerGlobalScope()) {
     worker_global_scope_->GetInterfaceProvider()->GetInterface(
         mojo::MakeRequest(&socket_ptr_info));
diff --git a/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.h b/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.h
index c38f99b..2e9f09b8 100644
--- a/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.h
+++ b/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.h
@@ -46,7 +46,7 @@
 #include "platform/wtf/Forward.h"
 #include "platform/wtf/Vector.h"
 #include "platform/wtf/text/WTFString.h"
-#include "public/platform/modules/websockets/websocket.mojom-blink.h"
+#include "services/network/public/mojom/websocket.mojom-blink.h"
 
 namespace blink {
 
@@ -115,7 +115,7 @@
 
     bool Connect(const KURL&,
                  const String& protocol,
-                 mojom::blink::WebSocketPtr);
+                 network::mojom::blink::WebSocketPtr);
     void SendTextAsCharVector(std::unique_ptr<Vector<char>>);
     void SendBinaryAsCharVector(std::unique_ptr<Vector<char>>);
     void SendBlob(scoped_refptr<BlobDataHandle>);
@@ -182,7 +182,7 @@
                              WorkerThreadLifecycleContext*,
                              const KURL&,
                              const String& protocol,
-                             mojom::blink::WebSocketPtrInfo,
+                             network::mojom::blink::WebSocketPtrInfo,
                              WebSocketChannelSyncHelper*);
 
     // Returns null when |disconnect| has already been called.
diff --git a/third_party/WebKit/Source/modules/xr/XRFrameProvider.cpp b/third_party/WebKit/Source/modules/xr/XRFrameProvider.cpp
index 4c471ed..b49ce50 100644
--- a/third_party/WebKit/Source/modules/xr/XRFrameProvider.cpp
+++ b/third_party/WebKit/Source/modules/xr/XRFrameProvider.cpp
@@ -13,6 +13,7 @@
 #include "core/imagebitmap/ImageBitmap.h"
 #include "modules/xr/XR.h"
 #include "modules/xr/XRDevice.h"
+#include "modules/xr/XRPresentationContext.h"
 #include "modules/xr/XRSession.h"
 #include "modules/xr/XRViewport.h"
 #include "modules/xr/XRWebGLLayer.h"
@@ -329,8 +330,9 @@
   frame_transport_->FramePreImage(webgl_context->ContextGL());
 
   std::unique_ptr<viz::SingleReleaseCallback> image_release_callback;
-  scoped_refptr<Image> image_ref =
+  scoped_refptr<StaticBitmapImage> image_ref =
       layer->TransferToStaticBitmapImage(&image_release_callback);
+
   if (!image_ref)
     return;
 
diff --git a/third_party/WebKit/Source/modules/xr/XRSession.cpp b/third_party/WebKit/Source/modules/xr/XRSession.cpp
index 0dae3ba..517117af 100644
--- a/third_party/WebKit/Source/modules/xr/XRSession.cpp
+++ b/third_party/WebKit/Source/modules/xr/XRSession.cpp
@@ -349,7 +349,7 @@
   output_width_ = element->OffsetWidth() * devicePixelRatio;
   output_height_ = element->OffsetHeight() * devicePixelRatio;
 
-  if (!exclusive_ && base_layer_) {
+  if (base_layer_) {
     base_layer_->OnResize();
   }
 }
diff --git a/third_party/WebKit/Source/modules/xr/XRWebGLLayer.cpp b/third_party/WebKit/Source/modules/xr/XRWebGLLayer.cpp
index 16dee29..c41fb60 100644
--- a/third_party/WebKit/Source/modules/xr/XRWebGLLayer.cpp
+++ b/third_party/WebKit/Source/modules/xr/XRWebGLLayer.cpp
@@ -17,6 +17,7 @@
 #include "modules/xr/XRView.h"
 #include "modules/xr/XRViewport.h"
 #include "platform/geometry/DoubleSize.h"
+#include "platform/geometry/FloatPoint.h"
 #include "platform/geometry/IntSize.h"
 
 namespace blink {
@@ -121,6 +122,11 @@
       framebuffer_(framebuffer),
       framebuffer_scale_(framebuffer_scale) {
   DCHECK(drawing_buffer);
+  // If the contents need mirroring, indicate that to the drawing buffer.
+  if (session->exclusive() && session->outputContext() &&
+      session->device()->external()) {
+    drawing_buffer_->SetMirrorClient(this);
+  }
   UpdateViewports();
 }
 
@@ -189,6 +195,43 @@
                        framebuffer_height * viewport_scale_);
 
     session()->device()->frameProvider()->UpdateWebGLLayerViewports(this);
+
+    // When mirroring make sure to also update the mirrored canvas UVs so it
+    // only shows a single eye's data, cropped to display proportionally.
+    if (session()->outputContext()) {
+      float left = 0;
+      float top = 0;
+      float right = static_cast<float>(left_viewport_->width()) /
+                    static_cast<float>(framebuffer_width);
+      float bottom = static_cast<float>(left_viewport_->height()) /
+                     static_cast<float>(framebuffer_height);
+
+      // Adjust the UVs so that the mirrored content always fills the canvas
+      // and is centered while staying proportional.
+      DoubleSize output_size = session()->OutputCanvasSize();
+      double output_aspect = output_size.Width() / output_size.Height();
+      double viewport_aspect = static_cast<float>(left_viewport_->width()) /
+                               static_cast<float>(left_viewport_->height());
+
+      if (output_aspect > viewport_aspect) {
+        float viewport_scale = bottom;
+        output_aspect = viewport_aspect / output_aspect;
+        top = 0.5 - (output_aspect * 0.5);
+        bottom = top + output_aspect;
+        top *= viewport_scale;
+        bottom *= viewport_scale;
+      } else {
+        float viewport_scale = right;
+        output_aspect = output_aspect / viewport_aspect;
+        left = 0.5 - (output_aspect * 0.5);
+        right = left + output_aspect;
+        left *= viewport_scale;
+        right *= viewport_scale;
+      }
+
+      session()->outputContext()->SetUV(FloatPoint(left, top),
+                                        FloatPoint(right, bottom));
+    }
   } else {
     left_viewport_ = new XRViewport(0, 0, framebuffer_width * viewport_scale_,
                                     framebuffer_height * viewport_scale_);
@@ -217,11 +260,18 @@
 }
 
 void XRWebGLLayer::OnResize() {
-  DoubleSize framebuffers_size = session()->IdealFramebufferSize();
+  if (!session()->exclusive()) {
+    // For non-exclusive sessions a resize indicates we should adjust the
+    // drawing buffer size to match the canvas.
+    DoubleSize framebuffers_size = session()->IdealFramebufferSize();
 
-  IntSize desired_size(framebuffers_size.Width() * framebuffer_scale_,
-                       framebuffers_size.Height() * framebuffer_scale_);
-  drawing_buffer_->Resize(desired_size);
+    IntSize desired_size(framebuffers_size.Width() * framebuffer_scale_,
+                         framebuffers_size.Height() * framebuffer_scale_);
+    drawing_buffer_->Resize(desired_size);
+  }
+
+  // With both exclusive and non-exclusive session the viewports should be
+  // recomputed when the output canvas resizes.
   viewports_dirty_ = true;
 }
 
@@ -230,6 +280,23 @@
   return drawing_buffer_->TransferToStaticBitmapImage(out_release_callback);
 }
 
+void XRWebGLLayer::OnMirrorImageAvailable(
+    scoped_refptr<StaticBitmapImage> image,
+    std::unique_ptr<viz::SingleReleaseCallback> release_callback) {
+  ImageBitmap* image_bitmap = ImageBitmap::Create(std::move(image));
+
+  session()->outputContext()->SetImage(image_bitmap);
+
+  if (mirror_release_callback_) {
+    // TODO(bajones): We should probably have the compositor report to us when
+    // it's done with the image, rather than reporting back that it's usable as
+    // soon as we receive a new one.
+    mirror_release_callback_->Run(gpu::SyncToken(), false /* lost_resource */);
+  }
+
+  mirror_release_callback_ = std::move(release_callback);
+}
+
 void XRWebGLLayer::Trace(blink::Visitor* visitor) {
   visitor->Trace(left_viewport_);
   visitor->Trace(right_viewport_);
diff --git a/third_party/WebKit/Source/modules/xr/XRWebGLLayer.h b/third_party/WebKit/Source/modules/xr/XRWebGLLayer.h
index 613879e..7143a62 100644
--- a/third_party/WebKit/Source/modules/xr/XRWebGLLayer.h
+++ b/third_party/WebKit/Source/modules/xr/XRWebGLLayer.h
@@ -26,7 +26,8 @@
 class XRSession;
 class XRViewport;
 
-class XRWebGLLayer final : public XRLayer {
+class XRWebGLLayer final : public XRLayer,
+                           public XRWebGLDrawingBuffer::MirrorClient {
   DEFINE_WRAPPERTYPEINFO();
 
  public:
@@ -70,6 +71,11 @@
   scoped_refptr<StaticBitmapImage> TransferToStaticBitmapImage(
       std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback);
 
+  // XRWebGLDrawingBuffer::MirrorClient impementation
+  void OnMirrorImageAvailable(
+      scoped_refptr<StaticBitmapImage>,
+      std::unique_ptr<viz::SingleReleaseCallback>) override;
+
   virtual void Trace(blink::Visitor*);
   virtual void TraceWrappers(const ScriptWrappableVisitor*) const;
 
@@ -87,6 +93,8 @@
   scoped_refptr<XRWebGLDrawingBuffer> drawing_buffer_;
   Member<WebGLFramebuffer> framebuffer_;
 
+  std::unique_ptr<viz::SingleReleaseCallback> mirror_release_callback_;
+
   double framebuffer_scale_ = 1.0;
   double viewport_scale_ = 1.0;
   bool viewports_dirty_ = true;
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn
index 14477eb..817f4e0 100644
--- a/third_party/WebKit/Source/platform/BUILD.gn
+++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -319,6 +319,7 @@
     "FileMetadata.cpp",
     "FileMetadata.h",
     "FileSystemType.h",
+    "FrameScheduler.h",
     "Histogram.cpp",
     "Histogram.h",
     "InstanceCounters.cpp",
@@ -387,7 +388,6 @@
     "UkmTimeAggregator.h",
     "WaitableEvent.cpp",
     "WaitableEvent.h",
-    "WebFrameScheduler.h",
     "WebGestureEvent.cpp",
     "WebIconSizesParser.cpp",
     "WebMouseEvent.cpp",
diff --git a/third_party/WebKit/Source/platform/FrameScheduler.h b/third_party/WebKit/Source/platform/FrameScheduler.h
new file mode 100644
index 0000000..304d8736a
--- /dev/null
+++ b/third_party/WebKit/Source/platform/FrameScheduler.h
@@ -0,0 +1,180 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef FrameScheduler_h
+#define FrameScheduler_h
+
+#include <memory>
+
+#include "base/memory/scoped_refptr.h"
+#include "base/single_thread_task_runner.h"
+#include "platform/wtf/text/WTFString.h"
+#include "public/platform/TaskType.h"
+#include "public/platform/WebScopedVirtualTimePauser.h"
+
+namespace blink {
+
+class PageScheduler;
+
+class FrameScheduler {
+ public:
+  virtual ~FrameScheduler() = default;
+
+  // Observer type that regulates conditions to invoke callbacks.
+  enum class ObserverType { kLoader, kWorkerScheduler };
+
+  // Represents throttling state.
+  enum class ThrottlingState {
+    kThrottled,
+    kNotThrottled,
+    kStopped,
+  };
+
+  // Represents the type of frame: main (top-level) vs not.
+  enum class FrameType {
+    kMainFrame,
+    kSubframe,
+  };
+
+  class ActiveConnectionHandle {
+   public:
+    ActiveConnectionHandle() = default;
+    virtual ~ActiveConnectionHandle() = default;
+
+   private:
+    DISALLOW_COPY_AND_ASSIGN(ActiveConnectionHandle);
+  };
+
+  // Observer interface to receive scheduling policy change events.
+  class Observer {
+   public:
+    virtual ~Observer() = default;
+
+    // Notified when throttling state is changed.
+    virtual void OnThrottlingStateChanged(ThrottlingState) = 0;
+  };
+
+  class ThrottlingObserverHandle {
+   public:
+    ThrottlingObserverHandle() = default;
+    virtual ~ThrottlingObserverHandle() = default;
+
+   private:
+    DISALLOW_COPY_AND_ASSIGN(ThrottlingObserverHandle);
+  };
+
+  // Adds an Observer instance to be notified on scheduling policy changed.
+  // When an Observer is added, the initial state will be notified synchronously
+  // through the Observer interface.
+  // A RAII handle is returned and observer is unregistered when the handle is
+  // destroyed.
+  virtual std::unique_ptr<ThrottlingObserverHandle> AddThrottlingObserver(
+      ObserverType,
+      Observer*) = 0;
+
+  // The scheduler may throttle tasks associated with offscreen frames.
+  virtual void SetFrameVisible(bool) = 0;
+  virtual bool IsFrameVisible() const = 0;
+
+  // Query the page visibility state for the page associated with this frame.
+  // The scheduler may throttle tasks associated with pages that are not
+  // visible.
+  virtual bool IsPageVisible() const = 0;
+
+  // Set whether this frame is suspended. Only unthrottledTaskRunner tasks are
+  // allowed to run on a suspended frame.
+  virtual void SetPaused(bool) = 0;
+
+  // Notifies observers of transitioning to and from FROZEN state in
+  // background.
+  virtual void SetPageFrozen(bool) {}
+
+  // Set whether this frame is cross origin w.r.t. the top level frame. Cross
+  // origin frames may use a different scheduling policy from same origin
+  // frames.
+  virtual void SetCrossOrigin(bool) = 0;
+  virtual bool IsCrossOrigin() const = 0;
+  virtual void TraceUrlChange(const String&) = 0;
+
+  // Returns the frame type, which currently determines whether this frame is
+  // the top level frame, i.e. a main frame.
+  virtual FrameType GetFrameType() const = 0;
+
+  // The tasks runners below are listed in increasing QoS order.
+  // - throttleable task queue. Designed for custom user-provided javascript
+  //   tasks. Lowest guarantees. Can be paused, blocked during user gesture,
+  //   throttled when backgrounded or stopped completely after some time in
+  //   background.
+  // - deferrable task queue. These tasks can be deferred for a small period
+  //   (several seconds) when high-priority work is anticipated. These tasks
+  //   can be paused.
+  // - pausable task queue. Default queue for high-priority javascript tasks.
+  //   They can be paused according to the spec during javascript alert
+  //   dialogs, printing windows and devtools debugging. Otherwise scheduler
+  //   does not tamper with their execution.
+  // - unpausable task queue. Should be used for control tasks which should
+  //   run when the context is paused. Usage should be extremely rare.
+  //   Please consult scheduler-dev@ before using it. Running javascript
+  //   on it is strictly verboten and can lead to hard-to-diagnose errors.
+  //
+  //
+  // These queues below are separate due to special handling for their
+  // priorities.
+  // - loading task queue. Similar to deferrable task queue. Throttling might
+  //   be considered in the future.
+  // - loading control task queue. Loading task queue with increased priority
+  //   to run small loading tasks which schedule other loading tasks.
+
+  // Note: old-style timer task runner corresponds to throttleable task runner
+  // and unthrottled task runner corresponds to pausable task runner.
+
+  // Returns a task runner that is suitable with the given task type.
+  virtual scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(
+      TaskType) = 0;
+
+  // Returns the parent PageScheduler.
+  virtual PageScheduler* GetPageScheduler() const = 0;
+
+  // Returns a WebScopedVirtualTimePauser which can be used to vote for pausing
+  // virtual time. Virtual time will be paused if any WebScopedVirtualTimePauser
+  // votes to pause it, and only unpaused only if all
+  // WebScopedVirtualTimePausers are either destroyed or vote to unpause.  Note
+  // the WebScopedVirtualTimePauser returned by this method is initially
+  // unpaused.
+  virtual WebScopedVirtualTimePauser CreateWebScopedVirtualTimePauser(
+      WebScopedVirtualTimePauser::VirtualTaskDuration) = 0;
+
+  // Tells the scheduler that a provisional load has started, the scheduler may
+  // reset the task cost estimators and the UserModel. Must be called from the
+  // main thread.
+  virtual void DidStartProvisionalLoad(bool is_main_frame) = 0;
+
+  // Tells the scheduler that a provisional load has committed, the scheduler
+  // may reset the task cost estimators and the UserModel. Must be called from
+  // the main thread.
+  virtual void DidCommitProvisionalLoad(bool is_web_history_inert_commit,
+                                        bool is_reload,
+                                        bool is_main_frame) = 0;
+
+  // Tells the scheduler that the first meaningful paint has occured for this
+  // frame.
+  virtual void OnFirstMeaningfulPaint() = 0;
+
+  // Notifies scheduler that this frame has established an active real time
+  // connection (websocket, webrtc, etc). When connection is closed this handle
+  // must be destroyed.
+  virtual std::unique_ptr<ActiveConnectionHandle>
+  OnActiveConnectionCreated() = 0;
+
+  // Returns true if this frame is should not throttled (e.g. due to an active
+  // connection).
+  // Note that this only applies to the current frame,
+  // use GetPageScheduler()->IsExemptFromBudgetBasedThrottling for the status
+  // of the page.
+  virtual bool IsExemptFromBudgetBasedThrottling() const = 0;
+};
+
+}  // namespace blink
+
+#endif  // FrameScheduler_h
diff --git a/third_party/WebKit/Source/platform/InstanceCounters.h b/third_party/WebKit/Source/platform/InstanceCounters.h
index 8cc6fed1..541f853f 100644
--- a/third_party/WebKit/Source/platform/InstanceCounters.h
+++ b/third_party/WebKit/Source/platform/InstanceCounters.h
@@ -52,7 +52,8 @@
   V(V8PerContextData)             \
   V(WorkerGlobalScope)            \
   V(UACSSResource)                \
-  V(RTCPeerConnection)
+  V(RTCPeerConnection)            \
+  V(ResourceFetcher)
 
 class InstanceCounters {
   STATIC_ONLY(InstanceCounters);
diff --git a/third_party/WebKit/Source/platform/WaitableEvent.h b/third_party/WebKit/Source/platform/WaitableEvent.h
index 106b0201..2b2ad4d 100644
--- a/third_party/WebKit/Source/platform/WaitableEvent.h
+++ b/third_party/WebKit/Source/platform/WaitableEvent.h
@@ -41,6 +41,9 @@
 
 namespace blink {
 
+// TODO(crbug.com/796799): Deprecate blink::WaitableEvent and use
+// base::WaitableEvent instead.
+//
 // Provides a thread synchronization that can be used to allow one thread to
 // wait until another thread to finish some work.
 class PLATFORM_EXPORT WaitableEvent {
diff --git a/third_party/WebKit/Source/platform/WebFrameScheduler.h b/third_party/WebKit/Source/platform/WebFrameScheduler.h
deleted file mode 100644
index 5866cece..0000000
--- a/third_party/WebKit/Source/platform/WebFrameScheduler.h
+++ /dev/null
@@ -1,180 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef WebFrameScheduler_h
-#define WebFrameScheduler_h
-
-#include "base/memory/scoped_refptr.h"
-#include "base/single_thread_task_runner.h"
-#include "platform/wtf/text/WTFString.h"
-#include "public/platform/TaskType.h"
-#include "public/platform/WebScopedVirtualTimePauser.h"
-
-#include <memory>
-
-namespace blink {
-
-class PageScheduler;
-
-class WebFrameScheduler {
- public:
-  virtual ~WebFrameScheduler() = default;
-
-  // Observer type that regulates conditions to invoke callbacks.
-  enum class ObserverType { kLoader, kWorkerScheduler };
-
-  // Represents throttling state.
-  enum class ThrottlingState {
-    kThrottled,
-    kNotThrottled,
-    kStopped,
-  };
-
-  // Represents the type of frame: main (top-level) vs not.
-  enum class FrameType {
-    kMainFrame,
-    kSubframe,
-  };
-
-  class ActiveConnectionHandle {
-   public:
-    ActiveConnectionHandle() = default;
-    virtual ~ActiveConnectionHandle() = default;
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(ActiveConnectionHandle);
-  };
-
-  // Observer interface to receive scheduling policy change events.
-  class Observer {
-   public:
-    virtual ~Observer() = default;
-
-    // Notified when throttling state is changed.
-    virtual void OnThrottlingStateChanged(ThrottlingState) = 0;
-  };
-
-  class ThrottlingObserverHandle {
-   public:
-    ThrottlingObserverHandle() = default;
-    virtual ~ThrottlingObserverHandle() = default;
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(ThrottlingObserverHandle);
-  };
-
-  // Adds an Observer instance to be notified on scheduling policy changed.
-  // When an Observer is added, the initial state will be notified synchronously
-  // through the Observer interface.
-  // A RAII handle is returned and observer is unregistered when the handle is
-  // destroyed.
-  virtual std::unique_ptr<ThrottlingObserverHandle> AddThrottlingObserver(
-      ObserverType,
-      Observer*) = 0;
-
-  // The scheduler may throttle tasks associated with offscreen frames.
-  virtual void SetFrameVisible(bool) = 0;
-  virtual bool IsFrameVisible() const = 0;
-
-  // Query the page visibility state for the page associated with this frame.
-  // The scheduler may throttle tasks associated with pages that are not
-  // visible.
-  virtual bool IsPageVisible() const = 0;
-
-  // Set whether this frame is suspended. Only unthrottledTaskRunner tasks are
-  // allowed to run on a suspended frame.
-  virtual void SetPaused(bool) = 0;
-
-  // Notifies observers of transitioning to and from FROZEN state in
-  // background.
-  virtual void SetPageFrozen(bool) {}
-
-  // Set whether this frame is cross origin w.r.t. the top level frame. Cross
-  // origin frames may use a different scheduling policy from same origin
-  // frames.
-  virtual void SetCrossOrigin(bool) = 0;
-  virtual bool IsCrossOrigin() const = 0;
-  virtual void TraceUrlChange(const String&) = 0;
-
-  // Returns the frame type, which currently determines whether this frame is
-  // the top level frame, i.e. a main frame.
-  virtual FrameType GetFrameType() const = 0;
-
-  // The tasks runners below are listed in increasing QoS order.
-  // - throttleable task queue. Designed for custom user-provided javascript
-  //   tasks. Lowest guarantees. Can be paused, blocked during user gesture,
-  //   throttled when backgrounded or stopped completely after some time in
-  //   background.
-  // - deferrable task queue. These tasks can be deferred for a small period
-  //   (several seconds) when high-priority work is anticipated. These tasks
-  //   can be paused.
-  // - pausable task queue. Default queue for high-priority javascript tasks.
-  //   They can be paused according to the spec during javascript alert
-  //   dialogs, printing windows and devtools debugging. Otherwise scheduler
-  //   does not tamper with their execution.
-  // - unpausable task queue. Should be used for control tasks which should
-  //   run when the context is paused. Usage should be extremely rare.
-  //   Please consult scheduler-dev@ before using it. Running javascript
-  //   on it is strictly verboten and can lead to hard-to-diagnose errors.
-  //
-  //
-  // These queues below are separate due to special handling for their
-  // priorities.
-  // - loading task queue. Similar to deferrable task queue. Throttling might
-  //   be considered in the future.
-  // - loading control task queue. Loading task queue with increased priority
-  //   to run small loading tasks which schedule other loading tasks.
-
-  // Note: old-style timer task runner corresponds to throttleable task runner
-  // and unthrottled task runner corresponds to pausable task runner.
-
-  // Returns a task runner that is suitable with the given task type.
-  virtual scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(
-      TaskType) = 0;
-
-  // Returns the parent PageScheduler.
-  virtual PageScheduler* GetPageScheduler() const = 0;
-
-  // Returns a WebScopedVirtualTimePauser which can be used to vote for pausing
-  // virtual time. Virtual time will be paused if any WebScopedVirtualTimePauser
-  // votes to pause it, and only unpaused only if all
-  // WebScopedVirtualTimePausers are either destroyed or vote to unpause.  Note
-  // the WebScopedVirtualTimePauser returned by this method is initially
-  // unpaused.
-  virtual WebScopedVirtualTimePauser CreateWebScopedVirtualTimePauser(
-      WebScopedVirtualTimePauser::VirtualTaskDuration) = 0;
-
-  // Tells the scheduler that a provisional load has started, the scheduler may
-  // reset the task cost estimators and the UserModel. Must be called from the
-  // main thread.
-  virtual void DidStartProvisionalLoad(bool is_main_frame) = 0;
-
-  // Tells the scheduler that a provisional load has committed, the scheduler
-  // may reset the task cost estimators and the UserModel. Must be called from
-  // the main thread.
-  virtual void DidCommitProvisionalLoad(bool is_web_history_inert_commit,
-                                        bool is_reload,
-                                        bool is_main_frame) = 0;
-
-  // Tells the scheduler that the first meaningful paint has occured for this
-  // frame.
-  virtual void OnFirstMeaningfulPaint() = 0;
-
-  // Notifies scheduler that this frame has established an active real time
-  // connection (websocket, webrtc, etc). When connection is closed this handle
-  // must be destroyed.
-  virtual std::unique_ptr<ActiveConnectionHandle>
-  OnActiveConnectionCreated() = 0;
-
-  // Returns true if this frame is should not throttled (e.g. due to an active
-  // connection).
-  // Note that this only applies to the current frame,
-  // use GetPageScheduler()->IsExemptFromBudgetBasedThrottling for the status
-  // of the page.
-  virtual bool IsExemptFromBudgetBasedThrottling() const = 0;
-};
-
-}  // namespace blink
-
-#endif  // WebFrameScheduler_h
diff --git a/third_party/WebKit/Source/platform/WebTaskRunner.cpp b/third_party/WebKit/Source/platform/WebTaskRunner.cpp
index 430ea625..795f40005 100644
--- a/third_party/WebKit/Source/platform/WebTaskRunner.cpp
+++ b/third_party/WebKit/Source/platform/WebTaskRunner.cpp
@@ -116,7 +116,7 @@
 // avoid copying the closure later in the call chain. Copying the bound state
 // can lead to data races with ref counted objects like StringImpl. See
 // crbug.com/679915 for more details.
-void PostCrossThreadTask(base::SingleThreadTaskRunner& task_runner,
+void PostCrossThreadTask(base::SequencedTaskRunner& task_runner,
                          const base::Location& location,
                          CrossThreadClosure task) {
   task_runner.PostDelayedTask(
@@ -124,7 +124,7 @@
       base::TimeDelta());
 }
 
-void PostDelayedCrossThreadTask(base::SingleThreadTaskRunner& task_runner,
+void PostDelayedCrossThreadTask(base::SequencedTaskRunner& task_runner,
                                 const base::Location& location,
                                 CrossThreadClosure task,
                                 TimeDelta delay) {
@@ -132,7 +132,7 @@
       location, base::BindOnce(&RunCrossThreadClosure, std::move(task)), delay);
 }
 
-TaskHandle PostCancellableTask(base::SingleThreadTaskRunner& task_runner,
+TaskHandle PostCancellableTask(base::SequencedTaskRunner& task_runner,
                                const base::Location& location,
                                base::OnceClosure task) {
   DCHECK(task_runner.RunsTasksInCurrentSequence());
@@ -144,7 +144,7 @@
   return TaskHandle(runner);
 }
 
-TaskHandle PostDelayedCancellableTask(base::SingleThreadTaskRunner& task_runner,
+TaskHandle PostDelayedCancellableTask(base::SequencedTaskRunner& task_runner,
                                       const base::Location& location,
                                       base::OnceClosure task,
                                       TimeDelta delay) {
diff --git a/third_party/WebKit/Source/platform/WebTaskRunner.h b/third_party/WebKit/Source/platform/WebTaskRunner.h
index dcc0aae..9d0409d 100644
--- a/third_party/WebKit/Source/platform/WebTaskRunner.h
+++ b/third_party/WebKit/Source/platform/WebTaskRunner.h
@@ -8,7 +8,7 @@
 #include <memory>
 #include "base/callback.h"
 #include "base/location.h"
-#include "base/single_thread_task_runner.h"
+#include "base/sequenced_task_runner.h"
 #include "platform/wtf/Compiler.h"
 #include "platform/wtf/Functional.h"
 #include "platform/wtf/RefCounted.h"
@@ -44,11 +44,11 @@
 
  private:
   friend BLINK_PLATFORM_EXPORT WARN_UNUSED_RESULT TaskHandle
-  PostCancellableTask(base::SingleThreadTaskRunner&,
+  PostCancellableTask(base::SequencedTaskRunner&,
                       const base::Location&,
                       base::OnceClosure);
   friend BLINK_PLATFORM_EXPORT WARN_UNUSED_RESULT TaskHandle
-  PostDelayedCancellableTask(base::SingleThreadTaskRunner&,
+  PostDelayedCancellableTask(base::SequencedTaskRunner&,
                              const base::Location&,
                              base::OnceClosure,
                              TimeDelta delay);
@@ -58,11 +58,11 @@
 };
 
 // For cross-thread posting. Can be called from any thread.
-BLINK_PLATFORM_EXPORT void PostCrossThreadTask(base::SingleThreadTaskRunner&,
+BLINK_PLATFORM_EXPORT void PostCrossThreadTask(base::SequencedTaskRunner&,
                                                const base::Location&,
                                                CrossThreadClosure);
 BLINK_PLATFORM_EXPORT void PostDelayedCrossThreadTask(
-    base::SingleThreadTaskRunner&,
+    base::SequencedTaskRunner&,
     const base::Location&,
     CrossThreadClosure,
     TimeDelta delay);
@@ -70,11 +70,11 @@
 // For same-thread cancellable task posting. Returns a TaskHandle object for
 // cancellation.
 BLINK_PLATFORM_EXPORT WARN_UNUSED_RESULT TaskHandle
-PostCancellableTask(base::SingleThreadTaskRunner&,
+PostCancellableTask(base::SequencedTaskRunner&,
                     const base::Location&,
                     base::OnceClosure);
 BLINK_PLATFORM_EXPORT WARN_UNUSED_RESULT TaskHandle
-PostDelayedCancellableTask(base::SingleThreadTaskRunner&,
+PostDelayedCancellableTask(base::SequencedTaskRunner&,
                            const base::Location&,
                            base::OnceClosure,
                            TimeDelta delay);
diff --git a/third_party/WebKit/Source/platform/WebThread.cpp b/third_party/WebKit/Source/platform/WebThread.cpp
index e8ebcf2..88ded67 100644
--- a/third_party/WebKit/Source/platform/WebThread.cpp
+++ b/third_party/WebKit/Source/platform/WebThread.cpp
@@ -28,7 +28,7 @@
 }
 
 WebThreadCreationParams& WebThreadCreationParams::SetFrameScheduler(
-    WebFrameScheduler* scheduler) {
+    FrameScheduler* scheduler) {
   frame_scheduler = scheduler;
   return *this;
 }
diff --git a/third_party/WebKit/Source/platform/audio/Biquad.cpp b/third_party/WebKit/Source/platform/audio/Biquad.cpp
index 0e4b54c..861bfb4d 100644
--- a/third_party/WebKit/Source/platform/audio/Biquad.cpp
+++ b/third_party/WebKit/Source/platform/audio/Biquad.cpp
@@ -43,7 +43,7 @@
 namespace blink {
 
 #if defined(OS_MACOSX)
-const int kBufferSize = 1024;
+const int kBiquadBufferSize = 1024;
 #endif
 
 // Compute 10^x = exp(x*log(10))
@@ -54,8 +54,8 @@
 Biquad::Biquad() : has_sample_accurate_values_(false) {
 #if defined(OS_MACOSX)
   // Allocate two samples more for filter history
-  input_buffer_.Allocate(kBufferSize + 2);
-  output_buffer_.Allocate(kBufferSize + 2);
+  input_buffer_.Allocate(kBiquadBufferSize + 2);
+  output_buffer_.Allocate(kBiquadBufferSize + 2);
 #endif
 
   // Allocate enough space for the a-rate filter coefficients to handle a
@@ -209,12 +209,12 @@
   double* input2p = input_p + 2;
   double* output2p = output_p + 2;
 
-  // Break up processing into smaller slices (kBufferSize) if necessary.
+  // Break up processing into smaller slices (kBiquadBufferSize) if necessary.
 
   int n = frames_to_process;
 
   while (n > 0) {
-    int frames_this_time = n < kBufferSize ? n : kBufferSize;
+    int frames_this_time = n < kBiquadBufferSize ? n : kBiquadBufferSize;
 
     // Copy input to input buffer
     for (int i = 0; i < frames_this_time; ++i)
diff --git a/third_party/WebKit/Source/platform/exported/WebURLRequest.cpp b/third_party/WebKit/Source/platform/exported/WebURLRequest.cpp
index a8b34ea..e774a420 100644
--- a/third_party/WebKit/Source/platform/exported/WebURLRequest.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebURLRequest.cpp
@@ -122,6 +122,10 @@
   resource_request_->SetCacheMode(cache_mode);
 }
 
+double WebURLRequest::TimeoutInterval() const {
+  return resource_request_->TimeoutInterval();
+}
+
 WebString WebURLRequest::HttpMethod() const {
   return resource_request_->HttpMethod();
 }
diff --git a/third_party/WebKit/Source/platform/graphics/VideoFrameResourceProvider.cpp b/third_party/WebKit/Source/platform/graphics/VideoFrameResourceProvider.cpp
index c9717f93..4dbb250 100644
--- a/third_party/WebKit/Source/platform/graphics/VideoFrameResourceProvider.cpp
+++ b/third_party/WebKit/Source/platform/graphics/VideoFrameResourceProvider.cpp
@@ -56,9 +56,12 @@
       media_context_provider, shared_bitmap_manager_,
       gpu_memory_buffer_manager_, true, settings_.resource_settings);
 
+  // TODO(kylechar): VideoResourceUpdater needs something it can notify about
+  // SharedBitmaps that isn't a LayerTreeFrameSink. https://crbug.com/730660#c88
   resource_updater_ = std::make_unique<cc::VideoResourceUpdater>(
-      media_context_provider, resource_provider_.get(),
-      settings_.use_stream_video_draw_quad);
+      context_provider_, nullptr, resource_provider_.get(),
+      settings_.use_stream_video_draw_quad,
+      settings_.resource_settings.use_gpu_memory_buffer_resources);
 }
 
 void VideoFrameResourceProvider::AppendQuads(
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/PaintChunksToCcLayer.cpp b/third_party/WebKit/Source/platform/graphics/compositing/PaintChunksToCcLayer.cpp
index 3fc2f3052..28853613 100644
--- a/third_party/WebKit/Source/platform/graphics/compositing/PaintChunksToCcLayer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/compositing/PaintChunksToCcLayer.cpp
@@ -109,8 +109,8 @@
   // The current effect will change to the target effect.
   void SwitchToEffect(const EffectPaintPropertyNode*);
 
-  // Applies combined transform from current_transform_ to the target
-  // transform.
+  // Applies combined transform from |current_transform_| to |target_transform|
+  // This function doesn't change |current_transform_|.
   void ApplyTransform(const TransformPaintPropertyNode* target_transform) {
     if (target_transform == current_transform_)
       return;
@@ -132,9 +132,31 @@
     cc_list_.EndPaintOfPairedEnd();
   }
 
+  // Starts an effect state by adjusting clip and transform state, applying
+  // the effect as a SaveLayer[Alpha]Op (whose bounds will be updated in
+  // EndEffect()), and updating the current state.
+  void StartEffect(const EffectPaintPropertyNode*);
+  // Ends the effect on the top of the state stack if the stack is not empty,
+  // and update the bounds of the SaveLayer[Alpha]Op of the effect.
+  void EndEffect();
   void UpdateEffectBounds(const FloatRect&, const TransformPaintPropertyNode*);
-  void PopToParentEffect();
-  void PopClips();
+
+  // Starts a clip state by adjusting the transform state, applying
+  // |combined_clip_rect| which is combined from multiple rectangular
+  // consecutive clips, and updating the current state.
+  // |lowest_combined_clip_node| is the lowest node of the combined clips.
+  void StartCombinedClip(
+      const FloatRect& combined_clip_rect,
+      const ClipPaintPropertyNode* lowest_combined_clip_node);
+  // Starts a clip state by adjusting the transform state, applying the single
+  // clip node which can't be combined with other clips, and updating the
+  // current state.
+  void StartSingleClip(const ClipPaintPropertyNode*);
+  // Pop one clip state from the top of the stack.
+  void EndClip();
+  // Pop clip states from the top of the stack until the top is an effect state
+  // or the stack is empty.
+  void EndClips();
 
   const PropertyTreeState& layer_state_;
   gfx::Vector2dF layer_offset_;
@@ -161,15 +183,15 @@
   Vector<StateEntry> state_stack_;
 
   // This structure accumulates bounds of all chunks under an effect. When an
-  // effect starts, we emit a SaveLayerOp with null bounds starts, and push a
-  // new |EffectBoundsInfo| onto |effect_bounds_stack_|. When the effect ends,
-  // we update the bounds of the SaveLayerOp.
+  // effect starts, we emit a SaveLayer[Alpha]Op with null bounds starts, and
+  // push a new |EffectBoundsInfo| onto |effect_bounds_stack_|. When the effect
+  // ends, we update the bounds of the op.
   struct EffectBoundsInfo {
-    // The id of the SaveLayerOp for this effect. It's recorded when we push the
-    // SaveLayerOp for this effect, and used when this effect ends in
+    // The id of the SaveLayer[Alpha]Op for this effect. It's recorded when we
+    // push the op for this effect, and used when this effect ends in
     // UpdateSaveLayerBounds().
     size_t save_layer_id;
-    // The transform space when the SaveLayerOp was emitted.
+    // The transform space when the SaveLayer[Alpha]Op was emitted.
     const TransformPaintPropertyNode* transform;
     // Records the bounds of the effect which initiated the entry. Note that
     // the effect is not |this->effect| (which is the previous effect), but the
@@ -182,8 +204,13 @@
 };
 
 ConversionContext::~ConversionContext() {
-  while (state_stack_.size())
-    PopToParentEffect();
+  // End all states.
+  while (state_stack_.size()) {
+    if (state_stack_.back().type == StateEntry::kEffect)
+      EndEffect();
+    else
+      EndClip();
+  }
 }
 
 void ConversionContext::SwitchToClip(const ClipPaintPropertyNode* target_clip) {
@@ -234,30 +261,7 @@
 
   // Step 3: Now apply the list of clips in top-down order.
   Optional<FloatRect> pending_combined_clip_rect;
-  const ClipPaintPropertyNode* last_pending_combined_clip;
-  auto apply_pending_combined_clip_rect = [this, &pending_combined_clip_rect,
-                                           &last_pending_combined_clip]() {
-    if (!pending_combined_clip_rect)
-      return;
-    DCHECK(last_pending_combined_clip);
-    cc_list_.StartPaint();
-    cc_list_.push<cc::SaveOp>();
-    ApplyTransform(last_pending_combined_clip->LocalTransformSpace());
-    const bool antialias = true;
-    cc_list_.push<cc::ClipRectOp>(
-        static_cast<SkRect>(*pending_combined_clip_rect), SkClipOp::kIntersect,
-        antialias);
-
-    cc_list_.EndPaintOfPairedBegin();
-    state_stack_.emplace_back(StateEntry{StateEntry::kClip, 1,
-                                         current_transform_, current_clip_,
-                                         current_effect_});
-    current_clip_ = last_pending_combined_clip;
-    current_transform_ = last_pending_combined_clip->LocalTransformSpace();
-    last_pending_combined_clip = nullptr;
-    pending_combined_clip_rect.reset();
-  };
-
+  const ClipPaintPropertyNode* lowest_combined_clip_node = nullptr;
   for (size_t i = pending_clips.size(); i--;) {
     const auto* sub_clip = pending_clips[i];
     bool has_rounded_clip_or_clip_path =
@@ -267,45 +271,71 @@
             sub_clip->LocalTransformSpace()) {
       // Continue to combine rectangular clips in the same transform space.
       pending_combined_clip_rect->Intersect(sub_clip->ClipRect().Rect());
-      last_pending_combined_clip = sub_clip;
+      lowest_combined_clip_node = sub_clip;
       continue;
     }
 
-    apply_pending_combined_clip_rect();
+    if (pending_combined_clip_rect) {
+      StartCombinedClip(*pending_combined_clip_rect, lowest_combined_clip_node);
+      lowest_combined_clip_node = nullptr;
+      pending_combined_clip_rect.reset();
+    }
 
-    if (!has_rounded_clip_or_clip_path) {
+    if (has_rounded_clip_or_clip_path) {
+      // The clip can't be combined with others.
+      StartSingleClip(sub_clip);
+    } else {
+      // Start to combine clips.
       pending_combined_clip_rect = sub_clip->ClipRect().Rect();
-      last_pending_combined_clip = sub_clip;
-      continue;
+      lowest_combined_clip_node = sub_clip;
     }
-
-    cc_list_.StartPaint();
-    cc_list_.push<cc::SaveOp>();
-    ApplyTransform(sub_clip->LocalTransformSpace());
-    const bool antialias = true;
-    cc_list_.push<cc::ClipRectOp>(
-        static_cast<SkRect>(sub_clip->ClipRect().Rect()), SkClipOp::kIntersect,
-        antialias);
-    if (sub_clip->ClipRect().IsRounded()) {
-      cc_list_.push<cc::ClipRRectOp>(static_cast<SkRRect>(sub_clip->ClipRect()),
-                                     SkClipOp::kIntersect, antialias);
-    }
-    if (sub_clip->ClipPath()) {
-      cc_list_.push<cc::ClipPathOp>(sub_clip->ClipPath()->GetSkPath(),
-                                    SkClipOp::kIntersect, antialias);
-    }
-    cc_list_.EndPaintOfPairedBegin();
-    state_stack_.emplace_back(StateEntry{StateEntry::kClip, 1,
-                                         current_transform_, current_clip_,
-                                         current_effect_});
-    current_clip_ = sub_clip;
-    current_transform_ = sub_clip->LocalTransformSpace();
   }
 
-  apply_pending_combined_clip_rect();
+  if (pending_combined_clip_rect)
+    StartCombinedClip(*pending_combined_clip_rect, lowest_combined_clip_node);
+
   DCHECK_EQ(current_clip_, target_clip);
 }
 
+void ConversionContext::StartCombinedClip(
+    const FloatRect& combined_clip_rect,
+    const ClipPaintPropertyNode* lowest_combined_clip_node) {
+  cc_list_.StartPaint();
+  cc_list_.push<cc::SaveOp>();
+  ApplyTransform(lowest_combined_clip_node->LocalTransformSpace());
+  const bool antialias = true;
+  cc_list_.push<cc::ClipRectOp>(combined_clip_rect, SkClipOp::kIntersect,
+                                antialias);
+
+  cc_list_.EndPaintOfPairedBegin();
+  state_stack_.emplace_back(StateEntry{StateEntry::kClip, 1, current_transform_,
+                                       current_clip_, current_effect_});
+  current_clip_ = lowest_combined_clip_node;
+  current_transform_ = lowest_combined_clip_node->LocalTransformSpace();
+}
+
+void ConversionContext::StartSingleClip(const ClipPaintPropertyNode* clip) {
+  cc_list_.StartPaint();
+  cc_list_.push<cc::SaveOp>();
+  ApplyTransform(clip->LocalTransformSpace());
+  const bool antialias = true;
+  cc_list_.push<cc::ClipRectOp>(static_cast<SkRect>(clip->ClipRect().Rect()),
+                                SkClipOp::kIntersect, antialias);
+  if (clip->ClipRect().IsRounded()) {
+    cc_list_.push<cc::ClipRRectOp>(static_cast<SkRRect>(clip->ClipRect()),
+                                   SkClipOp::kIntersect, antialias);
+  }
+  if (clip->ClipPath()) {
+    cc_list_.push<cc::ClipPathOp>(clip->ClipPath()->GetSkPath(),
+                                  SkClipOp::kIntersect, antialias);
+  }
+  cc_list_.EndPaintOfPairedBegin();
+  state_stack_.emplace_back(StateEntry{StateEntry::kClip, 1, current_transform_,
+                                       current_clip_, current_effect_});
+  current_clip_ = clip;
+  current_transform_ = clip->LocalTransformSpace();
+}
+
 void ConversionContext::SwitchToEffect(
     const EffectPaintPropertyNode* target_effect) {
   if (target_effect == current_effect_)
@@ -324,7 +354,9 @@
 #endif
     if (!state_stack_.size())
       break;
-    PopToParentEffect();
+    // Pop to the parent effect.
+    EndClips();
+    EndEffect();
   }
 
   // Step 2: Collect all effects between the target effect and the current
@@ -342,84 +374,94 @@
   for (size_t i = pending_effects.size(); i--;) {
     const EffectPaintPropertyNode* sub_effect = pending_effects[i];
     DCHECK_EQ(current_effect_, sub_effect->Parent());
+    StartEffect(sub_effect);
+  }
+}
 
-    // Step 3a: Before each effect can be applied, we must enter its output
-    // clip first, or exit all clips if it doesn't have one.
-    if (sub_effect->OutputClip())
-      SwitchToClip(sub_effect->OutputClip());
-    else
-      PopClips();
+void ConversionContext::StartEffect(const EffectPaintPropertyNode* effect) {
+  // Before each effect can be applied, we must enter its output clip first,
+  // or exit all clips if it doesn't have one.
+  if (effect->OutputClip())
+    SwitchToClip(effect->OutputClip());
+  else
+    EndClips();
 
-    // Step 3b: Apply effects.
-    cc_list_.StartPaint();
-    int saved_count = 0;
-    size_t save_layer_id = kNotFound;
-    const auto* target_transform = current_transform_;
+  // Apply effects.
+  cc_list_.StartPaint();
+  int saved_count = 0;
+  size_t save_layer_id = kNotFound;
+  const auto* target_transform = current_transform_;
 
-    // We always create separate effect nodes for normal effects and filter
-    // effects, so we can handle them separately.
-    bool has_filter = !sub_effect->Filter().IsEmpty();
-    bool has_other_effects = sub_effect->Opacity() != 1.f ||
-                             sub_effect->BlendMode() != SkBlendMode::kSrcOver ||
-                             sub_effect->GetColorFilter() != kColorFilterNone;
-    DCHECK(!has_filter || !has_other_effects);
+  // We always create separate effect nodes for normal effects and filter
+  // effects, so we can handle them separately.
+  bool has_filter = !effect->Filter().IsEmpty();
+  bool has_opacity = effect->Opacity() != 1.f;
+  bool has_other_effects = effect->BlendMode() != SkBlendMode::kSrcOver ||
+                           effect->GetColorFilter() != kColorFilterNone;
+  DCHECK(!has_filter || !(has_opacity || has_other_effects));
 
-    if (!has_filter) {
-      // No need to adjust transform for non-filter effects because transform
-      // doesn't matter.
+  if (!has_filter) {
+    // No need to adjust transform for non-filter effects because transform
+    // doesn't matter.
+    // TODO(ajuma): This should really be rounding instead of flooring the
+    // alpha value, but that breaks slimming paint reftests.
+    auto alpha =
+        static_cast<uint8_t>(gfx::ToFlooredInt(255 * effect->Opacity()));
+    if (has_other_effects) {
       cc::PaintFlags flags;
-      flags.setBlendMode(sub_effect->BlendMode());
-      // TODO(ajuma): This should really be rounding instead of flooring the
-      // alpha value, but that breaks slimming paint reftests.
-      flags.setAlpha(
-          static_cast<uint8_t>(gfx::ToFlooredInt(255 * sub_effect->Opacity())));
+      flags.setBlendMode(effect->BlendMode());
+      flags.setAlpha(alpha);
       flags.setColorFilter(GraphicsContext::WebCoreColorFilterToSkiaColorFilter(
-          sub_effect->GetColorFilter()));
+          effect->GetColorFilter()));
       save_layer_id = cc_list_.push<cc::SaveLayerOp>(nullptr, &flags);
-      saved_count++;
     } else {
-      // Handle filter effect. Adjust transform first.
-      target_transform = sub_effect->LocalTransformSpace();
-      FloatPoint filter_origin = sub_effect->PaintOffset();
-      if (current_transform_ != target_transform ||
-          filter_origin != FloatPoint()) {
-        auto matrix = GetSkMatrix(target_transform);
-        matrix.preTranslate(filter_origin.X(), filter_origin.Y());
-        cc_list_.push<cc::SaveOp>();
-        cc_list_.push<cc::ConcatOp>(matrix);
-        saved_count++;
-      }
-
-      // The size parameter is only used to computed the origin of zoom
-      // operation, which we never generate.
-      gfx::SizeF empty;
-      cc::PaintFlags filter_flags;
-      filter_flags.setImageFilter(cc::RenderSurfaceFilters::BuildImageFilter(
-          sub_effect->Filter().AsCcFilterOperations(), empty));
-      save_layer_id = cc_list_.push<cc::SaveLayerOp>(nullptr, &filter_flags);
-
-      if (filter_origin != FloatPoint())
-        cc_list_.push<cc::TranslateOp>(-filter_origin.X(), -filter_origin.Y());
+      constexpr bool preserve_lcd_text_requests = false;
+      save_layer_id = cc_list_.push<cc::SaveLayerAlphaOp>(
+          nullptr, alpha, preserve_lcd_text_requests);
+    }
+    saved_count++;
+  } else {
+    // Handle filter effect. Adjust transform first.
+    target_transform = effect->LocalTransformSpace();
+    FloatPoint filter_origin = effect->PaintOffset();
+    if (current_transform_ != target_transform ||
+        filter_origin != FloatPoint()) {
+      auto matrix = GetSkMatrix(target_transform);
+      matrix.preTranslate(filter_origin.X(), filter_origin.Y());
+      cc_list_.push<cc::SaveOp>();
+      cc_list_.push<cc::ConcatOp>(matrix);
       saved_count++;
     }
 
-    DCHECK_GT(saved_count, 0);
-    DCHECK_LE(saved_count, 2);
-    DCHECK_NE(save_layer_id, kNotFound);
-    cc_list_.EndPaintOfPairedBegin();
+    // The size parameter is only used to computed the origin of zoom
+    // operation, which we never generate.
+    gfx::SizeF empty;
+    cc::PaintFlags filter_flags;
+    filter_flags.setImageFilter(cc::RenderSurfaceFilters::BuildImageFilter(
+        effect->Filter().AsCcFilterOperations(), empty));
+    save_layer_id = cc_list_.push<cc::SaveLayerOp>(nullptr, &filter_flags);
 
-    // Step 3c: Adjust state and push previous state onto effect stack.
-    // TODO(trchen): Change input clip to expansion hint once implemented.
-    const ClipPaintPropertyNode* input_clip = current_clip_;
-    state_stack_.emplace_back(StateEntry{StateEntry::PairedType::kEffect,
-                                         saved_count, current_transform_,
-                                         current_clip_, current_effect_});
-    effect_bounds_stack_.emplace_back(
-        EffectBoundsInfo{save_layer_id, target_transform});
-    current_transform_ = target_transform;
-    current_clip_ = input_clip;
-    current_effect_ = sub_effect;
+    if (filter_origin != FloatPoint())
+      cc_list_.push<cc::TranslateOp>(-filter_origin.X(), -filter_origin.Y());
+    saved_count++;
   }
+
+  DCHECK_GT(saved_count, 0);
+  DCHECK_LE(saved_count, 2);
+  DCHECK_NE(save_layer_id, kNotFound);
+  cc_list_.EndPaintOfPairedBegin();
+
+  // Adjust state and push previous state onto effect stack.
+  // TODO(trchen): Change input clip to expansion hint once implemented.
+  const ClipPaintPropertyNode* input_clip = current_clip_;
+  state_stack_.emplace_back(StateEntry{StateEntry::PairedType::kEffect,
+                                       saved_count, current_transform_,
+                                       current_clip_, current_effect_});
+  effect_bounds_stack_.emplace_back(
+      EffectBoundsInfo{save_layer_id, target_transform});
+  current_transform_ = target_transform;
+  current_clip_ = input_clip;
+  current_effect_ = effect;
 }
 
 void ConversionContext::UpdateEffectBounds(
@@ -435,14 +477,7 @@
   effect_bounds_info.bounds.Unite(mapped_bounds);
 }
 
-// Pop clip states (if any) and one effect state (if any) on the top of the
-// stack. Update the bounds of the SaveLayerOp of the effect.
-void ConversionContext::PopToParentEffect() {
-  DCHECK(state_stack_.size());
-  PopClips();
-  if (state_stack_.IsEmpty())
-    return;
-
+void ConversionContext::EndEffect() {
   const auto& previous_state = state_stack_.back();
   DCHECK_EQ(previous_state.type, StateEntry::kEffect);
   DCHECK_EQ(current_effect_->Parent(), previous_state.effect);
@@ -455,9 +490,9 @@
     if (current_effect_->Filter().IsEmpty()) {
       cc_list_.UpdateSaveLayerBounds(bounds_info.save_layer_id, bounds);
     } else {
-      // The bounds for the SaveLayerOp should be the source bounds before the
-      // filter is applied, in the space of the TranslateOp which was emitted
-      // before the SaveLayerOp.
+      // The bounds for the SaveLayer[Alpha]Op should be the source bounds
+      // before the filter is applied, in the space of the TranslateOp which was
+      // emitted before the SaveLayer[Alpha]Op.
       auto save_layer_bounds = bounds;
       save_layer_bounds.MoveBy(-current_effect_->PaintOffset());
       cc_list_.UpdateSaveLayerBounds(bounds_info.save_layer_id,
@@ -479,17 +514,19 @@
   state_stack_.pop_back();
 }
 
-// Pop clip states on the top of the stack until the top is an effect state
-// or the stack is empty.
-void ConversionContext::PopClips() {
-  while (state_stack_.size() && state_stack_.back().type == StateEntry::kClip) {
-    const auto& previous_state = state_stack_.back();
-    AppendRestore(previous_state.saved_count);
-    current_transform_ = previous_state.transform;
-    current_clip_ = previous_state.clip;
-    DCHECK_EQ(previous_state.effect, current_effect_);
-    state_stack_.pop_back();
-  }
+void ConversionContext::EndClips() {
+  while (state_stack_.size() && state_stack_.back().type == StateEntry::kClip)
+    EndClip();
+}
+
+void ConversionContext::EndClip() {
+  DCHECK_EQ(state_stack_.back().type, StateEntry::kClip);
+  const auto& previous_state = state_stack_.back();
+  AppendRestore(previous_state.saved_count);
+  current_transform_ = previous_state.transform;
+  current_clip_ = previous_state.clip;
+  DCHECK_EQ(previous_state.effect, current_effect_);
+  state_stack_.pop_back();
 }
 
 void ConversionContext::Convert(const Vector<const PaintChunk*>& paint_chunks,
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/PaintChunksToCcLayerTest.cpp b/third_party/WebKit/Source/platform/graphics/compositing/PaintChunksToCcLayerTest.cpp
index aad4ca3..04a4d9ef 100644
--- a/third_party/WebKit/Source/platform/graphics/compositing/PaintChunksToCcLayerTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/compositing/PaintChunksToCcLayerTest.cpp
@@ -100,12 +100,19 @@
   Vector<cc::PaintOpType> expected_ops_;
 };
 
-#define EXPECT_EFFECT_BOUNDS(x, y, width, height, op_buffer, index)           \
-  do {                                                                        \
-    const auto* save_layer =                                                  \
-        (op_buffer).GetOpAtForTesting<cc::SaveLayerOp>(index);                \
-    ASSERT_NE(nullptr, save_layer);                                           \
-    EXPECT_EQ(FloatRect(x, y, width, height), FloatRect(save_layer->bounds)); \
+#define EXPECT_EFFECT_BOUNDS(x, y, width, height, op_buffer, index)         \
+  do {                                                                      \
+    FloatRect bounds;                                                       \
+    if (const auto* save_layer_alpha =                                      \
+            (op_buffer).GetOpAtForTesting<cc::SaveLayerAlphaOp>(index)) {   \
+      bounds = save_layer_alpha->bounds;                                    \
+    } else if (const auto* save_layer =                                     \
+                   (op_buffer).GetOpAtForTesting<cc::SaveLayerOp>(index)) { \
+      bounds = save_layer->bounds;                                          \
+    } else {                                                                \
+      FAIL() << "No SaveLayer[Alpha]Op at " << index;                       \
+    }                                                                       \
+    EXPECT_EQ(FloatRect(x, y, width, height), bounds);                      \
   } while (false)
 
 #define EXPECT_TRANSFORM_MATRIX(transform, op_buffer, index)                 \
@@ -191,11 +198,12 @@
           gfx::Vector2dF(), chunks.items,
           cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
           ->ReleaseAsRecord();
-  EXPECT_THAT(*output,
-              PaintRecordMatcher::Make({cc::PaintOpType::SaveLayer,   // <e1>
-                                        cc::PaintOpType::DrawRecord,  // <p0/>
-                                        cc::PaintOpType::DrawRecord,  // <p1/>
-                                        cc::PaintOpType::Restore}));  // </e1>
+  EXPECT_THAT(
+      *output,
+      PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha,  // <e1>
+                                cc::PaintOpType::DrawRecord,      // <p0/>
+                                cc::PaintOpType::DrawRecord,      // <p1/>
+                                cc::PaintOpType::Restore}));      // </e1>
   EXPECT_EFFECT_BOUNDS(0, 0, 90, 90, *output, 0);
 }
 
@@ -217,15 +225,16 @@
           gfx::Vector2dF(), chunks.items,
           cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
           ->ReleaseAsRecord();
-  EXPECT_THAT(*output,
-              PaintRecordMatcher::Make({cc::PaintOpType::SaveLayer,   // <e1>
-                                        cc::PaintOpType::SaveLayer,   // <e2>
-                                        cc::PaintOpType::DrawRecord,  // <p0/>
-                                        cc::PaintOpType::Restore,     // </e2>
-                                        cc::PaintOpType::SaveLayer,   // <e3>
-                                        cc::PaintOpType::DrawRecord,  // <p1/>
-                                        cc::PaintOpType::Restore,     // </e3>
-                                        cc::PaintOpType::Restore}));  // </e1>
+  EXPECT_THAT(
+      *output,
+      PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha,  // <e1>
+                                cc::PaintOpType::SaveLayerAlpha,  // <e2>
+                                cc::PaintOpType::DrawRecord,      // <p0/>
+                                cc::PaintOpType::Restore,         // </e2>
+                                cc::PaintOpType::SaveLayerAlpha,  // <e3>
+                                cc::PaintOpType::DrawRecord,      // <p1/>
+                                cc::PaintOpType::Restore,         // </e3>
+                                cc::PaintOpType::Restore}));      // </e1>
   EXPECT_EFFECT_BOUNDS(0, 0, 444, 666, *output, 0);
   EXPECT_EFFECT_BOUNDS(0, 0, 100, 100, *output, 1);
   EXPECT_EFFECT_BOUNDS(111, 222, 333, 444, *output, 4);
@@ -260,7 +269,7 @@
   EXPECT_THAT(
       *output,
       PaintRecordMatcher::Make(
-          {cc::PaintOpType::SaveLayer,                      // <e1>
+          {cc::PaintOpType::SaveLayerAlpha,                 // <e1>
            cc::PaintOpType::Save, cc::PaintOpType::Concat,  // <t1*t2>
            cc::PaintOpType::DrawRecord,                     // <p1/>
            cc::PaintOpType::Restore,                        // </t1*t2>
@@ -317,28 +326,31 @@
           gfx::Vector2dF(), chunks.items,
           cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
           ->ReleaseAsRecord();
-  EXPECT_THAT(
-      *output,
-      PaintRecordMatcher::Make(
-          {cc::PaintOpType::Save,       cc::PaintOpType::ClipRect,  // <c1+c2>
-           cc::PaintOpType::DrawRecord,                             // <p0/>
-           cc::PaintOpType::Save,       cc::PaintOpType::ClipRect,  // <c3>
-           cc::PaintOpType::DrawRecord,                             // <p1/>
-           cc::PaintOpType::Restore,                                // </c3>
-           cc::PaintOpType::SaveLayer,                              // <e1>
-           cc::PaintOpType::Save,       cc::PaintOpType::ClipRect,  // <c3+c4>
-           cc::PaintOpType::SaveLayer,                              // <e2>
-           cc::PaintOpType::DrawRecord,                             // <p2/>
-           cc::PaintOpType::Restore,                                // </e2>
-           cc::PaintOpType::Restore,                                // </c3+c4>
-           cc::PaintOpType::Save,       cc::PaintOpType::ClipRect,  // <c3>
-           cc::PaintOpType::DrawRecord,                             // <p3/>
-           cc::PaintOpType::Restore,                                // </c3>
-           cc::PaintOpType::Restore,                                // </e1>
-           cc::PaintOpType::Save,       cc::PaintOpType::ClipRect,  // <c3+c4>
-           cc::PaintOpType::DrawRecord,                             // <p4/>
-           cc::PaintOpType::Restore,                                // </c3+c4>
-           cc::PaintOpType::Restore}));                             // </c1+c2>
+  EXPECT_THAT(*output, PaintRecordMatcher::Make(
+                           {cc::PaintOpType::Save,
+                            cc::PaintOpType::ClipRect,    // <c1+c2>
+                            cc::PaintOpType::DrawRecord,  // <p0/>
+                            cc::PaintOpType::Save,
+                            cc::PaintOpType::ClipRect,        // <c3>
+                            cc::PaintOpType::DrawRecord,      // <p1/>
+                            cc::PaintOpType::Restore,         // </c3>
+                            cc::PaintOpType::SaveLayerAlpha,  // <e1>
+                            cc::PaintOpType::Save,
+                            cc::PaintOpType::ClipRect,        // <c3+c4>
+                            cc::PaintOpType::SaveLayerAlpha,  // <e2>
+                            cc::PaintOpType::DrawRecord,      // <p2/>
+                            cc::PaintOpType::Restore,         // </e2>
+                            cc::PaintOpType::Restore,         // </c3+c4>
+                            cc::PaintOpType::Save,
+                            cc::PaintOpType::ClipRect,    // <c3>
+                            cc::PaintOpType::DrawRecord,  // <p3/>
+                            cc::PaintOpType::Restore,     // </c3>
+                            cc::PaintOpType::Restore,     // </e1>
+                            cc::PaintOpType::Save,
+                            cc::PaintOpType::ClipRect,    // <c3+c4>
+                            cc::PaintOpType::DrawRecord,  // <p4/>
+                            cc::PaintOpType::Restore,     // </c3+c4>
+                            cc::PaintOpType::Restore}));  // </c1+c2>
   EXPECT_EFFECT_BOUNDS(0, 0, 90, 90, *output, 7);
   EXPECT_EFFECT_BOUNDS(0, 0, 50, 50, *output, 10);
 }
@@ -397,14 +409,15 @@
           gfx::Vector2dF(), chunks.items,
           cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
           ->ReleaseAsRecord();
-  EXPECT_THAT(*output,
-              PaintRecordMatcher::Make({cc::PaintOpType::SaveLayer,   // <e1>
-                                        cc::PaintOpType::DrawRecord,  // <p0/>
-                                        cc::PaintOpType::Save,
-                                        cc::PaintOpType::Concat,      // <t1>
-                                        cc::PaintOpType::DrawRecord,  // <p1/>
-                                        cc::PaintOpType::Restore,     // </t1>
-                                        cc::PaintOpType::Restore}));  // </e1>
+  EXPECT_THAT(
+      *output,
+      PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha,  // <e1>
+                                cc::PaintOpType::DrawRecord,      // <p0/>
+                                cc::PaintOpType::Save,
+                                cc::PaintOpType::Concat,      // <t1>
+                                cc::PaintOpType::DrawRecord,  // <p1/>
+                                cc::PaintOpType::Restore,     // </t1>
+                                cc::PaintOpType::Restore}));  // </e1>
   EXPECT_EFFECT_BOUNDS(0, 0, 200, 200, *output, 0);
   EXPECT_TRANSFORM_MATRIX(t1->Matrix(), *output, 3);
 }
@@ -517,13 +530,14 @@
           gfx::Vector2dF(), chunks.items,
           cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
           ->ReleaseAsRecord();
-  EXPECT_THAT(*output,
-              PaintRecordMatcher::Make({cc::PaintOpType::SaveLayer,  // <e1>
-                                        cc::PaintOpType::Save,
-                                        cc::PaintOpType::ClipRect,    // <c2>
-                                        cc::PaintOpType::DrawRecord,  // <p0/>
-                                        cc::PaintOpType::Restore,     // </c2>
-                                        cc::PaintOpType::Restore}));  // </e1>
+  EXPECT_THAT(
+      *output,
+      PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha,  // <e1>
+                                cc::PaintOpType::Save,
+                                cc::PaintOpType::ClipRect,    // <c2>
+                                cc::PaintOpType::DrawRecord,  // <p0/>
+                                cc::PaintOpType::Restore,     // </c2>
+                                cc::PaintOpType::Restore}));  // </e1>
   EXPECT_EFFECT_BOUNDS(0, 0, 100, 100, *output, 0);
 }
 
@@ -547,15 +561,16 @@
           gfx::Vector2dF(), chunks.items,
           cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
           ->ReleaseAsRecord();
-  EXPECT_THAT(*output,
-              PaintRecordMatcher::Make({cc::PaintOpType::SaveLayer,  // <e1>
-                                        cc::PaintOpType::SaveLayer,  // <e2>
-                                        cc::PaintOpType::Save,
-                                        cc::PaintOpType::ClipRect,    // <c1>
-                                        cc::PaintOpType::DrawRecord,  // <p0/>
-                                        cc::PaintOpType::Restore,     // </c1>
-                                        cc::PaintOpType::Restore,     // </e2>
-                                        cc::PaintOpType::Restore}));  // </e1>
+  EXPECT_THAT(
+      *output,
+      PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha,  // <e1>
+                                cc::PaintOpType::SaveLayerAlpha,  // <e2>
+                                cc::PaintOpType::Save,
+                                cc::PaintOpType::ClipRect,    // <c1>
+                                cc::PaintOpType::DrawRecord,  // <p0/>
+                                cc::PaintOpType::Restore,     // </c1>
+                                cc::PaintOpType::Restore,     // </e2>
+                                cc::PaintOpType::Restore}));  // </e1>
   EXPECT_EFFECT_BOUNDS(0, 0, 100, 100, *output, 0);
   EXPECT_EFFECT_BOUNDS(0, 0, 100, 100, *output, 1);
 }
@@ -580,13 +595,14 @@
           gfx::Vector2dF(), chunks.items,
           cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
           ->ReleaseAsRecord();
-  EXPECT_THAT(*output,
-              PaintRecordMatcher::Make({cc::PaintOpType::SaveLayer,  // <e2>
-                                        cc::PaintOpType::Save,
-                                        cc::PaintOpType::ClipRect,    // <c1>
-                                        cc::PaintOpType::DrawRecord,  // <p0/>
-                                        cc::PaintOpType::Restore,     // </c1>
-                                        cc::PaintOpType::Restore}));  // </e2>
+  EXPECT_THAT(
+      *output,
+      PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha,  // <e2>
+                                cc::PaintOpType::Save,
+                                cc::PaintOpType::ClipRect,    // <c1>
+                                cc::PaintOpType::DrawRecord,  // <p0/>
+                                cc::PaintOpType::Restore,     // </c1>
+                                cc::PaintOpType::Restore}));  // </e2>
   EXPECT_EFFECT_BOUNDS(0, 0, 100, 100, *output, 0);
 }
 
@@ -610,10 +626,11 @@
           gfx::Vector2dF(), chunks.items,
           cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
           ->ReleaseAsRecord();
-  EXPECT_THAT(*output,
-              PaintRecordMatcher::Make({cc::PaintOpType::SaveLayer,   // <e2>
-                                        cc::PaintOpType::DrawRecord,  // <p0/>
-                                        cc::PaintOpType::Restore}));  // </e2>
+  EXPECT_THAT(
+      *output,
+      PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha,  // <e2>
+                                cc::PaintOpType::DrawRecord,      // <p0/>
+                                cc::PaintOpType::Restore}));      // </e2>
   EXPECT_EFFECT_BOUNDS(0, 0, 100, 100, *output, 0);
 }
 
@@ -756,8 +773,8 @@
           ->ReleaseAsRecord();
 
   EXPECT_THAT(*output, PaintRecordMatcher::Make({
-                           cc::PaintOpType::SaveLayer,  // <e1>
-                           cc::PaintOpType::Restore,    // </e1>
+                           cc::PaintOpType::SaveLayerAlpha,  // <e1>
+                           cc::PaintOpType::Restore,         // </e1>
                        }));
   EXPECT_EFFECT_BOUNDS(0, 0, 100, 100, *output, 0);
 }
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/ImageLayerBridge.cpp b/third_party/WebKit/Source/platform/graphics/gpu/ImageLayerBridge.cpp
index 89ab3c2..c95e59c 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/ImageLayerBridge.cpp
+++ b/third_party/WebKit/Source/platform/graphics/gpu/ImageLayerBridge.cpp
@@ -56,6 +56,12 @@
   has_presented_since_last_set_image_ = false;
 }
 
+void ImageLayerBridge::SetUV(const FloatPoint left_top,
+                             const FloatPoint right_bottom) {
+  layer_->SetUV(WebFloatPoint(left_top.X(), left_top.Y()),
+                WebFloatPoint(right_bottom.X(), right_bottom.Y()));
+}
+
 void ImageLayerBridge::Dispose() {
   if (layer_) {
     GraphicsLayer::UnregisterContentsLayer(layer_->Layer());
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/ImageLayerBridge.h b/third_party/WebKit/Source/platform/graphics/gpu/ImageLayerBridge.h
index 42f1876..0239416e 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/ImageLayerBridge.h
+++ b/third_party/WebKit/Source/platform/graphics/gpu/ImageLayerBridge.h
@@ -7,6 +7,7 @@
 
 #include "cc/layers/texture_layer_client.h"
 #include "platform/PlatformExport.h"
+#include "platform/geometry/FloatPoint.h"
 #include "platform/graphics/GraphicsTypes.h"
 #include "platform/graphics/StaticBitmapImage.h"
 #include "platform/heap/Heap.h"
@@ -53,6 +54,7 @@
   void SetFilterQuality(SkFilterQuality filter_quality) {
     filter_quality_ = filter_quality;
   }
+  void SetUV(const FloatPoint left_top, const FloatPoint right_bottom);
 
   bool IsAccelerated() { return image_->IsTextureBacked(); }
 
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/XRWebGLDrawingBuffer.cpp b/third_party/WebKit/Source/platform/graphics/gpu/XRWebGLDrawingBuffer.cpp
index 3b87c25b2..7155ea9 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/XRWebGLDrawingBuffer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/gpu/XRWebGLDrawingBuffer.cpp
@@ -159,6 +159,17 @@
   return drawing_buffer_->ContextGL();
 }
 
+void XRWebGLDrawingBuffer::SetMirrorClient(MirrorClient* client) {
+  mirror_client_ = client;
+  if (mirror_client_) {
+    // Immediately send a black 1x1 image to the mirror client to ensure that
+    // it has content to show.
+    sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(1, 1);
+    mirror_client_->OnMirrorImageAvailable(
+        StaticBitmapImage::Create(surface->makeImageSnapshot()), nullptr);
+  }
+}
+
 bool XRWebGLDrawingBuffer::ContextLost() {
   return drawing_buffer_->destroyed();
 }
@@ -419,8 +430,10 @@
 
   // This holds a ref on the XRWebGLDrawingBuffer that will keep it alive
   // until the mailbox is released (and while the callback is running).
-  auto func = WTF::Bind(&XRWebGLDrawingBuffer::MailboxReleased,
-                        scoped_refptr<XRWebGLDrawingBuffer>(this), buffer);
+  auto func =
+      WTF::Bind(mirror_client_ ? &XRWebGLDrawingBuffer::MailboxReleasedToMirror
+                               : &XRWebGLDrawingBuffer::MailboxReleased,
+                scoped_refptr<XRWebGLDrawingBuffer>(this), buffer);
 
   std::unique_ptr<viz::SingleReleaseCallback> release_callback =
       viz::SingleReleaseCallback::Create(std::move(func));
@@ -468,4 +481,35 @@
   recycled_color_buffer_queue_.push_front(color_buffer);
 }
 
+void XRWebGLDrawingBuffer::MailboxReleasedToMirror(
+    scoped_refptr<ColorBuffer> color_buffer,
+    const gpu::SyncToken& sync_token,
+    bool lost_resource) {
+  if (!mirror_client_ || lost_resource) {
+    MailboxReleased(std::move(color_buffer), sync_token, lost_resource);
+    return;
+  }
+
+  gpu::gles2::GLES2Interface* gl = drawing_buffer_->ContextGL();
+  color_buffer->receive_sync_token = sync_token;
+
+  auto func =
+      WTF::Bind(&XRWebGLDrawingBuffer::MailboxReleased,
+                scoped_refptr<XRWebGLDrawingBuffer>(this), color_buffer);
+
+  std::unique_ptr<viz::SingleReleaseCallback> release_callback =
+      viz::SingleReleaseCallback::Create(std::move(func));
+
+  GLuint texture_id =
+      gl->CreateAndConsumeTextureCHROMIUM(color_buffer->mailbox.name);
+
+  scoped_refptr<StaticBitmapImage> image =
+      AcceleratedStaticBitmapImage::CreateFromWebGLContextImage(
+          color_buffer->mailbox, color_buffer->produce_sync_token, texture_id,
+          drawing_buffer_->ContextProviderWeakPtr(), color_buffer->size);
+
+  mirror_client_->OnMirrorImageAvailable(std::move(image),
+                                         std::move(release_callback));
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/XRWebGLDrawingBuffer.h b/third_party/WebKit/Source/platform/graphics/gpu/XRWebGLDrawingBuffer.h
index 1e1033b..328fc9ac 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/XRWebGLDrawingBuffer.h
+++ b/third_party/WebKit/Source/platform/graphics/gpu/XRWebGLDrawingBuffer.h
@@ -48,6 +48,15 @@
   scoped_refptr<StaticBitmapImage> TransferToStaticBitmapImage(
       std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback);
 
+  class MirrorClient {
+   public:
+    virtual void OnMirrorImageAvailable(
+        scoped_refptr<StaticBitmapImage>,
+        std::unique_ptr<viz::SingleReleaseCallback>) = 0;
+  };
+
+  void SetMirrorClient(MirrorClient*);
+
  private:
   struct ColorBuffer : public RefCounted<ColorBuffer> {
     ColorBuffer(XRWebGLDrawingBuffer*, const IntSize&, GLuint texture_id);
@@ -95,6 +104,9 @@
   void MailboxReleased(scoped_refptr<ColorBuffer>,
                        const gpu::SyncToken&,
                        bool lost_resource);
+  void MailboxReleasedToMirror(scoped_refptr<ColorBuffer>,
+                               const gpu::SyncToken&,
+                               bool lost_resource);
 
   // Reference to the DrawingBuffer that owns the GL context for this object.
   scoped_refptr<DrawingBuffer> drawing_buffer_;
@@ -129,6 +141,8 @@
   int max_texture_size_ = 0;
   int sample_count_ = 0;
   bool framebuffer_incomplete_ = false;
+
+  MirrorClient* mirror_client_ = nullptr;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/heap/BlinkGC.h b/third_party/WebKit/Source/platform/heap/BlinkGC.h
index 4f5c343b..94666b6 100644
--- a/third_party/WebKit/Source/platform/heap/BlinkGC.h
+++ b/third_party/WebKit/Source/platform/heap/BlinkGC.h
@@ -64,6 +64,11 @@
 
 #define TypedArenaEnumName(Type) k##Type##ArenaIndex,
 
+class PLATFORM_EXPORT WorklistTaskId {
+ public:
+  static constexpr int MainThread = 0;
+};
+
 class PLATFORM_EXPORT BlinkGC final {
   STATIC_ONLY(BlinkGC);
 
diff --git a/third_party/WebKit/Source/platform/heap/Heap.cpp b/third_party/WebKit/Source/platform/heap/Heap.cpp
index 9333fc1f..54ca921 100644
--- a/third_party/WebKit/Source/platform/heap/Heap.cpp
+++ b/third_party/WebKit/Source/platform/heap/Heap.cpp
@@ -135,12 +135,10 @@
       region_tree_(std::make_unique<RegionTree>()),
       heap_does_not_contain_cache_(std::make_unique<HeapDoesNotContainCache>()),
       free_page_pool_(std::make_unique<PagePool>()),
-      marking_stack_(CallbackStack::Create()),
+      marking_worklist_(nullptr),
       not_fully_constructed_marking_stack_(CallbackStack::Create()),
       post_marking_callback_stack_(CallbackStack::Create()),
       weak_callback_stack_(CallbackStack::Create()),
-      ephemeron_stack_(CallbackStack::Create()),
-      ephemeron_iteration_done_stack_(CallbackStack::Create()),
       vector_backing_arena_index_(BlinkGC::kVector1ArenaIndex),
       current_arena_ages_(0),
       should_flush_heap_does_not_contain_cache_(false) {
@@ -214,12 +212,6 @@
 }
 #endif  // DCHECK_IS_ON()
 
-void ThreadHeap::PushTraceCallback(void* object, TraceCallback callback) {
-  DCHECK(thread_state_->IsInGC() || thread_state_->IsIncrementalMarking());
-  CallbackStack::Item* slot = marking_stack_->AllocateEntry();
-  *slot = CallbackStack::Item(object, callback);
-}
-
 void ThreadHeap::PushNotFullyConstructedTraceCallback(void* object) {
   DCHECK(thread_state_->IsInGC() || thread_state_->IsIncrementalMarking());
   CallbackStack::Item* slot =
@@ -248,16 +240,6 @@
   return true;
 }
 
-bool ThreadHeap::PopAndInvokeTraceCallback(Visitor* v) {
-  MarkingVisitor* visitor = reinterpret_cast<MarkingVisitor*>(v);
-  CallbackStack::Item* item = marking_stack_->Pop();
-  if (!item)
-    return false;
-  DCHECK(item->Callback());
-  item->Call(visitor);
-  return true;
-}
-
 void ThreadHeap::PushPostMarkingCallback(void* object, TraceCallback callback) {
   DCHECK(thread_state_->IsInGC());
 
@@ -273,12 +255,6 @@
   return false;
 }
 
-void ThreadHeap::InvokeEphemeronIterationDoneCallbacks(Visitor* visitor) {
-  while (CallbackStack::Item* item = ephemeron_iteration_done_stack_->Pop()) {
-    item->Call(visitor);
-  }
-}
-
 void ThreadHeap::PushWeakCallback(void* closure, WeakCallback callback) {
   CallbackStack::Item* slot = weak_callback_stack_->AllocateEntry();
   *slot = CallbackStack::Item(closure, callback);
@@ -293,31 +269,31 @@
 }
 
 void ThreadHeap::RegisterWeakTable(void* table,
-                                   EphemeronCallback iteration_callback,
-                                   EphemeronCallback iteration_done_callback) {
+                                   EphemeronCallback iteration_callback) {
   DCHECK(thread_state_->IsInGC());
-
-  CallbackStack::Item* slot = ephemeron_stack_->AllocateEntry();
-  *slot = CallbackStack::Item(table, iteration_callback);
-
-  slot = ephemeron_iteration_done_stack_->AllocateEntry();
-  *slot = CallbackStack::Item(table, iteration_done_callback);
-}
-
 #if DCHECK_IS_ON()
-bool ThreadHeap::WeakTableRegistered(const void* table) {
-  DCHECK(ephemeron_stack_);
-  return ephemeron_stack_->HasCallbackForObject(table);
+  auto result = ephemeron_callbacks_.insert(table, iteration_callback);
+  DCHECK(result.is_new_entry ||
+         result.stored_value->value == iteration_callback);
+#else
+  ephemeron_callbacks_.insert(table, iteration_callback);
+#endif  // DCHECK_IS_ON()
 }
-#endif
 
 void ThreadHeap::CommitCallbackStacks() {
-  marking_stack_->Commit();
+  marking_worklist_.reset(new MarkingWorklist());
   not_fully_constructed_marking_stack_->Commit();
   post_marking_callback_stack_->Commit();
   weak_callback_stack_->Commit();
-  ephemeron_stack_->Commit();
-  ephemeron_iteration_done_stack_->Commit();
+  DCHECK(ephemeron_callbacks_.IsEmpty());
+}
+
+void ThreadHeap::DecommitCallbackStacks() {
+  marking_worklist_.reset(nullptr);
+  not_fully_constructed_marking_stack_->Decommit();
+  post_marking_callback_stack_->Decommit();
+  weak_callback_stack_->Decommit();
+  ephemeron_callbacks_.clear();
 }
 
 HeapCompact* ThreadHeap::Compaction() {
@@ -340,15 +316,6 @@
                                              callback_data);
 }
 
-void ThreadHeap::DecommitCallbackStacks() {
-  marking_stack_->Decommit();
-  not_fully_constructed_marking_stack_->Decommit();
-  post_marking_callback_stack_->Decommit();
-  weak_callback_stack_->Decommit();
-  ephemeron_stack_->Decommit();
-  ephemeron_iteration_done_stack_->Decommit();
-}
-
 void ThreadHeap::ProcessMarkingStack(Visitor* visitor) {
   bool complete = AdvanceMarkingStackProcessing(
       visitor, std::numeric_limits<double>::infinity());
@@ -362,6 +329,28 @@
   }
 }
 
+void ThreadHeap::InvokeEphemeronCallbacks(Visitor* visitor) {
+  // Mark any strong pointers that have now become reachable in ephemeron maps.
+  TRACE_EVENT0("blink_gc", "ThreadHeap::InvokeEphemeronCallbacks");
+
+  // Avoid supporting a subtle scheme that allows insertion while iterating
+  // by just creating temporary lists for iteration and sinking.
+  WTF::HashMap<void*, EphemeronCallback> iteration_set;
+  WTF::HashMap<void*, EphemeronCallback> final_set;
+
+  bool found_new = false;
+  do {
+    iteration_set = std::move(ephemeron_callbacks_);
+    ephemeron_callbacks_.clear();
+    for (auto& tuple : iteration_set) {
+      final_set.insert(tuple.key, tuple.value);
+      tuple.value(visitor, tuple.key);
+    }
+    found_new = !ephemeron_callbacks_.IsEmpty();
+  } while (found_new);
+  ephemeron_callbacks_ = std::move(final_set);
+}
+
 bool ThreadHeap::AdvanceMarkingStackProcessing(Visitor* visitor,
                                                double deadline_seconds) {
   const size_t kDeadlineCheckInterval = 2500;
@@ -372,7 +361,9 @@
       // Iteratively mark all objects that are reachable from the objects
       // currently pushed onto the marking stack.
       TRACE_EVENT0("blink_gc", "ThreadHeap::processMarkingStackSingleThreaded");
-      while (PopAndInvokeTraceCallback(visitor)) {
+      MarkingItem item;
+      while (marking_worklist_->Pop(WorklistTaskId::MainThread, &item)) {
+        item.callback(visitor, item.object);
         processed_callback_count++;
         if (processed_callback_count % kDeadlineCheckInterval == 0) {
           if (deadline_seconds <= CurrentTimeTicksInSeconds()) {
@@ -382,15 +373,10 @@
       }
     }
 
-    {
-      // Mark any strong pointers that have now become reachable in
-      // ephemeron maps.
-      TRACE_EVENT0("blink_gc", "ThreadHeap::processEphemeronStack");
-      ephemeron_stack_->InvokeEphemeronCallbacks(visitor);
-    }
+    InvokeEphemeronCallbacks(visitor);
 
     // Rerun loop if ephemeron processing queued more objects for tracing.
-  } while (!marking_stack_->IsEmpty());
+  } while (!marking_worklist_->IsGlobalEmpty());
   return true;
 }
 
@@ -401,14 +387,13 @@
   //    (specifically to clear the queued bits for weak hash tables), and
   // 2. the markNoTracing callbacks on collection backings to mark them
   //    if they are only reachable from their front objects.
-  InvokeEphemeronIterationDoneCallbacks(visitor);
   while (PopAndInvokePostMarkingCallback(visitor)) {
   }
 
   // Post-marking callbacks should not trace any objects and
   // therefore the marking stack should be empty after the
   // post-marking callbacks.
-  DCHECK(marking_stack_->IsEmpty());
+  DCHECK(marking_worklist_->IsGlobalEmpty());
 }
 
 void ThreadHeap::WeakProcessing(Visitor* visitor) {
@@ -426,7 +411,7 @@
 
   // It is not permitted to trace pointers of live objects in the weak
   // callback phase, so the marking stack should still be empty here.
-  DCHECK(marking_stack_->IsEmpty());
+  DCHECK(marking_worklist_->IsGlobalEmpty());
 
   double time_for_weak_processing =
       WTF::CurrentTimeTicksInMilliseconds() - start_time;
@@ -523,12 +508,15 @@
 size_t ThreadHeap::ObjectPayloadSizeForTesting() {
   size_t object_payload_size = 0;
   thread_state_->SetGCState(ThreadState::kGCRunning);
+  thread_state_->SetGCPhase(ThreadState::GCPhase::kMarking);
   thread_state_->Heap().MakeConsistentForGC();
   thread_state_->Heap().PrepareForSweep();
   for (int i = 0; i < BlinkGC::kNumberOfArenas; ++i)
     object_payload_size += arenas_[i]->ObjectPayloadSizeForTesting();
   MakeConsistentForMutator();
+  thread_state_->SetGCPhase(ThreadState::GCPhase::kSweeping);
   thread_state_->SetGCState(ThreadState::kSweeping);
+  thread_state_->SetGCPhase(ThreadState::GCPhase::kNone);
   thread_state_->SetGCState(ThreadState::kNoGCScheduled);
   return object_payload_size;
 }
@@ -855,17 +843,9 @@
 
   // Mark and push trace callback.
   header->Mark();
-  PushTraceCallback(header->Payload(),
-                    ThreadHeap::GcInfo(header->GcInfoIndex())->trace_);
-}
-
-void ThreadHeap::CheckObjectNotInCallbackStacks(const void* object) {
-#if DCHECK_IS_ON()
-  DCHECK(!MarkingStack()->HasCallbackForObject(object));
-  DCHECK(!PostMarkingCallbackStack()->HasCallbackForObject(object));
-  DCHECK(!WeakCallbackStack()->HasCallbackForObject(object));
-  DCHECK(!EphemeronStack()->HasCallbackForObject(object));
-#endif
+  marking_worklist_->Push(
+      WorklistTaskId::MainThread,
+      {header->Payload(), ThreadHeap::GcInfo(header->GcInfoIndex())->trace_});
 }
 
 ThreadHeap* ThreadHeap::main_thread_heap_ = nullptr;
diff --git a/third_party/WebKit/Source/platform/heap/Heap.h b/third_party/WebKit/Source/platform/heap/Heap.h
index b5f7008e..6cda948 100644
--- a/third_party/WebKit/Source/platform/heap/Heap.h
+++ b/third_party/WebKit/Source/platform/heap/Heap.h
@@ -42,6 +42,7 @@
 #include "platform/heap/StackFrameDepth.h"
 #include "platform/heap/ThreadState.h"
 #include "platform/heap/Visitor.h"
+#include "platform/heap/Worklist.h"
 #include "platform/wtf/AddressSanitizer.h"
 #include "platform/wtf/Allocator.h"
 #include "platform/wtf/Assertions.h"
@@ -50,10 +51,28 @@
 
 namespace blink {
 
+namespace incremental_marking_test {
+class IncrementalMarkingScopeBase;
+}  // namespace incremental_marking_test
+
 class CallbackStack;
 class PagePool;
 class RegionTree;
 
+struct MarkingItem {
+  void* object;
+  TraceCallback callback;
+
+  // Only used for DCHECKs for Worklist::Contains.
+  bool operator==(const MarkingItem& other) const {
+    return object == other.object;
+  }
+};
+
+// Segment size of 512 entries necessary to avoid throughput regressions. Since
+// the work list is currently a temporary object this is not a problem.
+using MarkingWorklist = Worklist<MarkingItem, 512 /* local entries */>;
+
 class PLATFORM_EXPORT HeapAllocHooks {
  public:
   // TODO(hajimehoshi): Pass a type name of the allocated object.
@@ -224,7 +243,11 @@
   StackFrameDepth& GetStackFrameDepth() { return stack_frame_depth_; }
 
   ThreadHeapStats& HeapStats() { return stats_; }
-  CallbackStack* MarkingStack() const { return marking_stack_.get(); }
+
+  MarkingWorklist* GetMarkingWorklist() const {
+    return marking_worklist_.get();
+  }
+
   CallbackStack* NotFullyConstructedMarkingStack() const {
     return not_fully_constructed_marking_stack_.get();
   }
@@ -234,9 +257,6 @@
   CallbackStack* WeakCallbackStack() const {
     return weak_callback_stack_.get();
   }
-  CallbackStack* EphemeronStack() const { return ephemeron_stack_.get(); }
-
-  void CheckObjectNotInCallbackStacks(const void*);
 
   void VisitPersistentRoots(Visitor*);
   void VisitStackRoots(MarkingVisitor*);
@@ -276,9 +296,6 @@
         page, const_cast<T*>(object_pointer));
   }
 
-  // Push a trace callback on the marking stack.
-  void PushTraceCallback(void* container_object, TraceCallback);
-
   // Push a trace callback for not-fully-constructed objects.
   void PushNotFullyConstructedTraceCallback(void* container_object);
 
@@ -291,10 +308,6 @@
   // doesn't get marked in the current GC.
   void PushWeakCallback(void*, WeakCallback);
 
-  // Pop the top of a marking stack and call the callback with the visitor
-  // and the object.  Returns false when there is nothing more to do.
-  bool PopAndInvokeTraceCallback(Visitor*);
-
   // Pop the top of the not-yet-fully-constructed objects marking stack and call
   // the callback with the visitor and the object. Returns false when there is
   // nothing more to do. Can only be called during the atomic pause.
@@ -305,11 +318,6 @@
   // false when there is nothing more to do.
   bool PopAndInvokePostMarkingCallback(Visitor*);
 
-  // Invokes all ephemeronIterationDone callbacks on weak tables to do cleanup
-  // (specifically to clear the queued bits for weak hash tables). Needs to be
-  // called even when marking has been aborted.
-  void InvokeEphemeronIterationDoneCallbacks(Visitor*);
-
   // Remove an item from the weak callback work list and call the callback
   // with the visitor and the closure pointer.  Returns false when there is
   // nothing more to do.
@@ -317,11 +325,7 @@
 
   // Register an ephemeron table for fixed-point iteration.
   void RegisterWeakTable(void* container_object,
-                         EphemeronCallback,
                          EphemeronCallback);
-#if DCHECK_IS_ON()
-  bool WeakTableRegistered(const void*);
-#endif
 
   // Heap compaction registration methods:
 
@@ -515,8 +519,6 @@
 #endif
 
  private:
-  friend class incremental_marking_test::IncrementalMarkingScope;
-
   // Reset counters that track live and allocated-since-last-GC sizes.
   void ResetHeapCounters();
 
@@ -525,6 +527,8 @@
   void CommitCallbackStacks();
   void DecommitCallbackStacks();
 
+  void InvokeEphemeronCallbacks(Visitor*);
+
   // Fast write barrier assuming that incremental marking is running and
   // |value| is not nullptr.
   void WriteBarrierInternal(BasePage*, const void* value);
@@ -534,12 +538,13 @@
   std::unique_ptr<RegionTree> region_tree_;
   std::unique_ptr<HeapDoesNotContainCache> heap_does_not_contain_cache_;
   std::unique_ptr<PagePool> free_page_pool_;
-  std::unique_ptr<CallbackStack> marking_stack_;
+  std::unique_ptr<MarkingWorklist> marking_worklist_;
   std::unique_ptr<CallbackStack> not_fully_constructed_marking_stack_;
   std::unique_ptr<CallbackStack> post_marking_callback_stack_;
   std::unique_ptr<CallbackStack> weak_callback_stack_;
-  std::unique_ptr<CallbackStack> ephemeron_stack_;
-  std::unique_ptr<CallbackStack> ephemeron_iteration_done_stack_;
+  // No duplicates allowed for ephemeron callbacks. Hence, we use a hashmap
+  // with the key being the HashTable.
+  WTF::HashMap<void*, EphemeronCallback> ephemeron_callbacks_;
   StackFrameDepth stack_frame_depth_;
 
   std::unique_ptr<HeapCompact> compaction_;
@@ -561,6 +566,7 @@
 
   static ThreadHeap* main_thread_heap_;
 
+  friend class incremental_marking_test::IncrementalMarkingScopeBase;
   template <typename T>
   friend class Member;
   friend class ThreadState;
diff --git a/third_party/WebKit/Source/platform/heap/HeapAllocator.cpp b/third_party/WebKit/Source/platform/heap/HeapAllocator.cpp
index 7d0bac8..595f2dc 100644
--- a/third_party/WebKit/Source/platform/heap/HeapAllocator.cpp
+++ b/third_party/WebKit/Source/platform/heap/HeapAllocator.cpp
@@ -27,7 +27,6 @@
   // free is disabled for surviving backings during lazy sweeping.
   if (header->IsMarked())
     return;
-  state->Heap().CheckObjectNotInCallbackStacks(address);
   state->Heap().PromptlyFreed(header->GcInfoIndex());
   static_cast<NormalPage*>(page)->ArenaForNormalPage()->PromptlyFreeObject(
       header);
diff --git a/third_party/WebKit/Source/platform/heap/HeapAllocator.h b/third_party/WebKit/Source/platform/heap/HeapAllocator.h
index e29a6a56..c8297e6 100644
--- a/third_party/WebKit/Source/platform/heap/HeapAllocator.h
+++ b/third_party/WebKit/Source/platform/heap/HeapAllocator.h
@@ -190,20 +190,10 @@
   template <typename VisitorDispatcher>
   static bool RegisterWeakTable(VisitorDispatcher visitor,
                                 const void* closure,
-                                EphemeronCallback iteration_callback,
-                                EphemeronCallback iteration_done_callback) {
-    return visitor->RegisterWeakTable(closure, iteration_callback,
-                                      iteration_done_callback);
+                                EphemeronCallback iteration_callback) {
+    return visitor->RegisterWeakTable(closure, iteration_callback);
   }
 
-#if DCHECK_IS_ON()
-  template <typename VisitorDispatcher>
-  static bool WeakTableRegistered(VisitorDispatcher visitor,
-                                  const void* closure) {
-    return visitor->WeakTableRegistered(closure);
-  }
-#endif
-
   template <typename T, typename VisitorDispatcher>
   static void RegisterBackingStoreCallback(VisitorDispatcher visitor,
                                            T* backing_store,
diff --git a/third_party/WebKit/Source/platform/heap/HeapCompact.cpp b/third_party/WebKit/Source/platform/heap/HeapCompact.cpp
index 97f01286..e77bc4b 100644
--- a/third_party/WebKit/Source/platform/heap/HeapCompact.cpp
+++ b/third_party/WebKit/Source/platform/heap/HeapCompact.cpp
@@ -50,7 +50,7 @@
       return;
     }
     interior_fixups_.insert(slot, nullptr);
-    LOG_HEAP_COMPACTION("Interior slot: %p\n", slot);
+    LOG_HEAP_COMPACTION() << "Interior slot: " << slot;
     Address slot_address = reinterpret_cast<Address>(slot);
     if (!interiors_) {
       interiors_ = SparseHeapBitmap::Create(slot_address);
@@ -143,8 +143,8 @@
       if (it->value)
         continue;
       Address fixup = to + offset;
-      LOG_HEAP_COMPACTION("Range interior fixup: %p %p %p\n", from + offset,
-                          it->value, fixup);
+      LOG_HEAP_COMPACTION() << "Range interior fixup: " << (from + offset)
+                            << " " << it->value << " " << fixup;
       // Fill in the relocated location of the original slot at |slot|.
       // when the backing store corresponding to |slot| is eventually
       // moved/compacted, it'll update |to + offset| with a pointer to the
@@ -168,7 +168,8 @@
       if (!slot_location) {
         interior_fixups_.Set(slot, to);
       } else {
-        LOG_HEAP_COMPACTION("Redirected slot: %p => %p\n", slot, slot_location);
+        LOG_HEAP_COMPACTION()
+            << "Redirected slot: " << slot << " => " << slot_location;
         slot = slot_location;
       }
     }
@@ -180,9 +181,9 @@
     // The slot's contents may also have been cleared during weak processing;
     // no work to be done in that case either.
     if (UNLIKELY(*slot != from)) {
-      LOG_HEAP_COMPACTION(
-          "No relocation: slot = %p, *slot = %p, from = %p, to = %p\n", slot,
-          *slot, from, to);
+      LOG_HEAP_COMPACTION()
+          << "No relocation: slot = " << slot << ", *slot = " << *slot
+          << ", from = " << from << ", to = " << to;
 #if DCHECK_IS_ON()
       // Verify that the already updated slot is valid, meaning:
       //  - has been cleared.
@@ -219,11 +220,12 @@
 
 #if DEBUG_HEAP_COMPACTION
   void dumpDebugStats() {
-    LOG_HEAP_COMPACTION(
-        "Fixups: pages=%u objects=%u callbacks=%u interior-size=%zu"
-        " interiors-f=%u\n",
-        relocatable_pages_.size(), fixups_.size(), fixup_callbacks_.size(),
-        interiors_ ? interiors_->IntervalCount() : 0, interior_fixups_.size());
+    LOG_HEAP_COMPACTION() << "Fixups: pages=" << relocatable_pages_.size()
+                          << " objects=" << fixups_.size()
+                          << " callbacks=" << fixup_callbacks_.size()
+                          << " interior-size="
+                          << (interiors_ ? interiors_->IntervalCount() : 0,
+                              interior_fixups_.size());
   }
 #endif
 
@@ -296,9 +298,9 @@
   if (!RuntimeEnabledFeatures::HeapCompactionEnabled())
     return false;
 
-  LOG_HEAP_COMPACTION("shouldCompact(): gc=%s count=%zu free=%zu\n",
-                      ThreadState::GcReasonString(reason),
-                      gc_count_since_last_compaction_, free_list_size_);
+  LOG_HEAP_COMPACTION() << "shouldCompact(): gc=" << reason
+                        << " count=" << gc_count_since_last_compaction_
+                        << " free=" << free_list_size_;
   gc_count_since_last_compaction_++;
   // It is only safe to compact during non-conservative GCs.
   // TODO: for the main thread, limit this further to only idle GCs.
@@ -340,7 +342,7 @@
 
 void HeapCompact::Initialize(ThreadState* state) {
   DCHECK(RuntimeEnabledFeatures::HeapCompactionEnabled());
-  LOG_HEAP_COMPACTION("Compacting: free=%zu\n", free_list_size_);
+  LOG_HEAP_COMPACTION() << "Compacting: free=" << free_list_size_;
   do_compact_ = true;
   freed_pages_ = 0;
   freed_size_ = 0;
@@ -371,7 +373,7 @@
 
   compactable_arenas_ = 0;
 #if DEBUG_HEAP_FREELIST
-  LOG_HEAP_FREELIST("Arena residencies: {");
+  std::stringstream stream;
 #endif
   for (int i = BlinkGC::kVector1ArenaIndex; i <= BlinkGC::kHashTableArenaIndex;
        ++i) {
@@ -380,7 +382,9 @@
     size_t free_list_size = arena->FreeListSize();
     total_arena_size += arena_size;
     total_free_list_size += free_list_size;
-    LOG_HEAP_FREELIST("%d: [%zu, %zu], ", i, arena_size, free_list_size);
+#if DEBUG_HEAP_FREELIST
+    stream << i << ": [" << arena_size << ", " << free_list_size << "], ";
+#endif
     // TODO: be more discriminating and consider arena
     // load factor, effectiveness of past compactions etc.
     if (!arena_size)
@@ -388,8 +392,11 @@
     // Mark the arena as compactable.
     compactable_arenas_ |= 0x1u << i;
   }
-  LOG_HEAP_FREELIST("}\nTotal = %zu, Free = %zu\n", total_arena_size,
-                    total_free_list_size);
+#if DEBUG_HEAP_FREELIST
+  LOG_HEAP_FREELIST() << "Arena residencies: {" << stream.str() << "}";
+  LOG_HEAP_FREELIST() << "Total = " << total_arena_size
+                      << ", Free = " << total_free_list_size;
+#endif
 
   // TODO(sof): consider smoothing the reported sizes.
   free_list_size_ = total_free_list_size;
@@ -443,12 +450,12 @@
   object_size_freed_by_heap_compaction.Count(freed_size_ / 1024);
 
 #if DEBUG_LOG_HEAP_COMPACTION_RUNNING_TIME
-  LOG_HEAP_COMPACTION_INTERNAL(
-      "Compaction stats: time=%gms, pages freed=%zu, size=%zu\n",
-      time_for_heap_compaction, freed_pages_, freed_size_);
+  LOG_HEAP_COMPACTION_INTERNAL()
+      << "Compaction stats: time=" << time_for_heap_compaction
+      << "ms, pages freed=" << freed_pages_ << ", size=" << freed_size_;
 #else
-  LOG_HEAP_COMPACTION("Compaction stats: freed pages=%zu size=%zu\n",
-                      freed_pages_, freed_size_);
+  LOG_HEAP_COMPACTION() << "Compaction stats: freed pages=" << freed_pages_
+                        << " size=" << freed_size_;
 #endif
 }
 
diff --git a/third_party/WebKit/Source/platform/heap/HeapCompact.h b/third_party/WebKit/Source/platform/heap/HeapCompact.h
index bc26291..c78cdcf7 100644
--- a/third_party/WebKit/Source/platform/heap/HeapCompact.h
+++ b/third_party/WebKit/Source/platform/heap/HeapCompact.h
@@ -10,7 +10,6 @@
 #include "base/memory/ptr_util.h"
 #include "platform/PlatformExport.h"
 #include "platform/heap/BlinkGC.h"
-#include "platform/wtf/DataLog.h"
 #include "platform/wtf/ThreadingPrimitives.h"
 
 #include <bitset>
@@ -177,34 +176,24 @@
 
 // Logging macros activated by debug switches.
 
-#define LOG_HEAP_COMPACTION_INTERNAL(msg, ...) \
-  DeprecatedDataLogF(msg, ##__VA_ARGS__)
+#define LOG_HEAP_COMPACTION_INTERNAL() DLOG(INFO)
 
 #if DEBUG_HEAP_COMPACTION
-#define LOG_HEAP_COMPACTION(msg, ...) \
-  LOG_HEAP_COMPACTION_INTERNAL(msg, ##__VA_ARGS__)
+#define LOG_HEAP_COMPACTION() LOG_HEAP_COMPACTION_INTERNAL()
 #else
-#define LOG_HEAP_COMPACTION(msg, ...) \
-  do {                                \
-  } while (0)
+#define LOG_HEAP_COMPACTION() EAT_STREAM_PARAMETERS
 #endif
 
 #if DEBUG_HEAP_FREELIST
-#define LOG_HEAP_FREELIST(msg, ...) \
-  LOG_HEAP_COMPACTION_INTERNAL(msg, ##__VA_ARGS__)
+#define LOG_HEAP_FREELIST() LOG_HEAP_COMPACTION_INTERNAL()
 #else
-#define LOG_HEAP_FREELIST(msg, ...) \
-  do {                              \
-  } while (0)
+#define LOG_HEAP_FREELIST() EAT_STREAM_PARAMETERS
 #endif
 
 #if DEBUG_HEAP_FREELIST == 2
-#define LOG_HEAP_FREELIST_VERBOSE(msg, ...) \
-  LOG_HEAP_COMPACTION_INTERNAL(msg, ##__VA_ARGS__)
+#define LOG_HEAP_FREELIST_VERBOSE() LOG_HEAP_COMPACTION_INTERNAL()
 #else
-#define LOG_HEAP_FREELIST_VERBOSE(msg, ...) \
-  do {                                      \
-  } while (0)
+#define LOG_HEAP_FREELIST_VERBOSE() EAT_STREAM_PARAMETERS
 #endif
 
 #endif  // HeapCompact_h
diff --git a/third_party/WebKit/Source/platform/heap/HeapPage.cpp b/third_party/WebKit/Source/platform/heap/HeapPage.cpp
index df87be4..27b5aaa 100644
--- a/third_party/WebKit/Source/platform/heap/HeapPage.cpp
+++ b/third_party/WebKit/Source/platform/heap/HeapPage.cpp
@@ -459,13 +459,15 @@
     size += page->size();
     page = page->Next();
   }
-  LOG_HEAP_FREELIST_VERBOSE("Heap size: %zu (%d)\n", size, arenaIndex());
+  LOG_HEAP_FREELIST_VERBOSE()
+      << "Heap size: " << size << "(" << ArenaIndex() << ")";
   return size;
 }
 
 size_t NormalPageArena::FreeListSize() {
   size_t free_size = free_list_.FreeListSize();
-  LOG_HEAP_FREELIST_VERBOSE("Free size: %zu (%d)\n", freeSize, arenaIndex());
+  LOG_HEAP_FREELIST_VERBOSE()
+      << "Free size: " << free_size << "(" << ArenaIndex() << ")";
   return free_size;
 }
 
@@ -557,13 +559,16 @@
   // Return available pages to the free page pool, decommitting them from
   // the pagefile.
   BasePage* available_pages = context.available_pages_;
+#if DEBUG_HEAP_COMPACTION
+  std::stringstream stream;
+#endif
   while (available_pages) {
     size_t page_size = available_pages->size();
 #if DEBUG_HEAP_COMPACTION
     if (!freed_page_count)
-      LOG_HEAP_COMPACTION("Releasing:");
-    LOG_HEAP_COMPACTION(" [%p, %p]", available_pages,
-                        available_pages + page_size);
+      stream << "Releasing:";
+    stream << " [" << available_pages << ", " << (available_pages + page_size)
+           << "]";
 #endif
     freed_size += page_size;
     freed_page_count++;
@@ -585,8 +590,10 @@
     available_pages->RemoveFromHeap();
     available_pages = static_cast<NormalPage*>(next_page);
   }
+#if DEBUG_HEAP_COMPACTION
   if (freed_page_count)
-    LOG_HEAP_COMPACTION("\n");
+    LOG_HEAP_COMPACTION() << stream.str();
+#endif
   heap.Compaction()->FinishedArenaCompaction(this, freed_page_count,
                                              freed_size);
 
@@ -1201,7 +1208,7 @@
   }
 #if DEBUG_HEAP_FREELIST
   if (free_size) {
-    LOG_HEAP_FREELIST_VERBOSE("FreeList(%p): %zu\n", this, free_size);
+    LOG_HEAP_FREELIST_VERBOSE() << "FreeList(" << this << "): " << free_size;
     for (unsigned i = 0; i < kBlinkPageSizeLog2; ++i) {
       FreeListEntry* entry = free_lists_[i];
       size_t bucket = 0;
@@ -1212,8 +1219,9 @@
         entry = entry->Next();
       }
       if (bucket) {
-        LOG_HEAP_FREELIST_VERBOSE("[%d, %d]: %zu (%zu)\n", 0x1 << i,
-                                  0x1 << (i + 1), bucket, count);
+        LOG_HEAP_FREELIST_VERBOSE()
+            << "[" << (0x1 << i) << ", " << (0x1 << (i + 1)) << "]: " << bucket
+            << " (" << count << ")";
       }
     }
   }
diff --git a/third_party/WebKit/Source/platform/heap/IncrementalMarkingTest.cpp b/third_party/WebKit/Source/platform/heap/IncrementalMarkingTest.cpp
index 5e97310..ef91fa1 100644
--- a/third_party/WebKit/Source/platform/heap/IncrementalMarkingTest.cpp
+++ b/third_party/WebKit/Source/platform/heap/IncrementalMarkingTest.cpp
@@ -23,41 +23,52 @@
 namespace blink {
 namespace incremental_marking_test {
 
-class IncrementalMarkingScope {
+// Base class for initializing worklists.
+class IncrementalMarkingScopeBase {
+ public:
+  IncrementalMarkingScopeBase(ThreadState* thread_state)
+      : thread_state_(thread_state), heap_(thread_state_->Heap()) {
+    heap_.CommitCallbackStacks();
+  }
+
+  ~IncrementalMarkingScopeBase() { heap_.DecommitCallbackStacks(); }
+
+  ThreadHeap& heap() const { return heap_; }
+
+ protected:
+  ThreadState* const thread_state_;
+  ThreadHeap& heap_;
+};
+
+class IncrementalMarkingScope : public IncrementalMarkingScopeBase {
  public:
   explicit IncrementalMarkingScope(ThreadState* thread_state)
-      : gc_forbidden_scope_(thread_state),
-        thread_state_(thread_state),
-        heap_(thread_state_->Heap()),
-        marking_stack_(heap_.MarkingStack()),
+      : IncrementalMarkingScopeBase(thread_state),
+        gc_forbidden_scope_(thread_state),
+        marking_worklist_(heap_.GetMarkingWorklist()),
         not_fully_constructed_marking_stack_(
             heap_.NotFullyConstructedMarkingStack()) {
-    EXPECT_TRUE(marking_stack_->IsEmpty());
+    EXPECT_TRUE(marking_worklist_->IsGlobalEmpty());
     EXPECT_TRUE(not_fully_constructed_marking_stack_->IsEmpty());
-    heap_.CommitCallbackStacks();
     heap_.EnableIncrementalMarkingBarrier();
     thread_state->current_gc_data_.visitor =
         MarkingVisitor::Create(thread_state, MarkingVisitor::kGlobalMarking);
   }
 
   ~IncrementalMarkingScope() {
-    EXPECT_TRUE(marking_stack_->IsEmpty());
+    EXPECT_TRUE(marking_worklist_->IsGlobalEmpty());
     EXPECT_TRUE(not_fully_constructed_marking_stack_->IsEmpty());
     heap_.DisableIncrementalMarkingBarrier();
-    heap_.DecommitCallbackStacks();
   }
 
-  CallbackStack* marking_stack() const { return marking_stack_; }
+  MarkingWorklist* marking_worklist() const { return marking_worklist_; }
   CallbackStack* not_fully_constructed_marking_stack() const {
     return not_fully_constructed_marking_stack_;
   }
-  ThreadHeap& heap() const { return heap_; }
 
  protected:
   ThreadState::GCForbiddenScope gc_forbidden_scope_;
-  ThreadState* const thread_state_;
-  ThreadHeap& heap_;
-  CallbackStack* const marking_stack_;
+  MarkingWorklist* const marking_worklist_;
   CallbackStack* const not_fully_constructed_marking_stack_;
 };
 
@@ -70,7 +81,7 @@
   ExpectWriteBarrierFires(ThreadState* thread_state,
                           std::initializer_list<T*> objects)
       : IncrementalMarkingScope(thread_state), objects_(objects) {
-    EXPECT_TRUE(marking_stack_->IsEmpty());
+    EXPECT_TRUE(marking_worklist_->IsGlobalEmpty());
     for (T* object : objects_) {
       // Ensure that the object is in the normal arena so we can ignore backing
       // objects on the marking stack.
@@ -83,16 +94,16 @@
   }
 
   ~ExpectWriteBarrierFires() {
-    EXPECT_FALSE(marking_stack_->IsEmpty());
+    EXPECT_FALSE(marking_worklist_->IsGlobalEmpty());
     // All headers of objects watched should be marked.
     for (HeapObjectHeader* header : headers_) {
       EXPECT_TRUE(header->IsMarked());
       header->Unmark();
     }
+    MarkingItem item;
     // All objects watched should be on the marking stack.
-    while (!marking_stack_->IsEmpty()) {
-      CallbackStack::Item* item = marking_stack_->Pop();
-      T* obj = reinterpret_cast<T*>(item->Object());
+    while (marking_worklist_->Pop(WorklistTaskId::MainThread, &item)) {
+      T* obj = reinterpret_cast<T*>(item.object);
       // Ignore the backing object.
       if (!ThreadHeap::IsNormalArenaIndex(
               PageFromObject(obj)->Arena()->ArenaIndex())) {
@@ -109,6 +120,7 @@
         objects_.erase(pos);
     }
     EXPECT_TRUE(objects_.empty());
+    EXPECT_TRUE(marking_worklist_->IsGlobalEmpty());
   }
 
  private:
@@ -125,7 +137,7 @@
   ExpectNoWriteBarrierFires(ThreadState* thread_state,
                             std::initializer_list<T*> objects)
       : IncrementalMarkingScope(thread_state), objects_(objects) {
-    EXPECT_TRUE(marking_stack_->IsEmpty());
+    EXPECT_TRUE(marking_worklist_->IsGlobalEmpty());
     for (T* object : objects_) {
       HeapObjectHeader* header = HeapObjectHeader::FromPayload(object);
       headers_.push_back(header);
@@ -134,7 +146,7 @@
   }
 
   ~ExpectNoWriteBarrierFires() {
-    EXPECT_TRUE(marking_stack_->IsEmpty());
+    EXPECT_TRUE(marking_worklist_->IsGlobalEmpty());
     for (size_t i = 0; i < headers_.size(); i++) {
       EXPECT_EQ(was_marked_[i], headers_[i]->IsMarked());
       headers_[i]->Unmark();
@@ -203,12 +215,9 @@
 TEST(IncrementalMarkingTest, ManualWriteBarrierBailoutWhenMarkingIsOff) {
   Object* object = Object::Create();
   ThreadHeap& heap = ThreadState::Current()->Heap();
-  CallbackStack* marking_stack = heap.MarkingStack();
-  EXPECT_TRUE(marking_stack->IsEmpty());
   EXPECT_FALSE(object->IsMarked());
   heap.WriteBarrier(object);
   EXPECT_FALSE(object->IsMarked());
-  EXPECT_TRUE(marking_stack->IsEmpty());
 }
 
 // =============================================================================
@@ -1488,10 +1497,11 @@
   IncrementalMarkingScope scope(ThreadState::Current());
   ObjectRegistry registry;
   RegisteringObject* object = new RegisteringObject(&registry);
-  EXPECT_FALSE(scope.marking_stack()->IsEmpty());
-  CallbackStack::Item* item = scope.marking_stack()->Pop();
+  EXPECT_FALSE(scope.marking_worklist()->IsGlobalEmpty());
+  MarkingItem item;
+  EXPECT_TRUE(scope.marking_worklist()->Pop(WorklistTaskId::MainThread, &item));
   RegisteringObject* recorded_object =
-      reinterpret_cast<RegisteringObject*>(item->Object());
+      reinterpret_cast<RegisteringObject*>(item.object);
   // In this case, the Member write barrier will also add the object to the
   // regular marking stack. The not-fully-constructed object marking stack is
   // only needed when going through custom off-heap data structures that require
@@ -1500,8 +1510,8 @@
   // In this example, there are two more objects on the callback stack: the
   // backing store for which a write barrier triggers after rehashing, and
   // a write barrier for the Member assignment (which might not always happen).
-  scope.marking_stack()->Pop();
-  scope.marking_stack()->Pop();
+  scope.marking_worklist()->Pop(WorklistTaskId::MainThread, &item);
+  scope.marking_worklist()->Pop(WorklistTaskId::MainThread, &item);
   // The mixin object should be on the not-fully-constructed object marking
   // stack.
   EXPECT_FALSE(scope.not_fully_constructed_marking_stack()->IsEmpty());
diff --git a/third_party/WebKit/Source/platform/heap/MarkingVisitor.cpp b/third_party/WebKit/Source/platform/heap/MarkingVisitor.cpp
index 6a70cab6..a1af761 100644
--- a/third_party/WebKit/Source/platform/heap/MarkingVisitor.cpp
+++ b/third_party/WebKit/Source/platform/heap/MarkingVisitor.cpp
@@ -15,7 +15,10 @@
 }
 
 MarkingVisitor::MarkingVisitor(ThreadState* state, MarkingMode marking_mode)
-    : Visitor(state), marking_mode_(marking_mode) {
+    : Visitor(state),
+      marking_worklist_(Heap().GetMarkingWorklist(),
+                        WorklistTaskId::MainThread),
+      marking_mode_(marking_mode) {
   // See ThreadState::runScheduledGC() why we need to already be in a
   // GCForbiddenScope before any safe point is entered.
   DCHECK(state->IsGCForbidden());
@@ -126,19 +129,10 @@
       callback_data);
 }
 
-bool MarkingVisitor::RegisterWeakTable(
-    const void* closure,
-    EphemeronCallback iteration_callback,
-    EphemeronCallback iteration_done_callback) {
-  Heap().RegisterWeakTable(const_cast<void*>(closure), iteration_callback,
-                           iteration_done_callback);
+bool MarkingVisitor::RegisterWeakTable(const void* closure,
+                                       EphemeronCallback iteration_callback) {
+  Heap().RegisterWeakTable(const_cast<void*>(closure), iteration_callback);
   return true;
 }
 
-#if DCHECK_IS_ON()
-bool MarkingVisitor::WeakTableRegistered(const void* closure) {
-  return Heap().WeakTableRegistered(closure);
-}
-#endif
-
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/heap/MarkingVisitor.h b/third_party/WebKit/Source/platform/heap/MarkingVisitor.h
index 0500b0d..208a6ec 100644
--- a/third_party/WebKit/Source/platform/heap/MarkingVisitor.h
+++ b/third_party/WebKit/Source/platform/heap/MarkingVisitor.h
@@ -128,11 +128,7 @@
                                     MovingObjectCallback,
                                     void* callback_data) final;
   bool RegisterWeakTable(const void* closure,
-                         EphemeronCallback iteration_callback,
-                         EphemeronCallback iteration_done_callback) final;
-#if DCHECK_IS_ON()
-  bool WeakTableRegistered(const void* closure) final;
-#endif
+                         EphemeronCallback iteration_callback) final;
   void RegisterWeakCallback(void* closure, WeakCallback) final;
 
  private:
@@ -142,6 +138,7 @@
 
   void ConservativelyMarkHeader(HeapObjectHeader*);
 
+  MarkingWorklist::View marking_worklist_;
   const MarkingMode marking_mode_;
 };
 
@@ -151,6 +148,9 @@
   // A GC should only mark the objects that belong in its heap.
   DCHECK_EQ(State(),
             PageFromObject(header->Payload())->Arena()->GetThreadState());
+  // Never mark free space objects. This would e.g. hint to marking a promptly
+  // freed backing store.
+  DCHECK(!header->IsFree());
 
   return header->TryMark();
 }
@@ -161,8 +161,8 @@
   DCHECK(callback);
 
   if (MarkHeaderNoTracing(header)) {
-    Heap().PushTraceCallback(reinterpret_cast<void*>(header->Payload()),
-                             callback);
+    marking_worklist_.Push(
+        {reinterpret_cast<void*>(header->Payload()), callback});
   }
 }
 
diff --git a/third_party/WebKit/Source/platform/heap/ThreadState.cpp b/third_party/WebKit/Source/platform/heap/ThreadState.cpp
index 80b58c8..dd509600 100644
--- a/third_party/WebKit/Source/platform/heap/ThreadState.cpp
+++ b/third_party/WebKit/Source/platform/heap/ThreadState.cpp
@@ -156,6 +156,7 @@
       object_resurrection_forbidden_(false),
       gc_mixin_marker_(nullptr),
       gc_state_(kNoGCScheduled),
+      gc_phase_(GCPhase::kNone),
       isolate_(nullptr),
       trace_dom_wrappers_(nullptr),
       invalidate_dead_objects_in_wrappers_marking_deque_(nullptr),
@@ -810,6 +811,21 @@
 
 #undef VERIFY_STATE_TRANSITION
 
+void ThreadState::SetGCPhase(GCPhase gc_phase) {
+  switch (gc_phase) {
+    case GCPhase::kNone:
+      DCHECK_EQ(gc_phase_, GCPhase::kSweeping);
+      break;
+    case GCPhase::kMarking:
+      DCHECK_EQ(gc_phase_, GCPhase::kNone);
+      break;
+    case GCPhase::kSweeping:
+      DCHECK_EQ(gc_phase_, GCPhase::kMarking);
+      break;
+  }
+  gc_phase_ = gc_phase;
+}
+
 void ThreadState::RunScheduledGC(BlinkGC::StackState stack_state) {
   DCHECK(CheckThread());
   if (stack_state != BlinkGC::kNoHeapPointersOnStack)
@@ -872,12 +888,15 @@
     // Force setting NoGCScheduled to circumvent checkThread()
     // in setGCState().
     gc_state_ = kNoGCScheduled;
+    SetGCPhase(GCPhase::kSweeping);
+    SetGCPhase(GCPhase::kNone);
     return;
   }
 
   // We have to set the GCState to Sweeping before calling pre-finalizers
   // to disallow a GC during the pre-finalizers.
   SetGCState(kSweeping);
+  SetGCPhase(GCPhase::kSweeping);
 
   // Allocation is allowed during the pre-finalizers and destructors.
   // However, they must not mutate an object graph in a way in which
@@ -1032,6 +1051,7 @@
     }
   }
 
+  SetGCPhase(GCPhase::kNone);
   switch (GcState()) {
     case kSweeping:
       SetGCState(kNoGCScheduled);
@@ -1333,6 +1353,9 @@
 void ThreadState::MarkPhasePrologue(BlinkGC::StackState stack_state,
                                     BlinkGC::MarkingType marking_type,
                                     BlinkGC::GCReason reason) {
+  SetGCPhase(GCPhase::kMarking);
+  Heap().CommitCallbackStacks();
+
   current_gc_data_.stack_state = stack_state;
   current_gc_data_.marking_type = marking_type;
   current_gc_data_.reason = reason;
@@ -1358,7 +1381,6 @@
   if (marking_type == BlinkGC::kTakeSnapshot)
     BlinkGCMemoryDumpProvider::Instance()->ClearProcessDumpForCurrentGC();
 
-  Heap().CommitCallbackStacks();
   if (isolate_ && perform_cleanup_)
     perform_cleanup_(isolate_);
 
diff --git a/third_party/WebKit/Source/platform/heap/ThreadState.h b/third_party/WebKit/Source/platform/heap/ThreadState.h
index 43515f2..d60cfc0 100644
--- a/third_party/WebKit/Source/platform/heap/ThreadState.h
+++ b/third_party/WebKit/Source/platform/heap/ThreadState.h
@@ -155,6 +155,18 @@
     kSweepingAndPreciseGCScheduled,
   };
 
+  // The phase that the GC is in. The GCPhase will not return kNone for mutators
+  // running during incremental marking and lazy sweeping. See SetGCPhase() for
+  // possible state transitions.
+  enum class GCPhase {
+    // GC is doing nothing.
+    kNone,
+    // GC is in marking phase.
+    kMarking,
+    // GC is in sweeping phase.
+    kSweeping,
+  };
+
   // The NoAllocationScope class is used in debug mode to catch unwanted
   // allocations. E.g. allocations during GC.
   class NoAllocationScope final {
@@ -253,7 +265,9 @@
   void WillStartV8GC(BlinkGC::V8GCType);
   void SetGCState(GCState);
   GCState GcState() const { return gc_state_; }
+  void SetGCPhase(GCPhase);
   bool IsInGC() const { return GcState() == kGCRunning; }
+  bool IsMarkingInProgress() const { return gc_phase_ == GCPhase::kMarking; }
   bool IsSweepingInProgress() const {
     return GcState() == kSweeping ||
            GcState() == kSweepingAndPreciseGCScheduled ||
@@ -644,6 +658,7 @@
   GarbageCollectedMixinConstructorMarkerBase* gc_mixin_marker_;
 
   GCState gc_state_;
+  GCPhase gc_phase_;
 
   using PreFinalizerCallback = bool (*)(void*);
   using PreFinalizer = std::pair<void*, PreFinalizerCallback>;
diff --git a/third_party/WebKit/Source/platform/heap/Visitor.h b/third_party/WebKit/Source/platform/heap/Visitor.h
index a5a6a72..e96bdbf 100644
--- a/third_party/WebKit/Source/platform/heap/Visitor.h
+++ b/third_party/WebKit/Source/platform/heap/Visitor.h
@@ -209,15 +209,10 @@
 
   // Used to register ephemeron callbacks.
   virtual bool RegisterWeakTable(const void* closure,
-                                 EphemeronCallback iteration_callback,
-                                 EphemeronCallback iteration_done_callback) {
+                                 EphemeronCallback iteration_callback) {
     return false;
   }
 
-#if DCHECK_IS_ON()
-  virtual bool WeakTableRegistered(const void* closure) { return false; }
-#endif
-
   // |WeakCallback| will usually use |ObjectAliveTrait| to figure out liveness
   // of any children of |closure|. Upon return from the callback all references
   // to dead objects must have been purged. Any operation that extends the
diff --git a/third_party/WebKit/Source/platform/heap/Worklist.h b/third_party/WebKit/Source/platform/heap/Worklist.h
index 30d5b68..45b7b41 100644
--- a/third_party/WebKit/Source/platform/heap/Worklist.h
+++ b/third_party/WebKit/Source/platform/heap/Worklist.h
@@ -23,8 +23,6 @@
 
 namespace blink {
 
-constexpr int kMaxWorkerlistTasks = 8;
-
 // A concurrent worklist based on segments. Each tasks gets private
 // push and pop segments. Empty pop segments are swapped with their
 // corresponding push segments. Full push segments are published to a global
@@ -32,12 +30,10 @@
 //
 // Work stealing is best effort, i.e., there is no way to inform other tasks
 // of the need of items.
-template <typename EntryType,
-          int segment_size,
-          int max_tasks = kMaxWorkerlistTasks>
+template <typename EntryType, int segment_size, int max_tasks = 1>
 class Worklist {
   USING_FAST_MALLOC(Worklist);
-  using WorklistType = Worklist<EntryType, segment_size>;
+  using WorklistType = Worklist<EntryType, segment_size, max_tasks>;
 
  public:
   class View {
@@ -361,7 +357,7 @@
           reinterpret_cast<base::subtle::AtomicWord>(segment));
     }
 
-    base::Lock lock_;
+    mutable base::Lock lock_;
     Segment* top_;
   };
 
diff --git a/third_party/WebKit/Source/platform/heap/WorklistTest.cpp b/third_party/WebKit/Source/platform/heap/WorklistTest.cpp
index 5b05601..cd7a57a 100644
--- a/third_party/WebKit/Source/platform/heap/WorklistTest.cpp
+++ b/third_party/WebKit/Source/platform/heap/WorklistTest.cpp
@@ -18,7 +18,7 @@
 class SomeObject {};
 }  // namespace
 
-using TestWorklist = Worklist<SomeObject*, 64>;
+using TestWorklist = Worklist<SomeObject*, 64 /* entries */, 8 /* tasks */>;
 
 TEST(WorklistTest, SegmentCreate) {
   TestWorklist::Segment segment;
diff --git a/third_party/WebKit/Source/platform/image-decoders/png/PNGImageReader.cpp b/third_party/WebKit/Source/platform/image-decoders/png/PNGImageReader.cpp
index 8d09be5d..73ec772 100644
--- a/third_party/WebKit/Source/platform/image-decoders/png/PNGImageReader.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/png/PNGImageReader.cpp
@@ -116,19 +116,19 @@
 // Pre-conditions before using this:
 // - |reader|.size() >= |read_offset| + |length|
 // - |buffer|.size() >= |length|
-// - |length| <= |kBufferSize|
+// - |length| <= |kPngReadBufferSize|
 //
 // The reason for the last two precondition is that currently the png signature
 // plus IHDR chunk (8B + 25B = 33B) is the largest chunk that is read using this
 // method. If the data is not consecutive, it is stored in |buffer|, which must
 // have the size of (at least) |length|, but there's no need for it to be larger
-// than |kBufferSize|.
-static constexpr size_t kBufferSize = 33;
+// than |kPngReadBufferSize|.
+static constexpr size_t kPngReadBufferSize = 33;
 const png_byte* ReadAsConstPngBytep(const FastSharedBufferReader& reader,
                                     size_t read_offset,
                                     size_t length,
                                     char* buffer) {
-  DCHECK(length <= kBufferSize);
+  DCHECK(length <= kPngReadBufferSize);
   return reinterpret_cast<const png_byte*>(
       reader.GetConsecutiveData(read_offset, length, buffer));
 }
@@ -397,7 +397,7 @@
   // libpng for processing. A frame is registered on the next fcTL chunk or
   // when the IEND chunk is found. This ensures that only complete frames are
   // reported, unless there is an error in the stream.
-  char read_buffer[kBufferSize];
+  char read_buffer[kPngReadBufferSize];
   while (reader.size() >= read_offset_ + 8) {
     const png_byte* chunk =
         ReadAsConstPngBytep(reader, read_offset_, 8, read_buffer);
@@ -513,7 +513,7 @@
   if (decoder_->IsDecodedSizeAvailable())
     return true;
 
-  char read_buffer[kBufferSize];
+  char read_buffer[kPngReadBufferSize];
 
   if (setjmp(JMPBUF(png_)))
     return false;
diff --git a/third_party/WebKit/Source/platform/loader/fetch/FetchContext.h b/third_party/WebKit/Source/platform/loader/fetch/FetchContext.h
index c6f2dc7a..fabe757 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/FetchContext.h
+++ b/third_party/WebKit/Source/platform/loader/fetch/FetchContext.h
@@ -31,8 +31,8 @@
 #ifndef FetchContext_h
 #define FetchContext_h
 
+#include "platform/FrameScheduler.h"
 #include "platform/PlatformExport.h"
-#include "platform/WebFrameScheduler.h"
 #include "platform/heap/Handle.h"
 #include "platform/loader/fetch/FetchInitiatorInfo.h"
 #include "platform/loader/fetch/FetchParameters.h"
@@ -244,12 +244,12 @@
 
   virtual bool IsDetached() const { return false; }
 
-  // Obtains WebFrameScheduler instance that is used in the attached frame.
+  // Obtains FrameScheduler instance that is used in the attached frame.
   // May return nullptr if a frame is not attached or detached.
-  virtual WebFrameScheduler* GetFrameScheduler() const { return nullptr; }
+  virtual FrameScheduler* GetFrameScheduler() const { return nullptr; }
 
   // Returns a task runner intended for loading tasks. Should work even in a
-  // worker context, where WebFrameScheduler doesn't exist, but the returned
+  // worker context, where FrameScheduler doesn't exist, but the returned
   // base::SingleThreadTaskRunner will not work after the context detaches
   // (after Detach() is called, this will return a generic timer suitable for
   // post-detach actions like keepalive requests.
diff --git a/third_party/WebKit/Source/platform/loader/fetch/FetchParameters.cpp b/third_party/WebKit/Source/platform/loader/fetch/FetchParameters.cpp
index db5b03a..6d1ee82 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/FetchParameters.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/FetchParameters.cpp
@@ -122,7 +122,9 @@
   // Synchronous requests should always be max priority, lest they hang the
   // renderer.
   resource_request_.SetPriority(ResourceLoadPriority::kHighest);
-  resource_request_.SetTimeoutInterval(10);
+  if (resource_request_.TimeoutInterval() == INT_MAX) {
+    resource_request_.SetTimeoutInterval(10);
+  }
   options_.synchronous_policy = kRequestSynchronously;
 }
 
diff --git a/third_party/WebKit/Source/platform/loader/fetch/RawResource.cpp b/third_party/WebKit/Source/platform/loader/fetch/RawResource.cpp
index 808c8f4f..bef03a5 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/RawResource.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/RawResource.cpp
@@ -233,6 +233,8 @@
 }
 
 void RawResource::DidDownloadData(int data_length) {
+  downloaded_file_length_ =
+      (downloaded_file_length_ ? *downloaded_file_length_ : 0) + data_length;
   ResourceClientWalker<RawResourceClient> w(Clients());
   while (RawResourceClient* c = w.Next())
     c->DataDownloaded(this, data_length);
diff --git a/third_party/WebKit/Source/platform/loader/fetch/RawResource.h b/third_party/WebKit/Source/platform/loader/fetch/RawResource.h
index 020eb2e..d54b7001 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/RawResource.h
+++ b/third_party/WebKit/Source/platform/loader/fetch/RawResource.h
@@ -30,6 +30,7 @@
 #include "platform/loader/fetch/Resource.h"
 #include "platform/loader/fetch/ResourceClient.h"
 #include "platform/loader/fetch/ResourceLoaderOptions.h"
+#include "platform/wtf/Optional.h"
 #include "public/platform/WebDataConsumerHandle.h"
 
 namespace blink {
@@ -82,6 +83,10 @@
   bool WillFollowRedirect(const ResourceRequest&,
                           const ResourceResponse&) override;
 
+  WTF::Optional<int64_t> DownloadedFileLength() const {
+    return downloaded_file_length_;
+  }
+
  private:
   class RawResourceFactory : public NonTextResourceFactory {
    public:
@@ -114,6 +119,8 @@
                     base::SingleThreadTaskRunner*) override;
   void NotifyFinished() override;
 
+  WTF::Optional<int64_t> downloaded_file_length_;
+
   // Used for preload matching.
   std::unique_ptr<BufferingDataPipeWriter> data_pipe_writer_;
   std::unique_ptr<WebDataConsumerHandle> data_consumer_handle_;
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
index 1ecebca4..51cfbb4 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
@@ -33,6 +33,7 @@
 
 #include "base/time/time.h"
 #include "platform/Histogram.h"
+#include "platform/InstanceCounters.h"
 #include "platform/bindings/ScriptForbiddenScope.h"
 #include "platform/instrumentation/tracing/TraceEvent.h"
 #include "platform/instrumentation/tracing/TracedValue.h"
@@ -294,9 +295,13 @@
       auto_load_images_(true),
       images_enabled_(true),
       allow_stale_resources_(false),
-      image_fetched_(false) {}
+      image_fetched_(false) {
+  InstanceCounters::IncrementCounter(InstanceCounters::kResourceFetcherCounter);
+}
 
-ResourceFetcher::~ResourceFetcher() = default;
+ResourceFetcher::~ResourceFetcher() {
+  InstanceCounters::DecrementCounter(InstanceCounters::kResourceFetcherCounter);
+}
 
 Resource* ResourceFetcher::CachedResource(const KURL& resource_url) const {
   KURL url = MemoryCache::RemoveFragmentIdentifierIfNeeded(resource_url);
@@ -1340,9 +1345,8 @@
       Context().AddWarningConsoleMessage(
           "The resource " + resource->Url().GetString() +
               " was preloaded using link preload but not used within a few " +
-              "seconds from the window's load event. Please make sure it " +
-              "Please make sure it has an appropriate `as` value and it is " +
-              "preloaded intentionally.",
+              "seconds from the window's load event. Please make sure it has " +
+              "an appropriate `as` value and it is preloaded intentionally.",
           FetchContext::kJSSource);
     }
   }
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceLoadScheduler.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceLoadScheduler.cpp
index b43db9d..9172a353 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceLoadScheduler.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceLoadScheduler.cpp
@@ -124,7 +124,7 @@
   ~TrafficMonitor();
 
   // Notified when the ThrottlingState is changed.
-  void OnThrottlingStateChanged(WebFrameScheduler::ThrottlingState);
+  void OnThrottlingStateChanged(FrameScheduler::ThrottlingState);
 
   // Reports resource request completion.
   void Report(const ResourceLoadScheduler::TrafficReportHints&);
@@ -137,8 +137,8 @@
 
   const WeakPersistent<FetchContext> context_;  // NOT OWNED
 
-  WebFrameScheduler::ThrottlingState current_state_ =
-      WebFrameScheduler::ThrottlingState::kStopped;
+  FrameScheduler::ThrottlingState current_state_ =
+      FrameScheduler::ThrottlingState::kStopped;
 
   size_t total_throttled_request_count_ = 0;
   size_t total_throttled_traffic_bytes_ = 0;
@@ -172,7 +172,7 @@
 }
 
 void ResourceLoadScheduler::TrafficMonitor::OnThrottlingStateChanged(
-    WebFrameScheduler::ThrottlingState state) {
+    FrameScheduler::ThrottlingState state) {
   current_state_ = state;
   throttling_state_change_count_++;
 }
@@ -224,7 +224,7 @@
        kMaximumReportSize1G, kReportBucketCount));
 
   switch (current_state_) {
-    case WebFrameScheduler::ThrottlingState::kThrottled:
+    case FrameScheduler::ThrottlingState::kThrottled:
       if (is_main_frame_) {
         request_count_by_circumstance.Count(
             ToSample(ReportCircumstance::kMainframeThrottled));
@@ -240,7 +240,7 @@
       total_throttled_traffic_bytes_ += hints.encoded_data_length();
       total_throttled_decoded_bytes_ += hints.decoded_body_length();
       break;
-    case WebFrameScheduler::ThrottlingState::kNotThrottled:
+    case FrameScheduler::ThrottlingState::kNotThrottled:
       if (is_main_frame_) {
         request_count_by_circumstance.Count(
             ToSample(ReportCircumstance::kMainframeNotThrottled));
@@ -260,7 +260,7 @@
       total_not_throttled_traffic_bytes_ += hints.encoded_data_length();
       total_not_throttled_decoded_bytes_ += hints.decoded_body_length();
       break;
-    case WebFrameScheduler::ThrottlingState::kStopped:
+    case FrameScheduler::ThrottlingState::kStopped:
       break;
   }
 
@@ -396,7 +396,7 @@
     // Initialize TrafficMonitor's state to be |kNotThrottled| so that it
     // reports metrics in a reasonable state group.
     traffic_monitor_->OnThrottlingStateChanged(
-        WebFrameScheduler::ThrottlingState::kNotThrottled);
+        FrameScheduler::ThrottlingState::kNotThrottled);
     return;
   }
 
@@ -418,7 +418,7 @@
 
   is_enabled_ = true;
   scheduler_observer_handle_ = scheduler->AddThrottlingObserver(
-      WebFrameScheduler::ObserverType::kLoader, this);
+      FrameScheduler::ObserverType::kLoader, this);
 }
 
 ResourceLoadScheduler* ResourceLoadScheduler::Create(FetchContext* context) {
@@ -599,11 +599,11 @@
     return true;
 
   if (RuntimeEnabledFeatures::ResourceLoadSchedulerEnabled()) {
-    // If this scheduler is throttled by the associated WebFrameScheduler,
+    // If this scheduler is throttled by the associated FrameScheduler,
     // consider every prioritiy as throttlable.
     const auto state = frame_scheduler_throttling_state_;
-    if (state == WebFrameScheduler::ThrottlingState::kThrottled ||
-        state == WebFrameScheduler::ThrottlingState::kStopped) {
+    if (state == FrameScheduler::ThrottlingState::kThrottled ||
+        state == FrameScheduler::ThrottlingState::kStopped) {
       return true;
     }
   }
@@ -612,26 +612,26 @@
 }
 
 void ResourceLoadScheduler::OnThrottlingStateChanged(
-    WebFrameScheduler::ThrottlingState state) {
+    FrameScheduler::ThrottlingState state) {
   if (traffic_monitor_)
     traffic_monitor_->OnThrottlingStateChanged(state);
 
   frame_scheduler_throttling_state_ = state;
 
   switch (state) {
-    case WebFrameScheduler::ThrottlingState::kThrottled:
+    case FrameScheduler::ThrottlingState::kThrottled:
       if (throttling_history_ == ThrottlingHistory::kInitial)
         throttling_history_ = ThrottlingHistory::kThrottled;
       else if (throttling_history_ == ThrottlingHistory::kNotThrottled)
         throttling_history_ = ThrottlingHistory::kPartiallyThrottled;
       break;
-    case WebFrameScheduler::ThrottlingState::kNotThrottled:
+    case FrameScheduler::ThrottlingState::kNotThrottled:
       if (throttling_history_ == ThrottlingHistory::kInitial)
         throttling_history_ = ThrottlingHistory::kNotThrottled;
       else if (throttling_history_ == ThrottlingHistory::kThrottled)
         throttling_history_ = ThrottlingHistory::kPartiallyThrottled;
       break;
-    case WebFrameScheduler::ThrottlingState::kStopped:
+    case FrameScheduler::ThrottlingState::kStopped:
       throttling_history_ = ThrottlingHistory::kStopped;
       break;
   }
@@ -654,7 +654,7 @@
     // TODO(yhirano): Consider using a unified value.
     const auto num_requests =
         frame_scheduler_throttling_state_ ==
-                WebFrameScheduler::ThrottlingState::kNotThrottled
+                FrameScheduler::ThrottlingState::kNotThrottled
             ? running_throttlable_requests_.size()
             : running_requests_.size();
 
@@ -697,12 +697,12 @@
   size_t limit = kOutstandingUnlimited;
 
   switch (frame_scheduler_throttling_state_) {
-    case WebFrameScheduler::ThrottlingState::kThrottled:
+    case FrameScheduler::ThrottlingState::kThrottled:
       limit = std::min(limit, outstanding_limit_for_throttled_frame_scheduler_);
       break;
-    case WebFrameScheduler::ThrottlingState::kNotThrottled:
+    case FrameScheduler::ThrottlingState::kNotThrottled:
       break;
-    case WebFrameScheduler::ThrottlingState::kStopped:
+    case FrameScheduler::ThrottlingState::kStopped:
       if (RuntimeEnabledFeatures::ResourceLoadSchedulerEnabled())
         limit = 0;
       break;
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceLoadScheduler.h b/third_party/WebKit/Source/platform/loader/fetch/ResourceLoadScheduler.h
index 111d4a49..ce91914a 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceLoadScheduler.h
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceLoadScheduler.h
@@ -6,7 +6,7 @@
 #define ResourceLoadScheduler_h
 
 #include <set>
-#include "platform/WebFrameScheduler.h"
+#include "platform/FrameScheduler.h"
 #include "platform/heap/GarbageCollected.h"
 #include "platform/heap/HeapAllocator.h"
 #include "platform/loader/fetch/Resource.h"
@@ -77,7 +77,7 @@
 //      is less than |kMedium|.
 class PLATFORM_EXPORT ResourceLoadScheduler final
     : public GarbageCollectedFinalized<ResourceLoadScheduler>,
-      public WebFrameScheduler::Observer {
+      public FrameScheduler::Observer {
   WTF_MAKE_NONCOPYABLE(ResourceLoadScheduler);
 
  public:
@@ -194,8 +194,8 @@
   // This function returns false when RendererSideResourceScheduler is disabled.
   bool IsThrottablePriority(ResourceLoadPriority) const;
 
-  // WebFrameScheduler::Observer overrides:
-  void OnThrottlingStateChanged(WebFrameScheduler::ThrottlingState) override;
+  // FrameScheduler::Observer overrides:
+  void OnThrottlingStateChanged(FrameScheduler::ThrottlingState) override;
 
  private:
   class TrafficMonitor;
@@ -293,8 +293,8 @@
     kStopped,
   };
   ThrottlingHistory throttling_history_ = ThrottlingHistory::kInitial;
-  WebFrameScheduler::ThrottlingState frame_scheduler_throttling_state_ =
-      WebFrameScheduler::ThrottlingState::kNotThrottled;
+  FrameScheduler::ThrottlingState frame_scheduler_throttling_state_ =
+      FrameScheduler::ThrottlingState::kNotThrottled;
 
   // Holds clients that haven't been granted, and are waiting for a grant.
   HeapHashMap<ClientId, Member<ClientWithPriority>> pending_request_map_;
@@ -305,11 +305,11 @@
   // Holds an internal class instance to monitor and report traffic.
   std::unique_ptr<TrafficMonitor> traffic_monitor_;
 
-  // Holds FetchContext reference to contact WebFrameScheduler.
+  // Holds FetchContext reference to contact FrameScheduler.
   Member<FetchContext> context_;
 
   // Handle to throttling observer.
-  std::unique_ptr<WebFrameScheduler::ThrottlingObserverHandle>
+  std::unique_ptr<FrameScheduler::ThrottlingObserverHandle>
       scheduler_observer_handle_;
 };
 
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceLoader.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceLoader.cpp
index 583295b..b447b6c4 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceLoader.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceLoader.cpp
@@ -690,8 +690,6 @@
 }
 
 void ResourceLoader::RequestSynchronously(const ResourceRequest& request) {
-  // downloadToFile is not supported for synchronous requests.
-  DCHECK(!request.DownloadToFile());
   DCHECK(loader_);
   DCHECK_EQ(request.Priority(), ResourceLoadPriority::kHighest);
 
@@ -701,8 +699,10 @@
   WebData data_out;
   int64_t encoded_data_length = WebURLLoaderClient::kUnknownEncodedDataLength;
   int64_t encoded_body_length = 0;
+  base::Optional<int64_t> downloaded_file_length;
   loader_->LoadSynchronously(request_in, response_out, error_out, data_out,
-                             encoded_data_length, encoded_body_length);
+                             encoded_data_length, encoded_body_length,
+                             downloaded_file_length);
 
   // A message dispatched while synchronously fetching the resource
   // can bring about the cancellation of this load.
@@ -732,6 +732,11 @@
     });
     resource_->SetResourceBuffer(data_out);
   }
+
+  if (downloaded_file_length) {
+    DCHECK(request.DownloadToFile());
+    DidDownloadData(*downloaded_file_length, encoded_body_length);
+  }
   DidFinishLoading(CurrentTimeTicksInSeconds(), encoded_data_length,
                    encoded_body_length, decoded_body_length, false);
 }
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.h b/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.h
index 01e7bbd..749c057 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.h
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.h
@@ -359,7 +359,7 @@
   }
   bool IsSameDocumentNavigation() const { return is_same_document_navigation_; }
 
-  void SetIsAdResource() { is_ad_resource_ = true; };
+  void SetIsAdResource() { is_ad_resource_ = true; }
   bool IsAdResource() const { return is_ad_resource_; }
 
  private:
diff --git a/third_party/WebKit/Source/platform/loader/testing/MockFetchContext.h b/third_party/WebKit/Source/platform/loader/testing/MockFetchContext.h
index a8a6f32..071fec4d 100644
--- a/third_party/WebKit/Source/platform/loader/testing/MockFetchContext.h
+++ b/third_party/WebKit/Source/platform/loader/testing/MockFetchContext.h
@@ -5,13 +5,13 @@
 #ifndef MockFetchContext_h
 #define MockFetchContext_h
 
-#include "platform/WebFrameScheduler.h"
+#include "platform/FrameScheduler.h"
 #include "platform/exported/WrappedResourceRequest.h"
 #include "platform/loader/fetch/FetchContext.h"
 #include "platform/loader/fetch/FetchParameters.h"
 #include "platform/loader/fetch/ResourceTimingInfo.h"
+#include "platform/scheduler/test/fake_frame_scheduler.h"
 #include "platform/scheduler/test/fake_task_runner.h"
-#include "platform/scheduler/test/fake_web_frame_scheduler.h"
 #include "public/platform/Platform.h"
 #include "public/platform/WebURLLoaderFactory.h"
 
@@ -102,7 +102,7 @@
     return ResourceLoadScheduler::ThrottlingPolicy::kTight;
   }
 
-  WebFrameScheduler* GetFrameScheduler() const override {
+  FrameScheduler* GetFrameScheduler() const override {
     return frame_scheduler_.get();
   }
 
@@ -111,9 +111,10 @@
   }
 
  private:
-  class MockFrameScheduler final : public scheduler::FakeWebFrameScheduler {
+  class MockFrameScheduler final : public scheduler::FakeFrameScheduler {
    public:
-    MockFrameScheduler(scoped_refptr<base::SingleThreadTaskRunner> runner)
+    explicit MockFrameScheduler(
+        scoped_refptr<base::SingleThreadTaskRunner> runner)
         : runner_(std::move(runner)) {}
     scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(
         TaskType) override {
@@ -139,7 +140,7 @@
   enum LoadPolicy load_policy_;
   scoped_refptr<base::SingleThreadTaskRunner> runner_;
   scoped_refptr<const SecurityOrigin> security_origin_;
-  std::unique_ptr<WebFrameScheduler> frame_scheduler_;
+  std::unique_ptr<FrameScheduler> frame_scheduler_;
   std::unique_ptr<WebURLLoaderFactory> url_loader_factory_;
   bool complete_;
   long long transfer_size_;
diff --git a/third_party/WebKit/Source/platform/runtime_enabled_features.json5 b/third_party/WebKit/Source/platform/runtime_enabled_features.json5
index e8477b7..7d9b1cc 100644
--- a/third_party/WebKit/Source/platform/runtime_enabled_features.json5
+++ b/third_party/WebKit/Source/platform/runtime_enabled_features.json5
@@ -590,6 +590,10 @@
     },
     {
       name: "LayoutNG",
+      implied_by: ["LayoutNGBlockFragmentation"],
+    },
+    {
+      name: "LayoutNGBlockFragmentation",
     },
     {
       name: "LayoutNGFragmentCaching",
diff --git a/third_party/WebKit/Source/platform/scheduler/BUILD.gn b/third_party/WebKit/Source/platform/scheduler/BUILD.gn
index ccc7e6ad..342d37b4 100644
--- a/third_party/WebKit/Source/platform/scheduler/BUILD.gn
+++ b/third_party/WebKit/Source/platform/scheduler/BUILD.gn
@@ -100,6 +100,8 @@
     "renderer/deadline_task_runner.h",
     "renderer/frame_origin_type.cc",
     "renderer/frame_origin_type.h",
+    "renderer/frame_scheduler_impl.cc",
+    "renderer/frame_scheduler_impl.h",
     "renderer/frame_status.cc",
     "renderer/frame_status.h",
     "renderer/idle_time_estimator.cc",
@@ -127,8 +129,6 @@
     "renderer/task_cost_estimator.h",
     "renderer/user_model.cc",
     "renderer/user_model.h",
-    "renderer/web_frame_scheduler_impl.cc",
-    "renderer/web_frame_scheduler_impl.h",
     "renderer/web_scoped_virtual_time_pauser.cc",
     "renderer/webthread_impl_for_renderer_scheduler.cc",
     "renderer/webthread_impl_for_renderer_scheduler.h",
@@ -160,11 +160,11 @@
 
   sources = [
     "base/test_task_time_observer.h",
+    "test/fake_frame_scheduler.h",
     "test/fake_page_scheduler.h",
     "test/fake_renderer_scheduler.cc",
     "test/fake_task_runner.cc",
     "test/fake_task_runner.h",
-    "test/fake_web_frame_scheduler.h",
     "test/lazy_thread_controller_for_test.cc",
     "test/lazy_thread_controller_for_test.h",
     "test/renderer_scheduler_test_support.cc",
@@ -206,6 +206,7 @@
     "common/throttling/task_queue_throttler_unittest.cc",
     "renderer/auto_advancing_virtual_time_domain_unittest.cc",
     "renderer/deadline_task_runner_unittest.cc",
+    "renderer/frame_scheduler_impl_unittest.cc",
     "renderer/idle_time_estimator_unittest.cc",
     "renderer/page_scheduler_impl_unittest.cc",
     "renderer/queueing_time_estimator_unittest.cc",
@@ -214,7 +215,6 @@
     "renderer/renderer_scheduler_impl_unittest.cc",
     "renderer/task_cost_estimator_unittest.cc",
     "renderer/user_model_unittest.cc",
-    "renderer/web_frame_scheduler_impl_unittest.cc",
     "renderer/webthread_impl_for_renderer_scheduler_unittest.cc",
     "util/task_duration_metric_reporter_unittest.cc",
     "util/thread_load_tracker_unittest.cc",
diff --git a/third_party/WebKit/Source/platform/scheduler/child/compositor_worker_scheduler.cc b/third_party/WebKit/Source/platform/scheduler/child/compositor_worker_scheduler.cc
index a8fc595..ab125fc 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/compositor_worker_scheduler.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/compositor_worker_scheduler.cc
@@ -98,7 +98,5 @@
   return base::TimeTicks::Now();
 }
 
-void CompositorWorkerScheduler::SetThreadType(WebThreadType thread_type) {}
-
 }  // namespace scheduler
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/scheduler/child/compositor_worker_scheduler.h b/third_party/WebKit/Source/platform/scheduler/child/compositor_worker_scheduler.h
index 5290b92..520b109 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/compositor_worker_scheduler.h
+++ b/third_party/WebKit/Source/platform/scheduler/child/compositor_worker_scheduler.h
@@ -40,7 +40,6 @@
                        base::TimeTicks start,
                        base::TimeTicks end,
                        base::Optional<base::TimeDelta> thread_time) override;
-  void SetThreadType(WebThreadType thread_type) override;
 
   // ChildScheduler:
   scoped_refptr<base::SingleThreadTaskRunner> DefaultTaskRunner() override;
diff --git a/third_party/WebKit/Source/platform/scheduler/child/metrics_helper.cc b/third_party/WebKit/Source/platform/scheduler/child/metrics_helper.cc
index 67143ab..f42d7e58 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/metrics_helper.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/metrics_helper.cc
@@ -80,9 +80,5 @@
   }
 }
 
-void MetricsHelper::SetThreadType(WebThreadType thread_type) {
-  thread_type_ = thread_type;
-}
-
 }  // namespace scheduler
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/scheduler/child/metrics_helper.h b/third_party/WebKit/Source/platform/scheduler/child/metrics_helper.h
index c2586dd..104b3c3 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/metrics_helper.h
+++ b/third_party/WebKit/Source/platform/scheduler/child/metrics_helper.h
@@ -44,8 +44,6 @@
                                base::TimeTicks end_time,
                                base::Optional<base::TimeDelta> thread_time);
 
-  void SetThreadType(WebThreadType thread_type);
-
  protected:
   WebThreadType thread_type_;
 
diff --git a/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler.cc b/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler.cc
index d404f769..d2e2bc0 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler.cc
@@ -21,6 +21,7 @@
 WebThreadImplForWorkerScheduler::WebThreadImplForWorkerScheduler(
     const WebThreadCreationParams& params)
     : thread_(new base::Thread(params.name ? params.name : std::string())),
+      thread_type_(params.thread_type),
       worker_scheduler_proxy_(
           params.frame_scheduler
               ? std::make_unique<WorkerSchedulerProxy>(params.frame_scheduler)
@@ -86,7 +87,7 @@
 
 std::unique_ptr<WorkerScheduler>
 WebThreadImplForWorkerScheduler::CreateWorkerScheduler() {
-  return WorkerScheduler::Create(worker_scheduler_proxy_.get());
+  return WorkerScheduler::Create(thread_type_, worker_scheduler_proxy_.get());
 }
 
 void WebThreadImplForWorkerScheduler::WillDestroyCurrentMessageLoop() {
diff --git a/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler.h b/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler.h
index aad2006..768e93b 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler.h
+++ b/third_party/WebKit/Source/platform/scheduler/child/webthread_impl_for_worker_scheduler.h
@@ -70,6 +70,7 @@
   void ShutdownOnThread(base::WaitableEvent* completion);
 
   std::unique_ptr<base::Thread> thread_;
+  const WebThreadType thread_type_;
   std::unique_ptr<scheduler::WorkerSchedulerProxy> worker_scheduler_proxy_;
   std::unique_ptr<scheduler::WorkerScheduler> worker_scheduler_;
   std::unique_ptr<scheduler::WebSchedulerImpl> web_scheduler_;
diff --git a/third_party/WebKit/Source/platform/scheduler/child/worker_global_scope_scheduler_unittest.cc b/third_party/WebKit/Source/platform/scheduler/child/worker_global_scope_scheduler_unittest.cc
index 8e5d6d9..c771564 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/worker_global_scope_scheduler_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/worker_global_scope_scheduler_unittest.cc
@@ -32,6 +32,7 @@
   WorkerGlobalScopeSchedulerTest()
       : mock_task_runner_(new base::TestSimpleTaskRunner()),
         scheduler_(new WorkerSchedulerImpl(
+            WebThreadType::kTestThread,
             TaskQueueManagerForTest::Create(nullptr,
                                             mock_task_runner_,
                                             &clock_),
diff --git a/third_party/WebKit/Source/platform/scheduler/child/worker_metrics_helper.cc b/third_party/WebKit/Source/platform/scheduler/child/worker_metrics_helper.cc
index 8119322..1de6ffc 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/worker_metrics_helper.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/worker_metrics_helper.cc
@@ -9,8 +9,8 @@
 namespace blink {
 namespace scheduler {
 
-WorkerMetricsHelper::WorkerMetricsHelper()
-    : MetricsHelper(WebThreadType::kUnspecifiedWorkerThread),
+WorkerMetricsHelper::WorkerMetricsHelper(WebThreadType thread_type)
+    : MetricsHelper(thread_type),
       dedicated_worker_per_task_type_duration_reporter_(
           "RendererScheduler.TaskDurationPerTaskType.DedicatedWorker"),
       dedicated_worker_per_task_type_cpu_duration_reporter_(
diff --git a/third_party/WebKit/Source/platform/scheduler/child/worker_metrics_helper.h b/third_party/WebKit/Source/platform/scheduler/child/worker_metrics_helper.h
index fca18ef1..9f11668 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/worker_metrics_helper.h
+++ b/third_party/WebKit/Source/platform/scheduler/child/worker_metrics_helper.h
@@ -16,7 +16,7 @@
 
 class PLATFORM_EXPORT WorkerMetricsHelper : public MetricsHelper {
  public:
-  WorkerMetricsHelper();
+  explicit WorkerMetricsHelper(WebThreadType thread_type);
   ~WorkerMetricsHelper();
 
   void RecordTaskMetrics(WorkerTaskQueue* queue,
@@ -25,8 +25,6 @@
                          base::TimeTicks end_time,
                          base::Optional<base::TimeDelta> thread_time);
 
-  using MetricsHelper::SetThreadType;
-
   void SetParentFrameType(FrameOriginType frame_type);
 
  private:
diff --git a/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler.cc b/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler.cc
index 69b11cd..e01a9a8 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler.cc
@@ -20,9 +20,10 @@
 
 // static
 std::unique_ptr<WorkerScheduler> WorkerScheduler::Create(
+    WebThreadType thread_type,
     WorkerSchedulerProxy* proxy) {
-  return base::WrapUnique(new WorkerSchedulerImpl(
-      TaskQueueManager::TakeOverCurrentThread(), proxy));
+  return std::make_unique<WorkerSchedulerImpl>(
+      thread_type, TaskQueueManager::TakeOverCurrentThread(), proxy);
 }
 
 scoped_refptr<WorkerTaskQueue> WorkerScheduler::CreateTaskRunner() {
diff --git a/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler.h b/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler.h
index e09cfea8..124ef8e 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler.h
+++ b/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler.h
@@ -25,7 +25,8 @@
  public:
   ~WorkerScheduler() override;
 
-  static std::unique_ptr<WorkerScheduler> Create(WorkerSchedulerProxy* proxy);
+  static std::unique_ptr<WorkerScheduler> Create(WebThreadType thread_type,
+                                                 WorkerSchedulerProxy* proxy);
 
   // Blink should use WorkerScheduler::DefaultTaskQueue instead of
   // ChildScheduler::DefaultTaskRunner.
@@ -35,8 +36,6 @@
   // initialization needed such as initializing idle period detection.
   virtual void Init() = 0;
 
-  virtual void SetThreadType(WebThreadType thread_type) = 0;
-
   virtual void OnTaskCompleted(WorkerTaskQueue* worker_task_queue,
                                const TaskQueue::Task& task,
                                base::TimeTicks start,
diff --git a/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_impl.cc b/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_impl.cc
index 62cec39..0065c2e3 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_impl.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_impl.cc
@@ -46,6 +46,7 @@
 }  // namespace
 
 WorkerSchedulerImpl::WorkerSchedulerImpl(
+    WebThreadType thread_type,
     std::unique_ptr<TaskQueueManager> task_queue_manager,
     WorkerSchedulerProxy* proxy)
     : WorkerScheduler(
@@ -61,9 +62,9 @@
       load_tracker_(helper_->NowTicks(),
                     base::BindRepeating(&ReportWorkerTaskLoad),
                     kUnspecifiedWorkerThreadLoadTrackerReportingInterval),
-      throttling_state_(
-          proxy ? proxy->throttling_state()
-                : WebFrameScheduler::ThrottlingState::kNotThrottled),
+      throttling_state_(proxy ? proxy->throttling_state()
+                              : FrameScheduler::ThrottlingState::kNotThrottled),
+      worker_metrics_helper_(thread_type),
       weak_factory_(this) {
   thread_start_time_ = helper_->NowTicks();
   load_tracker_.Resume(thread_start_time_);
@@ -182,13 +183,8 @@
   load_tracker_.RecordTaskTime(start_time_ticks, end_time_ticks);
 }
 
-void WorkerSchedulerImpl::SetThreadType(WebThreadType thread_type) {
-  DCHECK_NE(thread_type, WebThreadType::kMainThread);
-  worker_metrics_helper_.SetThreadType(thread_type);
-}
-
 void WorkerSchedulerImpl::OnThrottlingStateChanged(
-    WebFrameScheduler::ThrottlingState throttling_state) {
+    FrameScheduler::ThrottlingState throttling_state) {
   throttling_state_ = throttling_state;
 }
 
diff --git a/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_impl.h b/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_impl.h
index 2d4be5400..6aa63cd 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_impl.h
+++ b/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_impl.h
@@ -9,7 +9,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
-#include "platform/WebFrameScheduler.h"
+#include "platform/FrameScheduler.h"
 #include "platform/scheduler/base/task_time_observer.h"
 #include "platform/scheduler/child/idle_canceled_delayed_task_sweeper.h"
 #include "platform/scheduler/child/idle_helper.h"
@@ -29,7 +29,8 @@
                                             public IdleHelper::Delegate,
                                             public TaskTimeObserver {
  public:
-  WorkerSchedulerImpl(std::unique_ptr<TaskQueueManager> task_queue_manager,
+  WorkerSchedulerImpl(WebThreadType thread_type,
+                      std::unique_ptr<TaskQueueManager> task_queue_manager,
                       WorkerSchedulerProxy* proxy);
   ~WorkerSchedulerImpl() override;
 
@@ -60,11 +61,9 @@
   SchedulerHelper* GetSchedulerHelperForTesting();
   base::TimeTicks CurrentIdleTaskDeadlineForTesting() const;
 
-  void SetThreadType(WebThreadType thread_type) override;
-
   // Virtual for test.
   virtual void OnThrottlingStateChanged(
-      WebFrameScheduler::ThrottlingState throttling_state);
+      FrameScheduler::ThrottlingState throttling_state);
 
   // Returns the control task queue.  Tasks posted to this queue are executed
   // with the highest priority. Care must be taken to avoid starvation of other
@@ -81,7 +80,7 @@
   void OnIdlePeriodEnded() override {}
   void OnPendingTasksChanged(bool new_state) override {}
 
-  WebFrameScheduler::ThrottlingState throttling_state() const {
+  FrameScheduler::ThrottlingState throttling_state() const {
     return throttling_state_;
   }
 
@@ -96,7 +95,7 @@
   bool initialized_;
   base::TimeTicks thread_start_time_;
   scoped_refptr<WorkerTaskQueue> control_task_queue_;
-  WebFrameScheduler::ThrottlingState throttling_state_;
+  FrameScheduler::ThrottlingState throttling_state_;
 
   WorkerMetricsHelper worker_metrics_helper_;
 
diff --git a/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_impl_unittest.cc b/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_impl_unittest.cc
index ab90389..750551d00 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_impl_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_impl_unittest.cc
@@ -55,7 +55,9 @@
  public:
   WorkerSchedulerImplForTest(std::unique_ptr<TaskQueueManager> manager,
                              base::SimpleTestTickClock* clock_)
-      : WorkerSchedulerImpl(std::move(manager), nullptr),
+      : WorkerSchedulerImpl(WebThreadType::kTestThread,
+                            std::move(manager),
+                            nullptr),
         clock_(clock_),
         timeline_(nullptr) {}
 
diff --git a/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_proxy.cc b/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_proxy.cc
index 8059fa5a..980955fd 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_proxy.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_proxy.cc
@@ -5,14 +5,14 @@
 #include "platform/scheduler/child/worker_scheduler_proxy.h"
 
 #include "platform/scheduler/child/worker_scheduler_impl.h"
-#include "platform/scheduler/renderer/web_frame_scheduler_impl.h"
+#include "platform/scheduler/renderer/frame_scheduler_impl.h"
 
 namespace blink {
 namespace scheduler {
 
-WorkerSchedulerProxy::WorkerSchedulerProxy(WebFrameScheduler* frame_scheduler) {
+WorkerSchedulerProxy::WorkerSchedulerProxy(FrameScheduler* frame_scheduler) {
   throttling_observer_handle_ = frame_scheduler->AddThrottlingObserver(
-      WebFrameScheduler::ObserverType::kWorkerScheduler, this);
+      FrameScheduler::ObserverType::kWorkerScheduler, this);
   parent_frame_type_ = GetFrameOriginType(frame_scheduler);
 }
 
@@ -32,7 +32,7 @@
 }
 
 void WorkerSchedulerProxy::OnThrottlingStateChanged(
-    WebFrameScheduler::ThrottlingState throttling_state) {
+    FrameScheduler::ThrottlingState throttling_state) {
   DCHECK(IsMainThread());
   if (throttling_state_ == throttling_state)
     return;
diff --git a/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_proxy.h b/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_proxy.h
index 4424a703..da75347 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_proxy.h
+++ b/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_proxy.h
@@ -9,8 +9,8 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/single_thread_task_runner.h"
+#include "platform/FrameScheduler.h"
 #include "platform/PlatformExport.h"
-#include "platform/WebFrameScheduler.h"
 #include "platform/scheduler/child/page_visibility_state.h"
 #include "platform/scheduler/renderer/frame_origin_type.h"
 #include "platform/wtf/WTF.h"
@@ -26,20 +26,19 @@
 // on the main thread. It's passed to WorkerScheduler during its construction.
 // Given that DedicatedWorkerThread object outlives worker thread, this class
 // outlives worker thread too.
-class PLATFORM_EXPORT WorkerSchedulerProxy
-    : public WebFrameScheduler::Observer {
+class PLATFORM_EXPORT WorkerSchedulerProxy : public FrameScheduler::Observer {
  public:
-  explicit WorkerSchedulerProxy(WebFrameScheduler* scheduler);
+  explicit WorkerSchedulerProxy(FrameScheduler* scheduler);
   ~WorkerSchedulerProxy() override;
 
   void OnWorkerSchedulerCreated(
       base::WeakPtr<WorkerSchedulerImpl> worker_scheduler);
 
   void OnThrottlingStateChanged(
-      WebFrameScheduler::ThrottlingState throttling_state) override;
+      FrameScheduler::ThrottlingState throttling_state) override;
 
   // Should be accessed only from the main thread or during init.
-  WebFrameScheduler::ThrottlingState throttling_state() const {
+  FrameScheduler::ThrottlingState throttling_state() const {
     DCHECK(IsMainThread() || !initialized_);
     return throttling_state_;
   }
@@ -56,10 +55,10 @@
   // Const after init on the worker thread.
   scoped_refptr<base::SingleThreadTaskRunner> worker_thread_task_runner_;
 
-  WebFrameScheduler::ThrottlingState throttling_state_ =
-      WebFrameScheduler::ThrottlingState::kNotThrottled;
+  FrameScheduler::ThrottlingState throttling_state_ =
+      FrameScheduler::ThrottlingState::kNotThrottled;
 
-  std::unique_ptr<WebFrameScheduler::ThrottlingObserverHandle>
+  std::unique_ptr<FrameScheduler::ThrottlingObserverHandle>
       throttling_observer_handle_;
 
   bool initialized_ = false;
diff --git a/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_proxy_unittest.cc b/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_proxy_unittest.cc
index a8a003b..4002219 100644
--- a/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_proxy_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/child/worker_scheduler_proxy_unittest.cc
@@ -8,9 +8,9 @@
 #include "platform/WaitableEvent.h"
 #include "platform/scheduler/child/webthread_impl_for_worker_scheduler.h"
 #include "platform/scheduler/child/worker_scheduler_impl.h"
+#include "platform/scheduler/renderer/frame_scheduler_impl.h"
 #include "platform/scheduler/renderer/page_scheduler_impl.h"
 #include "platform/scheduler/renderer/renderer_scheduler_impl.h"
-#include "platform/scheduler/renderer/web_frame_scheduler_impl.h"
 #include "platform/scheduler/test/task_queue_manager_for_test.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -25,11 +25,13 @@
   WorkerSchedulerImplForTest(std::unique_ptr<TaskQueueManager> manager,
                              WorkerSchedulerProxy* proxy,
                              WaitableEvent* throtting_state_changed)
-      : WorkerSchedulerImpl(std::move(manager), proxy),
+      : WorkerSchedulerImpl(WebThreadType::kTestThread,
+                            std::move(manager),
+                            proxy),
         throtting_state_changed_(throtting_state_changed) {}
 
   void OnThrottlingStateChanged(
-      WebFrameScheduler::ThrottlingState throttling_state) override {
+      FrameScheduler::ThrottlingState throttling_state) override {
     WorkerSchedulerImpl::OnThrottlingStateChanged(throttling_state);
 
     throtting_state_changed_->Signal();
@@ -44,7 +46,7 @@
 class WebThreadImplForWorkerSchedulerForTest
     : public WebThreadImplForWorkerScheduler {
  public:
-  WebThreadImplForWorkerSchedulerForTest(WebFrameScheduler* frame_scheduler,
+  WebThreadImplForWorkerSchedulerForTest(FrameScheduler* frame_scheduler,
                                          WaitableEvent* throtting_state_changed)
       : WebThreadImplForWorkerScheduler(
             WebThreadCreationParams(WebThreadType::kTestThread)
@@ -67,7 +69,7 @@
 };
 
 std::unique_ptr<WebThreadImplForWorkerSchedulerForTest> CreateWorkerThread(
-    WebFrameScheduler* frame_scheduler,
+    FrameScheduler* frame_scheduler,
     WaitableEvent* throtting_state_changed) {
   std::unique_ptr<WebThreadImplForWorkerSchedulerForTest> thread =
       std::make_unique<WebThreadImplForWorkerSchedulerForTest>(
@@ -92,9 +94,9 @@
             std::make_unique<PageSchedulerImpl>(nullptr,
                                                 renderer_scheduler_.get(),
                                                 false)),
-        frame_scheduler_(page_scheduler_->CreateWebFrameSchedulerImpl(
+        frame_scheduler_(page_scheduler_->CreateFrameSchedulerImpl(
             nullptr,
-            WebFrameScheduler::FrameType::kMainFrame)) {}
+            FrameScheduler::FrameType::kMainFrame)) {}
 
   ~WorkerSchedulerProxyTest() {
     frame_scheduler_.reset();
@@ -108,7 +110,7 @@
 
   std::unique_ptr<RendererSchedulerImpl> renderer_scheduler_;
   std::unique_ptr<PageSchedulerImpl> page_scheduler_;
-  std::unique_ptr<WebFrameSchedulerImpl> frame_scheduler_;
+  std::unique_ptr<FrameSchedulerImpl> frame_scheduler_;
 };
 
 TEST_F(WorkerSchedulerProxyTest, VisibilitySignalReceived) {
@@ -118,17 +120,17 @@
       CreateWorkerThread(frame_scheduler_.get(), &throtting_state_changed);
 
   DCHECK(worker_thread->GetWorkerScheduler()->throttling_state() ==
-         WebFrameScheduler::ThrottlingState::kNotThrottled);
+         FrameScheduler::ThrottlingState::kNotThrottled);
 
   page_scheduler_->SetPageVisible(false);
   throtting_state_changed.Wait();
   DCHECK(worker_thread->GetWorkerScheduler()->throttling_state() ==
-         WebFrameScheduler::ThrottlingState::kThrottled);
+         FrameScheduler::ThrottlingState::kThrottled);
 
   page_scheduler_->SetPageVisible(true);
   throtting_state_changed.Wait();
   DCHECK(worker_thread->GetWorkerScheduler()->throttling_state() ==
-         WebFrameScheduler::ThrottlingState::kNotThrottled);
+         FrameScheduler::ThrottlingState::kNotThrottled);
 
   mock_main_thread_task_runner_->RunUntilIdle();
 }
@@ -142,12 +144,12 @@
       CreateWorkerThread(frame_scheduler_.get(), &throtting_state_changed);
 
   DCHECK(worker_thread->GetWorkerScheduler()->throttling_state() ==
-         WebFrameScheduler::ThrottlingState::kNotThrottled);
+         FrameScheduler::ThrottlingState::kNotThrottled);
 
   page_scheduler_->SetPageVisible(false);
   throtting_state_changed.Wait();
   DCHECK(worker_thread->GetWorkerScheduler()->throttling_state() ==
-         WebFrameScheduler::ThrottlingState::kThrottled);
+         FrameScheduler::ThrottlingState::kThrottled);
 
   frame_scheduler_.reset();
   mock_main_thread_task_runner_->RunUntilIdle();
@@ -163,12 +165,12 @@
       CreateWorkerThread(frame_scheduler_.get(), &throtting_state_changed);
 
   DCHECK(worker_thread->GetWorkerScheduler()->throttling_state() ==
-         WebFrameScheduler::ThrottlingState::kNotThrottled);
+         FrameScheduler::ThrottlingState::kNotThrottled);
 
   page_scheduler_->SetPageVisible(false);
   throtting_state_changed.Wait();
   DCHECK(worker_thread->GetWorkerScheduler()->throttling_state() ==
-         WebFrameScheduler::ThrottlingState::kThrottled);
+         FrameScheduler::ThrottlingState::kThrottled);
 
   worker_thread.reset();
   mock_main_thread_task_runner_->RunUntilIdle();
diff --git a/third_party/WebKit/Source/platform/scheduler/common/throttling/task_queue_throttler.cc b/third_party/WebKit/Source/platform/scheduler/common/throttling/task_queue_throttler.cc
index 3db851f..7d24e2b 100644
--- a/third_party/WebKit/Source/platform/scheduler/common/throttling/task_queue_throttler.cc
+++ b/third_party/WebKit/Source/platform/scheduler/common/throttling/task_queue_throttler.cc
@@ -9,12 +9,11 @@
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/optional.h"
-#include "platform/WebFrameScheduler.h"
 #include "platform/scheduler/base/real_time_domain.h"
 #include "platform/scheduler/common/throttling/budget_pool.h"
 #include "platform/scheduler/common/throttling/throttled_time_domain.h"
+#include "platform/scheduler/renderer/frame_scheduler_impl.h"
 #include "platform/scheduler/renderer/renderer_scheduler_impl.h"
-#include "platform/scheduler/renderer/web_frame_scheduler_impl.h"
 
 namespace blink {
 namespace scheduler {
diff --git a/third_party/WebKit/Source/platform/scheduler/common/throttling/task_queue_throttler_unittest.cc b/third_party/WebKit/Source/platform/scheduler/common/throttling/task_queue_throttler_unittest.cc
index 89f2d16..a44d33b 100644
--- a/third_party/WebKit/Source/platform/scheduler/common/throttling/task_queue_throttler_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/common/throttling/task_queue_throttler_unittest.cc
@@ -18,8 +18,8 @@
 #include "platform/scheduler/base/task_queue_manager.h"
 #include "platform/scheduler/common/throttling/budget_pool.h"
 #include "platform/scheduler/renderer/auto_advancing_virtual_time_domain.h"
+#include "platform/scheduler/renderer/frame_scheduler_impl.h"
 #include "platform/scheduler/renderer/renderer_scheduler_impl.h"
-#include "platform/scheduler/renderer/web_frame_scheduler_impl.h"
 #include "platform/scheduler/test/task_queue_manager_for_test.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/frame_origin_type.cc b/third_party/WebKit/Source/platform/scheduler/renderer/frame_origin_type.cc
index 3fd9e63..59a080c 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/frame_origin_type.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/frame_origin_type.cc
@@ -4,15 +4,16 @@
 
 #include "platform/scheduler/renderer/frame_origin_type.h"
 
-#include "platform/WebFrameScheduler.h"
+#include "base/macros.h"
+#include "platform/FrameScheduler.h"
 
 namespace blink {
 namespace scheduler {
 
-FrameOriginType GetFrameOriginType(WebFrameScheduler* scheduler) {
+FrameOriginType GetFrameOriginType(FrameScheduler* scheduler) {
   DCHECK(scheduler);
 
-  if (scheduler->GetFrameType() == WebFrameScheduler::FrameType::kMainFrame)
+  if (scheduler->GetFrameType() == FrameScheduler::FrameType::kMainFrame)
     return FrameOriginType::kMainFrame;
 
   if (scheduler->IsCrossOrigin()) {
@@ -22,5 +23,20 @@
   }
 }
 
+const char* FrameOriginTypeToString(FrameOriginType origin) {
+  switch (origin) {
+    case FrameOriginType::kMainFrame:
+      return "main-frame";
+    case FrameOriginType::kSameOriginFrame:
+      return "same-origin";
+    case FrameOriginType::kCrossOriginFrame:
+      return "cross-origin";
+    case FrameOriginType::kCount:
+      NOTREACHED();
+  }
+  NOTREACHED();
+  return nullptr;
+}
+
 }  // namespace scheduler
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/frame_origin_type.h b/third_party/WebKit/Source/platform/scheduler/renderer/frame_origin_type.h
index 66c9a1e..a13cbc0f 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/frame_origin_type.h
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/frame_origin_type.h
@@ -6,7 +6,7 @@
 #define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_FRAME_ORIGIN_TYPE_H_
 
 namespace blink {
-class WebFrameScheduler;
+class FrameScheduler;
 
 namespace scheduler {
 
@@ -20,7 +20,9 @@
   kCount = 3
 };
 
-FrameOriginType GetFrameOriginType(WebFrameScheduler* frame_scheduler);
+FrameOriginType GetFrameOriginType(FrameScheduler* frame_scheduler);
+
+const char* FrameOriginTypeToString(FrameOriginType origin);
 
 }  // namespace scheduler
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/frame_scheduler_impl.cc b/third_party/WebKit/Source/platform/scheduler/renderer/frame_scheduler_impl.cc
new file mode 100644
index 0000000..15a3706
--- /dev/null
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/frame_scheduler_impl.cc
@@ -0,0 +1,614 @@
+// Copyright 2015 The Chromium Authors. ();All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/scheduler/renderer/frame_scheduler_impl.h"
+
+#include <memory>
+#include "base/metrics/histogram_macros.h"
+#include "base/trace_event/blame_context.h"
+#include "platform/runtime_enabled_features.h"
+#include "platform/scheduler/base/real_time_domain.h"
+#include "platform/scheduler/base/virtual_time_domain.h"
+#include "platform/scheduler/child/default_params.h"
+#include "platform/scheduler/child/page_visibility_state.h"
+#include "platform/scheduler/child/task_runner_impl.h"
+#include "platform/scheduler/child/worker_scheduler_proxy.h"
+#include "platform/scheduler/common/throttling/budget_pool.h"
+#include "platform/scheduler/renderer/auto_advancing_virtual_time_domain.h"
+#include "platform/scheduler/renderer/page_scheduler_impl.h"
+#include "platform/scheduler/renderer/renderer_scheduler_impl.h"
+#include "platform/scheduler/util/tracing_helper.h"
+#include "public/platform/BlameContext.h"
+#include "public/platform/WebString.h"
+
+namespace blink {
+namespace scheduler {
+
+namespace {
+
+const char* VisibilityStateToString(bool is_visible) {
+  if (is_visible) {
+    return "visible";
+  } else {
+    return "hidden";
+  }
+}
+
+const char* PausedStateToString(bool is_paused) {
+  if (is_paused) {
+    return "paused";
+  } else {
+    return "running";
+  }
+}
+
+const char* FrozenStateToString(bool is_frozen) {
+  if (is_frozen) {
+    return "frozen";
+  } else {
+    return "running";
+  }
+}
+
+}  // namespace
+
+FrameSchedulerImpl::ActiveConnectionHandleImpl::ActiveConnectionHandleImpl(
+    FrameSchedulerImpl* frame_scheduler)
+    : frame_scheduler_(frame_scheduler->GetWeakPtr()) {
+  frame_scheduler->DidOpenActiveConnection();
+}
+
+FrameSchedulerImpl::ActiveConnectionHandleImpl::~ActiveConnectionHandleImpl() {
+  if (frame_scheduler_)
+    frame_scheduler_->DidCloseActiveConnection();
+}
+
+FrameSchedulerImpl::ThrottlingObserverHandleImpl::ThrottlingObserverHandleImpl(
+    FrameSchedulerImpl* frame_scheduler,
+    Observer* observer)
+    : frame_scheduler_(frame_scheduler->GetWeakPtr()), observer_(observer) {}
+
+FrameSchedulerImpl::ThrottlingObserverHandleImpl::
+    ~ThrottlingObserverHandleImpl() {
+  if (frame_scheduler_)
+    frame_scheduler_->RemoveThrottlingObserver(observer_);
+}
+
+FrameSchedulerImpl::FrameSchedulerImpl(
+    RendererSchedulerImpl* renderer_scheduler,
+    PageSchedulerImpl* parent_page_scheduler,
+    base::trace_event::BlameContext* blame_context,
+    FrameScheduler::FrameType frame_type)
+    : frame_type_(frame_type),
+      renderer_scheduler_(renderer_scheduler),
+      parent_page_scheduler_(parent_page_scheduler),
+      blame_context_(blame_context),
+      throttling_state_(FrameScheduler::ThrottlingState::kNotThrottled),
+      frame_visible_(true,
+                     "FrameScheduler.FrameVisible",
+                     this,
+                     &tracing_controller_,
+                     VisibilityStateToString),
+      page_visibility_(kDefaultPageVisibility,
+                       "FrameScheduler.PageVisibility",
+                       this,
+                       &tracing_controller_,
+                       PageVisibilityStateToString),
+      page_frozen_(false,
+                   "FrameScheduler.PageFrozen",
+                   this,
+                   &tracing_controller_,
+                   FrozenStateToString),
+      frame_paused_(false,
+                    "FrameScheduler.FramePaused",
+                    this,
+                    &tracing_controller_,
+                    PausedStateToString),
+      frame_origin_type_(frame_type == FrameType::kMainFrame
+                             ? FrameOriginType::kMainFrame
+                             : FrameOriginType::kSameOriginFrame,
+                         "FrameScheduler.Origin",
+                         this,
+                         &tracing_controller_,
+                         FrameOriginTypeToString),
+      url_tracer_("FrameScheduler.URL", this),
+      task_queue_throttled_(false,
+                            "FrameScheduler.TaskQueueThrottled",
+                            this,
+                            &tracing_controller_,
+                            YesNoStateToString),
+      active_connection_count_(0),
+      weak_factory_(this) {
+  DCHECK_EQ(throttling_state_, CalculateThrottlingState());
+}
+
+namespace {
+
+void CleanUpQueue(MainThreadTaskQueue* queue) {
+  if (!queue)
+    return;
+  queue->DetachFromRendererScheduler();
+  queue->SetFrameScheduler(nullptr);
+  queue->SetBlameContext(nullptr);
+  queue->SetQueuePriority(TaskQueue::QueuePriority::kLowPriority);
+}
+
+}  // namespace
+
+FrameSchedulerImpl::~FrameSchedulerImpl() {
+  weak_factory_.InvalidateWeakPtrs();
+
+  RemoveThrottleableQueueFromBackgroundCPUTimeBudgetPool();
+
+  CleanUpQueue(loading_task_queue_.get());
+  CleanUpQueue(loading_control_task_queue_.get());
+  CleanUpQueue(throttleable_task_queue_.get());
+  CleanUpQueue(deferrable_task_queue_.get());
+  CleanUpQueue(pausable_task_queue_.get());
+  CleanUpQueue(unpausable_task_queue_.get());
+
+  if (parent_page_scheduler_) {
+    parent_page_scheduler_->Unregister(this);
+
+    if (active_connection_count_)
+      parent_page_scheduler_->OnConnectionUpdated();
+  }
+}
+
+void FrameSchedulerImpl::DetachFromPageScheduler() {
+  RemoveThrottleableQueueFromBackgroundCPUTimeBudgetPool();
+
+  parent_page_scheduler_ = nullptr;
+}
+
+void FrameSchedulerImpl::
+    RemoveThrottleableQueueFromBackgroundCPUTimeBudgetPool() {
+  if (!throttleable_task_queue_)
+    return;
+
+  if (!parent_page_scheduler_)
+    return;
+
+  CPUTimeBudgetPool* time_budget_pool =
+      parent_page_scheduler_->BackgroundCPUTimeBudgetPool();
+
+  if (!time_budget_pool)
+    return;
+
+  time_budget_pool->RemoveQueue(renderer_scheduler_->tick_clock()->NowTicks(),
+                                throttleable_task_queue_.get());
+}
+
+std::unique_ptr<FrameScheduler::ThrottlingObserverHandle>
+FrameSchedulerImpl::AddThrottlingObserver(ObserverType type,
+                                          Observer* observer) {
+  DCHECK(observer);
+  observer->OnThrottlingStateChanged(CalculateThrottlingState());
+  loader_observers_.insert(observer);
+  return std::make_unique<ThrottlingObserverHandleImpl>(this, observer);
+}
+
+void FrameSchedulerImpl::RemoveThrottlingObserver(Observer* observer) {
+  DCHECK(observer);
+  const auto found = loader_observers_.find(observer);
+  DCHECK(loader_observers_.end() != found);
+  loader_observers_.erase(found);
+}
+
+void FrameSchedulerImpl::SetFrameVisible(bool frame_visible) {
+  DCHECK(parent_page_scheduler_);
+  if (frame_visible_ == frame_visible)
+    return;
+  UMA_HISTOGRAM_BOOLEAN("RendererScheduler.IPC.FrameVisibility", frame_visible);
+  frame_visible_ = frame_visible;
+  UpdateTaskQueueThrottling();
+}
+
+bool FrameSchedulerImpl::IsFrameVisible() const {
+  return frame_visible_;
+}
+
+void FrameSchedulerImpl::SetCrossOrigin(bool cross_origin) {
+  DCHECK(parent_page_scheduler_);
+  if (frame_origin_type_ == FrameOriginType::kMainFrame) {
+    DCHECK(!cross_origin);
+    return;
+  }
+  if (cross_origin) {
+    frame_origin_type_ = FrameOriginType::kCrossOriginFrame;
+  } else {
+    frame_origin_type_ = FrameOriginType::kSameOriginFrame;
+  }
+  UpdateTaskQueueThrottling();
+}
+
+bool FrameSchedulerImpl::IsCrossOrigin() const {
+  return frame_origin_type_ == FrameOriginType::kCrossOriginFrame;
+}
+
+void FrameSchedulerImpl::TraceUrlChange(const String& url) {
+  url_tracer_.TraceString(url);
+}
+
+FrameScheduler::FrameType FrameSchedulerImpl::GetFrameType() const {
+  return frame_type_;
+}
+
+scoped_refptr<base::SingleThreadTaskRunner> FrameSchedulerImpl::GetTaskRunner(
+    TaskType type) {
+  // TODO(haraken): Optimize the mapping from TaskTypes to task runners.
+  switch (type) {
+    case TaskType::kJavascriptTimer:
+      return TaskRunnerImpl::Create(ThrottleableTaskQueue(), type);
+    case TaskType::kUnspecedLoading:
+    case TaskType::kNetworking:
+      return TaskRunnerImpl::Create(LoadingTaskQueue(), type);
+    case TaskType::kNetworkingControl:
+      return TaskRunnerImpl::Create(LoadingControlTaskQueue(), type);
+    // Throttling following tasks may break existing web pages, so tentatively
+    // these are unthrottled.
+    // TODO(nhiroki): Throttle them again after we're convinced that it's safe
+    // or provide a mechanism that web pages can opt-out it if throttling is not
+    // desirable.
+    case TaskType::kDatabaseAccess:
+    case TaskType::kDOMManipulation:
+    case TaskType::kHistoryTraversal:
+    case TaskType::kEmbed:
+    case TaskType::kCanvasBlobSerialization:
+    case TaskType::kRemoteEvent:
+    case TaskType::kWebSocket:
+    case TaskType::kMicrotask:
+    case TaskType::kUnshippedPortMessage:
+    case TaskType::kFileReading:
+    case TaskType::kPresentation:
+    case TaskType::kSensor:
+    case TaskType::kPerformanceTimeline:
+    case TaskType::kWebGL:
+    case TaskType::kIdleTask:
+    case TaskType::kUnspecedTimer:
+    case TaskType::kMiscPlatformAPI:
+      // TODO(altimin): Move appropriate tasks to throttleable task queue.
+      return TaskRunnerImpl::Create(DeferrableTaskQueue(), type);
+    // PostedMessage can be used for navigation, so we shouldn't defer it
+    // when expecting a user gesture.
+    case TaskType::kPostedMessage:
+    // UserInteraction tasks should be run even when expecting a user gesture.
+    case TaskType::kUserInteraction:
+    // Media events should not be deferred to ensure that media playback is
+    // smooth.
+    case TaskType::kMediaElementEvent:
+    case TaskType::kInternalIndexedDB:
+    case TaskType::kInternalMedia:
+    case TaskType::kInternalMediaRealTime:
+      return TaskRunnerImpl::Create(PausableTaskQueue(), type);
+    case TaskType::kUnthrottled:
+    case TaskType::kInternalTest:
+    case TaskType::kInternalWebCrypto:
+    case TaskType::kInternalIPC:
+      return TaskRunnerImpl::Create(UnpausableTaskQueue(), type);
+    case TaskType::kDeprecatedNone:
+    case TaskType::kCount:
+      NOTREACHED();
+      break;
+  }
+  NOTREACHED();
+  return nullptr;
+}
+
+scoped_refptr<TaskQueue> FrameSchedulerImpl::LoadingTaskQueue() {
+  DCHECK(parent_page_scheduler_);
+  if (!loading_task_queue_) {
+    // TODO(panicker): Avoid adding this queue in RS task_runners_.
+    loading_task_queue_ = renderer_scheduler_->NewLoadingTaskQueue(
+        MainThreadTaskQueue::QueueType::kFrameLoading);
+    loading_task_queue_->SetBlameContext(blame_context_);
+    loading_task_queue_->SetFrameScheduler(this);
+    loading_queue_enabled_voter_ =
+        loading_task_queue_->CreateQueueEnabledVoter();
+    loading_queue_enabled_voter_->SetQueueEnabled(!frame_paused_);
+  }
+  return loading_task_queue_;
+}
+
+scoped_refptr<TaskQueue> FrameSchedulerImpl::LoadingControlTaskQueue() {
+  DCHECK(parent_page_scheduler_);
+  if (!loading_control_task_queue_) {
+    loading_control_task_queue_ = renderer_scheduler_->NewLoadingTaskQueue(
+        MainThreadTaskQueue::QueueType::kFrameLoadingControl);
+    loading_control_task_queue_->SetBlameContext(blame_context_);
+    loading_control_task_queue_->SetFrameScheduler(this);
+    loading_control_queue_enabled_voter_ =
+        loading_control_task_queue_->CreateQueueEnabledVoter();
+    loading_control_queue_enabled_voter_->SetQueueEnabled(!frame_paused_);
+  }
+  return loading_control_task_queue_;
+}
+
+scoped_refptr<TaskQueue> FrameSchedulerImpl::ThrottleableTaskQueue() {
+  DCHECK(parent_page_scheduler_);
+  if (!throttleable_task_queue_) {
+    // TODO(panicker): Avoid adding this queue in RS task_runners_.
+    throttleable_task_queue_ = renderer_scheduler_->NewTaskQueue(
+        MainThreadTaskQueue::QueueCreationParams(
+            MainThreadTaskQueue::QueueType::kFrameThrottleable)
+            .SetCanBeThrottled(true)
+            .SetCanBeStopped(true)
+            .SetCanBeDeferred(true)
+            .SetCanBePaused(true));
+    throttleable_task_queue_->SetBlameContext(blame_context_);
+    throttleable_task_queue_->SetFrameScheduler(this);
+    throttleable_queue_enabled_voter_ =
+        throttleable_task_queue_->CreateQueueEnabledVoter();
+    throttleable_queue_enabled_voter_->SetQueueEnabled(!frame_paused_);
+
+    CPUTimeBudgetPool* time_budget_pool =
+        parent_page_scheduler_->BackgroundCPUTimeBudgetPool();
+    if (time_budget_pool) {
+      time_budget_pool->AddQueue(renderer_scheduler_->tick_clock()->NowTicks(),
+                                 throttleable_task_queue_.get());
+    }
+    UpdateTaskQueueThrottling();
+  }
+  return throttleable_task_queue_;
+}
+
+scoped_refptr<TaskQueue> FrameSchedulerImpl::DeferrableTaskQueue() {
+  DCHECK(parent_page_scheduler_);
+  if (!deferrable_task_queue_) {
+    deferrable_task_queue_ = renderer_scheduler_->NewTaskQueue(
+        MainThreadTaskQueue::QueueCreationParams(
+            MainThreadTaskQueue::QueueType::kFrameThrottleable)
+            .SetCanBeDeferred(true)
+            .SetCanBeStopped(
+                RuntimeEnabledFeatures::StopNonTimersInBackgroundEnabled())
+            .SetCanBePaused(true));
+    deferrable_task_queue_->SetBlameContext(blame_context_);
+    deferrable_task_queue_->SetFrameScheduler(this);
+    deferrable_queue_enabled_voter_ =
+        deferrable_task_queue_->CreateQueueEnabledVoter();
+    deferrable_queue_enabled_voter_->SetQueueEnabled(!frame_paused_);
+  }
+  return deferrable_task_queue_;
+}
+
+scoped_refptr<TaskQueue> FrameSchedulerImpl::PausableTaskQueue() {
+  DCHECK(parent_page_scheduler_);
+  if (!pausable_task_queue_) {
+    pausable_task_queue_ = renderer_scheduler_->NewTaskQueue(
+        MainThreadTaskQueue::QueueCreationParams(
+            MainThreadTaskQueue::QueueType::kFramePausable)
+            .SetCanBeStopped(
+                RuntimeEnabledFeatures::StopNonTimersInBackgroundEnabled())
+            .SetCanBePaused(true));
+    pausable_task_queue_->SetBlameContext(blame_context_);
+    pausable_task_queue_->SetFrameScheduler(this);
+    pausable_queue_enabled_voter_ =
+        pausable_task_queue_->CreateQueueEnabledVoter();
+    pausable_queue_enabled_voter_->SetQueueEnabled(!frame_paused_);
+  }
+  return pausable_task_queue_;
+}
+
+scoped_refptr<TaskQueue> FrameSchedulerImpl::UnpausableTaskQueue() {
+  DCHECK(parent_page_scheduler_);
+  if (!unpausable_task_queue_) {
+    unpausable_task_queue_ = renderer_scheduler_->NewTaskQueue(
+        MainThreadTaskQueue::QueueCreationParams(
+            MainThreadTaskQueue::QueueType::kFrameUnpausable));
+    unpausable_task_queue_->SetBlameContext(blame_context_);
+    unpausable_task_queue_->SetFrameScheduler(this);
+  }
+  return unpausable_task_queue_;
+}
+
+scoped_refptr<TaskQueue> FrameSchedulerImpl::ControlTaskQueue() {
+  DCHECK(parent_page_scheduler_);
+  return renderer_scheduler_->ControlTaskQueue();
+}
+
+blink::PageScheduler* FrameSchedulerImpl::GetPageScheduler() const {
+  return parent_page_scheduler_;
+}
+
+void FrameSchedulerImpl::DidStartProvisionalLoad(bool is_main_frame) {
+  renderer_scheduler_->DidStartProvisionalLoad(is_main_frame);
+}
+
+void FrameSchedulerImpl::DidCommitProvisionalLoad(
+    bool is_web_history_inert_commit,
+    bool is_reload,
+    bool is_main_frame) {
+  renderer_scheduler_->DidCommitProvisionalLoad(is_web_history_inert_commit,
+                                                is_reload, is_main_frame);
+}
+
+WebScopedVirtualTimePauser FrameSchedulerImpl::CreateWebScopedVirtualTimePauser(
+    WebScopedVirtualTimePauser::VirtualTaskDuration duration) {
+  return WebScopedVirtualTimePauser(renderer_scheduler_, duration);
+}
+
+void FrameSchedulerImpl::DidOpenActiveConnection() {
+  ++active_connection_count_;
+  if (parent_page_scheduler_)
+    parent_page_scheduler_->OnConnectionUpdated();
+}
+
+void FrameSchedulerImpl::DidCloseActiveConnection() {
+  DCHECK_GT(active_connection_count_, 0);
+  --active_connection_count_;
+  if (parent_page_scheduler_)
+    parent_page_scheduler_->OnConnectionUpdated();
+}
+
+void FrameSchedulerImpl::AsValueInto(
+    base::trace_event::TracedValue* state) const {
+  state->SetBoolean("frame_visible", frame_visible_);
+  state->SetBoolean("page_visible",
+                    page_visibility_ == PageVisibilityState::kVisible);
+  state->SetBoolean("cross_origin", IsCrossOrigin());
+  state->SetString("frame_type",
+                   frame_type_ == FrameScheduler::FrameType::kMainFrame
+                       ? "MainFrame"
+                       : "Subframe");
+  if (loading_task_queue_) {
+    state->SetString("loading_task_queue",
+                     PointerToString(loading_task_queue_.get()));
+  }
+  if (loading_control_task_queue_) {
+    state->SetString("loading_control_task_queue",
+                     PointerToString(loading_control_task_queue_.get()));
+  }
+  if (throttleable_task_queue_) {
+    state->SetString("throttleable_task_queue",
+                     PointerToString(throttleable_task_queue_.get()));
+  }
+  if (deferrable_task_queue_) {
+    state->SetString("deferrable_task_queue",
+                     PointerToString(deferrable_task_queue_.get()));
+  }
+  if (pausable_task_queue_) {
+    state->SetString("pausable_task_queue",
+                     PointerToString(pausable_task_queue_.get()));
+  }
+  if (unpausable_task_queue_) {
+    state->SetString("unpausable_task_queue",
+                     PointerToString(unpausable_task_queue_.get()));
+  }
+  if (blame_context_) {
+    state->BeginDictionary("blame_context");
+    state->SetString(
+        "id_ref",
+        PointerToString(reinterpret_cast<void*>(blame_context_->id())));
+    state->SetString("scope", blame_context_->scope());
+    state->EndDictionary();
+  }
+}
+
+void FrameSchedulerImpl::SetPageVisibility(
+    PageVisibilityState page_visibility) {
+  DCHECK(parent_page_scheduler_);
+  if (page_visibility_ == page_visibility)
+    return;
+  page_visibility_ = page_visibility;
+  if (page_visibility_ == PageVisibilityState::kVisible)
+    page_frozen_ = false;  // visible page must not be frozen.
+  // TODO(altimin): Avoid having to call all these methods here.
+  UpdateTaskQueues();
+  UpdateTaskQueueThrottling();
+  UpdateThrottlingState();
+}
+
+bool FrameSchedulerImpl::IsPageVisible() const {
+  return page_visibility_ == PageVisibilityState::kVisible;
+}
+
+void FrameSchedulerImpl::SetPaused(bool frame_paused) {
+  DCHECK(parent_page_scheduler_);
+  if (frame_paused_ == frame_paused)
+    return;
+
+  frame_paused_ = frame_paused;
+  UpdateTaskQueues();
+}
+
+void FrameSchedulerImpl::SetPageFrozen(bool frozen) {
+  if (frozen == page_frozen_)
+    return;
+  DCHECK(page_visibility_ == PageVisibilityState::kHidden);
+  page_frozen_ = frozen;
+  UpdateTaskQueues();
+  UpdateThrottlingState();
+}
+
+void FrameSchedulerImpl::UpdateTaskQueues() {
+  // Per-frame (stoppable) task queues will be stopped after 5mins in
+  // background. They will be resumed when the page is visible.
+  UpdateTaskQueue(throttleable_task_queue_,
+                  throttleable_queue_enabled_voter_.get());
+  UpdateTaskQueue(loading_task_queue_, loading_queue_enabled_voter_.get());
+  UpdateTaskQueue(loading_control_task_queue_,
+                  loading_control_queue_enabled_voter_.get());
+  UpdateTaskQueue(deferrable_task_queue_,
+                  deferrable_queue_enabled_voter_.get());
+  UpdateTaskQueue(pausable_task_queue_, pausable_queue_enabled_voter_.get());
+}
+
+void FrameSchedulerImpl::UpdateTaskQueue(
+    const scoped_refptr<MainThreadTaskQueue>& queue,
+    TaskQueue::QueueEnabledVoter* voter) {
+  if (!queue || !voter)
+    return;
+  bool queue_paused = frame_paused_ && queue->CanBePaused();
+  bool queue_frozen = page_frozen_ && queue->CanBeStopped();
+  voter->SetQueueEnabled(!queue_paused && !queue_frozen);
+}
+
+void FrameSchedulerImpl::UpdateThrottlingState() {
+  FrameScheduler::ThrottlingState throttling_state = CalculateThrottlingState();
+  if (throttling_state == throttling_state_)
+    return;
+  throttling_state_ = throttling_state;
+  for (auto observer : loader_observers_)
+    observer->OnThrottlingStateChanged(throttling_state_);
+}
+
+FrameScheduler::ThrottlingState FrameSchedulerImpl::CalculateThrottlingState()
+    const {
+  if (RuntimeEnabledFeatures::StopLoadingInBackgroundEnabled() &&
+      page_frozen_) {
+    DCHECK(page_visibility_ == PageVisibilityState::kHidden);
+    return FrameScheduler::ThrottlingState::kStopped;
+  }
+  if (page_visibility_ == PageVisibilityState::kHidden)
+    return FrameScheduler::ThrottlingState::kThrottled;
+  return FrameScheduler::ThrottlingState::kNotThrottled;
+}
+
+void FrameSchedulerImpl::OnFirstMeaningfulPaint() {
+  renderer_scheduler_->OnFirstMeaningfulPaint();
+}
+
+std::unique_ptr<FrameScheduler::ActiveConnectionHandle>
+FrameSchedulerImpl::OnActiveConnectionCreated() {
+  return std::make_unique<FrameSchedulerImpl::ActiveConnectionHandleImpl>(this);
+}
+
+bool FrameSchedulerImpl::ShouldThrottleTimers() const {
+  if (page_visibility_ == PageVisibilityState::kHidden)
+    return true;
+  return RuntimeEnabledFeatures::TimerThrottlingForHiddenFramesEnabled() &&
+         !frame_visible_ && IsCrossOrigin();
+}
+
+void FrameSchedulerImpl::UpdateTaskQueueThrottling() {
+  // Before we initialize a trottleable task queue, |task_queue_throttled_|
+  // stays false and this function ensures it indicates whether are we holding
+  // a queue reference for throttler or not.
+  // Don't modify that value neither amend the reference counter anywhere else.
+  if (!throttleable_task_queue_)
+    return;
+  bool should_throttle = ShouldThrottleTimers();
+  if (task_queue_throttled_ == should_throttle)
+    return;
+  task_queue_throttled_ = should_throttle;
+
+  if (should_throttle) {
+    renderer_scheduler_->task_queue_throttler()->IncreaseThrottleRefCount(
+        throttleable_task_queue_.get());
+  } else {
+    renderer_scheduler_->task_queue_throttler()->DecreaseThrottleRefCount(
+        throttleable_task_queue_.get());
+  }
+}
+
+base::WeakPtr<FrameSchedulerImpl> FrameSchedulerImpl::GetWeakPtr() {
+  return weak_factory_.GetWeakPtr();
+}
+
+bool FrameSchedulerImpl::IsExemptFromBudgetBasedThrottling() const {
+  return has_active_connection();
+}
+
+}  // namespace scheduler
+}  // namespace blink
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/frame_scheduler_impl.h b/third_party/WebKit/Source/platform/scheduler/renderer/frame_scheduler_impl.h
new file mode 100644
index 0000000..d3a5f1b
--- /dev/null
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/frame_scheduler_impl.h
@@ -0,0 +1,186 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_FRAME_SCHEDULER_IMPL_H_
+#define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_FRAME_SCHEDULER_IMPL_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/trace_event/trace_event.h"
+#include "platform/FrameScheduler.h"
+#include "platform/PlatformExport.h"
+#include "platform/scheduler/base/task_queue.h"
+#include "platform/scheduler/child/page_visibility_state.h"
+#include "platform/scheduler/child/worker_scheduler_proxy.h"
+#include "platform/scheduler/renderer/frame_origin_type.h"
+#include "platform/scheduler/util/tracing_helper.h"
+
+namespace base {
+namespace trace_event {
+class BlameContext;
+class TracedValue;
+}  // namespace trace_event
+}  // namespace base
+
+namespace blink {
+namespace scheduler {
+
+class MainThreadTaskQueue;
+class PageSchedulerImpl;
+class RendererSchedulerImpl;
+class TaskQueue;
+
+namespace renderer_scheduler_impl_unittest {
+class RendererSchedulerImplTest;
+}
+
+namespace frame_scheduler_impl_unittest {
+class FrameSchedulerImplTest;
+}
+
+namespace page_scheduler_impl_unittest {
+class PageSchedulerImplTest;
+}
+
+class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler {
+ public:
+  FrameSchedulerImpl(RendererSchedulerImpl* renderer_scheduler,
+                     PageSchedulerImpl* parent_page_scheduler,
+                     base::trace_event::BlameContext* blame_context,
+                     FrameScheduler::FrameType frame_type);
+
+  ~FrameSchedulerImpl() override;
+
+  // FrameScheduler implementation:
+  std::unique_ptr<ThrottlingObserverHandle> AddThrottlingObserver(
+      ObserverType,
+      Observer*) override;
+  void SetFrameVisible(bool frame_visible) override;
+  bool IsFrameVisible() const override;
+  bool IsPageVisible() const override;
+  void SetPaused(bool frame_paused) override;
+  void SetPageFrozen(bool) override;
+
+  void SetCrossOrigin(bool cross_origin) override;
+  bool IsCrossOrigin() const override;
+  void TraceUrlChange(const String& url) override;
+  FrameScheduler::FrameType GetFrameType() const override;
+  scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(TaskType) override;
+  PageScheduler* GetPageScheduler() const override;
+  void DidStartProvisionalLoad(bool is_main_frame) override;
+  void DidCommitProvisionalLoad(bool is_web_history_inert_commit,
+                                bool is_reload,
+                                bool is_main_frame) override;
+  WebScopedVirtualTimePauser CreateWebScopedVirtualTimePauser(
+      WebScopedVirtualTimePauser::VirtualTaskDuration duration) override;
+  void OnFirstMeaningfulPaint() override;
+  std::unique_ptr<ActiveConnectionHandle> OnActiveConnectionCreated() override;
+  void AsValueInto(base::trace_event::TracedValue* state) const;
+  bool IsExemptFromBudgetBasedThrottling() const override;
+
+  scoped_refptr<TaskQueue> ControlTaskQueue();
+  void SetPageVisibility(PageVisibilityState page_visibility);
+
+  bool has_active_connection() const { return active_connection_count_; }
+
+  void OnTraceLogEnabled() { tracing_controller_.OnTraceLogEnabled(); }
+
+ private:
+  friend class PageSchedulerImpl;
+  friend class renderer_scheduler_impl_unittest::RendererSchedulerImplTest;
+  friend class frame_scheduler_impl_unittest::FrameSchedulerImplTest;
+  friend class page_scheduler_impl_unittest::PageSchedulerImplTest;
+
+  class ActiveConnectionHandleImpl : public ActiveConnectionHandle {
+   public:
+    ActiveConnectionHandleImpl(FrameSchedulerImpl* frame_scheduler);
+    ~ActiveConnectionHandleImpl() override;
+
+   private:
+    base::WeakPtr<FrameSchedulerImpl> frame_scheduler_;
+
+    DISALLOW_COPY_AND_ASSIGN(ActiveConnectionHandleImpl);
+  };
+
+  class ThrottlingObserverHandleImpl : public ThrottlingObserverHandle {
+   public:
+    ThrottlingObserverHandleImpl(FrameSchedulerImpl* frame_scheduler,
+                                 Observer* observer);
+    ~ThrottlingObserverHandleImpl() override;
+
+   private:
+    base::WeakPtr<FrameSchedulerImpl> frame_scheduler_;
+    Observer* observer_;
+
+    DISALLOW_COPY_AND_ASSIGN(ThrottlingObserverHandleImpl);
+  };
+
+  void DetachFromPageScheduler();
+  void RemoveThrottleableQueueFromBackgroundCPUTimeBudgetPool();
+  void ApplyPolicyToThrottleableQueue();
+  bool ShouldThrottleTimers() const;
+  void UpdateTaskQueueThrottling();
+  FrameScheduler::ThrottlingState CalculateThrottlingState() const;
+  void UpdateThrottlingState();
+  void RemoveThrottlingObserver(Observer* observer);
+  void UpdateTaskQueues();
+  void UpdateTaskQueue(const scoped_refptr<MainThreadTaskQueue>& queue,
+                       TaskQueue::QueueEnabledVoter* voter);
+
+  void DidOpenActiveConnection();
+  void DidCloseActiveConnection();
+
+  scoped_refptr<TaskQueue> LoadingTaskQueue();
+  scoped_refptr<TaskQueue> LoadingControlTaskQueue();
+  scoped_refptr<TaskQueue> ThrottleableTaskQueue();
+  scoped_refptr<TaskQueue> DeferrableTaskQueue();
+  scoped_refptr<TaskQueue> PausableTaskQueue();
+  scoped_refptr<TaskQueue> UnpausableTaskQueue();
+
+  base::WeakPtr<FrameSchedulerImpl> GetWeakPtr();
+
+  const FrameScheduler::FrameType frame_type_;
+
+  TraceableVariableController tracing_controller_;
+  scoped_refptr<MainThreadTaskQueue> loading_task_queue_;
+  scoped_refptr<MainThreadTaskQueue> loading_control_task_queue_;
+  scoped_refptr<MainThreadTaskQueue> throttleable_task_queue_;
+  scoped_refptr<MainThreadTaskQueue> deferrable_task_queue_;
+  scoped_refptr<MainThreadTaskQueue> pausable_task_queue_;
+  scoped_refptr<MainThreadTaskQueue> unpausable_task_queue_;
+  std::unique_ptr<TaskQueue::QueueEnabledVoter> loading_queue_enabled_voter_;
+  std::unique_ptr<TaskQueue::QueueEnabledVoter>
+      loading_control_queue_enabled_voter_;
+  std::unique_ptr<TaskQueue::QueueEnabledVoter>
+      throttleable_queue_enabled_voter_;
+  std::unique_ptr<TaskQueue::QueueEnabledVoter> deferrable_queue_enabled_voter_;
+  std::unique_ptr<TaskQueue::QueueEnabledVoter> pausable_queue_enabled_voter_;
+  RendererSchedulerImpl* renderer_scheduler_;       // NOT OWNED
+  PageSchedulerImpl* parent_page_scheduler_;        // NOT OWNED
+  base::trace_event::BlameContext* blame_context_;  // NOT OWNED
+  std::set<Observer*> loader_observers_;            // NOT OWNED
+  FrameScheduler::ThrottlingState throttling_state_;
+  TraceableState<bool, kTracingCategoryNameInfo> frame_visible_;
+  TraceableState<PageVisibilityState, kTracingCategoryNameInfo>
+      page_visibility_;
+  TraceableState<bool, kTracingCategoryNameInfo> page_frozen_;
+  TraceableState<bool, kTracingCategoryNameInfo> frame_paused_;
+  TraceableState<FrameOriginType, kTracingCategoryNameInfo> frame_origin_type_;
+  StateTracer<kTracingCategoryNameInfo> url_tracer_;
+  // |task_queue_throttled_| is false if |throttleable_task_queue_| is absent.
+  TraceableState<bool, kTracingCategoryNameDebug> task_queue_throttled_;
+  int active_connection_count_;
+
+  base::WeakPtrFactory<FrameSchedulerImpl> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(FrameSchedulerImpl);
+};
+
+}  // namespace scheduler
+}  // namespace blink
+
+#endif  // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_FRAME_SCHEDULER_IMPL_H_
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/frame_scheduler_impl_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/frame_scheduler_impl_unittest.cc
new file mode 100644
index 0000000..88d3719
--- /dev/null
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/frame_scheduler_impl_unittest.cc
@@ -0,0 +1,435 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/scheduler/renderer/frame_scheduler_impl.h"
+
+#include <memory>
+
+#include "base/callback.h"
+#include "base/location.h"
+#include "base/test/simple_test_tick_clock.h"
+#include "components/viz/test/ordered_simple_task_runner.h"
+#include "platform/WebTaskRunner.h"
+#include "platform/runtime_enabled_features.h"
+#include "platform/scheduler/renderer/page_scheduler_impl.h"
+#include "platform/scheduler/renderer/renderer_scheduler_impl.h"
+#include "platform/scheduler/test/task_queue_manager_for_test.h"
+#include "platform/testing/runtime_enabled_features_test_helpers.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+namespace scheduler {
+// To avoid symbol collisions in jumbo builds.
+namespace frame_scheduler_impl_unittest {
+
+class FrameSchedulerImplTest : public ::testing::Test {
+ public:
+  FrameSchedulerImplTest() = default;
+  ~FrameSchedulerImplTest() override = default;
+
+  void SetUp() override {
+    clock_.Advance(base::TimeDelta::FromMicroseconds(5000));
+    mock_task_runner_ =
+        base::MakeRefCounted<cc::OrderedSimpleTaskRunner>(&clock_, true);
+    scheduler_.reset(new RendererSchedulerImpl(
+        TaskQueueManagerForTest::Create(nullptr, mock_task_runner_, &clock_),
+        base::nullopt));
+    page_scheduler_.reset(
+        new PageSchedulerImpl(nullptr, scheduler_.get(), false));
+    frame_scheduler_ = page_scheduler_->CreateFrameSchedulerImpl(
+        nullptr, FrameScheduler::FrameType::kSubframe);
+  }
+
+  void TearDown() override {
+    frame_scheduler_.reset();
+    page_scheduler_.reset();
+    scheduler_->Shutdown();
+    scheduler_.reset();
+  }
+
+ protected:
+  scoped_refptr<TaskQueue> throttleable_task_queue() {
+    return frame_scheduler_->throttleable_task_queue_;
+  }
+
+  void LazyInitThrottleableTaskQueue() {
+    EXPECT_FALSE(throttleable_task_queue());
+    frame_scheduler_->ThrottleableTaskQueue();
+    EXPECT_TRUE(throttleable_task_queue());
+  }
+
+  scoped_refptr<TaskQueue> ThrottleableTaskQueue() {
+    return frame_scheduler_->ThrottleableTaskQueue();
+  }
+
+  scoped_refptr<TaskQueue> LoadingTaskQueue() {
+    return frame_scheduler_->LoadingTaskQueue();
+  }
+
+  scoped_refptr<TaskQueue> DeferrableTaskQueue() {
+    return frame_scheduler_->DeferrableTaskQueue();
+  }
+
+  scoped_refptr<TaskQueue> PausableTaskQueue() {
+    return frame_scheduler_->PausableTaskQueue();
+  }
+
+  scoped_refptr<TaskQueue> UnpausableTaskQueue() {
+    return frame_scheduler_->UnpausableTaskQueue();
+  }
+
+  bool IsThrottled() {
+    EXPECT_TRUE(throttleable_task_queue());
+    return scheduler_->task_queue_throttler()->IsThrottled(
+        throttleable_task_queue().get());
+  }
+
+  base::SimpleTestTickClock clock_;
+  scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
+  std::unique_ptr<RendererSchedulerImpl> scheduler_;
+  std::unique_ptr<PageSchedulerImpl> page_scheduler_;
+  std::unique_ptr<FrameSchedulerImpl> frame_scheduler_;
+};
+
+namespace {
+
+class MockThrottlingObserver final : public FrameScheduler::Observer {
+ public:
+  MockThrottlingObserver()
+      : throttled_count_(0u), not_throttled_count_(0u), stopped_count_(0u) {}
+
+  void CheckObserverState(size_t throttled_count_expectation,
+                          size_t not_throttled_count_expectation,
+                          size_t stopped_count_expectation) {
+    EXPECT_EQ(throttled_count_expectation, throttled_count_);
+    EXPECT_EQ(not_throttled_count_expectation, not_throttled_count_);
+    EXPECT_EQ(stopped_count_expectation, stopped_count_);
+  }
+
+  void OnThrottlingStateChanged(
+      FrameScheduler::ThrottlingState state) override {
+    switch (state) {
+      case FrameScheduler::ThrottlingState::kThrottled:
+        throttled_count_++;
+        break;
+      case FrameScheduler::ThrottlingState::kNotThrottled:
+        not_throttled_count_++;
+        break;
+      case FrameScheduler::ThrottlingState::kStopped:
+        stopped_count_++;
+        break;
+        // We should not have another state, and compiler checks it.
+    }
+  }
+
+ private:
+  size_t throttled_count_;
+  size_t not_throttled_count_;
+  size_t stopped_count_;
+};
+
+void IncrementCounter(int* counter) {
+  ++*counter;
+}
+
+}  // namespace
+
+// Throttleable task queue is initialized lazily, so there're two scenarios:
+// - Task queue created first and throttling decision made later;
+// - Scheduler receives relevant signals to make a throttling decision but
+//   applies one once task queue gets created.
+// We test both (ExplicitInit/LazyInit) of them.
+
+TEST_F(FrameSchedulerImplTest, PageVisible) {
+  ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(true);
+  EXPECT_FALSE(throttleable_task_queue());
+  LazyInitThrottleableTaskQueue();
+  EXPECT_FALSE(IsThrottled());
+}
+
+TEST_F(FrameSchedulerImplTest, PageHidden_ExplicitInit) {
+  ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(true);
+  LazyInitThrottleableTaskQueue();
+  EXPECT_FALSE(IsThrottled());
+  page_scheduler_->SetPageVisible(false);
+  EXPECT_TRUE(IsThrottled());
+}
+
+TEST_F(FrameSchedulerImplTest, PageHidden_LazyInit) {
+  ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(false);
+  page_scheduler_->SetPageVisible(false);
+  LazyInitThrottleableTaskQueue();
+  EXPECT_TRUE(IsThrottled());
+}
+
+TEST_F(FrameSchedulerImplTest, PageHiddenThenVisible_ExplicitInit) {
+  ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(false);
+  LazyInitThrottleableTaskQueue();
+  EXPECT_FALSE(IsThrottled());
+  page_scheduler_->SetPageVisible(false);
+  EXPECT_TRUE(IsThrottled());
+  page_scheduler_->SetPageVisible(true);
+  EXPECT_FALSE(IsThrottled());
+  page_scheduler_->SetPageVisible(false);
+  EXPECT_TRUE(IsThrottled());
+}
+
+TEST_F(FrameSchedulerImplTest,
+       FrameHiddenThenVisible_CrossOrigin_ExplicitInit) {
+  ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(true);
+  LazyInitThrottleableTaskQueue();
+  EXPECT_FALSE(IsThrottled());
+  frame_scheduler_->SetFrameVisible(false);
+  frame_scheduler_->SetCrossOrigin(true);
+  frame_scheduler_->SetCrossOrigin(false);
+  EXPECT_FALSE(IsThrottled());
+  frame_scheduler_->SetCrossOrigin(true);
+  EXPECT_TRUE(IsThrottled());
+  frame_scheduler_->SetFrameVisible(true);
+  EXPECT_FALSE(IsThrottled());
+  frame_scheduler_->SetFrameVisible(false);
+  EXPECT_TRUE(IsThrottled());
+}
+
+TEST_F(FrameSchedulerImplTest, FrameHidden_CrossOrigin_LazyInit) {
+  ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(true);
+  frame_scheduler_->SetFrameVisible(false);
+  frame_scheduler_->SetCrossOrigin(true);
+  LazyInitThrottleableTaskQueue();
+  EXPECT_TRUE(IsThrottled());
+}
+
+TEST_F(FrameSchedulerImplTest,
+       FrameHidden_CrossOrigin_NoThrottling_ExplicitInit) {
+  ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(false);
+  LazyInitThrottleableTaskQueue();
+  EXPECT_FALSE(IsThrottled());
+  frame_scheduler_->SetFrameVisible(false);
+  frame_scheduler_->SetCrossOrigin(true);
+  EXPECT_FALSE(IsThrottled());
+}
+
+TEST_F(FrameSchedulerImplTest, FrameHidden_CrossOrigin_NoThrottling_LazyInit) {
+  ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(false);
+  frame_scheduler_->SetFrameVisible(false);
+  frame_scheduler_->SetCrossOrigin(true);
+  LazyInitThrottleableTaskQueue();
+  EXPECT_FALSE(IsThrottled());
+}
+
+TEST_F(FrameSchedulerImplTest, FrameHidden_SameOrigin_ExplicitInit) {
+  ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(true);
+  LazyInitThrottleableTaskQueue();
+  EXPECT_FALSE(IsThrottled());
+  frame_scheduler_->SetFrameVisible(false);
+  EXPECT_FALSE(IsThrottled());
+}
+
+TEST_F(FrameSchedulerImplTest, FrameHidden_SameOrigin_LazyInit) {
+  ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(true);
+  frame_scheduler_->SetFrameVisible(false);
+  LazyInitThrottleableTaskQueue();
+  EXPECT_FALSE(IsThrottled());
+}
+
+TEST_F(FrameSchedulerImplTest, FrameVisible_CrossOrigin_ExplicitInit) {
+  ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(true);
+  LazyInitThrottleableTaskQueue();
+  EXPECT_FALSE(IsThrottled());
+  EXPECT_TRUE(throttleable_task_queue());
+  frame_scheduler_->SetFrameVisible(true);
+  EXPECT_FALSE(IsThrottled());
+  frame_scheduler_->SetCrossOrigin(true);
+  EXPECT_FALSE(IsThrottled());
+}
+
+TEST_F(FrameSchedulerImplTest, FrameVisible_CrossOrigin_LazyInit) {
+  ScopedTimerThrottlingForHiddenFramesForTest throttle_hidden_frames(true);
+  frame_scheduler_->SetFrameVisible(true);
+  frame_scheduler_->SetCrossOrigin(true);
+  LazyInitThrottleableTaskQueue();
+  EXPECT_FALSE(IsThrottled());
+}
+
+TEST_F(FrameSchedulerImplTest, PauseAndResume) {
+  int counter = 0;
+  LoadingTaskQueue()->PostTask(
+      FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+  ThrottleableTaskQueue()->PostTask(
+      FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+  DeferrableTaskQueue()->PostTask(
+      FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+  PausableTaskQueue()->PostTask(
+      FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+  UnpausableTaskQueue()->PostTask(
+      FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+
+  frame_scheduler_->SetPaused(true);
+
+  EXPECT_EQ(0, counter);
+  mock_task_runner_->RunUntilIdle();
+  EXPECT_EQ(1, counter);
+
+  frame_scheduler_->SetPaused(false);
+
+  EXPECT_EQ(1, counter);
+  mock_task_runner_->RunUntilIdle();
+  EXPECT_EQ(5, counter);
+}
+
+TEST_F(FrameSchedulerImplTest, PageFreezeAndUnfreezeFlagEnabled) {
+  ScopedStopLoadingInBackgroundForTest stop_loading_enabler(true);
+  ScopedStopNonTimersInBackgroundForTest stop_non_timers_enabler(true);
+  int counter = 0;
+  LoadingTaskQueue()->PostTask(
+      FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+  ThrottleableTaskQueue()->PostTask(
+      FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+  DeferrableTaskQueue()->PostTask(
+      FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+  PausableTaskQueue()->PostTask(
+      FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+  UnpausableTaskQueue()->PostTask(
+      FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+
+  frame_scheduler_->SetPageVisibility(PageVisibilityState::kHidden);
+  frame_scheduler_->SetPageFrozen(true);
+
+  EXPECT_EQ(0, counter);
+  mock_task_runner_->RunUntilIdle();
+  // unpausable tasks continue to run.
+  EXPECT_EQ(1, counter);
+
+  frame_scheduler_->SetPageFrozen(false);
+
+  EXPECT_EQ(1, counter);
+  mock_task_runner_->RunUntilIdle();
+  EXPECT_EQ(5, counter);
+}
+
+TEST_F(FrameSchedulerImplTest, PageFreezeAndUnfreezeFlagDisabled) {
+  ScopedStopLoadingInBackgroundForTest stop_loading_enabler(false);
+  ScopedStopNonTimersInBackgroundForTest stop_non_timers_enabler(false);
+  int counter = 0;
+  LoadingTaskQueue()->PostTask(
+      FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+  ThrottleableTaskQueue()->PostTask(
+      FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+  DeferrableTaskQueue()->PostTask(
+      FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+  PausableTaskQueue()->PostTask(
+      FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+  UnpausableTaskQueue()->PostTask(
+      FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+
+  frame_scheduler_->SetPageVisibility(PageVisibilityState::kHidden);
+  frame_scheduler_->SetPageFrozen(true);
+
+  EXPECT_EQ(0, counter);
+  mock_task_runner_->RunUntilIdle();
+  // throttleable tasks are frozen, other tasks continue to run.
+  EXPECT_EQ(4, counter);
+
+  frame_scheduler_->SetPageFrozen(false);
+
+  EXPECT_EQ(4, counter);
+  mock_task_runner_->RunUntilIdle();
+  EXPECT_EQ(5, counter);
+}
+
+TEST_F(FrameSchedulerImplTest, PageFreezeAndPageVisible) {
+  ScopedStopLoadingInBackgroundForTest stop_loading_enabler(true);
+  ScopedStopNonTimersInBackgroundForTest stop_non_timers_enabler(true);
+  int counter = 0;
+  LoadingTaskQueue()->PostTask(
+      FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+  ThrottleableTaskQueue()->PostTask(
+      FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+  DeferrableTaskQueue()->PostTask(
+      FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+  PausableTaskQueue()->PostTask(
+      FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+  UnpausableTaskQueue()->PostTask(
+      FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+
+  frame_scheduler_->SetPageVisibility(PageVisibilityState::kHidden);
+  frame_scheduler_->SetPageFrozen(true);
+
+  EXPECT_EQ(0, counter);
+  mock_task_runner_->RunUntilIdle();
+  EXPECT_EQ(1, counter);
+
+  // Making the page visible should cause frozen queues to resume.
+  frame_scheduler_->SetPageVisibility(PageVisibilityState::kVisible);
+
+  EXPECT_EQ(1, counter);
+  mock_task_runner_->RunUntilIdle();
+  EXPECT_EQ(5, counter);
+}
+
+// Tests if throttling observer interfaces work.
+TEST_F(FrameSchedulerImplTest, ThrottlingObserver) {
+  std::unique_ptr<MockThrottlingObserver> observer =
+      std::make_unique<MockThrottlingObserver>();
+
+  size_t throttled_count = 0u;
+  size_t not_throttled_count = 0u;
+  size_t stopped_count = 0u;
+
+  observer->CheckObserverState(throttled_count, not_throttled_count,
+                               stopped_count);
+
+  auto observer_handle = frame_scheduler_->AddThrottlingObserver(
+      FrameScheduler::ObserverType::kLoader, observer.get());
+
+  // Initial state should be synchronously notified here.
+  // We assume kNotThrottled is notified as an initial state, but it could
+  // depend on implementation details and can be changed.
+  observer->CheckObserverState(throttled_count, ++not_throttled_count,
+                               stopped_count);
+
+  // Once the page gets to be invisible, it should notify the observer of
+  // kThrottled synchronously.
+  page_scheduler_->SetPageVisible(false);
+  observer->CheckObserverState(++throttled_count, not_throttled_count,
+                               stopped_count);
+
+  // When no state has changed, observers are not called.
+  page_scheduler_->SetPageVisible(false);
+  observer->CheckObserverState(throttled_count, not_throttled_count,
+                               stopped_count);
+
+  // Setting background page to STOPPED, notifies observers of kStopped.
+  page_scheduler_->SetPageFrozen(true);
+  observer->CheckObserverState(throttled_count, not_throttled_count,
+                               ++stopped_count);
+
+  // When page is not in the STOPPED state, then page visibility is used,
+  // notifying observer of kThrottled.
+  page_scheduler_->SetPageFrozen(false);
+  observer->CheckObserverState(++throttled_count, not_throttled_count,
+                               stopped_count);
+
+  // Going back to visible state should notify the observer of kNotThrottled
+  // synchronously.
+  page_scheduler_->SetPageVisible(true);
+  observer->CheckObserverState(throttled_count, ++not_throttled_count,
+                               stopped_count);
+
+  // Remove from the observer list, and see if any other callback should not be
+  // invoked when the condition is changed.
+  observer_handle.reset();
+  page_scheduler_->SetPageVisible(false);
+
+  // Wait 100 secs virtually and run pending tasks just in case.
+  clock_.Advance(base::TimeDelta::FromSeconds(100));
+  mock_task_runner_->RunUntilIdle();
+
+  observer->CheckObserverState(throttled_count, not_throttled_count,
+                               stopped_count);
+}
+
+}  // namespace frame_scheduler_impl_unittest
+}  // namespace scheduler
+}  // namespace blink
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/frame_status.cc b/third_party/WebKit/Source/platform/scheduler/renderer/frame_status.cc
index 9edd5ac..64f7a98 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/frame_status.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/frame_status.cc
@@ -4,7 +4,7 @@
 
 #include "platform/scheduler/renderer/frame_status.h"
 
-#include "platform/WebFrameScheduler.h"
+#include "platform/FrameScheduler.h"
 #include "platform/scheduler/renderer/page_scheduler.h"
 
 namespace blink {
@@ -33,7 +33,7 @@
 };
 
 FrameThrottlingState GetFrameThrottlingState(
-    const WebFrameScheduler& frame_scheduler) {
+    const FrameScheduler& frame_scheduler) {
   if (frame_scheduler.IsPageVisible()) {
     if (frame_scheduler.IsFrameVisible())
       return FrameThrottlingState::kVisible;
@@ -56,9 +56,8 @@
   return FrameThrottlingState::kBackground;
 }
 
-FrameOriginState GetFrameOriginState(const WebFrameScheduler& frame_scheduler) {
-  if (frame_scheduler.GetFrameType() ==
-      WebFrameScheduler::FrameType::kMainFrame) {
+FrameOriginState GetFrameOriginState(const FrameScheduler& frame_scheduler) {
+  if (frame_scheduler.GetFrameType() == FrameScheduler::FrameType::kMainFrame) {
     return FrameOriginState::kMainFrame;
   }
   if (frame_scheduler.IsCrossOrigin())
@@ -68,7 +67,7 @@
 
 }  // namespace
 
-FrameStatus GetFrameStatus(WebFrameScheduler* frame_scheduler) {
+FrameStatus GetFrameStatus(FrameScheduler* frame_scheduler) {
   if (!frame_scheduler)
     return FrameStatus::kNone;
   FrameThrottlingState throttling_state =
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/frame_status.h b/third_party/WebKit/Source/platform/scheduler/renderer/frame_status.h
index 16b18b8..680f03f5 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/frame_status.h
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/frame_status.h
@@ -8,7 +8,7 @@
 #include "platform/PlatformExport.h"
 
 namespace blink {
-class WebFrameScheduler;
+class FrameScheduler;
 
 namespace scheduler {
 
@@ -77,7 +77,7 @@
   kCount = 23
 };
 
-PLATFORM_EXPORT FrameStatus GetFrameStatus(WebFrameScheduler* frame_scheduler);
+PLATFORM_EXPORT FrameStatus GetFrameStatus(FrameScheduler* frame_scheduler);
 
 }  // namespace scheduler
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/main_thread_task_queue.cc b/third_party/WebKit/Source/platform/scheduler/renderer/main_thread_task_queue.cc
index b1d8159f..14dd433 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/main_thread_task_queue.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/main_thread_task_queue.cc
@@ -102,7 +102,7 @@
       can_be_stopped_(params.can_be_stopped),
       used_for_important_tasks_(params.used_for_important_tasks),
       renderer_scheduler_(renderer_scheduler),
-      web_frame_scheduler_(nullptr) {
+      frame_scheduler_(nullptr) {
   if (GetTaskQueueImpl()) {
     // TaskQueueImpl may be null for tests.
     // TODO(scheduler-dev): Consider mapping directly to
@@ -159,15 +159,15 @@
   if (renderer_scheduler_)
     renderer_scheduler_->OnShutdownTaskQueue(this);
   renderer_scheduler_ = nullptr;
-  web_frame_scheduler_ = nullptr;
+  frame_scheduler_ = nullptr;
 }
 
-WebFrameScheduler* MainThreadTaskQueue::GetFrameScheduler() const {
-  return web_frame_scheduler_;
+FrameScheduler* MainThreadTaskQueue::GetFrameScheduler() const {
+  return frame_scheduler_;
 }
 
-void MainThreadTaskQueue::SetFrameScheduler(WebFrameScheduler* frame) {
-  web_frame_scheduler_ = frame;
+void MainThreadTaskQueue::SetFrameScheduler(FrameScheduler* frame) {
+  frame_scheduler_ = frame;
 }
 
 }  // namespace scheduler
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/main_thread_task_queue.h b/third_party/WebKit/Source/platform/scheduler/renderer/main_thread_task_queue.h
index 6ff2deb5..4be47474 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/main_thread_task_queue.h
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/main_thread_task_queue.h
@@ -10,7 +10,7 @@
 
 namespace blink {
 
-class WebFrameScheduler;
+class FrameScheduler;
 
 namespace scheduler {
 
@@ -126,7 +126,7 @@
 
     QueueType queue_type;
     TaskQueue::Spec spec;
-    WebFrameScheduler* frame_;
+    FrameScheduler* frame_;
     bool can_be_blocked;
     bool can_be_throttled;
     bool can_be_paused;
@@ -162,8 +162,8 @@
   // Override base method to notify RendererScheduler about shutdown queue.
   void ShutdownTaskQueue() override;
 
-  WebFrameScheduler* GetFrameScheduler() const;
-  void SetFrameScheduler(WebFrameScheduler* frame);
+  FrameScheduler* GetFrameScheduler() const;
+  void SetFrameScheduler(FrameScheduler* frame);
 
  protected:
   MainThreadTaskQueue(std::unique_ptr<internal::TaskQueueImpl> impl,
@@ -190,7 +190,7 @@
   // Needed to notify renderer scheduler about completed tasks.
   RendererSchedulerImpl* renderer_scheduler_;  // NOT OWNED
 
-  WebFrameScheduler* web_frame_scheduler_;  // NOT OWNED
+  FrameScheduler* frame_scheduler_;  // NOT OWNED
 
   DISALLOW_COPY_AND_ASSIGN(MainThreadTaskQueue);
 };
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/page_scheduler.h b/third_party/WebKit/Source/platform/scheduler/renderer/page_scheduler.h
index c4b92a41..e250f8c 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/page_scheduler.h
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/page_scheduler.h
@@ -6,8 +6,8 @@
 #define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_PAGE_SCHEDULER_H_
 
 #include <memory>
+#include "platform/FrameScheduler.h"
 #include "platform/PlatformExport.h"
-#include "platform/WebFrameScheduler.h"
 #include "platform/wtf/Functional.h"
 #include "platform/wtf/text/WTFString.h"
 #include "public/platform/BlameContext.h"
@@ -32,12 +32,12 @@
   // The scheduler transitions app to and from STOPPED state in background.
   virtual void SetPageFrozen(bool) = 0;
 
-  // Creates a new WebFrameScheduler. The caller is responsible for deleting
+  // Creates a new FrameScheduler. The caller is responsible for deleting
   // it. All tasks executed by the frame scheduler will be attributed to
   // |blame_context|.
-  virtual std::unique_ptr<WebFrameScheduler> CreateFrameScheduler(
+  virtual std::unique_ptr<FrameScheduler> CreateFrameScheduler(
       BlameContext*,
-      WebFrameScheduler::FrameType) = 0;
+      FrameScheduler::FrameType) = 0;
 
   // Instructs this PageScheduler to use virtual time. When virtual time is
   // enabled the system doesn't actually sleep for the delays between tasks
@@ -68,13 +68,13 @@
     kAdvance,
 
     // In this policy virtual time is not allowed to advance. Delayed tasks
-    // posted to task runners owned by any child WebFrameSchedulers will be
+    // posted to task runners owned by any child FrameSchedulers will be
     // paused, unless their scheduled run time is less than or equal to the
     // current virtual time.  Note non-delayed tasks will run as normal.
     kPause,
 
     // In this policy virtual time is allowed to advance unless there are
-    // pending network fetches associated any child WebFrameScheduler, or a
+    // pending network fetches associated any child FrameScheduler, or a
     // document is being parsed on a background thread. Initially virtual time
     // is not allowed to advance until we have seen at least one load. The aim
     // being to try and make loading (more) deterministic.
@@ -84,7 +84,7 @@
   virtual void SetInitialVirtualTimeOffset(base::TimeDelta offset) = 0;
 
   // Sets the virtual time policy, which is applied imemdiatly to all child
-  // WebFrameSchedulers.
+  // FrameSchedulers.
   virtual void SetVirtualTimePolicy(VirtualTimePolicy) = 0;
 
   class PLATFORM_EXPORT VirtualTimeObserver {
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/page_scheduler_impl.cc b/third_party/WebKit/Source/platform/scheduler/renderer/page_scheduler_impl.cc
index 28b129a..5351b73 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/page_scheduler_impl.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/page_scheduler_impl.cc
@@ -8,14 +8,14 @@
 #include "base/metrics/field_trial_params.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
-#include "platform/WebFrameScheduler.h"
+#include "platform/FrameScheduler.h"
 #include "platform/runtime_enabled_features.h"
 #include "platform/scheduler/base/virtual_time_domain.h"
 #include "platform/scheduler/child/default_params.h"
 #include "platform/scheduler/common/throttling/budget_pool.h"
 #include "platform/scheduler/renderer/auto_advancing_virtual_time_domain.h"
+#include "platform/scheduler/renderer/frame_scheduler_impl.h"
 #include "platform/scheduler/renderer/renderer_scheduler_impl.h"
-#include "platform/scheduler/renderer/web_frame_scheduler_impl.h"
 
 namespace blink {
 namespace scheduler {
@@ -112,7 +112,7 @@
 PageSchedulerImpl::~PageSchedulerImpl() {
   // TODO(alexclarke): Find out why we can't rely on the web view outliving the
   // frame.
-  for (WebFrameSchedulerImpl* frame_scheduler : frame_schedulers_) {
+  for (FrameSchedulerImpl* frame_scheduler : frame_schedulers_) {
     frame_scheduler->DetachFromPageScheduler();
   }
   renderer_scheduler_->RemovePageScheduler(this);
@@ -136,33 +136,30 @@
 }
 
 void PageSchedulerImpl::SetPageFrozen(bool frozen) {
-  for (WebFrameSchedulerImpl* frame_scheduler : frame_schedulers_)
+  for (FrameSchedulerImpl* frame_scheduler : frame_schedulers_)
     frame_scheduler->SetPageFrozen(frozen);
   if (delegate_)
     delegate_->SetPageFrozen(frozen);
 }
 
-std::unique_ptr<WebFrameSchedulerImpl>
-PageSchedulerImpl::CreateWebFrameSchedulerImpl(
+std::unique_ptr<FrameSchedulerImpl> PageSchedulerImpl::CreateFrameSchedulerImpl(
     base::trace_event::BlameContext* blame_context,
-    WebFrameScheduler::FrameType frame_type) {
+    FrameScheduler::FrameType frame_type) {
   MaybeInitializeBackgroundCPUTimeBudgetPool();
-  std::unique_ptr<WebFrameSchedulerImpl> frame_scheduler(
-      new WebFrameSchedulerImpl(renderer_scheduler_, this, blame_context,
-                                frame_type));
+  std::unique_ptr<FrameSchedulerImpl> frame_scheduler(new FrameSchedulerImpl(
+      renderer_scheduler_, this, blame_context, frame_type));
   frame_scheduler->SetPageVisibility(page_visibility_);
   frame_schedulers_.insert(frame_scheduler.get());
   return frame_scheduler;
 }
 
-std::unique_ptr<blink::WebFrameScheduler>
-PageSchedulerImpl::CreateFrameScheduler(
+std::unique_ptr<blink::FrameScheduler> PageSchedulerImpl::CreateFrameScheduler(
     blink::BlameContext* blame_context,
-    WebFrameScheduler::FrameType frame_type) {
-  return CreateWebFrameSchedulerImpl(blame_context, frame_type);
+    FrameScheduler::FrameType frame_type) {
+  return CreateFrameSchedulerImpl(blame_context, frame_type);
 }
 
-void PageSchedulerImpl::Unregister(WebFrameSchedulerImpl* frame_scheduler) {
+void PageSchedulerImpl::Unregister(FrameSchedulerImpl* frame_scheduler) {
   DCHECK(frame_schedulers_.find(frame_scheduler) != frame_schedulers_.end());
   frame_schedulers_.erase(frame_scheduler);
 }
@@ -239,7 +236,7 @@
 
 void PageSchedulerImpl::OnConnectionUpdated() {
   bool has_active_connection = false;
-  for (WebFrameSchedulerImpl* frame_scheduler : frame_schedulers_) {
+  for (FrameSchedulerImpl* frame_scheduler : frame_schedulers_) {
     has_active_connection |= frame_scheduler->has_active_connection();
   }
 
@@ -251,7 +248,7 @@
 
 void PageSchedulerImpl::OnTraceLogEnabled() {
   tracing_controller_.OnTraceLogEnabled();
-  for (WebFrameSchedulerImpl* frame_scheduler : frame_schedulers_) {
+  for (FrameSchedulerImpl* frame_scheduler : frame_schedulers_) {
     frame_scheduler->OnTraceLogEnabled();
   }
 }
@@ -267,7 +264,7 @@
                     reported_background_throttling_since_navigation_);
 
   state->BeginDictionary("frame_schedulers");
-  for (WebFrameSchedulerImpl* frame_scheduler : frame_schedulers_) {
+  for (FrameSchedulerImpl* frame_scheduler : frame_schedulers_) {
     state->BeginDictionaryWithCopiedName(PointerToString(frame_scheduler));
     frame_scheduler->AsValueInto(state);
     state->EndDictionary();
@@ -331,7 +328,7 @@
 }
 
 void PageSchedulerImpl::UpdateBackgroundThrottlingState() {
-  for (WebFrameSchedulerImpl* frame_scheduler : frame_schedulers_)
+  for (FrameSchedulerImpl* frame_scheduler : frame_schedulers_)
     frame_scheduler->SetPageVisibility(page_visibility_);
   UpdateBackgroundBudgetPoolThrottlingState();
 }
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/page_scheduler_impl.h b/third_party/WebKit/Source/platform/scheduler/renderer/page_scheduler_impl.h
index 13bd2f6..671cb85 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/page_scheduler_impl.h
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/page_scheduler_impl.h
@@ -32,7 +32,7 @@
 
 class RendererSchedulerImpl;
 class CPUTimeBudgetPool;
-class WebFrameSchedulerImpl;
+class FrameSchedulerImpl;
 
 class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
  public:
@@ -45,9 +45,9 @@
   // PageScheduler implementation:
   void SetPageVisible(bool page_visible) override;
   void SetPageFrozen(bool) override;
-  std::unique_ptr<WebFrameScheduler> CreateFrameScheduler(
+  std::unique_ptr<FrameScheduler> CreateFrameScheduler(
       BlameContext*,
-      WebFrameScheduler::FrameType) override;
+      FrameScheduler::FrameType) override;
   base::TimeTicks EnableVirtualTime() override;
   void DisableVirtualTimeForTesting() override;
   bool VirtualTimeAllowedToAdvance() const override;
@@ -69,11 +69,11 @@
   // Virtual for testing.
   virtual void ReportIntervention(const std::string& message);
 
-  std::unique_ptr<WebFrameSchedulerImpl> CreateWebFrameSchedulerImpl(
+  std::unique_ptr<FrameSchedulerImpl> CreateFrameSchedulerImpl(
       base::trace_event::BlameContext*,
-      WebFrameScheduler::FrameType);
+      FrameScheduler::FrameType);
 
-  void Unregister(WebFrameSchedulerImpl*);
+  void Unregister(FrameSchedulerImpl*);
   void OnNavigation();
 
   void OnConnectionUpdated();
@@ -90,7 +90,7 @@
   }
 
  private:
-  friend class WebFrameSchedulerImpl;
+  friend class FrameSchedulerImpl;
 
   CPUTimeBudgetPool* BackgroundCPUTimeBudgetPool();
   void MaybeInitializeBackgroundCPUTimeBudgetPool();
@@ -107,7 +107,7 @@
   void UpdateBackgroundBudgetPoolThrottlingState();
 
   TraceableVariableController tracing_controller_;
-  std::set<WebFrameSchedulerImpl*> frame_schedulers_;
+  std::set<FrameSchedulerImpl*> frame_schedulers_;
   RendererSchedulerImpl* renderer_scheduler_;
 
   PageVisibilityState page_visibility_;
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/page_scheduler_impl_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/page_scheduler_impl_unittest.cc
index 6e1d5529..5a5a8d1 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/page_scheduler_impl_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/page_scheduler_impl_unittest.cc
@@ -15,8 +15,8 @@
 #include "base/test/simple_test_tick_clock.h"
 #include "components/viz/test/ordered_simple_task_runner.h"
 #include "platform/scheduler/child/task_runner_impl.h"
+#include "platform/scheduler/renderer/frame_scheduler_impl.h"
 #include "platform/scheduler/renderer/renderer_scheduler_impl.h"
-#include "platform/scheduler/renderer/web_frame_scheduler_impl.h"
 #include "platform/scheduler/test/task_queue_manager_for_test.h"
 #include "platform/testing/runtime_enabled_features_test_helpers.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -44,12 +44,12 @@
         base::nullopt));
     page_scheduler_.reset(new PageSchedulerImpl(
         nullptr, scheduler_.get(), DisableBackgroundTimerThrottling()));
-    web_frame_scheduler_ = page_scheduler_->CreateWebFrameSchedulerImpl(
-        nullptr, WebFrameScheduler::FrameType::kSubframe);
+    frame_scheduler_ = page_scheduler_->CreateFrameSchedulerImpl(
+        nullptr, FrameScheduler::FrameType::kSubframe);
   }
 
   void TearDown() override {
-    web_frame_scheduler_.reset();
+    frame_scheduler_.reset();
     page_scheduler_.reset();
     scheduler_->Shutdown();
     scheduler_.reset();
@@ -59,7 +59,7 @@
 
  protected:
   static scoped_refptr<TaskQueue> ThrottleableTaskQueueForScheduler(
-      WebFrameSchedulerImpl* scheduler) {
+      FrameSchedulerImpl* scheduler) {
     return scheduler->ThrottleableTaskQueue();
   }
 
@@ -73,36 +73,36 @@
   }
 
   scoped_refptr<TaskQueue> ThrottleableTaskQueue() {
-    return web_frame_scheduler_->ThrottleableTaskQueue();
+    return frame_scheduler_->ThrottleableTaskQueue();
   }
 
   scoped_refptr<TaskQueue> LoadingTaskQueue() {
-    return web_frame_scheduler_->LoadingTaskQueue();
+    return frame_scheduler_->LoadingTaskQueue();
   }
 
   base::SimpleTestTickClock clock_;
   scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
   std::unique_ptr<RendererSchedulerImpl> scheduler_;
   std::unique_ptr<PageSchedulerImpl> page_scheduler_;
-  std::unique_ptr<WebFrameSchedulerImpl> web_frame_scheduler_;
+  std::unique_ptr<FrameSchedulerImpl> frame_scheduler_;
 };
 
 TEST_F(PageSchedulerImplTest, TestDestructionOfFrameSchedulersBefore) {
-  std::unique_ptr<blink::WebFrameScheduler> frame1(
+  std::unique_ptr<blink::FrameScheduler> frame1(
       page_scheduler_->CreateFrameScheduler(
-          nullptr, WebFrameScheduler::FrameType::kSubframe));
-  std::unique_ptr<blink::WebFrameScheduler> frame2(
+          nullptr, FrameScheduler::FrameType::kSubframe));
+  std::unique_ptr<blink::FrameScheduler> frame2(
       page_scheduler_->CreateFrameScheduler(
-          nullptr, WebFrameScheduler::FrameType::kSubframe));
+          nullptr, FrameScheduler::FrameType::kSubframe));
 }
 
 TEST_F(PageSchedulerImplTest, TestDestructionOfFrameSchedulersAfter) {
-  std::unique_ptr<blink::WebFrameScheduler> frame1(
+  std::unique_ptr<blink::FrameScheduler> frame1(
       page_scheduler_->CreateFrameScheduler(
-          nullptr, WebFrameScheduler::FrameType::kSubframe));
-  std::unique_ptr<blink::WebFrameScheduler> frame2(
+          nullptr, FrameScheduler::FrameType::kSubframe));
+  std::unique_ptr<blink::FrameScheduler> frame2(
       page_scheduler_->CreateFrameScheduler(
-          nullptr, WebFrameScheduler::FrameType::kSubframe));
+          nullptr, FrameScheduler::FrameType::kSubframe));
   page_scheduler_.reset();
 }
 
@@ -175,9 +175,9 @@
 TEST_F(PageSchedulerImplTest, RepeatingTimers_OneBackgroundOneForeground) {
   std::unique_ptr<PageSchedulerImpl> page_scheduler2(
       new PageSchedulerImpl(nullptr, scheduler_.get(), false));
-  std::unique_ptr<WebFrameSchedulerImpl> web_frame_scheduler2 =
-      page_scheduler2->CreateWebFrameSchedulerImpl(
-          nullptr, WebFrameScheduler::FrameType::kSubframe);
+  std::unique_ptr<FrameSchedulerImpl> frame_scheduler2 =
+      page_scheduler2->CreateFrameSchedulerImpl(
+          nullptr, FrameScheduler::FrameType::kSubframe);
 
   page_scheduler_->SetPageVisible(true);
   page_scheduler2->SetPageVisible(false);
@@ -187,10 +187,10 @@
   ThrottleableTaskQueue()->PostDelayedTask(
       FROM_HERE, MakeRepeatingTask(ThrottleableTaskQueue(), &run_count1),
       base::TimeDelta::FromMilliseconds(1));
-  ThrottleableTaskQueueForScheduler(web_frame_scheduler2.get())
+  ThrottleableTaskQueueForScheduler(frame_scheduler2.get())
       ->PostDelayedTask(FROM_HERE,
                         MakeRepeatingTask(ThrottleableTaskQueueForScheduler(
-                                              web_frame_scheduler2.get()),
+                                              frame_scheduler2.get()),
                                           &run_count2),
                         base::TimeDelta::FromMilliseconds(1));
 
@@ -416,17 +416,17 @@
   EXPECT_EQ(1000, run_count);
 }
 
-TEST_F(PageSchedulerImplTest, VirtualTimeSettings_NewWebFrameScheduler) {
+TEST_F(PageSchedulerImplTest, VirtualTimeSettings_NewFrameScheduler) {
   std::vector<int> run_order;
 
   page_scheduler_->SetVirtualTimePolicy(VirtualTimePolicy::kPause);
   page_scheduler_->EnableVirtualTime();
 
-  std::unique_ptr<WebFrameSchedulerImpl> web_frame_scheduler =
-      page_scheduler_->CreateWebFrameSchedulerImpl(
-          nullptr, WebFrameScheduler::FrameType::kSubframe);
+  std::unique_ptr<FrameSchedulerImpl> frame_scheduler =
+      page_scheduler_->CreateFrameSchedulerImpl(
+          nullptr, FrameScheduler::FrameType::kSubframe);
 
-  ThrottleableTaskQueueForScheduler(web_frame_scheduler.get())
+  ThrottleableTaskQueueForScheduler(frame_scheduler.get())
       ->PostDelayedTask(
           FROM_HERE,
           base::BindOnce(&RunOrderTask, 1, base::Unretained(&run_order)),
@@ -450,15 +450,15 @@
 
 }  // namespace
 
-TEST_F(PageSchedulerImplTest, DeleteWebFrameSchedulers_InTask) {
+TEST_F(PageSchedulerImplTest, DeleteFrameSchedulers_InTask) {
   for (int i = 0; i < 10; i++) {
-    WebFrameSchedulerImpl* web_frame_scheduler =
+    FrameSchedulerImpl* frame_scheduler =
         page_scheduler_
-            ->CreateWebFrameSchedulerImpl(
-                nullptr, WebFrameScheduler::FrameType::kSubframe)
+            ->CreateFrameSchedulerImpl(nullptr,
+                                       FrameScheduler::FrameType::kSubframe)
             .release();
-    ThrottleableTaskQueueForScheduler(web_frame_scheduler)
-        ->PostDelayedTask(FROM_HERE, MakeDeletionTask(web_frame_scheduler),
+    ThrottleableTaskQueueForScheduler(frame_scheduler)
+        ->PostDelayedTask(FROM_HERE, MakeDeletionTask(frame_scheduler),
                           base::TimeDelta::FromMilliseconds(1));
   }
   mock_task_runner_->RunUntilIdle();
@@ -473,13 +473,13 @@
 TEST_F(PageSchedulerImplTest, DeleteThrottledQueue_InTask) {
   page_scheduler_->SetPageVisible(false);
 
-  WebFrameSchedulerImpl* web_frame_scheduler =
+  FrameSchedulerImpl* frame_scheduler =
       page_scheduler_
-          ->CreateWebFrameSchedulerImpl(nullptr,
-                                        WebFrameScheduler::FrameType::kSubframe)
+          ->CreateFrameSchedulerImpl(nullptr,
+                                     FrameScheduler::FrameType::kSubframe)
           .release();
   scoped_refptr<TaskQueue> timer_task_queue =
-      ThrottleableTaskQueueForScheduler(web_frame_scheduler);
+      ThrottleableTaskQueueForScheduler(frame_scheduler);
 
   int run_count = 0;
   timer_task_queue->PostDelayedTask(
@@ -489,7 +489,7 @@
   // Note this will run at time t = 10s since we start at time t = 5000us.
   // However, we still should run all tasks after frame scheduler deletion.
   timer_task_queue->PostDelayedTask(FROM_HERE,
-                                    MakeDeletionTask(web_frame_scheduler),
+                                    MakeDeletionTask(frame_scheduler),
                                     base::TimeDelta::FromMilliseconds(9990));
 
   mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(100));
@@ -525,13 +525,13 @@
   page_scheduler_->SetVirtualTimePolicy(
       VirtualTimePolicy::kDeterministicLoading);
 
-  std::unique_ptr<WebFrameSchedulerImpl> web_frame_scheduler =
-      page_scheduler_->CreateWebFrameSchedulerImpl(
-          nullptr, WebFrameScheduler::FrameType::kSubframe);
+  std::unique_ptr<FrameSchedulerImpl> frame_scheduler =
+      page_scheduler_->CreateFrameSchedulerImpl(
+          nullptr, FrameScheduler::FrameType::kSubframe);
 
   {
     WebScopedVirtualTimePauser virtual_time_pauser =
-        web_frame_scheduler->CreateWebScopedVirtualTimePauser(
+        frame_scheduler->CreateWebScopedVirtualTimePauser(
             WebScopedVirtualTimePauser::VirtualTaskDuration::kNonInstant);
     EXPECT_TRUE(scheduler_->VirtualTimeAllowedToAdvance());
 
@@ -553,15 +553,15 @@
   page_scheduler_->SetVirtualTimePolicy(
       VirtualTimePolicy::kDeterministicLoading);
 
-  std::unique_ptr<WebFrameSchedulerImpl> web_frame_scheduler =
-      page_scheduler_->CreateWebFrameSchedulerImpl(
-          nullptr, WebFrameScheduler::FrameType::kSubframe);
+  std::unique_ptr<FrameSchedulerImpl> frame_scheduler =
+      page_scheduler_->CreateFrameSchedulerImpl(
+          nullptr, FrameScheduler::FrameType::kSubframe);
 
   WebScopedVirtualTimePauser virtual_time_pauser1 =
-      web_frame_scheduler->CreateWebScopedVirtualTimePauser(
+      frame_scheduler->CreateWebScopedVirtualTimePauser(
           WebScopedVirtualTimePauser::VirtualTaskDuration::kNonInstant);
   WebScopedVirtualTimePauser virtual_time_pauser2 =
-      web_frame_scheduler->CreateWebScopedVirtualTimePauser(
+      frame_scheduler->CreateWebScopedVirtualTimePauser(
           WebScopedVirtualTimePauser::VirtualTaskDuration::kNonInstant);
 
   EXPECT_TRUE(scheduler_->VirtualTimeAllowedToAdvance());
@@ -592,13 +592,13 @@
 TEST_F(PageSchedulerImplTest, PauseTimersWhileVirtualTimeIsPaused) {
   std::vector<int> run_order;
 
-  std::unique_ptr<WebFrameSchedulerImpl> web_frame_scheduler =
-      page_scheduler_->CreateWebFrameSchedulerImpl(
-          nullptr, WebFrameScheduler::FrameType::kSubframe);
+  std::unique_ptr<FrameSchedulerImpl> frame_scheduler =
+      page_scheduler_->CreateFrameSchedulerImpl(
+          nullptr, FrameScheduler::FrameType::kSubframe);
   page_scheduler_->SetVirtualTimePolicy(VirtualTimePolicy::kPause);
   page_scheduler_->EnableVirtualTime();
 
-  ThrottleableTaskQueueForScheduler(web_frame_scheduler.get())
+  ThrottleableTaskQueueForScheduler(frame_scheduler.get())
       ->PostTask(FROM_HERE, base::BindOnce(&RunOrderTask, 1,
                                            base::Unretained(&run_order)));
 
@@ -871,8 +871,8 @@
       new PageSchedulerImpl(nullptr, scheduler_.get(), false));
 
   std::vector<base::TimeTicks> run_times;
-  web_frame_scheduler_ = page_scheduler_->CreateWebFrameSchedulerImpl(
-      nullptr, WebFrameScheduler::FrameType::kSubframe);
+  frame_scheduler_ = page_scheduler_->CreateFrameSchedulerImpl(
+      nullptr, FrameScheduler::FrameType::kSubframe);
   page_scheduler_->SetPageVisible(true);
 
   mock_task_runner_->RunUntilTime(base::TimeTicks() +
@@ -928,12 +928,12 @@
 
   std::vector<base::TimeTicks> run_times;
 
-  std::unique_ptr<WebFrameSchedulerImpl> web_frame_scheduler1 =
-      page_scheduler->CreateWebFrameSchedulerImpl(
-          nullptr, WebFrameScheduler::FrameType::kSubframe);
-  std::unique_ptr<WebFrameSchedulerImpl> web_frame_scheduler2 =
-      page_scheduler->CreateWebFrameSchedulerImpl(
-          nullptr, WebFrameScheduler::FrameType::kSubframe);
+  std::unique_ptr<FrameSchedulerImpl> frame_scheduler1 =
+      page_scheduler->CreateFrameSchedulerImpl(
+          nullptr, FrameScheduler::FrameType::kSubframe);
+  std::unique_ptr<FrameSchedulerImpl> frame_scheduler2 =
+      page_scheduler->CreateFrameSchedulerImpl(
+          nullptr, FrameScheduler::FrameType::kSubframe);
 
   page_scheduler->SetPageVisible(false);
 
@@ -942,7 +942,7 @@
                                   base::TimeDelta::FromMilliseconds(20500));
 
   for (size_t i = 0; i < 3; ++i) {
-    ThrottleableTaskQueueForScheduler(web_frame_scheduler1.get())
+    ThrottleableTaskQueueForScheduler(frame_scheduler1.get())
         ->PostDelayedTask(
             FROM_HERE, base::BindOnce(&ExpensiveTestTask, &clock_, &run_times),
             base::TimeDelta::FromMilliseconds(1));
@@ -959,11 +959,11 @@
                   base::TimeTicks() + base::TimeDelta::FromSeconds(51)));
   run_times.clear();
 
-  std::unique_ptr<WebFrameScheduler::ActiveConnectionHandle>
-      websocket_connection = web_frame_scheduler1->OnActiveConnectionCreated();
+  std::unique_ptr<FrameScheduler::ActiveConnectionHandle> websocket_connection =
+      frame_scheduler1->OnActiveConnectionCreated();
 
   for (size_t i = 0; i < 3; ++i) {
-    ThrottleableTaskQueueForScheduler(web_frame_scheduler1.get())
+    ThrottleableTaskQueueForScheduler(frame_scheduler1.get())
         ->PostDelayedTask(
             FROM_HERE, base::BindOnce(&ExpensiveTestTask, &clock_, &run_times),
             base::TimeDelta::FromMilliseconds(1));
@@ -983,7 +983,7 @@
   run_times.clear();
 
   for (size_t i = 0; i < 3; ++i) {
-    ThrottleableTaskQueueForScheduler(web_frame_scheduler2.get())
+    ThrottleableTaskQueueForScheduler(frame_scheduler2.get())
         ->PostDelayedTask(
             FROM_HERE, base::BindOnce(&ExpensiveTestTask, &clock_, &run_times),
             base::TimeDelta::FromMilliseconds(1));
@@ -1008,7 +1008,7 @@
                                   base::TimeDelta::FromMilliseconds(70500));
 
   for (size_t i = 0; i < 3; ++i) {
-    ThrottleableTaskQueueForScheduler(web_frame_scheduler1.get())
+    ThrottleableTaskQueueForScheduler(frame_scheduler1.get())
         ->PostDelayedTask(
             FROM_HERE, base::BindOnce(&ExpensiveTestTask, &clock_, &run_times),
             base::TimeDelta::FromMilliseconds(1));
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/queueing_time_estimator.cc b/third_party/WebKit/Source/platform/scheduler/renderer/queueing_time_estimator.cc
index 893fb6b..b970ee3 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/queueing_time_estimator.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/queueing_time_estimator.cc
@@ -5,7 +5,7 @@
 #include "platform/scheduler/renderer/queueing_time_estimator.h"
 
 #include "base/memory/ptr_util.h"
-#include "platform/WebFrameScheduler.h"
+#include "platform/FrameScheduler.h"
 
 #include <algorithm>
 #include <map>
@@ -185,7 +185,7 @@
     MainThreadTaskQueue* queue) {
   current_queue_type_ =
       queue ? queue->queue_type() : MainThreadTaskQueue::QueueType::kOther;
-  WebFrameScheduler* scheduler = queue ? queue->GetFrameScheduler() : nullptr;
+  FrameScheduler* scheduler = queue ? queue->GetFrameScheduler() : nullptr;
   current_frame_status_ =
       scheduler ? GetFrameStatus(scheduler) : FrameStatus::kNone;
 }
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/queueing_time_estimator_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/queueing_time_estimator_unittest.cc
index 684b07c..2bfaa66 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/queueing_time_estimator_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/queueing_time_estimator_unittest.cc
@@ -6,7 +6,7 @@
 #include "base/logging.h"
 #include "base/metrics/histogram_functions.h"
 #include "platform/scheduler/renderer/renderer_scheduler_impl.h"
-#include "platform/scheduler/test/fake_web_frame_scheduler.h"
+#include "platform/scheduler/test/fake_frame_scheduler.h"
 #include "platform/testing/HistogramTester.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -984,9 +984,9 @@
   // Beginning of window 1.
   time += base::TimeDelta::FromMilliseconds(500);
   // Scheduler with frame type: MAIN_FRAME_BACKGROUND.
-  std::unique_ptr<FakeWebFrameScheduler> frame1 =
-      FakeWebFrameScheduler::Builder()
-          .SetFrameType(WebFrameScheduler::FrameType::kMainFrame)
+  std::unique_ptr<FakeFrameScheduler> frame1 =
+      FakeFrameScheduler::Builder()
+          .SetFrameType(FrameScheduler::FrameType::kMainFrame)
           .Build();
   queue1->SetFrameScheduler(frame1.get());
   estimator.OnTopLevelTaskStarted(time, queue1.get());
@@ -996,9 +996,9 @@
   time += base::TimeDelta::FromMilliseconds(1500);
   // Beginning of window 2.
   // Scheduler with frame type: MAIN_FRAME_VISIBLE.
-  std::unique_ptr<FakeWebFrameScheduler> frame2 =
-      FakeWebFrameScheduler::Builder()
-          .SetFrameType(WebFrameScheduler::FrameType::kMainFrame)
+  std::unique_ptr<FakeFrameScheduler> frame2 =
+      FakeFrameScheduler::Builder()
+          .SetFrameType(FrameScheduler::FrameType::kMainFrame)
           .SetIsPageVisible(true)
           .SetIsFrameVisible(true)
           .Build();
@@ -1017,9 +1017,9 @@
 
   // Beginning of window 3.
   // Scheduler with frame type: MAIN_FRAME_VISIBLE.
-  std::unique_ptr<FakeWebFrameScheduler> frame3 =
-      FakeWebFrameScheduler::Builder()
-          .SetFrameType(WebFrameScheduler::FrameType::kMainFrame)
+  std::unique_ptr<FakeFrameScheduler> frame3 =
+      FakeFrameScheduler::Builder()
+          .SetFrameType(FrameScheduler::FrameType::kMainFrame)
           .SetIsPageVisible(true)
           .SetIsFrameVisible(true)
           .SetIsExemptFromThrottling(true)
@@ -1030,9 +1030,9 @@
   estimator.OnTopLevelTaskCompleted(time);
 
   // Scheduler with frame type: MAIN_FRAME_BACKGROUND.
-  std::unique_ptr<FakeWebFrameScheduler> frame4 =
-      FakeWebFrameScheduler::Builder()
-          .SetFrameType(WebFrameScheduler::FrameType::kMainFrame)
+  std::unique_ptr<FakeFrameScheduler> frame4 =
+      FakeFrameScheduler::Builder()
+          .SetFrameType(FrameScheduler::FrameType::kMainFrame)
           .SetIsFrameVisible(true)
           .SetIsExemptFromThrottling(true)
           .Build();
@@ -1044,28 +1044,28 @@
 
   time += base::TimeDelta::FromMilliseconds(1000);
   // Scheduler with frame type: SAME_ORIGIN_VISIBLE.
-  std::unique_ptr<FakeWebFrameScheduler> frame5 =
-      FakeWebFrameScheduler::Builder()
-          .SetFrameType(WebFrameScheduler::FrameType::kSubframe)
+  std::unique_ptr<FakeFrameScheduler> frame5 =
+      FakeFrameScheduler::Builder()
+          .SetFrameType(FrameScheduler::FrameType::kSubframe)
           .SetIsPageVisible(true)
           .SetIsFrameVisible(true)
           .Build();
   // Scheduler with frame type: SAME_ORIGIN_HIDDEN.
-  std::unique_ptr<FakeWebFrameScheduler> frame6 =
-      FakeWebFrameScheduler::Builder()
-          .SetFrameType(WebFrameScheduler::FrameType::kSubframe)
+  std::unique_ptr<FakeFrameScheduler> frame6 =
+      FakeFrameScheduler::Builder()
+          .SetFrameType(FrameScheduler::FrameType::kSubframe)
           .SetIsPageVisible(true)
           .Build();
   // Scheduler with frame type: CROSS_ORIGIN_VISIBLE.
-  std::unique_ptr<FakeWebFrameScheduler> frame7 =
-      FakeWebFrameScheduler::Builder()
-          .SetFrameType(WebFrameScheduler::FrameType::kSubframe)
+  std::unique_ptr<FakeFrameScheduler> frame7 =
+      FakeFrameScheduler::Builder()
+          .SetFrameType(FrameScheduler::FrameType::kSubframe)
           .SetIsPageVisible(true)
           .SetIsFrameVisible(true)
           .SetIsCrossOrigin(true)
           .Build();
-  FakeWebFrameScheduler* schedulers_for_thousand[] = {
-      frame5.get(), frame6.get(), frame7.get()};
+  FakeFrameScheduler* schedulers_for_thousand[] = {frame5.get(), frame6.get(),
+                                                   frame7.get()};
   for (auto scheduler : schedulers_for_thousand) {
     queue1->SetFrameScheduler(scheduler);
     estimator.OnTopLevelTaskStarted(time, queue1.get());
@@ -1075,31 +1075,31 @@
 
   // Beginning of window 5.
   // Scheduler with frame type: MAIN_FRAME_HIDDEN.
-  std::unique_ptr<FakeWebFrameScheduler> frame8 =
-      FakeWebFrameScheduler::Builder()
-          .SetFrameType(WebFrameScheduler::FrameType::kMainFrame)
+  std::unique_ptr<FakeFrameScheduler> frame8 =
+      FakeFrameScheduler::Builder()
+          .SetFrameType(FrameScheduler::FrameType::kMainFrame)
           .SetIsPageVisible(true)
           .Build();
   // Scheduler with frame type: SAME_ORIGIN_BACKGROUND.
-  std::unique_ptr<FakeWebFrameScheduler> frame9 =
-      FakeWebFrameScheduler::Builder()
-          .SetFrameType(WebFrameScheduler::FrameType::kSubframe)
+  std::unique_ptr<FakeFrameScheduler> frame9 =
+      FakeFrameScheduler::Builder()
+          .SetFrameType(FrameScheduler::FrameType::kSubframe)
           .Build();
   // Scheduler with frame type: CROSS_ORIGIN_HIDDEN.
-  std::unique_ptr<FakeWebFrameScheduler> frame10 =
-      FakeWebFrameScheduler::Builder()
-          .SetFrameType(WebFrameScheduler::FrameType::kSubframe)
+  std::unique_ptr<FakeFrameScheduler> frame10 =
+      FakeFrameScheduler::Builder()
+          .SetFrameType(FrameScheduler::FrameType::kSubframe)
           .SetIsPageVisible(true)
           .SetIsCrossOrigin(true)
           .Build();
   // Scheduler with frame type: CROSS_ORIGIN_BACKGROUND.
-  std::unique_ptr<FakeWebFrameScheduler> frame11 =
-      FakeWebFrameScheduler::Builder()
-          .SetFrameType(WebFrameScheduler::FrameType::kSubframe)
+  std::unique_ptr<FakeFrameScheduler> frame11 =
+      FakeFrameScheduler::Builder()
+          .SetFrameType(FrameScheduler::FrameType::kSubframe)
           .SetIsCrossOrigin(true)
           .Build();
   // One scheduler per supported frame type, excluding "Other".
-  FakeWebFrameScheduler* schedulers_for_four_hundred[] = {
+  FakeFrameScheduler* schedulers_for_four_hundred[] = {
       frame2.get(), frame1.get(), frame8.get(),  frame5.get(), frame6.get(),
       frame9.get(), frame7.get(), frame10.get(), frame11.get()};
   for (auto scheduler : schedulers_for_four_hundred) {
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper.cc b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper.cc
index 8953236..3374cdd2 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper.cc
@@ -6,7 +6,7 @@
 
 #include "base/bind.h"
 #include "base/metrics/histogram_macros.h"
-#include "platform/WebFrameScheduler.h"
+#include "platform/FrameScheduler.h"
 #include "platform/instrumentation/resource_coordinator/RendererResourceCoordinator.h"
 #include "platform/scheduler/renderer/renderer_scheduler_impl.h"
 #include "public/platform/scheduler/renderer_process_type.h"
@@ -41,6 +41,38 @@
 
 }  // namespace
 
+RendererMetricsHelper::PerQueueTypeDurationReporters::
+    PerQueueTypeDurationReporters()
+    : overall(DURATION_PER_QUEUE_TYPE_METRIC_NAME),
+      foreground(DURATION_PER_QUEUE_TYPE_METRIC_NAME ".Foreground"),
+      foreground_first_minute(DURATION_PER_QUEUE_TYPE_METRIC_NAME
+                              ".Foreground.FirstMinute"),
+      foreground_second_minute(DURATION_PER_QUEUE_TYPE_METRIC_NAME
+                               ".Foreground.SecondMinute"),
+      foreground_third_minute(DURATION_PER_QUEUE_TYPE_METRIC_NAME
+                              ".Foreground.ThirdMinute"),
+      foreground_after_third_minute(DURATION_PER_QUEUE_TYPE_METRIC_NAME
+                                    ".Foreground.AfterThirdMinute"),
+      background(DURATION_PER_QUEUE_TYPE_METRIC_NAME ".Background"),
+      background_first_minute(DURATION_PER_QUEUE_TYPE_METRIC_NAME
+                              ".Background.FirstMinute"),
+      background_second_minute(DURATION_PER_QUEUE_TYPE_METRIC_NAME
+                               ".Background.SecondMinute"),
+      background_third_minute(DURATION_PER_QUEUE_TYPE_METRIC_NAME
+                              ".Background.ThirdMinute"),
+      background_fourth_minute(DURATION_PER_QUEUE_TYPE_METRIC_NAME
+                               ".Background.FourthMinute"),
+      background_fifth_minute(DURATION_PER_QUEUE_TYPE_METRIC_NAME
+                              ".Background.FifthMinute"),
+      background_after_fifth_minute(DURATION_PER_QUEUE_TYPE_METRIC_NAME
+                                    ".Background.AfterFifthMinute"),
+      background_keep_active_after_fifth_minute(
+          DURATION_PER_QUEUE_TYPE_METRIC_NAME
+          ".Background.KeepAlive.AfterFifthMinute"),
+      hidden(DURATION_PER_QUEUE_TYPE_METRIC_NAME ".Hidden"),
+      visible(DURATION_PER_QUEUE_TYPE_METRIC_NAME ".Visible"),
+      hidden_music(DURATION_PER_QUEUE_TYPE_METRIC_NAME ".HiddenMusic") {}
+
 RendererMetricsHelper::RendererMetricsHelper(
     RendererSchedulerImpl* renderer_scheduler,
     base::TimeTicks now,
@@ -64,38 +96,6 @@
               &RendererMetricsHelper::RecordForegroundMainThreadTaskLoad,
               base::Unretained(this)),
           kThreadLoadTrackerReportingInterval),
-      per_queue_type_task_duration_reporter_(
-          DURATION_PER_QUEUE_TYPE_METRIC_NAME),
-      foreground_per_queue_type_task_duration_reporter_(
-          DURATION_PER_QUEUE_TYPE_METRIC_NAME ".Foreground"),
-      foreground_first_minute_per_queue_type_task_duration_reporter_(
-          DURATION_PER_QUEUE_TYPE_METRIC_NAME ".Foreground.FirstMinute"),
-      foreground_second_minute_per_queue_type_task_duration_reporter_(
-          DURATION_PER_QUEUE_TYPE_METRIC_NAME ".Foreground.SecondMinute"),
-      foreground_third_minute_per_queue_type_task_duration_reporter_(
-          DURATION_PER_QUEUE_TYPE_METRIC_NAME ".Foreground.ThirdMinute"),
-      foreground_after_third_minute_per_queue_type_task_duration_reporter_(
-          DURATION_PER_QUEUE_TYPE_METRIC_NAME ".Foreground.AfterThirdMinute"),
-      background_per_queue_type_task_duration_reporter_(
-          DURATION_PER_QUEUE_TYPE_METRIC_NAME ".Background"),
-      background_first_minute_per_queue_type_task_duration_reporter_(
-          DURATION_PER_QUEUE_TYPE_METRIC_NAME ".Background.FirstMinute"),
-      background_second_minute_per_queue_type_task_duration_reporter_(
-          DURATION_PER_QUEUE_TYPE_METRIC_NAME ".Background.SecondMinute"),
-      background_third_minute_per_queue_type_task_duration_reporter_(
-          DURATION_PER_QUEUE_TYPE_METRIC_NAME ".Background.ThirdMinute"),
-      background_fourth_minute_per_queue_type_task_duration_reporter_(
-          DURATION_PER_QUEUE_TYPE_METRIC_NAME ".Background.FourthMinute"),
-      background_fifth_minute_per_queue_type_task_duration_reporter_(
-          DURATION_PER_QUEUE_TYPE_METRIC_NAME ".Background.FifthMinute"),
-      background_after_fifth_minute_per_queue_type_task_duration_reporter_(
-          DURATION_PER_QUEUE_TYPE_METRIC_NAME ".Background.AfterFifthMinute"),
-      hidden_per_queue_type_task_duration_reporter_(
-          DURATION_PER_QUEUE_TYPE_METRIC_NAME ".Hidden"),
-      visible_per_queue_type_task_duration_reporter_(
-          DURATION_PER_QUEUE_TYPE_METRIC_NAME ".Visible"),
-      hidden_music_per_queue_type_task_duration_reporter_(
-          DURATION_PER_QUEUE_TYPE_METRIC_NAME ".HiddenMusic"),
       per_frame_status_duration_reporter_(DURATION_PER_FRAME_TYPE_METRIC_NAME),
       per_task_type_duration_reporter_(DURATION_PER_TASK_TYPE_METRIC_NAME),
       no_use_case_per_task_type_duration_reporter_(
@@ -242,109 +242,113 @@
                               MainThreadTaskQueue::QueueType::kCount);
   }
 
-  per_queue_type_task_duration_reporter_.RecordTask(queue_type, duration);
+  per_queue_type_reporters_.overall.RecordTask(queue_type, duration);
 
   TaskType task_type = static_cast<TaskType>(task.task_type());
   per_task_type_duration_reporter_.RecordTask(task_type, duration);
 
   if (renderer_scheduler_->main_thread_only().renderer_backgrounded) {
-    background_per_queue_type_task_duration_reporter_.RecordTask(queue_type,
-                                                                 duration);
+    per_queue_type_reporters_.background.RecordTask(queue_type, duration);
 
     // Collect detailed breakdown for first five minutes given that we stop
     // timers on mobile after five minutes.
     base::TimeTicks backgrounded_at =
         renderer_scheduler_->main_thread_only().background_status_changed_at;
 
-    background_first_minute_per_queue_type_task_duration_reporter_.RecordTask(
+    per_queue_type_reporters_.background_first_minute.RecordTask(
         queue_type, DurationOfIntervalOverlap(
                         start_time, end_time, backgrounded_at,
                         backgrounded_at + base::TimeDelta::FromMinutes(1)));
 
-    background_second_minute_per_queue_type_task_duration_reporter_.RecordTask(
+    per_queue_type_reporters_.background_second_minute.RecordTask(
         queue_type, DurationOfIntervalOverlap(
                         start_time, end_time,
                         backgrounded_at + base::TimeDelta::FromMinutes(1),
                         backgrounded_at + base::TimeDelta::FromMinutes(2)));
 
-    background_third_minute_per_queue_type_task_duration_reporter_.RecordTask(
+    per_queue_type_reporters_.background_third_minute.RecordTask(
         queue_type, DurationOfIntervalOverlap(
                         start_time, end_time,
                         backgrounded_at + base::TimeDelta::FromMinutes(2),
                         backgrounded_at + base::TimeDelta::FromMinutes(3)));
 
-    background_fourth_minute_per_queue_type_task_duration_reporter_.RecordTask(
+    per_queue_type_reporters_.background_fourth_minute.RecordTask(
         queue_type, DurationOfIntervalOverlap(
                         start_time, end_time,
                         backgrounded_at + base::TimeDelta::FromMinutes(3),
                         backgrounded_at + base::TimeDelta::FromMinutes(4)));
 
-    background_fifth_minute_per_queue_type_task_duration_reporter_.RecordTask(
+    per_queue_type_reporters_.background_fifth_minute.RecordTask(
         queue_type, DurationOfIntervalOverlap(
                         start_time, end_time,
                         backgrounded_at + base::TimeDelta::FromMinutes(4),
                         backgrounded_at + base::TimeDelta::FromMinutes(5)));
 
-    background_after_fifth_minute_per_queue_type_task_duration_reporter_
-        .RecordTask(
-            queue_type,
-            DurationOfIntervalOverlap(
-                start_time, end_time,
-                backgrounded_at + base::TimeDelta::FromMinutes(5),
-                std::max(backgrounded_at + base::TimeDelta::FromMinutes(5),
-                         end_time)));
+    per_queue_type_reporters_.background_after_fifth_minute.RecordTask(
+        queue_type,
+        DurationOfIntervalOverlap(
+            start_time, end_time,
+            backgrounded_at + base::TimeDelta::FromMinutes(5),
+            std::max(backgrounded_at + base::TimeDelta::FromMinutes(5),
+                     end_time)));
+
+    if (renderer_scheduler_->main_thread_only().keep_active_fetch_or_worker) {
+      per_queue_type_reporters_.background_keep_active_after_fifth_minute
+          .RecordTask(
+              queue_type,
+              DurationOfIntervalOverlap(
+                  start_time, end_time,
+                  backgrounded_at + base::TimeDelta::FromMinutes(5),
+                  std::max(backgrounded_at + base::TimeDelta::FromMinutes(5),
+                           end_time)));
+    }
 
     background_per_task_type_duration_reporter_.RecordTask(task_type, duration);
   } else {
-    foreground_per_queue_type_task_duration_reporter_.RecordTask(queue_type,
-                                                                 duration);
+    per_queue_type_reporters_.foreground.RecordTask(queue_type, duration);
 
     // For foreground tabs we do not expect such a notable difference as it is
     // the case with background tabs, so we limit breakdown to three minutes.
     base::TimeTicks foregrounded_at =
         renderer_scheduler_->main_thread_only().background_status_changed_at;
 
-    foreground_first_minute_per_queue_type_task_duration_reporter_.RecordTask(
+    per_queue_type_reporters_.foreground_first_minute.RecordTask(
         queue_type, DurationOfIntervalOverlap(
                         start_time, end_time, foregrounded_at,
                         foregrounded_at + base::TimeDelta::FromMinutes(1)));
 
-    foreground_second_minute_per_queue_type_task_duration_reporter_.RecordTask(
+    per_queue_type_reporters_.foreground_second_minute.RecordTask(
         queue_type, DurationOfIntervalOverlap(
                         start_time, end_time,
                         foregrounded_at + base::TimeDelta::FromMinutes(1),
                         foregrounded_at + base::TimeDelta::FromMinutes(2)));
 
-    foreground_third_minute_per_queue_type_task_duration_reporter_.RecordTask(
+    per_queue_type_reporters_.foreground_third_minute.RecordTask(
         queue_type, DurationOfIntervalOverlap(
                         start_time, end_time,
                         foregrounded_at + base::TimeDelta::FromMinutes(2),
                         foregrounded_at + base::TimeDelta::FromMinutes(3)));
 
-    foreground_after_third_minute_per_queue_type_task_duration_reporter_
-        .RecordTask(
-            queue_type,
-            DurationOfIntervalOverlap(
-                start_time, end_time,
-                foregrounded_at + base::TimeDelta::FromMinutes(3),
-                std::max(foregrounded_at + base::TimeDelta::FromMinutes(3),
-                         end_time)));
+    per_queue_type_reporters_.foreground_after_third_minute.RecordTask(
+        queue_type,
+        DurationOfIntervalOverlap(
+            start_time, end_time,
+            foregrounded_at + base::TimeDelta::FromMinutes(3),
+            std::max(foregrounded_at + base::TimeDelta::FromMinutes(3),
+                     end_time)));
 
     foreground_per_task_type_duration_reporter_.RecordTask(task_type, duration);
   }
 
   if (renderer_scheduler_->main_thread_only().renderer_hidden) {
-    hidden_per_queue_type_task_duration_reporter_.RecordTask(queue_type,
-                                                             duration);
+    per_queue_type_reporters_.hidden.RecordTask(queue_type, duration);
 
     if (renderer_scheduler_->ShouldDisableThrottlingBecauseOfAudio(
             start_time)) {
-      hidden_music_per_queue_type_task_duration_reporter_.RecordTask(queue_type,
-                                                                     duration);
+      per_queue_type_reporters_.hidden_music.RecordTask(queue_type, duration);
     }
   } else {
-    visible_per_queue_type_task_duration_reporter_.RecordTask(queue_type,
-                                                              duration);
+    per_queue_type_reporters_.visible.RecordTask(queue_type, duration);
   }
 
   FrameStatus frame_status =
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper.h b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper.h
index fee4ab09..304e7ff8 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper.h
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper.h
@@ -83,37 +83,30 @@
   using TaskDurationPerQueueTypeMetricReporter =
       TaskDurationMetricReporter<MainThreadTaskQueue::QueueType>;
 
-  TaskDurationPerQueueTypeMetricReporter per_queue_type_task_duration_reporter_;
-  TaskDurationPerQueueTypeMetricReporter
-      foreground_per_queue_type_task_duration_reporter_;
-  TaskDurationPerQueueTypeMetricReporter
-      foreground_first_minute_per_queue_type_task_duration_reporter_;
-  TaskDurationPerQueueTypeMetricReporter
-      foreground_second_minute_per_queue_type_task_duration_reporter_;
-  TaskDurationPerQueueTypeMetricReporter
-      foreground_third_minute_per_queue_type_task_duration_reporter_;
-  TaskDurationPerQueueTypeMetricReporter
-      foreground_after_third_minute_per_queue_type_task_duration_reporter_;
-  TaskDurationPerQueueTypeMetricReporter
-      background_per_queue_type_task_duration_reporter_;
-  TaskDurationPerQueueTypeMetricReporter
-      background_first_minute_per_queue_type_task_duration_reporter_;
-  TaskDurationPerQueueTypeMetricReporter
-      background_second_minute_per_queue_type_task_duration_reporter_;
-  TaskDurationPerQueueTypeMetricReporter
-      background_third_minute_per_queue_type_task_duration_reporter_;
-  TaskDurationPerQueueTypeMetricReporter
-      background_fourth_minute_per_queue_type_task_duration_reporter_;
-  TaskDurationPerQueueTypeMetricReporter
-      background_fifth_minute_per_queue_type_task_duration_reporter_;
-  TaskDurationPerQueueTypeMetricReporter
-      background_after_fifth_minute_per_queue_type_task_duration_reporter_;
-  TaskDurationPerQueueTypeMetricReporter
-      hidden_per_queue_type_task_duration_reporter_;
-  TaskDurationPerQueueTypeMetricReporter
-      visible_per_queue_type_task_duration_reporter_;
-  TaskDurationPerQueueTypeMetricReporter
-      hidden_music_per_queue_type_task_duration_reporter_;
+  struct PerQueueTypeDurationReporters {
+    PerQueueTypeDurationReporters();
+
+    TaskDurationPerQueueTypeMetricReporter overall;
+    TaskDurationPerQueueTypeMetricReporter foreground;
+    TaskDurationPerQueueTypeMetricReporter foreground_first_minute;
+    TaskDurationPerQueueTypeMetricReporter foreground_second_minute;
+    TaskDurationPerQueueTypeMetricReporter foreground_third_minute;
+    TaskDurationPerQueueTypeMetricReporter foreground_after_third_minute;
+    TaskDurationPerQueueTypeMetricReporter background;
+    TaskDurationPerQueueTypeMetricReporter background_first_minute;
+    TaskDurationPerQueueTypeMetricReporter background_second_minute;
+    TaskDurationPerQueueTypeMetricReporter background_third_minute;
+    TaskDurationPerQueueTypeMetricReporter background_fourth_minute;
+    TaskDurationPerQueueTypeMetricReporter background_fifth_minute;
+    TaskDurationPerQueueTypeMetricReporter background_after_fifth_minute;
+    TaskDurationPerQueueTypeMetricReporter
+        background_keep_active_after_fifth_minute;
+    TaskDurationPerQueueTypeMetricReporter hidden;
+    TaskDurationPerQueueTypeMetricReporter visible;
+    TaskDurationPerQueueTypeMetricReporter hidden_music;
+  };
+
+  PerQueueTypeDurationReporters per_queue_type_reporters_;
 
   TaskDurationMetricReporter<FrameStatus> per_frame_status_duration_reporter_;
 
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper_unittest.cc
index ceeecea..347e704 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_metrics_helper_unittest.cc
@@ -9,10 +9,10 @@
 #include "base/test/histogram_tester.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "components/viz/test/ordered_simple_task_runner.h"
-#include "platform/WebFrameScheduler.h"
+#include "platform/FrameScheduler.h"
 #include "platform/scheduler/renderer/renderer_scheduler_impl.h"
+#include "platform/scheduler/test/fake_frame_scheduler.h"
 #include "platform/scheduler/test/fake_page_scheduler.h"
-#include "platform/scheduler/test/fake_web_frame_scheduler.h"
 #include "platform/scheduler/test/task_queue_manager_for_test.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -77,7 +77,7 @@
                                        start + duration, base::nullopt);
   }
 
-  void RunTask(WebFrameScheduler* scheduler,
+  void RunTask(FrameScheduler* scheduler,
                base::TimeTicks start,
                base::TimeDelta duration) {
     DCHECK_LE(clock_.NowTicks(), start);
@@ -113,104 +113,104 @@
 
   void ForceUpdatePolicy() { scheduler_->ForceUpdatePolicy(); }
 
-  std::unique_ptr<FakeWebFrameScheduler> CreateFakeWebFrameSchedulerWithType(
+  std::unique_ptr<FakeFrameScheduler> CreateFakeFrameSchedulerWithType(
       FrameStatus frame_status) {
-    FakeWebFrameScheduler::Builder builder;
+    FakeFrameScheduler::Builder builder;
     switch (frame_status) {
       case FrameStatus::kNone:
       case FrameStatus::kDetached:
         return nullptr;
       case FrameStatus::kMainFrameVisible:
-        builder.SetFrameType(WebFrameScheduler::FrameType::kMainFrame)
+        builder.SetFrameType(FrameScheduler::FrameType::kMainFrame)
             .SetIsPageVisible(true)
             .SetIsFrameVisible(true);
         break;
       case FrameStatus::kMainFrameVisibleService:
-        builder.SetFrameType(WebFrameScheduler::FrameType::kMainFrame)
+        builder.SetFrameType(FrameScheduler::FrameType::kMainFrame)
             .SetPageScheduler(playing_view_.get())
             .SetIsFrameVisible(true);
         break;
       case FrameStatus::kMainFrameHidden:
-        builder.SetFrameType(WebFrameScheduler::FrameType::kMainFrame)
+        builder.SetFrameType(FrameScheduler::FrameType::kMainFrame)
             .SetIsPageVisible(true);
         break;
       case FrameStatus::kMainFrameHiddenService:
-        builder.SetFrameType(WebFrameScheduler::FrameType::kMainFrame)
+        builder.SetFrameType(FrameScheduler::FrameType::kMainFrame)
             .SetPageScheduler(playing_view_.get());
         break;
       case FrameStatus::kMainFrameBackground:
-        builder.SetFrameType(WebFrameScheduler::FrameType::kMainFrame);
+        builder.SetFrameType(FrameScheduler::FrameType::kMainFrame);
         break;
       case FrameStatus::kMainFrameBackgroundExemptSelf:
-        builder.SetFrameType(WebFrameScheduler::FrameType::kMainFrame)
+        builder.SetFrameType(FrameScheduler::FrameType::kMainFrame)
             .SetIsExemptFromThrottling(true);
         break;
       case FrameStatus::kMainFrameBackgroundExemptOther:
-        builder.SetFrameType(WebFrameScheduler::FrameType::kMainFrame)
+        builder.SetFrameType(FrameScheduler::FrameType::kMainFrame)
             .SetPageScheduler(throtting_exempt_view_.get());
         break;
       case FrameStatus::kSameOriginVisible:
-        builder.SetFrameType(WebFrameScheduler::FrameType::kSubframe)
+        builder.SetFrameType(FrameScheduler::FrameType::kSubframe)
             .SetIsPageVisible(true)
             .SetIsFrameVisible(true);
         break;
       case FrameStatus::kSameOriginVisibleService:
-        builder.SetFrameType(WebFrameScheduler::FrameType::kSubframe)
+        builder.SetFrameType(FrameScheduler::FrameType::kSubframe)
             .SetPageScheduler(playing_view_.get())
             .SetIsFrameVisible(true);
         break;
       case FrameStatus::kSameOriginHidden:
-        builder.SetFrameType(WebFrameScheduler::FrameType::kSubframe)
+        builder.SetFrameType(FrameScheduler::FrameType::kSubframe)
             .SetIsPageVisible(true);
         break;
       case FrameStatus::kSameOriginHiddenService:
-        builder.SetFrameType(WebFrameScheduler::FrameType::kSubframe)
+        builder.SetFrameType(FrameScheduler::FrameType::kSubframe)
             .SetPageScheduler(playing_view_.get());
         break;
       case FrameStatus::kSameOriginBackground:
-        builder.SetFrameType(WebFrameScheduler::FrameType::kSubframe);
+        builder.SetFrameType(FrameScheduler::FrameType::kSubframe);
         break;
       case FrameStatus::kSameOriginBackgroundExemptSelf:
-        builder.SetFrameType(WebFrameScheduler::FrameType::kSubframe)
+        builder.SetFrameType(FrameScheduler::FrameType::kSubframe)
             .SetIsExemptFromThrottling(true);
         break;
       case FrameStatus::kSameOriginBackgroundExemptOther:
-        builder.SetFrameType(WebFrameScheduler::FrameType::kSubframe)
+        builder.SetFrameType(FrameScheduler::FrameType::kSubframe)
             .SetPageScheduler(throtting_exempt_view_.get());
         break;
       case FrameStatus::kCrossOriginVisible:
-        builder.SetFrameType(WebFrameScheduler::FrameType::kSubframe)
+        builder.SetFrameType(FrameScheduler::FrameType::kSubframe)
             .SetIsCrossOrigin(true)
             .SetIsPageVisible(true)
             .SetIsFrameVisible(true);
         break;
       case FrameStatus::kCrossOriginVisibleService:
-        builder.SetFrameType(WebFrameScheduler::FrameType::kSubframe)
+        builder.SetFrameType(FrameScheduler::FrameType::kSubframe)
             .SetIsCrossOrigin(true)
             .SetPageScheduler(playing_view_.get())
             .SetIsFrameVisible(true);
         break;
       case FrameStatus::kCrossOriginHidden:
-        builder.SetFrameType(WebFrameScheduler::FrameType::kSubframe)
+        builder.SetFrameType(FrameScheduler::FrameType::kSubframe)
             .SetIsCrossOrigin(true)
             .SetIsPageVisible(true);
         break;
       case FrameStatus::kCrossOriginHiddenService:
-        builder.SetFrameType(WebFrameScheduler::FrameType::kSubframe)
+        builder.SetFrameType(FrameScheduler::FrameType::kSubframe)
             .SetIsCrossOrigin(true)
             .SetPageScheduler(playing_view_.get());
         break;
       case FrameStatus::kCrossOriginBackground:
-        builder.SetFrameType(WebFrameScheduler::FrameType::kSubframe)
+        builder.SetFrameType(FrameScheduler::FrameType::kSubframe)
             .SetIsCrossOrigin(true);
         break;
       case FrameStatus::kCrossOriginBackgroundExemptSelf:
-        builder.SetFrameType(WebFrameScheduler::FrameType::kSubframe)
+        builder.SetFrameType(FrameScheduler::FrameType::kSubframe)
             .SetIsCrossOrigin(true)
             .SetIsExemptFromThrottling(true);
         break;
       case FrameStatus::kCrossOriginBackgroundExemptOther:
-        builder.SetFrameType(WebFrameScheduler::FrameType::kSubframe)
+        builder.SetFrameType(FrameScheduler::FrameType::kSubframe)
             .SetIsCrossOrigin(true)
             .SetPageScheduler(throtting_exempt_view_.get());
         break;
@@ -385,8 +385,8 @@
       FrameStatus::kCrossOriginHiddenService,
       FrameStatus::kMainFrameBackgroundExemptOther};
   for (FrameStatus frame_status : frame_statuses_tested) {
-    std::unique_ptr<FakeWebFrameScheduler> frame =
-        CreateFakeWebFrameSchedulerWithType(frame_status);
+    std::unique_ptr<FakeFrameScheduler> frame =
+        CreateFakeFrameSchedulerWithType(frame_status);
     EXPECT_EQ(GetFrameStatus(frame.get()), frame_status);
   }
 }
@@ -485,8 +485,8 @@
       {FrameStatus::kSameOriginVisibleService, 6}};
 
   for (const auto& data : test_data) {
-    std::unique_ptr<FakeWebFrameScheduler> frame =
-        CreateFakeWebFrameSchedulerWithType(data.frame_status);
+    std::unique_ptr<FakeFrameScheduler> frame =
+        CreateFakeFrameSchedulerWithType(data.frame_status);
     for (int i = 0; i < data.count; ++i) {
       RunTask(frame.get(), Milliseconds(++task_count),
               base::TimeDelta::FromMicroseconds(100));
@@ -528,8 +528,8 @@
   };
 
   for (const auto& data : test_data) {
-    std::unique_ptr<FakeWebFrameScheduler> frame =
-        CreateFakeWebFrameSchedulerWithType(data.frame_status);
+    std::unique_ptr<FakeFrameScheduler> frame =
+        CreateFakeFrameSchedulerWithType(data.frame_status);
     for (size_t i = 0; i < data.durations.size(); ++i) {
       RunTask(frame.get(), Milliseconds(++total_duration),
               base::TimeDelta::FromMilliseconds(data.durations[i]));
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc
index dd1e665..50f946c 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl.cc
@@ -97,14 +97,6 @@
   }
 }
 
-const char* YesNoStateToString(bool is_yes) {
-  if (is_yes) {
-    return "yes";
-  } else {
-    return "no";
-  }
-}
-
 const char* RendererProcessTypeToString(RendererProcessType process_type) {
   switch (process_type) {
     case RendererProcessType::kRenderer:
@@ -116,10 +108,6 @@
   return "";  // MSVC needs that.
 }
 
-bool StopLoadingInBackgroundEnabled() {
-  return RuntimeEnabledFeatures::StopLoadingInBackgroundEnabled();
-}
-
 const char* TaskTypeToString(TaskType task_type) {
   switch (task_type) {
     case TaskType::kDeprecatedNone:
@@ -721,7 +709,8 @@
   return NewTaskQueue(
       MainThreadTaskQueue::QueueCreationParams(queue_type)
           .SetCanBePaused(true)
-          .SetCanBeStopped(StopLoadingInBackgroundEnabled())
+          .SetCanBeStopped(
+              RuntimeEnabledFeatures::StopLoadingInBackgroundEnabled())
           .SetCanBeDeferred(true)
           .SetUsedForImportantTasks(
               queue_type ==
@@ -1543,7 +1532,7 @@
 
   if (main_thread_only().stopped_when_backgrounded) {
     new_policy.timer_queue_policy().is_stopped = true;
-    if (StopLoadingInBackgroundEnabled())
+    if (RuntimeEnabledFeatures::StopLoadingInBackgroundEnabled())
       new_policy.loading_queue_policy().is_stopped = true;
   }
   if (main_thread_only().renderer_pause_count != 0) {
@@ -2160,6 +2149,8 @@
     return false;
   if (is_blocked && task_queue->CanBeDeferred())
     return false;
+  // TODO(panicker): Remove this, as it is redundant as we stop per-frame
+  // task_queues in WebFrameScheduler
   if (is_stopped && task_queue->CanBeStopped())
     return false;
   return true;
@@ -2363,7 +2354,7 @@
   // may still enter a more specific blame context if necessary.
   //
   // Per-frame task runners (loading, timers, etc.) are configured with a more
-  // specific blame context by WebFrameSchedulerImpl.
+  // specific blame context by FrameSchedulerImpl.
   //
   // TODO(altimin): automatically enter top-level for all task queues associated
   // with renderer scheduler which do not have a corresponding frame.
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc
index 58bf04b..8d18ec5 100644
--- a/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc
+++ b/third_party/WebKit/Source/platform/scheduler/renderer/renderer_scheduler_impl_unittest.cc
@@ -22,7 +22,7 @@
 #include "platform/scheduler/child/features.h"
 #include "platform/scheduler/common/throttling/budget_pool.h"
 #include "platform/scheduler/renderer/auto_advancing_virtual_time_domain.h"
-#include "platform/scheduler/renderer/web_frame_scheduler_impl.h"
+#include "platform/scheduler/renderer/frame_scheduler_impl.h"
 #include "platform/scheduler/test/task_queue_manager_for_test.h"
 #include "platform/testing/runtime_enabled_features_test_helpers.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -728,7 +728,7 @@
   }
 
   static scoped_refptr<TaskQueue> ThrottableTaskQueue(
-      WebFrameSchedulerImpl* scheduler) {
+      FrameSchedulerImpl* scheduler) {
     return scheduler->ThrottleableTaskQueue();
   }
 
@@ -3806,14 +3806,14 @@
                             false /* disable_background_timer_throttling */));
   scheduler_->AddPageScheduler(page_scheduler.get());
 
-  std::unique_ptr<WebFrameSchedulerImpl> web_frame_scheduler =
-      page_scheduler->CreateWebFrameSchedulerImpl(
-          nullptr, WebFrameScheduler::FrameType::kSubframe);
+  std::unique_ptr<FrameSchedulerImpl> frame_scheduler =
+      page_scheduler->CreateFrameSchedulerImpl(
+          nullptr, FrameScheduler::FrameType::kSubframe);
 
-  TaskQueue* timer_tq = ThrottableTaskQueue(web_frame_scheduler.get()).get();
+  TaskQueue* timer_tq = ThrottableTaskQueue(frame_scheduler.get()).get();
 
-  web_frame_scheduler->SetCrossOrigin(true);
-  web_frame_scheduler->SetFrameVisible(false);
+  frame_scheduler->SetCrossOrigin(true);
+  frame_scheduler->SetFrameVisible(false);
   EXPECT_TRUE(scheduler_->task_queue_throttler()->IsThrottled(timer_tq));
 
   scheduler_->EnableVirtualTime(
@@ -3895,9 +3895,9 @@
       base::WrapUnique(new PageSchedulerImpl(nullptr, scheduler_.get(), false));
   scheduler_->AddPageScheduler(page_scheduler1.get());
 
-  std::unique_ptr<WebFrameSchedulerImpl> web_frame_scheduler =
-      page_scheduler1->CreateWebFrameSchedulerImpl(
-          nullptr, WebFrameScheduler::FrameType::kSubframe);
+  std::unique_ptr<FrameSchedulerImpl> frame_scheduler =
+      page_scheduler1->CreateFrameSchedulerImpl(
+          nullptr, FrameScheduler::FrameType::kSubframe);
 
   std::unique_ptr<PageSchedulerImpl> page_scheduler2 =
       base::WrapUnique(new PageSchedulerImpl(nullptr, scheduler_.get(), false));
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl.cc b/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl.cc
deleted file mode 100644
index 95c223ff..0000000
--- a/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl.cc
+++ /dev/null
@@ -1,595 +0,0 @@
-// Copyright 2015 The Chromium Authors. ();All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "platform/scheduler/renderer/web_frame_scheduler_impl.h"
-
-#include <memory>
-#include "base/metrics/histogram_macros.h"
-#include "base/trace_event/blame_context.h"
-#include "platform/runtime_enabled_features.h"
-#include "platform/scheduler/base/real_time_domain.h"
-#include "platform/scheduler/base/virtual_time_domain.h"
-#include "platform/scheduler/child/default_params.h"
-#include "platform/scheduler/child/page_visibility_state.h"
-#include "platform/scheduler/child/task_runner_impl.h"
-#include "platform/scheduler/child/worker_scheduler_proxy.h"
-#include "platform/scheduler/common/throttling/budget_pool.h"
-#include "platform/scheduler/renderer/auto_advancing_virtual_time_domain.h"
-#include "platform/scheduler/renderer/page_scheduler_impl.h"
-#include "platform/scheduler/renderer/renderer_scheduler_impl.h"
-#include "platform/scheduler/util/tracing_helper.h"
-#include "public/platform/BlameContext.h"
-#include "public/platform/WebString.h"
-
-namespace blink {
-namespace scheduler {
-
-namespace {
-
-const char* VisibilityStateToString(bool is_visible) {
-  if (is_visible) {
-    return "visible";
-  } else {
-    return "hidden";
-  }
-}
-
-const char* PausedStateToString(bool is_paused) {
-  if (is_paused) {
-    return "paused";
-  } else {
-    return "running";
-  }
-}
-
-const char* FrozenStateToString(bool is_frozen) {
-  if (is_frozen) {
-    return "frozen";
-  } else {
-    return "running";
-  }
-}
-
-const char* CrossOriginStateToString(bool is_cross_origin) {
-  if (is_cross_origin) {
-    return "cross-origin";
-  } else {
-    return "same-origin";
-  }
-}
-
-bool StopNonTimersInBackgroundEnabled() {
-  return RuntimeEnabledFeatures::StopNonTimersInBackgroundEnabled();
-}
-
-}  // namespace
-
-WebFrameSchedulerImpl::ActiveConnectionHandleImpl::ActiveConnectionHandleImpl(
-    WebFrameSchedulerImpl* frame_scheduler)
-    : frame_scheduler_(frame_scheduler->GetWeakPtr()) {
-  frame_scheduler->DidOpenActiveConnection();
-}
-
-WebFrameSchedulerImpl::ActiveConnectionHandleImpl::
-    ~ActiveConnectionHandleImpl() {
-  if (frame_scheduler_)
-    frame_scheduler_->DidCloseActiveConnection();
-}
-
-WebFrameSchedulerImpl::ThrottlingObserverHandleImpl::
-    ThrottlingObserverHandleImpl(WebFrameSchedulerImpl* frame_scheduler,
-                                 Observer* observer)
-    : frame_scheduler_(frame_scheduler->GetWeakPtr()), observer_(observer) {}
-
-WebFrameSchedulerImpl::ThrottlingObserverHandleImpl::
-    ~ThrottlingObserverHandleImpl() {
-  if (frame_scheduler_)
-    frame_scheduler_->RemoveThrottlingObserver(observer_);
-}
-
-WebFrameSchedulerImpl::WebFrameSchedulerImpl(
-    RendererSchedulerImpl* renderer_scheduler,
-    PageSchedulerImpl* parent_page_scheduler,
-    base::trace_event::BlameContext* blame_context,
-    WebFrameScheduler::FrameType frame_type)
-    : renderer_scheduler_(renderer_scheduler),
-      parent_page_scheduler_(parent_page_scheduler),
-      blame_context_(blame_context),
-      throttling_state_(WebFrameScheduler::ThrottlingState::kNotThrottled),
-      frame_visible_(true,
-                     "WebFrameScheduler.FrameVisible",
-                     this,
-                     &tracing_controller_,
-                     VisibilityStateToString),
-      page_visibility_(kDefaultPageVisibility,
-                       "WebFrameScheduler.PageVisibility",
-                       this,
-                       &tracing_controller_,
-                       PageVisibilityStateToString),
-      page_frozen_(false,
-                   "WebFrameScheduler.PageFrozen",
-                   this,
-                   &tracing_controller_,
-                   FrozenStateToString),
-      frame_paused_(false,
-                    "WebFrameScheduler.FramePaused",
-                    this,
-                    &tracing_controller_,
-                    PausedStateToString),
-      cross_origin_(false,
-                    "WebFrameScheduler.Origin",
-                    this,
-                    &tracing_controller_,
-                    CrossOriginStateToString),
-      url_tracer_("WebFrameScheduler.URL", this),
-      frame_type_(frame_type),
-      active_connection_count_(0),
-      weak_factory_(this) {
-  DCHECK_EQ(throttling_state_, CalculateThrottlingState());
-}
-
-namespace {
-
-void CleanUpQueue(MainThreadTaskQueue* queue) {
-  if (!queue)
-    return;
-  queue->DetachFromRendererScheduler();
-  queue->SetFrameScheduler(nullptr);
-  queue->SetBlameContext(nullptr);
-  queue->SetQueuePriority(TaskQueue::QueuePriority::kLowPriority);
-}
-
-}  // namespace
-
-WebFrameSchedulerImpl::~WebFrameSchedulerImpl() {
-  weak_factory_.InvalidateWeakPtrs();
-
-  RemoveThrottleableQueueFromBackgroundCPUTimeBudgetPool();
-
-  CleanUpQueue(loading_task_queue_.get());
-  CleanUpQueue(loading_control_task_queue_.get());
-  CleanUpQueue(throttleable_task_queue_.get());
-  CleanUpQueue(deferrable_task_queue_.get());
-  CleanUpQueue(pausable_task_queue_.get());
-  CleanUpQueue(unpausable_task_queue_.get());
-
-  if (parent_page_scheduler_) {
-    parent_page_scheduler_->Unregister(this);
-
-    if (active_connection_count_)
-      parent_page_scheduler_->OnConnectionUpdated();
-  }
-}
-
-void WebFrameSchedulerImpl::DetachFromPageScheduler() {
-  RemoveThrottleableQueueFromBackgroundCPUTimeBudgetPool();
-
-  parent_page_scheduler_ = nullptr;
-}
-
-void WebFrameSchedulerImpl::
-    RemoveThrottleableQueueFromBackgroundCPUTimeBudgetPool() {
-  if (!throttleable_task_queue_)
-    return;
-
-  if (!parent_page_scheduler_)
-    return;
-
-  CPUTimeBudgetPool* time_budget_pool =
-      parent_page_scheduler_->BackgroundCPUTimeBudgetPool();
-
-  if (!time_budget_pool)
-    return;
-
-  time_budget_pool->RemoveQueue(renderer_scheduler_->tick_clock()->NowTicks(),
-                                throttleable_task_queue_.get());
-}
-
-std::unique_ptr<WebFrameScheduler::ThrottlingObserverHandle>
-WebFrameSchedulerImpl::AddThrottlingObserver(ObserverType type,
-                                             Observer* observer) {
-  DCHECK(observer);
-  observer->OnThrottlingStateChanged(CalculateThrottlingState());
-  loader_observers_.insert(observer);
-  return std::make_unique<ThrottlingObserverHandleImpl>(this, observer);
-}
-
-void WebFrameSchedulerImpl::RemoveThrottlingObserver(Observer* observer) {
-  DCHECK(observer);
-  const auto found = loader_observers_.find(observer);
-  DCHECK(loader_observers_.end() != found);
-  loader_observers_.erase(found);
-}
-
-void WebFrameSchedulerImpl::SetFrameVisible(bool frame_visible) {
-  DCHECK(parent_page_scheduler_);
-  if (frame_visible_ == frame_visible)
-    return;
-  UMA_HISTOGRAM_BOOLEAN("RendererScheduler.IPC.FrameVisibility", frame_visible);
-  bool was_throttled = ShouldThrottleTimers();
-  frame_visible_ = frame_visible;
-  UpdateThrottling(was_throttled);
-}
-
-bool WebFrameSchedulerImpl::IsFrameVisible() const {
-  return frame_visible_;
-}
-
-void WebFrameSchedulerImpl::SetCrossOrigin(bool cross_origin) {
-  DCHECK(parent_page_scheduler_);
-  if (cross_origin_ == cross_origin)
-    return;
-  bool was_throttled = ShouldThrottleTimers();
-  cross_origin_ = cross_origin;
-  UpdateThrottling(was_throttled);
-}
-
-bool WebFrameSchedulerImpl::IsCrossOrigin() const {
-  return cross_origin_;
-}
-
-void WebFrameSchedulerImpl::TraceUrlChange(const String& url) {
-  url_tracer_.TraceString(url);
-}
-
-WebFrameScheduler::FrameType WebFrameSchedulerImpl::GetFrameType() const {
-  return frame_type_;
-}
-
-scoped_refptr<base::SingleThreadTaskRunner>
-WebFrameSchedulerImpl::GetTaskRunner(TaskType type) {
-  // TODO(haraken): Optimize the mapping from TaskTypes to task runners.
-  switch (type) {
-    case TaskType::kJavascriptTimer:
-      return TaskRunnerImpl::Create(ThrottleableTaskQueue(), type);
-    case TaskType::kUnspecedLoading:
-    case TaskType::kNetworking:
-      return TaskRunnerImpl::Create(LoadingTaskQueue(), type);
-    case TaskType::kNetworkingControl:
-      return TaskRunnerImpl::Create(LoadingControlTaskQueue(), type);
-    // Throttling following tasks may break existing web pages, so tentatively
-    // these are unthrottled.
-    // TODO(nhiroki): Throttle them again after we're convinced that it's safe
-    // or provide a mechanism that web pages can opt-out it if throttling is not
-    // desirable.
-    case TaskType::kDatabaseAccess:
-    case TaskType::kDOMManipulation:
-    case TaskType::kHistoryTraversal:
-    case TaskType::kEmbed:
-    case TaskType::kCanvasBlobSerialization:
-    case TaskType::kRemoteEvent:
-    case TaskType::kWebSocket:
-    case TaskType::kMicrotask:
-    case TaskType::kUnshippedPortMessage:
-    case TaskType::kFileReading:
-    case TaskType::kPresentation:
-    case TaskType::kSensor:
-    case TaskType::kPerformanceTimeline:
-    case TaskType::kWebGL:
-    case TaskType::kIdleTask:
-    case TaskType::kUnspecedTimer:
-    case TaskType::kMiscPlatformAPI:
-      // TODO(altimin): Move appropriate tasks to throttleable task queue.
-      return TaskRunnerImpl::Create(DeferrableTaskQueue(), type);
-    // PostedMessage can be used for navigation, so we shouldn't defer it
-    // when expecting a user gesture.
-    case TaskType::kPostedMessage:
-    // UserInteraction tasks should be run even when expecting a user gesture.
-    case TaskType::kUserInteraction:
-    // Media events should not be deferred to ensure that media playback is
-    // smooth.
-    case TaskType::kMediaElementEvent:
-    case TaskType::kInternalIndexedDB:
-    case TaskType::kInternalMedia:
-    case TaskType::kInternalMediaRealTime:
-      return TaskRunnerImpl::Create(PausableTaskQueue(), type);
-    case TaskType::kUnthrottled:
-    case TaskType::kInternalTest:
-    case TaskType::kInternalWebCrypto:
-    case TaskType::kInternalIPC:
-      return TaskRunnerImpl::Create(UnpausableTaskQueue(), type);
-    case TaskType::kDeprecatedNone:
-    case TaskType::kCount:
-      NOTREACHED();
-      break;
-  }
-  NOTREACHED();
-  return nullptr;
-}
-
-scoped_refptr<TaskQueue> WebFrameSchedulerImpl::LoadingTaskQueue() {
-  DCHECK(parent_page_scheduler_);
-  if (!loading_task_queue_) {
-    loading_task_queue_ = renderer_scheduler_->NewLoadingTaskQueue(
-        MainThreadTaskQueue::QueueType::kFrameLoading);
-    loading_task_queue_->SetBlameContext(blame_context_);
-    loading_task_queue_->SetFrameScheduler(this);
-    loading_queue_enabled_voter_ =
-        loading_task_queue_->CreateQueueEnabledVoter();
-    loading_queue_enabled_voter_->SetQueueEnabled(!frame_paused_);
-  }
-  return loading_task_queue_;
-}
-
-scoped_refptr<TaskQueue> WebFrameSchedulerImpl::LoadingControlTaskQueue() {
-  DCHECK(parent_page_scheduler_);
-  if (!loading_control_task_queue_) {
-    loading_control_task_queue_ = renderer_scheduler_->NewLoadingTaskQueue(
-        MainThreadTaskQueue::QueueType::kFrameLoadingControl);
-    loading_control_task_queue_->SetBlameContext(blame_context_);
-    loading_control_task_queue_->SetFrameScheduler(this);
-    loading_control_queue_enabled_voter_ =
-        loading_control_task_queue_->CreateQueueEnabledVoter();
-    loading_control_queue_enabled_voter_->SetQueueEnabled(!frame_paused_);
-  }
-  return loading_control_task_queue_;
-}
-
-scoped_refptr<TaskQueue> WebFrameSchedulerImpl::ThrottleableTaskQueue() {
-  DCHECK(parent_page_scheduler_);
-  if (!throttleable_task_queue_) {
-    throttleable_task_queue_ = renderer_scheduler_->NewTaskQueue(
-        MainThreadTaskQueue::QueueCreationParams(
-            MainThreadTaskQueue::QueueType::kFrameThrottleable)
-            .SetCanBeThrottled(true)
-            .SetCanBeStopped(true)
-            .SetCanBeDeferred(true)
-            .SetCanBePaused(true));
-    throttleable_task_queue_->SetBlameContext(blame_context_);
-    throttleable_task_queue_->SetFrameScheduler(this);
-    throttleable_queue_enabled_voter_ =
-        throttleable_task_queue_->CreateQueueEnabledVoter();
-    throttleable_queue_enabled_voter_->SetQueueEnabled(!frame_paused_);
-
-    CPUTimeBudgetPool* time_budget_pool =
-        parent_page_scheduler_->BackgroundCPUTimeBudgetPool();
-    if (time_budget_pool) {
-      time_budget_pool->AddQueue(renderer_scheduler_->tick_clock()->NowTicks(),
-                                 throttleable_task_queue_.get());
-    }
-
-    if (ShouldThrottleTimers()) {
-      renderer_scheduler_->task_queue_throttler()->IncreaseThrottleRefCount(
-          throttleable_task_queue_.get());
-    }
-  }
-  return throttleable_task_queue_;
-}
-
-scoped_refptr<TaskQueue> WebFrameSchedulerImpl::DeferrableTaskQueue() {
-  DCHECK(parent_page_scheduler_);
-  if (!deferrable_task_queue_) {
-    deferrable_task_queue_ = renderer_scheduler_->NewTaskQueue(
-        MainThreadTaskQueue::QueueCreationParams(
-            MainThreadTaskQueue::QueueType::kFrameThrottleable)
-            .SetCanBeDeferred(true)
-            .SetCanBeStopped(StopNonTimersInBackgroundEnabled())
-            .SetCanBePaused(true));
-    deferrable_task_queue_->SetBlameContext(blame_context_);
-    deferrable_task_queue_->SetFrameScheduler(this);
-    deferrable_queue_enabled_voter_ =
-        deferrable_task_queue_->CreateQueueEnabledVoter();
-    deferrable_queue_enabled_voter_->SetQueueEnabled(!frame_paused_);
-  }
-  return deferrable_task_queue_;
-}
-
-scoped_refptr<TaskQueue> WebFrameSchedulerImpl::PausableTaskQueue() {
-  DCHECK(parent_page_scheduler_);
-  if (!pausable_task_queue_) {
-    pausable_task_queue_ = renderer_scheduler_->NewTaskQueue(
-        MainThreadTaskQueue::QueueCreationParams(
-            MainThreadTaskQueue::QueueType::kFramePausable)
-            .SetCanBeStopped(StopNonTimersInBackgroundEnabled())
-            .SetCanBePaused(true));
-    pausable_task_queue_->SetBlameContext(blame_context_);
-    pausable_task_queue_->SetFrameScheduler(this);
-    pausable_queue_enabled_voter_ =
-        pausable_task_queue_->CreateQueueEnabledVoter();
-    pausable_queue_enabled_voter_->SetQueueEnabled(!frame_paused_);
-  }
-  return pausable_task_queue_;
-}
-
-scoped_refptr<TaskQueue> WebFrameSchedulerImpl::UnpausableTaskQueue() {
-  DCHECK(parent_page_scheduler_);
-  if (!unpausable_task_queue_) {
-    unpausable_task_queue_ = renderer_scheduler_->NewTaskQueue(
-        MainThreadTaskQueue::QueueCreationParams(
-            MainThreadTaskQueue::QueueType::kFrameUnpausable));
-    unpausable_task_queue_->SetBlameContext(blame_context_);
-    unpausable_task_queue_->SetFrameScheduler(this);
-  }
-  return unpausable_task_queue_;
-}
-
-scoped_refptr<TaskQueue> WebFrameSchedulerImpl::ControlTaskQueue() {
-  DCHECK(parent_page_scheduler_);
-  return renderer_scheduler_->ControlTaskQueue();
-}
-
-blink::PageScheduler* WebFrameSchedulerImpl::GetPageScheduler() const {
-  return parent_page_scheduler_;
-}
-
-void WebFrameSchedulerImpl::DidStartProvisionalLoad(bool is_main_frame) {
-  renderer_scheduler_->DidStartProvisionalLoad(is_main_frame);
-}
-
-void WebFrameSchedulerImpl::DidCommitProvisionalLoad(
-    bool is_web_history_inert_commit,
-    bool is_reload,
-    bool is_main_frame) {
-  renderer_scheduler_->DidCommitProvisionalLoad(is_web_history_inert_commit,
-                                                is_reload, is_main_frame);
-}
-
-WebScopedVirtualTimePauser
-WebFrameSchedulerImpl::CreateWebScopedVirtualTimePauser(
-    WebScopedVirtualTimePauser::VirtualTaskDuration duration) {
-  return WebScopedVirtualTimePauser(renderer_scheduler_, duration);
-}
-
-void WebFrameSchedulerImpl::DidOpenActiveConnection() {
-  ++active_connection_count_;
-  if (parent_page_scheduler_)
-    parent_page_scheduler_->OnConnectionUpdated();
-}
-
-void WebFrameSchedulerImpl::DidCloseActiveConnection() {
-  DCHECK_GT(active_connection_count_, 0);
-  --active_connection_count_;
-  if (parent_page_scheduler_)
-    parent_page_scheduler_->OnConnectionUpdated();
-}
-
-void WebFrameSchedulerImpl::AsValueInto(
-    base::trace_event::TracedValue* state) const {
-  state->SetBoolean("frame_visible", frame_visible_);
-  state->SetBoolean("page_visible",
-                    page_visibility_ == PageVisibilityState::kVisible);
-  state->SetBoolean("cross_origin", cross_origin_);
-  state->SetString("frame_type",
-                   frame_type_ == WebFrameScheduler::FrameType::kMainFrame
-                       ? "MainFrame"
-                       : "Subframe");
-  if (loading_task_queue_) {
-    state->SetString("loading_task_queue",
-                     PointerToString(loading_task_queue_.get()));
-  }
-  if (loading_control_task_queue_) {
-    state->SetString("loading_control_task_queue",
-                     PointerToString(loading_control_task_queue_.get()));
-  }
-  if (throttleable_task_queue_) {
-    state->SetString("throttleable_task_queue",
-                     PointerToString(throttleable_task_queue_.get()));
-  }
-  if (deferrable_task_queue_) {
-    state->SetString("deferrable_task_queue",
-                     PointerToString(deferrable_task_queue_.get()));
-  }
-  if (pausable_task_queue_) {
-    state->SetString("pausable_task_queue",
-                     PointerToString(pausable_task_queue_.get()));
-  }
-  if (unpausable_task_queue_) {
-    state->SetString("unpausable_task_queue",
-                     PointerToString(unpausable_task_queue_.get()));
-  }
-  if (blame_context_) {
-    state->BeginDictionary("blame_context");
-    state->SetString(
-        "id_ref",
-        PointerToString(reinterpret_cast<void*>(blame_context_->id())));
-    state->SetString("scope", blame_context_->scope());
-    state->EndDictionary();
-  }
-}
-
-void WebFrameSchedulerImpl::SetPageVisibility(
-    PageVisibilityState page_visibility) {
-  DCHECK(parent_page_scheduler_);
-  if (page_visibility_ == page_visibility)
-    return;
-  bool was_throttled = ShouldThrottleTimers();
-  page_visibility_ = page_visibility;
-  if (page_visibility_ == PageVisibilityState::kVisible)
-    page_frozen_ = false;  // visible page must not be frozen.
-  UpdateThrottling(was_throttled);
-  UpdateThrottlingState();
-}
-
-bool WebFrameSchedulerImpl::IsPageVisible() const {
-  return page_visibility_ == PageVisibilityState::kVisible;
-}
-
-void WebFrameSchedulerImpl::SetPaused(bool frame_paused) {
-  DCHECK(parent_page_scheduler_);
-  if (frame_paused_ == frame_paused)
-    return;
-
-  frame_paused_ = frame_paused;
-  if (loading_queue_enabled_voter_)
-    loading_queue_enabled_voter_->SetQueueEnabled(!frame_paused);
-  if (loading_control_queue_enabled_voter_)
-    loading_control_queue_enabled_voter_->SetQueueEnabled(!frame_paused);
-  if (throttleable_queue_enabled_voter_)
-    throttleable_queue_enabled_voter_->SetQueueEnabled(!frame_paused);
-  if (deferrable_queue_enabled_voter_)
-    deferrable_queue_enabled_voter_->SetQueueEnabled(!frame_paused);
-  if (pausable_queue_enabled_voter_)
-    pausable_queue_enabled_voter_->SetQueueEnabled(!frame_paused);
-}
-
-void WebFrameSchedulerImpl::SetPageFrozen(bool frozen) {
-  if (frozen == page_frozen_)
-    return;
-  DCHECK(page_visibility_ == PageVisibilityState::kHidden);
-  page_frozen_ = frozen;
-  UpdateThrottlingState();
-}
-
-void WebFrameSchedulerImpl::UpdateThrottlingState() {
-  WebFrameScheduler::ThrottlingState throttling_state =
-      CalculateThrottlingState();
-  if (throttling_state == throttling_state_)
-    return;
-  throttling_state_ = throttling_state;
-  for (auto observer : loader_observers_)
-    observer->OnThrottlingStateChanged(throttling_state_);
-}
-
-WebFrameScheduler::ThrottlingState
-WebFrameSchedulerImpl::CalculateThrottlingState() const {
-  if (RuntimeEnabledFeatures::StopLoadingInBackgroundEnabled() &&
-      page_frozen_) {
-    DCHECK(page_visibility_ == PageVisibilityState::kHidden);
-    return WebFrameScheduler::ThrottlingState::kStopped;
-  }
-  if (page_visibility_ == PageVisibilityState::kHidden)
-    return WebFrameScheduler::ThrottlingState::kThrottled;
-  return WebFrameScheduler::ThrottlingState::kNotThrottled;
-}
-
-void WebFrameSchedulerImpl::OnFirstMeaningfulPaint() {
-  renderer_scheduler_->OnFirstMeaningfulPaint();
-}
-
-std::unique_ptr<WebFrameScheduler::ActiveConnectionHandle>
-WebFrameSchedulerImpl::OnActiveConnectionCreated() {
-  return std::make_unique<WebFrameSchedulerImpl::ActiveConnectionHandleImpl>(
-      this);
-}
-
-bool WebFrameSchedulerImpl::ShouldThrottleTimers() const {
-  if (page_visibility_ == PageVisibilityState::kHidden)
-    return true;
-  return RuntimeEnabledFeatures::TimerThrottlingForHiddenFramesEnabled() &&
-         !frame_visible_ && cross_origin_;
-}
-
-void WebFrameSchedulerImpl::UpdateThrottling(bool was_throttled) {
-  bool should_throttle = ShouldThrottleTimers();
-  if (was_throttled == should_throttle || !throttleable_task_queue_)
-    return;
-  if (should_throttle) {
-    renderer_scheduler_->task_queue_throttler()->IncreaseThrottleRefCount(
-        throttleable_task_queue_.get());
-  } else {
-    renderer_scheduler_->task_queue_throttler()->DecreaseThrottleRefCount(
-        throttleable_task_queue_.get());
-  }
-}
-
-base::WeakPtr<WebFrameSchedulerImpl> WebFrameSchedulerImpl::GetWeakPtr() {
-  return weak_factory_.GetWeakPtr();
-}
-
-bool WebFrameSchedulerImpl::IsExemptFromBudgetBasedThrottling() const {
-  return has_active_connection();
-}
-
-}  // namespace scheduler
-}  // namespace blink
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl.h b/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl.h
deleted file mode 100644
index d41748b..0000000
--- a/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl.h
+++ /dev/null
@@ -1,181 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_WEB_FRAME_SCHEDULER_IMPL_H_
-#define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_WEB_FRAME_SCHEDULER_IMPL_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/memory/scoped_refptr.h"
-#include "base/memory/weak_ptr.h"
-#include "base/trace_event/trace_event.h"
-#include "platform/PlatformExport.h"
-#include "platform/WebFrameScheduler.h"
-#include "platform/scheduler/base/task_queue.h"
-#include "platform/scheduler/child/page_visibility_state.h"
-#include "platform/scheduler/child/worker_scheduler_proxy.h"
-#include "platform/scheduler/util/tracing_helper.h"
-
-namespace base {
-namespace trace_event {
-class BlameContext;
-class TracedValue;
-}  // namespace trace_event
-}  // namespace base
-
-namespace blink {
-namespace scheduler {
-
-class MainThreadTaskQueue;
-class PageSchedulerImpl;
-class RendererSchedulerImpl;
-class TaskQueue;
-
-namespace renderer_scheduler_impl_unittest {
-class RendererSchedulerImplTest;
-}
-
-namespace web_frame_scheduler_impl_unittest {
-class WebFrameSchedulerImplTest;
-}
-
-namespace page_scheduler_impl_unittest {
-class PageSchedulerImplTest;
-}
-
-class PLATFORM_EXPORT WebFrameSchedulerImpl : public WebFrameScheduler {
- public:
-  WebFrameSchedulerImpl(RendererSchedulerImpl* renderer_scheduler,
-                        PageSchedulerImpl* parent_page_scheduler,
-                        base::trace_event::BlameContext* blame_context,
-                        WebFrameScheduler::FrameType frame_type);
-
-  ~WebFrameSchedulerImpl() override;
-
-  // WebFrameScheduler implementation:
-  std::unique_ptr<ThrottlingObserverHandle> AddThrottlingObserver(
-      ObserverType,
-      Observer*) override;
-  void SetFrameVisible(bool frame_visible) override;
-  bool IsFrameVisible() const override;
-  bool IsPageVisible() const override;
-  void SetPaused(bool frame_paused) override;
-  void SetPageFrozen(bool) override;
-
-  void SetCrossOrigin(bool cross_origin) override;
-  bool IsCrossOrigin() const override;
-  void TraceUrlChange(const String& url) override;
-  WebFrameScheduler::FrameType GetFrameType() const override;
-  scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(TaskType) override;
-  PageScheduler* GetPageScheduler() const override;
-  void DidStartProvisionalLoad(bool is_main_frame) override;
-  void DidCommitProvisionalLoad(bool is_web_history_inert_commit,
-                                bool is_reload,
-                                bool is_main_frame) override;
-  WebScopedVirtualTimePauser CreateWebScopedVirtualTimePauser(
-      WebScopedVirtualTimePauser::VirtualTaskDuration duration) override;
-  void OnFirstMeaningfulPaint() override;
-  std::unique_ptr<ActiveConnectionHandle> OnActiveConnectionCreated() override;
-  void AsValueInto(base::trace_event::TracedValue* state) const;
-  bool IsExemptFromBudgetBasedThrottling() const override;
-
-  scoped_refptr<TaskQueue> ControlTaskQueue();
-  void SetPageVisibility(PageVisibilityState page_visibility);
-
-  bool has_active_connection() const { return active_connection_count_; }
-
-  void OnTraceLogEnabled() {
-    tracing_controller_.OnTraceLogEnabled();
-  }
-
- private:
-  friend class PageSchedulerImpl;
-  friend class renderer_scheduler_impl_unittest::RendererSchedulerImplTest;
-  friend class web_frame_scheduler_impl_unittest::WebFrameSchedulerImplTest;
-  friend class page_scheduler_impl_unittest::PageSchedulerImplTest;
-
-  class ActiveConnectionHandleImpl : public ActiveConnectionHandle {
-   public:
-    ActiveConnectionHandleImpl(WebFrameSchedulerImpl* frame_scheduler);
-    ~ActiveConnectionHandleImpl() override;
-
-   private:
-    base::WeakPtr<WebFrameSchedulerImpl> frame_scheduler_;
-
-    DISALLOW_COPY_AND_ASSIGN(ActiveConnectionHandleImpl);
-  };
-
-  class ThrottlingObserverHandleImpl : public ThrottlingObserverHandle {
-   public:
-    ThrottlingObserverHandleImpl(WebFrameSchedulerImpl* frame_scheduler,
-                                 Observer* observer);
-    ~ThrottlingObserverHandleImpl() override;
-
-   private:
-    base::WeakPtr<WebFrameSchedulerImpl> frame_scheduler_;
-    Observer* observer_;
-
-    DISALLOW_COPY_AND_ASSIGN(ThrottlingObserverHandleImpl);
-  };
-
-  void DetachFromPageScheduler();
-  void RemoveThrottleableQueueFromBackgroundCPUTimeBudgetPool();
-  void ApplyPolicyToThrottleableQueue();
-  bool ShouldThrottleTimers() const;
-  void UpdateThrottling(bool was_throttled);
-  WebFrameScheduler::ThrottlingState CalculateThrottlingState() const;
-  void UpdateThrottlingState();
-  void RemoveThrottlingObserver(Observer* observer);
-
-  void DidOpenActiveConnection();
-  void DidCloseActiveConnection();
-
-  scoped_refptr<TaskQueue> LoadingTaskQueue();
-  scoped_refptr<TaskQueue> LoadingControlTaskQueue();
-  scoped_refptr<TaskQueue> ThrottleableTaskQueue();
-  scoped_refptr<TaskQueue> DeferrableTaskQueue();
-  scoped_refptr<TaskQueue> PausableTaskQueue();
-  scoped_refptr<TaskQueue> UnpausableTaskQueue();
-
-  base::WeakPtr<WebFrameSchedulerImpl> GetWeakPtr();
-
-  TraceableVariableController tracing_controller_;
-  scoped_refptr<MainThreadTaskQueue> loading_task_queue_;
-  scoped_refptr<MainThreadTaskQueue> loading_control_task_queue_;
-  scoped_refptr<MainThreadTaskQueue> throttleable_task_queue_;
-  scoped_refptr<MainThreadTaskQueue> deferrable_task_queue_;
-  scoped_refptr<MainThreadTaskQueue> pausable_task_queue_;
-  scoped_refptr<MainThreadTaskQueue> unpausable_task_queue_;
-  std::unique_ptr<TaskQueue::QueueEnabledVoter> loading_queue_enabled_voter_;
-  std::unique_ptr<TaskQueue::QueueEnabledVoter>
-      loading_control_queue_enabled_voter_;
-  std::unique_ptr<TaskQueue::QueueEnabledVoter>
-      throttleable_queue_enabled_voter_;
-  std::unique_ptr<TaskQueue::QueueEnabledVoter> deferrable_queue_enabled_voter_;
-  std::unique_ptr<TaskQueue::QueueEnabledVoter> pausable_queue_enabled_voter_;
-  RendererSchedulerImpl* renderer_scheduler_;       // NOT OWNED
-  PageSchedulerImpl* parent_page_scheduler_;        // NOT OWNED
-  base::trace_event::BlameContext* blame_context_;  // NOT OWNED
-  std::set<Observer*> loader_observers_;            // NOT OWNED
-  WebFrameScheduler::ThrottlingState throttling_state_;
-  TraceableState<bool, kTracingCategoryNameInfo> frame_visible_;
-  TraceableState<PageVisibilityState, kTracingCategoryNameInfo>
-      page_visibility_;
-  TraceableState<bool, kTracingCategoryNameInfo> page_frozen_;
-  TraceableState<bool, kTracingCategoryNameInfo> frame_paused_;
-  TraceableState<bool, kTracingCategoryNameInfo> cross_origin_;
-  StateTracer<kTracingCategoryNameInfo> url_tracer_;
-  WebFrameScheduler::FrameType frame_type_;
-  int active_connection_count_;
-
-  base::WeakPtrFactory<WebFrameSchedulerImpl> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(WebFrameSchedulerImpl);
-};
-
-}  // namespace scheduler
-}  // namespace blink
-
-#endif  // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_RENDERER_WEB_FRAME_SCHEDULER_IMPL_H_
diff --git a/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl_unittest.cc b/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl_unittest.cc
deleted file mode 100644
index 8e4c63e..0000000
--- a/third_party/WebKit/Source/platform/scheduler/renderer/web_frame_scheduler_impl_unittest.cc
+++ /dev/null
@@ -1,330 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "platform/scheduler/renderer/web_frame_scheduler_impl.h"
-
-#include <memory>
-
-#include "base/callback.h"
-#include "base/location.h"
-#include "base/test/simple_test_tick_clock.h"
-#include "components/viz/test/ordered_simple_task_runner.h"
-#include "platform/WebTaskRunner.h"
-#include "platform/runtime_enabled_features.h"
-#include "platform/scheduler/renderer/page_scheduler_impl.h"
-#include "platform/scheduler/renderer/renderer_scheduler_impl.h"
-#include "platform/scheduler/test/task_queue_manager_for_test.h"
-#include "platform/testing/runtime_enabled_features_test_helpers.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace blink {
-namespace scheduler {
-// To avoid symbol collisions in jumbo builds.
-namespace web_frame_scheduler_impl_unittest {
-
-class WebFrameSchedulerImplTest : public ::testing::Test {
- public:
-  WebFrameSchedulerImplTest() = default;
-  ~WebFrameSchedulerImplTest() override = default;
-
-  void SetUp() override {
-    clock_.Advance(base::TimeDelta::FromMicroseconds(5000));
-    mock_task_runner_ =
-        base::MakeRefCounted<cc::OrderedSimpleTaskRunner>(&clock_, true);
-    scheduler_.reset(new RendererSchedulerImpl(
-        TaskQueueManagerForTest::Create(nullptr, mock_task_runner_, &clock_),
-        base::nullopt));
-    page_scheduler_.reset(
-        new PageSchedulerImpl(nullptr, scheduler_.get(), false));
-    web_frame_scheduler_ = page_scheduler_->CreateWebFrameSchedulerImpl(
-        nullptr, WebFrameScheduler::FrameType::kSubframe);
-  }
-
-  void TearDown() override {
-    web_frame_scheduler_.reset();
-    page_scheduler_.reset();
-    scheduler_->Shutdown();
-    scheduler_.reset();
-  }
-
- protected:
-  scoped_refptr<TaskQueue> ThrottleableTaskQueue() {
-    return web_frame_scheduler_->ThrottleableTaskQueue();
-  }
-
-  scoped_refptr<TaskQueue> LoadingTaskQueue() {
-    return web_frame_scheduler_->LoadingTaskQueue();
-  }
-
-  scoped_refptr<TaskQueue> DeferrableTaskQueue() {
-    return web_frame_scheduler_->DeferrableTaskQueue();
-  }
-
-  scoped_refptr<TaskQueue> PausableTaskQueue() {
-    return web_frame_scheduler_->PausableTaskQueue();
-  }
-
-  scoped_refptr<TaskQueue> UnpausableTaskQueue() {
-    return web_frame_scheduler_->UnpausableTaskQueue();
-  }
-
-  base::SimpleTestTickClock clock_;
-  scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
-  std::unique_ptr<RendererSchedulerImpl> scheduler_;
-  std::unique_ptr<PageSchedulerImpl> page_scheduler_;
-  std::unique_ptr<WebFrameSchedulerImpl> web_frame_scheduler_;
-};
-
-namespace {
-
-class MockThrottlingObserver final : public WebFrameScheduler::Observer {
- public:
-  MockThrottlingObserver()
-      : throttled_count_(0u), not_throttled_count_(0u), stopped_count_(0u) {}
-
-  void CheckObserverState(size_t throttled_count_expectation,
-                          size_t not_throttled_count_expectation,
-                          size_t stopped_count_expectation) {
-    EXPECT_EQ(throttled_count_expectation, throttled_count_);
-    EXPECT_EQ(not_throttled_count_expectation, not_throttled_count_);
-    EXPECT_EQ(stopped_count_expectation, stopped_count_);
-  }
-
-  void OnThrottlingStateChanged(
-      WebFrameScheduler::ThrottlingState state) override {
-    switch (state) {
-      case WebFrameScheduler::ThrottlingState::kThrottled:
-        throttled_count_++;
-        break;
-      case WebFrameScheduler::ThrottlingState::kNotThrottled:
-        not_throttled_count_++;
-        break;
-      case WebFrameScheduler::ThrottlingState::kStopped:
-        stopped_count_++;
-        break;
-        // We should not have another state, and compiler checks it.
-    }
-  }
-
- private:
-  size_t throttled_count_;
-  size_t not_throttled_count_;
-  size_t stopped_count_;
-};
-
-void RunRepeatingTask(scoped_refptr<TaskQueue> task_queue, int* run_count);
-
-base::OnceClosure MakeRepeatingTask(scoped_refptr<TaskQueue> task_queue,
-                                    int* run_count) {
-  return base::BindOnce(&RunRepeatingTask, std::move(task_queue),
-                        base::Unretained(run_count));
-}
-
-void RunRepeatingTask(scoped_refptr<TaskQueue> task_queue, int* run_count) {
-  ++*run_count;
-
-  TaskQueue* task_queue_ptr = task_queue.get();
-  task_queue_ptr->PostDelayedTask(
-      FROM_HERE, MakeRepeatingTask(std::move(task_queue), run_count),
-      TimeDelta::FromMilliseconds(1));
-}
-
-void IncrementCounter(int* counter) {
-  ++*counter;
-}
-
-}  // namespace
-
-TEST_F(WebFrameSchedulerImplTest, RepeatingTimer_PageInForeground) {
-  ScopedTimerThrottlingForHiddenFramesForTest
-      timer_throttling_for_hidden_frames(true);
-
-  int run_count = 0;
-  ThrottleableTaskQueue()->PostDelayedTask(
-      FROM_HERE, MakeRepeatingTask(ThrottleableTaskQueue(), &run_count),
-      TimeDelta::FromMilliseconds(1));
-
-  mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
-  EXPECT_EQ(1000, run_count);
-}
-
-TEST_F(WebFrameSchedulerImplTest, RepeatingTimer_PageInBackground) {
-  ScopedTimerThrottlingForHiddenFramesForTest
-      timer_throttling_for_hidden_frames(true);
-  page_scheduler_->SetPageVisible(false);
-
-  int run_count = 0;
-  ThrottleableTaskQueue()->PostDelayedTask(
-      FROM_HERE, MakeRepeatingTask(ThrottleableTaskQueue(), &run_count),
-      TimeDelta::FromMilliseconds(1));
-
-  mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
-  EXPECT_EQ(1, run_count);
-}
-
-TEST_F(WebFrameSchedulerImplTest, RepeatingTimer_FrameHidden_SameOrigin) {
-  ScopedTimerThrottlingForHiddenFramesForTest
-      timer_throttling_for_hidden_frames(true);
-  web_frame_scheduler_->SetFrameVisible(false);
-
-  int run_count = 0;
-  ThrottleableTaskQueue()->PostDelayedTask(
-      FROM_HERE, MakeRepeatingTask(ThrottleableTaskQueue(), &run_count),
-      TimeDelta::FromMilliseconds(1));
-
-  mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
-  EXPECT_EQ(1000, run_count);
-}
-
-TEST_F(WebFrameSchedulerImplTest, RepeatingTimer_FrameVisible_CrossOrigin) {
-  ScopedTimerThrottlingForHiddenFramesForTest
-      timer_throttling_for_hidden_frames(true);
-  web_frame_scheduler_->SetFrameVisible(true);
-  web_frame_scheduler_->SetCrossOrigin(true);
-
-  int run_count = 0;
-  ThrottleableTaskQueue()->PostDelayedTask(
-      FROM_HERE, MakeRepeatingTask(ThrottleableTaskQueue(), &run_count),
-      TimeDelta::FromMilliseconds(1));
-
-  mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
-  EXPECT_EQ(1000, run_count);
-}
-
-TEST_F(WebFrameSchedulerImplTest, RepeatingTimer_FrameHidden_CrossOrigin) {
-  ScopedTimerThrottlingForHiddenFramesForTest
-      timer_throttling_for_hidden_frames(true);
-  web_frame_scheduler_->SetFrameVisible(false);
-  web_frame_scheduler_->SetCrossOrigin(true);
-
-  int run_count = 0;
-  ThrottleableTaskQueue()->PostDelayedTask(
-      FROM_HERE, MakeRepeatingTask(ThrottleableTaskQueue(), &run_count),
-      TimeDelta::FromMilliseconds(1));
-
-  mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
-  EXPECT_EQ(1, run_count);
-}
-
-TEST_F(WebFrameSchedulerImplTest, PageInBackground_ThrottlingDisabled) {
-  ScopedTimerThrottlingForHiddenFramesForTest
-      timer_throttling_for_hidden_frames(false);
-  page_scheduler_->SetPageVisible(false);
-
-  int run_count = 0;
-  ThrottleableTaskQueue()->PostDelayedTask(
-      FROM_HERE, MakeRepeatingTask(ThrottleableTaskQueue(), &run_count),
-      TimeDelta::FromMilliseconds(1));
-
-  mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
-  EXPECT_EQ(1, run_count);
-}
-
-TEST_F(WebFrameSchedulerImplTest,
-       RepeatingTimer_FrameHidden_CrossOrigin_ThrottlingDisabled) {
-  ScopedTimerThrottlingForHiddenFramesForTest
-      timer_throttling_for_hidden_frames(false);
-  web_frame_scheduler_->SetFrameVisible(false);
-  web_frame_scheduler_->SetCrossOrigin(true);
-
-  int run_count = 0;
-  ThrottleableTaskQueue()->PostDelayedTask(
-      FROM_HERE, MakeRepeatingTask(ThrottleableTaskQueue(), &run_count),
-      TimeDelta::FromMilliseconds(1));
-
-  mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
-  EXPECT_EQ(1000, run_count);
-}
-
-TEST_F(WebFrameSchedulerImplTest, PauseAndResume) {
-  int counter = 0;
-  LoadingTaskQueue()->PostTask(
-      FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
-  ThrottleableTaskQueue()->PostTask(
-      FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
-  DeferrableTaskQueue()->PostTask(
-      FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
-  PausableTaskQueue()->PostTask(
-      FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
-  UnpausableTaskQueue()->PostTask(
-      FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
-
-  web_frame_scheduler_->SetPaused(true);
-
-  EXPECT_EQ(0, counter);
-  mock_task_runner_->RunUntilIdle();
-  EXPECT_EQ(1, counter);
-
-  web_frame_scheduler_->SetPaused(false);
-
-  EXPECT_EQ(1, counter);
-  mock_task_runner_->RunUntilIdle();
-  EXPECT_EQ(5, counter);
-}
-
-// Tests if throttling observer interfaces work.
-TEST_F(WebFrameSchedulerImplTest, ThrottlingObserver) {
-  std::unique_ptr<MockThrottlingObserver> observer =
-      std::make_unique<MockThrottlingObserver>();
-
-  size_t throttled_count = 0u;
-  size_t not_throttled_count = 0u;
-  size_t stopped_count = 0u;
-
-  observer->CheckObserverState(throttled_count, not_throttled_count,
-                               stopped_count);
-
-  auto observer_handle = web_frame_scheduler_->AddThrottlingObserver(
-      WebFrameScheduler::ObserverType::kLoader, observer.get());
-
-  // Initial state should be synchronously notified here.
-  // We assume kNotThrottled is notified as an initial state, but it could
-  // depend on implementation details and can be changed.
-  observer->CheckObserverState(throttled_count, ++not_throttled_count,
-                               stopped_count);
-
-  // Once the page gets to be invisible, it should notify the observer of
-  // kThrottled synchronously.
-  page_scheduler_->SetPageVisible(false);
-  observer->CheckObserverState(++throttled_count, not_throttled_count,
-                               stopped_count);
-
-  // When no state has changed, observers are not called.
-  page_scheduler_->SetPageVisible(false);
-  observer->CheckObserverState(throttled_count, not_throttled_count,
-                               stopped_count);
-
-  // Setting background page to STOPPED, notifies observers of kStopped.
-  page_scheduler_->SetPageFrozen(true);
-  observer->CheckObserverState(throttled_count, not_throttled_count,
-                               ++stopped_count);
-
-  // When page is not in the STOPPED state, then page visibility is used,
-  // notifying observer of kThrottled.
-  page_scheduler_->SetPageFrozen(false);
-  observer->CheckObserverState(++throttled_count, not_throttled_count,
-                               stopped_count);
-
-  // Going back to visible state should notify the observer of kNotThrottled
-  // synchronously.
-  page_scheduler_->SetPageVisible(true);
-  observer->CheckObserverState(throttled_count, ++not_throttled_count,
-                               stopped_count);
-
-  // Remove from the observer list, and see if any other callback should not be
-  // invoked when the condition is changed.
-  observer_handle.reset();
-  page_scheduler_->SetPageVisible(false);
-
-  // Wait 100 secs virtually and run pending tasks just in case.
-  clock_.Advance(base::TimeDelta::FromSeconds(100));
-  mock_task_runner_->RunUntilIdle();
-
-  observer->CheckObserverState(throttled_count, not_throttled_count,
-                               stopped_count);
-}
-
-}  // namespace web_frame_scheduler_impl_unittest
-}  // namespace scheduler
-}  // namespace blink
diff --git a/third_party/WebKit/Source/platform/scheduler/test/fake_frame_scheduler.h b/third_party/WebKit/Source/platform/scheduler/test/fake_frame_scheduler.h
new file mode 100644
index 0000000..913e690
--- /dev/null
+++ b/third_party/WebKit/Source/platform/scheduler/test/fake_frame_scheduler.h
@@ -0,0 +1,157 @@
+// 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 THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_TEST_FAKE_FRAME_SCHEDULER_H_
+#define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_TEST_FAKE_FRAME_SCHEDULER_H_
+
+#include <deque>
+
+#include "platform/FrameScheduler.h"
+#include "platform/scheduler/child/worker_scheduler_proxy.h"
+#include "platform/scheduler/renderer/main_thread_task_queue.h"
+
+namespace blink {
+namespace scheduler {
+
+class MainThreadTaskQueueForTest : public MainThreadTaskQueue {
+ public:
+  MainThreadTaskQueueForTest(QueueType queue_type)
+      : MainThreadTaskQueue(nullptr,
+                            Spec(MainThreadTaskQueue::NameForQueueType(
+                                MainThreadTaskQueue::QueueType::kTest)),
+                            QueueCreationParams(queue_type),
+                            nullptr) {}
+  ~MainThreadTaskQueueForTest() = default;
+};
+
+// A dummy FrameScheduler for tests.
+class FakeFrameScheduler : public FrameScheduler {
+ public:
+  FakeFrameScheduler()
+      : page_scheduler_(nullptr),
+        is_page_visible_(false),
+        is_frame_visible_(false),
+        frame_type_(FrameScheduler::FrameType::kSubframe),
+        is_cross_origin_(false),
+        is_exempt_from_throttling_(false) {}
+  FakeFrameScheduler(PageScheduler* page_scheduler,
+                     bool is_page_visible,
+                     bool is_frame_visible,
+                     FrameScheduler::FrameType frame_type,
+                     bool is_cross_origin,
+                     bool is_exempt_from_throttling)
+      : page_scheduler_(page_scheduler),
+        is_page_visible_(is_page_visible),
+        is_frame_visible_(is_frame_visible),
+        frame_type_(frame_type),
+        is_cross_origin_(is_cross_origin),
+        is_exempt_from_throttling_(is_exempt_from_throttling) {
+    DCHECK(frame_type_ != FrameType::kMainFrame || !is_cross_origin);
+  }
+  ~FakeFrameScheduler() override = default;
+
+  class Builder {
+   public:
+    Builder() = default;
+
+    std::unique_ptr<FakeFrameScheduler> Build() {
+      return std::make_unique<FakeFrameScheduler>(
+          page_scheduler_, is_page_visible_, is_frame_visible_, frame_type_,
+          is_cross_origin_, is_exempt_from_throttling_);
+    }
+
+    Builder& SetPageScheduler(PageScheduler* page_scheduler) {
+      page_scheduler_ = page_scheduler;
+      return *this;
+    }
+
+    Builder& SetIsPageVisible(bool is_page_visible) {
+      is_page_visible_ = is_page_visible;
+      return *this;
+    }
+
+    Builder& SetIsFrameVisible(bool is_frame_visible) {
+      is_frame_visible_ = is_frame_visible;
+      return *this;
+    }
+
+    Builder& SetFrameType(FrameScheduler::FrameType frame_type) {
+      frame_type_ = frame_type;
+      return *this;
+    }
+
+    Builder& SetIsCrossOrigin(bool is_cross_origin) {
+      is_cross_origin_ = is_cross_origin;
+      return *this;
+    }
+
+    Builder& SetIsExemptFromThrottling(bool is_exempt_from_throttling) {
+      is_exempt_from_throttling_ = is_exempt_from_throttling;
+      return *this;
+    }
+
+   private:
+    PageScheduler* page_scheduler_ = nullptr;
+    bool is_page_visible_ = false;
+    bool is_frame_visible_ = false;
+    FrameScheduler::FrameType frame_type_ =
+        FrameScheduler::FrameType::kMainFrame;
+    bool is_cross_origin_ = false;
+    bool is_exempt_from_throttling_ = false;
+  };
+
+  // FrameScheduler implementation:
+  std::unique_ptr<ThrottlingObserverHandle> AddThrottlingObserver(
+      ObserverType,
+      Observer*) override {
+    return nullptr;
+  }
+  void SetFrameVisible(bool) override {}
+  bool IsFrameVisible() const override { return is_frame_visible_; }
+  bool IsPageVisible() const override { return is_page_visible_; }
+  void SetPaused(bool) override {}
+  void SetCrossOrigin(bool) override {}
+  bool IsCrossOrigin() const override { return is_cross_origin_; }
+  void TraceUrlChange(const String&) override {}
+  FrameScheduler::FrameType GetFrameType() const override {
+    return frame_type_;
+  }
+  scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(TaskType) override {
+    return nullptr;
+  }
+  PageScheduler* GetPageScheduler() const override { return page_scheduler_; }
+  WebScopedVirtualTimePauser CreateWebScopedVirtualTimePauser(
+      WebScopedVirtualTimePauser::VirtualTaskDuration duration) {
+    return WebScopedVirtualTimePauser();
+  }
+  void DidStartProvisionalLoad(bool is_main_frame) override {}
+  void DidCommitProvisionalLoad(bool is_web_history_inert_commit,
+                                bool is_reload,
+                                bool is_main_frame) override {}
+  void OnFirstMeaningfulPaint() override {}
+  std::unique_ptr<ActiveConnectionHandle> OnActiveConnectionCreated() override {
+    return nullptr;
+  }
+  bool IsExemptFromBudgetBasedThrottling() const override {
+    return is_exempt_from_throttling_;
+  }
+  std::unique_ptr<WorkerSchedulerProxy> CreateWorkerSchedulerProxy() {
+    return nullptr;
+  }
+
+ private:
+  PageScheduler* page_scheduler_;  // NOT OWNED
+
+  bool is_page_visible_;
+  bool is_frame_visible_;
+  FrameScheduler::FrameType frame_type_;
+  bool is_cross_origin_;
+  bool is_exempt_from_throttling_;
+  DISALLOW_COPY_AND_ASSIGN(FakeFrameScheduler);
+};
+
+}  // namespace scheduler
+}  // namespace blink
+
+#endif  // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_TEST_FAKE_FRAME_SCHEDULER_H_
diff --git a/third_party/WebKit/Source/platform/scheduler/test/fake_page_scheduler.h b/third_party/WebKit/Source/platform/scheduler/test/fake_page_scheduler.h
index 8e03da7..66acff88 100644
--- a/third_party/WebKit/Source/platform/scheduler/test/fake_page_scheduler.h
+++ b/third_party/WebKit/Source/platform/scheduler/test/fake_page_scheduler.h
@@ -51,9 +51,9 @@
   void SetPageVisible(bool is_page_visible) override {}
   void SetPageFrozen(bool is_page_frozen) override {}
 
-  std::unique_ptr<WebFrameScheduler> CreateFrameScheduler(
+  std::unique_ptr<FrameScheduler> CreateFrameScheduler(
       BlameContext* blame_context,
-      WebFrameScheduler::FrameType frame_type) override {
+      FrameScheduler::FrameType frame_type) override {
     return nullptr;
   }
   base::TimeTicks EnableVirtualTime() override { return base::TimeTicks(); }
diff --git a/third_party/WebKit/Source/platform/scheduler/test/fake_web_frame_scheduler.h b/third_party/WebKit/Source/platform/scheduler/test/fake_web_frame_scheduler.h
deleted file mode 100644
index 0171f54..0000000
--- a/third_party/WebKit/Source/platform/scheduler/test/fake_web_frame_scheduler.h
+++ /dev/null
@@ -1,157 +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.
-
-#ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_TEST_FAKE_WEB_FRAME_SCHEDULER_H_
-#define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_TEST_FAKE_WEB_FRAME_SCHEDULER_H_
-
-#include <deque>
-
-#include "platform/WebFrameScheduler.h"
-#include "platform/scheduler/child/worker_scheduler_proxy.h"
-#include "platform/scheduler/renderer/main_thread_task_queue.h"
-
-namespace blink {
-namespace scheduler {
-
-class MainThreadTaskQueueForTest : public MainThreadTaskQueue {
- public:
-  MainThreadTaskQueueForTest(QueueType queue_type)
-      : MainThreadTaskQueue(nullptr,
-                            Spec(MainThreadTaskQueue::NameForQueueType(
-                                MainThreadTaskQueue::QueueType::kTest)),
-                            QueueCreationParams(queue_type),
-                            nullptr) {}
-  ~MainThreadTaskQueueForTest() = default;
-};
-
-// A dummy WebFrameScheduler for tests.
-class FakeWebFrameScheduler : public WebFrameScheduler {
- public:
-  FakeWebFrameScheduler()
-      : page_scheduler_(nullptr),
-        is_page_visible_(false),
-        is_frame_visible_(false),
-        frame_type_(WebFrameScheduler::FrameType::kSubframe),
-        is_cross_origin_(false),
-        is_exempt_from_throttling_(false) {}
-  FakeWebFrameScheduler(PageScheduler* page_scheduler,
-                        bool is_page_visible,
-                        bool is_frame_visible,
-                        WebFrameScheduler::FrameType frame_type,
-                        bool is_cross_origin,
-                        bool is_exempt_from_throttling)
-      : page_scheduler_(page_scheduler),
-        is_page_visible_(is_page_visible),
-        is_frame_visible_(is_frame_visible),
-        frame_type_(frame_type),
-        is_cross_origin_(is_cross_origin),
-        is_exempt_from_throttling_(is_exempt_from_throttling) {
-    DCHECK(frame_type_ != FrameType::kMainFrame || !is_cross_origin);
-  }
-  ~FakeWebFrameScheduler() override = default;
-
-  class Builder {
-   public:
-    Builder() = default;
-
-    std::unique_ptr<FakeWebFrameScheduler> Build() {
-      return std::make_unique<FakeWebFrameScheduler>(
-          page_scheduler_, is_page_visible_, is_frame_visible_, frame_type_,
-          is_cross_origin_, is_exempt_from_throttling_);
-    }
-
-    Builder& SetPageScheduler(PageScheduler* page_scheduler) {
-      page_scheduler_ = page_scheduler;
-      return *this;
-    }
-
-    Builder& SetIsPageVisible(bool is_page_visible) {
-      is_page_visible_ = is_page_visible;
-      return *this;
-    }
-
-    Builder& SetIsFrameVisible(bool is_frame_visible) {
-      is_frame_visible_ = is_frame_visible;
-      return *this;
-    }
-
-    Builder& SetFrameType(WebFrameScheduler::FrameType frame_type) {
-      frame_type_ = frame_type;
-      return *this;
-    }
-
-    Builder& SetIsCrossOrigin(bool is_cross_origin) {
-      is_cross_origin_ = is_cross_origin;
-      return *this;
-    }
-
-    Builder& SetIsExemptFromThrottling(bool is_exempt_from_throttling) {
-      is_exempt_from_throttling_ = is_exempt_from_throttling;
-      return *this;
-    }
-
-   private:
-    PageScheduler* page_scheduler_ = nullptr;
-    bool is_page_visible_ = false;
-    bool is_frame_visible_ = false;
-    WebFrameScheduler::FrameType frame_type_ =
-        WebFrameScheduler::FrameType::kMainFrame;
-    bool is_cross_origin_ = false;
-    bool is_exempt_from_throttling_ = false;
-  };
-
-  // WebFrameScheduler implementation:
-  std::unique_ptr<ThrottlingObserverHandle> AddThrottlingObserver(
-      ObserverType,
-      Observer*) override {
-    return nullptr;
-  }
-  void SetFrameVisible(bool) override {}
-  bool IsFrameVisible() const override { return is_frame_visible_; }
-  bool IsPageVisible() const override { return is_page_visible_; }
-  void SetPaused(bool) override {}
-  void SetCrossOrigin(bool) override {}
-  bool IsCrossOrigin() const override { return is_cross_origin_; }
-  void TraceUrlChange(const String&) override {}
-  WebFrameScheduler::FrameType GetFrameType() const override {
-    return frame_type_;
-  }
-  scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(TaskType) override {
-    return nullptr;
-  }
-  PageScheduler* GetPageScheduler() const override { return page_scheduler_; }
-  WebScopedVirtualTimePauser CreateWebScopedVirtualTimePauser(
-      WebScopedVirtualTimePauser::VirtualTaskDuration duration) {
-    return WebScopedVirtualTimePauser();
-  }
-  void DidStartProvisionalLoad(bool is_main_frame) override {}
-  void DidCommitProvisionalLoad(bool is_web_history_inert_commit,
-                                bool is_reload,
-                                bool is_main_frame) override {}
-  void OnFirstMeaningfulPaint() override {}
-  std::unique_ptr<ActiveConnectionHandle> OnActiveConnectionCreated() override {
-    return nullptr;
-  }
-  bool IsExemptFromBudgetBasedThrottling() const override {
-    return is_exempt_from_throttling_;
-  }
-  std::unique_ptr<WorkerSchedulerProxy> CreateWorkerSchedulerProxy() {
-    return nullptr;
-  }
-
- private:
-  PageScheduler* page_scheduler_;  // NOT OWNED
-
-  bool is_page_visible_;
-  bool is_frame_visible_;
-  WebFrameScheduler::FrameType frame_type_;
-  bool is_cross_origin_;
-  bool is_exempt_from_throttling_;
-  DISALLOW_COPY_AND_ASSIGN(FakeWebFrameScheduler);
-};
-
-}  // namespace scheduler
-}  // namespace blink
-
-#endif  // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_TEST_FAKE_WEB_FRAME_SCHEDULER_H_
diff --git a/third_party/WebKit/Source/platform/scheduler/util/tracing_helper.cc b/third_party/WebKit/Source/platform/scheduler/util/tracing_helper.cc
index ad56b1a0..b9e6e7b3 100644
--- a/third_party/WebKit/Source/platform/scheduler/util/tracing_helper.cc
+++ b/third_party/WebKit/Source/platform/scheduler/util/tracing_helper.cc
@@ -65,6 +65,14 @@
   return value.InMillisecondsF();
 }
 
+const char* YesNoStateToString(bool is_yes) {
+  if (is_yes) {
+    return "yes";
+  } else {
+    return "no";
+  }
+}
+
 TraceableVariableController::TraceableVariableController() {
 }
 
diff --git a/third_party/WebKit/Source/platform/scheduler/util/tracing_helper.h b/third_party/WebKit/Source/platform/scheduler/util/tracing_helper.h
index 728f7d1..8bd3a39 100644
--- a/third_party/WebKit/Source/platform/scheduler/util/tracing_helper.h
+++ b/third_party/WebKit/Source/platform/scheduler/util/tracing_helper.h
@@ -40,6 +40,8 @@
 
 PLATFORM_EXPORT double TimeDeltaToMilliseconds(const base::TimeDelta& value);
 
+PLATFORM_EXPORT const char* YesNoStateToString(bool is_yes);
+
 class TraceableVariable;
 
 // Unfortunately, using |base::trace_event::TraceLog::EnabledStateObserver|
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollableArea.cpp b/third_party/WebKit/Source/platform/scroll/ScrollableArea.cpp
index 0714535..b39af113 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollableArea.cpp
+++ b/third_party/WebKit/Source/platform/scroll/ScrollableArea.cpp
@@ -290,7 +290,7 @@
 }
 
 LayoutRect ScrollableArea::ScrollIntoView(
-    const LayoutRect& rect_in_content,
+    const LayoutRect& rect_in_absolute,
     const WebScrollIntoViewParams& params) {
   // TODO(bokan): This should really be implemented here but ScrollAlignment is
   // in Core which is a dependency violation.
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollableArea.h b/third_party/WebKit/Source/platform/scroll/ScrollableArea.h
index 6edc346..fcc472eb 100644
--- a/third_party/WebKit/Source/platform/scroll/ScrollableArea.h
+++ b/third_party/WebKit/Source/platform/scroll/ScrollableArea.h
@@ -94,14 +94,11 @@
                                  ScrollType,
                                  ScrollBehavior = kScrollBehaviorInstant);
 
-  // Scrolls the area so that the given rect, given in the document's content
-  // coordinates, such that it's visible in the area. Returns the new location
-  // of the input rect relative once again to the document.
-  // Note, in the case of a Document container, such as FrameView, the output
-  // will always be the input rect since scrolling it can't change the location
-  // of content relative to the document, unlike an overflowing element.
-  virtual LayoutRect ScrollIntoView(const LayoutRect& rect_in_content,
-                                    const WebScrollIntoViewParams& params);
+  // Scrolls the area so that the given rect, given in absolute coordinates,
+  // such that it's visible in the area. Returns the new location of the input
+  // rect in absolute coordinates.
+  virtual LayoutRect ScrollIntoView(const LayoutRect&,
+                                    const WebScrollIntoViewParams&);
 
   static bool ScrollBehaviorFromString(const String&, ScrollBehavior&);
 
diff --git a/third_party/WebKit/Source/platform/testing/weburl_loader_mock.cc b/third_party/WebKit/Source/platform/testing/weburl_loader_mock.cc
index 401ba3d..4dc54375 100644
--- a/third_party/WebKit/Source/platform/testing/weburl_loader_mock.cc
+++ b/third_party/WebKit/Source/platform/testing/weburl_loader_mock.cc
@@ -103,12 +103,14 @@
   return redirect_url;
 }
 
-void WebURLLoaderMock::LoadSynchronously(const WebURLRequest& request,
-                                         WebURLResponse& response,
-                                         base::Optional<WebURLError>& error,
-                                         WebData& data,
-                                         int64_t& encoded_data_length,
-                                         int64_t& encoded_body_length) {
+void WebURLLoaderMock::LoadSynchronously(
+    const WebURLRequest& request,
+    WebURLResponse& response,
+    base::Optional<WebURLError>& error,
+    WebData& data,
+    int64_t& encoded_data_length,
+    int64_t& encoded_body_length,
+    base::Optional<int64_t>& downloaded_file_length) {
   if (factory_->IsMockedURL(request.Url())) {
     factory_->LoadSynchronously(request, &response, &error, &data,
                                 &encoded_data_length);
@@ -117,7 +119,8 @@
   AssertFallbackLoaderAvailability(request.Url(), default_loader_.get());
   using_default_loader_ = true;
   default_loader_->LoadSynchronously(request, response, error, data,
-                                     encoded_data_length, encoded_body_length);
+                                     encoded_data_length, encoded_body_length,
+                                     downloaded_file_length);
 }
 
 void WebURLLoaderMock::LoadAsynchronously(const WebURLRequest& request,
diff --git a/third_party/WebKit/Source/platform/testing/weburl_loader_mock.h b/third_party/WebKit/Source/platform/testing/weburl_loader_mock.h
index 1d049ea..10b1719 100644
--- a/third_party/WebKit/Source/platform/testing/weburl_loader_mock.h
+++ b/third_party/WebKit/Source/platform/testing/weburl_loader_mock.h
@@ -45,12 +45,14 @@
                        const WebURLResponse& redirect_response);
 
   // WebURLLoader methods:
-  void LoadSynchronously(const WebURLRequest& request,
-                         WebURLResponse& response,
-                         Optional<WebURLError>& error,
-                         WebData& data,
-                         int64_t& encoded_data_length,
-                         int64_t& encoded_body_length) override;
+  void LoadSynchronously(
+      const WebURLRequest&,
+      WebURLResponse&,
+      Optional<WebURLError>&,
+      WebData&,
+      int64_t& encoded_data_length,
+      int64_t& encoded_body_length,
+      base::Optional<int64_t>& downloaded_file_length) override;
   void LoadAsynchronously(const WebURLRequest& request,
                           WebURLLoaderClient* client) override;
   void Cancel() override;
diff --git a/third_party/WebKit/Source/platform/text/BidiContext.cpp b/third_party/WebKit/Source/platform/text/BidiContext.cpp
index 1dcc32af..bbab91c 100644
--- a/third_party/WebKit/Source/platform/text/BidiContext.cpp
+++ b/third_party/WebKit/Source/platform/text/BidiContext.cpp
@@ -27,8 +27,6 @@
 
 namespace blink {
 
-using namespace WTF::Unicode;
-
 struct SameSizeAsBidiContext
     : public ThreadSafeRefCounted<SameSizeAsBidiContext> {
   uint32_t bitfields : 16;
@@ -40,7 +38,7 @@
 
 inline scoped_refptr<BidiContext> BidiContext::CreateUncached(
     unsigned char level,
-    CharDirection direction,
+    WTF::Unicode::CharDirection direction,
     bool override,
     BidiEmbeddingSource source,
     BidiContext* parent) {
@@ -48,12 +46,14 @@
       new BidiContext(level, direction, override, source, parent));
 }
 
-scoped_refptr<BidiContext> BidiContext::Create(unsigned char level,
-                                               CharDirection direction,
-                                               bool override,
-                                               BidiEmbeddingSource source,
-                                               BidiContext* parent) {
-  DCHECK_EQ(direction, (level % 2 ? kRightToLeft : kLeftToRight));
+scoped_refptr<BidiContext> BidiContext::Create(
+    unsigned char level,
+    WTF::Unicode::CharDirection direction,
+    bool override,
+    BidiEmbeddingSource source,
+    BidiContext* parent) {
+  DCHECK_EQ(direction, (level % 2 ? WTF::Unicode::kRightToLeft
+                                  : WTF::Unicode::kLeftToRight));
 
   if (parent || level >= 2)
     return CreateUncached(level, direction, override, source, parent);
@@ -61,28 +61,28 @@
   DCHECK_LE(level, 1);
   if (!level) {
     if (!override) {
-      DEFINE_STATIC_REF(
-          BidiContext, ltr_context,
-          (CreateUncached(0, kLeftToRight, false, kFromStyleOrDOM, nullptr)));
+      DEFINE_STATIC_REF(BidiContext, ltr_context,
+                        (CreateUncached(0, WTF::Unicode::kLeftToRight, false,
+                                        kFromStyleOrDOM, nullptr)));
       return ltr_context;
     }
 
-    DEFINE_STATIC_REF(
-        BidiContext, ltr_override_context,
-        (CreateUncached(0, kLeftToRight, true, kFromStyleOrDOM, nullptr)));
+    DEFINE_STATIC_REF(BidiContext, ltr_override_context,
+                      (CreateUncached(0, WTF::Unicode::kLeftToRight, true,
+                                      kFromStyleOrDOM, nullptr)));
     return ltr_override_context;
   }
 
   if (!override) {
-    DEFINE_STATIC_REF(
-        BidiContext, rtl_context,
-        (CreateUncached(1, kRightToLeft, false, kFromStyleOrDOM, nullptr)));
+    DEFINE_STATIC_REF(BidiContext, rtl_context,
+                      (CreateUncached(1, WTF::Unicode::kRightToLeft, false,
+                                      kFromStyleOrDOM, nullptr)));
     return rtl_context;
   }
 
-  DEFINE_STATIC_REF(
-      BidiContext, rtl_override_context,
-      (CreateUncached(1, kRightToLeft, true, kFromStyleOrDOM, nullptr)));
+  DEFINE_STATIC_REF(BidiContext, rtl_override_context,
+                    (CreateUncached(1, WTF::Unicode::kRightToLeft, true,
+                                    kFromStyleOrDOM, nullptr)));
   return rtl_override_context;
 }
 
@@ -91,7 +91,7 @@
     BidiContext* parent) {
   DCHECK(context);
   unsigned char new_level = parent ? parent->Level() : 0;
-  if (context->Dir() == kRightToLeft)
+  if (context->Dir() == WTF::Unicode::kRightToLeft)
     new_level = NextGreaterOddLevel(new_level);
   else if (parent)
     new_level = NextGreaterEvenLevel(new_level);
diff --git a/third_party/WebKit/Source/platform/text/HyphenationTest.cpp b/third_party/WebKit/Source/platform/text/HyphenationTest.cpp
index 3d9d3b1..0811206 100644
--- a/third_party/WebKit/Source/platform/text/HyphenationTest.cpp
+++ b/third_party/WebKit/Source/platform/text/HyphenationTest.cpp
@@ -134,7 +134,7 @@
   // Line breaker is not supposed to pass with trailing spaces.
   String trailing_space("principle ");
   EXPECT_THAT(hyphenation->HyphenLocations(trailing_space),
-              testing::AnyOf(ElementsAre(), ElementsAre(6, 4)));
+              ::testing::AnyOf(ElementsAre(), ElementsAre(6, 4)));
   EXPECT_EQ(0u, hyphenation->LastHyphenLocation(trailing_space, 10));
 }
 
@@ -148,8 +148,8 @@
   ASSERT_TRUE(hyphenation) << "Cannot find the hyphenation for en-us";
 
   Vector<size_t, 8> locations = hyphenation->HyphenLocations("hyphenation");
-  EXPECT_THAT(locations, testing::AnyOf(ElementsAreArray({6, 2}),
-                                        ElementsAreArray({7, 6, 2})));
+  EXPECT_THAT(locations, ::testing::AnyOf(ElementsAreArray({6, 2}),
+                                          ElementsAreArray({7, 6, 2})));
 }
 
 TEST_F(HyphenationTest, German) {
diff --git a/third_party/WebKit/Source/platform/wtf/Alignment.h b/third_party/WebKit/Source/platform/wtf/Alignment.h
index 045d0dd..5094c23f 100644
--- a/third_party/WebKit/Source/platform/wtf/Alignment.h
+++ b/third_party/WebKit/Source/platform/wtf/Alignment.h
@@ -22,7 +22,6 @@
 #define WTF_Alignment_h
 
 #include <stdint.h>
-#include <utility>
 #include "build/build_config.h"
 
 namespace WTF {
@@ -39,50 +38,6 @@
 #error WTF_ALIGN macros need alignment control.
 #endif
 
-#if defined(COMPILER_GCC)
-typedef char __attribute__((__may_alias__)) AlignedBufferChar;  // NOLINT
-#else
-typedef char AlignedBufferChar;
-#endif
-
-template <size_t size, size_t alignment>
-struct AlignedBuffer;
-template <size_t size>
-struct AlignedBuffer<size, 1> {
-  AlignedBufferChar buffer[size];
-};
-template <size_t size>
-struct AlignedBuffer<size, 2> {
-  WTF_ALIGNED(AlignedBufferChar, buffer[size], 2);
-};
-template <size_t size>
-struct AlignedBuffer<size, 4> {
-  WTF_ALIGNED(AlignedBufferChar, buffer[size], 4);
-};
-template <size_t size>
-struct AlignedBuffer<size, 8> {
-  WTF_ALIGNED(AlignedBufferChar, buffer[size], 8);
-};
-template <size_t size>
-struct AlignedBuffer<size, 16> {
-  WTF_ALIGNED(AlignedBufferChar, buffer[size], 16);
-};
-template <size_t size>
-struct AlignedBuffer<size, 32> {
-  WTF_ALIGNED(AlignedBufferChar, buffer[size], 32);
-};
-template <size_t size>
-struct AlignedBuffer<size, 64> {
-  WTF_ALIGNED(AlignedBufferChar, buffer[size], 64);
-};
-
-template <size_t size, size_t alignment>
-void swap(AlignedBuffer<size, alignment>& a,
-          AlignedBuffer<size, alignment>& b) {
-  for (size_t i = 0; i < size; ++i)
-    std::swap(a.buffer[i], b.buffer[i]);
-}
-
 template <uintptr_t mask>
 inline bool IsAlignedTo(const void* pointer) {
   return !(reinterpret_cast<uintptr_t>(pointer) & mask);
diff --git a/third_party/WebKit/Source/platform/wtf/BUILD.gn b/third_party/WebKit/Source/platform/wtf/BUILD.gn
index 5bbda9c..da6f7d6 100644
--- a/third_party/WebKit/Source/platform/wtf/BUILD.gn
+++ b/third_party/WebKit/Source/platform/wtf/BUILD.gn
@@ -65,8 +65,6 @@
     "ContainerAnnotations.h",
     "CryptographicallyRandomNumber.cpp",
     "CryptographicallyRandomNumber.h",
-    "DataLog.cpp",
-    "DataLog.h",
     "DateMath.cpp",
     "DateMath.h",
     "Deque.h",
diff --git a/third_party/WebKit/Source/platform/wtf/DataLog.cpp b/third_party/WebKit/Source/platform/wtf/DataLog.cpp
deleted file mode 100644
index 2c923f76..0000000
--- a/third_party/WebKit/Source/platform/wtf/DataLog.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "platform/wtf/DataLog.h"
-
-#include <cstdarg>
-#include <cstdio>
-#include <cstdlib>
-#include "build/build_config.h"
-
-#define DATA_LOG_TO_FILE 0
-
-// Uncomment to force logging to the given file regardless of what the
-// environment variable says. Note that we will append ".<pid>.txt" where <pid>
-// is the PID.
-
-// This path won't work on Windows, make sure to change to something like
-// C:\\Users\\<more path>\\log.txt.
-#define DATA_LOG_FILENAME "/tmp/WTFLog"
-
-namespace WTF {
-
-static FILE* OpenLogFile() {
-  FILE* file = nullptr;
-#if DATA_LOG_TO_FILE
-#ifdef DATA_LOG_FILENAME
-  const char* filename = DATA_LOG_FILENAME;
-#else
-  const char* filename = getenv("WTF_DATA_LOG_FILENAME");
-#endif
-  char actual_filename[1024];
-
-  snprintf(actual_filename, sizeof(actual_filename), "%s.%d.txt", filename,
-           getpid());
-
-  if (filename) {
-    file = fopen(actual_filename, "w");
-    if (!file) {
-      fprintf(stderr, "Warning: Could not open log file %s for writing.\n",
-              actual_filename);
-    }
-  }
-#endif  // DATA_LOG_TO_FILE
-  if (!file)
-    file = stderr;
-
-  // Prefer unbuffered output, so that we get a full log upon crash or
-  // deadlock.
-  setvbuf(file, nullptr, _IONBF, 0);
-
-  return file;
-}
-
-void DeprecatedDataLogF(const char* format, ...) {
-  static FILE* file = OpenLogFile();
-  va_list arg_list;
-  va_start(arg_list, format);
-  vfprintf(file, format, arg_list);
-  va_end(arg_list);
-}
-
-}  // namespace WTF
diff --git a/third_party/WebKit/Source/platform/wtf/DataLog.h b/third_party/WebKit/Source/platform/wtf/DataLog.h
deleted file mode 100644
index e0eb931..0000000
--- a/third_party/WebKit/Source/platform/wtf/DataLog.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef DataLog_h
-#define DataLog_h
-
-#include "base/compiler_specific.h"
-#include "platform/wtf/WTFExport.h"
-
-namespace WTF {
-
-// Do not use this function.  Use base/logging.h instead.
-WTF_EXPORT PRINTF_FORMAT(1, 2) void DeprecatedDataLogF(const char* format, ...);
-
-}  // namespace WTF
-
-using WTF::DeprecatedDataLogF;
-
-#endif  // DataLog_h
diff --git a/third_party/WebKit/Source/platform/wtf/HashMap.h b/third_party/WebKit/Source/platform/wtf/HashMap.h
index 8120c84e..15676137 100644
--- a/third_party/WebKit/Source/platform/wtf/HashMap.h
+++ b/third_party/WebKit/Source/platform/wtf/HashMap.h
@@ -716,7 +716,15 @@
   typedef
       typename HashMap<T, U, V, W, X, Y>::const_iterator::KeysIterator iterator;
 
-  vector.resize(collection.size());
+  {
+    // Disallow GC during resize allocation; see crbugs 568173 and 823612.
+    // The element copy doesn't need to be in this scope because garbage
+    // collection can only remove elements from collection if its keys are
+    // WeakMembers, in which case copying them doesn't perform a heap
+    // allocation.
+    typename Z::GCForbiddenScope scope;
+    vector.resize(collection.size());
+  }
 
   iterator it = collection.begin().Keys();
   iterator end = collection.end().Keys();
@@ -736,6 +744,11 @@
   typedef typename HashMap<T, U, V, W, X, Y>::const_iterator::ValuesIterator
       iterator;
 
+  // Disallow GC during resize allocation and copy operations (which may also
+  // perform allocations and therefore cause elements of collection to be
+  // removed); see crbugs 568173 and 823612.
+  typename Z::GCForbiddenScope scope;
+
   vector.resize(collection.size());
 
   iterator it = collection.begin().Values();
diff --git a/third_party/WebKit/Source/platform/wtf/HashTable.cpp b/third_party/WebKit/Source/platform/wtf/HashTable.cpp
index ec51b67a..74678282 100644
--- a/third_party/WebKit/Source/platform/wtf/HashTable.cpp
+++ b/third_party/WebKit/Source/platform/wtf/HashTable.cpp
@@ -21,7 +21,7 @@
 
 #if DUMP_HASHTABLE_STATS || DUMP_HASHTABLE_STATS_PER_TABLE
 
-#include "platform/wtf/DataLog.h"
+#include <iomanip>
 #include "platform/wtf/ThreadingPrimitives.h"
 
 namespace WTF {
@@ -75,22 +75,26 @@
 }
 
 void HashTableStats::DumpStatsWithoutLock() {
-  DeprecatedDataLogF("\nWTF::HashTable statistics\n\n");
-  DeprecatedDataLogF("%d accesses\n", numAccesses);
-  DeprecatedDataLogF("%d total collisions, average %.2f probes per access\n",
-                     numCollisions,
-                     1.0 * (numAccesses + numCollisions) / numAccesses);
-  DeprecatedDataLogF("longest collision chain: %d\n", maxCollisions);
+  std::stringstream collision_str;
+  collision_str << std::fixed << std::setprecision(2);
   for (int i = 1; i <= maxCollisions; i++) {
-    DeprecatedDataLogF(
-        "  %d lookups with exactly %d collisions (%.2f%% , %.2f%% with this "
-        "many or more)\n",
-        collisionGraph[i], i,
-        100.0 * (collisionGraph[i] - collisionGraph[i + 1]) / numAccesses,
-        100.0 * collisionGraph[i] / numAccesses);
+    collision_str << "      " << collisionGraph[i] << " lookups with exactly "
+                  << i << " collisions ("
+                  << (100.0 * (collisionGraph[i] - collisionGraph[i + 1]) /
+                      numAccesses)
+                  << "% , " << (100.0 * collisionGraph[i] / numAccesses)
+                  << "% with this many or more)\n";
   }
-  DeprecatedDataLogF("%d rehashes\n", numRehashes);
-  DeprecatedDataLogF("%d reinserts\n", numReinserts);
+
+  DLOG(INFO) << std::fixed << std::setprecision(2)
+             << "WTF::HashTable statistics:\n"
+             << "    " << numAccesses << " accesses\n"
+             << "    " << numCollisions << " total collisions, average "
+             << (1.0 * (numAccesses + numCollisions) / numAccesses)
+             << " probes per access\n"
+             << "    longest collision chain: " << maxCollisions << "\n"
+             << collision_str.str() << "    " << numRehashes << " rehashes\n"
+             << "    " << numReinserts << " reinserts";
 }
 
 }  // namespace WTF
diff --git a/third_party/WebKit/Source/platform/wtf/HashTable.h b/third_party/WebKit/Source/platform/wtf/HashTable.h
index 08e1fa2..02eeed3 100644
--- a/third_party/WebKit/Source/platform/wtf/HashTable.h
+++ b/third_party/WebKit/Source/platform/wtf/HashTable.h
@@ -2001,8 +2001,6 @@
   static void Process(typename Allocator::Visitor* visitor, void* closure) {}
   static void EphemeronIteration(typename Allocator::Visitor* visitor,
                                  void* closure) {}
-  static void EphemeronIterationDone(typename Allocator::Visitor* visitor,
-                                     void* closure) {}
 };
 
 template <typename Key,
@@ -2077,18 +2075,6 @@
       }
     }
   }
-
-  // Called when the ephemeron iteration is done and before running the per
-  // thread weak processing. It is guaranteed to be called before any thread
-  // is resumed.
-  static void EphemeronIterationDone(typename Allocator::Visitor* visitor,
-                                     void* closure) {
-    HashTableType* table = reinterpret_cast<HashTableType*>(closure);
-#if DCHECK_IS_ON()
-    DCHECK(Allocator::WeakTableRegistered(visitor, table));
-#endif
-    table->ClearEnqueued();
-  }
 };
 
 template <typename Key,
@@ -2114,12 +2100,6 @@
     // Weak HashTable. The HashTable may be held alive strongly from somewhere
     // else, e.g., an iterator.
 
-    // Small performance optimization: It is safe to assume that if the enqueued
-    // flag has been set all callbacks have been previously registered and it is
-    // safe to bail out.
-    if (Enqueued())
-      return;
-
     // Marking of the table is delayed because the backing store is potentially
     // held alive strongly by other objects. Delayed marking happens after
     // regular marking.
@@ -2134,29 +2114,17 @@
                                       KeyTraits, Allocator>::Process);
 
     if (IsTraceableInCollectionTrait<Traits>::value) {
-#if DCHECK_IS_ON()
-      DCHECK(!Allocator::WeakTableRegistered(visitor, this) || Enqueued());
-#endif
-
       // Mix of strong and weak fields. We use an approach similar to ephemeron
       // marking to find a fixed point, c.f.:
       // - http://dl.acm.org/citation.cfm?doid=263698.263733
       // - http://www.jucs.org/jucs_14_21/eliminating_cycles_in_weak
       // Adding the table for ephemeron marking delays marking any elements in
       // the backing until regular marking is finished.
-      if (!Enqueued() &&
-          Allocator::RegisterWeakTable(
-              visitor, this,
-              WeakProcessingHashTableHelper<Traits::kWeakHandlingFlag, Key,
-                                            Value, Extractor, HashFunctions,
-                                            Traits, KeyTraits,
-                                            Allocator>::EphemeronIteration,
-              WeakProcessingHashTableHelper<
-                  Traits::kWeakHandlingFlag, Key, Value, Extractor,
-                  HashFunctions, Traits, KeyTraits,
-                  Allocator>::EphemeronIterationDone)) {
-        SetEnqueued();
-      }
+      Allocator::RegisterWeakTable(
+          visitor, this,
+          WeakProcessingHashTableHelper<
+              Traits::kWeakHandlingFlag, Key, Value, Extractor, HashFunctions,
+              Traits, KeyTraits, Allocator>::EphemeronIteration);
     }
   }
 }
diff --git a/third_party/WebKit/Source/platform/wtf/ListHashSet.h b/third_party/WebKit/Source/platform/wtf/ListHashSet.h
index 5f94c89..2ab8c46 100644
--- a/third_party/WebKit/Source/platform/wtf/ListHashSet.h
+++ b/third_party/WebKit/Source/platform/wtf/ListHashSet.h
@@ -329,7 +329,7 @@
 
   ListHashSetAllocator()
       : free_list_(Pool()), is_done_with_initial_free_list_(false) {
-    memset(pool_.buffer, 0, sizeof(pool_.buffer));
+    memset(pool_, 0, sizeof(pool_));
   }
 
   Node* AllocateNode() {
@@ -383,7 +383,7 @@
                          Node* node) {}
 
  private:
-  Node* Pool() { return reinterpret_cast_ptr<Node*>(pool_.buffer); }
+  Node* Pool() { return reinterpret_cast_ptr<Node*>(pool_); }
   Node* PastPool() { return Pool() + kPoolSize; }
 
   Node* free_list_;
@@ -396,7 +396,7 @@
 #else
   static const size_t kPoolSize = inlineCapacity;
 #endif
-  AlignedBuffer<sizeof(NodeBase) * kPoolSize, WTF_ALIGN_OF(NodeBase)> pool_;
+  alignas(NodeBase) char pool_[sizeof(NodeBase) * kPoolSize];
 };
 
 template <typename ValueArg, typename AllocatorArg>
diff --git a/third_party/WebKit/Source/platform/wtf/SizeLimits.cpp b/third_party/WebKit/Source/platform/wtf/SizeLimits.cpp
index 22c7890..c443a7ed 100644
--- a/third_party/WebKit/Source/platform/wtf/SizeLimits.cpp
+++ b/third_party/WebKit/Source/platform/wtf/SizeLimits.cpp
@@ -59,7 +59,7 @@
 struct SameSizeAsVectorWithInlineCapacity {
   SameSizeAsVectorWithInlineCapacity<T, 0> base_capacity;
 #if !defined(ANNOTATE_CONTIGUOUS_CONTAINER)
-  AlignedBuffer<inlineCapacity * sizeof(T), WTF_ALIGN_OF(T)> inline_buffer;
+  T inline_buffer[inlineCapacity];
 #endif
 };
 
diff --git a/third_party/WebKit/Source/platform/wtf/Vector.h b/third_party/WebKit/Source/platform/wtf/Vector.h
index 8421b13..946da865 100644
--- a/third_party/WebKit/Source/platform/wtf/Vector.h
+++ b/third_party/WebKit/Source/platform/wtf/Vector.h
@@ -876,14 +876,12 @@
   using Base::capacity_;
 
   static const size_t kInlineBufferSize = inlineCapacity * sizeof(T);
-  T* InlineBuffer() {
-    return unsafe_reinterpret_cast_ptr<T*>(inline_buffer_.buffer);
-  }
+  T* InlineBuffer() { return unsafe_reinterpret_cast_ptr<T*>(inline_buffer_); }
   const T* InlineBuffer() const {
-    return unsafe_reinterpret_cast_ptr<const T*>(inline_buffer_.buffer);
+    return unsafe_reinterpret_cast_ptr<const T*>(inline_buffer_);
   }
 
-  AlignedBuffer<kInlineBufferSize, WTF_ALIGN_OF(T)> inline_buffer_;
+  alignas(T) char inline_buffer_[kInlineBufferSize];
   template <typename U, size_t inlineBuffer, typename V>
   friend class Deque;
 
diff --git a/third_party/WebKit/Source/platform/wtf/text/WTFString.cpp b/third_party/WebKit/Source/platform/wtf/text/WTFString.cpp
index ce5dcce..c7a75b2d 100644
--- a/third_party/WebKit/Source/platform/wtf/text/WTFString.cpp
+++ b/third_party/WebKit/Source/platform/wtf/text/WTFString.cpp
@@ -24,8 +24,6 @@
 
 #include "base/strings/string_util.h"
 #include "platform/wtf/ASCIICType.h"
-#include "platform/wtf/DataLog.h"
-#include "platform/wtf/HexNumber.h"
 #include "platform/wtf/MathExtras.h"
 #include "platform/wtf/StringExtras.h"
 #include "platform/wtf/Vector.h"
@@ -42,31 +40,6 @@
 
 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');
-      HexNumber::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)
     : impl_(characters ? StringImpl::Create(characters, length) : nullptr) {}
@@ -825,7 +798,7 @@
 
 #ifndef NDEBUG
 void String::Show() const {
-  DeprecatedDataLogF("%s\n", AsciiDebug(Impl()).data());
+  DLOG(INFO) << *this;
 }
 #endif
 
diff --git a/third_party/WebKit/Tools/Scripts/audit-non-blink-usage.py b/third_party/WebKit/Tools/Scripts/audit-non-blink-usage.py
index 0f58880..28c42bd4 100755
--- a/third_party/WebKit/Tools/Scripts/audit-non-blink-usage.py
+++ b/third_party/WebKit/Tools/Scripts/audit-non-blink-usage.py
@@ -35,6 +35,8 @@
             'base::MakeRefCounted',
             'base::Optional',
             'base::RefCountedData',
+            'base::CreateSequencedTaskRunnerWithTraits',
+            'base::SequencedTaskRunner',
             'base::SingleThreadTaskRunner',
             'base::Time',
             'base::TimeDelta',
@@ -58,6 +60,9 @@
             # //base/memory/ptr_util.h.
             'base::WrapUnique',
 
+            # //base/synchronization/waitable_event.h.
+            'base::WaitableEvent',
+
             # Debugging helpers from //base/debug are allowed everywhere.
             'base::debug::.+',
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py
index 3ae937f..d40e9918 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py
@@ -1090,34 +1090,6 @@
     def path_to_never_fix_tests_file(self):
         return self._filesystem.join(self.layout_tests_dir(), 'NeverFixTests')
 
-    def _expectations_from_skipped_files(self, skipped_file_paths):
-        # TODO(qyearsley): Remove this if there are no more "Skipped" files.
-        tests_to_skip = []
-        for search_path in skipped_file_paths:
-            filename = self._filesystem.join(self._absolute_baseline_path(search_path), 'Skipped')
-            if not self._filesystem.exists(filename):
-                _log.debug('Skipped does not exist: %s', filename)
-                continue
-            _log.debug('Using Skipped file: %s', filename)
-            tests_to_skip.extend(self._tests_from_file(filename))
-        return tests_to_skip
-
-    @memoized
-    def skipped_perf_tests(self):
-        tests = self._expectations_from_skipped_files([self._perf_tests_dir()])
-        # Best to normalize directory names to not include the trailing slash.
-        # TODO(qyearsley): Explain why removing trailing slashes is needed here.
-        return sorted(test.rstrip('/') for test in tests)
-
-    def skips_perf_test(self, test_name):
-        for test_or_category in self.skipped_perf_tests():
-            if test_or_category == test_name:
-                return True
-            category = self._filesystem.join(self._perf_tests_dir(), test_or_category)
-            if self._filesystem.isdir(category) and test_name.startswith(test_or_category):
-                return True
-        return False
-
     def name(self):
         """Returns a name that uniquely identifies this particular type of port.
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py
index 9c087b63..8c53b9a 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py
@@ -87,23 +87,6 @@
         self.assertIn('canvas', dirs)
         self.assertIn('css2.1', dirs)
 
-    def test_skipped_perf_tests(self):
-        port = self.make_port()
-
-        def add_text_file(dirname, filename, content='some content'):
-            dirname = port.host.filesystem.join(
-                PathFinder(port.host.filesystem).perf_tests_dir(), dirname)
-            port.host.filesystem.maybe_make_directory(dirname)
-            port.host.filesystem.write_text_file(port.host.filesystem.join(dirname, filename), content)
-
-        add_text_file('inspector', 'test1.html')
-        add_text_file('inspector', 'unsupported_test1.html')
-        add_text_file('inspector', 'test2.html')
-        add_text_file('inspector/resources', 'resource_file.html')
-        add_text_file('unsupported', 'unsupported_test2.html')
-        add_text_file('', 'Skipped', '\n'.join(['Layout', '', 'SunSpider', 'Supported/some-test.html']))
-        self.assertEqual(port.skipped_perf_tests(), ['Layout', 'SunSpider', 'Supported/some-test.html'])
-
     def test_get_option__set(self):
         options, _ = optparse.OptionParser().parse_args([])
         options.foo = 'bar'
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/servers/apache_http.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/servers/apache_http.py
index 31a51e0..b615459 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/servers/apache_http.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/servers/apache_http.py
@@ -64,6 +64,7 @@
         cert_file = self._filesystem.join(self._port_obj.apache_config_directory(), 'webkit-httpd.pem')
         inspector_sources_dir = self._port_obj.inspector_build_directory()
         generated_sources_dir = self._port_obj.generated_sources_directory()
+        php_ini_dir = self._filesystem.join(test_dir, "http", "conf")
 
         self._access_log_path = self._filesystem.join(output_dir, 'access_log.txt')
         self._error_log_path = self._filesystem.join(output_dir, 'error_log.txt')
@@ -92,6 +93,7 @@
             '-c', 'TypesConfig "%s"' % mime_types_path,
             '-c', 'CustomLog "%s" common' % self._access_log_path,
             '-c', 'ErrorLog "%s"' % self._error_log_path,
+            '-c', 'PHPINIDir "%s"' % php_ini_dir,
             '-c', 'PidFile %s' % self._pid_file,
             '-c', 'SSLCertificateFile "%s"' % cert_file,
             '-c', 'DefaultType None',
diff --git a/third_party/WebKit/public/BUILD.gn b/third_party/WebKit/public/BUILD.gn
index 8e35b7d..8f26bf6 100644
--- a/third_party/WebKit/public/BUILD.gn
+++ b/third_party/WebKit/public/BUILD.gn
@@ -770,7 +770,6 @@
     "platform/modules/presentation/presentation.mojom",
     "platform/modules/webauth/authenticator.mojom",
     "platform/modules/webdatabase/web_database.mojom",
-    "platform/modules/websockets/websocket.mojom",
     "platform/oom_intervention.mojom",
     "platform/referrer.mojom",
     "platform/reporting.mojom",
@@ -943,6 +942,8 @@
     # variant of the generated files.
     ":core_mojo_bindings__generator",
     ":core_mojo_bindings_blink__generator",
+    ":media_devices_mojo_bindings__generator",
+    ":media_devices_mojo_bindings_blink__generator",
     ":mojo_bindings__generator",
     ":mojo_bindings_blink__generator",
     ":offscreen_canvas_mojo_bindings_blink__generator",
diff --git a/third_party/WebKit/public/platform/WebExternalTextureLayer.h b/third_party/WebKit/public/platform/WebExternalTextureLayer.h
index 58854a1c5..f4fbbb2e 100644
--- a/third_party/WebKit/public/platform/WebExternalTextureLayer.h
+++ b/third_party/WebKit/public/platform/WebExternalTextureLayer.h
@@ -27,6 +27,7 @@
 #define WebExternalTextureLayer_h
 
 #include "WebCommon.h"
+#include "WebFloatPoint.h"
 #include "WebFloatRect.h"
 #include "WebLayer.h"
 
@@ -65,6 +66,10 @@
   // Sets whether this texture should use nearest neighbor interpolation as
   // opposed to bilinear. Defaults to false.
   virtual void SetNearestNeighbor(bool) = 0;
+
+  // Sets a UV transform to be used at draw time. Defaults to (0, 0) and (1, 1).
+  virtual void SetUV(const WebFloatPoint left_top,
+                     const WebFloatPoint right_bottom) = 0;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/public/platform/WebMediaStreamSource.h b/third_party/WebKit/public/platform/WebMediaStreamSource.h
index e5386837..d588e171 100644
--- a/third_party/WebKit/public/platform/WebMediaStreamSource.h
+++ b/third_party/WebKit/public/platform/WebMediaStreamSource.h
@@ -82,6 +82,8 @@
     WebVector<double> aspect_ratio;
     WebVector<double> frame_rate;
     WebVector<bool> echo_cancellation;
+    WebVector<bool> auto_gain_control;
+    WebVector<bool> noise_suppression;
 
     WebMediaStreamTrack::FacingMode facing_mode =
         WebMediaStreamTrack::FacingMode::kNone;
diff --git a/third_party/WebKit/public/platform/WebThread.h b/third_party/WebKit/public/platform/WebThread.h
index acf64da..32161ec 100644
--- a/third_party/WebKit/public/platform/WebThread.h
+++ b/third_party/WebKit/public/platform/WebThread.h
@@ -39,8 +39,8 @@
 class TaskTimeObserver;
 }
 
+class FrameScheduler;
 class WebScheduler;
-class WebFrameScheduler;
 
 // Always an integer value.
 typedef uintptr_t PlatformThreadId;
@@ -52,11 +52,11 @@
 
   // Sets a scheduler for the frame which was responsible for the creation
   // of this thread.
-  WebThreadCreationParams& SetFrameScheduler(WebFrameScheduler*);
+  WebThreadCreationParams& SetFrameScheduler(FrameScheduler*);
 
   WebThreadType thread_type;
   const char* name;
-  WebFrameScheduler* frame_scheduler;  // NOT OWNED
+  FrameScheduler* frame_scheduler;  // NOT OWNED
   base::Thread::Options thread_options;
 };
 
diff --git a/third_party/WebKit/public/platform/WebURLLoader.h b/third_party/WebKit/public/platform/WebURLLoader.h
index fbc751e..dc4b205 100644
--- a/third_party/WebKit/public/platform/WebURLLoader.h
+++ b/third_party/WebKit/public/platform/WebURLLoader.h
@@ -51,12 +51,14 @@
   // Load the request synchronously, returning results directly to the
   // caller upon completion.  There is no mechanism to interrupt a
   // synchronous load!!
-  virtual void LoadSynchronously(const WebURLRequest&,
-                                 WebURLResponse&,
-                                 base::Optional<WebURLError>&,
-                                 WebData&,
-                                 int64_t& encoded_data_length,
-                                 int64_t& encoded_body_length) = 0;
+  virtual void LoadSynchronously(
+      const WebURLRequest&,
+      WebURLResponse&,
+      base::Optional<WebURLError>&,
+      WebData&,
+      int64_t& encoded_data_length,
+      int64_t& encoded_body_length,
+      base::Optional<int64_t>& downloaded_file_length) = 0;
 
   // Load the request asynchronously, sending notifications to the given
   // client.  The client will receive no further notifications if the
diff --git a/third_party/WebKit/public/platform/WebURLRequest.h b/third_party/WebKit/public/platform/WebURLRequest.h
index 836ee53..c55a6fa 100644
--- a/third_party/WebKit/public/platform/WebURLRequest.h
+++ b/third_party/WebKit/public/platform/WebURLRequest.h
@@ -175,6 +175,8 @@
   BLINK_PLATFORM_EXPORT mojom::FetchCacheMode GetCacheMode() const;
   BLINK_PLATFORM_EXPORT void SetCacheMode(mojom::FetchCacheMode);
 
+  BLINK_PLATFORM_EXPORT double TimeoutInterval() const;
+
   BLINK_PLATFORM_EXPORT WebString HttpMethod() const;
   BLINK_PLATFORM_EXPORT void SetHTTPMethod(const WebString&);
 
diff --git a/third_party/WebKit/public/platform/WebWorkerFetchContext.h b/third_party/WebKit/public/platform/WebWorkerFetchContext.h
index 930ff2c..b28df2d 100644
--- a/third_party/WebKit/public/platform/WebWorkerFetchContext.h
+++ b/third_party/WebKit/public/platform/WebWorkerFetchContext.h
@@ -12,6 +12,10 @@
 #include "public/platform/WebDocumentSubresourceFilter.h"
 #include "public/platform/WebURL.h"
 
+namespace base {
+class WaitableEvent;
+}  // namespace base
+
 namespace blink {
 
 class WebURLLoaderFactory;
@@ -27,6 +31,13 @@
  public:
   virtual ~WebWorkerFetchContext() = default;
 
+  // Returns a raw pointer of a WaitableEvent which will be signaled from the
+  // main thread when the worker's GlobalScope is terminated, which will
+  // terminate sync loading requests on the worker thread.
+  // The raw pointer is valid only while the WebWorkerFetchContext is alive
+  // which is supposed to have the same lifetime as the worker's GlobalScope.
+  virtual base::WaitableEvent* GetTerminateSyncLoadEvent() = 0;
+
   virtual void InitializeOnWorkerThread() = 0;
 
   // Returns a new WebURLLoaderFactory which is associated with the worker
diff --git a/third_party/WebKit/public/platform/modules/mediastream/media_devices.mojom b/third_party/WebKit/public/platform/modules/mediastream/media_devices.mojom
index 25864ce..a7f6f07 100644
--- a/third_party/WebKit/public/platform/modules/mediastream/media_devices.mojom
+++ b/third_party/WebKit/public/platform/modules/mediastream/media_devices.mojom
@@ -41,9 +41,14 @@
 // enumeration requests and managing subscriptions for device-change
 // notifications.
 interface MediaDevicesDispatcherHost {
-  // Each of the arrays in the reply always contains NUM_MEDIA_DEVICE_TYPES and
-  // MEDIA_VIDEO_INPUT elements respectively. |enumeration| is indexed by device
-  // type as defined in content/common/media/media_devices.h.
+  // Enumerates media devices and capabilities. The reply contains the
+  // |enumeration| and |video_input_device_capabilities| arrays. The
+  // |enumeration| array always has NUM_MEDIA_DEVICE_TYPES elements indexed by
+  // device type as defined in MediaDeviceType. Each element of |enumeration| is
+  // an array with as many elements as devices of the corresponding type exist
+  // in the system, or zero if the device types was not requested. Similarly,
+  // the number of elements in |video_input_device_capabilities| is equal to the
+  // number of video input devices in the system, or zero if not requested.
   EnumerateDevices(bool request_audio_input,
                    bool request_video_input,
                    bool request_audio_output,
diff --git a/third_party/WebKit/public/platform/modules/websockets/OWNERS b/third_party/WebKit/public/platform/modules/websockets/OWNERS
deleted file mode 100644
index d6fd3dac..0000000
--- a/third_party/WebKit/public/platform/modules/websockets/OWNERS
+++ /dev/null
@@ -1,8 +0,0 @@
-yhirano@chromium.org
-ricea@chromium.org
-
-per-file *.mojom=set noparent
-per-file *.mojom=file://ipc/SECURITY_OWNERS
-
-# TEAM: blink-network-dev@chromium.org
-# COMPONENT: Blink>Network>WebSockets
diff --git a/third_party/WebKit/public/platform/modules/websockets/websocket.mojom b/third_party/WebKit/public/platform/modules/websockets/websocket.mojom
deleted file mode 100644
index e3302612..0000000
--- a/third_party/WebKit/public/platform/modules/websockets/websocket.mojom
+++ /dev/null
@@ -1,140 +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 blink.mojom;
-
-import "url/mojom/url.mojom";
-
-enum WebSocketMessageType {
-  CONTINUATION,
-  TEXT,
-  BINARY,
-  LAST = BINARY
-};
-
-// TODO(darin): Move to a more general location.
-struct HttpHeader {
-  string name;
-  string value;
-};
-
-// TODO(darin): Remove redundancy b/w |headers| and |headers_text|.
-
-struct WebSocketHandshakeRequest {
-  url.mojom.Url url;
-  array<HttpHeader> headers;
-  string headers_text;
-};
-
-struct WebSocketHandshakeResponse {
-  url.mojom.Url url;
-  int32 status_code;
-  string status_text;
-  array<HttpHeader> headers;
-  string headers_text;
-};
-
-interface WebSocketClient {
-  OnFailChannel(string reason);
-
-  // Notify the renderer that the browser has started an opening handshake.
-  // This message is for showing the request in the inspector and
-  // can be omitted if the inspector is not active.
-  OnStartOpeningHandshake(WebSocketHandshakeRequest request);
-
-  // Notify the renderer that the browser has finished an opening handshake.
-  // This message precedes AddChannelResponse.
-  // This message is for showing the response in the inspector and
-  // can be omitted if the inspector is not active.
-  OnFinishOpeningHandshake(WebSocketHandshakeResponse response);
-
-  // Response to an AddChannelRequest. |selected_protocol| is the sub-protocol
-  // the server selected, or empty if no sub-protocol was selected.
-  // |extensions| is the list of extensions negotiated for the connection.
-  OnAddChannelResponse(string selected_protocol, string extensions);
-
-  // Receive a non-control frame from the remote server.
-  // - |fin| indicates that this frame is the last in the current message.
-  // - |type| is the type of the message. On the first frame of a message, it
-  //   must be set to either WebSocketMessageType.TEXT or
-  //   WebSocketMessageType.BINARY. On subsequent frames, it must be set to
-  //   WebSocketMessageType.CONTINUATION, and the type is the same as that of
-  //   the first message. If |type| is WebSocketMessageType.TEXT, then the
-  //   concatenation of the |data| from every frame in the message must be valid
-  //   UTF-8. If |fin| is not set, |data| must be non-empty.
-  OnDataFrame(bool fin, WebSocketMessageType type, array<uint8> data);
-
-  // Add |quota| tokens of send quota for the channel. |quota| must be a
-  // positive integer. Both the browser and the renderer set send quota for the
-  // other side, and check that quota has not been exceeded when receiving
-  // messages.  Both sides start a new channel with a quota of 0, and must wait
-  // for a FlowControl message before calling SendFrame. The total available
-  // quota on one side must never exceed 0x7FFFFFFFFFFFFFFF tokens.
-  OnFlowControl(int64 quota);
-
-  // Drop the channel.
-  //
-  // When sent by the renderer, this will cause a Close message will be sent and
-  // the TCP/IP connection will be closed.
-  //
-  // When sent by the browser, this indicates that a Close has been received,
-  // the connection was closed, or a network or protocol error occurred.
-  //
-  // - |code| is one of the reason codes specified in RFC6455.
-  // - |reason|, if non-empty, is a UTF-8 encoded string which may be useful
-  //   for debugging but is not necessarily human-readable, as supplied by the
-  //   server in the Close message.
-  // - If |was_clean| is false, then the WebSocket connection was not closed
-  //   cleanly.
-  OnDropChannel(bool was_clean, uint16 code, string reason);
-
-  // Notify the renderer that a closing handshake has been initiated by the
-  // server, so that it can set the Javascript readyState to CLOSING.
-  OnClosingHandshake();
-};
-
-interface WebSocket {
-  // The client side may observe the following disconnection reason from the
-  // service side:
-  const uint32 kInsufficientResources = 1;
-
-  // Open new WebSocket connection to |socket_url|. |requested_protocols| is a
-  // list of tokens identifying sub-protocols the renderer would like to use,
-  // as described in RFC6455 "Subprotocols Using the WebSocket Protocol".
-  AddChannelRequest(url.mojom.Url url,
-                    array<string> requested_protocols,
-                    url.mojom.Url first_party_for_cookies,
-                    string user_agent_override,
-                    WebSocketClient client);
-
-  // Send a non-control frame to the remote server.
-  // - |fin| indicates that this frame is the last in the current message.
-  // - |type| is the type of the message. On the first frame of a message, it
-  //   must be set to either WebSocketMessageType.TEXT or
-  //   WebSocketMessageType.BINARY. On subsequent frames, it must be set to
-  //   WebSocketMessageType.CONTINUATION, and the type is the same as that of
-  //   the first message. If |type| is WebSocketMessageType.TEXT, then the
-  //   concatenation of the |data| from every frame in the message must be valid
-  //   UTF-8. If |fin| is not set, |data| must be non-empty.
-  SendFrame(bool fin, WebSocketMessageType type, array<uint8> data);
-
-  // Add |quota| tokens of send quota for the channel. |quota| must be a
-  // positive integer. Both the browser and the renderer set send quota for the
-  // other side, and check that quota has not been exceeded when receiving
-  // messages.  Both sides start a new channel with a quota of 0, and must wait
-  // for a FlowControl message before calling SendFrame. The total available
-  // quota on one side must never exceed 0x7FFFFFFFFFFFFFFF tokens.
-  SendFlowControl(int64 quota);
-
-  // Close the channel gracefully.
-  //
-  // When sent by the renderer, this will cause a Close message will be sent and
-  // the TCP/IP connection will be closed.
-  //
-  // - |code| is one of the reason codes specified in RFC6455.
-  // - |reason|, if non-empty, is a UTF-8 encoded string which may be useful for
-  //   debugging but is not necessarily human-readable, as supplied by the
-  //   server in the Close message.
-  StartClosingHandshake(uint16 code, string reason);
-};
diff --git a/third_party/WebKit/public/platform/web_feature.mojom b/third_party/WebKit/public/platform/web_feature.mojom
index 15539120..7f495ed 100644
--- a/third_party/WebKit/public/platform/web_feature.mojom
+++ b/third_party/WebKit/public/platform/web_feature.mojom
@@ -1882,6 +1882,11 @@
   kVRDisplayGetFrameData = 2390,
   kXMLHttpRequestResponseXML = 2391,
   kMessagePortTransferClosedPort = 2392,
+  kRTCLocalSdpModification = 2393,
+  kKeyboardApiLock = 2394,
+  kKeyboardApiUnlock = 2395,
+  kPPAPIURLRequestStreamToFile = 2396,
+  kPaymentHandler = 2397,
 
   // Add new features immediately above this line. Don't change assigned
   // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/WebKit/public/web/WebDocumentLoader.h b/third_party/WebKit/public/web/WebDocumentLoader.h
index 19ec4cc..dd11f105 100644
--- a/third_party/WebKit/public/web/WebDocumentLoader.h
+++ b/third_party/WebKit/public/web/WebDocumentLoader.h
@@ -35,6 +35,7 @@
 
 #include "WebNavigationType.h"
 #include "WebTextDirection.h"
+#include "base/time/time.h"
 #include "public/platform/WebCommon.h"
 #include "public/platform/WebSourceLocation.h"
 
@@ -111,14 +112,14 @@
   // should be called before WebFrameClient::didCommitProvisionalLoad.
   // Calling it later may confuse users, because JavaScript may have run and
   // the user may have already recorded the original value.
-  virtual void SetNavigationStartTime(double) = 0;
+  virtual void SetNavigationStartTime(base::TimeTicks) = 0;
 
   // Sets timing and attributes of the navigation.
   // Ordinarily, they are determined in WebCore, but when the navigation is
   // handled by the client, they can be passed here.
-  virtual void UpdateNavigation(double redirect_start_time,
-                                double redirect_end_time,
-                                double fetch_start_time,
+  virtual void UpdateNavigation(base::TimeTicks redirect_start_time,
+                                base::TimeTicks redirect_end_time,
+                                base::TimeTicks fetch_start_time,
                                 bool has_redirect) = 0;
 
   // Allows the embedder to inject a filter that will be consulted for each
diff --git a/third_party/WebKit/public/web/WebImeTextSpan.h b/third_party/WebKit/public/web/WebImeTextSpan.h
index e509a4c9..5275016 100644
--- a/third_party/WebKit/public/web/WebImeTextSpan.h
+++ b/third_party/WebKit/public/web/WebImeTextSpan.h
@@ -57,7 +57,6 @@
       : type(Type::kComposition),
         start_offset(0),
         end_offset(0),
-        underline_color(0),
         thickness(ui::mojom::ImeTextSpanThickness::kThin),
         background_color(0),
         suggestion_highlight_color(0),
@@ -67,7 +66,6 @@
       Type ty,
       unsigned s,
       unsigned e,
-      WebColor uc,
       ui::mojom::ImeTextSpanThickness th,
       WebColor bc,
       WebColor shc = 0,
@@ -75,7 +73,6 @@
       : type(ty),
         start_offset(s),
         end_offset(e),
-        underline_color(uc),
         thickness(th),
         background_color(bc),
         suggestion_highlight_color(shc),
@@ -92,7 +89,7 @@
   Type type;
   unsigned start_offset;
   unsigned end_offset;
-  WebColor underline_color;
+  WebColor underline_color = 0x00000000;
   ui::mojom::ImeTextSpanThickness thickness;
   WebColor background_color;
   WebColor suggestion_highlight_color;
diff --git a/third_party/WebKit/public/web/WebLeakDetector.h b/third_party/WebKit/public/web/WebLeakDetector.h
index ccb6e1b..bde4b9a 100644
--- a/third_party/WebKit/public/web/WebLeakDetector.h
+++ b/third_party/WebKit/public/web/WebLeakDetector.h
@@ -51,6 +51,7 @@
     unsigned number_of_live_v8_per_context_data;
     unsigned number_of_worker_global_scopes;
     unsigned number_of_live_ua_css_resources;
+    unsigned number_of_live_resource_fetchers;
   };
 
   virtual void OnLeakDetectionComplete(const Result&) = 0;
diff --git a/third_party/WebKit/public/web/WebLocalFrame.h b/third_party/WebKit/public/web/WebLocalFrame.h
index e0bc9bb..1dc822f2 100644
--- a/third_party/WebKit/public/web/WebLocalFrame.h
+++ b/third_party/WebKit/public/web/WebLocalFrame.h
@@ -30,6 +30,7 @@
 
 namespace blink {
 
+class FrameScheduler;
 class InterfaceRegistry;
 class WebAssociatedURLLoader;
 class WebAutofillClient;
@@ -41,7 +42,6 @@
 class WebDOMEvent;
 class WebFrameClient;
 class WebFrameWidget;
-class WebFrameScheduler;
 class WebInputMethodController;
 class WebPerformance;
 class WebRange;
@@ -496,6 +496,12 @@
   // Logs to the console associated with this frame.
   virtual void AddMessageToConsole(const WebConsoleMessage&) = 0;
 
+  // Expose modal dialog methods to avoid having to go through JavaScript.
+  virtual void Alert(const WebString& message) = 0;
+  virtual bool Confirm(const WebString& message) = 0;
+  virtual WebString Prompt(const WebString& message,
+                           const WebString& default_value) = 0;
+
   // Editing -------------------------------------------------------------
 
   virtual void SetMarkedText(const WebString& text,
@@ -753,7 +759,7 @@
 
   // Scheduling ---------------------------------------------------------------
 
-  virtual WebFrameScheduler* Scheduler() const = 0;
+  virtual FrameScheduler* Scheduler() const = 0;
 
   // Task queues --------------------------------------------------------------
 
diff --git a/third_party/blink/tools/move_blink_source.py b/third_party/blink/tools/move_blink_source.py
index 11c8d14..15f71cb9 100755
--- a/third_party/blink/tools/move_blink_source.py
+++ b/third_party/blink/tools/move_blink_source.py
@@ -218,6 +218,8 @@
 Update file contents without moving files.
 
 NOAUTOREVERT=true
+NOPRESUBMIT=true
+NOTREECHECKS=true
 Bug: 768828
 """)
 
@@ -274,6 +276,8 @@
 Move and rename files.
 
 NOAUTOREVERT=true
+NOPRESUBMIT=true
+NOTREECHECKS=true
 Bug: 768828
 """)
 
diff --git a/third_party/blink/tools/plan_blink_move.py b/third_party/blink/tools/plan_blink_move.py
index d8a1ffa1..5b30519 100755
--- a/third_party/blink/tools/plan_blink_move.py
+++ b/third_party/blink/tools/plan_blink_move.py
@@ -32,6 +32,7 @@
         # Skip some inspector-related files. #includes for these files are
         # generated by a script outside of Blink.
         if (re.match(r'Inspector.*Agent', basename)
+                or basename.startswith('AdTracker')
                 or basename == 'InspectorTraceEvents'
                 or basename == 'PerformanceMonitor'
                 or basename == 'PlatformTraceEventsAgent'):
diff --git a/third_party/closure_compiler/compiled_resources2.gyp b/third_party/closure_compiler/compiled_resources2.gyp
index 1a6c7894..403718f1 100644
--- a/third_party/closure_compiler/compiled_resources2.gyp
+++ b/third_party/closure_compiler/compiled_resources2.gyp
@@ -18,6 +18,7 @@
         '<(DEPTH)/chrome/browser/resources/chromeos/braille_ime/compiled_resources2.gyp:*',
         '<(DEPTH)/chrome/browser/resources/chromeos/compiled_resources2.gyp:*',
         '<(DEPTH)/chrome/browser/resources/chromeos/login/compiled_resources2.gyp:*',
+        '<(DEPTH)/chrome/browser/resources/chromeos/multidevice_setup/compiled_resources2.gyp:*',
         '<(DEPTH)/chrome/browser/resources/chromeos/network_ui/compiled_resources2.gyp:*',
         '<(DEPTH)/chrome/browser/resources/chromeos/select_to_speak/compiled_resources2.gyp:*',
         '<(DEPTH)/chrome/browser/resources/chromeos/switch_access/compiled_resources2.gyp:*',
diff --git a/third_party/feed/BUILD.gn b/third_party/feed/BUILD.gn
index f0f2024..55ff591 100644
--- a/third_party/feed/BUILD.gn
+++ b/third_party/feed/BUILD.gn
@@ -4,6 +4,8 @@
 
 import("//build/config/android/config.gni")
 import("//build/config/android/rules.gni")
+import("//third_party/feed/java_sources.gni")
+import("//third_party/feed/proto_sources.gni")
 import("//third_party/protobuf/proto_library.gni")
 
 android_resources("piet_resources") {
@@ -12,140 +14,12 @@
   custom_package = "com.google.android.libraries.feed.piet"
 }
 
-android_library("feed_java") {
+android_library("feed_lib_java") {
   chromium_code = false
-  java_files = [
-    "src/src/main/java/com/google/android/libraries/feed/api/actionhandler/FeedActionHandler.java",
-    "src/src/main/java/com/google/android/libraries/feed/api/actionhandler/FeedActionHandlerImpl.java",
-    "src/src/main/java/com/google/android/libraries/feed/api/common/PayloadWithId.java",
-    "src/src/main/java/com/google/android/libraries/feed/api/common/StreamSession.java",
-    "src/src/main/java/com/google/android/libraries/feed/api/common/ThreadUtils.java",
-    "src/src/main/java/com/google/android/libraries/feed/api/common/UiRunnableHandler.java",
-    "src/src/main/java/com/google/android/libraries/feed/api/lifecycle/AppLifecycleListener.java",
-    "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/FeatureChange.java",
-    "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/FeatureChangeObserver.java",
-    "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/ModelChild.java",
-    "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/ModelCursor.java",
-    "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/ModelFeature.java",
-    "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/ModelMutation.java",
-    "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/ModelProvider.java",
-    "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/ModelProviderFactory.java",
-    "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/ModelProviderObserver.java",
-    "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/ModelToken.java",
-    "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/TokenCompleted.java",
-    "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/TokenCompletedObserver.java",
-    "src/src/main/java/com/google/android/libraries/feed/api/protocoladapter/ProtocolAdapter.java",
-    "src/src/main/java/com/google/android/libraries/feed/api/requestmanager/RequestManager.java",
-    "src/src/main/java/com/google/android/libraries/feed/api/scope/FeedProcessScope.java",
-    "src/src/main/java/com/google/android/libraries/feed/api/scope/FeedStreamScope.java",
-    "src/src/main/java/com/google/android/libraries/feed/api/sessionmanager/SessionManager.java",
-    "src/src/main/java/com/google/android/libraries/feed/api/sessionmanager/SessionMutation.java",
-    "src/src/main/java/com/google/android/libraries/feed/api/store/ContentMutation.java",
-    "src/src/main/java/com/google/android/libraries/feed/api/store/SessionMutation.java",
-    "src/src/main/java/com/google/android/libraries/feed/api/store/Store.java",
-    "src/src/main/java/com/google/android/libraries/feed/api/stream/CardConfiguration.java",
-    "src/src/main/java/com/google/android/libraries/feed/api/stream/ContentChangedListener.java",
-    "src/src/main/java/com/google/android/libraries/feed/api/stream/ScrollListener.java",
-    "src/src/main/java/com/google/android/libraries/feed/api/stream/Stream.java",
-    "src/src/main/java/com/google/android/libraries/feed/basicstream/BasicStream.java",
-    "src/src/main/java/com/google/android/libraries/feed/basicstream/internal/StreamActionApiImpl.java",
-    "src/src/main/java/com/google/android/libraries/feed/basicstream/internal/StreamRecyclerViewAdapter.java",
-    "src/src/main/java/com/google/android/libraries/feed/basicstream/internal/piet/PietSharedStateSupplier.java",
-    "src/src/main/java/com/google/android/libraries/feed/common/Committer.java",
-    "src/src/main/java/com/google/android/libraries/feed/common/Consumer.java",
-    "src/src/main/java/com/google/android/libraries/feed/common/DateUtils.java",
-    "src/src/main/java/com/google/android/libraries/feed/common/Dumpable.java",
-    "src/src/main/java/com/google/android/libraries/feed/common/Dumper.java",
-    "src/src/main/java/com/google/android/libraries/feed/common/Logger.java",
-    "src/src/main/java/com/google/android/libraries/feed/common/TimingUtils.java",
-    "src/src/main/java/com/google/android/libraries/feed/common/UiRunnableHandlerImpl.java",
-    "src/src/main/java/com/google/android/libraries/feed/common/Validators.java",
-    "src/src/main/java/com/google/android/libraries/feed/common/protoextensions/FeedExtensionRegistry.java",
-    "src/src/main/java/com/google/android/libraries/feed/feedapplifecyclelistener/FeedAppLifecycleListener.java",
-    "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/FeedModelProvider.java",
-    "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/FeedModelProviderFactory.java",
-    "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/internal/CursorProvider.java",
-    "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/internal/FeatureChangeImpl.java",
-    "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/internal/ModelChildBinder.java",
-    "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/internal/ModelCursorImpl.java",
-    "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/internal/ModelMutationImpl.java",
-    "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/internal/UpdatableModelChild.java",
-    "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/internal/UpdatableModelFeature.java",
-    "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/internal/UpdatableModelToken.java",
-    "src/src/main/java/com/google/android/libraries/feed/feedprotocoladapter/FeedProtocolAdapter.java",
-    "src/src/main/java/com/google/android/libraries/feed/feedrequestmanager/FeedRequestManager.java",
-    "src/src/main/java/com/google/android/libraries/feed/feedsessionmanager/FeedSessionManager.java",
-    "src/src/main/java/com/google/android/libraries/feed/feedsessionmanager/internal/HeadSessionImpl.java",
-    "src/src/main/java/com/google/android/libraries/feed/feedsessionmanager/internal/InitializableSession.java",
-    "src/src/main/java/com/google/android/libraries/feed/feedsessionmanager/internal/Session.java",
-    "src/src/main/java/com/google/android/libraries/feed/feedsessionmanager/internal/SessionFactory.java",
-    "src/src/main/java/com/google/android/libraries/feed/feedsessionmanager/internal/SessionImpl.java",
-    "src/src/main/java/com/google/android/libraries/feed/feedsessionmanager/internal/SessionMutationImpl.java",
-    "src/src/main/java/com/google/android/libraries/feed/feedstore/FeedStore.java",
-    "src/src/main/java/com/google/android/libraries/feed/feedstore/internal/FeedContentMutation.java",
-    "src/src/main/java/com/google/android/libraries/feed/feedstore/internal/FeedSessionMutation.java",
-    "src/src/main/java/com/google/android/libraries/feed/feedstore/internal/SessionState.java",
-    "src/src/main/java/com/google/android/libraries/feed/host/action/ActionApi.java",
-    "src/src/main/java/com/google/android/libraries/feed/host/action/ActionParser.java",
-    "src/src/main/java/com/google/android/libraries/feed/host/action/StreamActionApi.java",
-    "src/src/main/java/com/google/android/libraries/feed/host/common/Callback.java",
-    "src/src/main/java/com/google/android/libraries/feed/host/common/ProtoExtensionProvider.java",
-    "src/src/main/java/com/google/android/libraries/feed/host/config/ConfigManager.java",
-    "src/src/main/java/com/google/android/libraries/feed/hostimpl/storage/InMemoryJournalStorage.java",
-    "src/src/main/java/com/google/android/libraries/feed/hostimpl/storage/InMemoryKeyValuePairStorage.java",
-    "src/src/main/java/com/google/android/libraries/feed/host/imageloader/ImageLoaderApi.java",
-    "src/src/main/java/com/google/android/libraries/feed/host/logging/LoggingApi.java",
-    "src/src/main/java/com/google/android/libraries/feed/host/network/HttpRequest.java",
-    "src/src/main/java/com/google/android/libraries/feed/host/network/HttpResponse.java",
-    "src/src/main/java/com/google/android/libraries/feed/host/network/NetworkClient.java",
-    "src/src/main/java/com/google/android/libraries/feed/host/scheduler/SchedulerApi.java",
-    "src/src/main/java/com/google/android/libraries/feed/host/storage/JournalMutation.java",
-    "src/src/main/java/com/google/android/libraries/feed/host/storage/JournalOperation.java",
-    "src/src/main/java/com/google/android/libraries/feed/host/storage/JournalStorage.java",
-    "src/src/main/java/com/google/android/libraries/feed/host/storage/KeyValuePairStorage.java",
-    "src/src/main/java/com/google/android/libraries/feed/host/storage/StorageMutation.java",
-    "src/src/main/java/com/google/android/libraries/feed/host/storage/StorageOperation.java",
-    "src/src/main/java/com/google/android/libraries/feed/host/storage/StorageOperationListSimplifier.java",
-    "src/src/main/java/com/google/android/libraries/feed/hostimpl/logging/LoggingApiImpl.java",
-    "src/src/main/java/com/google/android/libraries/feed/hostimpl/scheduler/SchedulerApiImpl.java",
-    "src/src/main/java/com/google/android/libraries/feed/mocknetworkclient/MockServerNetworkClient.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/AdapterFactory.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/AdapterParameters.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/ChunkedTextElementAdapter.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/CustomElementAdapter.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/ElementAdapter.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/ElementAdapterFactory.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/ElementContainerAdapter.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/ElementListAdapter.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/ErrorViewUtils.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/FrameAdapter.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/FrameContext.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/FrameModelBinder.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/GridRowAdapter.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/ImageElementAdapter.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/KeyedRecyclerPool.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/ParameterizedTextElementAdapter.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/ParameterizedTextEvaluator.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/PietManager.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/PietStylesHelper.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/RecyclerKey.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/RecyclerPool.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/SingleKeyRecyclerPool.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/SpacerElementAdapter.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/StyleProvider.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/TemplateInvocationAdapter.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/TextElementAdapter.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/ViewUtils.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/host/ActionHandler.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/host/AssetProvider.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/host/CustomElementProvider.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/ui/RoundedCornerColorDrawable.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/util/Producer.java",
-    "src/src/main/java/com/google/android/libraries/feed/piet/util/Producers.java",
-  ]
+  java_files = feed_lib_java_sources
 
   deps = [
-    ":piet_proto_java",
+    ":feed_lib_proto_java",
     ":piet_resources",
     "//third_party/android_tools:android_support_annotations_java",
     "//third_party/android_tools:android_support_cardview_java",
@@ -156,41 +30,8 @@
   ]
 }
 
-proto_java_library("piet_proto_java") {
+proto_java_library("feed_lib_proto_java") {
   proto_path = "src"
   generate_lite = true
-  sources = [
-    "src/src/main/proto/com/google/android/libraries/feed/api/proto/stream_data.proto",
-    "src/src/main/proto/search/now/proto/ui/action/feed_action.proto",
-    "src/src/main/proto/search/now/proto/ui/action/piet_extensions.proto",
-    "src/src/main/proto/search/now/proto/ui/piet/accessibility.proto",
-    "src/src/main/proto/search/now/proto/ui/piet/actions.proto",
-    "src/src/main/proto/search/now/proto/ui/piet/binding_refs.proto",
-    "src/src/main/proto/search/now/proto/ui/piet/elements.proto",
-    "src/src/main/proto/search/now/proto/ui/piet/gradients.proto",
-    "src/src/main/proto/search/now/proto/ui/piet/images.proto",
-    "src/src/main/proto/search/now/proto/ui/piet/piet.proto",
-    "src/src/main/proto/search/now/proto/ui/piet/piet_android_support.proto",
-    "src/src/main/proto/search/now/proto/ui/piet/piet_web_support.proto",
-    "src/src/main/proto/search/now/proto/ui/piet/rounded_corners.proto",
-    "src/src/main/proto/search/now/proto/ui/piet/shadows.proto",
-    "src/src/main/proto/search/now/proto/ui/piet/styles.proto",
-    "src/src/main/proto/search/now/proto/ui/piet/text.proto",
-    "src/src/main/proto/search/now/proto/ui/stream/stream_structure.proto",
-    "src/src/main/proto/search/now/proto/wire/feed/client_info.proto",
-    "src/src/main/proto/search/now/proto/wire/feed/content_id.proto",
-    "src/src/main/proto/search/now/proto/wire/feed/data_operation.proto",
-    "src/src/main/proto/search/now/proto/wire/feed/feature.proto",
-    "src/src/main/proto/search/now/proto/wire/feed/feed_card.proto",
-    "src/src/main/proto/search/now/proto/wire/feed/feed_query.proto",
-    "src/src/main/proto/search/now/proto/wire/feed/feed_request.proto",
-    "src/src/main/proto/search/now/proto/wire/feed/feed_response.proto",
-    "src/src/main/proto/search/now/proto/wire/feed/feed_stream.proto",
-    "src/src/main/proto/search/now/proto/wire/feed/mockserver/mock_server.proto",
-    "src/src/main/proto/search/now/proto/wire/feed/payload_metadata.proto",
-    "src/src/main/proto/search/now/proto/wire/feed/piet_shared_state_item.proto",
-    "src/src/main/proto/search/now/proto/wire/feed/request.proto",
-    "src/src/main/proto/search/now/proto/wire/feed/response.proto",
-    "src/src/main/proto/search/now/proto/wire/feed/version.proto",
-  ]
+  sources = feed_lib_proto_sources
 }
diff --git a/third_party/feed/java_sources.gni b/third_party/feed/java_sources.gni
new file mode 100644
index 0000000..2ce218d
--- /dev/null
+++ b/third_party/feed/java_sources.gni
@@ -0,0 +1,133 @@
+# Copyright 2018 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.
+
+feed_lib_java_sources = [
+  "src/src/main/java/com/google/android/libraries/feed/api/actionhandler/FeedActionHandler.java",
+  "src/src/main/java/com/google/android/libraries/feed/api/actionhandler/FeedActionHandlerImpl.java",
+  "src/src/main/java/com/google/android/libraries/feed/api/common/PayloadWithId.java",
+  "src/src/main/java/com/google/android/libraries/feed/api/common/StreamSession.java",
+  "src/src/main/java/com/google/android/libraries/feed/api/common/ThreadUtils.java",
+  "src/src/main/java/com/google/android/libraries/feed/api/common/UiRunnableHandler.java",
+  "src/src/main/java/com/google/android/libraries/feed/api/lifecycle/AppLifecycleListener.java",
+  "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/FeatureChange.java",
+  "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/FeatureChangeObserver.java",
+  "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/ModelChild.java",
+  "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/ModelCursor.java",
+  "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/ModelFeature.java",
+  "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/ModelMutation.java",
+  "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/ModelProvider.java",
+  "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/ModelProviderFactory.java",
+  "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/ModelProviderObserver.java",
+  "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/ModelToken.java",
+  "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/TokenCompleted.java",
+  "src/src/main/java/com/google/android/libraries/feed/api/modelprovider/TokenCompletedObserver.java",
+  "src/src/main/java/com/google/android/libraries/feed/api/protocoladapter/ProtocolAdapter.java",
+  "src/src/main/java/com/google/android/libraries/feed/api/requestmanager/RequestManager.java",
+  "src/src/main/java/com/google/android/libraries/feed/api/scope/FeedProcessScope.java",
+  "src/src/main/java/com/google/android/libraries/feed/api/scope/FeedStreamScope.java",
+  "src/src/main/java/com/google/android/libraries/feed/api/sessionmanager/SessionManager.java",
+  "src/src/main/java/com/google/android/libraries/feed/api/sessionmanager/SessionMutation.java",
+  "src/src/main/java/com/google/android/libraries/feed/api/store/ContentMutation.java",
+  "src/src/main/java/com/google/android/libraries/feed/api/store/SessionMutation.java",
+  "src/src/main/java/com/google/android/libraries/feed/api/store/Store.java",
+  "src/src/main/java/com/google/android/libraries/feed/api/stream/CardConfiguration.java",
+  "src/src/main/java/com/google/android/libraries/feed/api/stream/ContentChangedListener.java",
+  "src/src/main/java/com/google/android/libraries/feed/api/stream/ScrollListener.java",
+  "src/src/main/java/com/google/android/libraries/feed/api/stream/Stream.java",
+  "src/src/main/java/com/google/android/libraries/feed/basicstream/BasicStream.java",
+  "src/src/main/java/com/google/android/libraries/feed/basicstream/internal/StreamActionApiImpl.java",
+  "src/src/main/java/com/google/android/libraries/feed/basicstream/internal/StreamRecyclerViewAdapter.java",
+  "src/src/main/java/com/google/android/libraries/feed/basicstream/internal/piet/PietSharedStateSupplier.java",
+  "src/src/main/java/com/google/android/libraries/feed/common/Committer.java",
+  "src/src/main/java/com/google/android/libraries/feed/common/Consumer.java",
+  "src/src/main/java/com/google/android/libraries/feed/common/DateUtils.java",
+  "src/src/main/java/com/google/android/libraries/feed/common/Dumpable.java",
+  "src/src/main/java/com/google/android/libraries/feed/common/Dumper.java",
+  "src/src/main/java/com/google/android/libraries/feed/common/Logger.java",
+  "src/src/main/java/com/google/android/libraries/feed/common/TimingUtils.java",
+  "src/src/main/java/com/google/android/libraries/feed/common/UiRunnableHandlerImpl.java",
+  "src/src/main/java/com/google/android/libraries/feed/common/Validators.java",
+  "src/src/main/java/com/google/android/libraries/feed/common/protoextensions/FeedExtensionRegistry.java",
+  "src/src/main/java/com/google/android/libraries/feed/feedapplifecyclelistener/FeedAppLifecycleListener.java",
+  "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/FeedModelProvider.java",
+  "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/FeedModelProviderFactory.java",
+  "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/internal/CursorProvider.java",
+  "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/internal/FeatureChangeImpl.java",
+  "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/internal/ModelChildBinder.java",
+  "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/internal/ModelCursorImpl.java",
+  "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/internal/ModelMutationImpl.java",
+  "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/internal/UpdatableModelChild.java",
+  "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/internal/UpdatableModelFeature.java",
+  "src/src/main/java/com/google/android/libraries/feed/feedmodelprovider/internal/UpdatableModelToken.java",
+  "src/src/main/java/com/google/android/libraries/feed/feedprotocoladapter/FeedProtocolAdapter.java",
+  "src/src/main/java/com/google/android/libraries/feed/feedrequestmanager/FeedRequestManager.java",
+  "src/src/main/java/com/google/android/libraries/feed/feedsessionmanager/FeedSessionManager.java",
+  "src/src/main/java/com/google/android/libraries/feed/feedsessionmanager/internal/HeadSessionImpl.java",
+  "src/src/main/java/com/google/android/libraries/feed/feedsessionmanager/internal/InitializableSession.java",
+  "src/src/main/java/com/google/android/libraries/feed/feedsessionmanager/internal/Session.java",
+  "src/src/main/java/com/google/android/libraries/feed/feedsessionmanager/internal/SessionFactory.java",
+  "src/src/main/java/com/google/android/libraries/feed/feedsessionmanager/internal/SessionImpl.java",
+  "src/src/main/java/com/google/android/libraries/feed/feedsessionmanager/internal/SessionMutationImpl.java",
+  "src/src/main/java/com/google/android/libraries/feed/feedstore/FeedStore.java",
+  "src/src/main/java/com/google/android/libraries/feed/feedstore/internal/FeedContentMutation.java",
+  "src/src/main/java/com/google/android/libraries/feed/feedstore/internal/FeedSessionMutation.java",
+  "src/src/main/java/com/google/android/libraries/feed/feedstore/internal/SessionState.java",
+  "src/src/main/java/com/google/android/libraries/feed/host/action/ActionApi.java",
+  "src/src/main/java/com/google/android/libraries/feed/host/action/ActionParser.java",
+  "src/src/main/java/com/google/android/libraries/feed/host/action/StreamActionApi.java",
+  "src/src/main/java/com/google/android/libraries/feed/host/common/Callback.java",
+  "src/src/main/java/com/google/android/libraries/feed/host/common/ProtoExtensionProvider.java",
+  "src/src/main/java/com/google/android/libraries/feed/host/config/ConfigManager.java",
+  "src/src/main/java/com/google/android/libraries/feed/host/imageloader/ImageLoaderApi.java",
+  "src/src/main/java/com/google/android/libraries/feed/host/logging/LoggingApi.java",
+  "src/src/main/java/com/google/android/libraries/feed/host/network/HttpRequest.java",
+  "src/src/main/java/com/google/android/libraries/feed/host/network/HttpResponse.java",
+  "src/src/main/java/com/google/android/libraries/feed/host/network/NetworkClient.java",
+  "src/src/main/java/com/google/android/libraries/feed/host/scheduler/SchedulerApi.java",
+  "src/src/main/java/com/google/android/libraries/feed/host/storage/JournalMutation.java",
+  "src/src/main/java/com/google/android/libraries/feed/host/storage/JournalOperation.java",
+  "src/src/main/java/com/google/android/libraries/feed/host/storage/JournalStorage.java",
+  "src/src/main/java/com/google/android/libraries/feed/host/storage/KeyValuePairStorage.java",
+  "src/src/main/java/com/google/android/libraries/feed/host/storage/StorageMutation.java",
+  "src/src/main/java/com/google/android/libraries/feed/host/storage/StorageOperation.java",
+  "src/src/main/java/com/google/android/libraries/feed/host/storage/StorageOperationListSimplifier.java",
+  "src/src/main/java/com/google/android/libraries/feed/hostimpl/logging/LoggingApiImpl.java",
+  "src/src/main/java/com/google/android/libraries/feed/hostimpl/scheduler/SchedulerApiImpl.java",
+  "src/src/main/java/com/google/android/libraries/feed/hostimpl/storage/InMemoryJournalStorage.java",
+  "src/src/main/java/com/google/android/libraries/feed/hostimpl/storage/InMemoryKeyValuePairStorage.java",
+  "src/src/main/java/com/google/android/libraries/feed/mocknetworkclient/MockServerNetworkClient.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/AdapterFactory.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/AdapterParameters.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/ChunkedTextElementAdapter.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/CustomElementAdapter.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/ElementAdapter.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/ElementAdapterFactory.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/ElementContainerAdapter.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/ElementListAdapter.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/ErrorViewUtils.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/FrameAdapter.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/FrameContext.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/FrameModelBinder.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/GridRowAdapter.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/ImageElementAdapter.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/KeyedRecyclerPool.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/ParameterizedTextElementAdapter.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/ParameterizedTextEvaluator.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/PietManager.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/PietStylesHelper.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/RecyclerKey.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/RecyclerPool.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/SingleKeyRecyclerPool.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/SpacerElementAdapter.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/StyleProvider.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/TemplateInvocationAdapter.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/TextElementAdapter.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/ViewUtils.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/host/ActionHandler.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/host/AssetProvider.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/host/CustomElementProvider.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/ui/RoundedCornerColorDrawable.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/util/Producer.java",
+  "src/src/main/java/com/google/android/libraries/feed/piet/util/Producers.java",
+]
diff --git a/third_party/feed/proto_sources.gni b/third_party/feed/proto_sources.gni
new file mode 100644
index 0000000..a466f98
--- /dev/null
+++ b/third_party/feed/proto_sources.gni
@@ -0,0 +1,38 @@
+# Copyright 2018 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.
+
+feed_lib_proto_sources = [
+  "src/src/main/proto/com/google/android/libraries/feed/api/proto/stream_data.proto",
+  "src/src/main/proto/search/now/proto/ui/action/feed_action.proto",
+  "src/src/main/proto/search/now/proto/ui/action/piet_extensions.proto",
+  "src/src/main/proto/search/now/proto/ui/piet/accessibility.proto",
+  "src/src/main/proto/search/now/proto/ui/piet/actions.proto",
+  "src/src/main/proto/search/now/proto/ui/piet/binding_refs.proto",
+  "src/src/main/proto/search/now/proto/ui/piet/elements.proto",
+  "src/src/main/proto/search/now/proto/ui/piet/gradients.proto",
+  "src/src/main/proto/search/now/proto/ui/piet/images.proto",
+  "src/src/main/proto/search/now/proto/ui/piet/piet.proto",
+  "src/src/main/proto/search/now/proto/ui/piet/piet_android_support.proto",
+  "src/src/main/proto/search/now/proto/ui/piet/piet_web_support.proto",
+  "src/src/main/proto/search/now/proto/ui/piet/rounded_corners.proto",
+  "src/src/main/proto/search/now/proto/ui/piet/shadows.proto",
+  "src/src/main/proto/search/now/proto/ui/piet/styles.proto",
+  "src/src/main/proto/search/now/proto/ui/piet/text.proto",
+  "src/src/main/proto/search/now/proto/ui/stream/stream_structure.proto",
+  "src/src/main/proto/search/now/proto/wire/feed/client_info.proto",
+  "src/src/main/proto/search/now/proto/wire/feed/content_id.proto",
+  "src/src/main/proto/search/now/proto/wire/feed/data_operation.proto",
+  "src/src/main/proto/search/now/proto/wire/feed/feature.proto",
+  "src/src/main/proto/search/now/proto/wire/feed/feed_card.proto",
+  "src/src/main/proto/search/now/proto/wire/feed/feed_query.proto",
+  "src/src/main/proto/search/now/proto/wire/feed/feed_request.proto",
+  "src/src/main/proto/search/now/proto/wire/feed/feed_response.proto",
+  "src/src/main/proto/search/now/proto/wire/feed/feed_stream.proto",
+  "src/src/main/proto/search/now/proto/wire/feed/mockserver/mock_server.proto",
+  "src/src/main/proto/search/now/proto/wire/feed/payload_metadata.proto",
+  "src/src/main/proto/search/now/proto/wire/feed/piet_shared_state_item.proto",
+  "src/src/main/proto/search/now/proto/wire/feed/request.proto",
+  "src/src/main/proto/search/now/proto/wire/feed/response.proto",
+  "src/src/main/proto/search/now/proto/wire/feed/version.proto",
+]
diff --git a/third_party/ink/OWNERS b/third_party/ink/OWNERS
new file mode 100644
index 0000000..675a16b
--- /dev/null
+++ b/third_party/ink/OWNERS
@@ -0,0 +1,2 @@
+dvallet@chromium.org
+martiw@chromium.org
diff --git a/third_party/libjpeg.gni b/third_party/libjpeg.gni
new file mode 100644
index 0000000..049348b7
--- /dev/null
+++ b/third_party/libjpeg.gni
@@ -0,0 +1,12 @@
+# Copyright 2018 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.
+
+declare_args() {
+  # Uses system libjpeg. If true, overrides use_libjpeg_turbo.
+  use_system_libjpeg = false
+
+  # Uses libjpeg_turbo as the jpeg implementation. Has no effect if
+  # use_system_libjpeg is set.
+  use_libjpeg_turbo = true
+}
diff --git a/third_party/libusb/src/libusb/os/windows_usb.c b/third_party/libusb/src/libusb/os/windows_usb.c
index 48ea08ca..9caab76 100644
--- a/third_party/libusb/src/libusb/os/windows_usb.c
+++ b/third_party/libusb/src/libusb/os/windows_usb.c
@@ -1105,7 +1105,10 @@
 	dev->port_number = port_number;
 	priv->depth = parent_priv->depth + 1;
 	priv->parent_dev = parent_dev;
-	dev->parent_dev = libusb_ref_device(parent_dev);
+	if (dev->parent_dev != parent_dev) {
+		safe_unref_device(dev->parent_dev);
+		dev->parent_dev = libusb_ref_device(parent_dev);
+	}
 
 	// If the device address is already set, we can stop here
 	if (dev->device_address != 0) {
diff --git a/third_party/libvpx/README.chromium b/third_party/libvpx/README.chromium
index fc28ad8..710bc51 100644
--- a/third_party/libvpx/README.chromium
+++ b/third_party/libvpx/README.chromium
@@ -5,9 +5,9 @@
 License File: source/libvpx/LICENSE
 Security Critical: yes
 
-Date: Monday March 12 2018
+Date: Tuesday March 20 2018
 Branch: master
-Commit: 7b5a57449ba07f35cc400516d311ce88c49dce9a
+Commit: 1f82e061229352b6e86564da7e3132b97ed924be
 
 Description:
 Contains the sources used to compile libvpx binaries used by Google Chrome and
diff --git a/third_party/libvpx/generate_gni.sh b/third_party/libvpx/generate_gni.sh
index a293e170..5704e760 100755
--- a/third_party/libvpx/generate_gni.sh
+++ b/third_party/libvpx/generate_gni.sh
@@ -422,7 +422,11 @@
   cp vpx_version.h $BASE_DIR/$LIBVPX_CONFIG_DIR
 
   echo "Generate X86_64 source list."
-  config=$(print_config linux/x64)
+  # Windows needs float_control_word.asm for Windows. This was previously
+  # emms_mmx.asm but a refactoring pulled out the cross platform bits. Because
+  # of this, use the win/x64 configuration as the reference. The empty asm
+  # object should not perturb the other builds.
+  config=$(print_config win/x64)
   make_clean
   make libvpx_srcs.txt target=libs $config > /dev/null
   convert_srcs_to_project_files libvpx_srcs.txt libvpx_srcs_x86_64
diff --git a/third_party/libvpx/libvpx_srcs.gni b/third_party/libvpx/libvpx_srcs.gni
index eff8642c..412d60d 100644
--- a/third_party/libvpx/libvpx_srcs.gni
+++ b/third_party/libvpx/libvpx_srcs.gni
@@ -268,10 +268,12 @@
   "//third_party/libvpx/source/libvpx/vp9/vp9_dx_iface.h",
   "//third_party/libvpx/source/libvpx/vp9/vp9_iface_common.h",
   "//third_party/libvpx/source/libvpx/vpx/internal/vpx_codec_internal.h",
+  "//third_party/libvpx/source/libvpx/vpx/src/svc_encodeframe.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_codec.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_decoder.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_encoder.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_image.c",
+  "//third_party/libvpx/source/libvpx/vpx/svc_context.h",
   "//third_party/libvpx/source/libvpx/vpx/vp8.h",
   "//third_party/libvpx/source/libvpx/vpx/vp8cx.h",
   "//third_party/libvpx/source/libvpx/vpx/vp8dx.h",
@@ -407,10 +409,11 @@
   "//third_party/libvpx/source/libvpx/vpx_dsp/x86/vpx_subpixel_8t_ssse3.asm",
   "//third_party/libvpx/source/libvpx/vpx_dsp/x86/vpx_subpixel_bilinear_sse2.asm",
   "//third_party/libvpx/source/libvpx/vpx_dsp/x86/vpx_subpixel_bilinear_ssse3.asm",
-  "//third_party/libvpx/source/libvpx/vpx_ports/emms.asm",
 ]
-libvpx_srcs_x86_mmx =
-    [ "//third_party/libvpx/source/libvpx/vp8/common/x86/idct_blk_mmx.c" ]
+libvpx_srcs_x86_mmx = [
+  "//third_party/libvpx/source/libvpx/vp8/common/x86/idct_blk_mmx.c",
+  "//third_party/libvpx/source/libvpx/vpx_ports/emms_mmx.c",
+]
 libvpx_srcs_x86_sse2 = [
   "//third_party/libvpx/source/libvpx/vp8/common/x86/idct_blk_sse2.c",
   "//third_party/libvpx/source/libvpx/vp8/encoder/x86/denoising_sse2.c",
@@ -740,10 +743,12 @@
   "//third_party/libvpx/source/libvpx/vp9/vp9_dx_iface.h",
   "//third_party/libvpx/source/libvpx/vp9/vp9_iface_common.h",
   "//third_party/libvpx/source/libvpx/vpx/internal/vpx_codec_internal.h",
+  "//third_party/libvpx/source/libvpx/vpx/src/svc_encodeframe.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_codec.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_decoder.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_encoder.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_image.c",
+  "//third_party/libvpx/source/libvpx/vpx/svc_context.h",
   "//third_party/libvpx/source/libvpx/vpx/vp8.h",
   "//third_party/libvpx/source/libvpx/vpx/vp8cx.h",
   "//third_party/libvpx/source/libvpx/vpx/vp8dx.h",
@@ -884,7 +889,7 @@
   "//third_party/libvpx/source/libvpx/vpx_dsp/x86/vpx_subpixel_8t_ssse3.asm",
   "//third_party/libvpx/source/libvpx/vpx_dsp/x86/vpx_subpixel_bilinear_sse2.asm",
   "//third_party/libvpx/source/libvpx/vpx_dsp/x86/vpx_subpixel_bilinear_ssse3.asm",
-  "//third_party/libvpx/source/libvpx/vpx_ports/emms.asm",
+  "//third_party/libvpx/source/libvpx/vpx_ports/float_control_word.asm",
 ]
 libvpx_srcs_x86_64_mmx =
     [ "//third_party/libvpx/source/libvpx/vp8/common/x86/idct_blk_mmx.c" ]
@@ -1213,10 +1218,12 @@
   "//third_party/libvpx/source/libvpx/vp9/vp9_dx_iface.h",
   "//third_party/libvpx/source/libvpx/vp9/vp9_iface_common.h",
   "//third_party/libvpx/source/libvpx/vpx/internal/vpx_codec_internal.h",
+  "//third_party/libvpx/source/libvpx/vpx/src/svc_encodeframe.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_codec.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_decoder.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_encoder.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_image.c",
+  "//third_party/libvpx/source/libvpx/vpx/svc_context.h",
   "//third_party/libvpx/source/libvpx/vpx/vp8.h",
   "//third_party/libvpx/source/libvpx/vpx/vp8cx.h",
   "//third_party/libvpx/source/libvpx/vpx/vp8dx.h",
@@ -1582,10 +1589,12 @@
   "//third_party/libvpx/source/libvpx/vp9/vp9_dx_iface.h",
   "//third_party/libvpx/source/libvpx/vp9/vp9_iface_common.h",
   "//third_party/libvpx/source/libvpx/vpx/internal/vpx_codec_internal.h",
+  "//third_party/libvpx/source/libvpx/vpx/src/svc_encodeframe.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_codec.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_decoder.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_encoder.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_image.c",
+  "//third_party/libvpx/source/libvpx/vpx/svc_context.h",
   "//third_party/libvpx/source/libvpx/vpx/vp8.h",
   "//third_party/libvpx/source/libvpx/vpx/vp8cx.h",
   "//third_party/libvpx/source/libvpx/vpx/vp8dx.h",
@@ -1968,10 +1977,12 @@
   "//third_party/libvpx/source/libvpx/vp9/vp9_dx_iface.h",
   "//third_party/libvpx/source/libvpx/vp9/vp9_iface_common.h",
   "//third_party/libvpx/source/libvpx/vpx/internal/vpx_codec_internal.h",
+  "//third_party/libvpx/source/libvpx/vpx/src/svc_encodeframe.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_codec.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_decoder.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_encoder.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_image.c",
+  "//third_party/libvpx/source/libvpx/vpx/svc_context.h",
   "//third_party/libvpx/source/libvpx/vpx/vp8.h",
   "//third_party/libvpx/source/libvpx/vpx/vp8cx.h",
   "//third_party/libvpx/source/libvpx/vpx/vp8dx.h",
@@ -2410,10 +2421,12 @@
   "//third_party/libvpx/source/libvpx/vp9/vp9_dx_iface.h",
   "//third_party/libvpx/source/libvpx/vp9/vp9_iface_common.h",
   "//third_party/libvpx/source/libvpx/vpx/internal/vpx_codec_internal.h",
+  "//third_party/libvpx/source/libvpx/vpx/src/svc_encodeframe.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_codec.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_decoder.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_encoder.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_image.c",
+  "//third_party/libvpx/source/libvpx/vpx/svc_context.h",
   "//third_party/libvpx/source/libvpx/vpx/vp8.h",
   "//third_party/libvpx/source/libvpx/vpx/vp8cx.h",
   "//third_party/libvpx/source/libvpx/vpx/vp8dx.h",
@@ -2787,10 +2800,12 @@
   "//third_party/libvpx/source/libvpx/vp9/vp9_dx_iface.h",
   "//third_party/libvpx/source/libvpx/vp9/vp9_iface_common.h",
   "//third_party/libvpx/source/libvpx/vpx/internal/vpx_codec_internal.h",
+  "//third_party/libvpx/source/libvpx/vpx/src/svc_encodeframe.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_codec.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_decoder.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_encoder.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_image.c",
+  "//third_party/libvpx/source/libvpx/vpx/svc_context.h",
   "//third_party/libvpx/source/libvpx/vpx/vp8.h",
   "//third_party/libvpx/source/libvpx/vpx/vp8cx.h",
   "//third_party/libvpx/source/libvpx/vpx/vp8dx.h",
@@ -3126,10 +3141,12 @@
   "//third_party/libvpx/source/libvpx/vp9/vp9_dx_iface.h",
   "//third_party/libvpx/source/libvpx/vp9/vp9_iface_common.h",
   "//third_party/libvpx/source/libvpx/vpx/internal/vpx_codec_internal.h",
+  "//third_party/libvpx/source/libvpx/vpx/src/svc_encodeframe.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_codec.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_decoder.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_encoder.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_image.c",
+  "//third_party/libvpx/source/libvpx/vpx/svc_context.h",
   "//third_party/libvpx/source/libvpx/vpx/vp8.h",
   "//third_party/libvpx/source/libvpx/vpx/vp8cx.h",
   "//third_party/libvpx/source/libvpx/vpx/vp8dx.h",
@@ -3464,10 +3481,12 @@
   "//third_party/libvpx/source/libvpx/vp9/vp9_dx_iface.h",
   "//third_party/libvpx/source/libvpx/vp9/vp9_iface_common.h",
   "//third_party/libvpx/source/libvpx/vpx/internal/vpx_codec_internal.h",
+  "//third_party/libvpx/source/libvpx/vpx/src/svc_encodeframe.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_codec.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_decoder.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_encoder.c",
   "//third_party/libvpx/source/libvpx/vpx/src/vpx_image.c",
+  "//third_party/libvpx/source/libvpx/vpx/svc_context.h",
   "//third_party/libvpx/source/libvpx/vpx/vp8.h",
   "//third_party/libvpx/source/libvpx/vpx/vp8cx.h",
   "//third_party/libvpx/source/libvpx/vpx/vp8dx.h",
diff --git a/third_party/libvpx/source/config/ios/arm-neon/vpx_config.asm b/third_party/libvpx/source/config/ios/arm-neon/vpx_config.asm
index 2f1107d..d459dae 100644
--- a/third_party/libvpx/source/config/ios/arm-neon/vpx_config.asm
+++ b/third_party/libvpx/source/config/ios/arm-neon/vpx_config.asm
@@ -84,7 +84,6 @@
 .set CONFIG_EXPERIMENTAL ,  0
 .set CONFIG_SIZE_LIMIT ,  1
 .set CONFIG_ALWAYS_ADJUST_BPM ,  0
-.set CONFIG_SPATIAL_SVC ,  0
 .set CONFIG_FP_MB_STATS ,  0
 .set CONFIG_EMULATE_HARDWARE ,  0
 .set DECODE_WIDTH_LIMIT ,  16384
diff --git a/third_party/libvpx/source/config/ios/arm-neon/vpx_config.h b/third_party/libvpx/source/config/ios/arm-neon/vpx_config.h
index 3dbebf99..b80461bd 100644
--- a/third_party/libvpx/source/config/ios/arm-neon/vpx_config.h
+++ b/third_party/libvpx/source/config/ios/arm-neon/vpx_config.h
@@ -90,7 +90,6 @@
 #define CONFIG_EXPERIMENTAL 0
 #define CONFIG_SIZE_LIMIT 1
 #define CONFIG_ALWAYS_ADJUST_BPM 0
-#define CONFIG_SPATIAL_SVC 0
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define DECODE_WIDTH_LIMIT 16384
diff --git a/third_party/libvpx/source/config/ios/arm64/vpx_config.asm b/third_party/libvpx/source/config/ios/arm64/vpx_config.asm
index 0a0b36e..63979ef 100644
--- a/third_party/libvpx/source/config/ios/arm64/vpx_config.asm
+++ b/third_party/libvpx/source/config/ios/arm64/vpx_config.asm
@@ -84,7 +84,6 @@
 .set CONFIG_EXPERIMENTAL ,  0
 .set CONFIG_SIZE_LIMIT ,  1
 .set CONFIG_ALWAYS_ADJUST_BPM ,  0
-.set CONFIG_SPATIAL_SVC ,  0
 .set CONFIG_FP_MB_STATS ,  0
 .set CONFIG_EMULATE_HARDWARE ,  0
 .set DECODE_WIDTH_LIMIT ,  16384
diff --git a/third_party/libvpx/source/config/ios/arm64/vpx_config.h b/third_party/libvpx/source/config/ios/arm64/vpx_config.h
index c65638d..1ab268c 100644
--- a/third_party/libvpx/source/config/ios/arm64/vpx_config.h
+++ b/third_party/libvpx/source/config/ios/arm64/vpx_config.h
@@ -90,7 +90,6 @@
 #define CONFIG_EXPERIMENTAL 0
 #define CONFIG_SIZE_LIMIT 1
 #define CONFIG_ALWAYS_ADJUST_BPM 0
-#define CONFIG_SPATIAL_SVC 0
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define DECODE_WIDTH_LIMIT 16384
diff --git a/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_config.asm b/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_config.asm
index 02638630..ccf2d701 100644
--- a/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_config.asm
+++ b/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_config.asm
@@ -81,7 +81,6 @@
 .equ CONFIG_EXPERIMENTAL ,  0
 .equ CONFIG_SIZE_LIMIT ,  1
 .equ CONFIG_ALWAYS_ADJUST_BPM ,  0
-.equ CONFIG_SPATIAL_SVC ,  0
 .equ CONFIG_FP_MB_STATS ,  0
 .equ CONFIG_EMULATE_HARDWARE ,  0
 .equ DECODE_WIDTH_LIMIT ,  16384
diff --git a/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_config.h b/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_config.h
index 40332e46..9cb0939 100644
--- a/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_config.h
+++ b/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_config.h
@@ -90,7 +90,6 @@
 #define CONFIG_EXPERIMENTAL 0
 #define CONFIG_SIZE_LIMIT 1
 #define CONFIG_ALWAYS_ADJUST_BPM 0
-#define CONFIG_SPATIAL_SVC 0
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define DECODE_WIDTH_LIMIT 16384
diff --git a/third_party/libvpx/source/config/linux/arm-neon/vpx_config.asm b/third_party/libvpx/source/config/linux/arm-neon/vpx_config.asm
index 7eb1d08..87cfb6a 100644
--- a/third_party/libvpx/source/config/linux/arm-neon/vpx_config.asm
+++ b/third_party/libvpx/source/config/linux/arm-neon/vpx_config.asm
@@ -81,7 +81,6 @@
 .equ CONFIG_EXPERIMENTAL ,  0
 .equ CONFIG_SIZE_LIMIT ,  1
 .equ CONFIG_ALWAYS_ADJUST_BPM ,  0
-.equ CONFIG_SPATIAL_SVC ,  0
 .equ CONFIG_FP_MB_STATS ,  0
 .equ CONFIG_EMULATE_HARDWARE ,  0
 .equ DECODE_WIDTH_LIMIT ,  16384
diff --git a/third_party/libvpx/source/config/linux/arm-neon/vpx_config.h b/third_party/libvpx/source/config/linux/arm-neon/vpx_config.h
index 3dbebf99..b80461bd 100644
--- a/third_party/libvpx/source/config/linux/arm-neon/vpx_config.h
+++ b/third_party/libvpx/source/config/linux/arm-neon/vpx_config.h
@@ -90,7 +90,6 @@
 #define CONFIG_EXPERIMENTAL 0
 #define CONFIG_SIZE_LIMIT 1
 #define CONFIG_ALWAYS_ADJUST_BPM 0
-#define CONFIG_SPATIAL_SVC 0
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define DECODE_WIDTH_LIMIT 16384
diff --git a/third_party/libvpx/source/config/linux/arm/vpx_config.asm b/third_party/libvpx/source/config/linux/arm/vpx_config.asm
index b06082f..6cc4a69 100644
--- a/third_party/libvpx/source/config/linux/arm/vpx_config.asm
+++ b/third_party/libvpx/source/config/linux/arm/vpx_config.asm
@@ -81,7 +81,6 @@
 .equ CONFIG_EXPERIMENTAL ,  0
 .equ CONFIG_SIZE_LIMIT ,  1
 .equ CONFIG_ALWAYS_ADJUST_BPM ,  0
-.equ CONFIG_SPATIAL_SVC ,  0
 .equ CONFIG_FP_MB_STATS ,  0
 .equ CONFIG_EMULATE_HARDWARE ,  0
 .equ DECODE_WIDTH_LIMIT ,  16384
diff --git a/third_party/libvpx/source/config/linux/arm/vpx_config.h b/third_party/libvpx/source/config/linux/arm/vpx_config.h
index 4afe67a..826ac8d1 100644
--- a/third_party/libvpx/source/config/linux/arm/vpx_config.h
+++ b/third_party/libvpx/source/config/linux/arm/vpx_config.h
@@ -90,7 +90,6 @@
 #define CONFIG_EXPERIMENTAL 0
 #define CONFIG_SIZE_LIMIT 1
 #define CONFIG_ALWAYS_ADJUST_BPM 0
-#define CONFIG_SPATIAL_SVC 0
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define DECODE_WIDTH_LIMIT 16384
diff --git a/third_party/libvpx/source/config/linux/arm64/vpx_config.asm b/third_party/libvpx/source/config/linux/arm64/vpx_config.asm
index f8ed0b6..c5284f8 100644
--- a/third_party/libvpx/source/config/linux/arm64/vpx_config.asm
+++ b/third_party/libvpx/source/config/linux/arm64/vpx_config.asm
@@ -81,7 +81,6 @@
 .equ CONFIG_EXPERIMENTAL ,  0
 .equ CONFIG_SIZE_LIMIT ,  1
 .equ CONFIG_ALWAYS_ADJUST_BPM ,  0
-.equ CONFIG_SPATIAL_SVC ,  0
 .equ CONFIG_FP_MB_STATS ,  0
 .equ CONFIG_EMULATE_HARDWARE ,  0
 .equ DECODE_WIDTH_LIMIT ,  16384
diff --git a/third_party/libvpx/source/config/linux/arm64/vpx_config.h b/third_party/libvpx/source/config/linux/arm64/vpx_config.h
index c65638d..1ab268c 100644
--- a/third_party/libvpx/source/config/linux/arm64/vpx_config.h
+++ b/third_party/libvpx/source/config/linux/arm64/vpx_config.h
@@ -90,7 +90,6 @@
 #define CONFIG_EXPERIMENTAL 0
 #define CONFIG_SIZE_LIMIT 1
 #define CONFIG_ALWAYS_ADJUST_BPM 0
-#define CONFIG_SPATIAL_SVC 0
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define DECODE_WIDTH_LIMIT 16384
diff --git a/third_party/libvpx/source/config/linux/generic/vpx_config.asm b/third_party/libvpx/source/config/linux/generic/vpx_config.asm
index 160e31d0..fc694fb 100644
--- a/third_party/libvpx/source/config/linux/generic/vpx_config.asm
+++ b/third_party/libvpx/source/config/linux/generic/vpx_config.asm
@@ -81,7 +81,6 @@
 .equ CONFIG_EXPERIMENTAL ,  0
 .equ CONFIG_SIZE_LIMIT ,  1
 .equ CONFIG_ALWAYS_ADJUST_BPM ,  0
-.equ CONFIG_SPATIAL_SVC ,  0
 .equ CONFIG_FP_MB_STATS ,  0
 .equ CONFIG_EMULATE_HARDWARE ,  0
 .equ DECODE_WIDTH_LIMIT ,  16384
diff --git a/third_party/libvpx/source/config/linux/generic/vpx_config.h b/third_party/libvpx/source/config/linux/generic/vpx_config.h
index 180ab1b..cc20ff9e 100644
--- a/third_party/libvpx/source/config/linux/generic/vpx_config.h
+++ b/third_party/libvpx/source/config/linux/generic/vpx_config.h
@@ -90,7 +90,6 @@
 #define CONFIG_EXPERIMENTAL 0
 #define CONFIG_SIZE_LIMIT 1
 #define CONFIG_ALWAYS_ADJUST_BPM 0
-#define CONFIG_SPATIAL_SVC 0
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define DECODE_WIDTH_LIMIT 16384
diff --git a/third_party/libvpx/source/config/linux/ia32/vpx_config.asm b/third_party/libvpx/source/config/linux/ia32/vpx_config.asm
index 4537261..b1c79dd 100644
--- a/third_party/libvpx/source/config/linux/ia32/vpx_config.asm
+++ b/third_party/libvpx/source/config/linux/ia32/vpx_config.asm
@@ -78,7 +78,6 @@
 %define CONFIG_EXPERIMENTAL 0
 %define CONFIG_SIZE_LIMIT 1
 %define CONFIG_ALWAYS_ADJUST_BPM 0
-%define CONFIG_SPATIAL_SVC 0
 %define CONFIG_FP_MB_STATS 0
 %define CONFIG_EMULATE_HARDWARE 0
 %define DECODE_WIDTH_LIMIT 16384
diff --git a/third_party/libvpx/source/config/linux/ia32/vpx_config.h b/third_party/libvpx/source/config/linux/ia32/vpx_config.h
index 12c4f24f..dbd8c1d3 100644
--- a/third_party/libvpx/source/config/linux/ia32/vpx_config.h
+++ b/third_party/libvpx/source/config/linux/ia32/vpx_config.h
@@ -90,7 +90,6 @@
 #define CONFIG_EXPERIMENTAL 0
 #define CONFIG_SIZE_LIMIT 1
 #define CONFIG_ALWAYS_ADJUST_BPM 0
-#define CONFIG_SPATIAL_SVC 0
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define DECODE_WIDTH_LIMIT 16384
diff --git a/third_party/libvpx/source/config/linux/mips64el/vpx_config.h b/third_party/libvpx/source/config/linux/mips64el/vpx_config.h
index a7a29383a..d876f25b 100644
--- a/third_party/libvpx/source/config/linux/mips64el/vpx_config.h
+++ b/third_party/libvpx/source/config/linux/mips64el/vpx_config.h
@@ -90,7 +90,6 @@
 #define CONFIG_EXPERIMENTAL 0
 #define CONFIG_SIZE_LIMIT 1
 #define CONFIG_ALWAYS_ADJUST_BPM 0
-#define CONFIG_SPATIAL_SVC 0
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define DECODE_WIDTH_LIMIT 16384
diff --git a/third_party/libvpx/source/config/linux/mipsel/vpx_config.h b/third_party/libvpx/source/config/linux/mipsel/vpx_config.h
index 533077f..967e544 100644
--- a/third_party/libvpx/source/config/linux/mipsel/vpx_config.h
+++ b/third_party/libvpx/source/config/linux/mipsel/vpx_config.h
@@ -90,7 +90,6 @@
 #define CONFIG_EXPERIMENTAL 0
 #define CONFIG_SIZE_LIMIT 1
 #define CONFIG_ALWAYS_ADJUST_BPM 0
-#define CONFIG_SPATIAL_SVC 0
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define DECODE_WIDTH_LIMIT 16384
diff --git a/third_party/libvpx/source/config/linux/x64/vpx_config.asm b/third_party/libvpx/source/config/linux/x64/vpx_config.asm
index 032dfdb2..84f986d3f 100644
--- a/third_party/libvpx/source/config/linux/x64/vpx_config.asm
+++ b/third_party/libvpx/source/config/linux/x64/vpx_config.asm
@@ -78,7 +78,6 @@
 %define CONFIG_EXPERIMENTAL 0
 %define CONFIG_SIZE_LIMIT 1
 %define CONFIG_ALWAYS_ADJUST_BPM 0
-%define CONFIG_SPATIAL_SVC 0
 %define CONFIG_FP_MB_STATS 0
 %define CONFIG_EMULATE_HARDWARE 0
 %define DECODE_WIDTH_LIMIT 16384
diff --git a/third_party/libvpx/source/config/linux/x64/vpx_config.h b/third_party/libvpx/source/config/linux/x64/vpx_config.h
index 84f1c01..aedc476 100644
--- a/third_party/libvpx/source/config/linux/x64/vpx_config.h
+++ b/third_party/libvpx/source/config/linux/x64/vpx_config.h
@@ -90,7 +90,6 @@
 #define CONFIG_EXPERIMENTAL 0
 #define CONFIG_SIZE_LIMIT 1
 #define CONFIG_ALWAYS_ADJUST_BPM 0
-#define CONFIG_SPATIAL_SVC 0
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define DECODE_WIDTH_LIMIT 16384
diff --git a/third_party/libvpx/source/config/mac/ia32/vpx_config.asm b/third_party/libvpx/source/config/mac/ia32/vpx_config.asm
index 4537261..b1c79dd 100644
--- a/third_party/libvpx/source/config/mac/ia32/vpx_config.asm
+++ b/third_party/libvpx/source/config/mac/ia32/vpx_config.asm
@@ -78,7 +78,6 @@
 %define CONFIG_EXPERIMENTAL 0
 %define CONFIG_SIZE_LIMIT 1
 %define CONFIG_ALWAYS_ADJUST_BPM 0
-%define CONFIG_SPATIAL_SVC 0
 %define CONFIG_FP_MB_STATS 0
 %define CONFIG_EMULATE_HARDWARE 0
 %define DECODE_WIDTH_LIMIT 16384
diff --git a/third_party/libvpx/source/config/mac/ia32/vpx_config.h b/third_party/libvpx/source/config/mac/ia32/vpx_config.h
index 12c4f24f..dbd8c1d3 100644
--- a/third_party/libvpx/source/config/mac/ia32/vpx_config.h
+++ b/third_party/libvpx/source/config/mac/ia32/vpx_config.h
@@ -90,7 +90,6 @@
 #define CONFIG_EXPERIMENTAL 0
 #define CONFIG_SIZE_LIMIT 1
 #define CONFIG_ALWAYS_ADJUST_BPM 0
-#define CONFIG_SPATIAL_SVC 0
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define DECODE_WIDTH_LIMIT 16384
diff --git a/third_party/libvpx/source/config/mac/x64/vpx_config.asm b/third_party/libvpx/source/config/mac/x64/vpx_config.asm
index 032dfdb2..84f986d3f 100644
--- a/third_party/libvpx/source/config/mac/x64/vpx_config.asm
+++ b/third_party/libvpx/source/config/mac/x64/vpx_config.asm
@@ -78,7 +78,6 @@
 %define CONFIG_EXPERIMENTAL 0
 %define CONFIG_SIZE_LIMIT 1
 %define CONFIG_ALWAYS_ADJUST_BPM 0
-%define CONFIG_SPATIAL_SVC 0
 %define CONFIG_FP_MB_STATS 0
 %define CONFIG_EMULATE_HARDWARE 0
 %define DECODE_WIDTH_LIMIT 16384
diff --git a/third_party/libvpx/source/config/mac/x64/vpx_config.h b/third_party/libvpx/source/config/mac/x64/vpx_config.h
index 84f1c01..aedc476 100644
--- a/third_party/libvpx/source/config/mac/x64/vpx_config.h
+++ b/third_party/libvpx/source/config/mac/x64/vpx_config.h
@@ -90,7 +90,6 @@
 #define CONFIG_EXPERIMENTAL 0
 #define CONFIG_SIZE_LIMIT 1
 #define CONFIG_ALWAYS_ADJUST_BPM 0
-#define CONFIG_SPATIAL_SVC 0
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define DECODE_WIDTH_LIMIT 16384
diff --git a/third_party/libvpx/source/config/nacl/vpx_config.h b/third_party/libvpx/source/config/nacl/vpx_config.h
index 180ab1b..cc20ff9e 100644
--- a/third_party/libvpx/source/config/nacl/vpx_config.h
+++ b/third_party/libvpx/source/config/nacl/vpx_config.h
@@ -90,7 +90,6 @@
 #define CONFIG_EXPERIMENTAL 0
 #define CONFIG_SIZE_LIMIT 1
 #define CONFIG_ALWAYS_ADJUST_BPM 0
-#define CONFIG_SPATIAL_SVC 0
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define DECODE_WIDTH_LIMIT 16384
diff --git a/third_party/libvpx/source/config/vpx_version.h b/third_party/libvpx/source/config/vpx_version.h
index b793be0..c9371c2c 100644
--- a/third_party/libvpx/source/config/vpx_version.h
+++ b/third_party/libvpx/source/config/vpx_version.h
@@ -2,7 +2,7 @@
 #define VERSION_MAJOR  1
 #define VERSION_MINOR  7
 #define VERSION_PATCH  0
-#define VERSION_EXTRA  "146-g7b5a57449"
+#define VERSION_EXTRA  "191-g1f82e0612"
 #define VERSION_PACKED ((VERSION_MAJOR<<16)|(VERSION_MINOR<<8)|(VERSION_PATCH))
-#define VERSION_STRING_NOSP "v1.7.0-146-g7b5a57449"
-#define VERSION_STRING      " v1.7.0-146-g7b5a57449"
+#define VERSION_STRING_NOSP "v1.7.0-191-g1f82e0612"
+#define VERSION_STRING      " v1.7.0-191-g1f82e0612"
diff --git a/third_party/libvpx/source/config/win/ia32/vpx_config.asm b/third_party/libvpx/source/config/win/ia32/vpx_config.asm
index b0eb9f0..0592279 100644
--- a/third_party/libvpx/source/config/win/ia32/vpx_config.asm
+++ b/third_party/libvpx/source/config/win/ia32/vpx_config.asm
@@ -78,7 +78,6 @@
 %define CONFIG_EXPERIMENTAL 0
 %define CONFIG_SIZE_LIMIT 1
 %define CONFIG_ALWAYS_ADJUST_BPM 0
-%define CONFIG_SPATIAL_SVC 0
 %define CONFIG_FP_MB_STATS 0
 %define CONFIG_EMULATE_HARDWARE 0
 %define DECODE_WIDTH_LIMIT 16384
diff --git a/third_party/libvpx/source/config/win/ia32/vpx_config.h b/third_party/libvpx/source/config/win/ia32/vpx_config.h
index a2dfec7..0725ed3 100644
--- a/third_party/libvpx/source/config/win/ia32/vpx_config.h
+++ b/third_party/libvpx/source/config/win/ia32/vpx_config.h
@@ -90,7 +90,6 @@
 #define CONFIG_EXPERIMENTAL 0
 #define CONFIG_SIZE_LIMIT 1
 #define CONFIG_ALWAYS_ADJUST_BPM 0
-#define CONFIG_SPATIAL_SVC 0
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define DECODE_WIDTH_LIMIT 16384
diff --git a/third_party/libvpx/source/config/win/x64/vpx_config.asm b/third_party/libvpx/source/config/win/x64/vpx_config.asm
index 664ecc0..c17b1e3 100644
--- a/third_party/libvpx/source/config/win/x64/vpx_config.asm
+++ b/third_party/libvpx/source/config/win/x64/vpx_config.asm
@@ -78,7 +78,6 @@
 %define CONFIG_EXPERIMENTAL 0
 %define CONFIG_SIZE_LIMIT 1
 %define CONFIG_ALWAYS_ADJUST_BPM 0
-%define CONFIG_SPATIAL_SVC 0
 %define CONFIG_FP_MB_STATS 0
 %define CONFIG_EMULATE_HARDWARE 0
 %define DECODE_WIDTH_LIMIT 16384
diff --git a/third_party/libvpx/source/config/win/x64/vpx_config.h b/third_party/libvpx/source/config/win/x64/vpx_config.h
index c3a567e..f0fbf89 100644
--- a/third_party/libvpx/source/config/win/x64/vpx_config.h
+++ b/third_party/libvpx/source/config/win/x64/vpx_config.h
@@ -90,7 +90,6 @@
 #define CONFIG_EXPERIMENTAL 0
 #define CONFIG_SIZE_LIMIT 1
 #define CONFIG_ALWAYS_ADJUST_BPM 0
-#define CONFIG_SPATIAL_SVC 0
 #define CONFIG_FP_MB_STATS 0
 #define CONFIG_EMULATE_HARDWARE 0
 #define DECODE_WIDTH_LIMIT 16384
diff --git a/third_party/libxml/README.chromium b/third_party/libxml/README.chromium
index 8ba967d..8a8e6ce 100644
--- a/third_party/libxml/README.chromium
+++ b/third_party/libxml/README.chromium
@@ -1,6 +1,6 @@
 Name: libxml
 URL: http://xmlsoft.org
-Version: 2677fbf4a4a6dec69ff52265addab713fe48ad1f
+Version: 7a1bd7f6497ac33a9023d556f6f47a48f01deac0
 License: MIT
 License File: src/Copyright
 Security Critical: yes
diff --git a/third_party/libxml/chromium/chromium-issue-628581.patch b/third_party/libxml/chromium/chromium-issue-628581.patch
index 42b7c63..2fcf4e5 100644
--- a/third_party/libxml/chromium/chromium-issue-628581.patch
+++ b/third_party/libxml/chromium/chromium-issue-628581.patch
@@ -1,8 +1,8 @@
-diff --git a/third_party/libxml/src/entities.c b/third_party/libxml/src/entities.c
-index 64808ff64d6a..2851e2d43113 100644
+diff --git a/entities.c b/entities.c
+index 43549bc5..e4a09d62 100644
 --- a/entities.c
 +++ b/entities.c
-@@ -159,6 +159,7 @@ xmlCreateEntity(xmlDictPtr dict, const xmlChar *name, int type,
+@@ -164,6 +164,7 @@ xmlCreateEntity(xmlDictPtr dict, const xmlChar *name, int type,
      memset(ret, 0, sizeof(xmlEntity));
      ret->type = XML_ENTITY_DECL;
      ret->checked = 0;
@@ -10,7 +10,7 @@
  
      /*
       * fill the structure.
-@@ -931,6 +932,7 @@ xmlCopyEntity(xmlEntityPtr ent) {
+@@ -936,6 +937,7 @@ xmlCopyEntity(void *payload, const xmlChar *name ATTRIBUTE_UNUSED) {
  	cur->orig = xmlStrdup(ent->orig);
      if (ent->URI != NULL)
  	cur->URI = xmlStrdup(ent->URI);
@@ -18,8 +18,8 @@
      return(cur);
  }
  
-diff --git a/third_party/libxml/src/include/libxml/entities.h b/third_party/libxml/src/include/libxml/entities.h
-index 47b4573eba65..012efab294cb 100644
+diff --git a/include/libxml/entities.h b/include/libxml/entities.h
+index 47b4573e..012efab2 100644
 --- a/include/libxml/entities.h
 +++ b/include/libxml/entities.h
 @@ -35,8 +35,13 @@ typedef enum {
@@ -53,8 +53,8 @@
  };
  
  /*
-diff --git a/third_party/libxml/src/parser.c b/third_party/libxml/src/parser.c
-index 53a6b7f0c961..e3136123dca6 100644
+diff --git a/parser.c b/parser.c
+index ca9fde2c..4264445a 100644
 --- a/parser.c
 +++ b/parser.c
 @@ -137,18 +137,24 @@ xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size,
@@ -79,10 +79,10 @@
  				  XML_SUBSTITUTE_REF, 0, 0, 0);
          --ctxt->depth;
 +        ent->guard = XML_ENTITY_NOT_BEING_CHECKED;
- 	if (ctxt->errNo == XML_ERR_ENTITY_LOOP) {
+ 	if ((rep == NULL) || (ctxt->errNo == XML_ERR_ENTITY_LOOP)) {
  	    ent->content[0] = 0;
  	}
-@@ -7329,23 +7335,28 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
+@@ -7105,23 +7111,28 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
  	 * if its replacement text matches the production labeled
  	 * content.
  	 */
@@ -128,7 +128,7 @@
  
  	/*
  	 * Store the number of entities needing parsing for this entity
-@@ -7448,23 +7459,29 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
+@@ -7229,23 +7240,29 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
  	    else
  		user_data = ctxt->userData;
  
@@ -175,6 +175,3 @@
  	    if (ret == XML_ERR_ENTITY_LOOP) {
  		xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
  		return;
--- 
-2.12.2.715.g7642488e1d-goog
-
diff --git a/third_party/libxml/chromium/roll.py b/third_party/libxml/chromium/roll.py
index 3ed0bc62..67ef7a1c 100755
--- a/third_party/libxml/chromium/roll.py
+++ b/third_party/libxml/chromium/roll.py
@@ -259,7 +259,8 @@
         files_to_remove: The files to remove.
     """
     files_to_remove = [f for f in files_to_remove if os.path.exists(f)]
-    git('rm', '-rf', *files_to_remove)
+    if files_to_remove:
+        git('rm', '-rf', *files_to_remove)
 
 
 def sed_in_place(input_filename, program):
diff --git a/third_party/libxml/linux/config.h b/third_party/libxml/linux/config.h
index fcc66cde..7e1b6d5 100644
--- a/third_party/libxml/linux/config.h
+++ b/third_party/libxml/linux/config.h
@@ -267,7 +267,7 @@
 #define VA_LIST_IS_ARRAY 1
 
 /* Version number of package */
-#define VERSION "2.9.7"
+#define VERSION "2.9.8"
 
 /* Determine what socket length (socklen_t) data type is */
 #define XML_SOCKLEN_T socklen_t
diff --git a/third_party/libxml/linux/include/libxml/xmlversion.h b/third_party/libxml/linux/include/libxml/xmlversion.h
index 2a09d53..68bd54d 100644
--- a/third_party/libxml/linux/include/libxml/xmlversion.h
+++ b/third_party/libxml/linux/include/libxml/xmlversion.h
@@ -29,21 +29,21 @@
  *
  * the version string like "1.2.3"
  */
-#define LIBXML_DOTTED_VERSION "2.9.7"
+#define LIBXML_DOTTED_VERSION "2.9.8"
 
 /**
  * LIBXML_VERSION:
  *
  * the version number: 1.2.3 value is 10203
  */
-#define LIBXML_VERSION 20907
+#define LIBXML_VERSION 20908
 
 /**
  * LIBXML_VERSION_STRING:
  *
  * the version number string, 1.2.3 value is "10203"
  */
-#define LIBXML_VERSION_STRING "20907"
+#define LIBXML_VERSION_STRING "20908"
 
 /**
  * LIBXML_VERSION_EXTRA:
@@ -58,7 +58,7 @@
  * Macro to check that the libxml version in use is compatible with
  * the version the software has been compiled against
  */
-#define LIBXML_TEST_VERSION xmlCheckVersion(20907);
+#define LIBXML_TEST_VERSION xmlCheckVersion(20908);
 
 #ifndef VMS
 #if 0
diff --git a/third_party/libxml/linux/xml2-config b/third_party/libxml/linux/xml2-config
index 6ed8eb1..9e140ed 100755
--- a/third_party/libxml/linux/xml2-config
+++ b/third_party/libxml/linux/xml2-config
@@ -58,7 +58,7 @@
       ;;
 
     --version)
-	echo 2.9.7
+	echo 2.9.8
 	exit 0
 	;;
 
@@ -86,12 +86,12 @@
 	then
 	    if [ "-L${libdir}" = "-L/usr/lib" -o "-L${libdir}" = "-L/usr/lib64" ]
 	    then
-		echo -lxml2      -L/usr/lib/x86_64-linux-gnu -licui18n -licuuc -licudata   -lm  
+		echo -lxml2     -licui18n -licuuc -licudata -lm  
 	    else
-		echo -L${libdir} -lxml2      -L/usr/lib/x86_64-linux-gnu -licui18n -licuuc -licudata   -lm  
+		echo -L${libdir} -lxml2     -licui18n -licuuc -licudata -lm  
 	    fi
 	else
-	    echo -L${libdir} -lxml2      -L/usr/lib/x86_64-linux-gnu -licui18n -licuuc -licudata   -lm   
+	    echo -L${libdir} -lxml2     -licui18n -licuuc -licudata -lm   
 	fi
        	;;
 
diff --git a/third_party/libxml/mac/config.h b/third_party/libxml/mac/config.h
index e8073fb..4065ff5 100644
--- a/third_party/libxml/mac/config.h
+++ b/third_party/libxml/mac/config.h
@@ -267,7 +267,7 @@
 #define VA_LIST_IS_ARRAY 1
 
 /* Version number of package */
-#define VERSION "2.9.7"
+#define VERSION "2.9.8"
 
 /* Determine what socket length (socklen_t) data type is */
 #define XML_SOCKLEN_T socklen_t
diff --git a/third_party/libxml/mac/include/libxml/xmlversion.h b/third_party/libxml/mac/include/libxml/xmlversion.h
index 2a09d53..68bd54d 100644
--- a/third_party/libxml/mac/include/libxml/xmlversion.h
+++ b/third_party/libxml/mac/include/libxml/xmlversion.h
@@ -29,21 +29,21 @@
  *
  * the version string like "1.2.3"
  */
-#define LIBXML_DOTTED_VERSION "2.9.7"
+#define LIBXML_DOTTED_VERSION "2.9.8"
 
 /**
  * LIBXML_VERSION:
  *
  * the version number: 1.2.3 value is 10203
  */
-#define LIBXML_VERSION 20907
+#define LIBXML_VERSION 20908
 
 /**
  * LIBXML_VERSION_STRING:
  *
  * the version number string, 1.2.3 value is "10203"
  */
-#define LIBXML_VERSION_STRING "20907"
+#define LIBXML_VERSION_STRING "20908"
 
 /**
  * LIBXML_VERSION_EXTRA:
@@ -58,7 +58,7 @@
  * Macro to check that the libxml version in use is compatible with
  * the version the software has been compiled against
  */
-#define LIBXML_TEST_VERSION xmlCheckVersion(20907);
+#define LIBXML_TEST_VERSION xmlCheckVersion(20908);
 
 #ifndef VMS
 #if 0
diff --git a/third_party/libxml/src/aclocal.m4 b/third_party/libxml/src/aclocal.m4
index 5b60f23..6db5ac1 100644
--- a/third_party/libxml/src/aclocal.m4
+++ b/third_party/libxml/src/aclocal.m4
@@ -1,6 +1,6 @@
-# generated automatically by aclocal 1.15.1 -*- Autoconf -*-
+# generated automatically by aclocal 1.16.1 -*- Autoconf -*-
 
-# Copyright (C) 1996-2017 Free Software Foundation, Inc.
+# Copyright (C) 1996-2018 Free Software Foundation, Inc.
 
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -296,7 +296,7 @@
 AS_VAR_IF([$1], [""], [$5], [$4])dnl
 ])dnl PKG_CHECK_VAR
 
-# Copyright (C) 2002-2017 Free Software Foundation, Inc.
+# Copyright (C) 2002-2018 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -308,10 +308,10 @@
 # generated from the m4 files accompanying Automake X.Y.
 # (This private macro should not be called outside this file.)
 AC_DEFUN([AM_AUTOMAKE_VERSION],
-[am__api_version='1.15'
+[am__api_version='1.16'
 dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
 dnl require some minimum version.  Point them to the right macro.
-m4_if([$1], [1.15.1], [],
+m4_if([$1], [1.16.1], [],
       [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
 ])
 
@@ -327,14 +327,14 @@
 # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
 # This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
 AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
-[AM_AUTOMAKE_VERSION([1.15.1])dnl
+[AM_AUTOMAKE_VERSION([1.16.1])dnl
 m4_ifndef([AC_AUTOCONF_VERSION],
   [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
 _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
 
 # AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-
 
-# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+# Copyright (C) 2001-2018 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -386,7 +386,7 @@
 
 # AM_CONDITIONAL                                            -*- Autoconf -*-
 
-# Copyright (C) 1997-2017 Free Software Foundation, Inc.
+# Copyright (C) 1997-2018 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -417,7 +417,7 @@
 Usually this means the macro was only invoked conditionally.]])
 fi])])
 
-# Copyright (C) 1999-2017 Free Software Foundation, Inc.
+# Copyright (C) 1999-2018 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -608,13 +608,12 @@
 
 # Generate code to set up dependency tracking.              -*- Autoconf -*-
 
-# Copyright (C) 1999-2017 Free Software Foundation, Inc.
+# Copyright (C) 1999-2018 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-
 # _AM_OUTPUT_DEPENDENCY_COMMANDS
 # ------------------------------
 AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
@@ -622,49 +621,41 @@
   # Older Autoconf quotes --file arguments for eval, but not when files
   # are listed without --file.  Let's play safe and only enable the eval
   # if we detect the quoting.
-  case $CONFIG_FILES in
-  *\'*) eval set x "$CONFIG_FILES" ;;
-  *)   set x $CONFIG_FILES ;;
-  esac
+  # TODO: see whether this extra hack can be removed once we start
+  # requiring Autoconf 2.70 or later.
+  AS_CASE([$CONFIG_FILES],
+          [*\'*], [eval set x "$CONFIG_FILES"],
+          [*], [set x $CONFIG_FILES])
   shift
-  for mf
+  # Used to flag and report bootstrapping failures.
+  am_rc=0
+  for am_mf
   do
     # Strip MF so we end up with the name of the file.
-    mf=`echo "$mf" | sed -e 's/:.*$//'`
-    # Check whether this is an Automake generated Makefile or not.
-    # We used to match only the files named 'Makefile.in', but
-    # some people rename them; so instead we look at the file content.
-    # Grep'ing the first line is not enough: some people post-process
-    # each Makefile.in and add a new line on top of each file to say so.
-    # Grep'ing the whole file is not good either: AIX grep has a line
+    am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'`
+    # Check whether this is an Automake generated Makefile which includes
+    # dependency-tracking related rules and includes.
+    # Grep'ing the whole file directly is not great: AIX grep has a line
     # limit of 2048, but all sed's we know have understand at least 4000.
-    if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
-      dirpart=`AS_DIRNAME("$mf")`
-    else
-      continue
-    fi
-    # Extract the definition of DEPDIR, am__include, and am__quote
-    # from the Makefile without running 'make'.
-    DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
-    test -z "$DEPDIR" && continue
-    am__include=`sed -n 's/^am__include = //p' < "$mf"`
-    test -z "$am__include" && continue
-    am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
-    # Find all dependency output files, they are included files with
-    # $(DEPDIR) in their names.  We invoke sed twice because it is the
-    # simplest approach to changing $(DEPDIR) to its actual value in the
-    # expansion.
-    for file in `sed -n "
-      s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
-	 sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
-      # Make sure the directory exists.
-      test -f "$dirpart/$file" && continue
-      fdir=`AS_DIRNAME(["$file"])`
-      AS_MKDIR_P([$dirpart/$fdir])
-      # echo "creating $dirpart/$file"
-      echo '# dummy' > "$dirpart/$file"
-    done
+    sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \
+      || continue
+    am_dirpart=`AS_DIRNAME(["$am_mf"])`
+    am_filepart=`AS_BASENAME(["$am_mf"])`
+    AM_RUN_LOG([cd "$am_dirpart" \
+      && sed -e '/# am--include-marker/d' "$am_filepart" \
+        | $MAKE -f - am--depfiles]) || am_rc=$?
   done
+  if test $am_rc -ne 0; then
+    AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments
+    for automatic dependency tracking.  Try re-running configure with the
+    '--disable-dependency-tracking' option to at least be able to build
+    the package (albeit without support for automatic dependency tracking).])
+  fi
+  AS_UNSET([am_dirpart])
+  AS_UNSET([am_filepart])
+  AS_UNSET([am_mf])
+  AS_UNSET([am_rc])
+  rm -f conftest-deps.mk
 }
 ])# _AM_OUTPUT_DEPENDENCY_COMMANDS
 
@@ -673,18 +664,17 @@
 # -----------------------------
 # This macro should only be invoked once -- use via AC_REQUIRE.
 #
-# This code is only required when automatic dependency tracking
-# is enabled.  FIXME.  This creates each '.P' file that we will
-# need in order to bootstrap the dependency handling code.
+# This code is only required when automatic dependency tracking is enabled.
+# This creates each '.Po' and '.Plo' makefile fragment that we'll need in
+# order to bootstrap the dependency handling code.
 AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
 [AC_CONFIG_COMMANDS([depfiles],
      [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
-     [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
-])
+     [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])])
 
 # Do all the work for Automake.                             -*- Autoconf -*-
 
-# Copyright (C) 1996-2017 Free Software Foundation, Inc.
+# Copyright (C) 1996-2018 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -771,8 +761,8 @@
 AC_REQUIRE([AC_PROG_MKDIR_P])dnl
 # For better backward compatibility.  To be removed once Automake 1.9.x
 # dies out for good.  For more background, see:
-# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
-# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
+# <https://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
+# <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
 AC_SUBST([mkdir_p], ['$(MKDIR_P)'])
 # We need awk for the "check" target (and possibly the TAP driver).  The
 # system "awk" is bad on some platforms.
@@ -839,7 +829,7 @@
 Aborting the configuration process, to ensure you take notice of the issue.
 
 You can download and install GNU coreutils to get an 'rm' implementation
-that behaves properly: <http://www.gnu.org/software/coreutils/>.
+that behaves properly: <https://www.gnu.org/software/coreutils/>.
 
 If you want to complete the configuration process using your problematic
 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
@@ -881,7 +871,7 @@
 done
 echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
 
-# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+# Copyright (C) 2001-2018 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -902,7 +892,7 @@
 fi
 AC_SUBST([install_sh])])
 
-# Copyright (C) 2003-2017 Free Software Foundation, Inc.
+# Copyright (C) 2003-2018 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -924,7 +914,7 @@
 # Add --enable-maintainer-mode option to configure.         -*- Autoconf -*-
 # From Jim Meyering
 
-# Copyright (C) 1996-2017 Free Software Foundation, Inc.
+# Copyright (C) 1996-2018 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -959,7 +949,7 @@
 
 # Check to see how 'make' treats includes.	            -*- Autoconf -*-
 
-# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+# Copyright (C) 2001-2018 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -967,49 +957,42 @@
 
 # AM_MAKE_INCLUDE()
 # -----------------
-# Check to see how make treats includes.
+# Check whether make has an 'include' directive that can support all
+# the idioms we need for our automatic dependency tracking code.
 AC_DEFUN([AM_MAKE_INCLUDE],
-[am_make=${MAKE-make}
-cat > confinc << 'END'
+[AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive])
+cat > confinc.mk << 'END'
 am__doit:
-	@echo this is the am__doit target
+	@echo this is the am__doit target >confinc.out
 .PHONY: am__doit
 END
-# If we don't find an include directive, just comment out the code.
-AC_MSG_CHECKING([for style of include used by $am_make])
 am__include="#"
 am__quote=
-_am_result=none
-# First try GNU make style include.
-echo "include confinc" > confmf
-# Ignore all kinds of additional output from 'make'.
-case `$am_make -s -f confmf 2> /dev/null` in #(
-*the\ am__doit\ target*)
-  am__include=include
-  am__quote=
-  _am_result=GNU
-  ;;
-esac
-# Now try BSD make style include.
-if test "$am__include" = "#"; then
-   echo '.include "confinc"' > confmf
-   case `$am_make -s -f confmf 2> /dev/null` in #(
-   *the\ am__doit\ target*)
-     am__include=.include
-     am__quote="\""
-     _am_result=BSD
-     ;;
-   esac
-fi
-AC_SUBST([am__include])
-AC_SUBST([am__quote])
-AC_MSG_RESULT([$_am_result])
-rm -f confinc confmf
-])
+# BSD make does it like this.
+echo '.include "confinc.mk" # ignored' > confmf.BSD
+# Other make implementations (GNU, Solaris 10, AIX) do it like this.
+echo 'include confinc.mk # ignored' > confmf.GNU
+_am_result=no
+for s in GNU BSD; do
+  AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out])
+  AS_CASE([$?:`cat confinc.out 2>/dev/null`],
+      ['0:this is the am__doit target'],
+      [AS_CASE([$s],
+          [BSD], [am__include='.include' am__quote='"'],
+          [am__include='include' am__quote=''])])
+  if test "$am__include" != "#"; then
+    _am_result="yes ($s style)"
+    break
+  fi
+done
+rm -f confinc.* confmf.*
+AC_MSG_RESULT([${_am_result}])
+AC_SUBST([am__include])])
+AC_SUBST([am__quote])])
 
 # Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
 
-# Copyright (C) 1997-2017 Free Software Foundation, Inc.
+# Copyright (C) 1997-2018 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -1048,7 +1031,7 @@
 
 # Helper functions for option handling.                     -*- Autoconf -*-
 
-# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+# Copyright (C) 2001-2018 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -1077,7 +1060,7 @@
 AC_DEFUN([_AM_IF_OPTION],
 [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
 
-# Copyright (C) 1999-2017 Free Software Foundation, Inc.
+# Copyright (C) 1999-2018 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -1124,7 +1107,7 @@
 # For backward compatibility.
 AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
 
-# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+# Copyright (C) 2001-2018 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -1143,7 +1126,7 @@
 
 # Check to make sure that the build environment is sane.    -*- Autoconf -*-
 
-# Copyright (C) 1996-2017 Free Software Foundation, Inc.
+# Copyright (C) 1996-2018 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -1224,7 +1207,7 @@
 rm -f conftest.file
 ])
 
-# Copyright (C) 2009-2017 Free Software Foundation, Inc.
+# Copyright (C) 2009-2018 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -1284,7 +1267,7 @@
 _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
 ])
 
-# Copyright (C) 2001-2017 Free Software Foundation, Inc.
+# Copyright (C) 2001-2018 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -1312,7 +1295,7 @@
 INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
 AC_SUBST([INSTALL_STRIP_PROGRAM])])
 
-# Copyright (C) 2006-2017 Free Software Foundation, Inc.
+# Copyright (C) 2006-2018 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -1331,7 +1314,7 @@
 
 # Check how to create a tarball.                            -*- Autoconf -*-
 
-# Copyright (C) 2004-2017 Free Software Foundation, Inc.
+# Copyright (C) 2004-2018 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
diff --git a/third_party/libxml/src/configure.ac b/third_party/libxml/src/configure.ac
index 988e32e5..370e2de 100644
--- a/third_party/libxml/src/configure.ac
+++ b/third_party/libxml/src/configure.ac
@@ -9,7 +9,7 @@
 
 LIBXML_MAJOR_VERSION=2
 LIBXML_MINOR_VERSION=9
-LIBXML_MICRO_VERSION=7
+LIBXML_MICRO_VERSION=8
 LIBXML_MICRO_VERSION_SUFFIX=
 LIBXML_VERSION=$LIBXML_MAJOR_VERSION.$LIBXML_MINOR_VERSION.$LIBXML_MICRO_VERSION$LIBXML_MICRO_VERSION_SUFFIX
 LIBXML_VERSION_INFO=`expr $LIBXML_MAJOR_VERSION + $LIBXML_MINOR_VERSION`:$LIBXML_MICRO_VERSION:$LIBXML_MINOR_VERSION
@@ -769,9 +769,9 @@
     fi
 
     # warnings we'd like to see
-    EXTRA_CFLAGS="${EXTRA_CFLAGS} -pedantic -W -Wformat -Wno-format-extra-args -Wunused -Wimplicit -Wreturn-type -Wswitch -Wcomment -Wtrigraphs -Wchar-subscripts -Wuninitialized -Wparentheses -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline -Wredundant-decls"
+    EXTRA_CFLAGS="${EXTRA_CFLAGS} -pedantic -Wall -Wextra -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline -Wredundant-decls"
     # warnings we'd like to supress
-    EXTRA_CFLAGS="${EXTRA_CFLAGS} -Wno-long-long"
+    EXTRA_CFLAGS="${EXTRA_CFLAGS} -Wno-long-long -Wno-format-extra-args -Wno-array-bounds"
     case "${host}" in
           alpha*-*-linux* )
 	       EXTRA_CFLAGS="${EXTRA_CFLAGS} -mieee"
diff --git a/third_party/libxml/src/libxml2.spec b/third_party/libxml/src/libxml2.spec
index e0d24ff..9ed16ce9a 100644
--- a/third_party/libxml/src/libxml2.spec
+++ b/third_party/libxml/src/libxml2.spec
@@ -2,7 +2,7 @@
 
 Summary: Library providing XML and HTML support
 Name: libxml2
-Version: 2.9.7
+Version: 2.9.8
 Release: 1%{?dist}%{?extra_release}
 License: MIT
 Group: Development/Libraries
@@ -203,6 +203,6 @@
 %endif # with_python3
 
 %changelog
-* Wed Dec 13 2017 Daniel Veillard <veillard@redhat.com>
-- upstream release 2.9.7 see http://xmlsoft.org/news.html
+* Wed Mar 21 2018 Daniel Veillard <veillard@redhat.com>
+- upstream release 2.9.8 see http://xmlsoft.org/news.html
 
diff --git a/third_party/libxml/src/libxml2.syms b/third_party/libxml/src/libxml2.syms
index 370dcf1..9889cb2 100644
--- a/third_party/libxml/src/libxml2.syms
+++ b/third_party/libxml/src/libxml2.syms
@@ -2279,3 +2279,10 @@
   xmlXPathSetContextNode;
 } LIBXML2_2.9.0;
 
+LIBXML2_2.9.8 {
+    global:
+
+# hash
+  xmlHashDefaultDeallocator;
+} LIBXML2_2.9.1;
+
diff --git a/third_party/libxml/src/parser.c b/third_party/libxml/src/parser.c
index 6a34b27..4264445a 100644
--- a/third_party/libxml/src/parser.c
+++ b/third_party/libxml/src/parser.c
@@ -155,7 +155,7 @@
 				  XML_SUBSTITUTE_REF, 0, 0, 0);
         --ctxt->depth;
         ent->guard = XML_ENTITY_NOT_BEING_CHECKED;
-	if (ctxt->errNo == XML_ERR_ENTITY_LOOP) {
+	if ((rep == NULL) || (ctxt->errNo == XML_ERR_ENTITY_LOOP)) {
 	    ent->content[0] = 0;
 	}
 
@@ -3376,9 +3376,9 @@
 	     */
 	    ctxt->input->cur -= l;
 	    GROW;
-	    ctxt->input->cur += l;
             if (ctxt->instate == XML_PARSER_EOF)
                 return(NULL);
+	    ctxt->input->cur += l;
 	    c = CUR_CHAR(l);
 	}
     }
@@ -7200,6 +7200,8 @@
 		   (ret != XML_WAR_UNDECLARED_ENTITY)) {
 	    xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
 		     "Entity '%s' failed to parse\n", ent->name);
+            if (ent->content != NULL)
+                ent->content[0] = 0;
 	    xmlParserEntityCheck(ctxt, 0, ent, 0);
 	} else if (list != NULL) {
 	    xmlFreeNodeList(list);
@@ -12233,6 +12235,7 @@
 		    /* TODO 2.6.0 */
 		    xmlGenericError(xmlGenericErrorContext,
 				    "xmlParseChunk: encoder error\n");
+                    xmlHaltParser(ctxt);
 		    return(XML_ERR_INVALID_ENCODING);
 		}
 		xmlBufSetInputBaseCur(in->buffer, ctxt->input, base, current);
@@ -13381,6 +13384,7 @@
 	ctxt->userData = ctxt;
     if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
     ctxt->dict = oldctxt->dict;
+    ctxt->input_id = oldctxt->input_id + 1;
     ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
     ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
     ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
@@ -13634,6 +13638,7 @@
     xmlDetectSAX2(ctxt);
     ctxt->myDoc = doc;
     /* parsing in context, i.e. as within existing content */
+    ctxt->input_id = 2;
     ctxt->instate = XML_PARSER_CONTENT;
 
     fake = xmlNewComment(NULL);
@@ -13846,6 +13851,7 @@
 	newDoc->oldNs = doc->oldNs;
     }
     ctxt->instate = XML_PARSER_CONTENT;
+    ctxt->input_id = 2;
     ctxt->depth = depth;
 
     /*
@@ -14006,6 +14012,11 @@
     if (pctx != NULL) {
         ctxt->options = pctx->options;
         ctxt->_private = pctx->_private;
+	/*
+	 * this is a subparser of pctx, so the input_id should be
+	 * incremented to distinguish from main entity
+	 */
+	ctxt->input_id = pctx->input_id + 1;
     }
 
     uri = xmlBuildURI(URL, base);
diff --git a/third_party/libxml/src/testapi.c b/third_party/libxml/src/testapi.c
index fe42a379..4a751e20 100644
--- a/third_party/libxml/src/testapi.c
+++ b/third_party/libxml/src/testapi.c
@@ -9989,6 +9989,43 @@
 
 
 static int
+test_xmlHashDefaultDeallocator(void) {
+    int test_ret = 0;
+
+    int mem_base;
+    void * entry; /* the hash table entry */
+    int n_entry;
+    xmlChar * name; /* the entry's name */
+    int n_name;
+
+    for (n_entry = 0;n_entry < gen_nb_void_ptr;n_entry++) {
+    for (n_name = 0;n_name < gen_nb_const_xmlChar_ptr;n_name++) {
+        mem_base = xmlMemBlocks();
+        entry = gen_void_ptr(n_entry, 0);
+        name = gen_const_xmlChar_ptr(n_name, 1);
+
+        xmlHashDefaultDeallocator(entry, (const xmlChar *)name);
+        call_tests++;
+        des_void_ptr(n_entry, entry, 0);
+        des_const_xmlChar_ptr(n_name, (const xmlChar *)name, 1);
+        xmlResetLastError();
+        if (mem_base != xmlMemBlocks()) {
+            printf("Leak of %d blocks found in xmlHashDefaultDeallocator",
+	           xmlMemBlocks() - mem_base);
+	    test_ret++;
+            printf(" %d", n_entry);
+            printf(" %d", n_name);
+            printf("\n");
+        }
+    }
+    }
+    function_tests++;
+
+    return(test_ret);
+}
+
+
+static int
 test_xmlHashLookup(void) {
     int test_ret = 0;
 
@@ -10720,13 +10757,14 @@
 test_hash(void) {
     int test_ret = 0;
 
-    if (quiet == 0) printf("Testing hash : 16 of 24 functions ...\n");
+    if (quiet == 0) printf("Testing hash : 17 of 25 functions ...\n");
     test_ret += test_xmlHashAddEntry();
     test_ret += test_xmlHashAddEntry2();
     test_ret += test_xmlHashAddEntry3();
     test_ret += test_xmlHashCopy();
     test_ret += test_xmlHashCreate();
     test_ret += test_xmlHashCreateDict();
+    test_ret += test_xmlHashDefaultDeallocator();
     test_ret += test_xmlHashLookup();
     test_ret += test_xmlHashLookup2();
     test_ret += test_xmlHashLookup3();
diff --git a/third_party/libxml/src/win32/Makefile.msvc b/third_party/libxml/src/win32/Makefile.msvc
index ff8378e..491dc880 100644
--- a/third_party/libxml/src/win32/Makefile.msvc
+++ b/third_party/libxml/src/win32/Makefile.msvc
@@ -22,6 +22,7 @@
 XML_NAME = xml2
 XML_BASENAME = lib$(XML_NAME)
 XML_SO = $(XML_BASENAME).dll
+XML_RES = $(XML_BASENAME).res
 XML_IMP = $(XML_BASENAME).lib
 XML_DEF = $(XML_BASENAME).def
 XML_A = $(XML_BASENAME)_a.lib
@@ -69,7 +70,11 @@
 LIBS = $(LIBS) iconv.lib
 !endif 
 !if "$(WITH_ICU)" == "1"
-LIBS = $(LIBS) icu.lib
+!if "$(STATIC)" == "1"
+LIBS = $(LIBS) advapi32.lib sicuuc.lib sicuin.lib sicudt.lib
+!else
+LIBS = $(LIBS) icuuc.lib icuin.lib icudt.lib
+!endif
 !endif
 !if "$(WITH_ZLIB)" == "1"
 # could be named differently zdll or zlib
@@ -256,7 +261,10 @@
 	$(BINDIR)\testXPath.exe\
 	$(BINDIR)\runtest.exe\
 	$(BINDIR)\runsuite.exe\
+	$(BINDIR)\runxmlconf.exe\
 	$(BINDIR)\testapi.exe\
+	$(BINDIR)\testchar.exe\
+	$(BINDIR)\testdict.exe\
 	$(BINDIR)\testlimits.exe\
 	$(BINDIR)\testrecurse.exe
 	
@@ -367,11 +375,13 @@
 # Creates the export definition file (DEF) for libxml.
 $(XML_INTDIR)\$(XML_DEF) : $(XML_INTDIR) $(XML_DEF).src
 	$(CPP) $(CPPFLAGS) $(XML_DEF).src > $(XML_INTDIR)\$(XML_DEF)
+$(XML_INTDIR)\$(XML_RES) : $(XML_INTDIR) libxml2.rc
+	rc -Fo $(XML_INTDIR)\$(XML_RES) libxml2.rc
 
 # Creates the libxml shared object.
-$(BINDIR)\$(XML_SO) : $(BINDIR) $(XML_OBJS) $(XML_INTDIR)\$(XML_DEF)
+$(BINDIR)\$(XML_SO) : $(BINDIR) $(XML_OBJS) $(XML_INTDIR)\$(XML_DEF) $(XML_INTDIR)\$(XML_RES)
 	$(LD) $(LDFLAGS) /DLL \
-		/IMPLIB:$(BINDIR)\$(XML_IMP) /OUT:$(BINDIR)\$(XML_SO) $(XML_OBJS) $(LIBS)
+		/IMPLIB:$(BINDIR)\$(XML_IMP) /OUT:$(BINDIR)\$(XML_SO) $(XML_OBJS) $(XML_INTDIR)\$(XML_RES) $(LIBS)
 	@$(_VC_MANIFEST_EMBED_DLL)
 
 #$(BINDIR)\$(XML_SO) : $(BINDIR) $(XML_OBJS) $(XML_INTDIR)\$(XML_DEF)
diff --git a/third_party/libxml/src/win32/configure.js b/third_party/libxml/src/win32/configure.js
index 92b9ba052..dbf238c 100644
--- a/third_party/libxml/src/win32/configure.js
+++ b/third_party/libxml/src/win32/configure.js
@@ -280,6 +280,18 @@
 		vf.WriteLine("DYNRUNTIME=" + (dynruntime? "1" : "0"));
 	}
 	vf.Close();
+	versionFile = "rcVersion.h"
+	vf = fso.CreateTextFile(versionFile, true);
+	vf.WriteLine("/*");
+	vf.WriteLine("  " + versionFile);
+	vf.WriteLine("  This file is generated automatically by " + WScript.ScriptName + ".");
+	vf.WriteLine("*/");
+	vf.WriteBlankLines(1);
+	vf.WriteLine("#define LIBXML_MAJOR_VERSION " + verMajor);
+	vf.WriteLine("#define LIBXML_MINOR_VERSION " + verMinor);
+	vf.WriteLine("#define LIBXML_MICRO_VERSION " + verMicro);
+	vf.WriteLine("#define LIBXML_DOTTED_VERSION " + "\"" + verMajor + "." + verMinor + "." + verMicro + "\"");
+	vf.Close()
 }
 
 /* Configures libxml. This one will generate xmlversion.h from xmlversion.h.in
diff --git a/third_party/libxml/src/win32/libxml2.rc b/third_party/libxml/src/win32/libxml2.rc
new file mode 100644
index 0000000..c774a5e
--- /dev/null
+++ b/third_party/libxml/src/win32/libxml2.rc
@@ -0,0 +1,36 @@
+#include <winver.h>
+#include "rcVersion.h"
+
+VS_VERSION_INFO		VERSIONINFO
+  FILEVERSION		LIBXML_MAJOR_VERSION,LIBXML_MINOR_VERSION,LIBXML_MICRO_VERSION,0
+  PRODUCTVERSION	LIBXML_MAJOR_VERSION,LIBXML_MINOR_VERSION,LIBXML_MICRO_VERSION,0
+  FILEFLAGSMASK		VS_FFI_FILEFLAGSMASK
+#ifdef _DEBUG
+  FILEFLAGS		VS_FF_DEBUG
+#else
+  FILEFLAGS		0
+#endif
+  FILEOS		VOS__WINDOWS32
+  FILETYPE		VFT_DLL
+  FILESUBTYPE	VFT2_UNKNOWN	// not used
+BEGIN
+  BLOCK "StringFileInfo"
+  BEGIN
+    BLOCK "04090000"  /* Lang = US English, Charset = ASCII */
+    BEGIN
+      VALUE "FileDescription",	"libxml2 library\0"
+      VALUE "FileVersion",	LIBXML_DOTTED_VERSION "\0"
+      VALUE "InternalName",	"libxml2.dll\0"
+      VALUE "LegalCopyright",	"Copyright (C) Daniel Veillard\0"
+      VALUE "LegalTrademarks",	"\0"
+      VALUE "OriginalFilename",	"libxml2.dll\0"
+      VALUE "ProductName",	"libxml2\0"
+      VALUE "ProductVersion",	LIBXML_DOTTED_VERSION "\0"
+      VALUE "Comments",		"For more information visit http://xmlsoft.org/\0"
+    END
+  END
+  BLOCK "VarFileInfo"
+  BEGIN
+      VALUE "Translation", 0x0409, 0  /* US English, ASCII */
+  END
+END
diff --git a/third_party/libxml/src/xpath.c b/third_party/libxml/src/xpath.c
index d134025a..af9c0b4b 100644
--- a/third_party/libxml/src/xpath.c
+++ b/third_party/libxml/src/xpath.c
@@ -477,27 +477,28 @@
  *									*
  ************************************************************************/
 
-#ifndef NAN
-#define NAN (0.0 / 0.0)
-#endif
-
 #ifndef INFINITY
-#define INFINITY HUGE_VAL
+#define INFINITY (DBL_MAX * DBL_MAX)
 #endif
 
-double xmlXPathNAN = NAN;
-double xmlXPathPINF = INFINITY;
-double xmlXPathNINF = -INFINITY;
+#ifndef NAN
+#define NAN (INFINITY / INFINITY)
+#endif
+
+double xmlXPathNAN;
+double xmlXPathPINF;
+double xmlXPathNINF;
 
 /**
  * xmlXPathInit:
  *
  * Initialize the XPath environment
- *
- * Does nothing but must be kept as public function.
  */
 void
 xmlXPathInit(void) {
+    xmlXPathNAN = NAN;
+    xmlXPathPINF = INFINITY;
+    xmlXPathNINF = -INFINITY;
 }
 
 /**
diff --git a/third_party/libxml/win32/include/libxml/xmlversion.h b/third_party/libxml/win32/include/libxml/xmlversion.h
index cd9ebed..c26c962 100644
--- a/third_party/libxml/win32/include/libxml/xmlversion.h
+++ b/third_party/libxml/win32/include/libxml/xmlversion.h
@@ -29,21 +29,21 @@
  *

  * the version string like "1.2.3"

  */

-#define LIBXML_DOTTED_VERSION "2.9.7"

+#define LIBXML_DOTTED_VERSION "2.9.8"

 

 /**

  * LIBXML_VERSION:

  *

  * the version number: 1.2.3 value is 10203

  */

-#define LIBXML_VERSION 20907

+#define LIBXML_VERSION 20908

 

 /**

  * LIBXML_VERSION_STRING:

  *

  * the version number string, 1.2.3 value is "10203"

  */

-#define LIBXML_VERSION_STRING "20907"

+#define LIBXML_VERSION_STRING "20908"

 

 /**

  * LIBXML_VERSION_EXTRA:

@@ -58,7 +58,7 @@
  * Macro to check that the libxml version in use is compatible with

  * the version the software has been compiled against

  */

-#define LIBXML_TEST_VERSION xmlCheckVersion(20907);

+#define LIBXML_TEST_VERSION xmlCheckVersion(20908);

 

 #ifndef VMS

 #if 0

diff --git a/third_party/metrics_proto/README.chromium b/third_party/metrics_proto/README.chromium
index 8dfa3335..2b74727 100644
--- a/third_party/metrics_proto/README.chromium
+++ b/third_party/metrics_proto/README.chromium
@@ -1,8 +1,8 @@
 Name: Metrics Protos
 Short Name: metrics_proto
 URL: This is the canonical public repository
-Version: 187110743
-Date: 2018/02/26
+Version: 187110744
+Date: 2018/03/22
 License: BSD
 Security Critical: Yes
 
diff --git a/third_party/metrics_proto/omnibox_event.proto b/third_party/metrics_proto/omnibox_event.proto
index 222ed5c71..e9531ed 100644
--- a/third_party/metrics_proto/omnibox_event.proto
+++ b/third_party/metrics_proto/omnibox_event.proto
@@ -14,7 +14,7 @@
 import "omnibox_input_type.proto";
 
 // Stores information about an omnibox interaction.
-// Next tag: 17
+// Next tag: 18
 message OmniboxEventProto {
   // The timestamp for the event, in seconds.
   // This value comes from Chromium's TimeTicks::Now(), which is an abstract
@@ -45,6 +45,11 @@
   // This corresponds the index of the |suggestion| below.
   optional int32 selected_index = 5;
 
+  // Whether the user selected the option to switch tabs (or ignored it
+  // and navigated). If true, one or more |Suggestions| will have
+  // |has_tab_match| set as well, which must include the |selected_index|.
+  optional bool selected_tab_match = 17;
+
   // DEPRECATED. Whether or not the top match was hidden in the omnibox
   // suggestions dropdown.
   optional bool DEPRECATED_is_top_result_hidden_in_dropdown = 14
@@ -177,7 +182,7 @@
   }
 
   // The result set displayed on the completion popup
-  // Next tag: 8
+  // Next tag: 9
   message Suggestion {
     // Where does this result come from?
     optional ProviderType provider = 1;
@@ -267,6 +272,10 @@
     // provider of each suggestion type and is different for every suggestion
     // type. See enum ResultType above for more details.
     optional int32 result_subtype_identifier = 7;
+
+    // Whether the suggestion presented in the match, regardless of type,
+    // matched an open tab.
+    optional bool has_tab_match = 8;
   }
   repeated Suggestion suggestion = 9;
 
diff --git a/third_party/metrics_proto/ukm/source.proto b/third_party/metrics_proto/ukm/source.proto
index 3ef2deb..e05866df 100644
--- a/third_party/metrics_proto/ukm/source.proto
+++ b/third_party/metrics_proto/ukm/source.proto
@@ -11,6 +11,17 @@
 // Source contains data related to a top-level navigation.
 // Next tag: 10
 message Source {
+  // The URL scheme, such as HTTP, HTTPS, CHROME_EXTENSION, etc.
+  enum UrlScheme {
+    UNSUPPORTED = 0;
+    HTTP = 1;
+    HTTPS = 2;
+    FTP = 3;
+    ABOUT = 4;
+    CHROME = 5;
+    CHROME_EXTENSION = 6;
+  };
+
   // An identifier for the source. This should be unique within a session.
   optional int64 id = 1;
 
diff --git a/third_party/polymer/v1_0/bower.json b/third_party/polymer/v1_0/bower.json
index ae1dbc2..61ea684a 100644
--- a/third_party/polymer/v1_0/bower.json
+++ b/third_party/polymer/v1_0/bower.json
@@ -7,13 +7,13 @@
     "iron-a11y-keys-behavior": "PolymerElements/iron-a11y-keys-behavior#1.1.9",
     "iron-a11y-keys": "PolymerElements/iron-a11y-keys#2.0.0",
     "iron-autogrow-textarea": "PolymerElements/iron-autogrow-textarea#2.1.1",
-    "iron-behaviors": "PolymerElements/iron-behaviors#1.0.17",
-    "iron-checked-element-behavior": "PolymerElements/iron-checked-element-behavior#1.0.5",
+    "iron-behaviors": "PolymerElements/iron-behaviors#2.1.1",
+    "iron-checked-element-behavior": "PolymerElements/iron-checked-element-behavior#2.1.0",
     "iron-collapse": "PolymerElements/iron-collapse#2.1.0",
     "iron-dropdown": "PolymerElements/iron-dropdown#2.1.0",
     "iron-fit-behavior": "PolymerElements/iron-fit-behavior#2.1.0",
     "iron-flex-layout": "PolymerElements/iron-flex-layout#1.3.1",
-    "iron-form-element-behavior": "PolymerElements/iron-form-element-behavior#1.0.6",
+    "iron-form-element-behavior": "PolymerElements/iron-form-element-behavior#2.1.1",
     "iron-icon": "PolymerElements/iron-icon#2.0.1",
     "iron-iconset-svg": "PolymerElements/iron-iconset-svg#2.1.1",
     "iron-icons": "PolymerElements/iron-icons#2.0.1",
@@ -33,7 +33,7 @@
     "iron-test-helpers": "PolymerElements/iron-test-helpers#2.0.0",
     "iron-validatable-behavior": "PolymerElements/iron-validatable-behavior#1.1.1",
     "neon-animation": "PolymerElements/neon-animation#2.1.0",
-    "paper-behaviors": "PolymerElements/paper-behaviors#1.0.12",
+    "paper-behaviors": "PolymerElements/paper-behaviors#2.1.0",
     "paper-button": "PolymerElements/paper-button#2.0.0",
     "paper-checkbox": "PolymerElements/paper-checkbox#2.0.2",
     "paper-fab": "PolymerElements/paper-fab#2.0.0",
diff --git a/third_party/polymer/v1_0/components-chromium/iron-behaviors/bower.json b/third_party/polymer/v1_0/components-chromium/iron-behaviors/bower.json
index fd877fe..6350520 100644
--- a/third_party/polymer/v1_0/components-chromium/iron-behaviors/bower.json
+++ b/third_party/polymer/v1_0/components-chromium/iron-behaviors/bower.json
@@ -1,6 +1,6 @@
 {
   "name": "iron-behaviors",
-  "version": "1.0.17",
+  "version": "2.1.1",
   "description": "Provides a set of behaviors for the iron elements",
   "private": true,
   "authors": [
@@ -16,17 +16,38 @@
   ],
   "license": "http://polymer.github.io/LICENSE.txt",
   "dependencies": {
-    "polymer": "Polymer/polymer#^1.2.0",
-    "iron-a11y-keys-behavior": "PolymerElements/iron-a11y-keys-behavior#^1.0.0"
+    "polymer": "Polymer/polymer#1.9 - 2",
+    "iron-a11y-keys-behavior": "PolymerElements/iron-a11y-keys-behavior#1 - 2"
   },
   "devDependencies": {
-    "paper-styles": "polymerelements/paper-styles#^1.0.2",
-    "paper-input": "polymerelements/paper-input#^1.0.0",
-    "iron-test-helpers": "polymerelements/iron-test-helpers#^1.0.0",
-    "iron-component-page": "polymerelements/iron-component-page#^1.0.0",
-    "test-fixture": "polymerelements/test-fixture#^1.0.0",
-    "web-component-tester": "^4.0.0",
-    "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0"
+    "paper-styles": "PolymerElements/paper-styles#1 - 2",
+    "paper-input": "PolymerElements/paper-input#1 - 2",
+    "iron-test-helpers": "PolymerElements/iron-test-helpers#1 - 2",
+    "iron-component-page": "PolymerElements/iron-component-page#1 - 2",
+    "web-component-tester": "^6.0.0",
+    "webcomponentsjs": "webcomponents/webcomponentsjs#^1.0.0"
   },
-  "ignore": []
+  "ignore": [],
+  "variants": {
+    "1.x": {
+      "dependencies": {
+        "polymer": "Polymer/polymer#^1.9",
+        "iron-a11y-keys-behavior": "PolymerElements/iron-a11y-keys-behavior#^1.0.0"
+      },
+      "devDependencies": {
+        "paper-styles": "PolymerElements/paper-styles#^1.0.0",
+        "paper-input": "PolymerElements/paper-input#^1.0.0",
+        "iron-test-helpers": "PolymerElements/iron-test-helpers#^1.0.0",
+        "iron-component-page": "PolymerElements/iron-component-page#^1.0.0",
+        "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0",
+        "web-component-tester": "Polymer/web-component-tester#^4.0.0"
+      },
+      "resolutions": {
+        "webcomponentsjs": "^0.7"
+      }
+    }
+  },
+  "resolutions": {
+    "webcomponentsjs": "^1.0.0"
+  }
 }
diff --git a/third_party/polymer/v1_0/components-chromium/iron-behaviors/iron-button-state-extracted.js b/third_party/polymer/v1_0/components-chromium/iron-behaviors/iron-button-state-extracted.js
index 5a2cf2c7..6dd5d3a8 100644
--- a/third_party/polymer/v1_0/components-chromium/iron-behaviors/iron-button-state-extracted.js
+++ b/third_party/polymer/v1_0/components-chromium/iron-behaviors/iron-button-state-extracted.js
@@ -75,10 +75,13 @@
     },
 
     observers: [
-      '_detectKeyboardFocus(focused)',
+      '_focusChanged(focused)',
       '_activeChanged(active, ariaActiveAttribute)'
     ],
 
+    /**
+     * @type {!Object}
+     */
     keyBindings: {
       'enter:keydown': '_asyncClick',
       'space:keydown': '_spaceKeyDownHandler',
@@ -96,6 +99,14 @@
       }
     },
 
+    _focusChanged: function(focused) {
+      this._detectKeyboardFocus(focused);
+
+      if (!focused) {
+        this._setPressed(false);
+      }
+    },
+
     _detectKeyboardFocus: function(focused) {
       this._setReceivedFocusFromKeyboard(!this.pointerDown && focused);
     },
diff --git a/third_party/polymer/v1_0/components-chromium/iron-behaviors/iron-control-state-extracted.js b/third_party/polymer/v1_0/components-chromium/iron-behaviors/iron-control-state-extracted.js
index 06538f0..859ac005 100644
--- a/third_party/polymer/v1_0/components-chromium/iron-behaviors/iron-control-state-extracted.js
+++ b/third_party/polymer/v1_0/components-chromium/iron-behaviors/iron-control-state-extracted.js
@@ -28,8 +28,13 @@
         reflectToAttribute: true
       },
 
+      /**
+       * Value of the `tabindex` attribute before `disabled` was activated.
+       * `null` means the attribute was not present.
+       * @type {?string|undefined}
+       */
       _oldTabIndex: {
-        type: Number
+        type: String
       },
 
       _boundFocusBlurHandler: {
@@ -37,29 +42,43 @@
         value: function() {
           return this._focusBlurHandler.bind(this);
         }
-      }
+      },
 
+      __handleEventRetargeting: {
+        type: Boolean,
+        value: function() {
+          return !this.shadowRoot && !Polymer.Element;
+        }
+      }
     },
 
     observers: [
       '_changedControlState(focused, disabled)'
     ],
 
+    /**
+     * @return {void}
+     */
     ready: function() {
       this.addEventListener('focus', this._boundFocusBlurHandler, true);
       this.addEventListener('blur', this._boundFocusBlurHandler, true);
     },
 
     _focusBlurHandler: function(event) {
+      // In Polymer 2.0, the library takes care of retargeting events.
+      if (Polymer.Element) {
+        this._setFocused(event.type === 'focus');
+        return;
+      }
+
       // NOTE(cdata):  if we are in ShadowDOM land, `event.target` will
       // eventually become `this` due to retargeting; if we are not in
       // ShadowDOM land, `event.target` will eventually become `this` due
       // to the second conditional which fires a synthetic event (that is also
       // handled). In either case, we can disregard `event.path`.
-
       if (event.target === this) {
         this._setFocused(event.type === 'focus');
-      } else if (!this.shadowRoot) {
+      } else if (this.__handleEventRetargeting) {
         var target = /** @type {Node} */(Polymer.dom(event).localTarget);
         if (!this.isLightDescendant(target)) {
           this.fire(event.type, {sourceEvent: event}, {
@@ -75,12 +94,20 @@
       this.setAttribute('aria-disabled', disabled ? 'true' : 'false');
       this.style.pointerEvents = disabled ? 'none' : '';
       if (disabled) {
-        this._oldTabIndex = this.tabIndex;
+        // Read the `tabindex` attribute instead of the `tabIndex` property.
+        // The property returns `-1` if there is no `tabindex` attribute.
+        // This distinction is important when restoring the value because
+        // leaving `-1` hides shadow root children from the tab order.
+        this._oldTabIndex = this.getAttribute('tabindex');
         this._setFocused(false);
         this.tabIndex = -1;
         this.blur();
       } else if (this._oldTabIndex !== undefined) {
-        this.tabIndex = this._oldTabIndex;
+        if (this._oldTabIndex === null) {
+          this.removeAttribute('tabindex');
+        } else {
+          this.setAttribute('tabindex', this._oldTabIndex);
+        }
       }
     },
 
diff --git a/third_party/polymer/v1_0/components-chromium/iron-checked-element-behavior/bower.json b/third_party/polymer/v1_0/components-chromium/iron-checked-element-behavior/bower.json
index f645217c..95768596 100644
--- a/third_party/polymer/v1_0/components-chromium/iron-checked-element-behavior/bower.json
+++ b/third_party/polymer/v1_0/components-chromium/iron-checked-element-behavior/bower.json
@@ -1,6 +1,6 @@
 {
   "name": "iron-checked-element-behavior",
-  "version": "1.0.5",
+  "version": "2.0.0",
   "description": "Implements an element that has a checked attribute and can be added to a form",
   "authors": "The Polymer Authors",
   "keywords": [
@@ -19,16 +19,37 @@
   "homepage": "https://github.com/PolymerElements/iron-checked-element-behavior",
   "ignore": [],
   "dependencies": {
-    "polymer": "Polymer/polymer#^1.1.0",
-    "iron-validatable-behavior": "PolymerElements/iron-validatable-behavior#^1.0.0",
-    "iron-form-element-behavior": "PolymerElements/iron-form-element-behavior#^1.0.0"
+    "polymer": "Polymer/polymer#1.9 - 2",
+    "iron-validatable-behavior": "PolymerElements/iron-validatable-behavior#1 - 2",
+    "iron-form-element-behavior": "PolymerElements/iron-form-element-behavior#1 - 2"
   },
   "devDependencies": {
-    "paper-styles": "PolymerElements/paper-styles#^1.0.0",
-    "paper-button": "PolymerElements/paper-button#^1.0.0",
-    "iron-component-page": "PolymerElements/iron-component-page#^1.0.0",
-    "test-fixture": "PolymerElements/test-fixture#^1.0.0",
-    "web-component-tester": "^4.0.0",
-    "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0"
+    "paper-styles": "PolymerElements/paper-styles#1 - 2",
+    "paper-button": "PolymerElements/paper-button#1 - 2",
+    "iron-component-page": "PolymerElements/iron-component-page#1 - 2",
+    "web-component-tester": "^6.0.0",
+    "webcomponentsjs": "webcomponents/webcomponentsjs#^1.0.0"
+  },
+  "variants": {
+    "1.x": {
+      "dependencies": {
+        "polymer": "Polymer/polymer#^1.9",
+        "iron-validatable-behavior": "PolymerElements/iron-validatable-behavior#^1.0.0",
+        "iron-form-element-behavior": "PolymerElements/iron-form-element-behavior#^1.0.0"
+      },
+      "devDependencies": {
+        "paper-styles": "PolymerElements/paper-styles#^1.0.0",
+        "paper-button": "PolymerElements/paper-button#^1.0.0",
+        "iron-component-page": "PolymerElements/iron-component-page#^1.0.0",
+        "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0",
+        "web-component-tester": "Polymer/web-component-tester#^4.0.0"
+      },
+      "resolutions": {
+        "webcomponentsjs": "^0.7"
+      }
+    }
+  },
+  "resolutions": {
+    "webcomponentsjs": "^1.0.0"
   }
 }
diff --git a/third_party/polymer/v1_0/components-chromium/iron-form-element-behavior/bower.json b/third_party/polymer/v1_0/components-chromium/iron-form-element-behavior/bower.json
index 865f9b549..7e24b72 100644
--- a/third_party/polymer/v1_0/components-chromium/iron-form-element-behavior/bower.json
+++ b/third_party/polymer/v1_0/components-chromium/iron-form-element-behavior/bower.json
@@ -1,6 +1,6 @@
 {
   "name": "iron-form-element-behavior",
-  "version": "1.0.6",
+  "version": "2.1.1",
   "license": "http://polymer.github.io/LICENSE.txt",
   "private": true,
   "main": "iron-form-element-behavior.html",
@@ -18,14 +18,32 @@
     "url": "git://github.com/PolymerElements/iron-form-element-behavior.git"
   },
   "dependencies": {
-    "polymer": "Polymer/polymer#^1.0.0"
+    "polymer": "Polymer/polymer#1.9 - 2"
   },
   "devDependencies": {
-    "iron-component-page": "PolymerElements/iron-component-page#^1.0.0",
-    "paper-styles": "PolymerElements/paper-styles#^1.0.0",
-    "test-fixture": "PolymerElements/test-fixture#^1.0.0",
-    "web-component-tester": "polymer/web-component-tester#^3.4.0",
-    "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0"
+    "iron-component-page": "PolymerElements/iron-component-page#1 - 2",
+    "paper-styles": "PolymerElements/paper-styles#1 - 2",
+    "web-component-tester": "^6.0.0",
+    "webcomponentsjs": "webcomponents/webcomponentsjs#^1.0.0"
   },
-  "ignore": []
+  "variants": {
+    "1.x": {
+      "dependencies": {
+        "polymer": "Polymer/polymer#^1.9"
+      },
+      "devDependencies": {
+        "iron-component-page": "PolymerElements/iron-component-page#^1.0.0",
+        "paper-styles": "PolymerElements/paper-styles#^1.0.0",
+        "web-component-tester": "^4.0.0",
+        "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0"
+      },
+      "resolutions": {
+        "webcomponentsjs": "^0.7"
+      }
+    }
+  },
+  "ignore": [],
+  "resolutions": {
+    "webcomponentsjs": "^1.0.0"
+  }
 }
diff --git a/third_party/polymer/v1_0/components-chromium/iron-form-element-behavior/iron-form-element-behavior-extracted.js b/third_party/polymer/v1_0/components-chromium/iron-form-element-behavior/iron-form-element-behavior-extracted.js
index 640842c..6d9aa04 100644
--- a/third_party/polymer/v1_0/components-chromium/iron-form-element-behavior/iron-form-element-behavior-extracted.js
+++ b/third_party/polymer/v1_0/components-chromium/iron-form-element-behavior/iron-form-element-behavior-extracted.js
@@ -2,6 +2,8 @@
   Polymer.IronFormElementBehavior enables a custom element to be included
   in an `iron-form`.
 
+  Events `iron-form-element-register` and `iron-form-element-unregister` are not fired on Polymer 2.0.
+
   @demo demo/index.html
   @polymerBehavior
   */
@@ -19,7 +21,7 @@
        *
        * @event iron-form-element-unregister
        */
-
+       
       /**
        * The name of this element.
        */
@@ -56,14 +58,16 @@
       }
     },
 
-    attached: function() {
-      // Note: the iron-form that this element belongs to will set this
-      // element's _parentForm property when handling this event.
-      this.fire('iron-form-element-register');
+    attached() {
+      if (!Polymer.Element) {
+        // Note: the iron-form that this element belongs to will set this
+        // element's _parentForm property when handling this event.
+        this.fire('iron-form-element-register');
+      }
     },
 
-    detached: function() {
-      if (this._parentForm) {
+    detached() {
+      if (!Polymer.Element && this._parentForm) {
         this._parentForm.fire('iron-form-element-unregister', {target: this});
       }
     }
diff --git a/third_party/polymer/v1_0/components-chromium/paper-behaviors/BUILD.gn b/third_party/polymer/v1_0/components-chromium/paper-behaviors/BUILD.gn
index a101156..ed519e50 100644
--- a/third_party/polymer/v1_0/components-chromium/paper-behaviors/BUILD.gn
+++ b/third_party/polymer/v1_0/components-chromium/paper-behaviors/BUILD.gn
@@ -29,6 +29,7 @@
 
 js_library("paper-ripple-behavior-extracted") {
   deps = [
+    "../iron-behaviors:iron-button-state-extracted",
     "../paper-ripple:paper-ripple-extracted",
   ]
 }
diff --git a/third_party/polymer/v1_0/components-chromium/paper-behaviors/bower.json b/third_party/polymer/v1_0/components-chromium/paper-behaviors/bower.json
index 8439368..0846138a 100644
--- a/third_party/polymer/v1_0/components-chromium/paper-behaviors/bower.json
+++ b/third_party/polymer/v1_0/components-chromium/paper-behaviors/bower.json
@@ -1,6 +1,6 @@
 {
   "name": "paper-behaviors",
-  "version": "1.0.12",
+  "version": "2.1.0",
   "description": "Common behaviors across the paper elements",
   "authors": [
     "The Polymer Authors"
@@ -25,18 +25,42 @@
   "license": "http://polymer.github.io/LICENSE.txt",
   "homepage": "https://github.com/PolymerElements/paper-behaviors",
   "dependencies": {
-    "iron-behaviors": "PolymerElements/iron-behaviors#^1.0.0",
-    "iron-checked-element-behavior": "PolymerElements/iron-checked-element-behavior#^1.0.0",
-    "paper-ripple": "PolymerElements/paper-ripple#^1.0.0",
-    "polymer": "Polymer/polymer#^1.2.1"
+    "iron-behaviors": "PolymerElements/iron-behaviors#1 - 2",
+    "iron-checked-element-behavior": "PolymerElements/iron-checked-element-behavior#1 - 2",
+    "paper-ripple": "PolymerElements/paper-ripple#1 - 2",
+    "polymer": "Polymer/polymer#1.9 - 2"
   },
   "devDependencies": {
-    "iron-component-page": "polymerelements/iron-component-page#^1.0.0",
-    "iron-test-helpers": "polymerelements/iron-test-helpers#^1.0.0",
-    "paper-material": "PolymerElements/paper-material#^1.0.0",
-    "test-fixture": "PolymerElements/test-fixture#^1.0.0",
-    "web-component-tester": "^4.0.0",
-    "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0"
+    "iron-component-page": "polymerelements/iron-component-page#1 - 2",
+    "iron-test-helpers": "polymerelements/iron-test-helpers#1 - 2",
+    "paper-styles": "PolymerElements/paper-styles#1 - 2",
+    "test-fixture": "PolymerElements/test-fixture#^3.0.0-rc.1",
+    "web-component-tester": "^6.0.0",
+    "webcomponentsjs": "webcomponents/webcomponentsjs#^1.0.0"
   },
-  "ignore": []
+  "ignore": [],
+  "variants": {
+    "1.x": {
+      "dependencies": {
+        "iron-behaviors": "PolymerElements/iron-behaviors#^1.0.0",
+        "iron-checked-element-behavior": "PolymerElements/iron-checked-element-behavior#^1.0.0",
+        "paper-ripple": "PolymerElements/paper-ripple#^1.0.0",
+        "polymer": "Polymer/polymer#^1.9"
+      },
+      "devDependencies": {
+        "iron-component-page": "polymerelements/iron-component-page#^1.0.0",
+        "iron-test-helpers": "polymerelements/iron-test-helpers#^1.0.0",
+        "paper-styles": "PolymerElements/paper-styles#^1.0.0",
+        "test-fixture": "PolymerElements/test-fixture#^1.0.0",
+        "web-component-tester": "^4.0.0",
+        "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0"
+      },
+      "resolutions": {
+        "webcomponentsjs": "^0.7"
+      }
+    }
+  },
+  "resolutions": {
+    "webcomponentsjs": "^1.0.0"
+  }
 }
diff --git a/third_party/polymer/v1_0/components-chromium/paper-behaviors/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/paper-behaviors/compiled_resources2.gyp
index 64eb3528..7d3adf7 100644
--- a/third_party/polymer/v1_0/components-chromium/paper-behaviors/compiled_resources2.gyp
+++ b/third_party/polymer/v1_0/components-chromium/paper-behaviors/compiled_resources2.gyp
@@ -32,6 +32,7 @@
     {
       'target_name': 'paper-ripple-behavior-extracted',
       'dependencies': [
+        '../iron-behaviors/compiled_resources2.gyp:iron-button-state-extracted',
         '../paper-ripple/compiled_resources2.gyp:paper-ripple-extracted',
       ],
       'includes': ['../../../../closure_compiler/compile_js2.gypi'],
diff --git a/third_party/polymer/v1_0/components-chromium/paper-behaviors/paper-ripple-behavior-extracted.js b/third_party/polymer/v1_0/components-chromium/paper-behaviors/paper-ripple-behavior-extracted.js
index 31891f3..77ed87a9 100644
--- a/third_party/polymer/v1_0/components-chromium/paper-behaviors/paper-ripple-behavior-extracted.js
+++ b/third_party/polymer/v1_0/components-chromium/paper-behaviors/paper-ripple-behavior-extracted.js
@@ -99,8 +99,9 @@
      * @return {!PaperRippleElement} Returns a `<paper-ripple>` element.
      */
     _createRipple: function() {
-      return /** @type {!PaperRippleElement} */ (
+      var element = /** @type {!PaperRippleElement} */ (
           document.createElement('paper-ripple'));
+      return element;
     },
 
     _noinkChanged: function(noink) {
diff --git a/third_party/polymer/v1_0/components-chromium/paper-behaviors/paper-ripple-behavior.html b/third_party/polymer/v1_0/components-chromium/paper-behaviors/paper-ripple-behavior.html
index 39312fd..106e2eb 100644
--- a/third_party/polymer/v1_0/components-chromium/paper-behaviors/paper-ripple-behavior.html
+++ b/third_party/polymer/v1_0/components-chromium/paper-behaviors/paper-ripple-behavior.html
@@ -7,6 +7,7 @@
 Code distributed by Google as part of the polymer project is also
 subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
 --><html><head><link rel="import" href="../polymer/polymer.html">
+<link rel="import" href="../iron-behaviors/iron-button-state.html">
 <link rel="import" href="../paper-ripple/paper-ripple.html">
 
 </head><body><script src="paper-ripple-behavior-extracted.js"></script></body></html>
\ No newline at end of file
diff --git a/third_party/polymer/v1_0/components_summary.txt b/third_party/polymer/v1_0/components_summary.txt
index 5506162f..f9905d49 100644
--- a/third_party/polymer/v1_0/components_summary.txt
+++ b/third_party/polymer/v1_0/components_summary.txt
@@ -30,15 +30,15 @@
 
 Name: iron-behaviors
 Repository: https://github.com/PolymerElements/iron-behaviors.git
-Tree: v1.0.17
-Revision: ef8e89b5f0aa4e8a6b51ca6491ea453bf395f94f
-Tree link: https://github.com/PolymerElements/iron-behaviors/tree/v1.0.17
+Tree: v2.1.1
+Revision: a27b45bebb2af58506af77c377dab301bf7406ce
+Tree link: https://github.com/PolymerElements/iron-behaviors/tree/v2.1.1
 
 Name: iron-checked-element-behavior
 Repository: https://github.com/PolymerElements/iron-checked-element-behavior.git
-Tree: v1.0.5
-Revision: c70add47a9af62d30746587e8a1303fb390787c6
-Tree link: https://github.com/PolymerElements/iron-checked-element-behavior/tree/v1.0.5
+Tree: v2.1.0
+Revision: 3bd74f1dda95020aad873467ca25c37dc09d6ee4
+Tree link: https://github.com/PolymerElements/iron-checked-element-behavior/tree/v2.1.0
 
 Name: iron-collapse
 Repository: https://github.com/PolymerElements/iron-collapse.git
@@ -66,9 +66,9 @@
 
 Name: iron-form-element-behavior
 Repository: https://github.com/PolymerElements/iron-form-element-behavior.git
-Tree: v1.0.6
-Revision: cf9e09ded62daf3363852ce98260aaad1ed0fae1
-Tree link: https://github.com/PolymerElements/iron-form-element-behavior/tree/v1.0.6
+Tree: v2.1.1
+Revision: 89568e9b7ae3ebfa86f67395085b7f1f34df505e
+Tree link: https://github.com/PolymerElements/iron-form-element-behavior/tree/v2.1.1
 
 Name: iron-icon
 Repository: https://github.com/PolymerElements/iron-icon.git
@@ -186,9 +186,9 @@
 
 Name: paper-behaviors
 Repository: https://github.com/PolymerElements/paper-behaviors.git
-Tree: v1.0.12
-Revision: 424919089ce3a68dfac1de17e6a56f4e09048e95
-Tree link: https://github.com/PolymerElements/paper-behaviors/tree/v1.0.12
+Tree: v2.1.0
+Revision: ddde7f8cf41078b7a7b724473558421d6bc37f57
+Tree link: https://github.com/PolymerElements/paper-behaviors/tree/v2.1.0
 
 Name: paper-button
 Repository: https://github.com/PolymerElements/paper-button.git
diff --git a/third_party/unrar/BUILD.gn b/third_party/unrar/BUILD.gn
index 4fb271d..a330d27 100644
--- a/third_party/unrar/BUILD.gn
+++ b/third_party/unrar/BUILD.gn
@@ -33,7 +33,6 @@
       "src/options.cpp",
       "src/pathfn.cpp",
       "src/qopen.cpp",
-      "src/rar.cpp",
       "src/rarvm.cpp",
       "src/rawread.cpp",
       "src/rdwrfn.cpp",
@@ -71,9 +70,10 @@
       "_FILE_OFFSET_BITS=64",
       "LARGEFILE_SOURCE",
       "RAR_SMP",
+
       # The following is set to disable certain macro definitions in the unrar
       # source code.
-      "CHROMIUM_UNRAR"
+      "CHROMIUM_UNRAR",
     ]
   }
 }
diff --git a/third_party/usrsctp/README.chromium b/third_party/usrsctp/README.chromium
index 6e59c23..d3081b07 100644
--- a/third_party/usrsctp/README.chromium
+++ b/third_party/usrsctp/README.chromium
@@ -1,8 +1,8 @@
 Name: usrsctp
 URL: http://github.com/sctplab/usrsctp
 Version: 0
-Date: Aug 3, 2017
-Revision: f4819e1b177f7bfdd761c147f5a649b9f1a78c06
+Date: Mar 13, 2018
+Revision: 159d060dceec41a64a57356cbba8c455105f3f72
 License: New BSD
 License File: LICENSE
 Security Critical: yes
diff --git a/third_party/widevine/cdm/BUILD.gn b/third_party/widevine/cdm/BUILD.gn
index 977005ec..55b471ea 100644
--- a/third_party/widevine/cdm/BUILD.gn
+++ b/third_party/widevine/cdm/BUILD.gn
@@ -86,7 +86,7 @@
 
   public_deps = [
     ":version_h",  # Forward permission to use version header.
-    "//media:media_features",
+    "//media:media_buildflags",
   ]
 }
 
@@ -120,6 +120,13 @@
 }
 
 group("cdm") {
+  # Needed at run time by tests, e.g. swarming tests to generate isolate.
+  # See https://crbug.com/824493 for context.
+  data_deps = [
+    ":widevine_cdm_binary",
+    ":widevine_cdm_manifest",
+  ]
+  # Needed at build time e.g. for mac bundle (//chrome:chrome_framework).
   public_deps = [
     ":widevine_cdm_binary",
     ":widevine_cdm_manifest",
diff --git a/third_party/widevine/cdm/DEPS b/third_party/widevine/cdm/DEPS
index 716b001..ae3be09 100644
--- a/third_party/widevine/cdm/DEPS
+++ b/third_party/widevine/cdm/DEPS
@@ -1,4 +1,4 @@
 include_rules = [
-  "+media/media_features.h",
+  "+media/media_buildflags.h",
   "+ppapi/features",
 ]
diff --git a/third_party/widevine/cdm/widevine_cdm_common.h b/third_party/widevine/cdm/widevine_cdm_common.h
index c20c624..d2802dd 100644
--- a/third_party/widevine/cdm/widevine_cdm_common.h
+++ b/third_party/widevine/cdm/widevine_cdm_common.h
@@ -5,7 +5,7 @@
 #ifndef WIDEVINE_CDM_WIDEVINE_CDM_COMMON_H_
 #define WIDEVINE_CDM_WIDEVINE_CDM_COMMON_H_
 
-#include "media/media_features.h"
+#include "media/media_buildflags.h"
 
 // This file defines constants common to all Widevine CDM versions.
 
diff --git a/tools/android/adb_remote_setup.sh b/tools/android/adb_remote_setup.sh
index 06280fe..030f023f 100755
--- a/tools/android/adb_remote_setup.sh
+++ b/tools/android/adb_remote_setup.sh
@@ -63,8 +63,8 @@
 
 # Ensure local and remote versions of adb are the same.
 remote_adb_version=$(ssh "$remote_host" "$remote_adb version" \
-    | grep -v "^Revision")
-local_adb_version=$(adb version | grep -v "^Revision")
+    | grep -v -e "^Revision" -e "^Installed as")
+local_adb_version=$(adb version | grep -v -e "^Revision" -e "^Installed as")
 if [[ "$local_adb_version" != "$remote_adb_version" ]]; then
   echo >&2
   echo "WARNING: local adb is not the same version as remote adb." >&2
diff --git a/tools/binary_size/README.md b/tools/binary_size/README.md
index b7afdb12..8b9a87c 100644
--- a/tools/binary_size/README.md
+++ b/tools/binary_size/README.md
@@ -33,9 +33,15 @@
 ### Example Usage
 
 ``` bash
-# Build and diff HEAD^ and HEAD.
+# Build and diff monochrome_public_apk HEAD^ and HEAD.
 tools/binary_size/diagnose_bloat.py HEAD -v
 
+# Build and diff monochrome_apk HEAD^ and HEAD.
+tools/binary_size/diagnose_bloat.py HEAD --enable-chrome-android-internal -v
+
+# Build and diff monochrome_public_apk HEAD^ and HEAD without is_official_build.
+tools/binary_size/diagnose_bloat.py HEAD --gn-args="is_official_build=false" -v
+
 # Diff BEFORE_REV and AFTER_REV using build artifacts downloaded from perf bots.
 tools/binary_size/diagnose_bloat.py AFTER_REV --reference-rev BEFORE_REV --cloud -v
 
diff --git a/tools/binary_size/diagnose_bloat.py b/tools/binary_size/diagnose_bloat.py
index 815cf44..3b7cf22d 100755
--- a/tools/binary_size/diagnose_bloat.py
+++ b/tools/binary_size/diagnose_bloat.py
@@ -33,7 +33,6 @@
     os.path.join(os.path.dirname(__file__), os.pardir, os.pardir))
 _DEFAULT_ARCHIVE_DIR = os.path.join(_SRC_ROOT, 'out', 'binary-size-results')
 _DEFAULT_OUT_DIR = os.path.join(_SRC_ROOT, 'out', 'binary-size-build')
-_DEFAULT_ANDROID_TARGET = 'monochrome_public_apk'
 _BINARY_SIZE_DIR = os.path.join(_SRC_ROOT, 'tools', 'binary_size')
 _RESOURCE_SIZES_PATH = os.path.join(
     _SRC_ROOT, 'build', 'android', 'resource_sizes.py')
@@ -195,7 +194,7 @@
   def __init__(self, args):
     self.cloud = args.cloud
     self.enable_chrome_android_internal = args.enable_chrome_android_internal
-    self.extra_gn_args_str = ''
+    self.extra_gn_args_str = args.gn_args
     self.max_jobs = args.max_jobs
     self.max_load_average = args.max_load_average
     self.output_directory = args.output_directory
@@ -261,14 +260,24 @@
       self.max_jobs = '10000' if self.use_goma else '500'
 
     if os.path.exists(os.path.join(os.path.dirname(_SRC_ROOT), 'src-internal')):
-      self.extra_gn_args_str = ' is_chrome_branded=true'
+      self.extra_gn_args_str = (
+          'is_chrome_branded=true ' + self.extra_gn_args_str)
     else:
       self.extra_gn_args_str = (
-          ' ffmpeg_branding="Chrome" proprietary_codecs=true')
+          'ffmpeg_branding="Chrome" proprietary_codecs=true' +
+          self.extra_gn_args_str)
     if self.IsLinux():
-      self.extra_gn_args_str += (
-          ' is_cfi=false generate_linker_map=true')
-    self.target = self.target if self.IsAndroid() else 'chrome'
+      self.extra_gn_args_str = (
+          'is_cfi=false generate_linker_map=true ' + self.extra_gn_args_str)
+    self.extra_gn_args_str = ' ' + self.extra_gn_args_str.strip()
+
+    if not self.target:
+      if self.IsLinux():
+        self.target = 'chrome'
+      elif self.enable_chrome_android_internal:
+        self.target = 'monochrome_apk'
+      else:
+        self.target = 'monochrome_public_apk'
 
   def _GenGnCmd(self):
     gn_args = 'is_official_build=true'
@@ -568,7 +577,7 @@
   return retcode
 
 
-def _SyncAndBuild(archive, build, subrepo):
+def _SyncAndBuild(archive, build, subrepo, no_gclient):
   """Sync, build and return non 0 if any commands failed."""
   # Simply do a checkout if subrepo is used.
   retcode = 0
@@ -577,7 +586,7 @@
       logging.info('Skipping git checkout since already at desired rev')
     else:
       logging.info('Skipping gclient sync since already at desired rev')
-  elif subrepo != _SRC_ROOT:
+  elif subrepo != _SRC_ROOT or no_gclient:
     _GitCmd(['checkout',  archive.rev], subrepo)
   else:
     # Move to a detached state since gclient sync doesn't work with local
@@ -760,17 +769,20 @@
 
 def _SetRestoreFunc(subrepo):
   branch = _GitCmd(['rev-parse', '--abbrev-ref', 'HEAD'], subrepo)
-  atexit.register(lambda: _GitCmd(['checkout', branch], subrepo))
+  def _RestoreFunc():
+    logging.warning('Restoring original git checkout')
+    _GitCmd(['checkout', branch], subrepo)
+  atexit.register(_RestoreFunc)
 
 
 def main():
   parser = argparse.ArgumentParser(
       description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
+  parser.add_argument('rev',
+                      help='Find binary size bloat for this commit.')
   parser.add_argument('--archive-directory',
                       default=_DEFAULT_ARCHIVE_DIR,
                       help='Where results are stored.')
-  parser.add_argument('rev',
-                      help='Find binary size bloat for this commit.')
   parser.add_argument('--reference-rev',
                       help='Older rev to diff against. If not supplied, '
                            'the previous commit to rev will be used.')
@@ -797,10 +809,13 @@
                       help='Custom path to depot tools. Needed for --cloud if '
                            'depot tools isn\'t in your PATH.')
   parser.add_argument('--subrepo',
-                      help='Specify a subrepo directory to use. Gclient sync '
-                           'will be skipped if this option is used and all git '
-                           'commands will be executed from the subrepo '
-                           'directory. This option doesn\'t work with --cloud.')
+                      help='Specify a subrepo directory to use. Implies '
+                           '--no-gclient. All git commands will be executed '
+                           'from the subrepo directory. Does not work with '
+                           '--cloud.')
+  parser.add_argument('--no-gclient',
+                      action='store_true',
+                      help='Do not perform gclient sync steps.')
   parser.add_argument('-v',
                       '--verbose',
                       action='store_true',
@@ -823,6 +838,9 @@
   build_group.add_argument('--clean',
                            action='store_true',
                            help='Do a clean build for each revision.')
+  build_group.add_argument('--gn-args',
+                           default='',
+                           help='Extra GN args to set.')
   build_group.add_argument('--target-os',
                            default='android',
                            choices=['android', 'linux'],
@@ -835,9 +853,10 @@
                            action='store_true',
                            help='Allow downstream targets to be built.')
   build_group.add_argument('--target',
-                           default=_DEFAULT_ANDROID_TARGET,
-                           help='GN APK target to build. Ignored for Linux. '
-                                'Default %s.' % _DEFAULT_ANDROID_TARGET)
+                           help='GN target to build. Linux default: chrome. '
+                                'Android default: monochrome_public_apk or '
+                                'monochrome_apk (depending on '
+                                '--enable-chrome-android-internal)')
   if len(sys.argv) == 1:
     parser.print_help()
     sys.exit()
@@ -886,7 +905,8 @@
           _DownloadBuildArtifacts(
               archive, build, supersize_path, args.depot_tools_path)
         else:
-          build_failure = _SyncAndBuild(archive, build, subrepo)
+          build_failure = _SyncAndBuild(archive, build, subrepo,
+                                        args.no_gclient)
           if build_failure:
             logging.info(
                 'Build failed for %s, diffs using this rev will be skipped.',
diff --git a/tools/chrome_proxy/webdriver/client_config.py b/tools/chrome_proxy/webdriver/client_config.py
index cfe485a..79cdbe2d 100644
--- a/tools/chrome_proxy/webdriver/client_config.py
+++ b/tools/chrome_proxy/webdriver/client_config.py
@@ -30,6 +30,21 @@
         self.assertHasChromeProxyViaHeader(response)
         self.assertEqual(200, response.status)
 
+  # Ensure Chrome uses a direct connection when no valid client config is given.
+  def testNoClientConfigUseDirect(self):
+    with TestDriver() as t:
+      t.AddChromeArg('--enable-spdy-proxy-auth')
+      # The test server won't respond with a valid client config.
+      t.UseNetLog()
+      t.AddChromeArg('--data-reduction-proxy-config-url='
+        'https://chromeproxy-test.appspot.com')
+      t.SleepUntilHistogramHasEntry(
+        'DataReductionProxy.ConfigService.FetchResponseCode')
+      t.LoadURL('http://check.googlezip.net/test.html')
+      responses = t.GetHTTPResponses()
+      self.assertEqual(2, len(responses))
+      for response in responses:
+        self.assertNotHasChromeProxyViaHeader(response)
 
   # Ensure client config is fetched at the start of the Chrome session, and the
   # variations ID is set in the request.
@@ -93,4 +108,4 @@
       self.assertEqual(0, variation_header_count)
 
 if __name__ == '__main__':
-  IntegrationTest.RunAllTests()
\ No newline at end of file
+  IntegrationTest.RunAllTests()
diff --git a/tools/code_coverage/coverage.py b/tools/code_coverage/coverage.py
index c30c225..8bfdafe 100755
--- a/tools/code_coverage/coverage.py
+++ b/tools/code_coverage/coverage.py
@@ -816,6 +816,9 @@
 def _ExecuteCommand(target, command):
   """Runs a single command and generates a profraw data file."""
   # Per Clang "Source-based Code Coverage" doc:
+  #
+  # "%p" expands out to the process ID.
+  #
   # "%Nm" expands out to the instrumented binary's signature. When this pattern
   # is specified, the runtime creates a pool of N raw profiles which are used
   # for on-line profile merging. The runtime takes care of selecting a raw
@@ -824,10 +827,15 @@
   # N must be between 1 and 9. The merge pool specifier can only occur once per
   # filename pattern.
   #
-  # 4 is chosen because it creates some level of parallelism, but it's not too
-  # big to consume too much computing resource or disk space.
+  # "%p" is used when tests run in single process, however, it can't be used for
+  # multi-process because each process produces an intermediate dump, which may
+  # consume hundreds of gigabytes of disk space.
+  #
+  # For "%Nm", 4 is chosen because it creates some level of parallelism, but
+  # it's not too big to consume too much computing resource or disk space.
+  profile_pattern_string = '%p' if _IsFuzzerTarget(target) else '%4m'
   expected_profraw_file_name = os.extsep.join(
-      [target, '%4m', PROFRAW_FILE_EXTENSION])
+      [target, profile_pattern_string, PROFRAW_FILE_EXTENSION])
   expected_profraw_file_path = os.path.join(OUTPUT_DIR,
                                             expected_profraw_file_name)
 
@@ -842,6 +850,14 @@
   return output
 
 
+def _IsFuzzerTarget(target):
+  """Returns true if the target is a fuzzer target."""
+  build_args = _GetBuildArgs()
+  use_libfuzzer = ('use_libfuzzer' in build_args and
+                   build_args['use_libfuzzer'] == 'true')
+  return use_libfuzzer and target.endswith('_fuzzer')
+
+
 def _ExecuteIOSCommand(target, command):
   """Runs a single iOS command and generates a profraw data file.
 
diff --git a/tools/fuchsia/local-sdk.py b/tools/fuchsia/local-sdk.py
index cb3bb24..d9c842f4 100755
--- a/tools/fuchsia/local-sdk.py
+++ b/tools/fuchsia/local-sdk.py
@@ -34,13 +34,13 @@
 def BuildForArch(arch):
   Run('scripts/build-zircon.sh', '-t', arch)
   Run('build/gn/gen.py', '--target_cpu=' + arch,
-      '--packages=garnet/packages/sdk/base', '--release')
+      '--packages=garnet/packages/sdk', '--release')
   Run('buildtools/ninja', '-C', 'out/release-' + arch)
   # Also build the deprecated bootfs-based image.
   # TODO(crbug.com/805057): Remove this once the bootfs path is turned down.
   build_dir_bootfs = 'out/release-' + arch + '-bootfs'
   Run('build/gn/gen.py', '--target_cpu=' + arch,
-      '--packages=garnet/packages/sdk/bootfs', '--release',
+      '--packages=garnet/packages/sdk_bootfs', '--release',
       '--args=bootfs_packages=true',
       '--build-dir='+build_dir_bootfs)
   Run('buildtools/ninja', '-C', build_dir_bootfs)
diff --git a/tools/gritsettings/resource_ids b/tools/gritsettings/resource_ids
index 51e29e5..697409b 100644
--- a/tools/gritsettings/resource_ids
+++ b/tools/gritsettings/resource_ids
@@ -83,6 +83,9 @@
     "includes": [11000],
     "structures": [11470],
   },
+  "chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup_resources.grd": {
+    "structures": [11515],
+  },
   "chrome/browser/resources/component_extension_resources.grd": {
     "includes": [11560],
     "structures": [11810],
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 6dd7574..8bfb92d 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -175,7 +175,6 @@
       'Linux Builder Goma Canary': 'release_bot',
       'Linux x64 Goma Canary (clobber)': 'release_bot',
       'Linux x64 Goma Canary LocalOutputCache': 'release_bot',
-      'linux-gcc-rel': 'release_bot_x86_minimal_symbols_no_clang_cxx11',
 
       'mac-views-rel': 'mac_views_browser_release_bot',
       'Chromium Mac 10.11': 'release_bot',
@@ -347,6 +346,7 @@
       'Fuchsia x64 Cast Audio': 'release_bot_fuchsia_cast_audio',
       'Fuchsia x64': 'release_bot_fuchsia',
       'Ozone Linux': 'ozone_linux_release_bot',
+      'linux-gcc-rel': 'release_bot_x86_minimal_symbols_no_clang_cxx11',
     },
 
     'chromium.lkgr': {
@@ -480,7 +480,6 @@
 
     'chromium.webrtc': {
       'Linux Builder': 'release_bot_chrome_with_codecs',
-      'Linux Builder (Chromium w/o WebRTC)': 'release_bot_chrome_with_codecs_disable_webrtc',
       'Mac Builder': 'release_bot_chrome_with_codecs',
       'Win Builder': 'release_bot_x86_minimal_symbols_no_com_init_hooks_with_codecs',
     },
@@ -653,6 +652,7 @@
       'linux_site_isolation': 'release_trybot',
       'linux_upload_clang': 'release_bot',
       'linux_vr': 'vr_release_trybot',
+      'linux-gcc-rel': 'release_bot_x86_minimal_symbols_no_clang_cxx11',
     },
 
     'tryserver.chromium.mac': {
@@ -1273,7 +1273,7 @@
     'debug_bot_x86_minimal_symbols': [ 'debug_bot', 'x86', 'minimal_symbols' ],
 
     'debug_bot_x86_minimal_symbols_no_com_init_hooks_with_codecs': [
-      'debug_bot', 'x86', 'minimal_symbols', 'no_com_init_hooks', 'proprietary_codecs'
+      'debug_bot', 'x86', 'minimal_symbols', 'no_com_init_hooks', 'chrome_with_codecs'
     ],
 
     'debug_libfuzzer_asan': [
@@ -1522,10 +1522,6 @@
       'release_bot', 'chrome_with_codecs',
     ],
 
-    'release_bot_chrome_with_codecs_disable_webrtc': [
-      'release_bot', 'chrome_with_codecs', 'disable_webrtc',
-    ],
-
     'release_bot_enable_blink_heap_verification_dcheck_always_on': [
       'release_bot', 'enable_blink_heap_verification', 'dcheck_always_on',
     ],
@@ -1573,7 +1569,7 @@
     ],
 
     'release_bot_x86_minimal_symbols_no_com_init_hooks_with_codecs': [
-      'release_bot', 'x86', 'minimal_symbols', 'no_com_init_hooks', 'proprietary_codecs'
+      'release_bot', 'x86', 'minimal_symbols', 'no_com_init_hooks', 'chrome_with_codecs'
     ],
 
     # TODO(tikuta): Remove this once gcp goma backend supports all windows nacl compilers.
@@ -1581,8 +1577,6 @@
       'release_bot_x86_minimal_symbols_disable_nacl', 'no_clang'
     ],
 
-
-
     'release_libfuzzer_asan': [
       'release', 'libfuzzer', 'asan', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing',
     ],
@@ -1914,10 +1908,6 @@
       'gn_args': 'enable_nacl=false',
     },
 
-    'disable_webrtc': {
-      'gn_args': 'enable_webrtc=false',
-    },
-
     'edge': {
       'gn_args': 'sanitizer_coverage_flags="trace-pc-guard"',
     },
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 3dc60bc6..de99374 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -5003,6 +5003,13 @@
   </description>
 </action>
 
+<action name="FileBrowser.ClickBreadcrumbs">
+  <owner>joelhockey@chromium.org</owner>
+  <description>
+    User clicked the breadcrumbs in order to return to a parent directory.
+  </description>
+</action>
+
 <action name="FileBrowser.CreateNewFolder">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <description>Please enter the description of this user action.</description>
@@ -5662,6 +5669,7 @@
 </action>
 
 <action name="InProductHelp.NotifyEvent.IPH_ChromeHomeMenuHeader">
+  <obsolete>Unused as of 03/2018</obsolete>
   <owner>twellington@chromium.org</owner>
   <owner>mdjones@chromium.org</owner>
   <description>
@@ -5857,6 +5865,7 @@
 </action>
 
 <action name="InProductHelp.NotifyUsedEvent.IPH_ChromeHomeMenuHeader">
+  <obsolete>Unused as of 03/2018</obsolete>
   <owner>twellington@chromium.org</owner>
   <owner>mdjones@chromium.org</owner>
   <description>
@@ -6053,6 +6062,7 @@
 </action>
 
 <action name="InProductHelp.ShouldTriggerHelpUI.IPH_ChromeHomeMenuHeader">
+  <obsolete>Unused as of 03/2018</obsolete>
   <owner>twellington@chromium.org</owner>
   <owner>mdjones@chromium.org</owner>
   <description>
@@ -6288,6 +6298,7 @@
 
 <action
     name="InProductHelp.ShouldTriggerHelpUIResult.NotTriggered.IPH_ChromeHomeMenuHeader">
+  <obsolete>Unused as of 03/2018</obsolete>
   <owner>twellington@chromium.org</owner>
   <owner>mdjones@chromium.org</owner>
   <description>
@@ -6518,6 +6529,7 @@
 
 <action
     name="InProductHelp.ShouldTriggerHelpUIResult.Triggered.IPH_ChromeHomeMenuHeader">
+  <obsolete>Unused as of 03/2018</obsolete>
   <owner>twellington@chromium.org</owner>
   <owner>mdjones@chromium.org</owner>
   <description>
@@ -6729,6 +6741,7 @@
 
 <action
     name="InProductHelp.ShouldTriggerHelpUIResult.WouldHaveTriggered.IPH_ChromeHomeMenuHeader">
+  <obsolete>Unused as of 03/2018</obsolete>
   <owner>twellington@chromium.org</owner>
   <owner>mdjones@chromium.org</owner>
   <description>
@@ -18403,6 +18416,7 @@
 </action>
 
 <action name="StatusArea_TapDraggingDisabled">
+  <obsolete>Tap dragging removed from status area menu 03/2018.</obsolete>
   <owner>minch@chromium.org</owner>
   <description>
     Ash system menu: Accessibility: Disable tap dragging
@@ -18410,6 +18424,7 @@
 </action>
 
 <action name="StatusArea_TapDraggingEnabled">
+  <obsolete>Tap dragging removed from status area menu 03/2018.</obsolete>
   <owner>minch@chromium.org</owner>
   <description>Ash system menu: Accessibility: Enable tap dragging</description>
 </action>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index fffa971..1651e83e 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -2736,9 +2736,8 @@
 </enum>
 
 <enum name="BackingStoreResults">
-  <int value="0" label="Unused"/>
-  <int value="1" label="Success"/>
-  <int value="2" label="Failure"/>
+  <int value="0" label="Success"/>
+  <int value="1" label="Failure"/>
 </enum>
 
 <enum name="BadMessageReasonChrome">
@@ -17976,6 +17975,11 @@
   <int value="2390" label="VRDisplayGetFrameData"/>
   <int value="2391" label="XMLHttpRequestResponseXML"/>
   <int value="2392" label="MessagePortTransferClosedPort"/>
+  <int value="2393" label="RTCLocalSdpModification"/>
+  <int value="2394" label="KeyboardApiLock"/>
+  <int value="2395" label="KeyboardApiUnlock"/>
+  <int value="2396" label="PPAPIURLRequestStreamToFile"/>
+  <int value="2397" label="PaymentHandler"/>
 </enum>
 
 <enum name="FeedbackSource">
@@ -18852,6 +18856,19 @@
   <int value="6" label="Error"/>
 </enum>
 
+<enum name="FileManagerMenuCommands">
+  <int value="0" label="Help"/>
+  <int value="1" label="Help (In Google Drive)"/>
+  <int value="2" label="Buy more storage"/>
+  <int value="3" label="Go to drive.google.com"/>
+  <int value="4" label="Toggle show hidden files (Show)"/>
+  <int value="5" label="Toggle show hidden files (Hide)"/>
+  <int value="6" label="Toggle use mobile data for sync (on)"/>
+  <int value="7" label="Toggle use mobile data for sync (off)"/>
+  <int value="8" label="Toggle Show Google Docs files (on)"/>
+  <int value="9" label="Toggle Show Google Docs files (off)"/>
+</enum>
+
 <enum name="FileManagerQuickViewWayToOpen">
   <int value="0" label="Context menu"/>
   <int value="1" label="Space key"/>
@@ -25778,6 +25795,7 @@
       label="enable-loading-ipc-optimization-for-small-resources"/>
   <int value="-1844754731" label="Mash:disabled"/>
   <int value="-1839874877" label="WebXROrientationSensorDevice:enabled"/>
+  <int value="-1839637286" label="AutofillCreditCardBankNameDisplay:disabled"/>
   <int value="-1839496458" label="disable-file-manager-touch-mode"/>
   <int value="-1838482444" label="disable-settings-window"/>
   <int value="-1837329460" label="NewEncodeCpuLoadEstimator:enabled"/>
@@ -25924,6 +25942,7 @@
   <int value="-1480926949" label="MaterialDesignBookmarks:enabled"/>
   <int value="-1480866718" label="ash-disable-login-dim-and-blur"/>
   <int value="-1478876902" label="disable-permission-action-reporting"/>
+  <int value="-1477560322" label="kiosk"/>
   <int value="-1476930281" label="Windows10CustomTitlebar:enabled"/>
   <int value="-1473668019" label="token-binding:disabled"/>
   <int value="-1473136627" label="enable-web-payments"/>
@@ -26009,6 +26028,8 @@
   <int value="-1310737697" label="MaterialDesignSettings:enabled"/>
   <int value="-1302904242" label="enable-navigation-tracing"/>
   <int value="-1294050129" label="ContentFullscreen:disabled"/>
+  <int value="-1290053302"
+      label="OfflinePagesInDownloadHomeOpenInCct:disabled"/>
   <int value="-1289678848" label="SystemDownloadManager:enabled"/>
   <int value="-1288130734" label="OpenVR:disabled"/>
   <int value="-1287511172"
@@ -26031,6 +26052,7 @@
   <int value="-1246840031" label="OptInImeMenu:disabled"/>
   <int value="-1241747717" label="enable-android-password-link"/>
   <int value="-1235586511" label="enable-datasaver-prompt"/>
+  <int value="-1234740672" label="UsePdfCompositorServiceForPrint:disabled"/>
   <int value="-1225198073" label="ReaderModeInCCT:disabled"/>
   <int value="-1224962996" label="PwaImprovedSplashScreen:disabled"/>
   <int value="-1222805155" label="PdfIsolation:enabled"/>
@@ -26080,6 +26102,7 @@
   <int value="-1132704128" label="AndroidPaymentAppsFilter:disabled"/>
   <int value="-1127996427" label="enable-files-details-panel"/>
   <int value="-1126217973" label="IdleTimeSpellChecking:disabled"/>
+  <int value="-1125840399" label="ViewsBrowserWindows:enabled"/>
   <int value="-1125133283" label="disable-threaded-scrolling"/>
   <int value="-1121931029" label="DownloadsForeground:enabled"/>
   <int value="-1119700637" label="ui-disable-partial-swap"/>
@@ -26232,6 +26255,7 @@
   <int value="-759830869" label="enable-tab-discarding"/>
   <int value="-757946835"
       label="OmniboxUIExperimentShowSuggestionFavicons:enabled"/>
+  <int value="-751273871" label="AutofillCreditCardBankNameDisplay:enabled"/>
   <int value="-750175757" label="ClientLoFi:enabled"/>
   <int value="-749048160" label="enable-panels"/>
   <int value="-747463111" label="ContentSuggestionsNotifications:disabled"/>
@@ -26251,6 +26275,7 @@
   <int value="-711991950" label="SiteExplorationUi:enabled"/>
   <int value="-711890895" label="enable-website-settings-manager"/>
   <int value="-709058455" label="ui-slow-animations"/>
+  <int value="-707655322" label="Newblue:disabled"/>
   <int value="-706733351" label="enable-floating-virtual-keyboard:enabled"/>
   <int value="-704232562" label="UseMonitorColorSpace:enabled"/>
   <int value="-702477233" label="ContentFullscreen:enabled"/>
@@ -26447,6 +26472,7 @@
       label="NonValidatingReloadOnRefreshContentV2:disabled"/>
   <int value="-231922000" label="enable-renderer-mojo-channel"/>
   <int value="-230824955" label="NTPMostLikelyFaviconsFromServer:enabled"/>
+  <int value="-220599034" label="UsePdfCompositorServiceForPrint:enabled"/>
   <int value="-216219963" label="ash-shelf-color-scheme"/>
   <int value="-215534141" label="NativeWindowNavButtons:enabled"/>
   <int value="-213518852" label="protect-sync-credential:enabled"/>
@@ -26721,6 +26747,7 @@
   <int value="494733611" label="disable-drop-sync-credential"/>
   <int value="497137719" label="OmniboxVoiceSearchAlwaysVisible:disabled"/>
   <int value="501477022" label="DrawOcclusion:enabled"/>
+  <int value="503189154" label="ViewsBrowserWindows:disabled"/>
   <int value="503245473" label="disable-translate-new-ux"/>
   <int value="504994663" label="GenericSensor:disabled"/>
   <int value="506680761" label="WebNFC:disabled"/>
@@ -26869,6 +26896,7 @@
   <int value="867512869" label="mark-non-secure-as"/>
   <int value="869531646" label="enable-session-crashed-bubble"/>
   <int value="871713352" label="ImprovedLanguageSettings:enabled"/>
+  <int value="876879670" label="OfflinePagesInDownloadHomeOpenInCct:enabled"/>
   <int value="878773995" label="ChromeHomeBottomNavLabels:disabled"/>
   <int value="879699575" label="disable-gesture-tap-highlight"/>
   <int value="879992337" label="disable-pull-to-refresh-effect"/>
@@ -27268,6 +27296,7 @@
   <int value="1838990777" label="V8Future:enabled"/>
   <int value="1839740266" label="LocationHardReload:disabled"/>
   <int value="1844110073" label="enable-app-view"/>
+  <int value="1845131710" label="Newblue:enabled"/>
   <int value="1847024354" label="enable-hotword-hardware"/>
   <int value="1849379463" label="OfflinePagesCTV2:enabled"/>
   <int value="1851358497" label="enable-ash-sidebar"/>
@@ -30309,6 +30338,35 @@
   <int value="1" label="Connection tester"/>
 </enum>
 
+<enum name="NetNetworkErrorLoggingHeaderOutcome">
+  <int value="0" label="Discarded: no NetworkErrorLoggingService"/>
+  <int value="1" label="Discarded: invalid SSLInfo"/>
+  <int value="2" label="Discarded: cert status error"/>
+  <int value="3" label="Discarded: insecure origin"/>
+  <int value="4" label="Discarded: JSON too big"/>
+  <int value="5" label="Discarded: JSON invalid"/>
+  <int value="6" label="Discarded: not a dictionary"/>
+  <int value="7" label="Discarded: TTL missing"/>
+  <int value="8" label="Discarded: TTL not an integer"/>
+  <int value="9" label="Discarded: TTL negative"/>
+  <int value="10" label="Discarded: report-to missing"/>
+  <int value="11" label="Discarded: report-to not a string"/>
+  <int value="12" label="Removed (max-age = 0)"/>
+  <int value="13" label="Set (max-age &gt; 0)"/>
+</enum>
+
+<enum name="NetNetworkErrorLoggingRequestOutcome">
+  <int value="0" label="Discarded: no NetworkErrorLoggingService"/>
+  <int value="1" label="Discarded: no ReportingService"/>
+  <int value="2" label="Discarded: insecure origin"/>
+  <int value="3" label="Discarded: no origin policy"/>
+  <int value="4" label="Discarded: unmapped error"/>
+  <int value="5" label="Discarded: Reporting upload"/>
+  <int value="6" label="Discarded: unsampled success"/>
+  <int value="7" label="Discarded: unsampled failure"/>
+  <int value="8" label="Queued"/>
+</enum>
+
 <enum name="NetPreconnectUtilization">
   <int value="0" label="non-speculative, never connected"/>
   <int value="1" label="non-speculative, never used"/>
@@ -42021,6 +42079,20 @@
   <int value="1" label="Leave the current page"/>
 </enum>
 
+<enum name="StreamParserBufferDurationType">
+  <summary>
+    MSE parsing of WebM buffers may require estimating the duration. &quot;Known
+    duration&quot; indicates no estimation was needed. &quot;Constant
+    estimate&quot; indicates the estimate uses the constant duration observed
+    from other buffers in the track. &quot;Rough estimate&quot; indicates the
+    track's durations vary and estimation is performed using a min or max of
+    observed durations.
+  </summary>
+  <int value="0" label="Known duration"/>
+  <int value="1" label="Constant estimate"/>
+  <int value="2" label="Rough estimate"/>
+</enum>
+
 <enum name="StrongPopupBlockerAction">
   <int value="0" label="Navigation commit"/>
   <int value="1" label="Commit warn site"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index d665ed0ef..1a5cb805 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -26837,6 +26837,13 @@
   </summary>
 </histogram>
 
+<histogram name="FileBrowser.MenuItemSelected" enum="FileManagerMenuCommands">
+  <owner>sashab@chromium.org</owner>
+  <summary>
+    Chrome OS Files App: The commands selected in the menu by the files app.
+  </summary>
+</histogram>
+
 <histogram name="FileBrowser.OpenFiles.RootType" enum="FileManagerRootType">
   <owner>fukino@chromium.org</owner>
   <summary>
@@ -28597,6 +28604,15 @@
   <summary>What type of swapchain was actually created for an overlay.</summary>
 </histogram>
 
+<histogram name="GPU.DisplayCompositorLifetimeEvents"
+    enum="GPUProcessLifetimeEvent">
+  <owner>mohsen@chromium.org</owner>
+  <summary>
+    Counts of the number of gpu process crashes when it only has display
+    compositor (no hardware acceleration and software compositing).
+  </summary>
+</histogram>
+
 <histogram name="GPU.DisplayLinkInstallationStatus"
     enum="DisplayLinkInstallationStatus">
   <obsolete>
@@ -36120,6 +36136,15 @@
   </summary>
 </histogram>
 
+<histogram name="Media.MSE.AudioSpliceDurationType"
+    enum="StreamParserBufferDurationType">
+  <owner>chcunningham@chromium.org</owner>
+  <summary>
+    Categorizes MSE audio splicing by the type of duration used in the
+    overlapped buffer.
+  </summary>
+</histogram>
+
 <histogram name="Media.MSE.DemuxerDestructionTime" units="ms">
   <owner>wolenetz@chromium.org</owner>
   <summary>
@@ -38806,12 +38831,8 @@
 </histogram>
 
 <histogram name="Memory.ExtensionProcessCount" units="processes">
-  <obsolete>
-    Deprecated 03/2018. No direct replacement.
-  </obsolete>
-  <owner>hajimehoshi@chromium.org</owner>
-  <owner>kenjibaheux@google.com</owner>
-  <owner>kouhei@chromium.org</owner>
+  <owner>creis@chromium.org</owner>
+  <owner>nasko@chromium.org</owner>
   <summary>
     The count of active extension processes.  Recorded once per UMA ping.
   </summary>
@@ -39135,12 +39156,8 @@
 </histogram>
 
 <histogram name="Memory.ProcessCount" units="processes">
-  <obsolete>
-    Deprecated 03/2018. No direct replacement.
-  </obsolete>
-  <owner>hajimehoshi@chromium.org</owner>
-  <owner>kenjibaheux@google.com</owner>
-  <owner>kouhei@chromium.org</owner>
+  <owner>creis@chromium.org</owner>
+  <owner>nasko@chromium.org</owner>
   <summary>
     The count of all active processes.  Recorded once per UMA ping.
   </summary>
@@ -39273,12 +39290,8 @@
 </histogram>
 
 <histogram name="Memory.RendererProcessCount" units="processes">
-  <obsolete>
-    Deprecated 03/2018. No direct replacement.
-  </obsolete>
-  <owner>hajimehoshi@chromium.org</owner>
-  <owner>kenjibaheux@google.com</owner>
-  <owner>kouhei@chromium.org</owner>
+  <owner>creis@chromium.org</owner>
+  <owner>nasko@chromium.org</owner>
   <summary>
     The count of active renderer processes.  Recorded once per UMA ping.
   </summary>
@@ -46081,6 +46094,26 @@
   </summary>
 </histogram>
 
+<histogram name="Net.NetworkErrorLogging.HeaderOutcome"
+    enum="NetNetworkErrorLoggingHeaderOutcome">
+  <owner>juliatuttle@chromium.org</owner>
+  <summary>
+    When Network Error Logging receives a &quot;NEL:&quot; header, what happens
+    to it.
+  </summary>
+</histogram>
+
+<histogram name="Net.NetworkErrorLogging.RequestOutcome"
+    enum="NetNetworkErrorLoggingRequestOutcome">
+  <owner>juliatuttle@chromium.org</owner>
+  <summary>
+    When Network Error Logging observes a completed request that might generate
+    a report, what happens to it. NEL observes all requests, since it can send
+    reports for a fraction of successful requests as well so error rates can be
+    calculated.
+  </summary>
+</histogram>
+
 <histogram name="Net.NetworkErrorsRecovered.MainFrame" enum="NetErrorCodes">
   <obsolete>
     Deprecated 04/2016 as doesn't have data nor owner.
@@ -108033,7 +108066,11 @@
       label="In product help for Chrome Home shown on cold start."/>
   <suffix name="IPH_ChromeHomeMenuHeader"
       label="In product help for Chrome Home shown as a header in the app
-             menu."/>
+             menu.">
+    <obsolete>
+      Unused as of 03/2018
+    </obsolete>
+  </suffix>
   <suffix name="IPH_ChromeHomePullToRefresh"
       label="In product help for Chrome Home shown after a pull-to-refresh."/>
   <suffix name="IPH_DataSaverPreview"
@@ -113588,6 +113625,10 @@
       label="Time spent in tasks of a particular type starting from the sixth
              minute after backgrounding the renderer. The renderer is
              expected to be mostly idle during this period."/>
+  <suffix name="Background.KeepAlive.AfterFifthMinute"
+      label="Time spent in tasks of a particular type starting from the sixth
+             minute after backgrounding the renderer when keep-alive signal
+             is present."/>
   <suffix name="Foreground"
       label="Time spent in tasks of a particular type when the renderer is in
              the foreground. Please note that individual tabs in this
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml
index 472749c..6fcd1e6 100644
--- a/tools/metrics/ukm/ukm.xml
+++ b/tools/metrics/ukm/ukm.xml
@@ -429,6 +429,13 @@
       not recorded if there was no subsequent scroll.
     </summary>
   </metric>
+  <metric name="FontSize">
+    <summary>
+      Emits a value from 0-10 representing the effective font size on the
+      screen.  A value of 0 means the font size cannot be obtained.  A value of
+      1 represents a very small font and a value of 10 represents a large font.
+    </summary>
+  </metric>
   <metric name="IsEntity">
     <summary>
       Emits a 1 or 0 to indicate whether the word tapped appears to be part of
@@ -514,6 +521,15 @@
       caption within the overlay panel.  This is a tertiary outcome metric.
     </summary>
   </metric>
+  <metric name="PortionOfElement">
+    <summary>
+      Emits an integer in the range 0-10 inclusive that expresses the portion of
+      the enclosing element that is the word tapped.  A zero will be emitted if
+      the ratio cannot be calculated. A value of 10 means the word spans the
+      entire element, and a value of 1 means the word is 10% or less than the
+      entire element.
+    </summary>
+  </metric>
   <metric name="Previous28DayCtrPercent">
     <summary>
       The CTR of the overlay panel for this user, aggregated over a previous 28
diff --git a/tools/perf/benchmark.csv b/tools/perf/benchmark.csv
index a4c46a4..3122719 100644
--- a/tools/perf/benchmark.csv
+++ b/tools/perf/benchmark.csv
@@ -6,7 +6,7 @@
 battor.trivial_pages,charliea@chromium.org,
 blink_perf.bindings,"jbroman@chromium.org, yukishiino@chromium.org, haraken@chromium.org",
 blink_perf.canvas,junov@chromium.org,
-blink_perf.css,rune@opera.com,
+blink_perf.css,futhark@chromium.org,
 blink_perf.dom,"jbroman@chromium.org, yukishiino@chromium.org, haraken@chromium.org",
 blink_perf.events,hayato@chromium.org,
 blink_perf.image_decoder,cblume@chromium.org,
diff --git a/tools/perf/benchmarks/blink_perf.py b/tools/perf/benchmarks/blink_perf.py
index 63864c8..510a60b 100644
--- a/tools/perf/benchmarks/blink_perf.py
+++ b/tools/perf/benchmarks/blink_perf.py
@@ -230,6 +230,7 @@
                            'blink_perf.js'), 'r') as f:
       self._blink_perf_js = f.read()
     self._extra_chrome_categories = None
+    self._enable_systrace = None
 
   def WillNavigateToPage(self, page, tab):
     del tab  # unused
@@ -249,6 +250,8 @@
       options.AppendExtraBrowserArgs('--expose-internals-for-testing')
     if options.extra_chrome_categories:
       self._extra_chrome_categories = options.extra_chrome_categories
+    if options.enable_systrace:
+      self._enable_systrace = True
 
   def _ContinueTestRunWithTracing(self, tab):
     tracing_categories = tab.EvaluateJavaScript(
@@ -262,6 +265,8 @@
     if self._extra_chrome_categories:
       config.chrome_trace_config.category_filter.AddFilterString(
           self._extra_chrome_categories)
+    if self._enable_systrace:
+      config.chrome_trace_config.SetEnableSystrace()
     tab.browser.platform.tracing_controller.StartTracing(config)
     tab.EvaluateJavaScript('testRunner.scheduleTestRun()')
     tab.WaitForJavaScriptCondition('testRunner.isDone')
@@ -355,7 +360,7 @@
   tag = 'bindings'
   subdir = 'Bindings'
 
-@benchmark.Owner(emails=['rune@opera.com'])
+@benchmark.Owner(emails=['futhark@chromium.org'])
 class BlinkPerfCSS(_BlinkPerfBenchmark):
   tag = 'css'
   subdir = 'CSS'
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py
index d4f7169..d0c2b5bf 100755
--- a/tools/perf/core/perf_data_generator.py
+++ b/tools/perf/core/perf_data_generator.py
@@ -508,8 +508,9 @@
          ('load_library_perf_tests', 'build29-a9'),
          ('net_perftests', 'build29-a9'),
          ('tracing_perftests', 'build29-a9'),
-         ('media_perftests', 'build30-a9'),
-         ('views_perftests', 'build31-a9')
+         ('media_perftests', 'build30-a9')
+         # crbug.com/811766
+         # ('views_perftests', 'build31-a9')
        ]
       }
     ])
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config
index 66ebed8..ea0d20a3 100644
--- a/tools/perf/expectations.config
+++ b/tools/perf/expectations.config
@@ -36,6 +36,9 @@
 crbug.com/799540 [ Nexus_5 ] blink_perf.paint/* [ Skip ]
 crbug.com/799540 [ Nexus_7 ] blink_perf.paint/* [ Skip ]
 
+# Benchmark: blink_perf.owp_storage
+crbug.com/823357 [ Android_One ] blink_perf.owp_storage/blob-perf-shm.html [ Skip ]
+
 # Benchmark: blink_perf.parser
 crbug.com/796115 [ Android_One ] blink_perf.parser/html5-full-render.html [ Skip ]
 
@@ -189,6 +192,7 @@
 crbug.com/785286 [ Android_Webview ] smoothness.tough_canvas_cases/http://www.smashcat.org/av/canvas_test/ [ Skip ]
 crbug.com/785286 [ Android_Webview ] smoothness.tough_canvas_cases/http://www.effectgames.com/demos/canvascycle/ [ Skip ]
 crbug.com/364248 [ Nexus_5 ] smoothness.tough_canvas_cases/http://geoapis.appspot.com/agdnZW9hcGlzchMLEgtFeGFtcGxlQ29kZRjh1wIM [ Skip ]
+crbug.com/825234 [ Android_Webview ] smoothness.tough_canvas_cases/tough_canvas_cases/canvas2d_balls_common/bouncing_balls.html?ball=image_with_shadow&back=image [ Skip ]
 
 # Benchmark: smoothness.tough_pinch_zoom_cases
 crbug.com/822925 [ Android_Webview ] smoothness.tough_pinch_zoom_cases/http://games.yahoo.com [ Skip ]
diff --git a/tools/perf/measurements/smoothness.py b/tools/perf/measurements/smoothness.py
index d96c716..84721185 100644
--- a/tools/perf/measurements/smoothness.py
+++ b/tools/perf/measurements/smoothness.py
@@ -53,6 +53,8 @@
     if self.options and self.options.extra_chrome_categories:
       config.chrome_trace_config.category_filter.AddFilterString(
           self.options.extra_chrome_categories)
+    if self.options and self.options.enable_systrace:
+      config.chrome_trace_config.SetEnableSystrace()
 
     tab.browser.platform.tracing_controller.StartTracing(config)
 
diff --git a/tools/perf/measurements/thread_times.py b/tools/perf/measurements/thread_times.py
index dac37934..a1aec61e 100644
--- a/tools/perf/measurements/thread_times.py
+++ b/tools/perf/measurements/thread_times.py
@@ -29,6 +29,8 @@
       category_filter = chrome_trace_category_filter.CreateLowOverheadFilter()
       if self.options and self.options.extra_chrome_categories:
         category_filter.AddFilterString(self.options.extra_chrome_categories)
+      if self.options and self.options.enable_systrace:
+        self._timeline_controller.enable_systrace = True
       self._timeline_controller.trace_categories = category_filter.filter_string
     self._timeline_controller.SetUp(page, tab)
 
diff --git a/tools/perf/measurements/timeline_controller.py b/tools/perf/measurements/timeline_controller.py
index 6b25d2340..98c4c61 100644
--- a/tools/perf/measurements/timeline_controller.py
+++ b/tools/perf/measurements/timeline_controller.py
@@ -18,6 +18,7 @@
   def __init__(self, enable_auto_issuing_record=True):
     super(TimelineController, self).__init__()
     self.trace_categories = None
+    self.enable_systrace = False
     self._model = None
     self._renderer_process = None
     self._smooth_records = []
@@ -37,6 +38,8 @@
     config = tracing_config.TracingConfig()
     config.chrome_trace_config.category_filter.AddFilterString(
         self.trace_categories)
+    if self.enable_systrace:
+      config.chrome_trace_config.SetEnableSystrace()
     config.enable_chrome_trace = True
     tab.browser.platform.tracing_controller.StartTracing(config)
 
diff --git a/tools/perf/page_sets/key_mobile_sites_smooth.py b/tools/perf/page_sets/key_mobile_sites_smooth.py
index 5fbb5d7..3f2996c3 100644
--- a/tools/perf/page_sets/key_mobile_sites_smooth.py
+++ b/tools/perf/page_sets/key_mobile_sites_smooth.py
@@ -6,6 +6,87 @@
 from telemetry import story
 
 
+FASTPATH_URLS = [
+    # Why: Top news site.
+    ('http://nytimes.com/', 'nytimes'),
+    # Why: Image-heavy site.
+    ('http://cuteoverload.com', 'cuteoverload'),
+    # Why: #5 Alexa news.
+    ('http://www.reddit.com/r/programming/comments/1g96ve', 'reddit'),
+    # Why: Problematic use of fixed position elements.
+    ('http://www.boingboing.net', 'boingboing'),
+    # Why: crbug.com/169827
+    ('http://slashdot.org', 'slashdot'),
+]
+
+
+URLS_LIST = [
+    # Why: #11 (Alexa global), google property; some blogger layouts
+    # have infinite scroll but more interesting.
+    ('http://googlewebmastercentral.blogspot.com/', 'blogspot'),
+    # Why: #18 (Alexa global), Picked an interesting post
+    ('http://en.blog.wordpress.com/2012/09/04/freshly-pressed-editors-picks-for-august-2012/',
+     'wordpress'),
+    # Why: #6 (Alexa) most visited worldwide, picked an interesting page
+    ('http://en.wikipedia.org/wiki/Wikipedia', 'wikipedia'),
+    # Why: #8 (Alexa global), picked an interesting page
+    ('http://twitter.com/katyperry', 'twitter'),
+    # Why: #37 (Alexa global).
+    ('http://pinterest.com', 'pinterest'),
+    # Why: #1 sports.
+    ('http://espn.go.com', 'espn'),
+    # Why: crbug.com/231413
+    ('http://forecast.io', 'forecast.io'),
+    # Why: Social; top Google property; Public profile; infinite scrolls.
+    ('https://plus.google.com/app/basic/110031535020051778989/posts?source=apppromo',
+     'google_plus'),
+    # Why: crbug.com/242544
+    # pylint: disable=line-too-long
+    ('http://www.androidpolice.com/2012/10/03/rumor-evidence-mounts-that-an-lg-optimus-g-nexus-is-coming-along-with-a-nexus-phone-certification-program/',
+     'androidpolice'),
+    # Why: crbug.com/149958
+    ('http://gsp.ro', 'gsp.ro'),
+    # Why: Top tech blog
+    ('http://theverge.com', 'theverge'),
+    # Why: Top tech site
+    ('http://digg.com', 'digg'),
+    # Why: Top Google property; a Google tab is often open
+    ('https://www.google.co.uk/search?hl=en&q=barack+obama&cad=h',
+     'google_web_search'),
+    # Why: #1 news worldwide (Alexa global)
+    ('http://news.yahoo.com', 'yahoo_news'),
+    # Why: #2 news worldwide
+    ('http://www.cnn.com', 'cnn'),
+    # Why: #1 commerce website by time spent by users in US
+    ('http://shop.mobileweb.ebay.com/searchresults?kw=viking+helmet', 'ebay'),
+    # Why: #1 Alexa recreation
+    # pylint: disable=line-too-long
+    ('http://www.booking.com/searchresults.html?src=searchresults&latitude=65.0500&longitude=25.4667',
+     'booking.com'),
+    # Why: Top tech blog
+    ('http://techcrunch.com', 'techcrunch'),
+    # Why: #6 Alexa sports
+    ('http://mlb.com/', 'mlb'),
+    # Why: #14 Alexa California
+    ('http://www.sfgate.com/', 'sfgate'),
+    # Why: Non-latin character set
+    ('http://worldjournal.com/', 'worldjournal'),
+    # Why: #15 Alexa news
+    ('http://online.wsj.com/home-page', 'wsj'),
+    # Why: Image-heavy mobile site
+    ('http://www.deviantart.com/', 'deviantart'),
+    # Why: Top search engine
+    # pylint: disable=line-too-long
+    ('http://www.baidu.com/s?wd=barack+obama&rsv_bp=0&rsv_spt=3&rsv_sug3=9&rsv_sug=0&rsv_sug4=3824&rsv_sug1=3&inputT=4920',
+     'baidu'),
+    # Why: Top search engine
+    ('http://www.bing.com/search?q=sloths', 'bing'),
+    # Why: Good example of poor initial scrolling
+    ('http://ftw.usatoday.com/2014/05/spelling-bee-rules-shenanigans',
+     'usatoday'),
+]
+
+
 def _IssueMarkerAndScroll(action_runner):
   with action_runner.CreateGestureInteraction('ScrollAction'):
     action_runner.ScrollPage()
@@ -281,39 +362,27 @@
     super(WowwikiPage, self).RunNavigateSteps(action_runner)
 
 
+PREDEFINED_PAGE_CLASSES = [
+    (CapitolVolkswagenPage, 'capitolvolkswagen'),
+    (TheVergeArticlePage, 'theverge_article'),
+    (FacebookPage, 'facebook'),
+    (YoutubeMobilePage, 'youtube'),
+    (YahooAnswersPage, 'yahoo_answers'),
+    (GoogleNewsMobilePage, 'google_news'),
+    (LinkedInPage, 'linkedin'),
+    (WowwikiPage, 'wowwiki'),
+    (AmazonNicolasCagePage, 'amazon'),
+    (CnnArticlePage, 'cnn_article'),
+]
+
+
 def AddPagesToPageSet(page_set):
   # Add pages with predefined classes that contain custom navigation logic.
-  predefined_page_classes = [
-      (CapitolVolkswagenPage, 'capitolvolkswagen'),
-      (TheVergeArticlePage, 'theverge_article'),
-      (FacebookPage, 'facebook'),
-      (YoutubeMobilePage, 'youtube'),
-      (YahooAnswersPage, 'yahoo_answers'),
-      (GoogleNewsMobilePage, 'google_news'),
-      (LinkedInPage, 'linkedin'),
-      (WowwikiPage, 'wowwiki'),
-      (AmazonNicolasCagePage, 'amazon'),
-      (CnnArticlePage, 'cnn_article'),
-  ]
-
-  for page_class, page_name in predefined_page_classes:
+  for page_class, page_name in PREDEFINED_PAGE_CLASSES:
     page_set.AddStory(page_class(page_set=page_set, name=page_name))
 
   # Add pages with custom tags.
-  fastpath_urls = [
-      # Why: Top news site.
-      ('http://nytimes.com/', 'nytimes'),
-      # Why: Image-heavy site.
-      ('http://cuteoverload.com', 'cuteoverload'),
-      # Why: #5 Alexa news.
-      ('http://www.reddit.com/r/programming/comments/1g96ve', 'reddit'),
-      # Why: Problematic use of fixed position elements.
-      ('http://www.boingboing.net', 'boingboing'),
-      # Why: crbug.com/169827
-      ('http://slashdot.org', 'slashdot'),
-  ]
-
-  for page_url, page_name in fastpath_urls:
+  for page_url, page_name in FASTPATH_URLS:
     page_set.AddStory(
         KeyMobileSitesSmoothPage(
             url=page_url, page_set=page_set, name=page_name, tags=['fastpath']))
@@ -327,73 +396,7 @@
           action_on_load_complete=True))
 
   # Add simple pages with no custom navigation logic or tags.
-  urls_list = [
-      # Why: #11 (Alexa global), google property; some blogger layouts
-      # have infinite scroll but more interesting.
-      ('http://googlewebmastercentral.blogspot.com/', 'blogspot'),
-      # Why: #18 (Alexa global), Picked an interesting post
-      ('http://en.blog.wordpress.com/2012/09/04/freshly-pressed-editors-picks-for-august-2012/',
-       'wordpress'),
-      # Why: #6 (Alexa) most visited worldwide, picked an interesting page
-      ('http://en.wikipedia.org/wiki/Wikipedia', 'wikipedia'),
-      # Why: #8 (Alexa global), picked an interesting page
-      ('http://twitter.com/katyperry', 'twitter'),
-      # Why: #37 (Alexa global).
-      ('http://pinterest.com', 'pinterest'),
-      # Why: #1 sports.
-      ('http://espn.go.com', 'espn'),
-      # Why: crbug.com/231413
-      ('http://forecast.io', 'forecast.io'),
-      # Why: Social; top Google property; Public profile; infinite scrolls.
-      ('https://plus.google.com/app/basic/110031535020051778989/posts?source=apppromo',
-       'google_plus'),
-      # Why: crbug.com/242544
-      # pylint: disable=line-too-long
-      ('http://www.androidpolice.com/2012/10/03/rumor-evidence-mounts-that-an-lg-optimus-g-nexus-is-coming-along-with-a-nexus-phone-certification-program/',
-       'androidpolice'),
-      # Why: crbug.com/149958
-      ('http://gsp.ro', 'gsp.ro'),
-      # Why: Top tech blog
-      ('http://theverge.com', 'theverge'),
-      # Why: Top tech site
-      ('http://digg.com', 'digg'),
-      # Why: Top Google property; a Google tab is often open
-      ('https://www.google.co.uk/search?hl=en&q=barack+obama&cad=h',
-       'google_web_search'),
-      # Why: #1 news worldwide (Alexa global)
-      ('http://news.yahoo.com', 'yahoo_news'),
-      # Why: #2 news worldwide
-      ('http://www.cnn.com', 'cnn'),
-      # Why: #1 commerce website by time spent by users in US
-      ('http://shop.mobileweb.ebay.com/searchresults?kw=viking+helmet', 'ebay'),
-      # Why: #1 Alexa recreation
-      # pylint: disable=line-too-long
-      ('http://www.booking.com/searchresults.html?src=searchresults&latitude=65.0500&longitude=25.4667',
-       'booking.com'),
-      # Why: Top tech blog
-      ('http://techcrunch.com', 'techcrunch'),
-      # Why: #6 Alexa sports
-      ('http://mlb.com/', 'mlb'),
-      # Why: #14 Alexa California
-      ('http://www.sfgate.com/', 'sfgate'),
-      # Why: Non-latin character set
-      ('http://worldjournal.com/', 'worldjournal'),
-      # Why: #15 Alexa news
-      ('http://online.wsj.com/home-page', 'wsj'),
-      # Why: Image-heavy mobile site
-      ('http://www.deviantart.com/', 'deviantart'),
-      # Why: Top search engine
-      # pylint: disable=line-too-long
-      ('http://www.baidu.com/s?wd=barack+obama&rsv_bp=0&rsv_spt=3&rsv_sug3=9&rsv_sug=0&rsv_sug4=3824&rsv_sug1=3&inputT=4920',
-       'baidu'),
-      # Why: Top search engine
-      ('http://www.bing.com/search?q=sloths', 'bing'),
-      # Why: Good example of poor initial scrolling
-      ('http://ftw.usatoday.com/2014/05/spelling-bee-rules-shenanigans',
-       'usatoday'),
-  ]
-
-  for page_url, page_name in urls_list:
+  for page_url, page_name in URLS_LIST:
     page_set.AddStory(
         KeyMobileSitesSmoothPage(
             url=page_url, page_set=page_set, name=page_name))
diff --git a/tools/translation/testdata/part_grdp/IDS_PART_STRING2.png b/tools/translation/testdata/part_grdp/IDS_PART_STRING2.png
new file mode 100644
index 0000000..b33ff0c8
--- /dev/null
+++ b/tools/translation/testdata/part_grdp/IDS_PART_STRING2.png
Binary files differ
diff --git a/tools/translation/upload_screenshots.py b/tools/translation/upload_screenshots.py
index 78d93c6..926ea61 100755
--- a/tools/translation/upload_screenshots.py
+++ b/tools/translation/upload_screenshots.py
@@ -40,8 +40,8 @@
                                              'translation_expectations.pyl')
 
 # URL of the bucket used for storing screenshots.
-BUCKET_URL = 'gs://chrome-screenshots'
-
+# This is writable by @google.com accounts, readable by everyone.
+BUCKET_URL = 'gs://chromium-translation-screenshots'
 
 
 def query_yes_no(question, default='yes'):
@@ -97,12 +97,20 @@
 
 
 def find_screenshots(repo_root, translation_expectations):
-  grd_files = translation_helper.get_translatable_grds(
+  """Returns a list of translation related .png files in the repository."""
+  translatable_grds = translation_helper.get_translatable_grds(
       repo_root, list_grds_in_repository(repo_root), translation_expectations)
 
+  # Add the paths of grds and any files they include. This includes grdp files
+  # and files included via <structure> elements.
+  src_paths = []
+  for grd in translatable_grds:
+    src_paths.append(grd.path)
+    src_paths.extend(grd.grdp_paths)
+    src_paths.extend(grd.structure_paths)
+
   screenshots = []
-  for grd_file in grd_files:
-    grd_path = grd_file.path
+  for grd_path in src_paths:
     # Convert grd_path.grd to grd_path_grd/ directory.
     name, ext = os.path.splitext(os.path.basename(grd_path))
     relative_screenshots_dir = os.path.relpath(
@@ -141,6 +149,7 @@
                                               TRANSLATION_EXPECTATIONS_PATH))
   if not screenshots:
     print 'No screenshots found, exiting.'
+    exit(0)
 
   print 'Found %d updated screenshot(s): ' % len(screenshots)
   for s in screenshots:
diff --git a/tools/translation/upload_screenshots_unittest.py b/tools/translation/upload_screenshots_unittest.py
index 3235e3a..99b9695 100755
--- a/tools/translation/upload_screenshots_unittest.py
+++ b/tools/translation/upload_screenshots_unittest.py
@@ -19,10 +19,13 @@
     screenshots = upload_screenshots.find_screenshots(
         testdata_path,
         os.path.join(testdata_path, 'translation_expectations.pyl'))
-    self.assertEquals(1, len(screenshots))
+    self.assertEquals(2, len(screenshots))
     self.assertEquals(
         os.path.join(testdata_path, 'test_grd', 'IDS_TEST_STRING1.png'),
         screenshots[0])
+    self.assertEquals(
+        os.path.join(testdata_path, 'part_grdp', 'IDS_PART_STRING2.png'),
+        screenshots[1])
 
 
 if __name__ == '__main__':
diff --git a/ui/android/delegated_frame_host_android.cc b/ui/android/delegated_frame_host_android.cc
index 71ea29c..6bbbd4c 100644
--- a/ui/android/delegated_frame_host_android.cc
+++ b/ui/android/delegated_frame_host_android.cc
@@ -37,6 +37,7 @@
   layer->SetBounds(surface_info.size_in_pixels());
   layer->SetIsDrawable(true);
   layer->SetContentsOpaque(surface_opaque);
+  layer->SetHitTestable(true);
 
   return layer;
 }
diff --git a/ui/android/java/src/org/chromium/ui/DropdownPopupWindow.java b/ui/android/java/src/org/chromium/ui/DropdownPopupWindow.java
index d261ff2..f93877eb 100644
--- a/ui/android/java/src/org/chromium/ui/DropdownPopupWindow.java
+++ b/ui/android/java/src/org/chromium/ui/DropdownPopupWindow.java
@@ -82,7 +82,6 @@
         mHorizontalPadding = paddingRect.right + paddingRect.left;
         mAnchoredPopupWindow.setPreferredHorizontalOrientation(
                 AnchoredPopupWindow.HORIZONTAL_ORIENTATION_CENTER);
-        mAnchoredPopupWindow.setFocusable(true);
     }
 
     /**
diff --git a/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java b/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java
index e1e41c5..b5db879e 100644
--- a/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java
+++ b/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java
@@ -385,8 +385,12 @@
         @Override
         protected void onPostExecute(Uri result) {
             mCameraOutputUri = result;
-            if (mCameraOutputUri == null && captureCamera()) {
-                onFileNotSelected();
+            if (mCameraOutputUri == null) {
+                if (captureCamera() || mDirectToCamera) {
+                    onFileNotSelected();
+                } else {
+                    launchSelectFileWithCameraIntent(true, null);
+                }
                 return;
             }
 
diff --git a/ui/app_list/BUILD.gn b/ui/app_list/BUILD.gn
index 4d79daecb..2766ffd 100644
--- a/ui/app_list/BUILD.gn
+++ b/ui/app_list/BUILD.gn
@@ -104,7 +104,6 @@
     "//chromeos:chromeos",
     "//components/keyed_service/core",
     "//components/sync",
-    "//components/wallpaper",
     "//mojo/public/cpp/bindings",
     "//services/ui/public/cpp",
     "//services/ui/public/interfaces",
diff --git a/ui/app_list/DEPS b/ui/app_list/DEPS
index 0784ca1..f9660208 100644
--- a/ui/app_list/DEPS
+++ b/ui/app_list/DEPS
@@ -2,7 +2,6 @@
   "+chromeos/chromeos_switches.h",
   "+components/keyed_service/core",
   "+components/sync",
-  "+components/wallpaper",
   "+mojo/public/cpp",
   "+services/ui/public",
   "+skia",
diff --git a/ui/app_list/vector_icons/BUILD.gn b/ui/app_list/vector_icons/BUILD.gn
index c9c66f7..f667bec 100644
--- a/ui/app_list/vector_icons/BUILD.gn
+++ b/ui/app_list/vector_icons/BUILD.gn
@@ -8,33 +8,18 @@
   icon_directory = "."
 
   icons = [
-    "ic_arrow_up.1x.icon",
     "ic_arrow_up.icon",
-    "ic_badge_instant.1x.icon",
     "ic_badge_instant.icon",
-    "ic_badge_play.1x.icon",
     "ic_badge_play.icon",
-    "ic_badge_rating.1x.icon",
     "ic_badge_rating.icon",
-    "ic_bookmark.1x.icon",
     "ic_bookmark.icon",
-    "ic_close.1x.icon",
-    "ic_close.icon",
-    "ic_domain.1x.icon",
     "ic_domain.icon",
-    "ic_equal.1x.icon",
     "ic_equal.icon",
-    "ic_google_black.1x.icon",
     "ic_google_black.icon",
-    "ic_google_color.1x.icon",
     "ic_google_color.icon",
-    "ic_history.1x.icon",
     "ic_history.icon",
-    "ic_mic_black.1x.icon",
     "ic_mic_black.icon",
-    "ic_search.1x.icon",
     "ic_search.icon",
-    "ic_search_engine_not_google.1x.icon",
     "ic_search_engine_not_google.icon",
   ]
 }
diff --git a/ui/app_list/vector_icons/OWNERS b/ui/app_list/vector_icons/OWNERS
new file mode 100644
index 0000000..d7ec991
--- /dev/null
+++ b/ui/app_list/vector_icons/OWNERS
@@ -0,0 +1 @@
+file://components/vector_icons/OWNERS
diff --git a/ui/app_list/vector_icons/ic_arrow_up.1x.icon b/ui/app_list/vector_icons/ic_arrow_up.1x.icon
deleted file mode 100644
index 40d0ce7..0000000
--- a/ui/app_list/vector_icons/ic_arrow_up.1x.icon
+++ /dev/null
@@ -1,12 +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.
-
-CANVAS_DIMENSIONS, 12,
-MOVE_TO, 10.59f, 9,
-LINE_TO, 6, 4.67f,
-LINE_TO, 1.42f, 9,
-LINE_TO, 0, 7.66f,
-LINE_TO, 6, 2,
-R_LINE_TO, 6, 5.66f,
-CLOSE
diff --git a/ui/app_list/vector_icons/ic_arrow_up.icon b/ui/app_list/vector_icons/ic_arrow_up.icon
index 91c3daf..68b691d 100644
--- a/ui/app_list/vector_icons/ic_arrow_up.icon
+++ b/ui/app_list/vector_icons/ic_arrow_up.icon
@@ -10,3 +10,12 @@
 LINE_TO, 12, 5,
 R_LINE_TO, 12, 11.33f,
 CLOSE
+
+CANVAS_DIMENSIONS, 12,
+MOVE_TO, 10.59f, 9,
+LINE_TO, 6, 4.67f,
+LINE_TO, 1.42f, 9,
+LINE_TO, 0, 7.66f,
+LINE_TO, 6, 2,
+R_LINE_TO, 6, 5.66f,
+CLOSE
diff --git a/ui/app_list/vector_icons/ic_badge_instant.1x.icon b/ui/app_list/vector_icons/ic_badge_instant.1x.icon
deleted file mode 100644
index 664ec0f..0000000
--- a/ui/app_list/vector_icons/ic_badge_instant.1x.icon
+++ /dev/null
@@ -1,21 +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.
-
-CANVAS_DIMENSIONS, 12,
-MOVE_TO, 5.36f, 11,
-LINE_TO, 4.73f, 11,
-LINE_TO, 5.27f, 7,
-LINE_TO, 3.34f, 7,
-LINE_TO, 3.31f, 7,
-CUBIC_TO, 3.14f, 7, 3, 6.86f, 3, 6.69f,
-CUBIC_TO, 3, 6.62f, 3.07f, 6.49f, 3.07f, 6.49f,
-LINE_TO, 6.62f, 1,
-LINE_TO, 7.26f, 1,
-LINE_TO, 6.72f, 5,
-LINE_TO, 8.65f, 5,
-LINE_TO, 8.69f, 5,
-CUBIC_TO, 8.86f, 5, 9, 5.14f, 9, 5.31f,
-CUBIC_TO, 9, 5.38f, 8.98f, 5.44f, 8.94f, 5.49f,
-LINE_TO, 5.36f, 11,
-CLOSE
diff --git a/ui/app_list/vector_icons/ic_badge_instant.icon b/ui/app_list/vector_icons/ic_badge_instant.icon
index 59349c6..1172e96 100644
--- a/ui/app_list/vector_icons/ic_badge_instant.icon
+++ b/ui/app_list/vector_icons/ic_badge_instant.icon
@@ -19,3 +19,21 @@
 CUBIC_TO, 18.01f, 10.76f, 17.95f, 10.88f, 17.88f, 10.99f,
 LINE_TO, 10.73f, 22,
 CLOSE
+
+CANVAS_DIMENSIONS, 12,
+MOVE_TO, 5.36f, 11,
+LINE_TO, 4.73f, 11,
+LINE_TO, 5.27f, 7,
+LINE_TO, 3.34f, 7,
+LINE_TO, 3.31f, 7,
+CUBIC_TO, 3.14f, 7, 3, 6.86f, 3, 6.69f,
+CUBIC_TO, 3, 6.62f, 3.07f, 6.49f, 3.07f, 6.49f,
+LINE_TO, 6.62f, 1,
+LINE_TO, 7.26f, 1,
+LINE_TO, 6.72f, 5,
+LINE_TO, 8.65f, 5,
+LINE_TO, 8.69f, 5,
+CUBIC_TO, 8.86f, 5, 9, 5.14f, 9, 5.31f,
+CUBIC_TO, 9, 5.38f, 8.98f, 5.44f, 8.94f, 5.49f,
+LINE_TO, 5.36f, 11,
+CLOSE
diff --git a/ui/app_list/vector_icons/ic_badge_play.1x.icon b/ui/app_list/vector_icons/ic_badge_play.1x.icon
deleted file mode 100644
index d5325b0..0000000
--- a/ui/app_list/vector_icons/ic_badge_play.1x.icon
+++ /dev/null
@@ -1,36 +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.
-
-CANVAS_DIMENSIONS, 12,
-MOVE_TO, 8.06f, 4.5f,
-LINE_TO, 6.63f, 5.93f,
-LINE_TO, 8.06f, 7.36f,
-LINE_TO, 9.09f, 6.49f,
-CUBIC_TO, 9.37f, 6.34f, 9.5f, 6.14f, 9.5f, 5.93f,
-CUBIC_TO, 9.5f, 5.73f, 9.37f, 5.53f, 9.09f, 5.37f,
-LINE_TO, 8.06f, 4.5f,
-CLOSE,
-MOVE_TO, 6.07f, 5.37f,
-LINE_TO, 7.34f, 4.09f,
-LINE_TO, 1.99f, 1.06f,
-CUBIC_TO, 1.96f, 1.04f, 1.92f, 1.03f, 1.89f, 1.01f,
-CUBIC_TO, 1.8f, 0.98f, 1.74f, 1.04f, 1.81f, 1.12f,
-CUBIC_TO, 1.83f, 1.13f, 1.84f, 1.14f, 1.86f, 1.16f,
-LINE_TO, 6.07f, 5.37f,
-CLOSE,
-MOVE_TO, 1.82f, 10.75f,
-CUBIC_TO, 1.74f, 10.82f, 1.81f, 10.89f, 1.89f, 10.85f,
-CUBIC_TO, 1.93f, 10.84f, 1.96f, 10.82f, 2, 10.8f,
-LINE_TO, 7.34f, 7.77f,
-LINE_TO, 6.07f, 6.5f,
-CUBIC_TO, 6.07f, 6.5f, 2.47f, 10.1f, 1.86f, 10.71f,
-LINE_TO, 1.82f, 10.75f,
-CLOSE,
-MOVE_TO, 5.5f, 5.93f,
-LINE_TO, 1.19f, 1.62f,
-CUBIC_TO, 1.1f, 1.53f, 1, 1.59f, 1, 1.72f,
-LINE_TO, 1, 10.15f,
-CUBIC_TO, 1, 10.28f, 1.1f, 10.34f, 1.19f, 10.24f,
-LINE_TO, 5.5f, 5.93f,
-CLOSE
diff --git a/ui/app_list/vector_icons/ic_badge_play.icon b/ui/app_list/vector_icons/ic_badge_play.icon
index b3c4c7b..80541d8 100644
--- a/ui/app_list/vector_icons/ic_badge_play.icon
+++ b/ui/app_list/vector_icons/ic_badge_play.icon
@@ -37,3 +37,36 @@
 CUBIC_TO, 3, 20.69f, 3.19f, 20.81f, 3.38f, 20.62f,
 LINE_TO, 12, 12,
 CLOSE
+
+CANVAS_DIMENSIONS, 12,
+MOVE_TO, 8.06f, 4.5f,
+LINE_TO, 6.63f, 5.93f,
+LINE_TO, 8.06f, 7.36f,
+LINE_TO, 9.09f, 6.49f,
+CUBIC_TO, 9.37f, 6.34f, 9.5f, 6.14f, 9.5f, 5.93f,
+CUBIC_TO, 9.5f, 5.73f, 9.37f, 5.53f, 9.09f, 5.37f,
+LINE_TO, 8.06f, 4.5f,
+CLOSE,
+MOVE_TO, 6.07f, 5.37f,
+LINE_TO, 7.34f, 4.09f,
+LINE_TO, 1.99f, 1.06f,
+CUBIC_TO, 1.96f, 1.04f, 1.92f, 1.03f, 1.89f, 1.01f,
+CUBIC_TO, 1.8f, 0.98f, 1.74f, 1.04f, 1.81f, 1.12f,
+CUBIC_TO, 1.83f, 1.13f, 1.84f, 1.14f, 1.86f, 1.16f,
+LINE_TO, 6.07f, 5.37f,
+CLOSE,
+MOVE_TO, 1.82f, 10.75f,
+CUBIC_TO, 1.74f, 10.82f, 1.81f, 10.89f, 1.89f, 10.85f,
+CUBIC_TO, 1.93f, 10.84f, 1.96f, 10.82f, 2, 10.8f,
+LINE_TO, 7.34f, 7.77f,
+LINE_TO, 6.07f, 6.5f,
+CUBIC_TO, 6.07f, 6.5f, 2.47f, 10.1f, 1.86f, 10.71f,
+LINE_TO, 1.82f, 10.75f,
+CLOSE,
+MOVE_TO, 5.5f, 5.93f,
+LINE_TO, 1.19f, 1.62f,
+CUBIC_TO, 1.1f, 1.53f, 1, 1.59f, 1, 1.72f,
+LINE_TO, 1, 10.15f,
+CUBIC_TO, 1, 10.28f, 1.1f, 10.34f, 1.19f, 10.24f,
+LINE_TO, 5.5f, 5.93f,
+CLOSE
diff --git a/ui/app_list/vector_icons/ic_badge_rating.1x.icon b/ui/app_list/vector_icons/ic_badge_rating.1x.icon
deleted file mode 100644
index d7a8302..0000000
--- a/ui/app_list/vector_icons/ic_badge_rating.1x.icon
+++ /dev/null
@@ -1,16 +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.
-
-CANVAS_DIMENSIONS, 12,
-MOVE_TO, 6, 9.04f,
-LINE_TO, 9.09f, 11,
-R_LINE_TO, -0.82f, -3.7f,
-LINE_TO, 11, 4.81f,
-R_LINE_TO, -3.59f, -0.32f,
-LINE_TO, 6, 1,
-LINE_TO, 4.6f, 4.49f,
-LINE_TO, 1, 4.81f,
-LINE_TO, 3.73f, 7.3f,
-LINE_TO, 2.91f, 11,
-CLOSE
diff --git a/ui/app_list/vector_icons/ic_badge_rating.icon b/ui/app_list/vector_icons/ic_badge_rating.icon
index 4c0d253a7..b6b605d 100644
--- a/ui/app_list/vector_icons/ic_badge_rating.icon
+++ b/ui/app_list/vector_icons/ic_badge_rating.icon
@@ -14,3 +14,16 @@
 R_LINE_TO, 5.46f, 4.98f,
 LINE_TO, 5.82f, 22,
 CLOSE
+
+CANVAS_DIMENSIONS, 12,
+MOVE_TO, 6, 9.04f,
+LINE_TO, 9.09f, 11,
+R_LINE_TO, -0.82f, -3.7f,
+LINE_TO, 11, 4.81f,
+R_LINE_TO, -3.59f, -0.32f,
+LINE_TO, 6, 1,
+LINE_TO, 4.6f, 4.49f,
+LINE_TO, 1, 4.81f,
+LINE_TO, 3.73f, 7.3f,
+LINE_TO, 2.91f, 11,
+CLOSE
diff --git a/ui/app_list/vector_icons/ic_bookmark.1x.icon b/ui/app_list/vector_icons/ic_bookmark.1x.icon
deleted file mode 100644
index 7c77a3c..0000000
--- a/ui/app_list/vector_icons/ic_bookmark.1x.icon
+++ /dev/null
@@ -1,16 +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.
-
-CANVAS_DIMENSIONS, 18,
-MOVE_TO, 9, 13.25f,
-LINE_TO, 13.33f, 16,
-R_LINE_TO, -1.15f, -5.18f,
-LINE_TO, 16, 7.34f,
-R_LINE_TO, -5.03f, -0.45f,
-LINE_TO, 9, 2,
-LINE_TO, 7.03f, 6.89f,
-LINE_TO, 2, 7.34f,
-R_LINE_TO, 3.82f, 3.49f,
-LINE_TO, 4.67f, 16,
-CLOSE
diff --git a/ui/app_list/vector_icons/ic_bookmark.icon b/ui/app_list/vector_icons/ic_bookmark.icon
index 4f5ae02..06fb9551f 100644
--- a/ui/app_list/vector_icons/ic_bookmark.icon
+++ b/ui/app_list/vector_icons/ic_bookmark.icon
@@ -14,3 +14,16 @@
 R_LINE_TO, 8.19f, 6.97f,
 LINE_TO, 8.73f, 32,
 CLOSE
+
+CANVAS_DIMENSIONS, 18,
+MOVE_TO, 9, 13.25f,
+LINE_TO, 13.33f, 16,
+R_LINE_TO, -1.15f, -5.18f,
+LINE_TO, 16, 7.34f,
+R_LINE_TO, -5.03f, -0.45f,
+LINE_TO, 9, 2,
+LINE_TO, 7.03f, 6.89f,
+LINE_TO, 2, 7.34f,
+R_LINE_TO, 3.82f, 3.49f,
+LINE_TO, 4.67f, 16,
+CLOSE
diff --git a/ui/app_list/vector_icons/ic_close.1x.icon b/ui/app_list/vector_icons/ic_close.1x.icon
deleted file mode 100644
index 55c4b63..0000000
--- a/ui/app_list/vector_icons/ic_close.1x.icon
+++ /dev/null
@@ -1,18 +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.
-
-CANVAS_DIMENSIONS, 24,
-MOVE_TO, 19, 6.41f,
-LINE_TO, 17.59f, 5,
-LINE_TO, 12, 10.59f,
-LINE_TO, 6.41f, 5,
-LINE_TO, 5, 6.41f,
-LINE_TO, 10.59f, 12,
-LINE_TO, 5, 17.59f,
-LINE_TO, 6.41f, 19,
-LINE_TO, 12, 13.41f,
-LINE_TO, 17.59f, 19,
-LINE_TO, 19, 17.59f,
-LINE_TO, 13.41f, 12,
-CLOSE
diff --git a/ui/app_list/vector_icons/ic_close.icon b/ui/app_list/vector_icons/ic_close.icon
deleted file mode 100644
index 67d7220..0000000
--- a/ui/app_list/vector_icons/ic_close.icon
+++ /dev/null
@@ -1,18 +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.
-
-CANVAS_DIMENSIONS, 48,
-MOVE_TO, 38, 12.82f,
-LINE_TO, 35.18f, 10,
-LINE_TO, 24, 21.18f,
-LINE_TO, 12.82f, 10,
-LINE_TO, 10, 12.82f,
-LINE_TO, 21.18f, 24,
-LINE_TO, 10, 35.18f,
-LINE_TO, 12.82f, 38,
-LINE_TO, 24, 26.82f,
-LINE_TO, 35.18f, 38,
-LINE_TO, 38, 35.18f,
-LINE_TO, 26.82f, 24,
-CLOSE
diff --git a/ui/app_list/vector_icons/ic_domain.1x.icon b/ui/app_list/vector_icons/ic_domain.1x.icon
deleted file mode 100644
index 502a38f..0000000
--- a/ui/app_list/vector_icons/ic_domain.1x.icon
+++ /dev/null
@@ -1,25 +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.
-
-CANVAS_DIMENSIONS, 18,
-MOVE_TO, 3, 1,
-LINE_TO, 10, 1,
-LINE_TO, 15, 6,
-LINE_TO, 15, 17,
-LINE_TO, 3, 17,
-LINE_TO, 3, 1,
-CLOSE,
-MOVE_TO, 8, 3,
-LINE_TO, 5, 3,
-LINE_TO, 5, 15,
-LINE_TO, 13, 15,
-LINE_TO, 13, 8,
-LINE_TO, 8, 8,
-LINE_TO, 8, 3,
-CLOSE,
-MOVE_TO, 13, 6,
-LINE_TO, 10, 3,
-LINE_TO, 10, 6,
-LINE_TO, 13, 6,
-CLOSE
diff --git a/ui/app_list/vector_icons/ic_domain.icon b/ui/app_list/vector_icons/ic_domain.icon
index d56e9a9..99bb5f5f 100644
--- a/ui/app_list/vector_icons/ic_domain.icon
+++ b/ui/app_list/vector_icons/ic_domain.icon
@@ -23,3 +23,25 @@
 LINE_TO, 20, 13,
 LINE_TO, 26, 13,
 CLOSE
+
+CANVAS_DIMENSIONS, 18,
+MOVE_TO, 3, 1,
+LINE_TO, 10, 1,
+LINE_TO, 15, 6,
+LINE_TO, 15, 17,
+LINE_TO, 3, 17,
+LINE_TO, 3, 1,
+CLOSE,
+MOVE_TO, 8, 3,
+LINE_TO, 5, 3,
+LINE_TO, 5, 15,
+LINE_TO, 13, 15,
+LINE_TO, 13, 8,
+LINE_TO, 8, 8,
+LINE_TO, 8, 3,
+CLOSE,
+MOVE_TO, 13, 6,
+LINE_TO, 10, 3,
+LINE_TO, 10, 6,
+LINE_TO, 13, 6,
+CLOSE
diff --git a/ui/app_list/vector_icons/ic_equal.1x.icon b/ui/app_list/vector_icons/ic_equal.1x.icon
deleted file mode 100644
index 11ec410..0000000
--- a/ui/app_list/vector_icons/ic_equal.1x.icon
+++ /dev/null
@@ -1,17 +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.
-
-CANVAS_DIMENSIONS, 18,
-MOVE_TO, 4, 6,
-R_H_LINE_TO, 10,
-R_V_LINE_TO, 2,
-H_LINE_TO, 4,
-V_LINE_TO, 6,
-CLOSE,
-R_MOVE_TO, 0, 4,
-R_H_LINE_TO, 10,
-R_V_LINE_TO, 2,
-H_LINE_TO, 4,
-R_V_LINE_TO, -2,
-CLOSE
diff --git a/ui/app_list/vector_icons/ic_equal.icon b/ui/app_list/vector_icons/ic_equal.icon
index 4988a87..fc3f825b 100644
--- a/ui/app_list/vector_icons/ic_equal.icon
+++ b/ui/app_list/vector_icons/ic_equal.icon
@@ -15,3 +15,17 @@
 H_LINE_TO, 9,
 R_V_LINE_TO, -3,
 CLOSE
+
+CANVAS_DIMENSIONS, 18,
+MOVE_TO, 4, 6,
+R_H_LINE_TO, 10,
+R_V_LINE_TO, 2,
+H_LINE_TO, 4,
+V_LINE_TO, 6,
+CLOSE,
+R_MOVE_TO, 0, 4,
+R_H_LINE_TO, 10,
+R_V_LINE_TO, 2,
+H_LINE_TO, 4,
+R_V_LINE_TO, -2,
+CLOSE
diff --git a/ui/app_list/vector_icons/ic_google_black.1x.icon b/ui/app_list/vector_icons/ic_google_black.1x.icon
deleted file mode 100644
index f712169..0000000
--- a/ui/app_list/vector_icons/ic_google_black.1x.icon
+++ /dev/null
@@ -1,20 +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.
-
-CANVAS_DIMENSIONS, 24,
-MOVE_TO, 12, 10,
-LINE_TO, 21.69f, 10,
-CUBIC_TO, 21.83f, 10.63f, 22, 11.4f, 22, 12.23f,
-CUBIC_TO, 22, 17.94f, 18.09f, 22, 12.21f, 22,
-CUBIC_TO, 6.57f, 22, 2, 17.52f, 2, 12,
-CUBIC_TO, 2, 6.48f, 6.57f, 2, 12.2f, 2,
-CUBIC_TO, 14.95f, 2, 17.26f, 2.99f, 19.02f, 4.61f,
-LINE_TO, 16.13f, 7.37f,
-CUBIC_TO, 15.39f, 6.69f, 14.12f, 5.88f, 12.2f, 5.88f,
-CUBIC_TO, 8.82f, 5.88f, 6.07f, 8.63f, 6.07f, 12,
-CUBIC_TO, 6.07f, 15.37f, 8.83f, 18, 12.21f, 18,
-CUBIC_TO, 16.12f, 18, 17.54f, 15.57f, 17.81f, 14,
-LINE_TO, 12, 14,
-LINE_TO, 12, 10,
-CLOSE
diff --git a/ui/app_list/vector_icons/ic_google_black.icon b/ui/app_list/vector_icons/ic_google_black.icon
index 3e7b050d..5241cba 100644
--- a/ui/app_list/vector_icons/ic_google_black.icon
+++ b/ui/app_list/vector_icons/ic_google_black.icon
@@ -17,3 +17,20 @@
 LINE_TO, 24, 28,
 LINE_TO, 24, 20,
 CLOSE
+
+CANVAS_DIMENSIONS, 24,
+MOVE_TO, 12, 10,
+LINE_TO, 21.69f, 10,
+CUBIC_TO, 21.83f, 10.63f, 22, 11.4f, 22, 12.23f,
+CUBIC_TO, 22, 17.94f, 18.09f, 22, 12.21f, 22,
+CUBIC_TO, 6.57f, 22, 2, 17.52f, 2, 12,
+CUBIC_TO, 2, 6.48f, 6.57f, 2, 12.2f, 2,
+CUBIC_TO, 14.95f, 2, 17.26f, 2.99f, 19.02f, 4.61f,
+LINE_TO, 16.13f, 7.37f,
+CUBIC_TO, 15.39f, 6.69f, 14.12f, 5.88f, 12.2f, 5.88f,
+CUBIC_TO, 8.82f, 5.88f, 6.07f, 8.63f, 6.07f, 12,
+CUBIC_TO, 6.07f, 15.37f, 8.83f, 18, 12.21f, 18,
+CUBIC_TO, 16.12f, 18, 17.54f, 15.57f, 17.81f, 14,
+LINE_TO, 12, 14,
+LINE_TO, 12, 10,
+CLOSE
diff --git a/ui/app_list/vector_icons/ic_google_color.1x.icon b/ui/app_list/vector_icons/ic_google_color.1x.icon
deleted file mode 100644
index 4cf472c1..0000000
--- a/ui/app_list/vector_icons/ic_google_color.1x.icon
+++ /dev/null
@@ -1,49 +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.
-
-CANVAS_DIMENSIONS, 24,
-PATH_COLOR_ARGB, 0xFF, 0x42, 0x85, 0xF4,
-MOVE_TO, 21.73f, 10,
-LINE_TO, 12, 10,
-LINE_TO, 12, 14,
-LINE_TO, 17.82f, 14,
-CUBIC_TO, 17.58f, 15.25f, 16.73f, 16.35f, 15.65f, 17.06f,
-LINE_TO, 15.65f, 19.58f,
-LINE_TO, 18.96f, 19.58f,
-CUBIC_TO, 20.89f, 17.84f, 22, 15.27f, 22, 12.23f,
-CUBIC_TO, 22, 11.52f, 21.85f, 10.65f, 21.73f, 10,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0x0F, 0x9D, 0x58,
-MOVE_TO, 12.2f, 22,
-CUBIC_TO, 14.96f, 22, 17.27f, 21.11f, 18.96f, 19.58f,
-LINE_TO, 15.65f, 17.06f,
-CUBIC_TO, 14.74f, 17.66f, 13.58f, 18.03f, 12.2f, 18.03f,
-CUBIC_TO, 9.55f, 18.03f, 7.3f, 16.27f, 6.49f, 13.91f,
-LINE_TO, 3.09f, 13.91f,
-LINE_TO, 3.09f, 16.49f,
-CUBIC_TO, 4.77f, 19.75f, 8.22f, 22, 12.2f, 22,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0xFF, 0xCD, 0x40,
-MOVE_TO, 6.49f, 13.9f,
-CUBIC_TO, 6.29f, 13.3f, 6.17f, 12.66f, 6.17f, 12,
-CUBIC_TO, 6.17f, 11.34f, 6.29f, 10.7f, 6.49f, 10.1f,
-LINE_TO, 6.49f, 7.52f,
-LINE_TO, 3.09f, 7.52f,
-CUBIC_TO, 2.4f, 8.86f, 2, 10.38f, 2, 12,
-CUBIC_TO, 2, 13.62f, 2.4f, 15.14f, 3.09f, 16.48f,
-LINE_TO, 5.74f, 14.46f,
-LINE_TO, 6.49f, 13.9f,
-CLOSE,
-NEW_PATH,
-PATH_COLOR_ARGB, 0xFF, 0xDB, 0x44, 0x37,
-MOVE_TO, 12.2f, 5.98f,
-CUBIC_TO, 13.71f, 5.98f, 15.04f, 6.49f, 16.11f, 7.47f,
-LINE_TO, 19.03f, 4.61f,
-CUBIC_TO, 17.26f, 2.99f, 14.96f, 2, 12.2f, 2,
-CUBIC_TO, 8.22f, 2, 4.77f, 4.25f, 3.09f, 7.52f,
-LINE_TO, 6.49f, 10.1f,
-CUBIC_TO, 7.3f, 7.74f, 9.55f, 5.98f, 12.2f, 5.98f,
-CLOSE
diff --git a/ui/app_list/vector_icons/ic_google_color.icon b/ui/app_list/vector_icons/ic_google_color.icon
index ca9fe70..77d5e0ff 100644
--- a/ui/app_list/vector_icons/ic_google_color.icon
+++ b/ui/app_list/vector_icons/ic_google_color.icon
@@ -47,3 +47,49 @@
 R_LINE_TO, 5.8f, -5.7f,
 CUBIC_TO, 34.5f, 6, 29.9f, 4, 24.4f, 4,
 CLOSE
+
+CANVAS_DIMENSIONS, 24,
+PATH_COLOR_ARGB, 0xFF, 0x42, 0x85, 0xF4,
+MOVE_TO, 21.73f, 10,
+LINE_TO, 12, 10,
+LINE_TO, 12, 14,
+LINE_TO, 17.82f, 14,
+CUBIC_TO, 17.58f, 15.25f, 16.73f, 16.35f, 15.65f, 17.06f,
+LINE_TO, 15.65f, 19.58f,
+LINE_TO, 18.96f, 19.58f,
+CUBIC_TO, 20.89f, 17.84f, 22, 15.27f, 22, 12.23f,
+CUBIC_TO, 22, 11.52f, 21.85f, 10.65f, 21.73f, 10,
+CLOSE,
+NEW_PATH,
+PATH_COLOR_ARGB, 0xFF, 0x0F, 0x9D, 0x58,
+MOVE_TO, 12.2f, 22,
+CUBIC_TO, 14.96f, 22, 17.27f, 21.11f, 18.96f, 19.58f,
+LINE_TO, 15.65f, 17.06f,
+CUBIC_TO, 14.74f, 17.66f, 13.58f, 18.03f, 12.2f, 18.03f,
+CUBIC_TO, 9.55f, 18.03f, 7.3f, 16.27f, 6.49f, 13.91f,
+LINE_TO, 3.09f, 13.91f,
+LINE_TO, 3.09f, 16.49f,
+CUBIC_TO, 4.77f, 19.75f, 8.22f, 22, 12.2f, 22,
+CLOSE,
+NEW_PATH,
+PATH_COLOR_ARGB, 0xFF, 0xFF, 0xCD, 0x40,
+MOVE_TO, 6.49f, 13.9f,
+CUBIC_TO, 6.29f, 13.3f, 6.17f, 12.66f, 6.17f, 12,
+CUBIC_TO, 6.17f, 11.34f, 6.29f, 10.7f, 6.49f, 10.1f,
+LINE_TO, 6.49f, 7.52f,
+LINE_TO, 3.09f, 7.52f,
+CUBIC_TO, 2.4f, 8.86f, 2, 10.38f, 2, 12,
+CUBIC_TO, 2, 13.62f, 2.4f, 15.14f, 3.09f, 16.48f,
+LINE_TO, 5.74f, 14.46f,
+LINE_TO, 6.49f, 13.9f,
+CLOSE,
+NEW_PATH,
+PATH_COLOR_ARGB, 0xFF, 0xDB, 0x44, 0x37,
+MOVE_TO, 12.2f, 5.98f,
+CUBIC_TO, 13.71f, 5.98f, 15.04f, 6.49f, 16.11f, 7.47f,
+LINE_TO, 19.03f, 4.61f,
+CUBIC_TO, 17.26f, 2.99f, 14.96f, 2, 12.2f, 2,
+CUBIC_TO, 8.22f, 2, 4.77f, 4.25f, 3.09f, 7.52f,
+LINE_TO, 6.49f, 10.1f,
+CUBIC_TO, 7.3f, 7.74f, 9.55f, 5.98f, 12.2f, 5.98f,
+CLOSE
diff --git a/ui/app_list/vector_icons/ic_history.1x.icon b/ui/app_list/vector_icons/ic_history.1x.icon
deleted file mode 100644
index dca7a78..0000000
--- a/ui/app_list/vector_icons/ic_history.1x.icon
+++ /dev/null
@@ -1,25 +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.
-
-CANVAS_DIMENSIONS, 18,
-MOVE_TO, 8.99f, 1,
-CUBIC_TO, 13.42f, 1, 17, 4.58f, 17, 9,
-CUBIC_TO, 17, 13.42f, 13.42f, 17, 8.99f, 17,
-CUBIC_TO, 4.58f, 17, 1, 13.42f, 1, 9,
-CUBIC_TO, 1, 4.58f, 4.58f, 1, 8.99f, 1,
-CLOSE,
-MOVE_TO, 9, 15.4f,
-CUBIC_TO, 12.54f, 15.4f, 15.4f, 12.54f, 15.4f, 9,
-CUBIC_TO, 15.4f, 5.46f, 12.54f, 2.6f, 9, 2.6f,
-CUBIC_TO, 5.46f, 2.6f, 2.6f, 5.46f, 2.6f, 9,
-CUBIC_TO, 2.6f, 12.54f, 5.46f, 15.4f, 9, 15.4f,
-CLOSE,
-MOVE_TO, 9.4f, 5,
-LINE_TO, 9.4f, 9.2f,
-LINE_TO, 13, 11.34f,
-LINE_TO, 12.4f, 12.32f,
-LINE_TO, 8.2f, 9.8f,
-LINE_TO, 8.2f, 5,
-LINE_TO, 9.4f, 5,
-CLOSE
diff --git a/ui/app_list/vector_icons/ic_history.icon b/ui/app_list/vector_icons/ic_history.icon
index 9890851..3d3c604 100644
--- a/ui/app_list/vector_icons/ic_history.icon
+++ b/ui/app_list/vector_icons/ic_history.icon
@@ -23,3 +23,25 @@
 LINE_TO, 16.5f, 10.5f,
 LINE_TO, 18.75f, 10.5f,
 CLOSE
+
+CANVAS_DIMENSIONS, 18,
+MOVE_TO, 8.99f, 1,
+CUBIC_TO, 13.42f, 1, 17, 4.58f, 17, 9,
+CUBIC_TO, 17, 13.42f, 13.42f, 17, 8.99f, 17,
+CUBIC_TO, 4.58f, 17, 1, 13.42f, 1, 9,
+CUBIC_TO, 1, 4.58f, 4.58f, 1, 8.99f, 1,
+CLOSE,
+MOVE_TO, 9, 15.4f,
+CUBIC_TO, 12.54f, 15.4f, 15.4f, 12.54f, 15.4f, 9,
+CUBIC_TO, 15.4f, 5.46f, 12.54f, 2.6f, 9, 2.6f,
+CUBIC_TO, 5.46f, 2.6f, 2.6f, 5.46f, 2.6f, 9,
+CUBIC_TO, 2.6f, 12.54f, 5.46f, 15.4f, 9, 15.4f,
+CLOSE,
+MOVE_TO, 9.4f, 5,
+LINE_TO, 9.4f, 9.2f,
+LINE_TO, 13, 11.34f,
+LINE_TO, 12.4f, 12.32f,
+LINE_TO, 8.2f, 9.8f,
+LINE_TO, 8.2f, 5,
+LINE_TO, 9.4f, 5,
+CLOSE
diff --git a/ui/app_list/vector_icons/ic_mic_black.1x.icon b/ui/app_list/vector_icons/ic_mic_black.1x.icon
deleted file mode 100644
index 72ec88f..0000000
--- a/ui/app_list/vector_icons/ic_mic_black.1x.icon
+++ /dev/null
@@ -1,24 +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.
-
-CANVAS_DIMENSIONS, 24,
-MOVE_TO, 12, 15,
-CUBIC_TO, 13.66f, 15, 14.99f, 13.66f, 14.99f, 12,
-LINE_TO, 15, 6,
-CUBIC_TO, 15, 4.34f, 13.66f, 3, 12, 3,
-CUBIC_TO, 10.34f, 3, 9, 4.34f, 9, 6,
-LINE_TO, 9, 12,
-CUBIC_TO, 9, 13.66f, 10.34f, 15, 12, 15,
-CLOSE,
-MOVE_TO, 17.3f, 12,
-CUBIC_TO, 17.3f, 15, 14.76f, 17.1f, 12, 17.1f,
-CUBIC_TO, 9.24f, 17.1f, 6.7f, 15, 6.7f, 12,
-LINE_TO, 5, 12,
-CUBIC_TO, 5, 15.41f, 7.72f, 18.23f, 11, 18.72f,
-LINE_TO, 11, 22,
-LINE_TO, 13, 22,
-LINE_TO, 13, 18.72f,
-CUBIC_TO, 16.28f, 18.24f, 19, 15.42f, 19, 12,
-LINE_TO, 17.3f, 12,
-CLOSE
diff --git a/ui/app_list/vector_icons/ic_mic_black.icon b/ui/app_list/vector_icons/ic_mic_black.icon
index 08371f1..20ca3269 100644
--- a/ui/app_list/vector_icons/ic_mic_black.icon
+++ b/ui/app_list/vector_icons/ic_mic_black.icon
@@ -21,3 +21,24 @@
 CUBIC_TO, 32.56f, 35.48f, 38, 29.84f, 38, 23,
 LINE_TO, 34.6f, 23,
 CLOSE
+
+CANVAS_DIMENSIONS, 24,
+MOVE_TO, 12, 15,
+CUBIC_TO, 13.66f, 15, 14.99f, 13.66f, 14.99f, 12,
+LINE_TO, 15, 6,
+CUBIC_TO, 15, 4.34f, 13.66f, 3, 12, 3,
+CUBIC_TO, 10.34f, 3, 9, 4.34f, 9, 6,
+LINE_TO, 9, 12,
+CUBIC_TO, 9, 13.66f, 10.34f, 15, 12, 15,
+CLOSE,
+MOVE_TO, 17.3f, 12,
+CUBIC_TO, 17.3f, 15, 14.76f, 17.1f, 12, 17.1f,
+CUBIC_TO, 9.24f, 17.1f, 6.7f, 15, 6.7f, 12,
+LINE_TO, 5, 12,
+CUBIC_TO, 5, 15.41f, 7.72f, 18.23f, 11, 18.72f,
+LINE_TO, 11, 22,
+LINE_TO, 13, 22,
+LINE_TO, 13, 18.72f,
+CUBIC_TO, 16.28f, 18.24f, 19, 15.42f, 19, 12,
+LINE_TO, 17.3f, 12,
+CLOSE
diff --git a/ui/app_list/vector_icons/ic_search.1x.icon b/ui/app_list/vector_icons/ic_search.1x.icon
deleted file mode 100644
index 1cf4f35..0000000
--- a/ui/app_list/vector_icons/ic_search.1x.icon
+++ /dev/null
@@ -1,25 +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.
-
-CANVAS_DIMENSIONS, 18,
-MOVE_TO, 11.71f, 11.06f,
-LINE_TO, 11.46f, 10.82f,
-CUBIC_TO, 12.35f, 9.77f, 12.89f, 8.42f, 12.89f, 6.95f,
-CUBIC_TO, 12.89f, 3.66f, 10.23f, 1, 6.95f, 1,
-CUBIC_TO, 3.66f, 1, 1, 3.66f, 1, 6.95f,
-CUBIC_TO, 1, 10.23f, 3.66f, 12.89f, 6.95f, 12.89f,
-CUBIC_TO, 8.42f, 12.89f, 9.77f, 12.35f, 10.82f, 11.46f,
-LINE_TO, 11.06f, 11.71f,
-LINE_TO, 11.06f, 12.44f,
-LINE_TO, 15.64f, 17,
-LINE_TO, 17, 15.64f,
-LINE_TO, 12.44f, 11.06f,
-LINE_TO, 11.71f, 11.06f,
-CLOSE,
-MOVE_TO, 6.95f, 11.06f,
-CUBIC_TO, 4.67f, 11.06f, 2.83f, 9.22f, 2.83f, 6.95f,
-CUBIC_TO, 2.83f, 4.67f, 4.67f, 2.83f, 6.95f, 2.83f,
-CUBIC_TO, 9.22f, 2.83f, 11.06f, 4.67f, 11.06f, 6.95f,
-CUBIC_TO, 11.06f, 9.22f, 9.22f, 11.06f, 6.95f, 11.06f,
-CLOSE
diff --git a/ui/app_list/vector_icons/ic_search.icon b/ui/app_list/vector_icons/ic_search.icon
index 44b16812..d77c2ac 100644
--- a/ui/app_list/vector_icons/ic_search.icon
+++ b/ui/app_list/vector_icons/ic_search.icon
@@ -24,3 +24,25 @@
 CUBIC_TO, 18.36f, 7.97f, 21.35f, 10.96f, 21.35f, 14.66f,
 CUBIC_TO, 21.35f, 18.36f, 18.36f, 21.35f, 14.66f, 21.35f,
 CLOSE
+
+CANVAS_DIMENSIONS, 18,
+MOVE_TO, 11.71f, 11.06f,
+LINE_TO, 11.46f, 10.82f,
+CUBIC_TO, 12.35f, 9.77f, 12.89f, 8.42f, 12.89f, 6.95f,
+CUBIC_TO, 12.89f, 3.66f, 10.23f, 1, 6.95f, 1,
+CUBIC_TO, 3.66f, 1, 1, 3.66f, 1, 6.95f,
+CUBIC_TO, 1, 10.23f, 3.66f, 12.89f, 6.95f, 12.89f,
+CUBIC_TO, 8.42f, 12.89f, 9.77f, 12.35f, 10.82f, 11.46f,
+LINE_TO, 11.06f, 11.71f,
+LINE_TO, 11.06f, 12.44f,
+LINE_TO, 15.64f, 17,
+LINE_TO, 17, 15.64f,
+LINE_TO, 12.44f, 11.06f,
+LINE_TO, 11.71f, 11.06f,
+CLOSE,
+MOVE_TO, 6.95f, 11.06f,
+CUBIC_TO, 4.67f, 11.06f, 2.83f, 9.22f, 2.83f, 6.95f,
+CUBIC_TO, 2.83f, 4.67f, 4.67f, 2.83f, 6.95f, 2.83f,
+CUBIC_TO, 9.22f, 2.83f, 11.06f, 4.67f, 11.06f, 6.95f,
+CUBIC_TO, 11.06f, 9.22f, 9.22f, 11.06f, 6.95f, 11.06f,
+CLOSE
diff --git a/ui/app_list/vector_icons/ic_search_engine_not_google.1x.icon b/ui/app_list/vector_icons/ic_search_engine_not_google.1x.icon
deleted file mode 100644
index a0e8629d..0000000
--- a/ui/app_list/vector_icons/ic_search_engine_not_google.1x.icon
+++ /dev/null
@@ -1,25 +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.
-
-CANVAS_DIMENSIONS, 24,
-MOVE_TO, 15.5f, 14,
-LINE_TO, 14.71f, 14,
-LINE_TO, 14.43f, 13.73f,
-CUBIC_TO, 15.41f, 12.59f, 16, 11.11f, 16, 9.5f,
-CUBIC_TO, 16, 5.91f, 13.09f, 3, 9.5f, 3,
-CUBIC_TO, 5.91f, 3, 3, 5.91f, 3, 9.5f,
-CUBIC_TO, 3, 13.09f, 5.91f, 16, 9.5f, 16,
-CUBIC_TO, 11.11f, 16, 12.59f, 15.41f, 13.73f, 14.43f,
-LINE_TO, 14, 14.71f,
-LINE_TO, 14, 15.5f,
-LINE_TO, 19, 20.49f,
-LINE_TO, 20.49f, 19,
-LINE_TO, 15.5f, 14,
-CLOSE,
-MOVE_TO, 9.5f, 14,
-CUBIC_TO, 7.01f, 14, 5, 11.99f, 5, 9.5f,
-CUBIC_TO, 5, 7.01f, 7.01f, 5, 9.5f, 5,
-CUBIC_TO, 11.99f, 5, 14, 7.01f, 14, 9.5f,
-CUBIC_TO, 14, 11.99f, 11.99f, 14, 9.5f, 14,
-CLOSE
diff --git a/ui/app_list/vector_icons/ic_search_engine_not_google.icon b/ui/app_list/vector_icons/ic_search_engine_not_google.icon
index 4577140..4d43d70 100644
--- a/ui/app_list/vector_icons/ic_search_engine_not_google.icon
+++ b/ui/app_list/vector_icons/ic_search_engine_not_google.icon
@@ -22,3 +22,25 @@
 CUBIC_TO, 23.98f, 10, 28, 14.02f, 28, 19,
 CUBIC_TO, 28, 23.98f, 23.98f, 28, 19, 28,
 CLOSE
+
+CANVAS_DIMENSIONS, 24,
+MOVE_TO, 15.5f, 14,
+LINE_TO, 14.71f, 14,
+LINE_TO, 14.43f, 13.73f,
+CUBIC_TO, 15.41f, 12.59f, 16, 11.11f, 16, 9.5f,
+CUBIC_TO, 16, 5.91f, 13.09f, 3, 9.5f, 3,
+CUBIC_TO, 5.91f, 3, 3, 5.91f, 3, 9.5f,
+CUBIC_TO, 3, 13.09f, 5.91f, 16, 9.5f, 16,
+CUBIC_TO, 11.11f, 16, 12.59f, 15.41f, 13.73f, 14.43f,
+LINE_TO, 14, 14.71f,
+LINE_TO, 14, 15.5f,
+LINE_TO, 19, 20.49f,
+LINE_TO, 20.49f, 19,
+LINE_TO, 15.5f, 14,
+CLOSE,
+MOVE_TO, 9.5f, 14,
+CUBIC_TO, 7.01f, 14, 5, 11.99f, 5, 9.5f,
+CUBIC_TO, 5, 7.01f, 7.01f, 5, 9.5f, 5,
+CUBIC_TO, 11.99f, 5, 14, 7.01f, 14, 9.5f,
+CUBIC_TO, 14, 11.99f, 11.99f, 14, 9.5f, 14,
+CLOSE
diff --git a/ui/app_list/views/app_list_view.cc b/ui/app_list/views/app_list_view.cc
index ad9d0a6..3ee1d985 100644
--- a/ui/app_list/views/app_list_view.cc
+++ b/ui/app_list/views/app_list_view.cc
@@ -9,11 +9,11 @@
 #include <vector>
 
 #include "ash/app_list/model/app_list_model.h"
+#include "ash/public/cpp/wallpaper_types.h"
 #include "base/macros.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
 #include "base/strings/string_util.h"
-#include "components/wallpaper/wallpaper_color_profile.h"
 #include "mojo/public/cpp/bindings/type_converter.h"
 #include "services/ui/public/cpp/property_type_converters.h"
 #include "services/ui/public/interfaces/window_manager.mojom.h"
@@ -56,7 +56,7 @@
 #include "ui/wm/core/coordinate_conversion.h"
 #include "ui/wm/core/shadow_types.h"
 
-using wallpaper::ColorProfileType;
+using ash::ColorProfileType;
 
 namespace app_list {
 
@@ -293,6 +293,7 @@
   is_side_shelf_ = params.is_side_shelf;
   InitContents(params.initial_apps_page);
   AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE));
+  AddAccelerator(ui::Accelerator(ui::VKEY_BROWSER_BACK, ui::EF_NONE));
   parent_window_ = params.parent;
 
   InitializeFullscreen(params.parent, params.parent_container_id);
@@ -972,12 +973,18 @@
 }
 
 bool AppListView::AcceleratorPressed(const ui::Accelerator& accelerator) {
-  DCHECK_EQ(ui::VKEY_ESCAPE, accelerator.key_code());
-
-  // If the ContentsView does not handle the back action, then this is the
-  // top level, so we close the app list.
-  if (!app_list_main_view_->contents_view()->Back()) {
-    Dismiss();
+  switch (accelerator.key_code()) {
+    case ui::VKEY_ESCAPE:
+    case ui::VKEY_BROWSER_BACK:
+      // If the ContentsView does not handle the back action, then this is the
+      // top level, so we close the app list.
+      if (!app_list_main_view_->contents_view()->Back()) {
+        Dismiss();
+      }
+      break;
+    default:
+      NOTREACHED();
+      return false;
   }
 
   // Don't let DialogClientView handle the accelerator.
diff --git a/ui/app_list/views/search_box_view.cc b/ui/app_list/views/search_box_view.cc
index b5c83d4..7192242 100644
--- a/ui/app_list/views/search_box_view.cc
+++ b/ui/app_list/views/search_box_view.cc
@@ -11,8 +11,8 @@
 
 #include "ash/app_list/model/search/search_box_model.h"
 #include "ash/app_list/model/search/search_model.h"
+#include "ash/public/cpp/wallpaper_types.h"
 #include "base/macros.h"
-#include "components/wallpaper/wallpaper_color_profile.h"
 #include "ui/app_list/app_list_constants.h"
 #include "ui/app_list/app_list_util.h"
 #include "ui/app_list/app_list_view_delegate.h"
@@ -38,10 +38,11 @@
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/textfield/textfield.h"
 #include "ui/views/layout/box_layout.h"
+#include "ui/views/vector_icons.h"
 #include "ui/views/view.h"
 #include "ui/views/widget/widget.h"
 
-using wallpaper::ColorProfileType;
+using ash::ColorProfileType;
 
 namespace app_list {
 
@@ -328,7 +329,8 @@
   UpdateSearchIcon();
   close_button()->SetImage(
       views::Button::STATE_NORMAL,
-      gfx::CreateVectorIcon(kIcCloseIcon, kCloseIconSize, search_box_color()));
+      gfx::CreateVectorIcon(views::kIcCloseIcon, kCloseIconSize,
+                            search_box_color()));
   search_box()->set_placeholder_text_color(search_box_color());
   UpdateBackgroundColor(background_color());
   SchedulePaint();
@@ -374,9 +376,9 @@
 
 void SearchBoxView::SetupCloseButton() {
   views::ImageButton* close = close_button();
-  close->SetImage(
-      views::ImageButton::STATE_NORMAL,
-      gfx::CreateVectorIcon(kIcCloseIcon, kCloseIconSize, search_box_color()));
+  close->SetImage(views::ImageButton::STATE_NORMAL,
+                  gfx::CreateVectorIcon(views::kIcCloseIcon, kCloseIconSize,
+                                        search_box_color()));
   close->SetVisible(false);
   close->SetAccessibleName(
       l10n_util::GetStringUTF16(IDS_APP_LIST_CLEAR_SEARCHBOX));
diff --git a/ui/arc/notification/arc_notification_view_unittest.cc b/ui/arc/notification/arc_notification_view_unittest.cc
index 79c6821..271e8313 100644
--- a/ui/arc/notification/arc_notification_view_unittest.cc
+++ b/ui/arc/notification/arc_notification_view_unittest.cc
@@ -4,6 +4,8 @@
 
 #include <memory>
 
+#include "ash/shell.h"
+#include "ash/test/ash_test_base.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
@@ -163,16 +165,14 @@
 
 }  // namespace
 
-class ArcNotificationViewTest : public views::ViewsTestBase {
+class ArcNotificationViewTest : public ash::AshTestBase {
  public:
   ArcNotificationViewTest() = default;
   ~ArcNotificationViewTest() override = default;
 
   // views::ViewsTestBase
   void SetUp() override {
-    views::ViewsTestBase::SetUp();
-
-    MessageCenter::Initialize();
+    ash::AshTestBase::SetUp();
 
     const std::string notification_id("notification id");
     item_ = std::make_unique<MockArcNotificationItem>(notification_id);
@@ -193,19 +193,24 @@
     UpdateNotificationViews();
 
     views::Widget::InitParams init_params(
-        CreateParams(views::Widget::InitParams::TYPE_POPUP));
+        views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
+    init_params.context = CurrentContext();
+    init_params.parent = ash::Shell::GetPrimaryRootWindow()->GetChildById(
+        ash::kShellWindowId_DefaultContainer);
+    init_params.ownership =
+        views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
     views::Widget* widget = new views::Widget();
     widget->Init(init_params);
     widget->SetContentsView(notification_view_.get());
     widget->SetSize(notification_view_->GetPreferredSize());
     widget->Show();
+    EXPECT_EQ(widget, notification_view_->GetWidget());
   }
 
   void TearDown() override {
     widget()->Close();
     notification_view_.reset();
-    views::ViewsTestBase::TearDown();
-    MessageCenter::Shutdown();
+    ash::AshTestBase::TearDown();
   }
 
   SkColor GetBackgroundColor() const {
@@ -253,10 +258,8 @@
   }
 
   void DispatchGesture(const ui::GestureEventDetails& details) {
-    ui::test::EventGenerator generator(
-        notification_view()->GetWidget()->GetNativeWindow());
-    ui::GestureEvent event(0, 0, 0, ui::EventTimeForNow(), details);
-    generator.Dispatch(&event);
+    ui::GestureEvent event2(0, 0, 0, ui::EventTimeForNow(), details);
+    widget()->OnGestureEvent(&event2);
   }
 
   void BeginScroll() {
@@ -320,6 +323,7 @@
   std::string notification_id = notification()->id();
 
   BeginScroll();
+  EXPECT_EQ(0.f, GetNotificationSlideAmount());
   ScrollBy(-10);
   EXPECT_FALSE(IsRemoved(notification_id));
   EXPECT_EQ(-10.f, GetNotificationSlideAmount());
@@ -328,6 +332,7 @@
   EXPECT_EQ(0.f, GetNotificationSlideAmount());
 
   BeginScroll();
+  EXPECT_EQ(0.f, GetNotificationSlideAmount());
   ScrollBy(-200);
   EXPECT_FALSE(IsRemoved(notification_id));
   EXPECT_EQ(-200.f, GetNotificationSlideAmount());
@@ -343,6 +348,7 @@
   std::string notification_id = notification()->id();
 
   BeginScroll();
+  EXPECT_EQ(0.f, GetNotificationSlideAmount());
   ScrollBy(-10);
   EXPECT_FALSE(IsRemoved(notification_id));
   EXPECT_EQ(-10.f, GetNotificationSlideAmount());
@@ -351,6 +357,7 @@
   EXPECT_EQ(0.f, GetNotificationSlideAmount());
 
   BeginScroll();
+  EXPECT_EQ(0.f, GetNotificationSlideAmount());
   ScrollBy(-200);
   EXPECT_FALSE(IsRemoved(notification_id));
   EXPECT_EQ(-200.f, GetNotificationSlideAmount());
@@ -371,10 +378,12 @@
   std::string notification_id = notification()->id();
 
   BeginScroll();
+  EXPECT_EQ(0.f, GetNotificationSlideAmount());
   ScrollBy(-200);
   EXPECT_FALSE(IsRemoved(notification_id));
   EXPECT_LT(-200.f, GetNotificationSlideAmount());
   EndScroll();
+  EXPECT_EQ(0.f, GetNotificationSlideAmount());
   EXPECT_FALSE(IsRemoved(notification_id));
 }
 
diff --git a/ui/aura/BUILD.gn b/ui/aura/BUILD.gn
index 16f8d0d..c75b96e 100644
--- a/ui/aura/BUILD.gn
+++ b/ui/aura/BUILD.gn
@@ -266,6 +266,8 @@
     "test/ui_controls_factory_aura.h",
     "test/window_event_dispatcher_test_api.cc",
     "test/window_event_dispatcher_test_api.h",
+    "test/window_occlusion_tracker_test_api.cc",
+    "test/window_occlusion_tracker_test_api.h",
     "test/window_test_api.cc",
     "test/window_test_api.h",
   ]
diff --git a/ui/aura/event_injector.cc b/ui/aura/event_injector.cc
index d756e12..c9d9242 100644
--- a/ui/aura/event_injector.cc
+++ b/ui/aura/event_injector.cc
@@ -55,11 +55,11 @@
         event->AsLocatedEvent()->location_f());
   }
 
-  if (!remote_event_dispatcher_) {
+  if (!event_injector_) {
     env->window_tree_client_->connector()->BindInterface(
-        ui::mojom::kServiceName, &remote_event_dispatcher_);
+        ui::mojom::kServiceName, &event_injector_);
   }
-  remote_event_dispatcher_->DispatchEvent(
+  event_injector_->InjectEvent(
       host->GetDisplayId(), MapEvent(*event),
       base::BindOnce([](bool result) { DCHECK(result); }));
   return ui::EventDispatchDetails();
diff --git a/ui/aura/event_injector.h b/ui/aura/event_injector.h
index acfcf1c..bc336047f 100644
--- a/ui/aura/event_injector.h
+++ b/ui/aura/event_injector.h
@@ -5,7 +5,7 @@
 #ifndef UI_AURA_EVENT_INJECTOR_H_
 #define UI_AURA_EVENT_INJECTOR_H_
 
-#include "services/ui/public/interfaces/remote_event_dispatcher.mojom.h"
+#include "services/ui/public/interfaces/event_injector.mojom.h"
 #include "ui/aura/aura_export.h"
 
 namespace ui {
@@ -28,7 +28,7 @@
   ui::EventDispatchDetails Inject(WindowTreeHost* host, ui::Event* event);
 
  private:
-  ui::mojom::RemoteEventDispatcherPtr remote_event_dispatcher_;
+  ui::mojom::EventInjectorPtr event_injector_;
 
   DISALLOW_COPY_AND_ASSIGN(EventInjector);
 };
diff --git a/ui/aura/mus/input_method_mus.cc b/ui/aura/mus/input_method_mus.cc
index bfd2555..7366a5b 100644
--- a/ui/aura/mus/input_method_mus.cc
+++ b/ui/aura/mus/input_method_mus.cc
@@ -75,7 +75,7 @@
   UpdateTextInputType();
 }
 
-bool InputMethodMus::OnUntranslatedIMEMessage(const base::NativeEvent& event,
+bool InputMethodMus::OnUntranslatedIMEMessage(const ui::PlatformEvent& event,
                                               NativeEventResult* result) {
   // This method is not called on non-Windows platforms. See the comments for
   // ui::InputMethod::OnUntranslatedIMEMessage().
diff --git a/ui/aura/mus/input_method_mus.h b/ui/aura/mus/input_method_mus.h
index 027c733..e086071 100644
--- a/ui/aura/mus/input_method_mus.h
+++ b/ui/aura/mus/input_method_mus.h
@@ -40,7 +40,7 @@
   // Overridden from ui::InputMethod:
   void OnFocus() override;
   void OnBlur() override;
-  bool OnUntranslatedIMEMessage(const base::NativeEvent& event,
+  bool OnUntranslatedIMEMessage(const ui::PlatformEvent& event,
                                 NativeEventResult* result) override;
   ui::EventDispatchDetails DispatchKeyEvent(ui::KeyEvent* event) override;
   void OnTextInputTypeChanged(const ui::TextInputClient* client) override;
diff --git a/ui/aura/mus/window_tree_client.cc b/ui/aura/mus/window_tree_client.cc
index b7ecce8..e864bea 100644
--- a/ui/aura/mus/window_tree_client.cc
+++ b/ui/aura/mus/window_tree_client.cc
@@ -1701,7 +1701,7 @@
   if (mapped_event->type() == ui::ET_MOUSE_MOVED ||
       mapped_event->type() == ui::ET_MOUSE_DRAGGED) {
     mapped_event_with_native = std::make_unique<ui::MouseEvent>(
-        static_cast<const base::NativeEvent&>(mapped_event.get()));
+        static_cast<const ui::PlatformEvent&>(mapped_event.get()));
     // MouseEvent(NativeEvent) sets the root_location to location.
     mapped_event_with_native->set_root_location_f(
         event_location_in_screen_pixel_layout);
@@ -2341,8 +2341,8 @@
   // Check event_injector_ so we don't crash if access to the interface was
   // refused.
   if (event_injector_) {
-    event_injector_->DispatchEvent(display_id, ui::Event::Clone(event),
-                                   base::DoNothing());
+    event_injector_->InjectEvent(display_id, ui::Event::Clone(event),
+                                 base::DoNothing());
   }
 }
 
diff --git a/ui/aura/mus/window_tree_client.h b/ui/aura/mus/window_tree_client.h
index bc876ae..44dc350 100644
--- a/ui/aura/mus/window_tree_client.h
+++ b/ui/aura/mus/window_tree_client.h
@@ -24,7 +24,7 @@
 #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
 #include "mojo/public/cpp/bindings/associated_binding.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
-#include "services/ui/public/interfaces/remote_event_dispatcher.mojom.h"
+#include "services/ui/public/interfaces/event_injector.mojom.h"
 #include "services/ui/public/interfaces/window_tree.mojom.h"
 #include "ui/aura/aura_export.h"
 #include "ui/aura/client/transient_window_client_observer.h"
@@ -698,7 +698,7 @@
   // WindowManagerClient set this, but not |window_manager_internal_client_|.
   ui::mojom::WindowManagerClient* window_manager_client_ = nullptr;
 
-  ui::mojom::RemoteEventDispatcherPtr event_injector_;
+  ui::mojom::EventInjectorPtr event_injector_;
 
   bool has_pointer_watcher_ = false;
 
diff --git a/ui/aura/test/ui_controls_factory_aurax11.cc b/ui/aura/test/ui_controls_factory_aurax11.cc
index f012d14..24b88c1 100644
--- a/ui/aura/test/ui_controls_factory_aurax11.cc
+++ b/ui/aura/test/ui_controls_factory_aurax11.cc
@@ -40,7 +40,7 @@
 }
 
 // Returns true when the event is a marker event.
-bool Matcher(const base::NativeEvent& event) {
+bool Matcher(const ui::PlatformEvent& event) {
   return event->xany.type == ClientMessage &&
       event->xclient.message_type == MarkerEventAtom();
 }
diff --git a/ui/aura/test/ui_controls_factory_ozone.cc b/ui/aura/test/ui_controls_factory_ozone.cc
index cdd53a5..3839129 100644
--- a/ui/aura/test/ui_controls_factory_ozone.cc
+++ b/ui/aura/test/ui_controls_factory_ozone.cc
@@ -10,7 +10,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/ui/public/interfaces/constants.mojom.h"
-#include "services/ui/public/interfaces/remote_event_dispatcher.mojom.h"
+#include "services/ui/public/interfaces/event_injector.mojom.h"
 #include "ui/aura/client/screen_position_client.h"
 #include "ui/aura/env.h"
 #include "ui/aura/mus/window_tree_client.h"
@@ -211,7 +211,7 @@
         event_to_send = ui::Event::Clone(*event);
       }
 
-      GetRemoteEventDispatcher()->DispatchEvent(
+      GetEventInjector()->InjectEvent(
           host_->GetDisplayId(), std::move(event_to_send),
           base::BindOnce(&OnWindowServiceProcessedEvent, std::move(closure)));
       return;
@@ -276,22 +276,22 @@
     SendEventToSink(&mouse_event2, std::move(closure));
   }
 
-  // Returns the ui::mojom::RemoteEventDispatcher, which is used to send events
+  // Returns the ui::mojom::EventInjector, which is used to send events
   // to the Window Service for dispatch.
-  ui::mojom::RemoteEventDispatcher* GetRemoteEventDispatcher() {
+  ui::mojom::EventInjector* GetEventInjector() {
     DCHECK_EQ(aura::Env::Mode::MUS, aura::Env::GetInstance()->mode());
-    if (!remote_event_dispatcher_) {
+    if (!event_injector_) {
       DCHECK(aura::test::EnvTestHelper().GetWindowTreeClient());
       aura::test::EnvTestHelper()
           .GetWindowTreeClient()
           ->connector()
-          ->BindInterface(ui::mojom::kServiceName, &remote_event_dispatcher_);
+          ->BindInterface(ui::mojom::kServiceName, &event_injector_);
     }
-    return remote_event_dispatcher_.get();
+    return event_injector_.get();
   }
 
   WindowTreeHost* host_;
-  ui::mojom::RemoteEventDispatcherPtr remote_event_dispatcher_;
+  ui::mojom::EventInjectorPtr event_injector_;
 
   // Mask of the mouse buttons currently down. This is static as it needs to
   // track the state globally for all displays. A UIControlsOzone instance is
diff --git a/ui/aura/test/window_occlusion_tracker_test_api.cc b/ui/aura/test/window_occlusion_tracker_test_api.cc
new file mode 100644
index 0000000..3560066
--- /dev/null
+++ b/ui/aura/test/window_occlusion_tracker_test_api.cc
@@ -0,0 +1,25 @@
+// Copyright 2018 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 "ui/aura/test/window_occlusion_tracker_test_api.h"
+
+#include "ui/aura/window_occlusion_tracker.h"
+
+namespace aura {
+namespace test {
+
+WindowOcclusionTrackerTestApi::WindowOcclusionTrackerTestApi() = default;
+WindowOcclusionTrackerTestApi::~WindowOcclusionTrackerTestApi() = default;
+
+bool WindowOcclusionTrackerTestApi::WasOcclusionRecomputedTooManyTimes() {
+  const bool local_was_occlusion_recomputed_too_many_times =
+      WindowOcclusionTracker::GetInstance()
+          ->was_occlusion_recomputed_too_many_times_;
+  WindowOcclusionTracker::GetInstance()
+      ->was_occlusion_recomputed_too_many_times_ = false;
+  return local_was_occlusion_recomputed_too_many_times;
+}
+
+}  // namespace test
+}  // namespace aura
diff --git a/ui/aura/test/window_occlusion_tracker_test_api.h b/ui/aura/test/window_occlusion_tracker_test_api.h
new file mode 100644
index 0000000..bf11565
--- /dev/null
+++ b/ui/aura/test/window_occlusion_tracker_test_api.h
@@ -0,0 +1,29 @@
+// Copyright 2018 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 UI_AURA_TEST_WINDOW_OCCLUSION_TRACKER_TEST_API_H_
+#define UI_AURA_TEST_WINDOW_OCCLUSION_TRACKER_TEST_API_H_
+
+#include "base/macros.h"
+
+namespace aura {
+namespace test {
+
+class WindowOcclusionTrackerTestApi {
+ public:
+  WindowOcclusionTrackerTestApi();
+  ~WindowOcclusionTrackerTestApi();
+
+  // Returns true if WindowOcclusionTracker had to recompute occlusion too many
+  // times before becoming stable since the last call to this.
+  bool WasOcclusionRecomputedTooManyTimes();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(WindowOcclusionTrackerTestApi);
+};
+
+}  // namespace test
+}  // namespace aura
+
+#endif  // UI_AURA_TEST_WINDOW_OCCLUSION_TRACKER_TEST_API_H_
diff --git a/ui/aura/window.cc b/ui/aura/window.cc
index 22421e9..815056d5 100644
--- a/ui/aura/window.cc
+++ b/ui/aura/window.cc
@@ -274,7 +274,6 @@
   WindowOcclusionTracker::ScopedPauseOcclusionTracking pause_occlusion_tracking;
   for (WindowObserver& observer : observers_)
     observer.OnWindowTargetTransformChanging(this, transform);
-  gfx::Transform old_transform = layer()->transform();
   layer()->SetTransform(transform);
 }
 
diff --git a/ui/aura/window_occlusion_tracker.cc b/ui/aura/window_occlusion_tracker.cc
index dff18bd8..f1bd2aee 100644
--- a/ui/aura/window_occlusion_tracker.cc
+++ b/ui/aura/window_occlusion_tracker.cc
@@ -132,6 +132,11 @@
 
 WindowOcclusionTracker::~WindowOcclusionTracker() = default;
 
+WindowOcclusionTracker* WindowOcclusionTracker::GetInstance() {
+  DCHECK(g_tracker);
+  return g_tracker;
+}
+
 void WindowOcclusionTracker::MaybeComputeOcclusion() {
   if (g_num_pause_occlusion_tracking || num_times_occlusion_recomputed_ != 0)
     return;
@@ -352,8 +357,10 @@
   // TODO(fdoray): Remove this once we are confident that occlusion states are
   // stable after |kMaxRecomputeOcclusion| iterations in production.
   // https://crbug.com/813076
-  if (num_times_occlusion_recomputed_ == kMaxRecomputeOcclusion)
+  if (num_times_occlusion_recomputed_ == kMaxRecomputeOcclusion) {
+    was_occlusion_recomputed_too_many_times_ = true;
     base::debug::DumpWithoutCrashing();
+  }
 }
 
 bool WindowOcclusionTracker::WindowOrParentIsAnimated(Window* window) const {
@@ -490,8 +497,13 @@
 
 void WindowOcclusionTracker::OnWindowVisibilityChanged(Window* window,
                                                        bool visible) {
-  MarkRootWindowAsDirtyAndMaybeComputeOcclusionIf(
-      window, [=]() { return !WindowOrParentIsAnimated(window); });
+  MarkRootWindowAsDirtyAndMaybeComputeOcclusionIf(window, [=]() {
+    // A child isn't visible when its parent isn't IsVisible(). Therefore, there
+    // is no need to compute occlusion when Show() or Hide() is called on a
+    // window with a hidden parent.
+    return (!window->parent() || window->parent()->IsVisible()) &&
+           !WindowOrParentIsAnimated(window);
+  });
 }
 
 void WindowOcclusionTracker::OnWindowBoundsChanged(
diff --git a/ui/aura/window_occlusion_tracker.h b/ui/aura/window_occlusion_tracker.h
index c76f4f4..f609484 100644
--- a/ui/aura/window_occlusion_tracker.h
+++ b/ui/aura/window_occlusion_tracker.h
@@ -22,6 +22,10 @@
 
 namespace aura {
 
+namespace test {
+class WindowOcclusionTrackerTestApi;
+}
+
 // Notifies tracked Windows when their occlusion state change.
 //
 // To start tracking the occlusion state of a Window, call
@@ -54,6 +58,8 @@
   static void Track(Window* window);
 
  private:
+  friend class test::WindowOcclusionTrackerTestApi;
+
   struct RootWindowState {
     // Number of Windows whose occlusion state is tracked under this root
     // Window.
@@ -66,6 +72,8 @@
   WindowOcclusionTracker();
   ~WindowOcclusionTracker() override;
 
+  static WindowOcclusionTracker* GetInstance();
+
   // Recomputes the occlusion state of tracked windows under roots marked as
   // dirty in |root_windows_| if there are no active
   // ScopedPauseOcclusionTracking instance.
@@ -194,6 +202,11 @@
   // recomputed occlusion states. Always 0 when not in MaybeComputeOcclusion().
   int num_times_occlusion_recomputed_ = 0;
 
+  // Set to true when occlusion is recomputed too many times before it becomes
+  // stable. Reset in
+  // WindowOcclusionTrackerTestApi::WasOcclusionRecomputedTooManyTimes().
+  bool was_occlusion_recomputed_too_many_times_ = false;
+
   DISALLOW_COPY_AND_ASSIGN(WindowOcclusionTracker);
 };
 
diff --git a/ui/aura/window_occlusion_tracker_unittest.cc b/ui/aura/window_occlusion_tracker_unittest.cc
index 6394bd7..8ee2fd1 100644
--- a/ui/aura/window_occlusion_tracker_unittest.cc
+++ b/ui/aura/window_occlusion_tracker_unittest.cc
@@ -12,6 +12,7 @@
 #include "ui/aura/test/env_test_helper.h"
 #include "ui/aura/test/test_window_delegate.h"
 #include "ui/aura/test/test_windows.h"
+#include "ui/aura/test/window_occlusion_tracker_test_api.h"
 #include "ui/aura/window_observer.h"
 #include "ui/compositor/layer_animation_observer.h"
 #include "ui/compositor/layer_animation_sequence.h"
@@ -1443,12 +1444,15 @@
 
   DISALLOW_COPY_AND_ASSIGN(WindowDelegateChangingWindowVisibility);
 };
+
 }  // namespace
 
 // Verify that if a window changes its visibility every time it is notified that
 // its occlusion state changed, the occlusion state of all IsVisible() windows
-// is set to NOT_OCCLUDED and no infinite loop is entered.
+// is set to VISIBLE and no infinite loop is entered.
 TEST_F(WindowOcclusionTrackerTest, OcclusionStatesDontBecomeStable) {
+  test::WindowOcclusionTrackerTestApi test_api;
+
   // Create 2 superposed tracked windows.
   MockWindowDelegate* delegate_a = new MockWindowDelegate();
   delegate_a->set_expectation(Window::OcclusionState::VISIBLE);
@@ -1484,15 +1488,17 @@
   // Hide |window_d|. This will cause occlusion to be recomputed multiple times.
   // Once the maximum number of times that occlusion can be recomputed is
   // reached, the occlusion state of all IsVisible() windows should be set to
-  // NOT_OCCLUDED.
+  // VISIBLE.
   delegate_a->set_expectation(Window::OcclusionState::VISIBLE);
   delegate_d->set_expectation(Window::OcclusionState::HIDDEN);
+  EXPECT_FALSE(test_api.WasOcclusionRecomputedTooManyTimes());
   window_d->Hide();
+  EXPECT_TRUE(test_api.WasOcclusionRecomputedTooManyTimes());
   EXPECT_FALSE(delegate_a->is_expecting_call());
   EXPECT_FALSE(delegate_d->is_expecting_call());
 }
 
-// Verify that the occlusion states are correctly update when a branch of the
+// Verify that the occlusion states are correctly updated when a branch of the
 // tree is hidden.
 TEST_F(WindowOcclusionTrackerTest, HideTreeBranch) {
   // Create a branch of 3 tracked windows. Expect them to be visible.
@@ -1521,4 +1527,92 @@
   EXPECT_FALSE(delegate_c->is_expecting_call());
 }
 
+namespace {
+
+class WindowDelegateHidingWindow : public MockWindowDelegate {
+ public:
+  WindowDelegateHidingWindow() = default;
+
+  void set_window_to_update(Window* window) { window_to_update_ = window; }
+
+  // MockWindowDelegate:
+  void OnWindowOcclusionChanged(
+      Window::OcclusionState occlusion_state) override {
+    MockWindowDelegate::OnWindowOcclusionChanged(occlusion_state);
+    if (!window_to_update_)
+      return;
+
+    window_to_update_->Hide();
+  }
+
+ private:
+  Window* window_to_update_ = nullptr;
+
+  DISALLOW_COPY_AND_ASSIGN(WindowDelegateHidingWindow);
+};
+
+class WindowDelegateAddingAndHidingChild : public MockWindowDelegate {
+ public:
+  WindowDelegateAddingAndHidingChild(WindowOcclusionTrackerTest* test)
+      : test_(test) {}
+
+  void set_window_to_update(Window* window) { window_to_update_ = window; }
+
+  // MockWindowDelegate:
+  void OnWindowOcclusionChanged(
+      Window::OcclusionState occlusion_state) override {
+    MockWindowDelegate::OnWindowOcclusionChanged(occlusion_state);
+
+    if (!window_to_update_)
+      return;
+
+    // Create a child window and hide it. Since this code runs when occlusion
+    // has already been recomputed twice, if one of the operations below causes
+    // occlusion to be recomputed, the test will fail with a DCHECK.
+    Window* window =
+        test_->CreateUntrackedWindow(gfx::Rect(0, 0, 5, 5), window_to_update_);
+    window->Hide();
+  }
+
+ private:
+  WindowOcclusionTrackerTest* test_;
+  Window* window_to_update_ = nullptr;
+
+  DISALLOW_COPY_AND_ASSIGN(WindowDelegateAddingAndHidingChild);
+};
+
+}  // namespace
+
+// Verify that hiding a window that has a hidden parent doesn't cause occlusion
+// to be recomputed.
+TEST_F(WindowOcclusionTrackerTest,
+       HideWindowWithHiddenParentOnOcclusionChange) {
+  test::WindowOcclusionTrackerTestApi test_api;
+
+  auto* delegate_a = new WindowDelegateAddingAndHidingChild(this);
+  delegate_a->set_expectation(Window::OcclusionState::VISIBLE);
+  Window* window_a = CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10));
+  EXPECT_FALSE(delegate_a->is_expecting_call());
+
+  auto* delegate_b = new WindowDelegateHidingWindow();
+  delegate_b->set_expectation(Window::OcclusionState::VISIBLE);
+  Window* window_b = CreateTrackedWindow(delegate_b, gfx::Rect(0, 10, 10, 10));
+  EXPECT_FALSE(delegate_b->is_expecting_call());
+
+  // When |window_b| is hidden, it will hide |window_a|. |window_a| will in turn
+  // add a child to itself and hide it.
+  delegate_a->set_window_to_update(window_a);
+  delegate_b->set_window_to_update(window_a);
+
+  delegate_a->set_expectation(Window::OcclusionState::HIDDEN);
+  delegate_b->set_expectation(Window::OcclusionState::HIDDEN);
+  EXPECT_FALSE(test_api.WasOcclusionRecomputedTooManyTimes());
+  window_b->Hide();
+  // Hiding a child to |window_a| and hiding it shouldn't cause occlusion to be
+  // recomputed too many times.
+  EXPECT_FALSE(test_api.WasOcclusionRecomputedTooManyTimes());
+  EXPECT_FALSE(delegate_a->is_expecting_call());
+  EXPECT_FALSE(delegate_b->is_expecting_call());
+}
+
 }  // namespace aura
diff --git a/ui/aura/window_tree_host.h b/ui/aura/window_tree_host.h
index 2fb9a30..c95bf4a 100644
--- a/ui/aura/window_tree_host.h
+++ b/ui/aura/window_tree_host.h
@@ -10,7 +10,6 @@
 #include <memory>
 
 #include "base/containers/flat_set.h"
-#include "base/event_types.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/message_loop/message_loop.h"
@@ -22,6 +21,7 @@
 #include "ui/compositor/compositor_observer.h"
 #include "ui/display/display_observer.h"
 #include "ui/events/event_source.h"
+#include "ui/events/platform_event.h"
 #include "ui/gfx/native_widget_types.h"
 
 namespace gfx {
diff --git a/ui/base/clipboard/clipboard_aurax11.cc b/ui/base/clipboard/clipboard_aurax11.cc
index 3745f43..d071d15 100644
--- a/ui/base/clipboard/clipboard_aurax11.cc
+++ b/ui/base/clipboard/clipboard_aurax11.cc
@@ -46,7 +46,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 // Uses the XFixes API to provide sequence numbers for GetSequenceNumber().
-class SelectionChangeObserver : public ui::PlatformEventObserver {
+class SelectionChangeObserver : public PlatformEventObserver {
  public:
   static SelectionChangeObserver* GetInstance();
 
@@ -61,9 +61,9 @@
   SelectionChangeObserver();
   ~SelectionChangeObserver() override;
 
-  // ui::PlatformEventObserver:
-  void WillProcessEvent(const ui::PlatformEvent& event) override;
-  void DidProcessEvent(const ui::PlatformEvent& event) override {}
+  // PlatformEventObserver:
+  void WillProcessEvent(const PlatformEvent& event) override;
+  void DidProcessEvent(const PlatformEvent& event) override {}
 
   int event_base_;
   Atom clipboard_atom_;
@@ -95,7 +95,7 @@
                                XFixesSelectionWindowDestroyNotifyMask |
                                XFixesSelectionClientCloseNotifyMask);
 
-    ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this);
+    PlatformEventSource::GetInstance()->AddPlatformEventObserver(this);
   }
 }
 
@@ -107,7 +107,7 @@
   return base::Singleton<SelectionChangeObserver>::get();
 }
 
-void SelectionChangeObserver::WillProcessEvent(const ui::PlatformEvent& event) {
+void SelectionChangeObserver::WillProcessEvent(const PlatformEvent& event) {
   if (event->type == event_base_ + XFixesSelectionNotify) {
     XFixesSelectionNotifyEvent* ev =
         reinterpret_cast<XFixesSelectionNotifyEvent*>(event);
diff --git a/ui/base/dragdrop/os_exchange_data_provider_aurax11.h b/ui/base/dragdrop/os_exchange_data_provider_aurax11.h
index 6457584..f8e60b3 100644
--- a/ui/base/dragdrop/os_exchange_data_provider_aurax11.h
+++ b/ui/base/dragdrop/os_exchange_data_provider_aurax11.h
@@ -29,7 +29,7 @@
 // OSExchangeData::Provider implementation for aura on linux.
 class UI_BASE_EXPORT OSExchangeDataProviderAuraX11
     : public OSExchangeData::Provider,
-      public ui::PlatformEventDispatcher {
+      public PlatformEventDispatcher {
  public:
   // |x_window| is the window the cursor is over, and |selection| is the set of
   // data being offered.
@@ -91,7 +91,7 @@
   gfx::ImageSkia GetDragImage() const override;
   gfx::Vector2d GetDragImageOffset() const override;
 
-  // ui::PlatformEventDispatcher:
+  // PlatformEventDispatcher:
   bool CanDispatchEvent(const PlatformEvent& event) override;
   uint32_t DispatchEvent(const PlatformEvent& event) override;
 
diff --git a/ui/base/dragdrop/os_exchange_data_unittest.cc b/ui/base/dragdrop/os_exchange_data_unittest.cc
index 7345412..62d98d1 100644
--- a/ui/base/dragdrop/os_exchange_data_unittest.cc
+++ b/ui/base/dragdrop/os_exchange_data_unittest.cc
@@ -23,7 +23,7 @@
   OSExchangeDataTest()
       : scoped_task_environment_(
             base::test::ScopedTaskEnvironment::MainThreadType::UI),
-        event_source_(ui::PlatformEventSource::CreateDefault()) {}
+        event_source_(PlatformEventSource::CreateDefault()) {}
 
  private:
   base::test::ScopedTaskEnvironment scoped_task_environment_;
diff --git a/ui/base/ime/composition_text_unittest.cc b/ui/base/ime/composition_text_unittest.cc
index 3a1899e..9c57c23 100644
--- a/ui/base/ime/composition_text_unittest.cc
+++ b/ui/base/ime/composition_text_unittest.cc
@@ -13,17 +13,18 @@
 
 TEST(CompositionTextTest, CopyTest) {
   const base::string16 kSampleText = base::UTF8ToUTF16("Sample Text");
-  const ImeTextSpan kSampleUnderline1(
-      ImeTextSpan::Type::kComposition, 10, 20, SK_ColorBLACK,
-      ImeTextSpan::Thickness::kThin, SK_ColorTRANSPARENT);
+  const ImeTextSpan kSampleUnderline1(ImeTextSpan::Type::kComposition, 10, 20,
+                                      ImeTextSpan::Thickness::kThin,
+                                      SK_ColorTRANSPARENT);
 
-  const ImeTextSpan kSampleUnderline2(
-      ImeTextSpan::Type::kComposition, 11, 21, SK_ColorBLACK,
-      ImeTextSpan::Thickness::kThick, SK_ColorTRANSPARENT);
+  const ImeTextSpan kSampleUnderline2(ImeTextSpan::Type::kComposition, 11, 21,
+                                      ImeTextSpan::Thickness::kThick,
+                                      SK_ColorTRANSPARENT);
 
-  const ImeTextSpan kSampleUnderline3(
-      ImeTextSpan::Type::kComposition, 12, 22, SK_ColorRED,
-      ImeTextSpan::Thickness::kThin, SK_ColorTRANSPARENT);
+  ImeTextSpan kSampleUnderline3(ImeTextSpan::Type::kComposition, 12, 22,
+                                ImeTextSpan::Thickness::kThin,
+                                SK_ColorTRANSPARENT);
+  kSampleUnderline3.underline_color = SK_ColorRED;
 
   // Make CompositionText
   CompositionText text;
diff --git a/ui/base/ime/composition_text_util_pango.cc b/ui/base/ime/composition_text_util_pango.cc
index 1237585..e5980f36 100644
--- a/ui/base/ime/composition_text_util_pango.cc
+++ b/ui/base/ime/composition_text_util_pango.cc
@@ -74,10 +74,10 @@
           pango_attr_iterator_get(iter, PANGO_ATTR_UNDERLINE);
 
       if (background_attr || underline_attr) {
-        // Use a black thin underline by default.
+        // Use a thin underline with text color by default.
         ImeTextSpan ime_text_span(ImeTextSpan::Type::kComposition,
                                   char16_offsets[start], char16_offsets[end],
-                                  SK_ColorBLACK, ImeTextSpan::Thickness::kThin,
+                                  ImeTextSpan::Thickness::kThin,
                                   SK_ColorTRANSPARENT);
 
         // Always use thick underline for a range with background color, which
@@ -108,10 +108,10 @@
     pango_attr_iterator_destroy(iter);
   }
 
-  // Use a black thin underline by default.
+  // Use a thin underline with text color by default.
   if (composition->ime_text_spans.empty()) {
     composition->ime_text_spans.push_back(
-        ImeTextSpan(ImeTextSpan::Type::kComposition, 0, length, SK_ColorBLACK,
+        ImeTextSpan(ImeTextSpan::Type::kComposition, 0, length,
                     ImeTextSpan::Thickness::kThin, SK_ColorTRANSPARENT));
   }
 }
diff --git a/ui/base/ime/composition_text_util_pango_unittest.cc b/ui/base/ime/composition_text_util_pango_unittest.cc
index 593a4ac8..26e34395 100644
--- a/ui/base/ime/composition_text_util_pango_unittest.cc
+++ b/ui/base/ime/composition_text_util_pango_unittest.cc
@@ -47,11 +47,11 @@
       {PANGO_ATTR_BACKGROUND, 0, 4, 7},
       {PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_SINGLE, 8, 13},
       {0, 0, 0, 0}},
-     {{0, 3, SK_ColorBLACK, ui::ImeTextSpan::Thickness::kThin,
+     {{0, 3, SK_ColorTRANSPARENT, ui::ImeTextSpan::Thickness::kThin,
        SK_ColorTRANSPARENT},
-      {4, 7, SK_ColorBLACK, ui::ImeTextSpan::Thickness::kThick,
+      {4, 7, SK_ColorTRANSPARENT, ui::ImeTextSpan::Thickness::kThick,
        SK_ColorTRANSPARENT},
-      {8, 13, SK_ColorBLACK, ui::ImeTextSpan::Thickness::kThin,
+      {8, 13, SK_ColorTRANSPARENT, ui::ImeTextSpan::Thickness::kThin,
        SK_ColorTRANSPARENT},
       {0, 0, 0, ui::ImeTextSpan::Thickness::kThin, SK_ColorTRANSPARENT}}},
 
@@ -61,11 +61,11 @@
       {PANGO_ATTR_BACKGROUND, 0, 4, 7},
       {PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_SINGLE, 8, 20},
       {0, 0, 0, 0}},
-     {{0, 3, SK_ColorBLACK, ui::ImeTextSpan::Thickness::kThin,
+     {{0, 3, SK_ColorTRANSPARENT, ui::ImeTextSpan::Thickness::kThin,
        SK_ColorTRANSPARENT},
-      {4, 7, SK_ColorBLACK, ui::ImeTextSpan::Thickness::kThick,
+      {4, 7, SK_ColorTRANSPARENT, ui::ImeTextSpan::Thickness::kThick,
        SK_ColorTRANSPARENT},
-      {8, 13, SK_ColorBLACK, ui::ImeTextSpan::Thickness::kThin,
+      {8, 13, SK_ColorTRANSPARENT, ui::ImeTextSpan::Thickness::kThin,
        SK_ColorTRANSPARENT},
       {0, 0, 0, ui::ImeTextSpan::Thickness::kThin, SK_ColorTRANSPARENT}}},
 
@@ -75,18 +75,18 @@
       {PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_ERROR, 4, 7},
       {PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_SINGLE, 8, 13},
       {0, 0, 0, 0}},
-     {{0, 3, SK_ColorBLACK, ui::ImeTextSpan::Thickness::kThin,
+     {{0, 3, SK_ColorTRANSPARENT, ui::ImeTextSpan::Thickness::kThin,
        SK_ColorTRANSPARENT},
       {4, 7, SK_ColorRED, ui::ImeTextSpan::Thickness::kThin,
        SK_ColorTRANSPARENT},
-      {8, 13, SK_ColorBLACK, ui::ImeTextSpan::Thickness::kThin,
+      {8, 13, SK_ColorTRANSPARENT, ui::ImeTextSpan::Thickness::kThin,
        SK_ColorTRANSPARENT},
       {0, 0, 0, ui::ImeTextSpan::Thickness::kThin, SK_ColorTRANSPARENT}}},
 
     // Default underline.
     {"One Two Three",
      {{0, 0, 0, 0}},
-     {{0, 13, SK_ColorBLACK, ui::ImeTextSpan::Thickness::kThin,
+     {{0, 13, SK_ColorTRANSPARENT, ui::ImeTextSpan::Thickness::kThin,
        SK_ColorTRANSPARENT},
       {0, 0, 0, ui::ImeTextSpan::Thickness::kThin, SK_ColorTRANSPARENT}}},
 
@@ -98,13 +98,13 @@
       {PANGO_ATTR_BACKGROUND, 0, 5, 7},
       {PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_SINGLE, 7, 13},
       {0, 0, 0, 0}},
-     {{0, 3, SK_ColorBLACK, ui::ImeTextSpan::Thickness::kThin,
+     {{0, 3, SK_ColorTRANSPARENT, ui::ImeTextSpan::Thickness::kThin,
        SK_ColorTRANSPARENT},
-      {3, 5, SK_ColorBLACK, ui::ImeTextSpan::Thickness::kThin,
+      {3, 5, SK_ColorTRANSPARENT, ui::ImeTextSpan::Thickness::kThin,
        SK_ColorTRANSPARENT},
-      {5, 9, SK_ColorBLACK, ui::ImeTextSpan::Thickness::kThick,
+      {5, 9, SK_ColorTRANSPARENT, ui::ImeTextSpan::Thickness::kThick,
        SK_ColorTRANSPARENT},
-      {9, 15, SK_ColorBLACK, ui::ImeTextSpan::Thickness::kThin,
+      {9, 15, SK_ColorTRANSPARENT, ui::ImeTextSpan::Thickness::kThin,
        SK_ColorTRANSPARENT},
       {0, 0, 0, ui::ImeTextSpan::Thickness::kThin, SK_ColorTRANSPARENT}}},
 };
diff --git a/ui/base/ime/dummy_input_method.cc b/ui/base/ime/dummy_input_method.cc
index 9b6b2cd..99bacf1f 100644
--- a/ui/base/ime/dummy_input_method.cc
+++ b/ui/base/ime/dummy_input_method.cc
@@ -22,7 +22,7 @@
 void DummyInputMethod::OnBlur() {
 }
 
-bool DummyInputMethod::OnUntranslatedIMEMessage(const base::NativeEvent& event,
+bool DummyInputMethod::OnUntranslatedIMEMessage(const PlatformEvent& event,
                                                 NativeEventResult* result) {
   return false;
 }
diff --git a/ui/base/ime/dummy_input_method.h b/ui/base/ime/dummy_input_method.h
index 6a9201f..ed2f97e 100644
--- a/ui/base/ime/dummy_input_method.h
+++ b/ui/base/ime/dummy_input_method.h
@@ -21,7 +21,7 @@
   void SetDelegate(internal::InputMethodDelegate* delegate) override;
   void OnFocus() override;
   void OnBlur() override;
-  bool OnUntranslatedIMEMessage(const base::NativeEvent& event,
+  bool OnUntranslatedIMEMessage(const PlatformEvent& event,
                                 NativeEventResult* result) override;
   void SetFocusedTextInputClient(TextInputClient* client) override;
   void DetachTextInputClient(TextInputClient* client) override;
diff --git a/ui/base/ime/ime_text_span.cc b/ui/base/ime/ime_text_span.cc
index 489fb5a..14b482e 100644
--- a/ui/base/ime/ime_text_span.cc
+++ b/ui/base/ime/ime_text_span.cc
@@ -9,24 +9,20 @@
 
 namespace ui {
 
-ImeTextSpan::ImeTextSpan()
-    : ImeTextSpan(0, 0, SK_ColorTRANSPARENT, Thickness::kThin) {}
+ImeTextSpan::ImeTextSpan() : ImeTextSpan(0, 0, Thickness::kThin) {}
 
 ImeTextSpan::ImeTextSpan(uint32_t start_offset,
                          uint32_t end_offset,
-                         SkColor underline_color,
                          Thickness thickness)
     : ImeTextSpan(Type::kComposition,
                   start_offset,
                   end_offset,
-                  underline_color,
                   thickness,
                   SK_ColorTRANSPARENT) {}
 
 ImeTextSpan::ImeTextSpan(Type type,
                          uint32_t start_offset,
                          uint32_t end_offset,
-                         SkColor underline_color,
                          Thickness thickness,
                          SkColor background_color,
                          SkColor suggestion_highlight_color,
@@ -34,7 +30,6 @@
     : type(type),
       start_offset(start_offset),
       end_offset(end_offset),
-      underline_color(underline_color),
       thickness(thickness),
       background_color(background_color),
       suggestion_highlight_color(suggestion_highlight_color),
diff --git a/ui/base/ime/ime_text_span.h b/ui/base/ime/ime_text_span.h
index d16ca59..e47064a 100644
--- a/ui/base/ime/ime_text_span.h
+++ b/ui/base/ime/ime_text_span.h
@@ -42,13 +42,11 @@
   // TODO(huangs): remove this constructor.
   ImeTextSpan(uint32_t start_offset,
               uint32_t end_offset,
-              SkColor underline_color,
               Thickness thickness);
   ImeTextSpan(
       Type type,
       uint32_t start_offset,
       uint32_t end_offset,
-      SkColor underline_color,
       Thickness thickness,
       SkColor background_color,
       SkColor suggestion_highlight_color = SK_ColorTRANSPARENT,
@@ -75,7 +73,7 @@
   Type type;
   uint32_t start_offset;
   uint32_t end_offset;
-  SkColor underline_color;
+  SkColor underline_color = SK_ColorTRANSPARENT;
   Thickness thickness;
   SkColor background_color;
   SkColor suggestion_highlight_color;
diff --git a/ui/base/ime/input_method.h b/ui/base/ime/input_method.h
index fad2ecc..fc15cd9 100644
--- a/ui/base/ime/input_method.h
+++ b/ui/base/ime/input_method.h
@@ -11,11 +11,11 @@
 #include <string>
 #include <vector>
 
-#include "base/event_types.h"
 #include "build/build_config.h"
 #include "ui/base/ime/text_input_mode.h"
 #include "ui/base/ime/text_input_type.h"
 #include "ui/events/event_dispatcher.h"
+#include "ui/events/platform_event.h"
 #include "ui/gfx/geometry/rect.h"
 
 namespace extensions {
@@ -80,7 +80,7 @@
   // translated into other predefined event callbacks. Currently this method is
   // used only for IME functionalities specific to Windows.
   // TODO(ime): Break down these messages into platform-neutral methods.
-  virtual bool OnUntranslatedIMEMessage(const base::NativeEvent& event,
+  virtual bool OnUntranslatedIMEMessage(const PlatformEvent& event,
                                         NativeEventResult* result) = 0;
 
   // Sets the text input client which receives text input events such as
diff --git a/ui/base/ime/input_method_auralinux.cc b/ui/base/ime/input_method_auralinux.cc
index 04a5ed5..3e325191 100644
--- a/ui/base/ime/input_method_auralinux.cc
+++ b/ui/base/ime/input_method_auralinux.cc
@@ -46,9 +46,8 @@
 
 // Overriden from InputMethod.
 
-bool InputMethodAuraLinux::OnUntranslatedIMEMessage(
-    const base::NativeEvent& event,
-    NativeEventResult* result) {
+bool InputMethodAuraLinux::OnUntranslatedIMEMessage(const PlatformEvent& event,
+                                                    NativeEventResult* result) {
   return false;
 }
 
diff --git a/ui/base/ime/input_method_auralinux.h b/ui/base/ime/input_method_auralinux.h
index 7a2adae8..916d960 100644
--- a/ui/base/ime/input_method_auralinux.h
+++ b/ui/base/ime/input_method_auralinux.h
@@ -27,7 +27,7 @@
   LinuxInputMethodContext* GetContextForTesting(bool is_simple);
 
   // Overriden from InputMethod.
-  bool OnUntranslatedIMEMessage(const base::NativeEvent& event,
+  bool OnUntranslatedIMEMessage(const PlatformEvent& event,
                                 NativeEventResult* result) override;
   ui::EventDispatchDetails DispatchKeyEvent(ui::KeyEvent* event) override;
   void OnTextInputTypeChanged(const TextInputClient* client) override;
diff --git a/ui/base/ime/input_method_base_unittest.cc b/ui/base/ime/input_method_base_unittest.cc
index cccce2d7..2f873f0 100644
--- a/ui/base/ime/input_method_base_unittest.cc
+++ b/ui/base/ime/input_method_base_unittest.cc
@@ -141,7 +141,7 @@
  private:
   // Overriden from InputMethod.
   bool OnUntranslatedIMEMessage(
-      const base::NativeEvent& event,
+      const PlatformEvent& event,
       InputMethod::NativeEventResult* result) override {
     return false;
   }
diff --git a/ui/base/ime/input_method_chromeos.cc b/ui/base/ime/input_method_chromeos.cc
index d0b3d83..51c26741 100644
--- a/ui/base/ime/input_method_chromeos.cc
+++ b/ui/base/ime/input_method_chromeos.cc
@@ -146,9 +146,8 @@
   return ProcessKeyEventDone(event, std::move(ack_callback), false);
 }
 
-bool InputMethodChromeOS::OnUntranslatedIMEMessage(
-    const base::NativeEvent& event,
-    NativeEventResult* result) {
+bool InputMethodChromeOS::OnUntranslatedIMEMessage(const PlatformEvent& event,
+                                                   NativeEventResult* result) {
   return false;
 }
 
@@ -704,9 +703,9 @@
         continue;
       ImeTextSpan ime_text_span(ui::ImeTextSpan::Type::kComposition,
                                 char16_offsets[start], char16_offsets[end],
-                                text_ime_text_spans[i].underline_color,
                                 text_ime_text_spans[i].thickness,
                                 text_ime_text_spans[i].background_color);
+      ime_text_span.underline_color = text_ime_text_spans[i].underline_color;
       out_composition->ime_text_spans.push_back(ime_text_span);
     }
   }
@@ -717,7 +716,7 @@
     const uint32_t end = text.selection.end();
     ImeTextSpan ime_text_span(ui::ImeTextSpan::Type::kComposition,
                               char16_offsets[start], char16_offsets[end],
-                              SK_ColorBLACK, ui::ImeTextSpan::Thickness::kThick,
+                              ui::ImeTextSpan::Thickness::kThick,
                               SK_ColorTRANSPARENT);
     out_composition->ime_text_spans.push_back(ime_text_span);
 
@@ -733,11 +732,11 @@
     }
   }
 
-  // Use a black thin underline by default.
+  // Use a thin underline with text color by default.
   if (out_composition->ime_text_spans.empty()) {
-    out_composition->ime_text_spans.push_back(ImeTextSpan(
-        ui::ImeTextSpan::Type::kComposition, 0, length, SK_ColorBLACK,
-        ui::ImeTextSpan::Thickness::kThin, SK_ColorTRANSPARENT));
+    out_composition->ime_text_spans.push_back(
+        ImeTextSpan(ui::ImeTextSpan::Type::kComposition, 0, length,
+                    ui::ImeTextSpan::Thickness::kThin, SK_ColorTRANSPARENT));
   }
 }
 
diff --git a/ui/base/ime/input_method_chromeos.h b/ui/base/ime/input_method_chromeos.h
index 24859210..e3bcd5b 100644
--- a/ui/base/ime/input_method_chromeos.h
+++ b/ui/base/ime/input_method_chromeos.h
@@ -33,7 +33,7 @@
                                             AckCallback ack_callback);
 
   // Overridden from InputMethod:
-  bool OnUntranslatedIMEMessage(const base::NativeEvent& event,
+  bool OnUntranslatedIMEMessage(const PlatformEvent& event,
                                 NativeEventResult* result) override;
   ui::EventDispatchDetails DispatchKeyEvent(ui::KeyEvent* event) override;
   void OnTextInputTypeChanged(const TextInputClient* client) override;
diff --git a/ui/base/ime/input_method_chromeos_unittest.cc b/ui/base/ime/input_method_chromeos_unittest.cc
index 8019223..9dff2f2 100644
--- a/ui/base/ime/input_method_chromeos_unittest.cc
+++ b/ui/base/ime/input_method_chromeos_unittest.cc
@@ -547,8 +547,7 @@
   CompositionText composition_text;
   composition_text.text = kSampleText;
   ImeTextSpan underline(ImeTextSpan::Type::kComposition, 1UL, 4UL,
-                        SK_ColorBLACK, ui::ImeTextSpan::Thickness::kThin,
-                        SK_ColorTRANSPARENT);
+                        ui::ImeTextSpan::Thickness::kThin, SK_ColorTRANSPARENT);
   composition_text.ime_text_spans.push_back(underline);
 
   CompositionText composition_text2;
@@ -563,8 +562,9 @@
             composition_text2.ime_text_spans[0].start_offset);
   EXPECT_EQ(GetOffsetInUTF16(kSampleText, underline.end_offset),
             composition_text2.ime_text_spans[0].end_offset);
-  // Single underline represents as black thin line.
-  EXPECT_EQ(SK_ColorBLACK, composition_text2.ime_text_spans[0].underline_color);
+  // Single underline represents as thin line with text color.
+  EXPECT_EQ(SK_ColorTRANSPARENT,
+            composition_text2.ime_text_spans[0].underline_color);
   EXPECT_EQ(ui::ImeTextSpan::Thickness::kThin,
             composition_text2.ime_text_spans[0].thickness);
   EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT),
@@ -578,7 +578,7 @@
   CompositionText composition_text;
   composition_text.text = kSampleText;
   ImeTextSpan underline(ImeTextSpan::Type::kComposition, 1UL, 4UL,
-                        SK_ColorBLACK, ui::ImeTextSpan::Thickness::kThick,
+                        ui::ImeTextSpan::Thickness::kThick,
                         SK_ColorTRANSPARENT);
   composition_text.ime_text_spans.push_back(underline);
 
@@ -594,8 +594,9 @@
             composition_text2.ime_text_spans[0].start_offset);
   EXPECT_EQ(GetOffsetInUTF16(kSampleText, underline.end_offset),
             composition_text2.ime_text_spans[0].end_offset);
-  // Double underline represents as black thick line.
-  EXPECT_EQ(SK_ColorBLACK, composition_text2.ime_text_spans[0].underline_color);
+  // Double underline represents as thick line with text color.
+  EXPECT_EQ(SK_ColorTRANSPARENT,
+            composition_text2.ime_text_spans[0].underline_color);
   EXPECT_EQ(ui::ImeTextSpan::Thickness::kThick,
             composition_text2.ime_text_spans[0].thickness);
   EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT),
@@ -608,8 +609,9 @@
   // Set up chromeos composition text with one underline attribute.
   CompositionText composition_text;
   composition_text.text = kSampleText;
-  ImeTextSpan underline(ImeTextSpan::Type::kComposition, 1UL, 4UL, SK_ColorRED,
+  ImeTextSpan underline(ImeTextSpan::Type::kComposition, 1UL, 4UL,
                         ui::ImeTextSpan::Thickness::kThin, SK_ColorTRANSPARENT);
+  underline.underline_color = SK_ColorRED;
   composition_text.ime_text_spans.push_back(underline);
 
   CompositionText composition_text2;
@@ -649,7 +651,8 @@
             composition_text2.ime_text_spans[0].start_offset);
   EXPECT_EQ(GetOffsetInUTF16(kSampleText, composition_text.selection.end()),
             composition_text2.ime_text_spans[0].end_offset);
-  EXPECT_EQ(SK_ColorBLACK, composition_text2.ime_text_spans[0].underline_color);
+  EXPECT_EQ(SK_ColorTRANSPARENT,
+            composition_text2.ime_text_spans[0].underline_color);
   EXPECT_EQ(ui::ImeTextSpan::Thickness::kThick,
             composition_text2.ime_text_spans[0].thickness);
   EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT),
@@ -681,7 +684,8 @@
             composition_text2.ime_text_spans[0].start_offset);
   EXPECT_EQ(GetOffsetInUTF16(kSampleText, composition_text.selection.end()),
             composition_text2.ime_text_spans[0].end_offset);
-  EXPECT_EQ(SK_ColorBLACK, composition_text2.ime_text_spans[0].underline_color);
+  EXPECT_EQ(SK_ColorTRANSPARENT,
+            composition_text2.ime_text_spans[0].underline_color);
   EXPECT_EQ(ui::ImeTextSpan::Thickness::kThick,
             composition_text2.ime_text_spans[0].thickness);
   EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT),
@@ -713,7 +717,8 @@
             composition_text2.ime_text_spans[0].start_offset);
   EXPECT_EQ(GetOffsetInUTF16(kSampleText, composition_text.selection.end()),
             composition_text2.ime_text_spans[0].end_offset);
-  EXPECT_EQ(SK_ColorBLACK, composition_text2.ime_text_spans[0].underline_color);
+  EXPECT_EQ(SK_ColorTRANSPARENT,
+            composition_text2.ime_text_spans[0].underline_color);
   EXPECT_EQ(ui::ImeTextSpan::Thickness::kThick,
             composition_text2.ime_text_spans[0].thickness);
   EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT),
diff --git a/ui/base/ime/input_method_mac.h b/ui/base/ime/input_method_mac.h
index 25d3718..7a2630d 100644
--- a/ui/base/ime/input_method_mac.h
+++ b/ui/base/ime/input_method_mac.h
@@ -20,7 +20,7 @@
   ~InputMethodMac() override;
 
   // Overriden from InputMethod.
-  bool OnUntranslatedIMEMessage(const base::NativeEvent& event,
+  bool OnUntranslatedIMEMessage(const PlatformEvent& event,
                                 NativeEventResult* result) override;
   ui::EventDispatchDetails DispatchKeyEvent(ui::KeyEvent* event) override;
   void OnCaretBoundsChanged(const TextInputClient* client) override;
diff --git a/ui/base/ime/input_method_mac.mm b/ui/base/ime/input_method_mac.mm
index d048773..a6fdf24 100644
--- a/ui/base/ime/input_method_mac.mm
+++ b/ui/base/ime/input_method_mac.mm
@@ -15,7 +15,7 @@
 InputMethodMac::~InputMethodMac() {
 }
 
-bool InputMethodMac::OnUntranslatedIMEMessage(const base::NativeEvent& event,
+bool InputMethodMac::OnUntranslatedIMEMessage(const PlatformEvent& event,
                                               NativeEventResult* result) {
   return false;
 }
diff --git a/ui/base/ime/input_method_minimal.cc b/ui/base/ime/input_method_minimal.cc
index d040d9f..4462dbd7 100644
--- a/ui/base/ime/input_method_minimal.cc
+++ b/ui/base/ime/input_method_minimal.cc
@@ -19,9 +19,8 @@
 
 InputMethodMinimal::~InputMethodMinimal() {}
 
-bool InputMethodMinimal::OnUntranslatedIMEMessage(
-    const base::NativeEvent& event,
-    NativeEventResult* result) {
+bool InputMethodMinimal::OnUntranslatedIMEMessage(const PlatformEvent& event,
+                                                  NativeEventResult* result) {
   return false;
 }
 
diff --git a/ui/base/ime/input_method_minimal.h b/ui/base/ime/input_method_minimal.h
index 96359226..4a69d89 100644
--- a/ui/base/ime/input_method_minimal.h
+++ b/ui/base/ime/input_method_minimal.h
@@ -18,7 +18,7 @@
   ~InputMethodMinimal() override;
 
   // Overriden from InputMethod.
-  bool OnUntranslatedIMEMessage(const base::NativeEvent& event,
+  bool OnUntranslatedIMEMessage(const PlatformEvent& event,
                                 NativeEventResult* result) override;
   ui::EventDispatchDetails DispatchKeyEvent(ui::KeyEvent* event) override;
   void OnCaretBoundsChanged(const TextInputClient* client) override;
diff --git a/ui/base/ime/input_method_win.cc b/ui/base/ime/input_method_win.cc
index fc430495..4c5403d 100644
--- a/ui/base/ime/input_method_win.cc
+++ b/ui/base/ime/input_method_win.cc
@@ -52,7 +52,7 @@
 }
 
 bool InputMethodWin::OnUntranslatedIMEMessage(
-    const base::NativeEvent& event,
+    const PlatformEvent& event,
     InputMethod::NativeEventResult* result) {
   LRESULT original_result = 0;
   BOOL handled = FALSE;
@@ -100,7 +100,7 @@
   if (!event->HasNativeEvent())
     return DispatchFabricatedKeyEvent(event);
 
-  const base::NativeEvent& native_key_event = event->native_event();
+  const PlatformEvent& native_key_event = event->native_event();
   BOOL handled = FALSE;
   if (native_key_event.message == WM_CHAR) {
     auto ref = weak_ptr_factory_.GetWeakPtr();
diff --git a/ui/base/ime/input_method_win.h b/ui/base/ime/input_method_win.h
index e75a875..006adc0 100644
--- a/ui/base/ime/input_method_win.h
+++ b/ui/base/ime/input_method_win.h
@@ -27,7 +27,7 @@
   void OnFocus() override;
 
   // Overridden from InputMethod:
-  bool OnUntranslatedIMEMessage(const base::NativeEvent& event,
+  bool OnUntranslatedIMEMessage(const PlatformEvent& event,
                                 NativeEventResult* result) override;
   ui::EventDispatchDetails DispatchKeyEvent(ui::KeyEvent* event) override;
   void OnTextInputTypeChanged(const TextInputClient* client) override;
diff --git a/ui/base/ime/input_method_win_base.cc b/ui/base/ime/input_method_win_base.cc
index 013eafa..0e89451a 100644
--- a/ui/base/ime/input_method_win_base.cc
+++ b/ui/base/ime/input_method_win_base.cc
@@ -61,7 +61,7 @@
                                    UINT message,
                                    WPARAM wparam,
                                    LPARAM lparam,
-                                   const base::NativeEvent& event,
+                                   const PlatformEvent& event,
                                    BOOL* handled) {
   *handled = TRUE;
 
diff --git a/ui/base/ime/input_method_win_base.h b/ui/base/ime/input_method_win_base.h
index c0bb3903..9e63213 100644
--- a/ui/base/ime/input_method_win_base.h
+++ b/ui/base/ime/input_method_win_base.h
@@ -36,7 +36,7 @@
                  UINT message,
                  WPARAM wparam,
                  LPARAM lparam,
-                 const base::NativeEvent& event,
+                 const PlatformEvent& event,
                  BOOL* handled);
 
   // Some IMEs rely on WM_IME_REQUEST message even when TSF is enabled. So
diff --git a/ui/base/ime/input_method_win_tsf.cc b/ui/base/ime/input_method_win_tsf.cc
index 427ac89..de9aaf27 100644
--- a/ui/base/ime/input_method_win_tsf.cc
+++ b/ui/base/ime/input_method_win_tsf.cc
@@ -54,7 +54,7 @@
 }
 
 bool InputMethodWinTSF::OnUntranslatedIMEMessage(
-    const base::NativeEvent& event,
+    const PlatformEvent& event,
     InputMethod::NativeEventResult* result) {
   LRESULT original_result = 0;
   BOOL handled = FALSE;
diff --git a/ui/base/ime/input_method_win_tsf.h b/ui/base/ime/input_method_win_tsf.h
index 29fef84..0f7417c2 100644
--- a/ui/base/ime/input_method_win_tsf.h
+++ b/ui/base/ime/input_method_win_tsf.h
@@ -26,7 +26,7 @@
   ui::EventDispatchDetails DispatchKeyEvent(ui::KeyEvent* event) override;
   void OnFocus() override;
   void OnBlur() override;
-  bool OnUntranslatedIMEMessage(const base::NativeEvent& event,
+  bool OnUntranslatedIMEMessage(const PlatformEvent& event,
                                 NativeEventResult* result) override;
   void OnTextInputTypeChanged(const TextInputClient* client) override;
   void OnCaretBoundsChanged(const TextInputClient* client) override;
diff --git a/ui/base/ime/mock_input_method.cc b/ui/base/ime/mock_input_method.cc
index 43d6b07f5..829c8348a 100644
--- a/ui/base/ime/mock_input_method.cc
+++ b/ui/base/ime/mock_input_method.cc
@@ -55,7 +55,7 @@
     observer.OnBlur();
 }
 
-bool MockInputMethod::OnUntranslatedIMEMessage(const base::NativeEvent& event,
+bool MockInputMethod::OnUntranslatedIMEMessage(const PlatformEvent& event,
                                                NativeEventResult* result) {
   if (result)
     *result = NativeEventResult();
diff --git a/ui/base/ime/mock_input_method.h b/ui/base/ime/mock_input_method.h
index b841a7a..809080b 100644
--- a/ui/base/ime/mock_input_method.h
+++ b/ui/base/ime/mock_input_method.h
@@ -32,7 +32,7 @@
   void SetDelegate(internal::InputMethodDelegate* delegate) override;
   void OnFocus() override;
   void OnBlur() override;
-  bool OnUntranslatedIMEMessage(const base::NativeEvent& event,
+  bool OnUntranslatedIMEMessage(const PlatformEvent& event,
                                 NativeEventResult* result) override;
   void SetFocusedTextInputClient(TextInputClient* client) override;
   void DetachTextInputClient(TextInputClient* client) override;
diff --git a/ui/base/ime/win/imm32_manager.cc b/ui/base/ime/win/imm32_manager.cc
index 37ed61a..9f9e6548 100644
--- a/ui/base/ime/win/imm32_manager.cc
+++ b/ui/base/ime/win/imm32_manager.cc
@@ -330,7 +330,7 @@
     return;
 
   ImeTextSpan ime_text_span;
-  ime_text_span.underline_color = SK_ColorBLACK;
+  ime_text_span.underline_color = SK_ColorTRANSPARENT;
   ime_text_span.background_color = SK_ColorTRANSPARENT;
   if (target_start > 0) {
     ime_text_span.start_offset = 0U;
diff --git a/ui/base/material_design/material_design_controller.cc b/ui/base/material_design/material_design_controller.cc
index e19300ed..bfd3312d 100644
--- a/ui/base/material_design/material_design_controller.cc
+++ b/ui/base/material_design/material_design_controller.cc
@@ -53,6 +53,8 @@
     SetMode(MATERIAL_HYBRID);
   } else if (switch_value == switches::kTopChromeMDMaterialTouchOptimized) {
     SetMode(MATERIAL_TOUCH_OPTIMIZED);
+  } else if (switch_value == switches::kTopChromeMDMaterialRefresh) {
+    SetMode(MATERIAL_REFRESH);
   } else if (switch_value == switches::kTopChromeMDMaterialAuto) {
 #if defined(OS_WIN)
     // TODO(girard): add support for switching between modes when
@@ -88,6 +90,11 @@
 }
 
 // static
+bool MaterialDesignController::IsNewerMaterialUi() {
+  return IsTouchOptimizedUiEnabled() || GetMode() == MATERIAL_REFRESH;
+}
+
+// static
 MaterialDesignController::Mode MaterialDesignController::DefaultMode() {
 #if defined(OS_CHROMEOS)
   // If a scan of available devices has already completed, use material-hybrid
diff --git a/ui/base/material_design/material_design_controller.h b/ui/base/material_design/material_design_controller.h
index 731b304a..d9612ea 100644
--- a/ui/base/material_design/material_design_controller.h
+++ b/ui/base/material_design/material_design_controller.h
@@ -25,7 +25,9 @@
     // Material design targeted at mouse/touch hybrid devices.
     MATERIAL_HYBRID = 1,
     // Material design that is more optimized for touch devices.
-    MATERIAL_TOUCH_OPTIMIZED = 2
+    MATERIAL_TOUCH_OPTIMIZED = 2,
+    // Material Refresh design targeted at mouse devices.
+    MATERIAL_REFRESH = 3,
   };
 
   // Initializes |mode_|. Must be called before checking |mode_|.
@@ -38,9 +40,12 @@
   // should be extended to cover secondary UI.
   static bool IsSecondaryUiMaterial();
 
-  // Returns true if the touch-optimized UI material design mode is enabled;
+  // Returns true if the touch-optimized UI material design mode is enabled.
   static bool IsTouchOptimizedUiEnabled();
 
+  // Returns true if the Material Refresh or touch-optimized UI is enabled.
+  static bool IsNewerMaterialUi();
+
   // Returns the per-platform default material design variant.
   static Mode DefaultMode();
 
diff --git a/ui/base/test/run_all_unittests.cc b/ui/base/test/run_all_unittests.cc
index 2ee6100e..bf1a2492 100644
--- a/ui/base/test/run_all_unittests.cc
+++ b/ui/base/test/run_all_unittests.cc
@@ -49,10 +49,10 @@
 
   ui::RegisterPathProvider();
 
+#if defined(OS_MACOSX) && !defined(OS_IOS)
   base::FilePath exe_path;
   PathService::Get(base::DIR_EXE, &exe_path);
 
-#if defined(OS_MACOSX) && !defined(OS_IOS)
   mock_cr_app::RegisterMockCrApp();
 
   // On Mac, a test Framework bundle is created that links locale.pak and
@@ -73,12 +73,14 @@
   // On other platforms, the (hardcoded) paths for chrome_100_percent.pak and
   // locale.pak get populated by later build steps. To avoid clobbering them,
   // load the test .pak files directly.
+  base::FilePath assets_path;
+  PathService::Get(base::DIR_ASSETS, &assets_path);
   ui::ResourceBundle::InitSharedInstanceWithPakPath(
-      exe_path.AppendASCII("ui_test.pak"));
+      assets_path.AppendASCII("ui_test.pak"));
 
   // ui_base_unittests can't depend on the locales folder which Chrome will make
   // later, so use the path created by ui_test_pak.
-  PathService::Override(ui::DIR_LOCALES, exe_path.AppendASCII("ui"));
+  PathService::Override(ui::DIR_LOCALES, assets_path.AppendASCII("ui"));
 #endif
 }
 
diff --git a/ui/base/ui_features.gni b/ui/base/ui_features.gni
index 806ef95..1a8ec2b0 100644
--- a/ui/base/ui_features.gni
+++ b/ui/base/ui_features.gni
@@ -9,7 +9,7 @@
   use_xkbcommon = false
 
   # Whether the entire browser uses toolkit-views on Mac instead of Cocoa.
-  mac_views_browser = false
+  mac_views_browser = is_mac
 
   # Whether the platform provides a native accessibility toolkit.
   has_native_accessibility = use_atk || is_win || is_mac
diff --git a/ui/base/user_activity/user_activity_detector.cc b/ui/base/user_activity/user_activity_detector.cc
index a163830..c45121d 100644
--- a/ui/base/user_activity/user_activity_detector.cc
+++ b/ui/base/user_activity/user_activity_detector.cc
@@ -51,15 +51,15 @@
   CHECK(!g_instance);
   g_instance = this;
 
-  ui::PlatformEventSource* platform_event_source =
-      ui::PlatformEventSource::GetInstance();
+  PlatformEventSource* platform_event_source =
+      PlatformEventSource::GetInstance();
   if (platform_event_source)
     platform_event_source->AddPlatformEventObserver(this);
 }
 
 UserActivityDetector::~UserActivityDetector() {
-  ui::PlatformEventSource* platform_event_source =
-      ui::PlatformEventSource::GetInstance();
+  PlatformEventSource* platform_event_source =
+      PlatformEventSource::GetInstance();
   if (platform_event_source)
     platform_event_source->RemovePlatformEventObserver(this);
   g_instance = nullptr;
diff --git a/ui/base/user_activity/user_activity_detector.h b/ui/base/user_activity/user_activity_detector.h
index dab5bc4..c12fbd4 100644
--- a/ui/base/user_activity/user_activity_detector.h
+++ b/ui/base/user_activity/user_activity_detector.h
@@ -18,7 +18,7 @@
 class UserActivityObserver;
 
 // Watches for input events and notifies observers that the user is active.
-class UI_BASE_EXPORT UserActivityDetector : public ui::PlatformEventObserver {
+class UI_BASE_EXPORT UserActivityDetector : public PlatformEventObserver {
  public:
   // Minimum amount of time between notifications to observers.
   static const int kNotifyIntervalMs;
@@ -49,7 +49,7 @@
   // PlatformEventSource (e.g. the window server).
   void HandleExternalUserActivity();
 
-  // ui::PlatformEventObserver:
+  // PlatformEventObserver:
   void WillProcessEvent(const PlatformEvent& platform_event) override {}
   void DidProcessEvent(const PlatformEvent& platform_event) override;
 
diff --git a/ui/base/user_activity/user_activity_detector_unittest.cc b/ui/base/user_activity/user_activity_detector_unittest.cc
index b2decd6..82b26d23 100644
--- a/ui/base/user_activity/user_activity_detector_unittest.cc
+++ b/ui/base/user_activity/user_activity_detector_unittest.cc
@@ -41,7 +41,7 @@
 
 // A test implementation of PlatformEventSource that we can instantiate to make
 // sure that the PlatformEventSource has an instance while in unit tests.
-class TestPlatformEventSource : public ui::PlatformEventSource {
+class TestPlatformEventSource : public PlatformEventSource {
  public:
   TestPlatformEventSource() {}
   ~TestPlatformEventSource() override {}
diff --git a/ui/base/x/selection_requestor.h b/ui/base/x/selection_requestor.h
index 65d944a..746a535 100644
--- a/ui/base/x/selection_requestor.h
+++ b/ui/base/x/selection_requestor.h
@@ -10,12 +10,12 @@
 #include <vector>
 
 #include "base/callback.h"
-#include "base/event_types.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted_memory.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "ui/base/ui_base_export.h"
+#include "ui/events/platform_event.h"
 #include "ui/gfx/x/x11_types.h"
 
 namespace ui {
diff --git a/ui/base/x/selection_requestor_unittest.cc b/ui/base/x/selection_requestor_unittest.cc
index faac9a1..832a2c463 100644
--- a/ui/base/x/selection_requestor_unittest.cc
+++ b/ui/base/x/selection_requestor_unittest.cc
@@ -67,8 +67,8 @@
                               0,
                               NULL);
 
-    event_source_ = ui::PlatformEventSource::CreateDefault();
-    CHECK(ui::PlatformEventSource::GetInstance());
+    event_source_ = PlatformEventSource::CreateDefault();
+    CHECK(PlatformEventSource::GetInstance());
     requestor_.reset(new SelectionRequestor(x_display_, x_window_, NULL));
   }
 
@@ -84,7 +84,7 @@
   // |requestor_|'s window.
   XID x_window_;
 
-  std::unique_ptr<ui::PlatformEventSource> event_source_;
+  std::unique_ptr<PlatformEventSource> event_source_;
   std::unique_ptr<SelectionRequestor> requestor_;
 
   base::MessageLoopForUI message_loop_;
diff --git a/ui/base/x/x11_util.h b/ui/base/x/x11_util.h
index a769101..e7942b9 100644
--- a/ui/base/x/x11_util.h
+++ b/ui/base/x/x11_util.h
@@ -17,12 +17,12 @@
 #include <vector>
 
 #include "base/containers/flat_set.h"
-#include "base/event_types.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted_memory.h"
 #include "ui/base/x/ui_base_x_export.h"
 #include "ui/events/event_constants.h"
 #include "ui/events/keycodes/keyboard_codes.h"
+#include "ui/events/platform_event.h"
 #include "ui/gfx/x/x11_types.h"
 
 typedef unsigned long XSharedMemoryId;  // ShmSeg in the X headers.
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc
index 1233687..7f1ba9e 100644
--- a/ui/compositor/layer.cc
+++ b/ui/compositor/layer.cc
@@ -764,6 +764,7 @@
 
   if (!surface_layer_) {
     scoped_refptr<cc::SurfaceLayer> new_layer = cc::SurfaceLayer::Create();
+    new_layer->SetHitTestable(true);
     SwitchToLayer(new_layer);
     surface_layer_ = new_layer;
   }
diff --git a/ui/compositor/layer_unittest.cc b/ui/compositor/layer_unittest.cc
index 464687d..885b73ec 100644
--- a/ui/compositor/layer_unittest.cc
+++ b/ui/compositor/layer_unittest.cc
@@ -905,22 +905,34 @@
   layer->SetShowPrimarySurface(surface_id_one, gfx::Size(10, 10), SK_ColorWHITE,
                                cc::DeadlinePolicy::UseDefaultDeadline(), false);
   EXPECT_FALSE(layer->StretchContentToFillBounds());
+  EXPECT_TRUE(static_cast<cc::SurfaceLayer*>(layer->cc_layer_for_testing())
+                  ->hit_testable());
 
   auto clone = layer->Clone();
   EXPECT_FALSE(clone->StretchContentToFillBounds());
+  EXPECT_TRUE(static_cast<cc::SurfaceLayer*>(clone->cc_layer_for_testing())
+                  ->hit_testable());
   auto mirror = layer->Mirror();
-  EXPECT_FALSE(clone->StretchContentToFillBounds());
+  EXPECT_FALSE(mirror->StretchContentToFillBounds());
+  EXPECT_TRUE(static_cast<cc::SurfaceLayer*>(mirror->cc_layer_for_testing())
+                  ->hit_testable());
 
   local_surface_id = allocator.GenerateId();
   viz::SurfaceId surface_id_two(arbitrary_frame_sink, local_surface_id);
   layer->SetShowPrimarySurface(surface_id_two, gfx::Size(10, 10), SK_ColorWHITE,
                                cc::DeadlinePolicy::UseDefaultDeadline(), true);
   EXPECT_TRUE(layer->StretchContentToFillBounds());
+  EXPECT_TRUE(static_cast<cc::SurfaceLayer*>(layer->cc_layer_for_testing())
+                  ->hit_testable());
 
   clone = layer->Clone();
   EXPECT_TRUE(clone->StretchContentToFillBounds());
+  EXPECT_TRUE(static_cast<cc::SurfaceLayer*>(clone->cc_layer_for_testing())
+                  ->hit_testable());
   mirror = layer->Mirror();
-  EXPECT_TRUE(clone->StretchContentToFillBounds());
+  EXPECT_TRUE(mirror->StretchContentToFillBounds());
+  EXPECT_TRUE(static_cast<cc::SurfaceLayer*>(mirror->cc_layer_for_testing())
+                  ->hit_testable());
 }
 
 class LayerWithNullDelegateTest : public LayerWithDelegateTest {
diff --git a/ui/display/manager/BUILD.gn b/ui/display/manager/BUILD.gn
index f54a2bbf3..a001d48 100644
--- a/ui/display/manager/BUILD.gn
+++ b/ui/display/manager/BUILD.gn
@@ -59,6 +59,7 @@
     "//ui/base",
     "//ui/display/mojo:interfaces",
     "//ui/display/util",
+    "//ui/events:platform_event",
     "//ui/events/devices",
     "//ui/strings",
   ]
diff --git a/ui/display/manager/chromeos/DEPS b/ui/display/manager/chromeos/DEPS
index 11d4683f..c11eb4b 100644
--- a/ui/display/manager/chromeos/DEPS
+++ b/ui/display/manager/chromeos/DEPS
@@ -1,5 +1,6 @@
 include_rules = [
   "+chromeos",
+  "+ui/events/platform_event.h",
   # DeviceDataManager is not created in all environments (such as ash when
   # running in mus/mash).
   "-ui/events/devices/device_data_manager.h",
diff --git a/ui/display/manager/chromeos/display_configurator.h b/ui/display/manager/chromeos/display_configurator.h
index fe91b2ca..5763f52 100644
--- a/ui/display/manager/chromeos/display_configurator.h
+++ b/ui/display/manager/chromeos/display_configurator.h
@@ -13,7 +13,6 @@
 #include <vector>
 
 #include "base/containers/queue.h"
-#include "base/event_types.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
@@ -24,6 +23,7 @@
 #include "ui/display/types/display_constants.h"
 #include "ui/display/types/native_display_observer.h"
 #include "ui/display/util/display_util.h"
+#include "ui/events/platform_event.h"
 #include "ui/gfx/geometry/size.h"
 
 namespace gfx {
diff --git a/ui/display/types/display_snapshot.cc b/ui/display/types/display_snapshot.cc
index 5b918ad..b8586ff 100644
--- a/ui/display/types/display_snapshot.cc
+++ b/ui/display/types/display_snapshot.cc
@@ -143,7 +143,7 @@
 
 // static
 gfx::BufferFormat DisplaySnapshot::PrimaryFormat() {
-  return gfx::BufferFormat::BGRX_8888;
+  return gfx::BufferFormat::BGRA_8888;
 }
 
 }  // namespace display
diff --git a/ui/events/BUILD.gn b/ui/events/BUILD.gn
index 31b5ea9..5e388acc 100644
--- a/ui/events/BUILD.gn
+++ b/ui/events/BUILD.gn
@@ -41,6 +41,12 @@
   ]
 }
 
+source_set("platform_event") {
+  sources = [
+    "platform_event.h",
+  ]
+}
+
 component("events_base") {
   sources = [
     "android/scroller.cc",
@@ -80,6 +86,7 @@
   public_deps = [
     ":dom_keycode_converter",
     ":event_constants",
+    ":platform_event",
     "//base",
     "//ui/events/platform",
     "//ui/gfx/geometry",
@@ -377,6 +384,8 @@
       "blink/fling_booster_unittest.cc",
       "blink/input_handler_proxy_unittest.cc",
       "blink/input_scroll_elasticity_controller_unittest.cc",
+      "blink/snap_fling_controller_unittest.cc",
+      "blink/snap_fling_curve_unittest.cc",
       "blink/web_input_event_traits_unittest.cc",
       "blink/web_input_event_unittest.cc",
       "cocoa/events_mac_unittest.mm",
diff --git a/ui/events/blink/BUILD.gn b/ui/events/blink/BUILD.gn
index f226976..740bc8e 100644
--- a/ui/events/blink/BUILD.gn
+++ b/ui/events/blink/BUILD.gn
@@ -24,6 +24,10 @@
     "input_handler_proxy_client.h",
     "input_scroll_elasticity_controller.cc",
     "input_scroll_elasticity_controller.h",
+    "snap_fling_controller.cc",
+    "snap_fling_controller.h",
+    "snap_fling_curve.cc",
+    "snap_fling_curve.h",
     "synchronous_input_handler_proxy.h",
     "web_input_event.cc",
     "web_input_event.h",
diff --git a/ui/events/blink/input_handler_proxy.cc b/ui/events/blink/input_handler_proxy.cc
index 946facc..6db6b1c 100644
--- a/ui/events/blink/input_handler_proxy.cc
+++ b/ui/events/blink/input_handler_proxy.cc
@@ -114,6 +114,21 @@
   return cc::ScrollState(scroll_state_data);
 }
 
+cc::ScrollState CreateScrollStateForInertialEnd() {
+  cc::ScrollStateData scroll_state_data;
+  scroll_state_data.is_ending = true;
+  return cc::ScrollState(scroll_state_data);
+}
+
+cc::ScrollState CreateScrollStateForInertialUpdate(
+    const gfx::Vector2dF& delta) {
+  cc::ScrollStateData scroll_state_data;
+  scroll_state_data.delta_x = delta.x();
+  scroll_state_data.delta_y = delta.y();
+  scroll_state_data.is_in_inertial_phase = true;
+  return cc::ScrollState(scroll_state_data);
+}
+
 cc::InputHandler::ScrollInputType GestureScrollInputType(
     blink::WebGestureDevice device) {
   return device == blink::kWebGestureDeviceTouchpad
@@ -161,7 +176,8 @@
       current_overscroll_params_(nullptr),
       has_ongoing_compositor_scroll_fling_pinch_(false),
       is_first_gesture_scroll_update_(false),
-      tick_clock_(base::DefaultTickClock::GetInstance()) {
+      tick_clock_(base::DefaultTickClock::GetInstance()),
+      snap_fling_controller_(std::make_unique<SnapFlingController>(this)) {
   DCHECK(client);
   input_handler_->BindToClient(this,
                                touchpad_and_wheel_scroll_latching_enabled_);
@@ -364,8 +380,8 @@
         DCHECK(fling_booster_->fling_cancellation_is_deferred());
         TRACE_EVENT_INSTANT0("input", "InputHandlerProxy::FlingBoostStart",
                              TRACE_EVENT_SCOPE_THREAD);
-      } else if (WebInputEvent::kGestureScrollBegin ||
-                 WebInputEvent::kGestureScrollUpdate) {
+      } else if (event.GetType() == WebInputEvent::kGestureScrollBegin ||
+                 event.GetType() == WebInputEvent::kGestureScrollUpdate) {
         TRACE_EVENT_INSTANT0("input",
                              "InputHandlerProxy::ExtendBoostedFlingTimeout",
                              TRACE_EVENT_SCOPE_THREAD);
@@ -375,6 +391,9 @@
     }
   }
 
+  if (snap_fling_controller_->FilterEventForSnap(event))
+    return DROP_EVENT;
+
   switch (event.GetType()) {
     case WebInputEvent::kMouseWheel:
       return HandleMouseWheel(static_cast<const WebMouseWheelEvent&>(event));
@@ -779,6 +798,15 @@
         return DID_NOT_HANDLE;
     }
   }
+
+  if (snap_fling_controller_->HandleGestureScrollUpdate(gesture_event)) {
+#ifndef NDEBUG
+    expect_scroll_update_end_ = false;
+#endif
+    gesture_scroll_on_impl_thread_ = false;
+    return DROP_EVENT;
+  }
+
   cc::InputHandlerScrollResult scroll_result =
       input_handler_->ScrollBy(&scroll_state);
 
@@ -1039,6 +1067,8 @@
   if (scroll_elasticity_controller_)
     scroll_elasticity_controller_->Animate(time);
 
+  snap_fling_controller_->Animate(time);
+
   if (!fling_curve_)
     return;
 
@@ -1144,6 +1174,34 @@
   input_handler_->PinchGestureEnd(anchor, false);
 }
 
+bool InputHandlerProxy::GetSnapFlingInfo(
+    const gfx::Vector2dF& natural_displacement,
+    gfx::Vector2dF* initial_offset,
+    gfx::Vector2dF* target_offset) const {
+  return input_handler_->GetSnapFlingInfo(natural_displacement, initial_offset,
+                                          target_offset);
+}
+
+gfx::Vector2dF InputHandlerProxy::ScrollByForSnapFling(
+    const gfx::Vector2dF& delta) {
+  cc::ScrollState scroll_state = CreateScrollStateForInertialUpdate(delta);
+  // TODO(sunyunjia): We should consider moving the scroll to main, handling
+  // overscroll, and handling elastic scroll after ScrollBy().
+  // https://crbug.com/819855
+  cc::InputHandlerScrollResult scroll_result =
+      input_handler_->ScrollBy(&scroll_state);
+  return scroll_result.current_offset;
+}
+
+void InputHandlerProxy::ScrollEndForSnapFling() {
+  cc::ScrollState scroll_state = CreateScrollStateForInertialEnd();
+  input_handler_->ScrollEnd(&scroll_state, false);
+}
+
+void InputHandlerProxy::RequestAnimationForSnapFling() {
+  RequestAnimation();
+}
+
 void InputHandlerProxy::HandleOverscroll(
     const gfx::PointF& causal_event_viewport_point,
     const cc::InputHandlerScrollResult& scroll_result,
diff --git a/ui/events/blink/input_handler_proxy.h b/ui/events/blink/input_handler_proxy.h
index 9c1961c..f39f3a74 100644
--- a/ui/events/blink/input_handler_proxy.h
+++ b/ui/events/blink/input_handler_proxy.h
@@ -16,6 +16,7 @@
 #include "third_party/WebKit/public/web/WebActiveFlingParameters.h"
 #include "ui/events/blink/blink_features.h"
 #include "ui/events/blink/input_scroll_elasticity_controller.h"
+#include "ui/events/blink/snap_fling_controller.h"
 #include "ui/events/blink/synchronous_input_handler_proxy.h"
 #include "ui/events/blink/web_input_event_traits.h"
 
@@ -51,7 +52,8 @@
 // events intended for a specific WebWidget.
 class InputHandlerProxy : public cc::InputHandlerClient,
                           public SynchronousInputHandlerProxy,
-                          public blink::WebGestureCurveTarget {
+                          public blink::WebGestureCurveTarget,
+                          public SnapFlingClient {
  public:
   InputHandlerProxy(cc::InputHandler* input_handler,
                     InputHandlerProxyClient* client,
@@ -114,6 +116,14 @@
   bool ScrollBy(const blink::WebFloatSize& offset,
                 const blink::WebFloatSize& velocity) override;
 
+  // SnapFlingClient implementation.
+  bool GetSnapFlingInfo(const gfx::Vector2dF& natural_displacement,
+                        gfx::Vector2dF* initial_offset,
+                        gfx::Vector2dF* target_offset) const override;
+  gfx::Vector2dF ScrollByForSnapFling(const gfx::Vector2dF& delta) override;
+  void ScrollEndForSnapFling() override;
+  void RequestAnimationForSnapFling() override;
+
   bool gesture_scroll_on_impl_thread_for_testing() const {
     return gesture_scroll_on_impl_thread_;
   }
@@ -264,6 +274,8 @@
 
   std::unique_ptr<FlingBooster> fling_booster_;
 
+  std::unique_ptr<SnapFlingController> snap_fling_controller_;
+
   DISALLOW_COPY_AND_ASSIGN(InputHandlerProxy);
 };
 
diff --git a/ui/events/blink/input_handler_proxy_unittest.cc b/ui/events/blink/input_handler_proxy_unittest.cc
index ba19984..db6aa2d 100644
--- a/ui/events/blink/input_handler_proxy_unittest.cc
+++ b/ui/events/blink/input_handler_proxy_unittest.cc
@@ -196,6 +196,11 @@
   }
   void set_is_scrolling_root(bool is) { is_scrolling_root_ = is; }
 
+  MOCK_CONST_METHOD3(GetSnapFlingInfo,
+                     bool(const gfx::Vector2dF& natural_displacement,
+                          gfx::Vector2dF* initial_offset,
+                          gfx::Vector2dF* target_offset));
+
  private:
   bool is_scrolling_root_ = true;
   DISALLOW_COPY_AND_ASSIGN(MockInputHandler);
@@ -471,6 +476,7 @@
   void GestureScrollStarted();
   void ScrollHandlingSwitchedToMainThread();
   void GestureScrollIgnored();
+  void FlingAndSnap();
 
   const bool synchronous_root_scroll_;
   const bool install_synchronous_handler_;
@@ -810,6 +816,59 @@
   VERIFY_AND_RESET_MOCKS();
 }
 
+void InputHandlerProxyTest::FlingAndSnap() {
+  expected_disposition_ = InputHandlerProxy::DID_HANDLE;
+  VERIFY_AND_RESET_MOCKS();
+
+  EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
+      .WillOnce(testing::Return(kImplThreadScrollState));
+
+  gesture_.SetType(WebInputEvent::kGestureScrollBegin);
+  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+  // The event should be dropped if InputHandler decides to snap.
+  expected_disposition_ = InputHandlerProxy::DROP_EVENT;
+  VERIFY_AND_RESET_MOCKS();
+
+  gesture_.SetType(WebInputEvent::kGestureScrollUpdate);
+  gesture_.data.scroll_update.delta_y =
+      -40;  // -Y means scroll down - i.e. in the +Y direction.
+  gesture_.data.scroll_update.inertial_phase =
+      blink::WebGestureEvent::kMomentumPhase;
+  EXPECT_CALL(mock_input_handler_,
+              GetSnapFlingInfo(testing::_, testing::_, testing::_))
+      .WillOnce(DoAll(testing::SetArgPointee<1>(gfx::Vector2dF(0, 0)),
+                      testing::SetArgPointee<2>(gfx::Vector2dF(0, 100)),
+                      testing::Return(true)));
+  EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_)).Times(1);
+  EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
+  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+  VERIFY_AND_RESET_MOCKS();
+}
+
+TEST_P(InputHandlerProxyTest, SnapFlingIgnoresFollowingGSUAndGSE) {
+  FlingAndSnap();
+  // The next GestureScrollUpdate should also be ignored, and will not ask for
+  // snap position.
+  expected_disposition_ = InputHandlerProxy::DROP_EVENT;
+
+  EXPECT_CALL(mock_input_handler_,
+              GetSnapFlingInfo(testing::_, testing::_, testing::_))
+      .Times(0);
+  EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_)).Times(0);
+  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+  VERIFY_AND_RESET_MOCKS();
+
+  // The GestureScrollEnd should also be ignored.
+  expected_disposition_ = InputHandlerProxy::DROP_EVENT;
+  gesture_.SetType(WebInputEvent::kGestureScrollEnd);
+  gesture_.data.scroll_end.inertial_phase =
+      blink::WebGestureEvent::kMomentumPhase;
+  EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_, testing::_)).Times(0);
+  EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+  VERIFY_AND_RESET_MOCKS();
+}
+
 TEST_P(InputHandlerProxyTest, GesturePinch) {
   // We shouldn't send any events to the widget for this gesture.
   expected_disposition_ = InputHandlerProxy::DID_HANDLE;
diff --git a/ui/events/blink/snap_fling_controller.cc b/ui/events/blink/snap_fling_controller.cc
new file mode 100644
index 0000000..079b05b
--- /dev/null
+++ b/ui/events/blink/snap_fling_controller.cc
@@ -0,0 +1,102 @@
+// Copyright 2018 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 "ui/events/blink/snap_fling_controller.h"
+
+#include "third_party/WebKit/public/platform/WebGestureEvent.h"
+#include "ui/events/blink/snap_fling_curve.h"
+
+namespace ui {
+
+SnapFlingController::SnapFlingController(SnapFlingClient* client)
+    : client_(client), state_(State::kIdle) {}
+
+SnapFlingController::~SnapFlingController() = default;
+
+bool SnapFlingController::FilterEventForSnap(
+    const blink::WebInputEvent& event) {
+  switch (event.GetType()) {
+    case blink::WebInputEvent::kGestureScrollBegin: {
+      ClearSnapFling();
+      return false;
+    }
+    // TODO(sunyunjia): Need to update the existing snap curve if the GSU is
+    // from a fling boosting event.
+    case blink::WebInputEvent::kGestureScrollUpdate:
+    case blink::WebInputEvent::kGestureScrollEnd: {
+      return state_ == State::kActive || state_ == State::kFinished;
+    }
+    default:
+      return false;
+  }
+}
+
+void SnapFlingController::ClearSnapFling() {
+  if (state_ == State::kActive)
+    client_->ScrollEndForSnapFling();
+
+  curve_.reset();
+  state_ = State::kIdle;
+}
+
+bool SnapFlingController::HandleGestureScrollUpdate(
+    const blink::WebGestureEvent& event) {
+  DCHECK(state_ != State::kActive && state_ != State::kFinished);
+  if (state_ != State::kIdle)
+    return false;
+
+  if (event.data.scroll_update.inertial_phase !=
+      blink::WebGestureEvent::kMomentumPhase) {
+    return false;
+  }
+
+  gfx::Vector2dF event_delta(-event.data.scroll_update.delta_x,
+                             -event.data.scroll_update.delta_y);
+  gfx::Vector2dF ending_displacement =
+      SnapFlingCurve::EstimateDisplacement(event_delta);
+
+  gfx::Vector2dF target_offset, start_offset;
+  if (!client_->GetSnapFlingInfo(ending_displacement, &start_offset,
+                                 &target_offset)) {
+    state_ = State::kIgnored;
+    return false;
+  }
+
+  if (start_offset == target_offset) {
+    state_ = State::kFinished;
+    return true;
+  }
+
+  base::TimeTicks event_time =
+      base::TimeTicks() +
+      base::TimeDelta::FromSecondsD(event.TimeStampSeconds());
+  curve_ =
+      std::make_unique<SnapFlingCurve>(start_offset, target_offset, event_time);
+  state_ = State::kActive;
+  Animate(event_time);
+  return true;
+}
+
+void SnapFlingController::Animate(base::TimeTicks time) {
+  if (state_ != State::kActive)
+    return;
+
+  if (curve_->IsFinished()) {
+    client_->ScrollEndForSnapFling();
+    state_ = State::kFinished;
+    return;
+  }
+  gfx::Vector2dF snapped_delta = curve_->GetScrollDelta(time);
+  gfx::Vector2dF current_offset = client_->ScrollByForSnapFling(snapped_delta);
+  curve_->UpdateCurrentOffset(current_offset);
+  client_->RequestAnimationForSnapFling();
+}
+
+void SnapFlingController::SetCurveForTest(
+    std::unique_ptr<SnapFlingCurve> curve) {
+  curve_ = std::move(curve);
+  state_ = State::kActive;
+}
+
+}  // namespace ui
\ No newline at end of file
diff --git a/ui/events/blink/snap_fling_controller.h b/ui/events/blink/snap_fling_controller.h
new file mode 100644
index 0000000..01cfe11
--- /dev/null
+++ b/ui/events/blink/snap_fling_controller.h
@@ -0,0 +1,95 @@
+// Copyright 2018 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 UI_EVENTS_BLINK_SNAP_FLING_CONTROLLER_H_
+#define UI_EVENTS_BLINK_SNAP_FLING_CONTROLLER_H_
+
+#include <memory>
+
+#include "base/time/time.h"
+#include "ui/gfx/geometry/vector2d_f.h"
+
+namespace blink {
+class WebGestureEvent;
+class WebInputEvent;
+}  // namespace blink
+
+namespace ui {
+namespace test {
+class SnapFlingControllerTest;
+}
+
+class SnapFlingCurve;
+
+// A client that provides information to the controller. It also executes the
+// scroll operations and requests animation frames.
+class SnapFlingClient {
+ public:
+  virtual bool GetSnapFlingInfo(const gfx::Vector2dF& natural_displacement,
+                                gfx::Vector2dF* initial_offset,
+                                gfx::Vector2dF* target_offset) const = 0;
+  virtual gfx::Vector2dF ScrollByForSnapFling(const gfx::Vector2dF& delta) = 0;
+  virtual void ScrollEndForSnapFling() = 0;
+  virtual void RequestAnimationForSnapFling() = 0;
+};
+
+class SnapFlingController {
+ public:
+  explicit SnapFlingController(SnapFlingClient* client);
+
+  static std::unique_ptr<SnapFlingController> CreateForTests(
+      SnapFlingClient* client,
+      std::unique_ptr<SnapFlingCurve> curve);
+
+  ~SnapFlingController();
+
+  // Returns true if the event should be consumed for snapping and should not be
+  // processed further.
+  bool FilterEventForSnap(const blink::WebInputEvent& event);
+
+  // Creates the snap fling curve from the first inertial GSU. Returns true if
+  // the event if a snap fling curve has been created and the event should not
+  // be processed further.
+  bool HandleGestureScrollUpdate(const blink::WebGestureEvent& event);
+
+  // Notifies the snap fling controller to update or end the scroll animation.
+  void Animate(base::TimeTicks time);
+
+ private:
+  friend class test::SnapFlingControllerTest;
+
+  enum class State {
+    // We haven't received an inertial GSU in this scroll sequence.
+    kIdle,
+    // We have received an inertial GSU but decided not to snap for this scroll
+    // sequence.
+    kIgnored,
+    // We have received an inertial GSU and decided to snap and animate it for
+    // this scroll sequence. So subsequent GSUs and GSE in the scroll sequence
+    // are consumed for snapping.
+    kActive,
+    // The animation of the snap fling has finished for this scroll sequence.
+    // Subsequent GSUs and GSE in the scroll sequence are ignored.
+    kFinished,
+  };
+
+  SnapFlingController(SnapFlingClient* client,
+                      std::unique_ptr<SnapFlingCurve> curve);
+  void ClearSnapFling();
+
+  // Sets the |curve_| to |curve| and the |state| to |kActive|.
+  void SetCurveForTest(std::unique_ptr<SnapFlingCurve> curve);
+
+  void SetActiveStateForTest() { state_ = State::kActive; }
+
+  SnapFlingClient* client_;
+  State state_ = State::kIdle;
+  std::unique_ptr<SnapFlingCurve> curve_;
+
+  DISALLOW_COPY_AND_ASSIGN(SnapFlingController);
+};
+
+}  // namespace ui
+
+#endif  // UI_EVENTS_BLINK_SNAP_FLING_CONTROLLER_H_
\ No newline at end of file
diff --git a/ui/events/blink/snap_fling_controller_unittest.cc b/ui/events/blink/snap_fling_controller_unittest.cc
new file mode 100644
index 0000000..31bd9a6
--- /dev/null
+++ b/ui/events/blink/snap_fling_controller_unittest.cc
@@ -0,0 +1,167 @@
+// Copyright 2018 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 "ui/events/blink/snap_fling_controller.h"
+
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/WebGestureEvent.h"
+#include "ui/events/blink/snap_fling_curve.h"
+
+namespace ui {
+namespace test {
+namespace {
+
+class MockSnapFlingClient : public SnapFlingClient {
+ public:
+  MOCK_CONST_METHOD3(GetSnapFlingInfo,
+                     bool(const gfx::Vector2dF& natural_displacement,
+                          gfx::Vector2dF* initial_offset,
+                          gfx::Vector2dF* target_offset));
+  MOCK_METHOD0(ScrollEndForSnapFling, void());
+  MOCK_METHOD0(RequestAnimationForSnapFling, void());
+  MOCK_METHOD1(ScrollByForSnapFling, gfx::Vector2dF(const gfx::Vector2dF&));
+};
+
+class MockSnapFlingCurve : public SnapFlingCurve {
+ public:
+  MockSnapFlingCurve()
+      : SnapFlingCurve(gfx::Vector2dF(),
+                       gfx::Vector2dF(0, 100),
+                       base::TimeTicks()) {}
+  MOCK_CONST_METHOD0(IsFinished, bool());
+  MOCK_METHOD1(GetScrollDelta, gfx::Vector2dF(base::TimeTicks));
+};
+
+}  // namespace
+
+class SnapFlingControllerTest : public testing::Test {
+ public:
+  SnapFlingControllerTest() {
+    controller_ = std::make_unique<SnapFlingController>(&mock_client_);
+  }
+  void SetCurve(std::unique_ptr<SnapFlingCurve> curve) {
+    controller_->SetCurveForTest(std::move(curve));
+  }
+  void SetActiveState() { controller_->SetActiveStateForTest(); }
+
+ protected:
+  testing::StrictMock<MockSnapFlingClient> mock_client_;
+  std::unique_ptr<SnapFlingController> controller_;
+};
+
+TEST_F(SnapFlingControllerTest, DoesNotFilterGSBWhenIdle) {
+  blink::WebGestureEvent event(blink::WebInputEvent::kGestureScrollBegin, 0, 0);
+  EXPECT_FALSE(controller_->FilterEventForSnap(event));
+}
+
+TEST_F(SnapFlingControllerTest, FiltersGSUAndGSEDependingOnState) {
+  blink::WebGestureEvent scroll_update(
+      blink::WebInputEvent::kGestureScrollUpdate, 0, 0);
+  blink::WebGestureEvent scroll_end(blink::WebInputEvent::kGestureScrollEnd, 0,
+                                    0);
+  // Should not filter GSU and GSE if the fling is not active.
+  EXPECT_FALSE(controller_->FilterEventForSnap(scroll_update));
+  EXPECT_FALSE(controller_->FilterEventForSnap(scroll_end));
+
+  // Should filter GSU and GSE if the fling is active.
+  SetActiveState();
+  EXPECT_TRUE(controller_->FilterEventForSnap(scroll_update));
+  EXPECT_TRUE(controller_->FilterEventForSnap(scroll_end));
+}
+
+TEST_F(SnapFlingControllerTest, CreatesAndAnimatesCurveOnFirstInertialGSU) {
+  blink::WebGestureEvent event(blink::WebInputEvent::kGestureScrollUpdate, 0,
+                               0);
+  event.data.scroll_update.delta_x = 0;
+  event.data.scroll_update.delta_y = -10;
+  event.data.scroll_update.inertial_phase =
+      blink::WebGestureEvent::kMomentumPhase;
+
+  EXPECT_CALL(mock_client_,
+              GetSnapFlingInfo(testing::_, testing::_, testing::_))
+      .WillOnce(DoAll(testing::SetArgPointee<1>(gfx::Vector2dF(0, 0)),
+                      testing::SetArgPointee<2>(gfx::Vector2dF(0, 100)),
+                      testing::Return(true)));
+  EXPECT_CALL(mock_client_, RequestAnimationForSnapFling()).Times(1);
+  EXPECT_CALL(mock_client_, ScrollByForSnapFling(testing::_)).Times(1);
+  EXPECT_TRUE(controller_->HandleGestureScrollUpdate(event));
+  testing::Mock::VerifyAndClearExpectations(&mock_client_);
+}
+
+TEST_F(SnapFlingControllerTest, DoesNotHandleNonInertialGSU) {
+  blink::WebGestureEvent event(blink::WebInputEvent::kGestureScrollUpdate, 0,
+                               0);
+  event.data.scroll_update.delta_x = 0;
+  event.data.scroll_update.delta_y = -10;
+  event.data.scroll_update.inertial_phase =
+      blink::WebGestureEvent::kNonMomentumPhase;
+
+  EXPECT_CALL(mock_client_,
+              GetSnapFlingInfo(testing::_, testing::_, testing::_))
+      .Times(0);
+  EXPECT_CALL(mock_client_, RequestAnimationForSnapFling()).Times(0);
+  EXPECT_CALL(mock_client_, ScrollByForSnapFling(testing::_)).Times(0);
+  EXPECT_FALSE(controller_->HandleGestureScrollUpdate(event));
+  testing::Mock::VerifyAndClearExpectations(&mock_client_);
+}
+
+TEST_F(SnapFlingControllerTest, AnimatesTheCurve) {
+  std::unique_ptr<MockSnapFlingCurve> mock_curve =
+      std::make_unique<MockSnapFlingCurve>();
+  MockSnapFlingCurve* curve = mock_curve.get();
+  SetCurve(std::move(mock_curve));
+
+  EXPECT_CALL(*curve, IsFinished()).WillOnce(testing::Return(false));
+  EXPECT_CALL(*curve, GetScrollDelta(testing::_))
+      .WillOnce(testing::Return(gfx::Vector2dF(100, 100)));
+  EXPECT_CALL(mock_client_, RequestAnimationForSnapFling()).Times(1);
+  EXPECT_CALL(mock_client_, ScrollByForSnapFling(gfx::Vector2dF(100, 100)));
+  controller_->Animate(base::TimeTicks() + base::TimeDelta::FromSeconds(1));
+  testing::Mock::VerifyAndClearExpectations(&mock_client_);
+  testing::Mock::VerifyAndClearExpectations(curve);
+}
+
+TEST_F(SnapFlingControllerTest, FinishesTheCurve) {
+  std::unique_ptr<MockSnapFlingCurve> mock_curve =
+      std::make_unique<MockSnapFlingCurve>();
+  MockSnapFlingCurve* curve = mock_curve.get();
+  SetCurve(std::move(mock_curve));
+  EXPECT_CALL(*curve, IsFinished()).WillOnce(testing::Return(true));
+  EXPECT_CALL(*curve, GetScrollDelta(testing::_)).Times(0);
+  EXPECT_CALL(mock_client_, RequestAnimationForSnapFling()).Times(0);
+  EXPECT_CALL(mock_client_, ScrollByForSnapFling(testing::_)).Times(0);
+  EXPECT_CALL(mock_client_, ScrollEndForSnapFling()).Times(1);
+  controller_->Animate(base::TimeTicks() + base::TimeDelta::FromSeconds(1));
+  testing::Mock::VerifyAndClearExpectations(curve);
+  testing::Mock::VerifyAndClearExpectations(&mock_client_);
+
+  EXPECT_CALL(*curve, IsFinished()).Times(0);
+  EXPECT_CALL(mock_client_, RequestAnimationForSnapFling()).Times(0);
+  EXPECT_CALL(mock_client_, ScrollByForSnapFling(testing::_)).Times(0);
+  EXPECT_CALL(mock_client_, ScrollEndForSnapFling()).Times(0);
+  controller_->Animate(base::TimeTicks() + base::TimeDelta::FromSeconds(2));
+  testing::Mock::VerifyAndClearExpectations(curve);
+  testing::Mock::VerifyAndClearExpectations(&mock_client_);
+}
+
+TEST_F(SnapFlingControllerTest, GSBNotFilteredAndResetsStateWhenActive) {
+  SetActiveState();
+  blink::WebGestureEvent update_event(
+      blink::WebInputEvent::kGestureScrollUpdate, 0, 0);
+  update_event.data.scroll_update.inertial_phase =
+      blink::WebGestureEvent::kMomentumPhase;
+  EXPECT_TRUE(controller_->FilterEventForSnap(update_event));
+
+  EXPECT_CALL(mock_client_, ScrollEndForSnapFling()).Times(1);
+  blink::WebGestureEvent begin_event(blink::WebInputEvent::kGestureScrollBegin,
+                                     0, 0);
+  EXPECT_FALSE(controller_->FilterEventForSnap(begin_event));
+  testing::Mock::VerifyAndClearExpectations(&mock_client_);
+
+  EXPECT_FALSE(controller_->FilterEventForSnap(update_event));
+}
+
+}  // namespace test
+}  // namespace ui
diff --git a/ui/events/blink/snap_fling_curve.cc b/ui/events/blink/snap_fling_curve.cc
new file mode 100644
index 0000000..f1fb6a1
--- /dev/null
+++ b/ui/events/blink/snap_fling_curve.cc
@@ -0,0 +1,119 @@
+// Copyright 2018 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 "ui/events/blink/snap_fling_curve.h"
+
+#include <cmath>
+#include "build/build_config.h"
+
+namespace ui {
+namespace {
+
+#if defined(OS_ANDROID)
+constexpr double kDistanceEstimatorScalar = 40;
+// The delta to be scrolled in next frame is 0.9 of the delta in last frame.
+constexpr double kRatio = 0.9;
+#else
+constexpr double kDistanceEstimatorScalar = 25;
+// The delta to be scrolled in next frame is 0.92 of the delta in last frame.
+constexpr double kRatio = 0.92;
+#endif
+constexpr double kMsPerFrame = 16;
+constexpr base::TimeDelta kMaximumSnapDuration =
+    base::TimeDelta::FromSecondsD(5);
+
+double GetDistanceFromDisplacement(gfx::Vector2dF displacement) {
+  return std::hypot(displacement.x(), displacement.y());
+}
+
+double EstimateFramesFromDistance(double distance) {
+  // We approximate scroll deltas as a geometric sequence with the ratio kRatio,
+  // and the last scrolled delta should be less or equal than 1, yielding the
+  // total distance as (1 - kRatio^(-n)) / (1 - (1 / kRatio)). Solving this
+  // could get n as below, which is the total number of deltas in the sequence,
+  // and is also the total frames needed to finish the curve.
+  return std::ceil(-std::log(1 - distance * (1 - 1 / kRatio)) /
+                   std::log(kRatio));
+}
+
+double CalculateFirstDelta(double distance, double frames) {
+  // distance = first_delta (1 - kRatio^(frames) / (1 - kRatio)).
+  // We can get the |first_delta| by solving the equation above.
+  return distance * (1 - kRatio) / (1 - std::pow(kRatio, frames));
+}
+
+}  // namespace
+
+gfx::Vector2dF SnapFlingCurve::EstimateDisplacement(
+    const gfx::Vector2dF& first_delta) {
+  gfx::Vector2dF destination = first_delta;
+  destination.Scale(kDistanceEstimatorScalar);
+  return destination;
+}
+
+SnapFlingCurve::SnapFlingCurve(const gfx::Vector2dF& start_offset,
+                               const gfx::Vector2dF& target_offset,
+                               base::TimeTicks first_gsu_time)
+    : start_offset_(start_offset),
+      total_displacement_(target_offset - start_offset),
+      total_distance_(GetDistanceFromDisplacement(total_displacement_)),
+      start_time_(first_gsu_time),
+      total_frames_(EstimateFramesFromDistance(total_distance_)),
+      first_delta_(CalculateFirstDelta(total_distance_, total_frames_)),
+      duration_(base::TimeDelta::FromMilliseconds(total_frames_ * kMsPerFrame)),
+      is_finished_(total_distance_ == 0) {
+  if (is_finished_)
+    return;
+  ratio_x_ = total_displacement_.x() / total_distance_;
+  ratio_y_ = total_displacement_.y() / total_distance_;
+}
+
+SnapFlingCurve::~SnapFlingCurve() = default;
+
+double SnapFlingCurve::GetCurrentCurveDistance(base::TimeTicks time_stamp) {
+  double current_distance = GetDistanceFromDisplacement(current_displacement_);
+  base::TimeDelta current_time = time_stamp - start_time_;
+
+  // Finishes the curve if the time elapsed is longer than |duration_|, or the
+  // remaining distance is less than 1.
+  if (current_time >= duration_ || current_distance >= total_distance_ - 1) {
+    return total_distance_;
+  }
+
+  double current_frame = current_time.InMillisecondsF() / kMsPerFrame + 1;
+  double sum =
+      first_delta_ * (1 - std::pow(kRatio, current_frame)) / (1 - kRatio);
+  return sum <= total_distance_ ? sum : total_distance_;
+}
+
+gfx::Vector2dF SnapFlingCurve::GetScrollDelta(base::TimeTicks time_stamp) {
+  if (is_finished_)
+    return gfx::Vector2dF();
+
+  // The the snap offset may never be reached due to clamping or other factors.
+  // To avoid a never ending snap curve, we force the curve to end if the time
+  // has passed a maximum Duration.
+  if (time_stamp - start_time_ > kMaximumSnapDuration) {
+    is_finished_ = true;
+    return total_displacement_ - current_displacement_;
+  }
+
+  double new_distance = GetCurrentCurveDistance(time_stamp);
+  gfx::Vector2dF new_displacement(new_distance * ratio_x_,
+                                  new_distance * ratio_y_);
+
+  return new_displacement - current_displacement_;
+}
+
+void SnapFlingCurve::UpdateCurrentOffset(const gfx::Vector2dF& current_offset) {
+  current_displacement_ = current_offset - start_offset_;
+  if (current_displacement_ == total_displacement_)
+    is_finished_ = true;
+}
+
+bool SnapFlingCurve::IsFinished() const {
+  return is_finished_;
+}
+
+}  // namespace ui
diff --git a/ui/events/blink/snap_fling_curve.h b/ui/events/blink/snap_fling_curve.h
new file mode 100644
index 0000000..28d6adb
--- /dev/null
+++ b/ui/events/blink/snap_fling_curve.h
@@ -0,0 +1,77 @@
+// Copyright 2018 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 UI_EVENTS_BLINK_SNAP_FLING_CURVE_H_
+#define UI_EVENTS_BLINK_SNAP_FLING_CURVE_H_
+
+#include "base/time/time.h"
+#include "ui/gfx/geometry/rect_f.h"
+#include "ui/gfx/geometry/vector2d_f.h"
+
+namespace ui {
+
+// The curve for the snap fling animation. The curve would generate a geometric
+// sequence of deltas to be scrolled at each frame.
+class SnapFlingCurve {
+ public:
+  // Creates the curve based on the start offset, target offset, and the first
+  // inertial GSU's time_stamp.
+  SnapFlingCurve(const gfx::Vector2dF& start_offset,
+                 const gfx::Vector2dF& target_offset,
+                 base::TimeTicks first_gsu_time);
+
+  virtual ~SnapFlingCurve();
+
+  // Estimate the total distance that will be scrolled given the first GSU's
+  // delta
+  static gfx::Vector2dF EstimateDisplacement(const gfx::Vector2dF& first_delta);
+
+  // Returns the delta that should be scrolled at |time|.
+  virtual gfx::Vector2dF GetScrollDelta(base::TimeTicks time);
+
+  // Updates |current_displacement_|. This sync is necessary because the node
+  // might be scrolled by other calls and the scrolls might be clamped.
+  void UpdateCurrentOffset(const gfx::Vector2dF& current_offset);
+
+  // Returns true if the scroll has arrived at the snap destination.
+  virtual bool IsFinished() const;
+
+  base::TimeDelta duration() const { return duration_; }
+
+ private:
+  // Returns the curve's current distance at |time_stamp|.
+  double GetCurrentCurveDistance(base::TimeTicks time_stamp);
+
+  // The initial scroll offset of the scroller.
+  const gfx::Vector2dF start_offset_;
+
+  // The total displacement to the snap position.
+  const gfx::Vector2dF total_displacement_;
+  // 1D representation of |total_displacement_|.
+  const double total_distance_;
+
+  // The current displacement that has been scrolled.
+  gfx::Vector2dF current_displacement_;
+
+  // The timestamp of the first GSU.
+  const base::TimeTicks start_time_;
+
+  // The number of deltas in the curve's geometric sequence.
+  const double total_frames_;
+  // The first delta that defines the curve's geometric sequence.
+  const double first_delta_;
+  // The total milliseconds needed to finish the curve.
+  const base::TimeDelta duration_;
+
+  bool is_finished_ = false;
+
+  // |total_displacement_.x| / |total_distance_|
+  double ratio_x_;
+  // |total_displacement_.y| / |total_distance_|
+  double ratio_y_;
+};
+
+}  // namespace ui
+
+#endif  // UI_EVENTS_BLINK_SNAP_FLING_CURVE_H_
diff --git a/ui/events/blink/snap_fling_curve_unittest.cc b/ui/events/blink/snap_fling_curve_unittest.cc
new file mode 100644
index 0000000..2c1666e
--- /dev/null
+++ b/ui/events/blink/snap_fling_curve_unittest.cc
@@ -0,0 +1,71 @@
+// Copyright 2018 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 "ui/events/blink/snap_fling_curve.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace ui {
+namespace test {
+
+TEST(SnapFlingCurveTest, CurveInitialization) {
+  SnapFlingCurve active_curve(gfx::Vector2dF(100, 100),
+                              gfx::Vector2dF(500, 500), base::TimeTicks());
+  EXPECT_FALSE(active_curve.IsFinished());
+
+  SnapFlingCurve finished_curve(gfx::Vector2dF(100, 100),
+                                gfx::Vector2dF(100, 100), base::TimeTicks());
+  EXPECT_TRUE(finished_curve.IsFinished());
+}
+
+TEST(SnapFlingCurveTest, AdvanceHalfwayThrough) {
+  SnapFlingCurve curve(gfx::Vector2dF(100, 100), gfx::Vector2dF(500, 500),
+                       base::TimeTicks());
+  base::TimeDelta duration = curve.duration();
+  gfx::Vector2dF delta1 =
+      curve.GetScrollDelta(base::TimeTicks() + duration / 2);
+  EXPECT_LT(0, delta1.x());
+  EXPECT_LT(0, delta1.y());
+  EXPECT_FALSE(curve.IsFinished());
+
+  // Repeated offset computations at the same timestamp before applying the
+  // scrolled delta should yield identical results.
+  gfx::Vector2dF delta2 =
+      curve.GetScrollDelta(base::TimeTicks() + duration / 2);
+  EXPECT_EQ(delta1, delta2);
+  EXPECT_FALSE(curve.IsFinished());
+
+  curve.UpdateCurrentOffset(gfx::Vector2dF(100, 100) + delta1);
+  EXPECT_FALSE(curve.IsFinished());
+}
+
+TEST(SnapFlingCurveTest, AdvanceFullyThroughOnlyFinishesAfterUpdate) {
+  SnapFlingCurve curve(gfx::Vector2dF(100, 100), gfx::Vector2dF(500, 500),
+                       base::TimeTicks());
+  gfx::Vector2dF delta =
+      curve.GetScrollDelta(base::TimeTicks() + curve.duration());
+  EXPECT_EQ(gfx::Vector2dF(400, 400), delta);
+  EXPECT_FALSE(curve.IsFinished());
+
+  curve.UpdateCurrentOffset(gfx::Vector2dF(500, 500));
+  EXPECT_TRUE(curve.IsFinished());
+}
+
+TEST(SnapFlingCurveTest, ReturnsZeroAfterFinished) {
+  SnapFlingCurve curve(gfx::Vector2dF(100, 100), gfx::Vector2dF(500, 500),
+                       base::TimeTicks());
+  curve.UpdateCurrentOffset(gfx::Vector2dF(500, 500));
+  EXPECT_TRUE(curve.IsFinished());
+
+  gfx::Vector2dF delta = curve.GetScrollDelta(base::TimeTicks());
+  EXPECT_EQ(gfx::Vector2dF(), delta);
+  EXPECT_TRUE(curve.IsFinished());
+
+  delta = curve.GetScrollDelta(base::TimeTicks() + curve.duration());
+  EXPECT_EQ(gfx::Vector2dF(), delta);
+  EXPECT_TRUE(curve.IsFinished());
+}
+
+}  // namespace test
+}  // namespace ui
\ No newline at end of file
diff --git a/ui/events/blink/web_input_event.cc b/ui/events/blink/web_input_event.cc
index 8779ba726..16341243 100644
--- a/ui/events/blink/web_input_event.cc
+++ b/ui/events/blink/web_input_event.cc
@@ -68,7 +68,7 @@
 // construct our pre-translated events.
 
 blink::WebMouseEvent MakeUntranslatedWebMouseEventFromNativeEvent(
-    const base::NativeEvent& native_event,
+    const PlatformEvent& native_event,
     const base::TimeTicks& time_stamp,
     blink::WebPointerProperties::PointerType pointer_type) {
   return WebMouseEventBuilder::Build(
@@ -77,7 +77,7 @@
 }
 
 blink::WebMouseWheelEvent MakeUntranslatedWebMouseWheelEventFromNativeEvent(
-    const base::NativeEvent& native_event,
+    const PlatformEvent& native_event,
     const base::TimeTicks& time_stamp,
     blink::WebPointerProperties::PointerType pointer_type) {
   return WebMouseWheelEventBuilder::Build(
@@ -193,13 +193,13 @@
 // information cleanly and consistently.
 //
 // The only place where an Event's data differs from what the underlying
-// base::NativeEvent would provide is position data. We would like to provide
+// PlatformEvent would provide is position data. We would like to provide
 // coordinates relative to its hosting window, rather than the top level
 // platform window. To do this a callback is accepted to allow for clients to
 // map the coordinates.
 //
 // The approach is to fully construct a blink::WebInputEvent from the
-// Event's base::NativeEvent, and then replace the coordinate fields with
+// Event's PlatformEvent, and then replace the coordinate fields with
 // the translated values from the Event.
 //
 // The exception is mouse events on linux. The MouseEvent contains enough
@@ -312,7 +312,7 @@
   blink::WebKeyboardEvent webkit_event = MakeWebKeyboardEventFromUiEvent(event);
 #if defined(OS_WIN)
   if (event.HasNativeEvent()) {
-    const base::NativeEvent& native_event = event.native_event();
+    const PlatformEvent& native_event = event.native_event();
 
     // System key events are explicitly distinguished, under Windows.
     webkit_event.is_system_key = native_event.message == WM_SYSCHAR ||
@@ -382,7 +382,7 @@
       // NotifyVirtual events are created for intermediate windows that the
       // pointer crosses through. These occur when middle clicking.
       // Change these into mouse move events.
-      const base::NativeEvent& native_event = event.native_event();
+      const PlatformEvent& native_event = event.native_event();
 
       if (native_event && native_event->type == LeaveNotify &&
           native_event->xcrossing.detail == NotifyVirtual) {
diff --git a/ui/events/cocoa/events_mac.mm b/ui/events/cocoa/events_mac.mm
index a0280c53..4825cb9 100644
--- a/ui/events/cocoa/events_mac.mm
+++ b/ui/events/cocoa/events_mac.mm
@@ -21,7 +21,7 @@
 
 namespace ui {
 
-EventType EventTypeFromNative(const base::NativeEvent& native_event) {
+EventType EventTypeFromNative(const PlatformEvent& native_event) {
   NSEventType type = [native_event type];
   switch (type) {
     case NSKeyDown:
@@ -72,19 +72,19 @@
   return ET_UNKNOWN;
 }
 
-int EventFlagsFromNative(const base::NativeEvent& event) {
+int EventFlagsFromNative(const PlatformEvent& event) {
   NSUInteger modifiers = [event modifierFlags];
   return EventFlagsFromNSEventWithModifiers(event, modifiers);
 }
 
-base::TimeTicks EventTimeFromNative(const base::NativeEvent& native_event) {
+base::TimeTicks EventTimeFromNative(const PlatformEvent& native_event) {
   base::TimeTicks timestamp =
       ui::EventTimeStampFromSeconds([native_event timestamp]);
   ValidateEventTimeClock(&timestamp);
   return timestamp;
 }
 
-gfx::PointF EventLocationFromNative(const base::NativeEvent& native_event) {
+gfx::PointF EventLocationFromNative(const PlatformEvent& native_event) {
   NSWindow* window = [native_event window];
   if (!window) {
     NOTIMPLEMENTED();  // Point will be in screen coordinates.
@@ -95,19 +95,17 @@
   return gfx::PointF(location.x, NSHeight(content_rect) - location.y);
 }
 
-gfx::Point EventSystemLocationFromNative(
-    const base::NativeEvent& native_event) {
+gfx::Point EventSystemLocationFromNative(const PlatformEvent& native_event) {
   NOTIMPLEMENTED();
   return gfx::Point();
 }
 
-int EventButtonFromNative(const base::NativeEvent& native_event) {
+int EventButtonFromNative(const PlatformEvent& native_event) {
   NOTIMPLEMENTED();
   return 0;
 }
 
-int GetChangedMouseButtonFlagsFromNative(
-    const base::NativeEvent& native_event) {
+int GetChangedMouseButtonFlagsFromNative(const PlatformEvent& native_event) {
   NSEventType type = [native_event type];
   switch (type) {
     case NSLeftMouseDown:
@@ -129,11 +127,11 @@
 }
 
 PointerDetails GetMousePointerDetailsFromNative(
-    const base::NativeEvent& native_event) {
+    const PlatformEvent& native_event) {
   return PointerDetails(EventPointerType::POINTER_TYPE_MOUSE);
 }
 
-gfx::Vector2d GetMouseWheelOffset(const base::NativeEvent& event) {
+gfx::Vector2d GetMouseWheelOffset(const PlatformEvent& event) {
   if ([event hasPreciseScrollingDeltas]) {
     // Handle continuous scrolling devices such as a Magic Mouse or a trackpad.
     // -scrollingDelta{X|Y} have float return types but they return values that
@@ -154,25 +152,25 @@
   }
 }
 
-base::NativeEvent CopyNativeEvent(const base::NativeEvent& event) {
+PlatformEvent CopyNativeEvent(const PlatformEvent& event) {
   return [event copy];
 }
 
-void ReleaseCopiedNativeEvent(const base::NativeEvent& event) {
+void ReleaseCopiedNativeEvent(const PlatformEvent& event) {
   [event release];
 }
 
-void ClearTouchIdIfReleased(const base::NativeEvent& native_event) {
+void ClearTouchIdIfReleased(const PlatformEvent& native_event) {
   NOTIMPLEMENTED();
 }
 
-int GetTouchId(const base::NativeEvent& native_event) {
+int GetTouchId(const PlatformEvent& native_event) {
   NOTIMPLEMENTED();
   return 0;
 }
 
 PointerDetails GetTouchPointerDetailsFromNative(
-    const base::NativeEvent& native_event) {
+    const PlatformEvent& native_event) {
   NOTIMPLEMENTED();
   return PointerDetails(EventPointerType::POINTER_TYPE_UNKNOWN,
                         /* pointer_id*/ 0,
@@ -181,7 +179,7 @@
                         /* force */ 0.f);
 }
 
-bool GetScrollOffsets(const base::NativeEvent& native_event,
+bool GetScrollOffsets(const PlatformEvent& native_event,
                       float* x_offset,
                       float* y_offset,
                       float* x_offset_ordinal,
@@ -230,7 +228,7 @@
   return true;
 }
 
-bool GetFlingData(const base::NativeEvent& native_event,
+bool GetFlingData(const PlatformEvent& native_event,
                   float* vx,
                   float* vy,
                   float* vx_ordinal,
@@ -240,19 +238,19 @@
   return false;
 }
 
-KeyboardCode KeyboardCodeFromNative(const base::NativeEvent& native_event) {
+KeyboardCode KeyboardCodeFromNative(const PlatformEvent& native_event) {
   return KeyboardCodeFromNSEvent(native_event);
 }
 
-DomCode CodeFromNative(const base::NativeEvent& native_event) {
+DomCode CodeFromNative(const PlatformEvent& native_event) {
   return DomCodeFromNSEvent(native_event);
 }
 
-uint32_t WindowsKeycodeFromNative(const base::NativeEvent& native_event) {
+uint32_t WindowsKeycodeFromNative(const PlatformEvent& native_event) {
   return static_cast<uint32_t>(KeyboardCodeFromNSEvent(native_event));
 }
 
-uint16_t TextFromNative(const base::NativeEvent& native_event) {
+uint16_t TextFromNative(const PlatformEvent& native_event) {
   NSString* text = @"";
   if ([native_event type] != NSFlagsChanged)
     text = [native_event characters];
@@ -271,7 +269,7 @@
   return return_value;
 }
 
-uint16_t UnmodifiedTextFromNative(const base::NativeEvent& native_event) {
+uint16_t UnmodifiedTextFromNative(const PlatformEvent& native_event) {
   NSString* text = @"";
   if ([native_event type] != NSFlagsChanged)
     text = [native_event charactersIgnoringModifiers];
@@ -290,7 +288,7 @@
   return return_value;
 }
 
-bool IsCharFromNative(const base::NativeEvent& native_event) {
+bool IsCharFromNative(const PlatformEvent& native_event) {
   return false;
 }
 
diff --git a/ui/events/devices/BUILD.gn b/ui/events/devices/BUILD.gn
index 2caa514b..ed92538 100644
--- a/ui/events/devices/BUILD.gn
+++ b/ui/events/devices/BUILD.gn
@@ -44,6 +44,7 @@
     "//base",
     "//base/third_party/dynamic_annotations",
     "//skia",
+    "//ui/events:platform_event",
     "//ui/gfx:geometry_skia",
     "//ui/gfx/geometry",
   ]
diff --git a/ui/events/devices/x11/device_data_manager_x11.h b/ui/events/devices/x11/device_data_manager_x11.h
index b261327..daadcb87 100644
--- a/ui/events/devices/x11/device_data_manager_x11.h
+++ b/ui/events/devices/x11/device_data_manager_x11.h
@@ -12,12 +12,12 @@
 #include <set>
 #include <vector>
 
-#include "base/event_types.h"
 #include "base/macros.h"
 #include "ui/events/devices/device_data_manager.h"
 #include "ui/events/devices/x11/events_devices_x11_export.h"
 #include "ui/events/event_constants.h"
 #include "ui/events/keycodes/keyboard_codes.h"
+#include "ui/events/platform_event.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/x/x11.h"
 #include "ui/gfx/x/x11_types.h"
diff --git a/ui/events/event.cc b/ui/events/event.cc
index 68daf988..bbc278f 100644
--- a/ui/events/event.cc
+++ b/ui/events/event.cc
@@ -179,7 +179,7 @@
   return SourceEventType::UNKNOWN;
 }
 
-bool IsX11SendEventTrue(const base::NativeEvent& event) {
+bool IsX11SendEventTrue(const PlatformEvent& event) {
 #if defined(USE_X11)
   return event && event->xany.send_event;
 #else
@@ -188,7 +188,7 @@
 }
 
 #if defined(USE_X11)
-bool X11EventHasNonStandardState(const base::NativeEvent& event) {
+bool X11EventHasNonStandardState(const PlatformEvent& event) {
   const unsigned int kAllStateMask =
       Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask |
       Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask | ShiftMask |
@@ -198,6 +198,11 @@
 }
 #endif
 
+constexpr int kChangedButtonFlagMask =
+    ui::EF_LEFT_MOUSE_BUTTON | ui::EF_MIDDLE_MOUSE_BUTTON |
+    ui::EF_RIGHT_MOUSE_BUTTON | ui::EF_BACK_MOUSE_BUTTON |
+    ui::EF_FORWARD_MOUSE_BUTTON;
+
 }  // namespace
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -357,7 +362,7 @@
 }
 
 bool Event::HasNativeEvent() const {
-  base::NativeEvent null_event;
+  PlatformEvent null_event;
   std::memset(&null_event, 0, sizeof(null_event));
   return !!std::memcmp(&native_event_, &null_event, sizeof(null_event));
 }
@@ -382,7 +387,7 @@
     : type_(type),
       time_stamp_(time_stamp),
       flags_(flags),
-      native_event_(base::NativeEvent()),
+      native_event_(PlatformEvent()),
       delete_native_event_(false),
       cancelable_(true),
       target_(NULL),
@@ -393,9 +398,7 @@
     latency()->set_source_event_type(EventTypeToLatencySourceEventType(type));
 }
 
-Event::Event(const base::NativeEvent& native_event,
-             EventType type,
-             int flags)
+Event::Event(const PlatformEvent& native_event, EventType type, int flags)
     : type_(type),
       time_stamp_(EventTimeFromNative(native_event)),
       flags_(flags),
@@ -459,7 +462,7 @@
 
 LocatedEvent::~LocatedEvent() = default;
 
-LocatedEvent::LocatedEvent(const base::NativeEvent& native_event)
+LocatedEvent::LocatedEvent(const PlatformEvent& native_event)
     : Event(native_event,
             EventTypeFromNative(native_event),
             EventFlagsFromNative(native_event)),
@@ -550,7 +553,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 // MouseEvent
 
-MouseEvent::MouseEvent(const base::NativeEvent& native_event)
+MouseEvent::MouseEvent(const PlatformEvent& native_event)
     : LocatedEvent(native_event),
       changed_button_flags_(GetChangedMouseButtonFlagsFromNative(native_event)),
       pointer_details_(GetMousePointerDetailsFromNative(native_event)) {
@@ -624,6 +627,8 @@
       changed_button_flags_(changed_button_flags),
       pointer_details_(pointer_details) {
   DCHECK_NE(ET_MOUSEWHEEL, type);
+  DCHECK_EQ(changed_button_flags_,
+            changed_button_flags_ & kChangedButtonFlagMask);
   latency()->set_source_event_type(ui::SourceEventType::MOUSE);
   latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
   if (this->type() == ET_MOUSE_MOVED && IsAnyButton())
@@ -758,10 +763,8 @@
 ////////////////////////////////////////////////////////////////////////////////
 // MouseWheelEvent
 
-MouseWheelEvent::MouseWheelEvent(const base::NativeEvent& native_event)
-    : MouseEvent(native_event),
-      offset_(GetMouseWheelOffset(native_event)) {
-}
+MouseWheelEvent::MouseWheelEvent(const PlatformEvent& native_event)
+    : MouseEvent(native_event), offset_(GetMouseWheelOffset(native_event)) {}
 
 MouseWheelEvent::MouseWheelEvent(const ScrollEvent& scroll_event)
     : MouseEvent(scroll_event),
@@ -823,7 +826,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 // TouchEvent
 
-TouchEvent::TouchEvent(const base::NativeEvent& native_event)
+TouchEvent::TouchEvent(const PlatformEvent& native_event)
     : LocatedEvent(native_event),
       unique_event_id_(ui::GetNextTouchEventId()),
       may_cause_scrolling_(false),
@@ -1160,10 +1163,10 @@
   return false;
 }
 
-KeyEvent::KeyEvent(const base::NativeEvent& native_event)
+KeyEvent::KeyEvent(const PlatformEvent& native_event)
     : KeyEvent(native_event, EventFlagsFromNative(native_event)) {}
 
-KeyEvent::KeyEvent(const base::NativeEvent& native_event, int event_flags)
+KeyEvent::KeyEvent(const PlatformEvent& native_event, int event_flags)
     : Event(native_event, EventTypeFromNative(native_event), event_flags),
       key_code_(KeyboardCodeFromNative(native_event)),
       code_(CodeFromNative(native_event)),
@@ -1410,7 +1413,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 // ScrollEvent
 
-ScrollEvent::ScrollEvent(const base::NativeEvent& native_event)
+ScrollEvent::ScrollEvent(const PlatformEvent& native_event)
     : MouseEvent(native_event),
       x_offset_(0.0f),
       y_offset_(0.0f),
diff --git a/ui/events/event.h b/ui/events/event.h
index 01fbde3..017e807 100644
--- a/ui/events/event.h
+++ b/ui/events/event.h
@@ -13,7 +13,6 @@
 #include <vector>
 
 #include "base/compiler_specific.h"
-#include "base/event_types.h"
 #include "base/gtest_prod_util.h"
 #include "base/logging.h"
 #include "base/macros.h"
@@ -24,6 +23,7 @@
 #include "ui/events/gestures/gesture_types.h"
 #include "ui/events/keycodes/dom/dom_key.h"
 #include "ui/events/keycodes/keyboard_codes.h"
+#include "ui/events/platform_event.h"
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/geometry/point_conversions.h"
 #include "ui/latency/latency_info.h"
@@ -77,7 +77,7 @@
     DISALLOW_COPY_AND_ASSIGN(DispatcherApi);
   };
 
-  const base::NativeEvent& native_event() const { return native_event_; }
+  const PlatformEvent& native_event() const { return native_event_; }
   EventType type() const { return type_; }
   // time_stamp represents time since machine was booted.
   const base::TimeTicks time_stamp() const { return time_stamp_; }
@@ -308,7 +308,7 @@
 
  protected:
   Event(EventType type, base::TimeTicks time_stamp, int flags);
-  Event(const base::NativeEvent& native_event, EventType type, int flags);
+  Event(const PlatformEvent& native_event, EventType type, int flags);
   Event(const Event& copy);
   void SetType(EventType type);
   void set_cancelable(bool cancelable) { cancelable_ = cancelable; }
@@ -324,7 +324,7 @@
   base::TimeTicks time_stamp_;
   LatencyInfo latency_;
   int flags_;
-  base::NativeEvent native_event_;
+  PlatformEvent native_event_;
   bool delete_native_event_;
   bool cancelable_;
   EventTarget* target_;
@@ -394,7 +394,7 @@
 
   LocatedEvent(const LocatedEvent& copy);
 
-  explicit LocatedEvent(const base::NativeEvent& native_event);
+  explicit LocatedEvent(const PlatformEvent& native_event);
 
   // Create a new LocatedEvent which is identical to the provided model.
   // If source / target windows are provided, the model location will be
@@ -506,8 +506,8 @@
   static const PointerId kMousePointerId;
 
   // NOTE: On some platforms this will allow an event to be constructed from a
-  // void*, see base::NativeEvent.
-  explicit MouseEvent(const base::NativeEvent& native_event);
+  // void*, see PlatformEvent.
+  explicit MouseEvent(const PlatformEvent& native_event);
 
   // |pointer_event.IsMousePointerEvent()| must be true.
   // Note: If |pointer_event| is a mouse wheel pointer event, use the
@@ -645,7 +645,7 @@
   // See |offset| for details.
   static const int kWheelDelta;
 
-  explicit MouseWheelEvent(const base::NativeEvent& native_event);
+  explicit MouseWheelEvent(const PlatformEvent& native_event);
   explicit MouseWheelEvent(const ScrollEvent& scroll_event);
   explicit MouseWheelEvent(const PointerEvent& pointer_event);
   MouseWheelEvent(const MouseEvent& mouse_event, int x_offset, int y_offset);
@@ -683,7 +683,7 @@
 // decided not to show hover effects for pen.
 class EVENTS_EXPORT TouchEvent : public LocatedEvent {
  public:
-  explicit TouchEvent(const base::NativeEvent& native_event);
+  explicit TouchEvent(const PlatformEvent& native_event);
 
   // |pointer_event.IsTouchPointerEvent()| must be true.
   explicit TouchEvent(const PointerEvent& pointer_event);
@@ -836,11 +836,11 @@
   // Create a KeyEvent from a NativeEvent. For Windows this native event can
   // be either a keystroke message (WM_KEYUP/WM_KEYDOWN) or a character message
   // (WM_CHAR). Other systems have only keystroke events.
-  explicit KeyEvent(const base::NativeEvent& native_event);
+  explicit KeyEvent(const PlatformEvent& native_event);
 
   // Create a KeyEvent from a NativeEvent but with mocked flags.
   // This method is necessary for Windows since MSG does not contain all flags.
-  KeyEvent(const base::NativeEvent& native_event, int event_flags);
+  KeyEvent(const PlatformEvent& native_event, int event_flags);
 
   // Create a keystroke event from a legacy KeyboardCode.
   // This should not be used in new code.
@@ -995,7 +995,7 @@
 
 class EVENTS_EXPORT ScrollEvent : public MouseEvent {
  public:
-  explicit ScrollEvent(const base::NativeEvent& native_event);
+  explicit ScrollEvent(const PlatformEvent& native_event);
   template <class T>
   ScrollEvent(const ScrollEvent& model,
               T* source,
diff --git a/ui/events/event_utils.cc b/ui/events/event_utils.cc
index aa9b26e3..a92ebb5 100644
--- a/ui/events/event_utils.cc
+++ b/ui/events/event_utils.cc
@@ -16,7 +16,7 @@
 int g_custom_event_types = ET_LAST;
 }  // namespace
 
-std::unique_ptr<Event> EventFromNative(const base::NativeEvent& native_event) {
+std::unique_ptr<Event> EventFromNative(const PlatformEvent& native_event) {
   std::unique_ptr<Event> event;
   EventType type = EventTypeFromNative(native_event);
   switch(type) {
@@ -103,7 +103,7 @@
   return display::Display::TouchSupport::UNAVAILABLE;
 }
 
-void ComputeEventLatencyOS(const base::NativeEvent& native_event) {
+void ComputeEventLatencyOS(const PlatformEvent& native_event) {
   base::TimeTicks current_time = EventTimeForNow();
   base::TimeTicks time_stamp = EventTimeFromNative(native_event);
   base::TimeDelta delta = current_time - time_stamp;
diff --git a/ui/events/event_utils.h b/ui/events/event_utils.h
index 5e1d931..b0672fe 100644
--- a/ui/events/event_utils.h
+++ b/ui/events/event_utils.h
@@ -9,7 +9,6 @@
 
 #include <memory>
 
-#include "base/event_types.h"
 #include "base/strings/string16.h"
 #include "build/build_config.h"
 #include "ui/display/display.h"
@@ -18,6 +17,7 @@
 #include "ui/events/event_constants.h"
 #include "ui/events/events_export.h"
 #include "ui/events/keycodes/keyboard_codes.h"
+#include "ui/events/platform_event.h"
 #include "ui/gfx/native_widget_types.h"
 
 #if defined(OS_WIN)
@@ -43,20 +43,19 @@
 // Returns a ui::Event wrapping a native event. Ownership of the returned value
 // is transferred to the caller.
 EVENTS_EXPORT std::unique_ptr<Event> EventFromNative(
-    const base::NativeEvent& native_event);
+    const PlatformEvent& native_event);
 
 // Get the EventType from a native event.
-EVENTS_EXPORT EventType EventTypeFromNative(
-    const base::NativeEvent& native_event);
+EVENTS_EXPORT EventType EventTypeFromNative(const PlatformEvent& native_event);
 
 // Get the EventFlags from a native event.
-EVENTS_EXPORT int EventFlagsFromNative(const base::NativeEvent& native_event);
+EVENTS_EXPORT int EventFlagsFromNative(const PlatformEvent& native_event);
 
 // Get the timestamp from a native event.
 // Note: This is not a pure function meaning that multiple applications on the
 // same native event may return different values.
 EVENTS_EXPORT base::TimeTicks EventTimeFromNative(
-    const base::NativeEvent& native_event);
+    const PlatformEvent& native_event);
 
 // Ensures that the event timestamp values are coming from the same underlying
 // monotonic clock as base::TimeTicks::Now() and if it is not then falls
@@ -68,67 +67,64 @@
 // this "root window" and how it maps to platform-specific drawing surfaces is
 // defined in ui/aura/root_window.* and ui/aura/window_tree_host*.
 EVENTS_EXPORT gfx::PointF EventLocationFromNative(
-    const base::NativeEvent& native_event);
+    const PlatformEvent& native_event);
 
 // Gets the location in native system coordinate space.
 EVENTS_EXPORT gfx::Point EventSystemLocationFromNative(
-    const base::NativeEvent& native_event);
+    const PlatformEvent& native_event);
 
 #if defined(USE_X11)
 // Returns the 'real' button for an event. The button reported in slave events
 // does not take into account any remapping (e.g. using xmodmap), while the
 // button reported in master events do. This is a utility function to always
 // return the mapped button.
-EVENTS_EXPORT int EventButtonFromNative(const base::NativeEvent& native_event);
+EVENTS_EXPORT int EventButtonFromNative(const PlatformEvent& native_event);
 #endif
 
 // Returns the KeyboardCode from a native event.
-EVENTS_EXPORT KeyboardCode KeyboardCodeFromNative(
-    const base::NativeEvent& native_event);
+EVENTS_EXPORT KeyboardCode
+KeyboardCodeFromNative(const PlatformEvent& native_event);
 
 // Returns the DOM KeyboardEvent code (physical location in the
 // keyboard) from a native event.
-EVENTS_EXPORT DomCode CodeFromNative(const base::NativeEvent& native_event);
+EVENTS_EXPORT DomCode CodeFromNative(const PlatformEvent& native_event);
 
 // Returns true if the keyboard event is a character event rather than
 // a keystroke event.
-EVENTS_EXPORT bool IsCharFromNative(const base::NativeEvent& native_event);
+EVENTS_EXPORT bool IsCharFromNative(const PlatformEvent& native_event);
 
 // Returns the flags of the button that changed during a press/release.
 EVENTS_EXPORT int GetChangedMouseButtonFlagsFromNative(
-    const base::NativeEvent& native_event);
+    const PlatformEvent& native_event);
 
 // Returns the detailed pointer information for mouse events.
-EVENTS_EXPORT PointerDetails GetMousePointerDetailsFromNative(
-    const base::NativeEvent& native_event);
+EVENTS_EXPORT PointerDetails
+GetMousePointerDetailsFromNative(const PlatformEvent& native_event);
 
 // Gets the mouse wheel offsets from a native event.
 EVENTS_EXPORT gfx::Vector2d GetMouseWheelOffset(
-    const base::NativeEvent& native_event);
+    const PlatformEvent& native_event);
 
 // Returns a copy of |native_event|. Depending on the platform, this copy may
 // need to be deleted with ReleaseCopiedNativeEvent().
-base::NativeEvent CopyNativeEvent(
-    const base::NativeEvent& native_event);
+PlatformEvent CopyNativeEvent(const PlatformEvent& native_event);
 
 // Delete a |native_event| previously created by CopyNativeEvent().
-void ReleaseCopiedNativeEvent(
-    const base::NativeEvent& native_event);
+void ReleaseCopiedNativeEvent(const PlatformEvent& native_event);
 
 // Returns the detailed pointer information for touch events.
 EVENTS_EXPORT PointerDetails
-GetTouchPointerDetailsFromNative(const base::NativeEvent& native_event);
+GetTouchPointerDetailsFromNative(const PlatformEvent& native_event);
 
 // Gets the touch id from a native event.
-EVENTS_EXPORT int GetTouchId(const base::NativeEvent& native_event);
+EVENTS_EXPORT int GetTouchId(const PlatformEvent& native_event);
 
 // Clear the touch id from bookkeeping if it is a release/cancel event.
-EVENTS_EXPORT void ClearTouchIdIfReleased(
-    const base::NativeEvent& native_event);
+EVENTS_EXPORT void ClearTouchIdIfReleased(const PlatformEvent& native_event);
 
 // Gets the fling velocity from a native event. is_cancel is set to true if
 // this was a tap down, intended to stop an ongoing fling.
-EVENTS_EXPORT bool GetFlingData(const base::NativeEvent& native_event,
+EVENTS_EXPORT bool GetFlingData(const PlatformEvent& native_event,
                                 float* vx,
                                 float* vy,
                                 float* vx_ordinal,
@@ -137,7 +133,7 @@
 
 // Returns whether this is a scroll event and optionally gets the amount to be
 // scrolled. |x_offset|, |y_offset| and |finger_count| can be NULL.
-EVENTS_EXPORT bool GetScrollOffsets(const base::NativeEvent& native_event,
+EVENTS_EXPORT bool GetScrollOffsets(const PlatformEvent& native_event,
                                     float* x_offset,
                                     float* y_offset,
                                     float* x_offset_ordinal,
@@ -151,7 +147,7 @@
 // Returns whether or not the internal display produces touch events.
 EVENTS_EXPORT display::Display::TouchSupport GetInternalDisplayTouchSupport();
 
-EVENTS_EXPORT void ComputeEventLatencyOS(const base::NativeEvent& native_event);
+EVENTS_EXPORT void ComputeEventLatencyOS(const PlatformEvent& native_event);
 
 #if defined(OS_WIN)
 EVENTS_EXPORT int GetModifiersFromKeyState();
diff --git a/ui/events/events_default.cc b/ui/events/events_default.cc
index 665e21d6..f293ed6 100644
--- a/ui/events/events_default.cc
+++ b/ui/events/events_default.cc
@@ -8,23 +8,22 @@
 
 namespace ui {
 
-base::TimeTicks EventTimeFromNative(const base::NativeEvent& native_event) {
+base::TimeTicks EventTimeFromNative(const PlatformEvent& native_event) {
   const ui::Event* event = static_cast<const ui::Event*>(native_event);
   return event->time_stamp();
 }
 
-int EventFlagsFromNative(const base::NativeEvent& native_event) {
+int EventFlagsFromNative(const PlatformEvent& native_event) {
   const ui::Event* event = static_cast<const ui::Event*>(native_event);
   return event->flags();
 }
 
-EventType EventTypeFromNative(const base::NativeEvent& native_event) {
+EventType EventTypeFromNative(const PlatformEvent& native_event) {
   const ui::Event* event = static_cast<const ui::Event*>(native_event);
   return event->type();
 }
 
-gfx::Point EventSystemLocationFromNative(
-    const base::NativeEvent& native_event) {
+gfx::Point EventSystemLocationFromNative(const PlatformEvent& native_event) {
   const ui::LocatedEvent* e =
       static_cast<const ui::LocatedEvent*>(native_event);
   DCHECK(e->IsMouseEvent() || e->IsTouchEvent() || e->IsGestureEvent() ||
@@ -32,7 +31,7 @@
   return e->location();
 }
 
-gfx::PointF EventLocationFromNative(const base::NativeEvent& native_event) {
+gfx::PointF EventLocationFromNative(const PlatformEvent& native_event) {
   const ui::LocatedEvent* e =
       static_cast<const ui::LocatedEvent*>(native_event);
   DCHECK(e->IsMouseEvent() || e->IsTouchEvent() || e->IsGestureEvent() ||
@@ -40,8 +39,7 @@
   return e->location_f();
 }
 
-int GetChangedMouseButtonFlagsFromNative(
-    const base::NativeEvent& native_event) {
+int GetChangedMouseButtonFlagsFromNative(const PlatformEvent& native_event) {
   const ui::MouseEvent* event =
       static_cast<const ui::MouseEvent*>(native_event);
   DCHECK(event->IsMouseEvent() || event->IsScrollEvent());
@@ -49,7 +47,7 @@
 }
 
 PointerDetails GetMousePointerDetailsFromNative(
-    const base::NativeEvent& native_event) {
+    const PlatformEvent& native_event) {
   const ui::MouseEvent* event =
       static_cast<const ui::MouseEvent*>(native_event);
   DCHECK(event->IsMouseEvent() || event->IsScrollEvent());
@@ -58,43 +56,41 @@
   return pointer_detail;
 }
 
-KeyboardCode KeyboardCodeFromNative(const base::NativeEvent& native_event) {
+KeyboardCode KeyboardCodeFromNative(const PlatformEvent& native_event) {
   const ui::KeyEvent* event = static_cast<const ui::KeyEvent*>(native_event);
   DCHECK(event->IsKeyEvent());
   return event->key_code();
 }
 
-DomCode CodeFromNative(const base::NativeEvent& native_event) {
+DomCode CodeFromNative(const PlatformEvent& native_event) {
   const ui::KeyEvent* event = static_cast<const ui::KeyEvent*>(native_event);
   DCHECK(event->IsKeyEvent());
   return event->code();
 }
 
-bool IsCharFromNative(const base::NativeEvent& native_event) {
+bool IsCharFromNative(const PlatformEvent& native_event) {
   const ui::KeyEvent* event = static_cast<const ui::KeyEvent*>(native_event);
   DCHECK(event->IsKeyEvent());
   return event->is_char();
 }
 
-gfx::Vector2d GetMouseWheelOffset(const base::NativeEvent& native_event) {
+gfx::Vector2d GetMouseWheelOffset(const PlatformEvent& native_event) {
   const ui::MouseWheelEvent* event =
       static_cast<const ui::MouseWheelEvent*>(native_event);
   DCHECK(event->type() == ET_MOUSEWHEEL);
   return event->offset();
 }
 
-base::NativeEvent CopyNativeEvent(const base::NativeEvent& event) {
+PlatformEvent CopyNativeEvent(const PlatformEvent& event) {
   return NULL;
 }
 
-void ReleaseCopiedNativeEvent(const base::NativeEvent& event) {
-}
+void ReleaseCopiedNativeEvent(const PlatformEvent& event) {}
 
-void ClearTouchIdIfReleased(const base::NativeEvent& xev) {
-}
+void ClearTouchIdIfReleased(const PlatformEvent& xev) {}
 
 // TODO(687724): Will remove all GetTouchId functions.
-int GetTouchId(const base::NativeEvent& native_event) {
+int GetTouchId(const PlatformEvent& native_event) {
   const ui::TouchEvent* event =
       static_cast<const ui::TouchEvent*>(native_event);
   DCHECK(event->IsTouchEvent());
@@ -102,14 +98,14 @@
 }
 
 PointerDetails GetTouchPointerDetailsFromNative(
-    const base::NativeEvent& native_event) {
+    const PlatformEvent& native_event) {
   const ui::TouchEvent* event =
       static_cast<const ui::TouchEvent*>(native_event);
   DCHECK(event->IsTouchEvent());
   return event->pointer_details();
 }
 
-bool GetScrollOffsets(const base::NativeEvent& native_event,
+bool GetScrollOffsets(const PlatformEvent& native_event,
                       float* x_offset,
                       float* y_offset,
                       float* x_offset_ordinal,
@@ -135,7 +131,7 @@
   return true;
 }
 
-bool GetFlingData(const base::NativeEvent& native_event,
+bool GetFlingData(const PlatformEvent& native_event,
                   float* vx,
                   float* vy,
                   float* vx_ordinal,
diff --git a/ui/events/events_stub.cc b/ui/events/events_stub.cc
index 26fc632..b952952 100644
--- a/ui/events/events_stub.cc
+++ b/ui/events/events_stub.cc
@@ -17,73 +17,69 @@
 // Stub implementations of platform-specific methods in events_util.h, built
 // on platforms that currently do not have a complete implementation of events.
 
-EventType EventTypeFromNative(const base::NativeEvent& native_event) {
+EventType EventTypeFromNative(const PlatformEvent& native_event) {
   NOTIMPLEMENTED();
   return ET_UNKNOWN;
 }
 
-int EventFlagsFromNative(const base::NativeEvent& native_event) {
+int EventFlagsFromNative(const PlatformEvent& native_event) {
   NOTIMPLEMENTED();
   return 0;
 }
 
-base::TimeTicks EventTimeFromNative(const base::NativeEvent& native_event) {
+base::TimeTicks EventTimeFromNative(const PlatformEvent& native_event) {
   NOTIMPLEMENTED();
   return base::TimeTicks();
 }
 
-gfx::PointF EventLocationFromNative(const base::NativeEvent& native_event) {
+gfx::PointF EventLocationFromNative(const PlatformEvent& native_event) {
   NOTIMPLEMENTED();
   return gfx::PointF();
 }
 
-gfx::Point EventSystemLocationFromNative(
-    const base::NativeEvent& native_event) {
+gfx::Point EventSystemLocationFromNative(const PlatformEvent& native_event) {
   NOTIMPLEMENTED();
   return gfx::Point();
 }
 
-int EventButtonFromNative(const base::NativeEvent& native_event) {
+int EventButtonFromNative(const PlatformEvent& native_event) {
   NOTIMPLEMENTED();
   return 0;
 }
 
-int GetChangedMouseButtonFlagsFromNative(
-    const base::NativeEvent& native_event) {
+int GetChangedMouseButtonFlagsFromNative(const PlatformEvent& native_event) {
   NOTIMPLEMENTED();
   return 0;
 }
 
 PointerDetails GetMousePointerDetailsFromNative(
-    const base::NativeEvent& native_event) {
+    const PlatformEvent& native_event) {
   return PointerDetails(EventPointerType::POINTER_TYPE_MOUSE);
 }
 
-gfx::Vector2d GetMouseWheelOffset(const base::NativeEvent& native_event) {
+gfx::Vector2d GetMouseWheelOffset(const PlatformEvent& native_event) {
   NOTIMPLEMENTED();
   return gfx::Vector2d();
 }
 
-base::NativeEvent CopyNativeEvent(const base::NativeEvent& event) {
-  NOTIMPLEMENTED() <<
-      "Don't know how to copy base::NativeEvent for this platform";
+PlatformEvent CopyNativeEvent(const PlatformEvent& event) {
+  NOTIMPLEMENTED() << "Don't know how to copy PlatformEvent for this platform";
   return NULL;
 }
 
-void ReleaseCopiedNativeEvent(const base::NativeEvent& event) {
-}
+void ReleaseCopiedNativeEvent(const PlatformEvent& event) {}
 
-void ClearTouchIdIfReleased(const base::NativeEvent& native_event) {
+void ClearTouchIdIfReleased(const PlatformEvent& native_event) {
   NOTIMPLEMENTED();
 }
 
-int GetTouchId(const base::NativeEvent& native_event) {
+int GetTouchId(const PlatformEvent& native_event) {
   NOTIMPLEMENTED();
   return 0;
 }
 
 PointerDetails GetTouchPointerDetailsFromNative(
-    const base::NativeEvent& native_event) {
+    const PlatformEvent& native_event) {
   NOTIMPLEMENTED();
   return PointerDetails(EventPointerType::POINTER_TYPE_UNKNOWN,
                         /* radius_x */ 1.0,
@@ -94,7 +90,7 @@
                         /* tilt_y */ 0.f);
 }
 
-bool GetScrollOffsets(const base::NativeEvent& native_event,
+bool GetScrollOffsets(const PlatformEvent& native_event,
                       float* x_offset,
                       float* y_offset,
                       float* x_offset_ordinal,
@@ -105,7 +101,7 @@
   return false;
 }
 
-bool GetFlingData(const base::NativeEvent& native_event,
+bool GetFlingData(const PlatformEvent& native_event,
                   float* vx,
                   float* vy,
                   float* vx_ordinal,
@@ -115,32 +111,32 @@
   return false;
 }
 
-KeyboardCode KeyboardCodeFromNative(const base::NativeEvent& native_event) {
+KeyboardCode KeyboardCodeFromNative(const PlatformEvent& native_event) {
   NOTIMPLEMENTED();
   return static_cast<KeyboardCode>(0);
 }
 
-DomCode CodeFromNative(const base::NativeEvent& native_event) {
+DomCode CodeFromNative(const PlatformEvent& native_event) {
   NOTIMPLEMENTED();
   return DomCode::NONE;
 }
 
-bool IsCharFromNative(const base::NativeEvent& native_event) {
+bool IsCharFromNative(const PlatformEvent& native_event) {
   NOTIMPLEMENTED();
   return false;
 }
 
-uint32_t WindowsKeycodeFromNative(const base::NativeEvent& native_event) {
+uint32_t WindowsKeycodeFromNative(const PlatformEvent& native_event) {
   NOTIMPLEMENTED();
   return 0;
 }
 
-uint16_t TextFromNative(const base::NativeEvent& native_event) {
+uint16_t TextFromNative(const PlatformEvent& native_event) {
   NOTIMPLEMENTED();
   return 0;
 }
 
-uint16_t UnmodifiedTextFromNative(const base::NativeEvent& native_event) {
+uint16_t UnmodifiedTextFromNative(const PlatformEvent& native_event) {
   NOTIMPLEMENTED();
   return 0;
 }
diff --git a/ui/events/keycodes/platform_key_map_win.h b/ui/events/keycodes/platform_key_map_win.h
index 53e13ba..6d8cfa56 100644
--- a/ui/events/keycodes/platform_key_map_win.h
+++ b/ui/events/keycodes/platform_key_map_win.h
@@ -9,12 +9,12 @@
 
 #include <unordered_map>
 
-#include "base/event_types.h"
 #include "base/hash.h"
 #include "ui/events/event.h"
 #include "ui/events/events_export.h"
 #include "ui/events/keycodes/dom/dom_key.h"
 #include "ui/events/keycodes/keyboard_codes_win.h"
+#include "ui/events/platform_event.h"
 
 namespace ui {
 
diff --git a/ui/events/ozone/chromeos/cursor_controller.h b/ui/events/ozone/chromeos/cursor_controller.h
index 073f4d573..e886040 100644
--- a/ui/events/ozone/chromeos/cursor_controller.h
+++ b/ui/events/ozone/chromeos/cursor_controller.h
@@ -7,13 +7,13 @@
 
 #include <map>
 
-#include "base/event_types.h"
 #include "base/macros.h"
 #include "base/memory/singleton.h"
 #include "base/observer_list.h"
 #include "base/synchronization/lock.h"
 #include "ui/display/display.h"
 #include "ui/events/ozone/events_ozone_export.h"
+#include "ui/events/platform_event.h"
 #include "ui/gfx/geometry/point_f.h"
 #include "ui/gfx/geometry/vector2d_f.h"
 #include "ui/gfx/native_widget_types.h"
diff --git a/ui/events/ozone/events_ozone.cc b/ui/events/ozone/events_ozone.cc
index 94c0427..2a8f0135 100644
--- a/ui/events/ozone/events_ozone.cc
+++ b/ui/events/ozone/events_ozone.cc
@@ -9,7 +9,7 @@
 namespace ui {
 
 void DispatchEventFromNativeUiEvent(
-    const base::NativeEvent& native_event,
+    const PlatformEvent& native_event,
     base::OnceCallback<void(ui::Event*)> callback) {
   ui::Event* native_ui_event = static_cast<ui::Event*>(native_event);
   if (native_ui_event->IsKeyEvent()) {
diff --git a/ui/events/ozone/events_ozone.h b/ui/events/ozone/events_ozone.h
index 23935f3..6a893e1e 100644
--- a/ui/events/ozone/events_ozone.h
+++ b/ui/events/ozone/events_ozone.h
@@ -6,8 +6,8 @@
 #define UI_EVENTS_OZONE_EVENTS_OZONE_H_
 
 #include "base/callback.h"
-#include "base/event_types.h"
 #include "ui/events/events_export.h"
+#include "ui/events/platform_event.h"
 
 namespace ui {
 
@@ -31,7 +31,7 @@
 // define NativeEvent == ui::Event.
 //
 EVENTS_EXPORT void DispatchEventFromNativeUiEvent(
-    const base::NativeEvent& native_event,
+    const PlatformEvent& native_event,
     base::OnceCallback<void(ui::Event*)> callback);
 
 }  // namespace ui
diff --git a/ui/events/platform/BUILD.gn b/ui/events/platform/BUILD.gn
index 5055e6c..dfceb31d 100644
--- a/ui/events/platform/BUILD.gn
+++ b/ui/events/platform/BUILD.gn
@@ -15,7 +15,6 @@
     "platform_event_source.cc",
     "platform_event_source.h",
     "platform_event_source_stub.cc",
-    "platform_event_types.h",
     "scoped_event_dispatcher.cc",
     "scoped_event_dispatcher.h",
   ]
@@ -24,6 +23,7 @@
 
   deps = [
     "//base",
+    "//ui/events:platform_event",
   ]
 
   if (use_x11) {
diff --git a/ui/events/platform/platform_event_dispatcher.h b/ui/events/platform/platform_event_dispatcher.h
index 294bdb9a..d54c5101 100644
--- a/ui/events/platform/platform_event_dispatcher.h
+++ b/ui/events/platform/platform_event_dispatcher.h
@@ -8,7 +8,7 @@
 #include <stdint.h>
 
 #include "ui/events/events_export.h"
-#include "ui/events/platform/platform_event_types.h"
+#include "ui/events/platform_event.h"
 
 namespace ui {
 
diff --git a/ui/events/platform/platform_event_observer.h b/ui/events/platform/platform_event_observer.h
index 37aec63..3b1cc9e 100644
--- a/ui/events/platform/platform_event_observer.h
+++ b/ui/events/platform/platform_event_observer.h
@@ -6,7 +6,7 @@
 #define UI_EVENTS_PLATFORM_PLATFORM_EVENT_OBSERVER_H_
 
 #include "ui/events/events_export.h"
-#include "ui/events/platform/platform_event_types.h"
+#include "ui/events/platform_event.h"
 
 namespace ui {
 
diff --git a/ui/events/platform/platform_event_source.h b/ui/events/platform/platform_event_source.h
index ca193b33..dae1504 100644
--- a/ui/events/platform/platform_event_source.h
+++ b/ui/events/platform/platform_event_source.h
@@ -15,7 +15,7 @@
 #include "base/macros.h"
 #include "base/observer_list.h"
 #include "ui/events/events_export.h"
-#include "ui/events/platform/platform_event_types.h"
+#include "ui/events/platform_event.h"
 
 namespace ui {
 
diff --git a/ui/events/platform/platform_event_types.h b/ui/events/platform/platform_event_types.h
deleted file mode 100644
index dedb38ff..0000000
--- a/ui/events/platform/platform_event_types.h
+++ /dev/null
@@ -1,14 +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.
-
-#ifndef UI_EVENTS_PLATFORM_PLATFORM_EVENT_TYPES_H_
-#define UI_EVENTS_PLATFORM_PLATFORM_EVENT_TYPES_H_
-
-#include "base/event_types.h"
-
-namespace ui {
-typedef base::NativeEvent PlatformEvent;
-}  // namespace ui
-
-#endif  // UI_EVENTS_PLATFORM_PLATFORM_EVENT_TYPES_H_
diff --git a/ui/events/platform/x11/x11_event_source.cc b/ui/events/platform/x11/x11_event_source.cc
index ed3581a9..897248a21 100644
--- a/ui/events/platform/x11/x11_event_source.cc
+++ b/ui/events/platform/x11/x11_event_source.cc
@@ -183,6 +183,7 @@
   return GetCurrentServerTime();
 }
 
+#if !defined(USE_OZONE)
 base::Optional<gfx::Point>
 X11EventSource::GetRootCursorLocationFromCurrentEvent() const {
   if (!dispatching_event_)
@@ -218,6 +219,7 @@
     return ui::EventSystemLocationFromNative(event);
   return base::nullopt;
 }
+#endif
 
 ////////////////////////////////////////////////////////////////////////////////
 // X11EventSource, protected
diff --git a/ui/events/platform/x11/x11_event_source.h b/ui/events/platform/x11/x11_event_source.h
index a0cd370..1df54b42 100644
--- a/ui/events/platform/x11/x11_event_source.h
+++ b/ui/events/platform/x11/x11_event_source.h
@@ -11,6 +11,7 @@
 
 #include "base/macros.h"
 #include "base/optional.h"
+#include "build/build_config.h"
 #include "ui/events/events_export.h"
 #include "ui/gfx/x/x11_types.h"
 
@@ -69,9 +70,11 @@
   // current event does not have a timestamp.
   Time GetTimestamp();
 
+#if !defined(USE_OZONE)
   // Returns the root pointer location only if there is an event being
   // dispatched that contains that information.
   base::Optional<gfx::Point> GetRootCursorLocationFromCurrentEvent() const;
+#endif
 
   void StopCurrentEventStream();
   void OnDispatcherListChanged();
diff --git a/ui/events/platform_event.h b/ui/events/platform_event.h
new file mode 100644
index 0000000..817f4310
--- /dev/null
+++ b/ui/events/platform_event.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_EVENTS_PLATFORM_EVENT_H_
+#define UI_EVENTS_PLATFORM_EVENT_H_
+
+#include "build/build_config.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+#elif defined(USE_X11)
+typedef union _XEvent XEvent;
+#elif defined(OS_MACOSX)
+#if defined(__OBJC__)
+@class NSEvent;
+#else   // __OBJC__
+class NSEvent;
+#endif  // __OBJC__
+#endif
+
+namespace ui {
+class Event;
+}
+
+namespace ui {
+
+// Cross platform typedefs for native event types.
+#if defined(OS_WIN)
+using PlatformEvent = MSG;
+#elif defined(USE_X11)
+using PlatformEvent = XEvent*;
+#elif defined(OS_MACOSX)
+using PlatformEvent = NSEvent*;
+#elif defined(USE_OZONE)
+using PlatformEvent = ui::Event*;
+#else
+using PlatformEvent = void*;
+#endif
+
+}  // namespace ui
+
+#endif  // UI_EVENTS_PLATFORM_EVENT_H_
diff --git a/ui/events/test/platform_event_source_test_api.h b/ui/events/test/platform_event_source_test_api.h
index 803cbc7..a4e2d34 100644
--- a/ui/events/test/platform_event_source_test_api.h
+++ b/ui/events/test/platform_event_source_test_api.h
@@ -6,7 +6,7 @@
 #define UI_EVENTS_TEST_PLATFORM_EVENT_SOURCE_TEST_API_H_
 
 #include "base/macros.h"
-#include "ui/events/platform/platform_event_types.h"
+#include "ui/events/platform_event.h"
 
 namespace ui {
 
diff --git a/ui/events/win/events_win.cc b/ui/events/win/events_win.cc
index 543741d..d7ee6f0 100644
--- a/ui/events/win/events_win.cc
+++ b/ui/events/win/events_win.cc
@@ -28,7 +28,7 @@
 #define SIGNATURE_MASK 0xFFFFFF00
 
 // Get the native mouse key state from the native event message type.
-int GetNativeMouseKey(const base::NativeEvent& native_event) {
+int GetNativeMouseKey(const PlatformEvent& native_event) {
   switch (native_event.message) {
     case WM_LBUTTONDBLCLK:
     case WM_LBUTTONDOWN:
@@ -62,36 +62,36 @@
   return 0;
 }
 
-bool IsButtonDown(const base::NativeEvent& native_event) {
+bool IsButtonDown(const PlatformEvent& native_event) {
   return ((MK_LBUTTON | MK_MBUTTON | MK_RBUTTON | MK_XBUTTON1 | MK_XBUTTON2) &
           native_event.wParam) != 0;
 }
 
-bool IsClientMouseEvent(const base::NativeEvent& native_event) {
+bool IsClientMouseEvent(const PlatformEvent& native_event) {
   return native_event.message == WM_MOUSELEAVE ||
          native_event.message == WM_MOUSEHOVER ||
         (native_event.message >= WM_MOUSEFIRST &&
          native_event.message <= WM_MOUSELAST);
 }
 
-bool IsNonClientMouseEvent(const base::NativeEvent& native_event) {
+bool IsNonClientMouseEvent(const PlatformEvent& native_event) {
   return native_event.message == WM_NCMOUSELEAVE ||
          native_event.message == WM_NCMOUSEHOVER ||
         (native_event.message >= WM_NCMOUSEMOVE &&
          native_event.message <= WM_NCXBUTTONDBLCLK);
 }
 
-bool IsMouseEvent(const base::NativeEvent& native_event) {
+bool IsMouseEvent(const PlatformEvent& native_event) {
   return IsClientMouseEvent(native_event) ||
          IsNonClientMouseEvent(native_event);
 }
 
-bool IsMouseWheelEvent(const base::NativeEvent& native_event) {
+bool IsMouseWheelEvent(const PlatformEvent& native_event) {
   return native_event.message == WM_MOUSEWHEEL ||
          native_event.message == WM_MOUSEHWHEEL;
 }
 
-bool IsKeyEvent(const base::NativeEvent& native_event) {
+bool IsKeyEvent(const PlatformEvent& native_event) {
   return native_event.message == WM_KEYDOWN ||
          native_event.message == WM_SYSKEYDOWN ||
          native_event.message == WM_CHAR ||
@@ -100,14 +100,14 @@
          native_event.message == WM_SYSKEYUP;
 }
 
-bool IsScrollEvent(const base::NativeEvent& native_event) {
+bool IsScrollEvent(const PlatformEvent& native_event) {
   return native_event.message == WM_VSCROLL ||
          native_event.message == WM_HSCROLL;
 }
 
 // Returns a mask corresponding to the set of pressed modifier keys.
 // Checks the current global state and the state sent by client mouse messages.
-int KeyStateFlagsFromNative(const base::NativeEvent& native_event) {
+int KeyStateFlagsFromNative(const PlatformEvent& native_event) {
   int flags = GetModifiersFromKeyState();
 
   // Check key messages for the extended key flag.
@@ -126,7 +126,7 @@
 
 // Returns a mask corresponding to the set of pressed mouse buttons.
 // This includes the button of the given message, even if it is being released.
-int MouseStateFlagsFromNative(const base::NativeEvent& native_event) {
+int MouseStateFlagsFromNative(const PlatformEvent& native_event) {
   int win_flags = GetNativeMouseKey(native_event);
 
   // Client mouse messages provide key states in their WPARAMs.
@@ -143,7 +143,7 @@
 
 }  // namespace
 
-EventType EventTypeFromNative(const base::NativeEvent& native_event) {
+EventType EventTypeFromNative(const PlatformEvent& native_event) {
   switch (native_event.message) {
     case WM_KEYDOWN:
     case WM_SYSKEYDOWN:
@@ -208,7 +208,7 @@
   return ET_UNKNOWN;
 }
 
-int EventFlagsFromNative(const base::NativeEvent& native_event) {
+int EventFlagsFromNative(const PlatformEvent& native_event) {
   int flags = KeyStateFlagsFromNative(native_event);
   if (IsMouseEvent(native_event))
     flags |= MouseStateFlagsFromNative(native_event);
@@ -216,7 +216,7 @@
   return flags;
 }
 
-base::TimeTicks EventTimeFromNative(const base::NativeEvent& native_event) {
+base::TimeTicks EventTimeFromNative(const PlatformEvent& native_event) {
   // On Windows, the native input event timestamp (|native_event.time|) is
   // coming from |GetTickCount()| clock [1], while in platform independent code
   // path we get timestamps by calling |TimeTicks::Now()|, which, if using high-
@@ -230,7 +230,7 @@
   return EventTimeForNow();
 }
 
-gfx::PointF EventLocationFromNative(const base::NativeEvent& native_event) {
+gfx::PointF EventLocationFromNative(const PlatformEvent& native_event) {
   POINT native_point;
   if ((native_event.message == WM_MOUSELEAVE ||
        native_event.message == WM_NCMOUSELEAVE) ||
@@ -256,8 +256,7 @@
   return gfx::PointF(gfx::Point(native_point));
 }
 
-gfx::Point EventSystemLocationFromNative(
-    const base::NativeEvent& native_event) {
+gfx::Point EventSystemLocationFromNative(const PlatformEvent& native_event) {
   POINT global_point = {GET_X_LPARAM(native_event.lParam),
                         GET_Y_LPARAM(native_event.lParam)};
   // Wheel events have position in screen coordinates.
@@ -266,21 +265,20 @@
   return gfx::Point(global_point);
 }
 
-KeyboardCode KeyboardCodeFromNative(const base::NativeEvent& native_event) {
+KeyboardCode KeyboardCodeFromNative(const PlatformEvent& native_event) {
   return KeyboardCodeForWindowsKeyCode(static_cast<WORD>(native_event.wParam));
 }
 
-DomCode CodeFromNative(const base::NativeEvent& native_event) {
+DomCode CodeFromNative(const PlatformEvent& native_event) {
   const uint16_t scan_code = GetScanCodeFromLParam(native_event.lParam);
   return CodeForWindowsScanCode(scan_code);
 }
 
-bool IsCharFromNative(const base::NativeEvent& native_event) {
+bool IsCharFromNative(const PlatformEvent& native_event) {
   return native_event.message == WM_CHAR || native_event.message == WM_SYSCHAR;
 }
 
-int GetChangedMouseButtonFlagsFromNative(
-    const base::NativeEvent& native_event) {
+int GetChangedMouseButtonFlagsFromNative(const PlatformEvent& native_event) {
   switch (GetNativeMouseKey(native_event)) {
     case MK_LBUTTON:
       return EF_LEFT_MOUSE_BUTTON;
@@ -296,7 +294,7 @@
 }
 
 PointerDetails GetMousePointerDetailsFromNative(
-    const base::NativeEvent& native_event) {
+    const PlatformEvent& native_event) {
   // We should filter out all the mouse events Synthesized from touch events.
   // TODO(lanwei): Will set the pointer ID, see https://crbug.com/616771.
   if ((GetMessageExtraInfo() & SIGNATURE_MASK) != MOUSEEVENTF_FROMTOUCHPEN)
@@ -305,7 +303,7 @@
   return PointerDetails(EventPointerType::POINTER_TYPE_PEN);
 }
 
-gfx::Vector2d GetMouseWheelOffset(const base::NativeEvent& native_event) {
+gfx::Vector2d GetMouseWheelOffset(const PlatformEvent& native_event) {
   DCHECK(native_event.message == WM_MOUSEWHEEL ||
          native_event.message == WM_MOUSEHWHEEL);
   if (native_event.message == WM_MOUSEWHEEL)
@@ -313,24 +311,23 @@
   return gfx::Vector2d(GET_WHEEL_DELTA_WPARAM(native_event.wParam), 0);
 }
 
-base::NativeEvent CopyNativeEvent(const base::NativeEvent& event) {
+PlatformEvent CopyNativeEvent(const PlatformEvent& event) {
   return event;
 }
 
-void ReleaseCopiedNativeEvent(const base::NativeEvent& event) {
-}
+void ReleaseCopiedNativeEvent(const PlatformEvent& event) {}
 
-void ClearTouchIdIfReleased(const base::NativeEvent& xev) {
+void ClearTouchIdIfReleased(const PlatformEvent& xev) {
   NOTIMPLEMENTED();
 }
 
-int GetTouchId(const base::NativeEvent& xev) {
+int GetTouchId(const PlatformEvent& xev) {
   NOTIMPLEMENTED();
   return 0;
 }
 
 PointerDetails GetTouchPointerDetailsFromNative(
-    const base::NativeEvent& native_event) {
+    const PlatformEvent& native_event) {
   NOTIMPLEMENTED();
   return PointerDetails(EventPointerType::POINTER_TYPE_TOUCH,
                         /* pointer_id*/ 0,
@@ -339,7 +336,7 @@
                         /* force */ 0.f);
 }
 
-bool GetScrollOffsets(const base::NativeEvent& native_event,
+bool GetScrollOffsets(const PlatformEvent& native_event,
                       float* x_offset,
                       float* y_offset,
                       float* x_offset_ordinal,
@@ -353,7 +350,7 @@
   return false;
 }
 
-bool GetFlingData(const base::NativeEvent& native_event,
+bool GetFlingData(const PlatformEvent& native_event,
                   float* vx,
                   float* vy,
                   float* vx_ordinal,
diff --git a/ui/events/x/events_x.cc b/ui/events/x/events_x.cc
index 4a22e65..b8df7b0 100644
--- a/ui/events/x/events_x.cc
+++ b/ui/events/x/events_x.cc
@@ -72,60 +72,58 @@
 
 namespace ui {
 
-EventType EventTypeFromNative(const base::NativeEvent& native_event) {
+EventType EventTypeFromNative(const PlatformEvent& native_event) {
   return EventTypeFromXEvent(*native_event);
 }
 
-int EventFlagsFromNative(const base::NativeEvent& native_event) {
+int EventFlagsFromNative(const PlatformEvent& native_event) {
   return EventFlagsFromXEvent(*native_event);
 }
 
-base::TimeTicks EventTimeFromNative(const base::NativeEvent& native_event) {
+base::TimeTicks EventTimeFromNative(const PlatformEvent& native_event) {
   base::TimeTicks timestamp = EventTimeFromXEvent(*native_event);
   ValidateEventTimeClock(&timestamp);
   return timestamp;
 }
 
-gfx::PointF EventLocationFromNative(const base::NativeEvent& native_event) {
+gfx::PointF EventLocationFromNative(const PlatformEvent& native_event) {
   return gfx::PointF(EventLocationFromXEvent(*native_event));
 }
 
-gfx::Point EventSystemLocationFromNative(
-    const base::NativeEvent& native_event) {
+gfx::Point EventSystemLocationFromNative(const PlatformEvent& native_event) {
   return EventSystemLocationFromXEvent(*native_event);
 }
 
-int EventButtonFromNative(const base::NativeEvent& native_event) {
+int EventButtonFromNative(const PlatformEvent& native_event) {
   return EventButtonFromXEvent(*native_event);
 }
 
-KeyboardCode KeyboardCodeFromNative(const base::NativeEvent& native_event) {
+KeyboardCode KeyboardCodeFromNative(const PlatformEvent& native_event) {
   return KeyboardCodeFromXKeyEvent(native_event);
 }
 
-DomCode CodeFromNative(const base::NativeEvent& native_event) {
+DomCode CodeFromNative(const PlatformEvent& native_event) {
   return CodeFromXEvent(native_event);
 }
 
-bool IsCharFromNative(const base::NativeEvent& native_event) {
+bool IsCharFromNative(const PlatformEvent& native_event) {
   return false;
 }
 
-int GetChangedMouseButtonFlagsFromNative(
-    const base::NativeEvent& native_event) {
+int GetChangedMouseButtonFlagsFromNative(const PlatformEvent& native_event) {
   return GetChangedMouseButtonFlagsFromXEvent(*native_event);
 }
 
 PointerDetails GetMousePointerDetailsFromNative(
-    const base::NativeEvent& native_event) {
+    const PlatformEvent& native_event) {
   return PointerDetails(EventPointerType::POINTER_TYPE_MOUSE);
 }
 
-gfx::Vector2d GetMouseWheelOffset(const base::NativeEvent& native_event) {
+gfx::Vector2d GetMouseWheelOffset(const PlatformEvent& native_event) {
   return GetMouseWheelOffsetFromXEvent(*native_event);
 }
 
-base::NativeEvent CopyNativeEvent(const base::NativeEvent& native_event) {
+PlatformEvent CopyNativeEvent(const PlatformEvent& native_event) {
   if (!native_event || native_event->type == GenericEvent)
     return NULL;
   XEvent* copy = new XEvent;
@@ -133,20 +131,20 @@
   return copy;
 }
 
-void ReleaseCopiedNativeEvent(const base::NativeEvent& native_event) {
+void ReleaseCopiedNativeEvent(const PlatformEvent& native_event) {
   delete native_event;
 }
 
-void ClearTouchIdIfReleased(const base::NativeEvent& native_event) {
+void ClearTouchIdIfReleased(const PlatformEvent& native_event) {
   ClearTouchIdIfReleasedFromXEvent(*native_event);
 }
 
-int GetTouchId(const base::NativeEvent& native_event) {
+int GetTouchId(const PlatformEvent& native_event) {
   return GetTouchIdFromXEvent(*native_event);
 }
 
 PointerDetails GetTouchPointerDetailsFromNative(
-    const base::NativeEvent& native_event) {
+    const PlatformEvent& native_event) {
   return PointerDetails(EventPointerType::POINTER_TYPE_TOUCH,
                         GetTouchIdFromXEvent(*native_event),
                         GetTouchRadiusXFromXEvent(*native_event),
@@ -155,7 +153,7 @@
                         GetTouchAngleFromXEvent(*native_event));
 }
 
-bool GetScrollOffsets(const base::NativeEvent& native_event,
+bool GetScrollOffsets(const PlatformEvent& native_event,
                       float* x_offset,
                       float* y_offset,
                       float* x_offset_ordinal,
@@ -167,7 +165,7 @@
                                     finger_count);
 }
 
-bool GetFlingData(const base::NativeEvent& native_event,
+bool GetFlingData(const PlatformEvent& native_event,
                   float* vx,
                   float* vy,
                   float* vx_ordinal,
diff --git a/ui/events/x/events_x_unittest.cc b/ui/events/x/events_x_unittest.cc
index 0022b7f..e056288 100644
--- a/ui/events/x/events_x_unittest.cc
+++ b/ui/events/x/events_x_unittest.cc
@@ -382,7 +382,7 @@
 
 // Copied events should not remove native touch id mappings, as this causes a
 // crash (crbug.com/467102). Copied events do not contain a proper
-// base::NativeEvent and should not attempt to access it.
+// PlatformEvent and should not attempt to access it.
 TEST_F(EventsXTest, CopiedTouchEventNotRemovingFromNativeMapping) {
   std::vector<int> devices;
   devices.push_back(0);
diff --git a/ui/file_manager/file_manager/background/js/mock_volume_manager.js b/ui/file_manager/file_manager/background/js/mock_volume_manager.js
index 78ba0bf..42313b1f 100644
--- a/ui/file_manager/file_manager/background/js/mock_volume_manager.js
+++ b/ui/file_manager/file_manager/background/js/mock_volume_manager.js
@@ -126,7 +126,6 @@
  */
 MockVolumeManager.createMockVolumeInfo = function(type, volumeId, label) {
   var fileSystem = new MockFileSystem(volumeId, 'filesystem:' + volumeId);
-  fileSystem.entries['/'] = new MockDirectoryEntry(fileSystem, '');
 
   var volumeInfo = new VolumeInfoImpl(
       type, volumeId, fileSystem,
@@ -273,7 +272,6 @@
 MockVolumeManagerWrapper.createMockVolumeInfo =
     function(type, volumeId, label) {
   var fileSystem = new MockFileSystem(volumeId, 'filesystem:' + volumeId);
-  fileSystem.entries['/'] = new MockDirectoryEntry(fileSystem, '');
   var volumeInfo = new VolumeInfoImpl(
       type, volumeId, fileSystem,
       '',                                         // error
diff --git a/ui/file_manager/file_manager/background/js/volume_info_impl.js b/ui/file_manager/file_manager/background/js/volume_info_impl.js
index 1535b35..667ffe0 100644
--- a/ui/file_manager/file_manager/background/js/volume_info_impl.js
+++ b/ui/file_manager/file_manager/background/js/volume_info_impl.js
@@ -234,7 +234,7 @@
             Promise.reject(this.error));
     } else {
       // For Drive, we need to resolve.
-      var displayRootURL = this.fileSystem_.root.toURL() + '/root';
+      var displayRootURL = this.fileSystem_.root.toURL() + 'root';
       this.displayRootPromise_ = new Promise(
           window.webkitResolveLocalFileSystemURL.bind(null, displayRootURL));
       if (this.isTeamDrivesEnabled_) {
@@ -247,7 +247,7 @@
                   new Promise(window.webkitResolveLocalFileSystemURL.bind(
                       null,
                       this.fileSystem_.root.toURL() +
-                          VolumeManagerCommon.TEAM_DRIVES_DIRECTORY_PATH))
+                          VolumeManagerCommon.TEAM_DRIVES_DIRECTORY_NAME))
                 ])
                 .then(function(displayRoots) {
                   this.teamDriveDisplayRoot_ = displayRoots[1];
diff --git a/ui/file_manager/file_manager/common/js/mock_entry.js b/ui/file_manager/file_manager/common/js/mock_entry.js
index c1ffbcb..d275116 100644
--- a/ui/file_manager/file_manager/common/js/mock_entry.js
+++ b/ui/file_manager/file_manager/common/js/mock_entry.js
@@ -26,10 +26,10 @@
 
   /** @type {!Object<!Entry>} */
   this.entries = {};
-  this.entries['/'] = new MockDirectoryEntry(this, '');
+  this.entries['/'] = new MockDirectoryEntry(this, '/');
 
   /** @type {string} */
-  this.rootURL = opt_rootURL || 'filesystem:' + volumeId;
+  this.rootURL = opt_rootURL || 'filesystem:' + volumeId + '/';
 }
 
 MockFileSystem.prototype = {
@@ -50,7 +50,7 @@
  */
 MockFileSystem.prototype.populate = function(entries, opt_clear) {
   if (opt_clear)
-    this.entries = {'/': new MockDirectoryEntry(this, '')};
+    this.entries = {'/': new MockDirectoryEntry(this, '/')};
   entries.forEach(function(entry) {
     var path = entry.fullPath || entry;
     var metadata = entry.metadata || {size: 0};
@@ -142,7 +142,7 @@
     segments[i] = encodeURIComponent(segments[i]);
   }
 
-  return this.filesystem.rootURL + segments.join('/');
+  return joinPath(this.filesystem.rootURL, segments.join('/'));
 };
 
 /**
@@ -173,7 +173,7 @@
  */
 MockEntry.prototype.moveTo = function(parent, opt_newName, onSuccess, onError) {
   Promise.resolve().then(function() {
-    this.filesystem.entries[this.fullPath] = null;
+    delete this.filesystem.entries[this.fullPath];
     return this.clone(
         joinPath(parent.fullPath, opt_newName || this.name),
         parent.filesystem);
@@ -204,7 +204,7 @@
 MockEntry.prototype.remove = function(onSuccess, onError) {
   this.removed_ = true;
   Promise.resolve().then(function() {
-    this.filesystem.entries[this.fullPath] = null;
+    delete this.filesystem.entries[this.fullPath];
   }.bind(this)).then(onSuccess, onError);
 };
 
@@ -270,11 +270,14 @@
  *
  * @param {FileSystem} filesystem File system where the entry is localed.
  * @param {string} fullPath Full path for the entry.
- * @param {Object} metadata Metadata.
+ * @param {Object=} opt_metadata Metadata.
  * @extends {MockEntry}
  * @constructor
  */
-function MockDirectoryEntry(filesystem, fullPath, metadata) {
+function MockDirectoryEntry(filesystem, fullPath, opt_metadata) {
+  var metadata = opt_metadata || {};
+  metadata.size = metadata.size || 0;
+  metadata.modificationTime = metadata.modificationTime || new Date();
   MockEntry.call(this, filesystem, fullPath, metadata);
   this.isFile = false;
   this.isDirectory = true;
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
index c86da3e..66febd16 100644
--- a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
+++ b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
@@ -372,6 +372,60 @@
 ];
 
 /**
+ * Name of a command (for UMA).
+ * @enum {string}
+ * @const
+ */
+CommandHandler.MenuCommandsForUMA = {
+  HELP: 'volume-help',
+  DRIVE_HELP: 'volume-help-drive',
+  DRIVE_BUY_MORE_SPACE: 'drive-buy-more-space',
+  DRIVE_GO_TO_DRIVE: 'drive-go-to-drive',
+  HIDDEN_FILES_SHOW: 'toggle-hidden-files-on',
+  HIDDEN_FILES_HIDE: 'toggle-hidden-files-off',
+  MOBILE_DATA_ON: 'drive-sync-settings-enabled',
+  MOBILE_DATA_OFF: 'drive-sync-settings-disabled',
+  SHOW_GOOGLE_DOCS_FILES_OFF: 'drive-hosted-settings-disabled',
+  SHOW_GOOGLE_DOCS_FILES_ON: 'drive-hosted-settings-enabled',
+};
+
+/**
+ * Keep the order of this in sync with FileManagerMenuCommands in
+ * tools/metrics/histograms/enums.xml.
+ * The array indices will be recorded in UMA as enum values. The index for each
+ * root type should never be renumbered nor reused in this array.
+ *
+ * @type {!Array<CommandHandler.MenuCommandsForUMA>}
+ * @const
+ */
+CommandHandler.ValidMenuCommandsForUMA = [
+  CommandHandler.MenuCommandsForUMA.HELP,
+  CommandHandler.MenuCommandsForUMA.DRIVE_HELP,
+  CommandHandler.MenuCommandsForUMA.DRIVE_BUY_MORE_SPACE,
+  CommandHandler.MenuCommandsForUMA.DRIVE_GO_TO_DRIVE,
+  CommandHandler.MenuCommandsForUMA.HIDDEN_FILES_SHOW,
+  CommandHandler.MenuCommandsForUMA.HIDDEN_FILES_HIDE,
+  CommandHandler.MenuCommandsForUMA.MOBILE_DATA_ON,
+  CommandHandler.MenuCommandsForUMA.MOBILE_DATA_OFF,
+  CommandHandler.MenuCommandsForUMA.SHOW_GOOGLE_DOCS_FILES_ON,
+  CommandHandler.MenuCommandsForUMA.SHOW_GOOGLE_DOCS_FILES_OFF,
+];
+console.assert(
+    Object.keys(CommandHandler.MenuCommandsForUMA).length ===
+        CommandHandler.ValidMenuCommandsForUMA.length,
+    'Members in ValidMenuCommandsForUMA do not match those in ' +
+        'MenuCommandsForUMA.');
+
+/**
+ * Records the menu item as selected in UMA.
+ * @param {CommandHandler.MenuCommandsForUMA} menuItem The selected menu item.
+ */
+CommandHandler.recordMenuItemSelected_ = function(menuItem) {
+  metrics.recordEnum(
+      'MenuItemSelected', menuItem, CommandHandler.ValidMenuCommandsForUMA);
+};
+
+/**
  * Updates the availability of all commands.
  */
 CommandHandler.prototype.updateAvailability = function() {
@@ -706,6 +760,13 @@
     var isFilterHiddenOn = !fileManager.fileFilter.isFilterHiddenOn();
     fileManager.fileFilter.setFilterHidden(isFilterHiddenOn);
     event.command.checked = /* is show hidden files */!isFilterHiddenOn;
+    if (isFilterHiddenOn) {
+      CommandHandler.recordMenuItemSelected_(
+          CommandHandler.MenuCommandsForUMA.HIDDEN_FILES_SHOW);
+    } else {
+      CommandHandler.recordMenuItemSelected_(
+          CommandHandler.MenuCommandsForUMA.HIDDEN_FILES_HIDE);
+    }
   },
   /**
    * @param {!Event} event Command event.
@@ -729,6 +790,13 @@
         fileManager.ui.gearMenu.syncButton.hasAttribute('checked');
     var changeInfo = {cellularDisabled: !nowCellularDisabled};
     chrome.fileManagerPrivate.setPreferences(changeInfo);
+    if (nowCellularDisabled) {
+      CommandHandler.recordMenuItemSelected_(
+          CommandHandler.MenuCommandsForUMA.MOBILE_DATA_OFF);
+    } else {
+      CommandHandler.recordMenuItemSelected_(
+          CommandHandler.MenuCommandsForUMA.MOBILE_DATA_ON);
+    }
   },
   /**
    * @param {!Event} event Command event.
@@ -756,12 +824,20 @@
     var nowHostedFilesEnabled =
         fileManager.ui.gearMenu.hostedButton.hasAttribute('checked');
     var nowHostedFilesDisabled = !nowHostedFilesEnabled;
+
     /*
     var changeInfo = {hostedFilesDisabled: !nowHostedFilesDisabled};
     */
     var changeInfo = {};
     changeInfo['hostedFilesDisabled'] = !nowHostedFilesDisabled;
     chrome.fileManagerPrivate.setPreferences(changeInfo);
+    if (nowHostedFilesDisabled) {
+      CommandHandler.recordMenuItemSelected_(
+          CommandHandler.MenuCommandsForUMA.SHOW_GOOGLE_DOCS_FILES_OFF);
+    } else {
+      CommandHandler.recordMenuItemSelected_(
+          CommandHandler.MenuCommandsForUMA.SHOW_GOOGLE_DOCS_FILES_ON);
+    }
   },
   /**
    * @param {!Event} event Command event.
@@ -1062,10 +1138,15 @@
    * @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use.
    */
   execute: function(event, fileManager) {
-    if (fileManager.directoryModel.isOnDrive())
+    if (fileManager.directoryModel.isOnDrive()) {
       util.visitURL(str('GOOGLE_DRIVE_HELP_URL'));
-    else
+      CommandHandler.recordMenuItemSelected_(
+          CommandHandler.MenuCommandsForUMA.DRIVE_HELP);
+    } else {
       util.visitURL(str('FILES_APP_HELP_URL'));
+      CommandHandler.recordMenuItemSelected_(
+          CommandHandler.MenuCommandsForUMA.HELP);
+    }
   },
   /**
    * @param {!Event} event Command event.
@@ -1095,6 +1176,8 @@
    */
   execute: function(event, fileManager) {
     util.visitURL(str('GOOGLE_DRIVE_BUY_STORAGE_URL'));
+    CommandHandler.recordMenuItemSelected_(
+        CommandHandler.MenuCommandsForUMA.DRIVE_BUY_MORE_SPACE);
   },
   canExecute: CommandUtil.canExecuteVisibleOnDriveInNormalAppModeOnly
 });
@@ -1110,6 +1193,8 @@
    */
   execute: function(event, fileManager) {
     util.visitURL(str('GOOGLE_DRIVE_ROOT_URL'));
+    CommandHandler.recordMenuItemSelected_(
+        CommandHandler.MenuCommandsForUMA.DRIVE_GO_TO_DRIVE);
   },
   canExecute: CommandUtil.canExecuteVisibleOnDriveInNormalAppModeOnly
 });
diff --git a/ui/file_manager/file_manager/foreground/js/ui/compiled_resources2.gyp b/ui/file_manager/file_manager/foreground/js/ui/compiled_resources2.gyp
index 039fe8c..085759b 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/compiled_resources2.gyp
+++ b/ui/file_manager/file_manager/foreground/js/ui/compiled_resources2.gyp
@@ -268,6 +268,7 @@
       'dependencies': [
         '../../../../externs/compiled_resources2.gyp:platform',
         '../../../../externs/compiled_resources2.gyp:volume_manager',
+        '../../../common/js/compiled_resources2.gyp:metrics',
         '../../../common/js/compiled_resources2.gyp:util',
         '../../../common/js/compiled_resources2.gyp:volume_manager_common',
         '../compiled_resources2.gyp:volume_manager_wrapper',
diff --git a/ui/file_manager/file_manager/foreground/js/ui/default_task_dialog.js b/ui/file_manager/file_manager/foreground/js/ui/default_task_dialog.js
index 1dd8b5f..3106a07 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/default_task_dialog.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/default_task_dialog.js
@@ -35,6 +35,7 @@
     this.list_.activateItemAtIndex = this.activateItemAtIndex_.bind(this);
     // Use 'click' instead of 'change' for keyboard users.
     this.list_.addEventListener('click', this.onSelected_.bind(this));
+    this.list_.addEventListener('change', this.onListChange_.bind(this));
 
     this.initialFocusElement_ = this.list_;
 
@@ -71,6 +72,8 @@
       div.classList.add(item.class);
 
     result.appendChild(div);
+    // A11y - make it focusable and readable.
+    result.setAttribute('tabindex', '-1');
 
     cr.defineProperty(result, 'lead', cr.PropertyKind.BOOL_ATTR);
     cr.defineProperty(result, 'selected', cr.PropertyKind.BOOL_ATTR);
@@ -134,6 +137,20 @@
   };
 
   /**
+   * Called when cr.ui.List triggers a change event, which means user
+   * focused a new item on the list. Used here to isue .focus() on
+   * currently active item so ChromeVox can read it out.
+   * @param {!Event} event triggered by cr.ui.List.
+   */
+  DefaultTaskDialog.prototype.onListChange_ = function(event) {
+    var list = event.target;
+    var activeItem =
+        list.getListItemByIndex(list.selectionModel_.selectedIndex);
+    if (activeItem)
+      activeItem.focus();
+  };
+
+  /**
    * @override
    */
   DefaultTaskDialog.prototype.onContainerKeyDown_ = function(event) {
diff --git a/ui/file_manager/file_manager/foreground/js/ui/location_line.js b/ui/file_manager/file_manager/foreground/js/ui/location_line.js
index d5e0ff07f..1c93805f 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/location_line.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/location_line.js
@@ -336,6 +336,7 @@
     pathClickEvent.entry = entry;
     this.dispatchEvent(pathClickEvent);
   }.bind(this));
+  metrics.recordUserAction('ClickBreadcrumbs');
 };
 
 /**
diff --git a/ui/file_manager/file_manager/test/create_new_folder.js b/ui/file_manager/file_manager/test/create_new_folder.js
new file mode 100644
index 0000000..2281d33
--- /dev/null
+++ b/ui/file_manager/file_manager/test/create_new_folder.js
@@ -0,0 +1,157 @@
+// 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.
+
+'use strict';
+
+/**
+ * Selects the first item in the file list.
+ * @return {Promise} Promise to be fulfilled on success.
+ */
+test.selectFirstListItem = function() {
+  return Promise.resolve()
+      .then(() => {
+        // Ensure no selected item.
+        return test.waitForElementLost(
+            'div.detail-table > list > li[selected]');
+      })
+      .then(() => {
+        // Push Down.
+        assertTrue(test.fakeKeyDown(
+            '#file-list', 'ArrowDown', 'Down', true, false, false));
+        // Wait for selection.
+        return test.waitForElement('div.detail-table > list > li[selected]');
+      })
+      .then(() => {
+        // Ensure that only the first item is selected.
+        var elements =
+            document.querySelectorAll('div.detail-table > list > li[selected]');
+        assertEquals(1, elements.length);
+        assertEquals('listitem-' + test.minListItemId(), elements[0].id);
+        return elements[0];
+      });
+};
+
+/**
+ * Creates new folder.
+ * @param {Array<TestEntryInfo>} initialEntrySet Initial set of entries.
+ * @return {Promise} Promise to be fulfilled on success.
+ */
+test.createNewFolder = function(initialEntrySet) {
+  var maxListItemId = test.maxListItemId();
+  return Promise.resolve()
+      .then(() => {
+        // Push Ctrl + E.
+        assertTrue(
+            test.fakeKeyDown('#file-list', 'e', 'U+0045', true, false, false));
+        // Wait for rename text field.
+        return test.waitForElement('li[renaming] input.rename');
+      })
+      .then(() => {
+        var elements =
+            document.querySelectorAll('div.detail-table > list > li[selected]');
+        // Ensure that only the new directory is selected and being renamed.
+        assertTrue(elements.length == 1);
+        assertTrue('renaming' in elements[0].attributes);
+
+        // Check directory tree for new folder.
+        return test.waitForElement('#listitem-' + (maxListItemId + 1));
+      })
+      .then(() => {
+        // Type new folder name.
+        test.inputText('input.rename', 'Test Folder Name');
+        // Push Enter.
+        assertTrue(test.fakeKeyDown(
+            'input.rename', 'Enter', 'Enter', false, false, false));
+
+        // Wait until rename completes.
+        return test.waitForElementLost('input.rename');
+      })
+      .then(() => {
+        // Once it is renamed, the original 'New Folder' item is removed.
+        return test.waitForElementLost('#listitem-' + (maxListItemId + 1));
+      })
+      .then(() => {
+        // A newer entry is then added for the renamed folder.
+        if (chrome.extension.inIncognitoContext)
+          return test.waitForElement('#listitem-' + (maxListItemId + 2));
+      })
+      .then(() => {
+        var expectedEntryRows =
+            test.TestEntryInfo.getExpectedRows(initialEntrySet);
+        expectedEntryRows.push(['Test Folder Name', '--', 'Folder', '']);
+        // Wait for the new folder.
+        return test.waitForFiles(expectedEntryRows, {ignoreDate: true});
+      })
+      .then(() => {
+        // Wait until the new created folder is selected.
+        var nameSpanQuery = 'div.detail-table > list > ' +
+            'li[selected]:not([renaming]) span.entry-name';
+
+        return test.repeatUntil(() => {
+          var elements = document.querySelectorAll(
+              'div.detail-table > list > li[selected] span.entry-name');
+
+          if (elements.length !== 1) {
+            return test.pending(
+                'Selection is not ready (elements: %j)', elements);
+          } else if (elements[0].textContent !== 'Test Folder Name') {
+            return test.pending(
+                'Selected item is wrong. (actual: %s)', elements[0].text);
+          } else {
+            return true;
+          }
+        });
+      });
+};
+
+function testCreateNewFolderAfterSelectFile(done) {
+  test.setupAndWaitUntilReady()
+      .then(() => {
+        return test.selectFirstListItem();
+      })
+      .then(() => {
+        return test.createNewFolder(test.BASIC_LOCAL_ENTRY_SET);
+      })
+      .then(() => {
+        done();
+      })
+      .catch(err => {
+        console.error(err);
+        done(true);
+      });
+}
+
+function testCreateNewFolderDownloads(done) {
+  test.setupAndWaitUntilReady()
+      .then(() => {
+        return test.createNewFolder(test.BASIC_LOCAL_ENTRY_SET);
+      })
+      .then(() => {
+        done();
+      })
+      .catch(err => {
+        console.error(err);
+        done(true);
+      });
+}
+
+function testCreateNewFolderDrive(done) {
+  test.setupAndWaitUntilReady()
+      .then(() => {
+        assertTrue(
+            test.fakeMouseClick('#directory-tree [volume-type-icon="drive"]'));
+        return test.waitForFiles(
+            test.TestEntryInfo.getExpectedRows(test.BASIC_DRIVE_ENTRY_SET));
+      })
+      .then(() => {
+        return test.createNewFolder(test.BASIC_DRIVE_ENTRY_SET);
+      })
+      .then(() => {
+        done();
+      })
+      .catch(err => {
+        console.error(err);
+        done(true);
+      });
+}
diff --git a/ui/file_manager/file_manager/test/delete.js b/ui/file_manager/file_manager/test/delete.js
index 22c36d9..fade12b0 100644
--- a/ui/file_manager/file_manager/test/delete.js
+++ b/ui/file_manager/file_manager/test/delete.js
@@ -3,19 +3,21 @@
 // found in the LICENSE file.
 
 function testDeleteMenuItemIsDisabledWhenNoItemIsSelected(done) {
-  setupAndWaitUntilReady()
-      .then(detailTable => {
-        return waitForElement('list.list');
+  test.setupAndWaitUntilReady()
+      .then(() => {
+        return test.waitForElement('list.list');
       })
-      .then(emptySpace => {
-        assertTrue(test.util.sync.fakeMouseRightClick(window, 'list.list'));
-        return waitForElement('#file-context-menu:not([hidden])');
+      .then(() => {
+        assertTrue(test.fakeMouseRightClick('list.list'));
+        return test.waitForElement('#file-context-menu:not([hidden])');
       })
-      .then(result => {
-        return waitForElement(
+      .then(() => {
+        return test.waitForElement(
             'cr-menu-item[command="#delete"][disabled="disabled"]');
       })
-      .then(result => {
+      .then(() => {
+        // Click back on empty list to close #file-context-menu.
+        assertTrue(test.fakeMouseClick('list.list'));
         done();
       })
       .catch(err => {
@@ -25,42 +27,42 @@
 }
 
 function testDeleteOneItemFromToolbar(done) {
-  var beforeDeletion = TestEntryInfo.getExpectedRows([
-      ENTRIES.photos,
-      ENTRIES.hello,
-      ENTRIES.world,
-      ENTRIES.desktop,
-      ENTRIES.beautiful
+  var beforeDeletion = test.TestEntryInfo.getExpectedRows([
+    test.ENTRIES.photos,
+    test.ENTRIES.hello,
+    test.ENTRIES.world,
+    test.ENTRIES.desktop,
+    test.ENTRIES.beautiful,
   ]);
 
-  var afterDeletion = TestEntryInfo.getExpectedRows([
-      ENTRIES.photos,
-      ENTRIES.hello,
-      ENTRIES.world,
-      ENTRIES.beautiful
+  var afterDeletion = test.TestEntryInfo.getExpectedRows([
+    test.ENTRIES.photos,
+    test.ENTRIES.hello,
+    test.ENTRIES.world,
+    test.ENTRIES.beautiful,
   ]);
 
-  setupAndWaitUntilReady()
+  test.setupAndWaitUntilReady()
       .then(detailTable => {
-        return waitForFiles(beforeDeletion);
+        return test.waitForFiles(beforeDeletion);
       })
       .then(result => {
-        return test.util.sync.selectFile(window, 'My Desktop Background.png');
+        return test.selectFile('My Desktop Background.png');
       })
       .then(result => {
         assertTrue(result);
-        return test.util.sync.fakeMouseClick(window, 'button#delete-button');
+        return test.fakeMouseClick('button#delete-button');
       })
       .then(result => {
         assertTrue(result);
-        return waitForElement('.cr-dialog-container.shown');
+        return test.waitForElement('.cr-dialog-container.shown');
       })
       .then(result => {
-        return test.util.sync.fakeMouseClick(window, 'button.cr-dialog-ok');
+        return test.fakeMouseClick('button.cr-dialog-ok');
       })
       .then(result => {
         assertTrue(result);
-        return waitForFiles(afterDeletion);
+        return test.waitForFiles(afterDeletion);
       })
       .then(result => {
         done();
diff --git a/ui/file_manager/file_manager/test/js/chrome_api_test_impl.js b/ui/file_manager/file_manager/test/js/chrome_api_test_impl.js
index eada5e1..a2af8de 100644
--- a/ui/file_manager/file_manager/test/js/chrome_api_test_impl.js
+++ b/ui/file_manager/file_manager/test/js/chrome_api_test_impl.js
@@ -69,6 +69,7 @@
   },
 
   metricsPrivate: {
+    userActions_: [],
     MetricTypeType: {
       HISTOGRAM_LINEAR: 'histogram-linear',
     },
@@ -76,7 +77,9 @@
     recordPercentage: () => {},
     recordSmallCount: () => {},
     recordTime: () => {},
-    recordUserAction: () => {},
+    recordUserAction: (action) => {
+      chrome.metricsPrivate.userActions_.push(action);
+    },
     recordValue: () => {},
   },
 
diff --git a/ui/file_manager/file_manager/test/js/chrome_file_manager.js b/ui/file_manager/file_manager/test/js/chrome_file_manager.js
index c190ed79..af7795f 100644
--- a/ui/file_manager/file_manager/test/js/chrome_file_manager.js
+++ b/ui/file_manager/file_manager/test/js/chrome_file_manager.js
@@ -138,6 +138,7 @@
   onPreferencesChanged: {
     addListener: () => {},
   },
+  openInspector: (type) => {},
   removeFileWatch: (entry, callback) => {
     setTimeout(callback, 0, true);
   },
diff --git a/ui/file_manager/file_manager/test/js/strings.js b/ui/file_manager/file_manager/test/js/strings.js
index 76ee406..efa6234 100644
--- a/ui/file_manager/file_manager/test/js/strings.js
+++ b/ui/file_manager/file_manager/test/js/strings.js
@@ -62,6 +62,7 @@
       SIZE_COLUMN_LABEL: 'Size',
       SPACE_AVAILABLE: '$1 available',
       STATUS_COLUMN_LABEL: 'Status',
+      TIME_TODAY: 'Today $1',
       TYPE_COLUMN_LABEL: 'Type',
       UI_LOCALE: 'en_US',
       RECENT_ROOT_LABEL: 'Recent',
diff --git a/ui/file_manager/file_manager/test/js/test_util.js b/ui/file_manager/file_manager/test/js/test_util.js
index 6cd9d905..fd1cb6c 100644
--- a/ui/file_manager/file_manager/test/js/test_util.js
+++ b/ui/file_manager/file_manager/test/js/test_util.js
@@ -4,8 +4,11 @@
 
 'use strict';
 
+// All testing functions in namespace 'test'.
+var test = test || {};
+
 // Stores Blobs loaded from src/chrome/test/data/chromeos/file_manager.
-var DATA = {
+test.DATA = {
   'archive.zip': null,
   'image.png': null,
   'image2.png': null,
@@ -17,13 +20,13 @@
 };
 
 // Load DATA from local filesystem.
-function loadData() {
-  return Promise.all(Object.keys(DATA).map(filename => {
+test.loadData = function() {
+  return Promise.all(Object.keys(test.DATA).map(filename => {
     return new Promise(resolve => {
       var req = new XMLHttpRequest();
       req.responseType = 'blob';
       req.onload = () => {
-        DATA[filename] = req.response;
+        test.DATA[filename] = req.response;
         resolve();
       };
       req.open(
@@ -31,13 +34,13 @@
       req.send();
     });
   }));
-}
+};
 
 /**
  * @enum {string}
  * @const
  */
-var EntryType = Object.freeze({
+test.EntryType = Object.freeze({
   FILE: 'file',
   DIRECTORY: 'directory'
 });
@@ -46,7 +49,7 @@
  * @enum {string}
  * @const
  */
-var SharedOption = Object.freeze({
+test.SharedOption = Object.freeze({
   NONE: 'none',
   SHARED: 'shared'
 });
@@ -66,7 +69,7 @@
  * @param {string} typeText Type name to be shown in the type column.
  * @constructor
  */
-function TestEntryInfo(type,
+test.TestEntryInfo = function(type,
                        sourceFileName,
                        targetPath,
                        mimeType,
@@ -85,20 +88,20 @@
   this.sizeText = sizeText;
   this.typeText = typeText;
   Object.freeze(this);
-}
+};
 
-TestEntryInfo.getExpectedRows = function(entries) {
+test.TestEntryInfo.getExpectedRows = function(entries) {
   return entries.map(function(entry) { return entry.getExpectedRow(); });
 };
 
 /**
  * Returns 4-typle name, size, type, date as shown in file list.
  */
-TestEntryInfo.prototype.getExpectedRow = function() {
+test.TestEntryInfo.prototype.getExpectedRow = function() {
   return [this.nameText, this.sizeText, this.typeText, this.lastModifiedTime];
 };
 
-TestEntryInfo.getMockFileSystemPopulateRows = function(entries, prefix) {
+test.TestEntryInfo.getMockFileSystemPopulateRows = function(entries, prefix) {
   return entries.map(function(entry) {
     return entry.getMockFileSystemPopulateRow(prefix);
   });
@@ -108,9 +111,9 @@
  * Returns object {fullPath: ..., metadata: {...}, content: ...} as used in
  * MockFileSystem.populate.
  */
-TestEntryInfo.prototype.getMockFileSystemPopulateRow = function(prefix) {
-  var suffix = this.type == EntryType.DIRECTORY ? '/' : '';
-  var content = DATA[this.sourceFileName];
+test.TestEntryInfo.prototype.getMockFileSystemPopulateRow = function(prefix) {
+  var suffix = this.type == test.EntryType.DIRECTORY ? '/' : '';
+  var content = test.DATA[this.sourceFileName];
   var size = content && content.size || 0;
   return {
     fullPath: prefix + this.nameText + suffix,
@@ -118,6 +121,7 @@
       size: size,
       modificationTime: new Date(Date.parse(this.lastModifiedTime)),
       contentMimeType: this.mimeType,
+      hosted: this.mimeType == 'application/vnd.google-apps.document',
     },
     content: content
   };
@@ -128,106 +132,106 @@
  * @type {Object<TestEntryInfo>}
  * @const
  */
-var ENTRIES = {
-  hello: new TestEntryInfo(
-      EntryType.FILE, 'text.txt', 'hello.txt',
-      'text/plain', SharedOption.NONE, 'Sep 4, 1998, 12:34 PM',
+test.ENTRIES = {
+  hello: new test.TestEntryInfo(
+      test.EntryType.FILE, 'text.txt', 'hello.txt',
+      'text/plain', test.SharedOption.NONE, 'Sep 4, 1998, 12:34 PM',
       'hello.txt', '51 bytes', 'Plain text'),
 
-  world: new TestEntryInfo(
-      EntryType.FILE, 'video.ogv', 'world.ogv',
-      'video/ogg', SharedOption.NONE, 'Jul 4, 2012, 10:35 AM',
+  world: new test.TestEntryInfo(
+      test.EntryType.FILE, 'video.ogv', 'world.ogv',
+      'video/ogg', test.SharedOption.NONE, 'Jul 4, 2012, 10:35 AM',
       'world.ogv', '59 KB', 'OGG video'),
 
-  unsupported: new TestEntryInfo(
-      EntryType.FILE, 'random.bin', 'unsupported.foo',
-      'application/x-foo', SharedOption.NONE, 'Jul 4, 2012, 10:36 AM',
+  unsupported: new test.TestEntryInfo(
+      test.EntryType.FILE, 'random.bin', 'unsupported.foo',
+      'application/x-foo', test.SharedOption.NONE, 'Jul 4, 2012, 10:36 AM',
       'unsupported.foo', '8 KB', 'FOO file'),
 
-  desktop: new TestEntryInfo(
-      EntryType.FILE, 'image.png', 'My Desktop Background.png',
-      'image/png', SharedOption.NONE, 'Jan 18, 2038, 1:02 AM',
+  desktop: new test.TestEntryInfo(
+      test.EntryType.FILE, 'image.png', 'My Desktop Background.png',
+      'image/png', test.SharedOption.NONE, 'Jan 18, 2038, 1:02 AM',
       'My Desktop Background.png', '272 bytes', 'PNG image'),
 
   // An image file without an extension, to confirm that file type detection
   // using mime types works fine.
-  image2: new TestEntryInfo(
-      EntryType.FILE, 'image2.png', 'image2',
-      'image/png', SharedOption.NONE, 'Jan 18, 2038, 1:02 AM',
+  image2: new test.TestEntryInfo(
+      test.EntryType.FILE, 'image2.png', 'image2',
+      'image/png', test.SharedOption.NONE, 'Jan 18, 2038, 1:02 AM',
       'image2', '4 KB', 'PNG image'),
 
-  image3: new TestEntryInfo(
-      EntryType.FILE, 'image3.jpg', 'image3.jpg',
-      'image/jpeg', SharedOption.NONE, 'Jan 18, 2038, 1:02 AM',
+  image3: new test.TestEntryInfo(
+      test.EntryType.FILE, 'image3.jpg', 'image3.jpg',
+      'image/jpeg', test.SharedOption.NONE, 'Jan 18, 2038, 1:02 AM',
       'image3.jpg', '3 KB', 'JPEG image'),
 
   // An ogg file without a mime type, to confirm that file type detection using
   // file extensions works fine.
-  beautiful: new TestEntryInfo(
-      EntryType.FILE, 'music.ogg', 'Beautiful Song.ogg',
-      null, SharedOption.NONE, 'Nov 12, 2086, 12:00 PM',
+  beautiful: new test.TestEntryInfo(
+      test.EntryType.FILE, 'music.ogg', 'Beautiful Song.ogg',
+      null, test.SharedOption.NONE, 'Nov 12, 2086, 12:00 PM',
       'Beautiful Song.ogg', '14 KB', 'OGG audio'),
 
-  photos: new TestEntryInfo(
-      EntryType.DIRECTORY, null, 'photos',
-      null, SharedOption.NONE, 'Jan 1, 1980, 11:59 PM',
+  photos: new test.TestEntryInfo(
+      test.EntryType.DIRECTORY, null, 'photos',
+      null, test.SharedOption.NONE, 'Jan 1, 1980, 11:59 PM',
       'photos', '--', 'Folder'),
 
-  testDocument: new TestEntryInfo(
-      EntryType.FILE, null, 'Test Document',
+  testDocument: new test.TestEntryInfo(
+      test.EntryType.FILE, null, 'Test Document',
       'application/vnd.google-apps.document',
-      SharedOption.NONE, 'Apr 10, 2013, 4:20 PM',
+      test.SharedOption.NONE, 'Apr 10, 2013, 4:20 PM',
       'Test Document.gdoc', '--', 'Google document'),
 
-  testSharedDocument: new TestEntryInfo(
-      EntryType.FILE, null, 'Test Shared Document',
+  testSharedDocument: new test.TestEntryInfo(
+      test.EntryType.FILE, null, 'Test Shared Document',
       'application/vnd.google-apps.document',
-      SharedOption.SHARED, 'Mar 20, 2013, 10:40 PM',
+      test.SharedOption.SHARED, 'Mar 20, 2013, 10:40 PM',
       'Test Shared Document.gdoc', '--', 'Google document'),
 
-  newlyAdded: new TestEntryInfo(
-      EntryType.FILE, 'music.ogg', 'newly added file.ogg',
-      'audio/ogg', SharedOption.NONE, 'Sep 4, 1998, 12:00 AM',
+  newlyAdded: new test.TestEntryInfo(
+      test.EntryType.FILE, 'music.ogg', 'newly added file.ogg',
+      'audio/ogg', test.SharedOption.NONE, 'Sep 4, 1998, 12:00 AM',
       'newly added file.ogg', '14 KB', 'OGG audio'),
 
-  directoryA: new TestEntryInfo(
-      EntryType.DIRECTORY, null, 'A',
-      null, SharedOption.NONE, 'Jan 1, 2000, 1:00 AM',
+  directoryA: new test.TestEntryInfo(
+      test.EntryType.DIRECTORY, null, 'A',
+      null, test.SharedOption.NONE, 'Jan 1, 2000, 1:00 AM',
       'A', '--', 'Folder'),
 
-  directoryB: new TestEntryInfo(
-      EntryType.DIRECTORY, null, 'A/B',
-      null, SharedOption.NONE, 'Jan 1, 2000, 1:00 AM',
+  directoryB: new test.TestEntryInfo(
+      test.EntryType.DIRECTORY, null, 'A/B',
+      null, test.SharedOption.NONE, 'Jan 1, 2000, 1:00 AM',
       'B', '--', 'Folder'),
 
-  directoryC: new TestEntryInfo(
-      EntryType.DIRECTORY, null, 'A/B/C',
-      null, SharedOption.NONE, 'Jan 1, 2000, 1:00 AM',
+  directoryC: new test.TestEntryInfo(
+      test.EntryType.DIRECTORY, null, 'A/B/C',
+      null, test.SharedOption.NONE, 'Jan 1, 2000, 1:00 AM',
       'C', '--', 'Folder'),
 
-  directoryD: new TestEntryInfo(
-      EntryType.DIRECTORY, null, 'D',
-      null, SharedOption.NONE, 'Jan 1, 2000, 1:00 AM',
+  directoryD: new test.TestEntryInfo(
+      test.EntryType.DIRECTORY, null, 'D',
+      null, test.SharedOption.NONE, 'Jan 1, 2000, 1:00 AM',
       'D', '--', 'Folder'),
 
-  directoryE: new TestEntryInfo(
-      EntryType.DIRECTORY, null, 'D/E',
-      null, SharedOption.NONE, 'Jan 1, 2000, 1:00 AM',
+  directoryE: new test.TestEntryInfo(
+      test.EntryType.DIRECTORY, null, 'D/E',
+      null, test.SharedOption.NONE, 'Jan 1, 2000, 1:00 AM',
       'E', '--', 'Folder'),
 
-  directoryF: new TestEntryInfo(
-      EntryType.DIRECTORY, null, 'D/E/F',
-      null, SharedOption.NONE, 'Jan 1, 2000, 1:00 AM',
+  directoryF: new test.TestEntryInfo(
+      test.EntryType.DIRECTORY, null, 'D/E/F',
+      null, test.SharedOption.NONE, 'Jan 1, 2000, 1:00 AM',
       'F', '--', 'Folder'),
 
-  zipArchive: new TestEntryInfo(
-      EntryType.FILE, 'archive.zip', 'archive.zip',
-      'application/x-zip', SharedOption.NONE, 'Jan 1, 2014, 1:00 AM',
+  zipArchive: new test.TestEntryInfo(
+      test.EntryType.FILE, 'archive.zip', 'archive.zip',
+      'application/x-zip', test.SharedOption.NONE, 'Jan 1, 2014, 1:00 AM',
       'archive.zip', '533 bytes', 'Zip archive'),
 
-  hiddenFile: new TestEntryInfo(
-    EntryType.FILE, 'text.txt', '.hiddenfile.txt',
-    'text/plain', SharedOption.NONE, 'Sep 30, 2014, 3:30 PM',
+  hiddenFile: new test.TestEntryInfo(
+    test.EntryType.FILE, 'text.txt', '.hiddenfile.txt',
+    'text/plain', test.SharedOption.NONE, 'Sep 30, 2014, 3:30 PM',
     '.hiddenfile.txt', '51 bytes', 'Plain text')
 };
 
@@ -236,12 +240,12 @@
  * @type {Array<TestEntryInfo>}
  * @const
  */
-var BASIC_LOCAL_ENTRY_SET = [
-  ENTRIES.hello,
-  ENTRIES.world,
-  ENTRIES.desktop,
-  ENTRIES.beautiful,
-  ENTRIES.photos
+test.BASIC_LOCAL_ENTRY_SET = [
+  test.ENTRIES.hello,
+  test.ENTRIES.world,
+  test.ENTRIES.desktop,
+  test.ENTRIES.beautiful,
+  test.ENTRIES.photos
 ];
 
 /**
@@ -253,49 +257,112 @@
  * @type {Array<TestEntryInfo>}
  * @const
  */
-var BASIC_DRIVE_ENTRY_SET = [
-  ENTRIES.hello,
-  ENTRIES.world,
-  ENTRIES.desktop,
-  ENTRIES.beautiful,
-  ENTRIES.photos,
-  ENTRIES.unsupported,
-  ENTRIES.testDocument,
-  ENTRIES.testSharedDocument
+test.BASIC_DRIVE_ENTRY_SET = [
+  test.ENTRIES.hello,
+  test.ENTRIES.world,
+  test.ENTRIES.desktop,
+  test.ENTRIES.beautiful,
+  test.ENTRIES.photos,
+  test.ENTRIES.unsupported,
+  test.ENTRIES.testDocument,
+  test.ENTRIES.testSharedDocument
 ];
 
-var INTERVAL_FOR_WAIT_UNTIL = 100;  // ms
-var INTERVAL_FOR_WAIT_LOGGING = 10000; // 10s
+/**
+ * Interval milliseconds between checks of repeatUntil.
+ * @type {number}
+ * @const
+ */
+test.REPEAT_UNTIL_INTERVAL = 200;
 
 /**
- * Waits until testFunction becomes true.
- * @param {function(): Object} testFunction A function which is tested.
- * @return {!Promise} A promise which is fullfilled when the testFunction
- *     becomes true.
+ * Interval milliseconds between log output of repeatUntil.
+ * @type {number}
+ * @const
  */
-function waitUntil(testFunction) {
-  return new Promise(function(resolve) {
-    var tryTestFunction = function() {
-      var result = testFunction();
-      if (result) {
-        resolve(result);
+test.LOG_INTERVAL = 3000;
+
+/**
+ * Returns a pending marker. See also the repeatUntil function.
+ * @param {string} message Pending reason including %s, %d, or %j markers. %j
+ *     format an object as JSON.
+ * @param {Array<*>} var_args Values to be assigined to %x markers.
+ * @return {Object} Object which returns true for the expression: obj instanceof
+ *     pending.
+ */
+test.pending = function(message, var_args) {
+  var index = 1;
+  var args = arguments;
+  var formattedMessage = message.replace(/%[sdj]/g, function(pattern) {
+    var arg = args[index++];
+    switch(pattern) {
+      case '%s': return String(arg);
+      case '%d': return Number(arg);
+      case '%j': return JSON.stringify(arg);
+      default: return pattern;
+    }
+  });
+  var pendingMarker = Object.create(test.pending.prototype);
+  pendingMarker.message = formattedMessage;
+  return pendingMarker;
+};
+
+/**
+ * Waits until the checkFunction returns a value but a pending marker.
+ * @param {function():*} checkFunction Function to check a condition. It can
+ *     return a pending marker created by a pending function.
+ * @return {Promise} Promise to be fulfilled with the return value of
+ *     checkFunction when the checkFunction reutrns a value but a pending
+ *     marker.
+ */
+test.repeatUntil = function(checkFunction) {
+  var logTime = Date.now() + test.LOG_INTERVAL;
+  var step = function() {
+    return Promise.resolve(checkFunction()).then(function(result) {
+      if (result instanceof test.pending) {
+        if (Date.now() > logTime) {
+          console.warn(result.message);
+          logTime += test.LOG_INTERVAL;
+        }
+        return new Promise(resolve => {
+                 setTimeout(resolve, test.REPEAT_UNTIL_INTERVAL);
+               })
+            .then(step);
       } else {
-        setTimeout(tryTestFunction, INTERVAL_FOR_WAIT_UNTIL);
+        return result;
       }
-    };
-
-    tryTestFunction();
-  });
-}
+    });
+  };
+  return step();
+};
 
 /**
- * Waits until specified element exists.
+ * Waits for the specified element appearing in the DOM.
+ * @param {string} query Query string for the element.
+ * @return {Promise} Promise to be fulfilled when the element appears.
  */
-function waitForElement(selectors) {
-  return waitUntil(() => {
-    return document.querySelector(selectors);
+test.waitForElement = function(query) {
+  return test.repeatUntil(() => {
+    var element = document.querySelector(query);
+    if (element)
+      return element;
+    return test.pending('Element %s is not found.', query);
   });
-}
+};
+
+/**
+ * Waits for the specified element leaving from the DOM.
+ * @param {string} query Query string for the element.
+ * @return {Promise} Promise to be fulfilled when the element is lost.
+ */
+test.waitForElementLost = function(query) {
+  return test.repeatUntil(() => {
+    var element = document.querySelector(query);
+    if (element)
+      return test.pending('Elements %s still exists.', query);
+    return true;
+  });
+};
 
 /**
  * Adds specified TestEntryInfos to downloads and drive.
@@ -303,20 +370,20 @@
  * @param {!Array<TestEntryInfo} downloads Entries for downloads.
  * @param {!Array<TestEntryInfo} drive Entries for drive.
  */
-function addEntries(downloads, drive) {
+test.addEntries = function(downloads, drive) {
   var fsDownloads =
       mockVolumeManager
           .getCurrentProfileVolumeInfo(VolumeManagerCommon.VolumeType.DOWNLOADS)
           .fileSystem;
   fsDownloads.populate(
-      TestEntryInfo.getMockFileSystemPopulateRows(downloads, '/'), true);
+      test.TestEntryInfo.getMockFileSystemPopulateRows(downloads, '/'), true);
 
   var fsDrive =
       mockVolumeManager
           .getCurrentProfileVolumeInfo(VolumeManagerCommon.VolumeType.DRIVE)
           .fileSystem;
   fsDrive.populate(
-      TestEntryInfo.getMockFileSystemPopulateRows(drive, '/root/'), true);
+      test.TestEntryInfo.getMockFileSystemPopulateRows(drive, '/root/'), true);
 
   // Send onDirectoryChanged events.
   chrome.fileManagerPrivate.dispatchEvent_(
@@ -324,7 +391,7 @@
   chrome.fileManagerPrivate.dispatchEvent_(
       'onDirectoryChanged',
       {eventType: 'changed', entry: fsDrive.entries['/root']});
-}
+};
 
 /**
  * Waits for the file list turns to the given contents.
@@ -337,32 +404,40 @@
  * @return {Promise} Promise to be fulfilled when the file list turns to the
  *     given contents.
  */
-function waitForFiles(expected, opt_options) {
+test.waitForFiles = function(expected, opt_options) {
   var options = opt_options || {};
-  var nextLog = Date.now() + INTERVAL_FOR_WAIT_LOGGING;
-  return waitUntil(function() {
-    var files = test.util.sync.getFileList(window);
+  var nextLog = Date.now() + test.INTERVAL_FOR_WAIT_LOGGING;
+  return test.repeatUntil(function() {
+    var files = test.getFileList();
     if (Date.now() > nextLog) {
       console.debug('waitForFiles', expected, files);
-      nextLog = Date.now() + INTERVAL_FOR_WAIT_LOGGING;
+      nextLog = Date.now() + test.INTERVAL_FOR_WAIT_LOGGING;
     }
     if (!options.orderCheck) {
       files.sort();
       expected.sort();
     }
-    if (files.length != expected.length)
-      return false;
-    for (var i = 0; i < files.length; i++) {
-      // Each row is [name, size, type, date].
-      if ((!options.ignoreName && files[i][0] != expected[i][0]) ||
-          (!options.ignoreSize && files[i][1] != expected[i][1]) ||
-          (!options.ignoreType && files[i][2] != expected[i][2]) ||
-          (!options.ignoreDate && files[i][3] != expected[i][3]))
-        return false;
+
+    if (((a, b) => {
+          if (a.length != b.length)
+            return false;
+          for (var i = 0; i < files.length; i++) {
+            // Each row is [name, size, type, date].
+            if ((!options.ignoreName && a[i][0] != b[i][0]) ||
+                (!options.ignoreSize && a[i][1] != b[i][1]) ||
+                (!options.ignoreType && a[i][2] != b[i][2]) ||
+                (!options.ignoreDate && a[i][3] != b[i][3]))
+              return false;
+          }
+          return true;
+        })(expected, files)) {
+      return true;
+    } else {
+      return test.pending(
+          'waitForFiles: expected: %j actual %j.', expected, files);
     }
-    return true;
   });
-}
+};
 
 /**
  * Opens a Files app's main window and waits until it is initialized. Fills
@@ -371,24 +446,60 @@
  * @return {Promise} Promise to be fulfilled with the result object, which
  *     contains the file list.
  */
-function setupAndWaitUntilReady() {
-  return loadData()
-      .then(result => {
-        addEntries(BASIC_LOCAL_ENTRY_SET, BASIC_DRIVE_ENTRY_SET);
-        return waitForElement('#directory-tree [volume-type-icon="downloads"]');
+test.setupAndWaitUntilReady = function(resolve) {
+  // Copy some functions from test.util.sync and bind to main window.
+  test.fakeMouseClick = test.util.sync.fakeMouseClick.bind(null, window);
+  test.fakeMouseDoubleClick =
+      test.util.sync.fakeMouseDoubleClick.bind(null, window);
+  test.fakeMouseRightClick =
+      test.util.sync.fakeMouseRightClick.bind(null, window);
+  test.fakeKeyDown = test.util.sync.fakeKeyDown.bind(null, window);
+  test.getFileList = test.util.sync.getFileList.bind(null, window);
+  test.inputText = test.util.sync.inputText.bind(null, window);
+  test.selectFile = test.util.sync.selectFile.bind(null, window);
+
+  return test.loadData()
+      .then(() => {
+        test.addEntries(test.BASIC_LOCAL_ENTRY_SET, test.BASIC_DRIVE_ENTRY_SET);
+        return test.waitForElement(
+            '#directory-tree [volume-type-icon="downloads"]');
       })
       .then(() => {
-        return test.util.sync.fakeMouseClick(
-            window, '#directory-tree [volume-type-icon="downloads"]');
-      })
-      .then(result => {
-        assertTrue(result);
-        return waitForFiles(
-            TestEntryInfo.getExpectedRows(BASIC_LOCAL_ENTRY_SET));
+        assertTrue(test.fakeMouseClick(
+            '#directory-tree [volume-type-icon="downloads"]'));
+        return test.waitForFiles(
+            test.TestEntryInfo.getExpectedRows(test.BASIC_LOCAL_ENTRY_SET));
       });
-}
+};
 
-// Shortcut for endTests with success.
-function doneTests(opt_failed) {
+/**
+ * Shortcut for endTests with success.
+ * @param {boolean=} opt_failed True indicates failure.
+ */
+test.done = function(opt_failed) {
   endTests(!opt_failed);
-}
+};
+
+/**
+ * @return {number} Maximum listitem-? id from #file-list.
+ */
+test.maxListItemId = function() {
+  var listItems = document.querySelectorAll('#file-list .table-row');
+  if (!listItems)
+    return 0;
+  return Math.max(...Array.from(listItems).map(e => {
+    return e.id.replace('listitem-', '');
+  }));
+};
+
+/**
+ * @return {number} Minium listitem-? id from #file-list.
+ */
+test.minListItemId = function() {
+  var listItems = document.querySelectorAll('#file-list .table-row');
+  if (!listItems)
+    return 0;
+  return Math.min(...Array.from(listItems).map(e => {
+    return e.id.replace('listitem-', '');
+  }));
+};
diff --git a/ui/file_manager/file_manager/test/scripts/create_test_main.py b/ui/file_manager/file_manager/test/scripts/create_test_main.py
index a5e8c33..d88f4dd 100755
--- a/ui/file_manager/file_manager/test/scripts/create_test_main.py
+++ b/ui/file_manager/file_manager/test/scripts/create_test_main.py
@@ -116,9 +116,9 @@
     '../../webui/resources/js/assert.js',
     '../../webui/resources/js/cr.js',
     '../../webui/resources/js/cr/event_target.js',
-    '../../webui/resources/js/cr/ui/array_data_model.js">',
+    '../../webui/resources/js/cr/ui/array_data_model.js',
     '../../webui/resources/js/load_time_data.js',
-    '../../webui/resources/js/webui_resource_test.js">',
+    '../../webui/resources/js/webui_resource_test.js',
     'test/js/strings.js',
     'common/js/util.js',
     'common/js/mock_entry.js',
diff --git a/ui/file_manager/file_manager/test/uma.js b/ui/file_manager/file_manager/test/uma.js
new file mode 100644
index 0000000..11e0120f
--- /dev/null
+++ b/ui/file_manager/file_manager/test/uma.js
@@ -0,0 +1,28 @@
+// Copyright 2018 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.
+
+function testClickBreadcrumb(done) {
+  test.setupAndWaitUntilReady()
+      .then(() => {
+        // Reset metrics.
+        chrome.metricsPrivate.userActions_ = [];
+        // Click first row which is 'photos' dir, wait for breadcrumb to show.
+        assertTrue(test.fakeMouseDoubleClick('#file-list li.table-row'));
+        return test.waitForElement(
+            '#location-breadcrumbs .breadcrumb-path:nth-of-type(2)');
+      })
+      .then(result => {
+        // Click breadcrumb to return to parent dir.
+        assertTrue(test.fakeMouseClick(
+            '#location-breadcrumbs .breadcrumb-path:nth-of-type(1)'));
+        return test.waitForFiles(
+            test.TestEntryInfo.getExpectedRows(test.BASIC_LOCAL_ENTRY_SET));
+      })
+      .then(result => {
+        assertArrayEquals(
+            ['FileBrowser.ClickBreadcrumbs'],
+            chrome.metricsPrivate.userActions_);
+        done();
+      });
+}
diff --git a/ui/file_manager/integration_tests/file_manager/create_new_folder.js b/ui/file_manager/integration_tests/file_manager/create_new_folder.js
index 84642ed..c0ff132f 100644
--- a/ui/file_manager/integration_tests/file_manager/create_new_folder.js
+++ b/ui/file_manager/integration_tests/file_manager/create_new_folder.js
@@ -1,4 +1,4 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
+// Copyright 2018 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.
 
@@ -9,8 +9,8 @@
  * When we are not in guest mode, we fill Google Drive with the basic entry set
  * which causes an extra tree-item to be added.
  */
-var TREEITEM_DRIVE = '#directory-tree > div:nth-child(1) '
-var TREEITEM_DOWNLOADS = '#directory-tree > div:nth-child(2) '
+var TREEITEM_DRIVE = '#directory-tree > div:nth-child(1) ';
+var TREEITEM_DOWNLOADS = '#directory-tree > div:nth-child(2) ';
 var EXPAND_ICON = '> .tree-row > .expand-icon';
 var EXPANDED_SUBTREE = '> .tree-children[expanded]';
 var NEWFOLDER = '#tree-item-autogen-id-9';
@@ -139,7 +139,7 @@
       });
     });
   });
-};
+}
 
 /**
  * This is used to expand the tree item for Downloads or Drive.
@@ -170,7 +170,7 @@
   }).then(function() {
     return expandRoot(windowId, TREEITEM_DOWNLOADS);
   }).then(function() {
-    return remoteCall.waitForElement(windowId, '#detail-table')
+    return remoteCall.waitForElement(windowId, '#detail-table');
   }).then(function() {
     return createNewFolder(windowId, PATH, BASIC_LOCAL_ENTRY_SET);
   });
@@ -187,7 +187,7 @@
     windowId = results.windowId;
     return expandRoot(windowId, TREEITEM_DOWNLOADS);
   }).then(function() {
-    return remoteCall.waitForElement(windowId, '#detail-table')
+    return remoteCall.waitForElement(windowId, '#detail-table');
   }).then(function() {
     return createNewFolder(windowId, PATH, BASIC_LOCAL_ENTRY_SET);
   });
@@ -201,10 +201,10 @@
   var promise = new Promise(function(callback) {
     setupAndWaitUntilReady(null, PATH, callback);
   }).then(function(results) {
-    windowId = results.windowId
+    windowId = results.windowId;
     return expandRoot(windowId, TREEITEM_DRIVE);
   }).then(function() {
-    return remoteCall.waitForElement(windowId, '#detail-table')
+    return remoteCall.waitForElement(windowId, '#detail-table');
   }).then(function() {
     return createNewFolder(windowId, PATH, BASIC_DRIVE_ENTRY_SET);
   });
diff --git a/ui/gfx/color_palette.h b/ui/gfx/color_palette.h
index 3c77e6a..18db6ac7 100644
--- a/ui/gfx/color_palette.h
+++ b/ui/gfx/color_palette.h
@@ -29,6 +29,7 @@
 constexpr SkColor kGoogleRedDark600 = SkColorSetRGB(0xD3, 0x3B, 0x30);
 constexpr SkColor kGoogleRedDark800 = SkColorSetRGB(0xB4, 0x1B, 0x1A);
 constexpr SkColor kGoogleGreen300 = SkColorSetRGB(0x81, 0xC9, 0x95);
+constexpr SkColor kGoogleGreen600 = SkColorSetRGB(0x1E, 0x8E, 0x3E);
 constexpr SkColor kGoogleGreen700 = SkColorSetRGB(0x18, 0x80, 0x38);
 constexpr SkColor kGoogleYellow300 = SkColorSetRGB(0xFD, 0xD6, 0x63);
 constexpr SkColor kGoogleYellow700 = SkColorSetRGB(0xF2, 0x99, 0x00);
diff --git a/ui/gfx/linux/client_native_pixmap_factory_dmabuf.cc b/ui/gfx/linux/client_native_pixmap_factory_dmabuf.cc
index a9fd862..ea246a9 100644
--- a/ui/gfx/linux/client_native_pixmap_factory_dmabuf.cc
+++ b/ui/gfx/linux/client_native_pixmap_factory_dmabuf.cc
@@ -63,7 +63,9 @@
                format == gfx::BufferFormat::YVU_420;
       case gfx::BufferUsage::SCANOUT:
         return format == gfx::BufferFormat::BGRX_8888 ||
-               format == gfx::BufferFormat::RGBX_8888;
+               format == gfx::BufferFormat::RGBX_8888 ||
+               format == gfx::BufferFormat::RGBA_8888 ||
+               format == gfx::BufferFormat::BGRA_8888;
       case gfx::BufferUsage::SCANOUT_CPU_READ_WRITE:
         return
 #if defined(ARCH_CPU_X86_FAMILY)
diff --git a/ui/gl/BUILD.gn b/ui/gl/BUILD.gn
index b1bd611..03d6eb0 100644
--- a/ui/gl/BUILD.gn
+++ b/ui/gl/BUILD.gn
@@ -224,6 +224,12 @@
       ]
     }
   }
+  if (is_mac || use_egl) {
+    sources += [
+      "yuv_to_rgb_converter.cc",
+      "yuv_to_rgb_converter.h",
+    ]
+  }
   if (is_android || is_linux || is_fuchsia) {
     sources += [
       "gl_implementation_osmesa.cc",
@@ -313,8 +319,6 @@
       "gl_image_io_surface.mm",
       "scoped_cgl.cc",
       "scoped_cgl.h",
-      "yuv_to_rgb_converter.cc",
-      "yuv_to_rgb_converter.h",
     ]
 
     libs = [
diff --git a/ui/gl/gl_context_cgl.cc b/ui/gl/gl_context_cgl.cc
index 6b85039..d0a1d8fe 100644
--- a/ui/gl/gl_context_cgl.cc
+++ b/ui/gl/gl_context_cgl.cc
@@ -156,7 +156,8 @@
       SetCurrentGL(GetCurrentGL());
     }
 
-    ScopedCGLSetCurrentContext(static_cast<CGLContextObj>(context_));
+    ScopedCGLSetCurrentContext scoped_set_current(
+        static_cast<CGLContextObj>(context_));
     yuv_to_rgb_converters_.clear();
 
     // Rebind the current context's API if needed.
@@ -228,8 +229,8 @@
   std::unique_ptr<YUVToRGBConverter>& yuv_to_rgb_converter =
       yuv_to_rgb_converters_[color_space];
   if (!yuv_to_rgb_converter)
-    yuv_to_rgb_converter.reset(
-        new YUVToRGBConverter(*GetVersionInfo(), color_space));
+    yuv_to_rgb_converter =
+        std::make_unique<YUVToRGBConverter>(*GetVersionInfo(), color_space);
   return yuv_to_rgb_converter.get();
 }
 
diff --git a/ui/gl/gl_context_egl.cc b/ui/gl/gl_context_egl.cc
index 8e7043a..d9a82cf 100644
--- a/ui/gl/gl_context_egl.cc
+++ b/ui/gl/gl_context_egl.cc
@@ -21,8 +21,9 @@
 #include "third_party/khronos/EGL/eglext.h"
 #include "ui/gl/egl_util.h"
 #include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_gl_api_implementation.h"
 #include "ui/gl/gl_surface_egl.h"
-
+#include "ui/gl/yuv_to_rgb_converter.h"
 
 #ifndef EGL_CHROMIUM_create_context_bind_generates_resource
 #define EGL_CHROMIUM_create_context_bind_generates_resource 1
@@ -62,8 +63,8 @@
 
 GLContextEGL::GLContextEGL(GLShareGroup* share_group)
     : GLContextReal(share_group),
-      context_(nullptr),
-      display_(nullptr),
+      context_(EGL_NO_CONTEXT),
+      display_(EGL_NO_DISPLAY),
       config_(nullptr),
       unbind_fbo_on_makecurrent_(false) {}
 
@@ -204,6 +205,7 @@
 }
 
 void GLContextEGL::Destroy() {
+  ReleaseYUVToRGBConverters();
   if (context_) {
     if (!eglDestroyContext(display_, context_)) {
       LOG(ERROR) << "eglDestroyContext failed with error "
@@ -214,6 +216,58 @@
   }
 }
 
+YUVToRGBConverter* GLContextEGL::GetYUVToRGBConverter(
+    const gfx::ColorSpace& color_space) {
+  std::unique_ptr<YUVToRGBConverter>& yuv_to_rgb_converter =
+      yuv_to_rgb_converters_[color_space];
+  if (!yuv_to_rgb_converter) {
+    yuv_to_rgb_converter =
+        std::make_unique<YUVToRGBConverter>(*GetVersionInfo(), color_space);
+  }
+  return yuv_to_rgb_converter.get();
+}
+
+void GLContextEGL::ReleaseYUVToRGBConverters() {
+  if (!yuv_to_rgb_converters_.empty()) {
+    // If this context is not current, bind this context's API so that the YUV
+    // converter can safely destruct
+    GLContext* current_context = GetRealCurrent();
+    if (current_context != this) {
+      SetCurrentGL(GetCurrentGL());
+    }
+
+    EGLContext current_egl_context = eglGetCurrentContext();
+    EGLSurface current_draw_surface = EGL_NO_SURFACE;
+    EGLSurface current_read_surface = EGL_NO_SURFACE;
+    if (context_ != current_egl_context) {
+      current_draw_surface = eglGetCurrentSurface(EGL_DRAW);
+      current_read_surface = eglGetCurrentSurface(EGL_READ);
+      // This call relies on the fact that yuv_to_rgb_converters_ are only ever
+      // allocated in GLImageIOSurfaceEGL::CopyTexImage, which is only on
+      // MacOS, where surfaceless EGL contexts are always supported.
+      if (!eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE, context_)) {
+        DVLOG(1) << "eglMakeCurrent failed with error "
+                 << GetLastEGLErrorString();
+      }
+    }
+
+    yuv_to_rgb_converters_.clear();
+
+    // Rebind the current context's API if needed.
+    if (current_context && current_context != this) {
+      SetCurrentGL(current_context->GetCurrentGL());
+    }
+
+    if (context_ != current_egl_context) {
+      if (!eglMakeCurrent(display_, current_draw_surface, current_read_surface,
+                          current_egl_context)) {
+        DVLOG(1) << "eglMakeCurrent failed with error "
+                 << GetLastEGLErrorString();
+      }
+    }
+  }
+}
+
 bool GLContextEGL::MakeCurrent(GLSurface* surface) {
   DCHECK(context_);
   if (IsCurrent(surface))
diff --git a/ui/gl/gl_context_egl.h b/ui/gl/gl_context_egl.h
index 75b2f320..36a01ff 100644
--- a/ui/gl/gl_context_egl.h
+++ b/ui/gl/gl_context_egl.h
@@ -5,6 +5,7 @@
 #ifndef UI_GL_GL_CONTEXT_EGL_H_
 #define UI_GL_GL_CONTEXT_EGL_H_
 
+#include <map>
 #include <string>
 
 #include "base/compiler_specific.h"
@@ -35,17 +36,22 @@
   void OnSetSwapInterval(int interval) override;
   bool WasAllocatedUsingRobustnessExtension() override;
   void SetUnbindFboOnMakeCurrent() override;
+  YUVToRGBConverter* GetYUVToRGBConverter(
+      const gfx::ColorSpace& color_space) override;
 
  protected:
   ~GLContextEGL() override;
 
  private:
   void Destroy();
+  void ReleaseYUVToRGBConverters();
 
   EGLContext context_;
   EGLDisplay display_;
   EGLConfig config_;
   bool unbind_fbo_on_makecurrent_;
+  std::map<gfx::ColorSpace, std::unique_ptr<YUVToRGBConverter>>
+      yuv_to_rgb_converters_;
 
   DISALLOW_COPY_AND_ASSIGN(GLContextEGL);
 };
diff --git a/ui/gl/gl_image_io_surface_egl.h b/ui/gl/gl_image_io_surface_egl.h
index 17d96825..aeeee89c 100644
--- a/ui/gl/gl_image_io_surface_egl.h
+++ b/ui/gl/gl_image_io_surface_egl.h
@@ -22,6 +22,7 @@
  protected:
   ~GLImageIOSurfaceEGL() override;
   bool BindTexImageImpl(unsigned internalformat) override;
+  bool CopyTexImage(unsigned target) override;
 
  private:
   EGLDisplay display_;
diff --git a/ui/gl/gl_image_io_surface_egl.mm b/ui/gl/gl_image_io_surface_egl.mm
index 8050e423..e425d5a 100644
--- a/ui/gl/gl_image_io_surface_egl.mm
+++ b/ui/gl/gl_image_io_surface_egl.mm
@@ -4,7 +4,12 @@
 
 #include "ui/gl/gl_image_io_surface_egl.h"
 
+#include "base/callback_helpers.h"
+#include "base/mac/bind_objc_block.h"
+#include "ui/gl/gl_context.h"
 #include "ui/gl/gl_surface_egl.h"
+#include "ui/gl/scoped_binders.h"
+#include "ui/gl/yuv_to_rgb_converter.h"
 
 // Enums for the EGL_ANGLE_iosurface_client_buffer extension
 #define EGL_IOSURFACE_ANGLE 0x3454
@@ -128,7 +133,7 @@
       EGL_TEXTURE_TYPE_ANGLE,            formatType.type,
       EGL_NONE,                          EGL_NONE,
     };
-    // clang-format off
+    // clang-format on
 
     pbuffer_ = eglCreatePbufferFromClientBuffer(display_, EGL_IOSURFACE_ANGLE,
         io_surface_.get(), dummy_config_, attribs);
@@ -152,4 +157,138 @@
   return true;
 }
 
+bool GLImageIOSurfaceEGL::CopyTexImage(unsigned target) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+
+  if (format_ != gfx::BufferFormat::YUV_420_BIPLANAR)
+    return false;
+
+  GLContext* gl_context = GLContext::GetCurrent();
+  DCHECK(gl_context);
+
+  YUVToRGBConverter* yuv_to_rgb_converter =
+      gl_context->GetYUVToRGBConverter(color_space_for_yuv_to_rgb_);
+  DCHECK(yuv_to_rgb_converter);
+
+  // Note that state restoration is done explicitly instead of scoped binders to
+  // avoid https://crbug.com/601729.
+  GLint rgb_texture = 0;
+  GLenum target_getter = 0;
+  switch (target) {
+    case GL_TEXTURE_2D:
+      target_getter = GL_TEXTURE_BINDING_2D;
+      break;
+    case GL_TEXTURE_CUBE_MAP:
+      target_getter = GL_TEXTURE_BINDING_CUBE_MAP;
+      break;
+    case GL_TEXTURE_EXTERNAL_OES:
+      target_getter = GL_TEXTURE_BINDING_EXTERNAL_OES;
+      break;
+    case GL_TEXTURE_RECTANGLE_ARB:
+      target_getter = GL_TEXTURE_BINDING_RECTANGLE_ARB;
+      break;
+    default:
+      NOTIMPLEMENTED() << " Target not supported.";
+      return false;
+  }
+
+  EGLSurface y_surface = EGL_NO_SURFACE;
+  EGLSurface uv_surface = EGL_NO_SURFACE;
+
+  glGetIntegerv(target_getter, &rgb_texture);
+  base::ScopedClosureRunner destroy_resources_runner(base::BindBlock(^{
+    if (y_surface != EGL_NO_SURFACE) {
+      EGLBoolean result =
+          eglReleaseTexImage(display_, y_surface, EGL_BACK_BUFFER);
+      DCHECK(result == EGL_TRUE);
+      result = eglDestroySurface(display_, y_surface);
+      DCHECK(result == EGL_TRUE);
+    }
+    if (uv_surface != EGL_NO_SURFACE) {
+      EGLBoolean result =
+          eglReleaseTexImage(display_, uv_surface, EGL_BACK_BUFFER);
+      DCHECK(result == EGL_TRUE);
+      result = eglDestroySurface(display_, uv_surface);
+      DCHECK(result == EGL_TRUE);
+    }
+    glBindTexture(target, rgb_texture);
+  }));
+
+  glBindTexture(GL_TEXTURE_RECTANGLE_ARB, yuv_to_rgb_converter->y_texture());
+  if (glGetError() != GL_NO_ERROR) {
+    LOG(ERROR) << "Can't bind Y texture";
+    return false;
+  }
+
+  // clang-format off
+  const EGLint yAttribs[] = {
+    EGL_WIDTH,                         size_.width(),
+    EGL_HEIGHT,                        size_.height(),
+    EGL_IOSURFACE_PLANE_ANGLE,         0,
+    EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
+    EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_RED,
+    EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
+    EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
+    EGL_NONE,                          EGL_NONE,
+  };
+  // clang-format on
+
+  y_surface = eglCreatePbufferFromClientBuffer(display_, EGL_IOSURFACE_ANGLE,
+                                               io_surface_.get(), dummy_config_,
+                                               yAttribs);
+  if (y_surface == EGL_NO_SURFACE) {
+    LOG(ERROR) << "eglCreatePbufferFromClientBuffer failed, EGL error is "
+               << eglGetError();
+    return false;
+  }
+
+  EGLBoolean result = eglBindTexImage(display_, y_surface, EGL_BACK_BUFFER);
+  if (result != EGL_TRUE) {
+    LOG(ERROR) << "eglBindTexImage failed, EGL error is " << eglGetError();
+    return false;
+  }
+
+  glBindTexture(GL_TEXTURE_RECTANGLE_ARB, yuv_to_rgb_converter->uv_texture());
+  if (glGetError() != GL_NO_ERROR) {
+    LOG(ERROR) << "Can't bind UV texture";
+    return false;
+  }
+
+  // clang-format off
+  const EGLint uvAttribs[] = {
+    EGL_WIDTH,                         size_.width() / 2,
+    EGL_HEIGHT,                        size_.height() / 2,
+    EGL_IOSURFACE_PLANE_ANGLE,         1,
+    EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
+    EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_RG,
+    EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
+    EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
+    EGL_NONE,                          EGL_NONE,
+  };
+  // clang-format on
+
+  uv_surface = eglCreatePbufferFromClientBuffer(display_, EGL_IOSURFACE_ANGLE,
+                                                io_surface_.get(),
+                                                dummy_config_, uvAttribs);
+  if (uv_surface == EGL_NO_SURFACE) {
+    LOG(ERROR) << "eglCreatePbufferFromClientBuffer failed, EGL error is "
+               << eglGetError();
+    return false;
+  }
+
+  result = eglBindTexImage(display_, uv_surface, EGL_BACK_BUFFER);
+  if (result != EGL_TRUE) {
+    LOG(ERROR) << "eglBindTexImage failed, EGL error is " << eglGetError();
+    return false;
+  }
+
+  yuv_to_rgb_converter->CopyYUV420ToRGB(target, size_, rgb_texture);
+  if (glGetError() != GL_NO_ERROR) {
+    LOG(ERROR) << "Failed converting from YUV to RGB";
+    return false;
+  }
+
+  return true;
+}
+
 }  // namespace gl
diff --git a/ui/gl/yuv_to_rgb_converter.cc b/ui/gl/yuv_to_rgb_converter.cc
index 73410cb..bf6f8dd 100644
--- a/ui/gl/yuv_to_rgb_converter.cc
+++ b/ui/gl/yuv_to_rgb_converter.cc
@@ -14,6 +14,12 @@
 namespace gl {
 namespace {
 
+const char kVertexHeaderES3[] =
+    "#version 300 es\n"
+    "precision mediump float;\n"
+    "#define ATTRIBUTE in\n"
+    "#define VARYING out\n";
+
 const char kVertexHeaderCompatiblityProfile[] =
     "#version 110\n"
     "#define ATTRIBUTE attribute\n"
@@ -24,6 +30,14 @@
     "#define ATTRIBUTE in\n"
     "#define VARYING out\n";
 
+const char kFragmentHeaderES3[] =
+    "#version 300 es\n"
+    "precision mediump float;\n"
+    "#define VARYING in\n"
+    "#define TEX texture\n"
+    "#define FRAGCOLOR frag_color\n"
+    "out vec4 FRAGCOLOR;\n";
+
 const char kFragmentHeaderCompatiblityProfile[] =
     "#version 110\n"
     "#extension GL_ARB_texture_rectangle : require\n"
@@ -45,7 +59,7 @@
   uniform vec2 a_texScale;
   VARYING vec2 v_texCoord;
   void main() {
-    gl_Position = vec4(a_position.x, a_position.y, 0.0, 1.0);
+    gl_Position = vec4(a_position, 0.0, 1.0);
     v_texCoord = (a_position + vec2(1.0, 1.0)) * 0.5 * a_texScale;
   }
 );
@@ -75,22 +89,27 @@
   DCHECK(color_transform->CanGetShaderSource());
   std::string do_color_conversion = color_transform->GetShaderSource();
 
+  bool use_es3 = gl_version_info.is_es3;
   bool use_core_profile = gl_version_info.is_desktop_core_profile;
   glGenFramebuffersEXT(1, &framebuffer_);
   vertex_buffer_ = GLHelper::SetupQuadVertexBuffer();
   vertex_shader_ = GLHelper::LoadShader(
       GL_VERTEX_SHADER,
-      base::StringPrintf("%s\n%s",
-                         use_core_profile ? kVertexHeaderCoreProfile
-                                          : kVertexHeaderCompatiblityProfile,
-                         kVertexShader)
+      base::StringPrintf(
+          "%s\n%s",
+          use_es3 ? kVertexHeaderES3
+                  : (use_core_profile ? kVertexHeaderCoreProfile
+                                      : kVertexHeaderCompatiblityProfile),
+          kVertexShader)
           .c_str());
   fragment_shader_ = GLHelper::LoadShader(
       GL_FRAGMENT_SHADER,
-      base::StringPrintf("%s\n%s\n%s",
-                         use_core_profile ? kFragmentHeaderCoreProfile
-                                          : kFragmentHeaderCompatiblityProfile,
-                         do_color_conversion.c_str(), kFragmentShader)
+      base::StringPrintf(
+          "%s\n%s\n%s",
+          use_es3 ? kFragmentHeaderES3
+                  : (use_core_profile ? kFragmentHeaderCoreProfile
+                                      : kFragmentHeaderCompatiblityProfile),
+          do_color_conversion.c_str(), kFragmentShader)
           .c_str());
   program_ = GLHelper::SetupProgram(vertex_shader_, fragment_shader_);
 
diff --git a/ui/keyboard/container_floating_behavior.cc b/ui/keyboard/container_floating_behavior.cc
index 855cdc20..d929cb8 100644
--- a/ui/keyboard/container_floating_behavior.cc
+++ b/ui/keyboard/container_floating_behavior.cc
@@ -190,48 +190,57 @@
   if (keyboard_bounds.height() <= 0)
     return;
 
-  bool handle_drag = false;
   const ui::EventType type = event.type();
-  if (IsDragHandle(kb_offset, keyboard_bounds.size())) {
-    if (type == ui::ET_TOUCH_PRESSED ||
-        (type == ui::ET_MOUSE_PRESSED &&
-         ((const ui::MouseEvent*)&event)->IsOnlyLeftMouseButton())) {
-      // Drag is starting.
-      // Mouse events are limited to just the left mouse button.
-
-      drag_started_by_touch_ = (type == ui::ET_TOUCH_PRESSED);
-      if (!drag_descriptor_) {
+  switch (type) {
+    case ui::ET_TOUCH_PRESSED:
+    case ui::ET_MOUSE_PRESSED:
+      if (!IsDragHandle(kb_offset, keyboard_bounds.size())) {
+        drag_descriptor_ = nullptr;
+      } else if (type == ui::ET_MOUSE_PRESSED &&
+                 !((const ui::MouseEvent*)&event)->IsOnlyLeftMouseButton()) {
+        // Mouse events are limited to just the left mouse button.
+        drag_descriptor_ = nullptr;
+      } else if (!drag_descriptor_) {
         // If there is no active drag descriptor, start a new one.
-        drag_descriptor_.reset(
-            new DragDescriptor(keyboard_bounds.origin(), kb_offset));
+        bool drag_started_by_touch = (type == ui::ET_TOUCH_PRESSED);
+        drag_descriptor_.reset(new DragDescriptor(
+            keyboard_bounds.origin(), kb_offset, drag_started_by_touch));
       }
-      handle_drag = true;
-    }
-  }
-  if (drag_descriptor_ &&
-      (type == ui::ET_MOUSE_DRAGGED ||
-       (drag_started_by_touch_ && type == ui::ET_TOUCH_MOVED))) {
-    // Drag continues.
-    // If there is an active drag, use it to determine the new location
-    // of the keyboard.
-    const gfx::Point original_click_location =
-        drag_descriptor_->original_keyboard_location() +
-        drag_descriptor_->original_click_offset();
-    const gfx::Point current_drag_location =
-        keyboard_bounds.origin() + kb_offset;
-    const gfx::Vector2d cumulative_drag_offset =
-        current_drag_location - original_click_location;
-    const gfx::Point new_keyboard_location =
-        drag_descriptor_->original_keyboard_location() + cumulative_drag_offset;
-    const gfx::Rect new_bounds =
-        gfx::Rect(new_keyboard_location, keyboard_bounds.size());
-    controller_->MoveKeyboard(new_bounds);
-    SavePosition(container->bounds(), display_bounds.size());
-    handle_drag = true;
-  }
-  if (!handle_drag && drag_descriptor_) {
-    // drag has ended
-    drag_descriptor_ = nullptr;
+      break;
+
+    case ui::ET_MOUSE_DRAGGED:
+    case ui::ET_TOUCH_MOVED:
+      if (!drag_descriptor_) {
+        // do nothing
+      } else if (drag_descriptor_->is_touch_drag() !=
+                 (type == ui::ET_TOUCH_MOVED)) {
+        // If the event isn't of the same type that started the drag, end the
+        // drag to prevent confusion.
+        drag_descriptor_ = nullptr;
+      } else {
+        // Drag continues.
+        // If there is an active drag, use it to determine the new location
+        // of the keyboard.
+        const gfx::Point original_click_location =
+            drag_descriptor_->original_keyboard_location() +
+            drag_descriptor_->original_click_offset();
+        const gfx::Point current_drag_location =
+            keyboard_bounds.origin() + kb_offset;
+        const gfx::Vector2d cumulative_drag_offset =
+            current_drag_location - original_click_location;
+        const gfx::Point new_keyboard_location =
+            drag_descriptor_->original_keyboard_location() +
+            cumulative_drag_offset;
+        const gfx::Rect new_bounds =
+            gfx::Rect(new_keyboard_location, keyboard_bounds.size());
+        controller_->MoveKeyboard(new_bounds);
+        SavePosition(container->bounds(), display_bounds.size());
+      }
+      break;
+
+    default:
+      drag_descriptor_ = nullptr;
+      break;
   }
 }
 
diff --git a/ui/keyboard/container_floating_behavior.h b/ui/keyboard/container_floating_behavior.h
index 6ea2b2a..c8cb9e6ffc 100644
--- a/ui/keyboard/container_floating_behavior.h
+++ b/ui/keyboard/container_floating_behavior.h
@@ -84,10 +84,6 @@
   // Otherwise nullptr.
   std::unique_ptr<DragDescriptor> drag_descriptor_ = nullptr;
 
-  // Distinguish whether the current drag is from a touch event or mouse event,
-  // so drag/move events can be filtered accordingly
-  bool drag_started_by_touch_ = false;
-
   gfx::Rect draggable_area_ = gfx::Rect();
 };
 
diff --git a/ui/keyboard/drag_descriptor.cc b/ui/keyboard/drag_descriptor.cc
index e15d5fd..42c7308f 100644
--- a/ui/keyboard/drag_descriptor.cc
+++ b/ui/keyboard/drag_descriptor.cc
@@ -10,8 +10,10 @@
 namespace keyboard {
 
 DragDescriptor::DragDescriptor(const gfx::Point& keyboard_location,
-                               const gfx::Vector2d& click_offset)
+                               const gfx::Vector2d& click_offset,
+                               bool is_touch_drag)
     : original_keyboard_location_(keyboard_location),
-      original_click_offset_(click_offset) {}
+      original_click_offset_(click_offset),
+      is_touch_drag_(is_touch_drag) {}
 
 }  // namespace keyboard
diff --git a/ui/keyboard/drag_descriptor.h b/ui/keyboard/drag_descriptor.h
index a40ab22..f56a989 100644
--- a/ui/keyboard/drag_descriptor.h
+++ b/ui/keyboard/drag_descriptor.h
@@ -18,16 +18,22 @@
 class DragDescriptor {
  public:
   DragDescriptor(const gfx::Point& keyboard_location,
-                 const gfx::Vector2d& click_offset);
+                 const gfx::Vector2d& click_offset,
+                 bool is_touch_drag);
 
   gfx::Point original_keyboard_location() const {
     return original_keyboard_location_;
   }
   gfx::Vector2d original_click_offset() const { return original_click_offset_; }
+  bool is_touch_drag() { return is_touch_drag_; }
 
  private:
   const gfx::Point original_keyboard_location_;
   const gfx::Vector2d original_click_offset_;
+
+  // Distinguish whether the current drag is from a touch event or mouse event,
+  // so drag/move events can be filtered accordingly
+  const bool is_touch_drag_;
 };
 
 }  // namespace keyboard
diff --git a/ui/keyboard/keyboard_controller.cc b/ui/keyboard/keyboard_controller.cc
index d633e063..4e6ddb2c6 100644
--- a/ui/keyboard/keyboard_controller.cc
+++ b/ui/keyboard/keyboard_controller.cc
@@ -396,6 +396,12 @@
 void KeyboardController::HideAnimationFinished() {
   if (state_ == KeyboardControllerState::HIDDEN && queued_container_type_) {
     SetContainerBehaviorInternal(queued_container_type_->container_type());
+    // The position of the container window will be adjusted shortly in
+    // |PopulateKeyboardContent| before showing animation, so we can set the
+    // passed bounds directly.
+    if (queued_container_type_->target_bounds())
+      SetContainerBounds(queued_container_type_->target_bounds().value(),
+                         false /* contents_loaded */);
     ShowKeyboard(false /* lock */);
   }
 }
@@ -786,8 +792,6 @@
     const ContainerType type,
     base::Optional<gfx::Rect> target_bounds,
     base::OnceCallback<void(bool)> callback) {
-  // TODO(yhanada): Use target_bounds parameter to change the size of the
-  // container window.
   if (container_behavior_->GetType() == type) {
     std::move(callback).Run(false);
     return;
@@ -796,13 +800,15 @@
   if (state_ == KeyboardControllerState::SHOWN) {
     // Keyboard is already shown. Hiding the keyboard at first then switching
     // container type.
-    queued_container_type_ =
-        std::make_unique<QueuedContainerType>(this, type, std::move(callback));
+    queued_container_type_ = std::make_unique<QueuedContainerType>(
+        this, type, target_bounds, std::move(callback));
     HideKeyboard(HIDE_REASON_AUTOMATIC);
   } else {
     // Keyboard is hidden. Switching the container type immediately and invoking
     // the passed callback now.
     SetContainerBehaviorInternal(type);
+    if (target_bounds)
+      SetContainerBounds(target_bounds.value(), false /* contents_loaded */);
     DCHECK(GetActiveContainerType() == type);
     std::move(callback).Run(true /* change_successful */);
   }
diff --git a/ui/keyboard/keyboard_controller_unittest.cc b/ui/keyboard/keyboard_controller_unittest.cc
index 3d0ab6c..c0d9d05 100644
--- a/ui/keyboard/keyboard_controller_unittest.cc
+++ b/ui/keyboard/keyboard_controller_unittest.cc
@@ -773,6 +773,38 @@
   EXPECT_EQ(1, invocation_counter.invocation_count_for_status(false));
 }
 
+TEST_F(KeyboardControllerAnimationTest, ChangeContainerModeWithBounds) {
+  ScopedAccessibilityKeyboardEnabler scoped_keyboard_enabler;
+  SetModeCallbackInvocationCounter invocation_counter;
+
+  ui::Layer* layer = keyboard_container()->layer();
+  ShowKeyboard();
+  RunAnimationForLayer(layer);
+  EXPECT_EQ(ContainerType::FULL_WIDTH, controller()->GetActiveContainerType());
+  EXPECT_TRUE(keyboard_container()->IsVisible());
+  EXPECT_TRUE(contents_window()->IsVisible());
+
+  // Changing the mode to another mode invokes hiding + showing.
+  const gfx::Rect target_bounds(0, 0, 1200, 600);
+  controller()->SetContainerType(ContainerType::FLOATING,
+                                 base::make_optional(target_bounds),
+                                 invocation_counter.GetInvocationCallback());
+  // The container window shouldn't be resized until it's hidden even if the
+  // target bounds is passed to |SetContainerType|.
+  EXPECT_EQ(gfx::Rect(), notified_visible_bounds());
+  EXPECT_EQ(0, invocation_counter.invocation_count_for_status(true));
+  EXPECT_EQ(0, invocation_counter.invocation_count_for_status(false));
+  RunAnimationForLayer(layer);
+  // Hiding animation finished. The container window should be resized to the
+  // target bounds.
+  EXPECT_EQ(keyboard_container()->bounds().size(), target_bounds.size());
+  // Then showing animation automatically start.
+  layer = keyboard_container()->layer();
+  RunAnimationForLayer(layer);
+  EXPECT_EQ(1, invocation_counter.invocation_count_for_status(true));
+  EXPECT_EQ(0, invocation_counter.invocation_count_for_status(false));
+}
+
 // Show keyboard during keyboard hide animation should abort the hide animation
 // and the keyboard should animate in.
 // Test for crbug.com/333284.
diff --git a/ui/keyboard/queued_container_type.cc b/ui/keyboard/queued_container_type.cc
index 2cf7b88..d876b45 100644
--- a/ui/keyboard/queued_container_type.cc
+++ b/ui/keyboard/queued_container_type.cc
@@ -10,9 +10,11 @@
 QueuedContainerType::QueuedContainerType(
     KeyboardController* controller,
     ContainerType container_type,
+    base::Optional<gfx::Rect> bounds,
     base::OnceCallback<void(bool success)> callback)
     : controller_(controller),
       container_type_(container_type),
+      bounds_(bounds),
       callback_(std::move(callback)){};
 
 QueuedContainerType::~QueuedContainerType() {
diff --git a/ui/keyboard/queued_container_type.h b/ui/keyboard/queued_container_type.h
index ce58d930..aa678cd9 100644
--- a/ui/keyboard/queued_container_type.h
+++ b/ui/keyboard/queued_container_type.h
@@ -6,6 +6,8 @@
 #define UI_KEYBOARD_QUEUED_CONTAINER_TYPE_H_
 
 #include "base/bind.h"
+#include "base/optional.h"
+#include "ui/gfx/geometry/rect.h"
 #include "ui/keyboard/container_type.h"
 
 namespace keyboard {
@@ -22,13 +24,16 @@
  public:
   QueuedContainerType(KeyboardController* controller,
                       ContainerType container_type,
+                      base::Optional<gfx::Rect> bounds,
                       base::OnceCallback<void(bool success)> callback);
   ~QueuedContainerType();
   ContainerType container_type() { return container_type_; }
+  base::Optional<gfx::Rect> target_bounds() { return bounds_; }
 
  private:
   KeyboardController* controller_;
   ContainerType container_type_;
+  base::Optional<gfx::Rect> bounds_;
   base::OnceCallback<void(bool success)> callback_;
 };
 
diff --git a/ui/message_center/BUILD.gn b/ui/message_center/BUILD.gn
index c1ac7a78..e7b7e35 100644
--- a/ui/message_center/BUILD.gn
+++ b/ui/message_center/BUILD.gn
@@ -13,12 +13,10 @@
   icon_directory = "vector_icons"
 
   icons = [
-    "notification_close_button.1x.icon",
     "notification_close_button.icon",
     "notification_expand_less.icon",
     "notification_expand_more.icon",
     "notification_inline_reply.icon",
-    "notification_settings_button.1x.icon",
     "notification_settings_button.icon",
     "product.icon",
   ]
diff --git a/ui/message_center/vector_icons/notification_close_button.1x.icon b/ui/message_center/vector_icons/notification_close_button.1x.icon
deleted file mode 100644
index 8df1cab..0000000
--- a/ui/message_center/vector_icons/notification_close_button.1x.icon
+++ /dev/null
@@ -1,18 +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.
-
-CANVAS_DIMENSIONS, 12,
-MOVE_TO, 10.5f, 2.36f,
-LINE_TO, 9.64f, 1.5f,
-LINE_TO, 6, 5.14f,
-LINE_TO, 2.36f, 1.5f,
-LINE_TO, 1.5f, 2.36f,
-LINE_TO, 5.14f, 6,
-LINE_TO, 1.5f, 9.64f,
-LINE_TO, 2.36f, 10.5f,
-LINE_TO, 6, 6.86f,
-LINE_TO, 9.64f, 10.5f,
-LINE_TO, 10.5f, 9.64f,
-LINE_TO, 6.86f, 6,
-CLOSE
diff --git a/ui/message_center/vector_icons/notification_close_button.icon b/ui/message_center/vector_icons/notification_close_button.icon
index 37b056a..ced7c26 100644
--- a/ui/message_center/vector_icons/notification_close_button.icon
+++ b/ui/message_center/vector_icons/notification_close_button.icon
@@ -16,3 +16,18 @@
 LINE_TO, 20, 18.27f,
 LINE_TO, 13.73f, 12,
 CLOSE
+
+CANVAS_DIMENSIONS, 12,
+MOVE_TO, 10.5f, 2.36f,
+LINE_TO, 9.64f, 1.5f,
+LINE_TO, 6, 5.14f,
+LINE_TO, 2.36f, 1.5f,
+LINE_TO, 1.5f, 2.36f,
+LINE_TO, 5.14f, 6,
+LINE_TO, 1.5f, 9.64f,
+LINE_TO, 2.36f, 10.5f,
+LINE_TO, 6, 6.86f,
+LINE_TO, 9.64f, 10.5f,
+LINE_TO, 10.5f, 9.64f,
+LINE_TO, 6.86f, 6,
+CLOSE
diff --git a/ui/message_center/vector_icons/notification_settings_button.1x.icon b/ui/message_center/vector_icons/notification_settings_button.1x.icon
deleted file mode 100644
index 8d4a4971..0000000
--- a/ui/message_center/vector_icons/notification_settings_button.1x.icon
+++ /dev/null
@@ -1,53 +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.
-
-CANVAS_DIMENSIONS, 12,
-MOVE_TO, 9.82f, 6.49f,
-CUBIC_TO, 9.84f, 6.33f, 9.85f, 6.17f, 9.85f, 6,
-CUBIC_TO, 9.85f, 5.84f, 9.84f, 5.67f, 9.82f, 5.51f,
-LINE_TO, 10.9f, 4.68f,
-CUBIC_TO, 11, 4.61f, 11.03f, 4.47f, 10.97f, 4.37f,
-LINE_TO, 9.94f, 2.63f,
-CUBIC_TO, 9.87f, 2.53f, 9.74f, 2.48f, 9.62f, 2.53f,
-LINE_TO, 8.34f, 3.03f,
-CUBIC_TO, 8.08f, 2.83f, 7.79f, 2.66f, 7.48f, 2.54f,
-LINE_TO, 7.28f, 1.21f,
-CUBIC_TO, 7.26f, 1.09f, 7.15f, 1, 7.03f, 1,
-LINE_TO, 4.97f, 1,
-CUBIC_TO, 4.84f, 1, 4.74f, 1.09f, 4.72f, 1.21f,
-LINE_TO, 4.52f, 2.54f,
-CUBIC_TO, 4.21f, 2.66f, 3.92f, 2.83f, 3.66f, 3.03f,
-LINE_TO, 2.38f, 2.53f,
-CUBIC_TO, 2.26f, 2.48f, 2.13f, 2.53f, 2.06f, 2.63f,
-LINE_TO, 1.03f, 4.37f,
-CUBIC_TO, 0.97f, 4.47f, 1, 4.61f, 1.1f, 4.68f,
-LINE_TO, 2.18f, 5.51f,
-CUBIC_TO, 2.16f, 5.67f, 2.14f, 5.84f, 2.14f, 6,
-CUBIC_TO, 2.14f, 6.17f, 2.16f, 6.33f, 2.18f, 6.49f,
-LINE_TO, 1.1f, 7.32f,
-CUBIC_TO, 1, 7.39f, 0.97f, 7.53f, 1.03f, 7.64f,
-LINE_TO, 2.06f, 9.37f,
-CUBIC_TO, 2.13f, 9.48f, 2.26f, 9.52f, 2.38f, 9.48f,
-LINE_TO, 3.66f, 8.97f,
-CUBIC_TO, 3.92f, 9.17f, 4.21f, 9.34f, 4.52f, 9.47f,
-LINE_TO, 4.72f, 10.79f,
-CUBIC_TO, 4.74f, 10.91f, 4.84f, 11, 4.97f, 11,
-LINE_TO, 7.03f, 11,
-CUBIC_TO, 7.15f, 11, 7.26f, 10.91f, 7.28f, 10.79f,
-LINE_TO, 7.47f, 9.47f,
-CUBIC_TO, 7.79f, 9.34f, 8.08f, 9.17f, 8.34f, 8.97f,
-LINE_TO, 9.62f, 9.48f,
-CUBIC_TO, 9.74f, 9.52f, 9.87f, 9.48f, 9.94f, 9.37f,
-LINE_TO, 10.96f, 7.64f,
-CUBIC_TO, 11.03f, 7.53f, 11, 7.39f, 10.9f, 7.32f,
-LINE_TO, 9.82f, 6.49f,
-LINE_TO, 9.82f, 6.49f,
-CLOSE,
-MOVE_TO, 6, 7.5f,
-CUBIC_TO, 5.17f, 7.5f, 4.5f, 6.83f, 4.5f, 6,
-CUBIC_TO, 4.5f, 5.17f, 5.17f, 4.5f, 6, 4.5f,
-CUBIC_TO, 6.83f, 4.5f, 7.5f, 5.17f, 7.5f, 6,
-CUBIC_TO, 7.5f, 6.83f, 6.83f, 7.5f, 6, 7.5f,
-LINE_TO, 6, 7.5f,
-CLOSE
diff --git a/ui/message_center/vector_icons/notification_settings_button.icon b/ui/message_center/vector_icons/notification_settings_button.icon
index 2f312ea9..3a0a1d97 100644
--- a/ui/message_center/vector_icons/notification_settings_button.icon
+++ b/ui/message_center/vector_icons/notification_settings_button.icon
@@ -51,3 +51,53 @@
 CUBIC_TO, 15, 13.66f, 13.66f, 15, 12, 15,
 LINE_TO, 12, 15,
 CLOSE
+
+CANVAS_DIMENSIONS, 12,
+MOVE_TO, 9.82f, 6.49f,
+CUBIC_TO, 9.84f, 6.33f, 9.85f, 6.17f, 9.85f, 6,
+CUBIC_TO, 9.85f, 5.84f, 9.84f, 5.67f, 9.82f, 5.51f,
+LINE_TO, 10.9f, 4.68f,
+CUBIC_TO, 11, 4.61f, 11.03f, 4.47f, 10.97f, 4.37f,
+LINE_TO, 9.94f, 2.63f,
+CUBIC_TO, 9.87f, 2.53f, 9.74f, 2.48f, 9.62f, 2.53f,
+LINE_TO, 8.34f, 3.03f,
+CUBIC_TO, 8.08f, 2.83f, 7.79f, 2.66f, 7.48f, 2.54f,
+LINE_TO, 7.28f, 1.21f,
+CUBIC_TO, 7.26f, 1.09f, 7.15f, 1, 7.03f, 1,
+LINE_TO, 4.97f, 1,
+CUBIC_TO, 4.84f, 1, 4.74f, 1.09f, 4.72f, 1.21f,
+LINE_TO, 4.52f, 2.54f,
+CUBIC_TO, 4.21f, 2.66f, 3.92f, 2.83f, 3.66f, 3.03f,
+LINE_TO, 2.38f, 2.53f,
+CUBIC_TO, 2.26f, 2.48f, 2.13f, 2.53f, 2.06f, 2.63f,
+LINE_TO, 1.03f, 4.37f,
+CUBIC_TO, 0.97f, 4.47f, 1, 4.61f, 1.1f, 4.68f,
+LINE_TO, 2.18f, 5.51f,
+CUBIC_TO, 2.16f, 5.67f, 2.14f, 5.84f, 2.14f, 6,
+CUBIC_TO, 2.14f, 6.17f, 2.16f, 6.33f, 2.18f, 6.49f,
+LINE_TO, 1.1f, 7.32f,
+CUBIC_TO, 1, 7.39f, 0.97f, 7.53f, 1.03f, 7.64f,
+LINE_TO, 2.06f, 9.37f,
+CUBIC_TO, 2.13f, 9.48f, 2.26f, 9.52f, 2.38f, 9.48f,
+LINE_TO, 3.66f, 8.97f,
+CUBIC_TO, 3.92f, 9.17f, 4.21f, 9.34f, 4.52f, 9.47f,
+LINE_TO, 4.72f, 10.79f,
+CUBIC_TO, 4.74f, 10.91f, 4.84f, 11, 4.97f, 11,
+LINE_TO, 7.03f, 11,
+CUBIC_TO, 7.15f, 11, 7.26f, 10.91f, 7.28f, 10.79f,
+LINE_TO, 7.47f, 9.47f,
+CUBIC_TO, 7.79f, 9.34f, 8.08f, 9.17f, 8.34f, 8.97f,
+LINE_TO, 9.62f, 9.48f,
+CUBIC_TO, 9.74f, 9.52f, 9.87f, 9.48f, 9.94f, 9.37f,
+LINE_TO, 10.96f, 7.64f,
+CUBIC_TO, 11.03f, 7.53f, 11, 7.39f, 10.9f, 7.32f,
+LINE_TO, 9.82f, 6.49f,
+LINE_TO, 9.82f, 6.49f,
+CLOSE,
+MOVE_TO, 6, 7.5f,
+CUBIC_TO, 5.17f, 7.5f, 4.5f, 6.83f, 4.5f, 6,
+CUBIC_TO, 4.5f, 5.17f, 5.17f, 4.5f, 6, 4.5f,
+CUBIC_TO, 6.83f, 4.5f, 7.5f, 5.17f, 7.5f, 6,
+CUBIC_TO, 7.5f, 6.83f, 6.83f, 7.5f, 6, 7.5f,
+LINE_TO, 6, 7.5f,
+CLOSE
diff --git a/ui/message_center/views/message_popup_collection.cc b/ui/message_center/views/message_popup_collection.cc
index 1d15d41c..8a1f6290 100644
--- a/ui/message_center/views/message_popup_collection.cc
+++ b/ui/message_center/views/message_popup_collection.cc
@@ -11,7 +11,6 @@
 #include "base/i18n/rtl.h"
 #include "base/logging.h"
 #include "base/memory/weak_ptr.h"
-#include "base/run_loop.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "build/build_config.h"
@@ -39,11 +38,6 @@
 namespace message_center {
 namespace {
 
-// Timeout between the last user-initiated close of the toast and the moment
-// when normal layout/update of the toast stack continues. If the last toast was
-// just closed, the timeout is shorter.
-const int kMouseExitedDeferTimeoutMs = 200;
-
 // The margin between messages (and between the anchor unless
 // first_item_has_no_margin was specified).
 const int kToastMarginY = kMarginBetweenPopups;
@@ -58,7 +52,6 @@
       tray_(tray),
       alignment_delegate_(alignment_delegate) {
   DCHECK(message_center_);
-  defer_timer_.reset(new base::OneShotTimer);
   message_center_->AddObserver(this);
   alignment_delegate_->set_collection(this);
 #if !defined(OS_CHROMEOS)
@@ -198,8 +191,14 @@
 
     ToastContentsView* toast = new ToastContentsView(
         notification.id(), alignment_delegate_, weak_factory_.GetWeakPtr());
+
+    const RichNotificationData& optional_fields =
+        notification.rich_notification_data();
+    bool a11y_feedback_for_updates =
+        optional_fields.should_make_spoken_feedback_for_popup_updates;
+
     // There will be no contents already since this is a new ToastContentsView.
-    toast->SetContents(view, /*a11y_feedback_for_updates=*/false);
+    toast->SetContents(view, a11y_feedback_for_updates);
     toasts_.push_back(toast);
 
     gfx::Size preferred_size = toast->GetPreferredSize();
@@ -238,9 +237,6 @@
   latest_toast_entered_ = toast_entered;
 
   PausePopupTimers();
-
-  if (user_is_closing_toasts_by_clicking_)
-    defer_timer_->Stop();
 }
 
 void MessagePopupCollection::OnMouseExited(ToastContentsView* toast_exited) {
@@ -250,15 +246,7 @@
     return;
   latest_toast_entered_ = NULL;
 
-  if (user_is_closing_toasts_by_clicking_) {
-    defer_timer_->Start(
-        FROM_HERE,
-        base::TimeDelta::FromMilliseconds(kMouseExitedDeferTimeoutMs),
-        this,
-        &MessagePopupCollection::OnDeferTimerExpired);
-  } else {
-    RestartPopupTimers();
-  }
+  RestartPopupTimers();
 }
 
 std::set<std::string> MessagePopupCollection::CloseAllWidgets() {
@@ -325,50 +313,6 @@
   }
 }
 
-void MessagePopupCollection::RepositionWidgetsWithTarget() {
-  if (toasts_.empty())
-    return;
-
-  bool top_down = alignment_delegate_->IsTopDown();
-
-  // Nothing to do if there are no widgets above target if bottom-aligned or no
-  // widgets below target if top-aligned.
-  if (top_down == (GetBaselineForToast(toasts_.back()) <
-                   last_removed_notification_baseline_)) {
-    return;
-  }
-
-  Toasts::reverse_iterator iter = toasts_.rbegin();
-  for (; iter != toasts_.rend(); ++iter) {
-    // We only reposition widgets above target if bottom-aligned or widgets
-    // below target if top-aligned.
-    if (top_down ==
-        (GetBaselineForToast(*iter) < last_removed_notification_baseline_)) {
-      break;
-    }
-  }
-  --iter;
-
-  // Slide length is the number of pixels the widgets should move so that their
-  // bottom edge (top-edge if top-aligned) touches the target.
-  int slide_length = std::abs(last_removed_notification_baseline_ -
-                              GetBaselineForToast(*iter));
-  for (;; --iter) {
-    gfx::Rect bounds((*iter)->bounds());
-
-    // If top-aligned, shift widgets upwards by slide_length. If bottom-aligned,
-    // shift them downwards by slide_length.
-    if (top_down)
-      bounds.set_y(bounds.y() - slide_length);
-    else
-      bounds.set_y(bounds.y() + slide_length);
-    (*iter)->SetBoundsWithAnimation(bounds);
-
-    if (iter == toasts_.rbegin())
-      break;
-  }
-}
-
 int MessagePopupCollection::GetBaseline() const {
   if (toasts_.empty())
     return alignment_delegate_->GetBaseline();
@@ -389,7 +333,7 @@
 
 void MessagePopupCollection::OnNotificationAdded(
     const std::string& notification_id) {
-  DoUpdateIfPossible();
+  DoUpdate();
 }
 
 void MessagePopupCollection::OnNotificationRemoved(
@@ -404,35 +348,10 @@
   if (iter == toasts_.end())
     return;
 
-  last_removed_notification_baseline_ = GetBaselineForToast(*iter);
-
-  if (by_user && !user_is_closing_toasts_by_clicking_) {
-    // [Re] start a timeout after which the toasts re-position to their
-    // normal locations after tracking the mouse pointer for easy deletion.
-    // This provides a period of time when toasts are easy to remove because
-    // they re-position themselves to have Close button right under the mouse
-    // pointer. If the user continue to remove the toasts, the delay is reset.
-    // Once user stopped removing the toasts, the toasts re-populate/rearrange
-    // after the specified delay.
-    user_is_closing_toasts_by_clicking_ = true;
-    IncrementDeferCounter();
-  }
-
-  // CloseWithAnimation ultimately causes a call to RemoveToast, which calls
-  // OnMouseExited.  This means that |user_is_closing_toasts_by_clicking_| must
-  // have been set before this call, otherwise it will remain true even after
-  // the toast is closed, since the defer timer won't be started.
   RemoveToast(*iter, /*mark_as_shown=*/true);
 
   if (by_user)
-    RepositionWidgetsWithTarget();
-}
-
-void MessagePopupCollection::OnDeferTimerExpired() {
-  user_is_closing_toasts_by_clicking_ = false;
-  DecrementDeferCounter();
-
-  RestartPopupTimers();
+    RepositionWidgets();
 }
 
 void MessagePopupCollection::OnNotificationUpdated(
@@ -477,10 +396,7 @@
   if (!updated)
     RemoveToast(*toast_iter, /*mark_as_shown=*/true);
 
-  if (user_is_closing_toasts_by_clicking_)
-    RepositionWidgetsWithTarget();
-  else
-    DoUpdateIfPossible();
+  DoUpdate();
 }
 
 ToastContentsView* MessagePopupCollection::FindToast(
@@ -493,42 +409,16 @@
   return NULL;
 }
 
-void MessagePopupCollection::IncrementDeferCounter() {
-  defer_counter_++;
-}
-
-void MessagePopupCollection::DecrementDeferCounter() {
-  defer_counter_--;
-  DCHECK(defer_counter_ >= 0);
-  DoUpdateIfPossible();
-}
-
 // This is the main sequencer of tasks. It does a step, then waits for
 // all started transitions to play out before doing the next step.
 // First, remove all expired toasts.
-// Then, reposition widgets (the reposition on close happens before all
-// deferred tasks are even able to run)
+// Then, reposition widgets.
 // Then, see if there is vacant space for new toasts.
-void MessagePopupCollection::DoUpdateIfPossible() {
-  if (defer_counter_ > 0)
-    return;
-
+void MessagePopupCollection::DoUpdate() {
   RepositionWidgets();
 
-  if (defer_counter_ > 0)
-    return;
-
   // Reposition could create extra space which allows additional widgets.
   UpdateWidgets();
-
-  if (defer_counter_ > 0)
-    return;
-
-  // Test support. Quit the test run loop when no more updates are deferred,
-  // meaining th echeck for updates did not cause anything to change so no new
-  // transition animations were started.
-  if (run_loop_for_test_.get())
-    run_loop_for_test_->Quit();
 }
 
 void MessagePopupCollection::OnDisplayMetricsChanged(
@@ -546,17 +436,7 @@
   return NULL;
 }
 
-void MessagePopupCollection::CreateRunLoopForTest() {
-  run_loop_for_test_.reset(new base::RunLoop());
-}
-
-void MessagePopupCollection::WaitForTest() {
-  run_loop_for_test_->Run();
-  run_loop_for_test_.reset();
-}
-
 gfx::Rect MessagePopupCollection::GetToastRectAt(size_t index) const {
-  DCHECK(defer_counter_ == 0) << "Fetching the bounds with animations active.";
   size_t i = 0;
   for (Toasts::const_iterator iter = toasts_.begin(); iter != toasts_.end();
        ++iter) {
diff --git a/ui/message_center/views/message_popup_collection.h b/ui/message_center/views/message_popup_collection.h
index 6b900f3..178e41f9 100644
--- a/ui/message_center/views/message_popup_collection.h
+++ b/ui/message_center/views/message_popup_collection.h
@@ -22,10 +22,6 @@
 #include "ui/views/view_observer.h"
 #include "ui/views/widget/widget_observer.h"
 
-namespace base {
-class RunLoop;
-}
-
 namespace display {
 class Display;
 }
@@ -74,17 +70,8 @@
   void OnMouseEntered(ToastContentsView* toast_entered);
   void OnMouseExited(ToastContentsView* toast_exited);
 
-  // Invoked by toasts when they start/finish their animations.
-  // While "defer counter" is greater than zero, the popup collection does
-  // not perform updates. It is used to wait for various animations and user
-  // actions like serial closing of the toasts, when the remaining toasts "flow
-  // under the mouse".
-  void IncrementDeferCounter();
-  void DecrementDeferCounter();
-
-  // Runs the next step in update/animate sequence, if the defer counter is not
-  // zero. Otherwise, simply waits when it becomes zero.
-  void DoUpdateIfPossible();
+  // Runs the next step in update/animate sequence.
+  void DoUpdate();
 
   // Removes the toast from our internal list of toasts; this is called when the
   // toast is irrevocably closed (such as within RemoveToast).
@@ -110,11 +97,6 @@
   // Repositions all of the widgets based on the current work area.
   void RepositionWidgets();
 
-  // Repositions widgets to the top edge of the notification toast that was
-  // just removed, so that the user can click close button without mouse moves.
-  // See crbug.com/224089
-  void RepositionWidgetsWithTarget();
-
   // The baseline is an (imaginary) line that would touch the bottom of the
   // next created notification if bottom-aligned or its top if top-aligned.
   int GetBaseline() const;
@@ -139,8 +121,6 @@
 
   // "ForTest" methods.
   views::Widget* GetWidgetForTest(const std::string& id) const;
-  void CreateRunLoopForTest();
-  void WaitForTest();
   gfx::Rect GetToastRectAt(size_t index) const;
 
   MessageCenter* message_center_;
@@ -149,32 +129,14 @@
 
   PopupAlignmentDelegate* alignment_delegate_;
 
-  int defer_counter_ = 0;
-
   // This is only used to compare with incoming events, do not assume that
   // the toast will be valid if this pointer is non-NULL.
   ToastContentsView* latest_toast_entered_ = nullptr;
 
-  // Denotes a mode when user is clicking the Close button of toasts in a
-  // sequence, w/o moving the mouse. We reposition the toasts so the next one
-  // happens to be right under the mouse, and the user can just dispose of
-  // multipel toasts by clicking. The mode ends when defer_timer_ expires.
-  bool user_is_closing_toasts_by_clicking_ = false;
-  std::unique_ptr<base::OneShotTimer> defer_timer_;
-
-  // The y axis baseline of the last removed notification.
-  // Depending on the alignment specified by IsTopDown(), it's the origin y or
-  // the bottom y of the notification.
-  // Only to be used when |user_is_closing_toasts_by_clicking_| is true.
-  int last_removed_notification_baseline_ = 0;
-
   // This is the number of pause request for timer. If it's more than zero, the
   // timer is paused. If zero, the timer is not paused.
   int timer_pause_counter_ = 0;
 
-  // Weak, only exists temporarily in tests.
-  std::unique_ptr<base::RunLoop> run_loop_for_test_;
-
   std::unique_ptr<MessageViewContextMenuController> context_menu_controller_;
 
   ScopedObserver<views::View, views::ViewObserver> observed_views_{this};
diff --git a/ui/message_center/views/message_popup_collection_unittest.cc b/ui/message_center/views/message_popup_collection_unittest.cc
index ed2c9ea..c643fa73 100644
--- a/ui/message_center/views/message_popup_collection_unittest.cc
+++ b/ui/message_center/views/message_popup_collection_unittest.cc
@@ -12,8 +12,8 @@
 #include <numeric>
 #include <utility>
 
-#include "base/message_loop/message_loop.h"
 #include "base/optional.h"
+#include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
@@ -72,7 +72,8 @@
 
 namespace test {
 
-class MessagePopupCollectionTest : public views::ViewsTestBase {
+class MessagePopupCollectionTest : public views::ViewsTestBase,
+                                   public views::WidgetObserver {
  public:
   void SetUp() override {
     views::ViewsTestBase::SetUp();
@@ -87,7 +88,6 @@
     SetDisplayInfo(gfx::Rect(0, 0, 1920, 1070),  // taskbar at the bottom.
                    gfx::Rect(0, 0, 1920, 1080));
     id_ = 0;
-    PrepareForWait();
   }
 
   void TearDown() override {
@@ -122,7 +122,6 @@
     dummy_display.set_bounds(display_bounds);
     dummy_display.set_work_area(work_area);
     alignment_delegate_->RecomputeAlignment(dummy_display);
-    PrepareForWait();
   }
 
   gfx::Rect GetWorkArea() {
@@ -162,26 +161,30 @@
     return id;
   }
 
-  void PrepareForWait() { collection_->CreateRunLoopForTest(); }
-
-  // Assumes there is non-zero pending work.
-  void WaitForTransitionsDone() {
-    collection_->WaitForTest();
-    collection_->CreateRunLoopForTest();
-  }
-
   void CloseAllToasts() {
     // Assumes there is at least one toast to close.
     EXPECT_TRUE(GetToastCounts() > 0);
-    MessageCenter::Get()->RemoveAllNotifications(
-        false /* by_user */, MessageCenter::RemoveType::ALL);
+
+    auto toasts = collection_->toasts_;
+    for (ToastContentsView* toast : toasts) {
+      toast->GetWidget()->CloseNow();
+    }
   }
 
   gfx::Rect GetToastRectAt(size_t index) {
     return collection_->GetToastRectAt(index);
   }
 
-  void DecrementDeferCounter() { collection_->DecrementDeferCounter(); }
+  void RemoveToastAndWaitForClose(const std::string& id) {
+    GetWidget(id)->AddObserver(this);
+    MessageCenter::Get()->RemoveNotification(id, true /* by_user */);
+    widget_close_run_loop_.Run();
+  }
+
+  // views::WidgetObserver
+  void OnWidgetDestroyed(views::Widget* widget) override {
+    widget_close_run_loop_.Quit();
+  }
 
   // Checks:
   //  1) sizes of toast and corresponding widget are equal;
@@ -190,6 +193,7 @@
   class CheckedAnimationDelegate : public gfx::AnimationDelegate {
    public:
     explicit CheckedAnimationDelegate(MessagePopupCollectionTest* test);
+    ~CheckedAnimationDelegate() override;
 
     // returns first encountered error
     const base::Optional<std::string>& error_msg() const { return error_msg_; }
@@ -227,6 +231,7 @@
       const MessagePopupCollection::Toasts& toasts);
 
  private:
+  base::RunLoop widget_close_run_loop_;
   std::unique_ptr<MessagePopupCollection> collection_;
   std::unique_ptr<DesktopPopupAlignmentDelegate> alignment_delegate_;
   int id_;
@@ -239,6 +244,11 @@
   animation_delegate().bounds_animation_->set_delegate(this);
 }
 
+MessagePopupCollectionTest::CheckedAnimationDelegate::
+    ~CheckedAnimationDelegate() {
+  animation_delegate().bounds_animation_->set_delegate(&animation_delegate());
+}
+
 void MessagePopupCollectionTest::CheckedAnimationDelegate::AnimationEnded(
     const gfx::Animation* animation) {
   animation_delegate().AnimationEnded(animation);
@@ -347,21 +357,18 @@
 
   std::string id1 = AddNotification();
   std::string id2 = AddNotification();
-  WaitForTransitionsDone();
 
   EXPECT_EQ(2u, GetToastCounts());
   EXPECT_TRUE(IsToastShown(id1));
   EXPECT_TRUE(IsToastShown(id2));
 
   MessageCenter::Get()->ClickOnNotification(id2);
-  WaitForTransitionsDone();
 
   EXPECT_EQ(1u, GetToastCounts());
   EXPECT_TRUE(IsToastShown(id1));
   EXPECT_FALSE(IsToastShown(id2));
 
   MessageCenter::Get()->ClickOnNotificationButton(id1, 0);
-  WaitForTransitionsDone();
   EXPECT_EQ(0u, GetToastCounts());
   EXPECT_FALSE(IsToastShown(id1));
   EXPECT_FALSE(IsToastShown(id2));
@@ -372,21 +379,20 @@
 TEST_F(MessagePopupCollectionTest, NotDismissedOnClick) {
   std::string id1 = AddNotification();
   std::string id2 = AddNotification();
-  WaitForTransitionsDone();
 
   EXPECT_EQ(2u, GetToastCounts());
   EXPECT_TRUE(IsToastShown(id1));
   EXPECT_TRUE(IsToastShown(id2));
 
   MessageCenter::Get()->ClickOnNotification(id2);
-  collection()->DoUpdateIfPossible();
+  collection()->DoUpdate();
 
   EXPECT_EQ(2u, GetToastCounts());
   EXPECT_TRUE(IsToastShown(id1));
   EXPECT_TRUE(IsToastShown(id2));
 
   MessageCenter::Get()->ClickOnNotificationButton(id1, 0);
-  collection()->DoUpdateIfPossible();
+  collection()->DoUpdate();
   EXPECT_EQ(2u, GetToastCounts());
   EXPECT_TRUE(IsToastShown(id1));
   EXPECT_TRUE(IsToastShown(id2));
@@ -400,7 +406,6 @@
 TEST_F(MessagePopupCollectionTest, ShutdownDuringShowing) {
   std::string id1 = AddNotification();
   std::string id2 = AddNotification();
-  WaitForTransitionsDone();
   EXPECT_EQ(2u, GetToastCounts());
   EXPECT_TRUE(IsToastShown(id1));
   EXPECT_TRUE(IsToastShown(id2));
@@ -418,7 +423,6 @@
   std::string id1 = AddNotification();
   std::string id2 = AddNotification();
   std::string id3 = AddNotification();
-  WaitForTransitionsDone();
 
   gfx::Rect r0 = GetToastRectAt(0);
   gfx::Rect r1 = GetToastRectAt(1);
@@ -449,7 +453,6 @@
 
   CloseAllToasts();
   EXPECT_EQ(0u, GetToastCounts());
-  WaitForTransitionsDone();
 }
 
 TEST_F(MessagePopupCollectionTest, DefaultPositioningWithRightTaskbar) {
@@ -460,7 +463,6 @@
                  gfx::Rect(0, 0, 600, 400));  // Display-bounds.
   std::string id0 = AddNotification();
   std::string id1 = AddNotification();
-  WaitForTransitionsDone();
 
   gfx::Rect r0 = GetToastRectAt(0);
   gfx::Rect r1 = GetToastRectAt(1);
@@ -476,7 +478,6 @@
 
   CloseAllToasts();
   EXPECT_EQ(0u, GetToastCounts());
-  WaitForTransitionsDone();
 }
 
 TEST_F(MessagePopupCollectionTest, TopDownPositioningWithTopTaskbar) {
@@ -485,7 +486,6 @@
                  gfx::Rect(0, 0, 600, 400));  // Display-bounds.
   std::string id0 = AddNotification();
   std::string id1 = AddNotification();
-  WaitForTransitionsDone();
 
   gfx::Rect r0 = GetToastRectAt(0);
   gfx::Rect r1 = GetToastRectAt(1);
@@ -501,7 +501,6 @@
 
   CloseAllToasts();
   EXPECT_EQ(0u, GetToastCounts());
-  WaitForTransitionsDone();
 }
 
 TEST_F(MessagePopupCollectionTest, TopDownPositioningWithLeftAndTopTaskbar) {
@@ -513,7 +512,6 @@
                  gfx::Rect(0, 0, 600, 400));   // Display-bounds.
   std::string id0 = AddNotification();
   std::string id1 = AddNotification();
-  WaitForTransitionsDone();
 
   gfx::Rect r0 = GetToastRectAt(0);
   gfx::Rect r1 = GetToastRectAt(1);
@@ -529,7 +527,6 @@
 
   CloseAllToasts();
   EXPECT_EQ(0u, GetToastCounts());
-  WaitForTransitionsDone();
 }
 
 TEST_F(MessagePopupCollectionTest, TopDownPositioningWithBottomAndTopTaskbar) {
@@ -541,7 +538,6 @@
                  gfx::Rect(0, 0, 600, 400));  // Display-bounds.
   std::string id0 = AddNotification();
   std::string id1 = AddNotification();
-  WaitForTransitionsDone();
 
   gfx::Rect r0 = GetToastRectAt(0);
   gfx::Rect r1 = GetToastRectAt(1);
@@ -557,7 +553,6 @@
 
   CloseAllToasts();
   EXPECT_EQ(0u, GetToastCounts());
-  WaitForTransitionsDone();
 }
 
 TEST_F(MessagePopupCollectionTest, LeftPositioningWithLeftTaskbar) {
@@ -566,7 +561,6 @@
                  gfx::Rect(0, 0, 600, 400));  // Display-bounds.
   std::string id0 = AddNotification();
   std::string id1 = AddNotification();
-  WaitForTransitionsDone();
 
   gfx::Rect r0 = GetToastRectAt(0);
   gfx::Rect r1 = GetToastRectAt(1);
@@ -585,21 +579,17 @@
 
   CloseAllToasts();
   EXPECT_EQ(0u, GetToastCounts());
-  WaitForTransitionsDone();
 }
 
 // Regression test for https://crbug.com/679397
 TEST_F(MessagePopupCollectionTest, MultipleNotificationHeight) {
   std::string id0 = AddNotification();
-  WaitForTransitionsDone();
   std::string id1 = AddImageNotification();
-  WaitForTransitionsDone();
   EXPECT_EQ(2u, GetToastCounts());
 
   gfx::Rect r0 = GetToast(id0)->bounds();
 
-  MessageCenter::Get()->RemoveNotification(id0, true /* by_user */);
-  DecrementDeferCounter();
+  RemoveToastAndWaitForClose(id0);
   EXPECT_EQ(1u, GetToastCounts());
 
   gfx::Rect r1 = GetToast(id1)->bounds();
@@ -612,13 +602,11 @@
 
   CloseAllToasts();
   EXPECT_EQ(0u, GetToastCounts());
-  WaitForTransitionsDone();
 }
 
 TEST_F(MessagePopupCollectionTest, DetectMouseHover) {
   std::string id0 = AddNotification();
   std::string id1 = AddNotification();
-  WaitForTransitionsDone();
 
   views::WidgetDelegateView* toast0 = GetToast(id0);
   EXPECT_TRUE(toast0 != NULL);
@@ -654,7 +642,6 @@
 TEST_F(MessagePopupCollectionTest, DetectMouseHoverWithUserClose) {
   std::string id0 = AddNotification();
   std::string id1 = AddNotification();
-  WaitForTransitionsDone();
 
   views::WidgetDelegateView* toast0 = GetToast(id0);
   EXPECT_TRUE(toast0 != NULL);
@@ -664,18 +651,15 @@
   ui::MouseEvent event(ui::ET_MOUSE_MOVED, gfx::Point(), gfx::Point(),
                        ui::EventTimeForNow(), 0, 0);
   toast1->OnMouseEntered(event);
-  static_cast<MessageCenterObserver*>(collection())->OnNotificationRemoved(
-      id1, true);
+  RemoveToastAndWaitForClose(id1);
 
   EXPECT_FALSE(MouseInCollection());
   std::string id2 = AddNotification();
 
-  WaitForTransitionsDone();
   views::WidgetDelegateView* toast2 = GetToast(id2);
   EXPECT_TRUE(toast2 != NULL);
 
   CloseAllToasts();
-  WaitForTransitionsDone();
 }
 
 TEST_F(MessagePopupCollectionTest, ManyPopupNotifications) {
@@ -686,7 +670,6 @@
     ids[i] = AddNotification();
   }
 
-  WaitForTransitionsDone();
 
   for (size_t i = 0; i < notifications_to_add - 1; ++i) {
     EXPECT_TRUE(IsToastShown(ids[i])) << "Should show the " << i << "th ID";
@@ -694,7 +677,6 @@
   EXPECT_FALSE(IsToastShown(ids[notifications_to_add - 1]));
 
   CloseAllToasts();
-  WaitForTransitionsDone();
 }
 
 #if defined(OS_CHROMEOS)
@@ -712,7 +694,6 @@
 
   // Add a pinned notification.
   MessageCenter::Get()->AddNotification(std::move(notification));
-  WaitForTransitionsDone();
 
   // Confirms that there is a toast.
   EXPECT_EQ(1u, GetToastCounts());
@@ -726,7 +707,6 @@
   toast1->OnMouseEntered(event);
   static_cast<MessageCenterObserver*>(collection())
       ->OnNotificationRemoved(kNotificationId, true);
-  WaitForTransitionsDone();
 
   // Confirms that there is no toast.
   EXPECT_EQ(0u, GetToastCounts());
@@ -767,7 +747,6 @@
     }
   }
 
-  WaitForTransitionsDone();
 
   // Confirms that there are 2 toasts of 3 notifications.
   EXPECT_EQ(3u, GetToastCounts());
@@ -781,8 +760,6 @@
 
       CheckedAnimationDelegate checked_animation(this);
 
-      WaitForTransitionsDone();
-
       EXPECT_FALSE(checked_animation.error_msg())
           << "Animation error, test case: " << id << ' ' << update.name << ":\n"
           << *checked_animation.error_msg();
@@ -790,37 +767,7 @@
   }
 
   CloseAllToasts();
-  WaitForTransitionsDone();
 }
 
-// Regression test for https://crbug.com/804389 where notifications are added
-// and removed at the same time when UpdateWidgets is called.
-#if defined(OS_CHROMEOS)
-TEST_F(MessagePopupCollectionTest, AddedAndRemovedAtSameTime) {
-  collection()->IncrementDeferCounter();
-  std::vector<std::string> notification_ids;
-  for (size_t i = 0; i < kMaxVisiblePopupNotifications; ++i)
-    notification_ids.push_back(AddNotification());
-  collection()->DecrementDeferCounter();
-  WaitForTransitionsDone();
-
-  // Depending on the timing of ScopedNotificationsIterationLock, it is possible
-  // that a new notificaiton is added before the observer method of
-  // MarkSinglePopupAsShown are called.
-  // To reproduce the similar state in the unit test, it removes observer.
-  // TODO(tetsui): Remove this workaround with ScopedNotificationsIterationLock.
-  MessageCenter::Get()->RemoveObserver(collection());
-  for (auto& notification_id : notification_ids)
-    MessageCenter::Get()->MarkSinglePopupAsShown(notification_id, false);
-  MessageCenter::Get()->AddObserver(collection());
-
-  AddNotification();
-  WaitForTransitionsDone();
-
-  CloseAllToasts();
-  WaitForTransitionsDone();
-}
-#endif
-
 }  // namespace test
 }  // namespace message_center
diff --git a/ui/message_center/views/message_view.cc b/ui/message_center/views/message_view.cc
index e3a8cf84..025b1f0 100644
--- a/ui/message_center/views/message_view.cc
+++ b/ui/message_center/views/message_view.cc
@@ -6,6 +6,7 @@
 
 #include "base/feature_list.h"
 #include "base/strings/utf_string_conversions.h"
+#include "ui/accessibility/ax_enums.mojom.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/models/simple_menu_model.h"
@@ -94,7 +95,11 @@
 
 void MessageView::UpdateWithNotification(const Notification& notification) {
   pinned_ = notification.pinned();
-  accessible_name_ = CreateAccessibleName(notification);
+  base::string16 new_accessible_name = CreateAccessibleName(notification);
+  if (new_accessible_name != accessible_name_) {
+    accessible_name_ = new_accessible_name;
+    NotifyAccessibilityEvent(ax::mojom::Event::kTextChanged, true);
+  }
   slide_out_controller_.set_enabled(!GetPinned());
 }
 
@@ -299,7 +304,7 @@
                                            true /* by_user */);
 }
 
-void MessageView::OnSettingsButtonPressed(const ui::LocatedEvent& event) {
+void MessageView::OnSettingsButtonPressed(const ui::Event& event) {
   MessageCenter::Get()->ClickOnSettingsButton(notification_id_);
 }
 
diff --git a/ui/message_center/views/message_view.h b/ui/message_center/views/message_view.h
index ad6f1fd..7f9f9da9 100644
--- a/ui/message_center/views/message_view.h
+++ b/ui/message_center/views/message_view.h
@@ -77,7 +77,7 @@
   virtual void OnContainerAnimationEnded();
 
   void OnCloseButtonPressed();
-  virtual void OnSettingsButtonPressed(const ui::LocatedEvent& event);
+  virtual void OnSettingsButtonPressed(const ui::Event& event);
 
   // views::View
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
diff --git a/ui/message_center/views/notification_control_buttons_view.cc b/ui/message_center/views/notification_control_buttons_view.cc
index f817450..bf1dae5 100644
--- a/ui/message_center/views/notification_control_buttons_view.cc
+++ b/ui/message_center/views/notification_control_buttons_view.cc
@@ -155,7 +155,7 @@
   if (close_button_ && sender == close_button_.get()) {
     message_view_->OnCloseButtonPressed();
   } else if (settings_button_ && sender == settings_button_.get()) {
-    message_view_->OnSettingsButtonPressed(*event.AsLocatedEvent());
+    message_view_->OnSettingsButtonPressed(event);
   }
 }
 
diff --git a/ui/message_center/views/notification_view_md.cc b/ui/message_center/views/notification_view_md.cc
index f8379da9..4deadb0 100644
--- a/ui/message_center/views/notification_view_md.cc
+++ b/ui/message_center/views/notification_view_md.cc
@@ -700,7 +700,7 @@
       ui::GetGestureProviderConfig(
           ui::GestureProviderConfigType::CURRENT_PLATFORM)
           .gesture_detector_config.longpress_timeout.InSecondsF()) {
-    ToggleInlineSettings(*event.AsLocatedEvent());
+    ToggleInlineSettings(event);
     return;
   }
 
@@ -736,7 +736,7 @@
 
 void NotificationViewMD::OnGestureEvent(ui::GestureEvent* event) {
   if (event->type() == ui::ET_GESTURE_LONG_TAP) {
-    ToggleInlineSettings(*event->AsLocatedEvent());
+    ToggleInlineSettings(*event);
     return;
   }
   MessageView::OnGestureEvent(event);
@@ -803,7 +803,7 @@
   if (sender == settings_done_button_) {
     if (block_all_button_->checked())
       MessageCenter::Get()->DisableNotification(id);
-    ToggleInlineSettings(*event.AsLocatedEvent());
+    ToggleInlineSettings(event);
     return;
   }
 }
@@ -1239,7 +1239,7 @@
   }
 }
 
-void NotificationViewMD::ToggleInlineSettings(const ui::LocatedEvent& event) {
+void NotificationViewMD::ToggleInlineSettings(const ui::Event& event) {
   DCHECK(settings_row_);
 
   bool inline_settings_visible = !settings_row_->visible();
@@ -1303,8 +1303,7 @@
   manually_expanded_or_collapsed_ = value;
 }
 
-void NotificationViewMD::OnSettingsButtonPressed(
-    const ui::LocatedEvent& event) {
+void NotificationViewMD::OnSettingsButtonPressed(const ui::Event& event) {
   if (settings_row_)
     ToggleInlineSettings(event);
   else
@@ -1316,35 +1315,37 @@
   GetWidget()->Activate();
 }
 
-void NotificationViewMD::AddBackgroundAnimation(const ui::LocatedEvent& event) {
-  header_row_->SetSubpixelRenderingEnabled(false);
-
+void NotificationViewMD::AddBackgroundAnimation(const ui::Event& event) {
   SetInkDropMode(InkDropMode::ON_NO_GESTURE_HANDLER);
+  // In case the animation is triggered from keyboard operation.
+  if (!event.IsLocatedEvent()) {
+    AnimateInkDrop(views::InkDropState::ACTION_PENDING, nullptr);
+    return;
+  }
 
   // Convert the point of |event| from the coordinate system of
   // |control_buttons_view_| to that of NotificationViewMD, create a new
   // LocatedEvent which has the new point.
   views::View* target = static_cast<views::View*>(event.target());
-  const gfx::Point& location = event.location();
+  const gfx::Point& location = event.AsLocatedEvent()->location();
   gfx::Point converted_location(location);
   View::ConvertPointToTarget(target, this, &converted_location);
   std::unique_ptr<ui::Event> cloned_event = ui::Event::Clone(event);
   ui::LocatedEvent* cloned_located_event = cloned_event->AsLocatedEvent();
   cloned_located_event->set_location(converted_location);
 
-  if (View::HitTestPoint(event.location())) {
+  if (View::HitTestPoint(event.AsLocatedEvent()->location())) {
     AnimateInkDrop(views::InkDropState::ACTION_PENDING,
                    ui::LocatedEvent::FromIfValid(cloned_located_event));
   }
 }
 
 void NotificationViewMD::RemoveBackgroundAnimation() {
-  header_row_->SetSubpixelRenderingEnabled(true);
-
   AnimateInkDrop(views::InkDropState::HIDDEN, nullptr);
 }
 
 void NotificationViewMD::AddInkDropLayer(ui::Layer* ink_drop_layer) {
+  GetInkDrop()->AddObserver(this);
   header_row_->SetPaintToLayer();
   header_row_->layer()->SetFillsBoundsOpaquely(false);
   block_all_button_->SetPaintToLayer();
@@ -1364,6 +1365,7 @@
   settings_done_button_->DestroyLayer();
   ResetInkDropMask();
   ink_drop_container_->RemoveInkDropLayer(ink_drop_layer);
+  GetInkDrop()->RemoveObserver(this);
 }
 
 std::unique_ptr<views::InkDropRipple> NotificationViewMD::CreateInkDropRipple()
@@ -1377,4 +1379,14 @@
   return kSettingsRowBackgroundColor;
 }
 
+void NotificationViewMD::InkDropAnimationStarted() {
+  header_row_->SetSubpixelRenderingEnabled(false);
+}
+
+void NotificationViewMD::InkDropRippleAnimationEnded(
+    views::InkDropState ink_drop_state) {
+  if (ink_drop_state == views::InkDropState::HIDDEN)
+    header_row_->SetSubpixelRenderingEnabled(true);
+}
+
 }  // namespace message_center
diff --git a/ui/message_center/views/notification_view_md.h b/ui/message_center/views/notification_view_md.h
index 0958769..3c291e50 100644
--- a/ui/message_center/views/notification_view_md.h
+++ b/ui/message_center/views/notification_view_md.h
@@ -13,6 +13,7 @@
 #include "base/time/time.h"
 #include "ui/message_center/message_center_export.h"
 #include "ui/message_center/views/message_view.h"
+#include "ui/views/animation/ink_drop_observer.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/controls/button/image_button.h"
 #include "ui/views/controls/button/label_button.h"
@@ -215,6 +216,7 @@
 // returned by the Create() factory method below.
 class MESSAGE_CENTER_EXPORT NotificationViewMD
     : public MessageView,
+      public views::InkDropObserver,
       public NotificationInputDelegate,
       public views::ButtonListener {
  public:
@@ -223,7 +225,7 @@
 
   void Activate();
 
-  void AddBackgroundAnimation(const ui::LocatedEvent& event);
+  void AddBackgroundAnimation(const ui::Event& event);
   void RemoveBackgroundAnimation();
 
   // Overridden from views::View:
@@ -254,7 +256,11 @@
   bool IsManuallyExpandedOrCollapsed() const override;
   void SetManuallyExpandedOrCollapsed(bool value) override;
 
-  void OnSettingsButtonPressed(const ui::LocatedEvent& event) override;
+  void OnSettingsButtonPressed(const ui::Event& event) override;
+
+  // views::InkDropObserver:
+  void InkDropAnimationStarted() override;
+  void InkDropRippleAnimationEnded(views::InkDropState ink_drop_state) override;
 
   // Overridden from NotificationInputDelegate:
   void OnNotificationInputSubmit(size_t index,
@@ -296,7 +302,7 @@
   bool IsExpandable();
   void ToggleExpanded();
   void UpdateViewForExpandedState(bool expanded);
-  void ToggleInlineSettings(const ui::LocatedEvent& event);
+  void ToggleInlineSettings(const ui::Event& event);
 
   views::InkDropContainerView* const ink_drop_container_;
 
diff --git a/ui/message_center/views/popup_alignment_delegate.cc b/ui/message_center/views/popup_alignment_delegate.cc
index 9563637..219e721 100644
--- a/ui/message_center/views/popup_alignment_delegate.cc
+++ b/ui/message_center/views/popup_alignment_delegate.cc
@@ -14,7 +14,7 @@
 
 void PopupAlignmentDelegate::DoUpdateIfPossible() {
   if (collection_)
-    collection_->DoUpdateIfPossible();
+    collection_->DoUpdate();
 }
 
 }  // namespace message_center
diff --git a/ui/message_center/views/toast_contents_view.cc b/ui/message_center/views/toast_contents_view.cc
index 310def6..23c84cf 100644
--- a/ui/message_center/views/toast_contents_view.cc
+++ b/ui/message_center/views/toast_contents_view.cc
@@ -11,6 +11,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "ui/accessibility/ax_enums.mojom.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_targeter.h"
@@ -84,17 +85,11 @@
 void ToastContentsView::SetContents(MessageView* view,
                                     bool a11y_feedback_for_updates) {
   message_view_ = view;
-  bool already_has_contents = child_count() > 0;
   RemoveAllChildViews(true);
   AddChildView(view);
   UpdatePreferredSize();
-
-  // If it has the contents already, this invocation means an update of the
-  // popup toast, and the new contents should be read through a11y feature.
-  // The notification type should be ALERT, otherwise the accessibility message
-  // won't be read for this view which returns ROLE_WINDOW.
-  if (already_has_contents && a11y_feedback_for_updates)
-    NotifyAccessibilityEvent(ax::mojom::Event::kAlert, false);
+  if (a11y_feedback_for_updates)
+    NotifyAccessibilityEvent(ax::mojom::Event::kAlert, true);
 }
 
 void ToastContentsView::UpdateContents(const Notification& notification,
@@ -104,7 +99,7 @@
   message_view->UpdateWithNotification(notification);
   UpdatePreferredSize();
   if (a11y_feedback_for_updates)
-    NotifyAccessibilityEvent(ax::mojom::Event::kAlert, false);
+    NotifyAccessibilityEvent(ax::mojom::Event::kAlert, true);
 }
 
 void ToastContentsView::RevealWithAnimation(gfx::Point origin) {
@@ -164,9 +159,6 @@
   animated_bounds_start_ = GetWidget()->GetWindowBoundsInScreen();
   animated_bounds_end_ = new_bounds;
 
-  if (collection_)
-    collection_->IncrementDeferCounter();
-
   if (bounds_animation_.get())
     bounds_animation_->Stop();
 
@@ -175,9 +167,6 @@
 }
 
 void ToastContentsView::StartFadeIn() {
-  // The decrement is done in OnBoundsAnimationEndedOrCancelled callback.
-  if (collection_)
-    collection_->IncrementDeferCounter();
   fade_animation_->Stop();
 
   GetWidget()->SetOpacity(0);
@@ -187,9 +176,6 @@
 }
 
 void ToastContentsView::StartFadeOut() {
-  // The decrement is done in OnBoundsAnimationEndedOrCancelled callback.
-  if (collection_)
-    collection_->IncrementDeferCounter();
   fade_animation_->Stop();
 
   closing_animation_ = (is_closing_ ? fade_animation_.get() : nullptr);
@@ -219,13 +205,6 @@
 
     widget->Close();
   }
-
-  // This cannot be called before GetWidget()->Close(). Decrementing defer count
-  // will invoke update, which may invoke another close animation with
-  // incrementing defer counter. Close() after such process will cause a
-  // mismatch between increment/decrement. See crbug.com/238477
-  if (collection_)
-    collection_->DecrementDeferCounter();
 }
 
 // gfx::AnimationDelegate
@@ -251,7 +230,7 @@
 
 // views::WidgetDelegate
 void ToastContentsView::WindowClosing() {
-  if (!is_closing_ && collection_.get())
+  if (!is_closing_ && collection_)
     collection_->ForgetToast(this);
 }
 
@@ -332,7 +311,7 @@
 void ToastContentsView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
   if (child_count() > 0)
     child_at(0)->GetAccessibleNodeData(node_data);
-  node_data->role = ax::mojom::Role::kWindow;
+  node_data->role = ax::mojom::Role::kAlertDialog;
 }
 
 const char* ToastContentsView::GetClassName() const {
diff --git a/ui/ozone/demo/BUILD.gn b/ui/ozone/demo/BUILD.gn
index 8a01fb9..7144741 100644
--- a/ui/ozone/demo/BUILD.gn
+++ b/ui/ozone/demo/BUILD.gn
@@ -10,16 +10,22 @@
 
 executable("ozone_demo") {
   sources = [
+    "demo_window.cc",
+    "demo_window.h",
     "ozone_demo.cc",
     "renderer.h",
     "renderer_base.cc",
     "renderer_base.h",
+    "renderer_factory.cc",
+    "renderer_factory.h",
     "skia_renderer.cc",
     "skia_renderer.h",
     "software_renderer.cc",
     "software_renderer.h",
     "surfaceless_skia_renderer.cc",
     "surfaceless_skia_renderer.h",
+    "window_manager.cc",
+    "window_manager.h",
   ]
 
   deps = [
diff --git a/ui/ozone/demo/demo_window.cc b/ui/ozone/demo/demo_window.cc
new file mode 100644
index 0000000..f641537e
--- /dev/null
+++ b/ui/ozone/demo/demo_window.cc
@@ -0,0 +1,90 @@
+// Copyright 2018 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 "ui/ozone/demo/demo_window.h"
+
+#include "base/threading/thread_task_runner_handle.h"
+#include "ui/events/event.h"
+#include "ui/events/keycodes/dom/dom_code.h"
+#include "ui/ozone/demo/renderer.h"
+#include "ui/ozone/demo/renderer_factory.h"
+#include "ui/ozone/demo/window_manager.h"
+#include "ui/ozone/public/ozone_platform.h"
+#include "ui/platform_window/platform_window.h"
+
+namespace ui {
+
+DemoWindow::DemoWindow(WindowManager* window_manager,
+                       RendererFactory* renderer_factory,
+                       const gfx::Rect& bounds)
+    : window_manager_(window_manager),
+      renderer_factory_(renderer_factory),
+      weak_ptr_factory_(this) {
+  platform_window_ =
+      OzonePlatform::GetInstance()->CreatePlatformWindow(this, bounds);
+  platform_window_->Show();
+}
+
+DemoWindow::~DemoWindow() {}
+
+gfx::AcceleratedWidget DemoWindow::GetAcceleratedWidget() {
+  // TODO(spang): We should start rendering asynchronously.
+  DCHECK_NE(widget_, gfx::kNullAcceleratedWidget)
+      << "Widget not available synchronously";
+  return widget_;
+}
+
+gfx::Size DemoWindow::GetSize() {
+  return platform_window_->GetBounds().size();
+}
+
+void DemoWindow::Start() {
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE,
+      base::BindOnce(&DemoWindow::StartOnGpu, weak_ptr_factory_.GetWeakPtr()));
+}
+
+void DemoWindow::Quit() {
+  window_manager_->Quit();
+}
+
+void DemoWindow::OnBoundsChanged(const gfx::Rect& new_bounds) {}
+
+void DemoWindow::OnDamageRect(const gfx::Rect& damaged_region) {}
+
+void DemoWindow::DispatchEvent(Event* event) {
+  if (event->IsKeyEvent() && event->AsKeyEvent()->code() == DomCode::US_Q)
+    Quit();
+}
+
+void DemoWindow::OnCloseRequest() {
+  Quit();
+}
+
+void DemoWindow::OnClosed() {}
+
+void DemoWindow::OnWindowStateChanged(PlatformWindowState new_state) {}
+
+void DemoWindow::OnLostCapture() {}
+
+void DemoWindow::OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget,
+                                              float device_pixel_ratio) {
+  DCHECK_NE(widget, gfx::kNullAcceleratedWidget);
+  widget_ = widget;
+}
+
+void DemoWindow::OnAcceleratedWidgetDestroyed() {
+  NOTREACHED();
+}
+
+void DemoWindow::OnActivationChanged(bool active) {}
+
+void DemoWindow::StartOnGpu() {
+  renderer_ =
+      renderer_factory_->CreateRenderer(GetAcceleratedWidget(), GetSize());
+  if (!renderer_->Initialize())
+    LOG(ERROR) << "Failed to initialize renderer.";
+}
+
+}  // namespace ui
diff --git a/ui/ozone/demo/demo_window.h b/ui/ozone/demo/demo_window.h
new file mode 100644
index 0000000..6a41df1
--- /dev/null
+++ b/ui/ozone/demo/demo_window.h
@@ -0,0 +1,69 @@
+// Copyright 2018 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 UI_OZONE_DEMO_DEMO_WINDOW_H_
+#define UI_OZONE_DEMO_DEMO_WINDOW_H_
+
+#include "base/memory/weak_ptr.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/platform_window/platform_window_delegate.h"
+
+namespace ui {
+
+class Event;
+class PlatformWindow;
+class Renderer;
+class RendererFactory;
+class WindowManager;
+
+class DemoWindow : public PlatformWindowDelegate {
+ public:
+  DemoWindow(WindowManager* window_manager,
+             RendererFactory* renderer_factory,
+             const gfx::Rect& bounds);
+  ~DemoWindow() override;
+
+  gfx::AcceleratedWidget GetAcceleratedWidget();
+
+  gfx::Size GetSize();
+
+  void Start();
+  void Quit();
+
+  // PlatformWindowDelegate:
+  void OnBoundsChanged(const gfx::Rect& new_bounds) override;
+  void OnDamageRect(const gfx::Rect& damaged_region) override;
+  void DispatchEvent(Event* event) override;
+  void OnCloseRequest() override;
+  void OnClosed() override;
+  void OnWindowStateChanged(PlatformWindowState new_state) override;
+  void OnLostCapture() override;
+  void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget,
+                                    float device_pixel_ratio) override;
+  void OnAcceleratedWidgetDestroyed() override;
+  void OnActivationChanged(bool active) override;
+
+ private:
+  // Since we pretend to have a GPU process, we should also pretend to
+  // initialize the GPU resources via a posted task.
+  void StartOnGpu();
+
+  WindowManager* window_manager_;      // Not owned.
+  RendererFactory* renderer_factory_;  // Not owned.
+
+  std::unique_ptr<Renderer> renderer_;
+
+  // Window-related state.
+  std::unique_ptr<PlatformWindow> platform_window_;
+  gfx::AcceleratedWidget widget_ = gfx::kNullAcceleratedWidget;
+
+  base::WeakPtrFactory<DemoWindow> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(DemoWindow);
+};
+
+}  // namespace ui
+
+#endif  // UI_OZONE_DEMO_DEMO_WINDOW_H_
diff --git a/ui/ozone/demo/ozone_demo.cc b/ui/ozone/demo/ozone_demo.cc
index ed283ba6..6806dbe 100644
--- a/ui/ozone/demo/ozone_demo.cc
+++ b/ui/ozone/demo/ozone_demo.cc
@@ -3,336 +3,23 @@
 // found in the LICENSE file.
 
 #include <iostream>
-#include <utility>
 
 #include "base/at_exit.h"
 #include "base/command_line.h"
 #include "base/debug/stack_trace.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/task_scheduler/task_scheduler.h"
-#include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/trace_event.h"
 #include "components/tracing/common/trace_to_console.h"
 #include "components/tracing/common/tracing_switches.h"
-#include "ui/display/types/display_snapshot.h"
-#include "ui/display/types/native_display_delegate.h"
-#include "ui/display/types/native_display_observer.h"
-#include "ui/events/event.h"
-#include "ui/events/keycodes/dom/dom_code.h"
 #include "ui/events/ozone/layout/keyboard_layout_engine.h"
 #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/gl/gl_surface.h"
-#include "ui/gl/init/gl_factory.h"
-#include "ui/ozone/demo/skia_renderer.h"
-#include "ui/ozone/demo/software_renderer.h"
-#include "ui/ozone/demo/surfaceless_skia_renderer.h"
-#include "ui/ozone/public/ozone_gpu_test_helper.h"
+#include "ui/ozone/demo/window_manager.h"
 #include "ui/ozone/public/ozone_platform.h"
-#include "ui/ozone/public/ozone_switches.h"
-#include "ui/platform_window/platform_window.h"
-#include "ui/platform_window/platform_window_delegate.h"
 
-const int kTestWindowWidth = 800;
-const int kTestWindowHeight = 600;
-
-const char kDisableGpu[] = "disable-gpu";
-const char kDisableSurfaceless[] = "disable-surfaceless";
 const char kHelp[] = "help";
 
-const char kWindowSize[] = "window-size";
-
-class DemoWindow;
-
-scoped_refptr<gl::GLSurface> CreateGLSurface(gfx::AcceleratedWidget widget) {
-  scoped_refptr<gl::GLSurface> surface;
-  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(kDisableSurfaceless))
-    surface = gl::init::CreateSurfacelessViewGLSurface(widget);
-  if (!surface)
-    surface = gl::init::CreateViewGLSurface(widget);
-  return surface;
-}
-
-class RendererFactory {
- public:
-  enum RendererType {
-    SKIA,
-    SOFTWARE,
-  };
-
-  RendererFactory();
-  ~RendererFactory();
-
-  bool Initialize();
-  std::unique_ptr<ui::Renderer> CreateRenderer(gfx::AcceleratedWidget widget,
-                                               const gfx::Size& size);
-
- private:
-  RendererType type_ = SOFTWARE;
-
-  // Helper for applications that do GL on main thread.
-  ui::OzoneGpuTestHelper gpu_helper_;
-
-  DISALLOW_COPY_AND_ASSIGN(RendererFactory);
-};
-
-class WindowManager : public display::NativeDisplayObserver {
- public:
-  explicit WindowManager(const base::Closure& quit_closure);
-  ~WindowManager() override;
-
-  void Quit();
-
-  void AddWindow(DemoWindow* window);
-  void RemoveWindow(DemoWindow* window);
-
- private:
-  void OnDisplaysAquired(
-      const std::vector<display::DisplaySnapshot*>& displays);
-  void OnDisplayConfigured(const gfx::Rect& bounds, bool success);
-
-  // display::NativeDisplayDelegate:
-  void OnConfigurationChanged() override;
-  void OnDisplaySnapshotsInvalidated() override;
-
-  std::unique_ptr<display::NativeDisplayDelegate> delegate_;
-  base::Closure quit_closure_;
-  RendererFactory renderer_factory_;
-  std::vector<std::unique_ptr<DemoWindow>> windows_;
-
-  // Flags used to keep track of the current state of display configuration.
-  //
-  // True if configuring the displays. In this case a new display configuration
-  // isn't started.
-  bool is_configuring_ = false;
-
-  // If |is_configuring_| is true and another display configuration event
-  // happens, the event is deferred. This is set to true and a display
-  // configuration will be scheduled after the current one finishes.
-  bool should_configure_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(WindowManager);
-};
-
-class DemoWindow : public ui::PlatformWindowDelegate {
- public:
-  DemoWindow(WindowManager* window_manager,
-             RendererFactory* renderer_factory,
-             const gfx::Rect& bounds)
-      : window_manager_(window_manager),
-        renderer_factory_(renderer_factory),
-        weak_ptr_factory_(this) {
-    platform_window_ =
-        ui::OzonePlatform::GetInstance()->CreatePlatformWindow(this, bounds);
-    platform_window_->Show();
-  }
-  ~DemoWindow() override {}
-
-  gfx::AcceleratedWidget GetAcceleratedWidget() {
-    // TODO(spang): We should start rendering asynchronously.
-    DCHECK_NE(widget_, gfx::kNullAcceleratedWidget)
-        << "Widget not available synchronously";
-    return widget_;
-  }
-
-  gfx::Size GetSize() { return platform_window_->GetBounds().size(); }
-
-  void Start() {
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE,
-        base::Bind(&DemoWindow::StartOnGpu, weak_ptr_factory_.GetWeakPtr()));
-  }
-
-  void Quit() {
-    window_manager_->Quit();
-  }
-
-  // PlatformWindowDelegate:
-  void OnBoundsChanged(const gfx::Rect& new_bounds) override {}
-  void OnDamageRect(const gfx::Rect& damaged_region) override {}
-  void DispatchEvent(ui::Event* event) override {
-    if (event->IsKeyEvent() && event->AsKeyEvent()->code() == ui::DomCode::US_Q)
-      Quit();
-  }
-  void OnCloseRequest() override { Quit(); }
-  void OnClosed() override {}
-  void OnWindowStateChanged(ui::PlatformWindowState new_state) override {}
-  void OnLostCapture() override {}
-  void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget,
-                                    float device_pixel_ratio) override {
-    DCHECK_NE(widget, gfx::kNullAcceleratedWidget);
-    widget_ = widget;
-  }
-  void OnAcceleratedWidgetDestroyed() override {
-    NOTREACHED();
-  }
-  void OnActivationChanged(bool active) override {}
-
- private:
-  // Since we pretend to have a GPU process, we should also pretend to
-  // initialize the GPU resources via a posted task.
-  void StartOnGpu() {
-    renderer_ =
-        renderer_factory_->CreateRenderer(GetAcceleratedWidget(), GetSize());
-    if (!renderer_->Initialize())
-      LOG(ERROR) << "Failed to initialize renderer.";
-  }
-
-  WindowManager* window_manager_;      // Not owned.
-  RendererFactory* renderer_factory_;  // Not owned.
-
-  std::unique_ptr<ui::Renderer> renderer_;
-
-  // Window-related state.
-  std::unique_ptr<ui::PlatformWindow> platform_window_;
-  gfx::AcceleratedWidget widget_ = gfx::kNullAcceleratedWidget;
-
-  base::WeakPtrFactory<DemoWindow> weak_ptr_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(DemoWindow);
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// RendererFactory implementation:
-
-RendererFactory::RendererFactory() {
-}
-
-RendererFactory::~RendererFactory() {
-}
-
-bool RendererFactory::Initialize() {
-  ui::OzonePlatform::InitParams params;
-  params.single_process = true;
-  ui::OzonePlatform::InitializeForGPU(params);
-  ui::OzonePlatform::GetInstance()->AfterSandboxEntry();
-
-  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-  if (!command_line->HasSwitch(kDisableGpu) && gl::init::InitializeGLOneOff() &&
-      gpu_helper_.Initialize(base::ThreadTaskRunnerHandle::Get())) {
-    type_ = SKIA;
-  } else {
-    type_ = SOFTWARE;
-  }
-
-  return true;
-}
-
-std::unique_ptr<ui::Renderer> RendererFactory::CreateRenderer(
-    gfx::AcceleratedWidget widget,
-    const gfx::Size& size) {
-  switch (type_) {
-    case SKIA: {
-      scoped_refptr<gl::GLSurface> surface = CreateGLSurface(widget);
-      if (!surface)
-        LOG(FATAL) << "Failed to create GL surface";
-      if (surface->IsSurfaceless()) {
-        return std::make_unique<ui::SurfacelessSkiaRenderer>(widget, surface,
-                                                             size);
-      }
-      return std::make_unique<ui::SkiaRenderer>(widget, surface, size);
-    }
-    case SOFTWARE:
-      return std::make_unique<ui::SoftwareRenderer>(widget, size);
-  }
-
-  return nullptr;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// WindowManager implementation:
-
-WindowManager::WindowManager(const base::Closure& quit_closure)
-    : delegate_(
-          ui::OzonePlatform::GetInstance()->CreateNativeDisplayDelegate()),
-      quit_closure_(quit_closure) {
-  if (!renderer_factory_.Initialize())
-    LOG(FATAL) << "Failed to initialize renderer factory";
-
-  if (delegate_) {
-    delegate_->AddObserver(this);
-    delegate_->Initialize();
-    OnConfigurationChanged();
-  } else {
-    LOG(WARNING) << "No display delegate; falling back to test window";
-    int width = kTestWindowWidth;
-    int height = kTestWindowHeight;
-    sscanf(base::CommandLine::ForCurrentProcess()
-               ->GetSwitchValueASCII(kWindowSize)
-               .c_str(),
-           "%dx%d", &width, &height);
-
-    DemoWindow* window = new DemoWindow(this, &renderer_factory_,
-                                        gfx::Rect(gfx::Size(width, height)));
-    window->Start();
-  }
-}
-
-WindowManager::~WindowManager() {
-  if (delegate_)
-    delegate_->RemoveObserver(this);
-}
-
-void WindowManager::Quit() {
-  quit_closure_.Run();
-}
-
-void WindowManager::OnConfigurationChanged() {
-  if (is_configuring_) {
-    should_configure_ = true;
-    return;
-  }
-
-  is_configuring_ = true;
-  delegate_->GetDisplays(
-      base::Bind(&WindowManager::OnDisplaysAquired, base::Unretained(this)));
-}
-
-void WindowManager::OnDisplaySnapshotsInvalidated() {}
-
-void WindowManager::OnDisplaysAquired(
-    const std::vector<display::DisplaySnapshot*>& displays) {
-  windows_.clear();
-
-  gfx::Point origin;
-  for (auto* display : displays) {
-    if (!display->native_mode()) {
-      LOG(ERROR) << "Display " << display->display_id()
-                 << " doesn't have a native mode";
-      continue;
-    }
-
-    delegate_->Configure(
-        *display, display->native_mode(), origin,
-        base::Bind(&WindowManager::OnDisplayConfigured, base::Unretained(this),
-                   gfx::Rect(origin, display->native_mode()->size())));
-    origin.Offset(display->native_mode()->size().width(), 0);
-  }
-  is_configuring_ = false;
-
-  if (should_configure_) {
-    should_configure_ = false;
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::Bind(&WindowManager::OnConfigurationChanged,
-                              base::Unretained(this)));
-  }
-}
-
-void WindowManager::OnDisplayConfigured(const gfx::Rect& bounds, bool success) {
-  if (success) {
-    std::unique_ptr<DemoWindow> window(
-        new DemoWindow(this, &renderer_factory_, bounds));
-    window->Start();
-    windows_.push_back(std::move(window));
-  } else {
-    LOG(ERROR) << "Failed to configure display at " << bounds.ToString();
-  }
-}
-
 int main(int argc, char** argv) {
   base::CommandLine::Init(argc, argv);
   base::AtExitManager exit_manager;
@@ -384,7 +71,7 @@
 
   base::RunLoop run_loop;
 
-  WindowManager window_manager(run_loop.QuitClosure());
+  ui::WindowManager window_manager(run_loop.QuitClosure());
 
   run_loop.Run();
 
diff --git a/ui/ozone/demo/renderer_factory.cc b/ui/ozone/demo/renderer_factory.cc
new file mode 100644
index 0000000..10a0110
--- /dev/null
+++ b/ui/ozone/demo/renderer_factory.cc
@@ -0,0 +1,75 @@
+// Copyright 2018 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 "ui/ozone/demo/renderer_factory.h"
+
+#include <memory>
+
+#include "base/command_line.h"
+#include "ui/gl/gl_surface.h"
+#include "ui/gl/init/gl_factory.h"
+#include "ui/ozone/demo/skia_renderer.h"
+#include "ui/ozone/demo/software_renderer.h"
+#include "ui/ozone/demo/surfaceless_skia_renderer.h"
+#include "ui/ozone/public/ozone_platform.h"
+
+namespace ui {
+namespace {
+
+const char kDisableSurfaceless[] = "disable-surfaceless";
+const char kDisableGpu[] = "disable-gpu";
+
+scoped_refptr<gl::GLSurface> CreateGLSurface(gfx::AcceleratedWidget widget) {
+  scoped_refptr<gl::GLSurface> surface;
+  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(kDisableSurfaceless))
+    surface = gl::init::CreateSurfacelessViewGLSurface(widget);
+  if (!surface)
+    surface = gl::init::CreateViewGLSurface(widget);
+  return surface;
+}
+
+}  // namespace
+
+RendererFactory::RendererFactory() {}
+
+RendererFactory::~RendererFactory() {}
+
+bool RendererFactory::Initialize() {
+  OzonePlatform::InitParams params;
+  params.single_process = true;
+  OzonePlatform::InitializeForGPU(params);
+  OzonePlatform::GetInstance()->AfterSandboxEntry();
+
+  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+  if (!command_line->HasSwitch(kDisableGpu) && gl::init::InitializeGLOneOff() &&
+      gpu_helper_.Initialize(base::ThreadTaskRunnerHandle::Get())) {
+    type_ = SKIA;
+  } else {
+    type_ = SOFTWARE;
+  }
+
+  return true;
+}
+
+std::unique_ptr<Renderer> RendererFactory::CreateRenderer(
+    gfx::AcceleratedWidget widget,
+    const gfx::Size& size) {
+  switch (type_) {
+    case SKIA: {
+      scoped_refptr<gl::GLSurface> surface = CreateGLSurface(widget);
+      if (!surface)
+        LOG(FATAL) << "Failed to create GL surface";
+      if (surface->IsSurfaceless()) {
+        return std::make_unique<SurfacelessSkiaRenderer>(widget, surface, size);
+      }
+      return std::make_unique<SkiaRenderer>(widget, surface, size);
+    }
+    case SOFTWARE:
+      return std::make_unique<SoftwareRenderer>(widget, size);
+  }
+
+  return nullptr;
+}
+
+}  // namespace ui
diff --git a/ui/ozone/demo/renderer_factory.h b/ui/ozone/demo/renderer_factory.h
new file mode 100644
index 0000000..f87aeae
--- /dev/null
+++ b/ui/ozone/demo/renderer_factory.h
@@ -0,0 +1,41 @@
+// Copyright 2018 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 UI_OZONE_DEMO_RENDERER_FACTORY_H_
+#define UI_OZONE_DEMO_RENDERER_FACTORY_H_
+
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/ozone/public/ozone_gpu_test_helper.h"
+
+namespace ui {
+
+class Renderer;
+
+class RendererFactory {
+ public:
+  enum RendererType {
+    SKIA,
+    SOFTWARE,
+  };
+
+  RendererFactory();
+  ~RendererFactory();
+
+  bool Initialize();
+  std::unique_ptr<Renderer> CreateRenderer(gfx::AcceleratedWidget widget,
+                                           const gfx::Size& size);
+
+ private:
+  RendererType type_ = SOFTWARE;
+
+  // Helper for applications that do GL on main thread.
+  OzoneGpuTestHelper gpu_helper_;
+
+  DISALLOW_COPY_AND_ASSIGN(RendererFactory);
+};
+
+}  // namespace ui
+
+#endif  // UI_OZONE_DEMO_RENDERER_FACTORY_H_
diff --git a/ui/ozone/demo/surfaceless_skia_renderer.cc b/ui/ozone/demo/surfaceless_skia_renderer.cc
index b4cb10a..c3bce8b 100644
--- a/ui/ozone/demo/surfaceless_skia_renderer.cc
+++ b/ui/ozone/demo/surfaceless_skia_renderer.cc
@@ -114,7 +114,7 @@
           ->GetSurfaceFactoryOzone()
           ->CreateNativePixmap(widget, size, format, gfx::BufferUsage::SCANOUT);
   scoped_refptr<gl::GLImageNativePixmap> image(
-      new gl::GLImageNativePixmap(size, GL_RGB));
+      new gl::GLImageNativePixmap(size, GL_BGRA_EXT));
   if (!image->Initialize(pixmap.get(), format)) {
     LOG(ERROR) << "Failed to create GLImage";
     return false;
diff --git a/ui/ozone/demo/window_manager.cc b/ui/ozone/demo/window_manager.cc
new file mode 100644
index 0000000..9fb74d7e
--- /dev/null
+++ b/ui/ozone/demo/window_manager.cc
@@ -0,0 +1,112 @@
+// Copyright 2018 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 "ui/ozone/demo/window_manager.h"
+
+#include "base/command_line.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "ui/display/types/display_snapshot.h"
+#include "ui/display/types/native_display_delegate.h"
+#include "ui/ozone/demo/demo_window.h"
+#include "ui/ozone/public/ozone_platform.h"
+
+namespace ui {
+namespace {
+
+const int kTestWindowWidth = 800;
+const int kTestWindowHeight = 600;
+
+const char kWindowSize[] = "window-size";
+
+}  // namespace
+
+WindowManager::WindowManager(base::OnceClosure quit_closure)
+    : delegate_(
+          ui::OzonePlatform::GetInstance()->CreateNativeDisplayDelegate()),
+      quit_closure_(std::move(quit_closure)) {
+  if (!renderer_factory_.Initialize())
+    LOG(FATAL) << "Failed to initialize renderer factory";
+
+  if (delegate_) {
+    delegate_->AddObserver(this);
+    delegate_->Initialize();
+    OnConfigurationChanged();
+  } else {
+    LOG(WARNING) << "No display delegate; falling back to test window";
+    int width = kTestWindowWidth;
+    int height = kTestWindowHeight;
+    sscanf(base::CommandLine::ForCurrentProcess()
+               ->GetSwitchValueASCII(kWindowSize)
+               .c_str(),
+           "%dx%d", &width, &height);
+
+    DemoWindow* window = new DemoWindow(this, &renderer_factory_,
+                                        gfx::Rect(gfx::Size(width, height)));
+    window->Start();
+  }
+}
+
+WindowManager::~WindowManager() {
+  if (delegate_)
+    delegate_->RemoveObserver(this);
+}
+
+void WindowManager::Quit() {
+  std::move(quit_closure_).Run();
+}
+
+void WindowManager::OnConfigurationChanged() {
+  if (is_configuring_) {
+    should_configure_ = true;
+    return;
+  }
+
+  is_configuring_ = true;
+  delegate_->GetDisplays(base::BindRepeating(&WindowManager::OnDisplaysAquired,
+                                             base::Unretained(this)));
+}
+
+void WindowManager::OnDisplaySnapshotsInvalidated() {}
+
+void WindowManager::OnDisplaysAquired(
+    const std::vector<display::DisplaySnapshot*>& displays) {
+  windows_.clear();
+
+  gfx::Point origin;
+  for (auto* display : displays) {
+    if (!display->native_mode()) {
+      LOG(ERROR) << "Display " << display->display_id()
+                 << " doesn't have a native mode";
+      continue;
+    }
+
+    delegate_->Configure(
+        *display, display->native_mode(), origin,
+        base::BindRepeating(&WindowManager::OnDisplayConfigured,
+                            base::Unretained(this),
+                            gfx::Rect(origin, display->native_mode()->size())));
+    origin.Offset(display->native_mode()->size().width(), 0);
+  }
+  is_configuring_ = false;
+
+  if (should_configure_) {
+    should_configure_ = false;
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::BindRepeating(&WindowManager::OnConfigurationChanged,
+                                       base::Unretained(this)));
+  }
+}
+
+void WindowManager::OnDisplayConfigured(const gfx::Rect& bounds, bool success) {
+  if (success) {
+    std::unique_ptr<DemoWindow> window(
+        new DemoWindow(this, &renderer_factory_, bounds));
+    window->Start();
+    windows_.push_back(std::move(window));
+  } else {
+    LOG(ERROR) << "Failed to configure display at " << bounds.ToString();
+  }
+}
+
+}  // namespace ui
diff --git a/ui/ozone/demo/window_manager.h b/ui/ozone/demo/window_manager.h
new file mode 100644
index 0000000..d1559084
--- /dev/null
+++ b/ui/ozone/demo/window_manager.h
@@ -0,0 +1,66 @@
+// Copyright 2018 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 UI_OZONE_DEMO_WINDOW_MANAGER_H_
+#define UI_OZONE_DEMO_WINDOW_MANAGER_H_
+
+#include <vector>
+
+#include "base/callback.h"
+#include "ui/display/types/native_display_observer.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/ozone/demo/renderer_factory.h"
+
+namespace display {
+
+class DisplaySnapshot;
+class NativeDisplayDelegate;
+
+}  // namespace display
+
+namespace ui {
+
+class DemoWindow;
+
+class WindowManager : public display::NativeDisplayObserver {
+ public:
+  explicit WindowManager(base::OnceClosure quit_closure);
+  ~WindowManager() override;
+
+  void Quit();
+
+  void AddWindow(DemoWindow* window);
+  void RemoveWindow(DemoWindow* window);
+
+ private:
+  void OnDisplaysAquired(
+      const std::vector<display::DisplaySnapshot*>& displays);
+  void OnDisplayConfigured(const gfx::Rect& bounds, bool success);
+
+  // display::NativeDisplayDelegate:
+  void OnConfigurationChanged() override;
+  void OnDisplaySnapshotsInvalidated() override;
+
+  std::unique_ptr<display::NativeDisplayDelegate> delegate_;
+  base::OnceClosure quit_closure_;
+  RendererFactory renderer_factory_;
+  std::vector<std::unique_ptr<DemoWindow>> windows_;
+
+  // Flags used to keep track of the current state of display configuration.
+  //
+  // True if configuring the displays. In this case a new display configuration
+  // isn't started.
+  bool is_configuring_ = false;
+
+  // If |is_configuring_| is true and another display configuration event
+  // happens, the event is deferred. This is set to true and a display
+  // configuration will be scheduled after the current one finishes.
+  bool should_configure_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(WindowManager);
+};
+
+}  // namespace ui
+
+#endif  // UI_OZONE_DEMO_WINDOW_MANAGER_H_
diff --git a/ui/ozone/platform/cast/platform_window_cast.cc b/ui/ozone/platform/cast/platform_window_cast.cc
index d5a3337..08ce52b 100644
--- a/ui/ozone/platform/cast/platform_window_cast.cc
+++ b/ui/ozone/platform/cast/platform_window_cast.cc
@@ -18,15 +18,13 @@
   widget_ = (bounds.width() << 16) + bounds.height();
   delegate_->OnAcceleratedWidgetAvailable(widget_, 1.f);
 
-  if (ui::PlatformEventSource::GetInstance()) {
-    ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
-  }
+  if (PlatformEventSource::GetInstance())
+    PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
 }
 
 PlatformWindowCast::~PlatformWindowCast() {
-  if (ui::PlatformEventSource::GetInstance()) {
-    ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
-  }
+  if (PlatformEventSource::GetInstance())
+    PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
 }
 
 gfx::Rect PlatformWindowCast::GetBounds() {
@@ -45,12 +43,11 @@
   return nullptr;
 }
 
-bool PlatformWindowCast::CanDispatchEvent(const ui::PlatformEvent& ne) {
+bool PlatformWindowCast::CanDispatchEvent(const PlatformEvent& ne) {
   return true;
 }
 
-uint32_t PlatformWindowCast::DispatchEvent(
-    const ui::PlatformEvent& native_event) {
+uint32_t PlatformWindowCast::DispatchEvent(const PlatformEvent& native_event) {
   DispatchEventFromNativeUiEvent(
       native_event, base::BindOnce(&PlatformWindowDelegate::DispatchEvent,
                                    base::Unretained(delegate_)));
diff --git a/ui/ozone/platform/drm/gpu/crtc_controller.cc b/ui/ozone/platform/drm/gpu/crtc_controller.cc
index 8845685..fdf87224 100644
--- a/ui/ozone/platform/drm/gpu/crtc_controller.cc
+++ b/ui/ozone/platform/drm/gpu/crtc_controller.cc
@@ -44,11 +44,11 @@
 }
 
 bool CrtcController::Modeset(const OverlayPlane& plane, drmModeModeInfo mode) {
-  if (!drm_->SetCrtc(crtc_, plane.buffer->GetFramebufferId(),
+  if (!drm_->SetCrtc(crtc_, plane.buffer->GetOpaqueFramebufferId(),
                      std::vector<uint32_t>(1, connector_), &mode)) {
     PLOG(ERROR) << "Failed to modeset: crtc=" << crtc_
                 << " connector=" << connector_
-                << " framebuffer_id=" << plane.buffer->GetFramebufferId()
+                << " framebuffer_id=" << plane.buffer->GetOpaqueFramebufferId()
                 << " mode=" << mode.hdisplay << "x" << mode.vdisplay << "@"
                 << mode.vrefresh;
     return false;
diff --git a/ui/ozone/platform/drm/gpu/gbm_surface.cc b/ui/ozone/platform/drm/gpu/gbm_surface.cc
index d93fa59..56c05a9 100644
--- a/ui/ozone/platform/drm/gpu/gbm_surface.cc
+++ b/ui/ozone/platform/drm/gpu/gbm_surface.cc
@@ -136,7 +136,7 @@
     if (!pixmap)
       return false;
     scoped_refptr<gl::GLImageNativePixmap> image =
-        new gl::GLImageNativePixmap(GetSize(), GL_RGB);
+        new gl::GLImageNativePixmap(GetSize(), GL_BGRA_EXT);
     if (!image->Initialize(pixmap.get(),
                            display::DisplaySnapshot::PrimaryFormat()))
       return false;
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc
index b745207..42446c9 100644
--- a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc
+++ b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc
@@ -214,7 +214,10 @@
   if (!plane->CanUseForCrtc(crtc_index))
     return false;
 
-  if (!plane->IsSupportedFormat(overlay.buffer->GetFramebufferPixelFormat()))
+  const uint32_t format = overlay.enable_blend ?
+      overlay.buffer->GetFramebufferPixelFormat() :
+      overlay.buffer->GetOpaqueFramebufferPixelFormat();
+  if (!plane->IsSupportedFormat(format))
     return false;
 
   // TODO(kalyank): We should check for z-order and any needed transformation
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.cc b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.cc
index 8aaf4e28..3c6b9c4 100644
--- a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.cc
+++ b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.cc
@@ -167,7 +167,7 @@
   } else {
     plane_list->legacy_page_flips.back().planes.push_back(
         HardwareDisplayPlaneList::PageFlipInfo::Plane(
-            hw_plane->plane_id(), overlay.buffer->GetFramebufferId(),
+            hw_plane->plane_id(), overlay.buffer->GetOpaqueFramebufferId(),
             overlay.display_bounds, src_rect));
   }
   return true;
diff --git a/ui/ozone/platform/drm/gpu/screen_manager.cc b/ui/ozone/platform/drm/gpu/screen_manager.cc
index c09e8a3..4455933 100644
--- a/ui/ozone/platform/drm/gpu/screen_manager.cc
+++ b/ui/ozone/platform/drm/gpu/screen_manager.cc
@@ -32,9 +32,9 @@
 void FillModesetBuffer(const scoped_refptr<DrmDevice>& drm,
                        HardwareDisplayController* controller,
                        ScanoutBuffer* buffer) {
-  DrmConsoleBuffer modeset_buffer(drm, buffer->GetFramebufferId());
+  DrmConsoleBuffer modeset_buffer(drm, buffer->GetOpaqueFramebufferId());
   if (!modeset_buffer.Initialize()) {
-    VLOG(2) << "Failed to grab framebuffer " << buffer->GetFramebufferId();
+    VLOG(2) << "Failed to grab framebuffer " << buffer->GetOpaqueFramebufferId();
     return;
   }
 
diff --git a/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc b/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc
index 2fe14da..a50a0ac2 100644
--- a/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc
+++ b/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc
@@ -511,7 +511,7 @@
       drm_, kPrimaryCrtc, kPrimaryConnector, GetPrimaryBounds().origin(),
       kDefaultMode);
 
-  EXPECT_EQ(buffer->GetFramebufferId(), drm_->current_framebuffer());
+  EXPECT_EQ(buffer->GetOpaqueFramebufferId(), drm_->current_framebuffer());
 
   window = screen_manager_->RemoveWindow(1);
   window->Shutdown();
diff --git a/ui/ozone/platform/headless/ozone_platform_headless.cc b/ui/ozone/platform/headless/ozone_platform_headless.cc
index 8c569f4..166def2 100644
--- a/ui/ozone/platform/headless/ozone_platform_headless.cc
+++ b/ui/ozone/platform/headless/ozone_platform_headless.cc
@@ -31,7 +31,7 @@
 // A headless implementation of PlatformEventSource that we can instantiate to
 // make
 // sure that the PlatformEventSource has an instance while in unit tests.
-class HeadlessPlatformEventSource : public ui::PlatformEventSource {
+class HeadlessPlatformEventSource : public PlatformEventSource {
  public:
   HeadlessPlatformEventSource() = default;
   ~HeadlessPlatformEventSource() override = default;
diff --git a/ui/ozone/public/ozone_platform.h b/ui/ozone/public/ozone_platform.h
index f715a6af..5e1feb7 100644
--- a/ui/ozone/public/ozone_platform.h
+++ b/ui/ozone/public/ozone_platform.h
@@ -13,7 +13,6 @@
 #include "services/service_manager/public/cpp/binder_registry.h"
 #include "ui/events/system_input_injector.h"
 #include "ui/ozone/ozone_export.h"
-//#include "ui/ozone/public/interfaces/drm_device.mojom.h"
 
 namespace display {
 class NativeDisplayDelegate;
diff --git a/ui/platform_window/platform_window.h b/ui/platform_window/platform_window.h
index bd8dbb0..87a8b1d 100644
--- a/ui/platform_window/platform_window.h
+++ b/ui/platform_window/platform_window.h
@@ -11,6 +11,7 @@
 #include "ui/base/cursor/cursor.h"
 
 namespace gfx {
+class Point;
 class Rect;
 }
 
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn
index 443a433..0e57947 100644
--- a/ui/views/BUILD.gn
+++ b/ui/views/BUILD.gn
@@ -22,14 +22,13 @@
   icons = [
     "checkbox_active.icon",
     "checkbox_normal.icon",
-    "menu_check.1x.icon",
     "menu_check.icon",
     "menu_radio_empty.icon",
     "menu_radio_selected.icon",
     "radio_button_active.icon",
     "radio_button_normal.icon",
-    "submenu_arrow.1x.icon",
     "submenu_arrow.icon",
+    "ic_close.icon",
   ]
 }
 
diff --git a/ui/views/cocoa/bridged_content_view.mm b/ui/views/cocoa/bridged_content_view.mm
index 756745e6..76406e0 100644
--- a/ui/views/cocoa/bridged_content_view.mm
+++ b/ui/views/cocoa/bridged_content_view.mm
@@ -1435,16 +1435,16 @@
   composition.text = base::SysNSStringToUTF16(text);
   composition.selection = gfx::Range(selectedRange);
 
-  // Add a black underline with a transparent background to the composition
-  // text. TODO(karandeepb): On Cocoa textfields, the target clause of the
-  // composition has a thick underlines. The composition text also has
+  // Add an underline with text color and a transparent background to the
+  // composition text. TODO(karandeepb): On Cocoa textfields, the target clause
+  // of the composition has a thick underlines. The composition text also has
   // discontinous underlines for different clauses. This is also supported in
   // the Chrome renderer. Add code to extract underlines from |text| once our
   // render text implementation supports thick underlines and discontinous
   // underlines for consecutive characters. See http://crbug.com/612675.
-  composition.ime_text_spans.push_back(ui::ImeTextSpan(
-      ui::ImeTextSpan::Type::kComposition, 0, [text length], SK_ColorBLACK,
-      ui::ImeTextSpan::Thickness::kThin, SK_ColorTRANSPARENT));
+  composition.ime_text_spans.push_back(
+      ui::ImeTextSpan(ui::ImeTextSpan::Type::kComposition, 0, [text length],
+                      ui::ImeTextSpan::Thickness::kThin, SK_ColorTRANSPARENT));
   textInputClient_->SetCompositionText(composition);
   hasUnhandledKeyDownEvent_ = NO;
 }
diff --git a/ui/views/cocoa/bridged_native_widget.mm b/ui/views/cocoa/bridged_native_widget.mm
index 3c6e990..b2b794a 100644
--- a/ui/views/cocoa/bridged_native_widget.mm
+++ b/ui/views/cocoa/bridged_native_widget.mm
@@ -1008,6 +1008,12 @@
       HTCAPTION)
     return false;
 
+  // Properly parented modal dialogs should never be draggable by their dialog
+  // title on mac. They are either sheets, or tab-modals. See NativeWidgetMac::
+  // InitModalType().
+  if (parent_ && native_widget_mac_->GetWidget()->IsModal())
+    return false;
+
   // Check that the point is not obscured by non-content NSViews.
   for (NSView* subview : [[bridged_view_ superview] subviews]) {
     if (subview == bridged_view_.get())
diff --git a/ui/views/controls/button/md_text_button.cc b/ui/views/controls/button/md_text_button.cc
index b708b83b..60f6ca0 100644
--- a/ui/views/controls/button/md_text_button.cc
+++ b/ui/views/controls/button/md_text_button.cc
@@ -159,7 +159,7 @@
   return std::make_unique<InkDropHighlight>(
       gfx::RectF(GetLocalBounds()).CenterPoint(),
       base::WrapUnique(new BorderShadowLayerDelegate(
-          shadows, GetLocalBounds(), fill_color, kInkDropSmallCornerRadius)));
+          shadows, GetLocalBounds(), fill_color, corner_radius_)));
 }
 
 void MdTextButton::SetEnabledTextColors(SkColor color) {
@@ -179,7 +179,8 @@
 
 MdTextButton::MdTextButton(ButtonListener* listener, int button_context)
     : LabelButton(listener, base::string16(), button_context),
-      is_prominent_(false) {
+      is_prominent_(false),
+      corner_radius_(kInkDropSmallCornerRadius) {
   SetInkDropMode(InkDropMode::ON);
   set_has_ink_drop_action_on_click(true);
   SetHorizontalAlignment(gfx::ALIGN_CENTER);
@@ -330,7 +331,7 @@
   DCHECK_EQ(SK_AlphaOPAQUE, static_cast<int>(SkColorGetA(bg_color)));
   SetBackground(
       CreateBackgroundFromPainter(Painter::CreateRoundRectWith1PxBorderPainter(
-          bg_color, stroke_color, kInkDropSmallCornerRadius)));
+          bg_color, stroke_color, corner_radius_)));
   SchedulePaint();
 }
 
diff --git a/ui/views/controls/button/md_text_button.h b/ui/views/controls/button/md_text_button.h
index 27ba3c0..25f65ce5 100644
--- a/ui/views/controls/button/md_text_button.h
+++ b/ui/views/controls/button/md_text_button.h
@@ -34,6 +34,10 @@
   // See |bg_color_override_|.
   void SetBgColorOverride(const base::Optional<SkColor>& color);
 
+  // Override the default corner radius of the round rect used for the
+  // background and ink drop effects.
+  void set_corner_radius(float radius) { corner_radius_ = radius; }
+
   // View:
   void OnPaintBackground(gfx::Canvas* canvas) override;
 
@@ -64,6 +68,8 @@
   // When set, this provides the background color.
   base::Optional<SkColor> bg_color_override_;
 
+  float corner_radius_;
+
   DISALLOW_COPY_AND_ASSIGN(MdTextButton);
 };
 
diff --git a/ui/views/controls/label_unittest.cc b/ui/views/controls/label_unittest.cc
index 54654ac..9302fcb 100644
--- a/ui/views/controls/label_unittest.cc
+++ b/ui/views/controls/label_unittest.cc
@@ -193,7 +193,7 @@
   void PerformMousePress(const gfx::Point& point, int extra_flags = 0) {
     ui::MouseEvent pressed_event = ui::MouseEvent(
         ui::ET_MOUSE_PRESSED, point, point, ui::EventTimeForNow(),
-        ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON | extra_flags);
+        ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
     label()->OnMousePressed(pressed_event);
   }
 
diff --git a/ui/views/controls/textfield/textfield_model.cc b/ui/views/controls/textfield/textfield_model.cc
index dc64e80..eb53893 100644
--- a/ui/views/controls/textfield/textfield_model.cc
+++ b/ui/views/controls/textfield/textfield_model.cc
@@ -658,9 +658,10 @@
   base::string16 new_text = text();
   render_text_->SetText(new_text.insert(cursor, composition.text));
   composition_range_ = gfx::Range(cursor, cursor + composition.text.length());
-  // Don't render transparent IME spans.
+  // Don't render IME spans with thickness "kNone".
   if (composition.ime_text_spans.size() > 0 &&
-      composition.ime_text_spans[0].underline_color != 0)
+      composition.ime_text_spans[0].thickness !=
+          ui::ImeTextSpan::Thickness::kNone)
     render_text_->SetCompositionRange(composition_range_);
   else
     render_text_->SetCompositionRange(gfx::Range::InvalidRange());
diff --git a/ui/views/controls/textfield/textfield_model_unittest.cc b/ui/views/controls/textfield/textfield_model_unittest.cc
index e952dc6..4b79f54 100644
--- a/ui/views/controls/textfield/textfield_model_unittest.cc
+++ b/ui/views/controls/textfield/textfield_model_unittest.cc
@@ -974,7 +974,7 @@
   ui::CompositionText composition;
   composition.text = base::ASCIIToUTF16("678");
   composition.ime_text_spans.push_back(
-      ui::ImeTextSpan(0, 3, 0, ui::ImeTextSpan::Thickness::kThin));
+      ui::ImeTextSpan(0, 3, ui::ImeTextSpan::Thickness::kThin));
 
   // Cursor should be at the end of composition when characters are just typed.
   composition.selection = gfx::Range(3, 3);
@@ -990,9 +990,9 @@
   composition.selection = gfx::Range(1, 3);
   composition.ime_text_spans.clear();
   composition.ime_text_spans.push_back(
-      ui::ImeTextSpan(0, 2, 0, ui::ImeTextSpan::Thickness::kThick));
+      ui::ImeTextSpan(0, 2, ui::ImeTextSpan::Thickness::kThick));
   composition.ime_text_spans.push_back(
-      ui::ImeTextSpan(2, 3, 0, ui::ImeTextSpan::Thickness::kThin));
+      ui::ImeTextSpan(2, 3, ui::ImeTextSpan::Thickness::kThin));
   model.SetCompositionText(composition);
   EXPECT_TRUE(model.HasCompositionText());
   EXPECT_TRUE(model.HasSelection());
@@ -1585,7 +1585,7 @@
   ui::CompositionText composition;
   composition.text = base::ASCIIToUTF16("abc");
   composition.ime_text_spans.push_back(
-      ui::ImeTextSpan(0, 3, 0, ui::ImeTextSpan::Thickness::kThin));
+      ui::ImeTextSpan(0, 3, ui::ImeTextSpan::Thickness::kThin));
   composition.selection = gfx::Range(2, 3);
 
   model.SetText(base::ASCIIToUTF16("ABCDE"));
diff --git a/ui/views/controls/textfield/textfield_unittest.cc b/ui/views/controls/textfield/textfield_unittest.cc
index b33f6b3..eee738e2 100644
--- a/ui/views/controls/textfield/textfield_unittest.cc
+++ b/ui/views/controls/textfield/textfield_unittest.cc
@@ -88,7 +88,7 @@
   ~MockInputMethod() override;
 
   // Overridden from InputMethod:
-  bool OnUntranslatedIMEMessage(const base::NativeEvent& event,
+  bool OnUntranslatedIMEMessage(const ui::PlatformEvent& event,
                                 NativeEventResult* result) override;
   ui::EventDispatchDetails DispatchKeyEvent(ui::KeyEvent* key) override;
   void OnTextInputTypeChanged(const ui::TextInputClient* client) override;
@@ -149,7 +149,7 @@
 MockInputMethod::~MockInputMethod() {
 }
 
-bool MockInputMethod::OnUntranslatedIMEMessage(const base::NativeEvent& event,
+bool MockInputMethod::OnUntranslatedIMEMessage(const ui::PlatformEvent& event,
                                                NativeEventResult* result) {
   if (result)
     *result = NativeEventResult();
@@ -731,7 +731,7 @@
   void PressMouseButton(ui::EventFlags mouse_button_flags, int extra_flags) {
     ui::MouseEvent press(ui::ET_MOUSE_PRESSED, mouse_position_, mouse_position_,
                          ui::EventTimeForNow(), mouse_button_flags,
-                         mouse_button_flags | extra_flags);
+                         mouse_button_flags);
     textfield_->OnMousePressed(press);
   }
 
diff --git a/ui/views/layout/layout_provider.cc b/ui/views/layout/layout_provider.cc
index 0c0ef43..d00abb9f 100644
--- a/ui/views/layout/layout_provider.cc
+++ b/ui/views/layout/layout_provider.cc
@@ -43,6 +43,7 @@
 }
 
 gfx::Insets LayoutProvider::GetInsetsMetric(int metric) const {
+  DCHECK_GE(metric, VIEWS_INSETS_START);
   DCHECK_LT(metric, VIEWS_INSETS_MAX);
   switch (metric) {
     case InsetsMetric::INSETS_DIALOG:
@@ -72,7 +73,8 @@
 }
 
 int LayoutProvider::GetDistanceMetric(int metric) const {
-  DCHECK_GE(metric, VIEWS_INSETS_MAX);
+  DCHECK_GE(metric, VIEWS_DISTANCE_START);
+  DCHECK_LT(metric, VIEWS_DISTANCE_MAX);
   switch (metric) {
     case DistanceMetric::DISTANCE_BUTTON_HORIZONTAL_PADDING:
       return 16;
diff --git a/ui/views/layout/layout_provider.h b/ui/views/layout/layout_provider.h
index 08313f8..991b8e5 100644
--- a/ui/views/layout/layout_provider.h
+++ b/ui/views/layout/layout_provider.h
@@ -100,7 +100,10 @@
   DISTANCE_UNRELATED_CONTROL_VERTICAL,
 
   // Embedders must start DistanceMetric enum values from here.
-  VIEWS_DISTANCE_END
+  VIEWS_DISTANCE_END,
+
+  // All Distance enum values must be below this value.
+  VIEWS_DISTANCE_MAX = 0x2000
 };
 
 // The type of a dialog content element. TEXT should be used for Labels or other
diff --git a/ui/views/mouse_watcher.cc b/ui/views/mouse_watcher.cc
index 0f56dce..16d554cdd 100644
--- a/ui/views/mouse_watcher.cc
+++ b/ui/views/mouse_watcher.cc
@@ -6,7 +6,6 @@
 
 #include "base/bind.h"
 #include "base/compiler_specific.h"
-#include "base/event_types.h"
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
@@ -16,6 +15,7 @@
 #include "ui/events/event_constants.h"
 #include "ui/events/event_handler.h"
 #include "ui/events/event_utils.h"
+#include "ui/events/platform_event.h"
 #include "ui/views/event_monitor.h"
 
 namespace views {
diff --git a/ui/views/mus/drag_interactive_uitest.cc b/ui/views/mus/drag_interactive_uitest.cc
index 08bab8b2a..bd6b770f 100644
--- a/ui/views/mus/drag_interactive_uitest.cc
+++ b/ui/views/mus/drag_interactive_uitest.cc
@@ -124,9 +124,9 @@
   if (!result)
     quit_closure.Run();
 
-  ui::mojom::RemoteEventDispatcher* dispatcher =
-      MusClient::Get()->GetTestingEventDispater();
-  dispatcher->DispatchEvent(
+  ui::mojom::EventInjector* event_injector =
+      MusClient::Get()->GetTestingEventInjector();
+  event_injector->InjectEvent(
       display_id, CreateMouseUpEvent(30, 30),
       base::Bind(&DragTest_Part3, display_id, quit_closure));
 }
@@ -138,9 +138,9 @@
   if (!result)
     quit_closure.Run();
 
-  ui::mojom::RemoteEventDispatcher* dispatcher =
-      MusClient::Get()->GetTestingEventDispater();
-  dispatcher->DispatchEvent(
+  ui::mojom::EventInjector* event_injector =
+      MusClient::Get()->GetTestingEventInjector();
+  event_injector->InjectEvent(
       display_id, CreateMouseMoveEvent(30, 30),
       base::Bind(&DragTest_Part2, display_id, quit_closure));
 }
@@ -175,9 +175,9 @@
 
   {
     base::RunLoop run_loop;
-    ui::mojom::RemoteEventDispatcher* dispatcher =
-        MusClient::Get()->GetTestingEventDispater();
-    dispatcher->DispatchEvent(
+    ui::mojom::EventInjector* event_injector =
+        MusClient::Get()->GetTestingEventInjector();
+    event_injector->InjectEvent(
         display_id, CreateMouseDownEvent(10, 10),
         base::Bind(&DragTest_Part1, display_id, run_loop.QuitClosure()));
 
diff --git a/ui/views/mus/mus_client.cc b/ui/views/mus/mus_client.cc
index 738bcbc..1e049056 100644
--- a/ui/views/mus/mus_client.cc
+++ b/ui/views/mus/mus_client.cc
@@ -104,8 +104,7 @@
 
   if (testing_state == MusClientTestingState::CREATE_TESTING_STATE) {
     connector->BindInterface(ui::mojom::kServiceName, &server_test_ptr_);
-    connector->BindInterface(ui::mojom::kServiceName,
-                             &remote_event_dispatcher_ptr_);
+    connector->BindInterface(ui::mojom::kServiceName, &event_injector_);
   }
 
   window_tree_client_ = aura::WindowTreeClient::CreateForWindowTreeFactory(
@@ -289,9 +288,9 @@
   return server_test_ptr_.get();
 }
 
-ui::mojom::RemoteEventDispatcher* MusClient::GetTestingEventDispater() const {
-  CHECK(remote_event_dispatcher_ptr_);
-  return remote_event_dispatcher_ptr_.get();
+ui::mojom::EventInjector* MusClient::GetTestingEventInjector() const {
+  CHECK(event_injector_);
+  return event_injector_.get();
 }
 
 std::unique_ptr<DesktopWindowTreeHost> MusClient::CreateDesktopWindowTreeHost(
diff --git a/ui/views/mus/mus_client.h b/ui/views/mus/mus_client.h
index 666f75e..0543e03 100644
--- a/ui/views/mus/mus_client.h
+++ b/ui/views/mus/mus_client.h
@@ -13,7 +13,7 @@
 
 #include "base/macros.h"
 #include "services/service_manager/public/cpp/identity.h"
-#include "services/ui/public/interfaces/remote_event_dispatcher.mojom.h"
+#include "services/ui/public/interfaces/event_injector.mojom.h"
 #include "services/ui/public/interfaces/window_server_test.mojom.h"
 #include "ui/aura/client/capture_client.h"
 #include "ui/aura/mus/window_tree_client_delegate.h"
@@ -127,9 +127,9 @@
   // with MusClientTestingState::CREATE_TESTING_STATE.
   ui::mojom::WindowServerTest* GetTestingInterface() const;
 
-  // Returns an interface to dispatch events in the mus server. Only available
-  // when created with MusClientTestingState::CREATE_TESTING_STATE.
-  ui::mojom::RemoteEventDispatcher* GetTestingEventDispater() const;
+  // Returns an interface to inject events into the Window Service. Only
+  // available when created with MusClientTestingState::CREATE_TESTING_STATE.
+  ui::mojom::EventInjector* GetTestingEventInjector() const;
 
  private:
   friend class AuraInit;
@@ -182,7 +182,7 @@
   std::unique_ptr<PointerWatcherEventRouter> pointer_watcher_event_router_;
 
   ui::mojom::WindowServerTestPtr server_test_ptr_;
-  ui::mojom::RemoteEventDispatcherPtr remote_event_dispatcher_ptr_;
+  ui::mojom::EventInjectorPtr event_injector_;
 
   DISALLOW_COPY_AND_ASSIGN(MusClient);
 };
diff --git a/ui/views/test/ui_controls_factory_desktop_aurax11.cc b/ui/views/test/ui_controls_factory_desktop_aurax11.cc
index 3f391c4..9e16b4c 100644
--- a/ui/views/test/ui_controls_factory_desktop_aurax11.cc
+++ b/ui/views/test/ui_controls_factory_desktop_aurax11.cc
@@ -43,7 +43,7 @@
 }
 
 // Returns true when the event is a marker event.
-bool Matcher(const base::NativeEvent& event) {
+bool Matcher(const ui::PlatformEvent& event) {
   return event->xany.type == ClientMessage &&
       event->xclient.message_type == MarkerEventAtom();
 }
diff --git a/ui/views/test/x11_property_change_waiter.h b/ui/views/test/x11_property_change_waiter.h
index e0bbee5..7f1eec3f 100644
--- a/ui/views/test/x11_property_change_waiter.h
+++ b/ui/views/test/x11_property_change_waiter.h
@@ -12,7 +12,7 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "ui/events/platform/platform_event_dispatcher.h"
-#include "ui/events/platform/platform_event_types.h"
+#include "ui/events/platform_event.h"
 #include "ui/gfx/x/x11_types.h"
 
 namespace ui {
diff --git a/ui/views/vector_icons/ic_close.icon b/ui/views/vector_icons/ic_close.icon
new file mode 100644
index 0000000..686da72b
--- /dev/null
+++ b/ui/views/vector_icons/ic_close.icon
@@ -0,0 +1,33 @@
+// 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.
+
+CANVAS_DIMENSIONS, 48,
+MOVE_TO, 38, 12.82f,
+LINE_TO, 35.18f, 10,
+LINE_TO, 24, 21.18f,
+LINE_TO, 12.82f, 10,
+LINE_TO, 10, 12.82f,
+LINE_TO, 21.18f, 24,
+LINE_TO, 10, 35.18f,
+LINE_TO, 12.82f, 38,
+LINE_TO, 24, 26.82f,
+LINE_TO, 35.18f, 38,
+LINE_TO, 38, 35.18f,
+LINE_TO, 26.82f, 24,
+CLOSE
+
+CANVAS_DIMENSIONS, 24,
+MOVE_TO, 19, 6.41f,
+LINE_TO, 17.59f, 5,
+LINE_TO, 12, 10.59f,
+LINE_TO, 6.41f, 5,
+LINE_TO, 5, 6.41f,
+LINE_TO, 10.59f, 12,
+LINE_TO, 5, 17.59f,
+LINE_TO, 6.41f, 19,
+LINE_TO, 12, 13.41f,
+LINE_TO, 17.59f, 19,
+LINE_TO, 19, 17.59f,
+LINE_TO, 13.41f, 12,
+CLOSE
diff --git a/ui/views/vector_icons/menu_check.1x.icon b/ui/views/vector_icons/menu_check.1x.icon
deleted file mode 100644
index 18d76177..0000000
--- a/ui/views/vector_icons/menu_check.1x.icon
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 16,
-MOVE_TO, 2, 9.22f,
-R_LINE_TO, 1.36f, -1.38f,
-R_LINE_TO, 2.4f, 2.48f,
-R_LINE_TO, 7.2f, -7.4f,
-R_LINE_TO, 1.35f, 1.39f,
-R_LINE_TO, -8.55f, 8.78f,
-LINE_TO, 2, 9.22f,
-CLOSE
diff --git a/ui/views/vector_icons/menu_check.icon b/ui/views/vector_icons/menu_check.icon
index 46f105a..3e24215 100644
--- a/ui/views/vector_icons/menu_check.icon
+++ b/ui/views/vector_icons/menu_check.icon
@@ -11,3 +11,13 @@
 LINE_TO, 12.02f, 26,
 LINE_TO, 5, 18.78f,
 CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 2, 9.22f,
+R_LINE_TO, 1.36f, -1.38f,
+R_LINE_TO, 2.4f, 2.48f,
+R_LINE_TO, 7.2f, -7.4f,
+R_LINE_TO, 1.35f, 1.39f,
+R_LINE_TO, -8.55f, 8.78f,
+LINE_TO, 2, 9.22f,
+CLOSE
diff --git a/ui/views/vector_icons/submenu_arrow.1x.icon b/ui/views/vector_icons/submenu_arrow.1x.icon
deleted file mode 100644
index 823fd4d..0000000
--- a/ui/views/vector_icons/submenu_arrow.1x.icon
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 8,
-FLIPS_IN_RTL,
-MOVE_TO, 2, 8,
-R_LINE_TO, 5, -4,
-R_LINE_TO, -5, -4,
-R_V_LINE_TO, 8,
-CLOSE
diff --git a/ui/views/vector_icons/submenu_arrow.icon b/ui/views/vector_icons/submenu_arrow.icon
index 74b764c..9d633095 100644
--- a/ui/views/vector_icons/submenu_arrow.icon
+++ b/ui/views/vector_icons/submenu_arrow.icon
@@ -9,3 +9,11 @@
 LINE_TO, 3, 0,
 R_V_LINE_TO, 16,
 CLOSE
+
+CANVAS_DIMENSIONS, 8,
+FLIPS_IN_RTL,
+MOVE_TO, 2, 8,
+R_LINE_TO, 5, -4,
+R_LINE_TO, -5, -4,
+R_V_LINE_TO, 8,
+CLOSE
diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc
index 55dcdf78..ad0123ac 100644
--- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc
+++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc
@@ -7,7 +7,6 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#include "base/event_types.h"
 #include "base/lazy_instance.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
@@ -30,6 +29,7 @@
 #include "ui/events/event.h"
 #include "ui/events/event_utils.h"
 #include "ui/events/platform/platform_event_source.h"
+#include "ui/events/platform_event.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/x/x11.h"
 #include "ui/gfx/x/x11_atom_cache.h"
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
index d8a2110c..6ef1ae76 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
@@ -858,9 +858,9 @@
   // TODO(beng): inform the native_widget_delegate_.
 }
 
-bool DesktopWindowTreeHostWin::HandleMouseEvent(const ui::MouseEvent& event) {
-  SendEventToSink(const_cast<ui::MouseEvent*>(&event));
-  return event.handled();
+bool DesktopWindowTreeHostWin::HandleMouseEvent(ui::MouseEvent* event) {
+  SendEventToSink(event);
+  return event->handled();
 }
 
 bool DesktopWindowTreeHostWin::HandlePointerEvent(ui::PointerEvent* event) {
@@ -872,8 +872,7 @@
   SendEventToSink(event);
 }
 
-void DesktopWindowTreeHostWin::HandleTouchEvent(
-    const ui::TouchEvent& event) {
+void DesktopWindowTreeHostWin::HandleTouchEvent(ui::TouchEvent* event) {
   // HWNDMessageHandler asynchronously processes touch events. Because of this
   // it's possible for the aura::WindowEventDispatcher to have been destroyed
   // by the time we attempt to process them.
@@ -887,10 +886,10 @@
     DesktopWindowTreeHostWin* target =
         host->window()->GetProperty(kDesktopWindowTreeHostKey);
     if (target && target->HasCapture() && target != this) {
-      POINT target_location(event.location().ToPOINT());
+      POINT target_location(event->location().ToPOINT());
       ClientToScreen(GetHWND(), &target_location);
       ScreenToClient(target->GetHWND(), &target_location);
-      ui::TouchEvent target_event(event, static_cast<View*>(NULL),
+      ui::TouchEvent target_event(*event, static_cast<View*>(NULL),
                                   static_cast<View*>(NULL));
       target_event.set_location(gfx::Point(target_location));
       target_event.set_root_location(target_event.location());
@@ -898,7 +897,7 @@
       return;
     }
   }
-  SendEventToSink(const_cast<ui::TouchEvent*>(&event));
+  SendEventToSink(event);
 }
 
 bool DesktopWindowTreeHostWin::HandleIMEMessage(UINT message,
@@ -951,10 +950,9 @@
                                              LPARAM l_param) {
 }
 
-bool DesktopWindowTreeHostWin::HandleScrollEvent(
-    const ui::ScrollEvent& event) {
-  SendEventToSink(const_cast<ui::ScrollEvent*>(&event));
-  return event.handled();
+bool DesktopWindowTreeHostWin::HandleScrollEvent(ui::ScrollEvent* event) {
+  SendEventToSink(event);
+  return event->handled();
 }
 
 bool DesktopWindowTreeHostWin::HandleGestureEvent(ui::GestureEvent* event) {
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
index cbb800c3..ec5cfdd 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
@@ -193,10 +193,10 @@
   void HandleFrameChanged() override;
   void HandleNativeFocus(HWND last_focused_window) override;
   void HandleNativeBlur(HWND focused_window) override;
-  bool HandleMouseEvent(const ui::MouseEvent& event) override;
+  bool HandleMouseEvent(ui::MouseEvent* event) override;
   bool HandlePointerEvent(ui::PointerEvent* event) override;
   void HandleKeyEvent(ui::KeyEvent* event) override;
-  void HandleTouchEvent(const ui::TouchEvent& event) override;
+  void HandleTouchEvent(ui::TouchEvent* event) override;
   bool HandleIMEMessage(UINT message,
                         WPARAM w_param,
                         LPARAM l_param,
@@ -213,7 +213,7 @@
                     LPARAM l_param,
                     LRESULT* result) override;
   void PostHandleMSG(UINT message, WPARAM w_param, LPARAM l_param) override;
-  bool HandleScrollEvent(const ui::ScrollEvent& event) override;
+  bool HandleScrollEvent(ui::ScrollEvent* event) override;
   bool HandleGestureEvent(ui::GestureEvent* event) override;
   void HandleWindowSizeChanging() override;
   void HandleWindowSizeUnchanged() override;
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc
index c42176e9..a16045f 100644
--- a/ui/views/win/hwnd_message_handler.cc
+++ b/ui/views/win/hwnd_message_handler.cc
@@ -1114,7 +1114,7 @@
       offset, cursor_location, cursor_root_location, base::TimeTicks::Now(),
       ui::EF_PRECISION_SCROLLING_DELTA, ui::EF_NONE);
 
-  delegate_->HandleMouseEvent(wheel_event);
+  delegate_->HandleMouseEvent(&wheel_event);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -2176,7 +2176,7 @@
   MSG msg = {
       hwnd(), message, w_param, l_param, static_cast<DWORD>(GetMessageTime())};
   ui::ScrollEvent event(msg);
-  delegate_->HandleScrollEvent(event);
+  delegate_->HandleScrollEvent(&event);
   return 0;
 }
 
@@ -2620,8 +2620,10 @@
 
 void HWNDMessageHandler::HandleTouchEvents(const TouchEvents& touch_events) {
   base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr());
-  for (size_t i = 0; i < touch_events.size() && ref; ++i)
-    delegate_->HandleTouchEvent(touch_events[i]);
+  for (size_t i = 0; i < touch_events.size() && ref; ++i) {
+    ui::TouchEvent* touch_event = const_cast<ui::TouchEvent*>(&touch_events[i]);
+    delegate_->HandleTouchEvent(touch_event);
+  }
 }
 
 void HWNDMessageHandler::ResetTouchDownContext() {
@@ -2731,15 +2733,18 @@
     // OnMouseEvent.
     active_mouse_tracking_flags_ = 0;
   } else if (event.type() == ui::ET_MOUSEWHEEL) {
+    ui::MouseWheelEvent mouse_wheel_event(msg);
     // Reroute the mouse wheel to the window under the pointer if applicable.
     return (ui::RerouteMouseWheel(hwnd(), w_param, l_param) ||
-            delegate_->HandleMouseEvent(ui::MouseWheelEvent(msg))) ? 0 : 1;
+            delegate_->HandleMouseEvent(&mouse_wheel_event))
+               ? 0
+               : 1;
   }
 
   // There are cases where the code handling the message destroys the window,
   // so use the weak ptr to check if destruction occured or not.
   base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr());
-  bool handled = delegate_->HandleMouseEvent(event);
+  bool handled = delegate_->HandleMouseEvent(&event);
 
   if (!ref.get())
     return 0;
@@ -2838,7 +2843,7 @@
   // There are cases where the code handling the message destroys the
   // window, so use the weak ptr to check if destruction occurred or not.
   base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr());
-  delegate_->HandleTouchEvent(event);
+  delegate_->HandleTouchEvent(&event);
 
   if (event_type == ui::ET_TOUCH_RELEASED)
     id_generator_.ReleaseNumber(pointer_id);
@@ -2874,9 +2879,9 @@
   base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr());
   if (event) {
     if (event->IsTouchEvent()) {
-      delegate_->HandleTouchEvent(*event->AsTouchEvent());
+      delegate_->HandleTouchEvent(event->AsTouchEvent());
     } else if (event->IsMouseEvent()) {
-      delegate_->HandleMouseEvent(*event->AsMouseEvent());
+      delegate_->HandleMouseEvent(event->AsMouseEvent());
     } else {
       NOTREACHED();
     }
diff --git a/ui/views/win/hwnd_message_handler_delegate.h b/ui/views/win/hwnd_message_handler_delegate.h
index f4b3ff8e..1b2d98a8 100644
--- a/ui/views/win/hwnd_message_handler_delegate.h
+++ b/ui/views/win/hwnd_message_handler_delegate.h
@@ -186,7 +186,7 @@
 
   // Called when a mouse event is received. Returns true if the event was
   // handled by the delegate.
-  virtual bool HandleMouseEvent(const ui::MouseEvent& event) = 0;
+  virtual bool HandleMouseEvent(ui::MouseEvent* event) = 0;
 
   // Called when a pointer event is received. Returns true if the event was
   // handled by the delegate.
@@ -197,7 +197,7 @@
   virtual void HandleKeyEvent(ui::KeyEvent* event) = 0;
 
   // Called when a touch event is received.
-  virtual void HandleTouchEvent(const ui::TouchEvent& event) = 0;
+  virtual void HandleTouchEvent(ui::TouchEvent* event) = 0;
 
   // Called when an IME message needs to be processed by the delegate. Returns
   // true if the event was handled and no default processing should be
@@ -241,7 +241,7 @@
 
   // Called when a scroll event is received. Returns true if the event was
   // handled by the delegate.
-  virtual bool HandleScrollEvent(const ui::ScrollEvent& event) = 0;
+  virtual bool HandleScrollEvent(ui::ScrollEvent* event) = 0;
 
   // Called when a gesture event is received. Returns true if the event was
   // handled by the delegate.
diff --git a/ui/web_dialogs/web_dialog_ui.cc b/ui/web_dialogs/web_dialog_ui.cc
index 1d6cbc9..9b1d765 100644
--- a/ui/web_dialogs/web_dialog_ui.cc
+++ b/ui/web_dialogs/web_dialog_ui.cc
@@ -77,8 +77,8 @@
   // Hook up the javascript function calls, also known as chrome.send("foo")
   // calls in the HTML, to the actual C++ functions.
   web_ui_->RegisterMessageCallback(
-      "dialogClose",
-      base::Bind(&WebDialogUIBase::OnDialogClosed, base::Unretained(this)));
+      "dialogClose", base::BindRepeating(&WebDialogUIBase::OnDialogClosed,
+                                         base::Unretained(this)));
 
   // Pass the arguments to the renderer supplied by the delegate.
   std::string dialog_args;
diff --git a/url/BUILD.gn b/url/BUILD.gn
index f2af9f9..c4deb10 100644
--- a/url/BUILD.gn
+++ b/url/BUILD.gn
@@ -4,6 +4,7 @@
 
 import("//build/buildflag_header.gni")
 import("//testing/test.gni")
+import("//testing/libfuzzer/fuzzer_test.gni")
 import("features.gni")
 
 if (is_android) {
@@ -173,3 +174,15 @@
     ]
   }
 }
+
+fuzzer_test("gurl_fuzzer") {
+  sources = [
+    "gurl_fuzzer.cc",
+  ]
+  deps = [
+    ":url",
+    "//base",
+    "//base:i18n",
+  ]
+  dict = "gurl_fuzzer.dict"
+}
diff --git a/url/DEPS b/url/DEPS
index 946d75f..9591925b 100644
--- a/url/DEPS
+++ b/url/DEPS
@@ -7,6 +7,9 @@
 ]
 
 specific_include_rules = {
+  "gurl_fuzzer.cc": [
+    "+base/i18n",
+  ],
   "url_canon_icu(\.cc|_unittest\.cc)": [
     "+third_party/icu",
   ],
diff --git a/url/gurl_fuzzer.cc b/url/gurl_fuzzer.cc
new file mode 100644
index 0000000..0c6137a
--- /dev/null
+++ b/url/gurl_fuzzer.cc
@@ -0,0 +1,57 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/at_exit.h"
+#include "base/i18n/icu_util.h"
+#include "url/gurl.h"
+
+struct TestCase {
+  TestCase() { CHECK(base::i18n::InitializeICU()); }
+
+  // used by ICU integration.
+  base::AtExitManager at_exit_manager;
+};
+
+TestCase* test_case = new TestCase();
+
+// Entry point for LibFuzzer.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  if (size < 1)
+    return 0;
+
+  base::StringPiece string_piece_input(reinterpret_cast<const char*>(data),
+                                       size);
+  GURL url_from_string_piece(string_piece_input);
+
+  // Test for StringPiece16 if size is even.
+  if (size % 2 == 0) {
+    base::StringPiece16 string_piece_input16(
+        reinterpret_cast<const base::char16*>(data), size / 2);
+
+    GURL url_from_string_piece16(string_piece_input16);
+  }
+
+  // Resolve relative url tests.
+  size_t size_t_bytes = sizeof(size_t);
+  if (size < size_t_bytes + 1) {
+    return 0;
+  }
+  size_t relative_size =
+      *reinterpret_cast<const size_t*>(data) % (size - size_t_bytes);
+  std::string relative_string(
+      reinterpret_cast<const char*>(data + size_t_bytes), relative_size);
+  base::StringPiece string_piece_part_input(
+      reinterpret_cast<const char*>(data + size_t_bytes + relative_size),
+      size - relative_size - size_t_bytes);
+  GURL url_from_string_piece_part(string_piece_part_input);
+  url_from_string_piece_part.Resolve(relative_string);
+
+  if (relative_size % 2 == 0) {
+    base::string16 relative_string16(
+        reinterpret_cast<const base::char16*>(data + size_t_bytes),
+        relative_size / 2);
+    url_from_string_piece_part.Resolve(relative_string16);
+  }
+  return 0;
+}
diff --git a/testing/libfuzzer/fuzzers/dicts/generated/url_parse_fuzzer.dict b/url/gurl_fuzzer.dict
similarity index 100%
rename from testing/libfuzzer/fuzzers/dicts/generated/url_parse_fuzzer.dict
rename to url/gurl_fuzzer.dict